You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
MarkdownFormatter.tsx exists in two places with active drift — every security fix must be written twice and they already disagree on real bugs (see sibling filings on useEffect-deps divergence and on the module-level document mutation). Single-source this into a shared package.
Security fixes must be duplicated. The footnote href-scheme validation added in Security: validate footnote inline link href schemes #950 only landed in one copy of the tree; raw <a> sanitization (see related bug about isSafeHref coverage) must be handled twice.
Regressions. The correct [] deps in website/ have not been back-ported to app/ — a real user-facing bug persists because the two files drifted.
Dependency divergence. rehype-raw v9 vs v10 have different AST guarantees and different behavior around whitespace-only nodes; bugs can reproduce in one tree but not the other.
Suggested fix
Extract the component and its helpers (isSafeHref, safeJsonParse, HighlightedBlock, the components map) into a shared package that both trees depend on. Options, ordered by preference:
Publish from a monorepo workspace (e.g., packages/markdown-formatter) consumed by app/, website/, and calculator-app/.
Symlink a shared/components/blog/MarkdownFormatter.tsx into both trees via TS path aliases.
At minimum, add a CI check that diffs the two files and fails if they diverge outside a known allow-list.
Pin both trees to the same rehype-raw / react-markdown versions before extracting.
Severity
High — force-multiplier on every security and correctness bug in this file.
Relates to
Sibling filings in this batch: module-level DOM mutation in app/ only; useEffect deps fixed only in website/; missing parts[1] guard; isSafeHref coverage of raw HTML <a>. Also #949, #950, #956.
Summary
MarkdownFormatter.tsxexists in two places with active drift — every security fix must be written twice and they already disagree on real bugs (see sibling filings on useEffect-deps divergence and on the module-leveldocumentmutation). Single-source this into a shared package.Location
app/src/components/blog/MarkdownFormatter.tsx(1032 lines)website/src/components/blog/MarkdownFormatter.tsx(968 lines)What goes wrong
Divergences between the two files as of
origin/main:app/website/<Td>,<Tr>,HighlightedBlock[ref.current?.cellIndex](buggy — refs aren't reactive)[](correct)imgrendererOptimisedImage<img>blockquoteTwitter-embed detectionhref?.startsWith('https://twitter.com/'))lifootnote parsingrehype-rawpin^9.0.0^10.1.0Consequences:
href-scheme validation added in Security: validate footnote inline link href schemes #950 only landed in one copy of the tree; raw<a>sanitization (see related bug aboutisSafeHrefcoverage) must be handled twice.[]deps inwebsite/have not been back-ported toapp/— a real user-facing bug persists because the two files drifted.rehype-rawv9 vs v10 have different AST guarantees and different behavior around whitespace-only nodes; bugs can reproduce in one tree but not the other.Suggested fix
Extract the component and its helpers (
isSafeHref,safeJsonParse,HighlightedBlock, thecomponentsmap) into a shared package that both trees depend on. Options, ordered by preference:packages/markdown-formatter) consumed byapp/,website/, andcalculator-app/.shared/components/blog/MarkdownFormatter.tsxinto both trees via TS path aliases.Pin both trees to the same
rehype-raw/react-markdownversions before extracting.Severity
High — force-multiplier on every security and correctness bug in this file.
Relates to
Sibling filings in this batch: module-level DOM mutation in
app/only; useEffect deps fixed only inwebsite/; missingparts[1]guard;isSafeHrefcoverage of raw HTML<a>. Also #949, #950, #956.