three-text 0.4.0 → 0.4.2

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/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * three-text v0.4.0
2
+ * three-text v0.4.2
3
3
  * Copyright (C) 2025 Countertype LLC
4
4
  *
5
5
  * This program is free software: you can redistribute it and/or modify
@@ -181,8 +181,8 @@ const DEFAULT_EMERGENCY_STRETCH = 0;
181
181
  const SPACE_STRETCH_RATIO = 0.5; // stretch = 50% of space width (fontdimen 3 / fontdimen 2)
182
182
  const SPACE_SHRINK_RATIO = 1 / 3; // shrink = 33% of space width (fontdimen 4 / fontdimen 2)
183
183
 
184
- // Knuth-Plass line breaking algorithm with Liang hyphenation
185
- // References: tex.web (TeX), linebreak.c (LuaTeX), break.lua (SILE)
184
+ // Knuth-Plass line breaking with Liang hyphenation
185
+ // References: break.lua (SILE), tex.web (TeX), linebreak.c (LuaTeX), pTeX, xeCJK
186
186
  var ItemType;
187
187
  (function (ItemType) {
188
188
  ItemType[ItemType["BOX"] = 0] = "BOX";
@@ -198,7 +198,7 @@ var FitnessClass;
198
198
  FitnessClass[FitnessClass["DECENT"] = 2] = "DECENT";
199
199
  FitnessClass[FitnessClass["TIGHT"] = 3] = "TIGHT"; // lines shrinking 0.5 to 1.0 of their shrinkability
200
200
  })(FitnessClass || (FitnessClass = {}));
201
- // Active node management with Map for O(1) lookup by (position, fitness)
201
+ // Active node management with Map for lookup by (position, fitness)
202
202
  class ActiveNodeList {
203
203
  constructor() {
204
204
  this.nodesByKey = new Map();
@@ -218,6 +218,9 @@ class ActiveNodeList {
218
218
  existing.previous = node.previous;
219
219
  existing.hyphenated = node.hyphenated;
220
220
  existing.line = node.line;
221
+ existing.cumWidth = node.cumWidth;
222
+ existing.cumStretch = node.cumStretch;
223
+ existing.cumShrink = node.cumShrink;
221
224
  return true;
222
225
  }
223
226
  return false;
@@ -267,17 +270,24 @@ const EMERGENCY_STRETCH_INCREMENT = 0.1;
267
270
  class LineBreak {
268
271
  // TeX: badness function (tex.web lines 2337-2348)
269
272
  // Computes badness = 100 * (t/s)³ where t=adjustment, s=stretchability
273
+ // Simplified from TeX's fixed-point integer arithmetic to floating-point
274
+ //
275
+ // Returns INF_BAD+1 for overfull boxes so they're rejected even when
276
+ // threshold=INF_BAD in emergency pass
270
277
  static badness(t, s) {
271
278
  if (t === 0)
272
279
  return 0;
273
280
  if (s <= 0)
274
281
  return INF_BAD + 1;
275
- const r = Math.abs(t) / s;
282
+ const r = Math.abs(t / s);
276
283
  if (r > 10)
277
284
  return INF_BAD + 1;
278
- return Math.min(Math.round(100 * r * r * r), INF_BAD);
285
+ return Math.min(Math.round(100 * r ** 3), INF_BAD);
279
286
  }
280
- // TeX fitness classification (tex.web lines 16796-16812)
287
+ // TeX fitness classification (tex.web lines 16099-16105, 16799-16812)
288
+ // TeX uses badness thresholds 12 and 99, which correspond to ratios ~0.5 and ~1.0
289
+ // We use ratio directly since we compute it anyway. Well, and because SILE does
290
+ // it this way. Thanks Simon :)
281
291
  static fitnessClass(ratio) {
282
292
  if (ratio < -0.5)
283
293
  return FitnessClass.TIGHT; // shrinking significantly
@@ -287,27 +297,6 @@ class LineBreak {
287
297
  return FitnessClass.LOOSE; // stretching 0.5-1.0
288
298
  return FitnessClass.VERY_LOOSE; // stretching > 1.0
289
299
  }
290
- // Build prefix sums so we can quickly compute the width/stretch/shrink
291
- // of any range [a, b] as cumulative[b] - cumulative[a]
292
- static computeCumulativeWidths(items) {
293
- const n = items.length + 1;
294
- const width = new Float64Array(n);
295
- const stretch = new Float64Array(n);
296
- const shrink = new Float64Array(n);
297
- for (let i = 0; i < items.length; i++) {
298
- const item = items[i];
299
- width[i + 1] = width[i] + item.width;
300
- if (item.type === ItemType.GLUE) {
301
- stretch[i + 1] = stretch[i] + item.stretch;
302
- shrink[i + 1] = shrink[i] + item.shrink;
303
- }
304
- else {
305
- stretch[i + 1] = stretch[i];
306
- shrink[i + 1] = shrink[i];
307
- }
308
- }
309
- return { width, stretch, shrink };
310
- }
311
300
  static findHyphenationPoints(word, language = 'en-us', availablePatterns, lefthyphenmin = DEFAULT_LEFT_HYPHEN_MIN, righthyphenmin = DEFAULT_RIGHT_HYPHEN_MIN) {
312
301
  let patternTrie;
313
302
  if (availablePatterns && availablePatterns[language]) {
@@ -433,7 +422,7 @@ class LineBreak {
433
422
  );
434
423
  }
435
424
  static isCJPunctuation(char) {
436
- return this.isCJClosingPunctuation(char) || this.isCJOpeningPunctuation(char);
425
+ return (this.isCJClosingPunctuation(char) || this.isCJOpeningPunctuation(char));
437
426
  }
438
427
  static itemizeCJKText(text, measureText, measureTextWidths, context, startOffset = 0, glueParams) {
439
428
  const items = [];
@@ -456,7 +445,9 @@ class LineBreak {
456
445
  const char = chars[i];
457
446
  const nextChar = i < chars.length - 1 ? chars[i + 1] : null;
458
447
  if (/\s/.test(char)) {
459
- const width = widths ? (widths[i] ?? measureText(char)) : measureText(char);
448
+ const width = widths
449
+ ? (widths[i] ?? measureText(char))
450
+ : measureText(char);
460
451
  items.push({
461
452
  type: ItemType.GLUE,
462
453
  width,
@@ -499,11 +490,17 @@ class LineBreak {
499
490
  static itemizeParagraph(text, measureText, measureTextWidths, hyphenate, language, availablePatterns, lefthyphenmin, righthyphenmin, context, lineWidth) {
500
491
  const items = [];
501
492
  const chars = Array.from(text);
493
+ // Inter-character glue for CJK justification
494
+ // Matches pTeX's default \kanjiskip behavior
502
495
  let cjkGlueParams;
503
496
  const getCjkGlueParams = () => {
504
497
  if (!cjkGlueParams) {
505
498
  const baseCharWidth = measureText('字');
506
- cjkGlueParams = { width: 0, stretch: baseCharWidth * 0.04, shrink: baseCharWidth * 0.04 };
499
+ cjkGlueParams = {
500
+ width: 0,
501
+ stretch: baseCharWidth * 0.04,
502
+ shrink: baseCharWidth * 0.04
503
+ };
507
504
  }
508
505
  return cjkGlueParams;
509
506
  };
@@ -611,7 +608,9 @@ class LineBreak {
611
608
  }
612
609
  }
613
610
  }
614
- else if (hyphenate && segment.length >= lefthyphenmin + righthyphenmin && /^\p{L}+$/u.test(segment)) {
611
+ else if (hyphenate &&
612
+ segment.length >= lefthyphenmin + righthyphenmin &&
613
+ /^\p{L}+$/u.test(segment)) {
615
614
  const hyphenPoints = this.findHyphenationPoints(segment, language, availablePatterns, lefthyphenmin, righthyphenmin);
616
615
  if (hyphenPoints.length > 0) {
617
616
  let lastPoint = 0;
@@ -717,9 +716,8 @@ class LineBreak {
717
716
  // TeX: line_break inner loop (tex.web lines 16169-17256)
718
717
  // Finds optimal breakpoints using Knuth-Plass algorithm
719
718
  static lineBreak(items, lineWidth, threshold, emergencyStretch, context) {
720
- const cumulative = this.computeCumulativeWidths(items);
721
719
  const activeNodes = new ActiveNodeList();
722
- // Start node
720
+ // Start node with zero cumulative width
723
721
  activeNodes.insert({
724
722
  position: 0,
725
723
  line: 0,
@@ -728,17 +726,41 @@ class LineBreak {
728
726
  previous: null,
729
727
  hyphenated: false,
730
728
  active: true,
731
- activeIndex: 0
729
+ activeIndex: 0,
730
+ cumWidth: 0,
731
+ cumStretch: 0,
732
+ cumShrink: 0
732
733
  });
734
+ // Cumulative width from paragraph start, representing items[0..i-1]
735
+ let cumWidth = 0;
736
+ let cumStretch = 0;
737
+ let cumShrink = 0;
733
738
  // Process each item
734
739
  for (let i = 0; i < items.length; i++) {
735
740
  const item = items[i];
736
741
  // Check if this is a legal breakpoint
737
- const isBreakpoint = (item.type === ItemType.PENALTY && item.penalty < INFINITY_PENALTY) ||
738
- (item.type === ItemType.DISCRETIONARY) ||
739
- (item.type === ItemType.GLUE && i > 0 && items[i - 1].type === ItemType.BOX);
740
- if (!isBreakpoint)
742
+ const isBreakpoint = (item.type === ItemType.PENALTY &&
743
+ item.penalty < INFINITY_PENALTY) ||
744
+ item.type === ItemType.DISCRETIONARY ||
745
+ (item.type === ItemType.GLUE &&
746
+ i > 0 &&
747
+ items[i - 1].type === ItemType.BOX);
748
+ if (!isBreakpoint) {
749
+ // Accumulate width for non-breakpoint items
750
+ if (item.type === ItemType.BOX) {
751
+ cumWidth += item.width;
752
+ }
753
+ else if (item.type === ItemType.GLUE) {
754
+ const glue = item;
755
+ cumWidth += glue.width;
756
+ cumStretch += glue.stretch;
757
+ cumShrink += glue.shrink;
758
+ }
759
+ else if (item.type === ItemType.DISCRETIONARY) {
760
+ cumWidth += item.width;
761
+ }
741
762
  continue;
763
+ }
742
764
  // Get penalty and flagged status
743
765
  let pi = 0;
744
766
  let flagged = false;
@@ -760,23 +782,20 @@ class LineBreak {
760
782
  const bestDemerits = [Infinity, Infinity, Infinity, Infinity];
761
783
  // Nodes to deactivate
762
784
  const toDeactivate = [];
763
- // Current cumulative values at position i
764
- const curWidth = cumulative.width[i];
765
- const curStretch = cumulative.stretch[i];
766
- const curShrink = cumulative.shrink[i];
767
785
  // Try each active node as predecessor
768
786
  const active = activeNodes.getActive();
769
787
  for (let j = 0; j < active.length; j++) {
770
788
  const a = active[j];
771
- // Line width from a to i using cumulative arrays
772
- const lineW = curWidth - cumulative.width[a.position] + breakWidth;
773
- const lineStretch = curStretch - cumulative.stretch[a.position];
774
- const lineShrink = curShrink - cumulative.shrink[a.position];
789
+ // Line width from a to i
790
+ const lineW = cumWidth - a.cumWidth + breakWidth;
791
+ const lineStretch = cumStretch - a.cumStretch;
792
+ const lineShrink = cumShrink - a.cumShrink;
775
793
  const shortfall = lineWidth - lineW;
776
794
  let ratio;
777
795
  if (shortfall > 0) {
778
796
  const effectiveStretch = lineStretch + emergencyStretch;
779
- ratio = effectiveStretch > 0 ? shortfall / effectiveStretch : Infinity;
797
+ ratio =
798
+ effectiveStretch > 0 ? shortfall / effectiveStretch : Infinity;
780
799
  }
781
800
  else if (shortfall < 0) {
782
801
  ratio = lineShrink > 0 ? shortfall / lineShrink : -Infinity;
@@ -786,7 +805,7 @@ class LineBreak {
786
805
  }
787
806
  // Calculate badness
788
807
  const bad = this.badness(shortfall, shortfall > 0 ? lineStretch + emergencyStretch : lineShrink);
789
- // Check feasibility - THIS IS THE KEY FIX: compare bad vs threshold, not ratio
808
+ // Check feasibility
790
809
  if (ratio < -1) {
791
810
  toDeactivate.push(a);
792
811
  continue;
@@ -826,7 +845,10 @@ class LineBreak {
826
845
  previous: a,
827
846
  hyphenated: flagged,
828
847
  active: true,
829
- activeIndex: -1
848
+ activeIndex: -1,
849
+ cumWidth: cumWidth,
850
+ cumStretch: cumStretch,
851
+ cumShrink: cumShrink
830
852
  };
831
853
  }
832
854
  }
@@ -843,6 +865,19 @@ class LineBreak {
843
865
  if (activeNodes.size() === 0 && pi !== EJECT_PENALTY) {
844
866
  return null;
845
867
  }
868
+ // Accumulate width after evaluating this breakpoint
869
+ if (item.type === ItemType.BOX) {
870
+ cumWidth += item.width;
871
+ }
872
+ else if (item.type === ItemType.GLUE) {
873
+ const glue = item;
874
+ cumWidth += glue.width;
875
+ cumStretch += glue.stretch;
876
+ cumShrink += glue.shrink;
877
+ }
878
+ else if (item.type === ItemType.DISCRETIONARY) {
879
+ cumWidth += item.width;
880
+ }
846
881
  }
847
882
  // Find best solution
848
883
  let best = null;
@@ -906,7 +941,8 @@ class LineBreak {
906
941
  return allLines;
907
942
  }
908
943
  let useHyphenation = hyphenate;
909
- if (useHyphenation && (!hyphenationPatterns || !hyphenationPatterns[language])) {
944
+ if (useHyphenation &&
945
+ (!hyphenationPatterns || !hyphenationPatterns[language])) {
910
946
  logger.warn(`Hyphenation patterns for ${language} not available`);
911
947
  useHyphenation = false;
912
948
  }
@@ -928,7 +964,8 @@ class LineBreak {
928
964
  if (!width || width === Infinity) {
929
965
  const measuredWidth = measureText(text);
930
966
  perfLogger.end('LineBreak.breakText');
931
- return [{
967
+ return [
968
+ {
932
969
  text,
933
970
  originalStart: 0,
934
971
  originalEnd: text.length - 1,
@@ -936,7 +973,8 @@ class LineBreak {
936
973
  isLastLine: true,
937
974
  naturalWidth: measuredWidth,
938
975
  endedWithHyphen: false
939
- }];
976
+ }
977
+ ];
940
978
  }
941
979
  // First pass: without hyphenation
942
980
  let items = this.itemizeText(text, measureText, measureTextWidths, false, language, hyphenationPatterns, lefthyphenmin, righthyphenmin, context, width);
@@ -969,7 +1007,8 @@ class LineBreak {
969
1007
  return this.postLineBreak(text, items, breakpoints, width, align, direction, context);
970
1008
  }
971
1009
  perfLogger.end('LineBreak.breakText');
972
- return [{
1010
+ return [
1011
+ {
973
1012
  text,
974
1013
  originalStart: 0,
975
1014
  originalEnd: text.length - 1,
@@ -978,25 +1017,30 @@ class LineBreak {
978
1017
  isLastLine: true,
979
1018
  naturalWidth: measureText(text),
980
1019
  endedWithHyphen: false
981
- }];
1020
+ }
1021
+ ];
982
1022
  }
983
1023
  // TeX: post_line_break (tex.web lines 17260-17448)
984
1024
  // Creates the actual lines from the computed breakpoints
985
1025
  static postLineBreak(text, items, breakpoints, lineWidth, align, direction, context) {
986
1026
  if (breakpoints.length === 0) {
987
- return [{
1027
+ return [
1028
+ {
988
1029
  text,
989
1030
  originalStart: 0,
990
1031
  originalEnd: text.length - 1,
991
1032
  xOffset: 0
992
- }];
1033
+ }
1034
+ ];
993
1035
  }
994
1036
  const lines = [];
995
1037
  let lineStart = 0;
996
1038
  for (let i = 0; i < breakpoints.length; i++) {
997
1039
  const breakpoint = breakpoints[i];
998
1040
  const willHaveFinalLine = breakpoints[breakpoints.length - 1] + 1 < items.length - 1;
999
- const isLastLine = willHaveFinalLine ? false : i === breakpoints.length - 1;
1041
+ const isLastLine = willHaveFinalLine
1042
+ ? false
1043
+ : i === breakpoints.length - 1;
1000
1044
  const lineTextParts = [];
1001
1045
  let originalStart = -1;
1002
1046
  let originalEnd = -1;
@@ -1006,7 +1050,8 @@ class LineBreak {
1006
1050
  for (let j = lineStart; j < breakpoint; j++) {
1007
1051
  const item = items[j];
1008
1052
  if ((item.type === ItemType.PENALTY && !item.text) ||
1009
- (item.type === ItemType.DISCRETIONARY && !item.noBreak)) {
1053
+ (item.type === ItemType.DISCRETIONARY &&
1054
+ !item.noBreak)) {
1010
1055
  continue;
1011
1056
  }
1012
1057
  if (item.originIndex !== undefined) {
@@ -1034,7 +1079,8 @@ class LineBreak {
1034
1079
  const breakItem = items[breakpoint];
1035
1080
  let endedWithHyphen = false;
1036
1081
  if (breakpoint < items.length) {
1037
- if (breakItem.type === ItemType.PENALTY && breakItem.flagged) {
1082
+ if (breakItem.type === ItemType.PENALTY &&
1083
+ breakItem.flagged) {
1038
1084
  lineTextParts.push('-');
1039
1085
  naturalWidth += breakItem.width;
1040
1086
  endedWithHyphen = true;
@@ -1100,7 +1146,8 @@ class LineBreak {
1100
1146
  if (item.type === ItemType.PENALTY)
1101
1147
  continue;
1102
1148
  if (item.originIndex !== undefined) {
1103
- if (finalOriginalStart === -1 || item.originIndex < finalOriginalStart) {
1149
+ if (finalOriginalStart === -1 ||
1150
+ item.originIndex < finalOriginalStart) {
1104
1151
  finalOriginalStart = item.originIndex;
1105
1152
  }
1106
1153
  if (item.originIndex > finalOriginalEnd) {
@@ -4512,7 +4559,14 @@ class TextShaper {
4512
4559
 
4513
4560
  var hb = {exports: {}};
4514
4561
 
4515
- var fs = {}; const readFileSync = () => { throw new Error('fs not available in browser'); };
4562
+ var fs = {};
4563
+ const readFileSync = (...args) => {
4564
+ const req = typeof globalThis !== 'undefined' ? globalThis.require : undefined;
4565
+ if (typeof req === 'function') {
4566
+ return req('fs').readFileSync(...args);
4567
+ }
4568
+ throw new Error('fs not available in this environment');
4569
+ };
4516
4570
 
4517
4571
  var fs$1 = /*#__PURE__*/Object.freeze({
4518
4572
  __proto__: null,
@@ -4523,7 +4577,7 @@ var fs$1 = /*#__PURE__*/Object.freeze({
4523
4577
  var require$$0 = /*@__PURE__*/getAugmentedNamespace(fs$1);
4524
4578
 
4525
4579
  (function (module, exports) {
4526
- var createHarfBuzz=(()=>{var _scriptName=typeof document!="undefined"?document.currentScript?.src:undefined;return async function(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof WorkerGlobalScope!="undefined";var ENVIRONMENT_IS_NODE=typeof process=="object"&&process.versions?.node&&process.type!="renderer";var quit_=(status,toThrow)=>{throw toThrow};if(typeof __filename!="undefined"){_scriptName=__filename;}else if(ENVIRONMENT_IS_WORKER){_scriptName=self.location.href;}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require$$0;scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){process.argv[1].replace(/\\/g,"/");}process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow};}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href;}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status);};xhr.onerror=reject;xhr.send(null);})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)};}}else;console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;var isFileURI=filename=>filename.startsWith("file://");var readyPromiseResolve,readyPromiseReject;var wasmMemory;var HEAPU8;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=new Int8Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAP32"]=new Int32Array(b);Module["HEAPU32"]=new Uint32Array(b);Module["HEAPF32"]=new Float32Array(b);new BigInt64Array(b);new BigUint64Array(b);}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(onPreRuns);}function initRuntime(){runtimeInitialized=true;wasmExports["__wasm_call_ctors"]();}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(onPostRuns);}var runDependencies=0;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies);}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("hb.wasm")}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw "both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason);}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){return {env:wasmImports,wasi_snapshot_preview1:wasmImports}}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;Module["wasmExports"]=wasmExports;wasmMemory=wasmExports["memory"];Module["wasmMemory"]=wasmMemory;updateMemoryViews();wasmTable=wasmExports["__indirect_function_table"];assignWasmExports(wasmExports);removeRunDependency();return wasmExports}addRunDependency();function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(mod,inst)=>{resolve(receiveInstance(mod));});})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status;}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module);}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var __abort_js=()=>abort("");var runtimeKeepaliveCounter=0;var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0;};var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e);};var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true;}quit_(code,new ExitStatus(code));};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status);};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS);}catch(e){handleException(e);}}};var callUserCallback=func=>{if(ABORT){return}try{func();maybeExit();}catch(e){handleException(e);}};var _emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which];}if(!timeout_ms)return 0;var id=setTimeout(()=>{delete timers[which];callUserCallback(()=>__emscripten_timeout(which,_emscripten_get_now()));},timeout_ms);timers[which]={id,timeout_ms};return 0};var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var uleb128EncodeWithLen=arr=>{const n=arr.length;return [n%128|128,n>>7,...arr]};var wasmTypeCodes={i:127,p:127,j:126,f:125,d:124,e:111};var generateTypePack=types=>uleb128EncodeWithLen(Array.from(types,type=>{var code=wasmTypeCodes[type];return code}));var convertJsFunctionToWasm=(func,sig)=>{var bytes=Uint8Array.of(0,97,115,109,1,0,0,0,1,...uleb128EncodeWithLen([1,96,...generateTypePack(sig.slice(1)),...generateTypePack(sig[0]==="v"?"":sig[0])]),2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0);var module=new WebAssembly.Module(bytes);var instance=new WebAssembly.Instance(module,{e:{f:func}});var wrappedFunc=instance.exports["f"];return wrappedFunc};var wasmTable;var getWasmTableEntry=funcPtr=>wasmTable.get(funcPtr);var updateTableMap=(offset,count)=>{if(functionsInTableMap){for(var i=offset;i<offset+count;i++){var item=getWasmTableEntry(i);if(item){functionsInTableMap.set(item,i);}}}};var functionsInTableMap;var getFunctionAddress=func=>{if(!functionsInTableMap){functionsInTableMap=new WeakMap;updateTableMap(0,wasmTable.length);}return functionsInTableMap.get(func)||0};var freeTableIndexes=[];var getEmptyTableSlot=()=>{if(freeTableIndexes.length){return freeTableIndexes.pop()}return wasmTable["grow"](1)};var setWasmTableEntry=(idx,func)=>wasmTable.set(idx,func);var addFunction=(func,sig)=>{var rtn=getFunctionAddress(func);if(rtn){return rtn}var ret=getEmptyTableSlot();try{setWasmTableEntry(ret,func);}catch(err){if(!(err instanceof TypeError)){throw err}var wrapped=convertJsFunctionToWasm(func,sig);setWasmTableEntry(ret,wrapped);}functionsInTableMap.set(func,ret);return ret};var removeFunction=index=>{functionsInTableMap.delete(getWasmTableEntry(index));setWasmTableEntry(index,null);freeTableIndexes.push(index);};{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])Module["arguments"];if(Module["thisProgram"])Module["thisProgram"];}Module["wasmMemory"]=wasmMemory;Module["wasmExports"]=wasmExports;Module["addFunction"]=addFunction;Module["removeFunction"]=removeFunction;var __emscripten_timeout;function assignWasmExports(wasmExports){Module["_hb_blob_create"]=wasmExports["hb_blob_create"];Module["_hb_blob_destroy"]=wasmExports["hb_blob_destroy"];Module["_hb_blob_get_length"]=wasmExports["hb_blob_get_length"];Module["_hb_blob_get_data"]=wasmExports["hb_blob_get_data"];Module["_hb_buffer_serialize_glyphs"]=wasmExports["hb_buffer_serialize_glyphs"];Module["_hb_buffer_create"]=wasmExports["hb_buffer_create"];Module["_hb_buffer_destroy"]=wasmExports["hb_buffer_destroy"];Module["_hb_buffer_get_content_type"]=wasmExports["hb_buffer_get_content_type"];Module["_hb_buffer_set_direction"]=wasmExports["hb_buffer_set_direction"];Module["_hb_buffer_set_script"]=wasmExports["hb_buffer_set_script"];Module["_hb_buffer_set_language"]=wasmExports["hb_buffer_set_language"];Module["_hb_buffer_set_flags"]=wasmExports["hb_buffer_set_flags"];Module["_hb_buffer_set_cluster_level"]=wasmExports["hb_buffer_set_cluster_level"];Module["_hb_buffer_get_length"]=wasmExports["hb_buffer_get_length"];Module["_hb_buffer_get_glyph_infos"]=wasmExports["hb_buffer_get_glyph_infos"];Module["_hb_buffer_get_glyph_positions"]=wasmExports["hb_buffer_get_glyph_positions"];Module["_hb_glyph_info_get_glyph_flags"]=wasmExports["hb_glyph_info_get_glyph_flags"];Module["_hb_buffer_guess_segment_properties"]=wasmExports["hb_buffer_guess_segment_properties"];Module["_hb_buffer_add_utf8"]=wasmExports["hb_buffer_add_utf8"];Module["_hb_buffer_add_utf16"]=wasmExports["hb_buffer_add_utf16"];Module["_hb_buffer_set_message_func"]=wasmExports["hb_buffer_set_message_func"];Module["_hb_language_from_string"]=wasmExports["hb_language_from_string"];Module["_hb_script_from_string"]=wasmExports["hb_script_from_string"];Module["_hb_version"]=wasmExports["hb_version"];Module["_hb_version_string"]=wasmExports["hb_version_string"];Module["_hb_feature_from_string"]=wasmExports["hb_feature_from_string"];Module["_malloc"]=wasmExports["malloc"];Module["_free"]=wasmExports["free"];Module["_hb_draw_funcs_set_move_to_func"]=wasmExports["hb_draw_funcs_set_move_to_func"];Module["_hb_draw_funcs_set_line_to_func"]=wasmExports["hb_draw_funcs_set_line_to_func"];Module["_hb_draw_funcs_set_quadratic_to_func"]=wasmExports["hb_draw_funcs_set_quadratic_to_func"];Module["_hb_draw_funcs_set_cubic_to_func"]=wasmExports["hb_draw_funcs_set_cubic_to_func"];Module["_hb_draw_funcs_set_close_path_func"]=wasmExports["hb_draw_funcs_set_close_path_func"];Module["_hb_draw_funcs_create"]=wasmExports["hb_draw_funcs_create"];Module["_hb_draw_funcs_destroy"]=wasmExports["hb_draw_funcs_destroy"];Module["_hb_face_create"]=wasmExports["hb_face_create"];Module["_hb_face_destroy"]=wasmExports["hb_face_destroy"];Module["_hb_face_reference_table"]=wasmExports["hb_face_reference_table"];Module["_hb_face_get_upem"]=wasmExports["hb_face_get_upem"];Module["_hb_face_collect_unicodes"]=wasmExports["hb_face_collect_unicodes"];Module["_hb_font_draw_glyph"]=wasmExports["hb_font_draw_glyph"];Module["_hb_font_glyph_to_string"]=wasmExports["hb_font_glyph_to_string"];Module["_hb_font_create"]=wasmExports["hb_font_create"];Module["_hb_font_set_variations"]=wasmExports["hb_font_set_variations"];Module["_hb_font_destroy"]=wasmExports["hb_font_destroy"];Module["_hb_font_set_scale"]=wasmExports["hb_font_set_scale"];Module["_hb_set_create"]=wasmExports["hb_set_create"];Module["_hb_set_destroy"]=wasmExports["hb_set_destroy"];Module["_hb_ot_var_get_axis_infos"]=wasmExports["hb_ot_var_get_axis_infos"];Module["_hb_set_get_population"]=wasmExports["hb_set_get_population"];Module["_hb_set_next_many"]=wasmExports["hb_set_next_many"];Module["_hb_shape"]=wasmExports["hb_shape"];__emscripten_timeout=wasmExports["_emscripten_timeout"];}var wasmImports={_abort_js:__abort_js,_emscripten_runtime_keepalive_clear:__emscripten_runtime_keepalive_clear,_setitimer_js:__setitimer_js,emscripten_resize_heap:_emscripten_resize_heap,proc_exit:_proc_exit};var wasmExports=await createWasm();function run(){if(runDependencies>0){dependenciesFulfilled=run;return}preRun();if(runDependencies>0){dependenciesFulfilled=run;return}function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun();},1);}else {doRun();}}function preInit(){if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()();}}}preInit();run();if(runtimeInitialized){moduleRtn=Module;}else {moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject;});}
4580
+ var createHarfBuzz=(()=>{var _scriptName=typeof document!="undefined"?document.currentScript?.src:undefined;return async function(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof WorkerGlobalScope!="undefined";var ENVIRONMENT_IS_NODE=typeof process=="object"&&process.versions?.node&&process.type!="renderer";var quit_=(status,toThrow)=>{throw toThrow};if(typeof __filename!="undefined"){_scriptName=__filename;}else if(ENVIRONMENT_IS_WORKER){_scriptName=self.location.href;}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require$$0;scriptDirectory=(typeof __dirname!=="undefined"?__dirname+"/":"");readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){process.argv[1].replace(/\\/g,"/");}process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow};}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href;}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status);};xhr.onerror=reject;xhr.send(null);})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)};}}else;console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;var isFileURI=filename=>filename.startsWith("file://");var readyPromiseResolve,readyPromiseReject;var wasmMemory;var HEAPU8;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=new Int8Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAP32"]=new Int32Array(b);Module["HEAPU32"]=new Uint32Array(b);Module["HEAPF32"]=new Float32Array(b);new BigInt64Array(b);new BigUint64Array(b);}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(onPreRuns);}function initRuntime(){runtimeInitialized=true;wasmExports["__wasm_call_ctors"]();}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(onPostRuns);}var runDependencies=0;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies);}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("hb.wasm")}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw "both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason);}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){return {env:wasmImports,wasi_snapshot_preview1:wasmImports}}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;Module["wasmExports"]=wasmExports;wasmMemory=wasmExports["memory"];Module["wasmMemory"]=wasmMemory;updateMemoryViews();wasmTable=wasmExports["__indirect_function_table"];assignWasmExports(wasmExports);removeRunDependency();return wasmExports}addRunDependency();function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(mod,inst)=>{resolve(receiveInstance(mod));});})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status;}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module);}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var __abort_js=()=>abort("");var runtimeKeepaliveCounter=0;var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0;};var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e);};var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true;}quit_(code,new ExitStatus(code));};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status);};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS);}catch(e){handleException(e);}}};var callUserCallback=func=>{if(ABORT){return}try{func();maybeExit();}catch(e){handleException(e);}};var _emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which];}if(!timeout_ms)return 0;var id=setTimeout(()=>{delete timers[which];callUserCallback(()=>__emscripten_timeout(which,_emscripten_get_now()));},timeout_ms);timers[which]={id,timeout_ms};return 0};var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var uleb128EncodeWithLen=arr=>{const n=arr.length;return [n%128|128,n>>7,...arr]};var wasmTypeCodes={i:127,p:127,j:126,f:125,d:124,e:111};var generateTypePack=types=>uleb128EncodeWithLen(Array.from(types,type=>{var code=wasmTypeCodes[type];return code}));var convertJsFunctionToWasm=(func,sig)=>{var bytes=Uint8Array.of(0,97,115,109,1,0,0,0,1,...uleb128EncodeWithLen([1,96,...generateTypePack(sig.slice(1)),...generateTypePack(sig[0]==="v"?"":sig[0])]),2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0);var module=new WebAssembly.Module(bytes);var instance=new WebAssembly.Instance(module,{e:{f:func}});var wrappedFunc=instance.exports["f"];return wrappedFunc};var wasmTable;var getWasmTableEntry=funcPtr=>wasmTable.get(funcPtr);var updateTableMap=(offset,count)=>{if(functionsInTableMap){for(var i=offset;i<offset+count;i++){var item=getWasmTableEntry(i);if(item){functionsInTableMap.set(item,i);}}}};var functionsInTableMap;var getFunctionAddress=func=>{if(!functionsInTableMap){functionsInTableMap=new WeakMap;updateTableMap(0,wasmTable.length);}return functionsInTableMap.get(func)||0};var freeTableIndexes=[];var getEmptyTableSlot=()=>{if(freeTableIndexes.length){return freeTableIndexes.pop()}return wasmTable["grow"](1)};var setWasmTableEntry=(idx,func)=>wasmTable.set(idx,func);var addFunction=(func,sig)=>{var rtn=getFunctionAddress(func);if(rtn){return rtn}var ret=getEmptyTableSlot();try{setWasmTableEntry(ret,func);}catch(err){if(!(err instanceof TypeError)){throw err}var wrapped=convertJsFunctionToWasm(func,sig);setWasmTableEntry(ret,wrapped);}functionsInTableMap.set(func,ret);return ret};var removeFunction=index=>{functionsInTableMap.delete(getWasmTableEntry(index));setWasmTableEntry(index,null);freeTableIndexes.push(index);};{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])Module["arguments"];if(Module["thisProgram"])Module["thisProgram"];}Module["wasmMemory"]=wasmMemory;Module["wasmExports"]=wasmExports;Module["addFunction"]=addFunction;Module["removeFunction"]=removeFunction;var __emscripten_timeout;function assignWasmExports(wasmExports){Module["_hb_blob_create"]=wasmExports["hb_blob_create"];Module["_hb_blob_destroy"]=wasmExports["hb_blob_destroy"];Module["_hb_blob_get_length"]=wasmExports["hb_blob_get_length"];Module["_hb_blob_get_data"]=wasmExports["hb_blob_get_data"];Module["_hb_buffer_serialize_glyphs"]=wasmExports["hb_buffer_serialize_glyphs"];Module["_hb_buffer_create"]=wasmExports["hb_buffer_create"];Module["_hb_buffer_destroy"]=wasmExports["hb_buffer_destroy"];Module["_hb_buffer_get_content_type"]=wasmExports["hb_buffer_get_content_type"];Module["_hb_buffer_set_direction"]=wasmExports["hb_buffer_set_direction"];Module["_hb_buffer_set_script"]=wasmExports["hb_buffer_set_script"];Module["_hb_buffer_set_language"]=wasmExports["hb_buffer_set_language"];Module["_hb_buffer_set_flags"]=wasmExports["hb_buffer_set_flags"];Module["_hb_buffer_set_cluster_level"]=wasmExports["hb_buffer_set_cluster_level"];Module["_hb_buffer_get_length"]=wasmExports["hb_buffer_get_length"];Module["_hb_buffer_get_glyph_infos"]=wasmExports["hb_buffer_get_glyph_infos"];Module["_hb_buffer_get_glyph_positions"]=wasmExports["hb_buffer_get_glyph_positions"];Module["_hb_glyph_info_get_glyph_flags"]=wasmExports["hb_glyph_info_get_glyph_flags"];Module["_hb_buffer_guess_segment_properties"]=wasmExports["hb_buffer_guess_segment_properties"];Module["_hb_buffer_add_utf8"]=wasmExports["hb_buffer_add_utf8"];Module["_hb_buffer_add_utf16"]=wasmExports["hb_buffer_add_utf16"];Module["_hb_buffer_set_message_func"]=wasmExports["hb_buffer_set_message_func"];Module["_hb_language_from_string"]=wasmExports["hb_language_from_string"];Module["_hb_script_from_string"]=wasmExports["hb_script_from_string"];Module["_hb_version"]=wasmExports["hb_version"];Module["_hb_version_string"]=wasmExports["hb_version_string"];Module["_hb_feature_from_string"]=wasmExports["hb_feature_from_string"];Module["_malloc"]=wasmExports["malloc"];Module["_free"]=wasmExports["free"];Module["_hb_draw_funcs_set_move_to_func"]=wasmExports["hb_draw_funcs_set_move_to_func"];Module["_hb_draw_funcs_set_line_to_func"]=wasmExports["hb_draw_funcs_set_line_to_func"];Module["_hb_draw_funcs_set_quadratic_to_func"]=wasmExports["hb_draw_funcs_set_quadratic_to_func"];Module["_hb_draw_funcs_set_cubic_to_func"]=wasmExports["hb_draw_funcs_set_cubic_to_func"];Module["_hb_draw_funcs_set_close_path_func"]=wasmExports["hb_draw_funcs_set_close_path_func"];Module["_hb_draw_funcs_create"]=wasmExports["hb_draw_funcs_create"];Module["_hb_draw_funcs_destroy"]=wasmExports["hb_draw_funcs_destroy"];Module["_hb_face_create"]=wasmExports["hb_face_create"];Module["_hb_face_destroy"]=wasmExports["hb_face_destroy"];Module["_hb_face_reference_table"]=wasmExports["hb_face_reference_table"];Module["_hb_face_get_upem"]=wasmExports["hb_face_get_upem"];Module["_hb_face_collect_unicodes"]=wasmExports["hb_face_collect_unicodes"];Module["_hb_font_draw_glyph"]=wasmExports["hb_font_draw_glyph"];Module["_hb_font_glyph_to_string"]=wasmExports["hb_font_glyph_to_string"];Module["_hb_font_create"]=wasmExports["hb_font_create"];Module["_hb_font_set_variations"]=wasmExports["hb_font_set_variations"];Module["_hb_font_destroy"]=wasmExports["hb_font_destroy"];Module["_hb_font_set_scale"]=wasmExports["hb_font_set_scale"];Module["_hb_set_create"]=wasmExports["hb_set_create"];Module["_hb_set_destroy"]=wasmExports["hb_set_destroy"];Module["_hb_ot_var_get_axis_infos"]=wasmExports["hb_ot_var_get_axis_infos"];Module["_hb_set_get_population"]=wasmExports["hb_set_get_population"];Module["_hb_set_next_many"]=wasmExports["hb_set_next_many"];Module["_hb_shape"]=wasmExports["hb_shape"];__emscripten_timeout=wasmExports["_emscripten_timeout"];}var wasmImports={_abort_js:__abort_js,_emscripten_runtime_keepalive_clear:__emscripten_runtime_keepalive_clear,_setitimer_js:__setitimer_js,emscripten_resize_heap:_emscripten_resize_heap,proc_exit:_proc_exit};var wasmExports=await createWasm();function run(){if(runDependencies>0){dependenciesFulfilled=run;return}preRun();if(runDependencies>0){dependenciesFulfilled=run;return}function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun();},1);}else {doRun();}}function preInit(){if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()();}}}preInit();run();if(runtimeInitialized){moduleRtn=Module;}else {moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject;});}
4527
4581
  return moduleRtn}})();{module.exports=createHarfBuzz;module.exports.default=createHarfBuzz;}
4528
4582
  } (hb));
4529
4583
 
@@ -5507,7 +5561,11 @@ class Text {
5507
5561
  for (const pattern of Object.keys(options.color.byText)) {
5508
5562
  let index = 0;
5509
5563
  while ((index = options.text.indexOf(pattern, index)) !== -1) {
5510
- byTextMatches.push({ pattern, start: index, end: index + pattern.length });
5564
+ byTextMatches.push({
5565
+ pattern,
5566
+ start: index,
5567
+ end: index + pattern.length
5568
+ });
5511
5569
  for (let i = index; i < index + pattern.length; i++) {
5512
5570
  coloredTextIndices.add(i);
5513
5571
  }