TextMacrosConfiguration.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*************************************************************
  2. *
  3. * Copyright (c) 2020-2022 The MathJax Consortium
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /**
  18. * @fileoverview Configuration file for the textmacros package
  19. *
  20. * @author dpvc@mathjax.org (Davide P. Cervone)
  21. */
  22. import {TeX} from '../../tex.js';
  23. import TexParser from '../TexParser.js';
  24. import {Configuration, ParserConfiguration} from '../Configuration.js';
  25. import ParseOptions from '../ParseOptions.js';
  26. import {TagsFactory} from '../Tags.js';
  27. import {StartItem, StopItem, MmlItem, StyleItem} from '../base/BaseItems.js';
  28. import {TextParser} from './TextParser.js';
  29. import {TextMacrosMethods} from './TextMacrosMethods.js';
  30. import {MmlNode} from '../../../core/MmlTree/MmlNode.js';
  31. import './TextMacrosMappings.js';
  32. /**
  33. * The base text macro configuration (used in the TextParser)
  34. */
  35. export const TextBaseConfiguration = Configuration.create('text-base', {
  36. parser: 'text',
  37. handler: {
  38. character: ['command', 'text-special'],
  39. macro: ['text-macros']
  40. },
  41. fallback: {
  42. //
  43. // Unknown characters are added to the text verbatim
  44. //
  45. character: (parser: TextParser, c: string) => {
  46. parser.text += c;
  47. },
  48. //
  49. // For unknown macros, if they are defined in the main TeX parser
  50. // and not string-replacement macros, give an error, otherwise
  51. // run the macro (this either does the string replacement or
  52. // produces the error as configured in the main TeX parser, so
  53. // this will respect the noundefined package, if loaded).
  54. //
  55. macro: (parser: TextParser, name: string) => {
  56. const texParser = parser.texParser;
  57. const macro = texParser.lookup('macro', name);
  58. if (macro && macro._func !== TextMacrosMethods.Macro) {
  59. parser.Error('MathMacro', '%1 is only supported in math mode', '\\' + name);
  60. }
  61. texParser.parse('macro', [parser, name]);
  62. }
  63. },
  64. items: {
  65. [StartItem.prototype.kind]: StartItem,
  66. [StopItem.prototype.kind]: StopItem,
  67. [MmlItem.prototype.kind]: MmlItem,
  68. [StyleItem.prototype.kind]: StyleItem // needed for \color
  69. }
  70. });
  71. /**
  72. * Replacement for ParseUtil.internalMath that handles text-mode macros.
  73. *
  74. * @param {TexParser} parser The TexParser calling this function
  75. * @param {string} text The text-mode string to be processed
  76. * @param {number|string} level The scriptlevel of the text
  77. * @param {string} mathvariant The mathvariant for the text
  78. * @return {MmlNode[]} The final MmlNode generated for the text
  79. */
  80. function internalMath(parser: TexParser, text: string, level?: number | string, mathvariant?: string): MmlNode[] {
  81. const config = parser.configuration.packageData.get('textmacros');
  82. if (!(parser instanceof TextParser)) {
  83. config.texParser = parser;
  84. }
  85. return [(new TextParser(text, mathvariant ? {mathvariant} : {}, config.parseOptions, level)).mml()];
  86. }
  87. //
  88. // The textmacros package configuration
  89. //
  90. export const TextMacrosConfiguration = Configuration.create('textmacros', {
  91. /**
  92. * @param {ParserConfiguration} config The configuration object we are being configured within
  93. * @param {TeX<any,any,any>} jax The TeX input jax in which we are running
  94. */
  95. config(_config: ParserConfiguration, jax: TeX<any, any, any>) {
  96. //
  97. // Create the configuration and parseOptions objects for the
  98. // internal TextParser and add the textBase configuration.
  99. //
  100. const textConf = new ParserConfiguration(jax.parseOptions.options.textmacros.packages, ['tex', 'text']);
  101. textConf.init();
  102. const parseOptions = new ParseOptions(textConf, []);
  103. parseOptions.options = jax.parseOptions.options; // share the TeX options
  104. textConf.config(jax);
  105. TagsFactory.addTags(textConf.tags);
  106. parseOptions.tags = TagsFactory.getDefault();
  107. parseOptions.tags.configuration = parseOptions;
  108. //
  109. // Share the TeX input jax's parseOptions packageData object
  110. // so that require and other packages will work in both parsers,
  111. // set the textmacros data (texParser will be filled in later),
  112. // and replace the internalMath function with our own.
  113. //
  114. parseOptions.packageData = jax.parseOptions.packageData;
  115. parseOptions.packageData.set('textmacros', {parseOptions, jax, texParser: null});
  116. parseOptions.options.internalMath = internalMath;
  117. },
  118. preprocessors: [(data: {data: ParseOptions}) => {
  119. //
  120. // Set the MmlFactory for the nodeFactory, since it was not available
  121. // durring configuration above.
  122. //
  123. const config = data.data.packageData.get('textmacros');
  124. config.parseOptions.nodeFactory.setMmlFactory(config.jax.mmlFactory);
  125. }],
  126. options: {
  127. textmacros: {
  128. packages: ['text-base'] // textmacro packages to load
  129. }
  130. }
  131. });