From 253a70eceab21b6fd833bd7388104ae5dd1a6968 Mon Sep 17 00:00:00 2001 From: Thomas Kelly Date: Thu, 18 Sep 2025 09:53:40 -0400 Subject: [PATCH 1/2] fix: Support theme snippets in subfolders --- src/utilities/nodes.ts | 7 +++++-- test/commands/theme/component/map.test.ts | 6 ++++++ test/fixtures/theme/component.manifest.json | 4 +++- test/fixtures/theme/sections/subfolder.liquid | 2 ++ .../theme/snippets/subfolder/existing-subfolder.liquid | 1 + .../theme/snippets/subfolder/missing-subfolder.liquid | 1 + 6 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 test/fixtures/theme/sections/subfolder.liquid create mode 100644 test/fixtures/theme/snippets/subfolder/existing-subfolder.liquid create mode 100644 test/fixtures/theme/snippets/subfolder/missing-subfolder.liquid diff --git a/src/utilities/nodes.ts b/src/utilities/nodes.ts index f0cf0f1..c633ff9 100644 --- a/src/utilities/nodes.ts +++ b/src/utilities/nodes.ts @@ -79,11 +79,14 @@ export async function generateLiquidNode(file: string, type: LiquidNode['type'], .filter(file => !fs.statSync(file).isDirectory()) } + // For theme snippets, use just the filename (flatten subfolder structure) + const name = path.basename(file) + return { assets, body, file, - name: path.basename(file), + name, setup, snippets, themeFolder, @@ -122,7 +125,7 @@ export async function getThemeNodes(themeDir: string): Promise { const parentFolderName = path.basename(path.dirname(file)) as LiquidNode['themeFolder'] return generateLiquidNode(file, 'entry', parentFolderName) }) - const themeSnippets = globSync(path.join(themeDir, 'snippets', '*.liquid'), { absolute: true }) + const themeSnippets = globSync(path.join(themeDir, 'snippets', '**/*.liquid'), { absolute: true }) .map(file => generateLiquidNode(file, 'snippet', 'snippets')) const themeAssets = globSync(path.join(themeDir, 'assets', '*'), { absolute: true }) .map(file => generateLiquidNode(file, 'asset', 'assets')) diff --git a/test/commands/theme/component/map.test.ts b/test/commands/theme/component/map.test.ts index 6d34946..29c2e53 100644 --- a/test/commands/theme/component/map.test.ts +++ b/test/commands/theme/component/map.test.ts @@ -63,6 +63,7 @@ describe('theme component map', () => { const beforeData = JSON.parse(fs.readFileSync(path.join(testThemePath, 'component.manifest.json'), 'utf8')) expect(beforeData.files.assets['missing.css']).to.be.undefined expect(beforeData.files.snippets['missing.liquid']).to.be.undefined + expect(beforeData.files.snippets['missing-subfolder.liquid']).to.be.undefined await runCommand(['theme', 'component', 'map', testThemePath]) @@ -70,6 +71,7 @@ describe('theme component map', () => { const data = JSON.parse(fs.readFileSync(path.join(testThemePath, 'component.manifest.json'), 'utf8')) expect(data.files.assets['missing.css']).to.equal('@theme') expect(data.files.snippets['missing.liquid']).to.equal('@theme') + expect(data.files.snippets['missing-subfolder.liquid']).to.equal('@theme') }) it('adds entries for newly referenced components from current collection', async () => { @@ -177,12 +179,14 @@ describe('theme component map', () => { expect(beforeData.files.assets['theme-component.css']).to.equal('@theme') expect(beforeData.files.snippets['other-collection-component.liquid']).to.equal('@other/collection') expect(beforeData.files.assets['other-collection-component.css']).to.equal('@other/collection') + expect(beforeData.files.snippets['existing-subfolder.liquid']).to.equal('@theme') // Check that removed files are present in map expect(beforeData.files.snippets['theme-component-removed.liquid']).to.equal('@theme') expect(beforeData.files.assets['theme-component-removed.css']).to.equal('@theme') expect(beforeData.files.snippets['other-collection-component-removed.liquid']).to.equal('@other/collection') expect(beforeData.files.assets['other-collection-component-removed.css']).to.equal('@other/collection') + expect(beforeData.files.snippets['removed-subfolder.liquid']).to.equal('@theme') await runCommand(['theme', 'component', 'map', testThemePath]) @@ -193,12 +197,14 @@ describe('theme component map', () => { expect(data.files.assets['theme-component.css']).to.equal('@theme') expect(data.files.snippets['other-collection-component.liquid']).to.equal('@other/collection') expect(data.files.assets['other-collection-component.css']).to.equal('@other/collection') + expect(data.files.snippets['existing-subfolder.liquid']).to.equal('@theme') // Check that removed files are no longer present in map expect(data.files.snippets['theme-component-removed.liquid']).to.be.undefined expect(data.files.assets['theme-component-removed.css']).to.be.undefined expect(data.files.snippets['other-collection-component-removed.liquid']).to.be.undefined expect(data.files.assets['other-collection-component-removed.css']).to.be.undefined + expect(data.files.snippets['removed-subfolder.liquid']).to.be.undefined }) it('sorts the files and collections keys in the component.map.json file', async () => { diff --git a/test/fixtures/theme/component.manifest.json b/test/fixtures/theme/component.manifest.json index 5622823..6470e32 100644 --- a/test/fixtures/theme/component.manifest.json +++ b/test/fixtures/theme/component.manifest.json @@ -14,7 +14,9 @@ "override.liquid": "@theme", "override-parent.liquid": "@theme", "to-be-copied.liquid": "@archetype-themes/test-collection", - "to-be-copied-snippet.liquid": "@archetype-themes/test-collection" + "to-be-copied-snippet.liquid": "@archetype-themes/test-collection", + "existing-subfolder.liquid": "@theme", + "removed-subfolder.liquid": "@theme" }, "assets": { "other-collection-component.css": "@other/collection", diff --git a/test/fixtures/theme/sections/subfolder.liquid b/test/fixtures/theme/sections/subfolder.liquid new file mode 100644 index 0000000..ee67afc --- /dev/null +++ b/test/fixtures/theme/sections/subfolder.liquid @@ -0,0 +1,2 @@ +{% render 'existing-subfolder' %} +{% render 'missing-subfolder' %} \ No newline at end of file diff --git a/test/fixtures/theme/snippets/subfolder/existing-subfolder.liquid b/test/fixtures/theme/snippets/subfolder/existing-subfolder.liquid new file mode 100644 index 0000000..38f8675 --- /dev/null +++ b/test/fixtures/theme/snippets/subfolder/existing-subfolder.liquid @@ -0,0 +1 @@ +{% comment %} This file is included in the manifest.json {% endcomment %} \ No newline at end of file diff --git a/test/fixtures/theme/snippets/subfolder/missing-subfolder.liquid b/test/fixtures/theme/snippets/subfolder/missing-subfolder.liquid new file mode 100644 index 0000000..6e0d556 --- /dev/null +++ b/test/fixtures/theme/snippets/subfolder/missing-subfolder.liquid @@ -0,0 +1 @@ +{% comment %} This file is not included in the manifest.json {% endcomment %} \ No newline at end of file From 0c38f356a3f075d45a0de42ffdbc0fc3f6f41469 Mon Sep 17 00:00:00 2001 From: Thomas Kelly Date: Thu, 18 Sep 2025 12:35:04 -0400 Subject: [PATCH 2/2] Add other subfolders --- src/utilities/nodes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utilities/nodes.ts b/src/utilities/nodes.ts index c633ff9..d33250c 100644 --- a/src/utilities/nodes.ts +++ b/src/utilities/nodes.ts @@ -120,7 +120,7 @@ export async function getCollectionNodes(collectionDir: string): Promise { - const entryNodes = globSync(path.join(themeDir, '{layout,sections,blocks,templates}', '*.liquid'), { absolute: true }) + const entryNodes = globSync(path.join(themeDir, '{layout,sections,blocks,templates}', '**/*.liquid'), { absolute: true }) .map(file => { const parentFolderName = path.basename(path.dirname(file)) as LiquidNode['themeFolder'] return generateLiquidNode(file, 'entry', parentFolderName)