From 8e7a3072ef2edeacb901f174e1475a8a08936b02 Mon Sep 17 00:00:00 2001 From: JK Date: Sun, 28 Jun 2026 12:34:59 +0200 Subject: [PATCH] feat(snippets): add text transform for cleaning inline double dollar equations - Implement `Clean Inline Double Dollar Symbols` text transform snippet. - Convert inline double dollar signs `$$` to single dollar sign `$`. - Keep block/display equation dollar signs (`$$`) intact (e.g. multi-line blocks or single-line equations starting/ending with `$$`). - Add unit tests in `test_helpers/transforms.test.ts` to verify behavior. - Update documentation in `docs/features/snippets.md` to document the new and existing double-dollar cleanup transforms. --- docs/features/snippets.md | 2 ++ src/features/snippets/transforms.ts | 23 ++++++++++++++ test_helpers/transforms.test.ts | 49 +++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 test_helpers/transforms.test.ts diff --git a/docs/features/snippets.md b/docs/features/snippets.md index 8e90733..ac3c95b 100644 --- a/docs/features/snippets.md +++ b/docs/features/snippets.md @@ -32,5 +32,7 @@ The **Run Text Transform Snippet** command processes your highlighted editor tex | **Title Kebab Case** | `Example-Text-String` | Title heading slugifications. | | **Title Case** | `Example Text String` | Formatting article or note headings. | | **Clean Zotero Highlight** | Reformats HTML tags to raw markdown | Converting Zotero desktop highlights into blockquotes. | +| **Clean Double Dollar Symbols** | `$$` → `$` | Replaces all double dollar signs with single dollar signs in the selected text/line. | +| **Clean Inline Double Dollar Symbols** | `$$x$$` → `$x$` | Converts inline double dollar math into single dollar inline math while preserving display/block math blocks. | When any transformation runs, TeXcore displays a notice toast in the top-right corner indicating whether the change was successfully applied. diff --git a/src/features/snippets/transforms.ts b/src/features/snippets/transforms.ts index 509d93e..1c677fc 100644 --- a/src/features/snippets/transforms.ts +++ b/src/features/snippets/transforms.ts @@ -77,6 +77,22 @@ function cleanDoubleDollarSymbols(input: string): string { return input.replace(/\$\$/g, '$'); } +function cleanInlineDoubleDollarSymbols(input: string): string { + const lines = input.split(/\r?\n/); + const processedLines = lines.map(line => { + const trimmed = line.trim(); + const isBlockEquation = + trimmed === '$$' || + (trimmed.startsWith('$$') && trimmed.endsWith('$$') && trimmed.length > 2); + if (isBlockEquation) { + return line; + } + return line.replace(/\$\$/g, '$'); + }); + const hasCarriageReturn = input.includes('\r\n'); + return processedLines.join(hasCarriageReturn ? '\r\n' : '\n'); +} + export const BUILTIN_TEXT_TRANSFORM_SNIPPETS: TextTransformSnippet[] = [ { id: 'kebab-case', @@ -112,6 +128,13 @@ export const BUILTIN_TEXT_TRANSFORM_SNIPPETS: TextTransformSnippet[] = [ description: 'Replace all $$ with $', keywords: ['dollar', 'latex', 'equation', 'cleanup'], transform: cleanDoubleDollarSymbols + }, + { + id: 'clean-inline-double-dollar-symbols', + name: 'Clean Inline Double Dollar Symbols', + description: 'Replace inline $$ with $ while keeping block $$', + keywords: ['dollar', 'latex', 'equation', 'inline', 'cleanup'], + transform: cleanInlineDoubleDollarSymbols } ]; diff --git a/test_helpers/transforms.test.ts b/test_helpers/transforms.test.ts new file mode 100644 index 0000000..834efce --- /dev/null +++ b/test_helpers/transforms.test.ts @@ -0,0 +1,49 @@ +import { BUILTIN_TEXT_TRANSFORM_SNIPPETS } from '../src/features/snippets/transforms'; + +describe('transforms.ts tests', () => { + const inlineDoubleDollarTransform = BUILTIN_TEXT_TRANSFORM_SNIPPETS.find( + s => s.id === 'clean-inline-double-dollar-symbols' + )?.transform; + + it('should exist', () => { + expect(inlineDoubleDollarTransform).toBeDefined(); + }); + + if (inlineDoubleDollarTransform) { + it('should convert inline $$ to $ while keeping block $$', () => { + const sample = `At low concentrations, however, the expansion, +$$ +\\varepsilon_{\\rm reg}(k)=b_0^*+b_2^*k^2+\\cdots +$$ +has $$b_0^*$$ dominated by water dipole correlations, so $$E^*(\\kappa)\\approx\\varepsilon_{\\rm dip}(c)$$`; + + const expected = `At low concentrations, however, the expansion, +$$ +\\varepsilon_{\\rm reg}(k)=b_0^*+b_2^*k^2+\\cdots +$$ +has $b_0^*$ dominated by water dipole correlations, so $E^*(\\kappa)\\approx\\varepsilon_{\\rm dip}(c)$`; + + expect(inlineDoubleDollarTransform(sample)).toBe(expected); + }); + + it('should keep block $$ with leading spaces', () => { + const sample = ` $$ +\\varepsilon = b + $$`; + expect(inlineDoubleDollarTransform(sample)).toBe(sample); + }); + + it('should keep single-line block equation', () => { + expect(inlineDoubleDollarTransform('$$ x = y $$')).toBe('$$ x = y $$'); + expect(inlineDoubleDollarTransform(' $$ x = y $$ ')).toBe(' $$ x = y $$ '); + }); + + it('should handle single-line input for inline $$', () => { + expect(inlineDoubleDollarTransform('has $$b_0^*$$')).toBe('has $b_0^*$'); + }); + + it('should handle inline equation that starts at beginning of line but has text on same line', () => { + expect(inlineDoubleDollarTransform('$$b_0^*$$ is the value')).toBe('$b_0^*$ is the value'); + }); + } +});