three-text 0.4.0 → 0.4.1

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.1
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();
@@ -267,17 +267,24 @@ const EMERGENCY_STRETCH_INCREMENT = 0.1;
267
267
  class LineBreak {
268
268
  // TeX: badness function (tex.web lines 2337-2348)
269
269
  // Computes badness = 100 * (t/s)³ where t=adjustment, s=stretchability
270
+ // Simplified from TeX's fixed-point integer arithmetic to floating-point
271
+ //
272
+ // Returns INF_BAD+1 for overfull boxes so they're rejected even when
273
+ // threshold=INF_BAD in emergency pass
270
274
  static badness(t, s) {
271
275
  if (t === 0)
272
276
  return 0;
273
277
  if (s <= 0)
274
278
  return INF_BAD + 1;
275
- const r = Math.abs(t) / s;
279
+ const r = Math.abs(t / s);
276
280
  if (r > 10)
277
281
  return INF_BAD + 1;
278
- return Math.min(Math.round(100 * r * r * r), INF_BAD);
282
+ return Math.min(Math.round(100 * r ** 3), INF_BAD);
279
283
  }
280
- // TeX fitness classification (tex.web lines 16796-16812)
284
+ // TeX fitness classification (tex.web lines 16099-16105, 16799-16812)
285
+ // TeX uses badness thresholds 12 and 99, which correspond to ratios ~0.5 and ~1.0
286
+ // We use ratio directly since we compute it anyway. Well, and because SILE does
287
+ // it this way. Thanks Simon :)
281
288
  static fitnessClass(ratio) {
282
289
  if (ratio < -0.5)
283
290
  return FitnessClass.TIGHT; // shrinking significantly
@@ -433,7 +440,7 @@ class LineBreak {
433
440
  );
434
441
  }
435
442
  static isCJPunctuation(char) {
436
- return this.isCJClosingPunctuation(char) || this.isCJOpeningPunctuation(char);
443
+ return (this.isCJClosingPunctuation(char) || this.isCJOpeningPunctuation(char));
437
444
  }
438
445
  static itemizeCJKText(text, measureText, measureTextWidths, context, startOffset = 0, glueParams) {
439
446
  const items = [];
@@ -456,7 +463,9 @@ class LineBreak {
456
463
  const char = chars[i];
457
464
  const nextChar = i < chars.length - 1 ? chars[i + 1] : null;
458
465
  if (/\s/.test(char)) {
459
- const width = widths ? (widths[i] ?? measureText(char)) : measureText(char);
466
+ const width = widths
467
+ ? (widths[i] ?? measureText(char))
468
+ : measureText(char);
460
469
  items.push({
461
470
  type: ItemType.GLUE,
462
471
  width,
@@ -499,11 +508,17 @@ class LineBreak {
499
508
  static itemizeParagraph(text, measureText, measureTextWidths, hyphenate, language, availablePatterns, lefthyphenmin, righthyphenmin, context, lineWidth) {
500
509
  const items = [];
501
510
  const chars = Array.from(text);
511
+ // Inter-character glue for CJK justification
512
+ // Matches pTeX's default \kanjiskip behavior
502
513
  let cjkGlueParams;
503
514
  const getCjkGlueParams = () => {
504
515
  if (!cjkGlueParams) {
505
516
  const baseCharWidth = measureText('字');
506
- cjkGlueParams = { width: 0, stretch: baseCharWidth * 0.04, shrink: baseCharWidth * 0.04 };
517
+ cjkGlueParams = {
518
+ width: 0,
519
+ stretch: baseCharWidth * 0.04,
520
+ shrink: baseCharWidth * 0.04
521
+ };
507
522
  }
508
523
  return cjkGlueParams;
509
524
  };
@@ -611,7 +626,9 @@ class LineBreak {
611
626
  }
612
627
  }
613
628
  }
614
- else if (hyphenate && segment.length >= lefthyphenmin + righthyphenmin && /^\p{L}+$/u.test(segment)) {
629
+ else if (hyphenate &&
630
+ segment.length >= lefthyphenmin + righthyphenmin &&
631
+ /^\p{L}+$/u.test(segment)) {
615
632
  const hyphenPoints = this.findHyphenationPoints(segment, language, availablePatterns, lefthyphenmin, righthyphenmin);
616
633
  if (hyphenPoints.length > 0) {
617
634
  let lastPoint = 0;
@@ -734,9 +751,12 @@ class LineBreak {
734
751
  for (let i = 0; i < items.length; i++) {
735
752
  const item = items[i];
736
753
  // 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);
754
+ const isBreakpoint = (item.type === ItemType.PENALTY &&
755
+ item.penalty < INFINITY_PENALTY) ||
756
+ item.type === ItemType.DISCRETIONARY ||
757
+ (item.type === ItemType.GLUE &&
758
+ i > 0 &&
759
+ items[i - 1].type === ItemType.BOX);
740
760
  if (!isBreakpoint)
741
761
  continue;
742
762
  // Get penalty and flagged status
@@ -776,7 +796,8 @@ class LineBreak {
776
796
  let ratio;
777
797
  if (shortfall > 0) {
778
798
  const effectiveStretch = lineStretch + emergencyStretch;
779
- ratio = effectiveStretch > 0 ? shortfall / effectiveStretch : Infinity;
799
+ ratio =
800
+ effectiveStretch > 0 ? shortfall / effectiveStretch : Infinity;
780
801
  }
781
802
  else if (shortfall < 0) {
782
803
  ratio = lineShrink > 0 ? shortfall / lineShrink : -Infinity;
@@ -786,7 +807,7 @@ class LineBreak {
786
807
  }
787
808
  // Calculate badness
788
809
  const bad = this.badness(shortfall, shortfall > 0 ? lineStretch + emergencyStretch : lineShrink);
789
- // Check feasibility - THIS IS THE KEY FIX: compare bad vs threshold, not ratio
810
+ // Check feasibility
790
811
  if (ratio < -1) {
791
812
  toDeactivate.push(a);
792
813
  continue;
@@ -906,7 +927,8 @@ class LineBreak {
906
927
  return allLines;
907
928
  }
908
929
  let useHyphenation = hyphenate;
909
- if (useHyphenation && (!hyphenationPatterns || !hyphenationPatterns[language])) {
930
+ if (useHyphenation &&
931
+ (!hyphenationPatterns || !hyphenationPatterns[language])) {
910
932
  logger.warn(`Hyphenation patterns for ${language} not available`);
911
933
  useHyphenation = false;
912
934
  }
@@ -928,7 +950,8 @@ class LineBreak {
928
950
  if (!width || width === Infinity) {
929
951
  const measuredWidth = measureText(text);
930
952
  perfLogger.end('LineBreak.breakText');
931
- return [{
953
+ return [
954
+ {
932
955
  text,
933
956
  originalStart: 0,
934
957
  originalEnd: text.length - 1,
@@ -936,7 +959,8 @@ class LineBreak {
936
959
  isLastLine: true,
937
960
  naturalWidth: measuredWidth,
938
961
  endedWithHyphen: false
939
- }];
962
+ }
963
+ ];
940
964
  }
941
965
  // First pass: without hyphenation
942
966
  let items = this.itemizeText(text, measureText, measureTextWidths, false, language, hyphenationPatterns, lefthyphenmin, righthyphenmin, context, width);
@@ -969,7 +993,8 @@ class LineBreak {
969
993
  return this.postLineBreak(text, items, breakpoints, width, align, direction, context);
970
994
  }
971
995
  perfLogger.end('LineBreak.breakText');
972
- return [{
996
+ return [
997
+ {
973
998
  text,
974
999
  originalStart: 0,
975
1000
  originalEnd: text.length - 1,
@@ -978,25 +1003,30 @@ class LineBreak {
978
1003
  isLastLine: true,
979
1004
  naturalWidth: measureText(text),
980
1005
  endedWithHyphen: false
981
- }];
1006
+ }
1007
+ ];
982
1008
  }
983
1009
  // TeX: post_line_break (tex.web lines 17260-17448)
984
1010
  // Creates the actual lines from the computed breakpoints
985
1011
  static postLineBreak(text, items, breakpoints, lineWidth, align, direction, context) {
986
1012
  if (breakpoints.length === 0) {
987
- return [{
1013
+ return [
1014
+ {
988
1015
  text,
989
1016
  originalStart: 0,
990
1017
  originalEnd: text.length - 1,
991
1018
  xOffset: 0
992
- }];
1019
+ }
1020
+ ];
993
1021
  }
994
1022
  const lines = [];
995
1023
  let lineStart = 0;
996
1024
  for (let i = 0; i < breakpoints.length; i++) {
997
1025
  const breakpoint = breakpoints[i];
998
1026
  const willHaveFinalLine = breakpoints[breakpoints.length - 1] + 1 < items.length - 1;
999
- const isLastLine = willHaveFinalLine ? false : i === breakpoints.length - 1;
1027
+ const isLastLine = willHaveFinalLine
1028
+ ? false
1029
+ : i === breakpoints.length - 1;
1000
1030
  const lineTextParts = [];
1001
1031
  let originalStart = -1;
1002
1032
  let originalEnd = -1;
@@ -1006,7 +1036,8 @@ class LineBreak {
1006
1036
  for (let j = lineStart; j < breakpoint; j++) {
1007
1037
  const item = items[j];
1008
1038
  if ((item.type === ItemType.PENALTY && !item.text) ||
1009
- (item.type === ItemType.DISCRETIONARY && !item.noBreak)) {
1039
+ (item.type === ItemType.DISCRETIONARY &&
1040
+ !item.noBreak)) {
1010
1041
  continue;
1011
1042
  }
1012
1043
  if (item.originIndex !== undefined) {
@@ -1034,7 +1065,8 @@ class LineBreak {
1034
1065
  const breakItem = items[breakpoint];
1035
1066
  let endedWithHyphen = false;
1036
1067
  if (breakpoint < items.length) {
1037
- if (breakItem.type === ItemType.PENALTY && breakItem.flagged) {
1068
+ if (breakItem.type === ItemType.PENALTY &&
1069
+ breakItem.flagged) {
1038
1070
  lineTextParts.push('-');
1039
1071
  naturalWidth += breakItem.width;
1040
1072
  endedWithHyphen = true;
@@ -1100,7 +1132,8 @@ class LineBreak {
1100
1132
  if (item.type === ItemType.PENALTY)
1101
1133
  continue;
1102
1134
  if (item.originIndex !== undefined) {
1103
- if (finalOriginalStart === -1 || item.originIndex < finalOriginalStart) {
1135
+ if (finalOriginalStart === -1 ||
1136
+ item.originIndex < finalOriginalStart) {
1104
1137
  finalOriginalStart = item.originIndex;
1105
1138
  }
1106
1139
  if (item.originIndex > finalOriginalEnd) {
@@ -4512,7 +4545,14 @@ class TextShaper {
4512
4545
 
4513
4546
  var hb = {exports: {}};
4514
4547
 
4515
- var fs = {}; const readFileSync = () => { throw new Error('fs not available in browser'); };
4548
+ var fs = {};
4549
+ const readFileSync = (...args) => {
4550
+ const req = typeof globalThis !== 'undefined' ? globalThis.require : undefined;
4551
+ if (typeof req === 'function') {
4552
+ return req('fs').readFileSync(...args);
4553
+ }
4554
+ throw new Error('fs not available in this environment');
4555
+ };
4516
4556
 
4517
4557
  var fs$1 = /*#__PURE__*/Object.freeze({
4518
4558
  __proto__: null,
@@ -4523,7 +4563,7 @@ var fs$1 = /*#__PURE__*/Object.freeze({
4523
4563
  var require$$0 = /*@__PURE__*/getAugmentedNamespace(fs$1);
4524
4564
 
4525
4565
  (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;});}
4566
+ 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
4567
  return moduleRtn}})();{module.exports=createHarfBuzz;module.exports.default=createHarfBuzz;}
4528
4568
  } (hb));
4529
4569
 
@@ -5507,7 +5547,11 @@ class Text {
5507
5547
  for (const pattern of Object.keys(options.color.byText)) {
5508
5548
  let index = 0;
5509
5549
  while ((index = options.text.indexOf(pattern, index)) !== -1) {
5510
- byTextMatches.push({ pattern, start: index, end: index + pattern.length });
5550
+ byTextMatches.push({
5551
+ pattern,
5552
+ start: index,
5553
+ end: index + pattern.length
5554
+ });
5511
5555
  for (let i = index; i < index + pattern.length; i++) {
5512
5556
  coloredTextIndices.add(i);
5513
5557
  }