@zohofinance/commerce 1.0.1 → 2.0.0

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 (30) hide show
  1. package/README.md +0 -2
  2. package/package.json +2 -2
  3. package/public/iframe-bridge.js +1303 -0
  4. package/ts-dist/commands/serve-theme.d.ts.map +1 -1
  5. package/ts-dist/commands/serve-theme.js +488 -2
  6. package/ts-dist/custom-tags/sections-tag.d.ts.map +1 -1
  7. package/ts-dist/custom-tags/sections-tag.js +34 -8
  8. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/SKILL.md +2 -2
  9. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/ask-developer.md +1 -1
  10. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/dev-server-and-urls.md +14 -5
  11. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/subagent-escalation.md +1 -1
  12. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/visual-verify-loop.md +1 -1
  13. package/ts-dist/mocks/init-theme/.cursor/agents/visual-compare.md +2 -2
  14. package/ts-dist/mocks/init-theme/.cursor/commands/build-theme.md +1 -1
  15. package/ts-dist/mocks/init-theme/.cursor/commands/compare-section.md +1 -1
  16. package/ts-dist/mocks/init-theme/.cursor/skills/browser-verify.md +1 -1
  17. package/ts-dist/utils/editor-attributes.d.ts +3 -0
  18. package/ts-dist/utils/editor-attributes.d.ts.map +1 -0
  19. package/ts-dist/utils/editor-attributes.js +24 -0
  20. package/ts-dist/utils/prepare-section-data.d.ts +4 -1
  21. package/ts-dist/utils/prepare-section-data.d.ts.map +1 -1
  22. package/ts-dist/utils/prepare-section-data.js +24 -1
  23. package/ts-dist/utils/resolve-schema-translations.d.ts +3 -0
  24. package/ts-dist/utils/resolve-schema-translations.d.ts.map +1 -0
  25. package/ts-dist/utils/resolve-schema-translations.js +61 -0
  26. package/ts-dist/utils/template-engine.d.ts.map +1 -1
  27. package/ts-dist/utils/template-engine.js +19 -5
  28. package/ts-dist/utils/theme-mocks.d.ts +2 -0
  29. package/ts-dist/utils/theme-mocks.d.ts.map +1 -0
  30. package/ts-dist/utils/theme-mocks.js +40 -0
@@ -11,14 +11,14 @@ URL paths vary by store and dev setup. **Never assume** `/` is home or `/collect
11
11
  Before starting or requesting the dev server, ask:
12
12
 
13
13
  > What is your **storeUrl** for local dev?
14
- > Example: `https://yourstore.zohocommerce.com`
14
+ > Example: `<your store url>`
15
15
 
16
16
  Record it in scratchpad:
17
17
 
18
18
  ```json
19
19
  // .claude/scratchpad/<theme>/dev-config.json
20
20
  {
21
- "store_url": "https://yourstore.zohocommerce.com",
21
+ "store_url": "<your store url>",
22
22
  "dev_server_port": 3000,
23
23
  "page_urls": {},
24
24
  "confirmed_by_developer": false
@@ -31,11 +31,15 @@ Do not hardcode a demo store URL unless the developer confirms it.
31
31
 
32
32
  ## Step 2 — Dev server (ask or start)
33
33
 
34
+ Pass the developer's store URL into `theme dev` via `--storeUrl`. Without it, the preview uses mock data only.
35
+
36
+ Use the value from Step 1 (`dev-config.json` → `store_url`) as `<your store url>`.
37
+
34
38
  **Option A — Developer starts it (preferred if already running):**
35
39
 
36
40
  ```bash
37
41
  cd <theme_name>
38
- yarn run dev --storeUrl=<store_url_from_developer>
42
+ npx @zohofinance/commerce theme dev --storeUrl=<your store url>
39
43
  ```
40
44
 
41
45
  Ask: *"Is the dev server already running on port 3000? If not, please start it with the command above (or tell me to start it)."*
@@ -43,9 +47,14 @@ Ask: *"Is the dev server already running on port 3000? If not, please start it w
43
47
  **Option B — Agent starts it:**
44
48
 
45
49
  1. Check: `lsof -i :3000`
46
- 2. If not running, start in background from theme folder with developer's `storeUrl`
50
+ 2. If not running, start in background from the theme folder:
51
+
52
+ ```bash
53
+ npx @zohofinance/commerce theme dev --storeUrl=<your store url>
54
+ ```
55
+
47
56
  3. Wait for "Preview theme in http://localhost:3000" (up to 30s)
48
- 4. Tell the developer: *"Dev server started with storeUrl …"*
57
+ 4. Tell the developer: *"Dev server started with your storeUrl."*
49
58
 
50
59
  If the server fails to start → stop and ask the developer to fix CLI/network issues. Do not proceed to visual verify.
51
60
 
@@ -10,7 +10,7 @@ Every question, blocker, or notification from a **page orchestrator** or **secti
10
10
  |---|---|
11
11
  | `needs-developer.md` written | Surface immediately in chat with section/page name |
12
12
  | `unresolved.md` with `blocking: true` | Batch into `AskUserQuestion` before continuing |
13
- | Dev server not running | Ask developer to start OR start with confirmed `storeUrl` |
13
+ | Dev server not running | Ask developer to start OR start with `npx @zohofinance/commerce theme dev --storeUrl=<your store url>` (confirmed `store_url`) |
14
14
  | Page URLs not confirmed | Pause build; run URL confirmation flow (`dev-server-and-urls.md`) |
15
15
  | Visual verify stuck after 3 iterations | Show CRITICAL items from `visual-diff.md` |
16
16
  | Subagent aborted / timed out | Report which page/section; parent takes over or re-spawns |
@@ -29,7 +29,7 @@ Also always run:
29
29
 
30
30
  ### 1. Preconditions
31
31
  - `dev-config.json` exists with `confirmed_by_developer: true` — see `dev-server-and-urls.md`
32
- - Dev server running with developer's `storeUrl` (ask them to start, or start and notify)
32
+ - Dev server running with developer's `storeUrl`: `npx @zohofinance/commerce theme dev --storeUrl=<your store url>` (ask them to start, or start and notify; value from `dev-config.json`)
33
33
  - Chrome DevTools MCP connected
34
34
  - Figma node ID in `figma-spec.json`
35
35
  - **Do not `navigate_page` until page URLs are confirmed with the developer**
@@ -30,9 +30,9 @@ lsof -i :3000 2>/dev/null || lsof -i :9292 2>/dev/null
30
30
  **If NOT running**, start it in background:
31
31
  ```bash
32
32
  cd <theme_name>
33
- yarn run dev --storeUrl=<store_url> &
33
+ npx @zohofinance/commerce theme dev --storeUrl=<your store url> &
34
34
  ```
35
- Wait for "compiled" or "ready" in output (up to 30 seconds).
35
+ Wait for "compiled" or "ready" in output (up to 30 seconds). Use `store_url` from the inputs / `dev-config.json` for `<your store url>`. Without `--storeUrl`, the preview uses mock data only.
36
36
 
37
37
  **If already running**, skip to Step 2.
38
38
 
@@ -292,7 +292,7 @@ NEXT STEPS:
292
292
  1. Review unresolved items above
293
293
  2. /compare-section <theme_name> <section> — only if unresolved items exist
294
294
  3. /qa-theme <theme_name> — full QA after any manual fixes
295
- 4. yarn run dev --storeUrl=<url> — preview in browser
295
+ 4. npx @zohofinance/commerce theme dev --storeUrl=<your store url> — preview in browser (live store data; omit `--storeUrl` for mock only)
296
296
  ```
297
297
 
298
298
  ---
@@ -36,7 +36,7 @@ ensuring consistency between what was built and what is verified.
36
36
  **Default mode (code compare):** Extracts values from code and Figma MCP data, compares numerically. Fast and precise for CSS/Tailwind property matching.
37
37
 
38
38
  **Visual mode (`--visual`):** Launches the `visual-compare` subagent (see `.cursor/agents/visual-compare.md`). This mode:
39
- 1. Ensures the dev server is running (`yarn run dev --storeUrl=<url>`)
39
+ 1. Ensures the dev server is running (`npx @zohofinance/commerce theme dev --storeUrl=<your store url>` — from `--store-url` / `dev-config.json`; without `--storeUrl`, preview uses mock data only)
40
40
  2. Uses Claude in Chrome to navigate to the page and screenshot the rendered section (desktop + mobile)
41
41
  3. Fetches the Figma screenshot via Figma MCP (`get_screenshot`)
42
42
  4. Visually compares both screenshots and reports differences
@@ -12,7 +12,7 @@ Single source of truth for browser automation during theme development.
12
12
 
13
13
  1. **Developer confirmed `storeUrl`** — recorded in `.claude/scratchpad/<theme>/dev-config.json`
14
14
  2. **Developer confirmed page URLs** — same file, `confirmed_by_developer: true`
15
- 3. Dev server running: `yarn run dev --storeUrl=<store_url>` (developer starts OR agent starts and notifies)
15
+ 3. Dev server running: `npx @zohofinance/commerce theme dev --storeUrl=<your store url>` (developer starts OR agent starts and notifies). Use `store_url` from `dev-config.json` for `<your store url>`. Without `--storeUrl`, the preview uses mock data only.
16
16
  4. Chrome DevTools MCP connected
17
17
  5. Figma node ID known for visual compare
18
18
 
@@ -0,0 +1,3 @@
1
+ export declare function buildSectionComponentAttr(sectionType: string, sectionKey: string, jsonType: string, displayName?: string): string;
2
+ export declare function buildBlockZcommerceAttributes(blockType: string, blockKey: string, sectionKey: string, jsonType: string, displayName?: string): string;
3
+ //# sourceMappingURL=editor-attributes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor-attributes.d.ts","sourceRoot":"","sources":["../../src/utils/editor-attributes.ts"],"names":[],"mappings":"AAAA,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CAUR;AAED,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CAYR"}
@@ -0,0 +1,24 @@
1
+ export function buildSectionComponentAttr(sectionType, sectionKey, jsonType, displayName) {
2
+ return JSON.stringify({
3
+ id: `section_${sectionKey}`,
4
+ 'data-zcommerce-section-id': '',
5
+ 'data-zcommerce-component-name': sectionType,
6
+ 'data-zcommerce-component-key': `section_${sectionKey}`,
7
+ 'data-zcommerce-json-type': jsonType,
8
+ 'data-zcommerce-display-name': displayName || sectionType,
9
+ settingid: `setting_section_${sectionType}`
10
+ });
11
+ }
12
+ export function buildBlockZcommerceAttributes(blockType, blockKey, sectionKey, jsonType, displayName) {
13
+ const id = `block_${blockKey}_section_${sectionKey}`;
14
+ const attrJson = JSON.stringify({
15
+ id,
16
+ 'data-zcommerce-section-id': `section_${sectionKey}`,
17
+ 'data-zcommerce-component-name': blockType,
18
+ 'data-zcommerce-component-key': id,
19
+ 'data-zcommerce-json-type': jsonType,
20
+ 'data-zcommerce-display-name': displayName || blockType,
21
+ settingid: `setting_block_${blockType}`
22
+ }).replace(/'/g, '&#39;');
23
+ return `data-zcommerce-component='${attrJson}'`;
24
+ }
@@ -6,12 +6,15 @@ type SchemaSetting = {
6
6
  };
7
7
  type SchemaBlock = {
8
8
  type: string;
9
+ name?: string;
9
10
  settings?: SchemaSetting[];
10
11
  };
11
12
  type SectionSchema = {
12
13
  settings?: SchemaSetting[];
13
14
  blocks?: SchemaBlock[];
14
15
  };
15
- export declare function prepareSectionData(sectionData: SectionsType[string], schemaData?: SectionSchema, sectionKey?: string): import("types/common").SectionType;
16
+ export declare function prepareSectionData(sectionData: SectionsType[string], schemaData?: SectionSchema, sectionKey?: string, editorOptions?: {
17
+ jsonType: string;
18
+ }, cwd?: string): import("types/common").SectionType;
16
19
  export {};
17
20
  //# sourceMappingURL=prepare-section-data.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prepare-section-data.d.ts","sourceRoot":"","sources":["../../src/utils/prepare-section-data.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;CAC5B,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;CACxB,CAAC;AAwFF,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,YAAY,CAAC,MAAM,CAAC,EACjC,UAAU,CAAC,EAAE,aAAa,EAC1B,UAAU,CAAC,EAAE,MAAM,sCAqDpB"}
1
+ {"version":3,"file":"prepare-section-data.d.ts","sourceRoot":"","sources":["../../src/utils/prepare-section-data.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;CAC5B,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;CACxB,CAAC;AAwFF,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,YAAY,CAAC,MAAM,CAAC,EACjC,UAAU,CAAC,EAAE,aAAa,EAC1B,UAAU,CAAC,EAAE,MAAM,EACnB,aAAa,CAAC,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,EACpC,GAAG,CAAC,EAAE,MAAM,sCAmFb"}
@@ -1,4 +1,6 @@
1
1
  import { resolveThemeAssetUrlsInValue } from './resolve-theme-asset-url.js';
2
+ import { buildBlockZcommerceAttributes } from './editor-attributes.js';
3
+ import { resolveSchemaName } from './resolve-schema-translations.js';
2
4
  function isBlankImagePickerValue(value) {
3
5
  if (value === null || value === '') {
4
6
  return true;
@@ -61,7 +63,7 @@ function normalizeBlocksRecursively(blockData, sectionKey) {
61
63
  normalizeBlocksRecursively(child, sectionKey);
62
64
  }
63
65
  }
64
- export function prepareSectionData(sectionData, schemaData, sectionKey) {
66
+ export function prepareSectionData(sectionData, schemaData, sectionKey, editorOptions, cwd) {
65
67
  normalizeBlocksRecursively(sectionData, sectionKey);
66
68
  if (schemaData?.settings && sectionData.settings) {
67
69
  applyImagePickerDefaults(sectionData.settings, schemaData.settings);
@@ -90,5 +92,26 @@ export function prepareSectionData(sectionData, schemaData, sectionKey) {
90
92
  return block;
91
93
  });
92
94
  }
95
+ if (editorOptions && Array.isArray(sectionData.blocks)) {
96
+ const { jsonType } = editorOptions;
97
+ const blockSchemaNameMap = new Map((schemaData?.blocks || []).map((b) => [b.type, b.name]));
98
+ sectionData.blocks = sectionData.blocks.map((block) => {
99
+ const rawKey = (block.block_key || block.id || '');
100
+ const cleanKey = rawKey.startsWith('block_')
101
+ ? rawKey.replace(/^block_/, '').replace(/_section_.*$/, '')
102
+ : rawKey;
103
+ const blockType = (block.type || '');
104
+ const existingDisplayName = block.display_name;
105
+ const displayName = existingDisplayName
106
+ || (cwd
107
+ ? resolveSchemaName(blockSchemaNameMap.get(blockType), blockType, cwd)
108
+ : blockType);
109
+ return {
110
+ ...block,
111
+ type: blockType,
112
+ zcommerce_attributes: buildBlockZcommerceAttributes(blockType, cleanKey, sectionKey || '', jsonType, displayName)
113
+ };
114
+ });
115
+ }
93
116
  return sectionData;
94
117
  }
@@ -0,0 +1,3 @@
1
+ export declare function resolveSchemaTranslations<T>(schema: T, cwd: string): T;
2
+ export declare function resolveSchemaName(name: string | undefined, fallback: string, cwd: string): string;
3
+ //# sourceMappingURL=resolve-schema-translations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-schema-translations.d.ts","sourceRoot":"","sources":["../../src/utils/resolve-schema-translations.ts"],"names":[],"mappings":"AA+CA,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,CAItE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAMjG"}
@@ -0,0 +1,61 @@
1
+ import path from 'path';
2
+ import fs from 'fs-extra';
3
+ const localeCache = new Map();
4
+ function loadSchemaLocale(cwd) {
5
+ if (localeCache.has(cwd))
6
+ return localeCache.get(cwd);
7
+ const filePath = path.join(cwd, 'i18n', 'en.schema.json');
8
+ try {
9
+ const locale = fs.existsSync(filePath)
10
+ ? JSON.parse(fs.readFileSync(filePath, 'utf-8'))
11
+ : null;
12
+ localeCache.set(cwd, locale);
13
+ return locale;
14
+ }
15
+ catch {
16
+ localeCache.set(cwd, null);
17
+ return null;
18
+ }
19
+ }
20
+ function lookupTKey(key, locale) {
21
+ const parts = key.slice(2).split('.');
22
+ let node = locale;
23
+ for (const part of parts) {
24
+ if (node == null || typeof node !== 'object')
25
+ return undefined;
26
+ node = node[part];
27
+ }
28
+ return typeof node === 'string' ? node : undefined;
29
+ }
30
+ function resolveTKeysIn(value, locale) {
31
+ if (typeof value === 'string' && value.startsWith('t:')) {
32
+ return lookupTKey(value, locale) ?? value;
33
+ }
34
+ if (Array.isArray(value)) {
35
+ return value.map((item) => resolveTKeysIn(item, locale));
36
+ }
37
+ if (value !== null && typeof value === 'object') {
38
+ const out = {};
39
+ for (const [k, v] of Object.entries(value)) {
40
+ out[k] = resolveTKeysIn(v, locale);
41
+ }
42
+ return out;
43
+ }
44
+ return value;
45
+ }
46
+ export function resolveSchemaTranslations(schema, cwd) {
47
+ const locale = loadSchemaLocale(cwd);
48
+ if (!locale)
49
+ return schema;
50
+ return resolveTKeysIn(schema, locale);
51
+ }
52
+ export function resolveSchemaName(name, fallback, cwd) {
53
+ if (!name)
54
+ return fallback;
55
+ if (!name.startsWith('t:'))
56
+ return name;
57
+ const locale = loadSchemaLocale(cwd);
58
+ if (!locale)
59
+ return name;
60
+ return lookupTKey(name, locale) ?? name;
61
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"template-engine.d.ts","sourceRoot":"","sources":["../../src/utils/template-engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAwBlC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,UAGN,MAAM,kBAAkB,CAAC;AAc1B,OAAO,EAEL,KAAK,YAAY,EAElB,MAAM,cAAc,CAAC;AAEtB,qBAAa,cAAc;;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,CAAC,QAAQ,CACT;IAEP,IAAI,OAAO,IAGK,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CADzE;IACD,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,EAGzE;IAED,OAAO,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QACzB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAM;IAEP,GAAG,EAAE,MAAM,CAAC;gBAEA,OAAO,gBAAK,EAAE,UAAU,EAAE,UAAU;IAQhD,iBAAiB,CAAC,OAAO,KAAK;IA+DxB,mBAAmB,CAAC,EACxB,QAAQ,EACR,IAAI,EACL,EAAE;QACD,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,OAAO,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC;IA+F7C,cAAc,CAAC,EACnB,aAAa,EACb,QAAQ,EACR,IAAI,EACL,EAAE;QACD,aAAa,EAAE,MAAM,EAAE,CAAC;QACxB,QAAQ,EAAE,YAAY,CAAC;QACvB,IAAI,EAAE,GAAG,CAAC;KACX;IA6FK,YAAY,CAAC,EACjB,MAAgB,EAChB,sBAAsB,EACtB,IAAI,EACL,EAAE;QACD,MAAM,EAAE,MAAM,CAAC;QACf,sBAAsB,EAAE,MAAM,CAAC;QAC/B,IAAI,EAAE,MAAM,CAAC;KACd;IAgBK,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAO1C,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAI/C,WAAW,CAAC,QAAQ,EAAE,MAAM;IAI5B,OAAO;CAGR"}
1
+ {"version":3,"file":"template-engine.d.ts","sourceRoot":"","sources":["../../src/utils/template-engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAwBlC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,UAGN,MAAM,kBAAkB,CAAC;AAgB1B,OAAO,EAEL,KAAK,YAAY,EAElB,MAAM,cAAc,CAAC;AAEtB,qBAAa,cAAc;;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,CAAC,QAAQ,CACT;IAEP,IAAI,OAAO,IAGK,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CADzE;IACD,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,EAGzE;IAED,OAAO,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QACzB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAM;IAEP,GAAG,EAAE,MAAM,CAAC;gBAEA,OAAO,gBAAK,EAAE,UAAU,EAAE,UAAU;IAQhD,iBAAiB,CAAC,OAAO,KAAK;IA+DxB,mBAAmB,CAAC,EACxB,QAAQ,EACR,IAAI,EACL,EAAE;QACD,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,OAAO,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC;IA+F7C,cAAc,CAAC,EACnB,aAAa,EACb,QAAQ,EACR,IAAI,EACL,EAAE;QACD,aAAa,EAAE,MAAM,EAAE,CAAC;QACxB,QAAQ,EAAE,YAAY,CAAC;QACvB,IAAI,EAAE,GAAG,CAAC;KACX;IA+GK,YAAY,CAAC,EACjB,MAAgB,EAChB,sBAAsB,EACtB,IAAI,EACL,EAAE;QACD,MAAM,EAAE,MAAM,CAAC;QACf,sBAAsB,EAAE,MAAM,CAAC;QAC/B,IAAI,EAAE,MAAM,CAAC;KACd;IAgBK,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAO1C,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAI/C,WAAW,CAAC,QAAQ,EAAE,MAAM;IAI5B,OAAO;CAGR"}
@@ -7,9 +7,11 @@ import { LiquidError } from '../utils/liquid-error.js';
7
7
  import { extractLiquidErrorLocation, toThemeRelativePath } from './stack-trace.js';
8
8
  import { promises as fs } from 'fs';
9
9
  import { prepareSectionData } from './prepare-section-data.js';
10
+ import { buildSectionComponentAttr } from './editor-attributes.js';
10
11
  import { normalizeLiquidBlankAssignments } from './normalize-liquid-blank.js';
11
12
  import { createNormalizedLiquidFs } from './normalized-liquid-fs.js';
12
13
  import { resolveSchemaSettings } from './resolve-schema-settings.js';
14
+ import { resolveSchemaName } from './resolve-schema-translations.js';
13
15
  import { attachCliStackTrace, withLiquidRenderFrame, renderTrackedLiquidFile, renderTrackedLiquidString } from './liquid-render-frame.js';
14
16
  export class TemplateEngine {
15
17
  engine;
@@ -159,6 +161,8 @@ export class TemplateEngine {
159
161
  async renderSections({ section_order, sections, data }) {
160
162
  let renderedSection = '';
161
163
  let renderedSectionsArr = [];
164
+ const editorMode = this.engine.__editorMode;
165
+ const editorJsonType = this.engine.__editorJsonType || 'template';
162
166
  for (const section of section_order || []) {
163
167
  let sectionToRender = sections[section].type || '';
164
168
  let liquidSection = `sections/${sectionToRender}.liquid`;
@@ -189,14 +193,24 @@ export class TemplateEngine {
189
193
  console.error(`Failed to parse schema for section ${sectionToRender}:`, error);
190
194
  }
191
195
  }
192
- sections[section] = prepareSectionData(sections[section], schemaData, section);
196
+ sections[section] = prepareSectionData(sections[section], schemaData, section, editorMode ? { jsonType: editorJsonType } : undefined, this.cwd);
197
+ const sectionContext = {
198
+ ...sections[section],
199
+ id: `section_${section}`,
200
+ ...(editorMode ? {
201
+ settingid: `setting_section_${sectionToRender}`,
202
+ display_name: resolveSchemaName(schemaData?.name, sectionToRender, this.cwd)
203
+ } : {})
204
+ };
193
205
  let sectionData = await this.renderFile(this.getFilePath(`sections/${sectionToRender}.liquid`), {
194
206
  ...data,
195
- section: {
196
- ...sections[section],
197
- id: `section_${section}`
198
- }
207
+ section: sectionContext
199
208
  });
209
+ if (editorMode) {
210
+ const displayName = resolveSchemaName(schemaData?.name, sectionToRender, this.cwd);
211
+ const attrJson = buildSectionComponentAttr(sectionToRender, section, editorJsonType, displayName);
212
+ sectionData = `<div data-zcommerce-component='${attrJson.replace(/'/g, '&#39;')}' style="display:contents">${sectionData}</div>`;
213
+ }
200
214
  renderedSectionsArr.push(sectionData);
201
215
  }
202
216
  await Promise.all(renderedSectionsArr).then((arr) => {
@@ -0,0 +1,2 @@
1
+ export declare function getMock<T>(name: string, builtin: T): T;
2
+ //# sourceMappingURL=theme-mocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-mocks.d.ts","sourceRoot":"","sources":["../../src/utils/theme-mocks.ts"],"names":[],"mappings":"AAkCA,wBAAgB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAQtD"}
@@ -0,0 +1,40 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ /**
4
+ * Theme-level mock overrides for `theme dev` without --storeUrl.
5
+ *
6
+ * A theme may ship `mocks/<name>.json` next to `pages/` (e.g. mocks/products.json,
7
+ * mocks/global-objects.json). When present, it replaces the built-in mock of the same
8
+ * name, so a preview can use data that fits the theme. `mocks/` is not a theme folder:
9
+ * `theme build` never copies it and theme validation skips it.
10
+ *
11
+ * Objects are merged one level deep over the built-in (so a global-objects override can
12
+ * set just `store` and `menu` and keep `routes`); arrays and other values replace it.
13
+ * Files are read on every call so edits show up on the next page load.
14
+ */
15
+ const MOCKS_DIR = 'mocks';
16
+ function readOverride(name) {
17
+ const file = path.join(process.cwd(), MOCKS_DIR, `${name}.json`);
18
+ if (!fs.existsSync(file)) {
19
+ return undefined;
20
+ }
21
+ try {
22
+ return JSON.parse(fs.readFileSync(file, 'utf-8'));
23
+ }
24
+ catch (error) {
25
+ console.warn(`Ignoring ${MOCKS_DIR}/${name}.json: ${error.message}`);
26
+ return undefined;
27
+ }
28
+ }
29
+ function isPlainObject(value) {
30
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
31
+ }
32
+ export function getMock(name, builtin) {
33
+ const override = readOverride(name);
34
+ if (override === undefined) {
35
+ return builtin;
36
+ }
37
+ return isPlainObject(override) && isPlainObject(builtin)
38
+ ? { ...builtin, ...override }
39
+ : override;
40
+ }