Skip to content

chore: delete pre-fix copies that survived their own fixes - #397

Merged
PathGao merged 1 commit into
sftwrdotdev:masterfrom
PathGao:chore/remove-drifted-dead-copies
Aug 2, 2026
Merged

chore: delete pre-fix copies that survived their own fixes#397
PathGao merged 1 commit into
sftwrdotdev:masterfrom
PathGao:chore/remove-drifted-dead-copies

Conversation

@PathGao

@PathGao PathGao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

A pure deletion — 186 lines — plus one guardrail so this cannot recur silently.

These are not idle leftovers

Four already-fixed behaviours each left a copy behind, and every copy looks like a reusable shared implementation. The danger is not that they take up space; it is that a future "the viewer is too big, let's use the shared version" reverts a merged fix, with no test going red.

Deleted Zero-call evidence How it had drifted
markdown.ts::renderRichContent (141 lines, exported) grep -rn "utils/markdown" src scripts src-tauri/src — only processMarkdownHtml is ever imported Missing rememberDiagramSource. Without that attribute, the light-theme Mermaid re-render that PDF/HTML export depends on (#359) finds nothing to restore. It also hand-rolls isDark ? "dark" : "neutral" instead of resolveMermaidTheme — whose own comment says it exists "so the two cannot drift" — and carries an inline DOMPurify config instead of the shared contract
markdown.ts::getLanguage one definition, no importer; the viewer calls its own copy
markdown.ts::highlightColorMap same
Editor.svelte::getEditorScrollMax one hit in the whole tree: the definition Pre-#316 version using getScrollHeight(); the live getEditorContentScrollMax uses getContentHeight(). Reviving it re-introduces the editor's bottom padding into split scroll sync
Editor.svelte::getViewState, ::revealLine component exports with no caller; the viewer's editorPane type declares neither

isYoutubeLink / getYoutubeId are kept — still called inside processMarkdownHtml — but their now-pointless export is dropped.

Why nothing caught them

youtubeExternalFallback.test.ts, taskToggleMemory.test.ts, mermaidPrintTheme.test.ts and previewScrollSync.test.ts each readFileSync one hard-coded path. A second copy living anywhere else is invisible to all of them.

scripts/singleImplementationConvention.test.ts generalises the allowlist idea already used by renderPipelineConvention.test.ts: a data-driven table where each row is { marker, allowed paths, optional requires }, scanned across the whole src tree. Adding a newly-fixed behaviour is a one-row append. Eight rules ship, including:

Plus a meta-test asserting every rule still matches something, so a renamed symbol cannot turn a rule into a silent no-op.

Negative control: with the two edited source files stashed, 7 of the 9 tests fail, then pass again. It catches precisely the copies this PR removes.

One unrelated fix rode along

Toc.svelte's scroll $effect returned a cleanup that called removeEventListener on the current value of a prop rather than the node it had attached to. The element is stable today so it does not misbehave, but if the prop ever changed the listener would leak, and if it became null the cleanup would throw. Now captures the node.

Checks

npm run check   432 files, 0 errors, 0 warnings
npm test        391 / 391
cargo test       98 / 98

No test lost coverage — none of the deleted symbols had a test referencing it, and previewScrollSync.test.ts pins the live getEditorContentScrollMax, untouched.

One line in another test: #384's DOMPurify.sanitize call-site allowlist listed markdown.ts, whose only call site was inside the dead renderRichContent. That allowlist must be exactly consumed, so deleting the call site correctly failed it. The entry is removed. This is the allowlist doing its job, not a workaround.

Not deleted, and why

  • onDestroy in Editor.svelteit is used; an earlier scan claimed otherwise and was wrong.
  • exportHtml.ts::escapeHtmlText, a zero-increment return escapeHtml(v) wrapper — it still has a live caller in export.ts. Worth inlining separately.
  • Editor.svelte's getValue / setValue / focus / restoreViewState component exports also appear to have no callers (every in-file hit is on the Monaco object, not the component export). Left alone to keep this a scoped deletion; worth a follow-up.
  • A live pre-fix copy in MarkdownViewer.sveltereplaceWithYoutubeEmbed builds the very <iframe src="youtube.com/embed/…"> that a merged fix replaced with a browser-opening thumbnail, and frame-src is gone from the CSP so it could not even load. It is zero-caller, and youtubeExternalFallback.test.ts asserts no iframe — but only against markdown.ts, so this copy was invisible: exactly the failure mode this PR exists to close. It is handled in refactor(preview): drop the dead YouTube iframe copy from the viewer #388; until that lands, the iframe rule ships with that one path allowlisted under a KNOWN STALE COPY comment telling the next person to delete the copy and the allowlist entry together.

🤖 Generated with Claude Code

Four already-fixed behaviours each left a copy behind, and every copy
looks like a reusable shared implementation:

- `markdown.ts::renderRichContent` (141 lines, exported, zero importers)
  lacks `rememberDiagramSource`, so anything that "switched to the
  shared version" would silently disable the light-theme Mermaid
  re-render that PDF and HTML export depend on. It also hand-rolls the
  theme choice instead of `resolveMermaidTheme` and carries an inline
  DOMPurify config instead of the shared contract.
- `markdown.ts::getLanguage` and `::highlightColorMap` duplicate the
  live copies in the viewer.
- `Editor.svelte::getEditorScrollMax` is the pre-sftwrdotdev#316 version, using
  `getScrollHeight()` where the live one uses `getContentHeight()`.

They were invisible because the tests guarding those behaviours each
read one hard-coded path. `scripts/singleImplementationConvention.test.ts`
generalises the allowlist idea to the whole `src` tree: one row per
fixed behaviour, scanned everywhere, plus a meta-test asserting every
rule still matches something so a rename cannot turn a rule into a
no-op.

Also fixes a `$effect` cleanup in Toc.svelte that removed its listener
from the current value of a prop rather than the node it attached to.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@PathGao
PathGao merged commit c2bff74 into sftwrdotdev:master Aug 2, 2026
4 checks passed
@PathGao
PathGao deleted the chore/remove-drifted-dead-copies branch August 2, 2026 21:41
PathGao added a commit that referenced this pull request Aug 2, 2026
#397 shipped the "YouTube links never become embedded frames" rule with
one allowlist entry for `replaceWithYoutubeEmbed` in
MarkdownViewer.svelte, an uncalled pre-fix leftover it could not delete
because #388 owned that file. Its comment said to delete the copy and
the entry together. #388 deleted the copy; the entry stayed, so the
marker now matches nothing and the meta-test that catches stale rules
fires - correctly.

The rule was always meant to be "allowed nowhere", which is now true.

Co-authored-by: PathGao <gaoyanbo@gaoyanbodeMacBook-Air.local>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant