SafeHandler.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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 MathItem, MathDocument, and Handler for the safe extension
  19. *
  20. * @author dpvc@mathjax.org (Davide Cervone)
  21. */
  22. import {MathItem} from '../../core/MathItem.js';
  23. import {MathDocument, MathDocumentConstructor} from '../../core/MathDocument.js';
  24. import {Handler} from '../../core/Handler.js';
  25. import {Safe} from './safe.js';
  26. /*==========================================================================*/
  27. /**
  28. * Generic constructor for Mixins
  29. */
  30. export type Constructor<T> = new(...args: any[]) => T;
  31. /*==========================================================================*/
  32. /**
  33. * The properties needed in the MathDocument for sanitizing the internal MathML
  34. */
  35. export interface SafeMathDocument<N, T, D> extends MathDocument<N, T, D> {
  36. /**
  37. * The Safe object for this document
  38. */
  39. safe: Safe<N, T, D>;
  40. }
  41. /**
  42. * The mixin for adding safe render action to MathDocuments
  43. *
  44. * @param {B} BaseDocument The MathDocument class to be extended
  45. * @return {SafeMathDocument<N,T,D>} The extended MathDocument class
  46. */
  47. export function SafeMathDocumentMixin<N, T, D, B extends MathDocumentConstructor<MathDocument<N, T, D>>>(
  48. BaseDocument: B
  49. ): Constructor<SafeMathDocument<N, T, D>> & B {
  50. return class extends BaseDocument {
  51. /**
  52. * @override
  53. */
  54. public static OPTIONS = {
  55. ...BaseDocument.OPTIONS,
  56. safeOptions: {
  57. ...Safe.OPTIONS,
  58. },
  59. SafeClass: Safe
  60. };
  61. /**
  62. * An instance of the Safe object
  63. */
  64. public safe: Safe<N, T, D>;
  65. /**
  66. * Extend the MathItem class used for this MathDocument
  67. *
  68. * @override
  69. * @constructor
  70. */
  71. constructor(...args: any[]) {
  72. super(...args);
  73. this.safe = new this.options.SafeClass(this, this.options.safeOptions);
  74. const ProcessBits = (this.constructor as typeof BaseDocument).ProcessBits;
  75. if (!ProcessBits.has('safe')) {
  76. ProcessBits.allocate('safe');
  77. }
  78. for (const jax of this.inputJax) {
  79. if (jax.name.match(/MathML/)) {
  80. (jax as any).mathml.filterAttribute = this.safe.mmlAttribute.bind(this.safe);
  81. (jax as any).mathml.filterClassList = this.safe.mmlClassList.bind(this.safe);
  82. } else if (jax.name.match(/TeX/)) {
  83. jax.postFilters.add(this.sanitize.bind(jax), -5.5);
  84. }
  85. }
  86. }
  87. /**
  88. * @param {{document:SafeDocument<N,T,D>}} data The document to use for the filter
  89. * (note: this has been bound to the input jax)
  90. */
  91. protected sanitize(data: {math: MathItem<N, T, D>, document: SafeMathDocument<N, T, D>}) {
  92. data.math.root = (this as any).parseOptions.root;
  93. data.document.safe.sanitize(data.math, data.document);
  94. }
  95. };
  96. }
  97. /*==========================================================================*/
  98. /**
  99. * Add context-menu support to a Handler instance
  100. *
  101. * @param {Handler} handler The Handler instance to enhance
  102. * @return {Handler} The handler that was modified (for purposes of chaining extensions)
  103. */
  104. export function SafeHandler<N, T, D>(handler: Handler<N, T, D>): Handler<N, T, D> {
  105. handler.documentClass = SafeMathDocumentMixin(handler.documentClass);
  106. return handler;
  107. }