mirror of
https://github.com/ckelsoe/obsidian-rss-importer.git
synced 2026-07-22 07:48:56 +00:00
Converter: strip Substack app-install / subscribe / CTA clutter
Remove email-truncation and 'read in the app' promos, subscribe forms, and CTA buttons by their Substack data-component-name (InstallSubstackAppToDOM, SubscribeWidgetToDOM, ButtonCreateButton) plus the matching class families (install-substack-app, subscription-widget, preamble, digest-post-embed, fake-input/button, cta-caption). Real images (Image2ToDOM) and prose are kept. Structural match only, never body text. Test added.
This commit is contained in:
parent
7654740d6a
commit
b06dd6911d
2 changed files with 42 additions and 0 deletions
|
|
@ -138,6 +138,23 @@ describe("convertHtmlToMarkdown: widget stripping and degradation", () => {
|
|||
const md = convertHtmlToMarkdown("<p>You can subscribe at the library for free.</p>");
|
||||
expect(md).toContain("You can subscribe at the library for free.");
|
||||
});
|
||||
|
||||
it("strips Substack app-install and subscribe embeds by data-component-name, keeping images and prose", () => {
|
||||
const html =
|
||||
'<div data-component-name="InstallSubstackAppToDOM" class="install-substack-app-embed">' +
|
||||
'<p class="preamble">If you are reading this in email, the text may cut off. Get the app.</p>' +
|
||||
'<a class="install-substack-app-embed-btn button primary" href="https://substack.com/app">Get the app</a></div>' +
|
||||
"<p>The real article body that must be kept.</p>" +
|
||||
'<div class="captioned-image-container"><img src="https://substackcdn.com/image/x.png" alt="A figure" /></div>' +
|
||||
'<div data-component-name="SubscribeWidgetToDOM" class="subscription-widget show-subscribe">' +
|
||||
'<a href="https://pub.substack.com/subscribe">Become a supporter</a></div>';
|
||||
const md = convertHtmlToMarkdown(html);
|
||||
expect(md).toContain("The real article body that must be kept.");
|
||||
expect(md).toContain("https://substackcdn.com/image/x.png");
|
||||
expect(md).not.toContain("Get the app");
|
||||
expect(md).not.toContain("reading this in email");
|
||||
expect(md).not.toContain("Become a supporter");
|
||||
});
|
||||
});
|
||||
|
||||
describe("convertHtmlToMarkdown: footnotes", () => {
|
||||
|
|
|
|||
|
|
@ -99,6 +99,27 @@ const WIDGET_STRIP_KEYS: readonly string[] = [
|
|||
"poll-embed",
|
||||
"comments-button",
|
||||
"footer-buttons",
|
||||
// Substack email-truncation / "read in the app" promo and CTA form blocks.
|
||||
"install-substack-app",
|
||||
"subscription-widget",
|
||||
"preamble",
|
||||
"digest-post-embed",
|
||||
"fake-input",
|
||||
"fake-button",
|
||||
"email-input",
|
||||
"cta-caption",
|
||||
];
|
||||
|
||||
/**
|
||||
* `data-component-name` values Substack stamps on its embedded widgets. This is
|
||||
* the most reliable marker for the subscribe form, the "read in the app" promo,
|
||||
* and CTA buttons. `Image2ToDOM` (real captioned images) is deliberately NOT
|
||||
* listed so images are preserved. Matched exactly (not substring).
|
||||
*/
|
||||
const WIDGET_STRIP_COMPONENTS: readonly string[] = [
|
||||
"SubscribeWidgetToDOM",
|
||||
"InstallSubstackAppToDOM",
|
||||
"ButtonCreateButton",
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -153,6 +174,10 @@ function classMatchesAny(node: ClassedElement, keys: readonly string[]): boolean
|
|||
|
||||
/** Known subscribe/share/button widget: removed outright. */
|
||||
function isStripWidget(node: ClassedElement): boolean {
|
||||
const component = node.getAttribute("data-component-name");
|
||||
if (component !== null && WIDGET_STRIP_COMPONENTS.includes(component)) {
|
||||
return true;
|
||||
}
|
||||
return classMatchesAny(node, WIDGET_STRIP_KEYS);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue