63 lines
2.2 KiB
JavaScript
63 lines
2.2 KiB
JavaScript
// @flow
|
|
import defineFunction from "../defineFunction";
|
|
import ParseError from "../ParseError";
|
|
import {assertNodeType} from "../parseNode";
|
|
import environments from "../environments";
|
|
|
|
// Environment delimiters. HTML/MathML rendering is defined in the corresponding
|
|
// defineEnvironment definitions.
|
|
defineFunction({
|
|
type: "environment",
|
|
names: ["\\begin", "\\end"],
|
|
props: {
|
|
numArgs: 1,
|
|
argTypes: ["text"],
|
|
},
|
|
handler({parser, funcName}, args) {
|
|
const nameGroup = args[0];
|
|
if (nameGroup.type !== "ordgroup") {
|
|
throw new ParseError("Invalid environment name", nameGroup);
|
|
}
|
|
let envName = "";
|
|
for (let i = 0; i < nameGroup.body.length; ++i) {
|
|
envName += assertNodeType(nameGroup.body[i], "textord").text;
|
|
}
|
|
|
|
if (funcName === "\\begin") {
|
|
// begin...end is similar to left...right
|
|
if (!environments.hasOwnProperty(envName)) {
|
|
throw new ParseError(
|
|
"No such environment: " + envName, nameGroup);
|
|
}
|
|
// Build the environment object. Arguments and other information will
|
|
// be made available to the begin and end methods using properties.
|
|
const env = environments[envName];
|
|
const {args, optArgs} =
|
|
parser.parseArguments("\\begin{" + envName + "}", env);
|
|
const context = {
|
|
mode: parser.mode,
|
|
envName,
|
|
parser,
|
|
};
|
|
const result = env.handler(context, args, optArgs);
|
|
parser.expect("\\end", false);
|
|
const endNameToken = parser.nextToken;
|
|
const end = assertNodeType(parser.parseFunction(), "environment");
|
|
if (end.name !== envName) {
|
|
throw new ParseError(
|
|
`Mismatch: \\begin{${envName}} matched by \\end{${end.name}}`,
|
|
endNameToken);
|
|
}
|
|
// $FlowFixMe, "environment" handler returns an environment ParseNode
|
|
return result;
|
|
}
|
|
|
|
return {
|
|
type: "environment",
|
|
mode: parser.mode,
|
|
name: envName,
|
|
nameGroup,
|
|
};
|
|
},
|
|
});
|