Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

report unsupported macros by katex and expand user-define commands #99

Merged
merged 16 commits into from
Jun 12, 2024
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as Ast from "@unified-latex/unified-latex-types";
import {
expandMacrosExcludingDefinitions,
listNewcommands,
} from "@unified-latex/unified-latex-util-macros";
import { attachMacroArgs } from "@unified-latex/unified-latex-util-arguments";

/**
* Expands user-defined macros
*/
export function ExpandUserDefinedMacros(ast: Ast.Ast): void {
renee-k marked this conversation as resolved.
Show resolved Hide resolved
const newcommands = listNewcommands(ast);

const macroInfo = Object.fromEntries(
newcommands.map((m) => [m.name, { signature: m.signature }])
);

// attach the arguments to each macro before processing it
attachMacroArgs(ast, macroInfo);
expandMacrosExcludingDefinitions(ast, newcommands);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as Ast from "@unified-latex/unified-latex-types";
import { anyMacro, match } from "@unified-latex/unified-latex-util-match";
import { visit } from "@unified-latex/unified-latex-util-visit";
import { KATEX_SUPPORT } from "./pre-conversion-subs/katex-subs";

/**
* Return list of macros unsupported by Katex
*/
export function reportMacrosUnsupportedByKatex(ast: Ast.Ast): string[] {
const unsupported: string[] = [];

// match a macro supported by Katex
const isSupported = match.createMacroMatcher(KATEX_SUPPORT.macros);

// visit all nodes
visit(ast, (node, info) => {
// macro in math mode
if (anyMacro(node) && info.context.hasMathModeAncestor) {
// check if not supported by katex
if (!isSupported(node)) {
unsupported.push((node as Ast.Macro).content);
}
}
});

return unsupported;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { describe, it, expect } from "vitest";
import util from "util";
import { getParser } from "@unified-latex/unified-latex-util-parse";
import { printRaw } from "@unified-latex/unified-latex-util-print-raw";
import { ExpandUserDefinedMacros } from "@unified-latex/unified-latex-to-pretext/libs/expand-user-defined-macros";

// Make console.log pretty-print by default
const origLog = console.log;
console.log = (...args) => {
origLog(...args.map((x) => util.inspect(x, false, 10, true)));
};

describe("unified-latex-to-pretext:expand-user-deifned-macros", () => {
let value: string;

it("can expand newcommand", () => {
value = String.raw`\newcommand{\foo}{\bar} \foo`;

const parser = getParser();
const ast = parser.parse(value);

ExpandUserDefinedMacros(ast);

expect(printRaw(ast)).toEqual(String.raw`\newcommand{\foo}{\bar} \bar`);
});

it("can expand renewcommand", () => {
value = String.raw`\renewcommand{\O}{\mathcal{O}} \mathcal{O}`; // not subbing at all

const parser = getParser();
const ast = parser.parse(value);

ExpandUserDefinedMacros(ast);

expect(printRaw(ast)).toEqual(
String.raw`\renewcommand{\O}{\mathcal{O}} \O`
);
});

it("can expand multiple user-defined commands", () => {
value = String.raw`\newcommand{\join}{\vee}
\join
\renewcommand{\vee}{\foo}
\join`;

const parser = getParser();
const ast = parser.parse(value);

ExpandUserDefinedMacros(ast);

expect(printRaw(ast)).toEqual(String.raw`\newcommand{\join}{\vee}
\vee
\renewcommand{\vee}{\foo}
\foo`);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { describe, it, expect } from "vitest";
import util from "util";
import { getParser } from "@unified-latex/unified-latex-util-parse";
import { reportMacrosUnsupportedByKatex } from "@unified-latex/unified-latex-to-pretext/libs/report-unsupported-macro-katex";

// Make console.log pretty-print by default
const origLog = console.log;
console.log = (...args) => {
origLog(...args.map((x) => util.inspect(x, false, 10, true)));
};

describe("unified-latex-to-pretext:report-unsupported-macro-katex", () => {
let value: string;

it("can reported unsupported macros in mathmode", () => {
value = String.raw`$\mathbb{R} \fakemacro{X}$`;

const parser = getParser();
const ast = parser.parse(value);

expect(reportMacrosUnsupportedByKatex(ast)).toEqual(["fakemacro"]);
});

it("can report no unsupported macros in mathmode", () => {
value = String.raw`$\mathbb{R} \frac{1}{2} \cup$`;

const parser = getParser();
const ast = parser.parse(value);

expect(reportMacrosUnsupportedByKatex(ast)).toEqual([]);
});

it("can report no unsupported macros outside of math mode", () => {
renee-k marked this conversation as resolved.
Show resolved Hide resolved
value = String.raw`\fakemacro`;

const parser = getParser();
const ast = parser.parse(value);

expect(reportMacrosUnsupportedByKatex(ast)).toEqual([]);
});

it("can report unsupported macros in text mode with a math anscestor", () => {
renee-k marked this conversation as resolved.
Show resolved Hide resolved
value = String.raw`$\frac{1}{\text{ hi \unsupported}}$`;

const parser = getParser();
const ast = parser.parse(value);

expect(reportMacrosUnsupportedByKatex(ast)).toEqual(["unsupported"]);
});
});
renee-k marked this conversation as resolved.
Show resolved Hide resolved