From 87cdac47d10aa5fb6397465e3a9f21e6e8dca8c9 Mon Sep 17 00:00:00 2001 From: Tibo Mogul Date: Tue, 3 Sep 2024 09:54:30 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20skip=20code=20blocks=20when=20ru?= =?UTF-8?q?nning=20latex=20processing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit correct math syntax Co-authored-by: Erin Schnabel --- src/obsidian/processors/latexProcessor.ts | 22 +++ .../codeBlocks.unit.test.ts.snap | 124 +++++++++++++++ test/codeBlocks.unit.test.ts | 145 ++++++++++++++++++ 3 files changed, 291 insertions(+) create mode 100644 test/__snapshots__/codeBlocks.unit.test.ts.snap create mode 100644 test/codeBlocks.unit.test.ts diff --git a/src/obsidian/processors/latexProcessor.ts b/src/obsidian/processors/latexProcessor.ts index cb709d2..b015288 100644 --- a/src/obsidian/processors/latexProcessor.ts +++ b/src/obsidian/processors/latexProcessor.ts @@ -2,6 +2,28 @@ export class LatexProcessor { private singleLine = /\$(.*?)\$/g; process(markdown: string) { + return this.skipCodeBlocks(markdown); + } + + skipCodeBlocks(markdown: string): string { + const regex = + /(?<=(^|\r|\n|\r\n))`{3,}.*?(\r|\n|\r\n)[\s\S]*?(\r|\n|\r\n)`{3,}(?=($|\r|\n|\r\n))/; + const match = regex.exec(markdown); + + if (match) { + return ( + this.transformLatex(markdown.substring(0, match['index'])) + + match[0] + + this.skipCodeBlocks( + markdown.substring(match['index'] + match[0].length), + ) + ); + } else { + return this.transformLatex(markdown); + } + } + + private transformLatex(markdown: string) { const withoutEscapedCharaters = this.markEscapedCharacters(markdown); const processedMultiline = this.processMultiLine( withoutEscapedCharaters, diff --git a/test/__snapshots__/codeBlocks.unit.test.ts.snap b/test/__snapshots__/codeBlocks.unit.test.ts.snap new file mode 100644 index 0000000..481a4b7 --- /dev/null +++ b/test/__snapshots__/codeBlocks.unit.test.ts.snap @@ -0,0 +1,124 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Basic Markdown Syntax > Code Blocks 1`] = ` +" +
+ +\`\`\`dockerfile +FROM ubuntu +\`\`\` +
" +`; + +exports[`Basic Markdown Syntax > Code Blocks with multiple $ characters 1`] = ` +" +
+ +\`\`\`dockerfile +USER $USER_NAME:$USER_NAME +\`\`\` +
" +`; + +exports[`Basic Markdown Syntax > Math with Code Blocks 1`] = ` +" +
+ +$egin{vmatrix}a & b\\ +c & d +end{vmatrix}=ad-bc$ + +\`\`\`dockerfile +USER $USER_NAME:$USER_NAME +\`\`\` + +You can also do inline math like \`$s^{-2}_{n}sum_{i=1}^{n}$\` +
" +`; + +exports[`Basic Markdown Syntax > Math with Multiple Code Blocks 1`] = ` +" +
+ +$egin{vmatrix}a & b\\ +c & d +end{vmatrix}=ad-bc$ + +\`\`\`dockerfile +USER $USER_NAME:$USER_NAME +\`\`\` + +You can also do inline math like \`$s^{-2}_{n}sum_{i=1}^{n}$\` + +\`\`\`bash +eval "$(/home/$USER_NAME/.rbenv/bin/rbenv init -)" +\`\`\` + +That was ruby, now we have javascript: + +\`\`\` +console.log("Hello world!") +\`\`\` +
" +`; + +exports[`Code Block Syntax > Headers 1`] = ` +" +
+ +\`\`\` +USER $USER_NAME:$USER_NAME +\`\`\` + +The above does not show backticks +
" +`; + +exports[`Code Block Syntax > Headers 2`] = ` +" +
+ +\`\`\` +USER \`$USER_NAME:$\`USER_NAME +\`\`\` + +The above does show backticks +
" +`; + +exports[`Code Block Syntax > Headers 3`] = ` +" +
+ +\`\`\` +USER $USER_NAME:$USER_NAME +\`\`\` + +The above does not show backticks +
" +`; + +exports[`Embedded code has extra characters near dollar signs 1`] = ` +" +
+ +\`\`\`javascript +export class CounterService { + count$ = new BehaviorSubject(1000); + + double$ = this.count$.pipe(map((count) => count * 2)); + triple$ = this.count$.pipe(map((count) => count * 3)); + + combined$ = combineLatest([this.double$, this.triple$]).pipe( + map(([double, triple]) => double + triple) + ); + + over9000$ = this.combined$.pipe(map((combined) => combined > 9000)); + + message$ = this.over9000$.pipe( + map((over9000) => (over9000 ? "It's over 9000!" : "It's under 9000.")) + ); +} +\`\`\` +
" +`; diff --git a/test/codeBlocks.unit.test.ts b/test/codeBlocks.unit.test.ts new file mode 100644 index 0000000..414188c --- /dev/null +++ b/test/codeBlocks.unit.test.ts @@ -0,0 +1,145 @@ +import { MarkdownProcessor } from 'src/obsidian/markdownProcessor'; +import { obsidianUtils as utilsInstance } from './__mocks__/mockObsidianUtils'; +import { prepare } from './testUtils'; + +test('Basic Markdown Syntax > Code Blocks', () => { + const input = ` +\`\`\`dockerfile +FROM ubuntu +\`\`\` +`; + + const { options, markdown } = prepare(input); + const sut = new MarkdownProcessor(utilsInstance); + + return expect(sut.process(markdown, options)).toMatchSnapshot(); +}); + +test('Basic Markdown Syntax > Code Blocks with multiple $ characters', () => { + const input = ` +\`\`\`dockerfile +USER $USER_NAME:$USER_NAME +\`\`\` +`; + + const { options, markdown } = prepare(input); + const sut = new MarkdownProcessor(utilsInstance); + + return expect(sut.process(markdown, options)).toMatchSnapshot(); +}); + +test('Code Block Syntax > Headers', () => { + const input = ` +\`\`\` +USER $USER_NAME:$USER_NAME +\`\`\` + +The above does not show backticks +`; + + const { options, markdown } = prepare(input); + const sut = new MarkdownProcessor(utilsInstance); + + return expect(sut.process(markdown, options)).toMatchSnapshot(); +}); + +test('Code Block Syntax > Headers', () => { + const input = ` \`\`\` +USER $USER_NAME:$USER_NAME +\`\`\` + +The above does show backticks +`; + + const { options, markdown } = prepare(input); + const sut = new MarkdownProcessor(utilsInstance); + + return expect(sut.process(markdown, options)).toMatchSnapshot(); +}); + +test('Code Block Syntax > Headers', () => { + const input = `\`\`\` +USER $USER_NAME:$USER_NAME +\`\`\` + +The above does not show backticks +`; + + const { options, markdown } = prepare(input); + const sut = new MarkdownProcessor(utilsInstance); + + return expect(sut.process(markdown, options)).toMatchSnapshot(); +}); + +test('Basic Markdown Syntax > Math with Code Blocks', () => { + const input = `$$\begin{vmatrix}a & b\\ +c & d +\end{vmatrix}=ad-bc$$ + +\`\`\`dockerfile +USER $USER_NAME:$USER_NAME +\`\`\` + +You can also do inline math like $s^{-2}_{n}sum_{i=1}^{n}$`; + + const { options, markdown } = prepare(input); + const sut = new MarkdownProcessor(utilsInstance); + + return expect(sut.process(markdown, options)).toMatchSnapshot(); +}); + +test('Basic Markdown Syntax > Math with Multiple Code Blocks', () => { + const input = `$$\begin{vmatrix}a & b\\ +c & d +\end{vmatrix}=ad-bc$$ + +\`\`\`dockerfile +USER $USER_NAME:$USER_NAME +\`\`\` + +You can also do inline math like $s^{-2}_{n}sum_{i=1}^{n}$ + +\`\`\`bash +eval "$(/home/$USER_NAME/.rbenv/bin/rbenv init -)" +\`\`\` + +That was ruby, now we have javascript: + +\`\`\` +console.log("Hello world!") +\`\`\` +`; + + const { options, markdown } = prepare(input); + const sut = new MarkdownProcessor(utilsInstance); + + return expect(sut.process(markdown, options)).toMatchSnapshot(); +}); + +test('Embedded code has extra characters near dollar signs', () => { + const input = ` +\`\`\`javascript +export class CounterService { + count$ = new BehaviorSubject(1000); + + double$ = this.count$.pipe(map((count) => count * 2)); + triple$ = this.count$.pipe(map((count) => count * 3)); + + combined$ = combineLatest([this.double$, this.triple$]).pipe( + map(([double, triple]) => double + triple) + ); + + over9000$ = this.combined$.pipe(map((combined) => combined > 9000)); + + message$ = this.over9000$.pipe( + map((over9000) => (over9000 ? "It's over 9000!" : "It's under 9000.")) + ); +} +\`\`\``; + + const { options, markdown } = prepare(input); + const sut = new MarkdownProcessor(utilsInstance); + + return expect(sut.process(markdown, options)).toMatchSnapshot(); +}); +