import * as AST from '../ast'; import Env, { EnvError } from '../env'; export class RuleSet { public selectors: AST.Selector[]; public children: AST.Child[]; public constructor(selectors: AST.Selector[], children: AST.Child[] = []) { this.selectors = selectors; this.children = children; } public compile(env: Env, opts: AST.Opts): string | EnvError { const lineSpacer = opts.prettyPrint ? '\n' : ''; const wordSpacer = opts.prettyPrint ? ' ' : ''; const indentSpacer = opts.prettyPrint ? Array(opts.depth).fill(' ').join('') : ''; const [lBrace, rBrace] = ['{', '}']; const lineages = ([] as string[]).concat( ...this.selectors.map((sel) => sel.getLineages()) ); const rules: (String | EnvError)[] = []; const children: (String | EnvError)[] = []; for (const child of this.children) { if (child instanceof AST.Rule) { rules.push(child.compile(env, opts)); } else if (child instanceof RuleSet) { children.push(child.compile(env, opts)); } else if (child instanceof AST.Application) { const mixin = env.get(child.name.value); if (mixin instanceof EnvError) return mixin; if (mixin instanceof AST.Mixin) { const expansion = mixin.expand(env, opts, this.selectors, child.arguments); if (expansion instanceof EnvError) return expansion; expansion.rules.forEach((rule: String | EnvError) => rules.push(rule)); expansion.children.forEach((child: String | EnvError) => children.push(child)); } } } const rulesError = rules.find((node) => node instanceof EnvError); if (rulesError instanceof EnvError) return rulesError; const childrenError = children.find((node) => node instanceof EnvError); if (childrenError instanceof EnvError) return childrenError; const compiledRules = rules.join(lineSpacer); const compiledChildren = children.join(lineSpacer); const lineage = lineages.join(`,${wordSpacer}`); const frontMatter = `${indentSpacer}${lineage}${wordSpacer}${lBrace}${lineSpacer}`; const backMatter = `${lineSpacer}${indentSpacer}${rBrace}${ compiledChildren.length ? lineSpacer : '' }`; return rules.length ? `${frontMatter}${compiledRules}${backMatter}${compiledChildren}` : compiledChildren; } }