@@ -48,126 +48,186 @@ function parseValue(value: VariableValue): VariableValue {
4848 return number ;
4949 }
5050
51- return value ;
51+ // remove additional quotes around strings
52+ if ( / ^ ( ' | " ) .+ \1$ / . test ( value ) ) {
53+ value = value . substring ( 1 , value . length - 1 ) ;
54+ }
55+
56+ // remove additional spaces that get added to css functions somtimes
57+ return value . replace ( / ( ( \( ) \s + ) | ( \s + ( \) ) ) / g, "$2$4" ) ;
5258}
5359
54- function matchParen ( s : string , count = 0 ) : string {
60+ function consumeMatchingParens ( s : string , totalParens = 0 ) : string {
5561 const match = s . match ( / \( | \) / ) ;
5662 if ( ! match || typeof match . index === "undefined" ) {
5763 return s ;
5864 }
5965
6066 const i = match . index + 1 ;
67+ let addition = 1 ;
6168 if ( match [ 0 ] === ")" ) {
62- if ( count === 1 ) {
69+ if ( totalParens === 1 ) {
6370 return s . substring ( 0 , i ) ;
6471 }
6572
66- return s . substring ( 0 , i ) + matchParen ( s . substring ( i ) , count - 1 ) ;
73+ addition = - 1 ;
6774 }
6875
69- return s . substring ( 0 , i ) + matchParen ( s . substring ( i ) , count + 1 ) ;
76+ return (
77+ s . substring ( 0 , i ) +
78+ consumeMatchingParens ( s . substring ( i ) , totalParens + addition )
79+ ) ;
80+ }
81+
82+ function isCssFunction ( remaining : string , endIndex : number ) : boolean {
83+ return / ( v a r | c a l c | r g b a ? | r o t a t e ( 3 d ) ? | t r a n s l a t e ( X | Y | 3 d ) ? | c u b i c - b e z i e r ) \( / . test (
84+ remaining . substring ( 0 , endIndex + 1 )
85+ ) ;
7086}
7187
72- function parseMap ( mapValue : string ) : ValuedVariable [ ] {
73- let remaining = mapValue . substring ( 1 , mapValue . length - 1 ) ;
88+ const VALUE_SEP = ": " ;
89+
90+ function parseMap ( mapString : string ) : ValuedVariable [ ] {
7491 const values : ValuedVariable [ ] = [ ] ;
92+
93+ if ( mapString [ 0 ] !== "(" || mapString [ mapString . length - 1 ] !== ")" ) {
94+ throw new Error ( "INVALID MAP FORMAT" ) ;
95+ }
96+
97+ let remaining = mapString . substring ( 1 , mapString . length - 1 ) ;
7598 while ( remaining . length ) {
76- const i = remaining . indexOf ( ": " ) ;
77- if ( i === - 1 ) {
78- log . error (
79- "Unable to hack a css variable correctly since no valid key/value split was found."
80- ) ;
81- log . error ( "Original Map Value: " , mapValue ) ;
82- log . error ( "Remaining string: " , remaining ) ;
83- process . exit ( 1 ) ;
99+ const sepIndex = remaining . indexOf ( VALUE_SEP ) ;
100+ if ( sepIndex === - 1 ) {
101+ throw new Error ( "Unable to find a name" ) ;
84102 }
85103
86- const name = remaining . substring ( 0 , i ) ;
87- remaining = remaining . substring ( i + 2 ) ;
88- let j =
89- name === "font-family"
90- ? remaining . search ( / , [ - a - z ] + : / )
91- : remaining . indexOf ( "," ) ;
92- if ( j === - 1 ) {
93- j = remaining . length ;
104+ const name = remaining . substring ( 0 , sepIndex ) ;
105+ remaining = remaining . substring ( sepIndex + VALUE_SEP . length ) ;
106+ if ( name === "font-family" ) {
107+ const tokenIndex = remaining . search ( / , [ - a - z ] + : / ) ;
108+ if ( tokenIndex !== - 1 ) {
109+ const value = remaining . substring ( 0 , tokenIndex ) ;
110+ values . push ( {
111+ name,
112+ value : parseValue ( value ) ,
113+ } ) ;
114+ remaining = remaining . substring ( tokenIndex + 1 ) . trim ( ) ;
115+ continue ;
116+ } else {
117+ throw new Error ( "unsupported font-family value" ) ;
118+ }
94119 }
95120
96- const remainingString = remaining . substring ( 0 , j ) ;
97- let value : VariableValue = remainingString ;
98- if ( remainingString . startsWith ( "(" ) ) {
99- const mapString = matchParen ( remaining ) ;
100- j = mapString . length ;
101- value = parseMap ( mapString ) ;
102- } else if ( remainingString . includes ( "(" ) ) {
103- const matched = matchParen ( remaining ) ;
104- j = matched . length ;
105- value = matched ;
121+ const nextMatch = remaining . match ( / \( | \) | , / ) ;
122+ if ( ! nextMatch ) {
123+ values . push ( {
124+ name,
125+ value : parseValue ( remaining ) ,
126+ } ) ;
127+ break ;
106128 }
107129
108- value = parseValue ( value ) ;
109- remaining = remaining . substring ( j + 1 ) . trim ( ) ;
110- values . push ( { name, value } ) ;
130+ const nextMatchIndex = nextMatch . index ;
131+ if ( typeof nextMatchIndex !== "number" ) {
132+ throw new Error ( "NO MATCHINDEX" ) ;
133+ }
134+
135+ const token = remaining [ nextMatchIndex ] ;
136+ if ( token === "," ) {
137+ values . push ( {
138+ name,
139+ value : parseValue ( remaining . substring ( 0 , nextMatchIndex ) ) ,
140+ } ) ;
141+
142+ remaining = remaining . substring ( nextMatchIndex + 1 ) ;
143+ } else if ( token === ")" ) {
144+ throw new Error ( `token: "${ token } "` ) ;
145+ } else if ( isCssFunction ( remaining , nextMatchIndex ) ) {
146+ const variableValue = consumeMatchingParens ( remaining ) ;
147+ values . push ( {
148+ name,
149+ value : parseValue ( variableValue ) ,
150+ } ) ;
151+ remaining = remaining . substring ( variableValue . length + 1 ) ;
152+ } else {
153+ const nextMap = consumeMatchingParens ( remaining ) ;
154+ values . push ( {
155+ name,
156+ value : parseMap ( nextMap ) ,
157+ } ) ;
158+
159+ remaining = remaining . substring ( nextMap . length ) . replace ( / ^ , \s + / , "" ) ;
160+ }
161+
162+ remaining = remaining . trim ( ) ;
111163 }
112164
113165 return values ;
114166}
115167
116- export function getCompiledValue ( variable : VariableItem ) : ValuedVariable {
168+ export function getCompiledValue (
169+ variable : VariableItem ,
170+ index ?: number
171+ ) : ValuedVariable {
117172 const {
118173 file : { path } ,
119- context : { name, value } ,
174+ context : { name, value : originalValue } ,
120175 type,
121176 } = variable ;
122177
123- const prefix = `$${ name } : ` ;
124- const data = `@import '${ path } ';
125- @error '${ prefix } #{${ value } }'` ;
126-
127- try {
128- renderSync ( {
129- data,
130- outputStyle : "expanded" ,
131- includePaths : [ tempStylesDir ] ,
132- } ) ;
133- throw new Error ( "Should never happen" ) ;
134- } catch ( e ) {
135- const { message } = e as Error ;
136- if ( / U n d e f i n e d v a r i a b l e | F i l e t o i m p o r t n o t f o u n d / . test ( message ) ) {
137- log . error ( `Unable to hackily generate the value for "${ name } "` ) ;
138- log . error ( ) ;
139- log . error ( message ) ;
140- process . exit ( 1 ) ;
141- }
178+ // sanity check for typos since sassdoc doesn't have any validation for this
179+ if ( ! isValidType ( type || "" ) ) {
180+ log . error ( `${ name } variable has an invalid @type declaration: "${ type } "` ) ;
181+ log . error ( `index is: "${ index } "` ) ;
182+ log . error ( ) ;
183+ process . exit ( 1 ) ;
184+ }
142185
143- let value : VariableValue = message . substring ( prefix . length ) ;
144- switch ( type ) {
145- case "List" : {
146- const parsed = value
147- . split ( / \s | , / )
148- . map ( ( part ) => parseValue ( part ) ) as SimplePrimative [ ] ;
186+ const output = renderSync ( {
187+ data : `@use 'sass:meta';
188+ @use 'sass:math';
149189
150- value = parsed ;
151- break ;
152- }
153- case "Map" :
154- value = parseMap ( value ) ;
155- break ;
156- default :
157- // sanity check for typos since sassdoc doesn't have any validation for this
158- if ( ! isValidType ( type || "" ) ) {
159- log . error (
160- `${ name } variable has an invalid @type declaration: "${ type } "`
161- ) ;
162- log . error ( ) ;
163- process . exit ( 1 ) ;
164- }
165- value = parseValue ( value ) ;
166- }
190+ @import '${ path } ';
167191
168- return {
169- name,
170- value,
171- } ;
192+ .output {
193+ --value: #{meta.inspect(${ originalValue } )};
194+ }
195+ ` ,
196+ outputStyle : "expanded" ,
197+ includePaths : [ tempStylesDir ] ,
198+ } ) . css . toString ( ) ;
199+ // since the `rmd-option-selected-content` is unicode, an `@charset` value
200+ // might also be rendered in the output
201+ const compiledValue = output
202+ . substring ( output . indexOf ( "--value" ) + "--value: " . length )
203+ . replace ( ";\n}" , "" ) ;
204+
205+ let value : VariableValue ;
206+ switch ( type ) {
207+ case "List" :
208+ value = compiledValue
209+ . split ( / \s | , / )
210+ . map ( ( part ) => parseValue ( part ) ) as SimplePrimative [ ] ;
211+ break ;
212+ case "Map" :
213+ try {
214+ value = parseMap ( compiledValue ) ;
215+ } catch ( e ) {
216+ log . error ( `Unable to parse the map: ${ name } ` ) ;
217+ log . error ( `index is: "${ index } "` ) ;
218+ log . error ( compiledValue ) ;
219+ if ( "message" in e ) {
220+ log . error ( e . message ) ;
221+ }
222+ process . exit ( 1 ) ;
223+ }
224+ break ;
225+ default :
226+ value = parseValue ( compiledValue ) ;
172227 }
228+
229+ return {
230+ name,
231+ value,
232+ } ;
173233}
0 commit comments