securemark 0.235.3 → 0.236.0

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.236.0
4
+
5
+ - Extend figure syntax to allow ulist syntax and olist syntax.
6
+
3
7
  ## 0.235.3
4
8
 
5
9
  - Refactoring.
@@ -1,4 +1,4 @@
1
- /*! securemark v0.235.3 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED */
1
+ /*! securemark v0.236.0 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED */
2
2
  require = function () {
3
3
  function r(e, n, t) {
4
4
  function o(i, f) {
@@ -4778,7 +4778,7 @@ require = function () {
4778
4778
  translate: 'no',
4779
4779
  'data-invalid-syntax': 'codeblock',
4780
4780
  'data-invalid-type': !closer ? 'closer' : 'argument',
4781
- 'data-invalid-description': !closer ? `Missing the closing delimiter "${ delim }".` : 'Invalid argument.'
4781
+ 'data-invalid-message': !closer ? `Missing the closing delimiter "${ delim }"` : 'Invalid argument'
4782
4782
  }, `${ opener }${ body }${ closer }`)];
4783
4783
  const file = (_a = path.split('/').pop()) !== null && _a !== void 0 ? _a : '';
4784
4784
  const ext = file && file.includes('.', 1) ? file.split('.').pop() : '';
@@ -4916,7 +4916,7 @@ require = function () {
4916
4916
  translate: 'no',
4917
4917
  'data-invalid-syntax': 'aside',
4918
4918
  'data-invalid-type': !closer ? 'closer' : 'argument',
4919
- 'data-invalid-description': !closer ? `Missing the closing delimiter "${ delim }".` : 'Invalid argument.'
4919
+ 'data-invalid-message': !closer ? `Missing the closing delimiter "${ delim }"` : 'Invalid argument'
4920
4920
  }, `${ opener }${ body }${ closer }`)];
4921
4921
  const annotations = (0, typed_dom_1.html)('ol', { class: 'annotations' });
4922
4922
  const references = (0, typed_dom_1.html)('ol', { class: 'references' });
@@ -4934,7 +4934,7 @@ require = function () {
4934
4934
  translate: 'no',
4935
4935
  'data-invalid-syntax': 'aside',
4936
4936
  'data-invalid-type': 'content',
4937
- 'data-invalid-description': 'Missing the title at the first line.'
4937
+ 'data-invalid-message': 'Missing the title at the first line'
4938
4938
  }, `${ opener }${ body }${ closer }`)];
4939
4939
  return [(0, typed_dom_1.html)('aside', {
4940
4940
  id: (0, indexee_1.identity)((0, indexee_1.text)(heading)),
@@ -4971,7 +4971,7 @@ require = function () {
4971
4971
  translate: 'no',
4972
4972
  'data-invalid-syntax': 'example',
4973
4973
  'data-invalid-type': !closer ? 'closer' : 'argument',
4974
- 'data-invalid-description': !closer ? `Missing the closing delimiter "${ delim }".` : 'Invalid argument.'
4974
+ 'data-invalid-message': !closer ? `Missing the closing delimiter "${ delim }"` : 'Invalid argument'
4975
4975
  }, `${ opener }${ body }${ closer }`)];
4976
4976
  switch (type) {
4977
4977
  case 'markdown': {
@@ -5011,7 +5011,7 @@ require = function () {
5011
5011
  class: 'invalid',
5012
5012
  translate: 'no',
5013
5013
  'data-invalid-syntax': 'example',
5014
- 'data-invalid-description': 'Invalid example type.'
5014
+ 'data-invalid-message': 'Invalid example type'
5015
5015
  }, `${ opener }${ body }${ closer }`)];
5016
5016
  }
5017
5017
  }))));
@@ -5102,6 +5102,8 @@ require = function () {
5102
5102
  const combinator_1 = _dereq_('../../../combinator');
5103
5103
  const source_1 = _dereq_('../../source');
5104
5104
  const label_1 = _dereq_('../../inline/extension/label');
5105
+ const ulist_1 = _dereq_('../ulist');
5106
+ const olist_1 = _dereq_('../olist');
5105
5107
  const table_1 = _dereq_('../table');
5106
5108
  const codeblock_1 = _dereq_('../codeblock');
5107
5109
  const mathblock_1 = _dereq_('../mathblock');
@@ -5140,6 +5142,8 @@ require = function () {
5140
5142
  ])),
5141
5143
  (0, combinator_1.inits)([
5142
5144
  (0, combinator_1.block)((0, combinator_1.union)([
5145
+ ulist_1.ulist,
5146
+ olist_1.olist,
5143
5147
  table_1.table,
5144
5148
  codeblock_1.codeblock,
5145
5149
  mathblock_1.mathblock,
@@ -5170,15 +5174,15 @@ require = function () {
5170
5174
  ...invalidLabel && {
5171
5175
  'data-invalid-syntax': 'figure',
5172
5176
  'data-invalid-type': 'label',
5173
- 'data-invalid-description': 'The last part of the fixed label numbers must not be 0.'
5177
+ 'data-invalid-message': 'The last part of the fixed label numbers must not be 0'
5174
5178
  } || invalidParam && {
5175
5179
  'data-invalid-syntax': 'figure',
5176
5180
  'data-invalid-type': 'argument',
5177
- 'data-invalid-description': 'Invalid argument.'
5181
+ 'data-invalid-message': 'Invalid argument'
5178
5182
  } || invalidContent && {
5179
5183
  'data-invalid-syntax': 'figure',
5180
5184
  'data-invalid-type': 'content',
5181
- 'data-invalid-description': 'A figure labeled to define a formula number can contain only a math formula and no caption.'
5185
+ 'data-invalid-message': 'A figure labeled to define a formula number can contain only a math formula and no caption'
5182
5186
  } || global_1.undefined
5183
5187
  };
5184
5188
  }
@@ -5193,7 +5197,9 @@ require = function () {
5193
5197
  '../blockquote': 64,
5194
5198
  '../codeblock': 65,
5195
5199
  '../mathblock': 79,
5200
+ '../olist': 80,
5196
5201
  '../table': 85,
5202
+ '../ulist': 86,
5197
5203
  './example': 69,
5198
5204
  './placeholder': 74,
5199
5205
  './table': 75,
@@ -5229,7 +5235,7 @@ require = function () {
5229
5235
  translate: 'no',
5230
5236
  'data-invalid-syntax': 'message',
5231
5237
  'data-invalid-type': !closer ? 'closer' : 'argument',
5232
- 'data-invalid-description': !closer ? `Missing the closing delimiter "${ delim }".` : 'Invalid argument.'
5238
+ 'data-invalid-message': !closer ? `Missing the closing delimiter "${ delim }"` : 'Invalid argument'
5233
5239
  }, `${ opener }${ body }${ closer }`)];
5234
5240
  switch (type) {
5235
5241
  case 'note':
@@ -5241,7 +5247,7 @@ require = function () {
5241
5247
  class: 'invalid',
5242
5248
  translate: 'no',
5243
5249
  'data-invalid-syntax': 'message',
5244
- 'data-invalid-description': 'Invalid message type.'
5250
+ 'data-invalid-message': 'Invalid message type'
5245
5251
  }, `${ opener }${ body }${ closer }`)];
5246
5252
  }
5247
5253
  return [(0, typed_dom_1.html)('div', { class: `message type-${ type }` }, (0, array_1.unshift)([(0, typed_dom_1.html)('h6', title(type))], [...(0, segment_1.segment)(body)].reduce((acc, seg) => (0, array_1.push)(acc, (0, parser_1.eval)(content(seg, context), [])), [])))];
@@ -5300,7 +5306,7 @@ require = function () {
5300
5306
  translate: 'no',
5301
5307
  'data-invalid-syntax': 'extension',
5302
5308
  'data-invalid-type': !closer ? 'closer' : 'syntax',
5303
- 'data-invalid-description': !closer ? `Missing the closing delimiter "${ delim }".` : 'Invalid syntax.'
5309
+ 'data-invalid-message': !closer ? `Missing the closing delimiter "${ delim }"` : 'Invalid syntax'
5304
5310
  }, `${ opener }${ body }${ closer }`)])));
5305
5311
  },
5306
5312
  {
@@ -5334,16 +5340,16 @@ require = function () {
5334
5340
  translate: 'no',
5335
5341
  'data-invalid-syntax': 'table',
5336
5342
  'data-invalid-type': !closer ? 'closer' : 'argument',
5337
- 'data-invalid-description': !closer ? `Missing the closing delimiter "${ delim }".` : 'Invalid argument.'
5343
+ 'data-invalid-message': !closer ? `Missing the closing delimiter "${ delim }"` : 'Invalid argument'
5338
5344
  }, `${ opener }${ body }${ closer }`)];
5339
5345
  return (_a = (0, parser_1.eval)(parser(body, context))) !== null && _a !== void 0 ? _a : [(0, typed_dom_1.html)('table')];
5340
- }), (source, _, reason) => reason instanceof Error && reason.message === 'Number of columns must be 32 or less.' ? [
5346
+ }), (source, _, reason) => reason instanceof Error && reason.message === 'Number of columns must be 32 or less' ? [
5341
5347
  [(0, typed_dom_1.html)('pre', {
5342
5348
  class: 'invalid',
5343
5349
  translate: 'no',
5344
5350
  'data-invalid-syntax': 'table',
5345
5351
  'data-invalid-type': 'content',
5346
- 'data-invalid-description': reason.message
5352
+ 'data-invalid-message': reason.message
5347
5353
  }, source)],
5348
5354
  ''
5349
5355
  ] : (() => {
@@ -5390,7 +5396,7 @@ require = function () {
5390
5396
  ...valid ? { 'data-highlight-level': +highlight > 1 ? highlight : global_1.undefined } : {
5391
5397
  'data-invalid-syntax': 'table',
5392
5398
  'data-invalid-type': 'syntax',
5393
- 'data-invalid-description': 'Too much highlight level.'
5399
+ 'data-invalid-message': 'Too much highlight level'
5394
5400
  }
5395
5401
  };
5396
5402
  }
@@ -5528,7 +5534,7 @@ require = function () {
5528
5534
  valigns[j] && cell.setAttribute('valign', valigns[j]);
5529
5535
  }
5530
5536
  if (cells.length > 32)
5531
- throw new Error('Number of columns must be 32 or less.');
5537
+ throw new Error('Number of columns must be 32 or less');
5532
5538
  target.appendChild(row);
5533
5539
  switch (target) {
5534
5540
  case thead:
@@ -5669,7 +5675,7 @@ require = function () {
5669
5675
  class: 'invalid',
5670
5676
  'data-invalid-syntax': 'list',
5671
5677
  'data-invalid-type': 'syntax',
5672
- 'data-invalid-description': 'Use "-" instead of "+" or "*".'
5678
+ 'data-invalid-message': 'Use "-" instead of "+" or "*"'
5673
5679
  }, es)])));
5674
5680
  },
5675
5681
  {
@@ -5706,7 +5712,7 @@ require = function () {
5706
5712
  translate: 'no',
5707
5713
  'data-invalid-syntax': 'mathblock',
5708
5714
  'data-invalid-type': delim.length > 2 ? 'syntax' : !closer ? 'closer' : 'argument',
5709
- 'data-invalid-description': delim.length > 2 ? 'Invalid syntax' : !closer ? `Missing the closing delimiter "${ delim }".` : 'Invalid argument.'
5715
+ 'data-invalid-message': delim.length > 2 ? 'Invalid syntax' : !closer ? `Missing the closing delimiter "${ delim }"` : 'Invalid argument'
5710
5716
  }, `${ opener }${ body }${ closer }`)];
5711
5717
  })));
5712
5718
  },
@@ -5770,7 +5776,7 @@ require = function () {
5770
5776
  class: 'invalid',
5771
5777
  'data-invalid-syntax': 'listitem',
5772
5778
  'data-invalid-type': 'syntax',
5773
- 'data-invalid-description': 'Fix the indent or the head of the list item.'
5779
+ 'data-invalid-message': 'Fix the indent or the head of the list item'
5774
5780
  }, source.replace('\n', ''))
5775
5781
  ],
5776
5782
  ''
@@ -5963,7 +5969,7 @@ require = function () {
5963
5969
  class: 'quote invalid',
5964
5970
  'data-invalid-syntax': 'quote',
5965
5971
  'data-invalid-type': 'syntax',
5966
- 'data-invalid-description': `Missing the whitespace after "${ ns[0].split(/[^>]/, 1)[0] }".`
5972
+ 'data-invalid-message': `Missing the whitespace after "${ ns[0].split(/[^>]/, 1)[0] }"`
5967
5973
  }, (0, typed_dom_1.defrag)(ns)),
5968
5974
  (0, typed_dom_1.html)('br')
5969
5975
  ]), false)));
@@ -6037,7 +6043,7 @@ require = function () {
6037
6043
  class: 'invalid',
6038
6044
  'data-invalid-syntax': 'tablerow',
6039
6045
  'data-invalid-type': 'syntax',
6040
- 'data-invalid-description': 'Invalid table row.'
6046
+ 'data-invalid-message': 'Invalid table row'
6041
6047
  }, [(0, typed_dom_1.html)('td', source.replace('\n', ''))])],
6042
6048
  ''
6043
6049
  ])));
@@ -6119,7 +6125,7 @@ require = function () {
6119
6125
  class: 'invalid',
6120
6126
  'data-invalid-syntax': 'listitem',
6121
6127
  'data-invalid-type': 'syntax',
6122
- 'data-invalid-description': 'Fix the indent or the head of the list item.'
6128
+ 'data-invalid-message': 'Fix the indent or the head of the list item'
6123
6129
  }, source.replace('\n', ''))],
6124
6130
  ''
6125
6131
  ]);
@@ -6182,7 +6188,7 @@ require = function () {
6182
6188
  translate: 'no',
6183
6189
  'data-invalid-syntax': 'header',
6184
6190
  'data-invalid-type': 'syntax',
6185
- 'data-invalid-description': 'Invalid syntax.'
6191
+ 'data-invalid-message': 'Invalid syntax'
6186
6192
  }, (0, normalize_1.normalize)(source))],
6187
6193
  ''
6188
6194
  ]
@@ -7127,7 +7133,7 @@ require = function () {
7127
7133
  class: 'invalid',
7128
7134
  'data-invalid-syntax': 'extension',
7129
7135
  'data-invalid-type': 'syntax',
7130
- 'data-invalid-description': 'Invalid symbol.'
7136
+ 'data-invalid-message': 'Invalid symbol'
7131
7137
  }, (0, typed_dom_1.defrag)(bs))],
7132
7138
  rest
7133
7139
  ], ([as, bs], rest) => [
@@ -7235,37 +7241,37 @@ require = function () {
7235
7241
  function elem(tag, as, bs, cs, context) {
7236
7242
  var _a, _b, _c, _d, _e, _f;
7237
7243
  if (!tags.includes(tag))
7238
- return invalid('tag', `Invalid HTML tag <${ tag }>.`, as, bs, cs);
7244
+ return invalid('tag', `Invalid HTML tag <${ tag }>`, as, bs, cs);
7239
7245
  switch (tag) {
7240
7246
  case 'sup':
7241
7247
  case 'sub':
7242
7248
  switch (true) {
7243
7249
  case (_b = (_a = context.state) === null || _a === void 0 ? void 0 : _a.in) === null || _b === void 0 ? void 0 : _b.supsub:
7244
- return invalid('nest', `<${ tag }> HTML tag cannot be used in <sup> or <sub> HTML tag.`, as, bs, cs);
7250
+ return invalid('nest', `<${ tag }> HTML tag cannot be used in <sup> or <sub> HTML tag`, as, bs, cs);
7245
7251
  }
7246
7252
  break;
7247
7253
  case 'small':
7248
7254
  switch (true) {
7249
7255
  case (_d = (_c = context.state) === null || _c === void 0 ? void 0 : _c.in) === null || _d === void 0 ? void 0 : _d.supsub:
7250
7256
  case (_f = (_e = context.state) === null || _e === void 0 ? void 0 : _e.in) === null || _f === void 0 ? void 0 : _f.small:
7251
- return invalid('nest', `<${ tag }> HTML tag cannot be used in <sup>, <sub>, or <small> HTML tag.`, as, bs, cs);
7257
+ return invalid('nest', `<${ tag }> HTML tag cannot be used in <sup>, <sub>, or <small> HTML tag`, as, bs, cs);
7252
7258
  }
7253
7259
  break;
7254
7260
  }
7255
7261
  let attrs;
7256
7262
  switch (true) {
7257
7263
  case 'data-invalid-syntax' in (attrs = attributes('html', [], attrspec[tag], as.slice(1, -1))):
7258
- return invalid('attribute', 'Invalid HTML attribute.', as, bs, cs);
7264
+ return invalid('attribute', 'Invalid HTML attribute', as, bs, cs);
7259
7265
  default:
7260
7266
  return (0, typed_dom_1.html)(tag, attrs, bs);
7261
7267
  }
7262
7268
  }
7263
- function invalid(type, description, as, bs, cs) {
7269
+ function invalid(type, message, as, bs, cs) {
7264
7270
  return (0, typed_dom_1.html)('span', {
7265
7271
  class: 'invalid',
7266
7272
  'data-invalid-syntax': 'html',
7267
7273
  'data-invalid-type': type,
7268
- 'data-invalid-description': description
7274
+ 'data-invalid-message': message
7269
7275
  }, (0, typed_dom_1.defrag)((0, array_1.push)((0, array_1.unshift)(as, bs), cs)));
7270
7276
  }
7271
7277
  const requiredAttributes = (0, memoize_1.memoize)(spec => (0, alias_1.ObjectEntries)(spec).flatMap(([k, v]) => v && (0, alias_1.isFrozen)(v) ? [k] : []), new WeakMap());
@@ -7289,7 +7295,7 @@ require = function () {
7289
7295
  attrs['class'] = (0, array_1.join)(classes, ' ');
7290
7296
  attrs['data-invalid-syntax'] = syntax;
7291
7297
  attrs['data-invalid-type'] = 'argument';
7292
- attrs['data-invalid-description'] = 'Invalid argument.';
7298
+ attrs['data-invalid-message'] = 'Invalid argument';
7293
7299
  }
7294
7300
  return attrs;
7295
7301
  }
@@ -7328,7 +7334,7 @@ require = function () {
7328
7334
  class: 'invalid',
7329
7335
  'data-invalid-syntax': 'htmlentity',
7330
7336
  'data-invalid-type': 'syntax',
7331
- 'data-invalid-description': 'Invalid HTML entity.'
7337
+ 'data-invalid-message': 'Invalid HTML entity'
7332
7338
  }, test.slice(1)) : test]);
7333
7339
  const parse = (0, memoize_1.reduce)((el => entity => {
7334
7340
  if (entity === '&NewLine;')
@@ -7462,13 +7468,13 @@ require = function () {
7462
7468
  exports.resolve = resolve;
7463
7469
  function elem(INSECURE_URI, content, uri, origin) {
7464
7470
  let type;
7465
- let description;
7471
+ let message;
7466
7472
  switch (uri.protocol) {
7467
7473
  case 'http:':
7468
7474
  case 'https:':
7469
7475
  if (INSECURE_URI.slice(0, 2) === '^/' && /\/\.\.?(?:\/|$)/.test(INSECURE_URI.slice(0, INSECURE_URI.search(/[?#]|$/)))) {
7470
7476
  type = 'argument';
7471
- description = 'Dot-segments cannot be used in subresource paths.';
7477
+ message = 'Dot-segments cannot be used in subresource paths';
7472
7478
  break;
7473
7479
  }
7474
7480
  return (0, typed_dom_1.html)('a', {
@@ -7485,14 +7491,14 @@ require = function () {
7485
7491
  return (0, typed_dom_1.html)('a', { href: uri.source }, content);
7486
7492
  }
7487
7493
  type = 'content';
7488
- description = 'Invalid phone number.';
7494
+ message = 'Invalid phone number';
7489
7495
  break;
7490
7496
  }
7491
7497
  return (0, typed_dom_1.html)('a', {
7492
7498
  class: 'invalid',
7493
7499
  'data-invalid-syntax': 'link',
7494
7500
  'data-invalid-type': type !== null && type !== void 0 ? type : type = 'argument',
7495
- 'data-invalid-description': description !== null && description !== void 0 ? description : description = 'Invalid protocol.'
7501
+ 'data-invalid-message': message !== null && message !== void 0 ? message : message = 'Invalid protocol'
7496
7502
  }, content.length === 0 ? INSECURE_URI : content);
7497
7503
  }
7498
7504
  function decode(uri) {
@@ -7576,7 +7582,7 @@ require = function () {
7576
7582
  translate: 'no',
7577
7583
  'data-invalid-syntax': 'math',
7578
7584
  'data-invalid-type': 'content',
7579
- 'data-invalid-description': `"${ source.match(disallowedCommand)[0] }" command is disallowed.`
7585
+ 'data-invalid-message': `"${ source.match(disallowedCommand)[0] }" command is disallowed`
7580
7586
  }, source)],
7581
7587
  ''
7582
7588
  ];
@@ -7708,7 +7714,7 @@ require = function () {
7708
7714
  class: void target.classList.add('invalid'),
7709
7715
  'data-invalid-syntax': 'media',
7710
7716
  'data-invalid-type': 'argument',
7711
- 'data-invalid-description': 'Dot-segments cannot be used in media paths; use subresource paths instead.'
7717
+ 'data-invalid-message': 'Dot-segments cannot be used in media paths; use subresource paths instead'
7712
7718
  });
7713
7719
  return false;
7714
7720
  }
@@ -7718,7 +7724,7 @@ require = function () {
7718
7724
  class: void target.classList.add('invalid'),
7719
7725
  'data-invalid-syntax': 'media',
7720
7726
  'data-invalid-type': 'argument',
7721
- 'data-invalid-description': 'Invalid protocol.'
7727
+ 'data-invalid-message': 'Invalid protocol'
7722
7728
  });
7723
7729
  return false;
7724
7730
  }
@@ -7727,7 +7733,7 @@ require = function () {
7727
7733
  class: void target.classList.add('invalid'),
7728
7734
  'data-invalid-syntax': 'media',
7729
7735
  'data-invalid-type': 'content',
7730
- 'data-invalid-description': `Cannot use invalid HTML entitiy "${ alt.match(/&[0-9A-Za-z]+;/)[0] }".`,
7736
+ 'data-invalid-message': `Cannot use invalid HTML entitiy "${ alt.match(/&[0-9A-Za-z]+;/)[0] }"`,
7731
7737
  alt: (_a = target.getAttribute('alt')) === null || _a === void 0 ? void 0 : _a.replace(/\0/g, '')
7732
7738
  });
7733
7739
  return false;
@@ -7791,7 +7797,7 @@ require = function () {
7791
7797
  class: 'invalid',
7792
7798
  'data-invalid-syntax': 'reference',
7793
7799
  'data-invalid-type': 'syntax',
7794
- 'data-invalid-description': 'Invalid abbr.'
7800
+ 'data-invalid-message': 'Invalid abbr'
7795
7801
  } : { class: 'reference' };
7796
7802
  }
7797
7803
  },
@@ -7898,7 +7904,7 @@ require = function () {
7898
7904
  class: 'invalid',
7899
7905
  'data-invalid-syntax': 'ruby',
7900
7906
  'data-invalid-type': ss === texts ? 'content' : 'argument',
7901
- 'data-invalid-description': 'Invalid HTML entity.'
7907
+ 'data-invalid-message': 'Invalid HTML entity'
7902
7908
  };
7903
7909
  }
7904
7910
  }
@@ -8122,6 +8128,7 @@ require = function () {
8122
8128
  el.getAttribute('data-label'),
8123
8129
  el
8124
8130
  ]));
8131
+ const labels = new global_1.Set();
8125
8132
  const numbers = new global_1.Map();
8126
8133
  let base = '0';
8127
8134
  let bases = base.split('.');
@@ -8166,6 +8173,26 @@ require = function () {
8166
8173
  opts.id !== '' && def.setAttribute('id', `label:${ opts.id ? `${ opts.id }:` : '' }${ label }`);
8167
8174
  const figindex = group === '$' ? `(${ number })` : `${ capitalize(group) }${ group === 'fig' ? '.' : '' } ${ number }`;
8168
8175
  (0, typed_dom_1.define)(def.querySelector(':scope > figcaption > .figindex'), group === '$' ? figindex : `${ figindex }. `);
8176
+ if (labels.has(label)) {
8177
+ if (def.classList.contains('invalid') && def.getAttribute('data-invalid-message') !== 'Duplicate label')
8178
+ continue;
8179
+ (0, typed_dom_1.define)(def, {
8180
+ id: null,
8181
+ class: void def.classList.add('invalid'),
8182
+ 'data-invalid-syntax': 'figure',
8183
+ 'data-invalid-type': 'argument',
8184
+ 'data-invalid-message': 'Duplicate label'
8185
+ });
8186
+ continue;
8187
+ } else {
8188
+ labels.add(label);
8189
+ (0, typed_dom_1.define)(def, {
8190
+ class: void def.classList.remove('invalid'),
8191
+ 'data-invalid-syntax': null,
8192
+ 'data-invalid-type': null,
8193
+ 'data-invalid-message': null
8194
+ });
8195
+ }
8169
8196
  for (const ref of refs.take(label, global_1.Infinity)) {
8170
8197
  if (ref.hash.slice(1) === def.id && ref.innerText === figindex)
8171
8198
  continue;
@@ -8178,7 +8205,7 @@ require = function () {
8178
8205
  class: `${ ref.className } disabled invalid`,
8179
8206
  'data-invalid-syntax': 'label',
8180
8207
  'data-invalid-type': 'reference',
8181
- 'data-invalid-description': 'Missing the reference.'
8208
+ 'data-invalid-message': 'Missing the reference'
8182
8209
  });
8183
8210
  }
8184
8211
  yield ref;
@@ -8253,7 +8280,7 @@ require = function () {
8253
8280
  class: `${ ref.className } invalid`,
8254
8281
  'data-invalid-syntax': syntax,
8255
8282
  'data-invalid-type': 'style',
8256
- 'data-invalid-description': `${ syntax[0].toUpperCase() + syntax.slice(1) } style must be consistent.`
8283
+ 'data-invalid-message': `${ syntax[0].toUpperCase() + syntax.slice(1) } style must be consistent`
8257
8284
  });
8258
8285
  }
8259
8286
  if (((_a = ref.firstElementChild) === null || _a === void 0 ? void 0 : _a.getAttribute('hidden')) !== '') {
@@ -8280,7 +8307,7 @@ require = function () {
8280
8307
  class: void ref.classList.remove('invalid'),
8281
8308
  'data-invalid-syntax': null,
8282
8309
  'data-invalid-type': null,
8283
- 'data-invalid-description': null
8310
+ 'data-invalid-message': null
8284
8311
  });
8285
8312
  }
8286
8313
  }
@@ -8293,7 +8320,7 @@ require = function () {
8293
8320
  class: void ref.classList.add('invalid'),
8294
8321
  'data-invalid-syntax': syntax,
8295
8322
  'data-invalid-type': 'content',
8296
- 'data-invalid-description': 'Missing the content.'
8323
+ 'data-invalid-message': 'Missing the content'
8297
8324
  }
8298
8325
  });
8299
8326
  yield ref.appendChild((0, typed_dom_1.html)('a', { href: refId && defId && `#${ defId }` }, marker(defIndex, abbr)));
package/markdown.d.ts CHANGED
@@ -361,6 +361,8 @@ export namespace MarkdownParser {
361
361
  ]>,
362
362
  Parser<HTMLElement | string, Context, [
363
363
  Parser<HTMLElement | string, Context, [
364
+ UListParser,
365
+ OListParser,
364
366
  BlockParser.TableParser,
365
367
  CodeBlockParser,
366
368
  MathBlockParser,
package/package-lock.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.235.3",
3
+ "version": "0.236.0",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {
@@ -6171,9 +6171,9 @@
6171
6171
  "dev": true
6172
6172
  },
6173
6173
  "is-number-object": {
6174
- "version": "1.0.6",
6175
- "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz",
6176
- "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==",
6174
+ "version": "1.0.7",
6175
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
6176
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
6177
6177
  "dev": true,
6178
6178
  "requires": {
6179
6179
  "has-tostringtag": "^1.0.0"
@@ -6232,10 +6232,13 @@
6232
6232
  }
6233
6233
  },
6234
6234
  "is-shared-array-buffer": {
6235
- "version": "1.0.1",
6236
- "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz",
6237
- "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==",
6238
- "dev": true
6235
+ "version": "1.0.2",
6236
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
6237
+ "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
6238
+ "dev": true,
6239
+ "requires": {
6240
+ "call-bind": "^1.0.2"
6241
+ }
6239
6242
  },
6240
6243
  "is-stream": {
6241
6244
  "version": "2.0.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.235.3",
3
+ "version": "0.236.0",
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",
package/src/debug.test.ts CHANGED
@@ -7,11 +7,13 @@ export function inspect(result: Result<HTMLElement | string>, until: number | st
7
7
  assert(node);
8
8
  if (typeof node === 'string') return node;
9
9
  node = node.cloneNode(true);
10
+ assert(!node.matches('.invalid[data-invalid-message$="."]'));
11
+ assert(!node.querySelector('.invalid[data-invalid-message$="."]'));
10
12
  [node, ...node.querySelectorAll('.invalid')].forEach(el =>
11
13
  define(el, {
12
14
  'data-invalid-syntax': null,
13
15
  'data-invalid-type': null,
14
- 'data-invalid-description': null,
16
+ 'data-invalid-message': null,
15
17
  }));
16
18
  until = typeof until === 'number'
17
19
  ? until
@@ -190,7 +190,7 @@ describe('Unit: parser/api/parse', () => {
190
190
  ].join('\n\n'), { host: new URL(`${location.origin}/z`) }).children].map(el => el.outerHTML),
191
191
  [
192
192
  `<details class="header" open=""><summary>Header</summary><span class="field" data-name="URL" data-value="https://example/x"><span class="field-name">URL</span>: <span class="field-value">https://example/x</span>\n</span></details>`,
193
- '<pre class="invalid" translate="no" data-invalid-syntax="header" data-invalid-type="syntax" data-invalid-description="Invalid syntax.">---\nURL: https://example/y\n---\n</pre>',
193
+ '<pre class="invalid" translate="no" data-invalid-syntax="header" data-invalid-type="syntax" data-invalid-message="Invalid syntax">---\nURL: https://example/y\n---\n</pre>',
194
194
  '<aside class="example" data-type="markdown"><pre translate="no">---\nURL: https://example/y\n---\n\n{#}</pre><hr><section><details class="header" open=""><summary>Header</summary><span class="field" data-name="URL" data-value="https://example/y"><span class="field-name">URL</span>: <span class="field-value">https://example/y</span>\n</span></details><p><a href="https://example/y#" target="_blank">#</a></p><ol class="annotations"></ol><ol class="references"></ol></section></aside>',
195
195
  '<p><a href="https://example/x#" target="_blank">#</a></p>',
196
196
  ]);
@@ -30,7 +30,7 @@ export const codeblock: CodeBlockParser = block(validate('```', fmap(
30
30
  translate: 'no',
31
31
  'data-invalid-syntax': 'codeblock',
32
32
  'data-invalid-type': !closer ? 'closer' : 'argument',
33
- 'data-invalid-description': !closer ? `Missing the closing delimiter "${delim}".` : 'Invalid argument.',
33
+ 'data-invalid-message': !closer ? `Missing the closing delimiter "${delim}"` : 'Invalid argument',
34
34
  }, `${opener}${body}${closer}`)];
35
35
  const file = path.split('/').pop() ?? '';
36
36
  const ext = file && file.includes('.', 1)
@@ -13,7 +13,7 @@ export const aside: ExtensionParser.AsideParser = creator(100, block(validate('~
13
13
  translate: 'no',
14
14
  'data-invalid-syntax': 'aside',
15
15
  'data-invalid-type': !closer ? 'closer' : 'argument',
16
- 'data-invalid-description': !closer ? `Missing the closing delimiter "${delim}".` : 'Invalid argument.',
16
+ 'data-invalid-message': !closer ? `Missing the closing delimiter "${delim}"` : 'Invalid argument',
17
17
  }, `${opener}${body}${closer}`)];
18
18
  const annotations = html('ol', { class: 'annotations' });
19
19
  const references = html('ol', { class: 'references' });
@@ -33,7 +33,7 @@ export const aside: ExtensionParser.AsideParser = creator(100, block(validate('~
33
33
  translate: 'no',
34
34
  'data-invalid-syntax': 'aside',
35
35
  'data-invalid-type': 'content',
36
- 'data-invalid-description': 'Missing the title at the first line.',
36
+ 'data-invalid-message': 'Missing the title at the first line',
37
37
  }, `${opener}${body}${closer}`)];
38
38
  assert(identity(text(heading)));
39
39
  return [
@@ -16,7 +16,7 @@ export const example: ExtensionParser.ExampleParser = creator(100, block(validat
16
16
  translate: 'no',
17
17
  'data-invalid-syntax': 'example',
18
18
  'data-invalid-type': !closer ? 'closer' : 'argument',
19
- 'data-invalid-description': !closer ? `Missing the closing delimiter "${delim}".` : 'Invalid argument.',
19
+ 'data-invalid-message': !closer ? `Missing the closing delimiter "${delim}"` : 'Invalid argument',
20
20
  }, `${opener}${body}${closer}`)];
21
21
  switch (type) {
22
22
  case 'markdown': {
@@ -52,7 +52,7 @@ export const example: ExtensionParser.ExampleParser = creator(100, block(validat
52
52
  class: 'invalid',
53
53
  translate: 'no',
54
54
  'data-invalid-syntax': 'example',
55
- 'data-invalid-description': 'Invalid example type.',
55
+ 'data-invalid-message': 'Invalid example type',
56
56
  }, `${opener}${body}${closer}`),
57
57
  ];
58
58
  }
@@ -37,6 +37,8 @@ describe('Unit: parser/block/extension/figure', () => {
37
37
  assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\n\n\n~~~')), [['<figure data-label="group-name" data-group="group"><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt=""></a></div><figcaption><span class="figindex"></span></figcaption></figure>'], '']);
38
38
  assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\n\n\\\n~~~')), [['<figure data-label="group-name" data-group="group"><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt=""></a></div><figcaption><span class="figindex"></span>\\</figcaption></figure>'], '']);
39
39
  assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\n\n!https://caption\n~~~')), [['<figure data-label="group-name" data-group="group"><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt=""></a></div><figcaption><span class="figindex"></span>!<a href="https://caption" target="_blank">https://caption</a></figcaption></figure>'], '']);
40
+ assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n- a\n~~~')), [['<figure data-label="group-name" data-group="group"><div><ul><li>a</li></ul></div><figcaption><span class="figindex"></span></figcaption></figure>'], '']);
41
+ assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n1. a\n~~~')), [['<figure data-label="group-name" data-group="group"><div><ol><li>a</li></ol></div><figcaption><span class="figindex"></span></figcaption></figure>'], '']);
40
42
  assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n|\n|-\n|\n~~~')), [['<figure data-label="group-name" data-group="group"><div><table><thead><tr></tr></thead><tbody><tr></tr></tbody></table></div><figcaption><span class="figindex"></span></figcaption></figure>'], '']);
41
43
  assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n```\n\n```\n~~~')), [['<figure data-label="group-name" data-group="group"><div><pre class="text" translate="no"></pre></div><figcaption><span class="figindex"></span></figcaption></figure>'], '']);
42
44
  assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n```\n~~~\n```\n\n~~~')), [['<figure data-label="group-name" data-group="group"><div><pre class="text" translate="no">~~~</pre></div><figcaption><span class="figindex"></span></figcaption></figure>'], '']);
@@ -3,6 +3,8 @@ import { ExtensionParser } from '../../block';
3
3
  import { union, inits, sequence, some, block, line, rewrite, context, close, match, convert, trim, fmap } from '../../../combinator';
4
4
  import { str, contentline, emptyline } from '../../source';
5
5
  import { label, segment as seg_label } from '../../inline/extension/label';
6
+ import { ulist } from '../ulist';
7
+ import { olist } from '../olist';
6
8
  import { table as styled_table } from '../table';
7
9
  import { codeblock, segment_ as seg_code } from '../codeblock';
8
10
  import { mathblock, segment_ as seg_math } from '../mathblock';
@@ -52,6 +54,8 @@ export const figure: FigureParser = block(rewrite(segment, fmap(
52
54
  line(sequence([label, str(/^.*\n/)])),
53
55
  inits([
54
56
  block(union([
57
+ ulist,
58
+ olist,
55
59
  styled_table,
56
60
  codeblock,
57
61
  mathblock,
@@ -93,17 +97,17 @@ function attributes(label: string, param: string, content: HTMLElement, caption:
93
97
  invalidLabel && {
94
98
  'data-invalid-syntax': 'figure',
95
99
  'data-invalid-type': 'label',
96
- 'data-invalid-description': 'The last part of the fixed label numbers must not be 0.',
100
+ 'data-invalid-message': 'The last part of the fixed label numbers must not be 0',
97
101
  } ||
98
102
  invalidParam && {
99
103
  'data-invalid-syntax': 'figure',
100
104
  'data-invalid-type': 'argument',
101
- 'data-invalid-description': 'Invalid argument.',
105
+ 'data-invalid-message': 'Invalid argument',
102
106
  } ||
103
107
  invalidContent && {
104
108
  'data-invalid-syntax': 'figure',
105
109
  'data-invalid-type': 'content',
106
- 'data-invalid-description': 'A figure labeled to define a formula number can contain only a math formula and no caption.',
110
+ 'data-invalid-message': 'A figure labeled to define a formula number can contain only a math formula and no caption',
107
111
  } ||
108
112
  undefined,
109
113
  };
@@ -25,7 +25,7 @@ export const message: MessageParser = block(validate('~~~', fmap(
25
25
  translate: 'no',
26
26
  'data-invalid-syntax': 'message',
27
27
  'data-invalid-type': !closer ? 'closer' : 'argument',
28
- 'data-invalid-description': !closer ? `Missing the closing delimiter "${delim}".` : 'Invalid argument.',
28
+ 'data-invalid-message': !closer ? `Missing the closing delimiter "${delim}"` : 'Invalid argument',
29
29
  }, `${opener}${body}${closer}`)];
30
30
  switch (type) {
31
31
  case 'note':
@@ -37,7 +37,7 @@ export const message: MessageParser = block(validate('~~~', fmap(
37
37
  class: 'invalid',
38
38
  translate: 'no',
39
39
  'data-invalid-syntax': 'message',
40
- 'data-invalid-description': 'Invalid message type.',
40
+ 'data-invalid-message': 'Invalid message type',
41
41
  }, `${opener}${body}${closer}`)];
42
42
  }
43
43
  return [
@@ -18,6 +18,6 @@ export const placeholder: ExtensionParser.PlaceholderParser = block(validate('~~
18
18
  translate: 'no',
19
19
  'data-invalid-syntax': 'extension',
20
20
  'data-invalid-type': !closer ? 'closer' : 'syntax',
21
- 'data-invalid-description': !closer ? `Missing the closing delimiter "${delim}".` : 'Invalid syntax.',
21
+ 'data-invalid-message': !closer ? `Missing the closing delimiter "${delim}"` : 'Invalid syntax',
22
22
  }, `${opener}${body}${closer}`)
23
23
  ])));
@@ -32,19 +32,19 @@ export const table: TableParser = block(validate('~~~', recover(fmap(
32
32
  translate: 'no',
33
33
  'data-invalid-syntax': 'table',
34
34
  'data-invalid-type': !closer ? 'closer' : 'argument',
35
- 'data-invalid-description': !closer ? `Missing the closing delimiter "${delim}".` : 'Invalid argument.',
35
+ 'data-invalid-message': !closer ? `Missing the closing delimiter "${delim}"` : 'Invalid argument',
36
36
  }, `${opener}${body}${closer}`)];
37
37
  return eval(parser(body, context)) ?? [html('table')];
38
38
  }),
39
39
  (source, _, reason) =>
40
- reason instanceof Error && reason.message === 'Number of columns must be 32 or less.'
40
+ reason instanceof Error && reason.message === 'Number of columns must be 32 or less'
41
41
  ? [[
42
42
  html('pre', {
43
43
  class: 'invalid',
44
44
  translate: 'no',
45
45
  'data-invalid-syntax': 'table',
46
46
  'data-invalid-type': 'content',
47
- 'data-invalid-description': reason.message,
47
+ 'data-invalid-message': reason.message,
48
48
  }, source),
49
49
  ], '']
50
50
  : (() => { throw reason; })())));
@@ -128,7 +128,7 @@ function attributes(source: string) {
128
128
  : {
129
129
  'data-invalid-syntax': 'table',
130
130
  'data-invalid-type': 'syntax',
131
- 'data-invalid-description': 'Too much highlight level.',
131
+ 'data-invalid-message': 'Too much highlight level',
132
132
  },
133
133
  };
134
134
  }
@@ -279,7 +279,7 @@ function format(rows: Tree<RowParser>[]): HTMLTableSectionElement[] {
279
279
  aligns[j] && cell.setAttribute('align', aligns[j]);
280
280
  valigns[j] && cell.setAttribute('valign', valigns[j]);
281
281
  }
282
- if (cells.length > 32) throw new Error('Number of columns must be 32 or less.');
282
+ if (cells.length > 32) throw new Error('Number of columns must be 32 or less');
283
283
  target.appendChild(row);
284
284
  switch (target) {
285
285
  case thead:
@@ -27,6 +27,6 @@ export const ilist_: IListParser = lazy(() => block(fmap(validate(
27
27
  class: 'invalid',
28
28
  'data-invalid-syntax': 'list',
29
29
  'data-invalid-type': 'syntax',
30
- 'data-invalid-description': 'Use "-" instead of "+" or "*".',
30
+ 'data-invalid-message': 'Use "-" instead of "+" or "*"',
31
31
  }, es),
32
32
  ])));
@@ -23,6 +23,6 @@ export const mathblock: MathBlockParser = block(validate('$$', fmap(
23
23
  translate: 'no',
24
24
  'data-invalid-syntax': 'mathblock',
25
25
  'data-invalid-type': delim.length > 2 ? 'syntax' : !closer ? 'closer' : 'argument',
26
- 'data-invalid-description': delim.length > 2 ? 'Invalid syntax' : !closer ? `Missing the closing delimiter "${delim}".` : 'Invalid argument.',
26
+ 'data-invalid-message': delim.length > 2 ? 'Invalid syntax' : !closer ? `Missing the closing delimiter "${delim}"` : 'Invalid argument',
27
27
  }, `${opener}${body}${closer}`),
28
28
  ])));
@@ -58,7 +58,7 @@ const iitem = rewrite(contentline, source => [[
58
58
  class: 'invalid',
59
59
  'data-invalid-syntax': 'listitem',
60
60
  'data-invalid-type': 'syntax',
61
- 'data-invalid-description': 'Fix the indent or the head of the list item.',
61
+ 'data-invalid-message': 'Fix the indent or the head of the list item',
62
62
  }, source.replace('\n', ''))
63
63
  ], '']);
64
64
 
@@ -26,7 +26,7 @@ export const quote: ReplyParser.QuoteParser = lazy(() => creator(block(fmap(vali
26
26
  class: 'quote invalid',
27
27
  'data-invalid-syntax': 'quote',
28
28
  'data-invalid-type': 'syntax',
29
- 'data-invalid-description': `Missing the whitespace after "${ns[0].split(/[^>]/, 1)[0]}".`,
29
+ 'data-invalid-message': `Missing the whitespace after "${ns[0].split(/[^>]/, 1)[0]}"`,
30
30
  },
31
31
  defrag(ns)),
32
32
  html('br'),
@@ -31,7 +31,7 @@ const row = <P extends CellParser | AlignParser>(parser: P, optional: boolean):
31
31
  class: 'invalid',
32
32
  'data-invalid-syntax': 'tablerow',
33
33
  'data-invalid-type': 'syntax',
34
- 'data-invalid-description': 'Invalid table row.',
34
+ 'data-invalid-message': 'Invalid table row',
35
35
  }, [html('td', source.replace('\n', ''))])
36
36
  ], ''])));
37
37
 
@@ -36,7 +36,7 @@ const iitem = rewrite(contentline, source => [[
36
36
  class: 'invalid',
37
37
  'data-invalid-syntax': 'listitem',
38
38
  'data-invalid-type': 'syntax',
39
- 'data-invalid-description': 'Fix the indent or the head of the list item.',
39
+ 'data-invalid-message': 'Fix the indent or the head of the list item',
40
40
  }, source.replace('\n', ''))
41
41
  ], '']);
42
42
 
@@ -31,7 +31,7 @@ export const header: MarkdownParser.HeaderParser = lazy(() => validate(
31
31
  translate: 'no',
32
32
  'data-invalid-syntax': 'header',
33
33
  'data-invalid-type': 'syntax',
34
- 'data-invalid-description': 'Invalid syntax.',
34
+ 'data-invalid-message': 'Invalid syntax',
35
35
  }, normalize(source)),
36
36
  ], ''],
37
37
  ]))),
@@ -19,7 +19,7 @@ export const placeholder: ExtensionParser.PlaceholderParser = lazy(() => creator
19
19
  class: 'invalid',
20
20
  'data-invalid-syntax': 'extension',
21
21
  'data-invalid-type': 'syntax',
22
- 'data-invalid-description': 'Invalid symbol.',
22
+ 'data-invalid-message': 'Invalid symbol',
23
23
  }, defrag(bs)),
24
24
  ], rest],
25
25
  ([as, bs], rest) => [unshift(as, bs), rest]))));
@@ -116,38 +116,38 @@ function elem(tag: string, as: string[], bs: (HTMLElement | string)[], cs: strin
116
116
  assert(as[0][0] === '<' && as[as.length - 1].slice(-1) === '>');
117
117
  assert(bs.length === defrag(bs).length);
118
118
  assert(cs.length === 1);
119
- if (!tags.includes(tag)) return invalid('tag', `Invalid HTML tag <${tag}>.`, as, bs, cs);
119
+ if (!tags.includes(tag)) return invalid('tag', `Invalid HTML tag <${tag}>`, as, bs, cs);
120
120
  switch (tag) {
121
121
  case 'sup':
122
122
  case 'sub':
123
123
  switch (true) {
124
124
  case context.state?.in?.supsub:
125
- return invalid('nest', `<${tag}> HTML tag cannot be used in <sup> or <sub> HTML tag.`, as, bs, cs);
125
+ return invalid('nest', `<${tag}> HTML tag cannot be used in <sup> or <sub> HTML tag`, as, bs, cs);
126
126
  }
127
127
  break;
128
128
  case 'small':
129
129
  switch (true) {
130
130
  case context.state?.in?.supsub:
131
131
  case context.state?.in?.small:
132
- return invalid('nest', `<${tag}> HTML tag cannot be used in <sup>, <sub>, or <small> HTML tag.`, as, bs, cs);
132
+ return invalid('nest', `<${tag}> HTML tag cannot be used in <sup>, <sub>, or <small> HTML tag`, as, bs, cs);
133
133
  }
134
134
  break;
135
135
  }
136
136
  let attrs: Record<string, string | undefined> | undefined;
137
137
  switch (true) {
138
138
  case 'data-invalid-syntax' in (attrs = attributes('html', [], attrspec[tag], as.slice(1, -1) as string[])):
139
- return invalid('attribute', 'Invalid HTML attribute.', as, bs, cs);
139
+ return invalid('attribute', 'Invalid HTML attribute', as, bs, cs);
140
140
  default:
141
141
  assert(attrs);
142
142
  return h(tag as 'span', attrs, bs);
143
143
  }
144
144
  }
145
- function invalid(type: string, description: string, as: (HTMLElement | string)[], bs: (HTMLElement | string)[], cs: (HTMLElement | string)[]): HTMLElement {
145
+ function invalid(type: string, message: string, as: (HTMLElement | string)[], bs: (HTMLElement | string)[], cs: (HTMLElement | string)[]): HTMLElement {
146
146
  return h('span', {
147
147
  class: 'invalid',
148
148
  'data-invalid-syntax': 'html',
149
149
  'data-invalid-type': type,
150
- 'data-invalid-description': description,
150
+ 'data-invalid-message': message,
151
151
  }, defrag(push(unshift(as, bs), cs)));
152
152
  }
153
153
 
@@ -187,7 +187,7 @@ export function attributes(
187
187
  attrs['class'] = join(classes, ' ');
188
188
  attrs['data-invalid-syntax'] = syntax;
189
189
  attrs['data-invalid-type'] = 'argument';
190
- attrs['data-invalid-description'] = 'Invalid argument.';
190
+ attrs['data-invalid-message'] = 'Invalid argument';
191
191
  }
192
192
  return attrs;
193
193
  }
@@ -16,7 +16,7 @@ export const htmlentity: HTMLEntityParser = fmap(
16
16
  class: 'invalid',
17
17
  'data-invalid-syntax': 'htmlentity',
18
18
  'data-invalid-type': 'syntax',
19
- 'data-invalid-description': 'Invalid HTML entity.',
19
+ 'data-invalid-message': 'Invalid HTML entity',
20
20
  }, test.slice(1))
21
21
  : test,
22
22
  ]);
@@ -103,7 +103,7 @@ function elem(
103
103
  origin: string,
104
104
  ): HTMLAnchorElement {
105
105
  let type: string;
106
- let description: string;
106
+ let message: string;
107
107
  switch (uri.protocol) {
108
108
  case 'http:':
109
109
  case 'https:':
@@ -111,7 +111,7 @@ function elem(
111
111
  if (INSECURE_URI.slice(0, 2) === '^/' &&
112
112
  /\/\.\.?(?:\/|$)/.test(INSECURE_URI.slice(0, INSECURE_URI.search(/[?#]|$/)))) {
113
113
  type = 'argument';
114
- description = 'Dot-segments cannot be used in subresource paths.';
114
+ message = 'Dot-segments cannot be used in subresource paths';
115
115
  break;
116
116
  }
117
117
  return html('a',
@@ -140,7 +140,7 @@ function elem(
140
140
  return html('a', { href: uri.source }, content);
141
141
  }
142
142
  type = 'content';
143
- description = 'Invalid phone number.';
143
+ message = 'Invalid phone number';
144
144
  break;
145
145
  }
146
146
  return html('a',
@@ -148,7 +148,7 @@ function elem(
148
148
  class: 'invalid',
149
149
  'data-invalid-syntax': 'link',
150
150
  'data-invalid-type': type ??= 'argument',
151
- 'data-invalid-description': description ??= 'Invalid protocol.',
151
+ 'data-invalid-message': message ??= 'Invalid protocol',
152
152
  },
153
153
  content.length === 0
154
154
  ? INSECURE_URI
@@ -29,7 +29,7 @@ export const math: MathParser = lazy(() => creator(validate('$', rewrite(
29
29
  translate: 'no',
30
30
  'data-invalid-syntax': 'math',
31
31
  'data-invalid-type': 'content',
32
- 'data-invalid-description': `"${source.match(disallowedCommand)![0]}" command is disallowed.`,
32
+ 'data-invalid-message': `"${source.match(disallowedCommand)![0]}" command is disallowed`,
33
33
  },
34
34
  source)
35
35
  ], '']))));
@@ -81,7 +81,7 @@ function sanitize(target: HTMLElement, uri: ReadonlyURL, alt: string): boolean {
81
81
  class: void target.classList.add('invalid'),
82
82
  'data-invalid-syntax': 'media',
83
83
  'data-invalid-type': 'argument',
84
- 'data-invalid-description': 'Dot-segments cannot be used in media paths; use subresource paths instead.',
84
+ 'data-invalid-message': 'Dot-segments cannot be used in media paths; use subresource paths instead',
85
85
  });
86
86
  return false;
87
87
  }
@@ -91,7 +91,7 @@ function sanitize(target: HTMLElement, uri: ReadonlyURL, alt: string): boolean {
91
91
  class: void target.classList.add('invalid'),
92
92
  'data-invalid-syntax': 'media',
93
93
  'data-invalid-type': 'argument',
94
- 'data-invalid-description': 'Invalid protocol.',
94
+ 'data-invalid-message': 'Invalid protocol',
95
95
  });
96
96
  return false;
97
97
  }
@@ -100,7 +100,7 @@ function sanitize(target: HTMLElement, uri: ReadonlyURL, alt: string): boolean {
100
100
  class: void target.classList.add('invalid'),
101
101
  'data-invalid-syntax': 'media',
102
102
  'data-invalid-type': 'content',
103
- 'data-invalid-description': `Cannot use invalid HTML entitiy "${alt.match(/&[0-9A-Za-z]+;/)![0]}".`,
103
+ 'data-invalid-message': `Cannot use invalid HTML entitiy "${alt.match(/&[0-9A-Za-z]+;/)![0]}"`,
104
104
  alt: target.getAttribute('alt')?.replace(/\0/g, ''),
105
105
  });
106
106
  return false;
@@ -46,7 +46,7 @@ function attributes(ns: (string | HTMLElement)[]): Record<string, string | undef
46
46
  class: 'invalid',
47
47
  'data-invalid-syntax': 'reference',
48
48
  'data-invalid-type': 'syntax',
49
- 'data-invalid-description': 'Invalid abbr.',
49
+ 'data-invalid-message': 'Invalid abbr',
50
50
  }
51
51
  : { class: 'reference' };
52
52
  }
@@ -89,7 +89,7 @@ function attributes(texts: string[], rubies: string[]): Record<string, string> {
89
89
  class: 'invalid',
90
90
  'data-invalid-syntax': 'ruby',
91
91
  'data-invalid-type': ss === texts ? 'content' : 'argument',
92
- 'data-invalid-description': 'Invalid HTML entity.',
92
+ 'data-invalid-message': 'Invalid HTML entity',
93
93
  };
94
94
  }
95
95
  }
@@ -41,6 +41,8 @@ describe('Unit: parser/processor/figure', () => {
41
41
  '## 0',
42
42
  '$fig-b\n> ',
43
43
  '$table-a\n> ',
44
+ '$fig-b\n> ',
45
+ '$fig-c\n> ',
44
46
  ].join('\n\n'));
45
47
  for (let i = 0; i < 3; ++i) {
46
48
  [...figure(target)];
@@ -51,6 +53,8 @@ describe('Unit: parser/processor/figure', () => {
51
53
  '<h2 id="index:0">0</h2>',
52
54
  '<figure data-label="fig-b" data-group="fig" data-number="2" id="label:fig-b"><div><blockquote></blockquote></div><figcaption><span class="figindex">Fig. 2. </span></figcaption></figure>',
53
55
  '<figure data-label="table-a" data-group="table" data-number="1" id="label:table-a"><div><blockquote></blockquote></div><figcaption><span class="figindex">Table 1. </span></figcaption></figure>',
56
+ '<figure data-label="fig-b" data-group="fig" data-number="3" class="invalid" data-invalid-syntax="figure" data-invalid-type="argument" data-invalid-message="Duplicate label"><div><blockquote></blockquote></div><figcaption><span class="figindex">Fig. 3. </span></figcaption></figure>',
57
+ '<figure data-label="fig-c" data-group="fig" data-number="4" id="label:fig-c"><div><blockquote></blockquote></div><figcaption><span class="figindex">Fig. 4. </span></figcaption></figure>',
54
58
  ]);
55
59
  }
56
60
  });
@@ -94,7 +98,7 @@ describe('Unit: parser/processor/figure', () => {
94
98
  '<figure data-label="fig-a" data-group="fig" data-number="1" id="label:fig-a"><div><blockquote></blockquote></div><figcaption><span class="figindex">Fig. 1. </span></figcaption></figure>',
95
99
  '<p><a class="label" data-label="fig-2" href="#label:fig-2">Fig. 2</a></p>',
96
100
  '<p><a class="label" data-label="$-4.1.1" href="#label:$-4.1.1">(4.1.1)</a></p>',
97
- '<p><a class="label disabled invalid" data-label="fig-1" data-invalid-syntax="label" data-invalid-type="reference" data-invalid-description="Missing the reference.">$fig-1</a></p>',
101
+ '<p><a class="label disabled invalid" data-label="fig-1" data-invalid-syntax="label" data-invalid-type="reference" data-invalid-message="Missing the reference">$fig-1</a></p>',
98
102
  ]);
99
103
  }
100
104
  });
@@ -1,4 +1,4 @@
1
- import { Infinity, Map } from 'spica/global';
1
+ import { Infinity, Set, Map } from 'spica/global';
2
2
  import { number as calculate, isFixed } from '../inline/extension/label';
3
3
  import { define } from 'typed-dom';
4
4
  import { MultiMap } from 'spica/multimap';
@@ -16,6 +16,7 @@ export function* figure(
16
16
  footnotes?.annotations.querySelectorAll<HTMLAnchorElement>('a.label:not(.disabled)') ?? []),
17
17
  footnotes?.references.querySelectorAll<HTMLAnchorElement>('a.label:not(.disabled)') ?? [])
18
18
  .map(el => [el.getAttribute('data-label')!, el]));
19
+ const labels = new Set<string>();
19
20
  const numbers = new Map<string, string>();
20
21
  let base = '0';
21
22
  let bases: readonly string[] = base.split('.');
@@ -76,7 +77,7 @@ export function* figure(
76
77
  assert(def.tagName !== 'FIGURE' || !+def.setAttribute('data-number', number));
77
78
  continue;
78
79
  }
79
- assert(def.matches('figure:not([style])'));
80
+ assert(def.matches('figure:not([hidden])'));
80
81
  assert(number.split('.').pop() !== '0');
81
82
  !isFixed(label) && numbers.set(group, number);
82
83
  assert(!+def.setAttribute('data-number', number));
@@ -87,6 +88,27 @@ export function* figure(
87
88
  define(
88
89
  def.querySelector(':scope > figcaption > .figindex')!,
89
90
  group === '$' ? figindex : `${figindex}. `);
91
+ if (labels.has(label)) {
92
+ if (def.classList.contains('invalid') &&
93
+ def.getAttribute('data-invalid-message') !== 'Duplicate label') continue;
94
+ define(def, {
95
+ id: null,
96
+ class: void def.classList.add('invalid'),
97
+ 'data-invalid-syntax': 'figure',
98
+ 'data-invalid-type': 'argument',
99
+ 'data-invalid-message': 'Duplicate label',
100
+ });
101
+ continue;
102
+ }
103
+ else {
104
+ labels.add(label);
105
+ define(def, {
106
+ class: void def.classList.remove('invalid'),
107
+ 'data-invalid-syntax': null,
108
+ 'data-invalid-type': null,
109
+ 'data-invalid-message': null,
110
+ });
111
+ }
90
112
  for (const ref of refs.take(label, Infinity)) {
91
113
  if (ref.hash.slice(1) === def.id && ref.innerText === figindex) continue;
92
114
  yield define(ref,
@@ -100,7 +122,7 @@ export function* figure(
100
122
  class: `${ref.className} disabled invalid`,
101
123
  'data-invalid-syntax': 'label',
102
124
  'data-invalid-type': 'reference',
103
- 'data-invalid-description': 'Missing the reference.',
125
+ 'data-invalid-message': 'Missing the reference',
104
126
  });
105
127
  }
106
128
  yield ref;
@@ -56,7 +56,7 @@ function build(
56
56
  class: `${ref.className} invalid`,
57
57
  'data-invalid-syntax': syntax,
58
58
  'data-invalid-type': 'style',
59
- 'data-invalid-description': `${syntax[0].toUpperCase() + syntax.slice(1)} style must be consistent.`,
59
+ 'data-invalid-message': `${syntax[0].toUpperCase() + syntax.slice(1)} style must be consistent`,
60
60
  });
61
61
  }
62
62
  if (ref.firstElementChild?.getAttribute('hidden') !== '') {
@@ -96,7 +96,7 @@ function build(
96
96
  class: void ref.classList.remove('invalid'),
97
97
  'data-invalid-syntax': null,
98
98
  'data-invalid-type': null,
99
- 'data-invalid-description': null,
99
+ 'data-invalid-message': null,
100
100
  });
101
101
  }
102
102
  }
@@ -110,7 +110,7 @@ function build(
110
110
  : { class: void ref.classList.add('invalid'),
111
111
  'data-invalid-syntax': syntax,
112
112
  'data-invalid-type': 'content',
113
- 'data-invalid-description': 'Missing the content.',
113
+ 'data-invalid-message': 'Missing the content',
114
114
  },
115
115
  });
116
116
  yield ref.appendChild(html('a', { href: refId && defId && `#${defId}` }, marker(defIndex, abbr)));