mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-10 21:48:41 +00:00
extract sizing and styling implicit functions (#1116)
* extract sizing and styling implicit functions * add BreakToken type
This commit is contained in:
@@ -5,7 +5,6 @@ import functions from "./functions";
|
|||||||
import environments from "./environments";
|
import environments from "./environments";
|
||||||
import MacroExpander from "./MacroExpander";
|
import MacroExpander from "./MacroExpander";
|
||||||
import symbols from "./symbols";
|
import symbols from "./symbols";
|
||||||
import utils from "./utils";
|
|
||||||
import { validUnit } from "./units";
|
import { validUnit } from "./units";
|
||||||
import { supportedCodepoint } from "./unicodeScripts";
|
import { supportedCodepoint } from "./unicodeScripts";
|
||||||
import unicodeAccents from "./unicodeAccents";
|
import unicodeAccents from "./unicodeAccents";
|
||||||
@@ -16,7 +15,7 @@ import { combiningDiacriticalMarksEndRegex } from "./Lexer.js";
|
|||||||
import Settings from "./Settings";
|
import Settings from "./Settings";
|
||||||
import { Token } from "./Token";
|
import { Token } from "./Token";
|
||||||
|
|
||||||
import type { Mode, ArgType } from "./types";
|
import type { Mode, ArgType, BreakToken } from "./types";
|
||||||
import type { FunctionContext, FunctionSpec } from "./defineFunction" ;
|
import type { FunctionContext, FunctionSpec } from "./defineFunction" ;
|
||||||
import type { EnvSpec } from "./defineEnvironment";
|
import type { EnvSpec } from "./defineEnvironment";
|
||||||
|
|
||||||
@@ -184,7 +183,7 @@ export default class Parser {
|
|||||||
*/
|
*/
|
||||||
parseExpression(
|
parseExpression(
|
||||||
breakOnInfix: boolean,
|
breakOnInfix: boolean,
|
||||||
breakOnTokenText?: "]" | "}" | "$",
|
breakOnTokenText?: BreakToken,
|
||||||
): ParseNode[] {
|
): ParseNode[] {
|
||||||
const body = [];
|
const body = [];
|
||||||
// Keep adding atoms to the body until we can't parse any more atoms (either
|
// Keep adding atoms to the body until we can't parse any more atoms (either
|
||||||
@@ -348,7 +347,7 @@ export default class Parser {
|
|||||||
/**
|
/**
|
||||||
* Parses a group with optional super/subscripts.
|
* Parses a group with optional super/subscripts.
|
||||||
*/
|
*/
|
||||||
parseAtom(breakOnTokenText?: "]" | "}" | "$"): ?ParseNode {
|
parseAtom(breakOnTokenText?: BreakToken): ?ParseNode {
|
||||||
// The body of an atom is an implicit group, so that things like
|
// The body of an atom is an implicit group, so that things like
|
||||||
// \left(x\right)^2 work correctly.
|
// \left(x\right)^2 work correctly.
|
||||||
const base = this.parseImplicitGroup(breakOnTokenText);
|
const base = this.parseImplicitGroup(breakOnTokenText);
|
||||||
@@ -435,17 +434,6 @@ export default class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A list of the size-changing functions, for use in parseImplicitGroup
|
|
||||||
static sizeFuncs = [
|
|
||||||
"\\tiny", "\\sixptsize", "\\scriptsize", "\\footnotesize", "\\small",
|
|
||||||
"\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge",
|
|
||||||
];
|
|
||||||
|
|
||||||
// A list of the style-changing functions, for use in parseImplicitGroup
|
|
||||||
static styleFuncs = [
|
|
||||||
"\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Old font functions
|
// Old font functions
|
||||||
static oldFontFuncs = {
|
static oldFontFuncs = {
|
||||||
"\\rm": "mathrm",
|
"\\rm": "mathrm",
|
||||||
@@ -465,7 +453,7 @@ export default class Parser {
|
|||||||
* implicit grouping after it until the end of the group. E.g.
|
* implicit grouping after it until the end of the group. E.g.
|
||||||
* small text {\Large large text} small text again
|
* small text {\Large large text} small text again
|
||||||
*/
|
*/
|
||||||
parseImplicitGroup(breakOnTokenText?: "]" | "}" | "$"): ?ParseNode {
|
parseImplicitGroup(breakOnTokenText?: BreakToken): ?ParseNode {
|
||||||
const start = this.parseSymbol();
|
const start = this.parseSymbol();
|
||||||
|
|
||||||
if (start == null) {
|
if (start == null) {
|
||||||
@@ -527,25 +515,6 @@ export default class Parser {
|
|||||||
endNameToken);
|
endNameToken);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} else if (utils.contains(Parser.sizeFuncs, func)) {
|
|
||||||
// If we see a sizing function, parse out the implicit body
|
|
||||||
this.consumeSpaces();
|
|
||||||
const body = this.parseExpression(false, breakOnTokenText);
|
|
||||||
return new ParseNode("sizing", {
|
|
||||||
// Figure out what size to use based on the list of functions above
|
|
||||||
size: utils.indexOf(Parser.sizeFuncs, func) + 1,
|
|
||||||
value: body,
|
|
||||||
}, this.mode);
|
|
||||||
} else if (utils.contains(Parser.styleFuncs, func)) {
|
|
||||||
// If we see a styling function, parse out the implicit body
|
|
||||||
this.consumeSpaces();
|
|
||||||
const body = this.parseExpression(true, breakOnTokenText);
|
|
||||||
return new ParseNode("styling", {
|
|
||||||
// Figure out what style to use by pulling out the style from
|
|
||||||
// the function name
|
|
||||||
style: func.slice(1, func.length - 5),
|
|
||||||
value: body,
|
|
||||||
}, this.mode);
|
|
||||||
} else if (func in Parser.oldFontFuncs) {
|
} else if (func in Parser.oldFontFuncs) {
|
||||||
const style = Parser.oldFontFuncs[func];
|
const style = Parser.oldFontFuncs[func];
|
||||||
// If we see an old font function, parse out the implicit body
|
// If we see an old font function, parse out the implicit body
|
||||||
@@ -576,7 +545,7 @@ export default class Parser {
|
|||||||
}, this.mode);
|
}, this.mode);
|
||||||
} else {
|
} else {
|
||||||
// Defer to parseGivenFunction if it's not a function we handle
|
// Defer to parseGivenFunction if it's not a function we handle
|
||||||
return this.parseGivenFunction(start);
|
return this.parseGivenFunction(start, breakOnTokenText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -593,7 +562,10 @@ export default class Parser {
|
|||||||
* Same as parseFunction(), except that the base is provided, guaranteeing a
|
* Same as parseFunction(), except that the base is provided, guaranteeing a
|
||||||
* non-nullable result.
|
* non-nullable result.
|
||||||
*/
|
*/
|
||||||
parseGivenFunction(baseGroup: ParsedFuncOrArgOrDollar): ParseNode {
|
parseGivenFunction(
|
||||||
|
baseGroup: ParsedFuncOrArgOrDollar,
|
||||||
|
breakOnTokenText?: BreakToken,
|
||||||
|
): ParseNode {
|
||||||
baseGroup = assertFuncOrArg(baseGroup);
|
baseGroup = assertFuncOrArg(baseGroup);
|
||||||
if (baseGroup.type === "fn") {
|
if (baseGroup.type === "fn") {
|
||||||
const func = baseGroup.result;
|
const func = baseGroup.result;
|
||||||
@@ -611,7 +583,8 @@ export default class Parser {
|
|||||||
|
|
||||||
const {args, optArgs} = this.parseArguments(func, funcData);
|
const {args, optArgs} = this.parseArguments(func, funcData);
|
||||||
const token = baseGroup.token;
|
const token = baseGroup.token;
|
||||||
const result = this.callFunction(func, args, optArgs, token);
|
const result =
|
||||||
|
this.callFunction(func, args, optArgs, token, breakOnTokenText);
|
||||||
return new ParseNode(result.type, result, this.mode);
|
return new ParseNode(result.type, result, this.mode);
|
||||||
} else {
|
} else {
|
||||||
return baseGroup.result;
|
return baseGroup.result;
|
||||||
@@ -626,11 +599,13 @@ export default class Parser {
|
|||||||
args: ParseNode[],
|
args: ParseNode[],
|
||||||
optArgs: (?ParseNode)[],
|
optArgs: (?ParseNode)[],
|
||||||
token?: Token,
|
token?: Token,
|
||||||
|
breakOnTokenText?: BreakToken,
|
||||||
): * {
|
): * {
|
||||||
const context: FunctionContext = {
|
const context: FunctionContext = {
|
||||||
funcName: name,
|
funcName: name,
|
||||||
parser: this,
|
parser: this,
|
||||||
token,
|
token,
|
||||||
|
breakOnTokenText,
|
||||||
};
|
};
|
||||||
const func = functions[name];
|
const func = functions[name];
|
||||||
if (func && func.handler) {
|
if (func && func.handler) {
|
||||||
|
@@ -422,46 +422,6 @@ groupTypes.spacing = function(group, options) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function sizingGroup(value, options, baseOptions) {
|
|
||||||
const inner = buildExpression(value, options, false);
|
|
||||||
const multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier;
|
|
||||||
|
|
||||||
// Add size-resetting classes to the inner list and set maxFontSize
|
|
||||||
// manually. Handle nested size changes.
|
|
||||||
for (let i = 0; i < inner.length; i++) {
|
|
||||||
const pos = utils.indexOf(inner[i].classes, "sizing");
|
|
||||||
if (pos < 0) {
|
|
||||||
Array.prototype.push.apply(inner[i].classes,
|
|
||||||
options.sizingClasses(baseOptions));
|
|
||||||
} else if (inner[i].classes[pos + 1] === "reset-size" + options.size) {
|
|
||||||
// This is a nested size change: e.g., inner[i] is the "b" in
|
|
||||||
// `\Huge a \small b`. Override the old size (the `reset-` class)
|
|
||||||
// but not the new size.
|
|
||||||
inner[i].classes[pos + 1] = "reset-size" + baseOptions.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
inner[i].height *= multiplier;
|
|
||||||
inner[i].depth *= multiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buildCommon.makeFragment(inner);
|
|
||||||
}
|
|
||||||
|
|
||||||
groupTypes.sizing = function(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);
|
|
||||||
};
|
|
||||||
|
|
||||||
groupTypes.styling = function(group, options) {
|
|
||||||
// Style changes are handled in the TeXbook on pg. 442, Rule 3.
|
|
||||||
const newStyle = styleMap[group.value.style];
|
|
||||||
const newOptions = options.havingStyle(newStyle);
|
|
||||||
return sizingGroup(group.value.value, newOptions, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
groupTypes.font = function(group, options) {
|
groupTypes.font = function(group, options) {
|
||||||
const font = group.value.font;
|
const font = group.value.font;
|
||||||
return buildGroup(group.value.body, options.withFontFamily(font));
|
return buildGroup(group.value.body, options.withFontFamily(font));
|
||||||
|
@@ -247,55 +247,6 @@ groupTypes.font = function(group, options) {
|
|||||||
return buildGroup(group.value.body, options.withFontFamily(font));
|
return buildGroup(group.value.body, options.withFontFamily(font));
|
||||||
};
|
};
|
||||||
|
|
||||||
groupTypes.styling = function(group, options) {
|
|
||||||
// Figure out what style we're changing to.
|
|
||||||
// TODO(kevinb): dedupe this with buildHTML.js
|
|
||||||
// This will be easier of handling of styling nodes is in the same file.
|
|
||||||
const styleMap = {
|
|
||||||
"display": Style.DISPLAY,
|
|
||||||
"text": Style.TEXT,
|
|
||||||
"script": Style.SCRIPT,
|
|
||||||
"scriptscript": Style.SCRIPTSCRIPT,
|
|
||||||
};
|
|
||||||
|
|
||||||
const newStyle = styleMap[group.value.style];
|
|
||||||
const newOptions = options.havingStyle(newStyle);
|
|
||||||
|
|
||||||
const inner = buildExpression(group.value.value, newOptions);
|
|
||||||
|
|
||||||
const node = new mathMLTree.MathNode("mstyle", inner);
|
|
||||||
|
|
||||||
const styleAttributes = {
|
|
||||||
"display": ["0", "true"],
|
|
||||||
"text": ["0", "false"],
|
|
||||||
"script": ["1", "false"],
|
|
||||||
"scriptscript": ["2", "false"],
|
|
||||||
};
|
|
||||||
|
|
||||||
const attr = styleAttributes[group.value.style];
|
|
||||||
|
|
||||||
node.setAttribute("scriptlevel", attr[0]);
|
|
||||||
node.setAttribute("displaystyle", attr[1]);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
};
|
|
||||||
|
|
||||||
groupTypes.sizing = function(group, options) {
|
|
||||||
const newOptions = options.havingSize(group.value.size);
|
|
||||||
const inner = buildExpression(group.value.value, newOptions);
|
|
||||||
|
|
||||||
const node = new mathMLTree.MathNode("mstyle", inner);
|
|
||||||
|
|
||||||
// TODO(emily): This doesn't produce the correct size for nested size
|
|
||||||
// changes, because we don't keep state of what style we're currently
|
|
||||||
// in, so we can't reset the size to normal before changing it. Now
|
|
||||||
// that we're passing an options parameter we should be able to fix
|
|
||||||
// this.
|
|
||||||
node.setAttribute("mathsize", newOptions.sizeMultiplier + "em");
|
|
||||||
|
|
||||||
return node;
|
|
||||||
};
|
|
||||||
|
|
||||||
groupTypes.horizBrace = function(group, options) {
|
groupTypes.horizBrace = function(group, options) {
|
||||||
const accentNode = stretchy.mathMLnode(group.value.label);
|
const accentNode = stretchy.mathMLnode(group.value.label);
|
||||||
return new mathMLTree.MathNode(
|
return new mathMLTree.MathNode(
|
||||||
|
@@ -5,7 +5,7 @@ import {groupTypes as mathmlGroupTypes} from "./buildMathML";
|
|||||||
import type Parser from "./Parser" ;
|
import type Parser from "./Parser" ;
|
||||||
import type ParseNode from "./ParseNode" ;
|
import type ParseNode from "./ParseNode" ;
|
||||||
import type Options from "./Options";
|
import type Options from "./Options";
|
||||||
import type {ArgType} from "./types" ;
|
import type {ArgType, BreakToken} from "./types" ;
|
||||||
import type {Token} from "./Token" ;
|
import type {Token} from "./Token" ;
|
||||||
|
|
||||||
/** Context provided to function handlers for error messages. */
|
/** Context provided to function handlers for error messages. */
|
||||||
@@ -13,6 +13,7 @@ export type FunctionContext = {|
|
|||||||
funcName: string,
|
funcName: string,
|
||||||
parser: Parser,
|
parser: Parser,
|
||||||
token?: Token,
|
token?: Token,
|
||||||
|
breakOnTokenText?: BreakToken,
|
||||||
|};
|
|};
|
||||||
|
|
||||||
// TODO: Enumerate all allowed output types.
|
// TODO: Enumerate all allowed output types.
|
||||||
|
@@ -179,18 +179,9 @@ import "./functions/smash";
|
|||||||
|
|
||||||
import "./functions/delimsizing";
|
import "./functions/delimsizing";
|
||||||
|
|
||||||
// Sizing functions (handled in Parser.js explicitly, hence no handler)
|
import "./functions/sizing";
|
||||||
defineFunction([
|
|
||||||
"\\tiny", "\\scriptsize", "\\footnotesize", "\\small",
|
|
||||||
"\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge",
|
|
||||||
], {numArgs: 0}, null);
|
|
||||||
|
|
||||||
// Style changing functions (handled in Parser.js explicitly, hence no
|
import "./functions/styling";
|
||||||
// handler)
|
|
||||||
defineFunction([
|
|
||||||
"\\displaystyle", "\\textstyle", "\\scriptstyle",
|
|
||||||
"\\scriptscriptstyle",
|
|
||||||
], {numArgs: 0}, null);
|
|
||||||
|
|
||||||
// Old font changing functions
|
// Old font changing functions
|
||||||
defineFunction([
|
defineFunction([
|
||||||
|
84
src/functions/sizing.js
Normal file
84
src/functions/sizing.js
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
// @flow
|
||||||
|
import buildCommon from "../buildCommon";
|
||||||
|
import defineFunction from "../defineFunction";
|
||||||
|
import mathMLTree from "../mathMLTree";
|
||||||
|
import utils from "../utils";
|
||||||
|
|
||||||
|
import * as html from "../buildHTML";
|
||||||
|
import * as mml from "../buildMathML";
|
||||||
|
|
||||||
|
import type Options from "../Options";
|
||||||
|
|
||||||
|
export function sizingGroup(value: *, options: Options, baseOptions: Options) {
|
||||||
|
const inner = html.buildExpression(value, options, false);
|
||||||
|
const multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier;
|
||||||
|
|
||||||
|
// Add size-resetting classes to the inner list and set maxFontSize
|
||||||
|
// manually. Handle nested size changes.
|
||||||
|
for (let i = 0; i < inner.length; i++) {
|
||||||
|
const pos = utils.indexOf(inner[i].classes, "sizing");
|
||||||
|
if (pos < 0) {
|
||||||
|
Array.prototype.push.apply(inner[i].classes,
|
||||||
|
options.sizingClasses(baseOptions));
|
||||||
|
} else if (inner[i].classes[pos + 1] === "reset-size" + options.size) {
|
||||||
|
// This is a nested size change: e.g., inner[i] is the "b" in
|
||||||
|
// `\Huge a \small b`. Override the old size (the `reset-` class)
|
||||||
|
// but not the new size.
|
||||||
|
inner[i].classes[pos + 1] = "reset-size" + baseOptions.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
inner[i].height *= multiplier;
|
||||||
|
inner[i].depth *= multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildCommon.makeFragment(inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
const sizeFuncs = [
|
||||||
|
"\\tiny", "\\sixptsize", "\\scriptsize", "\\footnotesize", "\\small",
|
||||||
|
"\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge",
|
||||||
|
];
|
||||||
|
|
||||||
|
defineFunction({
|
||||||
|
type: "sizing",
|
||||||
|
names: sizeFuncs,
|
||||||
|
props: {
|
||||||
|
numArgs: 0,
|
||||||
|
allowedInText: true,
|
||||||
|
},
|
||||||
|
handler: (context, args) => {
|
||||||
|
const {breakOnTokenText, funcName, parser} = context;
|
||||||
|
|
||||||
|
parser.consumeSpaces();
|
||||||
|
const body = parser.parseExpression(false, breakOnTokenText);
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "sizing",
|
||||||
|
// Figure out what size to use based on the list of functions above
|
||||||
|
size: utils.indexOf(sizeFuncs, funcName) + 1,
|
||||||
|
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);
|
||||||
|
},
|
||||||
|
mathmlBuilder: (group, options) => {
|
||||||
|
const newOptions = options.havingSize(group.value.size);
|
||||||
|
const inner = mml.buildExpression(group.value.value, newOptions);
|
||||||
|
|
||||||
|
const node = new mathMLTree.MathNode("mstyle", inner);
|
||||||
|
|
||||||
|
// TODO(emily): This doesn't produce the correct size for nested size
|
||||||
|
// changes, because we don't keep state of what style we're currently
|
||||||
|
// in, so we can't reset the size to normal before changing it. Now
|
||||||
|
// that we're passing an options parameter we should be able to fix
|
||||||
|
// this.
|
||||||
|
node.setAttribute("mathsize", newOptions.sizeMultiplier + "em");
|
||||||
|
|
||||||
|
return node;
|
||||||
|
},
|
||||||
|
});
|
79
src/functions/styling.js
Normal file
79
src/functions/styling.js
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
// @flow
|
||||||
|
import defineFunction from "../defineFunction";
|
||||||
|
import mathMLTree from "../mathMLTree";
|
||||||
|
import Style from "../Style";
|
||||||
|
import {sizingGroup} from "./sizing";
|
||||||
|
|
||||||
|
import * as mml from "../buildMathML";
|
||||||
|
|
||||||
|
const styleMap = {
|
||||||
|
"display": Style.DISPLAY,
|
||||||
|
"text": Style.TEXT,
|
||||||
|
"script": Style.SCRIPT,
|
||||||
|
"scriptscript": Style.SCRIPTSCRIPT,
|
||||||
|
};
|
||||||
|
|
||||||
|
defineFunction({
|
||||||
|
type: "styling",
|
||||||
|
names: [
|
||||||
|
"\\displaystyle", "\\textstyle", "\\scriptstyle",
|
||||||
|
"\\scriptscriptstyle",
|
||||||
|
],
|
||||||
|
props: {
|
||||||
|
numArgs: 0,
|
||||||
|
allowedInText: true,
|
||||||
|
},
|
||||||
|
handler: (context, args) => {
|
||||||
|
const {breakOnTokenText, funcName, parser} = context;
|
||||||
|
|
||||||
|
// parse out the implicit body
|
||||||
|
parser.consumeSpaces();
|
||||||
|
const body = parser.parseExpression(true, breakOnTokenText);
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "styling",
|
||||||
|
// Figure out what style to use by pulling out the style from
|
||||||
|
// the function name
|
||||||
|
style: funcName.slice(1, funcName.length - 5),
|
||||||
|
value: body,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
htmlBuilder: (group, options) => {
|
||||||
|
// Style changes are handled in the TeXbook on pg. 442, Rule 3.
|
||||||
|
const newStyle = styleMap[group.value.style];
|
||||||
|
const newOptions = options.havingStyle(newStyle);
|
||||||
|
return sizingGroup(group.value.value, newOptions, options);
|
||||||
|
},
|
||||||
|
mathmlBuilder: (group, options) => {
|
||||||
|
// Figure out what style we're changing to.
|
||||||
|
// TODO(kevinb): dedupe this with buildHTML.js
|
||||||
|
// This will be easier of handling of styling nodes is in the same file.
|
||||||
|
const styleMap = {
|
||||||
|
"display": Style.DISPLAY,
|
||||||
|
"text": Style.TEXT,
|
||||||
|
"script": Style.SCRIPT,
|
||||||
|
"scriptscript": Style.SCRIPTSCRIPT,
|
||||||
|
};
|
||||||
|
|
||||||
|
const newStyle = styleMap[group.value.style];
|
||||||
|
const newOptions = options.havingStyle(newStyle);
|
||||||
|
|
||||||
|
const inner = mml.buildExpression(group.value.value, newOptions);
|
||||||
|
|
||||||
|
const node = new mathMLTree.MathNode("mstyle", inner);
|
||||||
|
|
||||||
|
const styleAttributes = {
|
||||||
|
"display": ["0", "true"],
|
||||||
|
"text": ["0", "false"],
|
||||||
|
"script": ["1", "false"],
|
||||||
|
"scriptscript": ["2", "false"],
|
||||||
|
};
|
||||||
|
|
||||||
|
const attr = styleAttributes[group.value.style];
|
||||||
|
|
||||||
|
node.setAttribute("scriptlevel", attr[0]);
|
||||||
|
node.setAttribute("displaystyle", attr[1]);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
},
|
||||||
|
});
|
@@ -22,3 +22,5 @@ export type ArgType = "color" | "size" | "url" | "original" | Mode;
|
|||||||
|
|
||||||
// LaTeX display style.
|
// LaTeX display style.
|
||||||
export type StyleStr = "text" | "display";
|
export type StyleStr = "text" | "display";
|
||||||
|
|
||||||
|
export type BreakToken = "]" | "}" | "$";
|
||||||
|
@@ -26,6 +26,7 @@ exports[`An implicit group parser within optional groups should work style comma
|
|||||||
"type": "styling",
|
"type": "styling",
|
||||||
"mode": "math",
|
"mode": "math",
|
||||||
"value": {
|
"value": {
|
||||||
|
"type": "styling",
|
||||||
"style": "text",
|
"style": "text",
|
||||||
"value": [
|
"value": [
|
||||||
{
|
{
|
||||||
@@ -113,6 +114,7 @@ exports[`An implicit group parser within optional groups should work with sizing
|
|||||||
"type": "sizing",
|
"type": "sizing",
|
||||||
"mode": "math",
|
"mode": "math",
|
||||||
"value": {
|
"value": {
|
||||||
|
"type": "sizing",
|
||||||
"size": 5,
|
"size": 5,
|
||||||
"value": [
|
"value": [
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user