Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions dist/public/syndication-export.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/public/syndication-export.js.map

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions src/public/syndication-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@ export async function exportPostArtifact(client: PublicClient, postUrl: string):
$("div > hr").each((_index, element) => { const parent = $(element).parent(); if (parent.is("div") && parent.children().length === 1) parent.replaceWith("<p>[[NORI_DIVIDER]]</p>"); });
$("a.footnote-anchor").each((_index, element) => { $(element).replaceWith(`[${$(element).text().trim()}]`); });
$("div.footnote").each((_index, element) => { const number = $(element).find(".footnote-number").text().trim(); const body = $(element).find(".footnote-content").text().trim().replace(/\s+/g, " "); $(element).replaceWith(`<p>[${number}] ${body}</p>`); });
// Article mentions are empty spans whose visible name lives in data-attrs.
// Preserve that source name so later platform-specific handling can resolve it
// without silently deleting the person from the sentence.
$(".mention-wrap,[data-component-name='MentionToDOM']").each((_index, element) => {
const node = $(element);
const rawAttributes = node.attr("data-attrs");
let label = node.text().trim();
try {
const attributes = rawAttributes ? JSON.parse(rawAttributes) as Record<string, unknown> : undefined;
const candidate = attributes?.name ?? attributes?.label;
if (typeof candidate === "string" && candidate.trim()) label = candidate.trim();
} catch { /* Preserve any visible fallback text when metadata is malformed. */ }
if (label) node.replaceWith(`<span>${escapeHtml(label)}</span>`);
});
$(".captioned-image-container").each((_index, element) => {
const url = $(element).find("img").first().attr("src") ?? "";
if (!url || url.includes("missing-image")) { $(element).remove(); return; }
Expand Down
4 changes: 3 additions & 1 deletion tests/syndication-export.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ test("exports a public Substack post as a portable article bundle", async () =>
title: "Agents from Modal",
canonical_url: `${server.origin}/p/agent-first`,
cover_image: `${server.origin}/cover.png`,
body_html: `<p>Keep “from Modal” verbatim.</p><p>The full list of reviews is here:</p><div class="digest-post-embed" data-attrs='{&quot;title&quot;:&quot;Ilya&apos;s Papers to Carmack: Table of Contents&quot;,&quot;canonical_url&quot;:&quot;https://example.com/p/ilyas-papers&quot;}'></div><p class="button-wrapper"><a class="button primary" href="https://luma.com/agentics-4qd8"><span>Click Here for Agentics Flagship Meetup</span></a></p><div class="subscription-widget">Subscribe now</div><div><hr></div><div class="captioned-image-container"><img src="${server.origin}/diagram.png"><figcaption>A diagram</figcaption></div><div id="youtube2-p-e4dHJTTuM" class="youtube-wrap"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/p-e4dHJTTuM?rel=0" frameborder="0"></iframe></div></div><div class="footnote"><span class="footnote-number">1</span><span class="footnote-content">Source note</span></div>`,
body_html: `<p>Keep “from Modal” verbatim.</p><p>My friend <span class="mention-wrap" data-attrs='{&quot;name&quot;:&quot;Danny D. Leybzon&quot;,&quot;id&quot;:4594584,&quot;type&quot;:&quot;user&quot;}' data-component-name="MentionToDOM"></span> wanted me to quote him.</p><p>The full list of reviews is here:</p><div class="digest-post-embed" data-attrs='{&quot;title&quot;:&quot;Ilya&apos;s Papers to Carmack: Table of Contents&quot;,&quot;canonical_url&quot;:&quot;https://example.com/p/ilyas-papers&quot;}'></div><p class="button-wrapper"><a class="button primary" href="https://luma.com/agentics-4qd8"><span>Click Here for Agentics Flagship Meetup</span></a></p><div class="subscription-widget">Subscribe now</div><div><hr></div><div class="captioned-image-container"><img src="${server.origin}/diagram.png"><figcaption>A diagram</figcaption></div><div id="youtube2-p-e4dHJTTuM" class="youtube-wrap"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/p-e4dHJTTuM?rel=0" frameborder="0"></iframe></div></div><div class="footnote"><span class="footnote-number">1</span><span class="footnote-content">Source note</span></div>`,
}));
});
closers.push(server.close);
Expand All @@ -45,6 +45,8 @@ test("exports a public Substack post as a portable article bundle", async () =>
images: [{ url: `${server.origin}/diagram.png`, caption: "A diagram" }],
});
expect(bundle.html).toContain("Keep “from Modal” verbatim.");
expect(bundle.html).toContain("My friend <span>Danny D. Leybzon</span> wanted me to quote him.");
expect(bundle.html).not.toContain("mention-wrap");
expect(bundle.html).toContain('The full list of reviews is here:</p><p><a href="https://example.com/p/ilyas-papers">Ilya\'s Papers to Carmack: Table of Contents</a></p>');
expect(bundle.html).not.toContain("digest-post-embed");
expect(bundle.html).toContain("[[NORI_DIVIDER]]");
Expand Down
Loading