diff --git a/README.md b/README.md index fbb7458..057f72d 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ nori-substack note export \ --output notes.json ``` -To select an approved older Note, add `--note-id `; the author and top-level filters still apply while the lookback cutoff is bypassed. Notes are ordered oldest first and preserve text, quote blocks, links, remote images, IDs, and timestamps. +To select an approved older Note, add `--note-id `; the author and top-level filters still apply while the lookback cutoff is bypassed. Notes are ordered oldest first and preserve text, quote blocks, links, remote images, IDs, and timestamps. Note artifacts advertise `substack-mention-spans-v1` in their `capabilities` array. When a Note contains an explicit Substack mention, its post object also includes a `mentions` array. Each entry identifies the visible `label`, Substack source identity, and half-open `start`/`end` span in the unchanged `text`; offsets use UTF-16 code units so JavaScript consumers can validate them with `text.slice(start, end)`. Ordinary prose names are not mentions and do not appear in this array. Example Article artifact: diff --git a/dist/public/syndication-export.js b/dist/public/syndication-export.js index 2044f12..8f5e3c5 100644 --- a/dist/public/syndication-export.js +++ b/dist/public/syndication-export.js @@ -139,15 +139,49 @@ async function youtubeTitle(watchUrl) { return undefined; } } -function inline(nodes = []) { return nodes.map((node) => node.type === "text" ? typeof node.text === "string" ? node.text : "" : /hard_?break/i.test(String(node.type)) ? "\n" : mention(node) ?? inline(node.content)).join(""); } -// A mention is a childless leaf node whose visible name lives in attrs.label, so without this the -// name vanishes and the sentence loses its subject (" was not amused"). Emit the bare label: the -// Substack profile it points at has no known X handle, and guessing one would tag a stranger. -function mention(node) { +const MENTION_MARKER = /\uE000NORI_MENTION:(\d+)\uE001/g; +function inline(nodes = [], context) { + return nodes.map((node) => node.type === "text" + ? typeof node.text === "string" ? node.text : "" + : /hard_?break/i.test(String(node.type)) + ? "\n" + : mention(node, context) ?? inline(node.content, context)).join(""); +} +// A mention is a childless leaf node whose visible name lives in attrs.label. Keep the visible +// text unchanged, but retain the structured source signal so downstream workflows can distinguish +// an explicit Substack mention from the same name appearing as ordinary prose. +function mention(node, context) { if (!isNodeType(node, "substackmention", "mention")) return undefined; const label = node.attrs?.label ?? node.attrs?.name; - return typeof label === "string" && label.trim() ? label.trim() : undefined; + if (typeof label !== "string" || !label.trim()) + return undefined; + const source = { label: label.trim() }; + const substackId = node.attrs?.id; + if (typeof substackId === "string" || typeof substackId === "number") + source.substackId = String(substackId); + if (typeof node.attrs?.mentionType === "string") + source.mentionType = node.attrs.mentionType; + const index = context.mentions.push(source) - 1; + return `\uE000NORI_MENTION:${index}\uE001`; +} +function materializeMentions(textWithMarkers, sources) { + let text = ""; + let cursor = 0; + const mentions = []; + MENTION_MARKER.lastIndex = 0; + for (let match = MENTION_MARKER.exec(textWithMarkers); match; match = MENTION_MARKER.exec(textWithMarkers)) { + const source = sources[Number(match[1])]; + if (!source) + continue; + text += textWithMarkers.slice(cursor, match.index); + const start = text.length; + text += source.label; + mentions.push({ ...source, start, end: text.length, offsetUnit: "utf16" }); + cursor = match.index + match[0].length; + } + text += textWithMarkers.slice(cursor); + return { text, mentions }; } // Prefix every line of quoted text with a leading ">" per our quote-syndication convention (blank lines become a bare ">"). function toBlockquote(text) { return text.split("\n").map((line) => line ? `> ${line}` : ">").join("\n"); } @@ -158,29 +192,31 @@ function isNodeType(node, ...names) { } // X has no list formatting, so a list has to carry its own plain-text markers. Without them every // item collapses into one run-on line ("entire xai team is firedcursor acquisition ..."). -function renderList(node) { +function renderList(node, context) { const ordered = isNodeType(node, "orderedlist"); const start = typeof node.attrs?.start === "number" ? node.attrs.start : 1; return (node.content ?? []).map((item, index) => { const marker = ordered ? `${start + index}. ` : "- "; // Nested lists hang off the same item, so keep an item's blocks on adjacent lines and indent // continuation lines under the marker. - const [first = "", ...rest] = (item.content ?? []).map(renderBlock).filter(Boolean).join("\n").split("\n"); + const [first = "", ...rest] = (item.content ?? []).map((child) => renderBlock(child, context)).filter(Boolean).join("\n").split("\n"); return [`${marker}${first}`, ...rest.map((line) => line ? ` ${line}` : line)].join("\n"); }).join("\n"); } -function renderBlock(node) { +function renderBlock(node, context) { if (isNodeType(node, "blockquote")) - return (node.content ?? []).map((child) => toBlockquote(inline(child.content))).join("\n\n"); + return (node.content ?? []).map((child) => toBlockquote(inline(child.content, context))).join("\n\n"); if (isNodeType(node, "bulletlist", "orderedlist")) - return renderList(node); - return inline(node.content); + return renderList(node, context); + return inline(node.content, context); } function renderNote(comment) { const content = comment.body_json?.content; if (!Array.isArray(content)) - return typeof comment.body === "string" ? comment.body.trim() : ""; - return content.map(renderBlock).join("\n\n").replace(/\n{3,}/g, "\n\n").trim(); + return { text: typeof comment.body === "string" ? comment.body.trim() : "", mentions: [] }; + const context = { mentions: [] }; + const textWithMarkers = content.map((node) => renderBlock(node, context)).join("\n\n").replace(/\n{3,}/g, "\n\n").trim(); + return materializeMentions(textWithMarkers, context.mentions); } function attachmentType(value) { return typeof value === "object" && value !== null && !Array.isArray(value); } // A restack ("post" attachment) carries the quoted excerpt in postSelection.text and the canonical link in post.canonical_url. @@ -221,7 +257,8 @@ export async function exportNotesArtifact(client, options) { const images = attachments.filter((attachment) => attachment.type === "image" && typeof attachment.imageUrl === "string").map((attachment) => attachment.imageUrl); const links = attachments.filter((attachment) => attachment.type === "link" && attachmentType(attachment.linkMetadata) && typeof attachment.linkMetadata.url === "string").map((attachment) => attachment.linkMetadata.url); const restacks = attachments.filter((attachment) => attachment.type === "post").map(renderRestack); - let text = renderNote(comment); + const rendered = renderNote(comment); + let text = rendered.text; for (const restack of restacks) { if (restack.quote && !text.includes(restack.quote)) text = text ? `${text}\n\n${toBlockquote(restack.quote)}` : toBlockquote(restack.quote); @@ -231,10 +268,16 @@ export async function exportNotesArtifact(client, options) { for (const url of links) if (!text.includes(url)) text = text ? `${text}\n\n${url}` : url; - return { id: String(comment.id), text, images, publishedAt: stringField(comment.date, "date") }; + return { + id: String(comment.id), + text, + images, + publishedAt: stringField(comment.date, "date"), + ...(rendered.mentions.length > 0 ? { mentions: rendered.mentions } : {}), + }; }).sort((left, right) => Date.parse(left.publishedAt) - Date.parse(right.publishedAt)); if (options.noteId && notes.length === 0) throw new CliError("NOT_FOUND", `Note ${options.noteId} was not found in the public profile feed.`, 8, false); - return { version: 1, kind: "posts", posts: notes }; + return { version: 1, kind: "posts", capabilities: ["substack-mention-spans-v1"], posts: notes }; } //# sourceMappingURL=syndication-export.js.map \ No newline at end of file diff --git a/dist/public/syndication-export.js.map b/dist/public/syndication-export.js.map index 5fedaaa..17598d0 100644 --- a/dist/public/syndication-export.js.map +++ b/dist/public/syndication-export.js.map @@ -1 +1 @@ -{"version":3,"file":"syndication-export.js","sourceRoot":"","sources":["../../src/public/syndication-export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAM7C,SAAS,WAAW,CAAC,KAAc,EAAE,IAAY;IAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,iCAAiC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;IACnH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAAoB,EAAE,OAAe;IAC5E,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QAAC,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,4BAA4B,EAAE,CAAC,CAAC,CAAC;IAAC,CAAC;IACrH,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IACrD,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,+BAA+B,EAAE,CAAC,CAAC,CAAC;IACvF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAgB,CAAC;IACpG,MAAM,YAAY,GAAG,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC;IAC3F,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7E,MAAM,MAAM,GAA4C,EAAE,CAAC;IAC3D,MAAM,MAAM,GAAuD,EAAE,CAAC;IACtE,6EAA6E;IAC7E,+EAA+E;IAC/E,CAAC,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QAC/C,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;QACxB,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC9C,IAAI,UAA+C,CAAC;QACpD,IAAI,CAAC;YACH,MAAM,gBAAgB,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAY,CAAC,CAAC,CAAC,SAAS,CAAC;YAC1F,IAAI,gBAAgB,IAAI,OAAO,gBAAgB,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC;gBAAE,UAAU,GAAG,gBAA2C,CAAC;QAC7J,CAAC;QAAC,MAAM,CAAC,CAAC,2DAA2D,CAAC,CAAC;QACvE,MAAM,IAAI,GAAG,OAAO,UAAU,EAAE,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACxI,MAAM,KAAK,GAAG,OAAO,UAAU,EAAE,KAAK,KAAK,QAAQ,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;QACnL,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK;YAAE,IAAI,CAAC,WAAW,CAAC,eAAe,UAAU,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;;YACrH,IAAI,CAAC,MAAM,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IACH,CAAC,CAAC,iJAAiJ,CAAC,CAAC,MAAM,EAAE,CAAC;IAC9J,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,GAAG,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1J,wGAAwG;IACxG,kGAAkG;IAClG,mFAAmF;IACnF,CAAC,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QAC5C,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,CAAC;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACvD,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI;YAAE,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,eAAe,UAAU,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;;YACzH,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;IAC3B,CAAC,CAAC,CAAC;IACH,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,GAAG,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxL,CAAC,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/G,CAAC,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,GAAG,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,OAAO,MAAM,KAAK,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/P,CAAC,CAAC,4BAA4B,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QACvD,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7D,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;YAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;YAAC,OAAO;QAAC,CAAC;QAC3E,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;QACnF,MAAM,MAAM,GAAG,gBAAgB,MAAM,CAAC,MAAM,IAAI,CAAC;QACjD,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAC9B,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,MAAM,MAAM,OAAO,OAAO,CAAC,CAAC,CAAC,UAAU,OAAO,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC3F,CAAC,CAAC,CAAC;IACH,gFAAgF;IAChF,gFAAgF;IAChF,6EAA6E;IAC7E,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,CAAC,CAAC,iDAAiD,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QAC5E,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;QACxB,IAAI,IAAI,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC,MAAM;YAAE,OAAO;QAC9D,MAAM,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACrG,MAAM,EAAE,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;QAChC,IAAI,CAAC,EAAE,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO;QACxC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrB,MAAM,GAAG,GAAG,mCAAmC,EAAE,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,gBAAgB,MAAM,CAAC,MAAM,IAAI,CAAC;QACjD,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QACzB,IAAI,CAAC,WAAW,CAAC,MAAM,MAAM,MAAM,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IACH,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,CAAC,CAAC,6BAA6B,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QACxD,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;QACxB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;YAAE,OAAO;QACpF,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE;YAAE,OAAO;QAChC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,EAAE,EAAE,GAAG,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;YAAE,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI;YAAE,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3Q,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;YAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC7E,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,kCAAkC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACpE,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QAC5C,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACrB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IACH,IAAI,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1B,6EAA6E;IAC7E,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACnD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,KAAK,CAAC,KAAK,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;QACnD,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,KAAK,IAAI,EAAE,YAAY,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC;IACpG,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACvM,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,qFAAqF,CAAC,CAAC;IAC/G,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACtC,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC1G,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,QAAgB;IAC1C,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,sCAAsC,kBAAkB,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACvJ,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,OAAO,SAAS,CAAC;QACnC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAyB,CAAC;QAC1D,OAAO,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7F,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,SAAS,CAAC;IAAC,CAAC;AAC/B,CAAC;AAED,SAAS,MAAM,CAAC,QAAoB,EAAE,IAAY,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACvP,kGAAkG;AAClG,iGAAiG;AACjG,8FAA8F;AAC9F,SAAS,OAAO,CAAC,IAAc;IAC7B,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,iBAAiB,EAAE,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IACtE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC;IACpD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9E,CAAC;AACD,4HAA4H;AAC5H,SAAS,YAAY,CAAC,IAAY,IAAY,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3H,oHAAoH;AACpH,SAAS,UAAU,CAAC,IAAc,EAAE,GAAG,KAAe;IACpD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACrE,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,CAAC;AAC3D,CAAC;AACD,kGAAkG;AAClG,0FAA0F;AAC1F,SAAS,UAAU,CAAC,IAAc;IAChC,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,OAAO,IAAI,CAAC,KAAK,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3E,OAAO,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QACrD,6FAA6F;QAC7F,uCAAuC;QACvC,MAAM,CAAC,KAAK,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3G,OAAO,CAAC,GAAG,MAAM,GAAG,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AACD,SAAS,WAAW,CAAC,IAAc;IACjC,IAAI,UAAU,CAAC,IAAI,EAAE,YAAY,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjI,IAAI,UAAU,CAAC,IAAI,EAAE,YAAY,EAAE,aAAa,CAAC;QAAE,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;IAC3E,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC9B,CAAC;AACD,SAAS,UAAU,CAAC,OAAoB;IACtC,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC;IAC3C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAChG,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;AACjF,CAAC;AACD,SAAS,cAAc,CAAC,KAAc,IAAsC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC1J,+HAA+H;AAC/H,wHAAwH;AACxH,SAAS,aAAa,CAAC,UAAmC;IACxD,MAAM,SAAS,GAAG,cAAc,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,OAAO,UAAU,CAAC,aAAa,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5J,MAAM,IAAI,GAAG,cAAc,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3E,MAAM,GAAG,GAAG,IAAI,IAAI,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ,IAAI,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3G,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACjF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAAoB,EAAE,OAAsG;IACpK,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IACzF,MAAM,KAAK,GAAqC,EAAE,CAAC;IACnD,IAAI,MAA0B,CAAC;IAC/B,KAAK,IAAI,UAAU,GAAG,CAAC,EAAE,UAAU,GAAG,GAAG,EAAE,UAAU,EAAE,EAAE,CAAC;QACxD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,CAAsE,CAAC;QAC9J,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;QACzB,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACjF,IAAI,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC;YAAE,MAAM;QAC/F,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC/I,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,GAAG,MAAM,CAAC;YAAE,MAAM;QAC3G,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,MAAM;QAC5B,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC;IAC3B,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;QAC3F,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;YAAE,OAAO,KAAK,CAAC;QAC1H,IAAI,OAAO,CAAC,MAAM;YAAE,OAAO,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC;QACjE,MAAM,SAAS,GAAG,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;QAC3F,OAAO,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,MAAM,CAAC;IAC3D,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QACjB,MAAM,WAAW,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QACvE,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,KAAK,OAAO,IAAI,OAAO,UAAU,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,QAAkB,CAAC,CAAC;QAC7K,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,KAAK,MAAM,IAAI,cAAc,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,OAAO,UAAU,CAAC,YAAY,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAE,UAAU,CAAC,YAAwC,CAAC,GAAa,CAAC,CAAC;QACnQ,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACnG,IAAI,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QAC/B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC;gBAAE,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,OAAO,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC5I,IAAI,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC;gBAAE,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;QAC1G,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QAC1F,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;IAClG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IACvF,IAAI,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,QAAQ,CAAC,WAAW,EAAE,QAAQ,OAAO,CAAC,MAAM,4CAA4C,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;IACxJ,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AACrD,CAAC"} \ No newline at end of file +{"version":3,"file":"syndication-export.js","sourceRoot":"","sources":["../../src/public/syndication-export.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/public/docs.md b/src/public/docs.md index e783b6e..12ba1b1 100644 --- a/src/public/docs.md +++ b/src/public/docs.md @@ -19,11 +19,12 @@ Path: @/src/public - Article export parses custom-domain `/p/` URLs, cleans subscription UI, and emits divider and image markers. - Note export follows public profile cursors until a forced ID or lookback boundary is reached. - Note filtering requires the requested author, a top-level feed entity, and either the time window or exact forced ID. +- Note artifacts advertise the `substack-mention-spans-v1` capability and retain explicit Substack mentions as optional structured UTF-16 spans while leaving visible text unchanged; plain names have no mention metadata. - Article artifacts use `kind: "article"`; Note candidates use a source-neutral `kind: "posts"` collection. ### Things to Know -- Source text is preserved; platform mentions, punctuation, quotations, and whitespace are not silently rewritten. +- Source text is preserved; platform mention provenance is carried beside the text, and punctuation, quotations, and whitespace are not silently rewritten. - Forced Note IDs that cannot be found fail explicitly instead of producing a successful empty artifact. - Post collections are ordered oldest first for deterministic approval and publishing workflows. - Artifact `version` changes require coordinated consumer support. diff --git a/src/public/syndication-export.ts b/src/public/syndication-export.ts index 6e0d9bc..908481d 100644 --- a/src/public/syndication-export.ts +++ b/src/public/syndication-export.ts @@ -5,6 +5,9 @@ import { CliError } from "../core/errors.js"; interface ArticlePost { title?: unknown; canonical_url?: unknown; cover_image?: unknown; body_html?: unknown } interface NoteNode { type?: unknown; text?: unknown; attrs?: Record; content?: NoteNode[] } interface NoteComment { id?: unknown; user_id?: unknown; type?: unknown; ancestor_path?: unknown; date?: unknown; body?: unknown; body_json?: { content?: NoteNode[] }; attachments?: unknown[] } +interface NoteMentionSource { label: string; substackId?: string; mentionType?: string } +interface NoteMention extends NoteMentionSource { start: number; end: number; offsetUnit: "utf16" } +interface NoteRenderContext { mentions: NoteMentionSource[] } function stringField(value: unknown, name: string): string { if (typeof value !== "string") throw new CliError("INVALID_RESPONSE", `Substack post did not contain ${name}.`, 8); @@ -119,14 +122,46 @@ async function youtubeTitle(watchUrl: string): Promise { } catch { return undefined; } } -function inline(nodes: NoteNode[] = []): string { return nodes.map((node) => node.type === "text" ? typeof node.text === "string" ? node.text : "" : /hard_?break/i.test(String(node.type)) ? "\n" : mention(node) ?? inline(node.content)).join(""); } -// A mention is a childless leaf node whose visible name lives in attrs.label, so without this the -// name vanishes and the sentence loses its subject (" was not amused"). Emit the bare label: the -// Substack profile it points at has no known X handle, and guessing one would tag a stranger. -function mention(node: NoteNode): string | undefined { +const MENTION_MARKER = /\uE000NORI_MENTION:(\d+)\uE001/g; + +function inline(nodes: NoteNode[] = [], context: NoteRenderContext): string { + return nodes.map((node) => node.type === "text" + ? typeof node.text === "string" ? node.text : "" + : /hard_?break/i.test(String(node.type)) + ? "\n" + : mention(node, context) ?? inline(node.content, context)).join(""); +} +// A mention is a childless leaf node whose visible name lives in attrs.label. Keep the visible +// text unchanged, but retain the structured source signal so downstream workflows can distinguish +// an explicit Substack mention from the same name appearing as ordinary prose. +function mention(node: NoteNode, context: NoteRenderContext): string | undefined { if (!isNodeType(node, "substackmention", "mention")) return undefined; const label = node.attrs?.label ?? node.attrs?.name; - return typeof label === "string" && label.trim() ? label.trim() : undefined; + if (typeof label !== "string" || !label.trim()) return undefined; + const source: NoteMentionSource = { label: label.trim() }; + const substackId = node.attrs?.id; + if (typeof substackId === "string" || typeof substackId === "number") source.substackId = String(substackId); + if (typeof node.attrs?.mentionType === "string") source.mentionType = node.attrs.mentionType; + const index = context.mentions.push(source) - 1; + return `\uE000NORI_MENTION:${index}\uE001`; +} + +function materializeMentions(textWithMarkers: string, sources: NoteMentionSource[]): { text: string; mentions: NoteMention[] } { + let text = ""; + let cursor = 0; + const mentions: NoteMention[] = []; + MENTION_MARKER.lastIndex = 0; + for (let match = MENTION_MARKER.exec(textWithMarkers); match; match = MENTION_MARKER.exec(textWithMarkers)) { + const source = sources[Number(match[1])]; + if (!source) continue; + text += textWithMarkers.slice(cursor, match.index); + const start = text.length; + text += source.label; + mentions.push({ ...source, start, end: text.length, offsetUnit: "utf16" }); + cursor = match.index + match[0].length; + } + text += textWithMarkers.slice(cursor); + return { text, mentions }; } // Prefix every line of quoted text with a leading ">" per our quote-syndication convention (blank lines become a bare ">"). function toBlockquote(text: string): string { return text.split("\n").map((line) => line ? `> ${line}` : ">").join("\n"); } @@ -137,26 +172,28 @@ function isNodeType(node: NoteNode, ...names: string[]): boolean { } // X has no list formatting, so a list has to carry its own plain-text markers. Without them every // item collapses into one run-on line ("entire xai team is firedcursor acquisition ..."). -function renderList(node: NoteNode): string { +function renderList(node: NoteNode, context: NoteRenderContext): string { const ordered = isNodeType(node, "orderedlist"); const start = typeof node.attrs?.start === "number" ? node.attrs.start : 1; return (node.content ?? []).map((item, index) => { const marker = ordered ? `${start + index}. ` : "- "; // Nested lists hang off the same item, so keep an item's blocks on adjacent lines and indent // continuation lines under the marker. - const [first = "", ...rest] = (item.content ?? []).map(renderBlock).filter(Boolean).join("\n").split("\n"); + const [first = "", ...rest] = (item.content ?? []).map((child) => renderBlock(child, context)).filter(Boolean).join("\n").split("\n"); return [`${marker}${first}`, ...rest.map((line) => line ? ` ${line}` : line)].join("\n"); }).join("\n"); } -function renderBlock(node: NoteNode): string { - if (isNodeType(node, "blockquote")) return (node.content ?? []).map((child) => toBlockquote(inline(child.content))).join("\n\n"); - if (isNodeType(node, "bulletlist", "orderedlist")) return renderList(node); - return inline(node.content); +function renderBlock(node: NoteNode, context: NoteRenderContext): string { + if (isNodeType(node, "blockquote")) return (node.content ?? []).map((child) => toBlockquote(inline(child.content, context))).join("\n\n"); + if (isNodeType(node, "bulletlist", "orderedlist")) return renderList(node, context); + return inline(node.content, context); } -function renderNote(comment: NoteComment): string { +function renderNote(comment: NoteComment): { text: string; mentions: NoteMention[] } { const content = comment.body_json?.content; - if (!Array.isArray(content)) return typeof comment.body === "string" ? comment.body.trim() : ""; - return content.map(renderBlock).join("\n\n").replace(/\n{3,}/g, "\n\n").trim(); + if (!Array.isArray(content)) return { text: typeof comment.body === "string" ? comment.body.trim() : "", mentions: [] }; + const context: NoteRenderContext = { mentions: [] }; + const textWithMarkers = content.map((node) => renderBlock(node, context)).join("\n\n").replace(/\n{3,}/g, "\n\n").trim(); + return materializeMentions(textWithMarkers, context.mentions); } function attachmentType(value: unknown): value is Record { return typeof value === "object" && value !== null && !Array.isArray(value); } // A restack ("post" attachment) carries the quoted excerpt in postSelection.text and the canonical link in post.canonical_url. @@ -193,14 +230,21 @@ export async function exportNotesArtifact(client: PublicClient, options: { accou const images = attachments.filter((attachment) => attachment.type === "image" && typeof attachment.imageUrl === "string").map((attachment) => attachment.imageUrl as string); const links = attachments.filter((attachment) => attachment.type === "link" && attachmentType(attachment.linkMetadata) && typeof attachment.linkMetadata.url === "string").map((attachment) => (attachment.linkMetadata as Record).url as string); const restacks = attachments.filter((attachment) => attachment.type === "post").map(renderRestack); - let text = renderNote(comment); + const rendered = renderNote(comment); + let text = rendered.text; for (const restack of restacks) { if (restack.quote && !text.includes(restack.quote)) text = text ? `${text}\n\n${toBlockquote(restack.quote)}` : toBlockquote(restack.quote); if (restack.url && !text.includes(restack.url)) text = text ? `${text}\n\n${restack.url}` : restack.url; } for (const url of links) if (!text.includes(url)) text = text ? `${text}\n\n${url}` : url; - return { id: String(comment.id), text, images, publishedAt: stringField(comment.date, "date") }; + return { + id: String(comment.id), + text, + images, + publishedAt: stringField(comment.date, "date"), + ...(rendered.mentions.length > 0 ? { mentions: rendered.mentions } : {}), + }; }).sort((left, right) => Date.parse(left.publishedAt) - Date.parse(right.publishedAt)); if (options.noteId && notes.length === 0) throw new CliError("NOT_FOUND", `Note ${options.noteId} was not found in the public profile feed.`, 8, false); - return { version: 1, kind: "posts", posts: notes }; + return { version: 1, kind: "posts", capabilities: ["substack-mention-spans-v1"], posts: notes }; } diff --git a/tests/syndication-export.test.ts b/tests/syndication-export.test.ts index e1e66e2..090c8b9 100644 --- a/tests/syndication-export.test.ts +++ b/tests/syndication-export.test.ts @@ -98,7 +98,7 @@ test("exports only recent top-level Notes from the requested author", async () = expect(result.code).toBe(0); const artifact = JSON.parse(await readFile(output, "utf8")); - expect(artifact).toMatchObject({ version: 1, kind: "posts" }); + expect(artifact).toMatchObject({ version: 1, kind: "posts", capabilities: ["substack-mention-spans-v1"] }); expect(artifact.posts).toEqual([{ id: "101", text: "intro\n\n> quoted\n\nhttps://example.com/read", @@ -187,7 +187,7 @@ test("exports Note lists with one item per line and plain-text markers", async ( ].join("\n")); }); -test("exports Note mentions as their visible label", async () => { +test("exports explicit Note mentions as structured spans without marking plain names", async () => { const server = await withHttpServer((request, response) => { response.setHeader("content-type", "application/json"); response.end(JSON.stringify({ items: [{ comment: { @@ -197,10 +197,10 @@ test("exports Note mentions as their visible label", async () => { ancestor_path: "", date: "2026-08-18T19:04:08.618Z", body_json: { content: [ - { type: "paragraph", content: [{ type: "text", text: "me to the team" }] }, + { type: "paragraph", content: [{ type: "text", text: "Plain Clifford and 😀" }] }, { type: "paragraph", content: [ { type: "substack_mention", attrs: { id: 50747867, label: "Clifford", mentionType: "user", url: null } }, - { type: "text", text: " was not amused" }, + { type: "text", text: " was not amused by Clifford" }, ] }, ] }, attachments: [], @@ -212,7 +212,20 @@ test("exports Note mentions as their visible label", async () => { const result = await runCli(["--account-origin", server.origin, "note", "export", "--user-id", "9744387", "--note-id", "317531633", "--output", output]); expect(result.code).toBe(0); - expect(JSON.parse(await readFile(output, "utf8")).posts[0].text).toBe("me to the team\n\nClifford was not amused"); + expect(JSON.parse(await readFile(output, "utf8")).posts[0]).toEqual({ + id: "317531633", + text: "Plain Clifford and 😀\n\nClifford was not amused by Clifford", + images: [], + publishedAt: "2026-08-18T19:04:08.618Z", + mentions: [{ + label: "Clifford", + substackId: "50747867", + mentionType: "user", + start: 23, + end: 31, + offsetUnit: "utf16", + }], + }); }); test("a forced Note id is exported even when it is outside the lookback window", async () => {