mathml-spec.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /* global expect: false */
  2. /* global it: false */
  3. /* global describe: false */
  4. import buildMathML from "../src/buildMathML";
  5. import parseTree from "../src/parseTree";
  6. import Options from "../src/Options";
  7. import Settings from "../src/Settings";
  8. import Style from "../src/Style";
  9. const getMathML = function(expr, settings = new Settings()) {
  10. let startStyle = Style.TEXT;
  11. if (settings.displayMode) {
  12. startStyle = Style.DISPLAY;
  13. }
  14. // Setup the default options
  15. const options = new Options({
  16. style: startStyle,
  17. maxSize: Infinity,
  18. });
  19. const built = buildMathML(parseTree(expr, settings), expr, options);
  20. // Strip off the surrounding <span>
  21. return built.children[0].toMarkup();
  22. };
  23. describe("A MathML builder", function() {
  24. it('should generate the right types of nodes', () => {
  25. expect(getMathML("\\sin{x}+1\\;\\text{a}")).toMatchSnapshot();
  26. });
  27. it('should concatenate digits into single <mn>', () => {
  28. expect(getMathML("\\sin{\\alpha}=0.34")).toMatchSnapshot();
  29. });
  30. it('should make prime operators into <mo> nodes', () => {
  31. expect(getMathML("f'")).toMatchSnapshot();
  32. });
  33. it('should generate <mphantom> nodes for \\phantom', () => {
  34. expect(getMathML("\\phantom{x}")).toMatchSnapshot();
  35. });
  36. it('should use <munderover> for large operators', () => {
  37. expect(getMathML("\\displaystyle\\sum_a^b")).toMatchSnapshot();
  38. });
  39. it('should use <msupsub> for regular operators', () => {
  40. expect(getMathML("\\textstyle\\sum_a^b")).toMatchSnapshot();
  41. });
  42. it("should output \\limsup_{x \\rightarrow \\infty} correctly in " +
  43. "\\textstyle", () => {
  44. const mathml = getMathML("\\limsup_{x \\rightarrow \\infty}");
  45. expect(mathml).toMatchSnapshot();
  46. });
  47. it("should output \\limsup_{x \\rightarrow \\infty} in " +
  48. "displaymode correctly", () => {
  49. const settings = new Settings({displayMode: true});
  50. const mathml = getMathML("\\limsup_{x \\rightarrow \\infty}", settings);
  51. expect(mathml).toMatchSnapshot();
  52. });
  53. it('should use <mpadded> for raisebox', () => {
  54. expect(getMathML("\\raisebox{0.25em}{b}")).toMatchSnapshot();
  55. });
  56. it('should use <menclose> for colorbox', () => {
  57. expect(getMathML("\\colorbox{red}{b}")).toMatchSnapshot();
  58. });
  59. it('should set href attribute for href appropriately', () => {
  60. expect(getMathML("\\href{http://example.org}{\\alpha}")).toMatchSnapshot();
  61. expect(getMathML("p \\Vdash \\beta \\href{http://example.org}{+ \\alpha} \\times \\gamma"));
  62. });
  63. it('should render mathchoice as if there was nothing', () => {
  64. const cmd = "\\sum_{k = 0}^{\\infty} x^k";
  65. expect(getMathML(`\\displaystyle\\mathchoice{${cmd}}{T}{S}{SS}`))
  66. .toMatchSnapshot();
  67. expect(getMathML(`\\mathchoice{D}{${cmd}}{S}{SS}`))
  68. .toMatchSnapshot();
  69. expect(getMathML(`x_{\\mathchoice{D}{T}{${cmd}}{SS}}`))
  70. .toMatchSnapshot();
  71. expect(getMathML(`x_{y_{\\mathchoice{D}{T}{S}{${cmd}}}}`))
  72. .toMatchSnapshot();
  73. });
  74. it("should render boldsymbol with the correct mathvariants", () => {
  75. expect(getMathML(`\\boldsymbol{Ax2k\\omega\\Omega\\imath+}`))
  76. .toMatchSnapshot();
  77. });
  78. it('accents turn into <mover accent="true"> in MathML', () => {
  79. expect(getMathML("über fiancée", {unicodeTextInMathMode: true}))
  80. .toMatchSnapshot();
  81. });
  82. it('tags use <mlabeledtr>', () => {
  83. expect(getMathML("\\tag{hi} x+y^2", {displayMode: true}))
  84. .toMatchSnapshot();
  85. });
  86. it('normal spaces render normally', function() {
  87. expect(getMathML("\\kern1em\\kern1ex")).toMatchSnapshot();
  88. });
  89. it('special spaces render specially', function() {
  90. expect(getMathML(
  91. "\\,\\thinspace\\:\\>\\medspace\\;\\thickspace" +
  92. "\\!\\negthinspace\\negmedspace\\negthickspace" +
  93. "\\mkern1mu\\mkern3mu\\mkern4mu\\mkern5mu" +
  94. "\\mkern-1mu\\mkern-3mu\\mkern-4mu\\mkern-5mu")).toMatchSnapshot();
  95. });
  96. it('ligatures render properly', () => {
  97. expect(getMathML("\\text{```Hi----'''}--" +
  98. "\\texttt{```Hi----'''}" +
  99. "\\text{\\tt ```Hi----'''}")).toMatchSnapshot();
  100. });
  101. it('\\text fonts become mathvariant', () => {
  102. expect(getMathML("\\text{" +
  103. "roman\\textit{italic\\textbf{bold italic}}\\textbf{bold}" +
  104. "\\textsf{ss\\textit{italic\\textbf{bold italic}}\\textbf{bold}}" +
  105. "\\texttt{tt\\textit{italic\\textbf{bold italic}}\\textbf{bold}}}"))
  106. .toMatchSnapshot();
  107. });
  108. it('\\html@mathml makes clean symbols', () => {
  109. expect(getMathML("\\copyright\\neq\\notin\u2258\\KaTeX"))
  110. .toMatchSnapshot();
  111. });
  112. });