@mrsf/marked-mrsf 0.4.9 → 0.4.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/browser.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/shared.ts
2
2
  import { Marked } from "marked";
3
3
 
4
- // ../shared/dist/comments.js
4
+ // src/comments.ts
5
5
  function getExtensionFields(comment) {
6
6
  const extensions = {};
7
7
  for (const [key, value] of Object.entries(comment)) {
@@ -60,8 +60,7 @@ function resolveComments(loader, options, env) {
60
60
  if (!showResolved) {
61
61
  comments = comments.filter((c) => !c.resolved);
62
62
  }
63
- if (comments.length === 0)
64
- return null;
63
+ if (comments.length === 0) return null;
65
64
  const lineMap = groupByLine(comments);
66
65
  return { lineMap, comments };
67
66
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/shared.ts", "../../shared/src/comments.ts", "../src/browser.ts"],
4
- "sourcesContent": ["/**\n * Shared logic for @mrsf/marked-mrsf.\n */\n\nimport { Marked, type MarkedExtension, type Token, type Tokens } from \"marked\";\nimport { resolveComments } from \"@mrsf/plugin-shared\";\nimport type { CommentLoader, CommentThread, LineMap, MrsfPluginOptions } from \"./types.js\";\n\ntype TokenWithMrsf = Token & {\n mrsfStartLine?: number;\n mrsfEndLine?: number;\n mrsfLine?: number;\n mrsfLineHighlight?: boolean;\n mrsfHeaderLine?: number;\n mrsfRowLines?: number[];\n};\n\ntype ListItemWithMrsf = Tokens.ListItem & {\n mrsfStartLine?: number;\n mrsfEndLine?: number;\n mrsfLine?: number;\n mrsfLineHighlight?: boolean;\n};\n\nconst markedRuntime = new Marked();\nconst BaseRenderer = markedRuntime.Renderer;\n\nconst blockquoteRenderer = BaseRenderer.prototype.blockquote;\nconst codeRenderer = BaseRenderer.prototype.code;\nconst headingRenderer = BaseRenderer.prototype.heading;\nconst hrRenderer = BaseRenderer.prototype.hr;\nconst listItemRenderer = BaseRenderer.prototype.listitem;\nconst paragraphRenderer = BaseRenderer.prototype.paragraph;\nconst tableRenderer = BaseRenderer.prototype.table;\n\nfunction countLines(value: string): number {\n if (!value) return 1;\n return value.split(\"\\n\").length;\n}\n\nfunction trimTrailingBlankLines(value: string): string {\n return value.replace(/\\n+$/g, \"\");\n}\n\nfunction firstCommentLine(lineMap: LineMap, startLine: number, endLine: number): number {\n for (let line = startLine; line <= endLine; line++) {\n const threads = lineMap.get(line);\n if (threads && threads.length > 0) {\n return line;\n }\n }\n return startLine;\n}\n\nfunction hasCommentInRange(lineMap: LineMap, startLine: number, endLine: number): boolean {\n for (let line = startLine; line <= endLine; line++) {\n const threads = lineMap.get(line);\n if (threads && threads.length > 0) {\n return true;\n }\n }\n return false;\n}\n\nfunction stampBlock(token: TokenWithMrsf, startLine: number, lineMap: LineMap): number {\n const raw = typeof token.raw === \"string\" ? token.raw : \"\";\n const semantic = trimTrailingBlankLines(raw);\n const endLine = startLine + countLines(semantic) - 1;\n\n token.mrsfStartLine = startLine;\n token.mrsfEndLine = endLine;\n token.mrsfLine = firstCommentLine(lineMap, startLine, endLine);\n token.mrsfLineHighlight = hasCommentInRange(lineMap, startLine, endLine);\n\n if (token.type === \"table\") {\n const tableToken = token as Tokens.Table & TokenWithMrsf;\n tableToken.mrsfHeaderLine = startLine;\n tableToken.mrsfRowLines = tableToken.rows.map((_, index) => startLine + 2 + index);\n }\n\n return startLine + countLines(raw) - 1;\n}\n\nfunction stampListItems(token: Tokens.List & TokenWithMrsf, lineMap: LineMap): void {\n let currentLine = token.mrsfStartLine ?? 1;\n\n for (const item of token.items as ListItemWithMrsf[]) {\n const raw = typeof item.raw === \"string\" ? item.raw : \"\";\n const semantic = trimTrailingBlankLines(raw);\n const endLine = currentLine + countLines(semantic) - 1;\n item.mrsfStartLine = currentLine;\n item.mrsfEndLine = endLine;\n item.mrsfLine = firstCommentLine(lineMap, currentLine, endLine);\n item.mrsfLineHighlight = hasCommentInRange(lineMap, currentLine, endLine);\n\n stampTokens(item.tokens as TokenWithMrsf[], currentLine, lineMap);\n currentLine += countLines(raw) - 1;\n }\n}\n\nfunction stampTokens(tokens: TokenWithMrsf[], startLine: number, lineMap: LineMap): number {\n let currentLine = startLine;\n\n for (const token of tokens) {\n currentLine = stampBlock(token, currentLine, lineMap);\n\n if (token.type === \"blockquote\") {\n stampTokens((token as Tokens.Blockquote).tokens as TokenWithMrsf[], token.mrsfStartLine ?? currentLine, lineMap);\n } else if (token.type === \"list\") {\n stampListItems(token as Tokens.List & TokenWithMrsf, lineMap);\n }\n }\n\n return currentLine;\n}\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\nfunction buildAttrs(token: { mrsfStartLine?: number; mrsfEndLine?: number; mrsfLine?: number; mrsfLineHighlight?: boolean }, lineHighlight: boolean): string {\n if (token.mrsfStartLine == null || token.mrsfEndLine == null || token.mrsfLine == null) {\n return \"\";\n }\n\n const attrs = [\n `data-mrsf-line=\"${token.mrsfLine}\"`,\n `data-mrsf-start-line=\"${token.mrsfStartLine}\"`,\n `data-mrsf-end-line=\"${token.mrsfEndLine}\"`,\n ];\n\n if (lineHighlight && token.mrsfLineHighlight) {\n attrs.push('class=\"mrsf-line-highlight\"');\n }\n\n return attrs.length > 0 ? \" \" + attrs.join(\" \") : \"\";\n}\n\nfunction addAttrs(html: string, attrs: string, tagName?: string): string {\n if (!attrs) return html;\n const pattern = tagName\n ? new RegExp(`^<${tagName}(?=[\\\\s>])`, \"i\")\n : /^<([a-z0-9-]+)(?=[\\s>])/i;\n return html.replace(pattern, (match) => match + attrs);\n}\n\nfunction flattenThreads(lineMap: LineMap): CommentThread[] {\n const threads: CommentThread[] = [];\n for (const lineThreads of lineMap.values()) {\n threads.push(...lineThreads);\n }\n return threads;\n}\n\nfunction createDataContainer(options: MrsfPluginOptions, threads: CommentThread[]): string {\n const payload = JSON.stringify({ threads });\n if (options.dataContainer === \"element\") {\n const elementId = options.dataElementId || \"mrsf-comment-data\";\n return `<div id=\"${escapeAttribute(elementId)}\" data-mrsf-json=\"${escapeAttribute(payload)}\" aria-hidden=\"true\"></div>`;\n }\n\n return `<script type=\"application/mrsf+json\">${payload.replace(/</g, \"\\\\u003c\")}</script>`;\n}\n\nfunction renderAnnotatedTable(\n this: { parser: { parseInline: (tokens: Token[]) => string } },\n token: Tokens.Table & TokenWithMrsf,\n lineMap: LineMap,\n lineHighlight: boolean,\n): string {\n const baseHtml = tableRenderer.call(this, token);\n const rowLines = [token.mrsfHeaderLine, ...(token.mrsfRowLines ?? [])];\n let rowIndex = 0;\n\n return baseHtml.replace(/<tr>/g, () => {\n const line = rowLines[rowIndex++];\n if (line == null) return \"<tr>\";\n\n const hasComment = hasCommentInRange(lineMap, line, line);\n\n const attrs = [\n `data-mrsf-line=\"${line}\"`,\n `data-mrsf-start-line=\"${line}\"`,\n `data-mrsf-end-line=\"${line}\"`,\n ];\n if (lineHighlight && hasComment) {\n attrs.push('class=\"mrsf-line-highlight\"');\n }\n return `<tr ${attrs.join(\" \")}>`;\n });\n}\n\nexport function createMarkedMrsf(loader: CommentLoader) {\n return function markedMrsf(options: MrsfPluginOptions = {}): MarkedExtension {\n let currentLineMap: LineMap | null = null;\n let currentThreads: CommentThread[] = [];\n\n return {\n hooks: {\n processAllTokens(tokens) {\n const result = resolveComments(loader, options);\n if (!result) {\n currentLineMap = null;\n currentThreads = [];\n return tokens;\n }\n\n currentLineMap = result.lineMap;\n currentThreads = flattenThreads(result.lineMap);\n stampTokens(tokens as TokenWithMrsf[], 1, result.lineMap);\n return tokens;\n },\n postprocess(html) {\n if (!currentLineMap || currentThreads.length === 0) {\n return html;\n }\n return html + createDataContainer(options, currentThreads);\n },\n },\n renderer: {\n heading(token) {\n return addAttrs(headingRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), `h${token.depth}`);\n },\n paragraph(token) {\n return addAttrs(paragraphRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"p\");\n },\n code(token) {\n return addAttrs(codeRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"pre\");\n },\n blockquote(token) {\n return addAttrs(blockquoteRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"blockquote\");\n },\n listitem(token) {\n return addAttrs(listItemRenderer.call(this, token), buildAttrs(token as ListItemWithMrsf, options.lineHighlight ?? false), \"li\");\n },\n hr(token) {\n return addAttrs(hrRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"hr\");\n },\n table(token) {\n return renderAnnotatedTable.call(\n this,\n token as Tokens.Table & TokenWithMrsf,\n currentLineMap ?? new Map(),\n options.lineHighlight ?? false,\n );\n },\n },\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 * Browser-safe entry point for @mrsf/marked-mrsf.\n */\n\nimport type { MrsfPluginOptions } from \"./types.js\";\nimport { createMarkedMrsf } from \"./shared.js\";\n\nexport type { MrsfPluginOptions, SlimComment, CommentThread, LineMap, CommentLoader } from \"./types.js\";\n\nexport const markedMrsf = createMarkedMrsf((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/marked-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 markedMrsf;"],
5
- "mappings": ";AAIA,SAAS,cAA6D;;;ACKtE,SAAS,mBAAmB,SAAgC;AAC1D,QAAM,aAA6C,CAAA;AAEnD,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,QAAI,IAAI,WAAW,IAAI,GAAG;AACxB,iBAAW,GAAoB,IAAI;IACrC;EACF;AAEA,SAAO;AACT;AAKM,SAAU,eAAe,KAAiB;AAC9C,SAAO,IAAI,SAAS,IAAI,CAAC,OAAO;IAC9B,IAAI,EAAE;IACN,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE,YAAY;IACxB,cAAc,EAAE,gBAAgB;IAChC,YAAY,EAAE,cAAc;IAC5B,eAAe,EAAE,iBAAiB;IAClC,UAAU,CAAC,CAAC,EAAE;IACd,UAAU,EAAE,YAAY;IACxB,UAAU,EAAE,YAAY;IACxB,MAAM,EAAE,QAAQ;IAChB,WAAW,EAAE,aAAa;IAC1B,GAAG,mBAAmB,CAA4B;IAClD;AACJ;AAKM,SAAU,YAAY,UAAuB;AACjD,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,IAAG;AACxB,aAAW,KAAK,SAAS;AACvB,UAAM,OAAO,SAAS,IAAI,EAAE,QAAS,KAAK,CAAA;AAC1C,SAAK,KAAK,CAAC;AACX,aAAS,IAAI,EAAE,UAAW,IAAI;EAChC;AAEA,QAAM,UAAmB,oBAAI,IAAG;AAChC,aAAW,KAAK,cAAc;AAC5B,UAAM,OAAO,EAAE;AACf,UAAM,UAAU,QAAQ,IAAI,IAAI,KAAK,CAAA;AACrC,YAAQ,KAAK;MACX,SAAS;MACT,SAAS,SAAS,IAAI,EAAE,EAAE,KAAK,CAAA;KAChC;AACD,YAAQ,IAAI,MAAM,OAAO;EAC3B;AAEA,SAAO;AACT;AAMM,SAAU,gBACd,QACA,SACA,KAAa;AAEb,QAAM,eAAe,QAAQ,gBAAgB;AAE7C,QAAM,MAAM,OAAO,SAAS,GAAG;AAC/B,MAAI,CAAC,OAAO,CAAC,IAAI,YAAY,IAAI,SAAS,WAAW,GAAG;AACtD,WAAO;EACT;AAEA,MAAI,WAAW,eAAe,GAAG;AACjC,MAAI,CAAC,cAAc;AACjB,eAAW,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ;EAC/C;AAEA,MAAI,SAAS,WAAW;AAAG,WAAO;AAElC,QAAM,UAAU,YAAY,QAAQ;AACpC,SAAO,EAAE,SAAS,SAAQ;AAC5B;;;ADxEA,IAAM,gBAAgB,IAAI,OAAO;AACjC,IAAM,eAAe,cAAc;AAEnC,IAAM,qBAAqB,aAAa,UAAU;AAClD,IAAM,eAAe,aAAa,UAAU;AAC5C,IAAM,kBAAkB,aAAa,UAAU;AAC/C,IAAM,aAAa,aAAa,UAAU;AAC1C,IAAM,mBAAmB,aAAa,UAAU;AAChD,IAAM,oBAAoB,aAAa,UAAU;AACjD,IAAM,gBAAgB,aAAa,UAAU;AAE7C,SAAS,WAAW,OAAuB;AACzC,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,MAAM,MAAM,IAAI,EAAE;AAC3B;AAEA,SAAS,uBAAuB,OAAuB;AACrD,SAAO,MAAM,QAAQ,SAAS,EAAE;AAClC;AAEA,SAAS,iBAAiB,SAAkB,WAAmB,SAAyB;AACtF,WAAS,OAAO,WAAW,QAAQ,SAAS,QAAQ;AAClD,UAAM,UAAU,QAAQ,IAAI,IAAI;AAChC,QAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,SAAkB,WAAmB,SAA0B;AACxF,WAAS,OAAO,WAAW,QAAQ,SAAS,QAAQ;AAClD,UAAM,UAAU,QAAQ,IAAI,IAAI;AAChC,QAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,WAAW,OAAsB,WAAmB,SAA0B;AACrF,QAAM,MAAM,OAAO,MAAM,QAAQ,WAAW,MAAM,MAAM;AACxD,QAAM,WAAW,uBAAuB,GAAG;AAC3C,QAAM,UAAU,YAAY,WAAW,QAAQ,IAAI;AAEnD,QAAM,gBAAgB;AACtB,QAAM,cAAc;AACpB,QAAM,WAAW,iBAAiB,SAAS,WAAW,OAAO;AAC7D,QAAM,oBAAoB,kBAAkB,SAAS,WAAW,OAAO;AAEvE,MAAI,MAAM,SAAS,SAAS;AAC1B,UAAM,aAAa;AACnB,eAAW,iBAAiB;AAC5B,eAAW,eAAe,WAAW,KAAK,IAAI,CAAC,GAAG,UAAU,YAAY,IAAI,KAAK;AAAA,EACnF;AAEA,SAAO,YAAY,WAAW,GAAG,IAAI;AACvC;AAEA,SAAS,eAAe,OAAoC,SAAwB;AAClF,MAAI,cAAc,MAAM,iBAAiB;AAEzC,aAAW,QAAQ,MAAM,OAA6B;AACpD,UAAM,MAAM,OAAO,KAAK,QAAQ,WAAW,KAAK,MAAM;AACtD,UAAM,WAAW,uBAAuB,GAAG;AAC3C,UAAM,UAAU,cAAc,WAAW,QAAQ,IAAI;AACrD,SAAK,gBAAgB;AACrB,SAAK,cAAc;AACnB,SAAK,WAAW,iBAAiB,SAAS,aAAa,OAAO;AAC9D,SAAK,oBAAoB,kBAAkB,SAAS,aAAa,OAAO;AAExE,gBAAY,KAAK,QAA2B,aAAa,OAAO;AAChE,mBAAe,WAAW,GAAG,IAAI;AAAA,EACnC;AACF;AAEA,SAAS,YAAY,QAAyB,WAAmB,SAA0B;AACzF,MAAI,cAAc;AAElB,aAAW,SAAS,QAAQ;AAC1B,kBAAc,WAAW,OAAO,aAAa,OAAO;AAEpD,QAAI,MAAM,SAAS,cAAc;AAC/B,kBAAa,MAA4B,QAA2B,MAAM,iBAAiB,aAAa,OAAO;AAAA,IACjH,WAAW,MAAM,SAAS,QAAQ;AAChC,qBAAe,OAAsC,OAAO;AAAA,IAC9D;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,gBAAgB,OAAuB;AAC9C,SAAO,MACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ;AAC3B;AAEA,SAAS,WAAW,OAAyG,eAAgC;AAC3J,MAAI,MAAM,iBAAiB,QAAQ,MAAM,eAAe,QAAQ,MAAM,YAAY,MAAM;AACtF,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ;AAAA,IACZ,mBAAmB,MAAM,QAAQ;AAAA,IACjC,yBAAyB,MAAM,aAAa;AAAA,IAC5C,uBAAuB,MAAM,WAAW;AAAA,EAC1C;AAEA,MAAI,iBAAiB,MAAM,mBAAmB;AAC5C,UAAM,KAAK,6BAA6B;AAAA,EAC1C;AAEA,SAAO,MAAM,SAAS,IAAI,MAAM,MAAM,KAAK,GAAG,IAAI;AACpD;AAEA,SAAS,SAAS,MAAc,OAAe,SAA0B;AACvE,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,UAAU,UACZ,IAAI,OAAO,KAAK,OAAO,cAAc,GAAG,IACxC;AACJ,SAAO,KAAK,QAAQ,SAAS,CAAC,UAAU,QAAQ,KAAK;AACvD;AAEA,SAAS,eAAe,SAAmC;AACzD,QAAM,UAA2B,CAAC;AAClC,aAAW,eAAe,QAAQ,OAAO,GAAG;AAC1C,YAAQ,KAAK,GAAG,WAAW;AAAA,EAC7B;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,SAA4B,SAAkC;AACzF,QAAM,UAAU,KAAK,UAAU,EAAE,QAAQ,CAAC;AAC1C,MAAI,QAAQ,kBAAkB,WAAW;AACvC,UAAM,YAAY,QAAQ,iBAAiB;AAC3C,WAAO,YAAY,gBAAgB,SAAS,CAAC,qBAAqB,gBAAgB,OAAO,CAAC;AAAA,EAC5F;AAEA,SAAO,wCAAwC,QAAQ,QAAQ,MAAM,SAAS,CAAC;AACjF;AAEA,SAAS,qBAEP,OACA,SACA,eACQ;AACR,QAAM,WAAW,cAAc,KAAK,MAAM,KAAK;AAC/C,QAAM,WAAW,CAAC,MAAM,gBAAgB,GAAI,MAAM,gBAAgB,CAAC,CAAE;AACrE,MAAI,WAAW;AAEf,SAAO,SAAS,QAAQ,SAAS,MAAM;AACrC,UAAM,OAAO,SAAS,UAAU;AAChC,QAAI,QAAQ,KAAM,QAAO;AAEzB,UAAM,aAAa,kBAAkB,SAAS,MAAM,IAAI;AAExD,UAAM,QAAQ;AAAA,MACZ,mBAAmB,IAAI;AAAA,MACvB,yBAAyB,IAAI;AAAA,MAC7B,uBAAuB,IAAI;AAAA,IAC7B;AACA,QAAI,iBAAiB,YAAY;AAC/B,YAAM,KAAK,6BAA6B;AAAA,IAC1C;AACA,WAAO,OAAO,MAAM,KAAK,GAAG,CAAC;AAAA,EAC/B,CAAC;AACH;AAEO,SAAS,iBAAiB,QAAuB;AACtD,SAAO,SAASA,YAAW,UAA6B,CAAC,GAAoB;AAC3E,QAAI,iBAAiC;AACrC,QAAI,iBAAkC,CAAC;AAEvC,WAAO;AAAA,MACL,OAAO;AAAA,QACL,iBAAiB,QAAQ;AACvB,gBAAM,SAAS,gBAAgB,QAAQ,OAAO;AAC9C,cAAI,CAAC,QAAQ;AACX,6BAAiB;AACjB,6BAAiB,CAAC;AAClB,mBAAO;AAAA,UACT;AAEA,2BAAiB,OAAO;AACxB,2BAAiB,eAAe,OAAO,OAAO;AAC9C,sBAAY,QAA2B,GAAG,OAAO,OAAO;AACxD,iBAAO;AAAA,QACT;AAAA,QACA,YAAY,MAAM;AAChB,cAAI,CAAC,kBAAkB,eAAe,WAAW,GAAG;AAClD,mBAAO;AAAA,UACT;AACA,iBAAO,OAAO,oBAAoB,SAAS,cAAc;AAAA,QAC3D;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,QAAQ,OAAO;AACb,iBAAO,SAAS,gBAAgB,KAAK,MAAM,KAAK,GAAG,WAAW,OAAwB,QAAQ,iBAAiB,KAAK,GAAG,IAAI,MAAM,KAAK,EAAE;AAAA,QAC1I;AAAA,QACA,UAAU,OAAO;AACf,iBAAO,SAAS,kBAAkB,KAAK,MAAM,KAAK,GAAG,WAAW,OAAwB,QAAQ,iBAAiB,KAAK,GAAG,GAAG;AAAA,QAC9H;AAAA,QACA,KAAK,OAAO;AACV,iBAAO,SAAS,aAAa,KAAK,MAAM,KAAK,GAAG,WAAW,OAAwB,QAAQ,iBAAiB,KAAK,GAAG,KAAK;AAAA,QAC3H;AAAA,QACA,WAAW,OAAO;AAChB,iBAAO,SAAS,mBAAmB,KAAK,MAAM,KAAK,GAAG,WAAW,OAAwB,QAAQ,iBAAiB,KAAK,GAAG,YAAY;AAAA,QACxI;AAAA,QACA,SAAS,OAAO;AACd,iBAAO,SAAS,iBAAiB,KAAK,MAAM,KAAK,GAAG,WAAW,OAA2B,QAAQ,iBAAiB,KAAK,GAAG,IAAI;AAAA,QACjI;AAAA,QACA,GAAG,OAAO;AACR,iBAAO,SAAS,WAAW,KAAK,MAAM,KAAK,GAAG,WAAW,OAAwB,QAAQ,iBAAiB,KAAK,GAAG,IAAI;AAAA,QACxH;AAAA,QACA,MAAM,OAAO;AACX,iBAAO,qBAAqB;AAAA,YAC1B;AAAA,YACA;AAAA,YACA,kBAAkB,oBAAI,IAAI;AAAA,YAC1B,QAAQ,iBAAiB;AAAA,UAC3B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AEpPO,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;",
3
+ "sources": ["../src/shared.ts", "../src/comments.ts", "../src/browser.ts"],
4
+ "sourcesContent": ["/**\n * Shared logic for @mrsf/marked-mrsf.\n */\n\nimport { Marked, type MarkedExtension, type Token, type Tokens } from \"marked\";\nimport { resolveComments } from \"./comments.js\";\nimport type { CommentLoader, CommentThread, LineMap, MrsfPluginOptions } from \"./types.js\";\n\ntype TokenWithMrsf = Token & {\n mrsfStartLine?: number;\n mrsfEndLine?: number;\n mrsfLine?: number;\n mrsfLineHighlight?: boolean;\n mrsfHeaderLine?: number;\n mrsfRowLines?: number[];\n};\n\ntype ListItemWithMrsf = Tokens.ListItem & {\n mrsfStartLine?: number;\n mrsfEndLine?: number;\n mrsfLine?: number;\n mrsfLineHighlight?: boolean;\n};\n\nconst markedRuntime = new Marked();\nconst BaseRenderer = markedRuntime.Renderer;\n\nconst blockquoteRenderer = BaseRenderer.prototype.blockquote;\nconst codeRenderer = BaseRenderer.prototype.code;\nconst headingRenderer = BaseRenderer.prototype.heading;\nconst hrRenderer = BaseRenderer.prototype.hr;\nconst listItemRenderer = BaseRenderer.prototype.listitem;\nconst paragraphRenderer = BaseRenderer.prototype.paragraph;\nconst tableRenderer = BaseRenderer.prototype.table;\n\nfunction countLines(value: string): number {\n if (!value) return 1;\n return value.split(\"\\n\").length;\n}\n\nfunction trimTrailingBlankLines(value: string): string {\n return value.replace(/\\n+$/g, \"\");\n}\n\nfunction firstCommentLine(lineMap: LineMap, startLine: number, endLine: number): number {\n for (let line = startLine; line <= endLine; line++) {\n const threads = lineMap.get(line);\n if (threads && threads.length > 0) {\n return line;\n }\n }\n return startLine;\n}\n\nfunction hasCommentInRange(lineMap: LineMap, startLine: number, endLine: number): boolean {\n for (let line = startLine; line <= endLine; line++) {\n const threads = lineMap.get(line);\n if (threads && threads.length > 0) {\n return true;\n }\n }\n return false;\n}\n\nfunction stampBlock(token: TokenWithMrsf, startLine: number, lineMap: LineMap): number {\n const raw = typeof token.raw === \"string\" ? token.raw : \"\";\n const semantic = trimTrailingBlankLines(raw);\n const endLine = startLine + countLines(semantic) - 1;\n\n token.mrsfStartLine = startLine;\n token.mrsfEndLine = endLine;\n token.mrsfLine = firstCommentLine(lineMap, startLine, endLine);\n token.mrsfLineHighlight = hasCommentInRange(lineMap, startLine, endLine);\n\n if (token.type === \"table\") {\n const tableToken = token as Tokens.Table & TokenWithMrsf;\n tableToken.mrsfHeaderLine = startLine;\n tableToken.mrsfRowLines = tableToken.rows.map((_, index) => startLine + 2 + index);\n }\n\n return startLine + countLines(raw) - 1;\n}\n\nfunction stampListItems(token: Tokens.List & TokenWithMrsf, lineMap: LineMap): void {\n let currentLine = token.mrsfStartLine ?? 1;\n\n for (const item of token.items as ListItemWithMrsf[]) {\n const raw = typeof item.raw === \"string\" ? item.raw : \"\";\n const semantic = trimTrailingBlankLines(raw);\n const endLine = currentLine + countLines(semantic) - 1;\n item.mrsfStartLine = currentLine;\n item.mrsfEndLine = endLine;\n item.mrsfLine = firstCommentLine(lineMap, currentLine, endLine);\n item.mrsfLineHighlight = hasCommentInRange(lineMap, currentLine, endLine);\n\n stampTokens(item.tokens as TokenWithMrsf[], currentLine, lineMap);\n currentLine += countLines(raw) - 1;\n }\n}\n\nfunction stampTokens(tokens: TokenWithMrsf[], startLine: number, lineMap: LineMap): number {\n let currentLine = startLine;\n\n for (const token of tokens) {\n currentLine = stampBlock(token, currentLine, lineMap);\n\n if (token.type === \"blockquote\") {\n stampTokens((token as Tokens.Blockquote).tokens as TokenWithMrsf[], token.mrsfStartLine ?? currentLine, lineMap);\n } else if (token.type === \"list\") {\n stampListItems(token as Tokens.List & TokenWithMrsf, lineMap);\n }\n }\n\n return currentLine;\n}\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\nfunction buildAttrs(token: { mrsfStartLine?: number; mrsfEndLine?: number; mrsfLine?: number; mrsfLineHighlight?: boolean }, lineHighlight: boolean): string {\n if (token.mrsfStartLine == null || token.mrsfEndLine == null || token.mrsfLine == null) {\n return \"\";\n }\n\n const attrs = [\n `data-mrsf-line=\"${token.mrsfLine}\"`,\n `data-mrsf-start-line=\"${token.mrsfStartLine}\"`,\n `data-mrsf-end-line=\"${token.mrsfEndLine}\"`,\n ];\n\n if (lineHighlight && token.mrsfLineHighlight) {\n attrs.push('class=\"mrsf-line-highlight\"');\n }\n\n return attrs.length > 0 ? \" \" + attrs.join(\" \") : \"\";\n}\n\nfunction addAttrs(html: string, attrs: string, tagName?: string): string {\n if (!attrs) return html;\n const pattern = tagName\n ? new RegExp(`^<${tagName}(?=[\\\\s>])`, \"i\")\n : /^<([a-z0-9-]+)(?=[\\s>])/i;\n return html.replace(pattern, (match) => match + attrs);\n}\n\nfunction flattenThreads(lineMap: LineMap): CommentThread[] {\n const threads: CommentThread[] = [];\n for (const lineThreads of lineMap.values()) {\n threads.push(...lineThreads);\n }\n return threads;\n}\n\nfunction createDataContainer(options: MrsfPluginOptions, threads: CommentThread[]): string {\n const payload = JSON.stringify({ threads });\n if (options.dataContainer === \"element\") {\n const elementId = options.dataElementId || \"mrsf-comment-data\";\n return `<div id=\"${escapeAttribute(elementId)}\" data-mrsf-json=\"${escapeAttribute(payload)}\" aria-hidden=\"true\"></div>`;\n }\n\n return `<script type=\"application/mrsf+json\">${payload.replace(/</g, \"\\\\u003c\")}</script>`;\n}\n\nfunction renderAnnotatedTable(\n this: { parser: { parseInline: (tokens: Token[]) => string } },\n token: Tokens.Table & TokenWithMrsf,\n lineMap: LineMap,\n lineHighlight: boolean,\n): string {\n const baseHtml = tableRenderer.call(this, token);\n const rowLines = [token.mrsfHeaderLine, ...(token.mrsfRowLines ?? [])];\n let rowIndex = 0;\n\n return baseHtml.replace(/<tr>/g, () => {\n const line = rowLines[rowIndex++];\n if (line == null) return \"<tr>\";\n\n const hasComment = hasCommentInRange(lineMap, line, line);\n\n const attrs = [\n `data-mrsf-line=\"${line}\"`,\n `data-mrsf-start-line=\"${line}\"`,\n `data-mrsf-end-line=\"${line}\"`,\n ];\n if (lineHighlight && hasComment) {\n attrs.push('class=\"mrsf-line-highlight\"');\n }\n return `<tr ${attrs.join(\" \")}>`;\n });\n}\n\nexport function createMarkedMrsf(loader: CommentLoader) {\n return function markedMrsf(options: MrsfPluginOptions = {}): MarkedExtension {\n let currentLineMap: LineMap | null = null;\n let currentThreads: CommentThread[] = [];\n\n return {\n hooks: {\n processAllTokens(tokens) {\n const result = resolveComments(loader, options);\n if (!result) {\n currentLineMap = null;\n currentThreads = [];\n return tokens;\n }\n\n currentLineMap = result.lineMap;\n currentThreads = flattenThreads(result.lineMap);\n stampTokens(tokens as TokenWithMrsf[], 1, result.lineMap);\n return tokens;\n },\n postprocess(html) {\n if (!currentLineMap || currentThreads.length === 0) {\n return html;\n }\n return html + createDataContainer(options, currentThreads);\n },\n },\n renderer: {\n heading(token) {\n return addAttrs(headingRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), `h${token.depth}`);\n },\n paragraph(token) {\n return addAttrs(paragraphRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"p\");\n },\n code(token) {\n return addAttrs(codeRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"pre\");\n },\n blockquote(token) {\n return addAttrs(blockquoteRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"blockquote\");\n },\n listitem(token) {\n return addAttrs(listItemRenderer.call(this, token), buildAttrs(token as ListItemWithMrsf, options.lineHighlight ?? false), \"li\");\n },\n hr(token) {\n return addAttrs(hrRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"hr\");\n },\n table(token) {\n return renderAnnotatedTable.call(\n this,\n token as Tokens.Table & TokenWithMrsf,\n currentLineMap ?? new Map(),\n options.lineHighlight ?? false,\n );\n },\n },\n };\n };\n}\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 * Browser-safe entry point for @mrsf/marked-mrsf.\n */\n\nimport type { MrsfPluginOptions } from \"./types.js\";\nimport { createMarkedMrsf } from \"./shared.js\";\n\nexport type { MrsfPluginOptions, SlimComment, CommentThread, LineMap, CommentLoader } from \"./types.js\";\n\nexport const markedMrsf = createMarkedMrsf((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/marked-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 markedMrsf;"],
5
+ "mappings": "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",
6
6
  "names": ["markedMrsf"]
7
7
  }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Shared comment loading and grouping logic for MRSF rendering plugins.
3
+ */
4
+ import type { MrsfDocument } from "@mrsf/cli";
5
+ import type { MrsfPluginOptions, SlimComment, LineMap, CommentLoader } from "./types.js";
6
+ export type { CommentLoader };
7
+ /**
8
+ * Convert an MrsfDocument into a slim comment array.
9
+ */
10
+ export declare function toSlimComments(doc: MrsfDocument): SlimComment[];
11
+ /**
12
+ * Group comments by line number, threading replies under parents.
13
+ */
14
+ export declare function groupByLine(comments: SlimComment[]): LineMap;
15
+ /**
16
+ * Resolve options into a filtered LineMap ready for rendering.
17
+ * Returns null if there are no comments to render.
18
+ */
19
+ export declare function resolveComments(loader: CommentLoader, options: MrsfPluginOptions, env?: unknown): {
20
+ lineMap: LineMap;
21
+ comments: SlimComment[];
22
+ } | null;
23
+ //# sourceMappingURL=comments.d.ts.map
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { parseSidecarContent } from "@mrsf/cli";
6
6
  // src/shared.ts
7
7
  import { Marked } from "marked";
8
8
 
9
- // ../shared/dist/comments.js
9
+ // src/comments.ts
10
10
  function getExtensionFields(comment) {
11
11
  const extensions = {};
12
12
  for (const [key, value] of Object.entries(comment)) {
@@ -65,8 +65,7 @@ function resolveComments(loader, options, env) {
65
65
  if (!showResolved) {
66
66
  comments = comments.filter((c) => !c.resolved);
67
67
  }
68
- if (comments.length === 0)
69
- return null;
68
+ if (comments.length === 0) return null;
70
69
  const lineMap = groupByLine(comments);
71
70
  return { lineMap, comments };
72
71
  }
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/index.ts", "../src/shared.ts", "../../shared/src/comments.ts"],
4
- "sourcesContent": ["/**\n * @mrsf/marked-mrsf \u2014 Marked plugin for MRSF review comments.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { parseSidecarContent } from \"@mrsf/cli\";\nimport type { MrsfPluginOptions } from \"./types.js\";\nimport { createMarkedMrsf } from \"./shared.js\";\n\nexport type { MrsfPluginOptions, SlimComment, CommentThread, LineMap, CommentLoader } from \"./types.js\";\n\nexport const markedMrsf = createMarkedMrsf((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) {\n try {\n const abs = path.resolve(options.cwd || process.cwd(), options.sidecarPath);\n const content = readFileSync(abs, \"utf-8\");\n return parseSidecarContent(content, abs);\n } catch {\n return null;\n }\n }\n\n if (options.documentPath) {\n try {\n const cwd = options.cwd || process.cwd();\n const abs = path.resolve(cwd, options.documentPath);\n const yamlPath = abs + \".review.yaml\";\n const jsonPath = abs + \".review.json\";\n\n let raw: string | null = null;\n let hint: string | null = null;\n try {\n raw = readFileSync(yamlPath, \"utf-8\");\n hint = yamlPath;\n } catch {\n try {\n raw = readFileSync(jsonPath, \"utf-8\");\n hint = jsonPath;\n } catch {\n return null;\n }\n }\n\n if (!raw) return null;\n return parseSidecarContent(raw, hint!);\n } catch {\n return null;\n }\n }\n\n return null;\n});\n\nexport default markedMrsf;", "/**\n * Shared logic for @mrsf/marked-mrsf.\n */\n\nimport { Marked, type MarkedExtension, type Token, type Tokens } from \"marked\";\nimport { resolveComments } from \"@mrsf/plugin-shared\";\nimport type { CommentLoader, CommentThread, LineMap, MrsfPluginOptions } from \"./types.js\";\n\ntype TokenWithMrsf = Token & {\n mrsfStartLine?: number;\n mrsfEndLine?: number;\n mrsfLine?: number;\n mrsfLineHighlight?: boolean;\n mrsfHeaderLine?: number;\n mrsfRowLines?: number[];\n};\n\ntype ListItemWithMrsf = Tokens.ListItem & {\n mrsfStartLine?: number;\n mrsfEndLine?: number;\n mrsfLine?: number;\n mrsfLineHighlight?: boolean;\n};\n\nconst markedRuntime = new Marked();\nconst BaseRenderer = markedRuntime.Renderer;\n\nconst blockquoteRenderer = BaseRenderer.prototype.blockquote;\nconst codeRenderer = BaseRenderer.prototype.code;\nconst headingRenderer = BaseRenderer.prototype.heading;\nconst hrRenderer = BaseRenderer.prototype.hr;\nconst listItemRenderer = BaseRenderer.prototype.listitem;\nconst paragraphRenderer = BaseRenderer.prototype.paragraph;\nconst tableRenderer = BaseRenderer.prototype.table;\n\nfunction countLines(value: string): number {\n if (!value) return 1;\n return value.split(\"\\n\").length;\n}\n\nfunction trimTrailingBlankLines(value: string): string {\n return value.replace(/\\n+$/g, \"\");\n}\n\nfunction firstCommentLine(lineMap: LineMap, startLine: number, endLine: number): number {\n for (let line = startLine; line <= endLine; line++) {\n const threads = lineMap.get(line);\n if (threads && threads.length > 0) {\n return line;\n }\n }\n return startLine;\n}\n\nfunction hasCommentInRange(lineMap: LineMap, startLine: number, endLine: number): boolean {\n for (let line = startLine; line <= endLine; line++) {\n const threads = lineMap.get(line);\n if (threads && threads.length > 0) {\n return true;\n }\n }\n return false;\n}\n\nfunction stampBlock(token: TokenWithMrsf, startLine: number, lineMap: LineMap): number {\n const raw = typeof token.raw === \"string\" ? token.raw : \"\";\n const semantic = trimTrailingBlankLines(raw);\n const endLine = startLine + countLines(semantic) - 1;\n\n token.mrsfStartLine = startLine;\n token.mrsfEndLine = endLine;\n token.mrsfLine = firstCommentLine(lineMap, startLine, endLine);\n token.mrsfLineHighlight = hasCommentInRange(lineMap, startLine, endLine);\n\n if (token.type === \"table\") {\n const tableToken = token as Tokens.Table & TokenWithMrsf;\n tableToken.mrsfHeaderLine = startLine;\n tableToken.mrsfRowLines = tableToken.rows.map((_, index) => startLine + 2 + index);\n }\n\n return startLine + countLines(raw) - 1;\n}\n\nfunction stampListItems(token: Tokens.List & TokenWithMrsf, lineMap: LineMap): void {\n let currentLine = token.mrsfStartLine ?? 1;\n\n for (const item of token.items as ListItemWithMrsf[]) {\n const raw = typeof item.raw === \"string\" ? item.raw : \"\";\n const semantic = trimTrailingBlankLines(raw);\n const endLine = currentLine + countLines(semantic) - 1;\n item.mrsfStartLine = currentLine;\n item.mrsfEndLine = endLine;\n item.mrsfLine = firstCommentLine(lineMap, currentLine, endLine);\n item.mrsfLineHighlight = hasCommentInRange(lineMap, currentLine, endLine);\n\n stampTokens(item.tokens as TokenWithMrsf[], currentLine, lineMap);\n currentLine += countLines(raw) - 1;\n }\n}\n\nfunction stampTokens(tokens: TokenWithMrsf[], startLine: number, lineMap: LineMap): number {\n let currentLine = startLine;\n\n for (const token of tokens) {\n currentLine = stampBlock(token, currentLine, lineMap);\n\n if (token.type === \"blockquote\") {\n stampTokens((token as Tokens.Blockquote).tokens as TokenWithMrsf[], token.mrsfStartLine ?? currentLine, lineMap);\n } else if (token.type === \"list\") {\n stampListItems(token as Tokens.List & TokenWithMrsf, lineMap);\n }\n }\n\n return currentLine;\n}\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\nfunction buildAttrs(token: { mrsfStartLine?: number; mrsfEndLine?: number; mrsfLine?: number; mrsfLineHighlight?: boolean }, lineHighlight: boolean): string {\n if (token.mrsfStartLine == null || token.mrsfEndLine == null || token.mrsfLine == null) {\n return \"\";\n }\n\n const attrs = [\n `data-mrsf-line=\"${token.mrsfLine}\"`,\n `data-mrsf-start-line=\"${token.mrsfStartLine}\"`,\n `data-mrsf-end-line=\"${token.mrsfEndLine}\"`,\n ];\n\n if (lineHighlight && token.mrsfLineHighlight) {\n attrs.push('class=\"mrsf-line-highlight\"');\n }\n\n return attrs.length > 0 ? \" \" + attrs.join(\" \") : \"\";\n}\n\nfunction addAttrs(html: string, attrs: string, tagName?: string): string {\n if (!attrs) return html;\n const pattern = tagName\n ? new RegExp(`^<${tagName}(?=[\\\\s>])`, \"i\")\n : /^<([a-z0-9-]+)(?=[\\s>])/i;\n return html.replace(pattern, (match) => match + attrs);\n}\n\nfunction flattenThreads(lineMap: LineMap): CommentThread[] {\n const threads: CommentThread[] = [];\n for (const lineThreads of lineMap.values()) {\n threads.push(...lineThreads);\n }\n return threads;\n}\n\nfunction createDataContainer(options: MrsfPluginOptions, threads: CommentThread[]): string {\n const payload = JSON.stringify({ threads });\n if (options.dataContainer === \"element\") {\n const elementId = options.dataElementId || \"mrsf-comment-data\";\n return `<div id=\"${escapeAttribute(elementId)}\" data-mrsf-json=\"${escapeAttribute(payload)}\" aria-hidden=\"true\"></div>`;\n }\n\n return `<script type=\"application/mrsf+json\">${payload.replace(/</g, \"\\\\u003c\")}</script>`;\n}\n\nfunction renderAnnotatedTable(\n this: { parser: { parseInline: (tokens: Token[]) => string } },\n token: Tokens.Table & TokenWithMrsf,\n lineMap: LineMap,\n lineHighlight: boolean,\n): string {\n const baseHtml = tableRenderer.call(this, token);\n const rowLines = [token.mrsfHeaderLine, ...(token.mrsfRowLines ?? [])];\n let rowIndex = 0;\n\n return baseHtml.replace(/<tr>/g, () => {\n const line = rowLines[rowIndex++];\n if (line == null) return \"<tr>\";\n\n const hasComment = hasCommentInRange(lineMap, line, line);\n\n const attrs = [\n `data-mrsf-line=\"${line}\"`,\n `data-mrsf-start-line=\"${line}\"`,\n `data-mrsf-end-line=\"${line}\"`,\n ];\n if (lineHighlight && hasComment) {\n attrs.push('class=\"mrsf-line-highlight\"');\n }\n return `<tr ${attrs.join(\" \")}>`;\n });\n}\n\nexport function createMarkedMrsf(loader: CommentLoader) {\n return function markedMrsf(options: MrsfPluginOptions = {}): MarkedExtension {\n let currentLineMap: LineMap | null = null;\n let currentThreads: CommentThread[] = [];\n\n return {\n hooks: {\n processAllTokens(tokens) {\n const result = resolveComments(loader, options);\n if (!result) {\n currentLineMap = null;\n currentThreads = [];\n return tokens;\n }\n\n currentLineMap = result.lineMap;\n currentThreads = flattenThreads(result.lineMap);\n stampTokens(tokens as TokenWithMrsf[], 1, result.lineMap);\n return tokens;\n },\n postprocess(html) {\n if (!currentLineMap || currentThreads.length === 0) {\n return html;\n }\n return html + createDataContainer(options, currentThreads);\n },\n },\n renderer: {\n heading(token) {\n return addAttrs(headingRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), `h${token.depth}`);\n },\n paragraph(token) {\n return addAttrs(paragraphRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"p\");\n },\n code(token) {\n return addAttrs(codeRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"pre\");\n },\n blockquote(token) {\n return addAttrs(blockquoteRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"blockquote\");\n },\n listitem(token) {\n return addAttrs(listItemRenderer.call(this, token), buildAttrs(token as ListItemWithMrsf, options.lineHighlight ?? false), \"li\");\n },\n hr(token) {\n return addAttrs(hrRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"hr\");\n },\n table(token) {\n return renderAnnotatedTable.call(\n this,\n token as Tokens.Table & TokenWithMrsf,\n currentLineMap ?? new Map(),\n options.lineHighlight ?? false,\n );\n },\n },\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"],
5
- "mappings": "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",
3
+ "sources": ["../src/index.ts", "../src/shared.ts", "../src/comments.ts"],
4
+ "sourcesContent": ["/**\n * @mrsf/marked-mrsf \u2014 Marked plugin for MRSF review comments.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { parseSidecarContent } from \"@mrsf/cli\";\nimport type { MrsfPluginOptions } from \"./types.js\";\nimport { createMarkedMrsf } from \"./shared.js\";\n\nexport type { MrsfPluginOptions, SlimComment, CommentThread, LineMap, CommentLoader } from \"./types.js\";\n\nexport const markedMrsf = createMarkedMrsf((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) {\n try {\n const abs = path.resolve(options.cwd || process.cwd(), options.sidecarPath);\n const content = readFileSync(abs, \"utf-8\");\n return parseSidecarContent(content, abs);\n } catch {\n return null;\n }\n }\n\n if (options.documentPath) {\n try {\n const cwd = options.cwd || process.cwd();\n const abs = path.resolve(cwd, options.documentPath);\n const yamlPath = abs + \".review.yaml\";\n const jsonPath = abs + \".review.json\";\n\n let raw: string | null = null;\n let hint: string | null = null;\n try {\n raw = readFileSync(yamlPath, \"utf-8\");\n hint = yamlPath;\n } catch {\n try {\n raw = readFileSync(jsonPath, \"utf-8\");\n hint = jsonPath;\n } catch {\n return null;\n }\n }\n\n if (!raw) return null;\n return parseSidecarContent(raw, hint!);\n } catch {\n return null;\n }\n }\n\n return null;\n});\n\nexport default markedMrsf;", "/**\n * Shared logic for @mrsf/marked-mrsf.\n */\n\nimport { Marked, type MarkedExtension, type Token, type Tokens } from \"marked\";\nimport { resolveComments } from \"./comments.js\";\nimport type { CommentLoader, CommentThread, LineMap, MrsfPluginOptions } from \"./types.js\";\n\ntype TokenWithMrsf = Token & {\n mrsfStartLine?: number;\n mrsfEndLine?: number;\n mrsfLine?: number;\n mrsfLineHighlight?: boolean;\n mrsfHeaderLine?: number;\n mrsfRowLines?: number[];\n};\n\ntype ListItemWithMrsf = Tokens.ListItem & {\n mrsfStartLine?: number;\n mrsfEndLine?: number;\n mrsfLine?: number;\n mrsfLineHighlight?: boolean;\n};\n\nconst markedRuntime = new Marked();\nconst BaseRenderer = markedRuntime.Renderer;\n\nconst blockquoteRenderer = BaseRenderer.prototype.blockquote;\nconst codeRenderer = BaseRenderer.prototype.code;\nconst headingRenderer = BaseRenderer.prototype.heading;\nconst hrRenderer = BaseRenderer.prototype.hr;\nconst listItemRenderer = BaseRenderer.prototype.listitem;\nconst paragraphRenderer = BaseRenderer.prototype.paragraph;\nconst tableRenderer = BaseRenderer.prototype.table;\n\nfunction countLines(value: string): number {\n if (!value) return 1;\n return value.split(\"\\n\").length;\n}\n\nfunction trimTrailingBlankLines(value: string): string {\n return value.replace(/\\n+$/g, \"\");\n}\n\nfunction firstCommentLine(lineMap: LineMap, startLine: number, endLine: number): number {\n for (let line = startLine; line <= endLine; line++) {\n const threads = lineMap.get(line);\n if (threads && threads.length > 0) {\n return line;\n }\n }\n return startLine;\n}\n\nfunction hasCommentInRange(lineMap: LineMap, startLine: number, endLine: number): boolean {\n for (let line = startLine; line <= endLine; line++) {\n const threads = lineMap.get(line);\n if (threads && threads.length > 0) {\n return true;\n }\n }\n return false;\n}\n\nfunction stampBlock(token: TokenWithMrsf, startLine: number, lineMap: LineMap): number {\n const raw = typeof token.raw === \"string\" ? token.raw : \"\";\n const semantic = trimTrailingBlankLines(raw);\n const endLine = startLine + countLines(semantic) - 1;\n\n token.mrsfStartLine = startLine;\n token.mrsfEndLine = endLine;\n token.mrsfLine = firstCommentLine(lineMap, startLine, endLine);\n token.mrsfLineHighlight = hasCommentInRange(lineMap, startLine, endLine);\n\n if (token.type === \"table\") {\n const tableToken = token as Tokens.Table & TokenWithMrsf;\n tableToken.mrsfHeaderLine = startLine;\n tableToken.mrsfRowLines = tableToken.rows.map((_, index) => startLine + 2 + index);\n }\n\n return startLine + countLines(raw) - 1;\n}\n\nfunction stampListItems(token: Tokens.List & TokenWithMrsf, lineMap: LineMap): void {\n let currentLine = token.mrsfStartLine ?? 1;\n\n for (const item of token.items as ListItemWithMrsf[]) {\n const raw = typeof item.raw === \"string\" ? item.raw : \"\";\n const semantic = trimTrailingBlankLines(raw);\n const endLine = currentLine + countLines(semantic) - 1;\n item.mrsfStartLine = currentLine;\n item.mrsfEndLine = endLine;\n item.mrsfLine = firstCommentLine(lineMap, currentLine, endLine);\n item.mrsfLineHighlight = hasCommentInRange(lineMap, currentLine, endLine);\n\n stampTokens(item.tokens as TokenWithMrsf[], currentLine, lineMap);\n currentLine += countLines(raw) - 1;\n }\n}\n\nfunction stampTokens(tokens: TokenWithMrsf[], startLine: number, lineMap: LineMap): number {\n let currentLine = startLine;\n\n for (const token of tokens) {\n currentLine = stampBlock(token, currentLine, lineMap);\n\n if (token.type === \"blockquote\") {\n stampTokens((token as Tokens.Blockquote).tokens as TokenWithMrsf[], token.mrsfStartLine ?? currentLine, lineMap);\n } else if (token.type === \"list\") {\n stampListItems(token as Tokens.List & TokenWithMrsf, lineMap);\n }\n }\n\n return currentLine;\n}\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\nfunction buildAttrs(token: { mrsfStartLine?: number; mrsfEndLine?: number; mrsfLine?: number; mrsfLineHighlight?: boolean }, lineHighlight: boolean): string {\n if (token.mrsfStartLine == null || token.mrsfEndLine == null || token.mrsfLine == null) {\n return \"\";\n }\n\n const attrs = [\n `data-mrsf-line=\"${token.mrsfLine}\"`,\n `data-mrsf-start-line=\"${token.mrsfStartLine}\"`,\n `data-mrsf-end-line=\"${token.mrsfEndLine}\"`,\n ];\n\n if (lineHighlight && token.mrsfLineHighlight) {\n attrs.push('class=\"mrsf-line-highlight\"');\n }\n\n return attrs.length > 0 ? \" \" + attrs.join(\" \") : \"\";\n}\n\nfunction addAttrs(html: string, attrs: string, tagName?: string): string {\n if (!attrs) return html;\n const pattern = tagName\n ? new RegExp(`^<${tagName}(?=[\\\\s>])`, \"i\")\n : /^<([a-z0-9-]+)(?=[\\s>])/i;\n return html.replace(pattern, (match) => match + attrs);\n}\n\nfunction flattenThreads(lineMap: LineMap): CommentThread[] {\n const threads: CommentThread[] = [];\n for (const lineThreads of lineMap.values()) {\n threads.push(...lineThreads);\n }\n return threads;\n}\n\nfunction createDataContainer(options: MrsfPluginOptions, threads: CommentThread[]): string {\n const payload = JSON.stringify({ threads });\n if (options.dataContainer === \"element\") {\n const elementId = options.dataElementId || \"mrsf-comment-data\";\n return `<div id=\"${escapeAttribute(elementId)}\" data-mrsf-json=\"${escapeAttribute(payload)}\" aria-hidden=\"true\"></div>`;\n }\n\n return `<script type=\"application/mrsf+json\">${payload.replace(/</g, \"\\\\u003c\")}</script>`;\n}\n\nfunction renderAnnotatedTable(\n this: { parser: { parseInline: (tokens: Token[]) => string } },\n token: Tokens.Table & TokenWithMrsf,\n lineMap: LineMap,\n lineHighlight: boolean,\n): string {\n const baseHtml = tableRenderer.call(this, token);\n const rowLines = [token.mrsfHeaderLine, ...(token.mrsfRowLines ?? [])];\n let rowIndex = 0;\n\n return baseHtml.replace(/<tr>/g, () => {\n const line = rowLines[rowIndex++];\n if (line == null) return \"<tr>\";\n\n const hasComment = hasCommentInRange(lineMap, line, line);\n\n const attrs = [\n `data-mrsf-line=\"${line}\"`,\n `data-mrsf-start-line=\"${line}\"`,\n `data-mrsf-end-line=\"${line}\"`,\n ];\n if (lineHighlight && hasComment) {\n attrs.push('class=\"mrsf-line-highlight\"');\n }\n return `<tr ${attrs.join(\" \")}>`;\n });\n}\n\nexport function createMarkedMrsf(loader: CommentLoader) {\n return function markedMrsf(options: MrsfPluginOptions = {}): MarkedExtension {\n let currentLineMap: LineMap | null = null;\n let currentThreads: CommentThread[] = [];\n\n return {\n hooks: {\n processAllTokens(tokens) {\n const result = resolveComments(loader, options);\n if (!result) {\n currentLineMap = null;\n currentThreads = [];\n return tokens;\n }\n\n currentLineMap = result.lineMap;\n currentThreads = flattenThreads(result.lineMap);\n stampTokens(tokens as TokenWithMrsf[], 1, result.lineMap);\n return tokens;\n },\n postprocess(html) {\n if (!currentLineMap || currentThreads.length === 0) {\n return html;\n }\n return html + createDataContainer(options, currentThreads);\n },\n },\n renderer: {\n heading(token) {\n return addAttrs(headingRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), `h${token.depth}`);\n },\n paragraph(token) {\n return addAttrs(paragraphRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"p\");\n },\n code(token) {\n return addAttrs(codeRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"pre\");\n },\n blockquote(token) {\n return addAttrs(blockquoteRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"blockquote\");\n },\n listitem(token) {\n return addAttrs(listItemRenderer.call(this, token), buildAttrs(token as ListItemWithMrsf, options.lineHighlight ?? false), \"li\");\n },\n hr(token) {\n return addAttrs(hrRenderer.call(this, token), buildAttrs(token as TokenWithMrsf, options.lineHighlight ?? false), \"hr\");\n },\n table(token) {\n return renderAnnotatedTable.call(\n this,\n token as Tokens.Table & TokenWithMrsf,\n currentLineMap ?? new Map(),\n options.lineHighlight ?? false,\n );\n },\n },\n };\n };\n}\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"],
5
+ "mappings": "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",
6
6
  "names": ["markedMrsf"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrsf/marked-mrsf",
3
- "version": "0.4.9",
3
+ "version": "0.4.11",
4
4
  "description": "Marked plugin for rendering Sidemark/MRSF review comments",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -68,14 +68,14 @@
68
68
  "LICENSE"
69
69
  ],
70
70
  "dependencies": {
71
- "@mrsf/cli": "^0.3.0",
71
+ "@mrsf/cli": "^0.4.3",
72
72
  "marked": "^16.4.2"
73
73
  },
74
74
  "devDependencies": {
75
- "@mrsf/plugin-shared": "file:../shared",
76
75
  "@types/node": "^22.13.10",
76
+ "@vitest/coverage-v8": "^3.2.4",
77
77
  "esbuild": "^0.27.3",
78
78
  "typescript": "^5.8.2",
79
- "vitest": "^3.0.9"
79
+ "vitest": "^3.2.4"
80
80
  }
81
- }
81
+ }