mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-05 11:18:39 +00:00
Make ParseNodeTypes more regular (#1373)
Make ParseNodeTypes more regular: make 'size' and 'url' node values be objects.
This commit is contained in:
committed by
Ashish Myles
parent
659b4e30c8
commit
3ec752f5f1
4988
package-lock.json
generated
4988
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -38,23 +38,15 @@ export default class ParseNode<TYPE: NodeType> {
|
||||
export type NodeType = $Keys<ParseNodeTypes>;
|
||||
export type NodeValue<TYPE: NodeType> = $ElementType<ParseNodeTypes, TYPE>;
|
||||
|
||||
export type AccentStructType = {|
|
||||
type: "accent" | "accentUnder",
|
||||
label: string,
|
||||
isStretchy?: boolean,
|
||||
isShifty?: boolean,
|
||||
base: ParseNode<*>,
|
||||
|};
|
||||
|
||||
export type LeftRightDelimType = {|
|
||||
type?: "leftright",
|
||||
type: "leftright",
|
||||
body: ParseNode<*>[],
|
||||
left: string,
|
||||
right: string,
|
||||
|};
|
||||
|
||||
// Map from `type` field value to corresponding `value` type.
|
||||
type ParseNodeTypes = {
|
||||
export type ParseNodeTypes = {
|
||||
"array": ArrayEnvNodeData,
|
||||
"color": {|
|
||||
type: "color",
|
||||
@@ -62,14 +54,6 @@ type ParseNodeTypes = {
|
||||
value: ParseNode<*>[],
|
||||
|},
|
||||
"color-token": string,
|
||||
"leftright": {|
|
||||
body: [{|
|
||||
type: "array",
|
||||
hskipBeforeAndAfter: boolean,
|
||||
|} | ParseNode<*>],
|
||||
left: string,
|
||||
right: string,
|
||||
|},
|
||||
// To avoid requiring run-time type assertions, this more carefully captures
|
||||
// the requirements on the fields per the op.js htmlBuilder logic:
|
||||
// - `body` and `value` are NEVER set simultanouesly.
|
||||
@@ -92,18 +76,23 @@ type ParseNodeTypes = {
|
||||
value: ParseNode<*>[],
|
||||
|},
|
||||
"ordgroup": ParseNode<*>[],
|
||||
"size": Measurement,
|
||||
"size": {|
|
||||
type: "size",
|
||||
value: Measurement,
|
||||
|},
|
||||
"styling": {|
|
||||
type: "styling",
|
||||
style: StyleStr,
|
||||
value: ParseNode<*>[],
|
||||
|},
|
||||
"supsub": {|
|
||||
type: "supsub",
|
||||
base: ?ParseNode<*>,
|
||||
sup?: ?ParseNode<*>,
|
||||
sub?: ?ParseNode<*>,
|
||||
|},
|
||||
"tag": {|
|
||||
type: "tag",
|
||||
body: ParseNode<*>[],
|
||||
tag: ParseNode<*>[],
|
||||
|},
|
||||
@@ -112,8 +101,12 @@ type ParseNodeTypes = {
|
||||
body: ParseNode<*>[],
|
||||
font?: string,
|
||||
|},
|
||||
"url": string,
|
||||
"url": {|
|
||||
type: "url",
|
||||
value: string,
|
||||
|},
|
||||
"verb": {|
|
||||
type: "verb",
|
||||
body: string,
|
||||
star: boolean,
|
||||
|},
|
||||
@@ -133,8 +126,20 @@ type ParseNodeTypes = {
|
||||
"textord": string,
|
||||
// From functions.js and functions/*.js. See also "color", "op", "styling",
|
||||
// and "text" above.
|
||||
"accent": AccentStructType,
|
||||
"accentUnder": AccentStructType,
|
||||
"accent": {|
|
||||
type: "accent",
|
||||
label: string,
|
||||
isStretchy?: boolean,
|
||||
isShifty?: boolean,
|
||||
base: ParseNode<*>,
|
||||
|},
|
||||
"accentUnder": {|
|
||||
type: "accentUnder",
|
||||
label: string,
|
||||
isStretchy?: boolean,
|
||||
isShifty?: boolean,
|
||||
base: ParseNode<*>,
|
||||
|},
|
||||
"cr": {|
|
||||
type: "cr",
|
||||
newRow: boolean,
|
||||
|
@@ -407,6 +407,7 @@ export default class Parser {
|
||||
if (superscript || subscript) {
|
||||
// If we got either a superscript or subscript, create a supsub
|
||||
return new ParseNode("supsub", {
|
||||
type: "supsub",
|
||||
base: base,
|
||||
sup: superscript,
|
||||
sub: subscript,
|
||||
@@ -794,7 +795,10 @@ export default class Parser {
|
||||
// and keep them as-is. Some browser will replace backslashes with
|
||||
// forward slashes.
|
||||
const url = raw.replace(/\\([#$%&~_^{}])/g, '$1');
|
||||
return newArgument(new ParseNode("url", url, this.mode), res);
|
||||
return newArgument(new ParseNode("url", {
|
||||
type: "url",
|
||||
value: url,
|
||||
}, this.mode), res);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -822,7 +826,10 @@ export default class Parser {
|
||||
if (!validUnit(data)) {
|
||||
throw new ParseError("Invalid unit: '" + data.unit + "'", res);
|
||||
}
|
||||
return newArgument(new ParseNode("size", data, this.mode), res);
|
||||
return newArgument(new ParseNode("size", {
|
||||
type: "size",
|
||||
value: data,
|
||||
}, this.mode), res);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -936,6 +943,7 @@ export default class Parser {
|
||||
arg = arg.slice(1, -1); // remove first and last char
|
||||
return newArgument(
|
||||
new ParseNode("verb", {
|
||||
type: "verb",
|
||||
body: arg,
|
||||
star: star,
|
||||
}, "text"), nucleus);
|
||||
|
@@ -207,7 +207,7 @@ const htmlBuilder = function(group, options) {
|
||||
const rowGap = groupValue.rowGaps[r];
|
||||
let gap = 0;
|
||||
if (rowGap) {
|
||||
gap = calculateSize(rowGap.value, options);
|
||||
gap = calculateSize(rowGap.value.value, options);
|
||||
if (gap > 0) { // \@argarraycr
|
||||
gap += arstrutDepth;
|
||||
if (depth < gap) {
|
||||
@@ -502,6 +502,7 @@ defineEnvironment({
|
||||
res = parseArray(context.parser, res, dCellStyle(context.envName));
|
||||
if (delimiters) {
|
||||
res = new ParseNode("leftright", {
|
||||
type: "leftright",
|
||||
body: [res],
|
||||
left: delimiters[0],
|
||||
right: delimiters[1],
|
||||
@@ -549,6 +550,7 @@ defineEnvironment({
|
||||
};
|
||||
res = parseArray(context.parser, res, dCellStyle(context.envName));
|
||||
res = new ParseNode("leftright", {
|
||||
type: "leftright",
|
||||
body: [res],
|
||||
left: "\\{",
|
||||
right: ".",
|
||||
|
@@ -58,7 +58,7 @@ defineFunction({
|
||||
span.classes.push("newline");
|
||||
if (group.value.size) {
|
||||
span.style.marginTop =
|
||||
calculateSize(group.value.size.value, options) + "em";
|
||||
calculateSize(group.value.size.value.value, options) + "em";
|
||||
}
|
||||
}
|
||||
return span;
|
||||
@@ -70,7 +70,7 @@ defineFunction({
|
||||
node.setAttribute("linebreak", "newline");
|
||||
if (group.value.size) {
|
||||
node.setAttribute("height",
|
||||
calculateSize(group.value.size.value, options) + "em");
|
||||
calculateSize(group.value.size.value.value, options) + "em");
|
||||
}
|
||||
}
|
||||
return node;
|
||||
|
@@ -15,7 +15,7 @@ defineFunction({
|
||||
},
|
||||
handler: (context, args) => {
|
||||
const body = args[1];
|
||||
const href = assertNodeType(args[0], "url").value;
|
||||
const href = assertNodeType(args[0], "url").value.value;
|
||||
return {
|
||||
type: "href",
|
||||
href: href,
|
||||
|
@@ -4,7 +4,8 @@
|
||||
import defineFunction from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import { calculateSize } from "../units";
|
||||
import {calculateSize} from "../units";
|
||||
import {assertNodeType} from "../ParseNode";
|
||||
|
||||
// TODO: \hskip and \mskip should support plus and minus in lengths
|
||||
|
||||
@@ -17,14 +18,15 @@ defineFunction({
|
||||
allowedInText: true,
|
||||
},
|
||||
handler: (context, args) => {
|
||||
const size = assertNodeType(args[0], "size");
|
||||
if (context.parser.settings.strict) {
|
||||
const mathFunction = (context.funcName[1] === 'm'); // \mkern, \mskip
|
||||
const muUnit = (args[0].value.unit === 'mu');
|
||||
const muUnit = (size.value.value.unit === 'mu');
|
||||
if (mathFunction) {
|
||||
if (!muUnit) {
|
||||
context.parser.settings.reportNonstrict("mathVsTextUnits",
|
||||
`LaTeX's ${context.funcName} supports only mu units, ` +
|
||||
`not ${args[0].value.unit} units`);
|
||||
`not ${size.value.value.unit} units`);
|
||||
}
|
||||
if (context.parser.mode !== "math") {
|
||||
context.parser.settings.reportNonstrict("mathVsTextUnits",
|
||||
@@ -39,7 +41,7 @@ defineFunction({
|
||||
}
|
||||
return {
|
||||
type: "kern",
|
||||
dimension: args[0].value,
|
||||
dimension: size.value.value,
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
|
@@ -83,6 +83,7 @@ defineFunction({
|
||||
}, baseArg.mode);
|
||||
|
||||
const supsub = new ParseNode("supsub", {
|
||||
type: "supsub",
|
||||
base: baseOp,
|
||||
sup: context.funcName === "\\underset" ? null : shiftedArg,
|
||||
sub: context.funcName === "\\underset" ? shiftedArg : null,
|
||||
|
@@ -39,7 +39,7 @@ defineFunction({
|
||||
size: 6, // simulate \normalsize
|
||||
}, group.mode);
|
||||
const body = sizing.htmlBuilder(sizedText, options);
|
||||
const dy = calculateSize(group.value.dy.value, options);
|
||||
const dy = calculateSize(group.value.dy.value.value, options);
|
||||
return buildCommon.makeVList({
|
||||
positionType: "shift",
|
||||
positionData: -dy,
|
||||
@@ -49,7 +49,8 @@ defineFunction({
|
||||
mathmlBuilder(group, options) {
|
||||
const node = new mathMLTree.MathNode(
|
||||
"mpadded", [mml.buildGroup(group.value.body, options)]);
|
||||
const dy = group.value.dy.value.number + group.value.dy.value.unit;
|
||||
const dy =
|
||||
group.value.dy.value.value.number + group.value.dy.value.value.unit;
|
||||
node.setAttribute("voffset", dy);
|
||||
return node;
|
||||
},
|
||||
|
@@ -20,8 +20,8 @@ defineFunction({
|
||||
return {
|
||||
type: "rule",
|
||||
shift: shift && shift.value,
|
||||
width: width.value,
|
||||
height: height.value,
|
||||
width: width.value.value,
|
||||
height: height.value.value,
|
||||
};
|
||||
},
|
||||
htmlBuilder(group, options) {
|
||||
|
@@ -28,6 +28,7 @@ const parseTree = function(toParse: string, settings: Settings): ParseNode<*>[]
|
||||
}
|
||||
parser.gullet.feed("\\df@tag");
|
||||
tree = [new ParseNode("tag", {
|
||||
type: "tag",
|
||||
body: tree,
|
||||
tag: parser.parse(),
|
||||
}, "text")];
|
||||
|
@@ -1803,6 +1803,7 @@ describe("A parse tree generator", function() {
|
||||
{
|
||||
"type": "supsub",
|
||||
"value": {
|
||||
"type": "supsub",
|
||||
"base": {
|
||||
"type": "mathord",
|
||||
"value": "\\sigma",
|
||||
|
Reference in New Issue
Block a user