Browse Source

Move mixin expansion logic into mixin class

master
Dylan Baker 3 years ago
parent
commit
51e7e43eb1
2 changed files with 47 additions and 25 deletions
  1. 43
    1
      src/ast/mixin.ts
  2. 4
    24
      src/ast/ruleSet.ts

+ 43
- 1
src/ast/mixin.ts View File

@@ -1,7 +1,12 @@
1 1
 import * as AST from '../ast';
2
-import Env from '../env';
2
+import Env, { EnvError } from '../env';
3 3
 import Token from '../token';
4 4
 
5
+interface Expansion {
6
+  rules: (String | EnvError)[];
7
+  children: (String | EnvError)[];
8
+}
9
+
5 10
 export class Mixin {
6 11
   public name: Token;
7 12
   public parameters: AST.Identifier[];
@@ -16,8 +21,45 @@ export class Mixin {
16 21
     this.parameters = parameters;
17 22
     this.children = children;
18 23
   }
24
+
19 25
   public compile(env: Env, _opts: AST.Opts) {
20 26
     env.set(this.name.value, this);
21 27
     return '';
22 28
   }
29
+
30
+  public expand(
31
+    env: Env,
32
+    opts: AST.Opts,
33
+    parents: AST.Selector[],
34
+    args: AST.Node[]
35
+  ): Expansion | EnvError {
36
+    if (this.parameters.length !== args.length) {
37
+      return new EnvError(
38
+        this.name.line,
39
+        `Expected ${this.parameters.length} arguments but received ${
40
+          args.length
41
+        }`
42
+      );
43
+    }
44
+
45
+    const mixinEnv = new Env(env);
46
+    this.parameters.forEach((param, index) => {
47
+      mixinEnv.set(param.name.value, args[index]);
48
+    });
49
+
50
+    const rules = this.children
51
+      .filter((child: AST.Node): child is AST.Rule => child instanceof AST.Rule)
52
+      .map((child: AST.Rule) => child.compile(mixinEnv, opts));
53
+
54
+    const children = this.children
55
+      .filter(
56
+        (child: AST.Node): child is AST.RuleSet => child instanceof AST.RuleSet
57
+      )
58
+      .map((child: AST.RuleSet) => {
59
+        child.selectors.forEach((sel) => (sel.parents = parents));
60
+        return child.compile(mixinEnv, opts);
61
+      });
62
+
63
+    return { rules, children };
64
+  }
23 65
 }

+ 4
- 24
src/ast/ruleSet.ts View File

@@ -32,30 +32,10 @@ export class RuleSet {
32 32
         const mixin = env.get(child.name.value);
33 33
         if (mixin instanceof EnvError) return mixin;
34 34
         if (mixin instanceof AST.Mixin) {
35
-          if (mixin.parameters.length !== child.arguments.length) {
36
-            return new EnvError(
37
-              child.name.value.line,
38
-              `Expected ${mixin.parameters.length} arguments but received ${
39
-                child.arguments.length
40
-              }`
41
-            );
42
-          }
43
-          const mixinEnv = new Env(env);
44
-          mixin.parameters.forEach((param, index) => {
45
-            mixinEnv.set(param.name.value, child.arguments[index]);
46
-          });
47
-          mixin.children.forEach((mixinChild) => {
48
-            if (mixinChild instanceof AST.Rule) {
49
-              rules.push(mixinChild.compile(mixinEnv, opts));
50
-            } else if (mixinChild instanceof RuleSet) {
51
-              mixinChild.selectors.map((sel) => {
52
-                sel.parents = this.selectors;
53
-              });
54
-              children.push(mixinChild.compile(mixinEnv, opts));
55
-            } else {
56
-              console.log(mixinChild);
57
-            }
58
-          });
35
+          const expansion = mixin.expand(env, opts, this.selectors, child.arguments);
36
+          if (expansion instanceof EnvError) return expansion;
37
+          expansion.rules.forEach((rule: String | EnvError) => rules.push(rule));
38
+          expansion.children.forEach((child: String | EnvError) => children.push(child));
59 39
         }
60 40
       }
61 41
     }

Loading…
Cancel
Save