Skip to content

Instantly share code, notes, and snippets.

@noih
Last active March 11, 2024 10:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save noih/9eae4b2fab4676a7b79b46c2200dece2 to your computer and use it in GitHub Desktop.
Save noih/9eae4b2fab4676a7b79b46c2200dece2 to your computer and use it in GitHub Desktop.
Parse CSS recursive version
/**
* 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