mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-05 19:28:39 +00:00
Create globalGroup option to place definitions in global scope (#2091)
If true, this allows \newcommand definitions to persist across calls to renderToString. Fix https://github.com/KaTeX/KaTeX/issues/2070
This commit is contained in:
committed by
Kevin Barabash
parent
f03671ce61
commit
36595343b7
@@ -51,6 +51,7 @@ You can provide an object of options as the last argument to [`katex.render` and
|
|||||||
- Allow all commands with specific protocols: `trust: (context) => ['http', 'https', '_relative'].includes(context.protocol)`
|
- Allow all commands with specific protocols: `trust: (context) => ['http', 'https', '_relative'].includes(context.protocol)`
|
||||||
- Allow all commands but forbid specific protocol: `trust: (context) => context.protocol !== 'file'`
|
- Allow all commands but forbid specific protocol: `trust: (context) => context.protocol !== 'file'`
|
||||||
- Allow certain commands with specific protocols: `trust: (context) => ['\\url', '\\href'].includes(context.command) && ['http', 'https', '_relative'].includes(context.protocol)`
|
- Allow certain commands with specific protocols: `trust: (context) => ['\\url', '\\href'].includes(context.command) && ['http', 'https', '_relative'].includes(context.protocol)`
|
||||||
|
- `globalGroup`: `boolean` (default: `false`). Place KaTeX code in the global group. As a consequence, `\def` and `\newcommand` persist in `macros` across render calls. In LaTeX, constructs such as `\begin{equation}` and `$$` create a local group and prevent definitions from becoming visible outside of those blocks.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
|
@@ -115,9 +115,11 @@ export default class Parser {
|
|||||||
* Main parsing function, which parses an entire input.
|
* Main parsing function, which parses an entire input.
|
||||||
*/
|
*/
|
||||||
parse(): AnyParseNode[] {
|
parse(): AnyParseNode[] {
|
||||||
|
if (!this.settings.globalGroup) {
|
||||||
// Create a group namespace for the math expression.
|
// Create a group namespace for the math expression.
|
||||||
// (LaTeX creates a new group for every $...$, $$...$$, \[...\].)
|
// (LaTeX creates a new group for every $...$, $$...$$, \[...\].)
|
||||||
this.gullet.beginGroup();
|
this.gullet.beginGroup();
|
||||||
|
}
|
||||||
|
|
||||||
// Use old \color behavior (same as LaTeX's \textcolor) if requested.
|
// Use old \color behavior (same as LaTeX's \textcolor) if requested.
|
||||||
// We do this within the group for the math expression, so it doesn't
|
// We do this within the group for the math expression, so it doesn't
|
||||||
@@ -133,7 +135,9 @@ export default class Parser {
|
|||||||
this.expect("EOF");
|
this.expect("EOF");
|
||||||
|
|
||||||
// End the group namespace for the expression
|
// End the group namespace for the expression
|
||||||
|
if (!this.settings.globalGroup) {
|
||||||
this.gullet.endGroup();
|
this.gullet.endGroup();
|
||||||
|
}
|
||||||
return parse;
|
return parse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -50,6 +50,7 @@ export type SettingsOptions = {
|
|||||||
trust?: boolean | TrustFunction;
|
trust?: boolean | TrustFunction;
|
||||||
maxSize?: number;
|
maxSize?: number;
|
||||||
maxExpand?: number;
|
maxExpand?: number;
|
||||||
|
globalGroup?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,6 +77,7 @@ export default class Settings {
|
|||||||
trust: boolean | TrustFunction;
|
trust: boolean | TrustFunction;
|
||||||
maxSize: number;
|
maxSize: number;
|
||||||
maxExpand: number;
|
maxExpand: number;
|
||||||
|
globalGroup: boolean;
|
||||||
|
|
||||||
constructor(options: SettingsOptions) {
|
constructor(options: SettingsOptions) {
|
||||||
// allow null options
|
// allow null options
|
||||||
@@ -96,6 +98,7 @@ export default class Settings {
|
|||||||
this.trust = utils.deflt(options.trust, false);
|
this.trust = utils.deflt(options.trust, false);
|
||||||
this.maxSize = Math.max(0, utils.deflt(options.maxSize, Infinity));
|
this.maxSize = Math.max(0, utils.deflt(options.maxSize, Infinity));
|
||||||
this.maxExpand = Math.max(0, utils.deflt(options.maxExpand, 1000));
|
this.maxExpand = Math.max(0, utils.deflt(options.maxExpand, 1000));
|
||||||
|
this.globalGroup = utils.deflt(options.globalGroup, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -3162,6 +3162,25 @@ describe("A macro expander", function() {
|
|||||||
expect(macros["\\foo"]).toBeFalsy();
|
expect(macros["\\foo"]).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("\\def changes settings.macros with globalGroup", () => {
|
||||||
|
const macros = {};
|
||||||
|
expect`\gdef\foo{1}`.toParse(new Settings({macros, globalGroup: true}));
|
||||||
|
expect(macros["\\foo"]).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("\\newcommand doesn't change settings.macros", () => {
|
||||||
|
const macros = {};
|
||||||
|
expect`\newcommand\foo{x^2}\foo+\foo`.toParse(new Settings({macros}));
|
||||||
|
expect(macros["\\foo"]).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("\\newcommand changes settings.macros with globalGroup", () => {
|
||||||
|
const macros = {};
|
||||||
|
expect`\newcommand\foo{x^2}\foo+\foo`.toParse(
|
||||||
|
new Settings({macros, globalGroup: true}));
|
||||||
|
expect(macros["\\foo"]).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
it("\\newcommand defines new macros", () => {
|
it("\\newcommand defines new macros", () => {
|
||||||
expect`\newcommand\foo{x^2}\foo+\foo`.toParseLike`x^2+x^2`;
|
expect`\newcommand\foo{x^2}\foo+\foo`.toParseLike`x^2+x^2`;
|
||||||
expect`\newcommand{\foo}{x^2}\foo+\foo`.toParseLike`x^2+x^2`;
|
expect`\newcommand{\foo}{x^2}\foo+\foo`.toParseLike`x^2+x^2`;
|
||||||
|
Reference in New Issue
Block a user