Quellcode durchsuchen

Compile mixin applications as long as mixins are not nested

master
Dylan Baker vor 5 Jahren
Ursprung
Commit
46e381f827
2 geänderte Dateien mit 49 neuen und 10 gelöschten Zeilen
  1. 37
    10
      src/ast.ts
  2. 12
    0
      src/tests/compiler.test.ts

+ 37
- 10
src/ast.ts Datei anzeigen

@@ -1,7 +1,6 @@
1 1
 import Env, { EnvError } from './env';
2 2
 import Token from './token';
3 3
 
4
-
5 4
 export namespace AST {
6 5
   export type Child = Rule | RuleSet | Application;
7 6
 
@@ -222,7 +221,11 @@ export namespace AST {
222 221
     public parameters: Identifier[];
223 222
     public children: Child[];
224 223
 
225
-    public constructor(name: Token, parameters: Identifier[], children: Child[]) {
224
+    public constructor(
225
+      name: Token,
226
+      parameters: Identifier[],
227
+      children: Child[]
228
+    ) {
226 229
       super();
227 230
       this.name = name;
228 231
       this.parameters = parameters;
@@ -260,12 +263,9 @@ export namespace AST {
260 263
 
261 264
   export class RuleSet extends Node {
262 265
     public selectors: Selector[];
263
-    public children: (Application | Rule | RuleSet)[];
266
+    public children: Child[];
264 267
 
265
-    public constructor(
266
-      selectors: Selector[],
267
-      children: (Application | Rule | RuleSet)[] = []
268
-    ) {
268
+    public constructor(selectors: Selector[], children: Child[] = []) {
269 269
       super();
270 270
       this.selectors = selectors;
271 271
       this.children = children;
@@ -284,15 +284,42 @@ export namespace AST {
284 284
       const rules: (String | EnvError)[] = [];
285 285
       const children: (String | EnvError)[] = [];
286 286
 
287
-      this.children.map((child) => {
287
+      for (const child of this.children) {
288 288
         if (child instanceof Rule) {
289 289
           rules.push(child.compile(env, opts));
290 290
         } else if (child instanceof RuleSet) {
291 291
           children.push(child.compile(env, opts));
292 292
         } else if (child instanceof Application) {
293
-          console.log(child.compile(env, opts));
293
+          const mixin = env.get(child.name.value);
294
+          if (mixin instanceof EnvError) return mixin;
295
+          if (mixin instanceof AST.Mixin) {
296
+            if (mixin.parameters.length !== child.arguments.length) {
297
+              return new EnvError(
298
+                child.name.value.line,
299
+                `Expected ${mixin.parameters.length} arguments but received ${
300
+                  child.arguments.length
301
+                }`
302
+              );
303
+            }
304
+            const mixinEnv = new Env(env);
305
+            mixin.parameters.forEach((param, index) => {
306
+              mixinEnv.set(param.name.value, child.arguments[index]);
307
+            });
308
+            mixin.children.forEach((mixinChild) => {
309
+              if (mixinChild instanceof Rule) {
310
+                rules.push(mixinChild.compile(mixinEnv, opts));
311
+              } else if (mixinChild instanceof RuleSet) {
312
+                mixinChild.selectors.map((sel) => {
313
+                  sel.parents = this.selectors;
314
+                });
315
+                children.push(mixinChild.compile(mixinEnv, opts));
316
+              } else {
317
+                console.log(mixinChild);
318
+              }
319
+            });
320
+          }
294 321
         }
295
-      });
322
+      }
296 323
 
297 324
       const rulesError = rules.find((node) => node instanceof EnvError);
298 325
       if (rulesError instanceof EnvError) return rulesError;

+ 12
- 0
src/tests/compiler.test.ts Datei anzeigen

@@ -169,3 +169,15 @@ test('compiles mixins', (t) => {
169 169
     ]
170 170
   ));
171 171
 });
172
+
173
+test('compiles mixin application', (t) => {
174
+  t.plan(1);
175
+  const result = compile('(@mixin centered ($width) :max-width $width :margin auto)(div (@centered 800px))');
176
+  t.equal(result, 'div{max-width:800px;margin:auto;}');
177
+});
178
+
179
+test('compiles mixin application with children', (t) => {
180
+  t.plan(1);
181
+  const result = compile('(@mixin heading-color ($color) (h1 :color $color))(div (@heading-color blue))');
182
+  t.equal(result, 'div h1{color:blue;}');
183
+});

Laden…
Abbrechen
Speichern