{"version":3,"file":"markdown-parser.mjs","names":[],"sources":["../src/images-optimization.ts","../src/utils/index.ts","../src/types/index.ts","../src/extensions/utils.ts","../src/extensions/nodes.ts","../src/extensions/marks.ts","../src/extensions/index.ts","../src/html-parser.ts","../src/markdown-parser.ts"],"sourcesContent":["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 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","export enum BlockTypes {\n  DOCUMENT = 'doc',\n  HEADING = 'heading',\n  PARAGRAPH = 'paragraph',\n  QUOTE = 'blockquote',\n  OL_LIST = 'ordered_list',\n  UL_LIST = 'bullet_list',\n  LIST_ITEM = 'list_item',\n  CODE_BLOCK = 'code_block',\n  HR = 'horizontal_rule',\n  BR = 'hard_break',\n  IMAGE = 'image',\n  EMOJI = 'emoji',\n  COMPONENT = 'blok',\n  TABLE = 'table',\n  TABLE_ROW = 'tableRow',\n  TABLE_CELL = 'tableCell',\n  TABLE_HEADER = 'tableHeader',\n}\n\nexport enum MarkTypes {\n  BOLD = 'bold',\n  STRONG = 'strong',\n  STRIKE = 'strike',\n  UNDERLINE = 'underline',\n  ITALIC = 'italic',\n  CODE = 'code',\n  LINK = 'link',\n  ANCHOR = 'anchor',\n  STYLED = 'styled',\n  SUPERSCRIPT = 'superscript',\n  SUBSCRIPT = 'subscript',\n  TEXT_STYLE = 'textStyle',\n  HIGHLIGHT = 'highlight',\n}\n\nexport enum TextTypes {\n  TEXT = 'text',\n}\n\nexport enum LinkTargets {\n  SELF = '_self',\n  BLANK = '_blank',\n}\n\nexport enum LinkTypes {\n  URL = 'url',\n  STORY = 'story',\n  ASSET = 'asset',\n  EMAIL = 'email',\n}\n\n/**\n * Represents text alignment attributes that can be applied to block-level elements.\n */\nexport interface TextAlignmentAttrs {\n  textAlign?: 'left' | 'center' | 'right' | 'justify';\n}\n\n/**\n * Represents common attributes that can be applied to block-level elements.\n */\nexport interface BlockAttributes extends TextAlignmentAttrs {\n  class?: string;\n  id?: string;\n  [key: string]: any;\n}\n\nexport interface StoryblokRichTextDocumentNode {\n  type: string;\n  content?: StoryblokRichTextDocumentNode[];\n  attrs?: BlockAttributes;\n  text?: string;\n  marks?: StoryblokRichTextDocumentNode[];\n}\n\nexport type StoryblokRichTextNodeTypes = BlockTypes | MarkTypes | TextTypes;\n\nexport interface StoryblokRichTextNode<T = string> {\n  type: StoryblokRichTextNodeTypes;\n  content: StoryblokRichTextNode<T>[];\n  children?: T;\n  attrs?: BlockAttributes;\n  text?: string;\n}\n\nexport interface LinkNode<T = string> extends StoryblokRichTextNode<T> {\n  type: MarkTypes.LINK | MarkTypes.ANCHOR;\n  linktype: LinkTypes;\n  attrs: BlockAttributes;\n}\n\nexport interface MarkNode<T = string> extends StoryblokRichTextNode<T> {\n  type: MarkTypes.BOLD |\n    MarkTypes.ITALIC |\n    MarkTypes.UNDERLINE |\n    MarkTypes.STRIKE |\n    MarkTypes.CODE |\n    MarkTypes.LINK |\n    MarkTypes.ANCHOR |\n    MarkTypes.STYLED |\n    MarkTypes.SUPERSCRIPT |\n    MarkTypes.SUBSCRIPT |\n    MarkTypes.TEXT_STYLE |\n    MarkTypes.HIGHLIGHT;\n  attrs?: BlockAttributes;\n}\n\nexport interface TextNode<T = string> extends StoryblokRichTextNode<T> {\n  type: TextTypes.TEXT;\n  text: string;\n  marks?: MarkNode<T>[];\n}\n\n/**\n * Represents the configuration options for optimizing images in rich text content.\n */\nexport interface StoryblokRichTextImageOptimizationOptions {\n  /**\n   * CSS class to be applied to the image.\n   */\n  class: string;\n\n  /**\n   * Width of the image in pixels.\n   */\n  width: number;\n\n  /**\n   * Height of the image in pixels.\n   */\n  height: number;\n\n  /**\n   * Loading strategy for the image. 'lazy' loads the image when it enters the viewport. 'eager' loads the image immediately.\n   */\n  loading: 'lazy' | 'eager';\n\n  /**\n   * Optional filters that can be applied to the image to adjust its appearance.\n   *\n   * @example\n   *\n   * ```typescript\n   * const filters: Partial<StoryblokRichTextImageOptimizationOptions['filters']> = {\n   *   blur: 5,\n   *   brightness: 150,\n   *   grayscale: true\n   * }\n   * ```\n   */\n  filters: Partial<{\n    blur: number;\n    brightness: number;\n    fill: 'transparent';\n    format: 'webp' | 'png' | 'jpg';\n    grayscale: boolean;\n    quality: number;\n    rotate: 0 | 90 | 180 | 270;\n  }>;\n\n  /**\n   * Defines a set of source set values that tell the browser different image sizes to load based on screen conditions.\n   * The entries can be just the width in pixels or a tuple of width and pixel density.\n   *\n   * @example\n   *\n   * ```typescript\n   * const srcset: (number | [number, number])[] = [\n   *   320,\n   *   [640, 2]\n   * ]\n   * ```\n   */\n  srcset: (number | [number, number])[];\n\n  /**\n   * A list of sizes that correspond to different viewport widths, instructing the browser on which srcset source to use.\n   *\n   * @example\n   *\n   * ```typescript\n   * const sizes: string[] = [\n   *   '(max-width: 320px) 280px',\n   *   '(max-width: 480px) 440px',\n   *   '800px'\n   * ]\n   * ```\n   */\n  sizes: string[];\n}\n\n/**\n * Represents the options for rendering rich text.\n */\nexport interface StoryblokRichTextOptions<T = string, S = (tag: string, attrs: BlockAttributes, children?: T) => T> {\n  /**\n   * Defines the function that will be used to render the final HTML string (vanilla) or Framework component (React, Vue).\n   *\n   * @example\n   *\n   * ```typescript\n   * const renderFn = (tag: string, attrs: Record<string, any>, text?: string) => {\n   *  return `<${tag} ${Object.keys(attrs).map(key => `${key}=\"${attrs[key]}\"`).join(' ')}>${text}</${tag}>`\n   * }\n   *\n   * const options: StoryblokRichTextOptions = {\n   *  renderFn\n   * }\n   * ```\n   */\n  renderFn?: S;\n\n  /**\n   * Defines the function that will be used to render HTML text.\n   *\n   * @example\n   *\n   * ```typescript\n   * import { h, createTextVNode } from 'vue'\n   *\n   * const options: StoryblokRichTextOptions = {\n   *  renderFn: h,\n   *  textFn: createTextVNode\n   * }\n   * ```\n   */\n  textFn?: (text: string, attrs?: BlockAttributes) => T;\n\n  /**\n   * Defines opt-out image optimization options.\n   *\n   * @example\n   *\n   * ```typescript\n   * const options: StoryblokRichTextOptions = {\n   *  optimizeImages: true\n   * }\n   * ```\n   *\n   * @example\n   *\n   * ```typescript\n   * const options: StoryblokRichTextOptions = {\n   *    optimizeImages: {\n   *    class: 'my-image',\n   *    width: 800,\n   *    height: 600,\n   *    loading: 'lazy',\n   * }\n   * ```\n   */\n  optimizeImages?: boolean | Partial<StoryblokRichTextImageOptimizationOptions>;\n  /**\n   * Defines whether to use the key attribute in the resolvers for framework use cases.\n   * @default false\n   * @example\n   *\n   * ```typescript\n   *\n   * const options: StoryblokRichTextOptions = {\n   *  renderFn: h,\n   *  keyedResolvers: true\n   * }\n   * ```\n   */\n  keyedResolvers?: boolean;\n  /**\n   * Custom tiptap extensions to override or add node/mark rendering.\n   * Extensions are merged with the built-in defaults, overriding by key.\n   */\n  tiptapExtensions?: Record<string, any>;\n}\n","import type { BlockAttributes } from '../types';\nimport { LinkTypes } from '../types';\nimport { cleanObject } from '../utils';\n\n/**\n * Processes block-level attributes, converting textAlign to inline style\n * and preserving class/id/existing style.\n */\nexport function processBlockAttrs(attrs: BlockAttributes = {}): BlockAttributes {\n  const { textAlign, class: className, id: idName, style: existingStyle, ...rest } = attrs;\n  const styles: string[] = [];\n\n  if (existingStyle) {\n    styles.push(existingStyle.endsWith(';') ? existingStyle : `${existingStyle};`);\n  }\n\n  if (textAlign) {\n    styles.push(`text-align: ${textAlign};`);\n  }\n\n  return cleanObject({\n    ...rest,\n    class: className,\n    id: idName,\n    ...(styles.length > 0 ? { style: styles.join(' ') } : {}),\n  });\n}\n\n/**\n * Resolves a Storyblok link's attributes into a final href and remaining attrs.\n */\nexport function resolveStoryblokLink(attrs: Record<string, any> = {}): { href: string; rest: Record<string, any> } {\n  const { linktype, href, anchor, uuid, custom, ...rest } = attrs;\n\n  let finalHref = href ?? '';\n  switch (linktype) {\n    case LinkTypes.ASSET:\n    case LinkTypes.URL:\n      break;\n    case LinkTypes.EMAIL:\n      if (finalHref && !finalHref.startsWith('mailto:')) {\n        finalHref = `mailto:${finalHref}`;\n      }\n      break;\n    case LinkTypes.STORY:\n      if (anchor) {\n        finalHref = `${finalHref}#${anchor}`;\n      }\n      break;\n    default:\n      break;\n  }\n\n  return { href: finalHref, rest: { ...rest, ...(custom || {}) } };\n}\n\n/**\n * Computes table cell attributes, converting colwidth/backgroundColor/textAlign to CSS styles.\n */\nexport function computeTableCellAttrs(attrs: Record<string, any> = {}): BlockAttributes {\n  const { colspan, rowspan, colwidth, backgroundColor, textAlign, ...rest } = attrs;\n  const styles: string[] = [];\n\n  if (colwidth) {\n    styles.push(`width: ${colwidth}px;`);\n  }\n\n  if (backgroundColor) {\n    styles.push(`background-color: ${backgroundColor};`);\n  }\n\n  if (textAlign) {\n    styles.push(`text-align: ${textAlign};`);\n  }\n\n  return cleanObject({\n    ...rest,\n    ...(colspan > 1 ? { colspan } : {}),\n    ...(rowspan > 1 ? { rowspan } : {}),\n    ...(styles.length > 0 ? { style: styles.join(' ') } : {}),\n  });\n}\n\n/**\n * List of supported HTML attributes by tag name, used by the Reporter mark.\n */\nexport const supportedAttributesByTagName: Record<string, string[]> = {\n  a: ['href', 'target', 'data-uuid', 'data-anchor', 'data-linktype'],\n  img: ['alt', 'src', 'title'],\n  span: ['class'],\n} as const;\n\n/**\n * Gets allowed style classes for an element, warning on invalid ones.\n */\nexport function getAllowedStylesForElement(element: HTMLElement, { allowedStyles }: { allowedStyles: string[] }): string[] {\n  const classString = element.getAttribute('class') || '';\n  const classes = classString.split(' ').filter(Boolean);\n  if (!classes.length) {\n    return [];\n  }\n\n  const invalidStyles = classes.filter(x => !allowedStyles.includes(x));\n  for (const invalidStyle of invalidStyles) {\n    console.warn(`[StoryblokRichText] - \\`class\\` \"${invalidStyle}\" on \\`<${element.tagName.toLowerCase()}>\\` can not be transformed to rich text.`);\n  }\n\n  return allowedStyles.filter(x => classes.includes(x));\n}\n","import { Node } from '@tiptap/core';\nimport { BulletList, ListItem, OrderedList } from '@tiptap/extension-list';\nimport { Details, DetailsContent, DetailsSummary } from '@tiptap/extension-details';\nimport { Table, TableCell, TableHeader, TableRow } from '@tiptap/extension-table';\nimport Blockquote from '@tiptap/extension-blockquote';\nimport CodeBlock from '@tiptap/extension-code-block';\nimport Document from '@tiptap/extension-document';\nimport Emoji from '@tiptap/extension-emoji';\nimport HardBreak from '@tiptap/extension-hard-break';\nimport Heading from '@tiptap/extension-heading';\nimport HorizontalRule from '@tiptap/extension-horizontal-rule';\nimport Image from '@tiptap/extension-image';\nimport Paragraph from '@tiptap/extension-paragraph';\nimport Text from '@tiptap/extension-text';\nimport { optimizeImage } from '../images-optimization';\nimport type { StoryblokRichTextImageOptimizationOptions } from '../types';\nimport { cleanObject } from '../utils';\nimport { computeTableCellAttrs, processBlockAttrs } from './utils';\n\n// Re-export unmodified extensions\nexport { Details, DetailsContent, DetailsSummary, Document, Text };\n\n// Blockquote, Paragraph, Heading need processBlockAttrs for textAlign support\nexport const StoryblokBlockquote = Blockquote.extend({\n  renderHTML({ HTMLAttributes }) {\n    return ['blockquote', processBlockAttrs(HTMLAttributes), 0];\n  },\n});\n\nexport const StoryblokParagraph = Paragraph.extend({\n  renderHTML({ HTMLAttributes }) {\n    return ['p', processBlockAttrs(HTMLAttributes), 0];\n  },\n});\n\nexport const StoryblokHeading = Heading.extend({\n  renderHTML({ node, HTMLAttributes }) {\n    const { level, ...rest } = HTMLAttributes;\n    return [`h${node.attrs.level}`, processBlockAttrs(rest), 0];\n  },\n});\n\nexport const StoryblokTableRow = TableRow.extend({\n  renderHTML({ HTMLAttributes }) {\n    return ['tr', processBlockAttrs(HTMLAttributes), 0];\n  },\n});\n\n// Storyblok uses snake_case names for some extensions\nexport const StoryblokBulletList = BulletList.extend({\n  name: 'bullet_list',\n  addOptions() {\n    return { ...this.parent!(), itemTypeName: 'list_item' };\n  },\n  renderHTML({ HTMLAttributes }) {\n    return ['ul', processBlockAttrs(HTMLAttributes), 0];\n  },\n});\n\nexport const StoryblokOrderedList = OrderedList.extend({\n  name: 'ordered_list',\n  addOptions() {\n    return { ...this.parent!(), itemTypeName: 'list_item' };\n  },\n  renderHTML({ HTMLAttributes }) {\n    return ['ol', processBlockAttrs(HTMLAttributes), 0];\n  },\n});\n\nexport const StoryblokListItem = ListItem.extend({\n  name: 'list_item',\n  addOptions() {\n    return { ...this.parent!(), bulletListTypeName: 'bullet_list', orderedListTypeName: 'ordered_list' };\n  },\n  renderHTML({ HTMLAttributes }) {\n    return ['li', processBlockAttrs(HTMLAttributes), 0];\n  },\n});\n\nexport const StoryblokCodeBlock = CodeBlock.extend({\n  name: 'code_block',\n  renderHTML({ node, HTMLAttributes }) {\n    const { language: _, ...rest } = HTMLAttributes;\n    const attrs = processBlockAttrs(rest);\n    const lang = node.attrs.language;\n    const codeAttrs = lang ? { class: `language-${lang}` } : {};\n    return ['pre', attrs, ['code', codeAttrs, 0]];\n  },\n});\nexport const StoryblokHardBreak = HardBreak.extend({ name: 'hard_break' });\nexport const StoryblokHorizontalRule = HorizontalRule.extend({ name: 'horizontal_rule' });\n\n// Table with custom renderHTML\n// Note: thead/tbody grouping is handled by the richtext renderer,\n// which inspects child rows to detect header vs body rows.\nexport const StoryblokTable = Table.extend({\n  renderHTML({ HTMLAttributes }) {\n    const attrs = processBlockAttrs(HTMLAttributes);\n    return ['table', attrs, 0];\n  },\n});\n\n// Table cell with custom style handling\nexport const StoryblokTableCell = TableCell.extend({\n  renderHTML({ HTMLAttributes }) {\n    return ['td', computeTableCellAttrs(HTMLAttributes), 0];\n  },\n});\n\n// Table header with custom style handling\nexport const StoryblokTableHeader = TableHeader.extend({\n  renderHTML({ HTMLAttributes }) {\n    return ['th', computeTableCellAttrs(HTMLAttributes), 0];\n  },\n});\n\n// Image with optimizeImages support\nexport const StoryblokImage = Image.extend<{ optimizeImages: boolean | Partial<StoryblokRichTextImageOptimizationOptions> }>({\n  addOptions() {\n    return { ...this.parent?.(), optimizeImages: false };\n  },\n  renderHTML({ HTMLAttributes }) {\n    const { src, alt, title, srcset, sizes } = HTMLAttributes;\n    let finalSrc = src;\n    let extraAttrs = {};\n\n    if (this.options.optimizeImages) {\n      const result = optimizeImage(src, this.options.optimizeImages);\n      finalSrc = result.src;\n      extraAttrs = result.attrs;\n    }\n\n    return ['img', cleanObject({ src: finalSrc, alt, title, srcset, sizes, ...extraAttrs })];\n  },\n});\n\n// Emoji with custom renderHTML\nexport const StoryblokEmoji = Emoji.extend({\n  renderHTML({ HTMLAttributes }) {\n    return ['span', {\n      'data-type': 'emoji',\n      'data-name': HTMLAttributes.name,\n      'data-emoji': HTMLAttributes.emoji,\n    }, ['img', {\n      src: HTMLAttributes.fallbackImage,\n      alt: HTMLAttributes.alt,\n      style: 'width: 1.25em; height: 1.25em; vertical-align: text-top',\n      draggable: 'false',\n      loading: 'lazy',\n    }]];\n  },\n});\n\n// Blok node (component placeholder for vanilla usage)\n// Configure `renderComponent` option to render blok components in framework SDKs.\n// Similar to PHP Tiptap extension's `renderer` callback:\n// https://github.com/storyblok/php-tiptap-extension/blob/main/src/Node/Blok.php\nexport const ComponentBlok = Node.create<{ renderComponent: ((blok: Record<string, unknown>, id?: string) => unknown) | null }>({\n  name: 'blok',\n  group: 'block',\n  atom: true,\n  addOptions() {\n    return {\n      renderComponent: null,\n    };\n  },\n  addAttributes() {\n    return {\n      id: { default: null },\n      body: { default: [] },\n    };\n  },\n  parseHTML() {\n    return [{ tag: 'div[data-blok]' }];\n  },\n  renderHTML({ HTMLAttributes }) {\n    console.warn('[StoryblokRichText] - BLOK resolver is not available for vanilla usage. Configure `renderComponent` option on the blok tiptapExtension.');\n    return ['span', cleanObject({\n      'data-blok': JSON.stringify(HTMLAttributes?.body?.[0] ?? null),\n      'data-blok-id': HTMLAttributes?.id,\n      'style': 'display: none',\n    })];\n  },\n});\n","import { Mark } from '@tiptap/core';\nimport Bold from '@tiptap/extension-bold';\nimport Code from '@tiptap/extension-code';\nimport Highlight from '@tiptap/extension-highlight';\nimport Italic from '@tiptap/extension-italic';\nimport LinkOriginal from '@tiptap/extension-link';\nimport Strike from '@tiptap/extension-strike';\nimport Subscript from '@tiptap/extension-subscript';\nimport Superscript from '@tiptap/extension-superscript';\nimport { TextStyleKit } from '@tiptap/extension-text-style';\nimport Underline from '@tiptap/extension-underline';\nimport { attrsToStyle, cleanObject } from '../utils';\nimport { getAllowedStylesForElement, resolveStoryblokLink, supportedAttributesByTagName } from './utils';\n\n// Unmodified mark extensions\nexport { Bold, Code, Highlight, Italic, Strike, Subscript, Superscript, TextStyleKit, Underline };\n\n// Link with Storyblok-specific attributes and renderHTML\nexport const StoryblokLink = LinkOriginal.extend({\n  addAttributes() {\n    return {\n      href: {\n        parseHTML: (element: HTMLElement) => element.getAttribute('href'),\n      },\n      uuid: {\n        default: null,\n        parseHTML: (element: HTMLElement) => element.getAttribute('data-uuid') || null,\n      },\n      anchor: {\n        default: null,\n        parseHTML: (element: HTMLElement) => element.getAttribute('data-anchor') || null,\n      },\n      target: {\n        parseHTML: (element: HTMLElement) => element.getAttribute('target') || null,\n      },\n      linktype: {\n        default: 'url',\n        parseHTML: (element: HTMLElement) => element.getAttribute('data-linktype') || 'url',\n      },\n    };\n  },\n  renderHTML({ HTMLAttributes }) {\n    const { href, rest } = resolveStoryblokLink(HTMLAttributes);\n    return ['a', cleanObject({ ...(href ? { href } : {}), ...rest }), 0];\n  },\n});\n\n// Link with custom attributes support\nexport const StoryblokLinkWithCustomAttributes = StoryblokLink.extend({\n  addAttributes() {\n    return {\n      ...this.parent?.(),\n      custom: {\n        default: null,\n        parseHTML: (element: HTMLElement) => {\n          const defaultLinkAttributes = supportedAttributesByTagName.a;\n          const customAttributeNames = element.getAttributeNames().filter(n => !defaultLinkAttributes.includes(n));\n          const customAttributes: Record<string, string | null> = {};\n          for (const attributeName of customAttributeNames) {\n            customAttributes[attributeName] = element.getAttribute(attributeName);\n          }\n          return Object.keys(customAttributes).length ? customAttributes : null;\n        },\n      },\n    };\n  },\n});\n\n// Anchor mark (renders as span with id)\nexport const StoryblokAnchor = Mark.create({\n  name: 'anchor',\n  addAttributes() {\n    return {\n      id: { default: null },\n    };\n  },\n  parseHTML() {\n    return [{ tag: 'span[id]' }];\n  },\n  renderHTML({ HTMLAttributes }) {\n    return ['span', { id: HTMLAttributes.id }, 0];\n  },\n});\n\nexport interface StyledOptions {\n  allowedStyles?: string[];\n}\n\n// Styled mark with whitelisted CSS classes\nexport const StoryblokStyled = Mark.create<StyledOptions>({\n  name: 'styled',\n  addAttributes() {\n    return {\n      class: {\n        parseHTML: (element: HTMLElement) => {\n          const styles = getAllowedStylesForElement(element, { allowedStyles: this.options.allowedStyles || [] });\n          return styles.length ? styles.join(' ') : null;\n        },\n      },\n    };\n  },\n  parseHTML() {\n    return [\n      {\n        tag: 'span',\n        consuming: false,\n        getAttrs: (element: HTMLElement) => {\n          const styles = getAllowedStylesForElement(element, { allowedStyles: this.options.allowedStyles || [] });\n          return styles.length ? null : false;\n        },\n      },\n    ];\n  },\n  renderHTML({ HTMLAttributes }) {\n    const { class: className, ...rest } = HTMLAttributes;\n    return ['span', cleanObject({ class: className, style: attrsToStyle(rest) || undefined }), 0];\n  },\n});\n\n// TextStyle mark\nexport const StoryblokTextStyle = Mark.create({\n  name: 'textStyle',\n  addAttributes() {\n    return {\n      class: { default: null },\n      id: { default: null },\n      color: { default: null },\n    };\n  },\n  parseHTML() {\n    return [{\n      tag: 'span',\n      consuming: false,\n      getAttrs: (element: HTMLElement) => {\n        // Only match spans with inline style containing color\n        const style = element.getAttribute('style');\n        if (style && /color/i.test(style)) {\n          return null;\n        }\n        return false;\n      },\n    }];\n  },\n  renderHTML({ HTMLAttributes }) {\n    const { class: className, id: idName, ...styleAttrs } = HTMLAttributes;\n    return ['span', cleanObject({\n      class: className,\n      id: idName,\n      style: attrsToStyle(styleAttrs) || undefined,\n    }), 0];\n  },\n});\n\n// Reporter mark: parse-only diagnostic, no renderHTML needed\nexport const Reporter = Mark.create({\n  name: 'reporter',\n  priority: 0,\n  addOptions() {\n    return {\n      allowCustomAttributes: false,\n    };\n  },\n  parseHTML() {\n    return [\n      {\n        tag: '*',\n        consuming: false,\n        getAttrs: (element: HTMLElement) => {\n          const tagName = element.tagName.toLowerCase();\n          if (tagName === 'a' && this.options.allowCustomAttributes) {\n            return false;\n          }\n\n          const unsupportedAttributes = element.getAttributeNames().filter((attr) => {\n            const supportedAttrs = tagName in supportedAttributesByTagName ? supportedAttributesByTagName[tagName] : [];\n            return !supportedAttrs.includes(attr);\n          });\n          for (const attr of unsupportedAttributes) {\n            console.warn(`[StoryblokRichText] - \\`${attr}\\` \"${element.getAttribute(attr)}\" on \\`<${tagName}>\\` can not be transformed to rich text.`);\n          }\n\n          return false;\n        },\n      },\n    ];\n  },\n});\n","import type { Extension, Mark, Node } from '@tiptap/core';\nimport type { StoryblokRichTextImageOptimizationOptions } from '../types';\nimport {\n  ComponentBlok,\n  Details,\n  DetailsContent,\n  DetailsSummary,\n  Document,\n  StoryblokBlockquote,\n  StoryblokBulletList,\n  StoryblokCodeBlock,\n  StoryblokEmoji,\n  StoryblokHardBreak,\n  StoryblokHeading,\n  StoryblokHorizontalRule,\n  StoryblokImage,\n  StoryblokListItem,\n  StoryblokOrderedList,\n  StoryblokParagraph,\n  StoryblokTable,\n  StoryblokTableCell,\n  StoryblokTableHeader,\n  StoryblokTableRow,\n  Text,\n} from './nodes';\nimport {\n  Bold,\n  Code,\n  Highlight,\n  Italic,\n  Reporter,\n  StoryblokAnchor,\n  StoryblokLink,\n  StoryblokLinkWithCustomAttributes,\n  StoryblokStyled,\n  StoryblokTextStyle,\n  Strike,\n  Subscript,\n  Superscript,\n  Underline,\n} from './marks';\n\nexport interface StyleOption {\n  name: string;\n  value: string;\n}\n\nexport interface HTMLParserOptions {\n  allowCustomAttributes?: boolean;\n  preserveWhitespace?: boolean | 'full';\n  tiptapExtensions?: Partial<typeof defaultExtensions & Record<string, Extension | Mark | Node>>;\n  styleOptions?: StyleOption[];\n}\n\nexport interface StoryblokExtensionOptions {\n  optimizeImages?: boolean | Partial<StoryblokRichTextImageOptimizationOptions>;\n  allowCustomAttributes?: boolean;\n  styleOptions?: StyleOption[];\n}\n\nconst defaultExtensions = {\n  document: Document,\n  text: Text,\n  paragraph: StoryblokParagraph,\n  blockquote: StoryblokBlockquote,\n  heading: StoryblokHeading,\n  bulletList: StoryblokBulletList,\n  orderedList: StoryblokOrderedList,\n  listItem: StoryblokListItem,\n  codeBlock: StoryblokCodeBlock,\n  hardBreak: StoryblokHardBreak,\n  horizontalRule: StoryblokHorizontalRule,\n  image: StoryblokImage,\n  emoji: StoryblokEmoji,\n  table: StoryblokTable,\n  tableRow: StoryblokTableRow,\n  tableCell: StoryblokTableCell,\n  tableHeader: StoryblokTableHeader,\n  blok: ComponentBlok,\n  details: Details,\n  detailsContent: DetailsContent,\n  detailsSummary: DetailsSummary,\n  bold: Bold,\n  italic: Italic,\n  strike: Strike,\n  underline: Underline,\n  code: Code,\n  superscript: Superscript,\n  subscript: Subscript,\n  highlight: Highlight,\n  textStyle: StoryblokTextStyle,\n  link: StoryblokLink as typeof StoryblokLink,\n  anchor: StoryblokAnchor,\n  styled: StoryblokStyled,\n  reporter: Reporter,\n};\n\nexport { defaultExtensions };\n\nexport function getStoryblokExtensions(options: StoryblokExtensionOptions = {}) {\n  const Link = options.allowCustomAttributes ? StoryblokLinkWithCustomAttributes : StoryblokLink;\n\n  return {\n    ...defaultExtensions,\n    image: StoryblokImage.configure({ optimizeImages: options.optimizeImages || false }),\n    link: Link,\n    styled: StoryblokStyled.configure({ allowedStyles: options.styleOptions?.map(o => o.value) }),\n    reporter: Reporter.configure({ allowCustomAttributes: options.allowCustomAttributes }),\n  };\n}\n\nexport * from './marks';\nexport * from './nodes';\nexport { computeTableCellAttrs, processBlockAttrs, resolveStoryblokLink } from './utils';\n","import { generateJSON } from '@tiptap/html';\nimport type { StoryblokRichTextDocumentNode } from './types';\nimport { getStoryblokExtensions } from './extensions';\nimport type { HTMLParserOptions } from './extensions';\n\nexport type { HTMLParserOptions, StyleOption } from './extensions';\nexport type { StyledOptions } from './extensions/marks';\n\nexport function htmlToStoryblokRichtext(\n  html: string,\n  options: HTMLParserOptions = {},\n) {\n  const { preserveWhitespace, tiptapExtensions, ...extensionOptions } = options;\n  const allExtensions = getStoryblokExtensions(extensionOptions);\n\n  const finalExtensions = tiptapExtensions\n    ? { ...allExtensions, ...tiptapExtensions }\n    : allExtensions;\n\n  return generateJSON(html, Object.values(finalExtensions), {\n    preserveWhitespace: preserveWhitespace || false,\n  }) as StoryblokRichTextDocumentNode;\n}\n","import MarkdownIt from 'markdown-it';\nimport { type HTMLParserOptions, htmlToStoryblokRichtext } from './html-parser';\n\nexport interface MarkdownParserOptions {\n  tiptapExtensions?: HTMLParserOptions['tiptapExtensions'];\n}\n\nexport function markdownToStoryblokRichtext(\n  md: string,\n  options: MarkdownParserOptions = {},\n) {\n  const html = new MarkdownIt({ html: false, linkify: true, typographer: true, breaks: true }).render(md);\n  return htmlToStoryblokRichtext(html, options);\n}\n"],"mappings":"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"}