fix(desktop,daemon): keep replacement-pattern sequences verbatim in export titles - #6947
Conversation
β¦xport titles (nexu-io#6795) String.replace expands $$, $&, $` and $' in string replacements, corrupting user-derived artifact titles in PDF/image export and skill-derived titles in example assembly. Switch the affected interpolations to function replacements and add regression tests for both exporters and assembleExample.
|
Hey @cactusrabbit β thanks for the focused fix here. Extending the hardening to the daemon-side Heads-up: PR #6796, PR #6891, and PR #6931 are already open against issue #6795 and touch the same export-title path, so maintainers will likely consolidate around one path here rather than land parallel fixes. |
|
π§ͺ Queued for QA validation β this PR changes exported document output, so it needs a manual QA pass before merge. Nothing needed from you right now; weβll update here once that pass is done. Thanks for the contribution. |
lefarcen
left a comment
There was a problem hiding this comment.
Hey @cactusrabbit β the write-up here is already easy to follow, especially the concrete Why/Changes split and the regression-test callouts. One body-level thing before pool review: since the UI box is checked, could you add a quick before/after screenshot (or exported-document capture) showing one of the $-pattern titles rendered correctly? That would complete the template without changing the rest of the description.
nettee
left a comment
There was a problem hiding this comment.
@cactusrabbit I reviewed all five changed files and verified that the function replacements preserve literal JavaScript replacement-pattern sequences across the desktop PDF/image exporters and daemon example assembly. The focused desktop (2 tests) and daemon (1 test) regression suites pass, along with both package typechecks, the workspace typecheck, and the repository guard. This is a nicely focused fix with clear regression coverageβthank you for carefully closing the loop on #6795!
π Powered by Looper Β· runner=reviewer Β· agent=codex Β· An autonomous AI dev team for your GitHub repos.|
Thanks for the contribution. I completed QA validation for this PR. QA Acceptance Record Scope:
Verified:
Not verified:
Risks / notes:
Conclusion:
|
π π‘ You just leveled up to Giotto
π Your contributions are sending a clear signal across the network: you care about making Open Design better. Keep transmitting. π Thanks for helping Open Design move forward. Keep building in the open. π π Rank #174 among 600+ contributors |

Fixes #6795
Why
injectTitle()(bothapps/desktop/src/main/pdf-export.tsandapps/desktop/src/main/artifact-export.ts) passes the user-derived title as the string replacement ofString.prototype.replace, so ECMA-262GetSubstitutionexpands$$,$&,$``, and$'inside it. Artifact titles containing those sequences were corrupted in exported PDFs/images β dropped$, broken<title>tags, and duplicated document tails.assembleExample()in the daemon'sstatic-resource.ts` interpolates skill-derived slides and titles through the same mechanism.Changes
apps/desktop/src/main/pdf-export.tsβ use a function replacement ininjectTitle(matching the siblinginjectBaseHrefpattern).apps/desktop/src/main/artifact-export.tsβ same change in itsinjectTitle.apps/daemon/src/routes/static-resource.tsβ harden both interpolations inassembleExample(slides + title) the same way.apps/desktop/tests/main/export-title-replacement-patterns.test.tsβ drivesexportPdfFromHtmlandexportArtifactwith titles containing$$,$&,$``,$'` and asserts the loaded document keeps the title verbatim (HTML-escaped only) and the body intact.apps/daemon/tests/assemble-example-title-patterns.test.tsβ assertsassembleExampleinterpolates slides and titles verbatim.Surface area
$-pattern titles now render correctlyValidation
pnpm --filter @open-design/desktop exec vitest run -c vitest.config.ts tests/main/export-title-replacement-patterns.test.tsβ 2 passedpnpm --filter @open-design/daemon exec vitest run -c vitest.config.ts tests/assemble-example-title-patterns.test.tsβ 1 passedpnpm --filter @open-design/desktop typecheckβ passedpnpm --filter @open-design/daemon typecheckβ passedpnpm guardβ all checks passed except a pre-existingci.ymlpackaged-leaf boundary failure, untouched by this PR