@wix/web5-core 1.58.0 → 1.60.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 (103) hide show
  1. package/dist/cjs/client/applyThemeOverrides.js +89 -0
  2. package/dist/cjs/client/applyThemeOverrides.js.map +1 -0
  3. package/dist/cjs/client/clientBundleUrl.js +43 -0
  4. package/dist/cjs/client/clientBundleUrl.js.map +1 -1
  5. package/dist/cjs/component/componentDefinitions/ComparisonSectionDefinition.js +33 -1
  6. package/dist/cjs/component/componentDefinitions/ComparisonSectionDefinition.js.map +1 -1
  7. package/dist/cjs/component/componentDefinitions/FeatureSection9PlusDefinition.js +9 -5
  8. package/dist/cjs/component/componentDefinitions/FeatureSection9PlusDefinition.js.map +1 -1
  9. package/dist/cjs/component/componentDefinitions/HeroEntitySectionDefinition.js +5 -2
  10. package/dist/cjs/component/componentDefinitions/HeroEntitySectionDefinition.js.map +1 -1
  11. package/dist/cjs/component/componentDefinitions/HeroSectionDefinition.js +4 -1
  12. package/dist/cjs/component/componentDefinitions/HeroSectionDefinition.js.map +1 -1
  13. package/dist/cjs/component/componentDefinitions/NextStepsSectionDefinition.js +35 -2
  14. package/dist/cjs/component/componentDefinitions/NextStepsSectionDefinition.js.map +1 -1
  15. package/dist/cjs/component/componentDefinitions/TextBlockSectionDefinition.js +27 -1
  16. package/dist/cjs/component/componentDefinitions/TextBlockSectionDefinition.js.map +1 -1
  17. package/dist/cjs/component/componentDefinitions/index.js +8 -1
  18. package/dist/cjs/component/componentDefinitions/index.js.map +1 -1
  19. package/dist/cjs/component/componentDefinitions/listItemsSectionDefinition.js +10 -5
  20. package/dist/cjs/component/componentDefinitions/listItemsSectionDefinition.js.map +1 -1
  21. package/dist/cjs/component/componentDefinitions/parse-utils.js +45 -8
  22. package/dist/cjs/component/componentDefinitions/parse-utils.js.map +1 -1
  23. package/dist/cjs/component/componentParser.js +15 -0
  24. package/dist/cjs/component/componentParser.js.map +1 -1
  25. package/dist/cjs/component/section-definition.js +14 -0
  26. package/dist/cjs/component/section-definition.js.map +1 -1
  27. package/dist/cjs/component/types.js.map +1 -1
  28. package/dist/cjs/components/ui/MarkdownText.js +41 -42
  29. package/dist/cjs/components/ui/MarkdownText.js.map +1 -1
  30. package/dist/cjs/components/ui/UnifiedLink.js +22 -10
  31. package/dist/cjs/components/ui/UnifiedLink.js.map +1 -1
  32. package/dist/cjs/hostScope.js.map +1 -1
  33. package/dist/cjs/index.js +13 -3
  34. package/dist/cjs/index.js.map +1 -1
  35. package/dist/cjs/utils/markdownPreprocessor.js +162 -8
  36. package/dist/cjs/utils/markdownPreprocessor.js.map +1 -1
  37. package/dist/esm/client/applyThemeOverrides.js +85 -0
  38. package/dist/esm/client/applyThemeOverrides.js.map +1 -0
  39. package/dist/esm/client/clientBundleUrl.js +39 -0
  40. package/dist/esm/client/clientBundleUrl.js.map +1 -1
  41. package/dist/esm/component/componentDefinitions/ComparisonSectionDefinition.js +34 -1
  42. package/dist/esm/component/componentDefinitions/ComparisonSectionDefinition.js.map +1 -1
  43. package/dist/esm/component/componentDefinitions/FeatureSection9PlusDefinition.js +10 -6
  44. package/dist/esm/component/componentDefinitions/FeatureSection9PlusDefinition.js.map +1 -1
  45. package/dist/esm/component/componentDefinitions/HeroEntitySectionDefinition.js +6 -3
  46. package/dist/esm/component/componentDefinitions/HeroEntitySectionDefinition.js.map +1 -1
  47. package/dist/esm/component/componentDefinitions/HeroSectionDefinition.js +5 -2
  48. package/dist/esm/component/componentDefinitions/HeroSectionDefinition.js.map +1 -1
  49. package/dist/esm/component/componentDefinitions/NextStepsSectionDefinition.js +36 -3
  50. package/dist/esm/component/componentDefinitions/NextStepsSectionDefinition.js.map +1 -1
  51. package/dist/esm/component/componentDefinitions/TextBlockSectionDefinition.js +27 -1
  52. package/dist/esm/component/componentDefinitions/TextBlockSectionDefinition.js.map +1 -1
  53. package/dist/esm/component/componentDefinitions/index.js +8 -1
  54. package/dist/esm/component/componentDefinitions/index.js.map +1 -1
  55. package/dist/esm/component/componentDefinitions/listItemsSectionDefinition.js +11 -6
  56. package/dist/esm/component/componentDefinitions/listItemsSectionDefinition.js.map +1 -1
  57. package/dist/esm/component/componentDefinitions/parse-utils.js +44 -8
  58. package/dist/esm/component/componentDefinitions/parse-utils.js.map +1 -1
  59. package/dist/esm/component/componentParser.js +15 -0
  60. package/dist/esm/component/componentParser.js.map +1 -1
  61. package/dist/esm/component/section-definition.js +13 -1
  62. package/dist/esm/component/section-definition.js.map +1 -1
  63. package/dist/esm/component/types.js.map +1 -1
  64. package/dist/esm/components/ui/MarkdownText.js +8 -9
  65. package/dist/esm/components/ui/MarkdownText.js.map +1 -1
  66. package/dist/esm/components/ui/UnifiedLink.js +7 -1
  67. package/dist/esm/components/ui/UnifiedLink.js.map +1 -1
  68. package/dist/esm/hostScope.js.map +1 -1
  69. package/dist/esm/index.js +4 -1
  70. package/dist/esm/index.js.map +1 -1
  71. package/dist/esm/utils/markdownPreprocessor.js +160 -8
  72. package/dist/esm/utils/markdownPreprocessor.js.map +1 -1
  73. package/dist/types/client/applyThemeOverrides.d.ts +19 -0
  74. package/dist/types/client/applyThemeOverrides.d.ts.map +1 -0
  75. package/dist/types/client/clientBundleUrl.d.ts +22 -0
  76. package/dist/types/client/clientBundleUrl.d.ts.map +1 -1
  77. package/dist/types/component/componentDefinitions/ComparisonSectionDefinition.d.ts +2 -2
  78. package/dist/types/component/componentDefinitions/ComparisonSectionDefinition.d.ts.map +1 -1
  79. package/dist/types/component/componentDefinitions/FeatureSection9PlusDefinition.d.ts.map +1 -1
  80. package/dist/types/component/componentDefinitions/HeroEntitySectionDefinition.d.ts.map +1 -1
  81. package/dist/types/component/componentDefinitions/HeroSectionDefinition.d.ts.map +1 -1
  82. package/dist/types/component/componentDefinitions/NextStepsSectionDefinition.d.ts.map +1 -1
  83. package/dist/types/component/componentDefinitions/TextBlockSectionDefinition.d.ts.map +1 -1
  84. package/dist/types/component/componentDefinitions/index.d.ts.map +1 -1
  85. package/dist/types/component/componentDefinitions/listItemsSectionDefinition.d.ts.map +1 -1
  86. package/dist/types/component/componentDefinitions/parse-utils.d.ts +10 -0
  87. package/dist/types/component/componentDefinitions/parse-utils.d.ts.map +1 -1
  88. package/dist/types/component/componentParser.d.ts.map +1 -1
  89. package/dist/types/component/section-definition.d.ts +13 -1
  90. package/dist/types/component/section-definition.d.ts.map +1 -1
  91. package/dist/types/component/types.d.ts +7 -0
  92. package/dist/types/component/types.d.ts.map +1 -1
  93. package/dist/types/components/ui/MarkdownText.d.ts +13 -0
  94. package/dist/types/components/ui/MarkdownText.d.ts.map +1 -1
  95. package/dist/types/components/ui/UnifiedLink.d.ts +1 -1
  96. package/dist/types/components/ui/UnifiedLink.d.ts.map +1 -1
  97. package/dist/types/hostScope.d.ts +11 -0
  98. package/dist/types/hostScope.d.ts.map +1 -1
  99. package/dist/types/index.d.ts +4 -2
  100. package/dist/types/index.d.ts.map +1 -1
  101. package/dist/types/utils/markdownPreprocessor.d.ts +30 -5
  102. package/dist/types/utils/markdownPreprocessor.d.ts.map +1 -1
  103. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
- import { headingText, bodyText, extractListItemText } from './parse-utils.js';
2
+ import { headingText, bodyText, extractListItemText, inlinePartsToMarkdown } from './parse-utils.js';
3
3
  import { getPartsByType } from '../../parts/parts.js';
4
4
  export class FeatureSection9PlusDefinition {
5
5
  constructor() {
@@ -21,14 +21,18 @@ export class FeatureSection9PlusDefinition {
21
21
  var _list$meta, _item$meta, _iconPart$meta, _item$meta2;
22
22
  const itemParts = ((_item$meta = item.meta) == null ? void 0 : _item$meta.parts) ?? [];
23
23
  const heading = itemParts.find(p => p.type === 'heading');
24
- const textParts = itemParts.filter(p => p.type === 'text' || p.type === 'richText');
25
- const featureDescription = textParts.map(p => {
26
- var _p$content;
27
- return (_p$content = p.content) == null ? void 0 : _p$content.trim();
28
- }).filter(Boolean).join('\n');
29
24
  const iconPart = itemParts.find(p => p.type === 'icon');
30
25
  const iconHint = iconPart == null || (_iconPart$meta = iconPart.meta) == null ? void 0 : _iconPart$meta.iconHint;
31
26
 
27
+ // Everything except the heading and the leading icon is the body.
28
+ // Serialize it rather than concatenating `content`: filtering to text
29
+ // parts used to drop `link` parts wholesale, deleting an inline link's
30
+ // url and label together. Same defect as listItemsSectionDefinition —
31
+ // this definition sits below that one in every registry, but the seed's
32
+ // FeatureIconsSection is registered against the other definition while
33
+ // typed on this one's props, so both have to behave the same.
34
+ const featureDescription = inlinePartsToMarkdown(itemParts.filter(p => p !== heading && p !== iconPart));
35
+
32
36
  // Try to parse bold title from markdown (preserves **bold**) or plain content
33
37
  // Strip leading icon markdown (e.g., "![](web5://icon/hint) ") before bold matching
34
38
  const rawMarkdown = (_item$meta2 = item.meta) == null || (_item$meta2 = _item$meta2.markdown) == null ? void 0 : _item$meta2.trim();
@@ -1 +1 @@
1
- {"version":3,"names":["headingText","bodyText","extractListItemText","getPartsByType","FeatureSection9PlusDefinition","constructor","_defineProperty","title","features","parse","parts","description","undefined","lists","list","item","_list$meta","meta","items","_item$meta","_iconPart$meta","_item$meta2","itemParts","heading","find","p","type","textParts","filter","featureDescription","map","_p$content","content","trim","Boolean","join","iconPart","iconHint","rawMarkdown","markdown","replace","boldMatch","match","iconField","_heading$content","push"],"sources":["../../../../src/component/componentDefinitions/FeatureSection9PlusDefinition.ts"],"sourcesContent":["import {\n headingText,\n bodyText,\n extractListItemText,\n} from './parse-utils';\nimport {\n getPartsByType,\n type Part,\n type ListPart,\n type IconPart,\n} from '../../parts/parts';\nimport type {\n FeatureSection9PlusCompProps,\n FeatureSection9PlusSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition } from '../section-definition';\n\nexport class FeatureSection9PlusDefinition\n implements SectionDefinition<FeatureSection9PlusSectionComponent>\n{\n sectionType = 'featureSection9Plus' as const;\n patterns = [\n 'html_comment? > (h2 | h3) > t? > list{item[2-]:(icon | h3 | t | link)* > t+}',\n ];\n\n defaults: FeatureSection9PlusCompProps = {\n title: 'Features',\n features: [],\n };\n\n fixtures: SectionFixture<FeatureSection9PlusCompProps>[] = [];\n\n parse(parts: Part[]): FeatureSection9PlusCompProps {\n const title = headingText(parts, 2) || headingText(parts, 3) || 'Features';\n const description = bodyText(parts) || undefined;\n\n const features: {\n title?: string;\n description: string;\n iconHint?: string;\n }[] = [];\n const lists = getPartsByType<ListPart>(parts, 'list');\n\n for (const list of lists) {\n for (const item of list.meta?.items ?? []) {\n const itemParts = (item.meta?.parts ?? []) as Part[];\n const heading = itemParts.find((p) => p.type === 'heading');\n const textParts = itemParts.filter(\n (p) => p.type === 'text' || p.type === 'richText',\n );\n const featureDescription = textParts\n .map((p) => p.content?.trim())\n .filter(Boolean)\n .join('\\n');\n\n const iconPart = itemParts.find((p) => p.type === 'icon') as\n | IconPart\n | undefined;\n const iconHint = (iconPart?.meta as { iconHint?: string })?.iconHint;\n\n // Try to parse bold title from markdown (preserves **bold**) or plain content\n // Strip leading icon markdown (e.g., \"![](web5://icon/hint) \") before bold matching\n const rawMarkdown = (item.meta?.markdown as string)?.trim();\n const markdown = rawMarkdown\n ?.replace(/^!\\[[^\\]]*\\]\\([^)]*\\)\\s*/, '')\n .trim();\n const content = markdown || extractListItemText(item);\n const boldMatch = content.match(/^\\*\\*([^*]+)\\*\\*:?\\s*(.*)/s);\n\n const iconField = iconHint ? { iconHint } : {};\n\n if (heading) {\n features.push({\n title: heading.content?.trim(),\n description: featureDescription || content,\n ...iconField,\n });\n } else if (boldMatch) {\n features.push({\n title: boldMatch[1].trim(),\n description: boldMatch[2].trim() || featureDescription,\n ...iconField,\n });\n } else {\n features.push({\n description: featureDescription || content,\n ...iconField,\n });\n }\n }\n }\n\n return { title, description, features };\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["headingText","bodyText","extractListItemText","inlinePartsToMarkdown","getPartsByType","FeatureSection9PlusDefinition","constructor","_defineProperty","title","features","parse","parts","description","undefined","lists","list","item","_list$meta","meta","items","_item$meta","_iconPart$meta","_item$meta2","itemParts","heading","find","p","type","iconPart","iconHint","featureDescription","filter","rawMarkdown","markdown","trim","replace","content","boldMatch","match","iconField","_heading$content","push"],"sources":["../../../../src/component/componentDefinitions/FeatureSection9PlusDefinition.ts"],"sourcesContent":["import {\n headingText,\n bodyText,\n extractListItemText,\n inlinePartsToMarkdown,\n} from './parse-utils';\nimport {\n getPartsByType,\n type Part,\n type ListPart,\n type IconPart,\n} from '../../parts/parts';\nimport type {\n FeatureSection9PlusCompProps,\n FeatureSection9PlusSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition } from '../section-definition';\n\nexport class FeatureSection9PlusDefinition\n implements SectionDefinition<FeatureSection9PlusSectionComponent>\n{\n sectionType = 'featureSection9Plus' as const;\n patterns = [\n 'html_comment? > (h2 | h3) > t? > list{item[2-]:(icon | h3 | t | link)* > t+}',\n ];\n\n defaults: FeatureSection9PlusCompProps = {\n title: 'Features',\n features: [],\n };\n\n fixtures: SectionFixture<FeatureSection9PlusCompProps>[] = [];\n\n parse(parts: Part[]): FeatureSection9PlusCompProps {\n const title = headingText(parts, 2) || headingText(parts, 3) || 'Features';\n const description = bodyText(parts) || undefined;\n\n const features: {\n title?: string;\n description: string;\n iconHint?: string;\n }[] = [];\n const lists = getPartsByType<ListPart>(parts, 'list');\n\n for (const list of lists) {\n for (const item of list.meta?.items ?? []) {\n const itemParts = (item.meta?.parts ?? []) as Part[];\n const heading = itemParts.find((p) => p.type === 'heading');\n\n const iconPart = itemParts.find((p) => p.type === 'icon') as\n | IconPart\n | undefined;\n const iconHint = (iconPart?.meta as { iconHint?: string })?.iconHint;\n\n // Everything except the heading and the leading icon is the body.\n // Serialize it rather than concatenating `content`: filtering to text\n // parts used to drop `link` parts wholesale, deleting an inline link's\n // url and label together. Same defect as listItemsSectionDefinition —\n // this definition sits below that one in every registry, but the seed's\n // FeatureIconsSection is registered against the other definition while\n // typed on this one's props, so both have to behave the same.\n const featureDescription = inlinePartsToMarkdown(\n itemParts.filter((p) => p !== heading && p !== iconPart),\n );\n\n // Try to parse bold title from markdown (preserves **bold**) or plain content\n // Strip leading icon markdown (e.g., \"![](web5://icon/hint) \") before bold matching\n const rawMarkdown = (item.meta?.markdown as string)?.trim();\n const markdown = rawMarkdown\n ?.replace(/^!\\[[^\\]]*\\]\\([^)]*\\)\\s*/, '')\n .trim();\n const content = markdown || extractListItemText(item);\n const boldMatch = content.match(/^\\*\\*([^*]+)\\*\\*:?\\s*(.*)/s);\n\n const iconField = iconHint ? { iconHint } : {};\n\n if (heading) {\n features.push({\n title: heading.content?.trim(),\n description: featureDescription || content,\n ...iconField,\n });\n } else if (boldMatch) {\n features.push({\n title: boldMatch[1].trim(),\n description: boldMatch[2].trim() || featureDescription,\n ...iconField,\n });\n } else {\n features.push({\n description: featureDescription || content,\n ...iconField,\n });\n }\n }\n }\n\n return { title, description, features };\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,5 +1,5 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
- import { headingText, bodyText, firstImageSrc, parseCalloutTag, extractEntityRefs } from './parse-utils.js';
2
+ import { headingText, headingMarkdown, bodyText, firstImageSrc, parseCalloutTag, extractEntityRefs } from './parse-utils.js';
3
3
  import { getPartsByType } from '../../parts/parts.js';
4
4
  import { DIAGNOSTIC_TYPES } from '../diagnosticTypes.js';
5
5
 
@@ -49,7 +49,7 @@ Nike offerings span performance and lifestyle lines.
49
49
  * [Nike Life Cable Knit Turtleneck Sweater](web5://entity/product/ZDvHxsa3IJA8CyGX8BNpdw)
50
50
  * [Nike x Jacquemus NRG HE Swoosh Hoodie](web5://entity/product/qH2lqINGneHWYVZzzGnXTA)`,
51
51
  expected: {
52
- headline: 'Nike collections',
52
+ headline: '**Nike** collections',
53
53
  content: 'Nike offerings span performance and lifestyle lines.',
54
54
  image: 'web5://image/Nike+Life+collection',
55
55
  items: [{
@@ -112,7 +112,10 @@ Nike offerings span performance and lifestyle lines.
112
112
  leadingQuote = parseCalloutTag(raw).text || undefined;
113
113
  }
114
114
  return {
115
- headline: headingText(parts, 1),
115
+ // Markdown-preserving (not headingText): the hero title now carries the
116
+ // bold+italic hook the ECHO callout used to own, so the FE needs the
117
+ // formatting, not just the plain text. See FeatureHeroEntity.tsx.
118
+ headline: headingMarkdown(parts, 1),
116
119
  badge: headingText(parts, 3) || undefined,
117
120
  content: bodyText(parts) || undefined,
118
121
  image: firstImageSrc(parts),
@@ -1 +1 @@
1
- {"version":3,"names":["headingText","bodyText","firstImageSrc","parseCalloutTag","extractEntityRefs","getPartsByType","DIAGNOSTIC_TYPES","HeroEntitySectionDefinition","constructor","_defineProperty","headline","content","items","entityId","entityType","entityUrl","linkText","markdown","expected","image","parse","parts","context","entityRefs","length","reportDiagnostic","SECTION_REJECTED","map","e","undefined","description","imageUrl","markdownImageUrl","callout","h1Index","findIndex","p","_p$meta","type","meta","level","blockquotes","leadingQuote","bq","_bq$meta","_bq$content","bqIndex","indexOf","raw","trim","text","badge"],"sources":["../../../../src/component/componentDefinitions/HeroEntitySectionDefinition.ts"],"sourcesContent":["import {\n headingText,\n bodyText,\n firstImageSrc,\n parseCalloutTag,\n extractEntityRefs,\n} from './parse-utils';\nimport type { Part } from '../../parts/parts';\nimport { getPartsByType } from '../../parts/parts';\nimport type {\n EntityItem,\n HeroEntityCompProps,\n HeroEntitySectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition, ParseContext } from '../section-definition';\nimport { DIAGNOSTIC_TYPES } from '../diagnosticTypes';\n\n/**\n * Hero section whose body carries one or more web5 entity links\n * (`web5://entity/...`). It mirrors the framing of {@link HeroSectionDefinition}\n * (leading callout, h1, image, intro text) but, instead of turning the links\n * into CTA buttons, surfaces them as resolvable entities.\n *\n * Registered ahead of `HeroSectionDefinition` so an entity-bearing hero is\n * claimed here first. The pattern requires at least one `link[entityType]`, and\n * `parse()` returns `null` when no entity refs are found, letting a plain hero\n * fall through to `HeroSectionDefinition`.\n */\nexport class HeroEntitySectionDefinition\n implements SectionDefinition<HeroEntitySectionComponent>\n{\n sectionType = 'hero-entity' as const;\n singleInstance = true;\n patterns = [\n // Leading slots mirror HeroSectionDefinition: section descriptor, then the\n // optional leading ECHO callout, then an optional h3 badge, then the h1.\n // Callout and badge are independent; the second `html_comment?` preserves the\n // legacy callout-before-descriptor ordering for pages saved before this change.\n // Entity links carried as list items (the canonical shape).\n 'html_comment? > callout? > html_comment? > h3? > h1 > (image | t | link)* > list{item[1-]:link[entityType] > image? > (t | callout)*}',\n // Entity links sitting at the top level of the hero body.\n 'html_comment? > callout? > html_comment? > h3? > h1 > (image | t)* > (link[entityType] > image? > (t | callout)*)[1-] > list?',\n ];\n\n defaults: HeroEntityCompProps = {\n headline: 'Featured collection',\n content: 'Explore the highlights from this collection.',\n items: [\n {\n entityId: 'example-1',\n entityType: 'product',\n entityUrl: 'web5://entity/product/example-1',\n linkText: 'Example product',\n },\n ],\n };\n\n fixtures: SectionFixture<HeroEntityCompProps>[] = [\n {\n markdown: `<!-- section:hero, id:hero, semantic:hero -->\n\n# **Nike** collections\n\n![Nike Life collection](web5://image/Nike+Life+collection)\nNike offerings span performance and lifestyle lines.\n\n* [Nike Throwback Future Collection](web5://entity/article/WAyuiC63OSjwpvnOyZcblQ)\n* [Nike Life Cable Knit Turtleneck Sweater](web5://entity/product/ZDvHxsa3IJA8CyGX8BNpdw)\n* [Nike x Jacquemus NRG HE Swoosh Hoodie](web5://entity/product/qH2lqINGneHWYVZzzGnXTA)`,\n expected: {\n headline: 'Nike collections',\n content: 'Nike offerings span performance and lifestyle lines.',\n image: 'web5://image/Nike+Life+collection',\n items: [\n {\n entityId: 'WAyuiC63OSjwpvnOyZcblQ',\n entityType: 'article',\n entityUrl:\n 'web5://entity/article/WAyuiC63OSjwpvnOyZcblQ',\n linkText: 'Nike Throwback Future Collection',\n },\n {\n entityId: 'ZDvHxsa3IJA8CyGX8BNpdw',\n entityType: 'product',\n entityUrl:\n 'web5://entity/product/ZDvHxsa3IJA8CyGX8BNpdw',\n linkText: 'Nike Life Cable Knit Turtleneck Sweater',\n },\n {\n entityId: 'qH2lqINGneHWYVZzzGnXTA',\n entityType: 'product',\n entityUrl:\n 'web5://entity/product/qH2lqINGneHWYVZzzGnXTA',\n linkText: 'Nike x Jacquemus NRG HE Swoosh Hoodie',\n },\n ],\n },\n },\n ];\n\n parse(parts: Part[], context?: ParseContext): HeroEntityCompProps | null {\n const entityRefs = extractEntityRefs(parts);\n\n if (entityRefs.length === 0) {\n // Not an entity hero — let HeroSectionDefinition claim it.\n context?.reportDiagnostic?.(\n DIAGNOSTIC_TYPES.SECTION_REJECTED,\n 'hero-entity: no entity links found',\n );\n return null;\n }\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 // The leading callout before the h1 — the ECHO the orchestrator emits as the\n // hero's opening line, right after the section descriptor — is part of the\n // hero, mirroring HeroSectionDefinition. A trailing callout falls through to a\n // downstream callout section. (Per-item callouts inside the entity list are\n // handled by extractEntityRefs above and are unaffected.)\n const h1Index = parts.findIndex(\n (p) =>\n p.type === 'heading' && (p.meta as { level?: number })?.level === 1,\n );\n const blockquotes = getPartsByType<Part>(parts, 'callout');\n let leadingQuote: string | undefined;\n\n for (const bq of blockquotes) {\n const bqIndex = parts.indexOf(bq);\n if (h1Index >= 0 && bqIndex > h1Index) {\n continue;\n }\n const raw = (bq.meta?.markdown as string)?.trim() || bq.content?.trim();\n if (!raw) {\n continue;\n }\n leadingQuote = parseCalloutTag(raw).text || undefined;\n }\n\n return {\n headline: headingText(parts, 1),\n badge: headingText(parts, 3) || undefined,\n content: bodyText(parts) || undefined,\n image: firstImageSrc(parts),\n leadingQuote,\n items,\n };\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["headingText","headingMarkdown","bodyText","firstImageSrc","parseCalloutTag","extractEntityRefs","getPartsByType","DIAGNOSTIC_TYPES","HeroEntitySectionDefinition","constructor","_defineProperty","headline","content","items","entityId","entityType","entityUrl","linkText","markdown","expected","image","parse","parts","context","entityRefs","length","reportDiagnostic","SECTION_REJECTED","map","e","undefined","description","imageUrl","markdownImageUrl","callout","h1Index","findIndex","p","_p$meta","type","meta","level","blockquotes","leadingQuote","bq","_bq$meta","_bq$content","bqIndex","indexOf","raw","trim","text","badge"],"sources":["../../../../src/component/componentDefinitions/HeroEntitySectionDefinition.ts"],"sourcesContent":["import {\n headingText,\n headingMarkdown,\n bodyText,\n firstImageSrc,\n parseCalloutTag,\n extractEntityRefs,\n} from './parse-utils';\nimport type { Part } from '../../parts/parts';\nimport { getPartsByType } from '../../parts/parts';\nimport type {\n EntityItem,\n HeroEntityCompProps,\n HeroEntitySectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition, ParseContext } from '../section-definition';\nimport { DIAGNOSTIC_TYPES } from '../diagnosticTypes';\n\n/**\n * Hero section whose body carries one or more web5 entity links\n * (`web5://entity/...`). It mirrors the framing of {@link HeroSectionDefinition}\n * (leading callout, h1, image, intro text) but, instead of turning the links\n * into CTA buttons, surfaces them as resolvable entities.\n *\n * Registered ahead of `HeroSectionDefinition` so an entity-bearing hero is\n * claimed here first. The pattern requires at least one `link[entityType]`, and\n * `parse()` returns `null` when no entity refs are found, letting a plain hero\n * fall through to `HeroSectionDefinition`.\n */\nexport class HeroEntitySectionDefinition\n implements SectionDefinition<HeroEntitySectionComponent>\n{\n sectionType = 'hero-entity' as const;\n singleInstance = true;\n patterns = [\n // Leading slots mirror HeroSectionDefinition: section descriptor, then the\n // optional leading ECHO callout, then an optional h3 badge, then the h1.\n // Callout and badge are independent; the second `html_comment?` preserves the\n // legacy callout-before-descriptor ordering for pages saved before this change.\n // Entity links carried as list items (the canonical shape).\n 'html_comment? > callout? > html_comment? > h3? > h1 > (image | t | link)* > list{item[1-]:link[entityType] > image? > (t | callout)*}',\n // Entity links sitting at the top level of the hero body.\n 'html_comment? > callout? > html_comment? > h3? > h1 > (image | t)* > (link[entityType] > image? > (t | callout)*)[1-] > list?',\n ];\n\n defaults: HeroEntityCompProps = {\n headline: 'Featured collection',\n content: 'Explore the highlights from this collection.',\n items: [\n {\n entityId: 'example-1',\n entityType: 'product',\n entityUrl: 'web5://entity/product/example-1',\n linkText: 'Example product',\n },\n ],\n };\n\n fixtures: SectionFixture<HeroEntityCompProps>[] = [\n {\n markdown: `<!-- section:hero, id:hero, semantic:hero -->\n\n# **Nike** collections\n\n![Nike Life collection](web5://image/Nike+Life+collection)\nNike offerings span performance and lifestyle lines.\n\n* [Nike Throwback Future Collection](web5://entity/article/WAyuiC63OSjwpvnOyZcblQ)\n* [Nike Life Cable Knit Turtleneck Sweater](web5://entity/product/ZDvHxsa3IJA8CyGX8BNpdw)\n* [Nike x Jacquemus NRG HE Swoosh Hoodie](web5://entity/product/qH2lqINGneHWYVZzzGnXTA)`,\n expected: {\n headline: '**Nike** collections',\n content: 'Nike offerings span performance and lifestyle lines.',\n image: 'web5://image/Nike+Life+collection',\n items: [\n {\n entityId: 'WAyuiC63OSjwpvnOyZcblQ',\n entityType: 'article',\n entityUrl:\n 'web5://entity/article/WAyuiC63OSjwpvnOyZcblQ',\n linkText: 'Nike Throwback Future Collection',\n },\n {\n entityId: 'ZDvHxsa3IJA8CyGX8BNpdw',\n entityType: 'product',\n entityUrl:\n 'web5://entity/product/ZDvHxsa3IJA8CyGX8BNpdw',\n linkText: 'Nike Life Cable Knit Turtleneck Sweater',\n },\n {\n entityId: 'qH2lqINGneHWYVZzzGnXTA',\n entityType: 'product',\n entityUrl:\n 'web5://entity/product/qH2lqINGneHWYVZzzGnXTA',\n linkText: 'Nike x Jacquemus NRG HE Swoosh Hoodie',\n },\n ],\n },\n },\n ];\n\n parse(parts: Part[], context?: ParseContext): HeroEntityCompProps | null {\n const entityRefs = extractEntityRefs(parts);\n\n if (entityRefs.length === 0) {\n // Not an entity hero — let HeroSectionDefinition claim it.\n context?.reportDiagnostic?.(\n DIAGNOSTIC_TYPES.SECTION_REJECTED,\n 'hero-entity: no entity links found',\n );\n return null;\n }\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 // The leading callout before the h1 — the ECHO the orchestrator emits as the\n // hero's opening line, right after the section descriptor — is part of the\n // hero, mirroring HeroSectionDefinition. A trailing callout falls through to a\n // downstream callout section. (Per-item callouts inside the entity list are\n // handled by extractEntityRefs above and are unaffected.)\n const h1Index = parts.findIndex(\n (p) =>\n p.type === 'heading' && (p.meta as { level?: number })?.level === 1,\n );\n const blockquotes = getPartsByType<Part>(parts, 'callout');\n let leadingQuote: string | undefined;\n\n for (const bq of blockquotes) {\n const bqIndex = parts.indexOf(bq);\n if (h1Index >= 0 && bqIndex > h1Index) {\n continue;\n }\n const raw = (bq.meta?.markdown as string)?.trim() || bq.content?.trim();\n if (!raw) {\n continue;\n }\n leadingQuote = parseCalloutTag(raw).text || undefined;\n }\n\n return {\n // Markdown-preserving (not headingText): the hero title now carries the\n // bold+italic hook the ECHO callout used to own, so the FE needs the\n // formatting, not just the plain text. See FeatureHeroEntity.tsx.\n headline: headingMarkdown(parts, 1),\n badge: headingText(parts, 3) || undefined,\n content: bodyText(parts) || undefined,\n image: firstImageSrc(parts),\n leadingQuote,\n items,\n };\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,5 +1,5 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
- import { headingText, bodyText, firstImageSrc, parseCalloutTag, extractListItemText } from './parse-utils.js';
2
+ import { headingText, headingMarkdown, bodyText, firstImageSrc, parseCalloutTag, extractListItemText } from './parse-utils.js';
3
3
  import { getPartsByType, getLinks } from '../../parts/parts.js';
4
4
  export class HeroSectionDefinition {
5
5
  constructor() {
@@ -198,7 +198,10 @@ Get started today with our amazing features.
198
198
  leadingQuote = parseCalloutTag(raw).text || undefined;
199
199
  }
200
200
  return {
201
- headline: headingText(parts, 1),
201
+ // Markdown-preserving (not headingText): the hero title now carries the
202
+ // bold+italic hook the ECHO callout used to own, so the FE needs the
203
+ // formatting, not just the plain text. See FeatureComparisonHero.tsx.
204
+ headline: headingMarkdown(parts, 1),
202
205
  badge: headingText(parts, 3) || undefined,
203
206
  content: bodyText(parts) || undefined,
204
207
  buttons: buttons.length > 0 ? buttons : undefined,
@@ -1 +1 @@
1
- {"version":3,"names":["headingText","bodyText","firstImageSrc","parseCalloutTag","extractListItemText","getPartsByType","getLinks","HeroSectionDefinition","constructor","_defineProperty","headline","content","buttons","id","text","variant","markdown","expected","onClick","image","parse","parts","lists","list","item","_list$meta","meta","items","_item$meta","itemParts","nestedImage","buttonIndex","map","l","i","_l$content","trim","href","length","trailingList","filteredItems","_list$meta2","_item$meta2","hasImage","some","p","type","push","allItemsAreLinks","listLinks","_item$meta3","_itemLinkParts$0$cont","itemLinkParts","filter","allText","linkTexts","_l$content2","join","link","isFirstButton","lines","_item$meta4","h1Index","findIndex","_p$meta","level","blockquotes","leadingQuote","bq","_bq$meta","_bq$content","bqIndex","indexOf","raw","undefined","badge"],"sources":["../../../../src/component/componentDefinitions/HeroSectionDefinition.ts"],"sourcesContent":["import {\n headingText,\n bodyText,\n firstImageSrc,\n parseCalloutTag,\n extractListItemText,\n} from './parse-utils';\nimport type { Part, ListPart, LinkPart, ListItemPart } from '../../parts/parts';\nimport { getPartsByType, getLinks } from '../../parts/parts';\nimport type {\n HeroButton,\n HeroCompProps,\n HeroSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition } from '../section-definition';\n\nexport class HeroSectionDefinition\n implements SectionDefinition<HeroSectionComponent>\n{\n sectionType = 'hero' as const;\n singleInstance = true;\n patterns = [\n // Canonical hero shape: section descriptor, then the leading ECHO callout\n // (optional in the grammar — the orchestrator always emits it, but a missing\n // ECHO must not stop the hero from rendering), then an optional h3 badge,\n // then the h1. The callout and badge are independent slots so a hero can\n // carry both. The second `html_comment?` keeps the legacy ordering\n // (callout before the descriptor) matching for pages saved before this change.\n 'html_comment? > callout? > html_comment? > h3? > h1 > (image | t | link)* > list?',\n ];\n\n defaults: HeroCompProps = {\n headline: 'Build something amazing',\n content: 'Your platform for data-driven decisions.',\n buttons: [{ id: 'btn-0', text: 'Get started', variant: 'primary' }],\n };\n\n fixtures: SectionFixture<HeroCompProps>[] = [\n {\n markdown:\n '# Welcome\\n\\nBuild amazing things.\\n\\n[Get Started](/) [Learn More](/about)',\n expected: {\n headline: 'Welcome',\n content: 'Build amazing things.',\n buttons: [\n {\n id: 'btn-0',\n text: 'Get Started',\n variant: 'primary',\n onClick: '/',\n },\n {\n id: 'btn-1',\n text: 'Learn More',\n variant: 'secondary',\n onClick: '/about',\n },\n ],\n },\n },\n {\n markdown: `<!-- Hero Section -->\n\n# Welcome to Our Platform\n\n![Hero Image](hero.jpg)\n\nGet started today with our amazing features.\n\n[Get Started](/signup) [Learn More](/about)`,\n expected: {\n headline: 'Welcome to Our Platform',\n content: 'Get started today with our amazing features.',\n buttons: [\n {\n id: 'btn-0',\n text: 'Get Started',\n variant: 'primary',\n onClick: '/signup',\n },\n {\n id: 'btn-1',\n text: 'Learn More',\n variant: 'secondary',\n onClick: '/about',\n },\n ],\n image: 'hero.jpg',\n },\n },\n ];\n\n parse(parts: Part[]): HeroCompProps {\n let image = firstImageSrc(parts);\n const lists = getPartsByType<ListPart>(parts, 'list');\n\n if (!image) {\n for (const list of lists) {\n for (const item of list.meta?.items ?? []) {\n const itemParts = (item.meta?.parts ?? []) as Part[];\n const nestedImage = firstImageSrc(itemParts);\n if (nestedImage) {\n image = nestedImage;\n break;\n }\n }\n if (image) {\n break;\n }\n }\n }\n\n // Start with top-level links as buttons\n let buttonIndex = 0;\n const buttons: HeroButton[] = getLinks(parts).map(\n (l, i): HeroButton => ({\n id: `btn-${i}`,\n text: l.content?.trim() || 'Learn more',\n variant: i === 0 ? 'primary' : 'secondary',\n onClick: l.meta.href,\n }),\n );\n buttonIndex = buttons.length;\n\n // Process lists: filter out image-only items, then check if remaining\n // items are all link-only. If so, convert to buttons; otherwise keep as trailingList.\n let trailingList: string | undefined;\n if (lists.length > 0) {\n for (const list of lists) {\n // Filter out image-only items\n const filteredItems: ListItemPart[] = [];\n for (const item of list.meta?.items ?? []) {\n const itemParts = (item.meta?.parts ?? []) as Part[];\n const hasImage = itemParts.some((p) => p.type === 'image');\n if (hasImage) {\n continue;\n }\n filteredItems.push(item);\n }\n\n if (filteredItems.length === 0) {\n continue;\n }\n\n // Check if ALL remaining items contain only links (no other text)\n let allItemsAreLinks = true;\n const listLinks: { text: string; href: string }[] = [];\n\n for (const item of filteredItems) {\n const itemParts = (item.meta?.parts ?? []) as Part[];\n const itemLinkParts = itemParts.filter(\n (p): p is LinkPart => p.type === 'link',\n );\n\n if (itemLinkParts.length === 0) {\n allItemsAreLinks = false;\n break;\n }\n\n // Check if the item text is entirely link text (no extra content)\n const allText = extractListItemText(item).trim();\n const linkTexts = itemLinkParts\n .map((l) => l.content?.trim() || '')\n .join(' ')\n .trim();\n\n if (allText !== linkTexts) {\n allItemsAreLinks = false;\n break;\n }\n\n listLinks.push({\n text: itemLinkParts[0].content?.trim() || 'Learn more',\n href: itemLinkParts[0].meta.href,\n });\n }\n\n if (allItemsAreLinks && listLinks.length > 0) {\n // Convert link-only list items to buttons\n for (const link of listLinks) {\n const isFirstButton = buttons.length === 0;\n buttons.push({\n id: `btn-${buttonIndex++}`,\n text: link.text,\n variant: isFirstButton ? 'primary' : 'secondary',\n onClick: link.href,\n });\n }\n } else {\n // Keep as trailing list markdown\n const lines: string[] = [];\n for (const item of filteredItems) {\n const text =\n (item.meta?.markdown as string) || extractListItemText(item);\n if (text) {\n lines.push(`- ${text}`);\n }\n }\n if (lines.length > 0) {\n trailingList = lines.join('\\n');\n }\n }\n }\n }\n\n // The hero claims the leading callout before the h1 — the ECHO the\n // orchestrator emits as the hero's opening line, right after the section\n // descriptor. A trailing blockquote is not part of the hero pattern, so it\n // falls through to a downstream callout section instead.\n const h1Index = parts.findIndex(\n (p) => p.type === 'heading' && (p.meta as { level: number })?.level === 1,\n );\n const blockquotes = getPartsByType<Part>(parts, 'callout');\n let leadingQuote: string | undefined;\n\n for (const bq of blockquotes) {\n const bqIndex = parts.indexOf(bq);\n if (h1Index >= 0 && bqIndex > h1Index) {\n continue;\n }\n const raw = (bq.meta?.markdown as string)?.trim() || bq.content?.trim();\n if (!raw) {\n continue;\n }\n leadingQuote = parseCalloutTag(raw).text || undefined;\n }\n\n return {\n headline: headingText(parts, 1),\n badge: headingText(parts, 3) || undefined,\n content: bodyText(parts) || undefined,\n buttons: buttons.length > 0 ? buttons : undefined,\n image,\n trailingList,\n leadingQuote,\n };\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["headingText","headingMarkdown","bodyText","firstImageSrc","parseCalloutTag","extractListItemText","getPartsByType","getLinks","HeroSectionDefinition","constructor","_defineProperty","headline","content","buttons","id","text","variant","markdown","expected","onClick","image","parse","parts","lists","list","item","_list$meta","meta","items","_item$meta","itemParts","nestedImage","buttonIndex","map","l","i","_l$content","trim","href","length","trailingList","filteredItems","_list$meta2","_item$meta2","hasImage","some","p","type","push","allItemsAreLinks","listLinks","_item$meta3","_itemLinkParts$0$cont","itemLinkParts","filter","allText","linkTexts","_l$content2","join","link","isFirstButton","lines","_item$meta4","h1Index","findIndex","_p$meta","level","blockquotes","leadingQuote","bq","_bq$meta","_bq$content","bqIndex","indexOf","raw","undefined","badge"],"sources":["../../../../src/component/componentDefinitions/HeroSectionDefinition.ts"],"sourcesContent":["import {\n headingText,\n headingMarkdown,\n bodyText,\n firstImageSrc,\n parseCalloutTag,\n extractListItemText,\n} from './parse-utils';\nimport type { Part, ListPart, LinkPart, ListItemPart } from '../../parts/parts';\nimport { getPartsByType, getLinks } from '../../parts/parts';\nimport type {\n HeroButton,\n HeroCompProps,\n HeroSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition } from '../section-definition';\n\nexport class HeroSectionDefinition\n implements SectionDefinition<HeroSectionComponent>\n{\n sectionType = 'hero' as const;\n singleInstance = true;\n patterns = [\n // Canonical hero shape: section descriptor, then the leading ECHO callout\n // (optional in the grammar — the orchestrator always emits it, but a missing\n // ECHO must not stop the hero from rendering), then an optional h3 badge,\n // then the h1. The callout and badge are independent slots so a hero can\n // carry both. The second `html_comment?` keeps the legacy ordering\n // (callout before the descriptor) matching for pages saved before this change.\n 'html_comment? > callout? > html_comment? > h3? > h1 > (image | t | link)* > list?',\n ];\n\n defaults: HeroCompProps = {\n headline: 'Build something amazing',\n content: 'Your platform for data-driven decisions.',\n buttons: [{ id: 'btn-0', text: 'Get started', variant: 'primary' }],\n };\n\n fixtures: SectionFixture<HeroCompProps>[] = [\n {\n markdown:\n '# Welcome\\n\\nBuild amazing things.\\n\\n[Get Started](/) [Learn More](/about)',\n expected: {\n headline: 'Welcome',\n content: 'Build amazing things.',\n buttons: [\n {\n id: 'btn-0',\n text: 'Get Started',\n variant: 'primary',\n onClick: '/',\n },\n {\n id: 'btn-1',\n text: 'Learn More',\n variant: 'secondary',\n onClick: '/about',\n },\n ],\n },\n },\n {\n markdown: `<!-- Hero Section -->\n\n# Welcome to Our Platform\n\n![Hero Image](hero.jpg)\n\nGet started today with our amazing features.\n\n[Get Started](/signup) [Learn More](/about)`,\n expected: {\n headline: 'Welcome to Our Platform',\n content: 'Get started today with our amazing features.',\n buttons: [\n {\n id: 'btn-0',\n text: 'Get Started',\n variant: 'primary',\n onClick: '/signup',\n },\n {\n id: 'btn-1',\n text: 'Learn More',\n variant: 'secondary',\n onClick: '/about',\n },\n ],\n image: 'hero.jpg',\n },\n },\n ];\n\n parse(parts: Part[]): HeroCompProps {\n let image = firstImageSrc(parts);\n const lists = getPartsByType<ListPart>(parts, 'list');\n\n if (!image) {\n for (const list of lists) {\n for (const item of list.meta?.items ?? []) {\n const itemParts = (item.meta?.parts ?? []) as Part[];\n const nestedImage = firstImageSrc(itemParts);\n if (nestedImage) {\n image = nestedImage;\n break;\n }\n }\n if (image) {\n break;\n }\n }\n }\n\n // Start with top-level links as buttons\n let buttonIndex = 0;\n const buttons: HeroButton[] = getLinks(parts).map(\n (l, i): HeroButton => ({\n id: `btn-${i}`,\n text: l.content?.trim() || 'Learn more',\n variant: i === 0 ? 'primary' : 'secondary',\n onClick: l.meta.href,\n }),\n );\n buttonIndex = buttons.length;\n\n // Process lists: filter out image-only items, then check if remaining\n // items are all link-only. If so, convert to buttons; otherwise keep as trailingList.\n let trailingList: string | undefined;\n if (lists.length > 0) {\n for (const list of lists) {\n // Filter out image-only items\n const filteredItems: ListItemPart[] = [];\n for (const item of list.meta?.items ?? []) {\n const itemParts = (item.meta?.parts ?? []) as Part[];\n const hasImage = itemParts.some((p) => p.type === 'image');\n if (hasImage) {\n continue;\n }\n filteredItems.push(item);\n }\n\n if (filteredItems.length === 0) {\n continue;\n }\n\n // Check if ALL remaining items contain only links (no other text)\n let allItemsAreLinks = true;\n const listLinks: { text: string; href: string }[] = [];\n\n for (const item of filteredItems) {\n const itemParts = (item.meta?.parts ?? []) as Part[];\n const itemLinkParts = itemParts.filter(\n (p): p is LinkPart => p.type === 'link',\n );\n\n if (itemLinkParts.length === 0) {\n allItemsAreLinks = false;\n break;\n }\n\n // Check if the item text is entirely link text (no extra content)\n const allText = extractListItemText(item).trim();\n const linkTexts = itemLinkParts\n .map((l) => l.content?.trim() || '')\n .join(' ')\n .trim();\n\n if (allText !== linkTexts) {\n allItemsAreLinks = false;\n break;\n }\n\n listLinks.push({\n text: itemLinkParts[0].content?.trim() || 'Learn more',\n href: itemLinkParts[0].meta.href,\n });\n }\n\n if (allItemsAreLinks && listLinks.length > 0) {\n // Convert link-only list items to buttons\n for (const link of listLinks) {\n const isFirstButton = buttons.length === 0;\n buttons.push({\n id: `btn-${buttonIndex++}`,\n text: link.text,\n variant: isFirstButton ? 'primary' : 'secondary',\n onClick: link.href,\n });\n }\n } else {\n // Keep as trailing list markdown\n const lines: string[] = [];\n for (const item of filteredItems) {\n const text =\n (item.meta?.markdown as string) || extractListItemText(item);\n if (text) {\n lines.push(`- ${text}`);\n }\n }\n if (lines.length > 0) {\n trailingList = lines.join('\\n');\n }\n }\n }\n }\n\n // The hero claims the leading callout before the h1 — the ECHO the\n // orchestrator emits as the hero's opening line, right after the section\n // descriptor. A trailing blockquote is not part of the hero pattern, so it\n // falls through to a downstream callout section instead.\n const h1Index = parts.findIndex(\n (p) => p.type === 'heading' && (p.meta as { level: number })?.level === 1,\n );\n const blockquotes = getPartsByType<Part>(parts, 'callout');\n let leadingQuote: string | undefined;\n\n for (const bq of blockquotes) {\n const bqIndex = parts.indexOf(bq);\n if (h1Index >= 0 && bqIndex > h1Index) {\n continue;\n }\n const raw = (bq.meta?.markdown as string)?.trim() || bq.content?.trim();\n if (!raw) {\n continue;\n }\n leadingQuote = parseCalloutTag(raw).text || undefined;\n }\n\n return {\n // Markdown-preserving (not headingText): the hero title now carries the\n // bold+italic hook the ECHO callout used to own, so the FE needs the\n // formatting, not just the plain text. See FeatureComparisonHero.tsx.\n headline: headingMarkdown(parts, 1),\n badge: headingText(parts, 3) || undefined,\n content: bodyText(parts) || undefined,\n buttons: buttons.length > 0 ? buttons : undefined,\n image,\n trailingList,\n leadingQuote,\n };\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,5 +1,5 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
- import { headingText, extractListItemText, firstImageSrc } from './parse-utils.js';
2
+ import { headingText, bodyText, extractListItemText, firstImageSrc } from './parse-utils.js';
3
3
  import { getPartsByType, getLinks } from '../../parts/parts.js';
4
4
  function linkToMarkdown(link) {
5
5
  var _link$content, _link$meta;
@@ -35,16 +35,39 @@ function inlineBodyMarkdown(parts) {
35
35
  export class NextStepsSectionDefinition {
36
36
  constructor() {
37
37
  _defineProperty(this, "sectionType", 'nextSteps');
38
- _defineProperty(this, "patterns", ['(html_comment[section^="next"] | html_comment[semantic^="next"]) > h2 > image? > list{item[1-]:(icon | t)* > (t? > link)+}', '(html_comment[section^="next"] | html_comment[semantic^="next"]) > h2 > image? > (t | link)+']);
38
+ _defineProperty(this, "patterns", [
39
+ // Framing sentence (`t?`) then one chip per bullet — the authored shape.
40
+ '(html_comment[section^="next"] | html_comment[semantic^="next"]) > h2 > image? > t? > list{item[1-]:(icon | t)* > (t? > link)+}',
41
+ // Legacy inline shape: chips embedded in the prose. Still arrives from
42
+ // sites whose next-steps prompt has not moved to the list shape.
43
+ '(html_comment[section^="next"] | html_comment[semantic^="next"]) > h2 > image? > (t | link)+']);
39
44
  _defineProperty(this, "defaults", {
40
45
  title: 'Next Steps',
41
- body: '[Get started](/start)',
46
+ body: 'Where would you like to go next?',
42
47
  backgroundImage: undefined,
43
48
  steps: [{
44
49
  content: '[Get started](/start)'
45
50
  }]
46
51
  });
47
52
  _defineProperty(this, "fixtures", [{
53
+ markdown: `<!-- section:next-steps, semantic:next_steps -->
54
+
55
+ ## Find the right care for mature, sensitive skin
56
+
57
+ Want to focus on rich hydrators and barrier builders?
58
+
59
+ - [hydrating creams →](web5://ask/hydrating+creams+for+mature+skin)
60
+ - [gentle resurfacing serums →](web5://ask/gentle+resurfacing+serums)`,
61
+ expected: {
62
+ title: 'Find the right care for mature, sensitive skin',
63
+ body: 'Want to focus on rich hydrators and barrier builders?',
64
+ steps: [{
65
+ content: '[hydrating creams →](web5://ask/hydrating+creams+for+mature+skin)'
66
+ }, {
67
+ content: '[gentle resurfacing serums →](web5://ask/gentle+resurfacing+serums)'
68
+ }]
69
+ }
70
+ }, {
48
71
  markdown: `<!-- section: next_steps -->
49
72
 
50
73
  ## Next Steps
@@ -66,10 +89,14 @@ export class NextStepsSectionDefinition {
66
89
  const backgroundImage = firstImageSrc(parts);
67
90
  const steps = [];
68
91
  let body;
92
+ let chipsInlineInBody = false;
69
93
 
70
94
  // Try list-based pattern first
71
95
  const lists = getPartsByType(parts, 'list');
72
96
  if (lists.length > 0) {
97
+ // The framing sentence is the only top-level prose — list items live
98
+ // under each list's meta.items, so bodyText never picks up a chip.
99
+ body = bodyText(parts) || undefined;
73
100
  for (const list of lists) {
74
101
  for (const item of ((_list$meta = list.meta) == null ? void 0 : _list$meta.items) ?? []) {
75
102
  var _list$meta, _item$meta, _iconPart$meta;
@@ -99,6 +126,9 @@ export class NextStepsSectionDefinition {
99
126
  }
100
127
  } else {
101
128
  body = inlineBodyMarkdown(parts);
129
+ // body carries the chips as inline links — flag it so renderers show the
130
+ // prose alone instead of repeating every chip as a row beneath it.
131
+ chipsInlineInBody = Boolean(body);
102
132
  }
103
133
 
104
134
  // Fallback: inline links pattern
@@ -120,6 +150,9 @@ export class NextStepsSectionDefinition {
120
150
  ...(body ? {
121
151
  body
122
152
  } : {}),
153
+ ...(chipsInlineInBody ? {
154
+ chipsInlineInBody
155
+ } : {}),
123
156
  ...(backgroundImage ? {
124
157
  backgroundImage
125
158
  } : {}),
@@ -1 +1 @@
1
- {"version":3,"names":["headingText","extractListItemText","firstImageSrc","getPartsByType","getLinks","linkToMarkdown","link","_link$content","_link$meta","content","trim","meta","href","appendInlineToken","current","token","trimmed","test","inlineBodyMarkdown","parts","body","reduce","part","type","_part$meta","markdown","undefined","NextStepsSectionDefinition","constructor","_defineProperty","title","backgroundImage","steps","expected","parse","lists","length","list","item","_list$meta","items","_item$meta","_iconPart$meta","itemParts","iconPart","find","p","iconHint","contentFragments","push","_p$content","filter","Boolean","join","links","_link$content2","_link$meta2","text"],"sources":["../../../../src/component/componentDefinitions/NextStepsSectionDefinition.ts"],"sourcesContent":["import {\n headingText,\n extractListItemText,\n firstImageSrc,\n} from './parse-utils';\nimport {\n getPartsByType,\n getLinks,\n type Part,\n type ListPart,\n type LinkPart,\n type IconPart,\n} from '../../parts/parts';\nimport type {\n NextStepsCompProps,\n NextStepsSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition } from '../section-definition';\n\nfunction linkToMarkdown(link: LinkPart): string {\n return `[${link.content?.trim() || ''}](${link.meta?.href || ''})`;\n}\n\nfunction appendInlineToken(current: string, token: string): string {\n const trimmed = token.trim();\n if (!trimmed) {\n return current;\n }\n if (!current) {\n return trimmed;\n }\n if (/^[,.;:!?)]/.test(trimmed)) {\n return `${current}${trimmed}`;\n }\n return `${current} ${trimmed}`;\n}\n\nfunction inlineBodyMarkdown(parts: Part[]): string | undefined {\n const body = parts.reduce((current, part) => {\n if (part.type === 'link') {\n return appendInlineToken(current, linkToMarkdown(part as LinkPart));\n }\n if (part.type === 'text' || part.type === 'richText') {\n const markdown = (part.meta?.markdown as string | undefined)?.trim();\n return appendInlineToken(current, markdown || part.content || '');\n }\n return current;\n }, '');\n\n return body || undefined;\n}\n\nexport class NextStepsSectionDefinition\n implements SectionDefinition<NextStepsSectionComponent>\n{\n sectionType = 'nextSteps' as const;\n patterns = [\n '(html_comment[section^=\"next\"] | html_comment[semantic^=\"next\"]) > h2 > image? > list{item[1-]:(icon | t)* > (t? > link)+}',\n '(html_comment[section^=\"next\"] | html_comment[semantic^=\"next\"]) > h2 > image? > (t | link)+',\n ];\n\n defaults: NextStepsCompProps = {\n title: 'Next Steps',\n body: '[Get started](/start)',\n backgroundImage: undefined,\n steps: [{ content: '[Get started](/start)' }],\n };\n\n fixtures: SectionFixture<NextStepsCompProps>[] = [\n {\n markdown: `<!-- section: next_steps -->\n\n## Next Steps\n\n- Check out [Documentation](/docs)\n- Try [Examples](/examples)`,\n expected: {\n title: 'Next Steps',\n steps: [\n { content: 'Check out [Documentation](/docs)' },\n { content: 'Try [Examples](/examples)' },\n ],\n },\n },\n ];\n\n parse(parts: Part[]): NextStepsCompProps {\n const title = headingText(parts, 2) || 'Next Steps';\n const backgroundImage = firstImageSrc(parts);\n const steps: { content: string; iconHint?: string }[] = [];\n let body: string | undefined;\n\n // Try list-based pattern first\n const lists = getPartsByType<ListPart>(parts, 'list');\n if (lists.length > 0) {\n for (const list of lists) {\n for (const item of list.meta?.items ?? []) {\n const itemParts = (item.meta?.parts ?? []) as Part[];\n\n const iconPart = itemParts.find((p) => p.type === 'icon') as\n | IconPart\n | undefined;\n const iconHint = (iconPart?.meta as { iconHint?: string })?.iconHint;\n\n const contentFragments: string[] = [];\n for (const p of itemParts) {\n if (p.type === 'link') {\n const link = p as LinkPart;\n contentFragments.push(linkToMarkdown(link));\n } else if (p.type === 'text' || p.type === 'richText') {\n contentFragments.push(p.content?.trim() || '');\n }\n }\n const content =\n contentFragments.filter(Boolean).join(' ') ||\n extractListItemText(item);\n if (content.trim()) {\n steps.push({\n content: content.trim(),\n ...(iconHint ? { iconHint } : {}),\n });\n }\n }\n }\n } else {\n body = inlineBodyMarkdown(parts);\n }\n\n // Fallback: inline links pattern\n if (steps.length === 0) {\n const links = getLinks(parts);\n for (const link of links) {\n const text = link.content?.trim();\n const href = link.meta?.href;\n if (text && href) {\n steps.push({ content: linkToMarkdown(link) });\n }\n }\n }\n\n return {\n title,\n ...(body ? { body } : {}),\n ...(backgroundImage ? { backgroundImage } : {}),\n steps,\n };\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["headingText","bodyText","extractListItemText","firstImageSrc","getPartsByType","getLinks","linkToMarkdown","link","_link$content","_link$meta","content","trim","meta","href","appendInlineToken","current","token","trimmed","test","inlineBodyMarkdown","parts","body","reduce","part","type","_part$meta","markdown","undefined","NextStepsSectionDefinition","constructor","_defineProperty","title","backgroundImage","steps","expected","parse","chipsInlineInBody","lists","length","list","item","_list$meta","items","_item$meta","_iconPart$meta","itemParts","iconPart","find","p","iconHint","contentFragments","push","_p$content","filter","Boolean","join","links","_link$content2","_link$meta2","text"],"sources":["../../../../src/component/componentDefinitions/NextStepsSectionDefinition.ts"],"sourcesContent":["import {\n headingText,\n bodyText,\n extractListItemText,\n firstImageSrc,\n} from './parse-utils';\nimport {\n getPartsByType,\n getLinks,\n type Part,\n type ListPart,\n type LinkPart,\n type IconPart,\n} from '../../parts/parts';\nimport type {\n NextStepsCompProps,\n NextStepsSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition } from '../section-definition';\n\nfunction linkToMarkdown(link: LinkPart): string {\n return `[${link.content?.trim() || ''}](${link.meta?.href || ''})`;\n}\n\nfunction appendInlineToken(current: string, token: string): string {\n const trimmed = token.trim();\n if (!trimmed) {\n return current;\n }\n if (!current) {\n return trimmed;\n }\n if (/^[,.;:!?)]/.test(trimmed)) {\n return `${current}${trimmed}`;\n }\n return `${current} ${trimmed}`;\n}\n\nfunction inlineBodyMarkdown(parts: Part[]): string | undefined {\n const body = parts.reduce((current, part) => {\n if (part.type === 'link') {\n return appendInlineToken(current, linkToMarkdown(part as LinkPart));\n }\n if (part.type === 'text' || part.type === 'richText') {\n const markdown = (part.meta?.markdown as string | undefined)?.trim();\n return appendInlineToken(current, markdown || part.content || '');\n }\n return current;\n }, '');\n\n return body || undefined;\n}\n\nexport class NextStepsSectionDefinition\n implements SectionDefinition<NextStepsSectionComponent>\n{\n sectionType = 'nextSteps' as const;\n patterns = [\n // Framing sentence (`t?`) then one chip per bullet — the authored shape.\n '(html_comment[section^=\"next\"] | html_comment[semantic^=\"next\"]) > h2 > image? > t? > list{item[1-]:(icon | t)* > (t? > link)+}',\n // Legacy inline shape: chips embedded in the prose. Still arrives from\n // sites whose next-steps prompt has not moved to the list shape.\n '(html_comment[section^=\"next\"] | html_comment[semantic^=\"next\"]) > h2 > image? > (t | link)+',\n ];\n\n defaults: NextStepsCompProps = {\n title: 'Next Steps',\n body: 'Where would you like to go next?',\n backgroundImage: undefined,\n steps: [{ content: '[Get started](/start)' }],\n };\n\n fixtures: SectionFixture<NextStepsCompProps>[] = [\n {\n markdown: `<!-- section:next-steps, semantic:next_steps -->\n\n## Find the right care for mature, sensitive skin\n\nWant to focus on rich hydrators and barrier builders?\n\n- [hydrating creams →](web5://ask/hydrating+creams+for+mature+skin)\n- [gentle resurfacing serums →](web5://ask/gentle+resurfacing+serums)`,\n expected: {\n title: 'Find the right care for mature, sensitive skin',\n body: 'Want to focus on rich hydrators and barrier builders?',\n steps: [\n {\n content:\n '[hydrating creams →](web5://ask/hydrating+creams+for+mature+skin)',\n },\n {\n content:\n '[gentle resurfacing serums →](web5://ask/gentle+resurfacing+serums)',\n },\n ],\n },\n },\n {\n markdown: `<!-- section: next_steps -->\n\n## Next Steps\n\n- Check out [Documentation](/docs)\n- Try [Examples](/examples)`,\n expected: {\n title: 'Next Steps',\n steps: [\n { content: 'Check out [Documentation](/docs)' },\n { content: 'Try [Examples](/examples)' },\n ],\n },\n },\n ];\n\n parse(parts: Part[]): NextStepsCompProps {\n const title = headingText(parts, 2) || 'Next Steps';\n const backgroundImage = firstImageSrc(parts);\n const steps: { content: string; iconHint?: string }[] = [];\n let body: string | undefined;\n let chipsInlineInBody = false;\n\n // Try list-based pattern first\n const lists = getPartsByType<ListPart>(parts, 'list');\n if (lists.length > 0) {\n // The framing sentence is the only top-level prose — list items live\n // under each list's meta.items, so bodyText never picks up a chip.\n body = bodyText(parts) || undefined;\n\n for (const list of lists) {\n for (const item of list.meta?.items ?? []) {\n const itemParts = (item.meta?.parts ?? []) as Part[];\n\n const iconPart = itemParts.find((p) => p.type === 'icon') as\n | IconPart\n | undefined;\n const iconHint = (iconPart?.meta as { iconHint?: string })?.iconHint;\n\n const contentFragments: string[] = [];\n for (const p of itemParts) {\n if (p.type === 'link') {\n const link = p as LinkPart;\n contentFragments.push(linkToMarkdown(link));\n } else if (p.type === 'text' || p.type === 'richText') {\n contentFragments.push(p.content?.trim() || '');\n }\n }\n const content =\n contentFragments.filter(Boolean).join(' ') ||\n extractListItemText(item);\n if (content.trim()) {\n steps.push({\n content: content.trim(),\n ...(iconHint ? { iconHint } : {}),\n });\n }\n }\n }\n } else {\n body = inlineBodyMarkdown(parts);\n // body carries the chips as inline links — flag it so renderers show the\n // prose alone instead of repeating every chip as a row beneath it.\n chipsInlineInBody = Boolean(body);\n }\n\n // Fallback: inline links pattern\n if (steps.length === 0) {\n const links = getLinks(parts);\n for (const link of links) {\n const text = link.content?.trim();\n const href = link.meta?.href;\n if (text && href) {\n steps.push({ content: linkToMarkdown(link) });\n }\n }\n }\n\n return {\n title,\n ...(body ? { body } : {}),\n ...(chipsInlineInBody ? { chipsInlineInBody } : {}),\n ...(backgroundImage ? { backgroundImage } : {}),\n steps,\n };\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -4,7 +4,24 @@ import { DIAGNOSTIC_TYPES } from '../diagnosticTypes.js';
4
4
  export class TextBlockSectionDefinition {
5
5
  constructor() {
6
6
  _defineProperty(this, "sectionType", 'textBlock');
7
- _defineProperty(this, "patterns", ['html_comment? > h2 > t > callout']);
7
+ // The trailing callout is OPTIONAL. A heading plus running copy is the shape
8
+ // stores emit constantly for explainer content, and requiring the blockquote
9
+ // meant those blocks matched no definition at all and fell through to
10
+ // `FallbackSectionDefinition` — rendered as undifferentiated prose with no
11
+ // section treatment. `parse()` already tolerates a missing callout (it only
12
+ // rejects when title AND description are empty).
13
+ //
14
+ // NOTE for registry authors: with the callout optional this also matches a
15
+ // bare `h2 > t`, and a pattern matches a PREFIX of the block. Register
16
+ // `textBlock` BELOW every definition whose block opens `h2 > t` — entity,
17
+ // entityCollection, listItemsSection, featureCards, ctaBanner, comparison,
18
+ // kpi, nextSteps. Above them it claims the heading + intro paragraph off the
19
+ // front of the block and strands the list / links / table that follow
20
+ // (`EntitySectionDefinition` allows `h2 > (t | callout)* > links…`, and
21
+ // `listItemsSection` / `ctaBanner` are the same shape). `createSdkRegistry`
22
+ // and the client registries in this repo order it that way; a client
23
+ // registry living outside this repo has to do the same.
24
+ _defineProperty(this, "patterns", ['html_comment? > h2 > t > callout?']);
8
25
  _defineProperty(this, "defaults", {
9
26
  title: 'Text Block Title',
10
27
  description: 'Description text.',
@@ -39,6 +56,15 @@ The platform scales with your needs.
39
56
  text: 'Start small with Go, then expand to the full suite as your data maturity grows.'
40
57
  }
41
58
  }
59
+ }, {
60
+ markdown: `## How to choose between a clinical serum and a nourishing dry oil
61
+
62
+ Clinically tested serums with patented actives target visible reduction of marks and uneven tone, while dry oils focus on broad nourishment and a satin finish.`,
63
+ expected: {
64
+ title: 'How to choose between a clinical serum and a nourishing dry oil',
65
+ description: 'Clinically tested serums with patented actives target visible reduction of marks and uneven tone, while dry oils focus on broad nourishment and a satin finish.',
66
+ callout: undefined
67
+ }
42
68
  }]);
43
69
  }
44
70
  parse(parts, context) {
@@ -1 +1 @@
1
- {"version":3,"names":["headingMarkdown","bodyText","calloutFromParts","DIAGNOSTIC_TYPES","TextBlockSectionDefinition","constructor","_defineProperty","title","description","callout","text","markdown","expected","parse","parts","context","reportDiagnostic","SECTION_REJECTED"],"sources":["../../../../src/component/componentDefinitions/TextBlockSectionDefinition.ts"],"sourcesContent":["import type { Part } from '../../parts/parts';\nimport { headingMarkdown, bodyText, calloutFromParts } from './parse-utils';\nimport type {\n TextBlockCompProps,\n TextBlockSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition, ParseContext } from '../section-definition';\nimport { DIAGNOSTIC_TYPES } from '../diagnosticTypes';\n\nexport class TextBlockSectionDefinition\n implements SectionDefinition<TextBlockSectionComponent>\n{\n sectionType = 'textBlock' as const;\n patterns = ['html_comment? > h2 > t > callout'];\n\n defaults: TextBlockCompProps = {\n title: 'Text Block Title',\n description: 'Description text.',\n callout: { text: 'A key insight or quote.' },\n };\n\n fixtures: SectionFixture<TextBlockCompProps>[] = [\n {\n markdown: `## Choosing the Right Liquid Data Option\n\nLiquid Data Go is designed for brands that want affordable, scalable access to syndicated POS, shopper, and pricing insights with minimal setup and no data expertise required.\n\n> If you mainly need fast, packaged insights in one category, Liquid Data Go is usually the right fit; if you need to integrate many datasets and support multiple enterprise workflows, the broader Liquid Data platform and its solutions become more relevant.`,\n expected: {\n title: 'Choosing the Right Liquid Data Option',\n description:\n 'Liquid Data Go is designed for brands that want affordable, scalable access to syndicated POS, shopper, and pricing insights with minimal setup and no data expertise required.',\n callout: {\n text: 'If you mainly need fast, packaged insights in one category, Liquid Data Go is usually the right fit; if you need to integrate many datasets and support multiple enterprise workflows, the broader Liquid Data platform and its solutions become more relevant.',\n },\n },\n },\n {\n markdown: `<!-- section: textBlock -->\n## Key Takeaway\n\nThe platform scales with your needs.\n\n> Start small with Go, then expand to the full suite as your data maturity grows.`,\n expected: {\n title: 'Key Takeaway',\n description: 'The platform scales with your needs.',\n callout: {\n text: 'Start small with Go, then expand to the full suite as your data maturity grows.',\n },\n },\n },\n ];\n\n parse(parts: Part[], context?: ParseContext): TextBlockCompProps | null {\n const title = headingMarkdown(parts, 2) || '';\n const description = bodyText(parts) || '';\n const callout = calloutFromParts(parts);\n\n if (!title && !description) {\n context?.reportDiagnostic?.(\n DIAGNOSTIC_TYPES.SECTION_REJECTED,\n 'textBlock: both title and description are empty',\n );\n return null;\n }\n\n return { title, description, callout };\n }\n}\n"],"mappings":";AACA,SAASA,eAAe,EAAEC,QAAQ,EAAEC,gBAAgB,QAAQ,eAAe;AAO3E,SAASC,gBAAgB,QAAQ,oBAAoB;AAErD,OAAO,MAAMC,0BAA0B,CAEvC;EAAAC,YAAA;IAAAC,eAAA,sBACgB,WAAW;IAAAA,eAAA,mBACd,CAAC,kCAAkC,CAAC;IAAAA,eAAA,mBAEhB;MAC7BC,KAAK,EAAE,kBAAkB;MACzBC,WAAW,EAAE,mBAAmB;MAChCC,OAAO,EAAE;QAAEC,IAAI,EAAE;MAA0B;IAC7C,CAAC;IAAAJ,eAAA,mBAEgD,CAC/C;MACEK,QAAQ,EAAE;AAChB;AACA;AACA;AACA,kQAAkQ;MAC5PC,QAAQ,EAAE;QACRL,KAAK,EAAE,uCAAuC;QAC9CC,WAAW,EACT,iLAAiL;QACnLC,OAAO,EAAE;UACPC,IAAI,EAAE;QACR;MACF;IACF,CAAC,EACD;MACEC,QAAQ,EAAE;AAChB;AACA;AACA;AACA;AACA,kFAAkF;MAC5EC,QAAQ,EAAE;QACRL,KAAK,EAAE,cAAc;QACrBC,WAAW,EAAE,sCAAsC;QACnDC,OAAO,EAAE;UACPC,IAAI,EAAE;QACR;MACF;IACF,CAAC,CACF;EAAA;EAEDG,KAAKA,CAACC,KAAa,EAAEC,OAAsB,EAA6B;IACtE,MAAMR,KAAK,GAAGP,eAAe,CAACc,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE;IAC7C,MAAMN,WAAW,GAAGP,QAAQ,CAACa,KAAK,CAAC,IAAI,EAAE;IACzC,MAAML,OAAO,GAAGP,gBAAgB,CAACY,KAAK,CAAC;IAEvC,IAAI,CAACP,KAAK,IAAI,CAACC,WAAW,EAAE;MAC1BO,OAAO,YAAPA,OAAO,CAAEC,gBAAgB,YAAzBD,OAAO,CAAEC,gBAAgB,CACvBb,gBAAgB,CAACc,gBAAgB,EACjC,iDACF,CAAC;MACD,OAAO,IAAI;IACb;IAEA,OAAO;MAAEV,KAAK;MAAEC,WAAW;MAAEC;IAAQ,CAAC;EACxC;AACF","ignoreList":[]}
1
+ {"version":3,"names":["headingMarkdown","bodyText","calloutFromParts","DIAGNOSTIC_TYPES","TextBlockSectionDefinition","constructor","_defineProperty","title","description","callout","text","markdown","expected","undefined","parse","parts","context","reportDiagnostic","SECTION_REJECTED"],"sources":["../../../../src/component/componentDefinitions/TextBlockSectionDefinition.ts"],"sourcesContent":["import type { Part } from '../../parts/parts';\nimport { headingMarkdown, bodyText, calloutFromParts } from './parse-utils';\nimport type {\n TextBlockCompProps,\n TextBlockSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition, ParseContext } from '../section-definition';\nimport { DIAGNOSTIC_TYPES } from '../diagnosticTypes';\n\nexport class TextBlockSectionDefinition\n implements SectionDefinition<TextBlockSectionComponent>\n{\n sectionType = 'textBlock' as const;\n // The trailing callout is OPTIONAL. A heading plus running copy is the shape\n // stores emit constantly for explainer content, and requiring the blockquote\n // meant those blocks matched no definition at all and fell through to\n // `FallbackSectionDefinition` — rendered as undifferentiated prose with no\n // section treatment. `parse()` already tolerates a missing callout (it only\n // rejects when title AND description are empty).\n //\n // NOTE for registry authors: with the callout optional this also matches a\n // bare `h2 > t`, and a pattern matches a PREFIX of the block. Register\n // `textBlock` BELOW every definition whose block opens `h2 > t` — entity,\n // entityCollection, listItemsSection, featureCards, ctaBanner, comparison,\n // kpi, nextSteps. Above them it claims the heading + intro paragraph off the\n // front of the block and strands the list / links / table that follow\n // (`EntitySectionDefinition` allows `h2 > (t | callout)* > links…`, and\n // `listItemsSection` / `ctaBanner` are the same shape). `createSdkRegistry`\n // and the client registries in this repo order it that way; a client\n // registry living outside this repo has to do the same.\n patterns = ['html_comment? > h2 > t > callout?'];\n\n defaults: TextBlockCompProps = {\n title: 'Text Block Title',\n description: 'Description text.',\n callout: { text: 'A key insight or quote.' },\n };\n\n fixtures: SectionFixture<TextBlockCompProps>[] = [\n {\n markdown: `## Choosing the Right Liquid Data Option\n\nLiquid Data Go is designed for brands that want affordable, scalable access to syndicated POS, shopper, and pricing insights with minimal setup and no data expertise required.\n\n> If you mainly need fast, packaged insights in one category, Liquid Data Go is usually the right fit; if you need to integrate many datasets and support multiple enterprise workflows, the broader Liquid Data platform and its solutions become more relevant.`,\n expected: {\n title: 'Choosing the Right Liquid Data Option',\n description:\n 'Liquid Data Go is designed for brands that want affordable, scalable access to syndicated POS, shopper, and pricing insights with minimal setup and no data expertise required.',\n callout: {\n text: 'If you mainly need fast, packaged insights in one category, Liquid Data Go is usually the right fit; if you need to integrate many datasets and support multiple enterprise workflows, the broader Liquid Data platform and its solutions become more relevant.',\n },\n },\n },\n {\n markdown: `<!-- section: textBlock -->\n## Key Takeaway\n\nThe platform scales with your needs.\n\n> Start small with Go, then expand to the full suite as your data maturity grows.`,\n expected: {\n title: 'Key Takeaway',\n description: 'The platform scales with your needs.',\n callout: {\n text: 'Start small with Go, then expand to the full suite as your data maturity grows.',\n },\n },\n },\n {\n markdown: `## How to choose between a clinical serum and a nourishing dry oil\n\nClinically tested serums with patented actives target visible reduction of marks and uneven tone, while dry oils focus on broad nourishment and a satin finish.`,\n expected: {\n title: 'How to choose between a clinical serum and a nourishing dry oil',\n description:\n 'Clinically tested serums with patented actives target visible reduction of marks and uneven tone, while dry oils focus on broad nourishment and a satin finish.',\n callout: undefined,\n },\n },\n ];\n\n parse(parts: Part[], context?: ParseContext): TextBlockCompProps | null {\n const title = headingMarkdown(parts, 2) || '';\n const description = bodyText(parts) || '';\n const callout = calloutFromParts(parts);\n\n if (!title && !description) {\n context?.reportDiagnostic?.(\n DIAGNOSTIC_TYPES.SECTION_REJECTED,\n 'textBlock: both title and description are empty',\n );\n return null;\n }\n\n return { title, description, callout };\n }\n}\n"],"mappings":";AACA,SAASA,eAAe,EAAEC,QAAQ,EAAEC,gBAAgB,QAAQ,eAAe;AAO3E,SAASC,gBAAgB,QAAQ,oBAAoB;AAErD,OAAO,MAAMC,0BAA0B,CAEvC;EAAAC,YAAA;IAAAC,eAAA,sBACgB,WAAW;IACzB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IAAAA,eAAA,mBACW,CAAC,mCAAmC,CAAC;IAAAA,eAAA,mBAEjB;MAC7BC,KAAK,EAAE,kBAAkB;MACzBC,WAAW,EAAE,mBAAmB;MAChCC,OAAO,EAAE;QAAEC,IAAI,EAAE;MAA0B;IAC7C,CAAC;IAAAJ,eAAA,mBAEgD,CAC/C;MACEK,QAAQ,EAAE;AAChB;AACA;AACA;AACA,kQAAkQ;MAC5PC,QAAQ,EAAE;QACRL,KAAK,EAAE,uCAAuC;QAC9CC,WAAW,EACT,iLAAiL;QACnLC,OAAO,EAAE;UACPC,IAAI,EAAE;QACR;MACF;IACF,CAAC,EACD;MACEC,QAAQ,EAAE;AAChB;AACA;AACA;AACA;AACA,kFAAkF;MAC5EC,QAAQ,EAAE;QACRL,KAAK,EAAE,cAAc;QACrBC,WAAW,EAAE,sCAAsC;QACnDC,OAAO,EAAE;UACPC,IAAI,EAAE;QACR;MACF;IACF,CAAC,EACD;MACEC,QAAQ,EAAE;AAChB;AACA,gKAAgK;MAC1JC,QAAQ,EAAE;QACRL,KAAK,EAAE,iEAAiE;QACxEC,WAAW,EACT,iKAAiK;QACnKC,OAAO,EAAEI;MACX;IACF,CAAC,CACF;EAAA;EAEDC,KAAKA,CAACC,KAAa,EAAEC,OAAsB,EAA6B;IACtE,MAAMT,KAAK,GAAGP,eAAe,CAACe,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE;IAC7C,MAAMP,WAAW,GAAGP,QAAQ,CAACc,KAAK,CAAC,IAAI,EAAE;IACzC,MAAMN,OAAO,GAAGP,gBAAgB,CAACa,KAAK,CAAC;IAEvC,IAAI,CAACR,KAAK,IAAI,CAACC,WAAW,EAAE;MAC1BQ,OAAO,YAAPA,OAAO,CAAEC,gBAAgB,YAAzBD,OAAO,CAAEC,gBAAgB,CACvBd,gBAAgB,CAACe,gBAAgB,EACjC,iDACF,CAAC;MACD,OAAO,IAAI;IACb;IAEA,OAAO;MAAEX,KAAK;MAAEC,WAAW;MAAEC;IAAQ,CAAC;EACxC;AACF","ignoreList":[]}
@@ -46,6 +46,13 @@ export function createSdkRegistry() {
46
46
  // Collection entities are claimed by their own definition first — it is a
47
47
  // strictly narrower match than EntitySectionDefinition, which would
48
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());
49
+ .register(new EntityCollectionSectionDefinition()).register(new EntitySectionDefinition()).register(new HeroEntitySectionDefinition()).register(new HeroSectionDefinition()).register(new FeatureCardsSectionDefinition()).register(new ListItemsSectionDefinition()).register(new FeatureSection9PlusDefinition()).register(new ComparisonSectionDefinition()).register(new HtmlCommentSectionDefinition()).register(new CtaBannerSectionDefinition())
50
+ // textBlock comes after every definition whose block opens `h2 > t`
51
+ // (entity, listItems, featureCards, ctaBanner, comparison, …). Its
52
+ // trailing callout is optional, so its pattern also matches a bare
53
+ // `h2 > t`, and a pattern matches a PREFIX of the block — registered
54
+ // above those it would claim the heading + intro paragraph and strand
55
+ // the list / links / table that follow in a separate section.
56
+ .register(new TextBlockSectionDefinition()).register(new CalloutSectionDefinition()).register(new FallbackSectionDefinition()).register(new ErrorSectionDefinition());
50
57
  }
51
58
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
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":[]}
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 ListItemsSectionDefinition())\n .register(new FeatureSection9PlusDefinition())\n .register(new ComparisonSectionDefinition())\n .register(new HtmlCommentSectionDefinition())\n .register(new CtaBannerSectionDefinition())\n // textBlock comes after every definition whose block opens `h2 > t`\n // (entity, listItems, featureCards, ctaBanner, comparison, …). Its\n // trailing callout is optional, so its pattern also matches a bare\n // `h2 > t`, and a pattern matches a PREFIX of the block — registered\n // above those it would claim the heading + intro paragraph and strand\n // the list / links / table that follow in a separate section.\n .register(new TextBlockSectionDefinition())\n .register(new CalloutSectionDefinition())\n .register(new FallbackSectionDefinition())\n .register(new ErrorSectionDefinition())\n );\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,5 +1,5 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
- import { headingText, extractListItemText } from './parse-utils.js';
2
+ import { headingText, extractListItemText, inlinePartsToMarkdown } from './parse-utils.js';
3
3
  import { getPartsByType } from '../../parts/parts.js';
4
4
  /** A valid list section needs at least this many feature items. */
5
5
  const MIN_FEATURES = 2;
@@ -34,11 +34,16 @@ export class ListItemsSectionDefinition {
34
34
  var _list$meta, _item$meta, _item$meta2;
35
35
  const itemParts = ((_item$meta = item.meta) == null ? void 0 : _item$meta.parts) ?? [];
36
36
  const heading = itemParts.find(p => p.type === 'heading');
37
- const textParts = itemParts.filter(p => p.type === 'text' || p.type === 'richText');
38
- const featureDescription = textParts.map(p => {
39
- var _p$content;
40
- return (_p$content = p.content) == null ? void 0 : _p$content.trim();
41
- }).filter(Boolean).join('\n');
37
+ // Everything except the heading is the body. Serialize it rather than
38
+ // concatenating `content`, so an inline link survives: filtering to
39
+ // text parts used to drop `link` parts wholesale, deleting both the
40
+ // url and its label from the rendered item.
41
+ //
42
+ // The item's own `meta.markdown` is not usable here — for a
43
+ // `- ### Title` item it runs the heading straight into the body with no
44
+ // separator ("Gentle daily washRead the ..."), so it would duplicate
45
+ // and mangle the title.
46
+ const featureDescription = inlinePartsToMarkdown(itemParts.filter(p => p !== heading));
42
47
  const markdown = (_item$meta2 = item.meta) == null || (_item$meta2 = _item$meta2.markdown) == null ? void 0 : _item$meta2.trim();
43
48
  const content = markdown || extractListItemText(item);
44
49
  const boldMatch = content.match(/^\*\*([^*]+)\*\*:?\s*(.*)/s);
@@ -1 +1 @@
1
- {"version":3,"names":["headingText","extractListItemText","getPartsByType","MIN_FEATURES","ListItemsSectionDefinition","constructor","_defineProperty","title","features","parse","parts","lists","list","item","_list$meta","meta","items","_item$meta","_item$meta2","itemParts","heading","find","p","type","textParts","filter","featureDescription","map","_p$content","content","trim","Boolean","join","markdown","boldMatch","match","_heading$content","push","description","length"],"sources":["../../../../src/component/componentDefinitions/listItemsSectionDefinition.ts"],"sourcesContent":["import { headingText, extractListItemText } from './parse-utils';\nimport { getPartsByType, type Part, type ListPart } from '../../parts/parts';\nimport type {\n ListItemsSectionCompProps,\n ListItemsSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition } from '../section-definition';\n\n/** A valid list section needs at least this many feature items. */\nconst MIN_FEATURES = 2;\n\nexport class ListItemsSectionDefinition\n implements SectionDefinition<ListItemsSectionComponent>\n{\n sectionType = 'listItemsSection' as const;\n\n // Comment-delimited: the section spans from a `<!-- section:list -->` marker\n // and greedily captures the tokens that follow. The repetition deliberately\n // excludes `html_comment`, so the match naturally ends just before the next\n // section marker (or end of input) without consuming it — no explicit `~`\n // stop clause needed, and it still matches when this is the final section.\n // The structural contract is enforced in `parse()` instead of the pattern:\n // `parse()` returns null unless the content is an h2 followed by a 2+ item\n // feature list, so a non-conforming block falls through to the next\n // matching definition.\n patterns = [\n 'html_comment[section=\"list\"] > (h2 | h3 | t | callout | list | image | link | table | blockquote)*',\n ];\n\n defaults: ListItemsSectionCompProps = {\n title: 'Features',\n features: [],\n };\n\n fixtures: SectionFixture<ListItemsSectionCompProps>[] = [];\n\n parse(parts: Part[]): ListItemsSectionCompProps | null {\n const title = headingText(parts, 2);\n if (!title) {\n return null;\n }\n\n const features: { title?: string; description: string }[] = [];\n const lists = getPartsByType<ListPart>(parts, 'list');\n\n for (const list of lists) {\n for (const item of list.meta?.items ?? []) {\n const itemParts = (item.meta?.parts ?? []) as Part[];\n const heading = itemParts.find((p) => p.type === 'heading');\n const textParts = itemParts.filter(\n (p) => p.type === 'text' || p.type === 'richText',\n );\n const featureDescription = textParts\n .map((p) => p.content?.trim())\n .filter(Boolean)\n .join('\\n');\n\n const markdown = (item.meta?.markdown as string)?.trim();\n const content = markdown || extractListItemText(item);\n const boldMatch = content.match(/^\\*\\*([^*]+)\\*\\*:?\\s*(.*)/s);\n\n if (heading) {\n features.push({\n title: heading.content?.trim(),\n description: featureDescription || content,\n });\n } else if (boldMatch) {\n features.push({\n title: boldMatch[1].trim(),\n description: boldMatch[2].trim() || featureDescription,\n });\n } else {\n features.push({\n description: featureDescription || content,\n });\n }\n }\n }\n\n // Valid structure is an h2 title followed by a 2+ item feature list.\n // Anything else is not this section — let the next definition try.\n if (features.length < MIN_FEATURES) {\n return null;\n }\n\n return { title, features };\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["headingText","extractListItemText","inlinePartsToMarkdown","getPartsByType","MIN_FEATURES","ListItemsSectionDefinition","constructor","_defineProperty","title","features","parse","parts","lists","list","item","_list$meta","meta","items","_item$meta","_item$meta2","itemParts","heading","find","p","type","featureDescription","filter","markdown","trim","content","boldMatch","match","_heading$content","push","description","length"],"sources":["../../../../src/component/componentDefinitions/listItemsSectionDefinition.ts"],"sourcesContent":["import {\n headingText,\n extractListItemText,\n inlinePartsToMarkdown,\n} from './parse-utils';\nimport { getPartsByType, type Part, type ListPart } from '../../parts/parts';\nimport type {\n ListItemsSectionCompProps,\n ListItemsSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition } from '../section-definition';\n\n/** A valid list section needs at least this many feature items. */\nconst MIN_FEATURES = 2;\n\nexport class ListItemsSectionDefinition\n implements SectionDefinition<ListItemsSectionComponent>\n{\n sectionType = 'listItemsSection' as const;\n\n // Comment-delimited: the section spans from a `<!-- section:list -->` marker\n // and greedily captures the tokens that follow. The repetition deliberately\n // excludes `html_comment`, so the match naturally ends just before the next\n // section marker (or end of input) without consuming it — no explicit `~`\n // stop clause needed, and it still matches when this is the final section.\n // The structural contract is enforced in `parse()` instead of the pattern:\n // `parse()` returns null unless the content is an h2 followed by a 2+ item\n // feature list, so a non-conforming block falls through to the next\n // matching definition.\n patterns = [\n 'html_comment[section=\"list\"] > (h2 | h3 | t | callout | list | image | link | table | blockquote)*',\n ];\n\n defaults: ListItemsSectionCompProps = {\n title: 'Features',\n features: [],\n };\n\n fixtures: SectionFixture<ListItemsSectionCompProps>[] = [];\n\n parse(parts: Part[]): ListItemsSectionCompProps | null {\n const title = headingText(parts, 2);\n if (!title) {\n return null;\n }\n\n const features: { title?: string; description: string }[] = [];\n const lists = getPartsByType<ListPart>(parts, 'list');\n\n for (const list of lists) {\n for (const item of list.meta?.items ?? []) {\n const itemParts = (item.meta?.parts ?? []) as Part[];\n const heading = itemParts.find((p) => p.type === 'heading');\n // Everything except the heading is the body. Serialize it rather than\n // concatenating `content`, so an inline link survives: filtering to\n // text parts used to drop `link` parts wholesale, deleting both the\n // url and its label from the rendered item.\n //\n // The item's own `meta.markdown` is not usable here — for a\n // `- ### Title` item it runs the heading straight into the body with no\n // separator (\"Gentle daily washRead the ...\"), so it would duplicate\n // and mangle the title.\n const featureDescription = inlinePartsToMarkdown(\n itemParts.filter((p) => p !== heading),\n );\n\n const markdown = (item.meta?.markdown as string)?.trim();\n const content = markdown || extractListItemText(item);\n const boldMatch = content.match(/^\\*\\*([^*]+)\\*\\*:?\\s*(.*)/s);\n\n if (heading) {\n features.push({\n title: heading.content?.trim(),\n description: featureDescription || content,\n });\n } else if (boldMatch) {\n features.push({\n title: boldMatch[1].trim(),\n description: boldMatch[2].trim() || featureDescription,\n });\n } else {\n features.push({\n description: featureDescription || content,\n });\n }\n }\n }\n\n // Valid structure is an h2 title followed by a 2+ item feature list.\n // Anything else is not this section — let the next definition try.\n if (features.length < MIN_FEATURES) {\n return null;\n }\n\n return { title, features };\n }\n}\n"],"mappings":";AAAA,SACEA,WAAW,EACXC,mBAAmB,EACnBC,qBAAqB,QAChB,eAAe;AACtB,SAASC,cAAc,QAAkC,mBAAmB;AAQ5E;AACA,MAAMC,YAAY,GAAG,CAAC;AAEtB,OAAO,MAAMC,0BAA0B,CAEvC;EAAAC,YAAA;IAAAC,eAAA,sBACgB,kBAAkB;IAEhC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IAAAA,eAAA,mBACW,CACT,oGAAoG,CACrG;IAAAA,eAAA,mBAEqC;MACpCC,KAAK,EAAE,UAAU;MACjBC,QAAQ,EAAE;IACZ,CAAC;IAAAF,eAAA,mBAEuD,EAAE;EAAA;EAE1DG,KAAKA,CAACC,KAAa,EAAoC;IACrD,MAAMH,KAAK,GAAGR,WAAW,CAACW,KAAK,EAAE,CAAC,CAAC;IACnC,IAAI,CAACH,KAAK,EAAE;MACV,OAAO,IAAI;IACb;IAEA,MAAMC,QAAmD,GAAG,EAAE;IAC9D,MAAMG,KAAK,GAAGT,cAAc,CAAWQ,KAAK,EAAE,MAAM,CAAC;IAErD,KAAK,MAAME,IAAI,IAAID,KAAK,EAAE;MACxB,KAAK,MAAME,IAAI,IAAI,EAAAC,UAAA,GAAAF,IAAI,CAACG,IAAI,qBAATD,UAAA,CAAWE,KAAK,KAAI,EAAE,EAAE;QAAA,IAAAF,UAAA,EAAAG,UAAA,EAAAC,WAAA;QACzC,MAAMC,SAAS,GAAI,EAAAF,UAAA,GAAAJ,IAAI,CAACE,IAAI,qBAATE,UAAA,CAAWP,KAAK,KAAI,EAAa;QACpD,MAAMU,OAAO,GAAGD,SAAS,CAACE,IAAI,CAAEC,CAAC,IAAKA,CAAC,CAACC,IAAI,KAAK,SAAS,CAAC;QAC3D;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,MAAMC,kBAAkB,GAAGvB,qBAAqB,CAC9CkB,SAAS,CAACM,MAAM,CAAEH,CAAC,IAAKA,CAAC,KAAKF,OAAO,CACvC,CAAC;QAED,MAAMM,QAAQ,IAAAR,WAAA,GAAIL,IAAI,CAACE,IAAI,cAAAG,WAAA,GAATA,WAAA,CAAWQ,QAAQ,qBAApBR,WAAA,CAAiCS,IAAI,CAAC,CAAC;QACxD,MAAMC,OAAO,GAAGF,QAAQ,IAAI1B,mBAAmB,CAACa,IAAI,CAAC;QACrD,MAAMgB,SAAS,GAAGD,OAAO,CAACE,KAAK,CAAC,4BAA4B,CAAC;QAE7D,IAAIV,OAAO,EAAE;UAAA,IAAAW,gBAAA;UACXvB,QAAQ,CAACwB,IAAI,CAAC;YACZzB,KAAK,GAAAwB,gBAAA,GAAEX,OAAO,CAACQ,OAAO,qBAAfG,gBAAA,CAAiBJ,IAAI,CAAC,CAAC;YAC9BM,WAAW,EAAET,kBAAkB,IAAII;UACrC,CAAC,CAAC;QACJ,CAAC,MAAM,IAAIC,SAAS,EAAE;UACpBrB,QAAQ,CAACwB,IAAI,CAAC;YACZzB,KAAK,EAAEsB,SAAS,CAAC,CAAC,CAAC,CAACF,IAAI,CAAC,CAAC;YAC1BM,WAAW,EAAEJ,SAAS,CAAC,CAAC,CAAC,CAACF,IAAI,CAAC,CAAC,IAAIH;UACtC,CAAC,CAAC;QACJ,CAAC,MAAM;UACLhB,QAAQ,CAACwB,IAAI,CAAC;YACZC,WAAW,EAAET,kBAAkB,IAAII;UACrC,CAAC,CAAC;QACJ;MACF;IACF;;IAEA;IACA;IACA,IAAIpB,QAAQ,CAAC0B,MAAM,GAAG/B,YAAY,EAAE;MAClC,OAAO,IAAI;IACb;IAEA,OAAO;MAAEI,KAAK;MAAEC;IAAS,CAAC;EAC5B;AACF","ignoreList":[]}