mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-07 04:08:43 +00:00
fix(Settings): use schema (#3375)
* refactor: don't repeat SettingsOptions * fix(Settings): use schema
This commit is contained in:
63
cli.js
63
cli.js
@@ -20,51 +20,18 @@ try {
|
|||||||
const {version} = require("./package.json");
|
const {version} = require("./package.json");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
|
|
||||||
const program = require("commander")
|
const program = require("commander").version(version);
|
||||||
.version(version)
|
for (const prop in katex.SETTINGS_SCHEMA) {
|
||||||
.option("-d, --display-mode",
|
if (katex.SETTINGS_SCHEMA.hasOwnProperty(prop)) {
|
||||||
"Render math in display mode, which puts the math in display style " +
|
const opt = katex.SETTINGS_SCHEMA[prop];
|
||||||
"(so \\int and \\sum are large, for example), and centers the math " +
|
if (opt.cli !== false) {
|
||||||
"on the page on its own line.")
|
program.option(opt.cli || "--" + prop, opt.cliDescription ||
|
||||||
.option("--leqno",
|
opt.description, opt.cliProcessor, opt.cliDefault);
|
||||||
"Render display math in leqno style (left-justified tags).")
|
}
|
||||||
.option("--fleqn",
|
}
|
||||||
"Render display math flush left.")
|
}
|
||||||
.option("-t, --no-throw-on-error",
|
program.option("-f, --macro-file <path>",
|
||||||
"Render errors (in the color given by --error-color) instead of " +
|
|
||||||
"throwing a ParseError exception when encountering an error.")
|
|
||||||
.option("-c, --error-color <color>",
|
|
||||||
"A color string given in the format 'rgb' or 'rrggbb' (no #). " +
|
|
||||||
"This option determines the color of errors rendered by the -t option.",
|
|
||||||
"#cc0000",
|
|
||||||
(color) => "#" + color)
|
|
||||||
.option("-b, --color-is-text-color",
|
|
||||||
"Makes \\color behave like LaTeX's 2-argument \\textcolor, " +
|
|
||||||
"instead of LaTeX's one-argument \\color mode change.")
|
|
||||||
.option("-S, --strict",
|
|
||||||
"Turn on strict / LaTeX faithfulness mode, which throws an error " +
|
|
||||||
"if the input uses features that are not supported by LaTeX.")
|
|
||||||
.option("-s, --max-size <n>",
|
|
||||||
"If non-zero, all user-specified sizes, e.g. in " +
|
|
||||||
"\\rule{500em}{500em}, will be capped to maxSize ems. " +
|
|
||||||
"Otherwise, elements and spaces can be arbitrarily large",
|
|
||||||
Infinity, parseInt)
|
|
||||||
.option("-e, --max-expand <n>",
|
|
||||||
"Limit the number of macro expansions to the specified number, to " +
|
|
||||||
"prevent e.g. infinite macro loops. If set to Infinity, the macro " +
|
|
||||||
"expander will try to fully expand as in LaTeX.",
|
|
||||||
(n) => (n === "Infinity" ? Infinity : parseInt(n)))
|
|
||||||
.option("-m, --macro <def>",
|
|
||||||
"Define custom macro of the form '\\foo:expansion' (use multiple -m " +
|
|
||||||
"arguments for multiple macros).",
|
|
||||||
(def, defs) => {
|
|
||||||
defs.push(def);
|
|
||||||
return defs;
|
|
||||||
}, [])
|
|
||||||
.option("-f, --macro-file <path>",
|
|
||||||
"Read macro definitions, one per line, from the given file.")
|
"Read macro definitions, one per line, from the given file.")
|
||||||
.option("-T, --trust",
|
|
||||||
"Trust the input, enabling all HTML features such as \\url.")
|
|
||||||
.option("-i, --input <path>", "Read LaTeX input from the given file.")
|
.option("-i, --input <path>", "Read LaTeX input from the given file.")
|
||||||
.option("-o, --output <path>", "Write html output to the given file.");
|
.option("-o, --output <path>", "Write html output to the given file.");
|
||||||
|
|
||||||
@@ -125,10 +92,14 @@ function readInput() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function writeOutput(input) {
|
function writeOutput(input) {
|
||||||
|
// --format specifies the KaTeX output
|
||||||
|
const outputFile = options.output;
|
||||||
|
options.output = options.format;
|
||||||
|
|
||||||
const output = katex.renderToString(input, options) + "\n";
|
const output = katex.renderToString(input, options) + "\n";
|
||||||
|
|
||||||
if (options.output) {
|
if (outputFile) {
|
||||||
fs.writeFile(options.output, output, function(err) {
|
fs.writeFile(outputFile, output, function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return console.log(err);
|
return console.log(err);
|
||||||
}
|
}
|
||||||
|
6
katex.js
6
katex.js
@@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import ParseError from "./src/ParseError";
|
import ParseError from "./src/ParseError";
|
||||||
import Settings from "./src/Settings";
|
import Settings, {SETTINGS_SCHEMA} from "./src/Settings";
|
||||||
|
|
||||||
import {buildTree, buildHTMLTree} from "./src/buildTree";
|
import {buildTree, buildHTMLTree} from "./src/buildTree";
|
||||||
import parseTree from "./src/parseTree";
|
import parseTree from "./src/parseTree";
|
||||||
@@ -156,6 +156,10 @@ export default {
|
|||||||
* KaTeX error, usually during parsing.
|
* KaTeX error, usually during parsing.
|
||||||
*/
|
*/
|
||||||
ParseError,
|
ParseError,
|
||||||
|
/**
|
||||||
|
* The shema of Settings
|
||||||
|
*/
|
||||||
|
SETTINGS_SCHEMA,
|
||||||
/**
|
/**
|
||||||
* Parses the given LaTeX into KaTeX's internal parse tree structure,
|
* Parses the given LaTeX into KaTeX's internal parse tree structure,
|
||||||
* without rendering to HTML or MathML.
|
* without rendering to HTML or MathML.
|
||||||
|
215
src/Settings.js
215
src/Settings.js
@@ -52,23 +52,180 @@ export type TrustContextTypes = {
|
|||||||
export type AnyTrustContext = $Values<TrustContextTypes>;
|
export type AnyTrustContext = $Values<TrustContextTypes>;
|
||||||
export type TrustFunction = (context: AnyTrustContext) => ?boolean;
|
export type TrustFunction = (context: AnyTrustContext) => ?boolean;
|
||||||
|
|
||||||
export type SettingsOptions = {
|
export type SettingsOptions = $Shape<Settings>;
|
||||||
displayMode?: boolean;
|
|
||||||
output?: "html" | "mathml" | "htmlAndMathml";
|
type EnumType = {| enum: string[] |};
|
||||||
leqno?: boolean;
|
type Type = "boolean" | "string" | "number" | "object" | "function" | EnumType;
|
||||||
fleqn?: boolean;
|
type Schema = {
|
||||||
throwOnError?: boolean;
|
[$Keys<SettingsOptions>]: {
|
||||||
errorColor?: string;
|
/**
|
||||||
macros?: MacroMap;
|
* Allowed type(s) of the value.
|
||||||
minRuleThickness?: number;
|
*/
|
||||||
colorIsTextColor?: boolean;
|
type: Type | Type[];
|
||||||
strict?: boolean | "ignore" | "warn" | "error" | StrictFunction;
|
/**
|
||||||
trust?: boolean | TrustFunction;
|
* The default value. If not specified, false for boolean, an empty string
|
||||||
maxSize?: number;
|
* for string, 0 for number, an empty object for object, or the first item
|
||||||
maxExpand?: number;
|
* for enum will be used. If multiple types are allowed, the first allowed
|
||||||
globalGroup?: boolean;
|
* type will be used for determining the default value.
|
||||||
|
*/
|
||||||
|
default?: any;
|
||||||
|
/**
|
||||||
|
* The description.
|
||||||
|
*/
|
||||||
|
description?: string;
|
||||||
|
/**
|
||||||
|
* The function to process the option.
|
||||||
|
*/
|
||||||
|
processor?: (any) => any,
|
||||||
|
/**
|
||||||
|
* The command line argument. See Commander.js docs for more information.
|
||||||
|
* If not specified, the name prefixed with -- will be used. Set false not
|
||||||
|
* to add to the CLI.
|
||||||
|
*/
|
||||||
|
cli?: string | false;
|
||||||
|
/**
|
||||||
|
* The default value for the CLI.
|
||||||
|
*/
|
||||||
|
cliDefault?: any;
|
||||||
|
/**
|
||||||
|
* The description for the CLI. If not specified, the description for the
|
||||||
|
* option will be used.
|
||||||
|
*/
|
||||||
|
cliDescription?: string;
|
||||||
|
/**
|
||||||
|
* The custom argument processor for the CLI. See Commander.js docs for
|
||||||
|
* more information.
|
||||||
|
*/
|
||||||
|
cliProcessor?: (any, any) => any;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: automatically generate documentation
|
||||||
|
// TODO: check all properties on Settings exist
|
||||||
|
// TODO: check the type of a property on Settings matches
|
||||||
|
export const SETTINGS_SCHEMA: Schema = {
|
||||||
|
displayMode: {
|
||||||
|
type: "boolean",
|
||||||
|
description: "Render math in display mode, which puts the math in " +
|
||||||
|
"display style (so \\int and \\sum are large, for example), and " +
|
||||||
|
"centers the math on the page on its own line.",
|
||||||
|
cli: "-d, --display-mode",
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
type: {enum: ["htmlAndMathml", "html", "mathml"]},
|
||||||
|
description: "Determines the markup language of the output.",
|
||||||
|
cli: "-F, --format <type>",
|
||||||
|
},
|
||||||
|
leqno: {
|
||||||
|
type: "boolean",
|
||||||
|
description: "Render display math in leqno style (left-justified tags).",
|
||||||
|
},
|
||||||
|
fleqn: {
|
||||||
|
type: "boolean",
|
||||||
|
description: "Render display math flush left.",
|
||||||
|
},
|
||||||
|
throwOnError: {
|
||||||
|
type: "boolean",
|
||||||
|
default: true,
|
||||||
|
cli: "-t, --no-throw-on-error",
|
||||||
|
cliDescription: "Render errors (in the color given by --error-color) ins" +
|
||||||
|
"tead of throwing a ParseError exception when encountering an error.",
|
||||||
|
},
|
||||||
|
errorColor: {
|
||||||
|
type: "string",
|
||||||
|
default: "#cc0000",
|
||||||
|
cli: "-c, --error-color <color>",
|
||||||
|
cliDescription: "A color string given in the format 'rgb' or 'rrggbb' " +
|
||||||
|
"(no #). This option determines the color of errors rendered by the " +
|
||||||
|
"-t option.",
|
||||||
|
cliProcessor: (color) => "#" + color,
|
||||||
|
},
|
||||||
|
macros: {
|
||||||
|
type: "object",
|
||||||
|
cli: "-m, --macro <def>",
|
||||||
|
cliDescription: "Define custom macro of the form '\\foo:expansion' (use " +
|
||||||
|
"multiple -m arguments for multiple macros).",
|
||||||
|
cliDefault: [],
|
||||||
|
cliProcessor: (def, defs) => {
|
||||||
|
defs.push(def);
|
||||||
|
return defs;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
minRuleThickness: {
|
||||||
|
type: "number",
|
||||||
|
description: "Specifies a minimum thickness, in ems, for fraction lines," +
|
||||||
|
" `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, " +
|
||||||
|
"`\\hdashline`, `\\underline`, `\\overline`, and the borders of " +
|
||||||
|
"`\\fbox`, `\\boxed`, and `\\fcolorbox`.",
|
||||||
|
processor: (t) => Math.max(0, t),
|
||||||
|
cli: "--min-rule-thickness <size>",
|
||||||
|
cliProcessor: parseFloat,
|
||||||
|
},
|
||||||
|
colorIsTextColor: {
|
||||||
|
type: "boolean",
|
||||||
|
description: "Makes \\color behave like LaTeX's 2-argument \\textcolor, " +
|
||||||
|
"instead of LaTeX's one-argument \\color mode change.",
|
||||||
|
cli: "-b, --color-is-text-color",
|
||||||
|
},
|
||||||
|
strict: {
|
||||||
|
type: [{enum: ["warn", "ignore", "error"]}, "boolean", "function"],
|
||||||
|
description: "Turn on strict / LaTeX faithfulness mode, which throws an " +
|
||||||
|
"error if the input uses features that are not supported by LaTeX.",
|
||||||
|
cli: "-S, --strict",
|
||||||
|
cliDefault: false,
|
||||||
|
},
|
||||||
|
trust: {
|
||||||
|
type: ["boolean", "function"],
|
||||||
|
description: "Trust the input, enabling all HTML features such as \\url.",
|
||||||
|
cli: "-T, --trust",
|
||||||
|
},
|
||||||
|
maxSize: {
|
||||||
|
type: "number",
|
||||||
|
default: Infinity,
|
||||||
|
description: "If non-zero, all user-specified sizes, e.g. in " +
|
||||||
|
"\\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, " +
|
||||||
|
"elements and spaces can be arbitrarily large",
|
||||||
|
processor: (s) => Math.max(0, s),
|
||||||
|
cli: "-s, --max-size <n>",
|
||||||
|
cliProcessor: parseInt,
|
||||||
|
},
|
||||||
|
maxExpand: {
|
||||||
|
type: "number",
|
||||||
|
default: 1000,
|
||||||
|
description: "Limit the number of macro expansions to the specified " +
|
||||||
|
"number, to prevent e.g. infinite macro loops. If set to Infinity, " +
|
||||||
|
"the macro expander will try to fully expand as in LaTeX.",
|
||||||
|
processor: (n) => Math.max(0, n),
|
||||||
|
cli: "-e, --max-expand <n>",
|
||||||
|
cliProcessor: (n) => (n === "Infinity" ? Infinity : parseInt(n)),
|
||||||
|
},
|
||||||
|
globalGroup: {
|
||||||
|
type: "boolean",
|
||||||
|
cli: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function getDefaultValue(schema): any {
|
||||||
|
if (schema.default) {
|
||||||
|
return schema.default;
|
||||||
|
}
|
||||||
|
const type = schema.type;
|
||||||
|
const defaultType = Array.isArray(type) ? type[0] : type;
|
||||||
|
if (typeof defaultType !== 'string') {
|
||||||
|
return defaultType.enum[0];
|
||||||
|
}
|
||||||
|
switch (defaultType) {
|
||||||
|
case 'boolean':
|
||||||
|
return false;
|
||||||
|
case 'string':
|
||||||
|
return '';
|
||||||
|
case 'number':
|
||||||
|
return 0;
|
||||||
|
case 'object':
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main Settings object
|
* The main Settings object
|
||||||
*
|
*
|
||||||
@@ -98,23 +255,17 @@ export default class Settings {
|
|||||||
constructor(options: SettingsOptions) {
|
constructor(options: SettingsOptions) {
|
||||||
// allow null options
|
// allow null options
|
||||||
options = options || {};
|
options = options || {};
|
||||||
this.displayMode = utils.deflt(options.displayMode, false);
|
for (const prop in SETTINGS_SCHEMA) {
|
||||||
this.output = utils.deflt(options.output, "htmlAndMathml");
|
if (SETTINGS_SCHEMA.hasOwnProperty(prop)) {
|
||||||
this.leqno = utils.deflt(options.leqno, false);
|
// $FlowFixMe
|
||||||
this.fleqn = utils.deflt(options.fleqn, false);
|
const schema = SETTINGS_SCHEMA[prop];
|
||||||
this.throwOnError = utils.deflt(options.throwOnError, true);
|
// TODO: validate options
|
||||||
this.errorColor = utils.deflt(options.errorColor, "#cc0000");
|
// $FlowFixMe
|
||||||
this.macros = options.macros || {};
|
this[prop] = options[prop] !== undefined ? (schema.processor
|
||||||
this.minRuleThickness = Math.max(
|
? schema.processor(options[prop]) : options[prop])
|
||||||
0,
|
: getDefaultValue(schema);
|
||||||
utils.deflt(options.minRuleThickness, 0)
|
}
|
||||||
);
|
}
|
||||||
this.colorIsTextColor = utils.deflt(options.colorIsTextColor, false);
|
|
||||||
this.strict = utils.deflt(options.strict, "warn");
|
|
||||||
this.trust = utils.deflt(options.trust, false);
|
|
||||||
this.maxSize = Math.max(0, utils.deflt(options.maxSize, Infinity));
|
|
||||||
this.maxExpand = Math.max(0, utils.deflt(options.maxExpand, 1000));
|
|
||||||
this.globalGroup = utils.deflt(options.globalGroup, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user