{"version":3,"file":"storybook.es.mjs","names":[],"sources":["../src/storybook/index.ts"],"sourcesContent":["/**\n * Storybook template helpers for authoring bQuery component stories.\n *\n * `storyHtml` mirrors bQuery's string-based `html` tag while adding support for\n * Storybook-friendly boolean attribute shorthand (`?disabled=${true}`).\n *\n * @module bquery/storybook\n */\n\nimport { sanitizeHtml } from '../security/sanitize';\n\ntype StoryValue = string | number | boolean | null | undefined | StoryValue[] | (() => StoryValue);\n\n/**\n * Marks template interpolation boundaries while inferring sanitizer allowlists.\n * Uses the null character because authored HTML/template strings should not\n * contain it, making it a safe internal sentinel during parsing.\n */\nconst INTERPOLATION_BOUNDARY_MARKER = '\\u0000';\n\nconst isWhitespace = (value: string): boolean => {\n  return value === ' ' || value === '\\t' || value === '\\n' || value === '\\r' || value === '\\f';\n};\n\n/**\n * Detects interpolation boundaries embedded into joined template string fragments.\n */\nconst isInterpolationBoundaryMarker = (value: string): boolean =>\n  value === INTERPOLATION_BOUNDARY_MARKER;\n\nconst isAttributeSeparator = (value: string): boolean => {\n  return isWhitespace(value) || isInterpolationBoundaryMarker(value);\n};\n\nconst isAsciiLetter = (value: string): boolean => {\n  const code = value.charCodeAt(0);\n\n  return (code >= 65 && code <= 90) || (code >= 97 && code <= 122);\n};\n\nconst isAttributeNameStart = (value: string): boolean => isAsciiLetter(value);\n\nconst isAttributeNameChar = (value: string): boolean => {\n  const code = value.charCodeAt(0);\n\n  return (\n    isAsciiLetter(value) ||\n    (code >= 48 && code <= 57) ||\n    value === ':' ||\n    value === '.' ||\n    value === '_' ||\n    value === '-'\n  );\n};\n\nconst isQuoteChar = (value: string): boolean => value === '\"' || value === \"'\";\n\nconst isTagNameChar = (value: string): boolean => {\n  const code = value.charCodeAt(0);\n\n  return (\n    isAsciiLetter(value) ||\n    (code >= 48 && code <= 57) ||\n    value === '.' ||\n    value === '_' ||\n    value === '-'\n  );\n};\n\nconst hasLineBreak = (value: string): boolean => {\n  for (let index = 0; index < value.length; index += 1) {\n    if (value[index] === '\\n' || value[index] === '\\r') {\n      return true;\n    }\n  }\n\n  return false;\n};\n\nconst getTagNameEnd = (fragment: string): number => {\n  let index = 0;\n\n  while (\n    index < fragment.length &&\n    !isAttributeSeparator(fragment[index]) &&\n    fragment[index] !== '/' &&\n    fragment[index] !== '>'\n  ) {\n    index += 1;\n  }\n\n  return index;\n};\n\nconst isCustomElementTagName = (tagName: string): boolean => {\n  if (!tagName.includes('-') || !isAsciiLetter(tagName[0])) {\n    return false;\n  }\n\n  const last = tagName[tagName.length - 1];\n  const code = last.charCodeAt(0);\n\n  return isAsciiLetter(last) || (code >= 48 && code <= 57) || last === '.' || last === '_';\n};\n\nconst isAutoAllowedStoryAttribute = (attributeName: string): boolean => {\n  return attributeName !== 'style' && !attributeName.startsWith('on');\n};\n\nconst findBooleanAttributeSuffix = (\n  part: string\n): { attribute: string; basePart: string; spacing: string } | null => {\n  let index = part.length - 1;\n\n  while (index >= 0 && isWhitespace(part[index])) {\n    index -= 1;\n  }\n\n  if (index < 0 || part[index] !== '=') {\n    return null;\n  }\n\n  index -= 1;\n\n  while (index >= 0 && isWhitespace(part[index])) {\n    index -= 1;\n  }\n\n  const attributeEnd = index;\n\n  while (\n    index >= 0 &&\n    !isWhitespace(part[index]) &&\n    part[index] !== '?' &&\n    part[index] !== '=' &&\n    part[index] !== '/' &&\n    part[index] !== '>'\n  ) {\n    index -= 1;\n  }\n\n  const attributeStart = index + 1;\n\n  if (attributeStart > attributeEnd || part[index] !== '?') {\n    return null;\n  }\n\n  const questionMarkIndex = index;\n  let spacingStart = questionMarkIndex;\n\n  while (spacingStart > 0 && isWhitespace(part[spacingStart - 1])) {\n    spacingStart -= 1;\n  }\n\n  return {\n    attribute: part.slice(attributeStart, attributeEnd + 1),\n    basePart: part.slice(0, spacingStart),\n    spacing: part.slice(spacingStart, questionMarkIndex),\n  };\n};\n\nconst collectOpeningTagFragments = (template: string): string[] => {\n  const fragments: string[] = [];\n  let index = 0;\n\n  while (index < template.length) {\n    if (template[index] !== '<') {\n      index += 1;\n      continue;\n    }\n\n    const next = template[index + 1];\n\n    if (!next || next === '/' || next === '!' || next === '?') {\n      index += 1;\n      continue;\n    }\n\n    let cursor = index + 1;\n\n    if (!isAsciiLetter(template[cursor])) {\n      index += 1;\n      continue;\n    }\n\n    while (cursor < template.length && isTagNameChar(template[cursor])) {\n      cursor += 1;\n    }\n\n    const tagStart = index + 1;\n    const tagName = template.slice(tagStart, cursor);\n\n    if (!tagName) {\n      index += 1;\n      continue;\n    }\n\n    let inQuote: '\"' | \"'\" | null = null;\n    let tagEnd = cursor;\n\n    while (tagEnd < template.length) {\n      const char = template[tagEnd];\n\n      if (inQuote) {\n        if (char === inQuote) {\n          inQuote = null;\n        }\n\n        tagEnd += 1;\n        continue;\n      }\n\n      if (char === '\"' || char === \"'\") {\n        inQuote = char;\n        tagEnd += 1;\n        continue;\n      }\n\n      if (char === '>') {\n        fragments.push(template.slice(index + 1, tagEnd));\n        tagEnd += 1;\n        break;\n      }\n\n      tagEnd += 1;\n    }\n\n    index = tagEnd;\n  }\n\n  return fragments;\n};\n\n/**\n * Consumes a literal HTML attribute value starting at the given index.\n *\n * Returns the position immediately after a quoted or unquoted value. When the\n * current position reaches an interpolation boundary (optionally after\n * whitespace), the returned index advances past the boundary marker so\n * interpolated attributes do not swallow following authored attributes during\n * sanitizer allowlist inference.\n *\n * @param fragment - The opening-tag fragment currently being scanned\n * @param index - The position immediately after the `=` sign\n * @returns The index after the consumed literal value, or just past an\n * interpolation boundary when no literal value should be consumed from the\n * current template fragment.\n */\nconst skipAttributeValue = (fragment: string, index: number): number => {\n  if (index >= fragment.length) {\n    return index;\n  }\n\n  let cursor = index;\n\n  if (isInterpolationBoundaryMarker(fragment[cursor])) {\n    return cursor + 1;\n  }\n\n  while (cursor < fragment.length && isWhitespace(fragment[cursor])) {\n    cursor += 1;\n  }\n\n  if (cursor >= fragment.length) {\n    return cursor;\n  }\n\n  if (isInterpolationBoundaryMarker(fragment[cursor])) {\n    return cursor + 1;\n  }\n\n  const quote = fragment[cursor];\n\n  if (isQuoteChar(quote)) {\n    cursor += 1;\n\n    while (cursor < fragment.length) {\n      if (fragment[cursor] === quote) {\n        return cursor + 1;\n      }\n\n      cursor += 1;\n    }\n\n    return cursor;\n  }\n\n  while (\n    cursor < fragment.length &&\n    !isAttributeSeparator(fragment[cursor]) &&\n    fragment[cursor] !== '/' &&\n    fragment[cursor] !== '>'\n  ) {\n    cursor += 1;\n  }\n\n  if (cursor < fragment.length && isInterpolationBoundaryMarker(fragment[cursor])) {\n    return cursor + 1;\n  }\n\n  return cursor;\n};\n\nconst collectAttributesFromTagFragment = (\n  fragment: string,\n  allowAttributes: Set<string>,\n  autoAllowAttributes: boolean\n): void => {\n  let index = 0;\n\n  while (index < fragment.length && !isAttributeSeparator(fragment[index])) {\n    index += 1;\n  }\n\n  while (index < fragment.length) {\n    while (index < fragment.length && isAttributeSeparator(fragment[index])) {\n      index += 1;\n    }\n\n    if (index >= fragment.length || fragment[index] === '/') {\n      return;\n    }\n\n    // Skip standalone colons (e.g. namespace prefixes or framework-specific bindings)\n    if (fragment[index] === ':') {\n      index += 1;\n      continue;\n    }\n\n    const hasBooleanPrefix = fragment[index] === '?';\n\n    if (hasBooleanPrefix) {\n      index += 1;\n    }\n\n    if (index >= fragment.length || !isAttributeNameStart(fragment[index])) {\n      // Skip unrecognised character to avoid an infinite loop\n      index += 1;\n      continue;\n    }\n\n    const nameStart = index;\n\n    index += 1;\n\n    while (index < fragment.length && isAttributeNameChar(fragment[index])) {\n      index += 1;\n    }\n\n    const attributeName = fragment.slice(nameStart, index).toLowerCase();\n\n    while (index < fragment.length && isAttributeSeparator(fragment[index])) {\n      index += 1;\n    }\n\n    if (index < fragment.length && fragment[index] === '=') {\n      if (autoAllowAttributes && isAutoAllowedStoryAttribute(attributeName)) {\n        allowAttributes.add(attributeName);\n      }\n      index = skipAttributeValue(fragment, index + 1);\n      continue;\n    }\n\n    if (hasBooleanPrefix && autoAllowAttributes && isAutoAllowedStoryAttribute(attributeName)) {\n      allowAttributes.add(attributeName);\n    }\n  }\n};\n\nconst collectTemplateSanitizeOptions = (strings: TemplateStringsArray) => {\n  const template = strings.join(INTERPOLATION_BOUNDARY_MARKER);\n  const allowTags = new Set<string>();\n  const allowAttributes = new Set<string>();\n\n  for (const fragment of collectOpeningTagFragments(template)) {\n    const tagName = fragment.slice(0, getTagNameEnd(fragment)).toLowerCase();\n    const isCustomElement = isCustomElementTagName(tagName);\n\n    if (isCustomElement) {\n      allowTags.add(tagName);\n    }\n\n    collectAttributesFromTagFragment(fragment, allowAttributes, isCustomElement);\n  }\n\n  return {\n    allowTags: Array.from(allowTags),\n    allowAttributes: Array.from(allowAttributes),\n  };\n};\n\nconst resolveStoryValue = (value: StoryValue): string => {\n  if (value == null) {\n    return '';\n  }\n\n  if (Array.isArray(value)) {\n    return value.map((item) => resolveStoryValue(item)).join('');\n  }\n\n  if (typeof value === 'function') {\n    return resolveStoryValue(value());\n  }\n\n  return String(value);\n};\n\nconst resolveBooleanStoryValue = (value: StoryValue): boolean => {\n  if (value == null) {\n    return false;\n  }\n\n  if (typeof value === 'function') {\n    return resolveBooleanStoryValue(value());\n  }\n\n  if (Array.isArray(value)) {\n    return Boolean(resolveStoryValue(value));\n  }\n\n  if (typeof value === 'boolean') {\n    return value;\n  }\n\n  return Boolean(value);\n};\n\n/**\n * Tagged template literal for Storybook render functions.\n *\n * Supports boolean attribute shorthand compatible with Storybook's string\n * renderer:\n *\n * ```ts\n * storyHtml`<bq-button ?disabled=${true}>Save</bq-button>`;\n * // => '<bq-button disabled=\"\">Save</bq-button>'\n * ```\n *\n * @param strings - Template literal string parts\n * @param values - Interpolated values\n * @returns HTML string compatible with `@storybook/web-components`\n */\nexport const storyHtml = (strings: TemplateStringsArray, ...values: StoryValue[]): string => {\n  const rendered = strings.reduce((acc, part, index) => {\n    if (index >= values.length) {\n      return `${acc}${part}`;\n    }\n\n    const booleanAttributeMatch = findBooleanAttributeSuffix(part);\n\n    if (booleanAttributeMatch) {\n      const { attribute, basePart, spacing } = booleanAttributeMatch;\n      const preservedSpacing = hasLineBreak(spacing) ? spacing : '';\n      const isEnabled = resolveBooleanStoryValue(values[index]);\n\n      return `${acc}${basePart}${isEnabled ? `${spacing}${attribute}` : preservedSpacing}`;\n    }\n\n    return `${acc}${part}${resolveStoryValue(values[index])}`;\n  }, '');\n\n  return sanitizeHtml(rendered, collectTemplateSanitizeOptions(strings));\n};\n\n/**\n * Conditionally render a value or template fragment.\n *\n * @param condition - Condition that controls rendering\n * @param truthyValue - Value or callback rendered when the condition is truthy\n * @param falsyValue - Optional value or callback rendered when the condition is falsy\n * @returns Rendered string fragment, or an empty string when the condition is\n * falsy and no fallback is provided\n */\nexport const when = (\n  condition: unknown,\n  truthyValue: StoryValue,\n  falsyValue?: StoryValue\n): string => {\n  return resolveStoryValue(condition ? truthyValue : falsyValue);\n};\n"],"mappings":"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"}