@wix/web5-core 1.57.2 → 1.58.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 (53) hide show
  1. package/dist/cjs/client/clientBundleUrl.js +40 -0
  2. package/dist/cjs/client/clientBundleUrl.js.map +1 -0
  3. package/dist/cjs/client/mergeClientConfig.js +59 -0
  4. package/dist/cjs/client/mergeClientConfig.js.map +1 -0
  5. package/dist/cjs/component/componentDefinitions/EntityCollectionSectionDefinition.js +159 -0
  6. package/dist/cjs/component/componentDefinitions/EntityCollectionSectionDefinition.js.map +1 -0
  7. package/dist/cjs/component/componentDefinitions/index.js +7 -1
  8. package/dist/cjs/component/componentDefinitions/index.js.map +1 -1
  9. package/dist/cjs/component/componentParser.js +38 -1
  10. package/dist/cjs/component/componentParser.js.map +1 -1
  11. package/dist/cjs/components/ui/SearchSection.css +66 -9
  12. package/dist/cjs/components/ui/SearchSection.js +23 -19
  13. package/dist/cjs/components/ui/SearchSection.js.map +1 -1
  14. package/dist/cjs/index.js +15 -3
  15. package/dist/cjs/index.js.map +1 -1
  16. package/dist/cjs/styles/prompt-input-tokens.css +41 -34
  17. package/dist/cjs/utils/matchDebug.js +93 -0
  18. package/dist/cjs/utils/matchDebug.js.map +1 -0
  19. package/dist/esm/client/clientBundleUrl.js +36 -0
  20. package/dist/esm/client/clientBundleUrl.js.map +1 -0
  21. package/dist/esm/client/mergeClientConfig.js +55 -0
  22. package/dist/esm/client/mergeClientConfig.js.map +1 -0
  23. package/dist/esm/component/componentDefinitions/EntityCollectionSectionDefinition.js +154 -0
  24. package/dist/esm/component/componentDefinitions/EntityCollectionSectionDefinition.js.map +1 -0
  25. package/dist/esm/component/componentDefinitions/index.js +7 -1
  26. package/dist/esm/component/componentDefinitions/index.js.map +1 -1
  27. package/dist/esm/component/componentParser.js +38 -1
  28. package/dist/esm/component/componentParser.js.map +1 -1
  29. package/dist/esm/components/ui/SearchSection.css +66 -9
  30. package/dist/esm/components/ui/SearchSection.js +5 -1
  31. package/dist/esm/components/ui/SearchSection.js.map +1 -1
  32. package/dist/esm/index.js +8 -1
  33. package/dist/esm/index.js.map +1 -1
  34. package/dist/esm/styles/prompt-input-tokens.css +41 -34
  35. package/dist/esm/utils/matchDebug.js +85 -0
  36. package/dist/esm/utils/matchDebug.js.map +1 -0
  37. package/dist/types/client/clientBundleUrl.d.ts +17 -0
  38. package/dist/types/client/clientBundleUrl.d.ts.map +1 -0
  39. package/dist/types/client/mergeClientConfig.d.ts +28 -0
  40. package/dist/types/client/mergeClientConfig.d.ts.map +1 -0
  41. package/dist/types/component/componentDefinitions/EntityCollectionSectionDefinition.d.ts +51 -0
  42. package/dist/types/component/componentDefinitions/EntityCollectionSectionDefinition.d.ts.map +1 -0
  43. package/dist/types/component/componentDefinitions/index.d.ts +1 -0
  44. package/dist/types/component/componentDefinitions/index.d.ts.map +1 -1
  45. package/dist/types/component/componentParser.d.ts.map +1 -1
  46. package/dist/types/components/ui/SearchSection.d.ts.map +1 -1
  47. package/dist/types/index.d.ts +4 -1
  48. package/dist/types/index.d.ts.map +1 -1
  49. package/dist/types/utils/matchDebug.d.ts +38 -0
  50. package/dist/types/utils/matchDebug.d.ts.map +1 -0
  51. package/package.json +2 -2
  52. package/src/components/ui/SearchSection.css +66 -9
  53. package/src/styles/prompt-input-tokens.css +41 -34
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.setMatchDebug = exports.resetMatchDebugCache = exports.logMatchDebug = exports.isMatchDebugEnabled = exports.MATCH_DEBUG_QUERY_PARAM = exports.MATCH_DEBUG_KEY = void 0;
5
+ /**
6
+ * Section-match tracing (debug-only).
7
+ *
8
+ * Turns the otherwise silent matching loop in `tryParseComponent` into a
9
+ * console trace: which definitions the active registry holds and in what
10
+ * order, which patterns were tried against a block, why each one failed, and
11
+ * when a matching definition then returned `null` from `parse()` and let the
12
+ * block fall through to the next candidate.
13
+ *
14
+ * Answers the two questions a "my section isn't rendering" report always
15
+ * splits into — *is my definition even registered?* (a missing entry in the
16
+ * registry order line usually means a stale bundle or a `web5-core` version
17
+ * skew; see the warning in `ComponentRegistry.register`) and *did it lose the
18
+ * match, or lose the parse?*
19
+ *
20
+ * Off by default. Enable with `?web5DebugMatch=1` (one-shot, wins over
21
+ * storage) or `localStorage["web5_debug_match"] = "1"` (sticky). Resolved once
22
+ * per page load — the tracing is on the hot parse path, so it must not read
23
+ * storage per block.
24
+ */
25
+
26
+ const MATCH_DEBUG_KEY = exports.MATCH_DEBUG_KEY = 'web5_debug_match';
27
+
28
+ /** Query param that forces match tracing on, overriding localStorage. */
29
+ const MATCH_DEBUG_QUERY_PARAM = exports.MATCH_DEBUG_QUERY_PARAM = 'web5DebugMatch';
30
+ const LOG_PREFIX = '[web5:match]';
31
+ const isTruthy = value => value === '1' || value === 'true';
32
+ let cached = null;
33
+
34
+ /**
35
+ * Whether match tracing is enabled. Memoized: the parse loop calls this for
36
+ * every block of every turn.
37
+ */
38
+ const isMatchDebugEnabled = () => {
39
+ if (cached !== null) {
40
+ return cached;
41
+ }
42
+ cached = false;
43
+ try {
44
+ if (isTruthy(new URLSearchParams(window.location.search).get(MATCH_DEBUG_QUERY_PARAM))) {
45
+ cached = true;
46
+ return cached;
47
+ }
48
+ } catch {
49
+ // window / URLSearchParams unavailable (SSR, non-DOM environments).
50
+ }
51
+ try {
52
+ cached = isTruthy(localStorage.getItem(MATCH_DEBUG_KEY));
53
+ } catch {
54
+ // localStorage can throw in privacy mode / non-DOM environments.
55
+ }
56
+ return cached;
57
+ };
58
+
59
+ /** Persist the toggle and apply it to the current page without a reload. */
60
+ exports.isMatchDebugEnabled = isMatchDebugEnabled;
61
+ const setMatchDebug = enabled => {
62
+ cached = enabled;
63
+ try {
64
+ if (enabled) {
65
+ localStorage.setItem(MATCH_DEBUG_KEY, '1');
66
+ } else {
67
+ localStorage.removeItem(MATCH_DEBUG_KEY);
68
+ }
69
+ } catch {
70
+ // Ignore — the toggle simply won't persist across reloads.
71
+ }
72
+ };
73
+
74
+ /** Drop the memoized value (tests, and after an external storage change). */
75
+ exports.setMatchDebug = setMatchDebug;
76
+ const resetMatchDebugCache = () => {
77
+ cached = null;
78
+ };
79
+
80
+ /**
81
+ * Log one trace line. Callers must gate on {@link isMatchDebugEnabled} before
82
+ * building expensive messages; this only guards the write.
83
+ */
84
+ exports.resetMatchDebugCache = resetMatchDebugCache;
85
+ const logMatchDebug = message => {
86
+ if (!isMatchDebugEnabled()) {
87
+ return;
88
+ }
89
+ // eslint-disable-next-line no-console
90
+ console.log(`${LOG_PREFIX} ${message}`);
91
+ };
92
+ exports.logMatchDebug = logMatchDebug;
93
+ //# sourceMappingURL=matchDebug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["MATCH_DEBUG_KEY","exports","MATCH_DEBUG_QUERY_PARAM","LOG_PREFIX","isTruthy","value","cached","isMatchDebugEnabled","URLSearchParams","window","location","search","get","localStorage","getItem","setMatchDebug","enabled","setItem","removeItem","resetMatchDebugCache","logMatchDebug","message","console","log"],"sources":["../../../src/utils/matchDebug.ts"],"sourcesContent":["/**\n * Section-match tracing (debug-only).\n *\n * Turns the otherwise silent matching loop in `tryParseComponent` into a\n * console trace: which definitions the active registry holds and in what\n * order, which patterns were tried against a block, why each one failed, and\n * when a matching definition then returned `null` from `parse()` and let the\n * block fall through to the next candidate.\n *\n * Answers the two questions a \"my section isn't rendering\" report always\n * splits into — *is my definition even registered?* (a missing entry in the\n * registry order line usually means a stale bundle or a `web5-core` version\n * skew; see the warning in `ComponentRegistry.register`) and *did it lose the\n * match, or lose the parse?*\n *\n * Off by default. Enable with `?web5DebugMatch=1` (one-shot, wins over\n * storage) or `localStorage[\"web5_debug_match\"] = \"1\"` (sticky). Resolved once\n * per page load — the tracing is on the hot parse path, so it must not read\n * storage per block.\n */\n\nexport const MATCH_DEBUG_KEY = 'web5_debug_match';\n\n/** Query param that forces match tracing on, overriding localStorage. */\nexport const MATCH_DEBUG_QUERY_PARAM = 'web5DebugMatch';\n\nconst LOG_PREFIX = '[web5:match]';\n\nconst isTruthy = (value: unknown): boolean => value === '1' || value === 'true';\n\nlet cached: boolean | null = null;\n\n/**\n * Whether match tracing is enabled. Memoized: the parse loop calls this for\n * every block of every turn.\n */\nexport const isMatchDebugEnabled = (): boolean => {\n if (cached !== null) {\n return cached;\n }\n cached = false;\n try {\n if (\n isTruthy(\n new URLSearchParams(window.location.search).get(\n MATCH_DEBUG_QUERY_PARAM,\n ),\n )\n ) {\n cached = true;\n return cached;\n }\n } catch {\n // window / URLSearchParams unavailable (SSR, non-DOM environments).\n }\n try {\n cached = isTruthy(localStorage.getItem(MATCH_DEBUG_KEY));\n } catch {\n // localStorage can throw in privacy mode / non-DOM environments.\n }\n return cached;\n};\n\n/** Persist the toggle and apply it to the current page without a reload. */\nexport const setMatchDebug = (enabled: boolean): void => {\n cached = enabled;\n try {\n if (enabled) {\n localStorage.setItem(MATCH_DEBUG_KEY, '1');\n } else {\n localStorage.removeItem(MATCH_DEBUG_KEY);\n }\n } catch {\n // Ignore — the toggle simply won't persist across reloads.\n }\n};\n\n/** Drop the memoized value (tests, and after an external storage change). */\nexport const resetMatchDebugCache = (): void => {\n cached = null;\n};\n\n/**\n * Log one trace line. Callers must gate on {@link isMatchDebugEnabled} before\n * building expensive messages; this only guards the write.\n */\nexport const logMatchDebug = (message: string): void => {\n if (!isMatchDebugEnabled()) {\n return;\n }\n // eslint-disable-next-line no-console\n console.log(`${LOG_PREFIX} ${message}`);\n};\n"],"mappings":";;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEO,MAAMA,eAAe,GAAAC,OAAA,CAAAD,eAAA,GAAG,kBAAkB;;AAEjD;AACO,MAAME,uBAAuB,GAAAD,OAAA,CAAAC,uBAAA,GAAG,gBAAgB;AAEvD,MAAMC,UAAU,GAAG,cAAc;AAEjC,MAAMC,QAAQ,GAAIC,KAAc,IAAcA,KAAK,KAAK,GAAG,IAAIA,KAAK,KAAK,MAAM;AAE/E,IAAIC,MAAsB,GAAG,IAAI;;AAEjC;AACA;AACA;AACA;AACO,MAAMC,mBAAmB,GAAGA,CAAA,KAAe;EAChD,IAAID,MAAM,KAAK,IAAI,EAAE;IACnB,OAAOA,MAAM;EACf;EACAA,MAAM,GAAG,KAAK;EACd,IAAI;IACF,IACEF,QAAQ,CACN,IAAII,eAAe,CAACC,MAAM,CAACC,QAAQ,CAACC,MAAM,CAAC,CAACC,GAAG,CAC7CV,uBACF,CACF,CAAC,EACD;MACAI,MAAM,GAAG,IAAI;MACb,OAAOA,MAAM;IACf;EACF,CAAC,CAAC,MAAM;IACN;EAAA;EAEF,IAAI;IACFA,MAAM,GAAGF,QAAQ,CAACS,YAAY,CAACC,OAAO,CAACd,eAAe,CAAC,CAAC;EAC1D,CAAC,CAAC,MAAM;IACN;EAAA;EAEF,OAAOM,MAAM;AACf,CAAC;;AAED;AAAAL,OAAA,CAAAM,mBAAA,GAAAA,mBAAA;AACO,MAAMQ,aAAa,GAAIC,OAAgB,IAAW;EACvDV,MAAM,GAAGU,OAAO;EAChB,IAAI;IACF,IAAIA,OAAO,EAAE;MACXH,YAAY,CAACI,OAAO,CAACjB,eAAe,EAAE,GAAG,CAAC;IAC5C,CAAC,MAAM;MACLa,YAAY,CAACK,UAAU,CAAClB,eAAe,CAAC;IAC1C;EACF,CAAC,CAAC,MAAM;IACN;EAAA;AAEJ,CAAC;;AAED;AAAAC,OAAA,CAAAc,aAAA,GAAAA,aAAA;AACO,MAAMI,oBAAoB,GAAGA,CAAA,KAAY;EAC9Cb,MAAM,GAAG,IAAI;AACf,CAAC;;AAED;AACA;AACA;AACA;AAHAL,OAAA,CAAAkB,oBAAA,GAAAA,oBAAA;AAIO,MAAMC,aAAa,GAAIC,OAAe,IAAW;EACtD,IAAI,CAACd,mBAAmB,CAAC,CAAC,EAAE;IAC1B;EACF;EACA;EACAe,OAAO,CAACC,GAAG,CAAC,GAAGpB,UAAU,IAAIkB,OAAO,EAAE,CAAC;AACzC,CAAC;AAACpB,OAAA,CAAAmB,aAAA,GAAAA,aAAA","ignoreList":[]}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Client-UMD URL resolution, shared between `web50-server-ui` (the main app)
3
+ * and `embed-placement` (the storefront widget) — DL #094 (per-msid) + DL #129
4
+ * (per-template). Centralized here for the same reason as
5
+ * `clientBundleOverride.ts`: both callers must derive identical URLs, and
6
+ * divergence on which bundle a tenant executes would be a real bug.
7
+ *
8
+ * Two tiers (DL #129):
9
+ * - `templateId` present (DIY store) → the shared per-template bundle,
10
+ * `<cdn>/templates/<id>/production/…`. Every store on a template runs the
11
+ * same artifact; `production` is the promoted channel.
12
+ * - `templateId` absent (customized tier: feature-com, circana, smallflower)
13
+ * → the per-msid bundle at `<cdn>/<msid>/latest/…`, byte-identical to the
14
+ * pre-template behavior.
15
+ */
16
+
17
+ const CLIENT_BUNDLE_CDN = 'https://d13cktzsgh0qls.cloudfront.net';
18
+ const CLIENT_BUNDLE_FILENAME = 'w5-components.umd.js';
19
+
20
+ /**
21
+ * Template ids are kebab-case slugs from `templates/manifest.json`
22
+ * (`web5-seed-1`). The id becomes a CDN path segment, so anything else is a
23
+ * config error — resolve falls back to the per-msid path (fail-soft, and the
24
+ * store keeps rendering) rather than fetching a malformed URL.
25
+ */
26
+ const TEMPLATE_ID_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
27
+ export function resolveClientBundleUrl(msid, templateId) {
28
+ if (templateId) {
29
+ if (TEMPLATE_ID_PATTERN.test(templateId)) {
30
+ return `${CLIENT_BUNDLE_CDN}/templates/${templateId}/production/${CLIENT_BUNDLE_FILENAME}`;
31
+ }
32
+ console.warn(`[web5-core] Ignoring malformed templateId "${templateId}" — falling back to the per-msid bundle.`);
33
+ }
34
+ return `${CLIENT_BUNDLE_CDN}/${msid}/latest/${CLIENT_BUNDLE_FILENAME}`;
35
+ }
36
+ //# sourceMappingURL=clientBundleUrl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["CLIENT_BUNDLE_CDN","CLIENT_BUNDLE_FILENAME","TEMPLATE_ID_PATTERN","resolveClientBundleUrl","msid","templateId","test","console","warn"],"sources":["../../../src/client/clientBundleUrl.ts"],"sourcesContent":["/**\n * Client-UMD URL resolution, shared between `web50-server-ui` (the main app)\n * and `embed-placement` (the storefront widget) — DL #094 (per-msid) + DL #129\n * (per-template). Centralized here for the same reason as\n * `clientBundleOverride.ts`: both callers must derive identical URLs, and\n * divergence on which bundle a tenant executes would be a real bug.\n *\n * Two tiers (DL #129):\n * - `templateId` present (DIY store) → the shared per-template bundle,\n * `<cdn>/templates/<id>/production/…`. Every store on a template runs the\n * same artifact; `production` is the promoted channel.\n * - `templateId` absent (customized tier: feature-com, circana, smallflower)\n * → the per-msid bundle at `<cdn>/<msid>/latest/…`, byte-identical to the\n * pre-template behavior.\n */\n\nconst CLIENT_BUNDLE_CDN = 'https://d13cktzsgh0qls.cloudfront.net';\nconst CLIENT_BUNDLE_FILENAME = 'w5-components.umd.js';\n\n/**\n * Template ids are kebab-case slugs from `templates/manifest.json`\n * (`web5-seed-1`). The id becomes a CDN path segment, so anything else is a\n * config error — resolve falls back to the per-msid path (fail-soft, and the\n * store keeps rendering) rather than fetching a malformed URL.\n */\nconst TEMPLATE_ID_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;\n\nexport function resolveClientBundleUrl(\n msid: string,\n templateId?: string | null,\n): string {\n if (templateId) {\n if (TEMPLATE_ID_PATTERN.test(templateId)) {\n return `${CLIENT_BUNDLE_CDN}/templates/${templateId}/production/${CLIENT_BUNDLE_FILENAME}`;\n }\n console.warn(\n `[web5-core] Ignoring malformed templateId \"${templateId}\" — falling back to the per-msid bundle.`,\n );\n }\n return `${CLIENT_BUNDLE_CDN}/${msid}/latest/${CLIENT_BUNDLE_FILENAME}`;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,MAAMA,iBAAiB,GAAG,uCAAuC;AACjE,MAAMC,sBAAsB,GAAG,sBAAsB;;AAErD;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,mBAAmB,GAAG,0BAA0B;AAEtD,OAAO,SAASC,sBAAsBA,CACpCC,IAAY,EACZC,UAA0B,EAClB;EACR,IAAIA,UAAU,EAAE;IACd,IAAIH,mBAAmB,CAACI,IAAI,CAACD,UAAU,CAAC,EAAE;MACxC,OAAO,GAAGL,iBAAiB,cAAcK,UAAU,eAAeJ,sBAAsB,EAAE;IAC5F;IACAM,OAAO,CAACC,IAAI,CACV,8CAA8CH,UAAU,0CAC1D,CAAC;EACH;EACA,OAAO,GAAGL,iBAAiB,IAAII,IAAI,WAAWH,sBAAsB,EAAE;AACxE","ignoreList":[]}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Universal client-config merge (DL #129 Q3/Q7): the loaded client bundle's
3
+ * `clientConfig` is the default; the backend `Configuration.clientConfig`
4
+ * overrides it **per field, only where a field was actually returned**.
5
+ *
6
+ * One rule for both tiers, shared between `web50-server-ui` and
7
+ * `embed-placement` (the two places that load `w5-components.umd.js`):
8
+ * - Customized-tier clients (feature-com, circana): the backend returns no
9
+ * `clientConfig`, so the merge is identity — the bundle's baked config
10
+ * passes through byte-identical (same reference, see spec).
11
+ * - DIY/template stores: the backend supplies per-store deltas that grow
12
+ * field-by-field as the client-config port (Phase 3b) lands; each ported
13
+ * field takes effect here with no FE change.
14
+ *
15
+ * Semantics — presence, not truthiness:
16
+ * - The wire omits unset proto fields, so key-absence means "not returned"
17
+ * → bundle value kept. A key that IS present wins even when falsy
18
+ * (`''`, `false`, `0`) — it was explicitly set.
19
+ * - `undefined`/`null` values are treated as absent (proto3 JSON never
20
+ * emits null for wrapper types; defensive against hand-written configs).
21
+ * - Plain objects merge per leaf; arrays replace wholesale; class
22
+ * instances / functions replace wholesale.
23
+ */
24
+
25
+ function isPlainObject(value) {
26
+ return typeof value === 'object' && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
27
+ }
28
+ export function mergeClientConfig(bundleConfig,
29
+ // `Record<string, unknown>` admitted alongside `DeepPartial<T>`: the wire
30
+ // value is untyped JSON (`Configuration.clientConfig`), so callers hold it
31
+ // as a plain record — the runtime presence checks do the validation.
32
+ backendConfig) {
33
+ if (backendConfig === undefined || backendConfig === null) {
34
+ return bundleConfig;
35
+ }
36
+ if (!isPlainObject(backendConfig)) {
37
+ return bundleConfig;
38
+ }
39
+ const keys = Object.keys(backendConfig).filter(key => backendConfig[key] !== undefined && backendConfig[key] !== null);
40
+ // Empty delta → identity, same reference: the byte-identical passthrough
41
+ // guarantee for clients whose Configuration carries no clientConfig.
42
+ if (keys.length === 0) {
43
+ return bundleConfig;
44
+ }
45
+ const result = {
46
+ ...bundleConfig
47
+ };
48
+ for (const key of keys) {
49
+ const backendValue = backendConfig[key];
50
+ const bundleValue = bundleConfig[key];
51
+ result[key] = isPlainObject(backendValue) && isPlainObject(bundleValue) ? mergeClientConfig(bundleValue, backendValue) : backendValue;
52
+ }
53
+ return result;
54
+ }
55
+ //# sourceMappingURL=mergeClientConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["isPlainObject","value","Array","isArray","Object","getPrototypeOf","prototype","mergeClientConfig","bundleConfig","backendConfig","undefined","keys","filter","key","length","result","backendValue","bundleValue"],"sources":["../../../src/client/mergeClientConfig.ts"],"sourcesContent":["/**\n * Universal client-config merge (DL #129 Q3/Q7): the loaded client bundle's\n * `clientConfig` is the default; the backend `Configuration.clientConfig`\n * overrides it **per field, only where a field was actually returned**.\n *\n * One rule for both tiers, shared between `web50-server-ui` and\n * `embed-placement` (the two places that load `w5-components.umd.js`):\n * - Customized-tier clients (feature-com, circana): the backend returns no\n * `clientConfig`, so the merge is identity — the bundle's baked config\n * passes through byte-identical (same reference, see spec).\n * - DIY/template stores: the backend supplies per-store deltas that grow\n * field-by-field as the client-config port (Phase 3b) lands; each ported\n * field takes effect here with no FE change.\n *\n * Semantics — presence, not truthiness:\n * - The wire omits unset proto fields, so key-absence means \"not returned\"\n * → bundle value kept. A key that IS present wins even when falsy\n * (`''`, `false`, `0`) — it was explicitly set.\n * - `undefined`/`null` values are treated as absent (proto3 JSON never\n * emits null for wrapper types; defensive against hand-written configs).\n * - Plain objects merge per leaf; arrays replace wholesale; class\n * instances / functions replace wholesale.\n */\n\nexport type DeepPartial<T> = T extends (infer U)[]\n ? U[]\n : T extends object\n ? { [K in keyof T]?: DeepPartial<T[K]> }\n : T;\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n (Object.getPrototypeOf(value) === Object.prototype ||\n Object.getPrototypeOf(value) === null)\n );\n}\n\nexport function mergeClientConfig<T extends object>(\n bundleConfig: T,\n // `Record<string, unknown>` admitted alongside `DeepPartial<T>`: the wire\n // value is untyped JSON (`Configuration.clientConfig`), so callers hold it\n // as a plain record — the runtime presence checks do the validation.\n backendConfig?: DeepPartial<T> | Record<string, unknown> | null,\n): T {\n if (backendConfig === undefined || backendConfig === null) {\n return bundleConfig;\n }\n if (!isPlainObject(backendConfig)) {\n return bundleConfig;\n }\n const keys = Object.keys(backendConfig).filter(\n (key) => (backendConfig as Record<string, unknown>)[key] !== undefined &&\n (backendConfig as Record<string, unknown>)[key] !== null,\n );\n // Empty delta → identity, same reference: the byte-identical passthrough\n // guarantee for clients whose Configuration carries no clientConfig.\n if (keys.length === 0) {\n return bundleConfig;\n }\n\n const result: Record<string, unknown> = {\n ...(bundleConfig as Record<string, unknown>),\n };\n for (const key of keys) {\n const backendValue = (backendConfig as Record<string, unknown>)[key];\n const bundleValue = (bundleConfig as Record<string, unknown>)[key];\n result[key] =\n isPlainObject(backendValue) && isPlainObject(bundleValue)\n ? mergeClientConfig(bundleValue, backendValue)\n : backendValue;\n }\n return result as T;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAQA,SAASA,aAAaA,CAACC,KAAc,EAAoC;EACvE,OACE,OAAOA,KAAK,KAAK,QAAQ,IACzBA,KAAK,KAAK,IAAI,IACd,CAACC,KAAK,CAACC,OAAO,CAACF,KAAK,CAAC,KACpBG,MAAM,CAACC,cAAc,CAACJ,KAAK,CAAC,KAAKG,MAAM,CAACE,SAAS,IAChDF,MAAM,CAACC,cAAc,CAACJ,KAAK,CAAC,KAAK,IAAI,CAAC;AAE5C;AAEA,OAAO,SAASM,iBAAiBA,CAC/BC,YAAe;AACf;AACA;AACA;AACAC,aAA+D,EAC5D;EACH,IAAIA,aAAa,KAAKC,SAAS,IAAID,aAAa,KAAK,IAAI,EAAE;IACzD,OAAOD,YAAY;EACrB;EACA,IAAI,CAACR,aAAa,CAACS,aAAa,CAAC,EAAE;IACjC,OAAOD,YAAY;EACrB;EACA,MAAMG,IAAI,GAAGP,MAAM,CAACO,IAAI,CAACF,aAAa,CAAC,CAACG,MAAM,CAC3CC,GAAG,IAAMJ,aAAa,CAA6BI,GAAG,CAAC,KAAKH,SAAS,IACnED,aAAa,CAA6BI,GAAG,CAAC,KAAK,IACxD,CAAC;EACD;EACA;EACA,IAAIF,IAAI,CAACG,MAAM,KAAK,CAAC,EAAE;IACrB,OAAON,YAAY;EACrB;EAEA,MAAMO,MAA+B,GAAG;IACtC,GAAIP;EACN,CAAC;EACD,KAAK,MAAMK,GAAG,IAAIF,IAAI,EAAE;IACtB,MAAMK,YAAY,GAAIP,aAAa,CAA6BI,GAAG,CAAC;IACpE,MAAMI,WAAW,GAAIT,YAAY,CAA6BK,GAAG,CAAC;IAClEE,MAAM,CAACF,GAAG,CAAC,GACTb,aAAa,CAACgB,YAAY,CAAC,IAAIhB,aAAa,CAACiB,WAAW,CAAC,GACrDV,iBAAiB,CAACU,WAAW,EAAED,YAAY,CAAC,GAC5CA,YAAY;EACpB;EACA,OAAOD,MAAM;AACf","ignoreList":[]}
@@ -0,0 +1,154 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import { headingText, entitySectionBodyText, extractEntityRefs, calloutFromParts } from './parse-utils.js';
3
+ import { DIAGNOSTIC_TYPES } from '../diagnosticTypes.js';
4
+
5
+ /**
6
+ * The semantic entity type this definition claims — the `<type>` segment of
7
+ * `web5://entity/<type>/<id>` (see the client `entityConfig.entityTypes` map).
8
+ */
9
+ const COLLECTION_ENTITY_TYPE = 'collection';
10
+
11
+ /**
12
+ * Entity section restricted to **collection** entities
13
+ * (`web5://entity/collection/<id>`).
14
+ *
15
+ * Same markdown shapes as {@link EntitySectionDefinition} — an `h2`, optional
16
+ * intro/callout, then entity links either at the top level or as list items —
17
+ * but every entity link must be a collection. That makes it a strictly narrower
18
+ * match, so it MUST be registered **before** `EntitySectionDefinition` (which
19
+ * claims any `link[entityType]`, i.e. product and article sections too). Once
20
+ * `EntitySectionDefinition` matches, the block is consumed and no later
21
+ * definition is consulted.
22
+ *
23
+ * Mixed blocks (a collection next to a product or an article) fall through:
24
+ * the patterns only cover consecutive collection links, and `parse()` returns
25
+ * `null` when a non-collection entity slipped into the matched slice, handing
26
+ * the block to `EntitySectionDefinition`.
27
+ *
28
+ * Props are the shared {@link EntityCompProps} shape, so a client renders it
29
+ * with a dedicated `EntityCollectionSection` component while product/article
30
+ * sections keep using their own components under `EntitySectionDefinition`.
31
+ */
32
+ export class EntityCollectionSectionDefinition {
33
+ constructor() {
34
+ _defineProperty(this, "sectionType", 'entityCollection');
35
+ /**
36
+ * One pattern, matching the shape the orchestrator actually emits for a
37
+ * collections block:
38
+ *
39
+ * <!-- section:entities, semantic:items -->
40
+ * ## Curated collections by theme
41
+ * - [](web5://entity/collection/<id>) description
42
+ *
43
+ * The head absorbs the section descriptor and any intro copy or ECHO
44
+ * callout; each list item is a collection link, an optional markdown image,
45
+ * then its description and optional per-item callout. A trailing
46
+ * section-level callout is intentionally left outside the pattern so it
47
+ * falls through to the downstream CalloutSection.
48
+ *
49
+ * Deliberately narrow: anything else (collection links at the top level
50
+ * rather than in a list, a block mixing entity types) falls through to
51
+ * `EntitySectionDefinition`, which is what handled it before this
52
+ * definition existed.
53
+ */
54
+ _defineProperty(this, "patterns", ['html_comment* > h2 > (html_comment | t | callout)* > list{item[1-]:link[entityType="collection"] > image? > (t | callout)*}']);
55
+ _defineProperty(this, "defaults", {
56
+ title: 'Collections',
57
+ items: [{
58
+ entityId: 'example-1',
59
+ entityType: COLLECTION_ENTITY_TYPE,
60
+ entityUrl: 'web5://entity/collection/example-1',
61
+ linkText: 'Example collection'
62
+ }]
63
+ });
64
+ _defineProperty(this, "fixtures", [{
65
+ markdown: '## Shop the collections\n\nCurated edits for the season.\n\n- [Running](web5://entity/collection/pUx3mVQ1TmyN2mVYQqQ8Jg) Shoes and kit built for the road\n- [Trail](web5://entity/collection/Rr8kQyO0S1uH2nQ0mQ2AqQ) Grip and protection off-road',
66
+ expected: {
67
+ title: 'Shop the collections',
68
+ description: 'Curated edits for the season.',
69
+ items: [{
70
+ entityId: 'pUx3mVQ1TmyN2mVYQqQ8Jg',
71
+ entityType: 'collection',
72
+ entityUrl: 'web5://entity/collection/pUx3mVQ1TmyN2mVYQqQ8Jg',
73
+ linkText: 'Running',
74
+ description: 'Shoes and kit built for the road'
75
+ }, {
76
+ entityId: 'Rr8kQyO0S1uH2nQ0mQ2AqQ',
77
+ entityType: 'collection',
78
+ entityUrl: 'web5://entity/collection/Rr8kQyO0S1uH2nQ0mQ2AqQ',
79
+ linkText: 'Trail',
80
+ description: 'Grip and protection off-road'
81
+ }]
82
+ }
83
+ }, {
84
+ // The shape the orchestrator emits: a section descriptor, empty link
85
+ // text, and a Shopify gid (which is itself a `://` url) as the entity id.
86
+ markdown: '<!-- section:entities, semantic:items -->\n## Curated collections by theme\n- [](web5://entity/collection/gid://shopify/Collection/347895267466) storewide assortment spanning the full product range\n- [](web5://entity/collection/gid://shopify/Collection/348001501322) artistic **Watercolor** candles with bright vessels',
87
+ expected: {
88
+ title: 'Curated collections by theme',
89
+ items: [{
90
+ entityId: 'gid://shopify/Collection/347895267466',
91
+ entityType: 'collection',
92
+ entityUrl: 'web5://entity/collection/gid://shopify/Collection/347895267466',
93
+ description: 'storewide assortment spanning the full product range'
94
+ }, {
95
+ entityId: 'gid://shopify/Collection/348001501322',
96
+ entityType: 'collection',
97
+ entityUrl: 'web5://entity/collection/gid://shopify/Collection/348001501322',
98
+ // Inline emphasis survives — descriptions keep their markdown.
99
+ description: 'artistic **Watercolor** candles with bright vessels'
100
+ }]
101
+ }
102
+ }, {
103
+ // Single collection — the full-width banner shape.
104
+ markdown: '## Winter essentials\n\n- [Shop winter](web5://entity/collection/aB1cD2eF3gH4iJ5kL6mN7o) Layers for the cold months',
105
+ expected: {
106
+ title: 'Winter essentials',
107
+ items: [{
108
+ entityId: 'aB1cD2eF3gH4iJ5kL6mN7o',
109
+ entityType: 'collection',
110
+ entityUrl: 'web5://entity/collection/aB1cD2eF3gH4iJ5kL6mN7o',
111
+ linkText: 'Shop winter',
112
+ description: 'Layers for the cold months'
113
+ }]
114
+ }
115
+ }]);
116
+ }
117
+ parse(parts, context) {
118
+ const entityRefs = extractEntityRefs(parts);
119
+ if (entityRefs.length === 0) {
120
+ context == null || context.reportDiagnostic == null || context.reportDiagnostic(DIAGNOSTIC_TYPES.SECTION_REJECTED, 'entityCollection: no entity links found');
121
+ return null;
122
+ }
123
+
124
+ // Guard the pattern: anything that is not a collection means this block
125
+ // belongs to the generic entity section, not here.
126
+ if (entityRefs.some(e => e.entityType !== COLLECTION_ENTITY_TYPE)) {
127
+ context == null || context.reportDiagnostic == null || context.reportDiagnostic(DIAGNOSTIC_TYPES.SECTION_REJECTED, 'entityCollection: block mixes collections with other entity types');
128
+ return null;
129
+ }
130
+ const title = headingText(parts, 2) || 'Collections';
131
+ const description = entitySectionBodyText(parts) || undefined;
132
+
133
+ // Every entity link lives inside the list, so any top-level callout is
134
+ // section-level by construction — per-item callouts are nested in the list
135
+ // items and are picked up by extractEntityRefs instead.
136
+ const callout = calloutFromParts(parts);
137
+ const items = entityRefs.map(e => ({
138
+ entityId: e.entityId,
139
+ entityType: e.entityType,
140
+ entityUrl: e.entityUrl,
141
+ linkText: e.linkText || undefined,
142
+ description: e.description || undefined,
143
+ imageUrl: e.markdownImageUrl,
144
+ callout: e.callout
145
+ }));
146
+ return {
147
+ title,
148
+ description,
149
+ callout,
150
+ items
151
+ };
152
+ }
153
+ }
154
+ //# sourceMappingURL=EntityCollectionSectionDefinition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["headingText","entitySectionBodyText","extractEntityRefs","calloutFromParts","DIAGNOSTIC_TYPES","COLLECTION_ENTITY_TYPE","EntityCollectionSectionDefinition","constructor","_defineProperty","title","items","entityId","entityType","entityUrl","linkText","markdown","expected","description","parse","parts","context","entityRefs","length","reportDiagnostic","SECTION_REJECTED","some","e","undefined","callout","map","imageUrl","markdownImageUrl"],"sources":["../../../../src/component/componentDefinitions/EntityCollectionSectionDefinition.ts"],"sourcesContent":["import {\n headingText,\n entitySectionBodyText,\n extractEntityRefs,\n calloutFromParts,\n} from './parse-utils';\nimport type { Part } from '../../parts/parts';\nimport type {\n EntityCompProps,\n EntityItem,\n EntitySectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition, ParseContext } from '../section-definition';\nimport { DIAGNOSTIC_TYPES } from '../diagnosticTypes';\n\n/**\n * The semantic entity type this definition claims — the `<type>` segment of\n * `web5://entity/<type>/<id>` (see the client `entityConfig.entityTypes` map).\n */\nconst COLLECTION_ENTITY_TYPE = 'collection';\n\n/**\n * Entity section restricted to **collection** entities\n * (`web5://entity/collection/<id>`).\n *\n * Same markdown shapes as {@link EntitySectionDefinition} — an `h2`, optional\n * intro/callout, then entity links either at the top level or as list items —\n * but every entity link must be a collection. That makes it a strictly narrower\n * match, so it MUST be registered **before** `EntitySectionDefinition` (which\n * claims any `link[entityType]`, i.e. product and article sections too). Once\n * `EntitySectionDefinition` matches, the block is consumed and no later\n * definition is consulted.\n *\n * Mixed blocks (a collection next to a product or an article) fall through:\n * the patterns only cover consecutive collection links, and `parse()` returns\n * `null` when a non-collection entity slipped into the matched slice, handing\n * the block to `EntitySectionDefinition`.\n *\n * Props are the shared {@link EntityCompProps} shape, so a client renders it\n * with a dedicated `EntityCollectionSection` component while product/article\n * sections keep using their own components under `EntitySectionDefinition`.\n */\nexport class EntityCollectionSectionDefinition\n implements SectionDefinition<EntitySectionComponent>\n{\n sectionType = 'entityCollection' as const;\n /**\n * One pattern, matching the shape the orchestrator actually emits for a\n * collections block:\n *\n * <!-- section:entities, semantic:items -->\n * ## Curated collections by theme\n * - [](web5://entity/collection/<id>) description\n *\n * The head absorbs the section descriptor and any intro copy or ECHO\n * callout; each list item is a collection link, an optional markdown image,\n * then its description and optional per-item callout. A trailing\n * section-level callout is intentionally left outside the pattern so it\n * falls through to the downstream CalloutSection.\n *\n * Deliberately narrow: anything else (collection links at the top level\n * rather than in a list, a block mixing entity types) falls through to\n * `EntitySectionDefinition`, which is what handled it before this\n * definition existed.\n */\n patterns = [\n 'html_comment* > h2 > (html_comment | t | callout)* > list{item[1-]:link[entityType=\"collection\"] > image? > (t | callout)*}',\n ];\n\n defaults: EntityCompProps = {\n title: 'Collections',\n items: [\n {\n entityId: 'example-1',\n entityType: COLLECTION_ENTITY_TYPE,\n entityUrl: 'web5://entity/collection/example-1',\n linkText: 'Example collection',\n },\n ],\n };\n\n fixtures: SectionFixture<EntityCompProps>[] = [\n {\n markdown:\n '## Shop the collections\\n\\nCurated edits for the season.\\n\\n- [Running](web5://entity/collection/pUx3mVQ1TmyN2mVYQqQ8Jg) Shoes and kit built for the road\\n- [Trail](web5://entity/collection/Rr8kQyO0S1uH2nQ0mQ2AqQ) Grip and protection off-road',\n expected: {\n title: 'Shop the collections',\n description: 'Curated edits for the season.',\n items: [\n {\n entityId: 'pUx3mVQ1TmyN2mVYQqQ8Jg',\n entityType: 'collection',\n entityUrl: 'web5://entity/collection/pUx3mVQ1TmyN2mVYQqQ8Jg',\n linkText: 'Running',\n description: 'Shoes and kit built for the road',\n },\n {\n entityId: 'Rr8kQyO0S1uH2nQ0mQ2AqQ',\n entityType: 'collection',\n entityUrl: 'web5://entity/collection/Rr8kQyO0S1uH2nQ0mQ2AqQ',\n linkText: 'Trail',\n description: 'Grip and protection off-road',\n },\n ],\n },\n },\n {\n // The shape the orchestrator emits: a section descriptor, empty link\n // text, and a Shopify gid (which is itself a `://` url) as the entity id.\n markdown:\n '<!-- section:entities, semantic:items -->\\n## Curated collections by theme\\n- [](web5://entity/collection/gid://shopify/Collection/347895267466) storewide assortment spanning the full product range\\n- [](web5://entity/collection/gid://shopify/Collection/348001501322) artistic **Watercolor** candles with bright vessels',\n expected: {\n title: 'Curated collections by theme',\n items: [\n {\n entityId: 'gid://shopify/Collection/347895267466',\n entityType: 'collection',\n entityUrl:\n 'web5://entity/collection/gid://shopify/Collection/347895267466',\n description: 'storewide assortment spanning the full product range',\n },\n {\n entityId: 'gid://shopify/Collection/348001501322',\n entityType: 'collection',\n entityUrl:\n 'web5://entity/collection/gid://shopify/Collection/348001501322',\n // Inline emphasis survives — descriptions keep their markdown.\n description: 'artistic **Watercolor** candles with bright vessels',\n },\n ],\n },\n },\n {\n // Single collection — the full-width banner shape.\n markdown:\n '## Winter essentials\\n\\n- [Shop winter](web5://entity/collection/aB1cD2eF3gH4iJ5kL6mN7o) Layers for the cold months',\n expected: {\n title: 'Winter essentials',\n items: [\n {\n entityId: 'aB1cD2eF3gH4iJ5kL6mN7o',\n entityType: 'collection',\n entityUrl: 'web5://entity/collection/aB1cD2eF3gH4iJ5kL6mN7o',\n linkText: 'Shop winter',\n description: 'Layers for the cold months',\n },\n ],\n },\n },\n ];\n\n parse(parts: Part[], context?: ParseContext): EntityCompProps | null {\n const entityRefs = extractEntityRefs(parts);\n\n if (entityRefs.length === 0) {\n context?.reportDiagnostic?.(\n DIAGNOSTIC_TYPES.SECTION_REJECTED,\n 'entityCollection: no entity links found',\n );\n return null;\n }\n\n // Guard the pattern: anything that is not a collection means this block\n // belongs to the generic entity section, not here.\n if (entityRefs.some((e) => e.entityType !== COLLECTION_ENTITY_TYPE)) {\n context?.reportDiagnostic?.(\n DIAGNOSTIC_TYPES.SECTION_REJECTED,\n 'entityCollection: block mixes collections with other entity types',\n );\n return null;\n }\n\n const title = headingText(parts, 2) || 'Collections';\n const description = entitySectionBodyText(parts) || undefined;\n\n // Every entity link lives inside the list, so any top-level callout is\n // section-level by construction — per-item callouts are nested in the list\n // items and are picked up by extractEntityRefs instead.\n const callout = calloutFromParts(parts);\n\n const items: EntityItem[] = entityRefs.map((e) => ({\n entityId: e.entityId,\n entityType: e.entityType,\n entityUrl: e.entityUrl,\n linkText: e.linkText || undefined,\n description: e.description || undefined,\n imageUrl: e.markdownImageUrl,\n callout: e.callout,\n }));\n\n return { title, description, callout, items };\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -5,6 +5,7 @@ export { HeroEntitySectionDefinition } from './HeroEntitySectionDefinition.js';
5
5
  export { KpiSectionDefinition } from './KpiSectionDefinition.js';
6
6
  export { FeatureCardsSectionDefinition } from './FeatureCardsSectionDefinition.js';
7
7
  export { EntitySectionDefinition } from './EntitySectionDefinition.js';
8
+ export { EntityCollectionSectionDefinition } from './EntityCollectionSectionDefinition.js';
8
9
  export { CtaBannerSectionDefinition } from './CtaBannerSectionDefinition.js';
9
10
  export { CalloutSectionDefinition } from './CalloutSectionDefinition.js';
10
11
  export { NextStepsSectionDefinition } from './NextStepsSectionDefinition.js';
@@ -21,6 +22,7 @@ import { SearchSectionDefinition } from './SearchSectionDefinition.js';
21
22
  import { KpiSectionDefinition } from './KpiSectionDefinition.js';
22
23
  import { NextStepsSectionDefinition } from './NextStepsSectionDefinition.js';
23
24
  import { EntitySectionDefinition } from './EntitySectionDefinition.js';
25
+ import { EntityCollectionSectionDefinition } from './EntityCollectionSectionDefinition.js';
24
26
  import { HeroEntitySectionDefinition } from './HeroEntitySectionDefinition.js';
25
27
  import { HeroSectionDefinition } from './HeroSectionDefinition.js';
26
28
  import { FeatureCardsSectionDefinition } from './FeatureCardsSectionDefinition.js';
@@ -40,6 +42,10 @@ import { TextBlockSectionDefinition } from './TextBlockSectionDefinition.js';
40
42
  * Registration order determines evaluation priority — first match wins.
41
43
  */
42
44
  export function createSdkRegistry() {
43
- return new ComponentRegistry(null).register(new SkipNodesSectionDefinition()).register(new SearchSectionDefinition()).register(new KpiSectionDefinition()).register(new NextStepsSectionDefinition()).register(new EntitySectionDefinition()).register(new HeroEntitySectionDefinition()).register(new HeroSectionDefinition()).register(new FeatureCardsSectionDefinition()).register(new TextBlockSectionDefinition()).register(new ListItemsSectionDefinition()).register(new FeatureSection9PlusDefinition()).register(new ComparisonSectionDefinition()).register(new HtmlCommentSectionDefinition()).register(new CtaBannerSectionDefinition()).register(new CalloutSectionDefinition()).register(new FallbackSectionDefinition()).register(new ErrorSectionDefinition());
45
+ return new ComponentRegistry(null).register(new SkipNodesSectionDefinition()).register(new SearchSectionDefinition()).register(new KpiSectionDefinition()).register(new NextStepsSectionDefinition())
46
+ // Collection entities are claimed by their own definition first — it is a
47
+ // strictly narrower match than EntitySectionDefinition, which would
48
+ // otherwise swallow collection, product and article blocks alike.
49
+ .register(new EntityCollectionSectionDefinition()).register(new EntitySectionDefinition()).register(new HeroEntitySectionDefinition()).register(new HeroSectionDefinition()).register(new FeatureCardsSectionDefinition()).register(new TextBlockSectionDefinition()).register(new ListItemsSectionDefinition()).register(new FeatureSection9PlusDefinition()).register(new ComparisonSectionDefinition()).register(new HtmlCommentSectionDefinition()).register(new CtaBannerSectionDefinition()).register(new CalloutSectionDefinition()).register(new FallbackSectionDefinition()).register(new ErrorSectionDefinition());
44
50
  }
45
51
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["ComparisonSectionDefinition","TextBlockSectionDefinition","HeroSectionDefinition","HeroEntitySectionDefinition","KpiSectionDefinition","FeatureCardsSectionDefinition","EntitySectionDefinition","CtaBannerSectionDefinition","CalloutSectionDefinition","NextStepsSectionDefinition","FeatureSection9PlusDefinition","ListItemsSectionDefinition","SkipNodesSectionDefinition","HtmlCommentSectionDefinition","SearchSectionDefinition","ErrorSectionDefinition","FallbackSectionDefinition","ComponentRegistry","createSdkRegistry","register"],"sources":["../../../../src/component/componentDefinitions/index.ts"],"sourcesContent":["export type { SectionDefinition } from '../section-definition';\nexport { ComparisonSectionDefinition } from './ComparisonSectionDefinition';\nexport { TextBlockSectionDefinition } from './TextBlockSectionDefinition';\nexport { HeroSectionDefinition } from './HeroSectionDefinition';\nexport { HeroEntitySectionDefinition } from './HeroEntitySectionDefinition';\nexport { KpiSectionDefinition } from './KpiSectionDefinition';\nexport { FeatureCardsSectionDefinition } from './FeatureCardsSectionDefinition';\nexport { EntitySectionDefinition } from './EntitySectionDefinition';\nexport { CtaBannerSectionDefinition } from './CtaBannerSectionDefinition';\nexport { CalloutSectionDefinition } from './CalloutSectionDefinition';\nexport { NextStepsSectionDefinition } from './NextStepsSectionDefinition';\nexport { FeatureSection9PlusDefinition } from './FeatureSection9PlusDefinition';\nexport { ListItemsSectionDefinition } from './listItemsSectionDefinition';\nexport { SkipNodesSectionDefinition } from './SkipNodesSectionDefinition';\nexport { HtmlCommentSectionDefinition } from './HtmlCommentSectionDefinition';\nexport { SearchSectionDefinition } from './SearchSectionDefinition';\nexport { ErrorSectionDefinition } from './ErrorSectionDefinition';\nexport { FallbackSectionDefinition } from './FallbackSectionDefinition';\n\nimport { ComponentRegistry } from '../../registry';\nimport { SkipNodesSectionDefinition } from './SkipNodesSectionDefinition';\nimport { SearchSectionDefinition } from './SearchSectionDefinition';\nimport { KpiSectionDefinition } from './KpiSectionDefinition';\nimport { NextStepsSectionDefinition } from './NextStepsSectionDefinition';\nimport { EntitySectionDefinition } from './EntitySectionDefinition';\nimport { HeroEntitySectionDefinition } from './HeroEntitySectionDefinition';\nimport { HeroSectionDefinition } from './HeroSectionDefinition';\nimport { FeatureCardsSectionDefinition } from './FeatureCardsSectionDefinition';\nimport { FeatureSection9PlusDefinition } from './FeatureSection9PlusDefinition';\nimport { ListItemsSectionDefinition } from './listItemsSectionDefinition';\nimport { ComparisonSectionDefinition } from './ComparisonSectionDefinition';\nimport { HtmlCommentSectionDefinition } from './HtmlCommentSectionDefinition';\nimport { CtaBannerSectionDefinition } from './CtaBannerSectionDefinition';\nimport { CalloutSectionDefinition } from './CalloutSectionDefinition';\nimport { FallbackSectionDefinition } from './FallbackSectionDefinition';\nimport { ErrorSectionDefinition } from './ErrorSectionDefinition';\nimport { TextBlockSectionDefinition } from './TextBlockSectionDefinition';\n\n/**\n * Creates an SDK registry with all section definitions registered in the\n * same priority order as the app registry (createAppRegistry.ts).\n * Registration order determines evaluation priority — first match wins.\n */\nexport function createSdkRegistry(): ComponentRegistry<null> {\n return new ComponentRegistry<null>(null)\n .register(new SkipNodesSectionDefinition())\n .register(new SearchSectionDefinition())\n .register(new KpiSectionDefinition())\n .register(new NextStepsSectionDefinition())\n .register(new EntitySectionDefinition())\n .register(new HeroEntitySectionDefinition())\n .register(new HeroSectionDefinition())\n .register(new FeatureCardsSectionDefinition())\n .register(new TextBlockSectionDefinition())\n .register(new ListItemsSectionDefinition())\n .register(new FeatureSection9PlusDefinition())\n .register(new ComparisonSectionDefinition())\n .register(new HtmlCommentSectionDefinition())\n .register(new CtaBannerSectionDefinition())\n .register(new CalloutSectionDefinition())\n .register(new FallbackSectionDefinition())\n .register(new ErrorSectionDefinition());\n}\n"],"mappings":"AACA,SAASA,2BAA2B,QAAQ,+BAA+B;AAC3E,SAASC,0BAA0B,QAAQ,8BAA8B;AACzE,SAASC,qBAAqB,QAAQ,yBAAyB;AAC/D,SAASC,2BAA2B,QAAQ,+BAA+B;AAC3E,SAASC,oBAAoB,QAAQ,wBAAwB;AAC7D,SAASC,6BAA6B,QAAQ,iCAAiC;AAC/E,SAASC,uBAAuB,QAAQ,2BAA2B;AACnE,SAASC,0BAA0B,QAAQ,8BAA8B;AACzE,SAASC,wBAAwB,QAAQ,4BAA4B;AACrE,SAASC,0BAA0B,QAAQ,8BAA8B;AACzE,SAASC,6BAA6B,QAAQ,iCAAiC;AAC/E,SAASC,0BAA0B,QAAQ,8BAA8B;AACzE,SAASC,0BAA0B,QAAQ,8BAA8B;AACzE,SAASC,4BAA4B,QAAQ,gCAAgC;AAC7E,SAASC,uBAAuB,QAAQ,2BAA2B;AACnE,SAASC,sBAAsB,QAAQ,0BAA0B;AACjE,SAASC,yBAAyB,QAAQ,6BAA6B;AAEvE,SAASC,iBAAiB,QAAQ,gBAAgB;AAClD,SAASL,0BAA0B,QAAQ,8BAA8B;AACzE,SAASE,uBAAuB,QAAQ,2BAA2B;AACnE,SAASV,oBAAoB,QAAQ,wBAAwB;AAC7D,SAASK,0BAA0B,QAAQ,8BAA8B;AACzE,SAASH,uBAAuB,QAAQ,2BAA2B;AACnE,SAASH,2BAA2B,QAAQ,+BAA+B;AAC3E,SAASD,qBAAqB,QAAQ,yBAAyB;AAC/D,SAASG,6BAA6B,QAAQ,iCAAiC;AAC/E,SAASK,6BAA6B,QAAQ,iCAAiC;AAC/E,SAASC,0BAA0B,QAAQ,8BAA8B;AACzE,SAASX,2BAA2B,QAAQ,+BAA+B;AAC3E,SAASa,4BAA4B,QAAQ,gCAAgC;AAC7E,SAASN,0BAA0B,QAAQ,8BAA8B;AACzE,SAASC,wBAAwB,QAAQ,4BAA4B;AACrE,SAASQ,yBAAyB,QAAQ,6BAA6B;AACvE,SAASD,sBAAsB,QAAQ,0BAA0B;AACjE,SAASd,0BAA0B,QAAQ,8BAA8B;;AAEzE;AACA;AACA;AACA;AACA;AACA,OAAO,SAASiB,iBAAiBA,CAAA,EAA4B;EAC3D,OAAO,IAAID,iBAAiB,CAAO,IAAI,CAAC,CACrCE,QAAQ,CAAC,IAAIP,0BAA0B,CAAC,CAAC,CAAC,CAC1CO,QAAQ,CAAC,IAAIL,uBAAuB,CAAC,CAAC,CAAC,CACvCK,QAAQ,CAAC,IAAIf,oBAAoB,CAAC,CAAC,CAAC,CACpCe,QAAQ,CAAC,IAAIV,0BAA0B,CAAC,CAAC,CAAC,CAC1CU,QAAQ,CAAC,IAAIb,uBAAuB,CAAC,CAAC,CAAC,CACvCa,QAAQ,CAAC,IAAIhB,2BAA2B,CAAC,CAAC,CAAC,CAC3CgB,QAAQ,CAAC,IAAIjB,qBAAqB,CAAC,CAAC,CAAC,CACrCiB,QAAQ,CAAC,IAAId,6BAA6B,CAAC,CAAC,CAAC,CAC7Cc,QAAQ,CAAC,IAAIlB,0BAA0B,CAAC,CAAC,CAAC,CAC1CkB,QAAQ,CAAC,IAAIR,0BAA0B,CAAC,CAAC,CAAC,CAC1CQ,QAAQ,CAAC,IAAIT,6BAA6B,CAAC,CAAC,CAAC,CAC7CS,QAAQ,CAAC,IAAInB,2BAA2B,CAAC,CAAC,CAAC,CAC3CmB,QAAQ,CAAC,IAAIN,4BAA4B,CAAC,CAAC,CAAC,CAC5CM,QAAQ,CAAC,IAAIZ,0BAA0B,CAAC,CAAC,CAAC,CAC1CY,QAAQ,CAAC,IAAIX,wBAAwB,CAAC,CAAC,CAAC,CACxCW,QAAQ,CAAC,IAAIH,yBAAyB,CAAC,CAAC,CAAC,CACzCG,QAAQ,CAAC,IAAIJ,sBAAsB,CAAC,CAAC,CAAC;AAC3C","ignoreList":[]}
1
+ {"version":3,"names":["ComparisonSectionDefinition","TextBlockSectionDefinition","HeroSectionDefinition","HeroEntitySectionDefinition","KpiSectionDefinition","FeatureCardsSectionDefinition","EntitySectionDefinition","EntityCollectionSectionDefinition","CtaBannerSectionDefinition","CalloutSectionDefinition","NextStepsSectionDefinition","FeatureSection9PlusDefinition","ListItemsSectionDefinition","SkipNodesSectionDefinition","HtmlCommentSectionDefinition","SearchSectionDefinition","ErrorSectionDefinition","FallbackSectionDefinition","ComponentRegistry","createSdkRegistry","register"],"sources":["../../../../src/component/componentDefinitions/index.ts"],"sourcesContent":["export type { SectionDefinition } from '../section-definition';\nexport { ComparisonSectionDefinition } from './ComparisonSectionDefinition';\nexport { TextBlockSectionDefinition } from './TextBlockSectionDefinition';\nexport { HeroSectionDefinition } from './HeroSectionDefinition';\nexport { HeroEntitySectionDefinition } from './HeroEntitySectionDefinition';\nexport { KpiSectionDefinition } from './KpiSectionDefinition';\nexport { FeatureCardsSectionDefinition } from './FeatureCardsSectionDefinition';\nexport { EntitySectionDefinition } from './EntitySectionDefinition';\nexport { EntityCollectionSectionDefinition } from './EntityCollectionSectionDefinition';\nexport { CtaBannerSectionDefinition } from './CtaBannerSectionDefinition';\nexport { CalloutSectionDefinition } from './CalloutSectionDefinition';\nexport { NextStepsSectionDefinition } from './NextStepsSectionDefinition';\nexport { FeatureSection9PlusDefinition } from './FeatureSection9PlusDefinition';\nexport { ListItemsSectionDefinition } from './listItemsSectionDefinition';\nexport { SkipNodesSectionDefinition } from './SkipNodesSectionDefinition';\nexport { HtmlCommentSectionDefinition } from './HtmlCommentSectionDefinition';\nexport { SearchSectionDefinition } from './SearchSectionDefinition';\nexport { ErrorSectionDefinition } from './ErrorSectionDefinition';\nexport { FallbackSectionDefinition } from './FallbackSectionDefinition';\n\nimport { ComponentRegistry } from '../../registry';\nimport { SkipNodesSectionDefinition } from './SkipNodesSectionDefinition';\nimport { SearchSectionDefinition } from './SearchSectionDefinition';\nimport { KpiSectionDefinition } from './KpiSectionDefinition';\nimport { NextStepsSectionDefinition } from './NextStepsSectionDefinition';\nimport { EntitySectionDefinition } from './EntitySectionDefinition';\nimport { EntityCollectionSectionDefinition } from './EntityCollectionSectionDefinition';\nimport { HeroEntitySectionDefinition } from './HeroEntitySectionDefinition';\nimport { HeroSectionDefinition } from './HeroSectionDefinition';\nimport { FeatureCardsSectionDefinition } from './FeatureCardsSectionDefinition';\nimport { FeatureSection9PlusDefinition } from './FeatureSection9PlusDefinition';\nimport { ListItemsSectionDefinition } from './listItemsSectionDefinition';\nimport { ComparisonSectionDefinition } from './ComparisonSectionDefinition';\nimport { HtmlCommentSectionDefinition } from './HtmlCommentSectionDefinition';\nimport { CtaBannerSectionDefinition } from './CtaBannerSectionDefinition';\nimport { CalloutSectionDefinition } from './CalloutSectionDefinition';\nimport { FallbackSectionDefinition } from './FallbackSectionDefinition';\nimport { ErrorSectionDefinition } from './ErrorSectionDefinition';\nimport { TextBlockSectionDefinition } from './TextBlockSectionDefinition';\n\n/**\n * Creates an SDK registry with all section definitions registered in the\n * same priority order as the app registry (createAppRegistry.ts).\n * Registration order determines evaluation priority — first match wins.\n */\nexport function createSdkRegistry(): ComponentRegistry<null> {\n return (\n new ComponentRegistry<null>(null)\n .register(new SkipNodesSectionDefinition())\n .register(new SearchSectionDefinition())\n .register(new KpiSectionDefinition())\n .register(new NextStepsSectionDefinition())\n // Collection entities are claimed by their own definition first — it is a\n // strictly narrower match than EntitySectionDefinition, which would\n // otherwise swallow collection, product and article blocks alike.\n .register(new EntityCollectionSectionDefinition())\n .register(new EntitySectionDefinition())\n .register(new HeroEntitySectionDefinition())\n .register(new HeroSectionDefinition())\n .register(new FeatureCardsSectionDefinition())\n .register(new TextBlockSectionDefinition())\n .register(new ListItemsSectionDefinition())\n .register(new FeatureSection9PlusDefinition())\n .register(new ComparisonSectionDefinition())\n .register(new HtmlCommentSectionDefinition())\n .register(new CtaBannerSectionDefinition())\n .register(new CalloutSectionDefinition())\n .register(new FallbackSectionDefinition())\n .register(new ErrorSectionDefinition())\n );\n}\n"],"mappings":"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","ignoreList":[]}
@@ -21,6 +21,7 @@ import { isWeb5ImageUrl } from '../types/link-types.js';
21
21
  import { findInvalidWeb5Links } from '../utils/web5LinkValidator.js';
22
22
  import { DIAGNOSTIC_TYPES } from './diagnosticTypes.js';
23
23
  import { ComponentTracking } from '../utils/componentTracking.js';
24
+ import { isMatchDebugEnabled, logMatchDebug } from '../utils/matchDebug.js';
24
25
  import { DiagnosticsCollector } from '../utils/diagnosticsCollector.js';
25
26
  import { parseAstToMarkdown, parseMarkdownToAst } from '../utils/unifiedMarkdownParser.js';
26
27
  import { preprocessMarkdown } from '../utils/markdownPreprocessor.js';
@@ -30,8 +31,17 @@ import { createPageSection } from '../utils/propsExtractor.js';
30
31
  function isEntityCompProps(props) {
31
32
  return typeof props === 'object' && props !== null && Array.isArray(props.items);
32
33
  }
34
+
35
+ /**
36
+ * Section types whose props are `EntityCompProps` and therefore participate in
37
+ * payload enrichment. `entityCollection` is `entity` narrowed to collection
38
+ * links — it produces the same props and arrives under the same
39
+ * `semantic: items` descriptor, so leaving it out would silently strip its
40
+ * items of their catalog data (image, title) and render the section blank.
41
+ */
42
+ const ENRICHABLE_ENTITY_SECTION_TYPES = new Set(['entity', 'entityCollection']);
33
43
  function isItemsFromContentSection(sectionType, semantic, serverSectionId) {
34
- if (sectionType !== 'entity') {
44
+ if (!ENRICHABLE_ENTITY_SECTION_TYPES.has(sectionType)) {
35
45
  return false;
36
46
  }
37
47
  const normalizedSemantic = semantic == null ? void 0 : semantic.toLowerCase().replace(/_/g, '-');
@@ -261,6 +271,15 @@ export function tryParseComponent(nodes, sectionIndex, context) {
261
271
  setMeta: context.tracking ? (sectionType, key, value) => context.tracking.setMeta(sectionType, key, value) : undefined,
262
272
  getMeta: context.tracking ? (sectionType, key) => context.tracking.getMeta(sectionType, key) : undefined
263
273
  };
274
+
275
+ // Debug-only trace (`?web5DebugMatch=1`). The registry order line doubles as
276
+ // a "is my definition even registered?" check — a definition missing from it
277
+ // never reached `register()` (stale client bundle / web5-core version skew).
278
+ const trace = isMatchDebugEnabled();
279
+ if (trace) {
280
+ logMatchDebug(`block #${sectionIndex} [${nodes.map(n => n.type).join(', ')}]`);
281
+ logMatchDebug(` registry order: ${definitions.map(d => d.sectionType).join(' > ')}`);
282
+ }
264
283
  for (const {
265
284
  sectionType,
266
285
  definition
@@ -270,12 +289,18 @@ export function tryParseComponent(nodes, sectionIndex, context) {
270
289
  // render (the main app) — their markdown should fall through to the generic
271
290
  // sections there. Skip them unless this is a placement parse.
272
291
  if (!placement && registry.isPlacementOnly(sectionType)) {
292
+ if (trace) {
293
+ logMatchDebug(` ${sectionType}: skipped (placement-only)`);
294
+ }
273
295
  continue;
274
296
  }
275
297
  for (const pattern of definition.patterns) {
276
298
  var _parts$find, _context$intent;
277
299
  const result = validatePattern(nodes, pattern);
278
300
  if (!result.valid) {
301
+ if (trace) {
302
+ logMatchDebug(` ${sectionType}: no match — ${result.error ?? 'pattern did not match'}\n pattern: ${pattern}`);
303
+ }
279
304
  continue;
280
305
  }
281
306
  let parsedNodes = result.astEndIndex !== undefined && result.astEndIndex >= 0 ? result.astEndIndex + 1 : result.endIndex >= 0 ? result.endIndex + 1 : 1;
@@ -298,8 +323,14 @@ export function tryParseComponent(nodes, sectionIndex, context) {
298
323
  };
299
324
  let props = definition.parse(parts, parseContext);
300
325
  if (props === null) {
326
+ if (trace) {
327
+ logMatchDebug(` ${sectionType}: pattern matched ${parsedNodes} node(s) but parse() returned null — falling through`);
328
+ }
301
329
  continue;
302
330
  }
331
+ if (trace) {
332
+ logMatchDebug(` ${sectionType}: MATCHED ${parsedNodes} node(s) via ${pattern}`);
333
+ }
303
334
  const leadingHtmlCommentMeta = (_parts$find = parts.find(p => p.type === 'htmlComment' && p.meta)) == null ? void 0 : _parts$find.meta;
304
335
  const semantic = leadingHtmlCommentMeta == null ? void 0 : leadingHtmlCommentMeta.semantic;
305
336
  const serverSectionId = leadingHtmlCommentMeta == null ? void 0 : leadingHtmlCommentMeta.id;
@@ -313,6 +344,9 @@ export function tryParseComponent(nodes, sectionIndex, context) {
313
344
  });
314
345
  }
315
346
  if (definition.singleInstance && context.tracking && context.tracking.getComponentCount(sectionType) > 0) {
347
+ if (trace) {
348
+ logMatchDebug(` ${sectionType}: dropped (singleInstance, already rendered once)`);
349
+ }
316
350
  continue;
317
351
  }
318
352
  const isNullComponent = definition.nullComponent === true;
@@ -360,6 +394,9 @@ export function tryParseComponent(nodes, sectionIndex, context) {
360
394
  };
361
395
  }
362
396
  }
397
+ if (trace) {
398
+ logMatchDebug(' no definition claimed this block');
399
+ }
363
400
  return {};
364
401
  }
365
402
  //# sourceMappingURL=componentParser.js.map