securemark 0.249.0 → 0.249.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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.249.1
4
+
5
+ - Update dependencies.
6
+
3
7
  ## 0.249.0
4
8
 
5
9
  - Change some parsers to trim leading blanks except linebreaks.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! securemark v0.249.0 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED License */
1
+ /*! securemark v0.249.1 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED License */
2
2
  (function webpackUniversalModuleDefinition(root, factory) {
3
3
  if(typeof exports === 'object' && typeof module === 'object')
4
4
  module.exports = factory(require("DOMPurify"), require("Prism"));
@@ -360,6 +360,8 @@ const clock_1 = __webpack_require__(7681);
360
360
 
361
361
  const invlist_1 = __webpack_require__(7452);
362
362
 
363
+ const heap_1 = __webpack_require__(818);
364
+
363
365
  const assign_1 = __webpack_require__(4401);
364
366
 
365
367
  const tuple_1 = __webpack_require__(5341);
@@ -370,26 +372,21 @@ class Cache {
370
372
  capacity: 0,
371
373
  space: global_1.Infinity,
372
374
  age: global_1.Infinity,
373
- life: 10,
374
- limit: 95,
375
+ earlyExpiring: false,
376
+ limit: 950,
375
377
  capture: {
376
378
  delete: true,
377
379
  clear: true
378
380
  }
379
381
  };
380
- this.SIZE = 0; // 1041 days < 2 ** 53 / 100,000,000 / 3600 / 24.
381
- // Hit counter only for LFU.
382
-
383
- this.clock = global_1.Number.MIN_SAFE_INTEGER; // LRU access counter only for LRU.
384
-
385
- this.clockR = global_1.Number.MIN_SAFE_INTEGER;
382
+ this.overlap = 0;
383
+ this.SIZE = 0;
386
384
  this.memory = new global_1.Map();
387
385
  this.indexes = {
388
386
  LRU: new invlist_1.List(),
389
- LFU: new invlist_1.List(),
390
- // expiryとLFUのclockを消すなら消せる
391
- OVL: new invlist_1.List()
387
+ LFU: new invlist_1.List()
392
388
  };
389
+ this.expiries = new heap_1.Heap();
393
390
  this.stats = {
394
391
  LRU: (0, tuple_1.tuple)(0, 0),
395
392
  LFU: (0, tuple_1.tuple)(0, 0),
@@ -415,7 +412,7 @@ class Cache {
415
412
  }
416
413
 
417
414
  };
418
- this.ratio = 50;
415
+ this.ratio = 500;
419
416
 
420
417
  if (typeof capacity === 'object') {
421
418
  opts = capacity;
@@ -428,8 +425,9 @@ class Cache {
428
425
  this.capacity = this.settings.capacity;
429
426
  if (this.capacity >= 1 === false) throw new Error(`Spica: Cache: Capacity must be 1 or more.`);
430
427
  this.space = this.settings.space;
431
- this.life = this.capacity * this.settings.life;
432
428
  this.limit = this.settings.limit;
429
+ this.earlyExpiring = this.settings.earlyExpiring;
430
+ this.disposer = this.settings.disposer;
433
431
  }
434
432
 
435
433
  get length() {
@@ -443,41 +441,29 @@ class Cache {
443
441
 
444
442
  evict(node, record, callback) {
445
443
  const index = node.value;
446
- callback &&= !!this.settings.disposer;
444
+ callback &&= !!this.disposer;
447
445
  record = callback ? record ?? this.memory.get(index.key) : record;
446
+ this.overlap -= +(index.region === 'LFU' && node.list === this.indexes.LRU);
448
447
  node.delete();
449
- node.value.overlap?.delete();
450
448
  this.memory.delete(index.key);
451
449
  this.SIZE -= index.size;
452
- callback && this.settings.disposer?.(record.value, index.key);
450
+ callback && this.disposer?.(record.value, index.key);
453
451
  }
454
452
 
455
453
  ensure(margin, skip) {
456
- if (skip) {
457
- // Prevent wrong disposal of `skip`.
458
- skip.value.clock = this.clock;
459
- skip.value.expiry = global_1.Infinity;
460
- }
461
-
462
454
  let size = skip?.value.size ?? 0;
463
455
  if (margin - size <= 0) return;
464
456
  const {
465
457
  LRU,
466
- LFU,
467
- OVL
458
+ LFU
468
459
  } = this.indexes;
469
460
 
470
461
  while (this.length === this.capacity || this.size + margin - size > this.space) {
471
- const lastNode = OVL.last ?? LFU.last;
472
- const lastIndex = lastNode?.value;
473
462
  let target;
474
463
 
475
464
  switch (true) {
476
- // NOTE: The following conditions must be ensured that they won't be true if `lastNode` is `skip`.
477
- // LRUの下限を5%以上確保すればわずかな性能低下と引き換えにクロックを消せる
478
- case lastIndex && lastIndex.clock < this.clock - this.life:
479
- case lastIndex && lastIndex.expiry !== global_1.Infinity && lastIndex.expiry < (0, clock_1.now)():
480
- target = lastNode.list === OVL ? lastNode.value.node : lastNode;
465
+ case (target = this.expiries.peek()) && target !== skip && target.value.expiry < (0, clock_1.now)():
466
+ target = this.expiries.extract();
481
467
  break;
482
468
 
483
469
  case LRU.length === 0:
@@ -485,14 +471,13 @@ class Cache {
485
471
  break;
486
472
  // @ts-expect-error
487
473
 
488
- case LFU.length > this.capacity * this.ratio / 100:
474
+ case LFU.length > this.capacity * this.ratio / 1000:
489
475
  target = LFU.last !== skip ? LFU.last : LFU.length >= 2 ? LFU.last.prev : skip;
490
476
 
491
477
  if (target !== skip) {
492
- if (this.ratio >= 50) break;
478
+ if (this.ratio > 500) break;
493
479
  LRU.unshiftNode(target);
494
- LRU.head.value.node = LRU.head;
495
- LRU.head.value.overlap = OVL.unshift(LRU.head.value);
480
+ ++this.overlap;
496
481
  }
497
482
 
498
483
  // fallthrough
@@ -507,12 +492,12 @@ class Cache {
507
492
  }
508
493
  }
509
494
 
510
- put(key, value, size = 1, age = this.settings.age) {
511
- if (size >= 1 === false) throw new Error(`Spica: Cache: Size must be 1 or more.`);
512
- if (age >= 1 === false) throw new Error(`Spica: Cache: Age must be 1 or more.`);
513
-
495
+ put(key, value, {
496
+ size = 1,
497
+ age = this.settings.age
498
+ } = {}) {
514
499
  if (size > this.space || age <= 0) {
515
- this.settings.disposer?.(value, key);
500
+ this.disposer?.(value, key);
516
501
  return false;
517
502
  }
518
503
 
@@ -520,16 +505,23 @@ class Cache {
520
505
  const record = this.memory.get(key);
521
506
 
522
507
  if (record) {
523
- const node = record.index;
508
+ const node = record.inode;
524
509
  const val = record.value;
525
510
  const index = node.value;
526
511
  this.ensure(size, node);
527
- index.clock = index.region === 'LRU' ? ++this.clockR : ++this.clock;
528
- index.expiry = expiry;
529
512
  this.SIZE += size - index.size;
530
513
  index.size = size;
514
+ index.expiry = expiry;
515
+
516
+ if (this.earlyExpiring && expiry !== global_1.Infinity) {
517
+ index.enode ? this.expiries.update(index.enode, -expiry) : index.enode = this.expiries.insert(-expiry, node);
518
+ } else if (index.enode) {
519
+ this.expiries.delete(index.enode);
520
+ index.enode = void 0;
521
+ }
522
+
531
523
  record.value = value;
532
- this.settings.disposer?.(val, key);
524
+ this.disposer?.(val, key);
533
525
  return true;
534
526
  }
535
527
 
@@ -538,28 +530,33 @@ class Cache {
538
530
  LRU
539
531
  } = this.indexes;
540
532
  this.SIZE += size;
533
+ const node = LRU.unshift({
534
+ key,
535
+ size,
536
+ expiry,
537
+ region: 'LRU'
538
+ });
541
539
  this.memory.set(key, {
542
- index: LRU.unshift({
543
- key,
544
- size,
545
- clock: ++this.clockR,
546
- expiry,
547
- region: 'LRU'
548
- }),
540
+ inode: node,
549
541
  value
550
542
  });
543
+
544
+ if (this.earlyExpiring && expiry !== global_1.Infinity) {
545
+ node.value.enode = this.expiries.insert(-expiry, node);
546
+ }
547
+
551
548
  return false;
552
549
  }
553
550
 
554
- set(key, value, size, age) {
555
- this.put(key, value, size, age);
551
+ set(key, value, opts) {
552
+ this.put(key, value, opts);
556
553
  return this;
557
554
  }
558
555
 
559
556
  get(key) {
560
557
  const record = this.memory.get(key);
561
558
  if (!record) return;
562
- const node = record.index;
559
+ const node = record.inode;
563
560
  const expiry = node.value.expiry;
564
561
 
565
562
  if (expiry !== global_1.Infinity && expiry < (0, clock_1.now)()) {
@@ -568,7 +565,7 @@ class Cache {
568
565
  } // Optimization for memoize.
569
566
 
570
567
 
571
- if (this.capacity >= 10 && node === node.list.head) return record.value;
568
+ if (this.capacity > 3 && node === node.list.head) return record.value;
572
569
  this.access(node);
573
570
  this.slide();
574
571
  return record.value;
@@ -579,10 +576,10 @@ class Cache {
579
576
  //assert(this.memory.size === this.indexes.LFU.length + this.indexes.LRU.length);
580
577
  const record = this.memory.get(key);
581
578
  if (!record) return false;
582
- const expiry = record.index.value.expiry;
579
+ const expiry = record.inode.value.expiry;
583
580
 
584
581
  if (expiry !== global_1.Infinity && expiry < (0, clock_1.now)()) {
585
- this.evict(record.index, record, true);
582
+ this.evict(record.inode, record, true);
586
583
  return false;
587
584
  }
588
585
 
@@ -592,25 +589,26 @@ class Cache {
592
589
  delete(key) {
593
590
  const record = this.memory.get(key);
594
591
  if (!record) return false;
595
- this.evict(record.index, record, this.settings.capture.delete === true);
592
+ this.evict(record.inode, record, this.settings.capture.delete === true);
596
593
  return true;
597
594
  }
598
595
 
599
596
  clear() {
597
+ this.overlap = 0;
600
598
  this.SIZE = 0;
601
- this.ratio = 50;
599
+ this.ratio = 500;
602
600
  this.stats.clear();
603
601
  this.indexes.LRU.clear();
604
602
  this.indexes.LFU.clear();
605
- this.indexes.OVL.clear();
606
- if (!this.settings.disposer || !this.settings.capture.clear) return void this.memory.clear();
603
+ this.expiries.clear();
604
+ if (!this.disposer || !this.settings.capture.clear) return void this.memory.clear();
607
605
  const memory = this.memory;
608
606
  this.memory = new global_1.Map();
609
607
 
610
608
  for (const [key, {
611
609
  value
612
610
  }] of memory) {
613
- this.settings.disposer(value, key);
611
+ this.disposer(value, key);
614
612
  }
615
613
  }
616
614
 
@@ -637,24 +635,24 @@ class Cache {
637
635
  } = this;
638
636
  const window = capacity;
639
637
  LRU[0] + LFU[0] === window && this.stats.slide();
640
- if ((LRU[0] + LFU[0]) * 100 % capacity || LRU[1] + LFU[1] === 0) return;
638
+ if ((LRU[0] + LFU[0]) * 1000 % capacity || LRU[1] + LFU[1] === 0) return;
641
639
  const lenR = indexes.LRU.length;
642
640
  const lenF = indexes.LFU.length;
643
- const lenV = indexes.OVL.length;
644
- const r = (lenF + lenV) * 1000 / (lenR + lenF) | 0;
645
- const rateR0 = rate(window, LRU[0], LRU[0] + LFU[0], LRU[1], LRU[1] + LFU[1], 0) * (1 + r);
646
- const rateF0 = rate(window, LFU[0], LRU[0] + LFU[0], LFU[1], LRU[1] + LFU[1], 0) * (1001 - r);
647
- const rateF1 = rate(window, LFU[1], LRU[1] + LFU[1], LFU[0], LRU[0] + LFU[0], 5) * (1001 - r); // 操作頻度を超えてキャッシュ比率を増減させても余剰比率の消化が追いつかず無駄
641
+ const lenV = this.overlap;
642
+ const r = (lenF + lenV) * 1000 / (lenR + lenF || 1) | 0;
643
+ const rateR0 = rate(window, LRU[0], LRU[0] + LFU[0], LRU[1], LRU[1] + LFU[1], 0) * r;
644
+ const rateF0 = rate(window, LFU[0], LRU[0] + LFU[0], LFU[1], LRU[1] + LFU[1], 0) * (1000 - r);
645
+ const rateF1 = rate(window, LFU[1], LRU[1] + LFU[1], LFU[0], LRU[0] + LFU[0], 5) * (1000 - r); // 操作頻度を超えてキャッシュ比率を増減させても余剰比率の消化が追いつかず無駄
648
646
  // LRUの下限設定ではLRU拡大の要否を迅速に判定できないためLFUのヒット率低下の検出で代替する
649
647
 
650
648
  if (ratio > 0 && (rateR0 > rateF0 || rateF0 < rateF1 * 0.95)) {
651
- if (lenR >= capacity * (100 - ratio) / 100) {
652
- //ratio % 10 || ratio === 100 || console.debug('-', ratio, LRU, LFU);
649
+ if (lenR >= capacity * (1000 - ratio) / 1000) {
650
+ //ratio % 100 || ratio === 1000 || console.debug('-', ratio, LRU, LFU);
653
651
  --this.ratio;
654
652
  }
655
653
  } else if (ratio < limit && rateF0 > rateR0) {
656
- if (lenF >= capacity * ratio / 100) {
657
- //ratio % 10 || ratio === 0 || console.debug('+', ratio, LRU, LFU);
654
+ if (lenF >= capacity * ratio / 1000) {
655
+ //ratio % 100 || ratio === 0 || console.debug('+', ratio, LRU, LFU);
658
656
  ++this.ratio;
659
657
  }
660
658
  }
@@ -666,33 +664,17 @@ class Cache {
666
664
 
667
665
  accessLRU(node) {
668
666
  const index = node.value;
669
- const {
670
- LRU,
671
- LFU
672
- } = this.indexes;
673
- ++this.stats[index.region][0]; // Prevent LFU destruction.
674
-
675
- if (!index.overlap && index.clock >= this.clockR - LRU.length / 3 && this.capacity > 3) {
676
- index.clock = ++this.clockR;
677
- node.moveToHead();
678
- return true;
679
- }
680
-
681
- index.clock = ++this.clock;
667
+ ++this.stats[index.region][0];
668
+ this.overlap -= +(index.region === 'LFU');
682
669
  index.region = 'LFU';
683
- index.overlap?.delete();
684
- LFU.unshiftNode(node);
670
+ this.indexes.LFU.unshiftNode(node);
685
671
  return true;
686
672
  }
687
673
 
688
674
  accessLFU(node) {
675
+ if (node.list !== this.indexes.LFU) return false;
689
676
  const index = node.value;
690
- const {
691
- LFU
692
- } = this.indexes;
693
- if (node.list !== LFU) return false;
694
677
  ++this.stats[index.region][0];
695
- index.clock = ++this.clock;
696
678
  node.moveToHead();
697
679
  return true;
698
680
  }
@@ -949,6 +931,151 @@ var global = (/* unused pure expression or super */ null && (globalThis));
949
931
 
950
932
  /***/ }),
951
933
 
934
+ /***/ 818:
935
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
936
+
937
+ "use strict";
938
+
939
+
940
+ Object.defineProperty(exports, "__esModule", ({
941
+ value: true
942
+ }));
943
+ exports.Heap = void 0;
944
+
945
+ const alias_1 = __webpack_require__(5406); // Max heap
946
+
947
+
948
+ const undefined = void 0;
949
+
950
+ class Heap {
951
+ constructor(stable = false) {
952
+ this.stable = stable;
953
+ this.array = [];
954
+ this.$length = 0;
955
+ }
956
+
957
+ get length() {
958
+ return this.$length;
959
+ }
960
+
961
+ insert(priority, value) {
962
+ const array = this.array;
963
+ const node = array[this.$length] = [priority, value, this.$length++];
964
+ upHeapify(array, this.$length);
965
+ return node;
966
+ }
967
+
968
+ replace(priority, value) {
969
+ const array = this.array;
970
+ if (this.$length === 0) return void this.insert(priority, value);
971
+ const replaced = array[0][1];
972
+ array[0] = [priority, value, 0];
973
+ downHeapify(array, 1, this.$length, this.stable);
974
+ return replaced;
975
+ }
976
+
977
+ extract() {
978
+ if (this.$length === 0) return;
979
+ const node = this.array[0];
980
+ this.delete(node);
981
+ return node[1];
982
+ }
983
+
984
+ delete(node) {
985
+ const array = this.array;
986
+ const index = node[2];
987
+ if (array[index] !== node) throw new Error('Invalid node');
988
+ swap(array, index, --this.$length); // @ts-expect-error
989
+
990
+ array[this.$length] = undefined;
991
+ index < this.$length && this.sort(array[index]);
992
+
993
+ if (array.length > 2 ** 16 && array.length > this.$length * 2) {
994
+ array.splice(array.length / 2, array.length);
995
+ }
996
+
997
+ return node[1];
998
+ }
999
+
1000
+ update(node, priority, value = node[1]) {
1001
+ const array = this.array;
1002
+ if (array[node[2]] !== node) throw new Error('Invalid node');
1003
+ node[1] = value;
1004
+ if (node[0] === priority) return;
1005
+ node[0] = priority;
1006
+ this.sort(node);
1007
+ }
1008
+
1009
+ sort(node) {
1010
+ const array = this.array;
1011
+ return upHeapify(array, node[2] + 1) || downHeapify(array, node[2] + 1, this.$length, this.stable);
1012
+ }
1013
+
1014
+ peek() {
1015
+ return this.array[0]?.[1];
1016
+ }
1017
+
1018
+ clear() {
1019
+ this.array = [];
1020
+ this.$length = 0;
1021
+ }
1022
+
1023
+ }
1024
+
1025
+ exports.Heap = Heap;
1026
+
1027
+ function upHeapify(array, index) {
1028
+ const priority = array[index - 1][0];
1029
+ let changed = false;
1030
+
1031
+ while (index > 1) {
1032
+ const parent = (0, alias_1.floor)(index / 2);
1033
+ if (array[parent - 1][0] >= priority) break;
1034
+ swap(array, index - 1, parent - 1);
1035
+ index = parent;
1036
+ changed ||= true;
1037
+ }
1038
+
1039
+ return changed;
1040
+ }
1041
+
1042
+ function downHeapify(array, index, length, stable) {
1043
+ let changed = false;
1044
+
1045
+ while (index < length) {
1046
+ const left = index * 2;
1047
+ const right = index * 2 + 1;
1048
+ let max = index;
1049
+
1050
+ if (left <= length && (stable ? array[left - 1][0] >= array[max - 1][0] : array[left - 1][0] > array[max - 1][0])) {
1051
+ max = left;
1052
+ }
1053
+
1054
+ if (right <= length && (stable ? array[right - 1][0] >= array[max - 1][0] : array[right - 1][0] > array[max - 1][0])) {
1055
+ max = right;
1056
+ }
1057
+
1058
+ if (max === index) break;
1059
+ swap(array, index - 1, max - 1);
1060
+ index = max;
1061
+ changed ||= true;
1062
+ }
1063
+
1064
+ return changed;
1065
+ }
1066
+
1067
+ function swap(array, index1, index2) {
1068
+ if (index1 === index2) return;
1069
+ const node1 = array[index1];
1070
+ const node2 = array[index2];
1071
+ node1[2] = index2;
1072
+ node2[2] = index1;
1073
+ array[index1] = node2;
1074
+ array[index2] = node1;
1075
+ }
1076
+
1077
+ /***/ }),
1078
+
952
1079
  /***/ 7452:
953
1080
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
954
1081
 
@@ -6136,13 +6263,13 @@ const attrspec = {
6136
6263
  };
6137
6264
  global_1.Object.setPrototypeOf(attrspec, null);
6138
6265
  global_1.Object.values(attrspec).forEach(o => global_1.Object.setPrototypeOf(o, null));
6139
- exports.html = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.validate)('<', (0, combinator_1.validate)(/^<[a-z]+(?=[^\S\n]|>)/, (0, combinator_1.union)([(0, combinator_1.match)(/^(?=<(wbr)(?=[^\S\n]|>))/, (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.surround)(`<${tag}`, (0, combinator_1.some)((0, combinator_1.union)([exports.attribute])), /^\s*>/, true, ([, bs = []], rest) => [[(0, dom_1.html)(tag, attributes('html', [], attrspec[tag], bs))], rest]), ([, tag]) => tags.indexOf(tag), [])), (0, combinator_1.match)(/^(?=<(sup|sub|small|bdo|bdi)(?=[^\S\n]|>))/, (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.surround)((0, combinator_1.surround)((0, source_1.str)(`<${tag}`), (0, combinator_1.some)(exports.attribute), (0, source_1.str)(/^\s*>/), true), (0, util_1.startLoose)((0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.open)(/^\n?/, (0, combinator_1.some)(inline_1.inline, (0, util_1.blankWith)('\n', `</${tag}>`)), true)]), `</${tag}>`), `</${tag}>`), (0, source_1.str)(`</${tag}>`), false, ([as, bs, cs], rest) => [[elem(tag, as, (0, dom_1.defrag)(bs), cs)], rest]), ([, tag]) => tags.indexOf(tag), [])), (0, combinator_1.match)(/^(?=<([a-z]+)(?=[^\S\n]|>))/, (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.surround)((0, combinator_1.surround)((0, source_1.str)(`<${tag}`), (0, combinator_1.some)(exports.attribute), (0, source_1.str)(/^\s*>/), true), (0, util_1.startLoose)((0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.open)(/^\n?/, (0, combinator_1.some)(inline_1.inline, (0, util_1.blankWith)('\n', `</${tag}>`)), true)]), `</${tag}>`), `</${tag}>`), (0, source_1.str)(`</${tag}>`), false, ([as, bs, cs], rest) => [[elem(tag, as, (0, dom_1.defrag)(bs), cs)], rest]), ([, tag]) => tag, new cache_1.Cache(10000)))])))));
6266
+ exports.html = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.validate)('<', (0, combinator_1.validate)(/^<[a-z]+(?=[^\S\n]|>)/, (0, combinator_1.union)([(0, combinator_1.match)(/^(?=<(wbr)(?=[^\S\n]|>))/, (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.surround)(`<${tag}`, (0, combinator_1.some)((0, combinator_1.union)([exports.attribute])), /^\s*>/, true, ([, bs = []], rest) => [[(0, dom_1.html)(tag, attributes('html', [], attrspec[tag], bs))], rest]), ([, tag]) => tags.indexOf(tag), [])), (0, combinator_1.match)(/^(?=<(sup|sub|small|bdo|bdi)(?=[^\S\n]|>))/, (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.surround)((0, combinator_1.surround)((0, source_1.str)(`<${tag}`), (0, combinator_1.some)(exports.attribute), (0, source_1.str)(/^\s*>/), true), (0, util_1.startLoose)((0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.open)(/^\n?/, (0, combinator_1.some)(inline_1.inline, (0, util_1.blankWith)('\n', `</${tag}>`)), true)])), `</${tag}>`), (0, source_1.str)(`</${tag}>`), false, ([as, bs, cs], rest) => [[elem(tag, as, bs, cs)], rest]), ([, tag]) => tags.indexOf(tag), [])), (0, combinator_1.match)(/^(?=<([a-z]+)(?=[^\S\n]|>))/, (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.surround)((0, combinator_1.surround)((0, source_1.str)(`<${tag}`), (0, combinator_1.some)(exports.attribute), (0, source_1.str)(/^\s*>/), true), (0, util_1.startLoose)((0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.open)(/^\n?/, (0, combinator_1.some)(inline_1.inline, (0, util_1.blankWith)('\n', `</${tag}>`)), true)])), `</${tag}>`), (0, source_1.str)(`</${tag}>`), false, ([as, bs, cs], rest) => [[elem(tag, as, bs, cs)], rest]), ([, tag]) => tag, new cache_1.Cache(10000)))])))));
6140
6267
  exports.attribute = (0, combinator_1.union)([(0, source_1.str)(/^[^\S\n]+[a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[^\S\n]|>)/)]);
6141
6268
 
6142
6269
  function elem(tag, as, bs, cs) {
6143
6270
  if (!tags.includes(tag)) return invalid('tag', `Invalid HTML tag <${tag}>`, as, bs, cs);
6144
6271
  const attrs = attributes('html', [], attrspec[tag], as.slice(1, -1));
6145
- return 'data-invalid-syntax' in attrs ? invalid('attribute', 'Invalid HTML attribute', as, bs, cs) : (0, dom_1.html)(tag, attrs, bs);
6272
+ return 'data-invalid-syntax' in attrs ? invalid('attribute', 'Invalid HTML attribute', as, bs, cs) : (0, dom_1.html)(tag, attrs, (0, dom_1.defrag)(bs));
6146
6273
  }
6147
6274
 
6148
6275
  function invalid(type, message, as, bs, cs) {
@@ -8629,7 +8756,7 @@ function fix(h) {
8629
8756
  /***/ 3252:
8630
8757
  /***/ (function(module) {
8631
8758
 
8632
- /*! typed-dom v0.0.297 https://github.com/falsandtru/typed-dom | (c) 2016, falsandtru | (Apache-2.0 AND MPL-2.0) License */
8759
+ /*! typed-dom v0.0.298 https://github.com/falsandtru/typed-dom | (c) 2016, falsandtru | (Apache-2.0 AND MPL-2.0) License */
8633
8760
  (function webpackUniversalModuleDefinition(root, factory) {
8634
8761
  if(true)
8635
8762
  module.exports = factory();
@@ -9063,7 +9190,7 @@ exports.defrag = defrag;
9063
9190
  /***/ 6120:
9064
9191
  /***/ (function(module) {
9065
9192
 
9066
- /*! typed-dom v0.0.297 https://github.com/falsandtru/typed-dom | (c) 2016, falsandtru | (Apache-2.0 AND MPL-2.0) License */
9193
+ /*! typed-dom v0.0.298 https://github.com/falsandtru/typed-dom | (c) 2016, falsandtru | (Apache-2.0 AND MPL-2.0) License */
9067
9194
  (function webpackUniversalModuleDefinition(root, factory) {
9068
9195
  if(true)
9069
9196
  module.exports = factory();
package/karma.conf.js CHANGED
@@ -12,7 +12,7 @@ module.exports = function (config) {
12
12
  { pattern: 'https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.3.8/purify.js', watched: false, served: false, included: true, integrity: 'sha512-QaF+0tDlqVmwZaQSc0kImgYmw+Cd66TxA5D9X70I5V9BNSqk6yBTbyqw2VEUsVYV5OTbxw8HD9d45on1wvYv7g==' },
13
13
  { pattern: 'dist/**/*.{js,map}', watched: true, served: true, included: true },
14
14
  ],
15
- reporters: ['dots', 'coverage'],
15
+ reporters: ['dots'],
16
16
  preprocessors: {
17
17
  'dist/**/*.js': ['coverage'],
18
18
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.249.0",
3
+ "version": "0.249.1",
4
4
  "description": "Secure markdown renderer working on browsers for user input data.",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/falsandtru/securemark",
@@ -34,11 +34,11 @@
34
34
  "@types/mocha": "9.1.1",
35
35
  "@types/power-assert": "1.5.8",
36
36
  "@types/prismjs": "1.26.0",
37
- "@typescript-eslint/parser": "^5.26.0",
37
+ "@typescript-eslint/parser": "^5.27.1",
38
38
  "babel-loader": "^8.2.5",
39
39
  "babel-plugin-unassert": "^3.2.0",
40
40
  "concurrently": "^7.2.1",
41
- "eslint": "^8.16.0",
41
+ "eslint": "^8.17.0",
42
42
  "eslint-plugin-redos": "^4.4.0",
43
43
  "eslint-webpack-plugin": "^3.1.1",
44
44
  "glob": "^8.0.3",
@@ -49,22 +49,22 @@
49
49
  "karma-mocha": "^2.0.1",
50
50
  "karma-power-assert": "^1.0.0",
51
51
  "mocha": "^10.0.0",
52
- "npm-check-updates": "^13.0.3",
52
+ "npm-check-updates": "^13.1.1",
53
53
  "semver": "^7.3.7",
54
- "spica": "0.0.554",
54
+ "spica": "0.0.564",
55
55
  "ts-loader": "^9.3.0",
56
- "typed-dom": "^0.0.297",
57
- "typescript": "4.7.2",
58
- "webpack": "^5.72.1",
56
+ "typed-dom": "^0.0.298",
57
+ "typescript": "4.7.3",
58
+ "webpack": "^5.73.0",
59
59
  "webpack-cli": "^4.9.2",
60
60
  "webpack-merge": "^5.8.0"
61
61
  },
62
62
  "scripts": {
63
63
  "update": "ncu -u && npm i --no-shrinkwrap && bundle update",
64
- "dev": "concurrently \"webpack --env mode=test -w\" \"karma start --auto-watch --reporters dots\" \"webpack --env mode=dist -w --output-path ./gh-pages/assets/dist\" \"bundle exec jekyll serve -s ./gh-pages -d ./gh-pages/_site --incremental\"",
65
- "test": "webpack --env mode=test && karma start --single-run --concurrency 1",
64
+ "dev": "concurrently \"webpack --env mode=test -w\" \"karma start --auto-watch\" \"webpack --env mode=dist -w --output-path ./gh-pages/assets/dist\" \"bundle exec jekyll serve -s ./gh-pages -d ./gh-pages/_site --incremental\"",
65
+ "test": "webpack --env mode=test && karma start --single-run --concurrency 1 --reporters dots,coverage",
66
66
  "lint": "webpack --env mode=lint",
67
- "bench": "webpack --env mode=bench && karma start --single-run --concurrency 1 --reporters dots",
67
+ "bench": "webpack --env mode=bench && karma start --single-run --concurrency 1",
68
68
  "dist": "webpack --env mode=dist"
69
69
  },
70
70
  "author": "falsandtru",
@@ -36,10 +36,10 @@ export const html: HTMLParser = lazy(() => creator(validate('<', validate(/^<[a-
36
36
  str(`<${tag}`), some(attribute), str(/^\s*>/), true),
37
37
  startLoose(some(union([
38
38
  open(/^\n?/, some(inline, blankWith('\n', `</${tag}>`)), true),
39
- ]), `</${tag}>`), `</${tag}>`),
39
+ ])), `</${tag}>`),
40
40
  str(`</${tag}>`), false,
41
41
  ([as, bs, cs], rest) =>
42
- [[elem(tag, as, defrag(bs), cs)], rest]),
42
+ [[elem(tag, as, bs, cs)], rest]),
43
43
  ([, tag]) => tags.indexOf(tag), [])),
44
44
  match(
45
45
  /^(?=<([a-z]+)(?=[^\S\n]|>))/,
@@ -49,10 +49,10 @@ export const html: HTMLParser = lazy(() => creator(validate('<', validate(/^<[a-
49
49
  str(`<${tag}`), some(attribute), str(/^\s*>/), true),
50
50
  startLoose(some(union([
51
51
  open(/^\n?/, some(inline, blankWith('\n', `</${tag}>`)), true),
52
- ]), `</${tag}>`), `</${tag}>`),
52
+ ])), `</${tag}>`),
53
53
  str(`</${tag}>`), false,
54
54
  ([as, bs, cs], rest) =>
55
- [[elem(tag, as, defrag(bs), cs)], rest]),
55
+ [[elem(tag, as, bs, cs)], rest]),
56
56
  ([, tag]) => tag,
57
57
  new Cache(10000))),
58
58
  ])))));
@@ -64,13 +64,12 @@ export const attribute: HTMLParser.TagParser.AttributeParser = union([
64
64
  function elem(tag: string, as: string[], bs: (HTMLElement | string)[], cs: string[]): HTMLElement {
65
65
  assert(as.length > 0);
66
66
  assert(as[0][0] === '<' && as[as.length - 1].slice(-1) === '>');
67
- assert(bs.length === defrag(bs).length);
68
67
  assert(cs.length === 1);
69
68
  if (!tags.includes(tag)) return invalid('tag', `Invalid HTML tag <${tag}>`, as, bs, cs);
70
69
  const attrs = attributes('html', [], attrspec[tag], as.slice(1, -1));
71
70
  return 'data-invalid-syntax' in attrs
72
71
  ? invalid('attribute', 'Invalid HTML attribute', as, bs, cs)
73
- : h(tag as 'span', attrs, bs);
72
+ : h(tag as 'span', attrs, defrag(bs));
74
73
  }
75
74
  function invalid(type: string, message: string, as: (HTMLElement | string)[], bs: (HTMLElement | string)[], cs: (HTMLElement | string)[]): HTMLElement {
76
75
  return h('span', {