mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-05 19:28:39 +00:00
Correct (type-wise) raisebox's usage of sizing's buildHtml. (#1361)
* Correct (type-wise) raisebox's usage of sizing's buildHtml. * Move HTML and MathML groupTypes into defineFunction. Currently, functions defined in functions/* import all exports from buildHtml and buildMathML, but they should never use `groupTypes` directly as it loses type-safety. They should instead use more type-safe `htmlBuilder`s and `mathmlBuilder`s exported directly from other definitions `functions/*` to allow flow to catch errors. * Rename groupTypes to groupBuilders.
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* This file does the main work of building a domTree structure from a parse
|
||||
* tree. The entry point is the `buildHTML` function, which takes a parse tree.
|
||||
* Then, the buildExpression, buildGroup, and various groupTypes functions are
|
||||
* called, to produce a final HTML tree.
|
||||
* Then, the buildExpression, buildGroup, and various groupBuilders functions
|
||||
* are called, to produce a final HTML tree.
|
||||
*/
|
||||
|
||||
import ParseError from "./ParseError";
|
||||
@@ -12,6 +12,7 @@ import buildCommon from "./buildCommon";
|
||||
import domTree from "./domTree";
|
||||
import utils from "./utils";
|
||||
import {spacings, tightSpacings} from "./spacingData";
|
||||
import {_htmlGroupBuilders as groupBuilders} from "./defineFunction";
|
||||
|
||||
const makeSpan = buildCommon.makeSpan;
|
||||
|
||||
@@ -209,9 +210,6 @@ export const makeNullDelimiter = function(options, classes) {
|
||||
return makeSpan(classes.concat(moreClasses));
|
||||
};
|
||||
|
||||
/** This is a map of group types to the function used to handle that type. */
|
||||
export const groupTypes = {};
|
||||
|
||||
/**
|
||||
* buildGroup is the function that takes a group and calls the correct groupType
|
||||
* function for it. It also handles the interaction of size and style changes
|
||||
@@ -222,9 +220,9 @@ export const buildGroup = function(group, options, baseOptions) {
|
||||
return makeSpan();
|
||||
}
|
||||
|
||||
if (groupTypes[group.type]) {
|
||||
// Call the groupTypes function
|
||||
let groupNode = groupTypes[group.type](group, options);
|
||||
if (groupBuilders[group.type]) {
|
||||
// Call the groupBuilders function
|
||||
let groupNode = groupBuilders[group.type](group, options);
|
||||
|
||||
// If the size changed between the parent and the current group, account
|
||||
// for that size difference.
|
||||
|
@@ -10,6 +10,7 @@ import mathMLTree from "./mathMLTree";
|
||||
import ParseError from "./ParseError";
|
||||
import symbols from "./symbols";
|
||||
import utils from "./utils";
|
||||
import {_mathmlGroupBuilders as groupBuilders} from "./defineFunction";
|
||||
|
||||
/**
|
||||
* Takes a symbol and converts it into a MathML text node after performing
|
||||
@@ -70,12 +71,6 @@ export const getVariant = function(group, options) {
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Functions for handling the different types of groups found in the parse
|
||||
* tree. Each function should take a parse group and return a MathML node.
|
||||
*/
|
||||
export const groupTypes = {};
|
||||
|
||||
/**
|
||||
* Takes a list of nodes, builds them, and returns a list of the generated
|
||||
* MathML nodes. Also combine consecutive <mtext> outputs into a single
|
||||
@@ -118,7 +113,7 @@ export const buildExpressionRow = function(expression, options) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes a group from the parser and calls the appropriate groupTypes function
|
||||
* Takes a group from the parser and calls the appropriate groupBuilders function
|
||||
* on it to produce a MathML node.
|
||||
*/
|
||||
export const buildGroup = function(group, options) {
|
||||
@@ -126,9 +121,9 @@ export const buildGroup = function(group, options) {
|
||||
return new mathMLTree.MathNode("mrow");
|
||||
}
|
||||
|
||||
if (groupTypes[group.type]) {
|
||||
// Call the groupTypes function
|
||||
const result = groupTypes[group.type](group, options);
|
||||
if (groupBuilders[group.type]) {
|
||||
// Call the groupBuilders function
|
||||
const result = groupBuilders[group.type](group, options);
|
||||
return result;
|
||||
} else {
|
||||
throw new ParseError(
|
||||
|
@@ -1,6 +1,5 @@
|
||||
// @flow
|
||||
import {groupTypes as htmlGroupTypes} from "./buildHTML";
|
||||
import {groupTypes as mathmlGroupTypes} from "./buildMathML";
|
||||
import {_htmlGroupBuilders, _mathmlGroupBuilders} from "./defineFunction";
|
||||
|
||||
import Options from "./Options";
|
||||
import ParseNode from "./ParseNode";
|
||||
@@ -114,9 +113,9 @@ export default function defineEnvironment<NODETYPE: NodeType>({
|
||||
_environments[names[i]] = data;
|
||||
}
|
||||
if (htmlBuilder) {
|
||||
htmlGroupTypes[type] = htmlBuilder;
|
||||
_htmlGroupBuilders[type] = htmlBuilder;
|
||||
}
|
||||
if (mathmlBuilder) {
|
||||
mathmlGroupTypes[type] = mathmlBuilder;
|
||||
_mathmlGroupBuilders[type] = mathmlBuilder;
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,4 @@
|
||||
// @flow
|
||||
import {groupTypes as htmlGroupTypes} from "./buildHTML";
|
||||
import {groupTypes as mathmlGroupTypes} from "./buildMathML";
|
||||
import {checkNodeType} from "./ParseNode";
|
||||
import domTree from "./domTree";
|
||||
|
||||
@@ -170,6 +168,18 @@ export type FunctionSpec<NODETYPE: NodeType> = {|
|
||||
*/
|
||||
export const _functions: {[string]: FunctionSpec<*>} = {};
|
||||
|
||||
/**
|
||||
* All HTML builders. Should be only used in the `define*` and the `build*ML`
|
||||
* functions.
|
||||
*/
|
||||
export const _htmlGroupBuilders: {[string]: HtmlBuilder<*>} = {};
|
||||
|
||||
/**
|
||||
* All MathML builders. Should be only used in the `define*` and the `build*ML`
|
||||
* functions.
|
||||
*/
|
||||
export const _mathmlGroupBuilders: {[string]: MathMLBuilder<*>} = {};
|
||||
|
||||
export default function defineFunction<NODETYPE: NodeType>({
|
||||
type,
|
||||
nodeType,
|
||||
@@ -199,10 +209,10 @@ export default function defineFunction<NODETYPE: NodeType>({
|
||||
}
|
||||
if (type) {
|
||||
if (htmlBuilder) {
|
||||
htmlGroupTypes[type] = htmlBuilder;
|
||||
_htmlGroupBuilders[type] = htmlBuilder;
|
||||
}
|
||||
if (mathmlBuilder) {
|
||||
mathmlGroupTypes[type] = mathmlBuilder;
|
||||
_mathmlGroupBuilders[type] = mathmlBuilder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,11 +2,11 @@
|
||||
import defineFunction, {ordargument} from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import {assertNodeType} from "../ParseNode";
|
||||
import ParseNode, {assertNodeType} from "../ParseNode";
|
||||
import {calculateSize} from "../units";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
import * as sizing from "./sizing";
|
||||
|
||||
// Box manipulation
|
||||
defineFunction({
|
||||
@@ -28,16 +28,17 @@ defineFunction({
|
||||
};
|
||||
},
|
||||
htmlBuilder(group, options) {
|
||||
const body = html.groupTypes.sizing({value: {
|
||||
value: [{
|
||||
type: "text",
|
||||
value: {
|
||||
body: group.value.value,
|
||||
font: "mathrm", // simulate \textrm
|
||||
},
|
||||
}],
|
||||
const text = new ParseNode("text", {
|
||||
type: "text",
|
||||
body: group.value.value,
|
||||
font: "mathrm", // simulate \textrm
|
||||
}, group.mode);
|
||||
const sizedText = new ParseNode("sizing", {
|
||||
type: "sizing",
|
||||
value: [text],
|
||||
size: 6, // simulate \normalsize
|
||||
}}, options);
|
||||
}, group.mode);
|
||||
const body = sizing.htmlBuilder(sizedText, options);
|
||||
const dy = calculateSize(group.value.dy.value, options);
|
||||
return buildCommon.makeVList({
|
||||
positionType: "shift",
|
||||
|
@@ -8,6 +8,7 @@ import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
import type Options from "../Options";
|
||||
import type {HtmlBuilder} from "../defineFunction";
|
||||
|
||||
export function sizingGroup(value: *, options: Options, baseOptions: Options) {
|
||||
const inner = html.buildExpression(value, options, false);
|
||||
@@ -39,6 +40,14 @@ const sizeFuncs = [
|
||||
"\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge",
|
||||
];
|
||||
|
||||
export const htmlBuilder: HtmlBuilder<"sizing"> = (group, options) => {
|
||||
// Handle sizing operators like \Huge. Real TeX doesn't actually allow
|
||||
// these functions inside of math expressions, so we do some special
|
||||
// handling.
|
||||
const newOptions = options.havingSize(group.value.size);
|
||||
return sizingGroup(group.value.value, newOptions, options);
|
||||
};
|
||||
|
||||
defineFunction({
|
||||
type: "sizing",
|
||||
names: sizeFuncs,
|
||||
@@ -59,13 +68,7 @@ defineFunction({
|
||||
value: body,
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
// Handle sizing operators like \Huge. Real TeX doesn't actually allow
|
||||
// these functions inside of math expressions, so we do some special
|
||||
// handling.
|
||||
const newOptions = options.havingSize(group.value.size);
|
||||
return sizingGroup(group.value.value, newOptions, options);
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder: (group, options) => {
|
||||
const newOptions = options.havingSize(group.value.size);
|
||||
const inner = mml.buildExpression(group.value.value, newOptions);
|
||||
|
Reference in New Issue
Block a user