@@ -5,36 +5,82 @@ import { cloneElement } from 'react';
5
5
import styles from './styles.module.css' ;
6
6
import CustomizableValue from '../../../components/CustomizableValue' ;
7
7
8
+ /**
9
+ * replaceCustomizeableValues takes a list of tokens and identifies customizable values
10
+ * marked by a start and end token, '$$'.
11
+ * It returns a new list of tokens with the customizable values replaced with a CustomizableValue component.
12
+ * If a customizable value begins or ends in the middle of a token, the token is split into two tokens.
13
+ */
8
14
function replaceCustomizeableValues ( tokens ) {
15
+ // The list of tokens including the customizable value components
9
16
let newTokens = [ ] ;
17
+ // A string that is being built up to capture the content of the current token, used to create a new token
10
18
let captured = '' ;
11
- let capturing = false ;
12
- for ( let token of tokens ) {
19
+ // A boolean indicating that we are currently within a customizable value
20
+ let withinCustomizableValue = false ;
21
+
22
+ // A boolean indicating that we should skip the first character of the next token
23
+ let skipFirstChar = false ;
24
+
25
+ // Loop over each token
26
+ for ( let i = 0 ; i < tokens . length ; i ++ ) {
27
+ let token = tokens [ i ] ;
28
+ let nextToken = i < tokens . length - 1 ? tokens [ i + 1 ] : null ;
29
+
13
30
let content = token . props . children ;
14
- for ( let i = 0 ; i < content . length ; i ++ ) {
15
- if ( content [ i ] === '$' && i < content . length - 1 && content [ i + 1 ] === '$' ) {
16
- if ( capturing ) {
31
+
32
+ // Loop over each character in the token
33
+ let initialIndex = 0 ;
34
+ if ( skipFirstChar ) {
35
+ // Start the loop at 1 to skip the first character
36
+ initialIndex = 1 ;
37
+ skipFirstChar = false ;
38
+ }
39
+
40
+ for ( let j = initialIndex ; j < content . length ; j ++ ) {
41
+ // The current charcter and the next character
42
+ // The next character may be in the next token, so we need to look ahead
43
+ let currentChar = content [ j ] ;
44
+ let nextChar = j < content . length - 1 ? content [ j + 1 ] : null ;
45
+ // Track if we used the next token to get the next character
46
+ let usedNextToken = false ;
47
+ if ( nextChar == null && nextToken != null && nextToken . props . children . length > 0 ) {
48
+ nextChar = nextToken . props . children [ 0 ] ;
49
+ usedNextToken = true ;
50
+ }
51
+
52
+ // If the current and next characters are both '$', we have found the start or end of a customizable value
53
+ if ( currentChar === '$' && nextChar === '$' ) {
54
+ if ( withinCustomizableValue ) {
55
+ // We have found the end of a customizable value, create a new token for the customizable value
17
56
newTokens . push (
18
57
< CustomizableValue
19
58
key = { captured + newTokens . length }
20
59
id = { captured }
21
60
/>
22
61
) ;
23
- } else {
62
+ } else if ( captured . length > 0 ) {
63
+ // We have found the start of a customizable value, if we have captured any content, create a new token
64
+ // to preserve the previous content
24
65
let newToken = cloneElement ( token , { key : newTokens . length } , captured )
25
66
newTokens . push ( newToken )
26
67
}
27
68
69
+ // Reset the captured content and toggle the withinCustomizableValue flag
28
70
captured = '' ;
29
- capturing = ! capturing ;
30
- i += 2 ;
31
- if ( i >= content . length ) {
71
+ withinCustomizableValue = ! withinCustomizableValue ;
72
+ // Skip the next two characters in this token, which will be the opening or closing $$
73
+ j += 2 ;
74
+ // If the marker was split across two tokens, we need to skip the first character of the next token
75
+ // to remove it from the output
76
+ skipFirstChar = usedNextToken ;
77
+ if ( j >= content . length ) {
32
78
break ;
33
79
}
34
80
}
35
- captured += content [ i ] ;
81
+ captured += content [ j ] ;
36
82
}
37
- if ( captured . length > 0 && ! capturing ) {
83
+ if ( captured . length > 0 && ! withinCustomizableValue ) {
38
84
let newToken = cloneElement ( token , { key : newTokens . length } , captured )
39
85
newTokens . push ( newToken )
40
86
captured = '' ;
0 commit comments