clone of repo on github
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

101 lines
4.7 KiB

import { describe, it, expect } from "vitest";
import { parseAdvancedmarkup } from "../../src/lib/utils/markup/advancedMarkupParser";
import { readFileSync } from "fs";
import { join } from "path";
describe("LaTeX Math Rendering", () => {
const mdPath = join(__dirname, "../../test_data/latex_markdown.md");
const raw = readFileSync(mdPath, "utf-8");
// Extract the markdown content field from the JSON
const content = JSON.parse(raw).content;
it('renders inline math as <span class="math-inline">', async () => {
const html = await parseAdvancedmarkup(content);
expect(html).toMatch(/<span class="math-inline">\$P \\neq NP\$<\/span>/);
expect(html).toMatch(
/<span class="math-inline">\$x_1 = \\text\{True\}\$<\/span>/,
);
});
it('renders display math as <div class="math-block', async () => {
const html = await parseAdvancedmarkup(content);
// Representative display math
expect(html).toMatch(
/<div class="math-block my-4 text-center">\$\$\s*P_j = \\bigotimes/,
);
expect(html).toMatch(
/<div class="math-block my-4 text-center">\$\$[\s\S]*?\\begin\{pmatrix\}/,
);
expect(html).toMatch(
/<div class="math-block my-4 text-center">\$\$\\boxed\{P \\neq NP\}\$\$<\/div>/,
);
});
it("does not wrap display math in <p> or <blockquote>", async () => {
const html = await parseAdvancedmarkup(content);
// No <p> or <blockquote> directly wrapping math-block
expect(html).not.toMatch(/<p[^>]*>\s*<div class="math-block/);
expect(html).not.toMatch(/<blockquote[^>]*>\s*<div class="math-block/);
});
it("renders LaTeX environments (pmatrix) within display math blocks", async () => {
const html = await parseAdvancedmarkup(content);
// Check that pmatrix is properly rendered within a display math block
expect(html).toMatch(
/<div class="math-block my-4 text-center">\$\$[\s\S]*?\\begin\{pmatrix\}[\s\S]*?\\end\{pmatrix\}[\s\S]*?\$\$<\/div>/,
);
});
it('renders all math as math (no unwrapped $...$, $$...$$, \\(...\\), \\[...\\], or environments left)', async () => {
const html = await parseAdvancedmarkup(content);
// No unwrapped $...$ outside math-inline or math-block
// Remove all math-inline and math-block tags and check for stray $...$
const htmlNoMath = html
.replace(/<span class="math-inline">\$[^$]+\$<\/span>/g, '')
.replace(/<div class="math-block[^"]*">\$\$[\s\S]*?\$\$<\/div>/g, '')
.replace(/<div class="math-block[^"]*">[\s\S]*?<\/div>/g, '');
expect(htmlNoMath).not.toMatch(/\$[^\$\n]+\$/); // inline math
expect(htmlNoMath).not.toMatch(/\$\$[\s\S]*?\$\$/); // display math
expect(htmlNoMath).not.toMatch(/\\\([^)]+\\\)/); // \(...\)
expect(htmlNoMath).not.toMatch(/\\\[[^\]]+\\\]/); // \[...\]
expect(htmlNoMath).not.toMatch(/\\begin\{[a-zA-Z*]+\}[\s\S]*?\\end\{[a-zA-Z*]+\}/); // environments
// No math inside code or pre
expect(html).not.toMatch(/<code[\s\S]*?\$[\s\S]*?\$[\s\S]*?<\/code>/);
expect(html).not.toMatch(/<pre[\s\S]*?\$[\s\S]*?\$[\s\S]*?<\/pre>/);
});
it('renders every line of the document: all math is wrapped', async () => {
const lines = content.split(/\r?\n/);
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (!line.trim()) continue;
const html = await parseAdvancedmarkup(line);
// If the line contains $...$, $$...$$, \(...\), \[...\], or bare LaTeX commands, it should be wrapped
const hasMath = /\$[^$]+\$|\$\$[\s\S]*?\$\$|\\\([^)]+\\\)|\\\[[^\]]+\\\]|\\[a-zA-Z]+(\{[^}]*\})*/.test(line);
if (hasMath) {
const wrapped = /math-inline|math-block/.test(html);
if (!wrapped) {
// eslint-disable-next-line no-console
console.error(`Line ${i + 1} failed:`, line);
// eslint-disable-next-line no-console
console.error('Rendered HTML:', html);
}
expect(wrapped).toBe(true);
}
// Should not have any unwrapped $...$, $$...$$, \(...\), \[...\], or bare LaTeX commands
const stray = /(^|[^>])\$[^$\n]+\$|\$\$[\s\S]*?\$\$|\\\([^)]+\\\)|\\\[[^\]]+\\\]|\\[a-zA-Z]+(\{[^}]*\})*/.test(html);
expect(stray).toBe(false);
}
});
it('renders standalone math lines as display math blocks', async () => {
const mdPath = require('path').join(__dirname, '../../test_data/latex_markdown.md');
const raw = require('fs').readFileSync(mdPath, 'utf-8');
const content = JSON.parse(raw).content || raw;
const html = await parseAdvancedmarkup(content);
// Example: Bures distance line
expect(html).toMatch(/<div class="math-block my-4 text-center">\$\$d_B\([^$]+\) = [^$]+\$\$<\/div>/);
// Example: P(\rho) = ...
expect(html).toMatch(/<div class="math-block my-4 text-center">\$\$P\([^$]+\) = [^$]+\$\$<\/div>/);
});
});