diff --git a/src/index.js b/src/index.js index c940dd2..1eb08b5 100644 --- a/src/index.js +++ b/src/index.js @@ -52,12 +52,24 @@ export function layer_tree_from_ast(ast) { } } } else { + // prelude.children contains the individual segments for dotted notation + // e.g., @layer base.props {} has children: ["base", "props"] + let layer_names = [] for (let child of node.prelude.children) { if (child.type === LAYER_NAME) { - root.add_child(current_stack, child.text, create_location(node)) - current_stack.push(child.text) + layer_names.push(child.text) } } + // Add each layer in the hierarchy + for (let i = 0; i < layer_names.length; i++) { + let layer_name = layer_names[i] + if (!layer_name) continue + let path = layer_names.slice(0, i) + let loc = i === layer_names.length - 1 ? create_location(node) : undefined + root.add_child(current_stack.concat(path), layer_name, loc) + } + // Push all layers to the stack + current_stack.push(...layer_names) } } else { let name = get_anonymous_id() @@ -90,15 +102,17 @@ export function layer_tree_from_ast(ast) { if (node.name === 'layer') { if (node.prelude && node.has_block) { + // Count how many layer segments we pushed + let layer_count = 0 for (let child of node.prelude.children) { if (child.type === LAYER_NAME) { - let layer_names = get_layer_names(child.text) - for (let i = 0; i < layer_names.length; i++) { - current_stack.pop() - } - break + layer_count++ } } + // Pop all of them + for (let i = 0; i < layer_count; i++) { + current_stack.pop() + } } else { // pop the anonymous layer current_stack.pop() diff --git a/test/global.spec.js b/test/global.spec.js index 0f08623..570b754 100644 --- a/test/global.spec.js +++ b/test/global.spec.js @@ -146,4 +146,238 @@ test('the fokus.dev boilerplate', () => { assert.equal(actual, expected) }) +test('nerdy.dev', () => { + let actual = layer_tree(` + @layer base.props {} + @layer base.normalize {} + @layer base.normalize {} + @layer base.theme {} + @layer base.utilities {} + @layer base.containers {} + @layer base.nojs {} + @layer base.normalize {} + + @layer components.links {} + @layer components.toast {} + @layer components.markdown {} + @layer components.syntax {} + @layer components.p3 {} + @layer components.quote {} + @layer components.fresh {} + + @layer overrides {} + `) + let expected = [ + { + name: 'base', + is_anonymous: false, + locations: [], + children: [ + { + name: 'props', + is_anonymous: false, + locations: [ + { + line: 2, + column: 3, + start: 3, + end: 23, + }, + ], + children: [], + }, + { + name: 'normalize', + is_anonymous: false, + locations: [ + { + line: 3, + column: 3, + start: 26, + end: 50, + }, + { + line: 4, + column: 3, + start: 53, + end: 77, + }, + { + line: 9, + column: 3, + start: 180, + end: 204, + }, + ], + children: [], + }, + { + name: 'theme', + is_anonymous: false, + locations: [ + { + line: 5, + column: 3, + start: 80, + end: 100, + }, + ], + children: [], + }, + { + name: 'utilities', + is_anonymous: false, + locations: [ + { + line: 6, + column: 3, + start: 103, + end: 127, + }, + ], + children: [], + }, + { + name: 'containers', + is_anonymous: false, + locations: [ + { + line: 7, + column: 3, + start: 130, + end: 155, + }, + ], + children: [], + }, + { + name: 'nojs', + is_anonymous: false, + locations: [ + { + line: 8, + column: 3, + start: 158, + end: 177, + }, + ], + children: [], + }, + ], + }, + { + name: 'components', + is_anonymous: false, + locations: [], + children: [ + { + name: 'links', + is_anonymous: false, + locations: [ + { + line: 11, + column: 3, + start: 208, + end: 234, + }, + ], + children: [], + }, + { + name: 'toast', + is_anonymous: false, + locations: [ + { + line: 12, + column: 3, + start: 237, + end: 263, + }, + ], + children: [], + }, + { + name: 'markdown', + is_anonymous: false, + locations: [ + { + line: 13, + column: 3, + start: 266, + end: 295, + }, + ], + children: [], + }, + { + name: 'syntax', + is_anonymous: false, + locations: [ + { + line: 14, + column: 3, + start: 298, + end: 325, + }, + ], + children: [], + }, + { + name: 'p3', + is_anonymous: false, + locations: [ + { + line: 15, + column: 3, + start: 328, + end: 351, + }, + ], + children: [], + }, + { + name: 'quote', + is_anonymous: false, + locations: [ + { + line: 16, + column: 3, + start: 354, + end: 380, + }, + ], + children: [], + }, + { + name: 'fresh', + is_anonymous: false, + locations: [ + { + line: 17, + column: 3, + start: 383, + end: 409, + }, + ], + children: [], + }, + ], + }, + { + name: 'overrides', + is_anonymous: false, + locations: [ + { + line: 19, + column: 3, + start: 413, + end: 432, + }, + ], + children: [], + }, + ] + assert.equal(actual, expected) +}) + test.run()