A stylesheet language written in TypeScript that compiles to CSS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ruleSet.ts 2.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import * as AST from '../ast';
  2. import Env, { EnvError } from '../env';
  3. export class RuleSet {
  4. public selectors: AST.Selector[];
  5. public children: AST.Child[];
  6. public constructor(selectors: AST.Selector[], children: AST.Child[] = []) {
  7. this.selectors = selectors;
  8. this.children = children;
  9. }
  10. public compile(env: Env, opts: AST.Opts): string | EnvError {
  11. const lineSpacer = opts.prettyPrint ? '\n' : '';
  12. const wordSpacer = opts.prettyPrint ? ' ' : '';
  13. const indentSpacer = opts.prettyPrint ? Array(opts.depth).fill(' ').join('') : '';
  14. const [lBrace, rBrace] = ['{', '}'];
  15. const lineages = ([] as string[]).concat(
  16. ...this.selectors.map((sel) => sel.getLineages())
  17. );
  18. const rules: (String | EnvError)[] = [];
  19. const children: (String | EnvError)[] = [];
  20. for (const child of this.children) {
  21. if (child instanceof AST.Rule) {
  22. rules.push(child.compile(env, opts));
  23. } else if (child instanceof RuleSet) {
  24. children.push(child.compile(env, opts));
  25. } else if (child instanceof AST.Application) {
  26. const mixin = env.get(child.name.value);
  27. if (mixin instanceof EnvError) return mixin;
  28. if (mixin instanceof AST.Mixin) {
  29. const expansion = mixin.expand(env, opts, this.selectors, child.arguments);
  30. if (expansion instanceof EnvError) return expansion;
  31. expansion.rules.forEach((rule: String | EnvError) => rules.push(rule));
  32. expansion.children.forEach((child: String | EnvError) => children.push(child));
  33. }
  34. }
  35. }
  36. const rulesError = rules.find((node) => node instanceof EnvError);
  37. if (rulesError instanceof EnvError) return rulesError;
  38. const childrenError = children.find((node) => node instanceof EnvError);
  39. if (childrenError instanceof EnvError) return childrenError;
  40. const compiledRules = rules.join(lineSpacer);
  41. const compiledChildren = children.join(lineSpacer);
  42. const lineage = lineages.join(`,${wordSpacer}`);
  43. const frontMatter = `${indentSpacer}${lineage}${wordSpacer}${lBrace}${lineSpacer}`;
  44. const backMatter = `${lineSpacer}${indentSpacer}${rBrace}${
  45. compiledChildren.length ? lineSpacer : ''
  46. }`;
  47. return rules.length
  48. ? `${frontMatter}${compiledRules}${backMatter}${compiledChildren}`
  49. : compiledChildren;
  50. }
  51. }