@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,40 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.resolveClientBundleUrl = resolveClientBundleUrl;
5
+ /**
6
+ * Client-UMD URL resolution, shared between `web50-server-ui` (the main app)
7
+ * and `embed-placement` (the storefront widget) — DL #094 (per-msid) + DL #129
8
+ * (per-template). Centralized here for the same reason as
9
+ * `clientBundleOverride.ts`: both callers must derive identical URLs, and
10
+ * divergence on which bundle a tenant executes would be a real bug.
11
+ *
12
+ * Two tiers (DL #129):
13
+ * - `templateId` present (DIY store) → the shared per-template bundle,
14
+ * `<cdn>/templates/<id>/production/…`. Every store on a template runs the
15
+ * same artifact; `production` is the promoted channel.
16
+ * - `templateId` absent (customized tier: feature-com, circana, smallflower)
17
+ * → the per-msid bundle at `<cdn>/<msid>/latest/…`, byte-identical to the
18
+ * pre-template behavior.
19
+ */
20
+
21
+ const CLIENT_BUNDLE_CDN = 'https://d13cktzsgh0qls.cloudfront.net';
22
+ const CLIENT_BUNDLE_FILENAME = 'w5-components.umd.js';
23
+
24
+ /**
25
+ * Template ids are kebab-case slugs from `templates/manifest.json`
26
+ * (`web5-seed-1`). The id becomes a CDN path segment, so anything else is a
27
+ * config error — resolve falls back to the per-msid path (fail-soft, and the
28
+ * store keeps rendering) rather than fetching a malformed URL.
29
+ */
30
+ const TEMPLATE_ID_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
31
+ function resolveClientBundleUrl(msid, templateId) {
32
+ if (templateId) {
33
+ if (TEMPLATE_ID_PATTERN.test(templateId)) {
34
+ return `${CLIENT_BUNDLE_CDN}/templates/${templateId}/production/${CLIENT_BUNDLE_FILENAME}`;
35
+ }
36
+ console.warn(`[web5-core] Ignoring malformed templateId "${templateId}" — falling back to the per-msid bundle.`);
37
+ }
38
+ return `${CLIENT_BUNDLE_CDN}/${msid}/latest/${CLIENT_BUNDLE_FILENAME}`;
39
+ }
40
+ //# 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;AAE/C,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,59 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.mergeClientConfig = mergeClientConfig;
5
+ /**
6
+ * Universal client-config merge (DL #129 Q3/Q7): the loaded client bundle's
7
+ * `clientConfig` is the default; the backend `Configuration.clientConfig`
8
+ * overrides it **per field, only where a field was actually returned**.
9
+ *
10
+ * One rule for both tiers, shared between `web50-server-ui` and
11
+ * `embed-placement` (the two places that load `w5-components.umd.js`):
12
+ * - Customized-tier clients (feature-com, circana): the backend returns no
13
+ * `clientConfig`, so the merge is identity — the bundle's baked config
14
+ * passes through byte-identical (same reference, see spec).
15
+ * - DIY/template stores: the backend supplies per-store deltas that grow
16
+ * field-by-field as the client-config port (Phase 3b) lands; each ported
17
+ * field takes effect here with no FE change.
18
+ *
19
+ * Semantics — presence, not truthiness:
20
+ * - The wire omits unset proto fields, so key-absence means "not returned"
21
+ * → bundle value kept. A key that IS present wins even when falsy
22
+ * (`''`, `false`, `0`) — it was explicitly set.
23
+ * - `undefined`/`null` values are treated as absent (proto3 JSON never
24
+ * emits null for wrapper types; defensive against hand-written configs).
25
+ * - Plain objects merge per leaf; arrays replace wholesale; class
26
+ * instances / functions replace wholesale.
27
+ */
28
+
29
+ function isPlainObject(value) {
30
+ return typeof value === 'object' && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
31
+ }
32
+ function mergeClientConfig(bundleConfig,
33
+ // `Record<string, unknown>` admitted alongside `DeepPartial<T>`: the wire
34
+ // value is untyped JSON (`Configuration.clientConfig`), so callers hold it
35
+ // as a plain record — the runtime presence checks do the validation.
36
+ backendConfig) {
37
+ if (backendConfig === undefined || backendConfig === null) {
38
+ return bundleConfig;
39
+ }
40
+ if (!isPlainObject(backendConfig)) {
41
+ return bundleConfig;
42
+ }
43
+ const keys = Object.keys(backendConfig).filter(key => backendConfig[key] !== undefined && backendConfig[key] !== null);
44
+ // Empty delta → identity, same reference: the byte-identical passthrough
45
+ // guarantee for clients whose Configuration carries no clientConfig.
46
+ if (keys.length === 0) {
47
+ return bundleConfig;
48
+ }
49
+ const result = {
50
+ ...bundleConfig
51
+ };
52
+ for (const key of keys) {
53
+ const backendValue = backendConfig[key];
54
+ const bundleValue = bundleConfig[key];
55
+ result[key] = isPlainObject(backendValue) && isPlainObject(bundleValue) ? mergeClientConfig(bundleValue, backendValue) : backendValue;
56
+ }
57
+ return result;
58
+ }
59
+ //# 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;AAEO,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,159 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ exports.__esModule = true;
5
+ exports.EntityCollectionSectionDefinition = void 0;
6
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
7
+ var _parseUtils = require("./parse-utils");
8
+ var _diagnosticTypes = require("../diagnosticTypes");
9
+ /**
10
+ * The semantic entity type this definition claims — the `<type>` segment of
11
+ * `web5://entity/<type>/<id>` (see the client `entityConfig.entityTypes` map).
12
+ */
13
+ const COLLECTION_ENTITY_TYPE = 'collection';
14
+
15
+ /**
16
+ * Entity section restricted to **collection** entities
17
+ * (`web5://entity/collection/<id>`).
18
+ *
19
+ * Same markdown shapes as {@link EntitySectionDefinition} — an `h2`, optional
20
+ * intro/callout, then entity links either at the top level or as list items —
21
+ * but every entity link must be a collection. That makes it a strictly narrower
22
+ * match, so it MUST be registered **before** `EntitySectionDefinition` (which
23
+ * claims any `link[entityType]`, i.e. product and article sections too). Once
24
+ * `EntitySectionDefinition` matches, the block is consumed and no later
25
+ * definition is consulted.
26
+ *
27
+ * Mixed blocks (a collection next to a product or an article) fall through:
28
+ * the patterns only cover consecutive collection links, and `parse()` returns
29
+ * `null` when a non-collection entity slipped into the matched slice, handing
30
+ * the block to `EntitySectionDefinition`.
31
+ *
32
+ * Props are the shared {@link EntityCompProps} shape, so a client renders it
33
+ * with a dedicated `EntityCollectionSection` component while product/article
34
+ * sections keep using their own components under `EntitySectionDefinition`.
35
+ */
36
+ class EntityCollectionSectionDefinition {
37
+ constructor() {
38
+ (0, _defineProperty2.default)(this, "sectionType", 'entityCollection');
39
+ /**
40
+ * One pattern, matching the shape the orchestrator actually emits for a
41
+ * collections block:
42
+ *
43
+ * <!-- section:entities, semantic:items -->
44
+ * ## Curated collections by theme
45
+ * - [](web5://entity/collection/<id>) description
46
+ *
47
+ * The head absorbs the section descriptor and any intro copy or ECHO
48
+ * callout; each list item is a collection link, an optional markdown image,
49
+ * then its description and optional per-item callout. A trailing
50
+ * section-level callout is intentionally left outside the pattern so it
51
+ * falls through to the downstream CalloutSection.
52
+ *
53
+ * Deliberately narrow: anything else (collection links at the top level
54
+ * rather than in a list, a block mixing entity types) falls through to
55
+ * `EntitySectionDefinition`, which is what handled it before this
56
+ * definition existed.
57
+ */
58
+ (0, _defineProperty2.default)(this, "patterns", ['html_comment* > h2 > (html_comment | t | callout)* > list{item[1-]:link[entityType="collection"] > image? > (t | callout)*}']);
59
+ (0, _defineProperty2.default)(this, "defaults", {
60
+ title: 'Collections',
61
+ items: [{
62
+ entityId: 'example-1',
63
+ entityType: COLLECTION_ENTITY_TYPE,
64
+ entityUrl: 'web5://entity/collection/example-1',
65
+ linkText: 'Example collection'
66
+ }]
67
+ });
68
+ (0, _defineProperty2.default)(this, "fixtures", [{
69
+ 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',
70
+ expected: {
71
+ title: 'Shop the collections',
72
+ description: 'Curated edits for the season.',
73
+ items: [{
74
+ entityId: 'pUx3mVQ1TmyN2mVYQqQ8Jg',
75
+ entityType: 'collection',
76
+ entityUrl: 'web5://entity/collection/pUx3mVQ1TmyN2mVYQqQ8Jg',
77
+ linkText: 'Running',
78
+ description: 'Shoes and kit built for the road'
79
+ }, {
80
+ entityId: 'Rr8kQyO0S1uH2nQ0mQ2AqQ',
81
+ entityType: 'collection',
82
+ entityUrl: 'web5://entity/collection/Rr8kQyO0S1uH2nQ0mQ2AqQ',
83
+ linkText: 'Trail',
84
+ description: 'Grip and protection off-road'
85
+ }]
86
+ }
87
+ }, {
88
+ // The shape the orchestrator emits: a section descriptor, empty link
89
+ // text, and a Shopify gid (which is itself a `://` url) as the entity id.
90
+ 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',
91
+ expected: {
92
+ title: 'Curated collections by theme',
93
+ items: [{
94
+ entityId: 'gid://shopify/Collection/347895267466',
95
+ entityType: 'collection',
96
+ entityUrl: 'web5://entity/collection/gid://shopify/Collection/347895267466',
97
+ description: 'storewide assortment spanning the full product range'
98
+ }, {
99
+ entityId: 'gid://shopify/Collection/348001501322',
100
+ entityType: 'collection',
101
+ entityUrl: 'web5://entity/collection/gid://shopify/Collection/348001501322',
102
+ // Inline emphasis survives — descriptions keep their markdown.
103
+ description: 'artistic **Watercolor** candles with bright vessels'
104
+ }]
105
+ }
106
+ }, {
107
+ // Single collection — the full-width banner shape.
108
+ markdown: '## Winter essentials\n\n- [Shop winter](web5://entity/collection/aB1cD2eF3gH4iJ5kL6mN7o) Layers for the cold months',
109
+ expected: {
110
+ title: 'Winter essentials',
111
+ items: [{
112
+ entityId: 'aB1cD2eF3gH4iJ5kL6mN7o',
113
+ entityType: 'collection',
114
+ entityUrl: 'web5://entity/collection/aB1cD2eF3gH4iJ5kL6mN7o',
115
+ linkText: 'Shop winter',
116
+ description: 'Layers for the cold months'
117
+ }]
118
+ }
119
+ }]);
120
+ }
121
+ parse(parts, context) {
122
+ const entityRefs = (0, _parseUtils.extractEntityRefs)(parts);
123
+ if (entityRefs.length === 0) {
124
+ context == null || context.reportDiagnostic == null || context.reportDiagnostic(_diagnosticTypes.DIAGNOSTIC_TYPES.SECTION_REJECTED, 'entityCollection: no entity links found');
125
+ return null;
126
+ }
127
+
128
+ // Guard the pattern: anything that is not a collection means this block
129
+ // belongs to the generic entity section, not here.
130
+ if (entityRefs.some(e => e.entityType !== COLLECTION_ENTITY_TYPE)) {
131
+ context == null || context.reportDiagnostic == null || context.reportDiagnostic(_diagnosticTypes.DIAGNOSTIC_TYPES.SECTION_REJECTED, 'entityCollection: block mixes collections with other entity types');
132
+ return null;
133
+ }
134
+ const title = (0, _parseUtils.headingText)(parts, 2) || 'Collections';
135
+ const description = (0, _parseUtils.entitySectionBodyText)(parts) || undefined;
136
+
137
+ // Every entity link lives inside the list, so any top-level callout is
138
+ // section-level by construction — per-item callouts are nested in the list
139
+ // items and are picked up by extractEntityRefs instead.
140
+ const callout = (0, _parseUtils.calloutFromParts)(parts);
141
+ const items = entityRefs.map(e => ({
142
+ entityId: e.entityId,
143
+ entityType: e.entityType,
144
+ entityUrl: e.entityUrl,
145
+ linkText: e.linkText || undefined,
146
+ description: e.description || undefined,
147
+ imageUrl: e.markdownImageUrl,
148
+ callout: e.callout
149
+ }));
150
+ return {
151
+ title,
152
+ description,
153
+ callout,
154
+ items
155
+ };
156
+ }
157
+ }
158
+ exports.EntityCollectionSectionDefinition = EntityCollectionSectionDefinition;
159
+ //# sourceMappingURL=EntityCollectionSectionDefinition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_parseUtils","require","_diagnosticTypes","COLLECTION_ENTITY_TYPE","EntityCollectionSectionDefinition","constructor","_defineProperty2","default","title","items","entityId","entityType","entityUrl","linkText","markdown","expected","description","parse","parts","context","entityRefs","extractEntityRefs","length","reportDiagnostic","DIAGNOSTIC_TYPES","SECTION_REJECTED","some","e","headingText","entitySectionBodyText","undefined","callout","calloutFromParts","map","imageUrl","markdownImageUrl","exports"],"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":";;;;;;AAAA,IAAAA,WAAA,GAAAC,OAAA;AAcA,IAAAC,gBAAA,GAAAD,OAAA;AAEA;AACA;AACA;AACA;AACA,MAAME,sBAAsB,GAAG,YAAY;;AAE3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMC,iCAAiC,CAE9C;EAAAC,YAAA;IAAA,IAAAC,gBAAA,CAAAC,OAAA,uBACgB,kBAAkB;IAChC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;IAlBE,IAAAD,gBAAA,CAAAC,OAAA,oBAmBW,CACT,6HAA6H,CAC9H;IAAA,IAAAD,gBAAA,CAAAC,OAAA,oBAE2B;MAC1BC,KAAK,EAAE,aAAa;MACpBC,KAAK,EAAE,CACL;QACEC,QAAQ,EAAE,WAAW;QACrBC,UAAU,EAAER,sBAAsB;QAClCS,SAAS,EAAE,oCAAoC;QAC/CC,QAAQ,EAAE;MACZ,CAAC;IAEL,CAAC;IAAA,IAAAP,gBAAA,CAAAC,OAAA,oBAE6C,CAC5C;MACEO,QAAQ,EACN,oPAAoP;MACtPC,QAAQ,EAAE;QACRP,KAAK,EAAE,sBAAsB;QAC7BQ,WAAW,EAAE,+BAA+B;QAC5CP,KAAK,EAAE,CACL;UACEC,QAAQ,EAAE,wBAAwB;UAClCC,UAAU,EAAE,YAAY;UACxBC,SAAS,EAAE,iDAAiD;UAC5DC,QAAQ,EAAE,SAAS;UACnBG,WAAW,EAAE;QACf,CAAC,EACD;UACEN,QAAQ,EAAE,wBAAwB;UAClCC,UAAU,EAAE,YAAY;UACxBC,SAAS,EAAE,iDAAiD;UAC5DC,QAAQ,EAAE,OAAO;UACjBG,WAAW,EAAE;QACf,CAAC;MAEL;IACF,CAAC,EACD;MACE;MACA;MACAF,QAAQ,EACN,iUAAiU;MACnUC,QAAQ,EAAE;QACRP,KAAK,EAAE,8BAA8B;QACrCC,KAAK,EAAE,CACL;UACEC,QAAQ,EAAE,uCAAuC;UACjDC,UAAU,EAAE,YAAY;UACxBC,SAAS,EACP,gEAAgE;UAClEI,WAAW,EAAE;QACf,CAAC,EACD;UACEN,QAAQ,EAAE,uCAAuC;UACjDC,UAAU,EAAE,YAAY;UACxBC,SAAS,EACP,gEAAgE;UAClE;UACAI,WAAW,EAAE;QACf,CAAC;MAEL;IACF,CAAC,EACD;MACE;MACAF,QAAQ,EACN,qHAAqH;MACvHC,QAAQ,EAAE;QACRP,KAAK,EAAE,mBAAmB;QAC1BC,KAAK,EAAE,CACL;UACEC,QAAQ,EAAE,wBAAwB;UAClCC,UAAU,EAAE,YAAY;UACxBC,SAAS,EAAE,iDAAiD;UAC5DC,QAAQ,EAAE,aAAa;UACvBG,WAAW,EAAE;QACf,CAAC;MAEL;IACF,CAAC,CACF;EAAA;EAEDC,KAAKA,CAACC,KAAa,EAAEC,OAAsB,EAA0B;IACnE,MAAMC,UAAU,GAAG,IAAAC,6BAAiB,EAACH,KAAK,CAAC;IAE3C,IAAIE,UAAU,CAACE,MAAM,KAAK,CAAC,EAAE;MAC3BH,OAAO,YAAPA,OAAO,CAAEI,gBAAgB,YAAzBJ,OAAO,CAAEI,gBAAgB,CACvBC,iCAAgB,CAACC,gBAAgB,EACjC,yCACF,CAAC;MACD,OAAO,IAAI;IACb;;IAEA;IACA;IACA,IAAIL,UAAU,CAACM,IAAI,CAAEC,CAAC,IAAKA,CAAC,CAAChB,UAAU,KAAKR,sBAAsB,CAAC,EAAE;MACnEgB,OAAO,YAAPA,OAAO,CAAEI,gBAAgB,YAAzBJ,OAAO,CAAEI,gBAAgB,CACvBC,iCAAgB,CAACC,gBAAgB,EACjC,mEACF,CAAC;MACD,OAAO,IAAI;IACb;IAEA,MAAMjB,KAAK,GAAG,IAAAoB,uBAAW,EAACV,KAAK,EAAE,CAAC,CAAC,IAAI,aAAa;IACpD,MAAMF,WAAW,GAAG,IAAAa,iCAAqB,EAACX,KAAK,CAAC,IAAIY,SAAS;;IAE7D;IACA;IACA;IACA,MAAMC,OAAO,GAAG,IAAAC,4BAAgB,EAACd,KAAK,CAAC;IAEvC,MAAMT,KAAmB,GAAGW,UAAU,CAACa,GAAG,CAAEN,CAAC,KAAM;MACjDjB,QAAQ,EAAEiB,CAAC,CAACjB,QAAQ;MACpBC,UAAU,EAAEgB,CAAC,CAAChB,UAAU;MACxBC,SAAS,EAAEe,CAAC,CAACf,SAAS;MACtBC,QAAQ,EAAEc,CAAC,CAACd,QAAQ,IAAIiB,SAAS;MACjCd,WAAW,EAAEW,CAAC,CAACX,WAAW,IAAIc,SAAS;MACvCI,QAAQ,EAAEP,CAAC,CAACQ,gBAAgB;MAC5BJ,OAAO,EAAEJ,CAAC,CAACI;IACb,CAAC,CAAC,CAAC;IAEH,OAAO;MAAEvB,KAAK;MAAEQ,WAAW;MAAEe,OAAO;MAAEtB;IAAM,CAAC;EAC/C;AACF;AAAC2B,OAAA,CAAAhC,iCAAA,GAAAA,iCAAA","ignoreList":[]}
@@ -16,6 +16,8 @@ var _FeatureCardsSectionDefinition = require("./FeatureCardsSectionDefinition");
16
16
  exports.FeatureCardsSectionDefinition = _FeatureCardsSectionDefinition.FeatureCardsSectionDefinition;
17
17
  var _EntitySectionDefinition = require("./EntitySectionDefinition");
18
18
  exports.EntitySectionDefinition = _EntitySectionDefinition.EntitySectionDefinition;
19
+ var _EntityCollectionSectionDefinition = require("./EntityCollectionSectionDefinition");
20
+ exports.EntityCollectionSectionDefinition = _EntityCollectionSectionDefinition.EntityCollectionSectionDefinition;
19
21
  var _CtaBannerSectionDefinition = require("./CtaBannerSectionDefinition");
20
22
  exports.CtaBannerSectionDefinition = _CtaBannerSectionDefinition.CtaBannerSectionDefinition;
21
23
  var _CalloutSectionDefinition = require("./CalloutSectionDefinition");
@@ -43,6 +45,10 @@ var _registry = require("../../registry");
43
45
  * Registration order determines evaluation priority — first match wins.
44
46
  */
45
47
  function createSdkRegistry() {
46
- return new _registry.ComponentRegistry(null).register(new _SkipNodesSectionDefinition.SkipNodesSectionDefinition()).register(new _SearchSectionDefinition.SearchSectionDefinition()).register(new _KpiSectionDefinition.KpiSectionDefinition()).register(new _NextStepsSectionDefinition.NextStepsSectionDefinition()).register(new _EntitySectionDefinition.EntitySectionDefinition()).register(new _HeroEntitySectionDefinition.HeroEntitySectionDefinition()).register(new _HeroSectionDefinition.HeroSectionDefinition()).register(new _FeatureCardsSectionDefinition.FeatureCardsSectionDefinition()).register(new _TextBlockSectionDefinition.TextBlockSectionDefinition()).register(new _listItemsSectionDefinition.ListItemsSectionDefinition()).register(new _FeatureSection9PlusDefinition.FeatureSection9PlusDefinition()).register(new _ComparisonSectionDefinition.ComparisonSectionDefinition()).register(new _HtmlCommentSectionDefinition.HtmlCommentSectionDefinition()).register(new _CtaBannerSectionDefinition.CtaBannerSectionDefinition()).register(new _CalloutSectionDefinition.CalloutSectionDefinition()).register(new _FallbackSectionDefinition.FallbackSectionDefinition()).register(new _ErrorSectionDefinition.ErrorSectionDefinition());
48
+ return new _registry.ComponentRegistry(null).register(new _SkipNodesSectionDefinition.SkipNodesSectionDefinition()).register(new _SearchSectionDefinition.SearchSectionDefinition()).register(new _KpiSectionDefinition.KpiSectionDefinition()).register(new _NextStepsSectionDefinition.NextStepsSectionDefinition())
49
+ // Collection entities are claimed by their own definition first — it is a
50
+ // strictly narrower match than EntitySectionDefinition, which would
51
+ // otherwise swallow collection, product and article blocks alike.
52
+ .register(new _EntityCollectionSectionDefinition.EntityCollectionSectionDefinition()).register(new _EntitySectionDefinition.EntitySectionDefinition()).register(new _HeroEntitySectionDefinition.HeroEntitySectionDefinition()).register(new _HeroSectionDefinition.HeroSectionDefinition()).register(new _FeatureCardsSectionDefinition.FeatureCardsSectionDefinition()).register(new _TextBlockSectionDefinition.TextBlockSectionDefinition()).register(new _listItemsSectionDefinition.ListItemsSectionDefinition()).register(new _FeatureSection9PlusDefinition.FeatureSection9PlusDefinition()).register(new _ComparisonSectionDefinition.ComparisonSectionDefinition()).register(new _HtmlCommentSectionDefinition.HtmlCommentSectionDefinition()).register(new _CtaBannerSectionDefinition.CtaBannerSectionDefinition()).register(new _CalloutSectionDefinition.CalloutSectionDefinition()).register(new _FallbackSectionDefinition.FallbackSectionDefinition()).register(new _ErrorSectionDefinition.ErrorSectionDefinition());
47
53
  }
48
54
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_ComparisonSectionDefinition","require","exports","ComparisonSectionDefinition","_TextBlockSectionDefinition","TextBlockSectionDefinition","_HeroSectionDefinition","HeroSectionDefinition","_HeroEntitySectionDefinition","HeroEntitySectionDefinition","_KpiSectionDefinition","KpiSectionDefinition","_FeatureCardsSectionDefinition","FeatureCardsSectionDefinition","_EntitySectionDefinition","EntitySectionDefinition","_CtaBannerSectionDefinition","CtaBannerSectionDefinition","_CalloutSectionDefinition","CalloutSectionDefinition","_NextStepsSectionDefinition","NextStepsSectionDefinition","_FeatureSection9PlusDefinition","FeatureSection9PlusDefinition","_listItemsSectionDefinition","ListItemsSectionDefinition","_SkipNodesSectionDefinition","SkipNodesSectionDefinition","_HtmlCommentSectionDefinition","HtmlCommentSectionDefinition","_SearchSectionDefinition","SearchSectionDefinition","_ErrorSectionDefinition","ErrorSectionDefinition","_FallbackSectionDefinition","FallbackSectionDefinition","_registry","createSdkRegistry","ComponentRegistry","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":"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","ignoreList":[]}
1
+ {"version":3,"names":["_ComparisonSectionDefinition","require","exports","ComparisonSectionDefinition","_TextBlockSectionDefinition","TextBlockSectionDefinition","_HeroSectionDefinition","HeroSectionDefinition","_HeroEntitySectionDefinition","HeroEntitySectionDefinition","_KpiSectionDefinition","KpiSectionDefinition","_FeatureCardsSectionDefinition","FeatureCardsSectionDefinition","_EntitySectionDefinition","EntitySectionDefinition","_EntityCollectionSectionDefinition","EntityCollectionSectionDefinition","_CtaBannerSectionDefinition","CtaBannerSectionDefinition","_CalloutSectionDefinition","CalloutSectionDefinition","_NextStepsSectionDefinition","NextStepsSectionDefinition","_FeatureSection9PlusDefinition","FeatureSection9PlusDefinition","_listItemsSectionDefinition","ListItemsSectionDefinition","_SkipNodesSectionDefinition","SkipNodesSectionDefinition","_HtmlCommentSectionDefinition","HtmlCommentSectionDefinition","_SearchSectionDefinition","SearchSectionDefinition","_ErrorSectionDefinition","ErrorSectionDefinition","_FallbackSectionDefinition","FallbackSectionDefinition","_registry","createSdkRegistry","ComponentRegistry","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":[]}
@@ -12,6 +12,7 @@ var _linkTypes = require("../types/link-types");
12
12
  var _web5LinkValidator = require("../utils/web5LinkValidator");
13
13
  var _diagnosticTypes = require("./diagnosticTypes");
14
14
  var _componentTracking = require("../utils/componentTracking");
15
+ var _matchDebug = require("../utils/matchDebug");
15
16
  var _diagnosticsCollector = require("../utils/diagnosticsCollector");
16
17
  var _unifiedMarkdownParser = require("../utils/unifiedMarkdownParser");
17
18
  var _markdownPreprocessor = require("../utils/markdownPreprocessor");
@@ -37,8 +38,17 @@ var _propsExtractor = require("../utils/propsExtractor");
37
38
  function isEntityCompProps(props) {
38
39
  return typeof props === 'object' && props !== null && Array.isArray(props.items);
39
40
  }
41
+
42
+ /**
43
+ * Section types whose props are `EntityCompProps` and therefore participate in
44
+ * payload enrichment. `entityCollection` is `entity` narrowed to collection
45
+ * links — it produces the same props and arrives under the same
46
+ * `semantic: items` descriptor, so leaving it out would silently strip its
47
+ * items of their catalog data (image, title) and render the section blank.
48
+ */
49
+ const ENRICHABLE_ENTITY_SECTION_TYPES = new Set(['entity', 'entityCollection']);
40
50
  function isItemsFromContentSection(sectionType, semantic, serverSectionId) {
41
- if (sectionType !== 'entity') {
51
+ if (!ENRICHABLE_ENTITY_SECTION_TYPES.has(sectionType)) {
42
52
  return false;
43
53
  }
44
54
  const normalizedSemantic = semantic == null ? void 0 : semantic.toLowerCase().replace(/_/g, '-');
@@ -268,6 +278,15 @@ function tryParseComponent(nodes, sectionIndex, context) {
268
278
  setMeta: context.tracking ? (sectionType, key, value) => context.tracking.setMeta(sectionType, key, value) : undefined,
269
279
  getMeta: context.tracking ? (sectionType, key) => context.tracking.getMeta(sectionType, key) : undefined
270
280
  };
281
+
282
+ // Debug-only trace (`?web5DebugMatch=1`). The registry order line doubles as
283
+ // a "is my definition even registered?" check — a definition missing from it
284
+ // never reached `register()` (stale client bundle / web5-core version skew).
285
+ const trace = (0, _matchDebug.isMatchDebugEnabled)();
286
+ if (trace) {
287
+ (0, _matchDebug.logMatchDebug)(`block #${sectionIndex} [${nodes.map(n => n.type).join(', ')}]`);
288
+ (0, _matchDebug.logMatchDebug)(` registry order: ${definitions.map(d => d.sectionType).join(' > ')}`);
289
+ }
271
290
  for (const {
272
291
  sectionType,
273
292
  definition
@@ -277,12 +296,18 @@ function tryParseComponent(nodes, sectionIndex, context) {
277
296
  // render (the main app) — their markdown should fall through to the generic
278
297
  // sections there. Skip them unless this is a placement parse.
279
298
  if (!placement && registry.isPlacementOnly(sectionType)) {
299
+ if (trace) {
300
+ (0, _matchDebug.logMatchDebug)(` ${sectionType}: skipped (placement-only)`);
301
+ }
280
302
  continue;
281
303
  }
282
304
  for (const pattern of definition.patterns) {
283
305
  var _parts$find, _context$intent;
284
306
  const result = (0, _patternValidator.validatePattern)(nodes, pattern);
285
307
  if (!result.valid) {
308
+ if (trace) {
309
+ (0, _matchDebug.logMatchDebug)(` ${sectionType}: no match — ${result.error ?? 'pattern did not match'}\n pattern: ${pattern}`);
310
+ }
286
311
  continue;
287
312
  }
288
313
  let parsedNodes = result.astEndIndex !== undefined && result.astEndIndex >= 0 ? result.astEndIndex + 1 : result.endIndex >= 0 ? result.endIndex + 1 : 1;
@@ -305,8 +330,14 @@ function tryParseComponent(nodes, sectionIndex, context) {
305
330
  };
306
331
  let props = definition.parse(parts, parseContext);
307
332
  if (props === null) {
333
+ if (trace) {
334
+ (0, _matchDebug.logMatchDebug)(` ${sectionType}: pattern matched ${parsedNodes} node(s) but parse() returned null — falling through`);
335
+ }
308
336
  continue;
309
337
  }
338
+ if (trace) {
339
+ (0, _matchDebug.logMatchDebug)(` ${sectionType}: MATCHED ${parsedNodes} node(s) via ${pattern}`);
340
+ }
310
341
  const leadingHtmlCommentMeta = (_parts$find = parts.find(p => p.type === 'htmlComment' && p.meta)) == null ? void 0 : _parts$find.meta;
311
342
  const semantic = leadingHtmlCommentMeta == null ? void 0 : leadingHtmlCommentMeta.semantic;
312
343
  const serverSectionId = leadingHtmlCommentMeta == null ? void 0 : leadingHtmlCommentMeta.id;
@@ -320,6 +351,9 @@ function tryParseComponent(nodes, sectionIndex, context) {
320
351
  });
321
352
  }
322
353
  if (definition.singleInstance && context.tracking && context.tracking.getComponentCount(sectionType) > 0) {
354
+ if (trace) {
355
+ (0, _matchDebug.logMatchDebug)(` ${sectionType}: dropped (singleInstance, already rendered once)`);
356
+ }
323
357
  continue;
324
358
  }
325
359
  const isNullComponent = definition.nullComponent === true;
@@ -367,6 +401,9 @@ function tryParseComponent(nodes, sectionIndex, context) {
367
401
  };
368
402
  }
369
403
  }
404
+ if (trace) {
405
+ (0, _matchDebug.logMatchDebug)(' no definition claimed this block');
406
+ }
370
407
  return {};
371
408
  }
372
409
  //# sourceMappingURL=componentParser.js.map