securemark 0.281.0 → 0.281.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.281.1
4
+
5
+ - Fix identifiers.
6
+
3
7
  ## 0.281.0
4
8
 
5
9
  - Change identifiers.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! securemark v0.281.0 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED License */
1
+ /*! securemark v0.281.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("Prism"), require("DOMPurify"));
@@ -6093,9 +6093,8 @@ function identity(id, text, type = 'index') {
6093
6093
  text = text.trim();
6094
6094
  if (text === '') return undefined;
6095
6095
  const str = text.replace(/\s/g, '_');
6096
- if (str.length <= MAX || type === '') return `${type}:${id ?? ''}:${str}`;
6097
6096
  const cs = [...str];
6098
- if (cs.length <= MAX) return `${type}:${id ?? ''}:${str}`;
6097
+ if (cs.length <= MAX || type === '') return `${type}:${id ?? ''}:${str}`;
6099
6098
  switch (type) {
6100
6099
  case 'index':
6101
6100
  case 'mark':
@@ -6106,21 +6105,21 @@ function identity(id, text, type = 'index') {
6106
6105
  }
6107
6106
  exports.identity = identity;
6108
6107
  function hash(source) {
6109
- let x = 1;
6108
+ let x = 0;
6110
6109
  for (let i = 0; i < source.length; ++i) {
6111
- x ^= x << 13;
6110
+ x ^= source.charCodeAt(i) << 1 | 1; // 16+1bit
6111
+ x ^= x << 13; // shift <= 32-17bit
6112
6112
  x ^= x >>> 17;
6113
6113
  x ^= x << 15;
6114
- x ^= source.charCodeAt(i) << 11;
6115
6114
  }
6116
6115
  return x >>> 0;
6117
6116
  }
6118
6117
  function index(source, optional = false) {
6119
6118
  if (!source.firstChild) return '';
6120
6119
  const indexer = source.querySelector(':scope > .indexer');
6121
- const index = indexer?.getAttribute('data-index');
6122
- if (index) return index.replace(/=\w+$/, '');
6123
- if (index === '' && optional) return '';
6120
+ const text = indexer?.getAttribute('data-index');
6121
+ if (text === '' && optional) return '';
6122
+ if (text) return [...text].length <= MAX ? text : text.replace(/=\w{1,7}$/, '');
6124
6123
  return signature(source);
6125
6124
  }
6126
6125
  exports.index = index;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.281.0",
3
+ "version": "0.281.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",
@@ -18,61 +18,73 @@ export function identity(
18
18
  text: string,
19
19
  type: 'index' | 'mark' | '' = 'index',
20
20
  ): string | undefined {
21
- assert(!id?.match(/[^0-9a-z/-]/i));
21
+ assert(id?.match(/^[0-9a-z/-]*$/i) ?? true);
22
22
  assert(!text.includes('\n'));
23
23
  if (id === '') return undefined;
24
24
  text = text.trim();
25
25
  if (text === '') return undefined;
26
26
  const str = text.replace(/\s/g, '_');
27
- if (str.length <= MAX || type === '') return `${type}:${id ?? ''}:${str}`;
28
27
  const cs = [...str];
29
- if (cs.length <= MAX) return `${type}:${id ?? ''}:${str}`;
28
+ if (cs.length <= MAX || type === '') return `${type}:${id ?? ''}:${str}`;
30
29
  switch (type) {
31
30
  case 'index':
32
31
  case 'mark':
33
32
  const s1 = cs.slice(0, PART + REM).join('');
34
33
  const s2 = cs.slice(-PART).join('');
34
+ assert([...`${s1}${ELLIPSIS}${s2}`].length === MAX);
35
35
  return `${type}:${id ?? ''}:${s1}${ELLIPSIS}${s2}=${hash(text).toString(36)}`;
36
36
  }
37
37
  assert(false);
38
38
  }
39
- function hash(source: string): number {
40
- let x = 1;
41
- assert(x !== 0);
42
- for (let i = 0; i < source.length; ++i) {
43
- x ^= x << 13;
44
- x ^= x >>> 17;
45
- x ^= x << 15;
46
- x ^= source.charCodeAt(i) << 11;
47
- }
48
- return x >>> 0;
49
- }
50
39
  assert.deepStrictEqual(
51
40
  identity(undefined, `${'0'.repeat(MAX - 1)}1`)!.slice(7),
52
41
  `${'0'.repeat(MAX - 1)}1`);
53
42
  assert.deepStrictEqual(
54
43
  identity(undefined, `0${'1'.repeat(MAX / 2)}${'2'.repeat(MAX / 2)}3`)!.slice(7),
55
- `0${'1'.repeat(PART + REM - 1)}${ELLIPSIS}${'2'.repeat(PART - 1)}3=x8ujbi`);
44
+ `0${'1'.repeat(PART + REM - 1)}${ELLIPSIS}${'2'.repeat(PART - 1)}3=mhy513`);
56
45
  assert.deepStrictEqual(
57
46
  identity(undefined, `0${'1'.repeat(MAX * 2)}${'2'.repeat(MAX * 2)}3`)!.slice(7),
58
- `0${'1'.repeat(PART + REM - 1)}${ELLIPSIS}${'2'.repeat(PART - 1)}3=1c1m3g9`);
47
+ `0${'1'.repeat(PART + REM - 1)}${ELLIPSIS}${'2'.repeat(PART - 1)}3=12jqtiv`);
59
48
  assert.deepStrictEqual(
60
49
  identity(undefined, ` ${'0 '.repeat(MAX)}`)!.slice(7),
61
50
  identity(undefined, ` ${'0 '.repeat(MAX)}`.trim())!.slice(7));
62
51
  assert.notDeepStrictEqual(
63
52
  identity(undefined, `${'0 '.repeat(MAX)}`)!.slice(7),
64
53
  identity(undefined, `${'0_'.repeat(MAX)}`)!.slice(7));
54
+ function hash(source: string): number {
55
+ let x = 0;
56
+ for (let i = 0; i < source.length; ++i) {
57
+ x ^= source.charCodeAt(i) << 1 | 1; // 16+1bit
58
+ x ^= x << 13; // shift <= 32-17bit
59
+ x ^= x >>> 17;
60
+ x ^= x << 15;
61
+ }
62
+ return x >>> 0;
63
+ }
64
+ assert(hash('\x00') !== 0);
65
+ assert(hash('\x01') !== 0);
66
+ assert(hash('\x00') !== hash(String.fromCharCode(1 << 15)));
65
67
 
66
68
  export function index(source: Element, optional = false): string {
67
69
  assert(!source.matches('.indexer'));
68
70
  assert(source.querySelectorAll(':scope > .indexer').length <= 1);
69
71
  if (!source.firstChild) return '';
70
72
  const indexer = source.querySelector(':scope > .indexer');
71
- const index = indexer?.getAttribute('data-index');
72
- if (index) return index.replace(/=\w+$/, '');
73
- if (index === '' && optional) return '';
73
+ const text = indexer?.getAttribute('data-index');
74
+ if (text === '' && optional) return '';
75
+ if (text) return [...text].length <= MAX ? text : text.replace(/=\w{1,7}$/, '');
74
76
  return signature(source);
75
77
  }
78
+ assert.deepStrictEqual(
79
+ index(define(document.createElement('b'), [
80
+ define(document.createElement('b'), { class: 'indexer', 'data-index': '0'.repeat(MAX - 2) + '=0' })
81
+ ])),
82
+ '0'.repeat(MAX - 2) + '=0');
83
+ assert.deepStrictEqual(
84
+ index(define(document.createElement('b'), [
85
+ define(document.createElement('b'), { class: 'indexer', 'data-index': '0'.repeat(MAX) + '=0' })
86
+ ])),
87
+ '0'.repeat(MAX));
76
88
 
77
89
  export function signature(source: Element | DocumentFragment): string {
78
90
  assert(!navigator.userAgent.includes('Chrome') || !source.querySelector('br:not(:has(+ :is(ul, ol)))'));