authorgravatar for lucenz@proton.meSimone <lucenz@proton.me> 2026-09-21 03:29:55+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-20 22:29:55-03:00
log2efb8178d83f4f7c4ccc3ae1165f2a2ded0b2742
treecde39f720cbccb5f91074bc976732ad5557dbbb0
parent411da2a7356dd795b720228e9c834ea9bad0415f
signature Signed by PGP key B5690EEEBB952194

fix(clients): keep backslashes in copied Codex citations (#12243)

Co-authored-by: Simone <185146821+Lucenx9@users.noreply.github.com>

2 files changed, 20 insertions(+), 0 deletions(-)

packages/client-runtime/src/codexFileCitations.ts+1
...@@ -44,6 +44,7 @@ function markdownLabel(value: string): string {...@@ -44,6 +44,7 @@ function markdownLabel(value: string): string {
4444
45function markdownDestination(value: string): string {45function markdownDestination(value: string): string {
46 return value46 return value
47 .replaceAll("\\", "%5C")
47 .replaceAll("<", "%3C")48 .replaceAll("<", "%3C")
48 .replaceAll(">", "%3E")49 .replaceAll(">", "%3E")
49 .replaceAll("\r", "%0D")50 .replaceAll("\r", "%0D")
packages/client-runtime/src/codexMarkdownDirectives.test.ts+19
...@@ -8,6 +8,7 @@ import {...@@ -8,6 +8,7 @@ import {
8 renderCodexFileCitationsAsMarkdown,8 renderCodexFileCitationsAsMarkdown,
9 splitCodexArtifactTemplateMarkdown,9 splitCodexArtifactTemplateMarkdown,
10} from "./codexMarkdownDirectives.js";10} from "./codexMarkdownDirectives.js";
11import { parseMarkdownFileLink } from "./markdownLinks.js";
1112
12interface TestNode {13interface TestNode {
13 readonly type: string;14 readonly type: string;
...@@ -89,6 +90,24 @@ describe("remarkCodexDirectives", () => {...@@ -89,6 +90,24 @@ describe("remarkCodexDirectives", () => {
89 });90 });
90});91});
9192
93describe.each([
94 { name: "renderCodexDirectivesForCopy", render: renderCodexDirectivesForCopy },
95 { name: "renderCodexFileCitationsAsMarkdown", render: renderCodexFileCitationsAsMarkdown },
96])("$name file citation round trips", ({ render }) => {
97 it.each([
98 "C:\\Users\\test\\[draft]\\report.md",
99 "\\\\server\\share\\report.md",
100 "outputs/report.md",
101 "/tmp/report%5C.md",
102 ])("preserves the literal path and line: %s", (path) => {
103 const markdown = render(`:codex-file-citation{path="${path}" line_range_start="7"}`);
104 const link = parseOrdinaryMarkdown(markdown).children?.[0]?.children?.[0];
105
106 expect(link?.type).toBe("link");
107 expect(parseMarkdownFileLink(link?.url ?? "")).toEqual({ path, line: 7 });
108 });
109});
110
92describe("native Markdown adapters", () => {111describe("native Markdown adapters", () => {
93 it("uses the same parser to render file citations as portable links", () => {112 it("uses the same parser to render file citations as portable links", () => {
94 expect(renderCodexFileCitationsAsMarkdown(`Created ${FILE_CITATION}.`)).toBe(113 expect(renderCodexFileCitationsAsMarkdown(`Created ${FILE_CITATION}.`)).toBe(