From 0cd7414bf974e2f192e90cd6ae31e04b0ddda6d6 Mon Sep 17 00:00:00 2001
From: Jitendra Bansal <146943450+Jbansal2@users.noreply.github.com>
Date: Wed, 28 Oct 2026 15:23:20 +0530
Subject: [PATCH] fix(legacy-html,man-page,sitemap): treat $$, $&, $` and $' in
values as literal text
String.prototype.replace(placeholder, value) treats some $ sequences in a
string replacement as patterns ($$ -> $, $& -> the match, $` / $' -> the
template before/after the match). Page content, navigation, man page
options/environment text, and sitemap URL fields are filled this way, so
any of those sequences in the source produced broken output (e.g. the
addons.md Makefile example $$(command -v node) rendered with one $
missing).
Pass each value through a replacer function instead, since a function's
return value is inserted as-is.
Fixes nodejs/doc-kit#1181
---
.changeset/fix-dollar-replacement.md | 7 +++
.../__tests__/replaceTemplateValues.test.mjs | 57 +++++++++++++++++++
.../utils/replaceTemplateValues.mjs | 19 ++++---
packages/node/src/man-page/generate.mjs | 4 +-
packages/react/src/sitemap/generate.mjs | 10 ++--
5 files changed, 81 insertions(+), 16 deletions(-)
create mode 100644 .changeset/fix-dollar-replacement.md
create mode 100644 packages/node-legacy/src/legacy-html/utils/__tests__/replaceTemplateValues.test.mjs
diff --git a/.changeset/fix-dollar-replacement.md b/.changeset/fix-dollar-replacement.md
new file mode 100644
index 000000000..26d88d4d6
--- /dev/null
+++ b/.changeset/fix-dollar-replacement.md
@@ -0,0 +1,7 @@
+---
+'@node-core/doc-kit-legacy': patch
+'@node-core/doc-kit': patch
+'@doc-kit/generator-react': patch
+---
+
+Fix `$$`, `$&`, `` $` `` and `$'` in page content being treated as `String.prototype.replace` replacement patterns instead of literal text. This affected the legacy HTML generator's page and navigation content, the man page generator's options/environment sections, and the sitemap generator's URL entries.
diff --git a/packages/node-legacy/src/legacy-html/utils/__tests__/replaceTemplateValues.test.mjs b/packages/node-legacy/src/legacy-html/utils/__tests__/replaceTemplateValues.test.mjs
new file mode 100644
index 000000000..1cb51bbf7
--- /dev/null
+++ b/packages/node-legacy/src/legacy-html/utils/__tests__/replaceTemplateValues.test.mjs
@@ -0,0 +1,57 @@
+'use strict';
+
+import assert from 'node:assert/strict';
+import { before, describe, it } from 'node:test';
+
+import { setConfig } from '@doc-kit/core/utils/configuration/index.mjs';
+
+import { replaceTemplateValues } from '../replaceTemplateValues.mjs';
+
+describe('replaceTemplateValues', () => {
+ before(() => setConfig({}));
+
+ const baseValues = {
+ path: '/test',
+ api: 'test',
+ added: undefined,
+ section: 'section',
+ toc: [],
+ nav: 'nav',
+ content: 'content',
+ };
+
+ const config = { version: { version: '1.0.0' }, changelog: [] };
+
+ it('does not treat `$$`, `$&`, "$`" and `$\'` in content as replacement patterns', () => {
+ const template = '__CONTENT__';
+
+ const dollarContent = 'dirname "$$(command -v node)" $& $` $\'';
+
+ const output = replaceTemplateValues(
+ template,
+ { ...baseValues, content: dollarContent },
+ config,
+ { skipGitHub: true }
+ );
+
+ assert.match(
+ output,
+ /dirname "\$\$\(command -v node\)" \$& \$` \$'<\/main>/
+ );
+ });
+
+ it('does not treat `$$`, `$&`, "$`" and `$\'` in nav as replacement patterns', () => {
+ const template = '__CONTENT__';
+
+ const dollarNav = "nav $$ $& $` $'";
+
+ const output = replaceTemplateValues(
+ template,
+ { ...baseValues, nav: dollarNav },
+ config,
+ { skipGitHub: true }
+ );
+
+ assert.match(output, /