Last active
March 11, 2024 10:00
-
-
Save noih/9eae4b2fab4676a7b79b46c2200dece2 to your computer and use it in GitHub Desktop.
Parse CSS recursive version
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Parse CSS recursive version | |
* | |
* loop version https://gist.github.com/noih/e77bb88f2d08ac6b0df67217b4d22d95 | |
* | |
* @link https://playcode.io/1765882 | |
* @author noih.dev | |
*/ | |
type Style = Record<string, string> | |
const parse = ( | |
chars: string[], | |
styles: Record<string, Style> = {}, | |
context: { str?: string, selectors?: string[], brackets?: number, comment?: string } = {} | |
): Record<string, Style> => { | |
if (!chars.length) { return styles } | |
const [c, ...others] = chars | |
const { selectors = [], str = '', brackets = 0, comment } = context | |
if (typeof comment === 'string') { | |
if (c === '/' && comment.endsWith('*')) { | |
return parse(others, styles, { selectors, str, brackets }) | |
} | |
return parse(others, styles, { selectors, str, brackets, comment: comment + c }) | |
} | |
switch (c) { | |
case '{': return parse(others, styles, { selectors: [...selectors, str.trim()] }) | |
case '}': return parse(others, styles, { selectors: selectors.slice(0, -1) }) | |
case '(': return parse(others, styles, { selectors, str: str + c, brackets: brackets + 1 }) | |
case ')': return parse(others, styles, { selectors, str: str + c, brackets: brackets - 1 }) | |
case '*': { | |
if (str.endsWith('/')) { | |
return parse(others, styles, { selectors, str: str.slice(0, -1), brackets, comment: '' }) | |
} | |
return parse(others, styles, { selectors, str: str + c, brackets }) | |
} | |
case ';': { | |
if (brackets) { | |
return parse(others, styles, { selectors, str: str + c, brackets }) | |
} | |
const selector = selectors.join(' ') | |
const [key, ...values] = str.split(':') | |
return parse( | |
others, | |
{ | |
...styles, | |
[selector]: { | |
...styles[selector], | |
[key.trim()]: values.join(':').trim() | |
} | |
}, | |
{ selectors } | |
) | |
} | |
default: return parse(others, styles, { selectors, str: str + c, brackets }) | |
} | |
} | |
const css = ` | |
.select { | |
width: 475px; /* comment */ | |
height: 40px !important; | |
color: rgba(148.000006377697, 163.00000548362732, 184.00000423192978, 1); | |
background: url(http://localhost:5050/123:456;789.png) | |
0px 0px / 10px 8px no-repeat border-box; | |
} | |
` | |
const parsed = parse( | |
css | |
.replace(/\n/gm, ' ') | |
.replace(/\s+/gm, ' ') | |
.trim() | |
.split('') | |
) | |
console.log(parsed) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment