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.
Files changed (167) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/LICENSE +1 -1
  3. package/README.md +8 -7
  4. package/contrib/auto-render/auto-render.js +12 -19
  5. package/contrib/auto-render/index.html +9 -3
  6. package/contrib/auto-render/splitAtDelimiters.js +44 -61
  7. package/contrib/auto-render/test/auto-render-spec.js +88 -52
  8. package/contrib/copy-tex/README.md +5 -9
  9. package/contrib/copy-tex/copy-tex.css +0 -3
  10. package/contrib/mathtex-script-type/README.md +5 -5
  11. package/contrib/mhchem/README.md +4 -2
  12. package/contrib/render-a11y-string/render-a11y-string.js +31 -2
  13. package/contrib/render-a11y-string/test/render-a11y-string-spec.js +23 -0
  14. package/dist/README.md +8 -7
  15. package/dist/contrib/auto-render.js +148 -171
  16. package/dist/contrib/auto-render.min.js +1 -1
  17. package/dist/contrib/auto-render.mjs +91 -95
  18. package/dist/contrib/copy-tex.css +3 -3
  19. package/dist/contrib/copy-tex.js +11 -108
  20. package/dist/contrib/copy-tex.min.css +1 -1
  21. package/dist/contrib/copy-tex.min.js +1 -1
  22. package/dist/contrib/copy-tex.mjs +21 -20
  23. package/dist/contrib/mathtex-script-type.js +66 -91
  24. package/dist/contrib/mathtex-script-type.min.js +1 -1
  25. package/dist/contrib/mathtex-script-type.mjs +3 -3
  26. package/dist/contrib/mhchem.js +70 -95
  27. package/dist/contrib/mhchem.min.js +1 -1
  28. package/dist/contrib/mhchem.mjs +2 -2
  29. package/dist/contrib/render-a11y-string.js +97 -92
  30. package/dist/contrib/render-a11y-string.min.js +1 -1
  31. package/dist/contrib/render-a11y-string.mjs +86 -45
  32. package/dist/fonts/KaTeX_AMS-Regular.ttf +0 -0
  33. package/dist/fonts/KaTeX_AMS-Regular.woff +0 -0
  34. package/dist/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  35. package/dist/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  36. package/dist/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  37. package/dist/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  38. package/dist/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  39. package/dist/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  40. package/dist/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  41. package/dist/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  42. package/dist/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  43. package/dist/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  44. package/dist/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  45. package/dist/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  46. package/dist/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  47. package/dist/fonts/KaTeX_Main-Bold.ttf +0 -0
  48. package/dist/fonts/KaTeX_Main-Bold.woff +0 -0
  49. package/dist/fonts/KaTeX_Main-Bold.woff2 +0 -0
  50. package/dist/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  51. package/dist/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  52. package/dist/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  53. package/dist/fonts/KaTeX_Main-Italic.ttf +0 -0
  54. package/dist/fonts/KaTeX_Main-Italic.woff +0 -0
  55. package/dist/fonts/KaTeX_Main-Italic.woff2 +0 -0
  56. package/dist/fonts/KaTeX_Main-Regular.ttf +0 -0
  57. package/dist/fonts/KaTeX_Main-Regular.woff +0 -0
  58. package/dist/fonts/KaTeX_Main-Regular.woff2 +0 -0
  59. package/dist/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  60. package/dist/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  61. package/dist/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  62. package/dist/fonts/KaTeX_Math-Italic.ttf +0 -0
  63. package/dist/fonts/KaTeX_Math-Italic.woff +0 -0
  64. package/dist/fonts/KaTeX_Math-Italic.woff2 +0 -0
  65. package/dist/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  66. package/dist/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  67. package/dist/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  68. package/dist/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  69. package/dist/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  70. package/dist/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  71. package/dist/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  72. package/dist/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  73. package/dist/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  74. package/dist/fonts/KaTeX_Script-Regular.ttf +0 -0
  75. package/dist/fonts/KaTeX_Script-Regular.woff +0 -0
  76. package/dist/fonts/KaTeX_Script-Regular.woff2 +0 -0
  77. package/dist/fonts/KaTeX_Size1-Regular.ttf +0 -0
  78. package/dist/fonts/KaTeX_Size1-Regular.woff +0 -0
  79. package/dist/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  80. package/dist/fonts/KaTeX_Size2-Regular.ttf +0 -0
  81. package/dist/fonts/KaTeX_Size2-Regular.woff +0 -0
  82. package/dist/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  83. package/dist/fonts/KaTeX_Size3-Regular.ttf +0 -0
  84. package/dist/fonts/KaTeX_Size3-Regular.woff +0 -0
  85. package/dist/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  86. package/dist/fonts/KaTeX_Size4-Regular.ttf +0 -0
  87. package/dist/fonts/KaTeX_Size4-Regular.woff +0 -0
  88. package/dist/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  89. package/dist/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  90. package/dist/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  91. package/dist/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  92. package/dist/katex.css +66 -10
  93. package/dist/katex.js +2714 -1950
  94. package/dist/katex.min.css +1 -1
  95. package/dist/katex.min.js +1 -1
  96. package/dist/katex.mjs +3162 -2372
  97. package/katex.js +4 -3
  98. package/package.json +69 -59
  99. package/src/Lexer.js +4 -2
  100. package/src/MacroExpander.js +117 -37
  101. package/src/Options.js +2 -2
  102. package/src/ParseError.js +1 -1
  103. package/src/Parser.js +100 -159
  104. package/src/Settings.js +2 -2
  105. package/src/Style.js +4 -4
  106. package/src/Token.js +1 -1
  107. package/src/buildCommon.js +12 -5
  108. package/src/buildHTML.js +11 -0
  109. package/src/buildMathML.js +6 -0
  110. package/src/defineEnvironment.js +0 -3
  111. package/src/defineFunction.js +15 -22
  112. package/src/delimiter.js +61 -57
  113. package/src/domTree.js +1 -1
  114. package/src/environments/array.js +223 -35
  115. package/src/environments/cd.js +312 -0
  116. package/src/fontMetrics.js +1 -1
  117. package/src/fontMetricsData.js +2076 -0
  118. package/src/fonts/.gitignore +9 -0
  119. package/src/fonts/Makefile +139 -0
  120. package/src/fonts/default.cfg +20 -0
  121. package/src/fonts/generate_fonts.py +61 -0
  122. package/src/fonts/lib/Extra.otf +0 -0
  123. package/src/fonts/lib/Space.ttx +234 -0
  124. package/src/fonts/makeBlacker +49 -0
  125. package/src/fonts/makeFF +2003 -0
  126. package/src/fonts/xbbold.mf +182 -0
  127. package/src/fonts.less +64 -0
  128. package/src/functions/accent.js +3 -2
  129. package/src/functions/arrow.js +8 -2
  130. package/src/functions/color.js +4 -4
  131. package/src/functions/cr.js +7 -25
  132. package/src/functions/def.js +50 -24
  133. package/src/functions/delimsizing.js +8 -0
  134. package/src/functions/enclose.js +80 -12
  135. package/src/functions/environment.js +1 -1
  136. package/src/functions/font.js +3 -4
  137. package/src/functions/genfrac.js +36 -11
  138. package/src/functions/hbox.js +39 -0
  139. package/src/functions/kern.js +1 -0
  140. package/src/functions/mathchoice.js +1 -0
  141. package/src/functions/mclass.js +2 -1
  142. package/src/functions/op.js +3 -7
  143. package/src/functions/operatorname.js +1 -1
  144. package/src/functions/raisebox.js +0 -1
  145. package/src/functions/styling.js +1 -0
  146. package/src/functions/supsub.js +1 -3
  147. package/src/functions/symbolsOrd.js +0 -2
  148. package/src/functions/text.js +2 -3
  149. package/src/functions/vcenter.js +44 -0
  150. package/src/functions.js +3 -0
  151. package/src/katex.less +69 -16
  152. package/src/macros.js +42 -6
  153. package/src/mathMLTree.js +16 -1
  154. package/src/metrics/.gitignore +1 -0
  155. package/src/metrics/README.md +23 -0
  156. package/src/metrics/extract_tfms.py +114 -0
  157. package/src/metrics/extract_ttfs.py +119 -0
  158. package/src/metrics/format_json.py +28 -0
  159. package/src/metrics/mapping.pl +1224 -0
  160. package/src/metrics/parse_tfm.py +211 -0
  161. package/src/parseNode.js +29 -1
  162. package/src/parseTree.js +6 -0
  163. package/src/stretchy.js +12 -5
  164. package/src/svgGeometry.js +33 -4
  165. package/src/symbols.js +5 -3
  166. package/src/types.js +3 -2
  167. package/src/unicodeScripts.js +5 -0
package/katex.js CHANGED
@@ -25,6 +25,7 @@ import {
25
25
 
26
26
  import type {SettingsOptions} from "./src/Settings";
27
27
  import type {AnyParseNode} from "./src/parseNode";
28
+ import type {DomSpan} from "./src/domTree";
28
29
 
29
30
  import {defineSymbol} from './src/symbols';
30
31
  import {defineMacro} from './src/macros';
@@ -36,7 +37,7 @@ declare var __VERSION__: string;
36
37
  * Parse and build an expression, and place that expression in the DOM node
37
38
  * given.
38
39
  */
39
- let render = function(
40
+ let render: (string, Node, SettingsOptions) => void = function(
40
41
  expression: string,
41
42
  baseNode: Node,
42
43
  options: SettingsOptions,
@@ -109,7 +110,7 @@ const renderError = function(
109
110
  const renderToDomTree = function(
110
111
  expression: string,
111
112
  options: SettingsOptions,
112
- ) {
113
+ ): DomSpan {
113
114
  const settings = new Settings(options);
114
115
  try {
115
116
  const tree = parseTree(expression, settings);
@@ -126,7 +127,7 @@ const renderToDomTree = function(
126
127
  const renderToHTMLTree = function(
127
128
  expression: string,
128
129
  options: SettingsOptions,
129
- ) {
130
+ ): DomSpan {
130
131
  const settings = new Settings(options);
131
132
  try {
132
133
  const tree = parseTree(expression, settings);
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "katex",
3
- "version": "0.12.0",
3
+ "version": "0.13.3",
4
4
  "description": "Fast math typesetting for the web.",
5
5
  "main": "dist/katex.js",
6
6
  "homepage": "https://katex.org",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git://github.com/KaTeX/KaTeX.git"
9
+ "url": "https://github.com/KaTeX/KaTeX.git"
10
10
  },
11
11
  "files": [
12
12
  "katex.js",
@@ -17,68 +17,78 @@
17
17
  ],
18
18
  "license": "MIT",
19
19
  "devDependencies": {
20
- "@babel/core": "^7.3.3",
21
- "@babel/plugin-proposal-class-properties": "^7.3.3",
22
- "@babel/plugin-transform-runtime": "^7.2.0",
23
- "@babel/preset-env": "^7.3.1",
24
- "@babel/preset-flow": "^7.0.0",
25
- "@babel/register": "^7.0.0",
26
- "@babel/runtime": "^7.3.1",
27
- "babel-eslint": "^10.0.1",
28
- "babel-jest": "^24.1.0",
20
+ "@babel/core": "^7.10.4",
21
+ "@babel/plugin-proposal-class-properties": "^7.10.4",
22
+ "@babel/plugin-transform-runtime": "^7.10.4",
23
+ "@babel/preset-env": "^7.10.4",
24
+ "@babel/preset-flow": "^7.10.4",
25
+ "@babel/register": "^7.10.4",
26
+ "@babel/runtime": "^7.10.4",
27
+ "@rollup/plugin-alias": "^3.1.1",
28
+ "@rollup/plugin-babel": "^5.0.4",
29
+ "@semantic-release/changelog": "^5.0.1",
30
+ "@semantic-release/git": "^9.0.0",
31
+ "babel-eslint": "^10.1.0",
32
+ "babel-jest": "^26.1.0",
29
33
  "babel-loader": "^8.0.5",
30
- "babel-plugin-istanbul": "^5.1.1",
31
- "babel-plugin-preval": "^3.0.1",
34
+ "babel-plugin-istanbul": "^6.0.0",
35
+ "babel-plugin-preval": "^5.0.0",
32
36
  "babel-plugin-version-inline": "^1.0.0",
33
37
  "benchmark": "^2.1.4",
34
- "browserslist": "^4.7.1",
35
- "caniuse-lite": "^1.0.30001002",
36
- "codecov": "^3.2.0",
37
- "css-loader": "^3.0.0",
38
- "cssnano": "^4.1.10",
39
- "eslint": "^5.14.1",
40
- "eslint-plugin-flowtype": "^3.4.2",
41
- "eslint-plugin-react": "^7.12.4",
42
- "eslint-plugin-transform-runtime-aliasing": "^2.0.0",
43
- "file-loader": "^3.0.1",
44
- "flow-bin": "^0.102.0",
45
- "fs-extra": "^7.0.1",
46
- "husky": "^1.3.1",
47
- "istanbul-api": "^2.1.1",
48
- "istanbul-lib-coverage": "^2.0.3",
49
- "jest": "^24.1.0",
50
- "jest-serializer-html": "^6.0.0",
51
- "js-yaml": "^3.12.1",
38
+ "browserslist": "^4.13.0",
39
+ "browserstack-local": "^1.4.5",
40
+ "caniuse-lite": "^1.0.30001102",
41
+ "css-loader": "^5.1.2",
42
+ "cssnano": "^5.0.0-rc.1",
43
+ "eslint": "^7.4.0",
44
+ "eslint-plugin-actions": "^1.0.1",
45
+ "eslint-plugin-flowtype": "^5.2.0",
46
+ "eslint-plugin-react": "^7.20.3",
47
+ "file-loader": "^6.0.0",
48
+ "flow-bin": "^0.135.0",
49
+ "fs-extra": "^9.0.1",
50
+ "got": "^11.8.0",
51
+ "husky": "^4.2.5",
52
+ "istanbul-lib-coverage": "^3.0.0",
53
+ "istanbul-lib-report": "^3.0.0",
54
+ "istanbul-reports": "^3.0.2",
55
+ "jest": "^26.1.0",
56
+ "jest-diff": "^26.1.0",
57
+ "jest-matcher-utils": "^26.1.0",
58
+ "jest-message-util": "^26.1.0",
59
+ "jest-serializer-html": "^7.0.0",
60
+ "js-yaml": "^4.0.0",
52
61
  "json-stable-stringify": "^1.0.1",
53
62
  "jspngopt": "^0.2.0",
54
- "less": "^3.9.0",
55
- "less-loader": "^4.1.0",
56
- "mini-css-extract-plugin": "^0.5.0",
57
- "mkdirp": "^0.5.1",
58
- "pako": "^1.0.8",
59
- "postcss-loader": "^3.0.0",
60
- "prettier": "^1.18.2",
61
- "query-string": "^6.2.0",
62
- "rimraf": "^2.6.3",
63
- "rollup": "^1.2.2",
64
- "rollup-plugin-alias": "^1.5.1",
65
- "rollup-plugin-babel": "^4.3.2",
63
+ "less": "^4.0.0",
64
+ "less-loader": "^8.0.0",
65
+ "mini-css-extract-plugin": "^1.0.0",
66
+ "mkdirp": "^1.0.4",
67
+ "pako": "^2.0.0",
68
+ "postcss": "^8.0.0",
69
+ "postcss-loader": "^5.2.0",
70
+ "postcss-preset-env": "^6.7.0",
71
+ "prettier": "^2.0.5",
72
+ "query-string": "^7.0.0",
73
+ "rimraf": "^3.0.2",
74
+ "rollup": "^2.21.0",
66
75
  "selenium-webdriver": "^3.6.0",
76
+ "semantic-release": "^17.4.1",
67
77
  "sri-toolbox": "^0.2.0",
68
- "style-loader": "^0.23.1",
69
- "stylelint": "^9.10.1",
70
- "stylelint-config-standard": "^18.2.0",
71
- "terser-webpack-plugin": "^1.2.2",
72
- "webpack": "^4.29.5",
73
- "webpack-bundle-analyzer": "^3.0.4",
74
- "webpack-cli": "^3.2.3",
75
- "webpack-dev-server": "^3.2.0"
78
+ "style-loader": "^2.0.0",
79
+ "stylelint": "^13.6.1",
80
+ "stylelint-config-standard": "^21.0.0",
81
+ "terser-webpack-plugin": "^5.0.3",
82
+ "webpack": "^5.8.0",
83
+ "webpack-bundle-analyzer": "^4.0.0",
84
+ "webpack-cli": "^4.2.0",
85
+ "webpack-dev-server": "^4.0.0-beta.0"
76
86
  },
77
87
  "bin": "cli.js",
78
88
  "scripts": {
79
89
  "test": "yarn test:lint && yarn test:flow && yarn test:jest",
80
90
  "test:lint": "yarn test:lint:js && yarn test:lint:css",
81
- "test:lint:js": "eslint *.js src static test contrib dockers website",
91
+ "test:lint:js": "eslint .",
82
92
  "test:lint:css": "stylelint src/katex.less static/main.css contrib/**/*.css website/static/**/*.css",
83
93
  "test:flow": "flow",
84
94
  "test:jest": "jest",
@@ -90,21 +100,21 @@
90
100
  "test:perf": "NODE_ENV=test node test/perf-test.js",
91
101
  "clean": "rm -rf dist/ node_modules/",
92
102
  "clean-install": "yarn clean && yarn",
93
- "start": "webpack-dev-server --hot --config webpack.dev.js",
103
+ "start": "webpack serve --config webpack.dev.js",
94
104
  "analyze": "webpack --config webpack.analyze.js",
95
- "build": "rimraf dist/ && mkdirp dist && cp README.md dist && rollup -c && webpack",
105
+ "build": "rimraf dist/ && mkdirp dist && cp README.md dist && rollup -c && webpack && node update-sri.js package dist/README.md",
96
106
  "watch": "yarn build --watch",
97
- "dist": "yarn test && yarn build && yarn dist:zip",
107
+ "postversion": "yarn dist && node update-sri.js package README.md contrib/*/README.md docs/*.md website/pages/index.html",
108
+ "semantic-release": "semantic-release",
109
+ "dist": "yarn build && yarn dist:zip",
98
110
  "dist:zip": "rimraf katex/ katex.tar.gz katex.zip && cp -R dist katex && tar czf katex.tar.gz katex && zip -rq katex.zip katex && rimraf katex/"
99
111
  },
100
112
  "dependencies": {
101
- "commander": "^2.19.0"
113
+ "commander": "^6.0.0"
102
114
  },
103
115
  "husky": {
104
116
  "hooks": {
105
- "pre-commit": "yarn test:lint",
106
- "post-merge": "git submodule update --init --recursive",
107
- "post-checkout": "git submodule update --init --recursive"
117
+ "pre-commit": "yarn test:lint"
108
118
  }
109
119
  },
110
120
  "jest": {
package/src/Lexer.js CHANGED
@@ -42,7 +42,7 @@ const controlWordWhitespaceRegexString =
42
42
  const controlWordWhitespaceRegex = new RegExp(
43
43
  `^(${controlWordRegexString})${spaceRegexString}*$`);
44
44
  const combiningDiacriticalMarkString = "[\u0300-\u036f]";
45
- export const combiningDiacriticalMarksEndRegex =
45
+ export const combiningDiacriticalMarksEndRegex: RegExp =
46
46
  new RegExp(`${combiningDiacriticalMarkString}+$`);
47
47
  const tokenRegexString = `(${spaceRegexString}+)|` + // whitespace
48
48
  "([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + // single codepoint
@@ -60,7 +60,8 @@ export default class Lexer implements LexerInterface {
60
60
  input: string;
61
61
  settings: Settings;
62
62
  tokenRegex: RegExp;
63
- // category codes, only supports comment characters (14) for now
63
+ // Category codes. The lexer only supports comment characters (14) for now.
64
+ // MacroExpander additionally distinguishes active (13).
64
65
  catcodes: {[string]: number};
65
66
 
66
67
  constructor(input: string, settings: Settings) {
@@ -70,6 +71,7 @@ export default class Lexer implements LexerInterface {
70
71
  this.tokenRegex = new RegExp(tokenRegexString, 'g');
71
72
  this.catcodes = {
72
73
  "%": 14, // comment character
74
+ "~": 13, // active character
73
75
  };
74
76
  }
75
77
 
@@ -13,7 +13,7 @@ import ParseError from "./ParseError";
13
13
  import Namespace from "./Namespace";
14
14
  import builtinMacros from "./macros";
15
15
 
16
- import type {MacroContextInterface, MacroDefinition, MacroExpansion}
16
+ import type {MacroContextInterface, MacroDefinition, MacroExpansion, MacroArg}
17
17
  from "./macros";
18
18
  import type Settings from "./Settings";
19
19
 
@@ -108,6 +108,32 @@ export default class MacroExpander implements MacroContextInterface {
108
108
  this.stack.push(...tokens);
109
109
  }
110
110
 
111
+ /**
112
+ * Find an macro argument without expanding tokens and append the array of
113
+ * tokens to the token stack. Uses Token as a container for the result.
114
+ */
115
+ scanArgument(isOptional: boolean): ?Token {
116
+ let start;
117
+ let end;
118
+ let tokens;
119
+ if (isOptional) {
120
+ this.consumeSpaces(); // \@ifnextchar gobbles any space following it
121
+ if (this.future().text !== "[") {
122
+ return null;
123
+ }
124
+ start = this.popToken(); // don't include [ in tokens
125
+ ({tokens, end} = this.consumeArg(["]"]));
126
+ } else {
127
+ ({tokens, start, end} = this.consumeArg());
128
+ }
129
+
130
+ // indicate the end of an argument
131
+ this.pushToken(new Token("EOF", end.loc));
132
+
133
+ this.pushTokens(tokens);
134
+ return start.range(end, "");
135
+ }
136
+
111
137
  /**
112
138
  * Consume all following space tokens, without expansion.
113
139
  */
@@ -123,40 +149,91 @@ export default class MacroExpander implements MacroContextInterface {
123
149
  }
124
150
 
125
151
  /**
126
- * Consume the specified number of arguments from the token stream,
127
- * and return the resulting array of arguments.
152
+ * Consume an argument from the token stream, and return the resulting array
153
+ * of tokens and start/end token.
128
154
  */
129
- consumeArgs(numArgs: number): Token[][] {
130
- const args: Token[][] = [];
131
- // obtain arguments, either single token or balanced {} group
132
- for (let i = 0; i < numArgs; ++i) {
133
- this.consumeSpaces(); // ignore spaces before each argument
134
- const startOfArg = this.popToken();
135
- if (startOfArg.text === "{") {
136
- const arg: Token[] = [];
137
- let depth = 1;
138
- while (depth !== 0) {
139
- const tok = this.popToken();
140
- arg.push(tok);
141
- if (tok.text === "{") {
142
- ++depth;
143
- } else if (tok.text === "}") {
144
- --depth;
145
- } else if (tok.text === "EOF") {
146
- throw new ParseError(
147
- "End of input in macro argument",
148
- startOfArg);
155
+ consumeArg(delims?: ?string[]): MacroArg {
156
+ // The argument for a delimited parameter is the shortest (possibly
157
+ // empty) sequence of tokens with properly nested {...} groups that is
158
+ // followed ... by this particular list of non-parameter tokens.
159
+ // The argument for an undelimited parameter is the next nonblank
160
+ // token, unless that token is ‘{’, when the argument will be the
161
+ // entire {...} group that follows.
162
+ const tokens: Token[] = [];
163
+ const isDelimited = delims && delims.length > 0;
164
+ if (!isDelimited) {
165
+ // Ignore spaces between arguments. As the TeXbook says:
166
+ // "After you have said ‘\def\row#1#2{...}’, you are allowed to
167
+ // put spaces between the arguments (e.g., ‘\row x n’), because
168
+ // TeX doesn’t use single spaces as undelimited arguments."
169
+ this.consumeSpaces();
170
+ }
171
+ const start = this.future();
172
+ let tok;
173
+ let depth = 0;
174
+ let match = 0;
175
+ do {
176
+ tok = this.popToken();
177
+ tokens.push(tok);
178
+ if (tok.text === "{") {
179
+ ++depth;
180
+ } else if (tok.text === "}") {
181
+ --depth;
182
+ if (depth === -1) {
183
+ throw new ParseError("Extra }", tok);
184
+ }
185
+ } else if (tok.text === "EOF") {
186
+ throw new ParseError("Unexpected end of input in a macro argument" +
187
+ ", expected '" + (delims && isDelimited ? delims[match] : "}") +
188
+ "'", tok);
189
+ }
190
+ if (delims && isDelimited) {
191
+ if ((depth === 0 || (depth === 1 && delims[match] === "{")) &&
192
+ tok.text === delims[match]) {
193
+ ++match;
194
+ if (match === delims.length) {
195
+ // don't include delims in tokens
196
+ tokens.splice(-match, match);
197
+ break;
149
198
  }
199
+ } else {
200
+ match = 0;
150
201
  }
151
- arg.pop(); // remove last }
152
- arg.reverse(); // like above, to fit in with stack order
153
- args[i] = arg;
154
- } else if (startOfArg.text === "EOF") {
202
+ }
203
+ } while (depth !== 0 || isDelimited);
204
+ // If the argument found ... has the form ‘{<nested tokens>}’,
205
+ // ... the outermost braces enclosing the argument are removed
206
+ if (start.text === "{" && tokens[tokens.length - 1].text === "}") {
207
+ tokens.pop();
208
+ tokens.shift();
209
+ }
210
+ tokens.reverse(); // to fit in with stack order
211
+ return {tokens, start, end: tok};
212
+ }
213
+
214
+ /**
215
+ * Consume the specified number of (delimited) arguments from the token
216
+ * stream and return the resulting array of arguments.
217
+ */
218
+ consumeArgs(numArgs: number, delimiters?: string[][]): Token[][] {
219
+ if (delimiters) {
220
+ if (delimiters.length !== numArgs + 1) {
155
221
  throw new ParseError(
156
- "End of input expecting macro argument");
157
- } else {
158
- args[i] = [startOfArg];
222
+ "The length of delimiters doesn't match the number of args!");
159
223
  }
224
+ const delims = delimiters[0];
225
+ for (let i = 0; i < delims.length; i++) {
226
+ const tok = this.popToken();
227
+ if (delims[i] !== tok.text) {
228
+ throw new ParseError(
229
+ "Use of the macro doesn't match its definition", tok);
230
+ }
231
+ }
232
+ }
233
+
234
+ const args: Token[][] = [];
235
+ for (let i = 0; i < numArgs; i++) {
236
+ args.push(this.consumeArg(delimiters && delimiters[i + 1]).tokens);
160
237
  }
161
238
  return args;
162
239
  }
@@ -177,10 +254,6 @@ export default class MacroExpander implements MacroContextInterface {
177
254
  *
178
255
  * Used to implement `expandAfterFuture` and `expandNextToken`.
179
256
  *
180
- * At the moment, macro expansion doesn't handle delimited macros,
181
- * i.e. things like those defined by \def\foo#1\end{…}.
182
- * See the TeX book page 202ff. for details on how those should behave.
183
- *
184
257
  * If expandableOnly, only expandable tokens are expanded and
185
258
  * an undefined control sequence results in an error.
186
259
  */
@@ -202,8 +275,8 @@ export default class MacroExpander implements MacroContextInterface {
202
275
  "need to increase maxExpand setting");
203
276
  }
204
277
  let tokens = expansion.tokens;
278
+ const args = this.consumeArgs(expansion.numArgs, expansion.delimiters);
205
279
  if (expansion.numArgs) {
206
- const args = this.consumeArgs(expansion.numArgs);
207
280
  // paste arguments in place of the placeholders
208
281
  tokens = tokens.slice(); // make a shallow copy
209
282
  for (let i = tokens.length - 1; i >= 0; --i) {
@@ -322,6 +395,14 @@ export default class MacroExpander implements MacroContextInterface {
322
395
  if (definition == null) { // mainly checking for undefined here
323
396
  return definition;
324
397
  }
398
+ // If a single character has an associated catcode other than 13
399
+ // (active character), then don't expand it.
400
+ if (name.length === 1) {
401
+ const catcode = this.lexer.catcodes[name];
402
+ if (catcode != null && catcode !== 13) {
403
+ return;
404
+ }
405
+ }
325
406
  const expansion =
326
407
  typeof definition === "function" ? definition(this) : definition;
327
408
  if (typeof expansion === "string") {
@@ -368,7 +449,6 @@ export default class MacroExpander implements MacroContextInterface {
368
449
  const macro = this.macros.get(name);
369
450
  return macro != null ? typeof macro === "string"
370
451
  || typeof macro === "function" || !macro.unexpandable
371
- // TODO(ylem): #2085
372
- : functions.hasOwnProperty(name)/* && !functions[name].primitive*/;
452
+ : functions.hasOwnProperty(name) && !functions[name].primitive;
373
453
  }
374
454
  }
package/src/Options.js CHANGED
@@ -83,7 +83,7 @@ class Options {
83
83
  /**
84
84
  * The base size index.
85
85
  */
86
- static BASESIZE = 6;
86
+ static BASESIZE: number = 6;
87
87
 
88
88
  constructor(data: OptionsData) {
89
89
  this.style = data.style;
@@ -242,7 +242,7 @@ class Options {
242
242
  /**
243
243
  * Create a new options objects with the given fontFamily.
244
244
  */
245
- withTextFontFamily(fontFamily: string) {
245
+ withTextFontFamily(fontFamily: string): Options {
246
246
  return this.extend({
247
247
  fontFamily,
248
248
  font: "",
package/src/ParseError.js CHANGED
@@ -18,7 +18,7 @@ class ParseError {
18
18
  constructor(
19
19
  message: string, // The error message
20
20
  token?: ?Token | AnyParseNode, // An object providing position information
21
- ) {
21
+ ): Error {
22
22
  let error = "KaTeX parse error: " + message;
23
23
  let start;
24
24