securemark 0.283.3 → 0.283.5

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.
Files changed (62) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/index.js +142 -107
  3. package/markdown.d.ts +16 -8
  4. package/package.json +1 -1
  5. package/src/combinator/control/manipulation/surround.ts +4 -4
  6. package/src/combinator/data/parser/context/delimiter.ts +20 -20
  7. package/src/combinator/data/parser/context.ts +4 -3
  8. package/src/parser/block/blockquote.ts +1 -1
  9. package/src/parser/block/dlist.ts +6 -6
  10. package/src/parser/block/extension/aside.ts +1 -1
  11. package/src/parser/block/extension/example.ts +2 -2
  12. package/src/parser/block/extension/figure.ts +3 -3
  13. package/src/parser/block/extension/table.ts +5 -5
  14. package/src/parser/block/heading.ts +6 -6
  15. package/src/parser/block/ilist.ts +1 -1
  16. package/src/parser/block/olist.ts +1 -1
  17. package/src/parser/block/paragraph.ts +3 -3
  18. package/src/parser/block/reply.ts +2 -2
  19. package/src/parser/block/sidefence.ts +1 -1
  20. package/src/parser/block/table.ts +4 -4
  21. package/src/parser/block/ulist.ts +1 -1
  22. package/src/parser/block.ts +4 -3
  23. package/src/parser/context.ts +18 -9
  24. package/src/parser/inline/annotation.ts +7 -4
  25. package/src/parser/inline/autolink/account.ts +15 -14
  26. package/src/parser/inline/autolink/anchor.ts +14 -13
  27. package/src/parser/inline/autolink/channel.ts +6 -3
  28. package/src/parser/inline/autolink/email.ts +4 -3
  29. package/src/parser/inline/autolink/hashnum.ts +11 -9
  30. package/src/parser/inline/autolink/hashtag.ts +11 -9
  31. package/src/parser/inline/autolink/url.ts +24 -18
  32. package/src/parser/inline/autolink.ts +4 -5
  33. package/src/parser/inline/bracket.ts +6 -6
  34. package/src/parser/inline/code.ts +1 -1
  35. package/src/parser/inline/deletion.ts +1 -1
  36. package/src/parser/inline/emphasis.ts +1 -1
  37. package/src/parser/inline/emstrong.ts +1 -1
  38. package/src/parser/inline/extension/index.ts +9 -6
  39. package/src/parser/inline/extension/indexer.ts +1 -1
  40. package/src/parser/inline/extension/label.ts +1 -1
  41. package/src/parser/inline/extension/placeholder.ts +1 -1
  42. package/src/parser/inline/html.ts +45 -43
  43. package/src/parser/inline/htmlentity.ts +3 -3
  44. package/src/parser/inline/insertion.ts +1 -1
  45. package/src/parser/inline/link.test.ts +7 -2
  46. package/src/parser/inline/link.ts +11 -15
  47. package/src/parser/inline/mark.ts +1 -1
  48. package/src/parser/inline/math.ts +1 -1
  49. package/src/parser/inline/media.ts +4 -4
  50. package/src/parser/inline/reference.ts +7 -4
  51. package/src/parser/inline/remark.ts +4 -4
  52. package/src/parser/inline/ruby.ts +7 -6
  53. package/src/parser/inline/shortmedia.ts +1 -1
  54. package/src/parser/inline/strong.ts +1 -1
  55. package/src/parser/inline/template.ts +2 -2
  56. package/src/parser/inline.test.ts +1 -0
  57. package/src/parser/segment.ts +3 -2
  58. package/src/parser/source/escapable.ts +2 -2
  59. package/src/parser/source/str.ts +1 -1
  60. package/src/parser/source/text.ts +3 -3
  61. package/src/parser/source/unescapable.ts +4 -2
  62. package/src/parser/visibility.ts +14 -13
@@ -1,10 +1,10 @@
1
1
  import { MarkParser } from '../inline';
2
+ import { State, Recursion } from '../context';
2
3
  import { union, some, syntax, creation, constraint, surround, open, lazy } from '../../combinator';
3
4
  import { inline } from '../inline';
4
5
  import { identity, signature } from './extension/indexee';
5
6
  import { str } from '../source';
6
7
  import { startTight, blankWith } from '../visibility';
7
- import { State, Recursion } from '../context';
8
8
  import { unshift } from 'spica/array';
9
9
  import { html, define, defrag } from 'typed-dom/dom';
10
10
 
@@ -1,7 +1,7 @@
1
1
  import { MathParser } from '../inline';
2
+ import { Recursion } from '../context';
2
3
  import { union, some, creation, precedence, validate, focus, rewrite, surround, lazy } from '../../combinator';
3
4
  import { escsource, unescsource, str } from '../source';
4
- import { Recursion } from '../context';
5
5
  import { html } from 'typed-dom/dom';
6
6
 
7
7
  const forbiddenCommand = /\\(?:begin|tiny|huge|large)(?![a-z])/i;
@@ -1,10 +1,10 @@
1
1
  import { MediaParser } from '../inline';
2
+ import { State, Recursion, Backtrack, Command, CmdRegExp } from '../context';
2
3
  import { union, inits, tails, some, syntax, creation, precedence, constraint, validate, verify, surround, open, dup, lazy, fmap, bind } from '../../combinator';
3
4
  import { unsafelink, uri, option as linkoption, resolve } from './link';
4
5
  import { attributes } from './html';
5
6
  import { unsafehtmlentity } from './htmlentity';
6
7
  import { txt, linebreak, str } from '../source';
7
- import { State, Recursion, Backtrack } from '../context';
8
8
  import { markInvalid } from '../util';
9
9
  import { ReadonlyURL } from 'spica/url';
10
10
  import { unshift, push } from 'spica/array';
@@ -25,7 +25,7 @@ export const media: MediaParser = lazy(() => validate(['![', '!{'], creation(1,
25
25
  bind(verify(fmap(tails([
26
26
  dup(surround(
27
27
  '[',
28
- some(union([unsafehtmlentity, bracket, txt]), ']', [[/^\\?\n/, 9]]),
28
+ some(union([unsafehtmlentity, bracket, txt]), ']', [['\n', 9]]),
29
29
  ']',
30
30
  true, undefined, undefined, 1 | Backtrack.media)),
31
31
  dup(surround(
@@ -105,8 +105,8 @@ function sanitize(target: HTMLElement, uri: ReadonlyURL, alt: string): boolean {
105
105
  markInvalid(target, 'media', 'argument', 'Invalid protocol');
106
106
  return false;
107
107
  }
108
- if (alt.includes('\x1B')) {
109
- define(target, { alt: target.getAttribute('alt')?.replace(/\x1B/g, '') });
108
+ if (alt.includes(Command.Escape)) {
109
+ define(target, { alt: target.getAttribute('alt')?.replace(CmdRegExp.Escape, '') });
110
110
  markInvalid(target, 'media', 'content',
111
111
  `Cannot use invalid HTML entitiy "${alt.match(/&[0-9A-Za-z]+;/)![0]}"`);
112
112
  return false;
@@ -1,9 +1,9 @@
1
1
  import { ReferenceParser } from '../inline';
2
+ import { State, Recursion, Backtrack } from '../context';
2
3
  import { union, subsequence, some, syntax, creation, constraint, surround, lazy } from '../../combinator';
3
4
  import { inline } from '../inline';
4
5
  import { str } from '../source';
5
- import { State, Recursion, Backtrack } from '../context';
6
- import { blank, trimBlankStart, trimNodeEnd } from '../visibility';
6
+ import { blank, trimBlankStart, trimBlankNodeEnd } from '../visibility';
7
7
  import { html, defrag } from 'typed-dom/dom';
8
8
 
9
9
  export const reference: ReferenceParser = lazy(() => creation(1, Recursion.ignore, surround(
@@ -12,11 +12,14 @@ export const reference: ReferenceParser = lazy(() => creation(1, Recursion.ignor
12
12
  syntax(1, State.annotation | State.reference | State.media,
13
13
  subsequence([
14
14
  abbr,
15
- trimBlankStart(some(inline, ']', [[/^\\?\n/, 9], [']', 1]])),
15
+ trimBlankStart(some(inline, ']', [['\n', 9], [']', 1]])),
16
16
  ]))),
17
17
  ']]',
18
18
  false,
19
- ([, ns], rest) => [[html('sup', attributes(ns), [html('span', trimNodeEnd(defrag(ns)))])], rest],
19
+ ([, ns], rest) =>
20
+ trimBlankNodeEnd(ns).length > 0
21
+ ? [[html('sup', attributes(ns), [html('span', defrag(ns))])], rest]
22
+ : undefined,
20
23
  undefined, 1 | Backtrack.bracket)));
21
24
 
22
25
  // Chicago-Style
@@ -1,19 +1,19 @@
1
1
  import { RemarkParser } from '../inline';
2
+ import { State, Recursion } from '../context';
2
3
  import { union, some, syntax, creation, validate, surround, open, close, match, lazy } from '../../combinator';
3
4
  import { inline } from '../inline';
4
5
  import { text, str } from '../source';
5
- import { State, Recursion } from '../context';
6
6
  import { memoize } from 'spica/memoize';
7
7
  import { unshift, push } from 'spica/array';
8
8
  import { html, defrag } from 'typed-dom/dom';
9
9
 
10
- export const remark: RemarkParser = lazy(() => validate('[%', creation(1, Recursion.inline, syntax(4, State.none, match(
10
+ export const remark: RemarkParser = lazy(() => validate('[%', creation(1, Recursion.inline, match(
11
11
  /^\[(%+)\s/,
12
12
  memoize(
13
13
  ([, fence]) =>
14
14
  surround(
15
15
  open(str(`[${fence}`), some(text, new RegExp(String.raw`^\s+${fence}\]|^\S`)), true),
16
- some(union([inline]), new RegExp(String.raw`^\s+${fence}\]`), [[new RegExp(String.raw`^\s+${fence}\]`), 4]]),
16
+ syntax(4, State.none, some(union([inline]), new RegExp(String.raw`^\s+${fence}\]`), [[new RegExp(String.raw`^\s+${fence}\]`), 4]])),
17
17
  close(some(text, /^\S/), str(`${fence}]`)), true,
18
18
  ([as, bs = [], cs], rest) => [[
19
19
  html('span', { class: 'remark' }, [
@@ -22,4 +22,4 @@ export const remark: RemarkParser = lazy(() => validate('[%', creation(1, Recurs
22
22
  ]),
23
23
  ], rest],
24
24
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
25
- ([, fence]) => fence.length, {}))))));
25
+ ([, fence]) => fence.length, {})))));
@@ -1,14 +1,15 @@
1
1
  import { RubyParser } from '../inline';
2
+ import { State, Recursion, Backtrack, Command, CmdRegExp } from '../context';
2
3
  import { eval, exec } from '../../combinator/data/parser';
3
4
  import { sequence, syntax, creation, validate, surround, lazy, fmap, bind } from '../../combinator';
4
5
  import { unsafehtmlentity } from './htmlentity';
5
6
  import { text as txt, str } from '../source';
6
- import { State, Recursion, Backtrack } from '../context';
7
7
  import { isStartTightNodes } from '../visibility';
8
8
  import { unshift, push } from 'spica/array';
9
9
  import { html, defrag } from 'typed-dom/dom';
10
10
 
11
- export const ruby: RubyParser = lazy(() => validate('[', creation(1, Recursion.ignore, syntax(1, State.all, fmap(
11
+ export const ruby: RubyParser = lazy(() => validate('[', creation(1, Recursion.ignore, fmap(
12
+ syntax(1, State.all,
12
13
  sequence([
13
14
  bind(surround('[', str(/^(?:\\[^\n]|[^\\[\](){}"\n])+/), ']', false, undefined, undefined, 3 | Backtrack.ruby), ([source], rest, context) => {
14
15
  const ns = eval(text({ source, context }), [undefined])[0];
@@ -19,7 +20,7 @@ export const ruby: RubyParser = lazy(() => validate('[', creation(1, Recursion.i
19
20
  const ns = eval(text({ source, context }), [undefined])[0];
20
21
  return ns && [[ns], rest];
21
22
  }),
22
- ]),
23
+ ])),
23
24
  ([texts, rubies]) => {
24
25
  switch (true) {
25
26
  case rubies.length <= texts.length:
@@ -50,7 +51,7 @@ export const ruby: RubyParser = lazy(() => validate('[', creation(1, Recursion.i
50
51
  [html('rp', '('), html('rt', rubies.join(' ').trim()), html('rp', ')')]))),
51
52
  ];
52
53
  }
53
- })))));
54
+ }))));
54
55
 
55
56
  const text: RubyParser.TextParser = creation(1, Recursion.ignore, ({ source, context }) => {
56
57
  const acc = [''];
@@ -90,8 +91,8 @@ function attributes(texts: string[], rubies: string[]): Record<string, string> {
90
91
  let attrs: Record<string, string> | undefined;
91
92
  for (const ss of [texts, rubies]) {
92
93
  for (let i = 0; i < ss.length; ++i) {
93
- if (!ss[i].includes('\x1B')) continue;
94
- ss[i] = ss[i].replace(/\x1B/g, '');
94
+ if (!ss[i].includes(Command.Escape)) continue;
95
+ ss[i] = ss[i].replace(CmdRegExp.Escape, '');
95
96
  attrs ??= {
96
97
  class: 'invalid',
97
98
  'data-invalid-syntax': 'ruby',
@@ -1,9 +1,9 @@
1
1
  import { ShortMediaParser } from '../inline';
2
+ import { State } from '../context';
2
3
  import { union, constraint, focus, rewrite, open, convert } from '../../combinator';
3
4
  import { url } from './autolink/url';
4
5
  import { media } from './media';
5
6
  import { linebreak } from '../source';
6
- import { State } from '../context';
7
7
 
8
8
  export const shortmedia: ShortMediaParser = rewrite(
9
9
  constraint(State.media, false,
@@ -1,9 +1,9 @@
1
1
  import { StrongParser } from '../inline';
2
+ import { State, Recursion } from '../context';
2
3
  import { union, some, syntax, creation, surround, open, lazy } from '../../combinator';
3
4
  import { inline } from '../inline';
4
5
  import { emstrong } from './emstrong';
5
6
  import { str } from '../source';
6
- import { State, Recursion } from '../context';
7
7
  import { startTight, blankWith } from '../visibility';
8
8
  import { unshift } from 'spica/array';
9
9
  import { html, defrag } from 'typed-dom/dom';
@@ -1,7 +1,7 @@
1
1
  import { TemplateParser } from '../inline';
2
+ import { State, Recursion, Backtrack } from '../context';
2
3
  import { union, some, syntax, creation, precedence, surround, lazy } from '../../combinator';
3
4
  import { escsource, str } from '../source';
4
- import { State, Recursion, Backtrack } from '../context';
5
5
  import { unshift } from 'spica/array';
6
6
  import { html } from 'typed-dom/dom';
7
7
 
@@ -10,7 +10,7 @@ export const template: TemplateParser = lazy(() => creation(1, Recursion.ignore,
10
10
  syntax(1, State.all, some(union([bracket, escsource]), '}')),
11
11
  '}}',
12
12
  true,
13
- ([, ns = []], rest) => [[html('span', { class: 'template' }, `{{${ns.join('').replace(/\x1B/g, '')}}}`)], rest],
13
+ ([, ns = []], rest) => [[html('span', { class: 'template' }, `{{${ns.join('')}}}`)], rest],
14
14
  undefined, 3 | Backtrack.template)));
15
15
 
16
16
  const bracket: TemplateParser.BracketParser = lazy(() => creation(0, Recursion.terminal, union([
@@ -173,6 +173,7 @@ describe('Unit: parser/inline', () => {
173
173
  assert.deepStrictEqual(inspect(parser('"[% *"*"*')), [['"', '[%', ' ', '*', '"', '*', '"', '*'], '']);
174
174
  assert.deepStrictEqual(inspect(parser('"[% "*"* %]')), [['"', '<span class="remark"><input type="checkbox"><span>[% "*"* %]</span></span>'], '']);
175
175
  assert.deepStrictEqual(inspect(parser('"{{""}}')), [['"', '{', '{', '"', '"', '}', '}'], '']);
176
+ assert.deepStrictEqual(inspect(parser('[#http://a/(<bdi>)]</bdi>')), [['<a class="index" href="#index::http://a/(&lt;bdi&gt;)">http://a/(&lt;bdi&gt;)</a>', '<', '/', 'bdi', '>'], '']);
176
177
  });
177
178
 
178
179
  it('uri', () => {
@@ -1,4 +1,5 @@
1
1
  import { MarkdownParser } from '../../markdown';
2
+ import { Command } from './context';
2
3
  import { eval, exec } from '../combinator/data/parser';
3
4
  import { union, some } from '../combinator';
4
5
  import { segment as heading } from './block/heading';
@@ -22,7 +23,7 @@ const parser: SegmentParser = union([
22
23
  ]);
23
24
 
24
25
  export function* segment(source: string): Generator<string, undefined, undefined> {
25
- if (!validate(source, MAX_INPUT_SIZE)) return yield `\x07Too large input over ${MAX_INPUT_SIZE.toLocaleString('en')} bytes.\n${source.slice(0, 1001)}`;
26
+ if (!validate(source, MAX_INPUT_SIZE)) return yield `${Command.Error}Too large input over ${MAX_INPUT_SIZE.toLocaleString('en')} bytes.\n${source.slice(0, 1001)}`;
26
27
  assert(source.length < Number.MAX_SAFE_INTEGER);
27
28
  while (source !== '') {
28
29
  const result = parser({ source, context: {} })!;
@@ -35,7 +36,7 @@ export function* segment(source: string): Generator<string, undefined, undefined
35
36
  const seg = segs[i];
36
37
  validate(seg, MAX_SEGMENT_SIZE)
37
38
  ? yield seg
38
- : yield `\x07Too large segment over ${MAX_SEGMENT_SIZE.toLocaleString('en')} bytes.\n${seg}`
39
+ : yield `${Command.Error}Too large segment over ${MAX_SEGMENT_SIZE.toLocaleString('en')} bytes.\n${seg}`
39
40
  }
40
41
  source = rest;
41
42
  }
@@ -1,7 +1,7 @@
1
1
  import { EscapableSourceParser } from '../source';
2
+ import { Recursion, Command } from '../context';
2
3
  import { creation } from '../../combinator';
3
4
  import { nonWhitespace } from './text';
4
- import { Recursion } from '../context';
5
5
 
6
6
  const delimiter = /[\s\x00-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F]/;
7
7
 
@@ -17,7 +17,7 @@ export const escsource: EscapableSourceParser = creation(1, Recursion.ignore, ({
17
17
  assert(!source.includes('\r', 1));
18
18
  context.resources && ++context.resources.clock;
19
19
  return [[], source.slice(1)];
20
- case '\x1B':
20
+ case Command.Escape:
21
21
  return [[source.slice(1, 2)], source.slice(2)];
22
22
  case '\\':
23
23
  switch (source[1]) {
@@ -1,7 +1,7 @@
1
1
  import { StrParser } from '../source';
2
+ import { Recursion } from '../context';
2
3
  import { Parser, Context } from '../../combinator/data/parser';
3
4
  import { creation } from '../../combinator';
4
- import { Recursion } from '../context';
5
5
 
6
6
  export function str(pattern: string | RegExp, not?: string): StrParser;
7
7
  export function str(pattern: string | RegExp, not?: string): Parser<string, Context<StrParser>, []> {
@@ -1,7 +1,7 @@
1
1
  import { TextParser, TxtParser, LinebreakParser } from '../source';
2
+ import { Recursion, Command } from '../context';
2
3
  import { union, creation, focus } from '../../combinator';
3
4
  import { str } from './str';
4
- import { Recursion } from '../context';
5
5
  import { html } from 'typed-dom/dom';
6
6
 
7
7
  export const delimiter = /[\s\x00-\x7F()[]{}“”‘’「」『』]|\S[#>]/u;
@@ -21,12 +21,12 @@ export const text: TextParser = creation(1, Recursion.ignore, ({ source, context
21
21
  assert(!source.includes('\r', 1));
22
22
  context.resources && ++context.resources.clock;
23
23
  return [[], source.slice(1)];
24
- case '\x1B':
24
+ case Command.Escape:
25
25
  case '\\':
26
26
  switch (source[1]) {
27
27
  case undefined:
28
28
  case '\n':
29
- assert(source[0] !== '\x1B');
29
+ assert(source[0] !== Command.Escape);
30
30
  return [[], source.slice(1)];
31
31
  default:
32
32
  return [[source.slice(1, 2)], source.slice(2)];
@@ -1,10 +1,9 @@
1
1
  import { UnescapableSourceParser } from '../source';
2
+ import { Recursion, Command } from '../context';
2
3
  import { creation } from '../../combinator';
3
4
  import { delimiter, nonWhitespace, nonAlphanumeric, isAlphanumeric } from './text';
4
- import { Recursion } from '../context';
5
5
 
6
6
  export const unescsource: UnescapableSourceParser = creation(1, Recursion.ignore, ({ source, context }) => {
7
- assert(source[0] !== '\x1B');
8
7
  if (source === '') return;
9
8
  const i = source.search(delimiter);
10
9
  switch (i) {
@@ -16,6 +15,9 @@ export const unescsource: UnescapableSourceParser = creation(1, Recursion.ignore
16
15
  assert(!source.includes('\r', 1));
17
16
  context.resources && ++context.resources.clock;
18
17
  return [[], source.slice(1)];
18
+ case Command.Escape:
19
+ assert(source[0] !== Command.Escape);
20
+ return [[source.slice(1, 2)], source.slice(2)];
19
21
  }
20
22
  const b = source[0] !== '\n' && source[0].trimStart() === '';
21
23
  const i = b || isAlphanumeric(source[0])
@@ -1,4 +1,5 @@
1
1
  import { MarkdownParser } from '../../markdown';
2
+ import { Command } from './context';
2
3
  import { Parser, Input, eval } from '../combinator/data/parser';
3
4
  import { union, some, verify, convert, fmap } from '../combinator';
4
5
  import { unsafehtmlentity } from './inline/htmlentity';
@@ -21,7 +22,7 @@ export function visualize<P extends Parser<HTMLElement | string>>(parser: P): P;
21
22
  export function visualize<T extends HTMLElement | string>(parser: Parser<T>): Parser<T> {
22
23
  return union([
23
24
  convert(
24
- source => source.replace(blank.line, line => line.replace(/[\\&<]/g, '\x1B$&')),
25
+ source => source.replace(blank.line, line => line.replace(/[\\&<]/g, `${Command.Escape}$&`)),
25
26
  verify(parser, (ns, rest) => !rest && hasVisible(ns))),
26
27
  some(union([linebreak, unescsource])),
27
28
  ]);
@@ -64,7 +65,7 @@ export function blankWith(starting: '' | '\n', delimiter?: string | RegExp): Reg
64
65
  //}
65
66
  //const isStartLoose = reduce(({ source, context }: Input<MarkdownParser.Context>, except?: string): boolean => {
66
67
  // return isStartTight({ source: source.replace(blank.start, ''), context }, except);
67
- //}, ({ source }, except = '') => `${source}\x1E${except}`);
68
+ //}, ({ source }, except = '') => `${source}${Command.Separator}${except}`);
68
69
 
69
70
  export function startTight<P extends Parser<unknown>>(parser: P, except?: string): P;
70
71
  export function startTight<T>(parser: Parser<T>, except?: string): Parser<T> {
@@ -103,7 +104,7 @@ const isStartTight = reduce(({ source, context }: Input<MarkdownParser.Context>,
103
104
  default:
104
105
  return source[0].trimStart() !== '';
105
106
  }
106
- }, ({ source }, except = '') => `${source}\x1E${except}`);
107
+ }, ({ source }, except = '') => `${source}${Command.Separator}${except}`);
107
108
 
108
109
  export function isStartLooseNodes(nodes: readonly (HTMLElement | string)[]): boolean {
109
110
  if (nodes.length === 0) return true;
@@ -159,16 +160,16 @@ export function trimBlankStart<T>(parser: Parser<T>): Parser<T> {
159
160
  source => source.replace(blank.start, ''),
160
161
  parser);
161
162
  }
162
- function trimBlankEnd<P extends Parser<HTMLElement | string>>(parser: P): P;
163
- function trimBlankEnd<T extends HTMLElement | string>(parser: Parser<T>): Parser<T> {
163
+ export function trimBlankEnd<P extends Parser<HTMLElement | string>>(parser: P): P;
164
+ export function trimBlankEnd<T extends HTMLElement | string>(parser: Parser<T>): Parser<T> {
164
165
  return fmap(
165
166
  parser,
166
- trimNodeEnd);
167
+ trimBlankNodeEnd);
167
168
  }
168
- //export function trimNode<T extends HTMLElement | string>(nodes: T[]): T[] {
169
- // return trimNodeStart(trimNodeEnd(nodes));
169
+ //export function trimBlankNode<T extends HTMLElement | string>(nodes: T[]): T[] {
170
+ // return trimBlankNodeStart(trimBlankNodeEnd(nodes));
170
171
  //}
171
- //function trimNodeStart<T extends HTMLElement | string>(nodes: T[]): T[] {
172
+ //function trimBlankNodeStart<T extends HTMLElement | string>(nodes: T[]): T[] {
172
173
  // for (let node = nodes[0]; nodes.length > 0 && !isVisible(node = nodes[0], 0);) {
173
174
  // if (typeof node === 'string') {
174
175
  // const pos = node.trimStart().length;
@@ -184,7 +185,7 @@ function trimBlankEnd<T extends HTMLElement | string>(parser: Parser<T>): Parser
184
185
  // }
185
186
  // return nodes;
186
187
  //}
187
- export function trimNodeEnd<T extends HTMLElement | string>(nodes: T[]): T[] {
188
+ export function trimBlankNodeEnd<T extends HTMLElement | string>(nodes: T[]): T[] {
188
189
  const skip = nodes.length > 0 &&
189
190
  typeof nodes.at(-1) === 'object' &&
190
191
  nodes.at(-1)!['className'] === 'indexer'
@@ -192,9 +193,9 @@ export function trimNodeEnd<T extends HTMLElement | string>(nodes: T[]): T[] {
192
193
  : [];
193
194
  for (let node = nodes[0]; nodes.length > 0 && !isVisible(node = nodes.at(-1)!, -1);) {
194
195
  if (typeof node === 'string') {
195
- const pos = node.trimEnd().length;
196
- if (pos > 0) {
197
- nodes[nodes.length - 1] = node.slice(0, pos) as T;
196
+ const len = node.trimEnd().length;
197
+ if (len > 0) {
198
+ nodes[nodes.length - 1] = node.slice(0, len) as T;
198
199
  break;
199
200
  }
200
201
  }