{
  "version": 3,
  "sources": ["../src/browser.ts", "../src/comments.ts", "../src/transform.ts", "../src/hast-utils.ts", "../src/shared.ts"],
  "sourcesContent": ["/**\n * Browser-safe entry point for @mrsf/rehype-mrsf.\n *\n * This entry is automatically selected by bundlers (Vite, webpack, esbuild)\n * via the `\"browser\"` export condition in package.json. It supports the\n * `comments` and `loader` provisioning modes \u2014 no Node.js file-system APIs.\n *\n * You do NOT need to import this directly. Just use:\n *   import { rehypeMrsf } from \"@mrsf/rehype-mrsf\";\n *\n * Your bundler will resolve to this file automatically when targeting\n * a browser environment.\n */\n\nimport type { MrsfPluginOptions } from \"./types.js\";\nimport { createRehypeMrsf } from \"./shared.js\";\n\nexport type { MrsfPluginOptions, SlimComment, CommentThread, LineMap, CommentLoader } from \"./types.js\";\n\n/**\n * The rehype plugin function (browser-safe).\n *\n * Supports `comments` (inline data) and `loader` (custom function) options.\n */\nexport const rehypeMrsf = createRehypeMrsf((options: MrsfPluginOptions, env?: unknown) => {\n  if (options.comments) {\n    return options.comments;\n  }\n\n  if (options.loader) {\n    try {\n      return options.loader(options, env);\n    } catch {\n      return null;\n    }\n  }\n\n  if (options.sidecarPath || options.documentPath) {\n    console.warn(\n      \"[@mrsf/rehype-mrsf] sidecarPath and documentPath require Node.js. \" +\n      \"Use `comments` or `loader` options in browser environments.\"\n    );\n  }\n\n  return null;\n});\n\nexport default rehypeMrsf;\n", "/* ---------------------------------------------------------------\n * AUTO-GENERATED \u2014 DO NOT EDIT\n *\n * Source: plugins/shared/src/comments.ts\n * Run `node plugins/sync-types.mjs` to regenerate.\n * --------------------------------------------------------------- */\n\n/**\n * Shared comment loading and grouping logic for MRSF rendering plugins.\n */\n\nimport type { MrsfDocument } from \"@mrsf/cli\";\nimport type { MrsfPluginOptions, SlimComment, CommentThread, LineMap, CommentLoader } from \"./types.js\";\n\nexport type { CommentLoader };\n\nfunction getExtensionFields(comment: Record<string, unknown>): Record<`x_${string}`, unknown> {\n  const extensions: Record<`x_${string}`, unknown> = {};\n\n  for (const [key, value] of Object.entries(comment)) {\n    if (key.startsWith(\"x_\")) {\n      extensions[key as `x_${string}`] = value;\n    }\n  }\n\n  return extensions;\n}\n\n/**\n * Convert an MrsfDocument into a slim comment array.\n */\nexport function toSlimComments(doc: MrsfDocument): SlimComment[] {\n  return doc.comments.map((c) => ({\n    id: c.id,\n    author: c.author || \"Unknown\",\n    text: c.text || \"\",\n    line: c.line ?? null,\n    end_line: c.end_line ?? null,\n    start_column: c.start_column ?? null,\n    end_column: c.end_column ?? null,\n    selected_text: c.selected_text || null,\n    resolved: !!c.resolved,\n    reply_to: c.reply_to || null,\n    severity: c.severity || null,\n    type: c.type || null,\n    timestamp: c.timestamp || null,\n    ...getExtensionFields(c as Record<string, unknown>),\n  }));\n}\n\n/**\n * Group comments by line number, threading replies under parents.\n */\nexport function groupByLine(comments: SlimComment[]): LineMap {\n  const rootComments = comments.filter((c) => !c.reply_to && c.line != null);\n  const replies = comments.filter((c) => c.reply_to);\n\n  const replyMap = new Map<string, SlimComment[]>();\n  for (const r of replies) {\n    const list = replyMap.get(r.reply_to!) || [];\n    list.push(r);\n    replyMap.set(r.reply_to!, list);\n  }\n\n  const lineMap: LineMap = new Map();\n  for (const c of rootComments) {\n    const line = c.line!;\n    const threads = lineMap.get(line) || [];\n    threads.push({\n      comment: c,\n      replies: replyMap.get(c.id) || [],\n    });\n    lineMap.set(line, threads);\n  }\n\n  return lineMap;\n}\n\n/**\n * Resolve options into a filtered LineMap ready for rendering.\n * Returns null if there are no comments to render.\n */\nexport function resolveComments(\n  loader: CommentLoader,\n  options: MrsfPluginOptions,\n  env?: unknown,\n): { lineMap: LineMap; comments: SlimComment[] } | null {\n  const showResolved = options.showResolved ?? true;\n\n  const doc = loader(options, env);\n  if (!doc || !doc.comments || doc.comments.length === 0) {\n    return null;\n  }\n\n  let comments = toSlimComments(doc);\n  if (!showResolved) {\n    comments = comments.filter((c) => !c.resolved);\n  }\n\n  if (comments.length === 0) return null;\n\n  const lineMap = groupByLine(comments);\n  return { lineMap, comments };\n}\n", "/**\n * MRSF rehype plugin \u2014 hast tree transformation (overlay gutter architecture).\n *\n * Walks the hast tree and annotates block elements with `data-mrsf-line`\n * attributes. Adds a highlight class on commented lines. Appends a\n * `<script type=\"application/mrsf+json\">` with serialized comment data\n * for the client-side MrsfController to consume.\n *\n * NO visual DOM is injected \u2014 all badges, tooltips, and gutter elements\n * are created at runtime by the controller.\n */\n\nimport type { Root, Element, ElementContent } from \"hast\";\nimport { visit } from \"unist-util-visit\";\nimport type { LineMap, CommentThread } from \"./types.js\";\nimport { createDataElement, createDataScript } from \"./hast-utils.js\";\n\n/** Block-level tag names that can carry line-anchored comments. */\nconst BLOCK_TAGS = new Set([\n  \"p\", \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\",\n  \"li\", \"blockquote\", \"pre\", \"table\", \"tr\",\n  \"div\", \"section\", \"article\", \"aside\",\n]);\n\n/**\n * Check whether a hast element's source position spans the given 1-based line.\n */\nfunction elementSpansLine(node: Element, line: number): boolean {\n  if (!node.position) return false;\n  return node.position.start.line <= line && line <= node.position.end.line;\n}\n\n/**\n * Check whether a parent block already covers this node's position,\n * meaning we should skip this node to avoid duplicate annotations.\n */\nfunction coveredByParentBlock(node: Element, parent: any): boolean {\n  if (!parent || parent.type !== \"element\") return false;\n  const p = parent as Element;\n  if (!BLOCK_TAGS.has(p.tagName)) return false;\n  if (!node.position || !p.position) return false;\n  const s = node.position.start.line;\n  const e = node.position.end.line;\n  return p.position.start.line <= s && e <= p.position.end.line;\n}\n\n/**\n * Check whether a line is owned by a descendant block element.\n */\nfunction lineOwnedByDescendant(node: Element, line: number): boolean {\n  for (const child of node.children) {\n    if (child.type !== \"element\") continue;\n    if (!child.position) continue;\n    if (BLOCK_TAGS.has(child.tagName) && elementSpansLine(child, line)) {\n      return true;\n    }\n    if (!BLOCK_TAGS.has(child.tagName) && lineOwnedByDescendant(child, line)) {\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * Add a CSS class to a hast element.\n */\nfunction addClass(node: Element, cls: string): void {\n  const existing = node.properties?.className;\n  if (Array.isArray(existing)) {\n    if (!existing.includes(cls)) existing.push(cls);\n  } else if (typeof existing === \"string\") {\n    node.properties!.className = [existing, cls];\n  } else {\n    node.properties!.className = [cls];\n  }\n}\n\nexport interface TransformOptions {\n  /** Whether to add mrsf-line-highlight class on commented elements. Default: false. */\n  lineHighlight?: boolean;\n  dataContainer?: \"script\" | \"element\";\n  dataElementId?: string;\n}\n\n/**\n * Transform a hast tree: annotate elements with data-mrsf-line and\n * append embedded comment data for the MrsfController.\n */\nexport function transformTree(\n  tree: Root,\n  lineMap: LineMap,\n  options: TransformOptions = {},\n): void {\n  const processed = new Set<number>();\n\n  visit(tree, \"element\", (node: Element, _index, parent) => {\n    if (!node.position) return;\n    if (!BLOCK_TAGS.has(node.tagName)) return;\n    if (coveredByParentBlock(node, parent)) return;\n    // Tables can't carry data attributes; let <tr> children handle their rows.\n    if (node.tagName === \"table\") return;\n    if (!node.properties) node.properties = {};\n\n    const startLine = node.position.start.line;\n    const endLine = node.position.end.line;\n\n    // Annotate the element with line range\n    node.properties[\"data-mrsf-line\"] = String(startLine);\n    node.properties[\"data-mrsf-start-line\"] = String(startLine);\n    node.properties[\"data-mrsf-end-line\"] = String(endLine);\n\n    // Mark lines with comments\n    for (let line = startLine; line <= endLine; line++) {\n      if (processed.has(line)) continue;\n      if (line !== startLine && lineOwnedByDescendant(node, line)) continue;\n\n      const threads = lineMap.get(line);\n      if (threads && threads.length > 0 && options.lineHighlight) {\n        addClass(node, \"mrsf-line-highlight\");\n      }\n      processed.add(line);\n    }\n  });\n\n  // Collect all threads into a flat array for the data script\n  const allThreads: CommentThread[] = [];\n  for (const threads of lineMap.values()) {\n    allThreads.push(...threads);\n  }\n\n  if (allThreads.length > 0) {\n    const dataNode = options.dataContainer === \"element\"\n      ? createDataElement(allThreads, options.dataElementId || \"mrsf-comment-data\")\n      : createDataScript(allThreads);\n    tree.children.push(dataNode as ElementContent);\n  }\n}\n", "/**\n * MRSF rehype plugin \u2014 hast element factories (overlay gutter architecture).\n *\n * In the new architecture, the only element we inject into the hast tree\n * is a `<script type=\"application/mrsf+json\">` containing serialized\n * comment data. All visual rendering is done at runtime by MrsfController.\n */\n\nimport type { Element } from \"hast\";\nimport type { CommentThread } from \"./types.js\";\n\nfunction escapeAttribute(value: string): string {\n  return value\n    .replace(/&/g, \"&amp;\")\n    .replace(/</g, \"&lt;\")\n    .replace(/>/g, \"&gt;\")\n    .replace(/\"/g, \"&quot;\");\n}\n\n/**\n * Create a `<script type=\"application/mrsf+json\">` element containing\n * serialized comment thread data for the MrsfController to consume.\n */\nexport function createDataScript(threads: CommentThread[]): Element {\n  // Escape </ sequences to prevent premature script tag termination (XSS safety)\n  const data = JSON.stringify({ threads }).replace(/</g, \"\\\\u003c\");\n  return {\n    type: \"element\",\n    tagName: \"script\",\n    properties: {\n      type: \"application/mrsf+json\",\n    },\n    children: [{ type: \"text\", value: data }],\n  };\n}\n\nexport function createDataElement(threads: CommentThread[], elementId: string): Element {\n  const payload = JSON.stringify({ threads });\n  return {\n    type: \"element\",\n    tagName: \"div\",\n    properties: {\n      id: escapeAttribute(elementId),\n      \"data-mrsf-json\": escapeAttribute(payload),\n      \"aria-hidden\": \"true\",\n    },\n    children: [],\n  };\n}\n", "/**\n * Shared logic for @mrsf/rehype-mrsf.\n *\n * Contains the plugin factory using shared comment loading/grouping logic.\n */\n\nimport type { Root } from \"hast\";\nimport type { MrsfPluginOptions, CommentLoader } from \"./types.js\";\nimport { resolveComments } from \"./comments.js\";\nimport { transformTree } from \"./transform.js\";\n\n/**\n * Create a rehype plugin function with the given comment loader.\n *\n * @param loader - Function that resolves sidecar data from plugin options\n * @returns A rehype plugin function\n */\nexport function createRehypeMrsf(loader: CommentLoader) {\n  return function rehypeMrsf(options: MrsfPluginOptions = {}) {\n    return (tree: Root) => {\n      const result = resolveComments(loader, options);\n      if (!result) return;\n\n      transformTree(tree, result.lineMap, {\n        lineHighlight: options.lineHighlight ?? false,\n        dataContainer: options.dataContainer,\n        dataElementId: options.dataElementId,\n      });\n    };\n  };\n}\n"],
  "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACgBA,SAAS,mBAAmB,SAAkE;AAC5F,QAAM,aAA6C,CAAC;AAEpD,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,QAAI,IAAI,WAAW,IAAI,GAAG;AACxB,iBAAW,GAAoB,IAAI;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,eAAe,KAAkC;AAC/D,SAAO,IAAI,SAAS,IAAI,CAAC,OAAO;AAAA,IAC9B,IAAI,EAAE;AAAA,IACN,QAAQ,EAAE,UAAU;AAAA,IACpB,MAAM,EAAE,QAAQ;AAAA,IAChB,MAAM,EAAE,QAAQ;AAAA,IAChB,UAAU,EAAE,YAAY;AAAA,IACxB,cAAc,EAAE,gBAAgB;AAAA,IAChC,YAAY,EAAE,cAAc;AAAA,IAC5B,eAAe,EAAE,iBAAiB;AAAA,IAClC,UAAU,CAAC,CAAC,EAAE;AAAA,IACd,UAAU,EAAE,YAAY;AAAA,IACxB,UAAU,EAAE,YAAY;AAAA,IACxB,MAAM,EAAE,QAAQ;AAAA,IAChB,WAAW,EAAE,aAAa;AAAA,IAC1B,GAAG,mBAAmB,CAA4B;AAAA,EACpD,EAAE;AACJ;AAKO,SAAS,YAAY,UAAkC;AAC5D,QAAM,eAAe,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,QAAQ,IAAI;AACzE,QAAM,UAAU,SAAS,OAAO,CAAC,MAAM,EAAE,QAAQ;AAEjD,QAAM,WAAW,oBAAI,IAA2B;AAChD,aAAW,KAAK,SAAS;AACvB,UAAM,OAAO,SAAS,IAAI,EAAE,QAAS,KAAK,CAAC;AAC3C,SAAK,KAAK,CAAC;AACX,aAAS,IAAI,EAAE,UAAW,IAAI;AAAA,EAChC;AAEA,QAAM,UAAmB,oBAAI,IAAI;AACjC,aAAW,KAAK,cAAc;AAC5B,UAAM,OAAO,EAAE;AACf,UAAM,UAAU,QAAQ,IAAI,IAAI,KAAK,CAAC;AACtC,YAAQ,KAAK;AAAA,MACX,SAAS;AAAA,MACT,SAAS,SAAS,IAAI,EAAE,EAAE,KAAK,CAAC;AAAA,IAClC,CAAC;AACD,YAAQ,IAAI,MAAM,OAAO;AAAA,EAC3B;AAEA,SAAO;AACT;AAMO,SAAS,gBACd,QACA,SACA,KACsD;AACtD,QAAM,eAAe,QAAQ,gBAAgB;AAE7C,QAAM,MAAM,OAAO,SAAS,GAAG;AAC/B,MAAI,CAAC,OAAO,CAAC,IAAI,YAAY,IAAI,SAAS,WAAW,GAAG;AACtD,WAAO;AAAA,EACT;AAEA,MAAI,WAAW,eAAe,GAAG;AACjC,MAAI,CAAC,cAAc;AACjB,eAAW,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ;AAAA,EAC/C;AAEA,MAAI,SAAS,WAAW,EAAG,QAAO;AAElC,QAAM,UAAU,YAAY,QAAQ;AACpC,SAAO,EAAE,SAAS,SAAS;AAC7B;;;AC1FA,8BAAsB;;;ACFtB,SAAS,gBAAgB,OAAuB;AAC9C,SAAO,MACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ;AAC3B;AAMO,SAAS,iBAAiB,SAAmC;AAElE,QAAM,OAAO,KAAK,UAAU,EAAE,QAAQ,CAAC,EAAE,QAAQ,MAAM,SAAS;AAChE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAY;AAAA,MACV,MAAM;AAAA,IACR;AAAA,IACA,UAAU,CAAC,EAAE,MAAM,QAAQ,OAAO,KAAK,CAAC;AAAA,EAC1C;AACF;AAEO,SAAS,kBAAkB,SAA0B,WAA4B;AACtF,QAAM,UAAU,KAAK,UAAU,EAAE,QAAQ,CAAC;AAC1C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAY;AAAA,MACV,IAAI,gBAAgB,SAAS;AAAA,MAC7B,kBAAkB,gBAAgB,OAAO;AAAA,MACzC,eAAe;AAAA,IACjB;AAAA,IACA,UAAU,CAAC;AAAA,EACb;AACF;;;AD9BA,IAAM,aAAa,oBAAI,IAAI;AAAA,EACzB;AAAA,EAAK;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EACnC;AAAA,EAAM;AAAA,EAAc;AAAA,EAAO;AAAA,EAAS;AAAA,EACpC;AAAA,EAAO;AAAA,EAAW;AAAA,EAAW;AAC/B,CAAC;AAKD,SAAS,iBAAiB,MAAe,MAAuB;AAC9D,MAAI,CAAC,KAAK,SAAU,QAAO;AAC3B,SAAO,KAAK,SAAS,MAAM,QAAQ,QAAQ,QAAQ,KAAK,SAAS,IAAI;AACvE;AAMA,SAAS,qBAAqB,MAAe,QAAsB;AACjE,MAAI,CAAC,UAAU,OAAO,SAAS,UAAW,QAAO;AACjD,QAAM,IAAI;AACV,MAAI,CAAC,WAAW,IAAI,EAAE,OAAO,EAAG,QAAO;AACvC,MAAI,CAAC,KAAK,YAAY,CAAC,EAAE,SAAU,QAAO;AAC1C,QAAM,IAAI,KAAK,SAAS,MAAM;AAC9B,QAAM,IAAI,KAAK,SAAS,IAAI;AAC5B,SAAO,EAAE,SAAS,MAAM,QAAQ,KAAK,KAAK,EAAE,SAAS,IAAI;AAC3D;AAKA,SAAS,sBAAsB,MAAe,MAAuB;AACnE,aAAW,SAAS,KAAK,UAAU;AACjC,QAAI,MAAM,SAAS,UAAW;AAC9B,QAAI,CAAC,MAAM,SAAU;AACrB,QAAI,WAAW,IAAI,MAAM,OAAO,KAAK,iBAAiB,OAAO,IAAI,GAAG;AAClE,aAAO;AAAA,IACT;AACA,QAAI,CAAC,WAAW,IAAI,MAAM,OAAO,KAAK,sBAAsB,OAAO,IAAI,GAAG;AACxE,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,SAAS,MAAe,KAAmB;AAClD,QAAM,WAAW,KAAK,YAAY;AAClC,MAAI,MAAM,QAAQ,QAAQ,GAAG;AAC3B,QAAI,CAAC,SAAS,SAAS,GAAG,EAAG,UAAS,KAAK,GAAG;AAAA,EAChD,WAAW,OAAO,aAAa,UAAU;AACvC,SAAK,WAAY,YAAY,CAAC,UAAU,GAAG;AAAA,EAC7C,OAAO;AACL,SAAK,WAAY,YAAY,CAAC,GAAG;AAAA,EACnC;AACF;AAaO,SAAS,cACd,MACA,SACA,UAA4B,CAAC,GACvB;AACN,QAAM,YAAY,oBAAI,IAAY;AAElC,qCAAM,MAAM,WAAW,CAAC,MAAe,QAAQ,WAAW;AACxD,QAAI,CAAC,KAAK,SAAU;AACpB,QAAI,CAAC,WAAW,IAAI,KAAK,OAAO,EAAG;AACnC,QAAI,qBAAqB,MAAM,MAAM,EAAG;AAExC,QAAI,KAAK,YAAY,QAAS;AAC9B,QAAI,CAAC,KAAK,WAAY,MAAK,aAAa,CAAC;AAEzC,UAAM,YAAY,KAAK,SAAS,MAAM;AACtC,UAAM,UAAU,KAAK,SAAS,IAAI;AAGlC,SAAK,WAAW,gBAAgB,IAAI,OAAO,SAAS;AACpD,SAAK,WAAW,sBAAsB,IAAI,OAAO,SAAS;AAC1D,SAAK,WAAW,oBAAoB,IAAI,OAAO,OAAO;AAGtD,aAAS,OAAO,WAAW,QAAQ,SAAS,QAAQ;AAClD,UAAI,UAAU,IAAI,IAAI,EAAG;AACzB,UAAI,SAAS,aAAa,sBAAsB,MAAM,IAAI,EAAG;AAE7D,YAAM,UAAU,QAAQ,IAAI,IAAI;AAChC,UAAI,WAAW,QAAQ,SAAS,KAAK,QAAQ,eAAe;AAC1D,iBAAS,MAAM,qBAAqB;AAAA,MACtC;AACA,gBAAU,IAAI,IAAI;AAAA,IACpB;AAAA,EACF,CAAC;AAGD,QAAM,aAA8B,CAAC;AACrC,aAAW,WAAW,QAAQ,OAAO,GAAG;AACtC,eAAW,KAAK,GAAG,OAAO;AAAA,EAC5B;AAEA,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,WAAW,QAAQ,kBAAkB,YACvC,kBAAkB,YAAY,QAAQ,iBAAiB,mBAAmB,IAC1E,iBAAiB,UAAU;AAC/B,SAAK,SAAS,KAAK,QAA0B;AAAA,EAC/C;AACF;;;AEvHO,SAAS,iBAAiB,QAAuB;AACtD,SAAO,SAASA,YAAW,UAA6B,CAAC,GAAG;AAC1D,WAAO,CAAC,SAAe;AACrB,YAAM,SAAS,gBAAgB,QAAQ,OAAO;AAC9C,UAAI,CAAC,OAAQ;AAEb,oBAAc,MAAM,OAAO,SAAS;AAAA,QAClC,eAAe,QAAQ,iBAAiB;AAAA,QACxC,eAAe,QAAQ;AAAA,QACvB,eAAe,QAAQ;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AJNO,IAAM,aAAa,iBAAiB,CAAC,SAA4B,QAAkB;AACxF,MAAI,QAAQ,UAAU;AACpB,WAAO,QAAQ;AAAA,EACjB;AAEA,MAAI,QAAQ,QAAQ;AAClB,QAAI;AACF,aAAO,QAAQ,OAAO,SAAS,GAAG;AAAA,IACpC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,QAAQ,eAAe,QAAQ,cAAc;AAC/C,YAAQ;AAAA,MACN;AAAA,IAEF;AAAA,EACF;AAEA,SAAO;AACT,CAAC;AAED,IAAO,kBAAQ;",
  "names": ["rehypeMrsf"]
}
