UNPKG

@chasemoskal/magical

Version:

web toolkit for lit apps

88 lines (74 loc) 2.13 kB
import {Token} from "./types.js" import {Expression} from "../../types.js" import {CamelCssMissingClosingBraceError, setupTracedErrors} from "../../errors.js" export function* parse(tokens: Iterable<Token.Any>) { type StackFrame = { selector: undefined | string ruleName: undefined | string rules: {[key: string]: string} childFrames: StackFrame[] } let frame: undefined | StackFrame const stack: StackFrame[] = [] for (const token of tokens) { const error = setupTracedErrors(token.trace) switch (token.type) { case Token.Type.Open: case Token.Type.AtRule: { frame = { selector: (token.type === Token.Type.AtRule) ? token.directive : token.selector.replaceAll(/\s+/gm, " "), ruleName: undefined, rules: {}, childFrames: [], } stack.push(frame) } break case Token.Type.RuleName: { if (!frame) throw error.ruleNamePlacement(token.name) frame.ruleName = token.name } break case Token.Type.RuleValue: { if (!frame || !frame.ruleName) throw error.ruleValuePlacement(token.value) frame.rules[frame.ruleName] = token.value frame.ruleName = undefined } break case Token.Type.Close: { const completedFrame = stack.pop() const parentFrame = stack.length > 0 ? stack[stack.length - 1] : undefined frame = parentFrame if (!completedFrame) throw error.excessClosingBrace() if (!completedFrame.selector) throw error.missingSelectorOrAtRule() if (parentFrame) parentFrame.childFrames.push(completedFrame) else { function recursiveFrameToExpression(frame: StackFrame): Expression { if (frame.selector!.startsWith("@")) { return [ frame.selector!, frame.childFrames.map(recursiveFrameToExpression), ] } else { return [ frame.selector!, frame.rules, frame.childFrames.map(recursiveFrameToExpression), ] } } yield recursiveFrameToExpression(completedFrame) } } break } } if (stack.length > 0) throw new CamelCssMissingClosingBraceError(stack.length) }