securemark 0.234.2 → 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,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.234.3
4
+
5
+ - Refactoring.
6
+
3
7
  ## 0.234.2
4
8
 
5
9
  - Refactoring.
@@ -1,4 +1,4 @@
1
- /*! securemark v0.234.2 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,11 +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
6678
  (0, combinator_1.some)(inline_1.inline, (0, util_1.delimiter)(String.raw`\*`)),
6678
6679
  (0, combinator_1.open)((0, combinator_1.some)(inline_1.inline, '*'), inline_1.inline)
6679
- ]))), (0, source_1.str)('*'), false, ([as, bs, cs], rest) => (0, util_1.isEndTightNodes)(bs) ? [
6680
+ ])), '*'), (0, source_1.str)('*'), false, ([as, bs, cs], rest) => (0, util_1.isEndTightNodes)(bs) ? [
6680
6681
  [(0, typed_dom_1.html)('em', (0, typed_dom_1.defrag)(bs))],
6681
6682
  rest
6682
6683
  ] : [
@@ -7113,8 +7114,8 @@ require = function () {
7113
7114
  (0, alias_1.ObjectSetPrototypeOf)(attrspec, null);
7114
7115
  (0, alias_1.ObjectValues)(attrspec).forEach(o => (0, alias_1.ObjectSetPrototypeOf)(o, null));
7115
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)([
7116
- (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) => [
7117
- [(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))],
7118
7119
  rest
7119
7120
  ]), ([, tag]) => tag)),
7120
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)((() => {
@@ -7237,17 +7238,16 @@ require = function () {
7237
7238
  exports.htmlentity = exports.unsafehtmlentity = void 0;
7238
7239
  const combinator_1 = _dereq_('../../combinator');
7239
7240
  const typed_dom_1 = _dereq_('typed-dom');
7240
- const parser = (0, typed_dom_1.html)('textarea');
7241
- exports.unsafehtmlentity = (0, combinator_1.creator)((0, combinator_1.validate)('&', (0, combinator_1.fmap)((0, combinator_1.focus)(/^&(?!NewLine;)[0-9A-Za-z]+;/, entity => [
7242
- [(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 }`],
7243
7243
  ''
7244
- ]), ([str]) => [str[0] !== '&' || str.length < 3 ? str : `\0${ str }`])));
7245
- 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', {
7246
7246
  class: 'invalid',
7247
7247
  'data-invalid-syntax': 'htmlentity',
7248
7248
  'data-invalid-type': 'syntax',
7249
7249
  'data-invalid-description': 'Invalid HTML entity.'
7250
- }, str.slice(1)) : str])));
7250
+ }, str.slice(1)) : str]);
7251
7251
  },
7252
7252
  {
7253
7253
  '../../combinator': 27,
@@ -7856,10 +7856,10 @@ require = function () {
7856
7856
  const util_1 = _dereq_('../util');
7857
7857
  const typed_dom_1 = _dereq_('typed-dom');
7858
7858
  const array_1 = _dereq_('spica/array');
7859
- 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)([
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
7860
  (0, combinator_1.some)(inline_1.inline, (0, util_1.delimiter)(String.raw`\*\*`)),
7861
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) ? [
7862
+ ])), '*'), (0, source_1.str)('**'), false, ([as, bs, cs], rest) => (0, util_1.isEndTightNodes)(bs) ? [
7863
7863
  [(0, typed_dom_1.html)('strong', (0, typed_dom_1.defrag)(bs))],
7864
7864
  rest
7865
7865
  ] : [
@@ -8656,47 +8656,14 @@ require = function () {
8656
8656
  const combinator_1 = _dereq_('../combinator');
8657
8657
  const htmlentity_1 = _dereq_('./inline/htmlentity');
8658
8658
  const source_1 = _dereq_('./source');
8659
+ const normalize_1 = _dereq_('./api/normalize');
8659
8660
  const array_1 = _dereq_('spica/array');
8660
- const invisibleHTMLEntityNames = [
8661
- 'Tab',
8662
- 'NewLine',
8663
- 'NonBreakingSpace',
8664
- 'nbsp',
8665
- 'shy',
8666
- 'ensp',
8667
- 'emsp',
8668
- 'emsp13',
8669
- 'emsp14',
8670
- 'numsp',
8671
- 'puncsp',
8672
- 'ThinSpace',
8673
- 'thinsp',
8674
- 'VeryThinSpace',
8675
- 'hairsp',
8676
- 'ZeroWidthSpace',
8677
- 'NegativeVeryThinSpace',
8678
- 'NegativeThinSpace',
8679
- 'NegativeMediumSpace',
8680
- 'NegativeThickSpace',
8681
- 'zwj',
8682
- 'zwnj',
8683
- 'lrm',
8684
- 'rlm',
8685
- 'MediumSpace',
8686
- 'NoBreak',
8687
- 'ApplyFunction',
8688
- 'af',
8689
- 'InvisibleTimes',
8690
- 'it',
8691
- 'InvisibleComma',
8692
- 'ic'
8693
- ];
8694
- const blankline = new RegExp(String.raw`^(?:\\$|\\?[^\S\n]|&(?:${ invisibleHTMLEntityNames.join('|') });|<wbr>)+$`, 'gm');
8695
8661
  function delimiter(opener) {
8696
- return new RegExp(String.raw`^(?:\s+|\\\s|&(?:${ invisibleHTMLEntityNames.join('|') });|<wbr>)?${ opener }`);
8662
+ return new RegExp(String.raw`^(?:\s+|\\\s|&(?:${ normalize_1.invisibleHTMLEntityNames.join('|') });|<wbr>)?${ opener }`);
8697
8663
  }
8698
8664
  exports.delimiter = delimiter;
8699
8665
  function visualize(parser) {
8666
+ const blankline = new RegExp(String.raw`^(?:\\$|\\?[^\S\n]|&(?:${ normalize_1.invisibleHTMLEntityNames.join('|') });|<wbr>)+$`, 'gm');
8700
8667
  return (0, combinator_1.union)([
8701
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))),
8702
8669
  (0, combinator_1.some)((0, combinator_1.union)([
@@ -8732,21 +8699,22 @@ require = function () {
8732
8699
  }
8733
8700
  exports.startLoose = startLoose;
8734
8701
  function isStartLoose(source, context, except) {
8735
- var _a;
8736
8702
  source && (source = source.replace(/^[^\S\n]+/, ''));
8737
8703
  if (source === '')
8738
8704
  return true;
8739
- 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);
8740
8706
  }
8741
8707
  exports.isStartLoose = isStartLoose;
8742
- function startTight(parser) {
8743
- 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;
8744
8710
  }
8745
8711
  exports.startTight = startTight;
8746
- function isStartTight(source, context) {
8712
+ function isStartTight(source, context, except) {
8747
8713
  var _a, _b, _c;
8748
8714
  if (source === '')
8749
8715
  return true;
8716
+ if (except && source.slice(0, except.length) === except)
8717
+ return false;
8750
8718
  switch (source[0]) {
8751
8719
  case ' ':
8752
8720
  case '\u3000':
@@ -8866,6 +8834,7 @@ require = function () {
8866
8834
  {
8867
8835
  '../combinator': 27,
8868
8836
  '../combinator/data/parser': 47,
8837
+ './api/normalize': 60,
8869
8838
  './inline/htmlentity': 112,
8870
8839
  './source': 128,
8871
8840
  'spica/array': 6,
package/package-lock.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.234.2",
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": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.234.2",
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",
@@ -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('')
@@ -1,5 +1,5 @@
1
1
  import { EmphasisParser } from '../inline';
2
- import { union, some, creator, surround, open, 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';
@@ -7,13 +7,13 @@ 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('*'), /^(?!\*)/),
10
+ export const emphasis: EmphasisParser = lazy(() => creator(surround(
11
+ str('*'),
12
12
  startTight(some(union([
13
13
  strong,
14
14
  some(inline, delimiter(String.raw`\*`)),
15
15
  open(some(inline, '*'), inline),
16
- ]))),
16
+ ])), '*'),
17
17
  str('*'), false,
18
18
  ([as, bs, cs], rest) =>
19
19
  isEndTightNodes(bs)
@@ -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
  ])))));
@@ -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');
6
-
7
- export const unsafehtmlentity: UnsafeHTMLEntityParser = creator(validate('&', fmap(focus(
5
+ export const unsafehtmlentity: UnsafeHTMLEntityParser = creator(validate('&', focus(
8
6
  /^&(?!NewLine;)[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
- ])));
7
+ (parser => entity => (
8
+ parser.innerHTML = entity,
9
+ entity = parser.textContent!,
10
+ [[`${entity[0] !== '&' || entity.length === 1 ? '' : '\0'}${entity}`], '']
11
+ ))(html('b')))));
15
12
 
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
+ ]);
@@ -1,17 +1,17 @@
1
1
  import { StrongParser } from '../inline';
2
- import { union, some, creator, surround, open, close, 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
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
- export const strong: StrongParser = lazy(() => creator(surround(close(
10
- str('**'), /^(?!\*)/),
9
+ export const strong: StrongParser = lazy(() => creator(surround(
10
+ str('**'),
11
11
  startTight(some(union([
12
12
  some(inline, delimiter(String.raw`\*\*`)),
13
13
  open(some(inline, '*'), inline),
14
- ]))),
14
+ ])), '*'),
15
15
  str('**'), false,
16
16
  ([as, bs, cs], rest) =>
17
17
  isEndTightNodes(bs)
@@ -4,51 +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
- ] as const;
44
- const blankline = new RegExp(String.raw`^(?:\\$|\\?[^\S\n]|&(?:${invisibleHTMLEntityNames.join('|')});|<wbr>)+$`, 'gm');
45
-
46
10
  export function delimiter(opener: string): RegExp {
47
11
  return new RegExp(String.raw`^(?:\s+|\\\s|&(?:${invisibleHTMLEntityNames.join('|')});|<wbr>)?${opener}`);
48
12
  }
49
13
 
50
14
  export function visualize<P extends Parser<HTMLElement | string>>(parser: P): P;
51
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');
52
17
  return union([
53
18
  convert(
54
19
  source => source.replace(blankline, line => line.replace(/[\\&<]/g, '\x1B$&')),
@@ -83,18 +48,18 @@ export function startLoose<T extends HTMLElement | string>(parser: Parser<T>, ex
83
48
  export function isStartLoose(source: string, context: MarkdownParser.Context, except?: string): boolean {
84
49
  source &&= source.replace(/^[^\S\n]+/, '');
85
50
  if (source === '') return true;
86
- return source.slice(0, except?.length ?? 0) !== except
87
- && isStartTight(source, context);
51
+ return isStartTight(source, context, except);
88
52
  }
89
- export function startTight<P extends Parser<unknown>>(parser: P): P;
90
- 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> {
91
55
  return (source, context) =>
92
- isStartTight(source, context)
56
+ isStartTight(source, context, except)
93
57
  ? parser(source, context)
94
58
  : undefined;
95
59
  }
96
- function isStartTight(source: string, context: MarkdownParser.Context): boolean {
60
+ function isStartTight(source: string, context: MarkdownParser.Context, except?: string): boolean {
97
61
  if (source === '') return true;
62
+ if (except && source.slice(0, except.length) === except) return false;
98
63
  switch (source[0]) {
99
64
  case ' ':
100
65
  case ' ':