render-a11y-string.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. (function webpackUniversalModuleDefinition(root, factory) {
  2. if(typeof exports === 'object' && typeof module === 'object')
  3. module.exports = factory(require("katex"));
  4. else if(typeof define === 'function' && define.amd)
  5. define(["katex"], factory);
  6. else {
  7. var a = typeof exports === 'object' ? factory(require("katex")) : factory(root["katex"]);
  8. for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
  9. }
  10. })((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__757__) {
  11. return /******/ (function() { // webpackBootstrap
  12. /******/ "use strict";
  13. /******/ var __webpack_modules__ = ({
  14. /***/ 757:
  15. /***/ (function(module) {
  16. module.exports = __WEBPACK_EXTERNAL_MODULE__757__;
  17. /***/ })
  18. /******/ });
  19. /************************************************************************/
  20. /******/ // The module cache
  21. /******/ var __webpack_module_cache__ = {};
  22. /******/
  23. /******/ // The require function
  24. /******/ function __webpack_require__(moduleId) {
  25. /******/ // Check if module is in cache
  26. /******/ var cachedModule = __webpack_module_cache__[moduleId];
  27. /******/ if (cachedModule !== undefined) {
  28. /******/ return cachedModule.exports;
  29. /******/ }
  30. /******/ // Create a new module (and put it into the cache)
  31. /******/ var module = __webpack_module_cache__[moduleId] = {
  32. /******/ // no module.id needed
  33. /******/ // no module.loaded needed
  34. /******/ exports: {}
  35. /******/ };
  36. /******/
  37. /******/ // Execute the module function
  38. /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
  39. /******/
  40. /******/ // Return the exports of the module
  41. /******/ return module.exports;
  42. /******/ }
  43. /******/
  44. /************************************************************************/
  45. /******/ /* webpack/runtime/compat get default export */
  46. /******/ !function() {
  47. /******/ // getDefaultExport function for compatibility with non-harmony modules
  48. /******/ __webpack_require__.n = function(module) {
  49. /******/ var getter = module && module.__esModule ?
  50. /******/ function() { return module['default']; } :
  51. /******/ function() { return module; };
  52. /******/ __webpack_require__.d(getter, { a: getter });
  53. /******/ return getter;
  54. /******/ };
  55. /******/ }();
  56. /******/
  57. /******/ /* webpack/runtime/define property getters */
  58. /******/ !function() {
  59. /******/ // define getter functions for harmony exports
  60. /******/ __webpack_require__.d = function(exports, definition) {
  61. /******/ for(var key in definition) {
  62. /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
  63. /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
  64. /******/ }
  65. /******/ }
  66. /******/ };
  67. /******/ }();
  68. /******/
  69. /******/ /* webpack/runtime/hasOwnProperty shorthand */
  70. /******/ !function() {
  71. /******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
  72. /******/ }();
  73. /******/
  74. /************************************************************************/
  75. var __webpack_exports__ = {};
  76. /* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(757);
  77. /* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(katex__WEBPACK_IMPORTED_MODULE_0__);
  78. /**
  79. * renderA11yString returns a readable string.
  80. *
  81. * In some cases the string will have the proper semantic math
  82. * meaning,:
  83. * renderA11yString("\\frac{1}{2}"")
  84. * -> "start fraction, 1, divided by, 2, end fraction"
  85. *
  86. * However, other cases do not:
  87. * renderA11yString("f(x) = x^2")
  88. * -> "f, left parenthesis, x, right parenthesis, equals, x, squared"
  89. *
  90. * The commas in the string aim to increase ease of understanding
  91. * when read by a screenreader.
  92. */
  93. // NOTE: since we're importing types here these files won't actually be
  94. // included in the build.
  95. const stringMap = {
  96. "(": "left parenthesis",
  97. ")": "right parenthesis",
  98. "[": "open bracket",
  99. "]": "close bracket",
  100. "\\{": "left brace",
  101. "\\}": "right brace",
  102. "\\lvert": "open vertical bar",
  103. "\\rvert": "close vertical bar",
  104. "|": "vertical bar",
  105. "\\uparrow": "up arrow",
  106. "\\Uparrow": "up arrow",
  107. "\\downarrow": "down arrow",
  108. "\\Downarrow": "down arrow",
  109. "\\updownarrow": "up down arrow",
  110. "\\leftarrow": "left arrow",
  111. "\\Leftarrow": "left arrow",
  112. "\\rightarrow": "right arrow",
  113. "\\Rightarrow": "right arrow",
  114. "\\langle": "open angle",
  115. "\\rangle": "close angle",
  116. "\\lfloor": "open floor",
  117. "\\rfloor": "close floor",
  118. "\\int": "integral",
  119. "\\intop": "integral",
  120. "\\lim": "limit",
  121. "\\ln": "natural log",
  122. "\\log": "log",
  123. "\\sin": "sine",
  124. "\\cos": "cosine",
  125. "\\tan": "tangent",
  126. "\\cot": "cotangent",
  127. "\\sum": "sum",
  128. "/": "slash",
  129. ",": "comma",
  130. ".": "point",
  131. "-": "negative",
  132. "+": "plus",
  133. "~": "tilde",
  134. ":": "colon",
  135. "?": "question mark",
  136. "'": "apostrophe",
  137. "\\%": "percent",
  138. " ": "space",
  139. "\\ ": "space",
  140. "\\$": "dollar sign",
  141. "\\angle": "angle",
  142. "\\degree": "degree",
  143. "\\circ": "circle",
  144. "\\vec": "vector",
  145. "\\triangle": "triangle",
  146. "\\pi": "pi",
  147. "\\prime": "prime",
  148. "\\infty": "infinity",
  149. "\\alpha": "alpha",
  150. "\\beta": "beta",
  151. "\\gamma": "gamma",
  152. "\\omega": "omega",
  153. "\\theta": "theta",
  154. "\\sigma": "sigma",
  155. "\\lambda": "lambda",
  156. "\\tau": "tau",
  157. "\\Delta": "delta",
  158. "\\delta": "delta",
  159. "\\mu": "mu",
  160. "\\rho": "rho",
  161. "\\nabla": "del",
  162. "\\ell": "ell",
  163. "\\ldots": "dots",
  164. // TODO: add entries for all accents
  165. "\\hat": "hat",
  166. "\\acute": "acute"
  167. };
  168. const powerMap = {
  169. "prime": "prime",
  170. "degree": "degrees",
  171. "circle": "degrees",
  172. "2": "squared",
  173. "3": "cubed"
  174. };
  175. const openMap = {
  176. "|": "open vertical bar",
  177. ".": ""
  178. };
  179. const closeMap = {
  180. "|": "close vertical bar",
  181. ".": ""
  182. };
  183. const binMap = {
  184. "+": "plus",
  185. "-": "minus",
  186. "\\pm": "plus minus",
  187. "\\cdot": "dot",
  188. "*": "times",
  189. "/": "divided by",
  190. "\\times": "times",
  191. "\\div": "divided by",
  192. "\\circ": "circle",
  193. "\\bullet": "bullet"
  194. };
  195. const relMap = {
  196. "=": "equals",
  197. "\\approx": "approximately equals",
  198. "≠": "does not equal",
  199. "\\geq": "is greater than or equal to",
  200. "\\ge": "is greater than or equal to",
  201. "\\leq": "is less than or equal to",
  202. "\\le": "is less than or equal to",
  203. ">": "is greater than",
  204. "<": "is less than",
  205. "\\leftarrow": "left arrow",
  206. "\\Leftarrow": "left arrow",
  207. "\\rightarrow": "right arrow",
  208. "\\Rightarrow": "right arrow",
  209. ":": "colon"
  210. };
  211. const accentUnderMap = {
  212. "\\underleftarrow": "left arrow",
  213. "\\underrightarrow": "right arrow",
  214. "\\underleftrightarrow": "left-right arrow",
  215. "\\undergroup": "group",
  216. "\\underlinesegment": "line segment",
  217. "\\utilde": "tilde"
  218. };
  219. const buildString = (str, type, a11yStrings) => {
  220. if (!str) {
  221. return;
  222. }
  223. let ret;
  224. if (type === "open") {
  225. ret = str in openMap ? openMap[str] : stringMap[str] || str;
  226. } else if (type === "close") {
  227. ret = str in closeMap ? closeMap[str] : stringMap[str] || str;
  228. } else if (type === "bin") {
  229. ret = binMap[str] || str;
  230. } else if (type === "rel") {
  231. ret = relMap[str] || str;
  232. } else {
  233. ret = stringMap[str] || str;
  234. }
  235. // If the text to add is a number and there is already a string
  236. // in the list and the last string is a number then we should
  237. // combine them into a single number
  238. const last = a11yStrings[a11yStrings.length - 1];
  239. if (/^\d+$/.test(ret) && a11yStrings.length > 0 && typeof last === "string" && /^\d+$/.test(last)) {
  240. a11yStrings[a11yStrings.length - 1] += ret;
  241. } else if (ret) {
  242. a11yStrings.push(ret);
  243. }
  244. };
  245. const buildRegion = (a11yStrings, callback) => {
  246. const regionStrings = [];
  247. a11yStrings.push(regionStrings);
  248. callback(regionStrings);
  249. };
  250. const handleObject = (tree, a11yStrings, atomType) => {
  251. // Everything else is assumed to be an object...
  252. switch (tree.type) {
  253. case "accent":
  254. {
  255. buildRegion(a11yStrings, a11yStrings => {
  256. buildA11yStrings(tree.base, a11yStrings, atomType);
  257. a11yStrings.push("with");
  258. buildString(tree.label, "normal", a11yStrings);
  259. a11yStrings.push("on top");
  260. });
  261. break;
  262. }
  263. case "accentUnder":
  264. {
  265. buildRegion(a11yStrings, a11yStrings => {
  266. buildA11yStrings(tree.base, a11yStrings, atomType);
  267. a11yStrings.push("with");
  268. buildString(accentUnderMap[tree.label], "normal", a11yStrings);
  269. a11yStrings.push("underneath");
  270. });
  271. break;
  272. }
  273. case "accent-token":
  274. {
  275. // Used internally by accent symbols.
  276. break;
  277. }
  278. case "atom":
  279. {
  280. const {
  281. text
  282. } = tree;
  283. switch (tree.family) {
  284. case "bin":
  285. {
  286. buildString(text, "bin", a11yStrings);
  287. break;
  288. }
  289. case "close":
  290. {
  291. buildString(text, "close", a11yStrings);
  292. break;
  293. }
  294. // TODO(kevinb): figure out what should be done for inner
  295. case "inner":
  296. {
  297. buildString(tree.text, "inner", a11yStrings);
  298. break;
  299. }
  300. case "open":
  301. {
  302. buildString(text, "open", a11yStrings);
  303. break;
  304. }
  305. case "punct":
  306. {
  307. buildString(text, "punct", a11yStrings);
  308. break;
  309. }
  310. case "rel":
  311. {
  312. buildString(text, "rel", a11yStrings);
  313. break;
  314. }
  315. default:
  316. {
  317. tree.family;
  318. throw new Error("\"" + tree.family + "\" is not a valid atom type");
  319. }
  320. }
  321. break;
  322. }
  323. case "color":
  324. {
  325. const color = tree.color.replace(/katex-/, "");
  326. buildRegion(a11yStrings, regionStrings => {
  327. regionStrings.push("start color " + color);
  328. buildA11yStrings(tree.body, regionStrings, atomType);
  329. regionStrings.push("end color " + color);
  330. });
  331. break;
  332. }
  333. case "color-token":
  334. {
  335. // Used by \color, \colorbox, and \fcolorbox but not directly rendered.
  336. // It's a leaf node and has no children so just break.
  337. break;
  338. }
  339. case "delimsizing":
  340. {
  341. if (tree.delim && tree.delim !== ".") {
  342. buildString(tree.delim, "normal", a11yStrings);
  343. }
  344. break;
  345. }
  346. case "genfrac":
  347. {
  348. buildRegion(a11yStrings, regionStrings => {
  349. // genfrac can have unbalanced delimiters
  350. const {
  351. leftDelim,
  352. rightDelim
  353. } = tree;
  354. // NOTE: Not sure if this is a safe assumption
  355. // hasBarLine true -> fraction, false -> binomial
  356. if (tree.hasBarLine) {
  357. regionStrings.push("start fraction");
  358. leftDelim && buildString(leftDelim, "open", regionStrings);
  359. buildA11yStrings(tree.numer, regionStrings, atomType);
  360. regionStrings.push("divided by");
  361. buildA11yStrings(tree.denom, regionStrings, atomType);
  362. rightDelim && buildString(rightDelim, "close", regionStrings);
  363. regionStrings.push("end fraction");
  364. } else {
  365. regionStrings.push("start binomial");
  366. leftDelim && buildString(leftDelim, "open", regionStrings);
  367. buildA11yStrings(tree.numer, regionStrings, atomType);
  368. regionStrings.push("over");
  369. buildA11yStrings(tree.denom, regionStrings, atomType);
  370. rightDelim && buildString(rightDelim, "close", regionStrings);
  371. regionStrings.push("end binomial");
  372. }
  373. });
  374. break;
  375. }
  376. case "hbox":
  377. {
  378. buildA11yStrings(tree.body, a11yStrings, atomType);
  379. break;
  380. }
  381. case "kern":
  382. {
  383. // No op: we don't attempt to present kerning information
  384. // to the screen reader.
  385. break;
  386. }
  387. case "leftright":
  388. {
  389. buildRegion(a11yStrings, regionStrings => {
  390. buildString(tree.left, "open", regionStrings);
  391. buildA11yStrings(tree.body, regionStrings, atomType);
  392. buildString(tree.right, "close", regionStrings);
  393. });
  394. break;
  395. }
  396. case "leftright-right":
  397. {
  398. // TODO: double check that this is a no-op
  399. break;
  400. }
  401. case "lap":
  402. {
  403. buildA11yStrings(tree.body, a11yStrings, atomType);
  404. break;
  405. }
  406. case "mathord":
  407. {
  408. buildString(tree.text, "normal", a11yStrings);
  409. break;
  410. }
  411. case "op":
  412. {
  413. const {
  414. body,
  415. name
  416. } = tree;
  417. if (body) {
  418. buildA11yStrings(body, a11yStrings, atomType);
  419. } else if (name) {
  420. buildString(name, "normal", a11yStrings);
  421. }
  422. break;
  423. }
  424. case "op-token":
  425. {
  426. // Used internally by operator symbols.
  427. buildString(tree.text, atomType, a11yStrings);
  428. break;
  429. }
  430. case "ordgroup":
  431. {
  432. buildA11yStrings(tree.body, a11yStrings, atomType);
  433. break;
  434. }
  435. case "overline":
  436. {
  437. buildRegion(a11yStrings, function (a11yStrings) {
  438. a11yStrings.push("start overline");
  439. buildA11yStrings(tree.body, a11yStrings, atomType);
  440. a11yStrings.push("end overline");
  441. });
  442. break;
  443. }
  444. case "pmb":
  445. {
  446. a11yStrings.push("bold");
  447. break;
  448. }
  449. case "phantom":
  450. {
  451. a11yStrings.push("empty space");
  452. break;
  453. }
  454. case "raisebox":
  455. {
  456. buildA11yStrings(tree.body, a11yStrings, atomType);
  457. break;
  458. }
  459. case "rule":
  460. {
  461. a11yStrings.push("rectangle");
  462. break;
  463. }
  464. case "sizing":
  465. {
  466. buildA11yStrings(tree.body, a11yStrings, atomType);
  467. break;
  468. }
  469. case "spacing":
  470. {
  471. a11yStrings.push("space");
  472. break;
  473. }
  474. case "styling":
  475. {
  476. // We ignore the styling and just pass through the contents
  477. buildA11yStrings(tree.body, a11yStrings, atomType);
  478. break;
  479. }
  480. case "sqrt":
  481. {
  482. buildRegion(a11yStrings, regionStrings => {
  483. const {
  484. body,
  485. index
  486. } = tree;
  487. if (index) {
  488. const indexString = flatten(buildA11yStrings(index, [], atomType)).join(",");
  489. if (indexString === "3") {
  490. regionStrings.push("cube root of");
  491. buildA11yStrings(body, regionStrings, atomType);
  492. regionStrings.push("end cube root");
  493. return;
  494. }
  495. regionStrings.push("root");
  496. regionStrings.push("start index");
  497. buildA11yStrings(index, regionStrings, atomType);
  498. regionStrings.push("end index");
  499. return;
  500. }
  501. regionStrings.push("square root of");
  502. buildA11yStrings(body, regionStrings, atomType);
  503. regionStrings.push("end square root");
  504. });
  505. break;
  506. }
  507. case "supsub":
  508. {
  509. const {
  510. base,
  511. sub,
  512. sup
  513. } = tree;
  514. let isLog = false;
  515. if (base) {
  516. buildA11yStrings(base, a11yStrings, atomType);
  517. isLog = base.type === "op" && base.name === "\\log";
  518. }
  519. if (sub) {
  520. const regionName = isLog ? "base" : "subscript";
  521. buildRegion(a11yStrings, function (regionStrings) {
  522. regionStrings.push("start " + regionName);
  523. buildA11yStrings(sub, regionStrings, atomType);
  524. regionStrings.push("end " + regionName);
  525. });
  526. }
  527. if (sup) {
  528. buildRegion(a11yStrings, function (regionStrings) {
  529. const supString = flatten(buildA11yStrings(sup, [], atomType)).join(",");
  530. if (supString in powerMap) {
  531. regionStrings.push(powerMap[supString]);
  532. return;
  533. }
  534. regionStrings.push("start superscript");
  535. buildA11yStrings(sup, regionStrings, atomType);
  536. regionStrings.push("end superscript");
  537. });
  538. }
  539. break;
  540. }
  541. case "text":
  542. {
  543. // TODO: handle other fonts
  544. if (tree.font === "\\textbf") {
  545. buildRegion(a11yStrings, function (regionStrings) {
  546. regionStrings.push("start bold text");
  547. buildA11yStrings(tree.body, regionStrings, atomType);
  548. regionStrings.push("end bold text");
  549. });
  550. break;
  551. }
  552. buildRegion(a11yStrings, function (regionStrings) {
  553. regionStrings.push("start text");
  554. buildA11yStrings(tree.body, regionStrings, atomType);
  555. regionStrings.push("end text");
  556. });
  557. break;
  558. }
  559. case "textord":
  560. {
  561. buildString(tree.text, atomType, a11yStrings);
  562. break;
  563. }
  564. case "smash":
  565. {
  566. buildA11yStrings(tree.body, a11yStrings, atomType);
  567. break;
  568. }
  569. case "enclose":
  570. {
  571. // TODO: create a map for these.
  572. // TODO: differentiate between a body with a single atom, e.g.
  573. // "cancel a" instead of "start cancel, a, end cancel"
  574. if (/cancel/.test(tree.label)) {
  575. buildRegion(a11yStrings, function (regionStrings) {
  576. regionStrings.push("start cancel");
  577. buildA11yStrings(tree.body, regionStrings, atomType);
  578. regionStrings.push("end cancel");
  579. });
  580. break;
  581. } else if (/box/.test(tree.label)) {
  582. buildRegion(a11yStrings, function (regionStrings) {
  583. regionStrings.push("start box");
  584. buildA11yStrings(tree.body, regionStrings, atomType);
  585. regionStrings.push("end box");
  586. });
  587. break;
  588. } else if (/sout/.test(tree.label)) {
  589. buildRegion(a11yStrings, function (regionStrings) {
  590. regionStrings.push("start strikeout");
  591. buildA11yStrings(tree.body, regionStrings, atomType);
  592. regionStrings.push("end strikeout");
  593. });
  594. break;
  595. } else if (/phase/.test(tree.label)) {
  596. buildRegion(a11yStrings, function (regionStrings) {
  597. regionStrings.push("start phase angle");
  598. buildA11yStrings(tree.body, regionStrings, atomType);
  599. regionStrings.push("end phase angle");
  600. });
  601. break;
  602. }
  603. throw new Error("KaTeX-a11y: enclose node with " + tree.label + " not supported yet");
  604. }
  605. case "vcenter":
  606. {
  607. buildA11yStrings(tree.body, a11yStrings, atomType);
  608. break;
  609. }
  610. case "vphantom":
  611. {
  612. throw new Error("KaTeX-a11y: vphantom not implemented yet");
  613. }
  614. case "operatorname":
  615. {
  616. buildA11yStrings(tree.body, a11yStrings, atomType);
  617. break;
  618. }
  619. case "array":
  620. {
  621. throw new Error("KaTeX-a11y: array not implemented yet");
  622. }
  623. case "raw":
  624. {
  625. throw new Error("KaTeX-a11y: raw not implemented yet");
  626. }
  627. case "size":
  628. {
  629. // Although there are nodes of type "size" in the parse tree, they have
  630. // no semantic meaning and should be ignored.
  631. break;
  632. }
  633. case "url":
  634. {
  635. throw new Error("KaTeX-a11y: url not implemented yet");
  636. }
  637. case "tag":
  638. {
  639. throw new Error("KaTeX-a11y: tag not implemented yet");
  640. }
  641. case "verb":
  642. {
  643. buildString("start verbatim", "normal", a11yStrings);
  644. buildString(tree.body, "normal", a11yStrings);
  645. buildString("end verbatim", "normal", a11yStrings);
  646. break;
  647. }
  648. case "environment":
  649. {
  650. throw new Error("KaTeX-a11y: environment not implemented yet");
  651. }
  652. case "horizBrace":
  653. {
  654. buildString("start " + tree.label.slice(1), "normal", a11yStrings);
  655. buildA11yStrings(tree.base, a11yStrings, atomType);
  656. buildString("end " + tree.label.slice(1), "normal", a11yStrings);
  657. break;
  658. }
  659. case "infix":
  660. {
  661. // All infix nodes are replace with other nodes.
  662. break;
  663. }
  664. case "includegraphics":
  665. {
  666. throw new Error("KaTeX-a11y: includegraphics not implemented yet");
  667. }
  668. case "font":
  669. {
  670. // TODO: callout the start/end of specific fonts
  671. // TODO: map \BBb{N} to "the naturals" or something like that
  672. buildA11yStrings(tree.body, a11yStrings, atomType);
  673. break;
  674. }
  675. case "href":
  676. {
  677. throw new Error("KaTeX-a11y: href not implemented yet");
  678. }
  679. case "cr":
  680. {
  681. // This is used by environments.
  682. throw new Error("KaTeX-a11y: cr not implemented yet");
  683. }
  684. case "underline":
  685. {
  686. buildRegion(a11yStrings, function (a11yStrings) {
  687. a11yStrings.push("start underline");
  688. buildA11yStrings(tree.body, a11yStrings, atomType);
  689. a11yStrings.push("end underline");
  690. });
  691. break;
  692. }
  693. case "xArrow":
  694. {
  695. throw new Error("KaTeX-a11y: xArrow not implemented yet");
  696. }
  697. case "cdlabel":
  698. {
  699. throw new Error("KaTeX-a11y: cdlabel not implemented yet");
  700. }
  701. case "cdlabelparent":
  702. {
  703. throw new Error("KaTeX-a11y: cdlabelparent not implemented yet");
  704. }
  705. case "mclass":
  706. {
  707. // \neq and \ne are macros so we let "htmlmathml" render the mathmal
  708. // side of things and extract the text from that.
  709. const atomType = tree.mclass.slice(1);
  710. // TODO(ts): drop the leading "m" from the values in mclass
  711. buildA11yStrings(tree.body, a11yStrings, atomType);
  712. break;
  713. }
  714. case "mathchoice":
  715. {
  716. // TODO: track which style we're using, e.g. display, text, etc.
  717. // default to text style if even that may not be the correct style
  718. buildA11yStrings(tree.text, a11yStrings, atomType);
  719. break;
  720. }
  721. case "htmlmathml":
  722. {
  723. buildA11yStrings(tree.mathml, a11yStrings, atomType);
  724. break;
  725. }
  726. case "middle":
  727. {
  728. buildString(tree.delim, atomType, a11yStrings);
  729. break;
  730. }
  731. case "internal":
  732. {
  733. // internal nodes are never included in the parse tree
  734. break;
  735. }
  736. case "html":
  737. {
  738. buildA11yStrings(tree.body, a11yStrings, atomType);
  739. break;
  740. }
  741. default:
  742. throw new Error("KaTeX a11y un-recognized type: " + tree.type);
  743. }
  744. };
  745. const buildA11yStrings = function (tree, a11yStrings, atomType) {
  746. if (a11yStrings === void 0) {
  747. a11yStrings = [];
  748. }
  749. if (tree instanceof Array) {
  750. for (let i = 0; i < tree.length; i++) {
  751. buildA11yStrings(tree[i], a11yStrings, atomType);
  752. }
  753. } else {
  754. handleObject(tree, a11yStrings, atomType);
  755. }
  756. return a11yStrings;
  757. };
  758. const flatten = function (array) {
  759. let result = [];
  760. array.forEach(function (item) {
  761. if (Array.isArray(item)) {
  762. result = result.concat(flatten(item));
  763. } else {
  764. result.push(item);
  765. }
  766. });
  767. return result;
  768. };
  769. const renderA11yString = function (text, settings) {
  770. const tree = katex__WEBPACK_IMPORTED_MODULE_0___default().__parse(text, settings);
  771. const a11yStrings = buildA11yStrings(tree, [], "normal");
  772. return flatten(a11yStrings).join(", ");
  773. };
  774. /* harmony default export */ __webpack_exports__["default"] = (renderA11yString);
  775. __webpack_exports__ = __webpack_exports__["default"];
  776. /******/ return __webpack_exports__;
  777. /******/ })()
  778. ;
  779. });