@wix/web5-core 1.63.31 → 1.63.33

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 (27) hide show
  1. package/dist/cjs/component/componentDefinitions/ComparisonSectionDefinition.js +20 -3
  2. package/dist/cjs/component/componentDefinitions/ComparisonSectionDefinition.js.map +1 -1
  3. package/dist/cjs/component/componentDefinitions/FeatureCardsSectionDefinition.js +13 -2
  4. package/dist/cjs/component/componentDefinitions/FeatureCardsSectionDefinition.js.map +1 -1
  5. package/dist/cjs/component/componentDefinitions/HeroSectionDefinition.js +6 -2
  6. package/dist/cjs/component/componentDefinitions/HeroSectionDefinition.js.map +1 -1
  7. package/dist/cjs/component/componentDefinitions/NextStepsSectionDefinition.js +17 -2
  8. package/dist/cjs/component/componentDefinitions/NextStepsSectionDefinition.js.map +1 -1
  9. package/dist/cjs/component/componentDefinitions/parse-utils.js +61 -18
  10. package/dist/cjs/component/componentDefinitions/parse-utils.js.map +1 -1
  11. package/dist/esm/component/componentDefinitions/ComparisonSectionDefinition.js +20 -3
  12. package/dist/esm/component/componentDefinitions/ComparisonSectionDefinition.js.map +1 -1
  13. package/dist/esm/component/componentDefinitions/FeatureCardsSectionDefinition.js +14 -3
  14. package/dist/esm/component/componentDefinitions/FeatureCardsSectionDefinition.js.map +1 -1
  15. package/dist/esm/component/componentDefinitions/HeroSectionDefinition.js +8 -4
  16. package/dist/esm/component/componentDefinitions/HeroSectionDefinition.js.map +1 -1
  17. package/dist/esm/component/componentDefinitions/NextStepsSectionDefinition.js +17 -2
  18. package/dist/esm/component/componentDefinitions/NextStepsSectionDefinition.js.map +1 -1
  19. package/dist/esm/component/componentDefinitions/parse-utils.js +60 -18
  20. package/dist/esm/component/componentDefinitions/parse-utils.js.map +1 -1
  21. package/dist/types/component/componentDefinitions/ComparisonSectionDefinition.d.ts.map +1 -1
  22. package/dist/types/component/componentDefinitions/FeatureCardsSectionDefinition.d.ts.map +1 -1
  23. package/dist/types/component/componentDefinitions/HeroSectionDefinition.d.ts.map +1 -1
  24. package/dist/types/component/componentDefinitions/NextStepsSectionDefinition.d.ts.map +1 -1
  25. package/dist/types/component/componentDefinitions/parse-utils.d.ts +41 -17
  26. package/dist/types/component/componentDefinitions/parse-utils.d.ts.map +1 -1
  27. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"names":["_parts","require","_entityLinkParser","_linkTypes","str","p","_p$content","content","trim","markdownOrText","_p$meta","meta","markdown","normalizeEntityDescription","description","replace","stripMarkdown","md","headingText","parts","level","heading","getHeading","headingMarkdown","_meta$markdown","bodyText","textParts","getPartsByType","richTextParts","map","filter","Boolean","join","inlineParagraphs","paragraphs","part","_part$meta","type","continuesNode","length","push","paragraphsToMarkdown","inlinePartsToMarkdown","paragraph","bodyMarkdown","proseBodyMarkdown","firstEntityLinkIndex","findIndex","_meta","isEntityHref","href","sectionParts","slice","every","entitySectionBodyText","_meta2","linksToHeroButtons","links","getLinks","lists","flatMap","l","_l$meta","items","item","_item$meta","i","_l$content","id","text","variant","onClick","firstImageSrc","_img$meta","images","getImages","img","src","undefined","firstLink","_link$content","link","blockquoteText","bqs","_p$meta2","calloutFromParts","_p$meta3","calloutParts","raw","parsed","parseCalloutTag","kind","listToMarkdown","lines","list","_list$meta","extractListItemText","parseEntityUrl","url","trimmedUrl","isWeb5EntityUrl","parseWeb5Url","Web5UrlType","ENTITY","entityType","entityId","parseTableValue","value","normalized","toLowerCase","parseKpiItem","trimmed","boldMatch","match","title","afterBold","indexOf","appendInlineToken","current","token","test","reduce","_part$meta2","_meta3","_part$content","label","_item$meta2","partsToMarkdown","inline","_part$meta3","_part$meta4","repeat","_list$meta2","_item$meta3","toUpperCase","generatePartId","Math","random","toString","extractNestedListItems","itemParts","nestedLists","features","nested","_list$meta3","extractEntityRefs","entities","_list$meta4","_item$meta4","entityLinks","_meta4","_link$content2","_images$","_p$content2","callout","_calloutParts$0$meta","parsed2","linkText","entityUrl","markdownImageUrl","markdownFeatures","topLinks","_l$meta2","some","e","_link$content3","linkIndex","j","_meta5","_p$content3","_meta6","_p$meta4","parsedCallout","_meta7"],"sources":["../../../../src/component/componentDefinitions/parse-utils.ts"],"sourcesContent":["import type {\n Part,\n ListPart,\n LinkPart,\n ListItemPart,\n ImagePart,\n} from '../../parts/parts';\nimport {\n getPartsByType,\n getHeading,\n getImages,\n getLinks,\n} from '../../parts/parts';\nimport { parseWeb5Url } from '../../utils/entityLinkParser';\nimport { Web5UrlType, isWeb5EntityUrl } from '../../types/link-types';\nimport type { Callout } from '../../types/callout';\nimport type { HeroButton } from '../types';\n\nfunction str(p: Part | undefined): string {\n return p?.content?.trim() ?? '';\n}\n\nfunction markdownOrText(p: Part): string {\n return ((p.meta?.markdown as string)?.trim() || str(p)).trim();\n}\n\nfunction normalizeEntityDescription(description: string): string {\n return description\n .replace(/^[\\s\\u2013\\u2014-]+/, '')\n .replace(/^[:\\s]+/, '')\n .trim();\n}\n\n/** Strip basic markdown formatting to get plain text */\nexport function stripMarkdown(md: string): string {\n return md\n .replace(/\\*\\*(.+?)\\*\\*/g, '$1')\n .replace(/__(.+?)__/g, '$1')\n .replace(/\\*(.+?)\\*/g, '$1')\n .replace(/_(.+?)_/g, '$1')\n .replace(/~~(.+?)~~/g, '$1')\n .replace(/`(.+?)`/g, '$1')\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '$1')\n .trim();\n}\n\nexport function headingText(parts: Part[], level?: number): string {\n const heading = getHeading(parts, level);\n return str(heading);\n}\n\n/** Like headingText but preserves inline markdown formatting (bold, italic, etc.) */\nexport function headingMarkdown(parts: Part[], level?: number): string {\n const heading = getHeading(parts, level);\n if (!heading) {\n return '';\n }\n const meta = heading.meta as Record<string, unknown>;\n return (meta?.markdown as string)?.trim() || str(heading);\n}\n\nexport function bodyText(parts: Part[]): string {\n const textParts = getPartsByType<Part>(parts, 'text');\n const richTextParts = getPartsByType<Part>(parts, 'richText');\n return [...textParts, ...richTextParts]\n .map(markdownOrText)\n .filter(Boolean)\n .join('\\n\\n');\n}\n\n/**\n * Group a run of inline parts back into paragraphs.\n *\n * `astToParts` marks every part after the first of a given AST node with\n * `meta.continuesNode`, which is exactly \"same paragraph, keep going\". Parts\n * without it open a new paragraph.\n */\nfunction inlineParagraphs(parts: Part[]): Part[][] {\n const paragraphs: Part[][] = [];\n\n for (const part of parts) {\n if (\n part.type !== 'text' &&\n part.type !== 'richText' &&\n part.type !== 'link'\n ) {\n continue;\n }\n if (part.meta?.continuesNode && paragraphs.length > 0) {\n paragraphs[paragraphs.length - 1].push(part);\n } else {\n paragraphs.push([part]);\n }\n }\n\n return paragraphs;\n}\n\nfunction paragraphsToMarkdown(paragraphs: Part[][]): string {\n return paragraphs\n .map(inlinePartsToMarkdown)\n .map((paragraph) => paragraph.trim())\n .filter(Boolean)\n .join('\\n\\n');\n}\n\n/**\n * Body copy as markdown, with inline links intact and paragraph breaks kept.\n *\n * `bodyText` reads text parts only, so a paragraph carrying an inline link —\n * `Try narrowing to [men](web5://ask/…) instead` — arrives as `t + link + t`\n * and comes back as `\"Try narrowing to\\n\\ninstead\"`: label and url both\n * deleted, and the sentence broken in two at the gap. That is DL #134's list\n * bug in a different helper, and it is why an ask link in prose never reached\n * the page. A bare `support@shop.example` is the same bug with no author in\n * sight: GFM autolinks an email into a `link` node, so plain prose loses the\n * address.\n *\n * `inlinePartsToMarkdown` already rebuilds a run of inline parts with links\n * intact, but it flattens to one line, which is wrong for multi-paragraph\n * copy — hence `inlineParagraphs` first.\n *\n * This keeps EVERY link, including one standing alone as its own block. That\n * is right for `textBlock`, whose section consumes nothing but the copy. It is\n * wrong for a section that already spends its links elsewhere — see\n * {@link proseBodyMarkdown}.\n *\n * Kept separate from `bodyText` deliberately, but not for the reason this\n * comment used to give. Of the four callers still on `bodyText`:\n * `ErrorSectionDefinition` and `CtaBannerSectionDefinition` do hand their\n * result to a consumer that renders it raw (`ErrorSection` prints the copy in\n * a `<p>`, `CtaBannerSection` the same), so markdown there would show a\n * visitor a literal `[label](url)`. `FeatureCardsSectionDefinition` does NOT —\n * both `FeatureCardsSection` renderers in this repo put `card.description`\n * through `MarkdownText`, so it loses inline links exactly like the sections\n * fixed here; it is left alone only because its callers were not verified end\n * to end. `FeatureSection9PlusDefinition` has no registered renderer at all.\n */\nexport function bodyMarkdown(parts: Part[]): string {\n return paragraphsToMarkdown(inlineParagraphs(parts));\n}\n\n/**\n * Body copy as markdown for a section that spends some of its links on another\n * slot — hero buttons, a comparison CTA, entity items.\n *\n * Same fix as {@link bodyMarkdown} for the case that matters — a link INSIDE a\n * sentence survives instead of being deleted with its label — but it drops the\n * two shapes those sections have already claimed, so nothing renders twice:\n *\n * - A paragraph that is nothing but links. `[Get started](/) [Learn more](/x)`\n * under a hero h1 is the button row `HeroSectionDefinition` turns into\n * `buttons`; the trailing link after a comparison table is its `ctaText` /\n * `ctaHref`. Whole-paragraph is the right test because a link that is part\n * of a sentence always shares its paragraph with the text around it.\n * - Everything from the first `web5://entity/…` link onward, which is item\n * copy rather than section copy — `HeroEntitySectionDefinition` reads those\n * links (and the text after each) into `items`. Same cut\n * {@link entitySectionBodyText} makes, for the same reason.\n *\n * Nothing is lost by either rule: the dropped links are exactly the ones the\n * section renders through some other prop.\n */\nexport function proseBodyMarkdown(parts: Part[]): string {\n const firstEntityLinkIndex = parts.findIndex(\n (p) => p.type === 'link' && isEntityHref((p as LinkPart).meta?.href),\n );\n const sectionParts =\n firstEntityLinkIndex >= 0 ? parts.slice(0, firstEntityLinkIndex) : parts;\n\n return paragraphsToMarkdown(\n inlineParagraphs(sectionParts).filter(\n (paragraph) => !paragraph.every((part) => part.type === 'link'),\n ),\n );\n}\n\n/**\n * Entity sections may be authored as one paragraph per entity:\n * `[Product](web5://entity/...) - why it matches`.\n * In that shape, text after the first entity link is item copy rather than\n * section copy, so only keep prose that appears before the first entity link.\n */\nexport function entitySectionBodyText(parts: Part[]): string {\n const firstEntityLinkIndex = parts.findIndex(\n (p) => p.type === 'link' && isEntityHref((p as LinkPart).meta?.href),\n );\n const sectionParts =\n firstEntityLinkIndex >= 0 ? parts.slice(0, firstEntityLinkIndex) : parts;\n\n return sectionParts\n .filter((p) => p.type === 'text' || p.type === 'richText')\n .map(markdownOrText)\n .filter(Boolean)\n .join('\\n\\n');\n}\n\n/** Build HeroButton[] from link parts — aligned to HeroSection1Button shape */\nexport function linksToHeroButtons(parts: Part[]): HeroButton[] {\n let links = getLinks(parts);\n if (!links.length) {\n const lists = getPartsByType<ListPart>(parts, 'list');\n links = lists.flatMap((l) =>\n (l.meta?.items ?? []).flatMap((item) =>\n ((item.meta?.parts ?? []) as Part[]).filter(\n (p): p is LinkPart => p.type === 'link',\n ),\n ),\n );\n }\n return links.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}\n\n/** Return just the src URL string of the first image part */\nexport function firstImageSrc(parts: Part[]): string | undefined {\n const images = getImages(parts);\n const img = images[0];\n return img?.meta?.src || undefined;\n}\n\n/** Return the first link as { text, href } */\nexport function firstLink(\n parts: Part[],\n): { text: string; href: string } | undefined {\n const links = getLinks(parts);\n const link = links[0];\n if (!link) {\n return undefined;\n }\n return { text: link.content?.trim() || '', href: link.meta.href };\n}\n\n/** Extract text content from blockquote parts, preserving markdown formatting when available */\nexport function blockquoteText(parts: Part[]): string | undefined {\n const bqs = getPartsByType<Part>(parts, 'blockquote');\n if (bqs.length === 0) {\n return undefined;\n }\n const text = bqs\n .map((p) => (p.meta?.markdown as string)?.trim() || str(p))\n .filter(Boolean)\n .join('\\n');\n return text || undefined;\n}\n\n/** Extract first callout from parts as a Callout object */\nexport function calloutFromParts(parts: Part[]): Callout | undefined {\n const calloutParts = getPartsByType<Part>(parts, 'callout');\n if (calloutParts.length === 0) {\n return undefined;\n }\n const p = calloutParts[0];\n const raw = (p.meta?.markdown as string)?.trim() || str(p);\n const parsed = parseCalloutTag(raw);\n return parsed.text ? { text: parsed.text, kind: parsed.kind } : undefined;\n}\n\n/** Convert list parts to a markdown-like string */\nexport function listToMarkdown(parts: Part[]): string | undefined {\n const lists = getPartsByType<ListPart>(parts, 'list');\n if (lists.length === 0) {\n return undefined;\n }\n const lines: string[] = [];\n for (const list of lists) {\n const items = list.meta?.items ?? [];\n for (const item of items) {\n const text = extractListItemText(item);\n if (text) {\n lines.push(`- ${text}`);\n }\n }\n }\n return lines.length > 0 ? lines.join('\\n') : undefined;\n}\n\n/**\n * Parse a web5://entity/ URL into entityType and entityId.\n * Delegates to the central `parseWeb5Url` parser.\n */\nexport function parseEntityUrl(\n url: string,\n): { entityType: string; entityId: string } | null {\n const trimmedUrl = url?.trim();\n if (!trimmedUrl || !isWeb5EntityUrl(trimmedUrl)) {\n return null;\n }\n const parsed = parseWeb5Url(trimmedUrl);\n if (\n parsed?.type !== Web5UrlType.ENTITY ||\n !parsed.entityType ||\n !parsed.entityId\n ) {\n return null;\n }\n return { entityType: parsed.entityType, entityId: parsed.entityId };\n}\n\n/**\n * Parse a table cell value into boolean or string.\n * Ported from web50-server-ui comparisonSectionParser.tsx.\n */\nexport function parseTableValue(value: string): boolean | string {\n const normalized = value.trim().toLowerCase();\n\n if (\n normalized === 'true' ||\n normalized === 'yes' ||\n normalized === '✓' ||\n normalized === 'check' ||\n normalized === 'y'\n ) {\n return true;\n }\n if (\n normalized === 'false' ||\n normalized === 'no' ||\n normalized === '✗' ||\n normalized === 'x' ||\n normalized === 'n' ||\n normalized === ''\n ) {\n return false;\n }\n\n return value.trim();\n}\n\n/**\n * Parse a KPI item from markdown text.\n * The first **bold** segment becomes the title; everything after it (leading \":\" stripped) is the description.\n */\nexport function parseKpiItem(\n markdown: string,\n): { title: string; description: string } | null {\n const trimmed = markdown.trim();\n if (!trimmed) {\n return null;\n }\n const boldMatch = trimmed.match(/\\*\\*(.+?)\\*\\*/);\n if (!boldMatch) {\n return null;\n }\n const title = boldMatch[1].trim();\n const afterBold = trimmed.slice(\n trimmed.indexOf(boldMatch[0]) + boldMatch[0].length,\n );\n const description = afterBold.replace(/^[:\\s]+/, '').trim();\n return { title, description };\n}\n\n/** Join inline tokens the way prose reads: single spaces, none before punctuation. */\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\n/**\n * Serialize a run of inline parts back to markdown, preserving links and\n * inline emphasis.\n *\n * Concatenating `part.content` alone silently deletes links: a `link` part\n * keeps its label in `content` and its url in `meta.href`, so a filter that\n * reads only text parts turns `Read the [pricing page](/pricing) first` into\n * `Read the first` — url and label both vanish, with nothing in the output to\n * show anything was lost.\n *\n * `content` is also the *plain* text of a text part — `nodesToParts` strips\n * inline formatting and keeps the original in `meta.markdown` whenever the two\n * differ. Reading `content` therefore drops emphasis the same way it used to\n * drop links: `The **4 oz size** is best` becomes `The 4 oz size is best`.\n * Prefer `meta.markdown`, which is exactly the segment's own markdown.\n */\nexport function inlinePartsToMarkdown(parts: Part[]): string {\n return parts.reduce((text, part) => {\n if (part.type === 'link') {\n const href = (part as LinkPart).meta?.href ?? '';\n const label = part.content?.trim() ?? '';\n return appendInlineToken(text, href ? `[${label}](${href})` : label);\n }\n return appendInlineToken(\n text,\n (part.meta?.markdown as string | undefined) ?? part.content ?? '',\n );\n }, '');\n}\n\nexport function extractListItemText(item: ListItemPart): string {\n if (item.content) {\n return item.content;\n }\n if (item.meta?.parts) {\n return (item.meta.parts as Part[])\n .map((p) => p.content)\n .filter(Boolean)\n .join(' ');\n }\n return '';\n}\n\n/**\n * Reconstruct markdown-like content from parts.\n *\n * `part.content` is the *plain* text — `nodesToParts` strips inline\n * formatting and preserves the original markdown (bold, italic, links) in\n * `part.meta.markdown` when they differ. Prefer it so markdown-rendering\n * consumers (e.g. the fallback section's ReactMarkdown) keep `**bold**`.\n */\nexport function partsToMarkdown(sectionParts: Part[]): string {\n const inline = (part: Part): string =>\n (part.meta?.markdown as string | undefined) ?? part.content;\n const lines: string[] = [];\n for (const part of sectionParts) {\n if (part.type === 'heading') {\n const level = (part.meta as { level: number })?.level ?? 2;\n lines.push(`${'#'.repeat(level)} ${inline(part)}`);\n } else if (part.type === 'text' || part.type === 'richText') {\n lines.push(inline(part));\n } else if (part.type === 'list') {\n const list = part as ListPart;\n for (const item of list.meta?.items ?? []) {\n lines.push(\n `- ${(item.meta?.markdown as string | undefined) ?? extractListItemText(item)}`,\n );\n }\n } else if (part.type === 'blockquote' || part.type === 'callout') {\n lines.push(`> ${inline(part)}`);\n }\n }\n return lines.join('\\n\\n');\n}\n\n/**\n * Extract callout kind tag from blockquote text.\n * Handles [!NOTE], [!TIP], [!IMPORTANT], [!WARNING], [!CAUTION] GFM syntax.\n */\nexport function parseCalloutTag(text: string): { text: string; kind?: string } {\n const match = text.match(/^\\[!(\\w+)\\]\\s*(.*)/s);\n if (match) {\n return { kind: match[1].toUpperCase(), text: match[2].trim() };\n }\n return { text: text.trim() };\n}\n\n/** Generate a simple unique ID */\nexport function generatePartId(): string {\n return Math.random().toString(36).slice(2, 10);\n}\n\nfunction isEntityHref(href: string | undefined): boolean {\n return !!href && isWeb5EntityUrl(href);\n}\n\nexport interface EntityRef {\n entityId: string;\n entityType: string;\n linkText: string;\n entityUrl: string;\n description: string;\n markdownImageUrl?: string;\n markdownFeatures?: string[];\n callout?: Callout;\n}\n\n/**\n * Extract text from nested list items within a list item's parts.\n */\nfunction extractNestedListItems(itemParts: Part[]): string[] {\n const nestedLists = itemParts.filter((p): p is ListPart => p.type === 'list');\n const features: string[] = [];\n for (const list of nestedLists) {\n for (const nested of list.meta?.items ?? []) {\n const text = extractListItemText(nested);\n if (text) {\n features.push(text);\n }\n }\n }\n return features;\n}\n\n/**\n * Extract entity references from list items containing web5://entity/ links.\n * Also extracts markdownFeatures from nested list items within each entity item.\n */\nexport function extractEntityRefs(parts: Part[]): EntityRef[] {\n const entities: EntityRef[] = [];\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 entityLinks = itemParts.filter(\n (p): p is LinkPart =>\n p.type === 'link' && isEntityHref((p as LinkPart).meta?.href),\n );\n\n for (const link of entityLinks) {\n const parsed = parseEntityUrl(link.meta.href);\n if (parsed) {\n const images = itemParts.filter(\n (p): p is ImagePart => p.type === 'image',\n );\n const textParts = itemParts.filter(\n (p) => p.type === 'text' && p.content?.trim(),\n );\n const description = normalizeEntityDescription(\n textParts.map(markdownOrText).join(' '),\n );\n const features = extractNestedListItems(itemParts);\n const calloutParts = itemParts.filter(\n (p) => p.type === 'callout' || p.type === 'blockquote',\n );\n let callout: Callout | undefined;\n if (calloutParts.length > 0) {\n const raw =\n (calloutParts[0].meta?.markdown as string)?.trim() ||\n str(calloutParts[0]);\n const parsed2 = parseCalloutTag(raw);\n if (parsed2.text) {\n callout = { text: parsed2.text, kind: parsed2.kind };\n }\n }\n entities.push({\n entityId: parsed.entityId,\n entityType: parsed.entityType,\n linkText: link.content?.trim() || '',\n entityUrl: link.meta.href,\n description,\n markdownImageUrl: images[0]?.meta?.src,\n markdownFeatures: features.length > 0 ? features : undefined,\n callout,\n });\n }\n }\n }\n }\n\n // Also check top-level links (with surrounding context for description/image/list)\n const topLinks = getLinks(parts).filter((l) => isEntityHref(l.meta?.href));\n for (const link of topLinks) {\n const parsed = parseEntityUrl(link.meta.href);\n if (parsed && !entities.some((e) => e.entityId === parsed.entityId)) {\n // Look for description text and image after this link in the parts array\n const linkIndex = parts.indexOf(link);\n let description = '';\n let markdownImageUrl: string | undefined;\n let callout: Callout | undefined;\n const features: string[] = [];\n\n if (linkIndex >= 0) {\n // Scan following parts for description, image, callout, and list items\n for (let j = linkIndex + 1; j < parts.length; j++) {\n const p = parts[j];\n // Stop at next entity link\n if (p.type === 'link' && isEntityHref((p as LinkPart).meta?.href)) {\n break;\n }\n if (p.type === 'text' && p.content?.trim()) {\n const text = markdownOrText(p);\n description = description\n ? `${description} ${text}`\n : text;\n } else if (p.type === 'image' && !markdownImageUrl) {\n markdownImageUrl = (p as ImagePart).meta?.src;\n } else if (\n (p.type === 'callout' || p.type === 'blockquote') &&\n !callout\n ) {\n const raw = (p.meta?.markdown as string)?.trim() || str(p);\n const parsedCallout = parseCalloutTag(raw);\n if (parsedCallout.text) {\n callout = { text: parsedCallout.text, kind: parsedCallout.kind };\n }\n } else if (p.type === 'list') {\n for (const item of (p as ListPart).meta?.items ?? []) {\n const text = extractListItemText(item);\n if (text) {\n features.push(text);\n }\n }\n }\n }\n }\n\n entities.push({\n entityId: parsed.entityId,\n entityType: parsed.entityType,\n linkText: link.content?.trim() || '',\n entityUrl: link.meta.href,\n description: normalizeEntityDescription(description),\n markdownImageUrl,\n markdownFeatures: features.length > 0 ? features : undefined,\n callout,\n });\n }\n }\n\n return entities;\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_parts","require","_entityLinkParser","_linkTypes","str","p","_p$content","content","trim","markdownOrText","_p$meta","meta","markdown","normalizeEntityDescription","description","replace","stripMarkdown","md","headingText","parts","level","heading","getHeading","headingMarkdown","_meta$markdown","bodyText","textParts","getPartsByType","richTextParts","map","filter","Boolean","join","inlineParagraphs","paragraphs","part","_part$meta","type","continuesNode","length","push","isLinkRow","paragraph","some","every","standaloneLinks","flat","paragraphsToMarkdown","inlinePartsToMarkdown","bodyMarkdown","proseBodyMarkdown","firstEntityLinkIndex","findIndex","_meta","isEntityHref","href","sectionParts","slice","entitySectionBodyText","_meta2","linksToHeroButtons","links","lists","flatMap","l","_l$meta","items","item","_item$meta","i","_l$content","id","text","variant","onClick","firstImageSrc","_img$meta","images","getImages","img","src","undefined","firstLink","_link$content","getLinks","link","blockquoteText","bqs","_p$meta2","calloutFromParts","_p$meta3","calloutParts","raw","parsed","parseCalloutTag","kind","listToMarkdown","lines","list","_list$meta","extractListItemText","parseEntityUrl","url","trimmedUrl","isWeb5EntityUrl","parseWeb5Url","Web5UrlType","ENTITY","entityType","entityId","parseTableValue","value","normalized","toLowerCase","parseKpiItem","trimmed","boldMatch","match","title","afterBold","indexOf","appendInlineToken","current","token","test","reduce","_part$meta2","_meta3","_part$content","label","_item$meta2","partsToMarkdown","inline","_part$meta3","_part$meta4","repeat","_list$meta2","_item$meta3","toUpperCase","generatePartId","Math","random","toString","extractNestedListItems","itemParts","nestedLists","features","nested","_list$meta3","extractEntityRefs","entities","_list$meta4","_item$meta4","entityLinks","_meta4","_link$content2","_images$","_p$content2","callout","_calloutParts$0$meta","parsed2","linkText","entityUrl","markdownImageUrl","markdownFeatures","topLinks","_l$meta2","e","_link$content3","linkIndex","j","_meta5","_p$content3","_meta6","_p$meta4","parsedCallout","_meta7"],"sources":["../../../../src/component/componentDefinitions/parse-utils.ts"],"sourcesContent":["import type {\n Part,\n ListPart,\n LinkPart,\n ListItemPart,\n ImagePart,\n} from '../../parts/parts';\nimport {\n getPartsByType,\n getHeading,\n getImages,\n getLinks,\n} from '../../parts/parts';\nimport { parseWeb5Url } from '../../utils/entityLinkParser';\nimport { Web5UrlType, isWeb5EntityUrl } from '../../types/link-types';\nimport type { Callout } from '../../types/callout';\nimport type { HeroButton } from '../types';\n\nfunction str(p: Part | undefined): string {\n return p?.content?.trim() ?? '';\n}\n\nfunction markdownOrText(p: Part): string {\n return ((p.meta?.markdown as string)?.trim() || str(p)).trim();\n}\n\nfunction normalizeEntityDescription(description: string): string {\n return description\n .replace(/^[\\s\\u2013\\u2014-]+/, '')\n .replace(/^[:\\s]+/, '')\n .trim();\n}\n\n/** Strip basic markdown formatting to get plain text */\nexport function stripMarkdown(md: string): string {\n return md\n .replace(/\\*\\*(.+?)\\*\\*/g, '$1')\n .replace(/__(.+?)__/g, '$1')\n .replace(/\\*(.+?)\\*/g, '$1')\n .replace(/_(.+?)_/g, '$1')\n .replace(/~~(.+?)~~/g, '$1')\n .replace(/`(.+?)`/g, '$1')\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '$1')\n .trim();\n}\n\nexport function headingText(parts: Part[], level?: number): string {\n const heading = getHeading(parts, level);\n return str(heading);\n}\n\n/** Like headingText but preserves inline markdown formatting (bold, italic, etc.) */\nexport function headingMarkdown(parts: Part[], level?: number): string {\n const heading = getHeading(parts, level);\n if (!heading) {\n return '';\n }\n const meta = heading.meta as Record<string, unknown>;\n return (meta?.markdown as string)?.trim() || str(heading);\n}\n\nexport function bodyText(parts: Part[]): string {\n const textParts = getPartsByType<Part>(parts, 'text');\n const richTextParts = getPartsByType<Part>(parts, 'richText');\n return [...textParts, ...richTextParts]\n .map(markdownOrText)\n .filter(Boolean)\n .join('\\n\\n');\n}\n\n/**\n * Group a run of inline parts back into paragraphs.\n *\n * `astToParts` marks every part after the first of a given AST node with\n * `meta.continuesNode`, which is exactly \"same paragraph, keep going\". Parts\n * without it open a new paragraph.\n */\nfunction inlineParagraphs(parts: Part[]): Part[][] {\n const paragraphs: Part[][] = [];\n\n for (const part of parts) {\n if (\n part.type !== 'text' &&\n part.type !== 'richText' &&\n part.type !== 'link'\n ) {\n continue;\n }\n if (part.meta?.continuesNode && paragraphs.length > 0) {\n paragraphs[paragraphs.length - 1].push(part);\n } else {\n paragraphs.push([part]);\n }\n }\n\n return paragraphs;\n}\n\n/**\n * A paragraph that is nothing but links — the hero's button row under the h1,\n * the CTA after a comparison table. This is the one shape a section is entitled\n * to spend on a control instead of printing as copy, and its complement — a\n * link sharing its paragraph with a sentence — is body copy and nothing else.\n *\n * A blank part does not disqualify it. A hard line break between two links\n * (`[A](/a)··\\n[B](/b)`) leaves an empty `t` part behind, and an empty part is\n * not a sentence; without this the row is BOTH a button and a line of body\n * copy, which is the duplication the rule exists to prevent.\n */\nfunction isLinkRow(paragraph: Part[]): boolean {\n return (\n paragraph.some((part) => part.type === 'link') &&\n paragraph.every(\n (part) => part.type === 'link' || markdownOrText(part) === '',\n )\n );\n}\n\n/**\n * The links a section is entitled to render as its own control — a hero button\n * row, a CTA — as opposed to a link that is part of a sentence.\n *\n * The exact complement of what {@link proseBodyMarkdown} keeps, and that is the\n * point: between the two, every top-level link reaches the page exactly once.\n * `getLinks` is the wrong tool for a control slot — it takes EVERY top-level\n * link part, and a link inside a prose paragraph is a top-level part, so\n * `Email support@shop.example` (GFM autolinks a bare address, no author needed)\n * arrived as the hero's first and therefore PRIMARY button, displacing the real\n * call to action into the secondary slot and printing the address twice.\n */\nexport function standaloneLinks(parts: Part[]): LinkPart[] {\n return inlineParagraphs(parts)\n .filter(isLinkRow)\n .flat()\n .filter((part): part is LinkPart => part.type === 'link');\n}\n\nfunction paragraphsToMarkdown(paragraphs: Part[][]): string {\n return paragraphs\n .map(inlinePartsToMarkdown)\n .map((paragraph) => paragraph.trim())\n .filter(Boolean)\n .join('\\n\\n');\n}\n\n/**\n * Body copy as markdown, with inline links intact and paragraph breaks kept.\n *\n * `bodyText` reads text parts only, so a paragraph carrying an inline link —\n * `Try narrowing to [men](web5://ask/…) instead` — arrives as `t + link + t`\n * and comes back as `\"Try narrowing to\\n\\ninstead\"`: label and url both\n * deleted, and the sentence broken in two at the gap. That is DL #134's list\n * bug in a different helper, and it is why an ask link in prose never reached\n * the page. A bare `support@shop.example` is the same bug with no author in\n * sight: GFM autolinks an email into a `link` node, so plain prose loses the\n * address.\n *\n * `inlinePartsToMarkdown` already rebuilds a run of inline parts with links\n * intact, but it flattens to one line, which is wrong for multi-paragraph\n * copy — hence `inlineParagraphs` first.\n *\n * This keeps EVERY link, including one standing alone as its own block. That\n * is right for `textBlock`, whose section consumes nothing but the copy. It is\n * wrong for a section that already spends its links elsewhere — see\n * {@link proseBodyMarkdown}.\n *\n * Kept separate from `bodyText` deliberately. Of the three callers still on\n * `bodyText`: `ErrorSectionDefinition` and `CtaBannerSectionDefinition` do\n * hand their result to a consumer that renders it raw (`ErrorSection` prints\n * the copy in a `<p>`, `CtaBannerSection` the same), so markdown there would\n * show a visitor a literal `[label](url)`. `FeatureSection9PlusDefinition` is\n * the odd one out: it has no registered renderer in either client bundle\n * (`createSdkRegistry` registers the definition with no component, and only\n * `createTestRegistry` gives it a stub), so its `description` reaches nothing\n * and there is no consumer to decide against. `FeatureCardsSectionDefinition`\n * used to be listed here as affected-but-unfixed; it now uses\n * {@link proseBodyMarkdown}.\n */\nexport function bodyMarkdown(parts: Part[]): string {\n return paragraphsToMarkdown(inlineParagraphs(parts));\n}\n\n/**\n * Body copy as markdown for a section that spends some of its links on another\n * slot — hero buttons, a comparison CTA, entity items.\n *\n * Same fix as {@link bodyMarkdown} for the case that matters — a link INSIDE a\n * sentence survives instead of being deleted with its label — but it drops the\n * two shapes those sections have already claimed, so nothing renders twice:\n *\n * - A paragraph that is nothing but links — {@link isLinkRow}.\n * `[Get started](/) [Learn more](/x)` under a hero h1 is the button row\n * `HeroSectionDefinition` turns into `buttons`; the trailing link after a\n * comparison table is its `ctaText` / `ctaHref`. Whole-paragraph is the right\n * test because a link that is part of a sentence always shares its paragraph\n * with the text around it. `HeroSectionDefinition` reads the same predicate\n * from the other side via {@link standaloneLinks}, so the two partition the\n * links rather than each deciding for itself.\n * - Everything from the first `web5://entity/…` link onward, which is item\n * copy rather than section copy — `HeroEntitySectionDefinition` reads those\n * links (and the text after each) into `items`. Same cut\n * {@link entitySectionBodyText} makes, for the same reason.\n *\n * Nothing is lost by either rule: the dropped links are exactly the ones the\n * section renders through some other prop.\n */\nexport function proseBodyMarkdown(parts: Part[]): string {\n const firstEntityLinkIndex = parts.findIndex(\n (p) => p.type === 'link' && isEntityHref((p as LinkPart).meta?.href),\n );\n const sectionParts =\n firstEntityLinkIndex >= 0 ? parts.slice(0, firstEntityLinkIndex) : parts;\n\n return paragraphsToMarkdown(\n inlineParagraphs(sectionParts).filter((paragraph) => !isLinkRow(paragraph)),\n );\n}\n\n/**\n * Entity sections may be authored as one paragraph per entity:\n * `[Product](web5://entity/...) - why it matches`.\n * In that shape, text after the first entity link is item copy rather than\n * section copy, so only keep prose that appears before the first entity link.\n */\nexport function entitySectionBodyText(parts: Part[]): string {\n const firstEntityLinkIndex = parts.findIndex(\n (p) => p.type === 'link' && isEntityHref((p as LinkPart).meta?.href),\n );\n const sectionParts =\n firstEntityLinkIndex >= 0 ? parts.slice(0, firstEntityLinkIndex) : parts;\n\n return sectionParts\n .filter((p) => p.type === 'text' || p.type === 'richText')\n .map(markdownOrText)\n .filter(Boolean)\n .join('\\n\\n');\n}\n\n/**\n * Build HeroButton[] from link parts — aligned to HeroSection1Button shape.\n *\n * `standaloneLinks`, not `getLinks`, for the reason spelled out there: a link\n * in a sentence is body copy, not a button. Currently uncalled — kept on the\n * same rule as `HeroSectionDefinition` so wiring it up cannot reintroduce the\n * bug.\n */\nexport function linksToHeroButtons(parts: Part[]): HeroButton[] {\n let links: LinkPart[] = standaloneLinks(parts);\n if (!links.length) {\n const lists = getPartsByType<ListPart>(parts, 'list');\n links = lists.flatMap((l) =>\n (l.meta?.items ?? []).flatMap((item) =>\n ((item.meta?.parts ?? []) as Part[]).filter(\n (p): p is LinkPart => p.type === 'link',\n ),\n ),\n );\n }\n return links.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}\n\n/** Return just the src URL string of the first image part */\nexport function firstImageSrc(parts: Part[]): string | undefined {\n const images = getImages(parts);\n const img = images[0];\n return img?.meta?.src || undefined;\n}\n\n/** Return the first link as { text, href } */\nexport function firstLink(\n parts: Part[],\n): { text: string; href: string } | undefined {\n const links = getLinks(parts);\n const link = links[0];\n if (!link) {\n return undefined;\n }\n return { text: link.content?.trim() || '', href: link.meta.href };\n}\n\n/** Extract text content from blockquote parts, preserving markdown formatting when available */\nexport function blockquoteText(parts: Part[]): string | undefined {\n const bqs = getPartsByType<Part>(parts, 'blockquote');\n if (bqs.length === 0) {\n return undefined;\n }\n const text = bqs\n .map((p) => (p.meta?.markdown as string)?.trim() || str(p))\n .filter(Boolean)\n .join('\\n');\n return text || undefined;\n}\n\n/** Extract first callout from parts as a Callout object */\nexport function calloutFromParts(parts: Part[]): Callout | undefined {\n const calloutParts = getPartsByType<Part>(parts, 'callout');\n if (calloutParts.length === 0) {\n return undefined;\n }\n const p = calloutParts[0];\n const raw = (p.meta?.markdown as string)?.trim() || str(p);\n const parsed = parseCalloutTag(raw);\n return parsed.text ? { text: parsed.text, kind: parsed.kind } : undefined;\n}\n\n/** Convert list parts to a markdown-like string */\nexport function listToMarkdown(parts: Part[]): string | undefined {\n const lists = getPartsByType<ListPart>(parts, 'list');\n if (lists.length === 0) {\n return undefined;\n }\n const lines: string[] = [];\n for (const list of lists) {\n const items = list.meta?.items ?? [];\n for (const item of items) {\n const text = extractListItemText(item);\n if (text) {\n lines.push(`- ${text}`);\n }\n }\n }\n return lines.length > 0 ? lines.join('\\n') : undefined;\n}\n\n/**\n * Parse a web5://entity/ URL into entityType and entityId.\n * Delegates to the central `parseWeb5Url` parser.\n */\nexport function parseEntityUrl(\n url: string,\n): { entityType: string; entityId: string } | null {\n const trimmedUrl = url?.trim();\n if (!trimmedUrl || !isWeb5EntityUrl(trimmedUrl)) {\n return null;\n }\n const parsed = parseWeb5Url(trimmedUrl);\n if (\n parsed?.type !== Web5UrlType.ENTITY ||\n !parsed.entityType ||\n !parsed.entityId\n ) {\n return null;\n }\n return { entityType: parsed.entityType, entityId: parsed.entityId };\n}\n\n/**\n * Parse a table cell value into boolean or string.\n * Ported from web50-server-ui comparisonSectionParser.tsx.\n */\nexport function parseTableValue(value: string): boolean | string {\n const normalized = value.trim().toLowerCase();\n\n if (\n normalized === 'true' ||\n normalized === 'yes' ||\n normalized === '✓' ||\n normalized === 'check' ||\n normalized === 'y'\n ) {\n return true;\n }\n if (\n normalized === 'false' ||\n normalized === 'no' ||\n normalized === '✗' ||\n normalized === 'x' ||\n normalized === 'n' ||\n normalized === ''\n ) {\n return false;\n }\n\n return value.trim();\n}\n\n/**\n * Parse a KPI item from markdown text.\n * The first **bold** segment becomes the title; everything after it (leading \":\" stripped) is the description.\n */\nexport function parseKpiItem(\n markdown: string,\n): { title: string; description: string } | null {\n const trimmed = markdown.trim();\n if (!trimmed) {\n return null;\n }\n const boldMatch = trimmed.match(/\\*\\*(.+?)\\*\\*/);\n if (!boldMatch) {\n return null;\n }\n const title = boldMatch[1].trim();\n const afterBold = trimmed.slice(\n trimmed.indexOf(boldMatch[0]) + boldMatch[0].length,\n );\n const description = afterBold.replace(/^[:\\s]+/, '').trim();\n return { title, description };\n}\n\n/** Join inline tokens the way prose reads: single spaces, none before punctuation. */\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\n/**\n * Serialize a run of inline parts back to markdown, preserving links and\n * inline emphasis.\n *\n * Concatenating `part.content` alone silently deletes links: a `link` part\n * keeps its label in `content` and its url in `meta.href`, so a filter that\n * reads only text parts turns `Read the [pricing page](/pricing) first` into\n * `Read the first` — url and label both vanish, with nothing in the output to\n * show anything was lost.\n *\n * `content` is also the *plain* text of a text part — `nodesToParts` strips\n * inline formatting and keeps the original in `meta.markdown` whenever the two\n * differ. Reading `content` therefore drops emphasis the same way it used to\n * drop links: `The **4 oz size** is best` becomes `The 4 oz size is best`.\n * Prefer `meta.markdown`, which is exactly the segment's own markdown.\n */\nexport function inlinePartsToMarkdown(parts: Part[]): string {\n return parts.reduce((text, part) => {\n if (part.type === 'link') {\n const href = (part as LinkPart).meta?.href ?? '';\n const label = part.content?.trim() ?? '';\n return appendInlineToken(text, href ? `[${label}](${href})` : label);\n }\n return appendInlineToken(\n text,\n (part.meta?.markdown as string | undefined) ?? part.content ?? '',\n );\n }, '');\n}\n\nexport function extractListItemText(item: ListItemPart): string {\n if (item.content) {\n return item.content;\n }\n if (item.meta?.parts) {\n return (item.meta.parts as Part[])\n .map((p) => p.content)\n .filter(Boolean)\n .join(' ');\n }\n return '';\n}\n\n/**\n * Reconstruct markdown-like content from parts.\n *\n * `part.content` is the *plain* text — `nodesToParts` strips inline\n * formatting and preserves the original markdown (bold, italic, links) in\n * `part.meta.markdown` when they differ. Prefer it so markdown-rendering\n * consumers (e.g. the fallback section's ReactMarkdown) keep `**bold**`.\n */\nexport function partsToMarkdown(sectionParts: Part[]): string {\n const inline = (part: Part): string =>\n (part.meta?.markdown as string | undefined) ?? part.content;\n const lines: string[] = [];\n for (const part of sectionParts) {\n if (part.type === 'heading') {\n const level = (part.meta as { level: number })?.level ?? 2;\n lines.push(`${'#'.repeat(level)} ${inline(part)}`);\n } else if (part.type === 'text' || part.type === 'richText') {\n lines.push(inline(part));\n } else if (part.type === 'list') {\n const list = part as ListPart;\n for (const item of list.meta?.items ?? []) {\n lines.push(\n `- ${(item.meta?.markdown as string | undefined) ?? extractListItemText(item)}`,\n );\n }\n } else if (part.type === 'blockquote' || part.type === 'callout') {\n lines.push(`> ${inline(part)}`);\n }\n }\n return lines.join('\\n\\n');\n}\n\n/**\n * Extract callout kind tag from blockquote text.\n * Handles [!NOTE], [!TIP], [!IMPORTANT], [!WARNING], [!CAUTION] GFM syntax.\n */\nexport function parseCalloutTag(text: string): { text: string; kind?: string } {\n const match = text.match(/^\\[!(\\w+)\\]\\s*(.*)/s);\n if (match) {\n return { kind: match[1].toUpperCase(), text: match[2].trim() };\n }\n return { text: text.trim() };\n}\n\n/** Generate a simple unique ID */\nexport function generatePartId(): string {\n return Math.random().toString(36).slice(2, 10);\n}\n\nfunction isEntityHref(href: string | undefined): boolean {\n return !!href && isWeb5EntityUrl(href);\n}\n\nexport interface EntityRef {\n entityId: string;\n entityType: string;\n linkText: string;\n entityUrl: string;\n description: string;\n markdownImageUrl?: string;\n markdownFeatures?: string[];\n callout?: Callout;\n}\n\n/**\n * Extract text from nested list items within a list item's parts.\n */\nfunction extractNestedListItems(itemParts: Part[]): string[] {\n const nestedLists = itemParts.filter((p): p is ListPart => p.type === 'list');\n const features: string[] = [];\n for (const list of nestedLists) {\n for (const nested of list.meta?.items ?? []) {\n const text = extractListItemText(nested);\n if (text) {\n features.push(text);\n }\n }\n }\n return features;\n}\n\n/**\n * Extract entity references from list items containing web5://entity/ links.\n * Also extracts markdownFeatures from nested list items within each entity item.\n */\nexport function extractEntityRefs(parts: Part[]): EntityRef[] {\n const entities: EntityRef[] = [];\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 entityLinks = itemParts.filter(\n (p): p is LinkPart =>\n p.type === 'link' && isEntityHref((p as LinkPart).meta?.href),\n );\n\n for (const link of entityLinks) {\n const parsed = parseEntityUrl(link.meta.href);\n if (parsed) {\n const images = itemParts.filter(\n (p): p is ImagePart => p.type === 'image',\n );\n const textParts = itemParts.filter(\n (p) => p.type === 'text' && p.content?.trim(),\n );\n const description = normalizeEntityDescription(\n textParts.map(markdownOrText).join(' '),\n );\n const features = extractNestedListItems(itemParts);\n const calloutParts = itemParts.filter(\n (p) => p.type === 'callout' || p.type === 'blockquote',\n );\n let callout: Callout | undefined;\n if (calloutParts.length > 0) {\n const raw =\n (calloutParts[0].meta?.markdown as string)?.trim() ||\n str(calloutParts[0]);\n const parsed2 = parseCalloutTag(raw);\n if (parsed2.text) {\n callout = { text: parsed2.text, kind: parsed2.kind };\n }\n }\n entities.push({\n entityId: parsed.entityId,\n entityType: parsed.entityType,\n linkText: link.content?.trim() || '',\n entityUrl: link.meta.href,\n description,\n markdownImageUrl: images[0]?.meta?.src,\n markdownFeatures: features.length > 0 ? features : undefined,\n callout,\n });\n }\n }\n }\n }\n\n // Also check top-level links (with surrounding context for description/image/list)\n const topLinks = getLinks(parts).filter((l) => isEntityHref(l.meta?.href));\n for (const link of topLinks) {\n const parsed = parseEntityUrl(link.meta.href);\n if (parsed && !entities.some((e) => e.entityId === parsed.entityId)) {\n // Look for description text and image after this link in the parts array\n const linkIndex = parts.indexOf(link);\n let description = '';\n let markdownImageUrl: string | undefined;\n let callout: Callout | undefined;\n const features: string[] = [];\n\n if (linkIndex >= 0) {\n // Scan following parts for description, image, callout, and list items\n for (let j = linkIndex + 1; j < parts.length; j++) {\n const p = parts[j];\n // Stop at next entity link\n if (p.type === 'link' && isEntityHref((p as LinkPart).meta?.href)) {\n break;\n }\n if (p.type === 'text' && p.content?.trim()) {\n const text = markdownOrText(p);\n description = description\n ? `${description} ${text}`\n : text;\n } else if (p.type === 'image' && !markdownImageUrl) {\n markdownImageUrl = (p as ImagePart).meta?.src;\n } else if (\n (p.type === 'callout' || p.type === 'blockquote') &&\n !callout\n ) {\n const raw = (p.meta?.markdown as string)?.trim() || str(p);\n const parsedCallout = parseCalloutTag(raw);\n if (parsedCallout.text) {\n callout = { text: parsedCallout.text, kind: parsedCallout.kind };\n }\n } else if (p.type === 'list') {\n for (const item of (p as ListPart).meta?.items ?? []) {\n const text = extractListItemText(item);\n if (text) {\n features.push(text);\n }\n }\n }\n }\n }\n\n entities.push({\n entityId: parsed.entityId,\n entityType: parsed.entityType,\n linkText: link.content?.trim() || '',\n entityUrl: link.meta.href,\n description: normalizeEntityDescription(description),\n markdownImageUrl,\n markdownFeatures: features.length > 0 ? features : undefined,\n callout,\n });\n }\n }\n\n return entities;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -21,7 +21,21 @@ function isBlankCell(raw) {
21
21
  export class ComparisonSectionDefinition {
22
22
  constructor() {
23
23
  _defineProperty(this, "sectionType", 'comparison');
24
- _defineProperty(this, "patterns", ['html_comment[section^="comparison"] > (h2 | h3 | h4 | t) > html_comment? > t* > table > (t | link)?']);
24
+ // The pre-table slot is the description paragraph, so it has to admit
25
+ // `link`: `convertToBlockElements` unwraps a paragraph into its inline
26
+ // nodes, so `Questions? Email support@shop.example for help.` arrives as
27
+ // `t link t` — GFM autolinks a bare email, no author required — and an
28
+ // authored `[men's shoes](web5://ask/…)` does the same. With `t*` the run
29
+ // ended at that `link`, the whole pattern failed, and the section never
30
+ // reached `parse()`: the heading and prose were claimed by `textBlock` and
31
+ // the TABLE fell to `FallbackSectionDefinition`, whose `partsToMarkdown`
32
+ // has no `table` branch — so it rendered as an empty section and the
33
+ // comparison silently vanished.
34
+ //
35
+ // The trailing slot stays `(t | link)?`: it is the CTA, and `parse()` reads
36
+ // it positionally (see `ctaText` below). Widening it would let the section
37
+ // swallow a paragraph belonging to whatever follows.
38
+ _defineProperty(this, "patterns", ['html_comment[section^="comparison"] > (h2 | h3 | h4 | t) > html_comment? > (t | link)* > table > (t | link)?']);
25
39
  _defineProperty(this, "defaults", {
26
40
  title: 'Comparison',
27
41
  columnLabels: ['Option A', 'Option B'],
@@ -129,8 +143,11 @@ See how our platform stacks up against the competition.
129
143
  }));
130
144
  }
131
145
 
132
- // Extract CTA from link parts
133
- const link = firstLink(parts);
146
+ // The CTA is the link AFTER the table, not merely the first link in the
147
+ // section the description may now carry its own inline links, and
148
+ // `firstLink(parts)` would promote one of those to the CTA button.
149
+ const lastTableIndex = parts.map(p => p.type).lastIndexOf('table');
150
+ const link = firstLink(lastTableIndex >= 0 ? parts.slice(lastTableIndex + 1) : parts);
134
151
  const ctaText = (link == null ? void 0 : link.text) || undefined;
135
152
  const ctaHref = (link == null ? void 0 : link.href) || undefined;
136
153
 
@@ -1 +1 @@
1
- {"version":3,"names":["headingText","proseBodyMarkdown","firstLink","parseTableValue","getPartsByType","DROP_SECTION","DIAGNOSTIC_TYPES","isBlankCell","raw","v","trim","toLowerCase","test","ComparisonSectionDefinition","constructor","_defineProperty","title","columnLabels","rows","feature","values","markdown","expected","featureColumnLabel","description","ctaText","ctaHref","parse","parts","context","_tableParts$","undefined","tableParts","tableMeta","meta","columns","rawValueRows","map","row","iconHint","allHeaders","headers","rawRows","slice","label","link","text","href","keptRow","some","filteredRows","filter","_","i","filteredRawRows","droppedCount","length","reportDiagnostic","ITEMS_DROPPED","blankColumns","col","every","SECTION_REJECTED","c","join"],"sources":["../../../../src/component/componentDefinitions/ComparisonSectionDefinition.ts"],"sourcesContent":["import {\n headingText,\n proseBodyMarkdown,\n firstLink,\n parseTableValue,\n} from './parse-utils';\nimport { getPartsByType, type Part } from '../../parts/parts';\nimport type {\n ComparisonColumn,\n ComparisonCompProps,\n ComparisonRow,\n ComparisonSectionComponent,\n SectionFixture,\n} from '../types';\nimport type {\n SectionDefinition,\n ParseContext,\n DropSection,\n} from '../section-definition';\nimport { DROP_SECTION } from '../section-definition';\nimport { DIAGNOSTIC_TYPES } from '../diagnosticTypes';\n\n/**\n * A cell the writer left blank: empty, or a dash / \"n/a\" placeholder standing in\n * for \"we have no fact here\".\n *\n * This has to be judged on the RAW cell text, before `parseTableValue`, because\n * that maps an empty cell to `false` — the very same value a deliberate \"No\"\n * produces. After parsing, \"no data\" and \"no, it does not have that\" are\n * indistinguishable.\n */\nfunction isBlankCell(raw: string | undefined): boolean {\n const v = (raw ?? '').trim().toLowerCase();\n // U+2010–U+2015 are the hyphen/dash family; U+2212 is minus.\n return v === '' || v === 'n/a' || /^[-‐-―−]+$/.test(v);\n}\n\nexport class ComparisonSectionDefinition\n implements SectionDefinition<ComparisonSectionComponent>\n{\n sectionType = 'comparison' as const;\n patterns = [\n 'html_comment[section^=\"comparison\"] > (h2 | h3 | h4 | t) > html_comment? > t* > table > (t | link)?',\n ];\n\n defaults: ComparisonCompProps = {\n title: 'Comparison',\n columnLabels: ['Option A', 'Option B'],\n rows: [\n { feature: 'Price', values: ['$10', '$20'] },\n { feature: 'Storage', values: ['100GB', '1TB'] },\n ],\n };\n\n fixtures: SectionFixture<ComparisonCompProps>[] = [\n {\n markdown: `<!-- section: comparison -->\n## Compare Plans\n\n| Feature | Basic | Pro |\n|---------|-------|-----|\n| Users | 5 | Unlimited |\n| Storage | 100GB | 1TB |`,\n expected: {\n title: 'Compare Plans',\n featureColumnLabel: 'Feature',\n columnLabels: ['Basic', 'Pro'],\n rows: [\n { feature: 'Users', values: ['5', 'Unlimited'] },\n { feature: 'Storage', values: ['100GB', '1TB'] },\n ],\n },\n },\n {\n markdown: `<!-- section: comparison -->\n## Platform Comparison\n\nSee how our platform stacks up against the competition.\n\n| Feature | Our Platform | Competitor |\n|---------|--------------|------------|\n| Storage | 1TB | 100GB |\n| Users | Unlimited | 5 |\n| Support | 24/7 Priority | Email Only |\n\n[Get started](#signup)`,\n expected: {\n title: 'Platform Comparison',\n description: 'See how our platform stacks up against the competition.',\n featureColumnLabel: 'Feature',\n columnLabels: ['Our Platform', 'Competitor'],\n rows: [\n { feature: 'Storage', values: ['1TB', '100GB'] },\n { feature: 'Users', values: ['Unlimited', '5'] },\n { feature: 'Support', values: ['24/7 Priority', 'Email Only'] },\n ],\n ctaText: 'Get started',\n ctaHref: '#signup',\n },\n },\n ];\n\n parse(\n parts: Part[],\n context?: ParseContext,\n ): ComparisonCompProps | DropSection {\n const title =\n headingText(parts, 2) ||\n headingText(parts, 3) ||\n headingText(parts, 4) ||\n 'Comparison';\n const description = proseBodyMarkdown(parts) || undefined;\n\n // Table meta from nodesToParts: { columnLabels, featureColumnLabel, rows: { feature, values }[] }\n const tableParts = getPartsByType<Part>(parts, 'table');\n const tableMeta = tableParts[0]?.meta as\n | {\n columnLabels?: string[];\n columns?: ComparisonColumn[];\n featureColumnLabel?: string;\n rows?: { feature: string; iconHint?: string; values: string[] }[];\n // Legacy format from partsConverter\n headers?: string[];\n }\n | undefined;\n\n let columnLabels: string[];\n let columns: ComparisonColumn[] | undefined;\n let featureColumnLabel: string | undefined;\n let rows: ComparisonRow[];\n /** The cells exactly as written, index-aligned with `rows`. */\n let rawValueRows: string[][];\n\n if (tableMeta?.columnLabels !== undefined) {\n // SDK nodesToParts format\n columnLabels = tableMeta.columnLabels;\n columns = tableMeta.columns;\n featureColumnLabel = tableMeta.featureColumnLabel || undefined;\n rawValueRows = (tableMeta.rows ?? []).map((row) => row.values);\n rows = (tableMeta.rows ?? []).map((row) => ({\n feature: row.feature,\n ...(row.iconHint ? { iconHint: row.iconHint } : {}),\n values: row.values.map(parseTableValue),\n }));\n } else {\n // Legacy partsConverter format: { headers: string[], rows: string[][] }\n const allHeaders = tableMeta?.headers ?? [];\n const rawRows = (tableMeta as any)?.rows ?? [];\n featureColumnLabel = allHeaders[0] || undefined;\n columnLabels = allHeaders.slice(1);\n columns = columnLabels.map((label) => ({ label }));\n rawValueRows = rawRows.map((row: string[]) => row.slice(1));\n rows = rawRows.map((row: string[]) => ({\n feature: row[0] ?? '',\n values: row.slice(1).map(parseTableValue),\n }));\n }\n\n // Extract CTA from link parts\n const link = firstLink(parts);\n const ctaText = link?.text || undefined;\n const ctaHref = link?.href || undefined;\n\n // Filter out rows where all values are empty (e.g. trailing non-table text parsed as a row)\n const keptRow = rawValueRows.map((raw) => raw.some((v) => !isBlankCell(v)));\n const filteredRows = rows.filter((_, i) => keptRow[i]);\n const filteredRawRows = rawValueRows.filter((_, i) => keptRow[i]);\n const droppedCount = rows.length - filteredRows.length;\n if (droppedCount > 0) {\n context?.reportDiagnostic?.(\n DIAGNOSTIC_TYPES.ITEMS_DROPPED,\n `comparison: ${droppedCount} row(s) dropped (all values empty)`,\n );\n }\n\n // A column blank in every row is a side of the comparison the writer had no\n // facts for — it renders as a full column of dashes next to a populated one,\n // which reads as a real answer and is not one. Half a comparison is worse\n // than none, so drop the whole section. (No rows left at all lands here too:\n // every column is vacuously blank.)\n const blankColumns = columnLabels\n .map((_, col) => col)\n .filter((col) =>\n filteredRawRows.every((raw) => isBlankCell(raw[col])),\n );\n if (columnLabels.length > 0 && blankColumns.length > 0) {\n context?.reportDiagnostic?.(\n DIAGNOSTIC_TYPES.SECTION_REJECTED,\n `comparison: column(s) ${blankColumns\n .map((c) => columnLabels[c] || `#${c + 1}`)\n .join(', ')} blank across all ${filteredRawRows.length} row(s) — section dropped`,\n );\n return DROP_SECTION;\n }\n\n return {\n title,\n description,\n columnLabels,\n columns,\n rows: filteredRows,\n featureColumnLabel,\n ctaText,\n ctaHref,\n };\n }\n}\n"],"mappings":";AAAA,SACEA,WAAW,EACXC,iBAAiB,EACjBC,SAAS,EACTC,eAAe,QACV,eAAe;AACtB,SAASC,cAAc,QAAmB,mBAAmB;AAa7D,SAASC,YAAY,QAAQ,uBAAuB;AACpD,SAASC,gBAAgB,QAAQ,oBAAoB;;AAErD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,WAAWA,CAACC,GAAuB,EAAW;EACrD,MAAMC,CAAC,GAAG,CAACD,GAAG,IAAI,EAAE,EAAEE,IAAI,CAAC,CAAC,CAACC,WAAW,CAAC,CAAC;EAC1C;EACA,OAAOF,CAAC,KAAK,EAAE,IAAIA,CAAC,KAAK,KAAK,IAAI,YAAY,CAACG,IAAI,CAACH,CAAC,CAAC;AACxD;AAEA,OAAO,MAAMI,2BAA2B,CAExC;EAAAC,YAAA;IAAAC,eAAA,sBACgB,YAAY;IAAAA,eAAA,mBACf,CACT,qGAAqG,CACtG;IAAAA,eAAA,mBAE+B;MAC9BC,KAAK,EAAE,YAAY;MACnBC,YAAY,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;MACtCC,IAAI,EAAE,CACJ;QAAEC,OAAO,EAAE,OAAO;QAAEC,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK;MAAE,CAAC,EAC5C;QAAED,OAAO,EAAE,SAAS;QAAEC,MAAM,EAAE,CAAC,OAAO,EAAE,KAAK;MAAE,CAAC;IAEpD,CAAC;IAAAL,eAAA,mBAEiD,CAChD;MACEM,QAAQ,EAAE;AAChB;AACA;AACA;AACA;AACA;AACA,0BAA0B;MACpBC,QAAQ,EAAE;QACRN,KAAK,EAAE,eAAe;QACtBO,kBAAkB,EAAE,SAAS;QAC7BN,YAAY,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC;QAC9BC,IAAI,EAAE,CACJ;UAAEC,OAAO,EAAE,OAAO;UAAEC,MAAM,EAAE,CAAC,GAAG,EAAE,WAAW;QAAE,CAAC,EAChD;UAAED,OAAO,EAAE,SAAS;UAAEC,MAAM,EAAE,CAAC,OAAO,EAAE,KAAK;QAAE,CAAC;MAEpD;IACF,CAAC,EACD;MACEC,QAAQ,EAAE;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uBAAuB;MACjBC,QAAQ,EAAE;QACRN,KAAK,EAAE,qBAAqB;QAC5BQ,WAAW,EAAE,yDAAyD;QACtED,kBAAkB,EAAE,SAAS;QAC7BN,YAAY,EAAE,CAAC,cAAc,EAAE,YAAY,CAAC;QAC5CC,IAAI,EAAE,CACJ;UAAEC,OAAO,EAAE,SAAS;UAAEC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO;QAAE,CAAC,EAChD;UAAED,OAAO,EAAE,OAAO;UAAEC,MAAM,EAAE,CAAC,WAAW,EAAE,GAAG;QAAE,CAAC,EAChD;UAAED,OAAO,EAAE,SAAS;UAAEC,MAAM,EAAE,CAAC,eAAe,EAAE,YAAY;QAAE,CAAC,CAChE;QACDK,OAAO,EAAE,aAAa;QACtBC,OAAO,EAAE;MACX;IACF,CAAC,CACF;EAAA;EAEDC,KAAKA,CACHC,KAAa,EACbC,OAAsB,EACa;IAAA,IAAAC,YAAA;IACnC,MAAMd,KAAK,GACThB,WAAW,CAAC4B,KAAK,EAAE,CAAC,CAAC,IACrB5B,WAAW,CAAC4B,KAAK,EAAE,CAAC,CAAC,IACrB5B,WAAW,CAAC4B,KAAK,EAAE,CAAC,CAAC,IACrB,YAAY;IACd,MAAMJ,WAAW,GAAGvB,iBAAiB,CAAC2B,KAAK,CAAC,IAAIG,SAAS;;IAEzD;IACA,MAAMC,UAAU,GAAG5B,cAAc,CAAOwB,KAAK,EAAE,OAAO,CAAC;IACvD,MAAMK,SAAS,IAAAH,YAAA,GAAGE,UAAU,CAAC,CAAC,CAAC,qBAAbF,YAAA,CAAeI,IASpB;IAEb,IAAIjB,YAAsB;IAC1B,IAAIkB,OAAuC;IAC3C,IAAIZ,kBAAsC;IAC1C,IAAIL,IAAqB;IACzB;IACA,IAAIkB,YAAwB;IAE5B,IAAI,CAAAH,SAAS,oBAATA,SAAS,CAAEhB,YAAY,MAAKc,SAAS,EAAE;MACzC;MACAd,YAAY,GAAGgB,SAAS,CAAChB,YAAY;MACrCkB,OAAO,GAAGF,SAAS,CAACE,OAAO;MAC3BZ,kBAAkB,GAAGU,SAAS,CAACV,kBAAkB,IAAIQ,SAAS;MAC9DK,YAAY,GAAG,CAACH,SAAS,CAACf,IAAI,IAAI,EAAE,EAAEmB,GAAG,CAAEC,GAAG,IAAKA,GAAG,CAAClB,MAAM,CAAC;MAC9DF,IAAI,GAAG,CAACe,SAAS,CAACf,IAAI,IAAI,EAAE,EAAEmB,GAAG,CAAEC,GAAG,KAAM;QAC1CnB,OAAO,EAAEmB,GAAG,CAACnB,OAAO;QACpB,IAAImB,GAAG,CAACC,QAAQ,GAAG;UAAEA,QAAQ,EAAED,GAAG,CAACC;QAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QACnDnB,MAAM,EAAEkB,GAAG,CAAClB,MAAM,CAACiB,GAAG,CAAClC,eAAe;MACxC,CAAC,CAAC,CAAC;IACL,CAAC,MAAM;MACL;MACA,MAAMqC,UAAU,GAAG,CAAAP,SAAS,oBAATA,SAAS,CAAEQ,OAAO,KAAI,EAAE;MAC3C,MAAMC,OAAO,GAAG,CAACT,SAAS,oBAATA,SAAS,CAAUf,IAAI,KAAI,EAAE;MAC9CK,kBAAkB,GAAGiB,UAAU,CAAC,CAAC,CAAC,IAAIT,SAAS;MAC/Cd,YAAY,GAAGuB,UAAU,CAACG,KAAK,CAAC,CAAC,CAAC;MAClCR,OAAO,GAAGlB,YAAY,CAACoB,GAAG,CAAEO,KAAK,KAAM;QAAEA;MAAM,CAAC,CAAC,CAAC;MAClDR,YAAY,GAAGM,OAAO,CAACL,GAAG,CAAEC,GAAa,IAAKA,GAAG,CAACK,KAAK,CAAC,CAAC,CAAC,CAAC;MAC3DzB,IAAI,GAAGwB,OAAO,CAACL,GAAG,CAAEC,GAAa,KAAM;QACrCnB,OAAO,EAAEmB,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE;QACrBlB,MAAM,EAAEkB,GAAG,CAACK,KAAK,CAAC,CAAC,CAAC,CAACN,GAAG,CAAClC,eAAe;MAC1C,CAAC,CAAC,CAAC;IACL;;IAEA;IACA,MAAM0C,IAAI,GAAG3C,SAAS,CAAC0B,KAAK,CAAC;IAC7B,MAAMH,OAAO,GAAG,CAAAoB,IAAI,oBAAJA,IAAI,CAAEC,IAAI,KAAIf,SAAS;IACvC,MAAML,OAAO,GAAG,CAAAmB,IAAI,oBAAJA,IAAI,CAAEE,IAAI,KAAIhB,SAAS;;IAEvC;IACA,MAAMiB,OAAO,GAAGZ,YAAY,CAACC,GAAG,CAAE7B,GAAG,IAAKA,GAAG,CAACyC,IAAI,CAAExC,CAAC,IAAK,CAACF,WAAW,CAACE,CAAC,CAAC,CAAC,CAAC;IAC3E,MAAMyC,YAAY,GAAGhC,IAAI,CAACiC,MAAM,CAAC,CAACC,CAAC,EAAEC,CAAC,KAAKL,OAAO,CAACK,CAAC,CAAC,CAAC;IACtD,MAAMC,eAAe,GAAGlB,YAAY,CAACe,MAAM,CAAC,CAACC,CAAC,EAAEC,CAAC,KAAKL,OAAO,CAACK,CAAC,CAAC,CAAC;IACjE,MAAME,YAAY,GAAGrC,IAAI,CAACsC,MAAM,GAAGN,YAAY,CAACM,MAAM;IACtD,IAAID,YAAY,GAAG,CAAC,EAAE;MACpB1B,OAAO,YAAPA,OAAO,CAAE4B,gBAAgB,YAAzB5B,OAAO,CAAE4B,gBAAgB,CACvBnD,gBAAgB,CAACoD,aAAa,EAC9B,eAAeH,YAAY,oCAC7B,CAAC;IACH;;IAEA;IACA;IACA;IACA;IACA;IACA,MAAMI,YAAY,GAAG1C,YAAY,CAC9BoB,GAAG,CAAC,CAACe,CAAC,EAAEQ,GAAG,KAAKA,GAAG,CAAC,CACpBT,MAAM,CAAES,GAAG,IACVN,eAAe,CAACO,KAAK,CAAErD,GAAG,IAAKD,WAAW,CAACC,GAAG,CAACoD,GAAG,CAAC,CAAC,CACtD,CAAC;IACH,IAAI3C,YAAY,CAACuC,MAAM,GAAG,CAAC,IAAIG,YAAY,CAACH,MAAM,GAAG,CAAC,EAAE;MACtD3B,OAAO,YAAPA,OAAO,CAAE4B,gBAAgB,YAAzB5B,OAAO,CAAE4B,gBAAgB,CACvBnD,gBAAgB,CAACwD,gBAAgB,EACjC,yBAAyBH,YAAY,CAClCtB,GAAG,CAAE0B,CAAC,IAAK9C,YAAY,CAAC8C,CAAC,CAAC,IAAI,IAAIA,CAAC,GAAG,CAAC,EAAE,CAAC,CAC1CC,IAAI,CAAC,IAAI,CAAC,qBAAqBV,eAAe,CAACE,MAAM,2BAC1D,CAAC;MACD,OAAOnD,YAAY;IACrB;IAEA,OAAO;MACLW,KAAK;MACLQ,WAAW;MACXP,YAAY;MACZkB,OAAO;MACPjB,IAAI,EAAEgC,YAAY;MAClB3B,kBAAkB;MAClBE,OAAO;MACPC;IACF,CAAC;EACH;AACF","ignoreList":[]}
1
+ {"version":3,"names":["headingText","proseBodyMarkdown","firstLink","parseTableValue","getPartsByType","DROP_SECTION","DIAGNOSTIC_TYPES","isBlankCell","raw","v","trim","toLowerCase","test","ComparisonSectionDefinition","constructor","_defineProperty","title","columnLabels","rows","feature","values","markdown","expected","featureColumnLabel","description","ctaText","ctaHref","parse","parts","context","_tableParts$","undefined","tableParts","tableMeta","meta","columns","rawValueRows","map","row","iconHint","allHeaders","headers","rawRows","slice","label","lastTableIndex","p","type","lastIndexOf","link","text","href","keptRow","some","filteredRows","filter","_","i","filteredRawRows","droppedCount","length","reportDiagnostic","ITEMS_DROPPED","blankColumns","col","every","SECTION_REJECTED","c","join"],"sources":["../../../../src/component/componentDefinitions/ComparisonSectionDefinition.ts"],"sourcesContent":["import {\n headingText,\n proseBodyMarkdown,\n firstLink,\n parseTableValue,\n} from './parse-utils';\nimport { getPartsByType, type Part } from '../../parts/parts';\nimport type {\n ComparisonColumn,\n ComparisonCompProps,\n ComparisonRow,\n ComparisonSectionComponent,\n SectionFixture,\n} from '../types';\nimport type {\n SectionDefinition,\n ParseContext,\n DropSection,\n} from '../section-definition';\nimport { DROP_SECTION } from '../section-definition';\nimport { DIAGNOSTIC_TYPES } from '../diagnosticTypes';\n\n/**\n * A cell the writer left blank: empty, or a dash / \"n/a\" placeholder standing in\n * for \"we have no fact here\".\n *\n * This has to be judged on the RAW cell text, before `parseTableValue`, because\n * that maps an empty cell to `false` — the very same value a deliberate \"No\"\n * produces. After parsing, \"no data\" and \"no, it does not have that\" are\n * indistinguishable.\n */\nfunction isBlankCell(raw: string | undefined): boolean {\n const v = (raw ?? '').trim().toLowerCase();\n // U+2010–U+2015 are the hyphen/dash family; U+2212 is minus.\n return v === '' || v === 'n/a' || /^[-‐-―−]+$/.test(v);\n}\n\nexport class ComparisonSectionDefinition\n implements SectionDefinition<ComparisonSectionComponent>\n{\n sectionType = 'comparison' as const;\n // The pre-table slot is the description paragraph, so it has to admit\n // `link`: `convertToBlockElements` unwraps a paragraph into its inline\n // nodes, so `Questions? Email support@shop.example for help.` arrives as\n // `t link t` — GFM autolinks a bare email, no author required — and an\n // authored `[men's shoes](web5://ask/…)` does the same. With `t*` the run\n // ended at that `link`, the whole pattern failed, and the section never\n // reached `parse()`: the heading and prose were claimed by `textBlock` and\n // the TABLE fell to `FallbackSectionDefinition`, whose `partsToMarkdown`\n // has no `table` branch — so it rendered as an empty section and the\n // comparison silently vanished.\n //\n // The trailing slot stays `(t | link)?`: it is the CTA, and `parse()` reads\n // it positionally (see `ctaText` below). Widening it would let the section\n // swallow a paragraph belonging to whatever follows.\n patterns = [\n 'html_comment[section^=\"comparison\"] > (h2 | h3 | h4 | t) > html_comment? > (t | link)* > table > (t | link)?',\n ];\n\n defaults: ComparisonCompProps = {\n title: 'Comparison',\n columnLabels: ['Option A', 'Option B'],\n rows: [\n { feature: 'Price', values: ['$10', '$20'] },\n { feature: 'Storage', values: ['100GB', '1TB'] },\n ],\n };\n\n fixtures: SectionFixture<ComparisonCompProps>[] = [\n {\n markdown: `<!-- section: comparison -->\n## Compare Plans\n\n| Feature | Basic | Pro |\n|---------|-------|-----|\n| Users | 5 | Unlimited |\n| Storage | 100GB | 1TB |`,\n expected: {\n title: 'Compare Plans',\n featureColumnLabel: 'Feature',\n columnLabels: ['Basic', 'Pro'],\n rows: [\n { feature: 'Users', values: ['5', 'Unlimited'] },\n { feature: 'Storage', values: ['100GB', '1TB'] },\n ],\n },\n },\n {\n markdown: `<!-- section: comparison -->\n## Platform Comparison\n\nSee how our platform stacks up against the competition.\n\n| Feature | Our Platform | Competitor |\n|---------|--------------|------------|\n| Storage | 1TB | 100GB |\n| Users | Unlimited | 5 |\n| Support | 24/7 Priority | Email Only |\n\n[Get started](#signup)`,\n expected: {\n title: 'Platform Comparison',\n description: 'See how our platform stacks up against the competition.',\n featureColumnLabel: 'Feature',\n columnLabels: ['Our Platform', 'Competitor'],\n rows: [\n { feature: 'Storage', values: ['1TB', '100GB'] },\n { feature: 'Users', values: ['Unlimited', '5'] },\n { feature: 'Support', values: ['24/7 Priority', 'Email Only'] },\n ],\n ctaText: 'Get started',\n ctaHref: '#signup',\n },\n },\n ];\n\n parse(\n parts: Part[],\n context?: ParseContext,\n ): ComparisonCompProps | DropSection {\n const title =\n headingText(parts, 2) ||\n headingText(parts, 3) ||\n headingText(parts, 4) ||\n 'Comparison';\n const description = proseBodyMarkdown(parts) || undefined;\n\n // Table meta from nodesToParts: { columnLabels, featureColumnLabel, rows: { feature, values }[] }\n const tableParts = getPartsByType<Part>(parts, 'table');\n const tableMeta = tableParts[0]?.meta as\n | {\n columnLabels?: string[];\n columns?: ComparisonColumn[];\n featureColumnLabel?: string;\n rows?: { feature: string; iconHint?: string; values: string[] }[];\n // Legacy format from partsConverter\n headers?: string[];\n }\n | undefined;\n\n let columnLabels: string[];\n let columns: ComparisonColumn[] | undefined;\n let featureColumnLabel: string | undefined;\n let rows: ComparisonRow[];\n /** The cells exactly as written, index-aligned with `rows`. */\n let rawValueRows: string[][];\n\n if (tableMeta?.columnLabels !== undefined) {\n // SDK nodesToParts format\n columnLabels = tableMeta.columnLabels;\n columns = tableMeta.columns;\n featureColumnLabel = tableMeta.featureColumnLabel || undefined;\n rawValueRows = (tableMeta.rows ?? []).map((row) => row.values);\n rows = (tableMeta.rows ?? []).map((row) => ({\n feature: row.feature,\n ...(row.iconHint ? { iconHint: row.iconHint } : {}),\n values: row.values.map(parseTableValue),\n }));\n } else {\n // Legacy partsConverter format: { headers: string[], rows: string[][] }\n const allHeaders = tableMeta?.headers ?? [];\n const rawRows = (tableMeta as any)?.rows ?? [];\n featureColumnLabel = allHeaders[0] || undefined;\n columnLabels = allHeaders.slice(1);\n columns = columnLabels.map((label) => ({ label }));\n rawValueRows = rawRows.map((row: string[]) => row.slice(1));\n rows = rawRows.map((row: string[]) => ({\n feature: row[0] ?? '',\n values: row.slice(1).map(parseTableValue),\n }));\n }\n\n // The CTA is the link AFTER the table, not merely the first link in the\n // section — the description may now carry its own inline links, and\n // `firstLink(parts)` would promote one of those to the CTA button.\n const lastTableIndex = parts.map((p) => p.type).lastIndexOf('table');\n const link = firstLink(\n lastTableIndex >= 0 ? parts.slice(lastTableIndex + 1) : parts,\n );\n const ctaText = link?.text || undefined;\n const ctaHref = link?.href || undefined;\n\n // Filter out rows where all values are empty (e.g. trailing non-table text parsed as a row)\n const keptRow = rawValueRows.map((raw) => raw.some((v) => !isBlankCell(v)));\n const filteredRows = rows.filter((_, i) => keptRow[i]);\n const filteredRawRows = rawValueRows.filter((_, i) => keptRow[i]);\n const droppedCount = rows.length - filteredRows.length;\n if (droppedCount > 0) {\n context?.reportDiagnostic?.(\n DIAGNOSTIC_TYPES.ITEMS_DROPPED,\n `comparison: ${droppedCount} row(s) dropped (all values empty)`,\n );\n }\n\n // A column blank in every row is a side of the comparison the writer had no\n // facts for — it renders as a full column of dashes next to a populated one,\n // which reads as a real answer and is not one. Half a comparison is worse\n // than none, so drop the whole section. (No rows left at all lands here too:\n // every column is vacuously blank.)\n const blankColumns = columnLabels\n .map((_, col) => col)\n .filter((col) =>\n filteredRawRows.every((raw) => isBlankCell(raw[col])),\n );\n if (columnLabels.length > 0 && blankColumns.length > 0) {\n context?.reportDiagnostic?.(\n DIAGNOSTIC_TYPES.SECTION_REJECTED,\n `comparison: column(s) ${blankColumns\n .map((c) => columnLabels[c] || `#${c + 1}`)\n .join(', ')} blank across all ${filteredRawRows.length} row(s) — section dropped`,\n );\n return DROP_SECTION;\n }\n\n return {\n title,\n description,\n columnLabels,\n columns,\n rows: filteredRows,\n featureColumnLabel,\n ctaText,\n ctaHref,\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 { headingMarkdown, bodyText, calloutFromParts, firstImageSrc, firstLink, stripMarkdown } from './parse-utils.js';
2
+ import { headingMarkdown, proseBodyMarkdown, calloutFromParts, firstImageSrc, firstLink, stripMarkdown } from './parse-utils.js';
3
3
  export class FeatureCardsSectionDefinition {
4
4
  constructor() {
5
5
  _defineProperty(this, "sectionType", 'featureCards');
@@ -81,10 +81,21 @@ Description B.`,
81
81
  for (const group of groups) {
82
82
  const title = headingMarkdown(group, 2) || headingMarkdown(group, 3) || '';
83
83
  let imageUrl = firstImageSrc(group);
84
- const description = bodyText(group) || '';
84
+ // Both `FeatureCardsSection` renderers put this through `MarkdownText`,
85
+ // so a link inside a sentence has to survive: `bodyText` kept only text
86
+ // parts and joined them with a blank line, so `Email support@shop.example
87
+ // anytime` arrived as "Email\n\nanytime" — address gone, sentence split
88
+ // at the gap (GFM autolinks a bare email into a `link` node, so this
89
+ // needed no author). `proseBodyMarkdown` rather than `bodyMarkdown`
90
+ // because a links-only paragraph is the card's own CTA, read below into
91
+ // `linkText` / `linkHref`; keeping it here would render it twice.
92
+ const description = proseBodyMarkdown(group) || '';
85
93
  let imageFromText;
86
94
  if (!imageUrl && context != null && context.getContextualImage) {
87
- const contentParts = [stripMarkdown(title), description];
95
+ // Strip before keyword matching, as the title already is: the matcher
96
+ // scans for whole words, and a raw `](web5://ask/hydration)` would let
97
+ // a url slug pick the card's image.
98
+ const contentParts = [stripMarkdown(title), stripMarkdown(description)];
88
99
  const result = context.getContextualImage(contentParts);
89
100
  if (result) {
90
101
  imageUrl = result.filename;
@@ -1 +1 @@
1
- {"version":3,"names":["headingMarkdown","bodyText","calloutFromParts","firstImageSrc","firstLink","stripMarkdown","FeatureCardsSectionDefinition","constructor","_defineProperty","cards","title","description","markdown","expected","callout","text","kind","parse","parts","context","groups","current","part","type","some","p","push","length","group","imageUrl","imageFromText","getContextualImage","contentParts","result","filename","isFromText","undefined","link","linkText","linkHref","href"],"sources":["../../../../src/component/componentDefinitions/FeatureCardsSectionDefinition.ts"],"sourcesContent":["import type { Part } from '../../parts/parts';\nimport {\n headingMarkdown,\n bodyText,\n calloutFromParts,\n firstImageSrc,\n firstLink,\n stripMarkdown,\n} from './parse-utils';\nimport type {\n FeatureCardCompProps,\n FeatureCardsCompProps,\n FeatureCardsSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition, ParseContext } from '../section-definition';\n\nexport class FeatureCardsSectionDefinition\n implements SectionDefinition<FeatureCardsSectionComponent>\n{\n sectionType = 'featureCards' as const;\n patterns = [\n '(html_comment[section^=\"information\"] > h2 > image? > t+ > link? > callout?)[2-]',\n ];\n\n defaults: FeatureCardsCompProps = {\n cards: [\n {\n title: 'Feature 1',\n description: 'Description of feature 1',\n },\n ],\n };\n\n fixtures: SectionFixture<FeatureCardsCompProps>[] = [\n {\n markdown: `<!-- section: information, reason: first card -->\n## Fast\n\nLightning quick performance\n\n> [!TIP] Speed is everything.\n\n<!-- section: information, reason: second card -->\n## Secure\n\nEnterprise-grade security\n\n> [!NOTE] Built with best practices.`,\n expected: {\n cards: [\n {\n title: 'Fast',\n description: 'Lightning quick performance',\n callout: { text: 'Speed is everything.', kind: 'TIP' },\n },\n {\n title: 'Secure',\n description: 'Enterprise-grade security',\n callout: { text: 'Built with best practices.', kind: 'NOTE' },\n },\n ],\n },\n },\n {\n markdown: `## Feature A\n\nFirst paragraph.\n\nSecond paragraph with more detail.\n\n## Feature B\n\nDescription B.`,\n expected: {\n cards: [\n {\n title: 'Feature A',\n description:\n 'First paragraph.\\n\\nSecond paragraph with more detail.',\n },\n { title: 'Feature B', description: 'Description B.' },\n ],\n },\n },\n ];\n\n parse(parts: Part[], context?: ParseContext): FeatureCardsCompProps {\n // Split flat parts into groups by heading boundaries\n const groups: Part[][] = [];\n let current: Part[] = [];\n\n for (const part of parts) {\n if (\n part.type === 'heading' &&\n current.some((p) => p.type === 'heading')\n ) {\n groups.push(current);\n current = [part];\n } else {\n current.push(part);\n }\n }\n if (current.length > 0 && current.some((p) => p.type === 'heading')) {\n groups.push(current);\n }\n\n const cards: FeatureCardCompProps[] = [];\n for (const group of groups) {\n const title =\n headingMarkdown(group, 2) || headingMarkdown(group, 3) || '';\n let imageUrl = firstImageSrc(group);\n const description = bodyText(group) || '';\n\n let imageFromText: boolean | undefined;\n if (!imageUrl && context?.getContextualImage) {\n const contentParts = [stripMarkdown(title), description];\n const result = context.getContextualImage(contentParts);\n if (result) {\n imageUrl = result.filename;\n imageFromText = result.isFromText || undefined;\n }\n }\n const link = firstLink(group);\n const linkText = link?.text || undefined;\n const linkHref = link?.href || undefined;\n const callout = calloutFromParts(group);\n\n cards.push({\n title,\n description,\n imageUrl,\n imageFromText,\n linkText,\n linkHref,\n callout,\n });\n }\n\n return { cards };\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["headingMarkdown","proseBodyMarkdown","calloutFromParts","firstImageSrc","firstLink","stripMarkdown","FeatureCardsSectionDefinition","constructor","_defineProperty","cards","title","description","markdown","expected","callout","text","kind","parse","parts","context","groups","current","part","type","some","p","push","length","group","imageUrl","imageFromText","getContextualImage","contentParts","result","filename","isFromText","undefined","link","linkText","linkHref","href"],"sources":["../../../../src/component/componentDefinitions/FeatureCardsSectionDefinition.ts"],"sourcesContent":["import type { Part } from '../../parts/parts';\nimport {\n headingMarkdown,\n proseBodyMarkdown,\n calloutFromParts,\n firstImageSrc,\n firstLink,\n stripMarkdown,\n} from './parse-utils';\nimport type {\n FeatureCardCompProps,\n FeatureCardsCompProps,\n FeatureCardsSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition, ParseContext } from '../section-definition';\n\nexport class FeatureCardsSectionDefinition\n implements SectionDefinition<FeatureCardsSectionComponent>\n{\n sectionType = 'featureCards' as const;\n patterns = [\n '(html_comment[section^=\"information\"] > h2 > image? > t+ > link? > callout?)[2-]',\n ];\n\n defaults: FeatureCardsCompProps = {\n cards: [\n {\n title: 'Feature 1',\n description: 'Description of feature 1',\n },\n ],\n };\n\n fixtures: SectionFixture<FeatureCardsCompProps>[] = [\n {\n markdown: `<!-- section: information, reason: first card -->\n## Fast\n\nLightning quick performance\n\n> [!TIP] Speed is everything.\n\n<!-- section: information, reason: second card -->\n## Secure\n\nEnterprise-grade security\n\n> [!NOTE] Built with best practices.`,\n expected: {\n cards: [\n {\n title: 'Fast',\n description: 'Lightning quick performance',\n callout: { text: 'Speed is everything.', kind: 'TIP' },\n },\n {\n title: 'Secure',\n description: 'Enterprise-grade security',\n callout: { text: 'Built with best practices.', kind: 'NOTE' },\n },\n ],\n },\n },\n {\n markdown: `## Feature A\n\nFirst paragraph.\n\nSecond paragraph with more detail.\n\n## Feature B\n\nDescription B.`,\n expected: {\n cards: [\n {\n title: 'Feature A',\n description:\n 'First paragraph.\\n\\nSecond paragraph with more detail.',\n },\n { title: 'Feature B', description: 'Description B.' },\n ],\n },\n },\n ];\n\n parse(parts: Part[], context?: ParseContext): FeatureCardsCompProps {\n // Split flat parts into groups by heading boundaries\n const groups: Part[][] = [];\n let current: Part[] = [];\n\n for (const part of parts) {\n if (\n part.type === 'heading' &&\n current.some((p) => p.type === 'heading')\n ) {\n groups.push(current);\n current = [part];\n } else {\n current.push(part);\n }\n }\n if (current.length > 0 && current.some((p) => p.type === 'heading')) {\n groups.push(current);\n }\n\n const cards: FeatureCardCompProps[] = [];\n for (const group of groups) {\n const title =\n headingMarkdown(group, 2) || headingMarkdown(group, 3) || '';\n let imageUrl = firstImageSrc(group);\n // Both `FeatureCardsSection` renderers put this through `MarkdownText`,\n // so a link inside a sentence has to survive: `bodyText` kept only text\n // parts and joined them with a blank line, so `Email support@shop.example\n // anytime` arrived as \"Email\\n\\nanytime\" — address gone, sentence split\n // at the gap (GFM autolinks a bare email into a `link` node, so this\n // needed no author). `proseBodyMarkdown` rather than `bodyMarkdown`\n // because a links-only paragraph is the card's own CTA, read below into\n // `linkText` / `linkHref`; keeping it here would render it twice.\n const description = proseBodyMarkdown(group) || '';\n\n let imageFromText: boolean | undefined;\n if (!imageUrl && context?.getContextualImage) {\n // Strip before keyword matching, as the title already is: the matcher\n // scans for whole words, and a raw `](web5://ask/hydration)` would let\n // a url slug pick the card's image.\n const contentParts = [stripMarkdown(title), stripMarkdown(description)];\n const result = context.getContextualImage(contentParts);\n if (result) {\n imageUrl = result.filename;\n imageFromText = result.isFromText || undefined;\n }\n }\n const link = firstLink(group);\n const linkText = link?.text || undefined;\n const linkHref = link?.href || undefined;\n const callout = calloutFromParts(group);\n\n cards.push({\n title,\n description,\n imageUrl,\n imageFromText,\n linkText,\n linkHref,\n callout,\n });\n }\n\n return { cards };\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,6 +1,6 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
- import { headingText, headingMarkdown, proseBodyMarkdown, firstImageSrc, parseCalloutTag, extractListItemText } from './parse-utils.js';
3
- import { getPartsByType, getLinks } from '../../parts/parts.js';
2
+ import { headingText, headingMarkdown, proseBodyMarkdown, firstImageSrc, parseCalloutTag, extractListItemText, standaloneLinks } from './parse-utils.js';
3
+ import { getPartsByType } from '../../parts/parts.js';
4
4
  export class HeroSectionDefinition {
5
5
  constructor() {
6
6
  _defineProperty(this, "sectionType", 'hero');
@@ -87,9 +87,13 @@ Get started today with our amazing features.
87
87
  }
88
88
  }
89
89
 
90
- // Start with top-level links as buttons
90
+ // Start with the hero's own button row. NOT every top-level link: a link
91
+ // inside a prose paragraph is a top-level part too, so `getLinks` handed
92
+ // `Email support@shop.example` the `btn-0` / primary slot and pushed the
93
+ // real call to action down to secondary. `standaloneLinks` keeps only a
94
+ // link that stands alone as its own block, which is the row the hero means.
91
95
  let buttonIndex = 0;
92
- const buttons = getLinks(parts).map((l, i) => {
96
+ const buttons = standaloneLinks(parts).map((l, i) => {
93
97
  var _l$content;
94
98
  return {
95
99
  id: `btn-${i}`,
@@ -1 +1 @@
1
- {"version":3,"names":["headingText","headingMarkdown","proseBodyMarkdown","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 proseBodyMarkdown,\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: proseBodyMarkdown(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","proseBodyMarkdown","firstImageSrc","parseCalloutTag","extractListItemText","standaloneLinks","getPartsByType","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 proseBodyMarkdown,\n firstImageSrc,\n parseCalloutTag,\n extractListItemText,\n standaloneLinks,\n} from './parse-utils';\nimport type { Part, ListPart, LinkPart, ListItemPart } from '../../parts/parts';\nimport { getPartsByType } 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 the hero's own button row. NOT every top-level link: a link\n // inside a prose paragraph is a top-level part too, so `getLinks` handed\n // `Email support@shop.example` the `btn-0` / primary slot and pushed the\n // real call to action down to secondary. `standaloneLinks` keeps only a\n // link that stands alone as its own block, which is the row the hero means.\n let buttonIndex = 0;\n const buttons: HeroButton[] = standaloneLinks(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: proseBodyMarkdown(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":[]}
@@ -36,8 +36,23 @@ export class NextStepsSectionDefinition {
36
36
  constructor() {
37
37
  _defineProperty(this, "sectionType", 'nextSteps');
38
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)+}',
39
+ // Framing sentence then one chip per bullet — the authored shape. The
40
+ // framing slot is `(t | link)*`, not `t?`, because a paragraph is unwrapped
41
+ // into its inline nodes: `Questions? Email support@shop.example for help.`
42
+ // arrives as `t link t` (GFM autolinks a bare email) and so does an
43
+ // authored `[men's shoes](web5://ask/…)`. With `t?` the run ended at that
44
+ // `link`, this pattern failed, and the legacy pattern below claimed the
45
+ // section instead — turning the prose link into a chip and stranding the
46
+ // real chip list in the fallback as raw bullets.
47
+ //
48
+ // This does NOT steal the legacy pattern's inputs: the `list` here is
49
+ // mandatory, so a section with chips in the prose and no list still falls
50
+ // through. It does change one rare shape — prose that is nothing but links
51
+ // ALONGSIDE a chip list now matches here, and `proseBodyMarkdown` drops
52
+ // link-only paragraphs, so those links are dropped rather than rendered
53
+ // inline. That shape previously stranded the list entirely, so neither
54
+ // outcome was whole; this one at least renders the authored chips.
55
+ '(html_comment[section^="next"] | html_comment[semantic^="next"]) > h2 > image? > (t | link)* > list{item[1-]:(icon | t)* > (t? > link)+}',
41
56
  // Legacy inline shape: chips embedded in the prose. Still arrives from
42
57
  // sites whose next-steps prompt has not moved to the list shape.
43
58
  '(html_comment[section^="next"] | html_comment[semantic^="next"]) > h2 > image? > (t | link)+']);
@@ -1 +1 @@
1
- {"version":3,"names":["headingText","proseBodyMarkdown","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 proseBodyMarkdown,\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 this never picks up a chip.\n body = proseBodyMarkdown(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":[]}
1
+ {"version":3,"names":["headingText","proseBodyMarkdown","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 proseBodyMarkdown,\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 then one chip per bullet — the authored shape. The\n // framing slot is `(t | link)*`, not `t?`, because a paragraph is unwrapped\n // into its inline nodes: `Questions? Email support@shop.example for help.`\n // arrives as `t link t` (GFM autolinks a bare email) and so does an\n // authored `[men's shoes](web5://ask/…)`. With `t?` the run ended at that\n // `link`, this pattern failed, and the legacy pattern below claimed the\n // section instead — turning the prose link into a chip and stranding the\n // real chip list in the fallback as raw bullets.\n //\n // This does NOT steal the legacy pattern's inputs: the `list` here is\n // mandatory, so a section with chips in the prose and no list still falls\n // through. It does change one rare shape — prose that is nothing but links\n // ALONGSIDE a chip list now matches here, and `proseBodyMarkdown` drops\n // link-only paragraphs, so those links are dropped rather than rendered\n // inline. That shape previously stranded the list entirely, so neither\n // outcome was whole; this one at least renders the authored chips.\n '(html_comment[section^=\"next\"] | html_comment[semantic^=\"next\"]) > h2 > image? > (t | link)* > 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 this never picks up a chip.\n body = proseBodyMarkdown(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":[]}