feat: implement \relax as no-op function (#3384)

* feat: implement \relax as no-op function

BREAKING CHANGE: `\relax` is now implemented as a function. It'll stop
expansions and parsing, so the behavior around `\relax` may change.
For example, `\kern2\relax em` will no longer work.
This commit is contained in:
ylemkimon
2021-10-31 12:46:43 +09:00
committed by GitHub
parent a12b89968c
commit 40109f6248
6 changed files with 34 additions and 8 deletions

View File

@@ -3,6 +3,12 @@ id: migration
title: Migration Guide
---
## v0.15.0
`\relax` is now implemented as a function. It'll stop expansions and parsing,
so the behavior around `\relax` may change. For example, `\kern2\relax em` will
no longer work.
## v0.14.0
With module loaders that support conditional exports and ECMAScript modules,

View File

@@ -20,7 +20,6 @@ import type Settings from "./Settings";
// List of commands that act like macros but aren't defined as a macro,
// function, or symbol. Used in `isDefined`.
export const implicitCommands = {
"\\relax": true, // MacroExpander.js
"^": true, // Parser.js
"_": true, // Parser.js
"\\limits": true, // Parser.js
@@ -333,15 +332,12 @@ export default class MacroExpander implements MacroContextInterface {
const expanded = this.expandOnce();
// expandOnce returns Token if and only if it's fully expanded.
if (expanded instanceof Token) {
// \relax stops the expansion, but shouldn't get returned (a
// null return value couldn't get implemented as a function).
// the token after \noexpand is interpreted as if its meaning
// were \relax
if (expanded.text === "\\relax" || expanded.treatAsRelax) {
this.stack.pop();
} else {
return this.stack.pop(); // === expanded
if (expanded.treatAsRelax) {
expanded.text = "\\relax";
}
return this.stack.pop(); // === expanded
}
}

View File

@@ -37,6 +37,7 @@ import "./functions/ordgroup";
import "./functions/overline";
import "./functions/phantom";
import "./functions/raisebox";
import "./functions/relax";
import "./functions/rule";
import "./functions/sizing";
import "./functions/smash";

17
src/functions/relax.js Normal file
View File

@@ -0,0 +1,17 @@
//@flow
import defineFunction from "../defineFunction";
defineFunction({
type: "internal",
names: ["\\relax"],
props: {
numArgs: 0,
allowedInText: true,
},
handler({parser}) {
return {
type: "internal",
mode: parser.mode,
};
},
});

View File

@@ -368,7 +368,7 @@ defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}");
// \renewcommand{\colon}{\nobreak\mskip2mu\mathpunct{}\nonscript
// \mkern-\thinmuskip{:}\mskip6muplus1mu\relax}
defineMacro("\\colon", "\\nobreak\\mskip2mu\\mathpunct{}" +
"\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu");
"\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu\\relax");
// \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}}
defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}");

View File

@@ -4046,3 +4046,9 @@ describe("debugging macros", () => {
});
});
});
describe("\\relax", () => {
it("should stop the expansion", () => {
expect`\kern2\relax em`.not.toParse();
});
});