@platformos/platformos-graph 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/getWebComponentMap.js +1 -1
  3. package/dist/getWebComponentMap.js.map +1 -1
  4. package/dist/graph/augment.js +0 -3
  5. package/dist/graph/augment.js.map +1 -1
  6. package/dist/graph/build.d.ts +2 -2
  7. package/dist/graph/build.js +11 -8
  8. package/dist/graph/build.js.map +1 -1
  9. package/dist/graph/module.d.ts +6 -9
  10. package/dist/graph/module.js +53 -117
  11. package/dist/graph/module.js.map +1 -1
  12. package/dist/graph/serialize.d.ts +2 -2
  13. package/dist/graph/serialize.js +2 -2
  14. package/dist/graph/serialize.js.map +1 -1
  15. package/dist/graph/test-helpers.d.ts +0 -13
  16. package/dist/graph/test-helpers.js +0 -10
  17. package/dist/graph/test-helpers.js.map +1 -1
  18. package/dist/graph/traverse.d.ts +3 -3
  19. package/dist/graph/traverse.js +19 -349
  20. package/dist/graph/traverse.js.map +1 -1
  21. package/dist/index.d.ts +3 -3
  22. package/dist/index.js +4 -6
  23. package/dist/index.js.map +1 -1
  24. package/dist/toSourceCode.d.ts +1 -4
  25. package/dist/toSourceCode.js +8 -52
  26. package/dist/toSourceCode.js.map +1 -1
  27. package/dist/tsconfig.tsbuildinfo +1 -1
  28. package/dist/types.d.ts +21 -78
  29. package/dist/types.js.map +1 -1
  30. package/dist/utils/index.d.ts +0 -3
  31. package/dist/utils/index.js +0 -18
  32. package/dist/utils/index.js.map +1 -1
  33. package/fixtures/skeleton/{layout/theme.liquid → app/views/layouts/application.liquid} +3 -4
  34. package/fixtures/skeleton/app/views/pages/index.liquid +5 -0
  35. package/fixtures/skeleton/app/views/partials/header.liquid +3 -0
  36. package/package.json +4 -4
  37. package/src/getWebComponentMap.ts +1 -1
  38. package/src/graph/augment.ts +1 -13
  39. package/src/graph/build.spec.ts +31 -171
  40. package/src/graph/build.ts +18 -14
  41. package/src/graph/module.ts +59 -135
  42. package/src/graph/serialize.spec.ts +22 -29
  43. package/src/graph/serialize.ts +2 -2
  44. package/src/graph/test-helpers.ts +1 -18
  45. package/src/graph/traverse.ts +28 -501
  46. package/src/index.ts +3 -3
  47. package/src/toSourceCode.ts +14 -55
  48. package/src/types.ts +23 -100
  49. package/src/utils/index.ts +0 -24
  50. package/fixtures/skeleton/blocks/_private.liquid +0 -1
  51. package/fixtures/skeleton/blocks/_static.liquid +0 -10
  52. package/fixtures/skeleton/blocks/group.liquid +0 -27
  53. package/fixtures/skeleton/blocks/render-static.liquid +0 -22
  54. package/fixtures/skeleton/blocks/text.liquid +0 -14
  55. package/fixtures/skeleton/jsconfig.json +0 -9
  56. package/fixtures/skeleton/sections/custom-section.liquid +0 -6
  57. package/fixtures/skeleton/sections/header-group.json +0 -36
  58. package/fixtures/skeleton/sections/header.liquid +0 -1
  59. package/fixtures/skeleton/templates/index.json +0 -20
@@ -1,56 +1,31 @@
1
- import { NamedTags, NodeTypes } from '@platformos/liquid-html-parser';
2
- import {
3
- JSONNode,
4
- nodeAtPath,
5
- ObjectNode,
6
- parseJSON,
7
- path,
8
- Preset,
9
- Section,
10
- SectionSchema,
11
- SourceCodeType,
12
- Template,
13
- ThemeBlock,
14
- ThemeBlockSchema,
15
- visit,
16
- Visitor,
17
- } from '@platformos/platformos-check-common';
1
+ import { NodeTypes } from '@platformos/liquid-html-parser';
2
+ import { SourceCodeType, visit, Visitor } from '@platformos/platformos-check-common';
18
3
  import {
19
4
  AugmentedDependencies,
20
- JsonModule,
21
- JsonModuleKind,
5
+ AppGraph,
6
+ AppModule,
22
7
  LiquidModule,
23
- LiquidModuleKind,
24
8
  ModuleType,
25
9
  Range,
26
10
  Reference,
27
- ThemeGraph,
28
- ThemeModule,
29
11
  Void,
30
12
  } from '../types';
31
- import { acceptsLocalBlocks, assertNever, exists, isString, unexpected, unique } from '../utils';
32
- import {
33
- getAssetModule,
34
- getLayoutModule,
35
- getSectionGroupModule,
36
- getSectionModule,
37
- getPartialModule,
38
- getThemeBlockModule,
39
- } from './module';
13
+ import { assertNever, exists, isString } from '../utils';
14
+ import { getAssetModule, getLayoutModule, getPartialModule } from './module';
40
15
 
41
16
  export async function traverseModule(
42
- module: ThemeModule,
43
- themeGraph: ThemeGraph,
17
+ module: AppModule,
18
+ appGraph: AppGraph,
44
19
  deps: AugmentedDependencies,
45
20
  ): Promise<Void> {
46
21
  // If the module is already traversed, skip it
47
- if (themeGraph.modules[module.uri]) {
22
+ if (appGraph.modules[module.uri]) {
48
23
  return;
49
24
  }
50
25
 
51
26
  // Signal to all users that the file is being traversed
52
27
  // This will prevent multiple traversals of the same file
53
- themeGraph.modules[module.uri] = module;
28
+ appGraph.modules[module.uri] = module;
54
29
 
55
30
  // Check if the module exists on disk
56
31
  module.exists = await exists(deps.fs, module.uri);
@@ -62,21 +37,11 @@ export async function traverseModule(
62
37
 
63
38
  switch (module.type) {
64
39
  case ModuleType.Liquid: {
65
- return traverseLiquidModule(module, themeGraph, deps);
40
+ return traverseLiquidModule(module, appGraph, deps);
66
41
  }
67
42
 
68
- case ModuleType.Json: {
69
- return traverseJsonModule(module, themeGraph, deps);
70
- }
71
-
72
- case ModuleType.JavaScript: {
73
- return; // TODO graph import/exports ?
74
- }
75
-
76
- case ModuleType.Css:
77
- case ModuleType.Svg:
78
- case ModuleType.Image: {
79
- return; // Nothing to do??
43
+ case ModuleType.Asset: {
44
+ return; // Nothing to traverse in assets
80
45
  }
81
46
 
82
47
  default: {
@@ -87,7 +52,7 @@ export async function traverseModule(
87
52
 
88
53
  async function traverseLiquidModule(
89
54
  module: LiquidModule,
90
- themeGraph: ThemeGraph,
55
+ appGraph: AppGraph,
91
56
  deps: AugmentedDependencies,
92
57
  ) {
93
58
  const sourceCode = await deps.getSourceCode(module.uri);
@@ -96,7 +61,7 @@ async function traverseLiquidModule(
96
61
 
97
62
  const visitor: Visitor<
98
63
  SourceCodeType.LiquidHtml,
99
- { target: ThemeModule; sourceRange: Range; targetRange?: Range }
64
+ { target: AppModule; sourceRange: Range; targetRange?: Range }
100
65
  > = {
101
66
  // {{ 'theme.js' | asset_url }}
102
67
  // {{ 'image.png' | asset_img_url }}
@@ -108,33 +73,15 @@ async function traverseLiquidModule(
108
73
  if (parentNode.expression.type !== NodeTypes.String) return;
109
74
  if (parentNode.filters[0] !== node) return;
110
75
  const asset = parentNode.expression.value;
111
- const module = getAssetModule(themeGraph, asset);
112
- if (!module) return;
76
+ const assetModule = getAssetModule(appGraph, asset);
77
+ if (!assetModule) return;
113
78
  return {
114
- target: module,
79
+ target: assetModule,
115
80
  sourceRange: [parentNode.position.start, parentNode.position.end],
116
81
  };
117
82
  }
118
83
  },
119
84
 
120
- // {% content_for 'block', type: 'staticBlockName', id: 'id' %}
121
- ContentForMarkup: async (node, ancestors) => {
122
- const parentNode = ancestors.at(-1)!;
123
- if (node.contentForType.value !== 'block') return;
124
- const blockTypeArg = node.args.find((arg) => arg.name === 'type');
125
- if (!blockTypeArg) return;
126
-
127
- const blockTypeValue = blockTypeArg.value;
128
- if (blockTypeValue.type !== NodeTypes.String) return;
129
-
130
- const blockType = blockTypeValue.value;
131
-
132
- return {
133
- target: getThemeBlockModule(themeGraph, blockType),
134
- sourceRange: [parentNode.position.start, node.position.end],
135
- };
136
- },
137
-
138
85
  // <custom-element></custom-element>
139
86
  HtmlElement: async (node) => {
140
87
  if (node.name.length !== 1) return;
@@ -146,11 +93,11 @@ async function traverseLiquidModule(
146
93
  const result = deps.getWebComponentDefinitionReference(nodeName);
147
94
  if (!result) return;
148
95
  const { assetName, range } = result;
149
- const module = getAssetModule(themeGraph, assetName);
150
- if (!module) return;
96
+ const assetModule = getAssetModule(appGraph, assetName);
97
+ if (!assetModule) return;
151
98
 
152
99
  return {
153
- target: module,
100
+ target: assetModule,
154
101
  sourceRange: [node.blockStartPosition.start, nodeNameNode.position.end],
155
102
  targetRange: range,
156
103
  };
@@ -162,37 +109,11 @@ async function traverseLiquidModule(
162
109
  const tag = ancestors.at(-1)!;
163
110
  if (!isString(snippet) && snippet.type === NodeTypes.String) {
164
111
  return {
165
- target: getPartialModule(themeGraph, snippet.value),
112
+ target: getPartialModule(appGraph, snippet.value),
166
113
  sourceRange: [tag.position.start, tag.position.end],
167
114
  };
168
115
  }
169
116
  },
170
-
171
- LiquidTag: async (node) => {
172
- switch (node.name) {
173
- // {% sections 'section-group' %}
174
- case NamedTags.sections: {
175
- if (!isString(node.markup)) {
176
- const sectionGroupType = node.markup.value;
177
- return {
178
- target: getSectionGroupModule(themeGraph, sectionGroupType),
179
- sourceRange: [node.position.start, node.position.end],
180
- };
181
- }
182
- }
183
-
184
- // {% section 'section' %}
185
- case NamedTags.section: {
186
- if (!isString(node.markup)) {
187
- const sectionType = node.markup.value;
188
- return {
189
- target: getSectionModule(themeGraph, sectionType),
190
- sourceRange: [node.position.start, node.position.end],
191
- };
192
- }
193
- }
194
- }
195
- },
196
117
  };
197
118
 
198
119
  const references = await visit(sourceCode.ast, visitor);
@@ -205,407 +126,13 @@ async function traverseLiquidModule(
205
126
  }
206
127
 
207
128
  const modules = unique(references.map((ref) => ref.target));
208
- const promises = modules.map((mod) => traverseModule(mod, themeGraph, deps));
209
-
210
- // Look at schema references if any
211
- if (module.kind === LiquidModuleKind.Section) {
212
- const sectionName = path.basename(module.uri, '.liquid');
213
- const sectionSchema = await deps.getSectionSchema(sectionName);
214
- promises.push(traverseLiquidSchema(sectionSchema, module, themeGraph, deps));
215
- } else if (module.kind === LiquidModuleKind.Block) {
216
- const blockName = path.basename(module.uri, '.liquid');
217
- const blockSchema = await deps.getBlockSchema(blockName);
218
- promises.push(traverseLiquidSchema(blockSchema, module, themeGraph, deps));
219
- }
220
-
221
- return Promise.all(promises);
222
- }
223
-
224
- async function traverseLiquidSchema(
225
- schema: SectionSchema | ThemeBlockSchema | undefined,
226
- module: LiquidModule,
227
- themeGraph: ThemeGraph,
228
- deps: AugmentedDependencies,
229
- ): Promise<Void> {
230
- if (!schema) return;
231
-
232
- const isSection = module.kind === LiquidModuleKind.Section;
233
- const hasLocalBlocks =
234
- isSection && (await acceptsLocalBlocks(path.basename(module.uri, '.liquid'), deps));
235
- if (hasLocalBlocks) return;
236
-
237
- const { ast, validSchema } = schema;
238
- if (validSchema instanceof Error || ast instanceof Error) return;
239
-
240
- const promises: Promise<Void>[] = [];
241
-
242
- // Traverse the blocks
243
- if (validSchema.blocks) {
244
- promises.push(traverseSchemaBlocks(schema, module, ast, validSchema.blocks, themeGraph, deps));
245
- }
246
-
247
- // Traverse the presets
248
- if (validSchema.presets) {
249
- promises.push(
250
- traverseSchemaPresets(schema, module, ast, validSchema.presets, themeGraph, deps),
251
- );
252
- }
253
-
254
- // Traverse section.default if it exists
255
- if ('default' in validSchema && validSchema.default) {
256
- promises.push(
257
- traverseSchemaDefault(
258
- schema as SectionSchema,
259
- module,
260
- ast,
261
- validSchema.default,
262
- themeGraph,
263
- deps,
264
- ),
265
- );
266
- }
267
-
268
- return Promise.all(promises);
269
- }
270
-
271
- async function traverseSchemaBlocks(
272
- schema: SectionSchema | ThemeBlockSchema,
273
- module: LiquidModule,
274
- ast: JSONNode,
275
- blocks: Section.Block[] | ThemeBlock.Block[],
276
- themeGraph: ThemeGraph,
277
- deps: AugmentedDependencies,
278
- ) {
279
- const promises: Promise<Void>[] = [];
280
-
281
- for (const [i, blockDef] of Object.entries(blocks)) {
282
- const nodePath = ['blocks', i];
283
- const node = nodeAtPath(ast, nodePath)! as ObjectNode;
284
- const typeProperty = node.children.find((child) => child.key.value === 'type');
285
- if (!typeProperty) continue;
286
-
287
- const sourceRange: Range = [
288
- schema.offset + typeProperty.loc.start.offset,
289
- schema.offset + typeProperty.loc.end.offset,
290
- ];
291
-
292
- // blocks: [{ "type": "@theme" }, { "type": "custom-block" }]
293
- switch (blockDef.type) {
294
- case '@theme': {
295
- const publicBlocks = await deps
296
- .getThemeBlockNames()
297
- .then((blocks) => blocks.filter((name) => !name.startsWith('_')));
298
- for (const publicBlock of publicBlocks) {
299
- const blockModule = getThemeBlockModule(
300
- themeGraph,
301
- path.basename(publicBlock, '.liquid'),
302
- );
303
- bind(module, blockModule, { sourceRange, type: 'indirect' });
304
- promises.push(traverseModule(blockModule, themeGraph, deps));
305
- }
306
-
307
- break;
308
- }
309
-
310
- case '@app': {
311
- break;
312
- }
313
-
314
- default: {
315
- const blockModule = getThemeBlockModule(themeGraph, blockDef.type);
316
- bind(module, blockModule, { sourceRange });
317
- promises.push(traverseModule(blockModule, themeGraph, deps));
318
- }
319
- }
320
- }
321
-
322
- return Promise.all(promises);
323
- }
324
-
325
- async function traverseSchemaPresets(
326
- schema: SectionSchema | ThemeBlockSchema,
327
- module: LiquidModule,
328
- ast: JSONNode,
329
- presets: Preset.Preset[],
330
- themeGraph: ThemeGraph,
331
- deps: AugmentedDependencies,
332
- ) {
333
- const promises: Promise<Void>[] = [];
334
-
335
- for (const [i, preset] of presets.entries()) {
336
- if (!('blocks' in preset)) continue;
337
-
338
- // Iterate over array entries or object entries depending on how the blocks are defined
339
- const iterator = Array.isArray(preset.blocks)
340
- ? preset.blocks.entries()
341
- : Object.entries(preset.blocks!);
342
-
343
- for (const [keyOrIndex, block] of iterator) {
344
- const nodePath = ['presets', i, 'blocks', keyOrIndex];
345
- const node = nodeAtPath(ast, nodePath)! as ObjectNode;
346
-
347
- const blockModule = getThemeBlockModule(themeGraph, block.type);
348
- if (!blockModule) continue;
349
-
350
- const typeProperty = node.children.find((child) => child.key.value === 'type');
351
- if (!typeProperty) continue;
352
-
353
- const sourceRange: Range = [
354
- schema.offset + typeProperty.loc.start.offset,
355
- schema.offset + typeProperty.loc.end.offset,
356
- ];
357
-
358
- bind(module, blockModule, { sourceRange, type: 'preset' });
359
- promises.push(traverseModule(blockModule, themeGraph, deps));
360
- if (block.blocks) {
361
- promises.push(
362
- traverseSchemaPresetBlock(schema, module, ast, block.blocks, nodePath, themeGraph, deps),
363
- );
364
- }
365
- }
366
- }
129
+ const promises = modules.map((mod) => traverseModule(mod, appGraph, deps));
367
130
 
368
131
  return Promise.all(promises);
369
132
  }
370
133
 
371
- async function traverseSchemaPresetBlock(
372
- schema: SectionSchema | ThemeBlockSchema,
373
- module: LiquidModule,
374
- ast: JSONNode,
375
- blocks: Preset.PresetBlockHash | Preset.PresetBlockForArray[],
376
- parentPath: (string | number)[],
377
- themeGraph: ThemeGraph,
378
- deps: AugmentedDependencies,
379
- ) {
380
- const promises: Promise<Void>[] = [];
381
-
382
- // Iterate over array entries or object entries depending on how the blocks are defined
383
- const iterator = Array.isArray(blocks) ? blocks.entries() : Object.entries(blocks);
384
-
385
- for (const [keyOrIndex, block] of iterator) {
386
- const nodePath = [...parentPath, 'blocks', keyOrIndex];
387
- const node = nodeAtPath(ast, nodePath)! as ObjectNode;
388
-
389
- const blockModule = getThemeBlockModule(themeGraph, block.type);
390
- if (!blockModule) continue;
391
-
392
- const typeProperty = node.children.find((child) => child.key.value === 'type');
393
- if (!typeProperty) continue;
394
-
395
- const sourceRange: Range = [
396
- schema.offset + typeProperty.loc.start.offset,
397
- schema.offset + typeProperty.loc.end.offset,
398
- ];
399
-
400
- bind(module, blockModule, { sourceRange, type: 'preset' });
401
- promises.push(traverseModule(blockModule, themeGraph, deps));
402
- if (block.blocks) {
403
- promises.push(
404
- traverseSchemaPresetBlock(schema, module, ast, block.blocks, nodePath, themeGraph, deps),
405
- );
406
- }
407
- }
408
-
409
- return Promise.all(promises);
410
- }
411
-
412
- async function traverseSchemaDefault(
413
- schema: SectionSchema,
414
- module: LiquidModule,
415
- ast: JSONNode,
416
- preset: Section.Default,
417
- themeGraph: ThemeGraph,
418
- deps: AugmentedDependencies,
419
- ) {
420
- const promises: Promise<Void>[] = [];
421
-
422
- if (!('blocks' in preset)) return;
423
-
424
- // Iterate over array entries or object entries depending on how the blocks are defined
425
- const iterator = Array.isArray(preset.blocks)
426
- ? preset.blocks.entries()
427
- : Object.entries(preset.blocks!);
428
-
429
- for (const [keyOrIndex, block] of iterator) {
430
- const nodePath = ['default', 'blocks', keyOrIndex];
431
- const node = nodeAtPath(ast, nodePath)! as ObjectNode;
432
-
433
- const blockModule = getThemeBlockModule(themeGraph, block.type);
434
- if (!blockModule) continue;
435
-
436
- const typeProperty = node.children.find((child) => child.key.value === 'type');
437
- if (!typeProperty) continue;
438
-
439
- const sourceRange: Range = [
440
- schema.offset + typeProperty.loc.start.offset,
441
- schema.offset + typeProperty.loc.end.offset,
442
- ];
443
-
444
- bind(module, blockModule, { sourceRange, type: 'preset' });
445
- promises.push(traverseModule(blockModule, themeGraph, deps));
446
- }
447
-
448
- return Promise.all(promises);
449
- }
450
-
451
- async function traverseJsonModule(
452
- module: JsonModule,
453
- themeGraph: ThemeGraph,
454
- deps: AugmentedDependencies,
455
- ): Promise<Void> {
456
- const sourceCode = await deps.getSourceCode(module.uri);
457
- if (sourceCode.type !== SourceCodeType.JSON) throw unexpected();
458
- const ast = sourceCode.ast;
459
- if (ast instanceof Error) return; // can't visit what you can't parse
460
-
461
- switch (module.kind) {
462
- case JsonModuleKind.Template: {
463
- // Should only happen once per template
464
- const template = parseJSON(sourceCode.source) as Template.Template;
465
- const promises: Promise<Void>[] = [];
466
- for (const [key, section] of Object.entries(template.sections)) {
467
- const sectionType = section.type;
468
- const path = ['sections', key];
469
- const node = nodeAtPath(ast, path)! as ObjectNode;
470
- const sectionModule = getSectionModule(themeGraph, sectionType);
471
- const typeProperty = node.children.find((child) => child.key.value === 'type')!;
472
- const start = typeProperty.loc.start.offset;
473
- const end = typeProperty.loc.end.offset;
474
- const sourceRange: Range = [start, end];
475
- // Link the template to the section
476
- bind(module, sectionModule, { sourceRange });
477
- promises.push(
478
- // Traverse the section themeselves
479
- traverseModule(sectionModule, themeGraph, deps),
480
- // Link the blocks used in the section to the template
481
- traverseSectionReferences(module, ast, path, section, themeGraph, deps),
482
- );
483
- }
484
-
485
- // Link the template to the layout
486
- const layout = template.layout;
487
- const layoutModule = getLayoutModule(themeGraph, template.layout);
488
- if (layoutModule) {
489
- let sourceRange: Range | undefined = undefined;
490
- let indirect = true;
491
- if (layout !== false && layout !== undefined) {
492
- const layoutPath = ['layout'];
493
- const node = nodeAtPath(ast, layoutPath)!;
494
- sourceRange = [node.loc.start.offset, node.loc.end.offset];
495
- indirect = false; // this is a direct reference to the layout
496
- }
497
- bind(module, layoutModule, { sourceRange, type: 'indirect' });
498
- promises.push(traverseModule(layoutModule, themeGraph, deps));
499
- }
500
-
501
- return Promise.all(promises);
502
- }
503
-
504
- case JsonModuleKind.SectionGroup: {
505
- const sectionGroup = parseJSON(sourceCode.source) as Template.SectionGroup;
506
- const promises: Promise<Void>[] = [];
507
- for (const [key, section] of Object.entries(sectionGroup.sections)) {
508
- const sectionType = section.type;
509
- const path = ['sections', key];
510
- const node = nodeAtPath(ast, path)! as ObjectNode;
511
- const sectionModule = getSectionModule(themeGraph, sectionType);
512
-
513
- const typeProperty = node.children.find((child) => child.key.value === 'type')!;
514
- const start = typeProperty.loc.start.offset;
515
- const end = typeProperty.loc.end.offset;
516
- const sourceRange: Range = [start, end];
517
-
518
- // Link the template to the section
519
- bind(module, sectionModule, { sourceRange });
520
- promises.push(
521
- // Traverse the section themeselves
522
- traverseModule(sectionModule, themeGraph, deps),
523
- // Link the blocks used in the section to the template
524
- traverseSectionReferences(module, ast, path, section, themeGraph, deps),
525
- );
526
- }
527
-
528
- return Promise.all(promises);
529
- }
530
-
531
- default: {
532
- return assertNever(module.kind);
533
- }
534
- }
535
- }
536
-
537
- /**
538
- * Traverses the actual references contained inside Template.Template['sections'] and Template.SectionGroup['sections'].
539
- *
540
- * Does nothing if the mode is not `GraphMode.Production`.
541
- */
542
- async function traverseSectionReferences(
543
- source: ThemeModule, // template or section group
544
- sourceAst: JSONNode,
545
- nodePath: string[] = [],
546
- section: Template.Section,
547
- themeGraph: ThemeGraph,
548
- deps: AugmentedDependencies,
549
- ): Promise<Void> {
550
- if (!section.blocks) return;
551
- const sectionHasLocalBlocks = await acceptsLocalBlocks(section.type, deps);
552
- if (sectionHasLocalBlocks) return;
553
-
554
- const promises: Promise<Void>[] = [];
555
-
556
- for (const [key, block] of Object.entries(section.blocks)) {
557
- const blockType = block.type;
558
- const blockModule = getThemeBlockModule(themeGraph, blockType);
559
- const path = [...nodePath, 'blocks', key];
560
- const node = nodeAtPath(sourceAst, path)! as ObjectNode;
561
- const typeProperty = node.children.find((child) => child.key.value === 'type')!;
562
- const start = typeProperty.loc.start.offset;
563
- const end = typeProperty.loc.end.offset;
564
- const sourceRange: Range = [start, end];
565
- // Link the template to the block
566
- bind(source, blockModule, { sourceRange });
567
- promises.push(
568
- // Traverse the block themselves
569
- traverseModule(blockModule, themeGraph, deps),
570
- // Traverse the block references
571
- traverseBlockReferences(source, sourceAst, path, block, themeGraph, deps),
572
- );
573
- }
574
-
575
- return Promise.all(promises);
576
- }
577
-
578
- async function traverseBlockReferences(
579
- source: ThemeModule, // template or section group
580
- sourceAst: JSONNode,
581
- nodePath: string[] = [],
582
- block: Template.Block,
583
- themeGraph: ThemeGraph,
584
- deps: AugmentedDependencies,
585
- ): Promise<Void> {
586
- if (!block.blocks) return;
587
-
588
- const promises: Promise<Void>[] = [];
589
- for (const [key, childBlock] of Object.entries(block.blocks)) {
590
- const childBlockType = childBlock.type;
591
- const childBlockModule = getThemeBlockModule(themeGraph, childBlockType);
592
- const path = [...nodePath, 'blocks', key];
593
- const node = nodeAtPath(sourceAst, path)! as ObjectNode;
594
- const typeProperty = node.children.find((child) => child.key.value === 'type')!;
595
- const start = typeProperty.loc.start.offset;
596
- const end = typeProperty.loc.end.offset;
597
- const sourceRange: Range = [start, end];
598
- // Link the template/section group to the block
599
- bind(source, childBlockModule, { sourceRange });
600
- promises.push(
601
- // Traverse the child block themselves
602
- traverseModule(childBlockModule, themeGraph, deps),
603
- // Traverse the child block references
604
- traverseBlockReferences(source, sourceAst, path, childBlock, themeGraph, deps),
605
- );
606
- }
607
-
608
- return Promise.all(promises);
134
+ function unique<T>(arr: T[]): T[] {
135
+ return [...new Set(arr)];
609
136
  }
610
137
 
611
138
  /**
@@ -616,12 +143,12 @@ async function traverseBlockReferences(
616
143
  * This function mutates the source and target modules.
617
144
  */
618
145
  export function bind(
619
- source: ThemeModule,
620
- target: ThemeModule,
146
+ source: AppModule,
147
+ target: AppModule,
621
148
  {
622
149
  sourceRange,
623
150
  targetRange,
624
- type = 'direct', // the type of dependency, can be 'direct', 'indirect' or 'preset'
151
+ type = 'direct', // the type of dependency, can be 'direct' or 'indirect'
625
152
  }: {
626
153
  sourceRange?: Range; // a range in the source module that references the child
627
154
  targetRange?: Range; // a range in the child module that is being referenced
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { buildThemeGraph } from './graph/build';
2
- export { serializeThemeGraph } from './graph/serialize';
1
+ export { buildAppGraph } from './graph/build';
2
+ export { serializeAppGraph } from './graph/serialize';
3
3
  export { getWebComponentMap, findWebComponentReferences } from './getWebComponentMap';
4
- export { toCssSourceCode, toJsSourceCode, toSourceCode, toSvgSourceCode } from './toSourceCode';
4
+ export { parseJs, toSourceCode } from './toSourceCode';
5
5
  export * from './types';