katex 0.12.0 → 0.13.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +112 -0
- package/LICENSE +1 -1
- package/README.md +8 -7
- package/contrib/auto-render/auto-render.js +12 -19
- package/contrib/auto-render/index.html +9 -3
- package/contrib/auto-render/splitAtDelimiters.js +44 -61
- package/contrib/auto-render/test/auto-render-spec.js +88 -52
- package/contrib/copy-tex/README.md +5 -9
- package/contrib/copy-tex/copy-tex.css +0 -3
- package/contrib/mathtex-script-type/README.md +5 -5
- package/contrib/mhchem/README.md +4 -2
- package/contrib/render-a11y-string/render-a11y-string.js +31 -2
- package/contrib/render-a11y-string/test/render-a11y-string-spec.js +23 -0
- package/dist/README.md +8 -7
- package/dist/contrib/auto-render.js +148 -171
- package/dist/contrib/auto-render.min.js +1 -1
- package/dist/contrib/auto-render.mjs +91 -95
- package/dist/contrib/copy-tex.css +3 -3
- package/dist/contrib/copy-tex.js +11 -108
- package/dist/contrib/copy-tex.min.css +1 -1
- package/dist/contrib/copy-tex.min.js +1 -1
- package/dist/contrib/copy-tex.mjs +21 -20
- package/dist/contrib/mathtex-script-type.js +66 -91
- package/dist/contrib/mathtex-script-type.min.js +1 -1
- package/dist/contrib/mathtex-script-type.mjs +3 -3
- package/dist/contrib/mhchem.js +70 -95
- package/dist/contrib/mhchem.min.js +1 -1
- package/dist/contrib/mhchem.mjs +2 -2
- package/dist/contrib/render-a11y-string.js +97 -92
- package/dist/contrib/render-a11y-string.min.js +1 -1
- package/dist/contrib/render-a11y-string.mjs +86 -45
- package/dist/fonts/KaTeX_AMS-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_AMS-Regular.woff +0 -0
- package/dist/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_Fraktur-Bold.woff +0 -0
- package/dist/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Fraktur-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_Main-Bold.woff +0 -0
- package/dist/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
- package/dist/fonts/KaTeX_Main-BoldItalic.woff +0 -0
- package/dist/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-Italic.ttf +0 -0
- package/dist/fonts/KaTeX_Main-Italic.woff +0 -0
- package/dist/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Main-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
- package/dist/fonts/KaTeX_Math-BoldItalic.woff +0 -0
- package/dist/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/dist/fonts/KaTeX_Math-Italic.ttf +0 -0
- package/dist/fonts/KaTeX_Math-Italic.woff +0 -0
- package/dist/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/dist/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_SansSerif-Bold.woff +0 -0
- package/dist/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
- package/dist/fonts/KaTeX_SansSerif-Italic.woff +0 -0
- package/dist/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/dist/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_SansSerif-Regular.woff +0 -0
- package/dist/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Script-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Script-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size1-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size1-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size2-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size2-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size3-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size3-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size4-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size4-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Typewriter-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/dist/katex.css +66 -10
- package/dist/katex.js +2714 -1950
- package/dist/katex.min.css +1 -1
- package/dist/katex.min.js +1 -1
- package/dist/katex.mjs +3162 -2372
- package/katex.js +4 -3
- package/package.json +69 -59
- package/src/Lexer.js +4 -2
- package/src/MacroExpander.js +117 -37
- package/src/Options.js +2 -2
- package/src/ParseError.js +1 -1
- package/src/Parser.js +100 -159
- package/src/Settings.js +2 -2
- package/src/Style.js +4 -4
- package/src/Token.js +1 -1
- package/src/buildCommon.js +12 -5
- package/src/buildHTML.js +11 -0
- package/src/buildMathML.js +6 -0
- package/src/defineEnvironment.js +0 -3
- package/src/defineFunction.js +15 -22
- package/src/delimiter.js +61 -57
- package/src/domTree.js +1 -1
- package/src/environments/array.js +223 -35
- package/src/environments/cd.js +312 -0
- package/src/fontMetrics.js +1 -1
- package/src/fontMetricsData.js +2076 -0
- package/src/fonts/.gitignore +9 -0
- package/src/fonts/Makefile +139 -0
- package/src/fonts/default.cfg +20 -0
- package/src/fonts/generate_fonts.py +61 -0
- package/src/fonts/lib/Extra.otf +0 -0
- package/src/fonts/lib/Space.ttx +234 -0
- package/src/fonts/makeBlacker +49 -0
- package/src/fonts/makeFF +2003 -0
- package/src/fonts/xbbold.mf +182 -0
- package/src/fonts.less +64 -0
- package/src/functions/accent.js +3 -2
- package/src/functions/arrow.js +8 -2
- package/src/functions/color.js +4 -4
- package/src/functions/cr.js +7 -25
- package/src/functions/def.js +50 -24
- package/src/functions/delimsizing.js +8 -0
- package/src/functions/enclose.js +80 -12
- package/src/functions/environment.js +1 -1
- package/src/functions/font.js +3 -4
- package/src/functions/genfrac.js +36 -11
- package/src/functions/hbox.js +39 -0
- package/src/functions/kern.js +1 -0
- package/src/functions/mathchoice.js +1 -0
- package/src/functions/mclass.js +2 -1
- package/src/functions/op.js +3 -7
- package/src/functions/operatorname.js +1 -1
- package/src/functions/raisebox.js +0 -1
- package/src/functions/styling.js +1 -0
- package/src/functions/supsub.js +1 -3
- package/src/functions/symbolsOrd.js +0 -2
- package/src/functions/text.js +2 -3
- package/src/functions/vcenter.js +44 -0
- package/src/functions.js +3 -0
- package/src/katex.less +69 -16
- package/src/macros.js +42 -6
- package/src/mathMLTree.js +16 -1
- package/src/metrics/.gitignore +1 -0
- package/src/metrics/README.md +23 -0
- package/src/metrics/extract_tfms.py +114 -0
- package/src/metrics/extract_ttfs.py +119 -0
- package/src/metrics/format_json.py +28 -0
- package/src/metrics/mapping.pl +1224 -0
- package/src/metrics/parse_tfm.py +211 -0
- package/src/parseNode.js +29 -1
- package/src/parseTree.js +6 -0
- package/src/stretchy.js +12 -5
- package/src/svgGeometry.js +33 -4
- package/src/symbols.js +5 -3
- package/src/types.js +3 -2
- package/src/unicodeScripts.js +5 -0
package/src/katex.less
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/* stylelint-disable font-family-no-missing-generic-family-keyword */
|
|
2
|
-
@import "
|
|
2
|
+
@import "fonts.less";
|
|
3
3
|
|
|
4
4
|
// The mu unit is defined as 1/18 em
|
|
5
|
-
@mu:
|
|
5
|
+
@mu: (1em / 18);
|
|
6
6
|
|
|
7
7
|
// The version is dynamically set from package.json via webpack.common.js
|
|
8
8
|
@version: "";
|
|
@@ -17,20 +17,22 @@
|
|
|
17
17
|
// Prevent a rendering bug that misplaces \vec in Chrome.
|
|
18
18
|
text-rendering: auto;
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
* {
|
|
21
|
+
// Prevent background resetting on elements in Windows's high-contrast
|
|
22
|
+
// mode, while still allowing background/foreground setting on root .katex
|
|
23
|
+
-ms-high-contrast-adjust: none !important;
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
// Insulate fraction bars and rules from CSS that sets border-color.
|
|
26
|
+
border-color: currentColor;
|
|
27
|
+
}
|
|
26
28
|
|
|
27
29
|
.katex-version::after {
|
|
28
30
|
content: @version;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
.katex-mathml {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
/* Accessibility hack to only show to screen readers
|
|
35
|
+
Found at: http://a11yproject.com/posts/how-to-hide-content/ */
|
|
34
36
|
position: absolute;
|
|
35
37
|
clip: rect(1px, 1px, 1px, 1px);
|
|
36
38
|
padding: 0;
|
|
@@ -161,7 +163,7 @@
|
|
|
161
163
|
// This value is also used in fontMetrics.js, if you change it make sure the
|
|
162
164
|
// values match.
|
|
163
165
|
@ptperem: 10;
|
|
164
|
-
@nulldelimiterspace: 1.2em / @ptperem;
|
|
166
|
+
@nulldelimiterspace: (1.2em / @ptperem);
|
|
165
167
|
|
|
166
168
|
@muspace: 0.055556em; // 1mu
|
|
167
169
|
@thinspace: 0.16667em; // 3mu
|
|
@@ -219,17 +221,13 @@
|
|
|
219
221
|
}
|
|
220
222
|
|
|
221
223
|
.vbox {
|
|
222
|
-
display: -ms-inline-flexbox;
|
|
223
224
|
display: inline-flex;
|
|
224
|
-
-ms-flex-direction: column;
|
|
225
225
|
flex-direction: column;
|
|
226
226
|
align-items: baseline;
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
.hbox {
|
|
230
|
-
display: -ms-inline-flexbox;
|
|
231
230
|
display: inline-flex;
|
|
232
|
-
-ms-flex-direction: row;
|
|
233
231
|
flex-direction: row;
|
|
234
232
|
width: 100%;
|
|
235
233
|
}
|
|
@@ -322,8 +320,8 @@
|
|
|
322
320
|
|
|
323
321
|
.sqrt {
|
|
324
322
|
> .root {
|
|
325
|
-
|
|
326
|
-
|
|
323
|
+
/* These values are taken from the definition of `\r@@t`,
|
|
324
|
+
`\mkern 5mu` and `\mkern -10mu`. */
|
|
327
325
|
margin-left: 5*@mu;
|
|
328
326
|
margin-right: -10*@mu;
|
|
329
327
|
}
|
|
@@ -559,6 +557,10 @@
|
|
|
559
557
|
padding: 0 0.5em;
|
|
560
558
|
}
|
|
561
559
|
|
|
560
|
+
.cd-arrow-pad {
|
|
561
|
+
padding: 0 0.55556em 0 0.27778em; // \;{#1}\;\;
|
|
562
|
+
}
|
|
563
|
+
|
|
562
564
|
.x-arrow,
|
|
563
565
|
.mover,
|
|
564
566
|
.munder {
|
|
@@ -588,6 +590,51 @@
|
|
|
588
590
|
border-bottom-style: solid;
|
|
589
591
|
border-bottom-width: 0.08em;
|
|
590
592
|
}
|
|
593
|
+
|
|
594
|
+
.angl {
|
|
595
|
+
// from package actuarialangle, which is always used in a subscript.
|
|
596
|
+
box-sizing: border-content;
|
|
597
|
+
border-top: 0.049em solid; // defaultRuleThickness in scriptstyle
|
|
598
|
+
border-right: 0.049em solid; // ditto
|
|
599
|
+
margin-right: 0.03889em; // 1 mu
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
.anglpad {
|
|
603
|
+
padding: 0 0.03889em 0 0.03889em; // pad 1mu left and right (in scriptstyle)
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
.eqn-num::before {
|
|
607
|
+
counter-increment: katexEqnNo;
|
|
608
|
+
content: "(" counter(katexEqnNo) ")";
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
.mml-eqn-num::before {
|
|
612
|
+
counter-increment: mmlEqnNo;
|
|
613
|
+
content: "(" counter(mmlEqnNo) ")";
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
.mtr-glue {
|
|
617
|
+
width: 50%;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
.cd-vert-arrow {
|
|
621
|
+
display: inline-block;
|
|
622
|
+
position: relative;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
.cd-label-left {
|
|
626
|
+
display: inline-block;
|
|
627
|
+
position: absolute;
|
|
628
|
+
right: calc(50% + 0.3em);
|
|
629
|
+
text-align: left;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
.cd-label-right {
|
|
633
|
+
display: inline-block;
|
|
634
|
+
position: absolute;
|
|
635
|
+
left: calc(50% + 0.3em);
|
|
636
|
+
text-align: right;
|
|
637
|
+
}
|
|
591
638
|
}
|
|
592
639
|
|
|
593
640
|
.katex-display {
|
|
@@ -623,3 +670,9 @@
|
|
|
623
670
|
text-align: left;
|
|
624
671
|
padding-left: 2em;
|
|
625
672
|
}
|
|
673
|
+
|
|
674
|
+
// Automatic equation numbers for some environments.
|
|
675
|
+
// Use parallel counters for HTML and MathML.
|
|
676
|
+
body {
|
|
677
|
+
counter-reset: katexEqnNo mmlEqnNo;
|
|
678
|
+
}
|
package/src/macros.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This can be used to define some commands in terms of others.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import fontMetricsData from "
|
|
7
|
+
import fontMetricsData from "./fontMetricsData";
|
|
8
8
|
import functions from "./functions";
|
|
9
9
|
import symbols from "./symbols";
|
|
10
10
|
import utils from "./utils";
|
|
@@ -71,6 +71,12 @@ export interface MacroContextInterface {
|
|
|
71
71
|
*/
|
|
72
72
|
expandMacroAsText(name: string): string | void;
|
|
73
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Consume an argument from the token stream, and return the resulting array
|
|
76
|
+
* of tokens and start/end token.
|
|
77
|
+
*/
|
|
78
|
+
consumeArg(delims?: ?string[]): MacroArg;
|
|
79
|
+
|
|
74
80
|
/**
|
|
75
81
|
* Consume the specified number of arguments from the token stream,
|
|
76
82
|
* and return the resulting array of arguments.
|
|
@@ -91,10 +97,17 @@ export interface MacroContextInterface {
|
|
|
91
97
|
isExpandable(name: string): boolean;
|
|
92
98
|
}
|
|
93
99
|
|
|
100
|
+
export type MacroArg = {
|
|
101
|
+
tokens: Token[],
|
|
102
|
+
start: Token,
|
|
103
|
+
end: Token
|
|
104
|
+
};
|
|
105
|
+
|
|
94
106
|
/** Macro tokens (in reverse order). */
|
|
95
107
|
export type MacroExpansion = {
|
|
96
108
|
tokens: Token[],
|
|
97
109
|
numArgs: number,
|
|
110
|
+
delimiters?: string[][],
|
|
98
111
|
unexpandable?: boolean, // used in \let
|
|
99
112
|
};
|
|
100
113
|
|
|
@@ -240,7 +253,7 @@ defineMacro("\\char", function(context) {
|
|
|
240
253
|
// \renewcommand{\macro}[args]{definition}
|
|
241
254
|
// TODO: Optional arguments: \newcommand{\macro}[args][default]{definition}
|
|
242
255
|
const newcommand = (context, existsOK: boolean, nonexistsOK: boolean) => {
|
|
243
|
-
let arg = context.
|
|
256
|
+
let arg = context.consumeArg().tokens;
|
|
244
257
|
if (arg.length !== 1) {
|
|
245
258
|
throw new ParseError(
|
|
246
259
|
"\\newcommand's first argument must be a macro name");
|
|
@@ -258,7 +271,7 @@ const newcommand = (context, existsOK: boolean, nonexistsOK: boolean) => {
|
|
|
258
271
|
}
|
|
259
272
|
|
|
260
273
|
let numArgs = 0;
|
|
261
|
-
arg = context.
|
|
274
|
+
arg = context.consumeArg().tokens;
|
|
262
275
|
if (arg.length === 1 && arg[0].text === "[") {
|
|
263
276
|
let argText = '';
|
|
264
277
|
let token = context.expandNextToken();
|
|
@@ -271,7 +284,7 @@ const newcommand = (context, existsOK: boolean, nonexistsOK: boolean) => {
|
|
|
271
284
|
throw new ParseError(`Invalid number of arguments: ${argText}`);
|
|
272
285
|
}
|
|
273
286
|
numArgs = parseInt(argText);
|
|
274
|
-
arg = context.
|
|
287
|
+
arg = context.consumeArg().tokens;
|
|
275
288
|
}
|
|
276
289
|
|
|
277
290
|
// Final arg is the expansion of the macro
|
|
@@ -314,10 +327,12 @@ defineMacro("\\bgroup", "{");
|
|
|
314
327
|
defineMacro("\\egroup", "}");
|
|
315
328
|
|
|
316
329
|
// Symbols from latex.ltx:
|
|
330
|
+
// \def~{\nobreakspace{}}
|
|
317
331
|
// \def\lq{`}
|
|
318
332
|
// \def\rq{'}
|
|
319
333
|
// \def \aa {\r a}
|
|
320
334
|
// \def \AA {\r A}
|
|
335
|
+
defineMacro("~", "\\nobreakspace");
|
|
321
336
|
defineMacro("\\lq", "`");
|
|
322
337
|
defineMacro("\\rq", "'");
|
|
323
338
|
defineMacro("\\aa", "\\r a");
|
|
@@ -361,6 +376,12 @@ defineMacro("\\llap", "\\mathllap{\\textrm{#1}}");
|
|
|
361
376
|
defineMacro("\\rlap", "\\mathrlap{\\textrm{#1}}");
|
|
362
377
|
defineMacro("\\clap", "\\mathclap{\\textrm{#1}}");
|
|
363
378
|
|
|
379
|
+
// \mathstrut from the TeXbook, p 360
|
|
380
|
+
defineMacro("\\mathstrut", "\\vphantom{(}");
|
|
381
|
+
|
|
382
|
+
// \underbar from TeXbook p 353
|
|
383
|
+
defineMacro("\\underbar", "\\underline{\\text{#1}}");
|
|
384
|
+
|
|
364
385
|
// \not is defined by base/fontmath.ltx via
|
|
365
386
|
// \DeclareMathSymbol{\not}{\mathrel}{symbols}{"36}
|
|
366
387
|
// It's thus treated like a \mathrel, but defined by a symbol that has zero
|
|
@@ -693,8 +714,10 @@ defineMacro("\\pmb", "\\html@mathml{" +
|
|
|
693
714
|
//////////////////////////////////////////////////////////////////////
|
|
694
715
|
// LaTeX source2e
|
|
695
716
|
|
|
696
|
-
//
|
|
697
|
-
|
|
717
|
+
// \expandafter\let\expandafter\@normalcr
|
|
718
|
+
// \csname\expandafter\@gobble\string\\ \endcsname
|
|
719
|
+
// \DeclareRobustCommand\newline{\@normalcr\relax}
|
|
720
|
+
defineMacro("\\newline", "\\\\\\relax");
|
|
698
721
|
|
|
699
722
|
// \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@}
|
|
700
723
|
// TODO: Doesn't normally work in math mode because \@ fails. KaTeX doesn't
|
|
@@ -839,6 +862,15 @@ defineMacro("\\notni", "\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220C}}");
|
|
|
839
862
|
defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}");
|
|
840
863
|
defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}");
|
|
841
864
|
|
|
865
|
+
//////////////////////////////////////////////////////////////////////
|
|
866
|
+
// From amsopn.sty
|
|
867
|
+
defineMacro("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}");
|
|
868
|
+
defineMacro("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}");
|
|
869
|
+
defineMacro("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{lim}}");
|
|
870
|
+
defineMacro("\\varliminf", "\\DOTSB\\operatorname*{\\underline{lim}}");
|
|
871
|
+
defineMacro("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{lim}}");
|
|
872
|
+
defineMacro("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{lim}}");
|
|
873
|
+
|
|
842
874
|
//////////////////////////////////////////////////////////////////////
|
|
843
875
|
// MathML alternates for KaTeX glyphs in the Unicode private area
|
|
844
876
|
defineMacro("\\gvertneqq", "\\html@mathml{\\@gvertneqq}{\u2269}");
|
|
@@ -987,6 +1019,10 @@ defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}");
|
|
|
987
1019
|
defineMacro("\\Bra", "\\left\\langle#1\\right|");
|
|
988
1020
|
defineMacro("\\Ket", "\\left|#1\\right\\rangle");
|
|
989
1021
|
|
|
1022
|
+
//////////////////////////////////////////////////////////////////////
|
|
1023
|
+
// actuarialangle.dtx
|
|
1024
|
+
defineMacro("\\angln", "{\\angl n}");
|
|
1025
|
+
|
|
990
1026
|
// Custom Khan Academy colors, should be moved to an optional package
|
|
991
1027
|
defineMacro("\\blue", "\\textcolor{##6495ed}{#1}");
|
|
992
1028
|
defineMacro("\\orange", "\\textcolor{##ffa500}{#1}");
|
package/src/mathMLTree.js
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
import utils from "./utils";
|
|
13
13
|
import {DocumentFragment} from "./tree";
|
|
14
|
+
import {createClass} from "./domTree";
|
|
14
15
|
|
|
15
16
|
import type {VirtualNode} from "./tree";
|
|
16
17
|
|
|
@@ -47,11 +48,17 @@ export class MathNode implements MathDomNode {
|
|
|
47
48
|
type: MathNodeType;
|
|
48
49
|
attributes: {[string]: string};
|
|
49
50
|
children: $ReadOnlyArray<MathDomNode>;
|
|
51
|
+
classes: string[];
|
|
50
52
|
|
|
51
|
-
constructor(
|
|
53
|
+
constructor(
|
|
54
|
+
type: MathNodeType,
|
|
55
|
+
children?: $ReadOnlyArray<MathDomNode>,
|
|
56
|
+
classes?: string[]
|
|
57
|
+
) {
|
|
52
58
|
this.type = type;
|
|
53
59
|
this.attributes = {};
|
|
54
60
|
this.children = children || [];
|
|
61
|
+
this.classes = classes || [];
|
|
55
62
|
}
|
|
56
63
|
|
|
57
64
|
/**
|
|
@@ -82,6 +89,10 @@ export class MathNode implements MathDomNode {
|
|
|
82
89
|
}
|
|
83
90
|
}
|
|
84
91
|
|
|
92
|
+
if (this.classes.length > 0) {
|
|
93
|
+
node.className = createClass(this.classes);
|
|
94
|
+
}
|
|
95
|
+
|
|
85
96
|
for (let i = 0; i < this.children.length; i++) {
|
|
86
97
|
node.appendChild(this.children[i].toNode());
|
|
87
98
|
}
|
|
@@ -104,6 +115,10 @@ export class MathNode implements MathDomNode {
|
|
|
104
115
|
}
|
|
105
116
|
}
|
|
106
117
|
|
|
118
|
+
if (this.classes.length > 0) {
|
|
119
|
+
markup += ` class ="${utils.escape(createClass(this.classes))}"`;
|
|
120
|
+
}
|
|
121
|
+
|
|
107
122
|
markup += ">";
|
|
108
123
|
|
|
109
124
|
for (let i = 0; i < this.children.length; i++) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*.pyc
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
### How to generate new metrics
|
|
2
|
+
-------------------------------
|
|
3
|
+
|
|
4
|
+
There are several requirements for generating the metrics used by KaTeX.
|
|
5
|
+
|
|
6
|
+
- You need to have an installation of TeX which supports kpathsea. You can check
|
|
7
|
+
this by running `tex --version`, and seeing if it has a line that looks like
|
|
8
|
+
> kpathsea version 6.2.0
|
|
9
|
+
|
|
10
|
+
- You need the Perl module `JSON`. You can install this either from CPAN
|
|
11
|
+
(e.g. using the `cpan` command line tool: `cpan install JSON`)
|
|
12
|
+
or with your package manager.
|
|
13
|
+
|
|
14
|
+
- You need the Python module `fonttools`. You can install this either from PyPI
|
|
15
|
+
(using `easy_install` or `pip`: `pip install fonttools`)
|
|
16
|
+
or with your package manager.
|
|
17
|
+
|
|
18
|
+
Once you have these things, run the following command from the root directory:
|
|
19
|
+
|
|
20
|
+
sh ./docker/fonts/buildMetrics.sh
|
|
21
|
+
|
|
22
|
+
which should generate new metrics and place them into `fontMetricsData.json`.
|
|
23
|
+
You're done!
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
import collections
|
|
4
|
+
import json
|
|
5
|
+
import parse_tfm
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def find_font_path(font_name):
|
|
11
|
+
try:
|
|
12
|
+
font_path = subprocess.check_output(['kpsewhich', font_name])
|
|
13
|
+
except OSError:
|
|
14
|
+
raise RuntimeError("Couldn't find kpsewhich program, make sure you" +
|
|
15
|
+
" have TeX installed")
|
|
16
|
+
except subprocess.CalledProcessError:
|
|
17
|
+
raise RuntimeError("Couldn't find font metrics: '%s'" % font_name)
|
|
18
|
+
return font_path.strip()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def main():
|
|
22
|
+
mapping = json.load(sys.stdin)
|
|
23
|
+
|
|
24
|
+
fonts = [
|
|
25
|
+
'cmbsy10.tfm',
|
|
26
|
+
'cmbx10.tfm',
|
|
27
|
+
'cmbxti10.tfm',
|
|
28
|
+
'cmex10.tfm',
|
|
29
|
+
'cmmi10.tfm',
|
|
30
|
+
'cmmib10.tfm',
|
|
31
|
+
'cmr10.tfm',
|
|
32
|
+
'cmsy10.tfm',
|
|
33
|
+
'cmti10.tfm',
|
|
34
|
+
'msam10.tfm',
|
|
35
|
+
'msbm10.tfm',
|
|
36
|
+
'eufm10.tfm',
|
|
37
|
+
'cmtt10.tfm',
|
|
38
|
+
'rsfs10.tfm',
|
|
39
|
+
'cmss10.tfm',
|
|
40
|
+
'cmssbx10.tfm',
|
|
41
|
+
'cmssi10.tfm',
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
# Extracted by running `\font\a=<font>` and then `\showthe\skewchar\a` in
|
|
45
|
+
# TeX, where `<font>` is the name of the font listed here. The skewchar
|
|
46
|
+
# will be printed out in the output. If it outputs `-1`, that means there
|
|
47
|
+
# is no skewchar, so we use `None` here.
|
|
48
|
+
font_skewchar = {
|
|
49
|
+
'cmbsy10': None,
|
|
50
|
+
'cmbx10': None,
|
|
51
|
+
'cmbxti10': None,
|
|
52
|
+
'cmex10': None,
|
|
53
|
+
'cmmi10': 127,
|
|
54
|
+
'cmmib10': None,
|
|
55
|
+
'cmr10': None,
|
|
56
|
+
'cmsy10': 48,
|
|
57
|
+
'cmti10': None,
|
|
58
|
+
'msam10': None,
|
|
59
|
+
'msbm10': None,
|
|
60
|
+
'eufm10': None,
|
|
61
|
+
'cmtt10': None,
|
|
62
|
+
'rsfs10': None,
|
|
63
|
+
'cmss10': None,
|
|
64
|
+
'cmssbx10': None,
|
|
65
|
+
'cmssi10': None,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
font_name_to_tfm = {}
|
|
69
|
+
|
|
70
|
+
for font_name in fonts:
|
|
71
|
+
font_basename = font_name.split('.')[0]
|
|
72
|
+
font_path = find_font_path(font_name)
|
|
73
|
+
font_name_to_tfm[font_basename] = parse_tfm.read_tfm_file(font_path)
|
|
74
|
+
|
|
75
|
+
families = collections.defaultdict(dict)
|
|
76
|
+
|
|
77
|
+
for family, chars in mapping.iteritems():
|
|
78
|
+
for char, char_data in chars.iteritems():
|
|
79
|
+
char_num = int(char)
|
|
80
|
+
|
|
81
|
+
font = char_data['font']
|
|
82
|
+
tex_char_num = int(char_data['char'])
|
|
83
|
+
yshift = float(char_data['yshift'])
|
|
84
|
+
|
|
85
|
+
if family == "Script-Regular":
|
|
86
|
+
tfm_char = font_name_to_tfm[font].get_char_metrics(tex_char_num,
|
|
87
|
+
fix_rsfs=True)
|
|
88
|
+
else:
|
|
89
|
+
tfm_char = font_name_to_tfm[font].get_char_metrics(tex_char_num)
|
|
90
|
+
|
|
91
|
+
height = round(tfm_char.height + yshift / 1000.0, 5)
|
|
92
|
+
depth = round(tfm_char.depth - yshift / 1000.0, 5)
|
|
93
|
+
italic = round(tfm_char.italic_correction, 5)
|
|
94
|
+
width = round(tfm_char.width, 5)
|
|
95
|
+
|
|
96
|
+
skewkern = 0.0
|
|
97
|
+
if (font_skewchar[font] and
|
|
98
|
+
font_skewchar[font] in tfm_char.kern_table):
|
|
99
|
+
skewkern = round(
|
|
100
|
+
tfm_char.kern_table[font_skewchar[font]], 5)
|
|
101
|
+
|
|
102
|
+
families[family][char_num] = {
|
|
103
|
+
'height': height,
|
|
104
|
+
'depth': depth,
|
|
105
|
+
'italic': italic,
|
|
106
|
+
'skew': skewkern,
|
|
107
|
+
'width': width
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
sys.stdout.write(
|
|
111
|
+
json.dumps(families, separators=(',', ':'), sort_keys=True))
|
|
112
|
+
|
|
113
|
+
if __name__ == '__main__':
|
|
114
|
+
main()
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
from fontTools.ttLib import TTFont
|
|
4
|
+
import sys
|
|
5
|
+
import json
|
|
6
|
+
|
|
7
|
+
# map of characters to extract
|
|
8
|
+
metrics_to_extract = {
|
|
9
|
+
# Font name
|
|
10
|
+
"AMS-Regular": {
|
|
11
|
+
u"\u21e2": None, # \dashrightarrow
|
|
12
|
+
u"\u21e0": None, # \dashleftarrow
|
|
13
|
+
},
|
|
14
|
+
"Main-Regular": {
|
|
15
|
+
# Skew and italic metrics can't be easily parsed from the TTF. Instead,
|
|
16
|
+
# we map each character to a "base character", which is a character
|
|
17
|
+
# from the same font with correct italic and skew metrics. A character
|
|
18
|
+
# maps to None if it doesn't have a base.
|
|
19
|
+
|
|
20
|
+
#u"\u2209": None, # \notin
|
|
21
|
+
#u"\u2260": None, # \neq
|
|
22
|
+
u"\u2245": None, # \cong
|
|
23
|
+
u"\u2026": None, # \ldots
|
|
24
|
+
u"\u22ef": None, # \cdots
|
|
25
|
+
u"\u22f1": None, # \ddots
|
|
26
|
+
u"\u22ee": None, # \vdots
|
|
27
|
+
u"\u22ee": None, # \vdots
|
|
28
|
+
u"\u22a8": None, # \models
|
|
29
|
+
u"\u22c8": None, # \bowtie
|
|
30
|
+
u"\u2250": None, # \doteq
|
|
31
|
+
u"\u23b0": None, # \lmoustache
|
|
32
|
+
u"\u23b1": None, # \rmoustache
|
|
33
|
+
u"\u27ee": None, # \lgroup
|
|
34
|
+
u"\u27ef": None, # \rgroup
|
|
35
|
+
u"\u27f5": None, # \longleftarrow
|
|
36
|
+
u"\u27f8": None, # \Longleftarrow
|
|
37
|
+
u"\u27f6": None, # \longrightarrow
|
|
38
|
+
u"\u27f9": None, # \Longrightarrow
|
|
39
|
+
u"\u27f7": None, # \longleftrightarrow
|
|
40
|
+
u"\u27fa": None, # \Longleftrightarrow
|
|
41
|
+
u"\u21a6": None, # \mapsto
|
|
42
|
+
u"\u27fc": None, # \longmapsto
|
|
43
|
+
u"\u21a9": None, # \hookleftarrow
|
|
44
|
+
u"\u21aa": None, # \hookrightarrow
|
|
45
|
+
u"\u21cc": None, # \rightleftharpoons
|
|
46
|
+
},
|
|
47
|
+
"Size1-Regular": {
|
|
48
|
+
u"\u222c": u"\u222b", # \iint, based on \int
|
|
49
|
+
u"\u222d": u"\u222b", # \iiint, based on \int
|
|
50
|
+
},
|
|
51
|
+
"Size2-Regular": {
|
|
52
|
+
u"\u222c": u"\u222b", # \iint, based on \int
|
|
53
|
+
u"\u222d": u"\u222b", # \iiint, based on \int
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def main():
|
|
59
|
+
start_json = json.load(sys.stdin)
|
|
60
|
+
|
|
61
|
+
for font in start_json:
|
|
62
|
+
fontInfo = TTFont("../../fonts/KaTeX_" + font + ".ttf")
|
|
63
|
+
glyf = fontInfo["glyf"]
|
|
64
|
+
widths = fontInfo.getGlyphSet()
|
|
65
|
+
unitsPerEm = float(fontInfo["head"].unitsPerEm)
|
|
66
|
+
|
|
67
|
+
# We keep ALL Unicode cmaps, not just fontInfo["cmap"].getcmap(3, 1).
|
|
68
|
+
# This is playing it extra safe, since it reports inconsistencies.
|
|
69
|
+
# Platform 0 is Unicode, platform 3 is Windows. For platform 3,
|
|
70
|
+
# encoding 1 is UCS-2 and encoding 10 is UCS-4.
|
|
71
|
+
cmap = [t.cmap for t in fontInfo["cmap"].tables
|
|
72
|
+
if (t.platformID == 0)
|
|
73
|
+
or (t.platformID == 3 and t.platEncID in (1, 10))]
|
|
74
|
+
|
|
75
|
+
chars = metrics_to_extract.get(font, {})
|
|
76
|
+
chars[u"\u0020"] = None # space
|
|
77
|
+
chars[u"\u00a0"] = None # nbsp
|
|
78
|
+
|
|
79
|
+
for char, base_char in chars.iteritems():
|
|
80
|
+
code = ord(char)
|
|
81
|
+
names = set(t.get(code) for t in cmap)
|
|
82
|
+
if not names:
|
|
83
|
+
sys.stderr.write(
|
|
84
|
+
"Codepoint {} of font {} maps to no name\n"
|
|
85
|
+
.format(code, font))
|
|
86
|
+
continue
|
|
87
|
+
if len(names) != 1:
|
|
88
|
+
sys.stderr.write(
|
|
89
|
+
"Codepoint {} of font {} maps to multiple names: {}\n"
|
|
90
|
+
.format(code, font, ", ".join(sorted(names))))
|
|
91
|
+
continue
|
|
92
|
+
name = names.pop()
|
|
93
|
+
|
|
94
|
+
height = depth = italic = skew = width = 0
|
|
95
|
+
glyph = glyf[name]
|
|
96
|
+
if glyph.numberOfContours:
|
|
97
|
+
height = glyph.yMax / unitsPerEm
|
|
98
|
+
depth = -glyph.yMin / unitsPerEm
|
|
99
|
+
width = widths[name].width / unitsPerEm
|
|
100
|
+
if base_char:
|
|
101
|
+
base_char_str = str(ord(base_char))
|
|
102
|
+
base_metrics = start_json[font][base_char_str]
|
|
103
|
+
italic = base_metrics["italic"]
|
|
104
|
+
skew = base_metrics["skew"]
|
|
105
|
+
width = base_metrics["width"]
|
|
106
|
+
|
|
107
|
+
start_json[font][str(code)] = {
|
|
108
|
+
"height": height,
|
|
109
|
+
"depth": depth,
|
|
110
|
+
"italic": italic,
|
|
111
|
+
"skew": skew,
|
|
112
|
+
"width": width
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
sys.stdout.write(
|
|
116
|
+
json.dumps(start_json, separators=(',', ':'), sort_keys=True))
|
|
117
|
+
|
|
118
|
+
if __name__ == "__main__":
|
|
119
|
+
main()
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
import json
|
|
5
|
+
|
|
6
|
+
props = ['depth', 'height', 'italic', 'skew']
|
|
7
|
+
|
|
8
|
+
if len(sys.argv) > 1:
|
|
9
|
+
if sys.argv[1] == '--width':
|
|
10
|
+
props.append('width')
|
|
11
|
+
|
|
12
|
+
data = json.load(sys.stdin)
|
|
13
|
+
sys.stdout.write(
|
|
14
|
+
"// This file is GENERATED by buildMetrics.sh. DO NOT MODIFY.\n")
|
|
15
|
+
sep = "export default {\n "
|
|
16
|
+
for font in sorted(data):
|
|
17
|
+
sys.stdout.write(sep + json.dumps(font))
|
|
18
|
+
sep = ": {\n "
|
|
19
|
+
for glyph in sorted(data[font], key=int):
|
|
20
|
+
sys.stdout.write(sep + json.dumps(glyph) + ": ")
|
|
21
|
+
|
|
22
|
+
values = [value if value != 0.0 else 0 for value in
|
|
23
|
+
[data[font][glyph][key] for key in props]]
|
|
24
|
+
|
|
25
|
+
sys.stdout.write(json.dumps(values))
|
|
26
|
+
sep = ",\n "
|
|
27
|
+
sep = ",\n },\n "
|
|
28
|
+
sys.stdout.write(",\n },\n};\n")
|