11/* eslint-disable no-continue, no-loop-func, no-cond-assign */
2+ import { mediaGetters } from './mediaGetters'
23import { propGetters } from './propGetters'
34
45// prop name is an ident: word chars, underscore and dash.
@@ -8,28 +9,79 @@ const PROP_CHAR = `[-\\w]`
89const VALUE_CHAR = `(?:\\\\.|[^\\\\;])`
910
1011// prettier-ignore
11- const PROP_REGEXP = new RegExp (
12+ const PROP_PATT = (
1213 `(${ PROP_CHAR } +)` + // capture prop name
1314 `(\\s*:\\s*)` + // colon & whitespace
1415 `(?=\\S)` + // prop value starts with non-whitespace
1516 `(${ VALUE_CHAR } *?)` + // capture prop value (non-greedy)
1617 `(\\s*!important)?` + // capture !important
17- `(\\s*;)` , // semi & whitespace
18- `gs` , // flags
18+ `(\\s*;)` // semi & whitespace
1919)
2020
21+ // simplistic but workable media query value.
22+ const MEDIA_CHAR = `[^{]`
23+
24+ // prettier-ignore
25+ const MEDIA_PATT = (
26+ `(@media\\b\\s*)` + // start of media query
27+ `(?=\\S)` + // value starts with non-whitespace
28+ `(${ MEDIA_CHAR } +?)` + // capture queries (non-greedy)
29+ `(\\s*\\{)` // brace & whitespace
30+ )
31+
32+ const MATCH_REGEXP = new RegExp ( `(?:${ PROP_PATT } |${ MEDIA_PATT } )` , `gs` )
33+
2134export function transform ( rawValue : any ) {
2235 if ( typeof rawValue !== 'string' ) return rawValue
2336 let matches
2437 let lastIndex = 0
2538 const values = [ ]
26- while ( ( matches = PROP_REGEXP . exec ( rawValue ) ) ) {
27- const [ , prop , colon , value , imp , semi ] = matches
28- const getter = ( propGetters as any ) [ prop ]
39+ while ( ( matches = MATCH_REGEXP . exec ( rawValue ) ) ) {
40+ const [ , prop , colon , value , imp , semi , media , query , brace ] = matches
41+ if ( media ) {
42+ values . push ( rawValue . slice ( lastIndex , matches . index ) )
43+ values . push ( media )
44+ mediaTransform ( query ) . forEach ( ( v ) => values . push ( v ) )
45+ values . push ( brace )
46+ lastIndex = matches . index + matches [ 0 ] . length
47+ } else {
48+ const getter = ( propGetters as any ) [ prop ]
49+ if ( getter ) {
50+ values . push ( rawValue . slice ( lastIndex , matches . index ) )
51+ values . push (
52+ ( p : object ) =>
53+ `${ prop } ${ colon } ${ getter ( value ) ( p ) } ${ imp || '' } ${ semi } ` ,
54+ )
55+ lastIndex = matches . index + matches [ 0 ] . length
56+ }
57+ }
58+ }
59+ values . push ( rawValue . slice ( lastIndex , rawValue . length ) )
60+ return values
61+ }
62+
63+ // media query prop/value pairs such as (min-width: 1024px)
64+ // prettier-ignore
65+ const QUERY_REGEXP = new RegExp (
66+ `(\\(\\s*)` + // open paren, whitespace
67+ `(${ PROP_CHAR } +)` + // capture prop name
68+ `(\\s*:\\s*)` + // colon & whitespace
69+ `([^\\)]*?)` + // capture prop value (non-greedy)
70+ `(\\s*\\))` , // close paren, whitespace
71+ `gs`
72+ )
73+
74+ function mediaTransform ( rawValue : string ) {
75+ let matches
76+ let lastIndex = 0
77+ const values = [ ]
78+ while ( ( matches = QUERY_REGEXP . exec ( rawValue ) ) ) {
79+ const [ , open , prop , colon , value , close ] = matches
80+ const getter = ( mediaGetters as any ) [ prop ]
2981 if ( getter ) {
3082 values . push ( rawValue . slice ( lastIndex , matches . index ) )
3183 values . push (
32- ( p : object ) => `${ prop } ${ colon } ${ getter ( value ) ( p ) } ${ imp || '' } ${ semi } ` ,
84+ ( p : object ) => `${ open } ${ prop } ${ colon } ${ getter ( value ) ( p ) } ${ close } ` ,
3385 )
3486 lastIndex = matches . index + matches [ 0 ] . length
3587 }
0 commit comments