From 3bad46ee5eab18af823542c18e2c8d2a792f1c2b Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 25 Aug 2026 00:21:53 +0000 Subject: [PATCH 1/2] fix: transform pspicture label text --- bundle/latex2html5.bundle.js | 13 ++++++++++--- packages/latex2js/src/lib/parser.ts | 19 ++++++++++++++----- .../latex2js/test/parser-semantics.test.ts | 19 ++++++++++++++++--- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/bundle/latex2html5.bundle.js b/bundle/latex2html5.bundle.js index abcfb68c..4fb56fe4 100644 --- a/bundle/latex2html5.bundle.js +++ b/bundle/latex2html5.bundle.js @@ -4785,6 +4785,9 @@ var LaTeX2HTML5 = (() => { }); return; } + if (typeof data.text === "string") { + data.text = this.parseLabel(data.text); + } } plot[k].push({ data, env, match: m, fn: this.PSTricks.Functions[k] }); if (this.dialect === "pstricks") { @@ -4906,13 +4909,17 @@ var LaTeX2HTML5 = (() => { return contents; } parseText(line) { + var contents = this.parseLabel(line); + Object.entries(this.Headers.Expressions).forEach(([k, exp]) => { + contents = this.parseHeadersExpression(line, exp, k, contents); + }); + return contents; + } + parseLabel(line) { var contents = line; Object.entries(this.Text.Expressions).forEach(([k, exp]) => { contents = this.parseTextExpression(line, exp, k, contents); }); - Object.entries(this.Headers.Expressions).forEach(([k, exp]) => { - contents = this.parseHeadersExpression(line, exp, k, contents); - }); return contents; } // ------------------------------------------------------------------------- diff --git a/packages/latex2js/src/lib/parser.ts b/packages/latex2js/src/lib/parser.ts index 2305e68d..ffe65724 100644 --- a/packages/latex2js/src/lib/parser.ts +++ b/packages/latex2js/src/lib/parser.ts @@ -882,6 +882,9 @@ class Parser { }); return; } + if (typeof data.text === 'string') { + data.text = this.parseLabel(data.text); + } } plot[k].push({ data: data, env: env, match: m, fn: this.PSTricks.Functions[k] }); @@ -1032,11 +1035,7 @@ class Parser { } parseText(line: string): string { - var contents = line; - // TEXT - Object.entries(this.Text.Expressions).forEach(([k, exp]: [string, any]) => { - contents = this.parseTextExpression(line, exp, k, contents); - }); + var contents = this.parseLabel(line); // HEADERS Object.entries(this.Headers.Expressions).forEach(([k, exp]: [string, any]) => { @@ -1046,6 +1045,16 @@ class Parser { return contents; } + parseLabel(line: string): string { + var contents = line; + // TEXT + Object.entries(this.Text.Expressions).forEach(([k, exp]: [string, any]) => { + contents = this.parseTextExpression(line, exp, k, contents); + }); + + return contents; + } + // ------------------------------------------------------------------------- // Diagnostics // ------------------------------------------------------------------------- diff --git a/packages/latex2js/test/parser-semantics.test.ts b/packages/latex2js/test/parser-semantics.test.ts index 90bdd502..2133a855 100644 --- a/packages/latex2js/test/parser-semantics.test.ts +++ b/packages/latex2js/test/parser-semantics.test.ts @@ -162,7 +162,7 @@ describe('Peggy grammar parser (new)', () => { expect(env.plot.pscircle).toHaveLength(2); }); - it('does not corrupt pspicture content with text transforms', () => { + it('applies text transforms to delimited rput labels', () => { const parsed = latex.parse(` \\begin{pspicture}(0,0)(4,4) \\rput(1,1){$a--b$} @@ -170,8 +170,21 @@ describe('Peggy grammar parser (new)', () => { `); const env = parsed.find((e: any) => e.type === 'pspicture'); - // the old parser turned `--` into – inside the rput math - expect(env.plot.rput[0].data.text).toBe('$a--b$'); + expect(env.plot.rput[0].data.text).toBe('$a–b$'); + }); + + it('applies text transforms to rput labels', () => { + const parsed = latex.parse(` +\\begin{pspicture}(0,0)(4,4) +\\rput(1.5,1){\\LaTeX} +\\rput(2,1){\\TeX} +\\rput(0.3,3.75){ $Im$ } +\\end{pspicture} + `); + + const env = parsed.find((e: any) => e.type === 'pspicture'); + const labels = env.plot.rput.map((rput: any) => rput.data.text); + expect(labels).toEqual(['$\\LaTeX$', '$\\TeX$', ' $Im$ ']); }); it('collects diagnostics for unknown commands', () => { From 47c23d43d0c1f2fb1f56e8d75b70e0b5239ed870 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 25 Aug 2026 00:25:29 +0000 Subject: [PATCH 2/2] fix: preserve math in pspicture labels --- bundle/latex2html5.bundle.js | 26 +++++++++++++++- packages/latex2js/src/lib/parser.ts | 31 +++++++++++++++++-- .../latex2js/test/parser-semantics.test.ts | 16 ++++++++-- 3 files changed, 68 insertions(+), 5 deletions(-) diff --git a/bundle/latex2html5.bundle.js b/bundle/latex2html5.bundle.js index 4fb56fe4..ffe0d802 100644 --- a/bundle/latex2html5.bundle.js +++ b/bundle/latex2html5.bundle.js @@ -4909,13 +4909,37 @@ var LaTeX2HTML5 = (() => { return contents; } parseText(line) { - var contents = this.parseLabel(line); + var contents = this.parseTextTransforms(line); Object.entries(this.Headers.Expressions).forEach(([k, exp]) => { contents = this.parseHeadersExpression(line, exp, k, contents); }); return contents; } parseLabel(line) { + var contents = ""; + var textStart = 0; + var mathStart = -1; + for (var i = 0; i < line.length; i++) { + if (line[i] !== "$") { + continue; + } + if (mathStart === -1) { + contents += this.parseTextTransforms(line.slice(textStart, i)); + mathStart = i; + } else { + contents += line.slice(mathStart, i + 1); + textStart = i + 1; + mathStart = -1; + } + } + if (mathStart === -1) { + contents += this.parseTextTransforms(line.slice(textStart)); + } else { + contents += this.parseTextTransforms(line.slice(mathStart)); + } + return contents; + } + parseTextTransforms(line) { var contents = line; Object.entries(this.Text.Expressions).forEach(([k, exp]) => { contents = this.parseTextExpression(line, exp, k, contents); diff --git a/packages/latex2js/src/lib/parser.ts b/packages/latex2js/src/lib/parser.ts index ffe65724..c4ff2887 100644 --- a/packages/latex2js/src/lib/parser.ts +++ b/packages/latex2js/src/lib/parser.ts @@ -1035,7 +1035,7 @@ class Parser { } parseText(line: string): string { - var contents = this.parseLabel(line); + var contents = this.parseTextTransforms(line); // HEADERS Object.entries(this.Headers.Expressions).forEach(([k, exp]: [string, any]) => { @@ -1046,8 +1046,35 @@ class Parser { } parseLabel(line: string): string { + var contents = ''; + var textStart = 0; + var mathStart = -1; + + for (var i = 0; i < line.length; i++) { + if (line[i] !== '$') { + continue; + } + if (mathStart === -1) { + contents += this.parseTextTransforms(line.slice(textStart, i)); + mathStart = i; + } else { + contents += line.slice(mathStart, i + 1); + textStart = i + 1; + mathStart = -1; + } + } + + if (mathStart === -1) { + contents += this.parseTextTransforms(line.slice(textStart)); + } else { + contents += this.parseTextTransforms(line.slice(mathStart)); + } + + return contents; + } + + parseTextTransforms(line: string): string { var contents = line; - // TEXT Object.entries(this.Text.Expressions).forEach(([k, exp]: [string, any]) => { contents = this.parseTextExpression(line, exp, k, contents); }); diff --git a/packages/latex2js/test/parser-semantics.test.ts b/packages/latex2js/test/parser-semantics.test.ts index 2133a855..58fd0539 100644 --- a/packages/latex2js/test/parser-semantics.test.ts +++ b/packages/latex2js/test/parser-semantics.test.ts @@ -162,7 +162,7 @@ describe('Peggy grammar parser (new)', () => { expect(env.plot.pscircle).toHaveLength(2); }); - it('applies text transforms to delimited rput labels', () => { + it('does not corrupt pspicture content with text transforms', () => { const parsed = latex.parse(` \\begin{pspicture}(0,0)(4,4) \\rput(1,1){$a--b$} @@ -170,7 +170,8 @@ describe('Peggy grammar parser (new)', () => { `); const env = parsed.find((e: any) => e.type === 'pspicture'); - expect(env.plot.rput[0].data.text).toBe('$a–b$'); + // the old parser turned `--` into – inside the rput math + expect(env.plot.rput[0].data.text).toBe('$a--b$'); }); it('applies text transforms to rput labels', () => { @@ -187,6 +188,17 @@ describe('Peggy grammar parser (new)', () => { expect(labels).toEqual(['$\\LaTeX$', '$\\TeX$', ' $Im$ ']); }); + it('transforms non-math parts of mixed rput labels', () => { + const parsed = latex.parse(` +\\begin{pspicture}(0,0)(4,4) +\\rput(1,1){{\\LaTeX\\ vs $a--b$}} +\\end{pspicture} + `); + + const env = parsed.find((e: any) => e.type === 'pspicture'); + expect(env.plot.rput[0].data.text).toBe('{$\\LaTeX$ vs $a--b$}'); + }); + it('collects diagnostics for unknown commands', () => { const parsed = latex.parse(` \\begin{pspicture}(0,0)(4,4)