{"version":3,"file":"dump/html-utils.mjs","sources":["../../../src/dump/html-utils.ts"],"sourcesContent":["import { closeSync, openSync, readSync, statSync } from 'node:fs';\nimport { antiEscapeScriptTag, escapeScriptTag } from '@midscene/shared/utils';\n\nexport const escapeContent = escapeScriptTag;\nexport const unescapeContent = antiEscapeScriptTag;\n\nfunction htmlScriptCloseTag(): string {\n  // biome-ignore lint/style/useTemplate: keep this token runtime-built for inline report bundles\n  return String.fromCharCode(60) + '/script>';\n}\n\n/** Chunk size for streaming file operations (64KB) */\nexport const STREAMING_CHUNK_SIZE = 64 * 1024;\n\n/**\n * Callback for processing matched tags during streaming.\n * @param content - The content between open and close tags\n * @returns true to stop scanning, false to continue\n */\ntype TagMatchCallback = (content: string) => boolean;\n\n/**\n * Stream through a file and find tags matching the pattern.\n * Memory usage: O(chunk_size + tag_size), not O(file_size).\n *\n * @param filePath - Absolute path to the file\n * @param openTag - Opening tag to search for\n * @param closeTag - Closing tag\n * @param onMatch - Callback for each matched tag content\n */\nexport function streamScanTags(\n  filePath: string,\n  openTag: string,\n  closeTag: string,\n  onMatch: TagMatchCallback,\n): void {\n  const fd = openSync(filePath, 'r');\n  const fileSize = statSync(filePath).size;\n  const buffer = Buffer.alloc(STREAMING_CHUNK_SIZE);\n\n  let position = 0;\n  let leftover = '';\n  let capturing = false;\n  let currentContent = '';\n\n  try {\n    while (position < fileSize) {\n      const bytesRead = readSync(fd, buffer, 0, STREAMING_CHUNK_SIZE, position);\n      const chunk = leftover + buffer.toString('utf-8', 0, bytesRead);\n      position += bytesRead;\n\n      let searchStart = 0;\n\n      while (searchStart < chunk.length) {\n        if (!capturing) {\n          const startIdx = chunk.indexOf(openTag, searchStart);\n          if (startIdx !== -1) {\n            capturing = true;\n            currentContent = chunk.slice(startIdx + openTag.length);\n            const endIdx = currentContent.indexOf(closeTag);\n            if (endIdx !== -1) {\n              const shouldStop = onMatch(currentContent.slice(0, endIdx));\n              if (shouldStop) return;\n              capturing = false;\n              currentContent = '';\n              searchStart =\n                startIdx + openTag.length + endIdx + closeTag.length;\n            } else {\n              leftover = currentContent.slice(-closeTag.length);\n              currentContent = currentContent.slice(0, -closeTag.length);\n              break;\n            }\n          } else {\n            leftover = chunk.slice(-openTag.length);\n            break;\n          }\n        } else {\n          const endIdx = chunk.indexOf(closeTag, searchStart);\n          if (endIdx !== -1) {\n            currentContent += chunk.slice(searchStart, endIdx);\n            const shouldStop = onMatch(currentContent);\n            if (shouldStop) return;\n            capturing = false;\n            currentContent = '';\n            searchStart = endIdx + closeTag.length;\n          } else {\n            currentContent += chunk.slice(searchStart, -closeTag.length);\n            leftover = chunk.slice(-closeTag.length);\n            break;\n          }\n        }\n      }\n    }\n  } finally {\n    closeSync(fd);\n  }\n}\n\n/**\n * Synchronously extract a specific image's base64 data from an HTML file by its id.\n * Uses streaming to avoid loading the entire file into memory.\n *\n * @param htmlPath - Absolute path to the HTML file\n * @param imageId - The id of the image to extract\n * @returns The base64 data string, or null if not found\n */\nexport function extractImageByIdSync(\n  htmlPath: string,\n  imageId: string,\n): string | null {\n  const targetTag = `<script type=\"midscene-image\" data-id=\"${imageId}\">`;\n  const closeTag = htmlScriptCloseTag();\n\n  let result: string | null = null;\n\n  streamScanTags(htmlPath, targetTag, closeTag, (content) => {\n    result = unescapeContent(content);\n    return true; // Stop after first match\n  });\n\n  return result;\n}\n\n/**\n * Stream image script tags from source file directly to output file.\n * Memory usage: O(single_image_size), not O(all_images_size).\n *\n * @param srcFilePath - Source HTML file path\n * @param destFilePath - Destination file path to append to\n */\nexport function streamImageScriptsToFile(\n  srcFilePath: string,\n  destFilePath: string,\n): void {\n  const { appendFileSync } = require('node:fs');\n  const openTag = '<script type=\"midscene-image\"';\n  const closeTag = htmlScriptCloseTag();\n\n  streamScanTags(srcFilePath, openTag, closeTag, (content) => {\n    // Write complete tag immediately to destination, don't accumulate\n    appendFileSync(destFilePath, `${openTag}${content}${closeTag}\\n`);\n    return false; // Continue scanning for more tags\n  });\n}\n\n/**\n * Extract the LAST dump script content from HTML file using streaming.\n * Memory usage: O(dump_size), not O(file_size).\n *\n * @param filePath - Absolute path to the HTML file\n * @returns The dump script content (trimmed), or empty string if not found\n */\nexport function extractLastDumpScriptSync(filePath: string): string {\n  const openTagPrefix = '<script type=\"midscene_web_dump\"';\n  const closeTag = htmlScriptCloseTag();\n\n  let lastContent = '';\n\n  // Custom streaming to handle the special case where open tag has variable attributes\n  const fd = openSync(filePath, 'r');\n  const fileSize = statSync(filePath).size;\n  const buffer = Buffer.alloc(STREAMING_CHUNK_SIZE);\n\n  let position = 0;\n  let leftover = '';\n  let capturing = false;\n  let currentContent = '';\n\n  try {\n    while (position < fileSize) {\n      const bytesRead = readSync(fd, buffer, 0, STREAMING_CHUNK_SIZE, position);\n      const chunk = leftover + buffer.toString('utf-8', 0, bytesRead);\n      position += bytesRead;\n\n      let searchStart = 0;\n\n      while (searchStart < chunk.length) {\n        if (!capturing) {\n          const startIdx = chunk.indexOf(openTagPrefix, searchStart);\n          if (startIdx !== -1) {\n            // Find the end of the opening tag (the '>' character)\n            const tagEndIdx = chunk.indexOf('>', startIdx);\n            if (tagEndIdx !== -1) {\n              capturing = true;\n              currentContent = chunk.slice(tagEndIdx + 1);\n              const endIdx = currentContent.indexOf(closeTag);\n              if (endIdx !== -1) {\n                lastContent = currentContent.slice(0, endIdx).trim();\n                capturing = false;\n                currentContent = '';\n                searchStart = tagEndIdx + 1 + endIdx + closeTag.length;\n              } else {\n                leftover = currentContent.slice(-closeTag.length);\n                currentContent = currentContent.slice(0, -closeTag.length);\n                break;\n              }\n            } else {\n              leftover = chunk.slice(startIdx);\n              break;\n            }\n          } else {\n            leftover = chunk.slice(-openTagPrefix.length);\n            break;\n          }\n        } else {\n          const endIdx = chunk.indexOf(closeTag, searchStart);\n          if (endIdx !== -1) {\n            currentContent += chunk.slice(searchStart, endIdx);\n            lastContent = currentContent.trim();\n            capturing = false;\n            currentContent = '';\n            searchStart = endIdx + closeTag.length;\n          } else {\n            currentContent += chunk.slice(searchStart, -closeTag.length);\n            leftover = chunk.slice(-closeTag.length);\n            break;\n          }\n        }\n      }\n    }\n  } finally {\n    closeSync(fd);\n  }\n\n  return lastContent;\n}\n\n/**\n * Extract ALL dump script contents from an HTML file using streaming.\n * Each entry includes the full opening tag (for attribute extraction) and the content.\n *\n * @param filePath - Absolute path to the HTML file\n * @returns Array of { openTag, content } for each dump script found\n */\nexport function extractAllDumpScriptsSync(\n  filePath: string,\n): { openTag: string; content: string }[] {\n  const results: { openTag: string; content: string }[] = [];\n  streamDumpScriptsSync(filePath, (dumpScript) => {\n    results.push(dumpScript);\n    return false;\n  });\n  return results;\n}\n\n/**\n * Stream ALL dump scripts from an HTML file.\n * Calls onMatch for each dump script and keeps memory bounded to a single\n * dump script payload instead of accumulating every dump in memory.\n *\n * @param filePath - Absolute path to the HTML file\n * @param onMatch - Callback for each dump script; return true to stop early\n */\nexport function streamDumpScriptsSync(\n  filePath: string,\n  onMatch: (dumpScript: { openTag: string; content: string }) => boolean,\n): void {\n  const openTagPrefix = '<script type=\"midscene_web_dump\"';\n  const closeTag = htmlScriptCloseTag();\n\n  const fd = openSync(filePath, 'r');\n  const fileSize = statSync(filePath).size;\n  const buffer = Buffer.alloc(STREAMING_CHUNK_SIZE);\n\n  let position = 0;\n  let leftover = '';\n  let capturing = false;\n  let currentContent = '';\n  let currentOpenTag = '';\n\n  try {\n    while (position < fileSize) {\n      const bytesRead = readSync(fd, buffer, 0, STREAMING_CHUNK_SIZE, position);\n      const chunk = leftover + buffer.toString('utf-8', 0, bytesRead);\n      position += bytesRead;\n\n      let searchStart = 0;\n\n      while (searchStart < chunk.length) {\n        if (!capturing) {\n          const startIdx = chunk.indexOf(openTagPrefix, searchStart);\n          if (startIdx !== -1) {\n            const tagEndIdx = chunk.indexOf('>', startIdx);\n            if (tagEndIdx !== -1) {\n              capturing = true;\n              currentOpenTag = chunk.slice(startIdx, tagEndIdx + 1);\n              currentContent = chunk.slice(tagEndIdx + 1);\n              const endIdx = currentContent.indexOf(closeTag);\n              if (endIdx !== -1) {\n                const shouldStop = onMatch({\n                  openTag: currentOpenTag,\n                  content: currentContent.slice(0, endIdx).trim(),\n                });\n                if (shouldStop) return;\n                capturing = false;\n                currentContent = '';\n                currentOpenTag = '';\n                searchStart = tagEndIdx + 1 + endIdx + closeTag.length;\n              } else {\n                leftover = currentContent.slice(-closeTag.length);\n                currentContent = currentContent.slice(0, -closeTag.length);\n                break;\n              }\n            } else {\n              leftover = chunk.slice(startIdx);\n              break;\n            }\n          } else {\n            leftover = chunk.slice(-openTagPrefix.length);\n            break;\n          }\n        } else {\n          const endIdx = chunk.indexOf(closeTag, searchStart);\n          if (endIdx !== -1) {\n            currentContent += chunk.slice(searchStart, endIdx);\n            const shouldStop = onMatch({\n              openTag: currentOpenTag,\n              content: currentContent.trim(),\n            });\n            if (shouldStop) return;\n            capturing = false;\n            currentContent = '';\n            currentOpenTag = '';\n            searchStart = endIdx + closeTag.length;\n          } else {\n            currentContent += chunk.slice(searchStart, -closeTag.length);\n            leftover = chunk.slice(-closeTag.length);\n            break;\n          }\n        }\n      }\n    }\n  } finally {\n    closeSync(fd);\n  }\n}\n\nexport function parseImageScripts(html: string): Record<string, string> {\n  const imageMap: Record<string, string> = {};\n  const regex =\n    /<script type=\"midscene-image\" data-id=\"([^\"]+)\">([\\s\\S]*?)<\\/script>/g;\n\n  for (const match of html.matchAll(regex)) {\n    const [, id, content] = match;\n    imageMap[id] = unescapeContent(content);\n  }\n\n  return imageMap;\n}\n\nexport function parseDumpScript(html: string): string {\n  // Use string search instead of regex to avoid ReDoS vulnerability\n  // Find the LAST dump script tag (template may contain similar patterns in bundled JS)\n  const scriptOpenTag = '<script type=\"midscene_web_dump\"';\n  const closeTag = htmlScriptCloseTag();\n\n  // Find the last occurrence of the opening tag\n  const lastOpenIndex = html.lastIndexOf(scriptOpenTag);\n  if (lastOpenIndex === -1) {\n    throw new Error('No dump script found in HTML');\n  }\n\n  // Find the end of the opening tag (the '>' character)\n  const tagEndIndex = html.indexOf('>', lastOpenIndex);\n  if (tagEndIndex === -1) {\n    throw new Error('No dump script found in HTML');\n  }\n\n  // Find the closing tag after the opening tag\n  const closeIndex = html.indexOf(closeTag, tagEndIndex);\n  if (closeIndex === -1) {\n    throw new Error('No dump script found in HTML');\n  }\n\n  // Extract content between opening and closing tags\n  const content = html.substring(tagEndIndex + 1, closeIndex);\n  return unescapeContent(content);\n}\n\nexport function parseDumpScriptAttributes(\n  html: string,\n): Record<string, string> {\n  const regex = /<script type=\"midscene_web_dump\"([^>]*)>/;\n  const match = regex.exec(html);\n\n  if (!match) {\n    return {};\n  }\n\n  const attrString = match[1];\n  const attributes: Record<string, string> = {};\n  const attrRegex = /(\\w+)=\"([^\"]*)\"/g;\n\n  for (const attrMatch of attrString.matchAll(attrRegex)) {\n    const [, key, value] = attrMatch;\n    if (key !== 'type') {\n      attributes[key] = decodeURIComponent(value);\n    }\n  }\n\n  return attributes;\n}\n\nexport function generateImageScriptTag(id: string, data: string): string {\n  // Do not use template string here, will cause bundle error with <script\n  const closeTag = htmlScriptCloseTag();\n  return (\n    // biome-ignore lint/style/useTemplate: <explanation>\n    '<script type=\"midscene-image\" data-id=\"' +\n    id +\n    '\">' +\n    escapeContent(data) +\n    closeTag\n  );\n}\n\n/**\n * Inline script that fixes relative URL resolution for directory-mode reports.\n *\n * Problem: when a static server (e.g. `npx serve`) serves `name/index.html`\n * at URL `/name` (without trailing slash), relative paths like\n * `./screenshots/xxx.png` resolve to `/screenshots/xxx.png` instead of\n * `/name/screenshots/xxx.png`.\n *\n * Fix: dynamically insert a <base> tag so relative URLs resolve correctly.\n */\n// Do not use template string here, will cause bundle error with <script\n//\n// The closing script tag is built at runtime so bundlers cannot inline the\n// token that would prematurely close the report template's inline app bundle.\n//\n// Do NOT replace this with a string constant, hex escape (\\x3c), or literal\n// string concatenation. Bundlers may optimise those forms back to the unsafe\n// token.\nlet _baseUrlFixScript: string;\nexport function getBaseUrlFixScript(): string {\n  if (!_baseUrlFixScript) {\n    const close = htmlScriptCloseTag();\n    _baseUrlFixScript =\n      // biome-ignore lint/style/useTemplate: see above\n      '\\n<script>(function(){' +\n      'var p=window.location.pathname;' +\n      'if(p.endsWith(\"/\")||/\\\\.\\\\w+$/.test(p))return;' +\n      'var b=document.createElement(\"base\");' +\n      'b.href=p+\"/\";' +\n      'document.head.insertBefore(b,document.head.firstChild)' +\n      '})()' +\n      close +\n      '\\n';\n  }\n  return _baseUrlFixScript;\n}\n\nexport function generateDumpScriptTag(\n  json: string,\n  attributes?: Record<string, string | number | boolean>,\n): string {\n  const closeTag = htmlScriptCloseTag();\n  let attrString = '';\n  if (attributes && Object.keys(attributes).length > 0) {\n    // Do not use template string here, will cause bundle error with <script\n    attrString =\n      // biome-ignore lint/style/useTemplate: <explanation>\n      ' ' +\n      Object.entries(attributes)\n        // biome-ignore lint/style/useTemplate: <explanation>\n        .map(([k, v]) => k + '=\"' + encodeURIComponent(v) + '\"')\n        .join(' ');\n  }\n\n  // Do not use template string here, will cause bundle error with <script\n  return (\n    // biome-ignore lint/style/useTemplate: <explanation>\n    '<script type=\"midscene_web_dump\"' +\n    attrString +\n    '>' +\n    escapeContent(json) +\n    closeTag\n  );\n}\n"],"names":["escapeContent","escapeScriptTag","unescapeContent","antiEscapeScriptTag","htmlScriptCloseTag","String","STREAMING_CHUNK_SIZE","streamScanTags","filePath","openTag","closeTag","onMatch","fd","openSync","fileSize","statSync","buffer","Buffer","position","leftover","capturing","currentContent","bytesRead","readSync","chunk","searchStart","endIdx","shouldStop","startIdx","closeSync","extractImageByIdSync","htmlPath","imageId","targetTag","result","content","streamImageScriptsToFile","srcFilePath","destFilePath","appendFileSync","require","extractLastDumpScriptSync","openTagPrefix","lastContent","tagEndIdx","extractAllDumpScriptsSync","results","streamDumpScriptsSync","dumpScript","currentOpenTag","parseImageScripts","html","imageMap","regex","match","id","parseDumpScript","scriptOpenTag","lastOpenIndex","Error","tagEndIndex","closeIndex","parseDumpScriptAttributes","attrString","attributes","attrRegex","attrMatch","key","value","decodeURIComponent","generateImageScriptTag","data","_baseUrlFixScript","getBaseUrlFixScript","close","generateDumpScriptTag","json","Object","k","v","encodeURIComponent"],"mappings":"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"}