securemark 0.234.0 → 0.234.3

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,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.234.3
4
+
5
+ - Refactoring.
6
+
7
+ ## 0.234.2
8
+
9
+ - Refactoring.
10
+
11
+ ## 0.234.1
12
+
13
+ - Fix emstrong parser, emphasis parser, strong parser, and mark parser.
14
+
3
15
  ## 0.234.0
4
16
 
5
17
  - Extend anchor syntax.
@@ -1,4 +1,4 @@
1
- /*! securemark v0.234.0 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED */
1
+ /*! securemark v0.234.3 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) {
@@ -4373,10 +4373,9 @@ require = function () {
4373
4373
  function (_dereq_, module, exports) {
4374
4374
  'use strict';
4375
4375
  Object.defineProperty(exports, '__esModule', { value: true });
4376
- exports.escape = exports.normalize = void 0;
4376
+ exports.escape = exports.invisibleHTMLEntityNames = exports.normalize = void 0;
4377
4377
  const parser_1 = _dereq_('../../combinator/data/parser');
4378
4378
  const htmlentity_1 = _dereq_('../inline/htmlentity');
4379
- const util_1 = _dereq_('../util');
4380
4379
  const UNICODE_REPLACEMENT_CHARACTER = '\uFFFD';
4381
4380
  function normalize(source) {
4382
4381
  return sanitize(format(source));
@@ -4388,7 +4387,9 @@ require = function () {
4388
4387
  function sanitize(source) {
4389
4388
  return source.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]|[\u2006\u200B-\u200F\u202A-\u202F\u2060\uFEFF]|(^|[^\u1820\u1821])\u180E/g, `$1${ UNICODE_REPLACEMENT_CHARACTER }`).replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]?|[\uDC00-\uDFFF]/g, char => char.length === 1 ? UNICODE_REPLACEMENT_CHARACTER : char);
4390
4389
  }
4391
- const unreadableHTMLEntityNames = [
4390
+ exports.invisibleHTMLEntityNames = [
4391
+ 'Tab',
4392
+ 'NewLine',
4392
4393
  'NonBreakingSpace',
4393
4394
  'nbsp',
4394
4395
  'shy',
@@ -4420,7 +4421,8 @@ require = function () {
4420
4421
  'InvisibleComma',
4421
4422
  'ic'
4422
4423
  ];
4423
- const unreadableEscapableCharacters = unreadableHTMLEntityNames.map(name => (0, util_1.stringify)((0, parser_1.eval)((0, htmlentity_1.htmlentity)(`&${ name };`, {}))));
4424
+ const unreadableHTMLEntityNames = exports.invisibleHTMLEntityNames.slice(2);
4425
+ const unreadableEscapableCharacters = unreadableHTMLEntityNames.map(name => (0, parser_1.eval)((0, htmlentity_1.unsafehtmlentity)(`&${ name };`, {}))[0]);
4424
4426
  const unreadableEscapableCharacter = new RegExp(`[${ [...new Set(unreadableEscapableCharacters)].join('') }]`, 'g');
4425
4427
  const unreadableSpecialCharacters = [
4426
4428
  '\u2006',
@@ -4445,8 +4447,7 @@ require = function () {
4445
4447
  },
4446
4448
  {
4447
4449
  '../../combinator/data/parser': 47,
4448
- '../inline/htmlentity': 112,
4449
- '../util': 134
4450
+ '../inline/htmlentity': 112
4450
4451
  }
4451
4452
  ],
4452
4453
  61: [
@@ -6672,10 +6673,11 @@ require = function () {
6672
6673
  const util_1 = _dereq_('../util');
6673
6674
  const typed_dom_1 = _dereq_('typed-dom');
6674
6675
  const array_1 = _dereq_('spica/array');
6675
- exports.emphasis = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.surround)((0, combinator_1.close)((0, source_1.str)('*'), /^(?!\*)/), (0, util_1.startTight)((0, combinator_1.some)((0, combinator_1.union)([
6676
+ exports.emphasis = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.surround)((0, source_1.str)('*'), (0, util_1.startTight)((0, combinator_1.some)((0, combinator_1.union)([
6676
6677
  strong_1.strong,
6677
- (0, combinator_1.some)(inline_1.inline, '*')
6678
- ]))), (0, source_1.str)('*'), false, ([as, bs, cs], rest) => (0, util_1.isEndTightNodes)(bs) ? [
6678
+ (0, combinator_1.some)(inline_1.inline, (0, util_1.delimiter)(String.raw`\*`)),
6679
+ (0, combinator_1.open)((0, combinator_1.some)(inline_1.inline, '*'), inline_1.inline)
6680
+ ])), '*'), (0, source_1.str)('*'), false, ([as, bs, cs], rest) => (0, util_1.isEndTightNodes)(bs) ? [
6679
6681
  [(0, typed_dom_1.html)('em', (0, typed_dom_1.defrag)(bs))],
6680
6682
  rest
6681
6683
  ] : [
@@ -6703,11 +6705,24 @@ require = function () {
6703
6705
  exports.emstrong = void 0;
6704
6706
  const combinator_1 = _dereq_('../../combinator');
6705
6707
  const inline_1 = _dereq_('../inline');
6708
+ const strong_1 = _dereq_('./strong');
6706
6709
  const source_1 = _dereq_('../source');
6707
6710
  const util_1 = _dereq_('../util');
6708
6711
  const typed_dom_1 = _dereq_('typed-dom');
6709
6712
  const array_1 = _dereq_('spica/array');
6710
- exports.emstrong = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.surround)((0, source_1.str)('***'), (0, util_1.startTight)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, '*')])), (0, source_1.str)(/^\*{1,3}/), false, ([as, bs, cs], rest, context) => {
6713
+ const substrong = (0, combinator_1.lazy)(() => (0, combinator_1.some)((0, combinator_1.union)([
6714
+ (0, combinator_1.some)(inline_1.inline, (0, util_1.delimiter)(String.raw`\*\*`)),
6715
+ (0, combinator_1.open)((0, combinator_1.some)(inline_1.inline, '*'), inline_1.inline)
6716
+ ])));
6717
+ const subemphasis = (0, combinator_1.lazy)(() => (0, combinator_1.some)((0, combinator_1.union)([
6718
+ strong_1.strong,
6719
+ (0, combinator_1.some)(inline_1.inline, (0, util_1.delimiter)(String.raw`\*`)),
6720
+ (0, combinator_1.open)((0, combinator_1.some)(inline_1.inline, '*'), inline_1.inline)
6721
+ ])));
6722
+ exports.emstrong = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.surround)((0, source_1.str)('***'), (0, util_1.startTight)((0, combinator_1.some)((0, combinator_1.union)([
6723
+ (0, combinator_1.some)(inline_1.inline, (0, util_1.delimiter)(String.raw`\*`)),
6724
+ (0, combinator_1.open)((0, combinator_1.some)(inline_1.inline, '*'), inline_1.inline)
6725
+ ]))), (0, source_1.str)(/^\*{1,3}/), false, ([as, bs, cs], rest, context) => {
6711
6726
  var _a, _b;
6712
6727
  if (!(0, util_1.isEndTightNodes)(bs))
6713
6728
  return [
@@ -6715,25 +6730,13 @@ require = function () {
6715
6730
  cs[0] + rest
6716
6731
  ];
6717
6732
  switch (cs[0]) {
6718
- case '*':
6719
- return (_a = (0, combinator_1.bind)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, '**')]), (ds, rest) => rest.slice(0, 2) === '**' && (0, util_1.isEndTightNodes)(ds) ? [
6720
- [(0, typed_dom_1.html)('strong', (0, array_1.unshift)([(0, typed_dom_1.html)('em', (0, typed_dom_1.defrag)(bs))], (0, typed_dom_1.defrag)(ds)))],
6721
- rest.slice(2)
6722
- ] : [
6723
- (0, array_1.unshift)([
6724
- '**',
6725
- (0, typed_dom_1.html)('em', (0, typed_dom_1.defrag)(bs))
6726
- ], ds),
6727
- rest
6728
- ])(rest, context)) !== null && _a !== void 0 ? _a : [
6729
- [
6730
- '**',
6731
- (0, typed_dom_1.html)('em', (0, typed_dom_1.defrag)(bs))
6732
- ],
6733
+ case '***':
6734
+ return [
6735
+ [(0, typed_dom_1.html)('em', [(0, typed_dom_1.html)('strong', (0, typed_dom_1.defrag)(bs))])],
6733
6736
  rest
6734
6737
  ];
6735
6738
  case '**':
6736
- return (_b = (0, combinator_1.bind)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, '*')]), (ds, rest) => rest.slice(0, 1) === '*' && (0, util_1.isEndTightNodes)(ds) ? [
6739
+ return (_a = (0, combinator_1.bind)(subemphasis, (ds, rest) => rest.slice(0, 1) === '*' && (0, util_1.isEndTightNodes)(ds) ? [
6737
6740
  [(0, typed_dom_1.html)('em', (0, array_1.unshift)([(0, typed_dom_1.html)('strong', (0, typed_dom_1.defrag)(bs))], (0, typed_dom_1.defrag)(ds)))],
6738
6741
  rest.slice(1)
6739
6742
  ] : [
@@ -6742,16 +6745,28 @@ require = function () {
6742
6745
  (0, typed_dom_1.html)('strong', (0, typed_dom_1.defrag)(bs))
6743
6746
  ], ds),
6744
6747
  rest
6745
- ])(rest, context)) !== null && _b !== void 0 ? _b : [
6748
+ ])(rest, context)) !== null && _a !== void 0 ? _a : [
6746
6749
  [
6747
6750
  '*',
6748
6751
  (0, typed_dom_1.html)('strong', (0, typed_dom_1.defrag)(bs))
6749
6752
  ],
6750
6753
  rest
6751
6754
  ];
6752
- case '***':
6753
- return [
6754
- [(0, typed_dom_1.html)('em', [(0, typed_dom_1.html)('strong', (0, typed_dom_1.defrag)(bs))])],
6755
+ case '*':
6756
+ return (_b = (0, combinator_1.bind)(substrong, (ds, rest) => rest.slice(0, 2) === '**' && (0, util_1.isEndTightNodes)(ds) ? [
6757
+ [(0, typed_dom_1.html)('strong', (0, array_1.unshift)([(0, typed_dom_1.html)('em', (0, typed_dom_1.defrag)(bs))], (0, typed_dom_1.defrag)(ds)))],
6758
+ rest.slice(2)
6759
+ ] : [
6760
+ (0, array_1.unshift)([
6761
+ '**',
6762
+ (0, typed_dom_1.html)('em', (0, typed_dom_1.defrag)(bs))
6763
+ ], ds),
6764
+ rest
6765
+ ])(rest, context)) !== null && _b !== void 0 ? _b : [
6766
+ [
6767
+ '**',
6768
+ (0, typed_dom_1.html)('em', (0, typed_dom_1.defrag)(bs))
6769
+ ],
6755
6770
  rest
6756
6771
  ];
6757
6772
  }
@@ -6765,6 +6780,7 @@ require = function () {
6765
6780
  '../inline': 88,
6766
6781
  '../source': 128,
6767
6782
  '../util': 134,
6783
+ './strong': 121,
6768
6784
  'spica/array': 6,
6769
6785
  'typed-dom': 26
6770
6786
  }
@@ -7098,8 +7114,8 @@ require = function () {
7098
7114
  (0, alias_1.ObjectSetPrototypeOf)(attrspec, null);
7099
7115
  (0, alias_1.ObjectValues)(attrspec).forEach(o => (0, alias_1.ObjectSetPrototypeOf)(o, null));
7100
7116
  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)([
7101
- (0, combinator_1.match)(/^(?=<(wbr)(?=[^\S\n]|>))/, (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.surround)((0, source_1.str)(`<${ tag }`), (0, combinator_1.some)((0, combinator_1.union)([exports.attribute])), (0, source_1.str)('>'), true, ([, as = []], rest) => [
7102
- [(0, typed_dom_1.html)(tag, attributes('html', [], attrspec[tag], as))],
7117
+ (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])), '>', true, ([, bs = []], rest) => [
7118
+ [(0, typed_dom_1.html)(tag, attributes('html', [], attrspec[tag], bs))],
7103
7119
  rest
7104
7120
  ]), ([, tag]) => tag)),
7105
7121
  (0, combinator_1.match)(/^(?=<(sup|sub|small|bdo|bdi)(?=[^\S\n]|>))/, (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.validate)(`<${ tag }`, `</${ tag }>`, (0, combinator_1.surround)((0, combinator_1.surround)((0, source_1.str)(`<${ tag }`), (0, combinator_1.some)(exports.attribute), (0, source_1.str)('>'), true), (0, util_1.startLoose)((0, combinator_1.context)((() => {
@@ -7222,17 +7238,16 @@ require = function () {
7222
7238
  exports.htmlentity = exports.unsafehtmlentity = void 0;
7223
7239
  const combinator_1 = _dereq_('../../combinator');
7224
7240
  const typed_dom_1 = _dereq_('typed-dom');
7225
- const parser = (0, typed_dom_1.html)('textarea');
7226
- exports.unsafehtmlentity = (0, combinator_1.creator)((0, combinator_1.validate)('&', (0, combinator_1.fmap)((0, combinator_1.focus)(/^&[0-9A-Za-z]+;/, entity => [
7227
- [(parser.innerHTML = entity, parser.value)],
7241
+ exports.unsafehtmlentity = (0, combinator_1.creator)((0, combinator_1.validate)('&', (0, combinator_1.focus)(/^&(?!NewLine;)[0-9A-Za-z]+;/, (parser => entity => (parser.innerHTML = entity, entity = parser.textContent, [
7242
+ [`${ entity[0] !== '&' || entity.length === 1 ? '' : '\0' }${ entity }`],
7228
7243
  ''
7229
- ]), ([str]) => [str[0] !== '&' || str.length < 3 ? str : `\0${ str }`])));
7230
- exports.htmlentity = (0, combinator_1.creator)((0, combinator_1.validate)('&', (0, combinator_1.fmap)((0, combinator_1.union)([exports.unsafehtmlentity]), ([str]) => [str[0] === '\0' ? (0, typed_dom_1.html)('span', {
7244
+ ]))((0, typed_dom_1.html)('b')))));
7245
+ exports.htmlentity = (0, combinator_1.fmap)((0, combinator_1.union)([exports.unsafehtmlentity]), ([str]) => [str[0] === '\0' ? (0, typed_dom_1.html)('span', {
7231
7246
  class: 'invalid',
7232
7247
  'data-invalid-syntax': 'htmlentity',
7233
7248
  'data-invalid-type': 'syntax',
7234
7249
  'data-invalid-description': 'Invalid HTML entity.'
7235
- }, str.slice(1)) : str])));
7250
+ }, str.slice(1)) : str]);
7236
7251
  },
7237
7252
  {
7238
7253
  '../../combinator': 27,
@@ -7422,7 +7437,10 @@ require = function () {
7422
7437
  const util_1 = _dereq_('../util');
7423
7438
  const typed_dom_1 = _dereq_('typed-dom');
7424
7439
  const array_1 = _dereq_('spica/array');
7425
- exports.mark = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.surround)((0, source_1.str)('=='), (0, util_1.startTight)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, '==')])), (0, source_1.str)('=='), false, ([as, bs, cs], rest) => (0, util_1.isEndTightNodes)(bs) ? [
7440
+ exports.mark = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.surround)((0, source_1.str)('=='), (0, util_1.startTight)((0, combinator_1.some)((0, combinator_1.union)([
7441
+ (0, combinator_1.some)(inline_1.inline, (0, util_1.delimiter)('==')),
7442
+ (0, combinator_1.open)((0, combinator_1.some)(inline_1.inline, '='), inline_1.inline)
7443
+ ]))), (0, source_1.str)('=='), false, ([as, bs, cs], rest) => (0, util_1.isEndTightNodes)(bs) ? [
7426
7444
  [(0, typed_dom_1.html)('mark', (0, typed_dom_1.defrag)(bs))],
7427
7445
  rest
7428
7446
  ] : [
@@ -7449,11 +7467,10 @@ require = function () {
7449
7467
  exports.math = void 0;
7450
7468
  const combinator_1 = _dereq_('../../combinator');
7451
7469
  const source_1 = _dereq_('../source');
7452
- const util_1 = _dereq_('../util');
7453
7470
  const typed_dom_1 = _dereq_('typed-dom');
7454
7471
  const disallowedCommand = /\\(?:begin|tiny|huge|large)(?![0-9a-z])/i;
7455
7472
  exports.math = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.validate)('$', (0, combinator_1.rewrite)((0, combinator_1.union)([
7456
- (0, combinator_1.surround)('$', (0, combinator_1.verify)((0, source_1.str)(/^(?![\s{}#$%&]|\d+(?:[,.]\d+)*[^-+*/=<>^_~\\$]|-[\da-z]|[a-z]+-)(?:\\\$|[\x20-\x23\x25-\x7E])+/i), util_1.isEndTightNodes), /^\$(?![0-9a-z])/i),
7473
+ (0, combinator_1.surround)('$', (0, source_1.str)(/^(?![\s{}#$%&]|\d+(?:[,.]\d+)*[^-+*/=<>^_~\\$]|-[\da-z]|[a-z]+-)(?:\\\$|\x20(?!\$)|[\x21-\x23\x25-\x7E])+/i), /^\$(?![0-9a-z])/i),
7457
7474
  (0, combinator_1.surround)('$', bracket, '$')
7458
7475
  ]), (source, {
7459
7476
  caches: {math: cache} = {}
@@ -7482,7 +7499,6 @@ require = function () {
7482
7499
  {
7483
7500
  '../../combinator': 27,
7484
7501
  '../source': 128,
7485
- '../util': 134,
7486
7502
  'typed-dom': 26
7487
7503
  }
7488
7504
  ],
@@ -7836,16 +7852,14 @@ require = function () {
7836
7852
  exports.strong = void 0;
7837
7853
  const combinator_1 = _dereq_('../../combinator');
7838
7854
  const inline_1 = _dereq_('../inline');
7839
- const emphasis_1 = _dereq_('./emphasis');
7840
7855
  const source_1 = _dereq_('../source');
7841
7856
  const util_1 = _dereq_('../util');
7842
7857
  const typed_dom_1 = _dereq_('typed-dom');
7843
7858
  const array_1 = _dereq_('spica/array');
7844
- exports.strong = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.surround)((0, combinator_1.close)((0, source_1.str)('**'), /^(?!\*)/), (0, util_1.startTight)((0, combinator_1.some)((0, combinator_1.union)([
7845
- emphasis_1.emphasis,
7846
- (0, combinator_1.some)(inline_1.inline, '*'),
7847
- (0, source_1.str)('*')
7848
- ]), '**')), (0, source_1.str)('**'), false, ([as, bs, cs], rest) => (0, util_1.isEndTightNodes)(bs) ? [
7859
+ exports.strong = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.surround)((0, source_1.str)('**'), (0, util_1.startTight)((0, combinator_1.some)((0, combinator_1.union)([
7860
+ (0, combinator_1.some)(inline_1.inline, (0, util_1.delimiter)(String.raw`\*\*`)),
7861
+ (0, combinator_1.open)((0, combinator_1.some)(inline_1.inline, '*'), inline_1.inline)
7862
+ ])), '*'), (0, source_1.str)('**'), false, ([as, bs, cs], rest) => (0, util_1.isEndTightNodes)(bs) ? [
7849
7863
  [(0, typed_dom_1.html)('strong', (0, typed_dom_1.defrag)(bs))],
7850
7864
  rest
7851
7865
  ] : [
@@ -7861,7 +7875,6 @@ require = function () {
7861
7875
  '../inline': 88,
7862
7876
  '../source': 128,
7863
7877
  '../util': 134,
7864
- './emphasis': 102,
7865
7878
  'spica/array': 6,
7866
7879
  'typed-dom': 26
7867
7880
  }
@@ -8637,49 +8650,20 @@ require = function () {
8637
8650
  function (_dereq_, module, exports) {
8638
8651
  'use strict';
8639
8652
  Object.defineProperty(exports, '__esModule', { value: true });
8640
- exports.stringify = exports.trimNodeEndBR = exports.trimNodeEnd = exports.trimNode = exports.isEndTightNodes = exports.isStartTightNodes = exports.startTight = exports.isStartLoose = exports.startLoose = exports.visualize = void 0;
8653
+ exports.stringify = exports.trimNodeEndBR = exports.trimNodeEnd = exports.trimNode = exports.isEndTightNodes = exports.isStartTightNodes = exports.startTight = exports.isStartLoose = exports.startLoose = exports.visualize = exports.delimiter = void 0;
8641
8654
  const global_1 = _dereq_('spica/global');
8642
8655
  const parser_1 = _dereq_('../combinator/data/parser');
8643
8656
  const combinator_1 = _dereq_('../combinator');
8644
8657
  const htmlentity_1 = _dereq_('./inline/htmlentity');
8645
8658
  const source_1 = _dereq_('./source');
8659
+ const normalize_1 = _dereq_('./api/normalize');
8646
8660
  const array_1 = _dereq_('spica/array');
8647
- const invisibleHTMLEntityNames = [
8648
- 'Tab',
8649
- 'NewLine',
8650
- 'NonBreakingSpace',
8651
- 'nbsp',
8652
- 'shy',
8653
- 'ensp',
8654
- 'emsp',
8655
- 'emsp13',
8656
- 'emsp14',
8657
- 'numsp',
8658
- 'puncsp',
8659
- 'ThinSpace',
8660
- 'thinsp',
8661
- 'VeryThinSpace',
8662
- 'hairsp',
8663
- 'ZeroWidthSpace',
8664
- 'NegativeVeryThinSpace',
8665
- 'NegativeThinSpace',
8666
- 'NegativeMediumSpace',
8667
- 'NegativeThickSpace',
8668
- 'zwj',
8669
- 'zwnj',
8670
- 'lrm',
8671
- 'rlm',
8672
- 'MediumSpace',
8673
- 'NoBreak',
8674
- 'ApplyFunction',
8675
- 'af',
8676
- 'InvisibleTimes',
8677
- 'it',
8678
- 'InvisibleComma',
8679
- 'ic'
8680
- ];
8681
- const blankline = new RegExp(String.raw`^(?!$)(?:\\$|\\?[^\S\n]|&(?:${ invisibleHTMLEntityNames.join('|') });|<wbr>)+$`, 'gm');
8661
+ function delimiter(opener) {
8662
+ return new RegExp(String.raw`^(?:\s+|\\\s|&(?:${ normalize_1.invisibleHTMLEntityNames.join('|') });|<wbr>)?${ opener }`);
8663
+ }
8664
+ exports.delimiter = delimiter;
8682
8665
  function visualize(parser) {
8666
+ const blankline = new RegExp(String.raw`^(?:\\$|\\?[^\S\n]|&(?:${ normalize_1.invisibleHTMLEntityNames.join('|') });|<wbr>)+$`, 'gm');
8683
8667
  return (0, combinator_1.union)([
8684
8668
  (0, combinator_1.convert)(source => source.replace(blankline, line => line.replace(/[\\&<]/g, '\x1B$&')), (0, combinator_1.verify)(parser, (ns, rest, context) => !rest && hasVisible(ns, context))),
8685
8669
  (0, combinator_1.some)((0, combinator_1.union)([
@@ -8715,28 +8699,28 @@ require = function () {
8715
8699
  }
8716
8700
  exports.startLoose = startLoose;
8717
8701
  function isStartLoose(source, context, except) {
8718
- var _a;
8719
8702
  source && (source = source.replace(/^[^\S\n]+/, ''));
8720
8703
  if (source === '')
8721
8704
  return true;
8722
- return source.slice(0, (_a = except === null || except === void 0 ? void 0 : except.length) !== null && _a !== void 0 ? _a : 0) !== except && isStartTight(source, context);
8705
+ return isStartTight(source, context, except);
8723
8706
  }
8724
8707
  exports.isStartLoose = isStartLoose;
8725
- function startTight(parser) {
8726
- return (source, context) => isStartTight(source, context) ? parser(source, context) : global_1.undefined;
8708
+ function startTight(parser, except) {
8709
+ return (source, context) => isStartTight(source, context, except) ? parser(source, context) : global_1.undefined;
8727
8710
  }
8728
8711
  exports.startTight = startTight;
8729
- function isStartTight(source, context) {
8712
+ function isStartTight(source, context, except) {
8730
8713
  var _a, _b, _c;
8731
8714
  if (source === '')
8732
8715
  return true;
8716
+ if (except && source.slice(0, except.length) === except)
8717
+ return false;
8733
8718
  switch (source[0]) {
8734
8719
  case ' ':
8735
8720
  case '\u3000':
8736
8721
  case '\t':
8737
8722
  case '\n':
8738
8723
  return false;
8739
- case '\x1B':
8740
8724
  case '\\':
8741
8725
  return ((_a = source[1]) === null || _a === void 0 ? void 0 : _a.trimStart()) !== '';
8742
8726
  case '&':
@@ -8850,6 +8834,7 @@ require = function () {
8850
8834
  {
8851
8835
  '../combinator': 27,
8852
8836
  '../combinator/data/parser': 47,
8837
+ './api/normalize': 60,
8853
8838
  './inline/htmlentity': 112,
8854
8839
  './source': 128,
8855
8840
  'spica/array': 6,
package/markdown.d.ts CHANGED
@@ -970,6 +970,7 @@ export namespace MarkdownParser {
970
970
  Inline<'mark'>,
971
971
  Parser<HTMLElement | string, Context, [
972
972
  InlineParser,
973
+ InlineParser,
973
974
  ]> {
974
975
  }
975
976
  export interface EmStrongParser extends
@@ -977,15 +978,15 @@ export namespace MarkdownParser {
977
978
  Inline<'emstrong'>,
978
979
  Parser<HTMLElement | string, Context, [
979
980
  InlineParser,
981
+ InlineParser,
980
982
  ]> {
981
983
  }
982
984
  export interface StrongParser extends
983
985
  // **abc**
984
986
  Inline<'strong'>,
985
987
  Parser<HTMLElement | string, Context, [
986
- EmphasisParser,
987
988
  InlineParser,
988
- SourceParser.StrParser,
989
+ InlineParser,
989
990
  ]> {
990
991
  }
991
992
  export interface EmphasisParser extends
@@ -994,6 +995,7 @@ export namespace MarkdownParser {
994
995
  Parser<HTMLElement | string, Context, [
995
996
  StrongParser,
996
997
  InlineParser,
998
+ InlineParser,
997
999
  ]> {
998
1000
  }
999
1001
  export interface CodeParser extends
package/package-lock.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.234.0",
3
+ "version": "0.234.3",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {
@@ -1924,9 +1924,9 @@
1924
1924
  "dev": true
1925
1925
  },
1926
1926
  "caniuse-lite": {
1927
- "version": "1.0.30001320",
1928
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz",
1929
- "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==",
1927
+ "version": "1.0.30001322",
1928
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001322.tgz",
1929
+ "integrity": "sha512-neRmrmIrCGuMnxGSoh+x7zYtQFFgnSY2jaomjU56sCkTA6JINqQrxutF459JpWcWRajvoyn95sOXq4Pqrnyjew==",
1930
1930
  "dev": true
1931
1931
  },
1932
1932
  "chalk": {
@@ -3030,9 +3030,9 @@
3030
3030
  "dev": true
3031
3031
  },
3032
3032
  "electron-to-chromium": {
3033
- "version": "1.4.96",
3034
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.96.tgz",
3035
- "integrity": "sha512-DPNjvNGPabv6FcyjzLAN4C0psN/GgD9rSGvMTuv81SeXG/EX3mCz0wiw9N1tUEnfQXYCJi3H8M0oFPRziZh7rw==",
3033
+ "version": "1.4.98",
3034
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.98.tgz",
3035
+ "integrity": "sha512-1IdsuSAnIGVxoYT1LkcUFb9MfjRxdHhCU9qiaDzhl1XvYgK9c8E2O9aJOPgGMQ68CSI8NxmLwrYhjvGauT8yuw==",
3036
3036
  "dev": true
3037
3037
  },
3038
3038
  "elliptic": {
@@ -3210,9 +3210,9 @@
3210
3210
  }
3211
3211
  },
3212
3212
  "es-abstract": {
3213
- "version": "1.19.1",
3214
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz",
3215
- "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==",
3213
+ "version": "1.19.2",
3214
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.2.tgz",
3215
+ "integrity": "sha512-gfSBJoZdlL2xRiOCy0g8gLMryhoe1TlimjzU99L/31Z8QEGIhVQI+EWwt5lT+AuU9SnorVupXFqqOGqGfsyO6w==",
3216
3216
  "dev": true,
3217
3217
  "requires": {
3218
3218
  "call-bind": "^1.0.2",
@@ -3221,15 +3221,15 @@
3221
3221
  "get-intrinsic": "^1.1.1",
3222
3222
  "get-symbol-description": "^1.0.0",
3223
3223
  "has": "^1.0.3",
3224
- "has-symbols": "^1.0.2",
3224
+ "has-symbols": "^1.0.3",
3225
3225
  "internal-slot": "^1.0.3",
3226
3226
  "is-callable": "^1.2.4",
3227
- "is-negative-zero": "^2.0.1",
3227
+ "is-negative-zero": "^2.0.2",
3228
3228
  "is-regex": "^1.1.4",
3229
3229
  "is-shared-array-buffer": "^1.0.1",
3230
3230
  "is-string": "^1.0.7",
3231
- "is-weakref": "^1.0.1",
3232
- "object-inspect": "^1.11.0",
3231
+ "is-weakref": "^1.0.2",
3232
+ "object-inspect": "^1.12.0",
3233
3233
  "object-keys": "^1.1.1",
3234
3234
  "object.assign": "^4.1.2",
3235
3235
  "string.prototype.trimend": "^1.0.4",
@@ -4608,9 +4608,9 @@
4608
4608
  "dev": true
4609
4609
  },
4610
4610
  "gauge": {
4611
- "version": "4.0.3",
4612
- "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.3.tgz",
4613
- "integrity": "sha512-ICw1DhAwMtb22rYFwEHgJcx1JCwJGv3x6G0OQUq56Nge+H4Q8JEwr8iveS0XFlsUNSI67F5ffMGK25bK4Pmskw==",
4611
+ "version": "4.0.4",
4612
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz",
4613
+ "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==",
4614
4614
  "dev": true,
4615
4615
  "requires": {
4616
4616
  "aproba": "^1.0.3 || ^2.0.0",
@@ -8918,9 +8918,9 @@
8918
8918
  "dev": true
8919
8919
  },
8920
8920
  "proc-log": {
8921
- "version": "2.0.0",
8922
- "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.0.tgz",
8923
- "integrity": "sha512-I/35MfCX2H8jBUhKN8JB8nmqvQo/nKdrBodBY7L3RhDSPPyvOHwLYNmPuhwuJq7a7C3vgFKWGQM+ecPStcvOHA==",
8921
+ "version": "2.0.1",
8922
+ "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz",
8923
+ "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==",
8924
8924
  "dev": true
8925
8925
  },
8926
8926
  "process": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.234.0",
3
+ "version": "0.234.3",
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",
@@ -8,7 +8,8 @@ export interface Ctx {
8
8
  export type Parser<T, C extends Ctx = Ctx, D extends Parser<unknown, C>[] = any>
9
9
  = (source: string, context: C) => Result<T, C, D>;
10
10
  export type Result<T, C extends Ctx = Ctx, D extends Parser<unknown, C>[] = any>
11
- = readonly [T[], string, C?, D?]
11
+ = readonly [T[], string, C, D]
12
+ | readonly [T[], string]
12
13
  | undefined;
13
14
  export type Tree<P extends Parser<unknown>> = P extends Parser<infer T> ? T : never;
14
15
  export type SubParsers<P extends Parser<unknown>> = P extends Parser<unknown, any, infer D> ? D : never;
@@ -1,6 +1,5 @@
1
1
  import { eval } from '../../combinator/data/parser';
2
- import { htmlentity } from '../inline/htmlentity';
3
- import { stringify } from '../util';
2
+ import { unsafehtmlentity } from '../inline/htmlentity';
4
3
 
5
4
  const UNICODE_REPLACEMENT_CHARACTER = '\uFFFD';
6
5
  assert(UNICODE_REPLACEMENT_CHARACTER.trim());
@@ -25,9 +24,9 @@ function sanitize(source: string): string {
25
24
 
26
25
  // https://dev.w3.org/html5/html-author/charref
27
26
  // https://en.wikipedia.org/wiki/Whitespace_character
28
- const unreadableHTMLEntityNames = [
29
- //'Tab',
30
- //'NewLine',
27
+ export const invisibleHTMLEntityNames = [
28
+ 'Tab',
29
+ 'NewLine',
31
30
  'NonBreakingSpace',
32
31
  'nbsp',
33
32
  'shy',
@@ -59,8 +58,10 @@ const unreadableHTMLEntityNames = [
59
58
  'InvisibleComma',
60
59
  'ic',
61
60
  ] as const;
61
+ const unreadableHTMLEntityNames: readonly string[] = invisibleHTMLEntityNames.slice(2);
62
62
  const unreadableEscapableCharacters = unreadableHTMLEntityNames
63
- .map(name => stringify(eval(htmlentity(`&${name};`, {}))!));
63
+ .map(name => eval(unsafehtmlentity(`&${name};`, {}))![0]);
64
+ assert(unreadableEscapableCharacters.length === unreadableHTMLEntityNames.length);
64
65
  assert(unreadableEscapableCharacters.every(c => c.length === 1));
65
66
  const unreadableEscapableCharacter = new RegExp(`[${
66
67
  [...new Set<string>(unreadableEscapableCharacters)].join('')
@@ -20,11 +20,19 @@ describe('Unit: parser/block/paragraph', () => {
20
20
  assert.deepStrictEqual(inspect(parser('a\\ \n')), [['<p>a</p>'], '']);
21
21
  assert.deepStrictEqual(inspect(parser('a\\\n')), [['<p>a</p>'], '']);
22
22
  assert.deepStrictEqual(inspect(parser('a\\\nb')), [['<p>a<span class="linebreak"> </span>b</p>'], '']);
23
+ assert.deepStrictEqual(inspect(parser('a&NewLine;b')), [['<p>a&amp;NewLine;b</p>'], '']);
24
+ assert.deepStrictEqual(inspect(parser('&Tab;&NewLine;')), [['<p>&amp;Tab;&amp;NewLine;</p>'], '']);
23
25
  assert.deepStrictEqual(inspect(parser('<wbr>')), [['<p>&lt;wbr&gt;</p>'], '']);
24
26
  assert.deepStrictEqual(inspect(parser('<wbr>\n')), [['<p>&lt;wbr&gt;</p>'], '']);
25
27
  assert.deepStrictEqual(inspect(parser('<wbr>\na')), [['<p>&lt;wbr&gt;<br>a</p>'], '']);
26
28
  assert.deepStrictEqual(inspect(parser('a\n<wbr>\n')), [['<p>a<br>&lt;wbr&gt;</p>'], '']);
27
29
  assert.deepStrictEqual(inspect(parser('a\n<wbr>\nb')), [['<p>a<br>&lt;wbr&gt;<br>b</p>'], '']);
30
+ assert.deepStrictEqual(inspect(parser('*a\n<wbr>*\nb')), [['<p>*a<br><wbr>*<br>b</p>'], '']);
31
+ assert.deepStrictEqual(inspect(parser('**a\n<wbr>**\nb')), [['<p>**a<br><wbr>**<br>b</p>'], '']);
32
+ assert.deepStrictEqual(inspect(parser('***a\n<wbr>***\nb')), [['<p>***a<br><wbr>***<br>b</p>'], '']);
33
+ assert.deepStrictEqual(inspect(parser('***a*b\n<wbr>**\nc')), [['<p>**<em>a</em>b<br><wbr>**<br>c</p>'], '']);
34
+ assert.deepStrictEqual(inspect(parser('***a**b\n<wbr>*\nc')), [['<p>*<strong>a</strong>b<br><wbr>*<br>c</p>'], '']);
35
+ assert.deepStrictEqual(inspect(parser('==a\n<wbr>==\nb')), [['<p>==a<br><wbr>==<br>b</p>'], '']);
28
36
  assert.deepStrictEqual(inspect(parser(' a')), [['<p>a</p>'], '']);
29
37
  });
30
38
 
@@ -9,10 +9,10 @@ describe('Unit: parser/inline/emphasis', () => {
9
9
  it('invalid', () => {
10
10
  assert.deepStrictEqual(inspect(parser('*')), undefined);
11
11
  assert.deepStrictEqual(inspect(parser('*a')), [['*', 'a'], '']);
12
- assert.deepStrictEqual(inspect(parser('*a *')), [['*', 'a', ' '], '*']);
13
- assert.deepStrictEqual(inspect(parser('*a\n*')), [['*', 'a', '<br>'], '*']);
14
- assert.deepStrictEqual(inspect(parser('*a\\ *')), [['*', 'a', ' '], '*']);
15
- assert.deepStrictEqual(inspect(parser('*a\\\n*')), [['*', 'a', '<span class="linebreak"> </span>'], '*']);
12
+ assert.deepStrictEqual(inspect(parser('*a *')), [['*', 'a', ' ', '*'], '']);
13
+ assert.deepStrictEqual(inspect(parser('*a\n*')), [['*', 'a', '<br>', '*'], '']);
14
+ assert.deepStrictEqual(inspect(parser('*a\\ *')), [['*', 'a', ' ', '*'], '']);
15
+ assert.deepStrictEqual(inspect(parser('*a\\\n*')), [['*', 'a', '<span class="linebreak"> </span>', '*'], '']);
16
16
  assert.deepStrictEqual(inspect(parser('*a**b')), [['*', 'a', '**', 'b'], '']);
17
17
  assert.deepStrictEqual(inspect(parser('*a**b*')), [['*', 'a', '**', 'b', '*'], '']);
18
18
  assert.deepStrictEqual(inspect(parser('* *')), undefined);
@@ -37,6 +37,11 @@ describe('Unit: parser/inline/emphasis', () => {
37
37
  });
38
38
 
39
39
  it('nest', () => {
40
+ assert.deepStrictEqual(inspect(parser('*a *b**')), [['<em>a <em>b</em></em>'], '']);
41
+ assert.deepStrictEqual(inspect(parser('*a **b***')), [['<em>a <strong>b</strong></em>'], '']);
42
+ assert.deepStrictEqual(inspect(parser('*a\\ *b**')), [['<em>a <em>b</em></em>'], '']);
43
+ assert.deepStrictEqual(inspect(parser('*a&Tab;*b**')), [['<em>a\t<em>b</em></em>'], '']);
44
+ assert.deepStrictEqual(inspect(parser('*a<wbr>*b**')), [['<em>a<wbr><em>b</em></em>'], '']);
40
45
  assert.deepStrictEqual(inspect(parser('*a**b**c*')), [['<em>a<strong>b</strong>c</em>'], '']);
41
46
  assert.deepStrictEqual(inspect(parser('*a**b**c*d')), [['<em>a<strong>b</strong>c</em>'], 'd']);
42
47
  assert.deepStrictEqual(inspect(parser('*`a`*')), [['<em><code data-src="`a`">a</code></em>'], '']);
@@ -1,15 +1,19 @@
1
1
  import { EmphasisParser } from '../inline';
2
- import { union, some, creator, surround, close, lazy } from '../../combinator';
2
+ import { union, some, creator, surround, open, lazy } from '../../combinator';
3
3
  import { inline } from '../inline';
4
4
  import { strong } from './strong';
5
5
  import { str } from '../source';
6
- import { startTight, isEndTightNodes } from '../util';
6
+ import { startTight, isEndTightNodes, delimiter } from '../util';
7
7
  import { html, defrag } from 'typed-dom';
8
8
  import { unshift } from 'spica/array';
9
9
 
10
- export const emphasis: EmphasisParser = lazy(() => creator(surround(close(
11
- str('*'), /^(?!\*)/),
12
- startTight(some(union([strong, some(inline, '*')]))),
10
+ export const emphasis: EmphasisParser = lazy(() => creator(surround(
11
+ str('*'),
12
+ startTight(some(union([
13
+ strong,
14
+ some(inline, delimiter(String.raw`\*`)),
15
+ open(some(inline, '*'), inline),
16
+ ])), '*'),
13
17
  str('*'), false,
14
18
  ([as, bs, cs], rest) =>
15
19
  isEndTightNodes(bs)
@@ -1,36 +1,53 @@
1
- import { EmStrongParser } from '../inline';
2
- import { union, some, creator, surround, lazy, bind } from '../../combinator';
1
+ import { MarkdownParser } from '../../../markdown';
2
+ import { EmStrongParser, EmphasisParser, StrongParser } from '../inline';
3
+ import { Result, IntermediateParser } from '../../combinator/data/parser';
4
+ import { union, some, creator, surround, open, lazy, bind } from '../../combinator';
3
5
  import { inline } from '../inline';
6
+ import { strong } from './strong';
4
7
  import { str } from '../source';
5
- import { startTight, isEndTightNodes } from '../util';
8
+ import { startTight, isEndTightNodes, delimiter } from '../util';
6
9
  import { html, defrag } from 'typed-dom';
7
10
  import { unshift } from 'spica/array';
8
11
 
12
+ const substrong: IntermediateParser<StrongParser> = lazy(() => some(union([
13
+ some(inline, delimiter(String.raw`\*\*`)),
14
+ open(some(inline, '*'), inline),
15
+ ])));
16
+ const subemphasis: IntermediateParser<EmphasisParser> = lazy(() => some(union([
17
+ strong,
18
+ some(inline, delimiter(String.raw`\*`)),
19
+ open(some(inline, '*'), inline),
20
+ ])));
21
+
9
22
  export const emstrong: EmStrongParser = lazy(() => creator(surround(
10
23
  str('***'),
11
- startTight(union([some(inline, '*')])),
24
+ startTight(some(union([
25
+ some(inline, delimiter(String.raw`\*`)),
26
+ open(some(inline, '*'), inline),
27
+ ]))),
12
28
  str(/^\*{1,3}/), false,
13
- ([as, bs, cs], rest, context) => {
29
+ ([as, bs, cs], rest, context): Result<HTMLElement | string, MarkdownParser.Context> => {
30
+ assert(cs.length === 1);
14
31
  if (!isEndTightNodes(bs)) return [unshift(as, bs), cs[0] + rest];
15
32
  switch (cs[0]) {
16
- case '*':
17
- return bind<EmStrongParser>(
18
- union([some(inline, '**')]),
19
- (ds, rest) =>
20
- rest.slice(0, 2) === '**' && isEndTightNodes(ds)
21
- ? [[html('strong', unshift([html('em', defrag(bs))], defrag(ds)))], rest.slice(2)]
22
- : [unshift(['**', html('em', defrag(bs))], ds), rest])
23
- (rest, context) ?? [['**', html('em', defrag(bs))], rest];
33
+ case '***':
34
+ return [[html('em', [html('strong', defrag(bs))])], rest];
24
35
  case '**':
25
- return bind<EmStrongParser>(
26
- union([some(inline, '*')]),
36
+ return bind<EmphasisParser>(
37
+ subemphasis,
27
38
  (ds, rest) =>
28
39
  rest.slice(0, 1) === '*' && isEndTightNodes(ds)
29
40
  ? [[html('em', unshift([html('strong', defrag(bs))], defrag(ds)))], rest.slice(1)]
30
41
  : [unshift(['*', html('strong', defrag(bs))], ds), rest])
31
42
  (rest, context) ?? [['*', html('strong', defrag(bs))], rest];
32
- case '***':
33
- return [[html('em', [html('strong', defrag(bs))])], rest];
43
+ case '*':
44
+ return bind<StrongParser>(
45
+ substrong,
46
+ (ds, rest) =>
47
+ rest.slice(0, 2) === '**' && isEndTightNodes(ds)
48
+ ? [[html('strong', unshift([html('em', defrag(bs))], defrag(ds)))], rest.slice(2)]
49
+ : [unshift(['**', html('em', defrag(bs))], ds), rest])
50
+ (rest, context) ?? [['**', html('em', defrag(bs))], rest];
34
51
  }
35
52
  assert(false);
36
53
  },
@@ -26,11 +26,9 @@ export const html: HTMLParser = lazy(() => creator(validate('<', validate(/^<[a-
26
26
  memoize(
27
27
  ([, tag]) =>
28
28
  surround(
29
- str(`<${tag}`), some(union([attribute])), str('>'), true,
30
- ([, as = []], rest) => [
31
- [h(tag as 'span', attributes('html', [], attrspec[tag], as))],
32
- rest
33
- ]),
29
+ `<${tag}`, some(union([attribute])), '>', true,
30
+ ([, bs = []], rest) =>
31
+ [[h(tag as 'span', attributes('html', [], attrspec[tag], bs))], rest]),
34
32
  ([, tag]) => tag)),
35
33
  match(
36
34
  /^(?=<(sup|sub|small|bdo|bdi)(?=[^\S\n]|>))/,
@@ -80,9 +78,7 @@ export const html: HTMLParser = lazy(() => creator(validate('<', validate(/^<[a-
80
78
  ([as, bs, cs], rest) =>
81
79
  [[elem(tag, as, trimNodeEndBR(defrag(bs)), cs, {})], rest],
82
80
  ([as, bs], rest) =>
83
- as.length === 1
84
- ? [unshift(as, bs), rest]
85
- : undefined)),
81
+ as.length === 1 ? [unshift(as, bs), rest] : undefined)),
86
82
  ([, tag]) => tag,
87
83
  new Cache(1000))),
88
84
  ])))));
@@ -14,6 +14,7 @@ describe('Unit: parser/inline/htmlentity', () => {
14
14
  assert.deepStrictEqual(inspect(parser('& ;')), undefined);
15
15
  assert.deepStrictEqual(inspect(parser('&\n;')), undefined);
16
16
  assert.deepStrictEqual(inspect(parser('&a;')), [['<span class="invalid">&amp;a;</span>'], '']);
17
+ assert.deepStrictEqual(inspect(parser('&NewLine;')), undefined);
17
18
  assert.deepStrictEqual(inspect(parser('&#;')), undefined);
18
19
  assert.deepStrictEqual(inspect(parser('&#g;')), undefined);
19
20
  assert.deepStrictEqual(inspect(parser('&#x;')), undefined);
@@ -2,18 +2,15 @@ import { HTMLEntityParser, UnsafeHTMLEntityParser } from '../inline';
2
2
  import { union, validate, focus, creator, fmap } from '../../combinator';
3
3
  import { html } from 'typed-dom';
4
4
 
5
- const parser = html('textarea');
5
+ export const unsafehtmlentity: UnsafeHTMLEntityParser = creator(validate('&', focus(
6
+ /^&(?!NewLine;)[0-9A-Za-z]+;/,
7
+ (parser => entity => (
8
+ parser.innerHTML = entity,
9
+ entity = parser.textContent!,
10
+ [[`${entity[0] !== '&' || entity.length === 1 ? '' : '\0'}${entity}`], '']
11
+ ))(html('b')))));
6
12
 
7
- export const unsafehtmlentity: UnsafeHTMLEntityParser = creator(validate('&', fmap(focus(
8
- /^&[0-9A-Za-z]+;/,
9
- entity => [[(parser.innerHTML = entity, parser.value)], '']),
10
- ([str]) => [
11
- str[0] !== '&' || str.length < 3
12
- ? str
13
- : `\0${str}`,
14
- ])));
15
-
16
- export const htmlentity: HTMLEntityParser = creator(validate('&', fmap(
13
+ export const htmlentity: HTMLEntityParser = fmap(
17
14
  union([unsafehtmlentity]),
18
15
  ([str]) => [
19
16
  str[0] === '\0'
@@ -24,4 +21,4 @@ export const htmlentity: HTMLEntityParser = creator(validate('&', fmap(
24
21
  'data-invalid-description': 'Invalid HTML entity.',
25
22
  }, str.slice(1))
26
23
  : str,
27
- ])));
24
+ ]);
@@ -12,10 +12,10 @@ describe('Unit: parser/inline/mark', () => {
12
12
  assert.deepStrictEqual(inspect(parser('==')), undefined);
13
13
  assert.deepStrictEqual(inspect(parser('==a')), [['==', 'a'], '']);
14
14
  assert.deepStrictEqual(inspect(parser('==a=')), [['==', 'a', '='], '']);
15
- assert.deepStrictEqual(inspect(parser('==a ==')), [['==', 'a', ' '], '==']);
16
- assert.deepStrictEqual(inspect(parser('==a\n==')), [['==', 'a', '<br>'], '==']);
17
- assert.deepStrictEqual(inspect(parser('==a\\ ==')), [['==', 'a', ' '], '==']);
18
- assert.deepStrictEqual(inspect(parser('==a\\\n==')), [['==', 'a', '<span class="linebreak"> </span>'], '==']);
15
+ assert.deepStrictEqual(inspect(parser('==a ==')), [['==', 'a', ' ', '=='], '']);
16
+ assert.deepStrictEqual(inspect(parser('==a\n==')), [['==', 'a', '<br>', '=='], '']);
17
+ assert.deepStrictEqual(inspect(parser('==a\\ ==')), [['==', 'a', ' ', '=='], '']);
18
+ assert.deepStrictEqual(inspect(parser('==a\\\n==')), [['==', 'a', '<span class="linebreak"> </span>', '=='], '']);
19
19
  assert.deepStrictEqual(inspect(parser('== ==')), undefined);
20
20
  assert.deepStrictEqual(inspect(parser('== a==')), undefined);
21
21
  assert.deepStrictEqual(inspect(parser('== a ==')), undefined);
@@ -35,6 +35,10 @@ describe('Unit: parser/inline/mark', () => {
35
35
  });
36
36
 
37
37
  it('nest', () => {
38
+ assert.deepStrictEqual(inspect(parser('==a ==b====')), [['<mark>a <mark>b</mark></mark>'], '']);
39
+ assert.deepStrictEqual(inspect(parser('==a\\ ==b====')), [['<mark>a <mark>b</mark></mark>'], '']);
40
+ assert.deepStrictEqual(inspect(parser('==a&Tab;==b====')), [['<mark>a\t<mark>b</mark></mark>'], '']);
41
+ assert.deepStrictEqual(inspect(parser('==a<wbr>==b====')), [['<mark>a<wbr><mark>b</mark></mark>'], '']);
38
42
  assert.deepStrictEqual(inspect(parser('==*==a==*==')), [['<mark><em><mark>a</mark></em></mark>'], '']);
39
43
  });
40
44
 
@@ -1,14 +1,17 @@
1
1
  import { MarkParser } from '../inline';
2
- import { union, some, creator, surround, lazy } from '../../combinator';
2
+ import { union, some, creator, surround, open, lazy } from '../../combinator';
3
3
  import { inline } from '../inline';
4
4
  import { str } from '../source';
5
- import { startTight, isEndTightNodes } from '../util';
5
+ import { startTight, isEndTightNodes, delimiter } from '../util';
6
6
  import { html, defrag } from 'typed-dom';
7
7
  import { unshift } from 'spica/array';
8
8
 
9
9
  export const mark: MarkParser = lazy(() => creator(surround(
10
10
  str('=='),
11
- startTight(union([some(inline, '==')])),
11
+ startTight(some(union([
12
+ some(inline, delimiter('==')),
13
+ open(some(inline, '='), inline),
14
+ ]))),
12
15
  str('=='), false,
13
16
  ([as, bs, cs], rest) =>
14
17
  isEndTightNodes(bs)
@@ -1,7 +1,6 @@
1
1
  import { MathParser } from '../inline';
2
- import { union, some, validate, verify, rewrite, creator, surround, lazy } from '../../combinator';
2
+ import { union, some, validate, rewrite, creator, surround, lazy } from '../../combinator';
3
3
  import { escsource, str } from '../source';
4
- import { isEndTightNodes } from '../util';
5
4
  import { html } from 'typed-dom';
6
5
 
7
6
  const disallowedCommand = /\\(?:begin|tiny|huge|large)(?![0-9a-z])/i;
@@ -10,15 +9,13 @@ export const math: MathParser = lazy(() => creator(validate('$', rewrite(
10
9
  union([
11
10
  surround(
12
11
  '$',
13
- verify(
14
- // Latex's reserved characters: # $ % ^ & _ { } ~ \
15
- // $[0-9]+ : Dollar
16
- // $[A-z]*- : Label
17
- // $[A-z]*(?!-) : Math
18
- // $[\^_[({|] : Math
19
- // $[#$%&] : Invalid first character in Latex syntax
20
- str(/^(?![\s{}#$%&]|\d+(?:[,.]\d+)*[^-+*/=<>^_~\\$]|-[\da-z]|[a-z]+-)(?:\\\$|[\x20-\x23\x25-\x7E])+/i),
21
- isEndTightNodes),
12
+ // Latex's reserved characters: # $ % ^ & _ { } ~ \
13
+ // $[0-9]+ : Dollar
14
+ // $[A-z]*- : Label
15
+ // $[A-z]*(?!-) : Math
16
+ // $[\^_[({|] : Math
17
+ // $[#$%&] : Invalid first character in Latex syntax
18
+ str(/^(?![\s{}#$%&]|\d+(?:[,.]\d+)*[^-+*/=<>^_~\\$]|-[\da-z]|[a-z]+-)(?:\\\$|\x20(?!\$)|[\x21-\x23\x25-\x7E])+/i),
22
19
  /^\$(?![0-9a-z])/i),
23
20
  surround('$', bracket, '$'),
24
21
  ]),
@@ -10,10 +10,10 @@ describe('Unit: parser/inline/strong', () => {
10
10
  assert.deepStrictEqual(inspect(parser('**')), undefined);
11
11
  assert.deepStrictEqual(inspect(parser('**a')), [['**', 'a'], '']);
12
12
  assert.deepStrictEqual(inspect(parser('**a*')), [['**', 'a', '*'], '']);
13
- assert.deepStrictEqual(inspect(parser('**a **')), [['**', 'a', ' '], '**']);
14
- assert.deepStrictEqual(inspect(parser('**a\n**')), [['**', 'a', '<br>'], '**']);
15
- assert.deepStrictEqual(inspect(parser('**a\\ **')), [['**', 'a', ' '], '**']);
16
- assert.deepStrictEqual(inspect(parser('**a\\\n**')), [['**', 'a', '<span class="linebreak"> </span>'], '**']);
13
+ assert.deepStrictEqual(inspect(parser('**a **')), [['**', 'a', ' ', '**'], '']);
14
+ assert.deepStrictEqual(inspect(parser('**a\n**')), [['**', 'a', '<br>', '**'], '']);
15
+ assert.deepStrictEqual(inspect(parser('**a\\ **')), [['**', 'a', ' ', '**'], '']);
16
+ assert.deepStrictEqual(inspect(parser('**a\\\n**')), [['**', 'a', '<span class="linebreak"> </span>', '**'], '']);
17
17
  assert.deepStrictEqual(inspect(parser('**a*b**')), [['**', 'a', '<em>b</em>', '*'], '']);
18
18
  assert.deepStrictEqual(inspect(parser('** **')), undefined);
19
19
  assert.deepStrictEqual(inspect(parser('** a**')), undefined);
@@ -35,9 +35,12 @@ describe('Unit: parser/inline/strong', () => {
35
35
  });
36
36
 
37
37
  it('nest', () => {
38
+ assert.deepStrictEqual(inspect(parser('**a *b***')), [['<strong>a <em>b</em></strong>'], '']);
39
+ assert.deepStrictEqual(inspect(parser('**a **b****')), [['<strong>a <strong>b</strong></strong>'], '']);
40
+ assert.deepStrictEqual(inspect(parser('**a&Tab;**b****')), [['<strong>a\t<strong>b</strong></strong>'], '']);
41
+ assert.deepStrictEqual(inspect(parser('**a<wbr>**b****')), [['<strong>a<wbr><strong>b</strong></strong>'], '']);
38
42
  assert.deepStrictEqual(inspect(parser('**a*b*c**')), [['<strong>a<em>b</em>c</strong>'], '']);
39
43
  assert.deepStrictEqual(inspect(parser('**a*b*c**d')), [['<strong>a<em>b</em>c</strong>'], 'd']);
40
- assert.deepStrictEqual(inspect(parser('**a *b***')), [['<strong>a <em>b</em></strong>'], '']);
41
44
  assert.deepStrictEqual(inspect(parser('**`a`**')), [['<strong><code data-src="`a`">a</code></strong>'], '']);
42
45
  assert.deepStrictEqual(inspect(parser('**<small>**')), [['<strong>&lt;small&gt;</strong>'], '']);
43
46
  assert.deepStrictEqual(inspect(parser('**(*a*)**')), [['<strong><span class="paren">(<em>a</em>)</span></strong>'], '']);
@@ -1,15 +1,17 @@
1
1
  import { StrongParser } from '../inline';
2
- import { union, some, creator, surround, close, lazy } from '../../combinator';
2
+ import { union, some, creator, surround, open, lazy } from '../../combinator';
3
3
  import { inline } from '../inline';
4
- import { emphasis } from './emphasis';
5
4
  import { str } from '../source';
6
- import { startTight, isEndTightNodes } from '../util';
5
+ import { startTight, isEndTightNodes, delimiter } from '../util';
7
6
  import { html, defrag } from 'typed-dom';
8
7
  import { unshift } from 'spica/array';
9
8
 
10
- export const strong: StrongParser = lazy(() => creator(surround(close(
11
- str('**'), /^(?!\*)/),
12
- startTight(some(union([emphasis, some(inline, '*'), str('*')]), '**')),
9
+ export const strong: StrongParser = lazy(() => creator(surround(
10
+ str('**'),
11
+ startTight(some(union([
12
+ some(inline, delimiter(String.raw`\*\*`)),
13
+ open(some(inline, '*'), inline),
14
+ ])), '*'),
13
15
  str('**'), false,
14
16
  ([as, bs, cs], rest) =>
15
17
  isEndTightNodes(bs)
@@ -26,26 +26,73 @@ describe('Unit: parser/inline', () => {
26
26
  assert.deepStrictEqual(inspect(parser('*** a***')), [['***', ' ', 'a', '***'], '']);
27
27
  assert.deepStrictEqual(inspect(parser('**** a****')), [['****', ' ', 'a', '****'], '']);
28
28
  assert.deepStrictEqual(inspect(parser('*a**')), [['<em>a</em>', '*'], '']);
29
+ assert.deepStrictEqual(inspect(parser('*a**b')), [['*', 'a', '**', 'b'], '']);
29
30
  assert.deepStrictEqual(inspect(parser('*a**b*')), [['*', 'a', '**', 'b', '*'], '']);
30
31
  assert.deepStrictEqual(inspect(parser('*a**b*c')), [['*', 'a', '**', 'b', '*', 'c'], '']);
31
32
  assert.deepStrictEqual(inspect(parser('*a**b*c*')), [['*', 'a', '**', 'b', '<em>c</em>'], '']);
32
33
  assert.deepStrictEqual(inspect(parser('*a**b**')), [['*', 'a', '<strong>b</strong>'], '']);
34
+ assert.deepStrictEqual(inspect(parser('*a**b**c')), [['*', 'a', '<strong>b</strong>', 'c'], '']);
35
+ assert.deepStrictEqual(inspect(parser('*a**b***')), [['<em>a<strong>b</strong></em>'], '']);
36
+ assert.deepStrictEqual(inspect(parser('*a**b***c')), [['<em>a<strong>b</strong></em>', 'c'], '']);
37
+ assert.deepStrictEqual(inspect(parser('*a**b****')), [['<em>a<strong>b</strong></em>', '*'], '']);
38
+ assert.deepStrictEqual(inspect(parser('*a**b****c')), [['*', 'a', '<strong>b</strong>', '**', 'c'], '']);
39
+ assert.deepStrictEqual(inspect(parser('*a***b****')), [['<em>a</em>', '<strong>b</strong>', '**'], '']);
40
+ assert.deepStrictEqual(inspect(parser('*a***b****c')), [['<em>a</em>', '<strong>b</strong>', '**', 'c'], '']);
41
+ assert.deepStrictEqual(inspect(parser('*a *b**')), [['<em>a <em>b</em></em>'], '']);
42
+ assert.deepStrictEqual(inspect(parser('*a *b**c')), [['*', 'a', ' ', '*', 'b', '**', 'c'], '']);
33
43
  assert.deepStrictEqual(inspect(parser('*a **b***')), [['<em>a <strong>b</strong></em>'], '']);
34
44
  assert.deepStrictEqual(inspect(parser('*a **b***c')), [['<em>a <strong>b</strong></em>', 'c'], '']);
45
+ assert.deepStrictEqual(inspect(parser('*a ***b****')), [['<em>a <em><strong>b</strong></em></em>'], '']);
46
+ assert.deepStrictEqual(inspect(parser('*a ***b****c')), [['<em>a <em><strong>b</strong></em></em>', 'c'], '']);
35
47
  assert.deepStrictEqual(inspect(parser('**a*')), [['**', 'a', '*'], '']);
36
48
  assert.deepStrictEqual(inspect(parser('**a*b**')), [['**', 'a', '<em>b</em>', '*'], '']);
37
49
  assert.deepStrictEqual(inspect(parser('**a*b**c')), [['**', 'a', '*', 'b', '**', 'c'], '']);
50
+ assert.deepStrictEqual(inspect(parser('**a*b***')), [['<strong>a<em>b</em></strong>'], '']);
51
+ assert.deepStrictEqual(inspect(parser('**a*b***c')), [['<strong>a<em>b</em></strong>', 'c'], '']);
52
+ assert.deepStrictEqual(inspect(parser('**a**b****')), [['<strong>a</strong>', 'b', '****'], '']);
53
+ assert.deepStrictEqual(inspect(parser('**a**b****c')), [['<strong>a</strong>', 'b', '****', 'c'], '']);
54
+ assert.deepStrictEqual(inspect(parser('**a***b*****')), [['<strong>a</strong>', '<em>b</em>', '****'], '']);
55
+ assert.deepStrictEqual(inspect(parser('**a***b*****c')), [['<strong>a</strong>', '<em>b</em>', '****', 'c'], '']);
38
56
  assert.deepStrictEqual(inspect(parser('**a *b***')), [['<strong>a <em>b</em></strong>'], '']);
39
57
  assert.deepStrictEqual(inspect(parser('**a *b***c')), [['<strong>a <em>b</em></strong>', 'c'], '']);
58
+ assert.deepStrictEqual(inspect(parser('**a **b****')), [['<strong>a <strong>b</strong></strong>'], '']);
59
+ assert.deepStrictEqual(inspect(parser('**a **b****c')), [['<strong>a <strong>b</strong></strong>', 'c'], '']);
60
+ assert.deepStrictEqual(inspect(parser('**a ***b*****')), [['<strong>a <em><strong>b</strong></em></strong>'], '']);
61
+ assert.deepStrictEqual(inspect(parser('**a ***b*****c')), [['<strong>a <em><strong>b</strong></em></strong>', 'c'], '']);
40
62
  assert.deepStrictEqual(inspect(parser('***a*b**')), [['<strong><em>a</em>b</strong>'], '']);
41
- assert.deepStrictEqual(inspect(parser('***a* b**')), [['<strong><em>a</em> b</strong>'], '']);
63
+ assert.deepStrictEqual(inspect(parser('***a*b**c')), [['<strong><em>a</em>b</strong>', 'c'], '']);
64
+ assert.deepStrictEqual(inspect(parser('***a*b*c***')), [['<strong><em>a</em>b<em>c</em></strong>'], '']);
65
+ assert.deepStrictEqual(inspect(parser('***a*b*c***d')), [['<strong><em>a</em>b<em>c</em></strong>', 'd'], '']);
66
+ assert.deepStrictEqual(inspect(parser('***a*b**c****')), [['<strong><em>a</em>b</strong>', 'c', '****'], '']);
67
+ assert.deepStrictEqual(inspect(parser('***a* **b****')), [['<strong><em>a</em> <strong>b</strong></strong>'], '']);
68
+ assert.deepStrictEqual(inspect(parser('***a*\\ **b****')), [['<strong><em>a</em> <strong>b</strong></strong>'], '']);
69
+ assert.deepStrictEqual(inspect(parser('***a*&Tab;**b****')), [['<strong><em>a</em>\t<strong>b</strong></strong>'], '']);
70
+ assert.deepStrictEqual(inspect(parser('***a*<wbr>**b****')), [['<strong><em>a</em><wbr><strong>b</strong></strong>'], '']);
71
+ assert.deepStrictEqual(inspect(parser('***a *b****')), [['<em><strong>a <em>b</em></strong></em>'], '']);
72
+ assert.deepStrictEqual(inspect(parser('***a\\ *b****')), [['<em><strong>a <em>b</em></strong></em>'], '']);
73
+ assert.deepStrictEqual(inspect(parser('***a&Tab;*b****')), [['<em><strong>a\t<em>b</em></strong></em>'], '']);
74
+ assert.deepStrictEqual(inspect(parser('***a<wbr>*b****')), [['<em><strong>a<wbr><em>b</em></strong></em>'], '']);
75
+ assert.deepStrictEqual(inspect(parser('***a*b **')), [['**', '<em>a</em>', 'b', ' ', '**'], '']);
76
+ assert.deepStrictEqual(inspect(parser('***a*b\\ **')), [['**', '<em>a</em>', 'b', ' ', '**'], '']);
42
77
  assert.deepStrictEqual(inspect(parser('***a**b*')), [['<em><strong>a</strong>b</em>'], '']);
43
- assert.deepStrictEqual(inspect(parser('***a** b*')), [['<em><strong>a</strong> b</em>'], '']);
78
+ assert.deepStrictEqual(inspect(parser('***a**b*c')), [['<em><strong>a</strong>b</em>', 'c'], '']);
79
+ assert.deepStrictEqual(inspect(parser('***a**b*c**')), [['<em><strong>a</strong>b</em>', 'c', '**'], '']);
80
+ assert.deepStrictEqual(inspect(parser('***a**b**c***')), [['<em><strong>a</strong>b<strong>c</strong></em>'], '']);
81
+ assert.deepStrictEqual(inspect(parser('***a**b**c***d')), [['<em><strong>a</strong>b<strong>c</strong></em>', 'd'], '']);
82
+ assert.deepStrictEqual(inspect(parser('***a** *b**')), [['<em><strong>a</strong> <em>b</em></em>'], '']);
83
+ assert.deepStrictEqual(inspect(parser('***a**\\ *b**')), [['<em><strong>a</strong> <em>b</em></em>'], '']);
84
+ assert.deepStrictEqual(inspect(parser('***a**&Tab;*b**')), [['<em><strong>a</strong>\t<em>b</em></em>'], '']);
85
+ assert.deepStrictEqual(inspect(parser('***a**<wbr>*b**')), [['<em><strong>a</strong><wbr><em>b</em></em>'], '']);
86
+ assert.deepStrictEqual(inspect(parser('***a **b*')), [['***', 'a', ' ', '**', 'b', '*'], '']);
87
+ assert.deepStrictEqual(inspect(parser('***a\\ **b*')), [['***', 'a', ' ', '**', 'b', '*'], '']);
88
+ assert.deepStrictEqual(inspect(parser('***a**b *')), [['*', '<strong>a</strong>', 'b', ' ', '*'], '']);
89
+ assert.deepStrictEqual(inspect(parser('***a**b\\ *')), [['*', '<strong>a</strong>', 'b', ' ', '*'], '']);
44
90
  assert.deepStrictEqual(inspect(parser('***a*')), [['**', '<em>a</em>'], '']);
45
91
  assert.deepStrictEqual(inspect(parser('***a**')), [['*', '<strong>a</strong>'], '']);
46
92
  assert.deepStrictEqual(inspect(parser('***a***')), [['<em><strong>a</strong></em>'], '']);
47
93
  assert.deepStrictEqual(inspect(parser('***a***b')), [['<em><strong>a</strong></em>', 'b'], '']);
48
94
  assert.deepStrictEqual(inspect(parser('***a****')), [['<em><strong>a</strong></em>', '*'], '']);
95
+ assert.deepStrictEqual(inspect(parser('***a *b****')), [['<em><strong>a <em>b</em></strong></em>'], '']);
49
96
  assert.deepStrictEqual(inspect(parser('****a***')), [['****', 'a', '***'], '']);
50
97
  assert.deepStrictEqual(inspect(parser('****a****')), [['****', 'a', '****'], '']);
51
98
  assert.deepStrictEqual(inspect(parser('*(*a*)*')), [['<em><span class="paren">(<em>a</em>)</span></em>'], '']);
@@ -4,47 +4,16 @@ import { Parser, eval } from '../combinator/data/parser';
4
4
  import { union, some, verify, convert } from '../combinator';
5
5
  import { unsafehtmlentity } from './inline/htmlentity';
6
6
  import { linebreak, unescsource } from './source';
7
+ import { invisibleHTMLEntityNames } from './api/normalize';
7
8
  import { push, pop } from 'spica/array';
8
9
 
9
- // https://dev.w3.org/html5/html-author/charref
10
- const invisibleHTMLEntityNames = [
11
- 'Tab',
12
- 'NewLine',
13
- 'NonBreakingSpace',
14
- 'nbsp',
15
- 'shy',
16
- 'ensp',
17
- 'emsp',
18
- 'emsp13',
19
- 'emsp14',
20
- 'numsp',
21
- 'puncsp',
22
- 'ThinSpace',
23
- 'thinsp',
24
- 'VeryThinSpace',
25
- 'hairsp',
26
- 'ZeroWidthSpace',
27
- 'NegativeVeryThinSpace',
28
- 'NegativeThinSpace',
29
- 'NegativeMediumSpace',
30
- 'NegativeThickSpace',
31
- 'zwj',
32
- 'zwnj',
33
- 'lrm',
34
- 'rlm',
35
- 'MediumSpace',
36
- 'NoBreak',
37
- 'ApplyFunction',
38
- 'af',
39
- 'InvisibleTimes',
40
- 'it',
41
- 'InvisibleComma',
42
- 'ic',
43
- ];
44
- const blankline = new RegExp(String.raw`^(?!$)(?:\\$|\\?[^\S\n]|&(?:${invisibleHTMLEntityNames.join('|')});|<wbr>)+$`, 'gm');
10
+ export function delimiter(opener: string): RegExp {
11
+ return new RegExp(String.raw`^(?:\s+|\\\s|&(?:${invisibleHTMLEntityNames.join('|')});|<wbr>)?${opener}`);
12
+ }
45
13
 
46
14
  export function visualize<P extends Parser<HTMLElement | string>>(parser: P): P;
47
15
  export function visualize<T extends HTMLElement | string>(parser: Parser<T>): Parser<T> {
16
+ const blankline = new RegExp(String.raw`^(?:\\$|\\?[^\S\n]|&(?:${invisibleHTMLEntityNames.join('|')});|<wbr>)+$`, 'gm');
48
17
  return union([
49
18
  convert(
50
19
  source => source.replace(blankline, line => line.replace(/[\\&<]/g, '\x1B$&')),
@@ -79,25 +48,24 @@ export function startLoose<T extends HTMLElement | string>(parser: Parser<T>, ex
79
48
  export function isStartLoose(source: string, context: MarkdownParser.Context, except?: string): boolean {
80
49
  source &&= source.replace(/^[^\S\n]+/, '');
81
50
  if (source === '') return true;
82
- return source.slice(0, except?.length ?? 0) !== except
83
- && isStartTight(source, context);
51
+ return isStartTight(source, context, except);
84
52
  }
85
- export function startTight<P extends Parser<unknown>>(parser: P): P;
86
- export function startTight<T>(parser: Parser<T>): Parser<T> {
53
+ export function startTight<P extends Parser<unknown>>(parser: P, except?: string): P;
54
+ export function startTight<T>(parser: Parser<T>, except?: string): Parser<T> {
87
55
  return (source, context) =>
88
- isStartTight(source, context)
56
+ isStartTight(source, context, except)
89
57
  ? parser(source, context)
90
58
  : undefined;
91
59
  }
92
- function isStartTight(source: string, context: MarkdownParser.Context): boolean {
60
+ function isStartTight(source: string, context: MarkdownParser.Context, except?: string): boolean {
93
61
  if (source === '') return true;
62
+ if (except && source.slice(0, except.length) === except) return false;
94
63
  switch (source[0]) {
95
64
  case ' ':
96
65
  case ' ':
97
66
  case '\t':
98
67
  case '\n':
99
68
  return false;
100
- case '\x1B':
101
69
  case '\\':
102
70
  return source[1]?.trimStart() !== '';
103
71
  case '&':