{"version":3,"file":"index.cjs","names":[],"sources":["../src/images-optimization.ts","../src/utils/index.ts","../src/static/dynamic-resolvers.ts","../src/static/render-map.generated.ts","../src/static/style.ts","../src/static/attribute.ts","../src/static/node-helpers.ts","../src/static/normalize-nodes.ts","../src/static/util.ts","../src/render-richtext.ts"],"sourcesContent":["import type { SbRichTextImageOptions } from './types';\n\n/**\n * Builds a Storyblok image object with optimized URL and attributes.\n *\n * This function:\n * - Applies Storyblok image transformations (width, height, filters, etc.)\n * - Generates optional srcset and sizes attributes\n * - Returns the transformed image `src` and related HTML attributes\n *\n * If no options are provided, the original image URL is returned unchanged.\n *\n * @param src - The original Storyblok image URL.\n * @param options - Optional configuration for image optimization.\n * @returns An object containing:\n *   - `src`: The transformed image URL\n *   - `attrs`: HTML attributes such as width, height, srcset, sizes, loading, and class\n *\n * @example\n * const image = buildStoryblokImage(src, {\n *   width: 800,\n *   height: 600,\n *   filters: { blur: 5 },\n * });\n *\n * <img {...image.attrs} src={image.src} />\n */\nexport function optimizeImage(src: string, options?: boolean | Partial<SbRichTextImageOptions>): { src: string; attrs: Record<string, unknown> } {\n  if (!options) {\n    return { src, attrs: {} };\n  }\n  let w = 0;\n  let h = 0;\n  const attrs: Record<string, unknown> = {};\n  const filterParams: string[] = [];\n\n  function validateAndPushFilterParam(value: number, min: number, max: number, filter: string, filterParams: string[]) {\n    if (typeof value !== 'number' || value <= min || value >= max) {\n      console.warn(`[StoryblokRichText] - ${filter.charAt(0).toUpperCase() + filter.slice(1)} value must be a number between ${min} and ${max} (inclusive)`);\n    }\n    else {\n      filterParams.push(`${filter}(${value})`);\n    }\n  }\n\n  if (typeof options === 'object') {\n    if (options.width !== undefined) {\n      if (typeof options.width === 'number' && options.width >= 0) {\n        attrs.width = options.width;\n        w = options.width;\n      }\n      else {\n        console.warn('[StoryblokRichText] - Width value must be a number greater than or equal to 0');\n      }\n    }\n    if (options.height !== undefined) {\n      if (typeof options.height === 'number' && options.height >= 0) {\n        attrs.height = options.height;\n        h = options.height;\n      }\n      else {\n        console.warn('[StoryblokRichText] - Height value must be a number greater than or equal to 0');\n      }\n    }\n    if (options.height === 0 && options.width === 0) {\n      delete attrs.width;\n      delete attrs.height;\n      console.warn('[StoryblokRichText] - Width and height values cannot both be 0');\n    }\n    if (options.loading && ['lazy', 'eager'].includes(options.loading)) {\n      attrs.loading = options.loading;\n    }\n    if (options.class) {\n      attrs.class = options.class;\n    }\n\n    if (options.filters) {\n      const { filters } = options || {};\n      const { blur, brightness, fill, format, grayscale, quality, rotate } = filters || {};\n\n      if (blur) {\n        validateAndPushFilterParam(blur, 0, 100, 'blur', filterParams);\n      }\n      if (quality) {\n        validateAndPushFilterParam(quality, 0, 100, 'quality', filterParams);\n      }\n      if (brightness) {\n        validateAndPushFilterParam(brightness, 0, 100, 'brightness', filterParams);\n      }\n      if (fill) {\n        filterParams.push(`fill(${fill})`);\n      }\n      if (grayscale) {\n        filterParams.push(`grayscale()`);\n      }\n      if (rotate && [0, 90, 180, 270].includes(options.filters.rotate || 0)) {\n        filterParams.push(`rotate(${rotate})`);\n      }\n      if (format && ['webp', 'png', 'jpeg'].includes(format)) {\n        filterParams.push(`format(${format})`);\n      }\n    }\n\n    // Construct srcset attribute\n    if (options.srcset) {\n      attrs.srcset = options.srcset.map((entry): string | undefined => {\n        if (typeof entry === 'number') {\n          return `${src}/m/${entry}x0/${filterParams.length > 0 ? `filters:${filterParams.join(':')}` : ''} ${entry}w`;\n        }\n        if (Array.isArray(entry) && entry.length === 2) {\n          const [entryWidth, entryHeight] = entry;\n          return `${src}/m/${entryWidth}x${entryHeight}/${filterParams.length > 0 ? `filters:${filterParams.join(':')}` : ''} ${entryWidth}w`;\n        }\n        else {\n          console.warn('[StoryblokRichText] - srcset entry must be a number or a tuple of two numbers');\n          return undefined;\n        }\n      }).join(', ');\n    }\n\n    // Construct sizes attribute\n    if (options.sizes) {\n      attrs.sizes = options.sizes.join(', ');\n    }\n  }\n\n  // server-side WebP support detection https://www.storyblok.com/docs/image-service/#optimize\n  // https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg/m/\n  let resultSrc = `${src}/m/`;\n  if (w > 0 || h > 0) {\n    resultSrc = `${resultSrc}${w}x${h}/`;\n  }\n  if (filterParams.length > 0) {\n    resultSrc = `${resultSrc}filters:${filterParams.join(':')}`;\n  }\n\n  return {\n    src: resultSrc,\n    attrs,\n  };\n}\n","/**\n * Deep equality comparison for plain objects, arrays, and primitives.\n */\nexport function deepEqual(a: any, b: any): boolean {\n  if (a === b) {\n    return true;\n  }\n  if (a === null || a === undefined || b === null || b === undefined) {\n    return a === b;\n  }\n  if (typeof a !== typeof b) {\n    return false;\n  }\n  if (typeof a !== 'object') {\n    return false;\n  }\n  if (Array.isArray(a) !== Array.isArray(b)) {\n    return false;\n  }\n  if (Array.isArray(a)) {\n    if (a.length !== (b as any[]).length) {\n      return false;\n    }\n    return a.every((v: any, i: number) => deepEqual(v, (b as any[])[i]));\n  }\n  const aKeys = Object.keys(a);\n  const bKeys = Object.keys(b);\n  if (aKeys.length !== bKeys.length) {\n    return false;\n  }\n  return aKeys.every(k => Object.prototype.hasOwnProperty.call(b, k) && deepEqual(a[k], b[k]));\n}\n\nexport const SELF_CLOSING_TAGS = [\n  'area',\n  'base',\n  'br',\n  'col',\n  'embed',\n  'hr',\n  'img',\n  'input',\n  'link',\n  'meta',\n  'param',\n  'source',\n  'track',\n  'wbr',\n];\n\nexport function escapeHtml(unsafeText: string): string {\n  return unsafeText\n    .replace(/&/g, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;')\n    .replace(/\"/g, '&quot;')\n    .replace(/'/g, '&#039;');\n}\nexport function createKeyGenerator() {\n  const counters = new Map<string, number>();\n\n  return (prefix: string) => {\n    const count = (counters.get(prefix) || 0) + 1;\n\n    counters.set(prefix, count);\n\n    return `${prefix}-${count}`;\n  };\n}\n","export const resolveHeadingTag = (attrs: { level?: number }): string => {\n  const level\n    = typeof attrs?.level === 'number'\n      ? Math.min(6, Math.max(1, attrs.level))\n      : 1;\n\n  return `h${level}`;\n};\n","// THIS FILE IS AUTO-GENERATED. DO NOT EDIT.\nimport { resolveHeadingTag } from './dynamic-resolvers';\n/**\n * Render config for Tiptap nodes\n */\nexport const NODE_RENDER_MAP = {\n  paragraph: {\n    tag: 'p',\n    content: true,\n  },\n  doc: null,\n  text: null,\n  emoji: {\n    tag: 'img',\n    attrs: {\n      style: 'width: 1.25em; height: 1.25em; vertical-align: text-top;',\n      draggable: 'false',\n      loading: 'lazy',\n    },\n  },\n  blockquote: {\n    tag: 'blockquote',\n    content: true,\n  },\n  heading: {\n    resolve: resolveHeadingTag,\n  },\n  bullet_list: {\n    tag: 'ul',\n    content: true,\n  },\n  ordered_list: {\n    tag: 'ol',\n    attrs: {\n      order: 1,\n    },\n    content: true,\n  },\n  list_item: {\n    tag: 'li',\n    content: true,\n  },\n  code_block: {\n    tag: 'pre',\n    children: [\n      {\n        tag: 'code',\n        content: true,\n      },\n    ],\n  },\n  hard_break: {\n    tag: 'br',\n  },\n  horizontal_rule: {\n    tag: 'hr',\n  },\n  image: {\n    tag: 'img',\n  },\n  table: {\n    tag: 'table',\n    content: true,\n  },\n  tableRow: {\n    tag: 'tr',\n    content: true,\n  },\n  tableCell: {\n    tag: 'td',\n    attrs: {\n      colspan: 1,\n      rowspan: 1,\n    },\n    content: true,\n  },\n  tableHeader: {\n    tag: 'th',\n    attrs: {\n      colspan: 1,\n      rowspan: 1,\n    },\n    content: true,\n  },\n  blok: null,\n} as const;\n\n/**\n * Render config for Tiptap marks\n */\nexport const MARK_RENDER_MAP = {\n  link: {\n    tag: 'a',\n    attrs: {\n      rel: 'noopener noreferrer nofollow',\n      linktype: 'url',\n      custom: {},\n    },\n    content: true,\n  },\n  bold: {\n    tag: 'strong',\n    content: true,\n  },\n  italic: {\n    tag: 'em',\n    content: true,\n  },\n  strike: {\n    tag: 's',\n    content: true,\n  },\n  underline: {\n    tag: 'u',\n    content: true,\n  },\n  code: {\n    tag: 'code',\n    content: true,\n  },\n  superscript: {\n    tag: 'sup',\n    content: true,\n  },\n  subscript: {\n    tag: 'sub',\n    content: true,\n  },\n  highlight: {\n    tag: 'mark',\n    content: true,\n  },\n  textStyle: {\n    tag: 'span',\n    content: true,\n  },\n  anchor: {\n    tag: 'span',\n    content: true,\n  },\n  styled: {\n    tag: 'span',\n    content: true,\n  },\n} as const;\n","/**\n * Converts a style object to a CSS string.\n * @param style - The style object to convert.\n * @returns A CSS string representation of the style object.\n * @example\n * const styleObj = { color: 'red', fontSize: '16px' };\n * const cssString = styleToString(styleObj);\n * console.log(cssString); // Output: \"color: red; font-size: 16px\"\n */\nexport function styleToString(\n  style: Record<string, unknown>,\n) {\n  return Object.entries(style)\n    .filter(([, value]) => isValidStyleValue(value))\n    .map(\n      ([key, value]) =>\n        `${camelToKebab(key)}: ${value};`,\n    )\n    .join(' ');\n}\n\n/**\n * Converts a CSS string to a style object.\n * @param style - The CSS string to convert.\n * @returns A style object representation of the CSS string.\n * @example\n * const cssString = \"color: red; font-size: 16px\";\n * const styleObj = stringToStyle(cssString);\n * console.log(styleObj); // Output: { color: 'red', fontSize: '16px' }\n */\nexport function stringToStyle(style: string): Record<string, string> {\n  return style\n    .split(';')\n    .map(rule => rule.trim())\n    .filter(Boolean)\n    .reduce<Record<string, string>>((acc, rule) => {\n      const colonIdx = rule.indexOf(':');\n\n      // ignore invalid declarations like \"color\" or \": red\"\n      if (colonIdx === -1) {\n        return acc;\n      }\n\n      const key = rule.slice(0, colonIdx).trim();\n      const value = rule.slice(colonIdx + 1).trim();\n\n      if (!key || !value) {\n        return acc;\n      }\n\n      acc[kebabToCamel(key)] = value;\n      return acc;\n    }, {});\n}\n\nexport function kebabToCamel(str: string) {\n  return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n}\nexport function camelToKebab(str: string) {\n  return str.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`);\n}\nexport function isValidStyleValue(value: unknown) {\n  return value !== null && value !== undefined && value !== '';\n}\n","import { NODE_RENDER_MAP } from './render-map.generated';\nimport { isValidStyleValue, stringToStyle } from './style';\nimport type { SbRichTextElement } from './types';\n\ntype StyleMap = Partial<{\n  [K in SbRichTextElement]: Record<string, string>;\n}>;\nexport type AttrMap = Record<string, string>;\n\n/**\n * Maps Tiptap attribute names to CSS property names for specific element types.\n */\nconst STYLE_MAP: StyleMap = {\n  highlight: {\n    color: 'backgroundColor',\n  },\n  textStyle: {\n    color: 'color',\n  },\n  paragraph: {\n    textAlign: 'textAlign',\n  },\n  heading: {\n    textAlign: 'textAlign',\n  },\n  tableCell: {\n    backgroundColor: 'backgroundColor',\n    colwidth: 'width',\n  },\n  tableHeader: {\n    colwidth: 'width',\n  },\n};\n\n/**\n * Maps Tiptap attribute names to HTML attribute names.\n */\nconst DEFAULT_ATTR_MAP: AttrMap = {\n  fallbackImage: 'src',\n  body: 'data-body',\n  colspan: 'colSpan',\n  rowspan: 'rowSpan',\n  name: 'data-name',\n  emoji: 'data-emoji',\n  order: 'start',\n};\n\n/**\n * Attributes that should be excluded from the output.\n */\nexport const EXCLUDED_ATTRS = new Set(['level', 'linktype', 'uuid', 'anchor', 'meta_data', 'copyright', 'source']);\n\n/**\n * Attributes that should be excluded when they have their default value of 1.\n * These are HTML defaults and including them adds unnecessary markup.\n */\nconst DEFAULT_VALUE_ONE_ATTRS = new Set(['colspan', 'rowspan', 'order']);\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Resolves the href for Storyblok link types (story, email).\n * @returns The resolved href, or undefined if no special handling is needed.\n */\nfunction resolveStoryblokLinkHref(attrs: Record<string, unknown>): string | undefined {\n  const { linktype, href, anchor } = attrs;\n\n  if (linktype === 'story') {\n    const base = typeof href === 'string' ? href : '';\n    const hash = typeof anchor === 'string' && anchor ? `#${anchor}` : '';\n    return `${base}${hash}`;\n  }\n\n  if (linktype === 'email' && typeof href === 'string') {\n    const email = href.replace(/^mailto:/, '');\n    return `mailto:${email}`;\n  }\n\n  return undefined;\n}\n\n/**\n * Extracts static attributes and styles from the render map for a given element type.\n */\nfunction getStaticAttrsFromRenderMap(\n  type: SbRichTextElement,\n): { staticAttrs: Record<string, unknown>; staticStyle: Record<string, unknown> } {\n  const staticStyle: Record<string, unknown> = {};\n  let staticAttrs: Record<string, unknown> = {};\n\n  if (!(type in NODE_RENDER_MAP)) {\n    return { staticAttrs, staticStyle };\n  }\n\n  const renderMap = NODE_RENDER_MAP[type as keyof typeof NODE_RENDER_MAP];\n  if (!renderMap || !('attrs' in renderMap)) {\n    return { staticAttrs, staticStyle };\n  }\n\n  const renderAttrs = renderMap.attrs || {};\n  const rawStyle = 'style' in renderAttrs && typeof renderAttrs.style === 'string'\n    ? renderAttrs.style\n    : '';\n\n  const { style: _style, ...rest } = renderAttrs as Record<string, unknown>;\n  staticAttrs = rest;\n\n  if (rawStyle) {\n    Object.assign(staticStyle, stringToStyle(rawStyle));\n  }\n\n  return { staticAttrs, staticStyle };\n}\n\n/**\n * Converts an attribute value to a CSS value based on the style map.\n * Handles arrays (e.g., colwidth) and primitive values.\n */\nfunction convertToStyleValue(value: unknown): unknown | undefined {\n  if (Array.isArray(value)) {\n    return value[0] != null ? `${value[0]}px` : undefined;\n  }\n\n  if (typeof value === 'number' || typeof value === 'string') {\n    return value;\n  }\n\n  return String(value);\n}\n\n/**\n * Processes a single attribute and adds it to either the style or rest object.\n */\nfunction processAttribute(\n  key: string,\n  value: unknown,\n  type: SbRichTextElement,\n  styleMap: Record<string, string>,\n  attrMap: AttrMap,\n  style: Record<string, unknown>,\n  rest: Record<string, unknown>,\n): void {\n  if (!isValidStyleValue(value) || EXCLUDED_ATTRS.has(key)) {\n    return;\n  }\n\n  // Skip attributes that have their default HTML value of 1\n  if (DEFAULT_VALUE_ONE_ATTRS.has(key) && value === 1) {\n    return;\n  }\n\n  // Handle style-mapped attributes\n  if (key in styleMap) {\n    const cssProp = styleMap[key]!;\n    const cssValue = convertToStyleValue(value);\n    if (cssValue !== undefined && isValidStyleValue(cssValue)) {\n      style[cssProp] = cssValue;\n    }\n    return;\n  }\n\n  const attrName = attrMap[key] ?? key;\n\n  // Handle custom attributes for links (spread them as individual attributes)\n  if (attrName === 'custom' && type === 'link' && typeof value === 'object' && value !== null) {\n    for (const [customKey, customValue] of Object.entries(value)) {\n      rest[customKey] = String(customValue);\n    }\n    return;\n  }\n\n  // Handle other object values (stringify them)\n  if (typeof value === 'object' && value !== null) {\n    rest[attrName] = JSON.stringify(value);\n    return;\n  }\n\n  // Default: pass through as-is\n  rest[attrName] = value;\n}\n\n// ============================================================================\n// Main Export\n// ============================================================================\n\n/**\n * Process Tiptap attributes into HTML attributes and inline styles.\n * Applies internal style mappings and allows extending or overriding\n * default attribute mappings via `extendAttrMap`.\n *\n * @param type - {@link SbRichTextElement}\n * @param attrs - Attributes from the node/mark\n * @param extendAttrMap - {@link AttrMap} Additional attribute mappings (overrides defaults)\n * @returns Processed attributes with optional `style` object\n */\nexport function processAttrs(\n  type: SbRichTextElement,\n  attrs: Record<string, unknown> = {},\n  extendAttrMap: AttrMap = {},\n): Record<string, unknown> {\n  const { staticAttrs, staticStyle } = getStaticAttrsFromRenderMap(type);\n  const style: Record<string, unknown> = { ...staticStyle };\n  const rest: Record<string, unknown> = {};\n\n  const styleMap = STYLE_MAP[type] || {};\n  const attrMap = { ...DEFAULT_ATTR_MAP, ...extendAttrMap };\n  const mergedAttrs = { ...staticAttrs, ...attrs };\n\n  for (const [key, value] of Object.entries(mergedAttrs)) {\n    processAttribute(key, value, type, styleMap, attrMap, style, rest);\n  }\n\n  // Special handling for Storyblok links\n  if (type === 'link') {\n    const linkHref = resolveStoryblokLinkHref(attrs);\n    if (linkHref !== undefined) {\n      rest.href = linkHref;\n    }\n  }\n\n  return {\n    ...rest,\n    ...(Object.keys(style).length > 0 && { style }),\n  };\n}\n\n/**\n * Escapes special HTML characters in attribute values.\n */\nexport const escapeAttr = (value: unknown): string =>\n  String(value).replace(/[&\"'<>]/g, (char) => {\n    switch (char) {\n      case '&': return '&amp;';\n      case '\"': return '&quot;';\n      case '\\'': return '&#39;';\n      case '<': return '&lt;';\n      case '>': return '&gt;';\n      default: return char;\n    }\n  });\n","import type { SbRichTextMark, SbRichTextNode } from './types.generated';\nimport { deepEqual } from '../utils';\n\n// ============================================================================\n// Link Mark Helpers\n// ============================================================================\n\n/**\n * Gets the link mark from a text node, or null if not present.\n * @param node - The node to check\n * @returns The link mark if found, null otherwise\n */\nexport function getTextNodeLinkMark(node: SbRichTextNode): LinkMark | null {\n  if (node.type !== 'text' || !node.marks) {\n    return null;\n  }\n\n  for (const mark of node.marks) {\n    if (mark.type === 'link') {\n      return mark;\n    }\n  }\n  return null;\n}\nexport type LinkMark = SbRichTextMark & { type: 'link' };\n\n/**\n * Checks if two link marks have identical attributes.\n * Used for merging adjacent text nodes with the same link.\n * @param markA - First link mark\n * @param markB - Second link mark\n * @returns True if the marks have identical attributes\n */\nexport function areLinkMarksEqual(markA: LinkMark | null, markB: LinkMark | null): boolean {\n  if (!markA || !markB) {\n    return false;\n  }\n\n  return deepEqual(markA.attrs ?? {}, markB.attrs ?? {});\n}\n\n/**\n * Gets non-link marks from a text node.\n * Used when rendering text inside a merged link group.\n * @param node - The text node\n * @returns Array of marks excluding the link mark\n */\nexport function getInnerMarks(node: SbRichTextNode): SbRichTextMark[] {\n  if (node.type !== 'text' || !node.marks) {\n    return [];\n  }\n  return node.marks.filter(m => m.type !== 'link');\n}\n\n/**\n * Identifies groups of adjacent text nodes that share the same link mark.\n * Returns an array of groups where each group is either:\n * - A single non-text node or text node without link\n * - Multiple consecutive text nodes with identical link marks\n *\n * @param children - Array of child nodes to group\n * @returns Array of node groups for rendering\n */\nexport function groupLinkNodes(children: SbRichTextNode[]): Array<{\n  nodes: SbRichTextNode[];\n  linkMark: LinkMark | null;\n  _key: string;\n}> {\n  const groups: Array<{ nodes: SbRichTextNode[]; linkMark: LinkMark | null; _key: string }> = [];\n  let i = 0;\n  const len = children.length;\n\n  while (i < len) {\n    const node = children[i];\n    const linkMark = getTextNodeLinkMark(node);\n\n    if (linkMark) {\n      // Find end of link group (consecutive text nodes with same link)\n      const groupNodes: SbRichTextNode[] = [node];\n      let end = i + 1;\n\n      while (end < len && areLinkMarksEqual(linkMark, getTextNodeLinkMark(children[end]))) {\n        groupNodes.push(children[end]);\n        end++;\n      }\n\n      groups.push({ nodes: groupNodes, linkMark, _key: `group-link-${i}` });\n      i = end;\n    }\n    else {\n      groups.push({ nodes: [node], linkMark: null, _key: `group-node-${i}` });\n      i++;\n    }\n  }\n\n  return groups;\n}\n\n// ============================================================================\n// Table Helpers\n// ============================================================================\n\n/**\n * Checks if a table row contains only tableHeader cells.\n * Used to determine which rows belong in thead vs tbody.\n * @param row - The table row node to check\n * @returns True if all cells are tableHeader type\n */\nexport function isTableHeaderRow(row: SbRichTextNode): boolean {\n  const cells = row.content;\n  if (!cells?.length) {\n    return false;\n  }\n\n  for (const cell of cells) {\n    if (cell.type !== 'tableHeader') {\n      return false;\n    }\n  }\n  return true;\n}\n\n/**\n * Splits table rows into header rows and body rows.\n * Header rows are contiguous tableHeader rows at the start.\n * @param rows - Array of table row nodes\n * @returns Object with headerRows and bodyRows arrays\n */\nexport function splitTableRows(rows: SbRichTextNode[] | undefined): {\n  headerRows: SbRichTextNode[];\n  bodyRows: SbRichTextNode[];\n} {\n  if (!rows?.length) {\n    return { headerRows: [], bodyRows: [] };\n  }\n\n  // Find where header rows end (contiguous tableHeader rows at start)\n  let headerEnd = 0;\n  while (headerEnd < rows.length && isTableHeaderRow(rows[headerEnd])) {\n    headerEnd++;\n  }\n\n  return {\n    headerRows: rows.slice(0, headerEnd),\n    bodyRows: rows.slice(headerEnd),\n  };\n}\n","import { createKeyGenerator } from '../utils';\nimport type { SbRichTextInput } from './types';\nimport type { SbRichTextNode } from './types.generated';\n\n/**\n * Normalizes a Storyblok Richtext input into an array of nodes.\n * Supports single nodes, doc nodes, arrays, and nullable values.\n */\nexport function normalizeNodes(\n  input: SbRichTextInput,\n  includeKeys = false,\n): SbRichTextNode[] {\n  if (!input) {\n    return [];\n  }\n  if (Array.isArray(input)) {\n    return input;\n  }\n  const nodes = input.type === 'doc' ? input.content || [] : [input];\n\n  if (!includeKeys) {\n    return nodes;\n  }\n  const keyGen = createKeyGenerator();\n\n  return addKeys(nodes, keyGen);\n}\nfunction addKeys(\n  nodes: SbRichTextNode[],\n  generateKey: (prefix: string) => string,\n): SbRichTextNode[] {\n  return nodes.map(node => ({\n    ...node,\n    _key: generateKey(node.type),\n    marks: node.marks?.map(mark => ({\n      ...mark,\n      _key: generateKey(mark.type),\n    })),\n    // Only re-attach `content` when the node actually has it. The root `doc`\n    // node always carries `content`, while leaf and empty nodes legitimately\n    // omit it, so we must not force `content: undefined` onto them.\n    ...(node.content ? { content: addKeys(node.content, generateKey) } : {}),\n  }));\n}\n","import { MARK_RENDER_MAP, NODE_RENDER_MAP } from './render-map.generated';\nimport type { SbRichTextMark, SbRichTextNode } from './types.generated';\nimport { SELF_CLOSING_TAGS } from '../utils';\nimport { escapeAttr } from './attribute';\n/**\n * Resolves the HTML tag for a given Richtext node or mark.\n * @param node - The Richtext node or mark to resolve the tag for.\n * @returns The resolved HTML tag as a string, or null if no tag could be resolved.\n * @example\n * const node = { type: 'paragraph', attrs: {} };\n * const tag = resolveTag(node);\n * console.log(tag); // Output: \"p\"\n */\nexport function resolveTag(node: SbRichTextNode | SbRichTextMark): string | null {\n  const type = node.type;\n\n  const entry\n    = NODE_RENDER_MAP[type as keyof typeof NODE_RENDER_MAP]\n      ?? MARK_RENDER_MAP[type as keyof typeof MARK_RENDER_MAP];\n\n  if (!entry) {\n    return null;\n  }\n\n  if ('resolve' in entry && typeof entry.resolve === 'function') {\n    return entry.resolve(node.attrs as Parameters<typeof entry.resolve>[0]);\n  }\n\n  if ('tag' in entry && typeof entry.tag === 'string') {\n    return entry.tag;\n  }\n\n  return null;\n}\n\n/**\n * Checks if a given HTML tag is self-closing.\n * @param tag - The HTML tag to check.\n * @returns True if the tag is self-closing, false otherwise.\n * @example\n * console.log(isSelfClosing('img')); // Output: true\n * console.log(isSelfClosing('div')); // Output: false\n *\n */\nexport function isSelfClosing(tag: string): boolean {\n  return SELF_CLOSING_TAGS.includes(tag);\n}\n\n/**\n * Returns static child definitions for a given RichText node.\n *\n * @param node - The RichText node\n * @returns Static child render specs, or null if none exist\n *\n * @example\n * const children = getStaticChildren({ type: 'table', attrs: {} });\n * // [{ tag: 'tbody', content: true }]\n */\nexport function getStaticChildren(node: SbRichTextNode) {\n  const renderMap = NODE_RENDER_MAP[node.type as keyof typeof NODE_RENDER_MAP];\n  const staticChildren = renderMap && 'children' in renderMap ? renderMap.children : null;\n  return staticChildren;\n}\n\n/** Converts attribute record to HTML string: ` key=\"value\" key2=\"value2\"` */\nexport function attrsToHtmlString(attrs: Record<string, unknown>): string {\n  let result = '';\n\n  for (const key in attrs) {\n    const value = attrs[key];\n    if (value != null) {\n      result += ` ${key}=\"${escapeAttr(value)}\"`;\n    }\n  }\n\n  return result;\n}\n","import { escapeHtml } from './utils';\nimport { optimizeImage } from './images-optimization';\nimport { areLinkMarksEqual, attrsToHtmlString, getStaticChildren, getTextNodeLinkMark, isSelfClosing, isTableHeaderRow, normalizeNodes, processAttrs, resolveTag, styleToString } from './static';\nimport type { RenderSpec, SbRichTextElement, SbRichTextInput, SbRichTextMark, SbRichTextNode, SbRichTextRenderContext, SbRichTextTextNode } from './static';\n/**\n * Renders a Storyblok RichText JSON document to an HTML string.\n *\n * @param document - RichText JSON document, array of nodes, or nullish value\n * @param context - Renderer configuration with custom node/mark renderers\n * @returns Rendered HTML string\n *\n * @example\n * ```ts\n * const html = renderRichText({\n *   type: 'doc',\n *   content: [{ type: 'paragraph', content: [{ type: 'text', text: 'Hello' }] }]\n * });\n * // => '<p>Hello</p>'\n * ```\n */\nexport function renderRichText(\n  document: SbRichTextInput,\n  context?: SbRichTextRenderContext,\n): string {\n  const nodes = normalizeNodes(document);\n  return nodes?.length ? renderChildren(nodes, context) : '';\n}\ntype NodeRenderer = (props: SbRichTextNode & { children: string; context?: SbRichTextRenderContext }) => string;\ntype MarkRenderer = (props: SbRichTextMark & { children: string }) => string;\n\n/** Renders a single node to HTML. */\nfunction renderNode(node: SbRichTextNode, context?: SbRichTextRenderContext): string {\n  if (node.type === 'text') {\n    return renderTextNode(node, node.marks, context);\n  }\n  const content = node.content ? renderChildren(node.content, context) : '';\n  // Custom renderer takes full control\n  const customRenderer = context?.renderers?.[node.type] as NodeRenderer | undefined;\n  if (customRenderer) {\n    return customRenderer({ ...node, children: content, context });\n  }\n\n  if (node.type === 'blok') {\n    console.warn(\n      '\"blok\" nodes require a custom renderer in renderRichText.',\n    );\n    return '';\n  }\n\n  const tag = resolveTag(node);\n\n  // No tag (e.g., nested doc): render children directly\n  if (!tag) {\n    return content;\n  }\n\n  if (node.type === 'image' && context?.optimizeImage) {\n    return renderOptimizedImage(node, context);\n  }\n\n  const htmlAttrs = buildHtmlAttrs(node.type, node.attrs);\n\n  if (isSelfClosing(tag)) {\n    return `<${tag}${htmlAttrs}>`;\n  }\n\n  if (node.type === 'table') {\n    return `<${tag}${htmlAttrs}>${renderTableRows(node.content, context)}</${tag}>`;\n  }\n\n  const staticChildren = getStaticChildren(node);\n  if (staticChildren) {\n    const inner = renderStaticStructure(node.type, staticChildren, node.attrs, content);\n    return `<${tag}>${inner}</${tag}>`;\n  }\n\n  return `<${tag}${htmlAttrs}>${content}</${tag}>`;\n}\n\n/** Renders an image node with optimization applied. */\nfunction renderOptimizedImage(\n  node: SbRichTextNode,\n  context: SbRichTextRenderContext,\n): string {\n  const attrs = node.attrs as Record<string, unknown> | undefined;\n  const src = attrs?.src as string | undefined;\n\n  let finalAttrs: Record<string, unknown> | undefined = attrs;\n\n  if (src) {\n    const { src: optimizedSrc, attrs: extraAttrs } = optimizeImage(\n      src,\n      context.optimizeImage,\n    );\n\n    finalAttrs = {\n      ...attrs,\n      src: optimizedSrc,\n      ...extraAttrs,\n    };\n  }\n\n  const htmlAttrs = buildHtmlAttrs('image', finalAttrs);\n  return htmlAttrs ? `<img${htmlAttrs}>` : '<img>';\n}\n\n/**\n * Renders child nodes, merging adjacent text nodes that share the same link mark.\n * This produces cleaner HTML: `<a href=\"...\">text <b>bold</b> more</a>`\n * instead of: `<a>text</a><a><b>bold</b></a><a>more</a>`\n */\nfunction renderChildren(children: SbRichTextNode[], context?: SbRichTextRenderContext): string {\n  let result = '';\n  let i = 0;\n  const len = children.length;\n\n  while (i < len) {\n    const node = children[i];\n    const linkMark = getTextNodeLinkMark(node);\n\n    if (linkMark) {\n      // Find end of link group (consecutive text nodes with same link)\n      let end = i + 1;\n      while (end < len && areLinkMarksEqual(linkMark, getTextNodeLinkMark(children[end]))) {\n        end++;\n      }\n      result += renderLinkGroup(children, i, end, linkMark, context);\n      i = end;\n    }\n    else {\n      result += renderNode(node, context);\n      i++;\n    }\n  }\n\n  return result;\n}\n\n/** Renders a text node with its marks. */\nfunction renderTextNode(\n  node: SbRichTextTextNode,\n  marks: SbRichTextMark[] | undefined,\n  context?: SbRichTextRenderContext,\n): string {\n  let html = escapeHtml(node.text);\n\n  if (!marks?.length) {\n    return html;\n  }\n\n  for (const mark of marks) {\n    html = wrapWithMark(html, mark, context);\n  }\n\n  return html;\n}\n\n/** Wraps content with a single mark tag. */\nfunction wrapWithMark(\n  content: string,\n  mark: SbRichTextMark,\n  context?: SbRichTextRenderContext,\n): string {\n  // Custom mark renderer\n  const customRenderer = context?.renderers?.[mark.type] as MarkRenderer | undefined;\n  if (customRenderer) {\n    return customRenderer({\n      ...mark,\n      children: content,\n    });\n  }\n\n  const tag = resolveTag(mark);\n  if (!tag) {\n    return content;\n  }\n\n  const htmlAttrs = buildHtmlAttrs(mark.type, mark.attrs);\n  return `<${tag}${htmlAttrs}>${content}</${tag}>`;\n}\n\n/** Link Mark Merging */\n\n/** Renders consecutive text nodes (from start to end) under a single link tag. */\nfunction renderLinkGroup(\n  children: SbRichTextNode[],\n  start: number,\n  end: number,\n  linkMark: SbRichTextMark,\n  context?: SbRichTextRenderContext,\n): string {\n  let inner = '';\n  for (let i = start; i < end; i++) {\n    const node = children[i] as SbRichTextTextNode;\n    const innerMarks = node.marks?.filter(m => m.type !== 'link');\n    inner += renderTextNode(node, innerMarks, context);\n  }\n\n  // Custom link renderer\n  const customRenderer = context?.renderers?.[linkMark.type] as MarkRenderer | undefined;\n  if (customRenderer) {\n    return customRenderer({\n      ...linkMark,\n      children: inner,\n    });\n  }\n\n  const tag = resolveTag(linkMark);\n  if (!tag) {\n    return inner;\n  }\n\n  const htmlAttrs = buildHtmlAttrs(linkMark.type, linkMark.attrs);\n  return `<${tag}${htmlAttrs}>${inner}</${tag}>`;\n}\n\n/** Table Rendering */\n\n/** Renders table rows with thead/tbody grouping based on cell types. */\nfunction renderTableRows(\n  rows: SbRichTextNode[] | undefined,\n  context?: SbRichTextRenderContext,\n): string {\n  if (!rows?.length) {\n    return '';\n  }\n\n  // Find where header rows end (contiguous tableHeader rows at start)\n  let headerEnd = 0;\n  while (headerEnd < rows.length && isTableHeaderRow(rows[headerEnd])) {\n    headerEnd++;\n  }\n\n  let result = '';\n\n  if (headerEnd > 0) {\n    result += '<thead>';\n    for (let i = 0; i < headerEnd; i++) {\n      result += renderNode(rows[i], context);\n    }\n    result += '</thead>';\n  }\n\n  if (headerEnd < rows.length) {\n    result += '<tbody>';\n    for (let i = headerEnd; i < rows.length; i++) {\n      result += renderNode(rows[i], context);\n    }\n    result += '</tbody>';\n  }\n\n  return result;\n}\n\n// Static Children (e.g., pre > code)\n\n/** Renders nested static structure defined in render map. */\nfunction renderStaticStructure(\n  type: SbRichTextElement,\n  specs: readonly RenderSpec[],\n  parentAttrs: Record<string, unknown> | undefined,\n  content: string,\n): string {\n  let result = '';\n\n  for (const spec of specs) {\n    const { tag, children, attrs: specAttrs } = spec;\n    const mergedAttrs = { ...specAttrs, ...parentAttrs };\n    const htmlAttrs = buildHtmlAttrs(type, mergedAttrs);\n\n    if (isSelfClosing(tag)) {\n      result += `<${tag}${htmlAttrs}>`;\n    }\n    else {\n      const inner = children\n        ? renderStaticStructure(type, children, parentAttrs, content)\n        : content;\n      result += `<${tag}${htmlAttrs}>${inner}</${tag}>`;\n    }\n  }\n\n  return result;\n}\n\n/** Builds HTML attribute string from node/mark type and attrs. */\nexport function buildHtmlAttrs(type: SbRichTextElement, attrs: Record<string, unknown> | undefined): string {\n  const processed = processAttrs(type, attrs, {\n    colspan: 'colspan',\n    rowspan: 'rowspan',\n  });\n\n  const styleObj = processed.style as Record<string, unknown> | undefined;\n  const finalAttrs: Record<string, unknown> = { ...processed };\n\n  if (styleObj) {\n    finalAttrs.style = styleToString(styleObj);\n  }\n\n  return attrsToHtmlString(finalAttrs);\n}\n"],"mappings":"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"}