{"version":3,"file":"static.cjs","names":[],"sources":["../src/static/dynamic-resolvers.ts","../src/static/render-map.generated.ts","../src/static/style.ts","../src/static/attribute.ts","../src/utils/index.ts","../src/static/node-helpers.ts","../src/images-optimization.ts","../src/static/util.ts","../src/static/render-richtext.ts"],"sourcesContent":["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  */\n  export const NODE_RENDER_MAP = {\n  paragraph: {\n  \"tag\": \"p\",\n  \"content\": true\n},\n  doc: null,\n  text: null,\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  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  table: {\n  \"tag\": \"table\",\n  \"content\": true\n},\n  tableRow: {\n  \"tag\": \"tr\",\n  \"content\": true\n},\n  tableCell: {\n  \"tag\": \"td\",\n  \"content\": true\n},\n  tableHeader: {\n  \"tag\": \"th\",\n  \"content\": true\n},\n  blok: {\n  \"tag\": \"span\",\n  \"attrs\": {\n    \"style\": \"display: none;\"\n  }\n},\n  details: {\n  \"tag\": \"details\",\n  \"content\": true\n},\n  detailsContent: {\n  \"tag\": \"div\",\n  \"attrs\": {\n    \"data-type\": \"detailsContent\"\n  },\n  \"content\": true\n},\n  detailsSummary: {\n  \"tag\": \"summary\",\n  \"content\": true\n},\n} as const;\n\n/**\n  * Render config for Tiptap marks\n  */\n  export const MARK_RENDER_MAP = {\n  link: {\n  \"tag\": \"a\",\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  reporter: null,\n} as const;\n\n","import type { AttrValue } from './types';\n\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, AttrValue>,\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\nfunction kebabToCamel(str: string) {\n  return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n}\nfunction 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 { AttrValue, 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};\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// 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, AttrValue> } {\n  const staticStyle: Record<string, AttrValue> = {};\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): AttrValue | 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, AttrValue>,\n  rest: Record<string, unknown>,\n): void {\n  if (!isValidStyleValue(value) || EXCLUDED_ATTRS.has(key)) {\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, AttrValue> = { ...staticStyle };\n  const rest: Record<string, unknown> = {};\n\n  const styleMap = STYLE_MAP[type] || {};\n  const attrMap = { ...DEFAULT_ATTR_MAP, ...extendAttrMap };\n  const mergedAttrs = { ...attrs, ...staticAttrs };\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 { BlockAttributes, MarkNode, StoryblokRichTextNode, TextNode } from '../types';\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\n/** Checks if two marks are equal by comparing their type and attrs. */\nexport function markEquals<T>(a: MarkNode<T>, b: MarkNode<T>): boolean {\n  return a.type === b.type && deepEqual(a.attrs, b.attrs);\n}\n\n/** Type guard: checks if a node is a text node with at least one mark. */\nexport function isMarkedTextNode<T>(node: StoryblokRichTextNode<T>): node is TextNode<T> {\n  return node.type === 'text' && !!(node as TextNode<T>).marks?.length;\n}\n\n/** Returns marks unique to a node (not in the shared set), or undefined if all marks are shared. */\nexport function getUniqueMarks<T>(marks: MarkNode<T>[], shared: MarkNode<T>[]): MarkNode<T>[] | undefined {\n  const unique = marks.filter(m => !shared.some(s => markEquals(s, m)));\n  return unique.length ? unique : undefined;\n}\n\nexport interface MarkedTextGroup<T> {\n  group: TextNode<T>[];\n  shared: MarkNode<T>[];\n  endIndex: number;\n}\n\n/**\n * Starting at `fromIndex`, collects adjacent marked text nodes that share at least one common mark.\n * Returns null if the node at `fromIndex` is not a marked text node.\n */\nexport function collectMarkedTextGroup<T>(\n  children: StoryblokRichTextNode<T>[],\n  fromIndex: number,\n): MarkedTextGroup<T> | null {\n  const child = children[fromIndex];\n  if (!isMarkedTextNode(child)) {\n    return null;\n  }\n\n  const group: TextNode<T>[] = [child];\n  let shared: MarkNode<T>[] = child.marks!;\n  let j = fromIndex + 1;\n  while (j < children.length) {\n    const next = children[j];\n    if (!isMarkedTextNode(next)) {\n      break;\n    }\n    const nextShared = shared.filter(m =>\n      next.marks!.some(n => markEquals(m, n)),\n    );\n    if (nextShared.length === 0) {\n      break;\n    }\n    shared = nextShared;\n    group.push(next);\n    j++;\n  }\n\n  return { group, shared, endIndex: j };\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 const BLOCK_LEVEL_TAGS = [\n  'address',\n  'article',\n  'aside',\n  'blockquote',\n  'canvas',\n  'dd',\n  'div',\n  'dl',\n  'dt',\n  'fieldset',\n  'figcaption',\n  'figure',\n  'footer',\n  'form',\n  'h1',\n  'h2',\n  'h3',\n  'h4',\n  'h5',\n  'h6',\n  'header',\n  'hgroup',\n  'hr',\n  'li',\n  'main',\n  'nav',\n  'noscript',\n  'ol',\n  'output',\n  'p',\n  'pre',\n  'section',\n  'table',\n  'tfoot',\n  'ul',\n  'video',\n];\n\n/**\n * Converts an object of attributes to a string.\n *\n * @param {Record<string, string>} [attrs]\n *\n * @returns {string} The string representation of the attributes.\n *\n * @example\n *\n * ```typescript\n * const attrs = {\n *  class: 'text-red',\n *  style: 'color: red',\n * }\n *\n * const attrsString = attrsToString(attrs)\n *\n * console.log(attrsString) // 'class=\"text-red\" style=\"color: red\"'\n *\n * ```\n *\n */\nexport const attrsToString = (attrs: BlockAttributes = {}) => {\n  const { custom, ...attrsWithoutCustom } = attrs;\n  const normalizedAttrs = { ...attrsWithoutCustom, ...custom };\n  return Object.keys(normalizedAttrs)\n    .filter(key => normalizedAttrs[key] != null)\n    .map(key => `${key}=\"${String(normalizedAttrs[key]).replace(/&/g, '&amp;').replace(/\"/g, '&quot;')}\"`)\n    .join(' ');\n};\n\n/**\n * Converts an object of attributes to a CSS style string.\n *\n * @param {Record<string, string>} [attrs]\n *\n * @returns {string} The string representation of the CSS styles.\n *\n * @example\n *\n * ```typescript\n * const attrs = {\n *  color: 'red',\n *  fontSize: '16px',\n * }\n *\n * const styleString = attrsToStyle(attrs)\n *\n * console.log(styleString) // 'color: red; font-size: 16px'\n * ```\n */\nexport const attrsToStyle = (attrs: Record<string, string> = {}) => Object.keys(attrs)\n  .map(key => `${key}: ${attrs[key]}`)\n  .join('; ');\n\n/**\n * Escapes HTML entities in a string.\n *\n * @param {string} unsafeText\n * @return {*}  {string}\n *\n * @example\n *\n * ```typescript\n * const unsafeText = '<script>alert(\"Hello\")</script>'\n *\n * const safeText = escapeHtml(unsafeText)\n *\n * console.log(safeText) // '&lt;script&gt;alert(\"Hello\")&lt;/script&gt;'\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}\n\n/**\n * Removes undefined values from an object.\n *\n * @param {Record<string, any>} obj\n * @return {*}  {Record<string, any>}\n *\n * @example\n *\n * ```typescript\n * const obj = {\n * name: 'John',\n * age: undefined,\n * }\n *\n * const cleanedObj = cleanObject(obj)\n *\n * console.log(cleanedObj) // { name: 'John' }\n * ```\n *\n */\nexport const cleanObject = (obj: Record<string, any>) => {\n  return Object.fromEntries(Object.entries(obj).filter(([_, v]) => v != null));\n};\n","import type { PMMark } from './types.generated';\nimport type { SbRichTextDoc } from './types';\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: SbRichTextDoc): 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 = PMMark & { 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: SbRichTextDoc): PMMark[] {\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: SbRichTextDoc[]): Array<{\n  nodes: SbRichTextDoc[];\n  linkMark: LinkMark | null;\n}> {\n  const groups: Array<{ nodes: SbRichTextDoc[]; linkMark: LinkMark | null }> = [];\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: SbRichTextDoc[] = [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 });\n      i = end;\n    }\n    else {\n      groups.push({ nodes: [node], linkMark: null });\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: SbRichTextDoc): 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: SbRichTextDoc[] | undefined): {\n  headerRows: SbRichTextDoc[];\n  bodyRows: SbRichTextDoc[];\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 type { StoryblokRichTextImageOptimizationOptions } from './types';\n\nexport function optimizeImage(src: string, options?: boolean | Partial<StoryblokRichTextImageOptimizationOptions>): { src: string; attrs: Record<string, any> } {\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","import { MARK_RENDER_MAP, NODE_RENDER_MAP } from './render-map.generated';\nimport type { PMMark, PMNode } from './types.generated';\nimport { SELF_CLOSING_TAGS } from '../utils';\nimport type { HtmlTag, SbRichTextComponents, SbRichTextElement } from './types';\n\n/**\n * Resolves a component from the provided components map based on the type.\n * @param type - The type of the component to resolve.\n * @param components - The components map to search in.\n * @returns The resolved component or undefined if not found.\n * @example\n * const components = {\n *   'heading': MyCustomHeading,\n * };\n * const resolvedComponent = resolveComponent('heading', components);\n * console.log(resolvedComponent); // Output: MyCustomHeading\n */\nexport function resolveComponent<\n  K extends SbRichTextElement,\n  TComponent,\n>(\n  type: K,\n  components?: SbRichTextComponents<TComponent>,\n): SbRichTextComponents<TComponent>[K] | undefined {\n  return components?.[type];\n}\n\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: PMNode | PMMark): HtmlTag | 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]) as HtmlTag;\n  }\n\n  if ('tag' in entry && typeof entry.tag === 'string') {\n    return entry.tag as HtmlTag;\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: HtmlTag | 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: PMNode) {\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","import { escapeHtml } from '../utils';\nimport { optimizeImage } from '../images-optimization';\nimport { escapeAttr, processAttrs } from './attribute';\nimport { areLinkMarksEqual, getTextNodeLinkMark, isTableHeaderRow } from './node-helpers';\nimport { styleToString } from './style';\nimport type { AttrValue, RenderSpec, SbRichTextDoc, SbRichTextElement, SbRichTextOptions } from './types';\nimport type { PMMark, PMNode } from './types.generated';\nimport { getStaticChildren, isSelfClosing, resolveTag } from './util';\n\ntype TextNode = PMNode & { type: 'text' };\n\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 options - 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: SbRichTextDoc | SbRichTextDoc[] | null | undefined,\n  options?: SbRichTextOptions,\n): string {\n  if (!document) {\n    return '';\n  }\n\n  if (Array.isArray(document)) {\n    return renderChildren(document, options);\n  }\n\n  const nodes = document.type === 'doc' ? document.content : [document];\n  return nodes?.length ? renderChildren(nodes, options) : '';\n}\n\n/** Renders a single node to HTML. */\nfunction renderNode(node: SbRichTextDoc, options?: SbRichTextOptions): string {\n  if (node.type === 'text') {\n    return renderTextNode(node as TextNode, node.marks, options);\n  }\n\n  // Custom renderer takes full control\n  const customRenderer = options?.renderers?.[node.type as keyof typeof options.renderers];\n  if (customRenderer) {\n    return (customRenderer as (props: typeof node) => string)(node);\n  }\n\n  if (node.type === 'blok') {\n    console.warn('Rendering of \"blok\" nodes is not supported in richTextRenderer.');\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 node.content ? renderChildren(node.content, options) : '';\n  }\n\n  if (node.type === 'image' && options?.optimizeImages) {\n    return renderOptimizedImage(node, options);\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, options)}</${tag}>`;\n  }\n\n  const content = node.content ? renderChildren(node.content, options) : '';\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: SbRichTextDoc,\n  options: SbRichTextOptions,\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      options.optimizeImages,\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: SbRichTextDoc[], options?: SbRichTextOptions): 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, options);\n      i = end;\n    }\n    else {\n      result += renderNode(node, options);\n      i++;\n    }\n  }\n\n  return result;\n}\n\n/** Renders a text node with its marks. */\nfunction renderTextNode(\n  node: TextNode,\n  marks: PMMark[] | undefined,\n  options?: SbRichTextOptions,\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, options);\n  }\n\n  return html;\n}\n\n/** Wraps content with a single mark tag. */\nfunction wrapWithMark(\n  content: string,\n  mark: PMMark,\n  options?: SbRichTextOptions,\n): string {\n  // Custom mark renderer\n  const customRenderer = options?.renderers?.[mark.type as keyof typeof options.renderers];\n  if (customRenderer) {\n    return (customRenderer as (props: typeof mark & { children: string }) => string)({\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: SbRichTextDoc[],\n  start: number,\n  end: number,\n  linkMark: PMMark,\n  options?: SbRichTextOptions,\n): string {\n  let inner = '';\n  for (let i = start; i < end; i++) {\n    const node = children[i] as TextNode;\n    const innerMarks = node.marks?.filter(m => m.type !== 'link');\n    inner += renderTextNode(node, innerMarks, options);\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: SbRichTextDoc[] | undefined,\n  options?: SbRichTextOptions,\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], options);\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], options);\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. */\nfunction 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, AttrValue> | 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\n/** Converts attribute record to HTML string: ` key=\"value\" key2=\"value2\"` */\nfunction 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"],"mappings":"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"}