mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-06 11:48:41 +00:00
\kern fixes, \hskip support, \TeX, \LaTeX, \KaTeX (#974)
* Refactor \kern, proper \mkern support, add \hskip * Move \kern, \mkern into functions directory * Add \hskip, \mskip support (but without supporting plus/minus) * Properly separate \kern, \hskip from \mkern, \mskip. (The former work in both modes, and don't support mu units. The latter work only in math mode and only support mu units.) * Render \kern etc. using MathML <mspace> * Implement \TeX macro * Implement \LaTeX * New KaTeX logo \katex * Rename hskip.js -> kern.js * Tweak katex \kern to 0.16em * \katex kern -.17em * Compute A raise height in \LaTeX and \katex * Switch mu unit errors to warnings * LaTeX screenshot test * Replace \KaTeX with macro definition * Update screenshots with \KaTeX in them * Fix font selection for \*TeX macros
This commit is contained in:
committed by
Kevin Barabash
parent
f6a377b91c
commit
7036eb85cd
@@ -735,18 +735,6 @@ groupTypes.rule = function(group, options) {
|
||||
return rule;
|
||||
};
|
||||
|
||||
groupTypes.kern = function(group, options) {
|
||||
// Make an empty span for the rule
|
||||
const rule = makeSpan(["mord", "rule"], [], options);
|
||||
|
||||
if (group.value.dimension) {
|
||||
const dimension = calculateSize(group.value.dimension, options);
|
||||
rule.style.marginLeft = dimension + "em";
|
||||
}
|
||||
|
||||
return rule;
|
||||
};
|
||||
|
||||
groupTypes.accent = function(group, options) {
|
||||
// Accents are handled in the TeXbook pg. 443, rule 12.
|
||||
let base = group.value.base;
|
||||
|
@@ -468,13 +468,6 @@ groupTypes.rule = function(group) {
|
||||
return node;
|
||||
};
|
||||
|
||||
groupTypes.kern = function(group) {
|
||||
// TODO(kevin): Figure out if there's a way to add space in MathML
|
||||
const node = new mathMLTree.MathNode("mrow");
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
groupTypes.mclass = function(group, options) {
|
||||
const inner = buildExpression(group.value.value, options);
|
||||
return new mathMLTree.MathNode("mstyle", inner);
|
||||
|
@@ -163,19 +163,7 @@ defineFunction(["\\rule"], {
|
||||
};
|
||||
});
|
||||
|
||||
// TODO: In TeX, \mkern only accepts mu-units, and \kern does not accept
|
||||
// mu-units. In current KaTeX we relax this; both commands accept any unit.
|
||||
defineFunction(["\\kern", "\\mkern"], {
|
||||
numArgs: 1,
|
||||
argTypes: ["size"],
|
||||
}, function(context, args) {
|
||||
return {
|
||||
type: "kern",
|
||||
dimension: args[0].value,
|
||||
};
|
||||
});
|
||||
|
||||
import "./functions/katex";
|
||||
import "./functions/kern";
|
||||
|
||||
import "./functions/phantom";
|
||||
|
||||
|
@@ -1,51 +0,0 @@
|
||||
// @flow
|
||||
// A KaTeX logo
|
||||
import defineFunction from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
|
||||
defineFunction({
|
||||
type: "katex",
|
||||
names: ["\\KaTeX"],
|
||||
props: {
|
||||
numArgs: 0,
|
||||
allowedInText: true,
|
||||
},
|
||||
handler: (context, args) => {
|
||||
return {
|
||||
type: "katex",
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
// The KaTeX logo. The offsets for the K and a were chosen to look
|
||||
// good, but the offsets for the T, E, and X were taken from the
|
||||
// definition of \TeX in TeX (see TeXbook pg. 356)
|
||||
const k = buildCommon.makeSpan(
|
||||
["k"], [buildCommon.mathsym("K", group.mode)], options);
|
||||
const a = buildCommon.makeSpan(
|
||||
["a"], [buildCommon.mathsym("A", group.mode)], options);
|
||||
|
||||
a.height = (a.height + 0.2) * 0.75;
|
||||
a.depth = (a.height - 0.2) * 0.75;
|
||||
|
||||
const t = buildCommon.makeSpan(
|
||||
["t"], [buildCommon.mathsym("T", group.mode)], options);
|
||||
const e = buildCommon.makeSpan(
|
||||
["e"], [buildCommon.mathsym("E", group.mode)], options);
|
||||
|
||||
e.height = (e.height - 0.2155);
|
||||
e.depth = (e.depth + 0.2155);
|
||||
|
||||
const x = buildCommon.makeSpan(
|
||||
["x"], [buildCommon.mathsym("X", group.mode)], options);
|
||||
|
||||
return buildCommon.makeSpan(
|
||||
["mord", "katex-logo"], [k, a, t, e, x], options);
|
||||
},
|
||||
mathmlBuilder: (group, options) => {
|
||||
const node = new mathMLTree.MathNode(
|
||||
"mtext", [new mathMLTree.TextNode("KaTeX")]);
|
||||
|
||||
return node;
|
||||
},
|
||||
});
|
66
src/functions/kern.js
Normal file
66
src/functions/kern.js
Normal file
@@ -0,0 +1,66 @@
|
||||
//@flow
|
||||
/* eslint no-console:0 */
|
||||
// Horizontal spacing commands
|
||||
|
||||
import defineFunction from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import { calculateSize } from "../units";
|
||||
import ParseError from "../ParseError";
|
||||
|
||||
// TODO: \hskip and \mskip should support plus and minus in lengths
|
||||
|
||||
defineFunction({
|
||||
type: "kern",
|
||||
names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"],
|
||||
props: {
|
||||
numArgs: 1,
|
||||
argTypes: ["size"],
|
||||
allowedInText: true,
|
||||
},
|
||||
handler: (context, args) => {
|
||||
const mathFunction = (context.funcName[1] === 'm'); // \mkern, \mskip
|
||||
const muUnit = (args[0].value.unit === 'mu');
|
||||
if (mathFunction) {
|
||||
if (!muUnit) {
|
||||
typeof console !== "undefined" && console.warn(
|
||||
`In LaTeX, ${context.funcName} supports only mu units, ` +
|
||||
`not ${args[0].value.unit} units`);
|
||||
}
|
||||
if (context.parser.mode !== "math") {
|
||||
throw new ParseError(
|
||||
`Can't use function '${context.funcName}' in text mode`);
|
||||
}
|
||||
} else { // !mathFunction
|
||||
if (muUnit) {
|
||||
typeof console !== "undefined" && console.warn(
|
||||
`In LaTeX, ${context.funcName} does not support mu units`);
|
||||
}
|
||||
}
|
||||
return {
|
||||
type: "kern",
|
||||
dimension: args[0].value,
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
// Make an empty span for the rule
|
||||
const rule = buildCommon.makeSpan(["mord", "rule"], [], options);
|
||||
|
||||
if (group.value.dimension) {
|
||||
const dimension = calculateSize(group.value.dimension, options);
|
||||
rule.style.marginLeft = dimension + "em";
|
||||
}
|
||||
|
||||
return rule;
|
||||
},
|
||||
mathmlBuilder: (group, options) => {
|
||||
const node = new mathMLTree.MathNode("mspace");
|
||||
|
||||
if (group.value.dimension) {
|
||||
const dimension = calculateSize(group.value.dimension, options);
|
||||
node.setAttribute("width", dimension + "em");
|
||||
}
|
||||
|
||||
return node;
|
||||
},
|
||||
});
|
@@ -4,6 +4,7 @@
|
||||
* This can be used to define some commands in terms of others.
|
||||
*/
|
||||
|
||||
import fontMetricsData from "./fontMetricsData";
|
||||
import symbols from "./symbols";
|
||||
import utils from "./utils";
|
||||
import {Token} from "./Token";
|
||||
@@ -85,10 +86,6 @@ defineMacro("\u211A", "\\mathbb{Q}");
|
||||
defineMacro("\u211D", "\\mathbb{R}");
|
||||
defineMacro("\u2124", "\\mathbb{Z}");
|
||||
|
||||
// We don't distinguish between math and nonmath kerns.
|
||||
// (In TeX, the mu unit works only with \mkern.)
|
||||
defineMacro("\\mkern", "\\kern");
|
||||
|
||||
// \llap and \rlap render their contents in text mode
|
||||
defineMacro("\\llap", "\\mathllap{\\textrm{#1}}");
|
||||
defineMacro("\\rlap", "\\mathrlap{\\textrm{#1}}");
|
||||
@@ -270,6 +267,37 @@ defineMacro("\\thickspace", "\\;"); // \let\thickspace\;
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// LaTeX source2e
|
||||
|
||||
// \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@}
|
||||
// TODO: Doesn't normally work in math mode because \@ fails. KaTeX doesn't
|
||||
// support \@ yet, so that's omitted, and we add \text so that the result
|
||||
// doesn't look funny in math mode.
|
||||
defineMacro("\\TeX", "\\textrm{T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX}");
|
||||
|
||||
// \DeclareRobustCommand{\LaTeX}{L\kern-.36em%
|
||||
// {\sbox\z@ T%
|
||||
// \vbox to\ht\z@{\hbox{\check@mathfonts
|
||||
// \fontsize\sf@size\z@
|
||||
// \math@fontsfalse\selectfont
|
||||
// A}%
|
||||
// \vss}%
|
||||
// }%
|
||||
// \kern-.15em%
|
||||
// \TeX}
|
||||
// This code aligns the top of the A with the T (from the perspective of TeX's
|
||||
// boxes, though visually the A appears to extend above slightly).
|
||||
// We compute the corresponding \raisebox when A is rendered at \scriptsize,
|
||||
// which is size3, which has a scale factor of 0.7 (see Options.js).
|
||||
const latexRaiseA = fontMetricsData['Main-Regular']["T".charCodeAt(0)][1] -
|
||||
0.7 * fontMetricsData['Main-Regular']["A".charCodeAt(0)][1] + "em";
|
||||
defineMacro("\\LaTeX",
|
||||
`\\textrm{L\\kern-.36em\\raisebox{${latexRaiseA}}{\\scriptsize A}` +
|
||||
"\\kern-.15em\\TeX}");
|
||||
|
||||
// New KaTeX logo based on tweaking LaTeX logo
|
||||
defineMacro("\\KaTeX",
|
||||
`\\textrm{K\\kern-.17em\\raisebox{${latexRaiseA}}{\\scriptsize A}` +
|
||||
"\\kern-.15em\\TeX}");
|
||||
|
||||
// \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace}
|
||||
// \def\@hspace#1{\hskip #1\relax}
|
||||
// KaTeX doesn't do line breaks, so \hspace and \hspace* are the same as \kern
|
||||
|
Reference in New Issue
Block a user