@@ -15,54 +15,73 @@ type StringInterpolationReturn<VariableValue extends any, OptionRaw> = Exclude<
15
15
16
16
/**
17
17
* Takes in a string containing variables and an object containing variables for interpolation. Accepts options.
18
+ *
19
+ * @example
20
+ *
21
+ * stringInterpolation("You have {{n}} messages", {
22
+ n: 3,
23
+ })
24
+
25
+ stringInterpolation("You have {{n}} messages from {{person}}", {
26
+ n: <strong>3</strong>,
27
+ person: "John",
28
+ })
18
29
*/
19
30
export function stringInterpolation <
20
31
VariableValue extends any ,
21
32
OptionRaw extends boolean | undefined
22
33
> (
23
- s : string ,
24
- v : Record < PropertyKey , VariableValue > ,
34
+ string : string ,
35
+ variables : Record < PropertyKey , VariableValue > ,
25
36
{
26
- pattern : p = new RegExp ( / \{ { ( [ ^ { ] + ) } } / g) ,
27
- sanity : S = true ,
28
- raw : r = false ,
37
+ pattern = new RegExp ( / \{ { ( [ ^ { ] + ) } } / g) ,
38
+ sanity = true ,
39
+ raw : rawOutput = false ,
29
40
} : StringInterpolationOptions < OptionRaw > = { }
30
41
) : StringInterpolationReturn < VariableValue , OptionRaw > {
31
- if ( ! s && S ) throw "Empty string"
42
+ if ( ! string && sanity ) throw "Empty string"
32
43
33
44
// Find all variables within string
34
- const sV = [ ...s . matchAll ( p ) ]
45
+ const stringVariables = [ ...string . matchAll ( pattern ) ]
35
46
36
47
// No variables => no need to interpolate
37
- if ( ! sV [ 0 ] ) return s as StringInterpolationReturn < VariableValue , OptionRaw >
48
+ if ( ! stringVariables [ 0 ] )
49
+ return string as StringInterpolationReturn < VariableValue , OptionRaw >
38
50
39
- if ( S ) {
51
+ if ( sanity ) {
40
52
// Sanity check string variables <-> passed in variables count
41
- const k = Object . keys ( v )
53
+ const variableKeys = Object . keys ( variables )
42
54
// Checks whether variables parsed from string exist in passed argument
43
- if ( sV . length !== k . length ) throw "Variable count mismatch"
44
- for ( const _v of sV ) {
45
- const vIs = _v [ 1 ] // Variable in string
46
- if ( vIs && ! k . includes ( vIs ) ) throw `Variable '${ vIs } ' not found`
55
+ if ( stringVariables . length !== variableKeys . length )
56
+ throw "Variable count mismatch"
57
+ for ( const regExpMatchArray of stringVariables ) {
58
+ const variable = regExpMatchArray [ 1 ]
59
+ if ( variable && ! variableKeys . includes ( variable ) )
60
+ throw `Variable '${ variable } ' not found`
47
61
}
48
62
}
49
63
50
- const raw = s
51
- . split ( p )
64
+ // Create raw interpolation result
65
+ const rawInterpolation = string
66
+ . split ( pattern )
52
67
// Trim empty string from array end (Could propably be done with regex as well)
53
68
. filter ( Boolean )
54
- . map ( ( _v ) => {
55
- return v [ _v ] ? v [ _v ] : _v
69
+ // Match parsed variables with passed in variables
70
+ . map ( ( splitItem ) => {
71
+ return variables [ splitItem ] ? variables [ splitItem ] : splitItem
56
72
} )
57
73
58
74
// Checks if raw interpolation can be joined or not.
59
75
// i.e. avoid printing [object Object | Array | Function | ...] within returned string.
60
- const j = ! raw . filter (
76
+ const canJoin = ! rawInterpolation . filter (
61
77
( i ) => typeof i !== "string" && typeof i !== "number"
62
78
) [ 0 ]
63
79
64
- if ( j && ! r )
65
- return raw . join ( "" ) as StringInterpolationReturn < VariableValue , OptionRaw >
80
+ if ( canJoin && ! rawOutput )
81
+ return rawInterpolation . join ( "" ) as StringInterpolationReturn <
82
+ VariableValue ,
83
+ OptionRaw
84
+ >
66
85
67
- return raw as StringInterpolationReturn < VariableValue , OptionRaw >
86
+ return rawInterpolation as StringInterpolationReturn < VariableValue , OptionRaw >
68
87
}
0 commit comments