temml 0.13.3 → 0.13.5

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.
package/dist/temml.js CHANGED
@@ -71,9 +71,17 @@ var temml = (function () {
71
71
  */
72
72
 
73
73
  /**
74
- * Provide a default value if a setting is undefined
74
+ * Look up `key` on a user-supplied `options` object and return its value, or
75
+ * `defaultIfUndefined` if the setting is absent. Reads via
76
+ * `Object.prototype.hasOwnProperty.call` rather than plain property access,
77
+ * so a key that only exists because `Object.prototype` was polluted
78
+ * elsewhere is never mistaken for a setting the caller actually provided.
75
79
  */
76
- const deflt = function(setting, defaultIfUndefined) {
80
+ const deflt = function(options, key, defaultIfUndefined) {
81
+ if (!Object.prototype.hasOwnProperty.call(options, key)) {
82
+ return defaultIfUndefined;
83
+ }
84
+ const setting = options[key];
77
85
  return setting === undefined ? defaultIfUndefined : setting;
78
86
  };
79
87
 
@@ -191,6 +199,27 @@ var temml = (function () {
191
199
  */
192
200
 
193
201
 
202
+ const FORBIDDEN_MACRO_KEYS = ["__proto__", "prototype", "constructor"];
203
+
204
+ // Sanitize a user-supplied macros object: strip its prototype (so later
205
+ // bracket-notation writes, e.g. from \gdef, can never reach Object.prototype)
206
+ // and delete any own key that could be used to pollute it. This mutates
207
+ // `macros` in place and returns the same reference, rather than a copy,
208
+ // because callers such as auto-render.js rely on that identity to share
209
+ // \gdef'd macros across multiple render calls that pass the same options
210
+ // object.
211
+ const sanitizeMacros = (macros) => {
212
+ if (macros == null || typeof macros !== "object") {
213
+ return Object.create(null);
214
+ }
215
+ for (const key of FORBIDDEN_MACRO_KEYS) {
216
+ if (Object.prototype.hasOwnProperty.call(macros, key)) {
217
+ delete macros[key];
218
+ }
219
+ }
220
+ return Object.setPrototypeOf(macros, null);
221
+ };
222
+
194
223
  /**
195
224
  * The main Settings object
196
225
  */
@@ -198,24 +227,29 @@ var temml = (function () {
198
227
  constructor(options) {
199
228
  // allow null options
200
229
  options = options || {};
201
- this.displayMode = deflt(options.displayMode, false); // boolean
202
- this.annotate = deflt(options.annotate, false); // boolean
203
- this.leqno = deflt(options.leqno, false); // boolean
204
- this.throwOnError = deflt(options.throwOnError, false); // boolean
205
- this.errorColor = deflt(options.errorColor, "#b22222"); // string
206
- this.macros = options.macros || {};
207
- this.wrap = deflt(options.wrap, "none"); // "none" | "tex" | "="
208
- this.xml = deflt(options.xml, false); // boolean
209
- this.colorIsTextColor = deflt(options.colorIsTextColor, false); // boolean
210
- this.strict = deflt(options.strict, false); // boolean
211
- this.trust = deflt(options.trust, false); // trust context. See html.js.
212
- this.maxSize = (options.maxSize === undefined
213
- ? [Infinity, Infinity]
214
- : Array.isArray(options.maxSize)
230
+ this.displayMode = deflt(options, "displayMode", false); // boolean
231
+ this.annotate = deflt(options, "annotate", false); // boolean
232
+ this.leqno = deflt(options, "leqno", false); // boolean
233
+ this.throwOnError = deflt(options, "throwOnError", false); // boolean
234
+ this.errorColor = deflt(options, "errorColor", "#b22222"); // string
235
+ this.macros = sanitizeMacros(
236
+ Object.prototype.hasOwnProperty.call(options, "macros") ? options.macros : undefined
237
+ );
238
+ this.wrap = deflt(options, "wrap", "none"); // "none" | "tex" | "="
239
+ this.xml = deflt(options, "xml", false); // boolean
240
+ this.colorIsTextColor = deflt(options, "colorIsTextColor", false); // boolean
241
+ this.strict = deflt(options, "strict", false); // boolean
242
+ this.trust = deflt(options, "trust", false); // trust context. See html.js.
243
+ const maxSize = Object.prototype.hasOwnProperty.call(options, "maxSize")
215
244
  ? options.maxSize
245
+ : undefined;
246
+ this.maxSize = (maxSize === undefined
247
+ ? [Infinity, Infinity]
248
+ : Array.isArray(maxSize)
249
+ ? maxSize
216
250
  : [Infinity, Infinity]
217
251
  );
218
- this.maxExpand = Math.max(0, deflt(options.maxExpand, 1000)); // number
252
+ this.maxExpand = Math.max(0, deflt(options, "maxExpand", 1000)); // number
219
253
  this.wrapDelimiterPairs = true; // boolean
220
254
  }
221
255
 
@@ -788,7 +822,7 @@ var temml = (function () {
788
822
  };
789
823
 
790
824
  const stretchyCodePoint = {
791
- widehat: "^",
825
+ widehat: "\u02c6", // Shorter than \u005e, which is appropriate for an accent.
792
826
  widecheck: "ˇ",
793
827
  widetilde: "~",
794
828
  wideparen: "⏜", // \u23dc
@@ -851,19 +885,30 @@ var temml = (function () {
851
885
  return node
852
886
  };
853
887
 
854
- const crookedWides = ["\\widetilde", "\\widehat", "\\widecheck", "\\utilde"];
888
+ const wideHats = ["\\widehat", "\\widecheck"];
855
889
 
856
- // TODO: Remove when Chromium stretches \widetilde & \widehat
890
+ // TODO: Remove if/when Chromium stretches \widetilde & \widehat
857
891
  const accentNode = (group) => {
858
892
  const mo = mathMLnode(group.label);
859
- if (crookedWides.includes(group.label)) {
893
+ if (group.label.indexOf("tilde") > -1) {
860
894
  const width = estimatedWidth(group.base);
861
895
  if (1 < width && width < 1.6) {
862
- mo.classes.push("tml-crooked-2");
896
+ mo.classes.push("tml-tilde-2");
863
897
  } else if (1.6 <= width && width < 2.5) {
864
- mo.classes.push("tml-crooked-3");
898
+ mo.classes.push("tml-tilde-3");
865
899
  } else if (2.5 <= width) {
866
- mo.classes.push("tml-crooked-4");
900
+ mo.classes.push("tml-tilde-4");
901
+ }
902
+ } else if (wideHats.includes(group.label)) {
903
+ const width = estimatedWidth(group.base);
904
+ if (0 < width && width <= 1) {
905
+ mo.classes.push("tml-hat-1");
906
+ } else if (1 < width && width < 1.6) {
907
+ mo.classes.push("tml-hat-2");
908
+ } else if (1.6 <= width && width < 2.5) {
909
+ mo.classes.push("tml-hat-3");
910
+ } else if (2.5 <= width) {
911
+ mo.classes.push("tml-hat-4");
867
912
  }
868
913
  }
869
914
  return mo
@@ -904,22 +949,26 @@ var temml = (function () {
904
949
  textord: 1
905
950
  };
906
951
 
907
- const symbols = {
908
- math: {},
909
- text: {}
910
- };
952
+ const symbols = Object.create(null);
953
+ symbols.math = Object.create(null);
954
+ symbols.text = Object.create(null);
911
955
 
912
- /** `acceptUnicodeChar = true` is only applicable if `replace` is set. */
913
956
  function defineSymbol(mode, group, replace, name, acceptUnicodeChar) {
914
- symbols[mode][name] = { group, replace };
957
+ if (mode !== "math" && mode !== "text") {
958
+ throw new TypeError(`Invalid mode: ${mode} called in defineSymbol`);
959
+ }
960
+
961
+ const entry = { group, replace };
962
+ symbols[mode][name] = entry;
915
963
 
964
+ /** `acceptUnicodeChar = true` is only applicable if `replace` is set. */
916
965
  if (acceptUnicodeChar && replace) {
917
- symbols[mode][replace] = symbols[mode][name];
966
+ symbols[mode][replace] = entry;
918
967
  }
919
968
  }
920
969
 
921
970
  // Some abbreviations for commonly used strings.
922
- // This helps minify the code, and also spotting typos using jshint.
971
+ // This helps minify the code, and also spotting typos via linter.
923
972
 
924
973
  // modes:
925
974
  const math = "math";
@@ -1772,7 +1821,7 @@ var temml = (function () {
1772
1821
  defineSymbol(math, accent, "\u203e", "\\bar");
1773
1822
  defineSymbol(math, accent, "\u02d8", "\\breve");
1774
1823
  defineSymbol(math, accent, "\u02c7", "\\check");
1775
- defineSymbol(math, accent, "\u005e", "\\hat");
1824
+ defineSymbol(math, accent, "\u02c6", "\\hat");
1776
1825
  defineSymbol(math, accent, "\u2192", "\\vec");
1777
1826
  defineSymbol(math, accent, "\u02d9", "\\dot");
1778
1827
  defineSymbol(math, accent, "\u02da", "\\mathring");
@@ -3549,7 +3598,7 @@ var temml = (function () {
3549
3598
  * `macros.js` exports this same dictionary again and makes it public.
3550
3599
  * `Parser.js` requires this dictionary via `macros.js`.
3551
3600
  */
3552
- const _macros = {};
3601
+ const _macros = Object.create(null);
3553
3602
 
3554
3603
  // This function might one day accept an additional argument and do more things.
3555
3604
  function defineMacro(name, body) {
@@ -10076,7 +10125,7 @@ var temml = (function () {
10076
10125
  * of initial (global-level) mappings, which will constantly change
10077
10126
  * according to any global/top-level `set`s done.
10078
10127
  */
10079
- constructor(builtins = {}, globalMacros = {}) {
10128
+ constructor(builtins = Object.create(null), globalMacros = Object.create(null)) {
10080
10129
  this.current = globalMacros;
10081
10130
  this.builtins = builtins;
10082
10131
  this.undefStack = [];
@@ -10086,7 +10135,7 @@ var temml = (function () {
10086
10135
  * Start a new nested group, affecting future local `set`s.
10087
10136
  */
10088
10137
  beginGroup() {
10089
- this.undefStack.push({});
10138
+ this.undefStack.push(Object.create(null));
10090
10139
  }
10091
10140
 
10092
10141
  /**
@@ -12284,7 +12333,7 @@ var temml = (function () {
12284
12333
  * https://mit-license.org/
12285
12334
  */
12286
12335
 
12287
- const version = "0.13.3";
12336
+ const version = "0.13.5";
12288
12337
 
12289
12338
  function postProcess(block) {
12290
12339
  const labelMap = {};
@@ -12605,7 +12654,7 @@ var temml = (function () {
12605
12654
 
12606
12655
  // Enable sharing of global macros defined via `\gdef` between different
12607
12656
  // math elements within a single call to `renderMathInElement`.
12608
- optionsCopy.macros = optionsCopy.macros || {};
12657
+ optionsCopy.macros = optionsCopy.macros || Object.create(null);
12609
12658
 
12610
12659
  renderElem(elem, optionsCopy);
12611
12660
  postProcess(elem);
@@ -12684,7 +12733,7 @@ var temml = (function () {
12684
12733
  */
12685
12734
  const definePreamble = function(expression, options) {
12686
12735
  const settings = new Settings(options);
12687
- settings.macros = {};
12736
+ settings.macros = Object.create(null);
12688
12737
  if (!(typeof expression === "string" || expression instanceof String)) {
12689
12738
  throw new TypeError("Temml can only parse string typed expression")
12690
12739
  }