securemark 0.270.1 → 0.271.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.271.0
4
+
5
+ - Extend table highlight syntax.
6
+
7
+ ## 0.270.2
8
+
9
+ - Refactoring.
10
+
3
11
  ## 0.270.1
4
12
 
5
13
  - Refactoring.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! securemark v0.270.1 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED License */
1
+ /*! securemark v0.271.0 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED License */
2
2
  (function webpackUniversalModuleDefinition(root, factory) {
3
3
  if(typeof exports === 'object' && typeof module === 'object')
4
4
  module.exports = factory(require("Prism"), require("DOMPurify"));
@@ -4465,8 +4465,8 @@ const visibility_1 = __webpack_require__(7618);
4465
4465
  const array_1 = __webpack_require__(8112);
4466
4466
  const dom_1 = __webpack_require__(3252);
4467
4467
  exports.dlist = (0, combinator_1.lazy)(() => (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.validate)(/^~[^\S\n]+(?=\S)/, (0, combinator_1.some)((0, combinator_1.inits)([(0, combinator_1.state)(256 /* State.annotation */ | 128 /* State.reference */ | 64 /* State.index */ | 32 /* State.label */ | 16 /* State.link */ | 8 /* State.media */, (0, combinator_1.some)(term)), (0, combinator_1.some)(desc)]))), es => [(0, dom_1.html)('dl', fillTrailingDescription(es))])));
4468
- const term = (0, combinator_1.creation)(1, false, (0, combinator_1.line)((0, inline_1.indexee)((0, combinator_1.fmap)((0, combinator_1.open)(/^~[^\S\n]+(?=\S)/, (0, visibility_1.visualize)((0, visibility_1.trimBlank)((0, combinator_1.some)((0, combinator_1.union)([inline_1.indexer, inline_1.inline])))), true), ns => [(0, dom_1.html)('dt', (0, dom_1.defrag)(ns))]))));
4469
- const desc = (0, combinator_1.creation)(1, false, (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.open)(/^:[^\S\n]+(?=\S)|/, (0, combinator_1.rewrite)((0, combinator_1.some)(source_1.anyline, /^[~:][^\S\n]+\S/), (0, visibility_1.visualize)((0, combinator_1.trimEnd)((0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]))))), true), ns => [(0, dom_1.html)('dd', (0, dom_1.defrag)(ns))]), false));
4468
+ const term = (0, combinator_1.creation)(1, false, (0, combinator_1.line)((0, inline_1.indexee)((0, combinator_1.fmap)((0, combinator_1.open)(/^~[^\S\n]+(?=\S)/, (0, visibility_1.visualize)((0, visibility_1.trimBlankStart)((0, combinator_1.some)((0, combinator_1.union)([inline_1.indexer, inline_1.inline])))), true), ns => [(0, dom_1.html)('dt', (0, visibility_1.trimNodeEnd)((0, dom_1.defrag)(ns)))]))));
4469
+ const desc = (0, combinator_1.creation)(1, false, (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.open)(/^:[^\S\n]+(?=\S)|/, (0, combinator_1.rewrite)((0, combinator_1.some)(source_1.anyline, /^[~:][^\S\n]+\S/), (0, visibility_1.visualize)((0, combinator_1.some)((0, combinator_1.union)([inline_1.inline])))), true), ns => [(0, dom_1.html)('dd', (0, visibility_1.trimNodeEnd)((0, dom_1.defrag)(ns)))]), false));
4470
4470
  function fillTrailingDescription(es) {
4471
4471
  return es.length > 0 && es[es.length - 1].tagName === 'DT' ? (0, array_1.push)(es, [(0, dom_1.html)('dd')]) : es;
4472
4472
  }
@@ -4701,11 +4701,11 @@ const dom_1 = __webpack_require__(3252);
4701
4701
  exports.segment = (0, combinator_1.block)((0, combinator_1.match)(/^(~{3,})(?:figure[^\S\n])?(?=\[?\$)/, (0, memoize_1.memoize)(([, fence], closer = new RegExp(String.raw`^${fence}[^\S\n]*(?:$|\n)`)) => (0, combinator_1.close)((0, combinator_1.sequence)([source_1.contentline, (0, combinator_1.inits)([
4702
4702
  // All parsers which can include closing terms.
4703
4703
  (0, combinator_1.union)([codeblock_1.segment_, mathblock_1.segment_, table_2.segment_, blockquote_1.segment, placeholder_1.segment_, (0, combinator_1.some)(source_1.contentline, closer)]), source_1.emptyline, (0, combinator_1.union)([source_1.emptyline, (0, combinator_1.some)(source_1.contentline, closer)])])]), closer), ([, fence]) => fence.length, [])));
4704
- exports.figure = (0, combinator_1.block)((0, combinator_1.fallback)((0, combinator_1.rewrite)(exports.segment, (0, combinator_1.fmap)((0, combinator_1.convert)(source => source.slice(source.match(/^~+(?:\w+\s+)?/)[0].length, source.trimEnd().lastIndexOf('\n')), (0, combinator_1.sequence)([(0, combinator_1.line)((0, combinator_1.sequence)([label_1.label, (0, source_1.str)(/^(?=\s).*\n/)])), (0, combinator_1.inits)([(0, combinator_1.block)((0, combinator_1.union)([ulist_1.ulist, olist_1.olist, table_1.table, codeblock_1.codeblock, mathblock_1.mathblock, example_1.example, table_2.table, blockquote_1.blockquote, placeholder_1.placeholder, (0, combinator_1.line)(inline_1.media), (0, combinator_1.line)(inline_1.shortmedia)])), source_1.emptyline, (0, combinator_1.block)((0, combinator_1.state)(8 /* State.media */, (0, visibility_1.visualize)((0, visibility_1.trimBlank)((0, combinator_1.trimEnd)((0, combinator_1.some)(inline_1.inline))))))])])), ([label, param, content, ...caption]) => [(0, dom_1.html)('figure', attributes(label.getAttribute('data-label'), param, content, caption), [(0, dom_1.html)('figcaption', [(0, dom_1.html)('span', {
4704
+ exports.figure = (0, combinator_1.block)((0, combinator_1.fallback)((0, combinator_1.rewrite)(exports.segment, (0, combinator_1.fmap)((0, combinator_1.convert)(source => source.slice(source.match(/^~+(?:\w+\s+)?/)[0].length, source.trimEnd().lastIndexOf('\n')), (0, combinator_1.sequence)([(0, combinator_1.line)((0, combinator_1.sequence)([label_1.label, (0, source_1.str)(/^(?=\s).*\n/)])), (0, combinator_1.inits)([(0, combinator_1.block)((0, combinator_1.union)([ulist_1.ulist, olist_1.olist, table_1.table, codeblock_1.codeblock, mathblock_1.mathblock, example_1.example, table_2.table, blockquote_1.blockquote, placeholder_1.placeholder, (0, combinator_1.line)(inline_1.media), (0, combinator_1.line)(inline_1.shortmedia)])), source_1.emptyline, (0, combinator_1.block)((0, combinator_1.state)(8 /* State.media */, (0, visibility_1.visualize)((0, visibility_1.trimBlankStart)((0, combinator_1.some)(inline_1.inline)))))])])), ([label, param, content, ...caption]) => [(0, dom_1.html)('figure', attributes(label.getAttribute('data-label'), param, content, caption), [(0, dom_1.html)('figcaption', [(0, dom_1.html)('span', {
4705
4705
  class: 'figindex'
4706
4706
  }), (0, dom_1.html)('span', {
4707
4707
  class: 'figtext'
4708
- }, (0, dom_1.defrag)(caption))]), (0, dom_1.html)('div', [content])])])), (0, combinator_1.fmap)((0, combinator_1.fence)(/^(~{3,})(?:figure|\[?\$\S*)(?!\S)[^\n]*(?:$|\n)/, 300), ([body, overflow, closer, opener, delim], _, context) => [(0, dom_1.html)('pre', {
4708
+ }, (0, visibility_1.trimNodeEnd)((0, dom_1.defrag)(caption)))]), (0, dom_1.html)('div', [content])])])), (0, combinator_1.fmap)((0, combinator_1.fence)(/^(~{3,})(?:figure|\[?\$\S*)(?!\S)[^\n]*(?:$|\n)/, 300), ([body, overflow, closer, opener, delim], _, context) => [(0, dom_1.html)('pre', {
4709
4709
  class: 'invalid',
4710
4710
  translate: 'no',
4711
4711
  'data-invalid-syntax': 'figure',
@@ -4949,28 +4949,36 @@ const parser = (0, combinator_1.lazy)(() => (0, combinator_1.block)((0, combinat
4949
4949
  const row = (0, combinator_1.lazy)(() => (0, combinator_1.dup)((0, combinator_1.fmap)((0, combinator_1.subsequence)([(0, combinator_1.dup)((0, combinator_1.union)([align])), (0, combinator_1.some)((0, combinator_1.union)([head, data, (0, combinator_1.some)(dataline, alignment), source_1.emptyline]))]), ns => !(0, alias_1.isArray)(ns[0]) ? (0, array_1.unshift)([[[]]], ns) : ns)));
4950
4950
  const alignment = /^[-=<>]+(?:\/[-=^v]*)?(?=[^\S\n]*\n)/;
4951
4951
  const align = (0, combinator_1.line)((0, combinator_1.fmap)((0, combinator_1.union)([(0, source_1.str)(alignment)]), ([s]) => s.split('/').map(s => s.split(''))));
4952
- const delimiter = /^[-=<>]+(?:\/[-=^v]*)?(?=[^\S\n]*\n)|^[#:](?:(?!:\D|0)\d*:(?!0)\d*)?!*(?=\s)/;
4953
- const head = (0, combinator_1.creation)(1, false, (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.open)((0, source_1.str)(/^#(?:(?!:\D|0)\d*:(?!0)\d*)?!*(?=\s)/), (0, combinator_1.rewrite)((0, combinator_1.inits)([source_1.anyline, (0, combinator_1.some)(source_1.contentline, delimiter)]), (0, combinator_1.trim)((0, visibility_1.visualize)((0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]))))), true), ns => [(0, dom_1.html)('th', attributes(ns.shift()), (0, dom_1.defrag)(ns))]), false));
4954
- const data = (0, combinator_1.creation)(1, false, (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.open)((0, source_1.str)(/^:(?:(?!:\D|0)\d*:(?!0)\d*)?!*(?=\s)/), (0, combinator_1.rewrite)((0, combinator_1.inits)([source_1.anyline, (0, combinator_1.some)(source_1.contentline, delimiter)]), (0, combinator_1.trim)((0, visibility_1.visualize)((0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]))))), true), ns => [(0, dom_1.html)('td', attributes(ns.shift()), (0, dom_1.defrag)(ns))]), false));
4952
+ const delimiter = /^[-=<>]+(?:\/[-=^v]*)?(?=[^\S\n]*\n)|^[#:](?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(?=\s)/;
4953
+ const head = (0, combinator_1.creation)(1, false, (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.open)((0, source_1.str)(/^#(?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(?=\s)/), (0, combinator_1.rewrite)((0, combinator_1.inits)([source_1.anyline, (0, combinator_1.some)(source_1.contentline, delimiter)]), (0, combinator_1.trim)((0, visibility_1.visualize)((0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]))))), true), ns => [(0, dom_1.html)('th', attributes(ns.shift()), (0, dom_1.defrag)(ns))]), false));
4954
+ const data = (0, combinator_1.creation)(1, false, (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.open)((0, source_1.str)(/^:(?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(?=\s)/), (0, combinator_1.rewrite)((0, combinator_1.inits)([source_1.anyline, (0, combinator_1.some)(source_1.contentline, delimiter)]), (0, combinator_1.trim)((0, visibility_1.visualize)((0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]))))), true), ns => [(0, dom_1.html)('td', attributes(ns.shift()), (0, dom_1.defrag)(ns))]), false));
4955
4955
  const dataline = (0, combinator_1.creation)(1, false, (0, combinator_1.line)((0, combinator_1.rewrite)(source_1.contentline, (0, combinator_1.union)([(0, combinator_1.validate)(/^!+\s/, (0, combinator_1.convert)(source => `:${source}`, data)), (0, combinator_1.convert)(source => `: ${source}`, data)]))));
4956
4956
  function attributes(source) {
4957
- let [, rowspan = undefined, colspan = undefined, highlight = undefined] = source.match(/^.(?:(\d+)?:(\d+)?)?(!+)?$/) ?? [];
4957
+ let [, rowspan = undefined, colspan = undefined, highlight = undefined, extension = undefined] = source.match(/^[#:](?:(\d+)?:(\d+)?)?(?:(!+)([+]?))?$/) ?? [];
4958
4958
  rowspan === '1' ? rowspan = undefined : undefined;
4959
4959
  colspan === '1' ? colspan = undefined : undefined;
4960
4960
  rowspan &&= `${(0, alias_1.max)(0, (0, alias_1.min)(+rowspan, 65534))}`;
4961
4961
  colspan &&= `${(0, alias_1.max)(0, (0, alias_1.min)(+colspan, 1000))}`;
4962
- highlight &&= highlight.length > 0 ? `${highlight.length}` : undefined;
4963
- const valid = !highlight || source[0] === '#' && +highlight <= 1 || source[0] === ':' && +highlight <= 6;
4962
+ extension ||= undefined;
4963
+ const level = highlight?.length ?? 0;
4964
+ const validH = !highlight || source[0] === '#' && level <= 6 || source[0] === ':' && level <= 6;
4965
+ const validE = source[0] === '#' || extension !== '+';
4966
+ const valid = validH && validE;
4964
4967
  return {
4965
4968
  class: valid ? highlight && 'highlight' : 'invalid',
4966
4969
  rowspan,
4967
4970
  colspan,
4968
- ...(valid ? {
4969
- 'data-highlight-level': +highlight > 1 ? highlight : undefined
4970
- } : {
4971
+ ...(!validH && {
4971
4972
  'data-invalid-syntax': 'table',
4972
4973
  'data-invalid-type': 'syntax',
4973
4974
  'data-invalid-message': 'Too much highlight level'
4975
+ } || !validE && {
4976
+ 'data-invalid-syntax': 'table',
4977
+ 'data-invalid-type': 'syntax',
4978
+ 'data-invalid-message': 'Extensible cells are only head cells'
4979
+ } || {
4980
+ 'data-highlight-level': level > 1 ? `${level}` : undefined,
4981
+ 'data-highlight-extension': extension
4974
4982
  })
4975
4983
  };
4976
4984
  }
@@ -4982,7 +4990,8 @@ function format(rows) {
4982
4990
  const valigns = [];
4983
4991
  let target = thead;
4984
4992
  let ranges = {};
4985
- let verticalHighlights = 0n;
4993
+ let verticalHighlightExtensions = 0n;
4994
+ let verticalHighlightLevels = [];
4986
4995
  ROW: for (let i = 0; i < rows.length; ++i) {
4987
4996
  // Copy to make them retryable.
4988
4997
  const [[[...as], [...vs] = []], ...cells] = rows[i];
@@ -5040,22 +5049,26 @@ function format(rows) {
5040
5049
  const row = (0, dom_1.html)('tr');
5041
5050
  let heads = 0n;
5042
5051
  let highlights = 0n;
5052
+ let highlightExtensions = 0n;
5053
+ let highlightLevels = [];
5043
5054
  let hasDataCell = false;
5044
- let lHeadCellIdx;
5045
- let rHeadCellIdx;
5055
+ let lHeadCellIndex;
5056
+ let rHeadCellIndex;
5046
5057
  for (let j = 0; j < cells.length; ++j) {
5047
5058
  const jn = BigInt(j);
5048
5059
  const isVirtual = !!ranges[i]?.[j];
5049
5060
  const cell = isVirtual ? (0, array_1.splice)(cells, j, 0, undefined) && ranges[i][j] : cells[j];
5050
5061
  const isHeadCell = cell.tagName === 'TH';
5051
- heads |= BigInt(isHeadCell) << jn;
5052
- highlights |= BigInt(cell.className === 'highlight') << jn;
5062
+ heads |= isHeadCell ? 1n << jn : 0n;
5063
+ highlights |= cell.className === 'highlight' ? 1n << jn : 0n;
5064
+ highlightExtensions |= cell.getAttribute('data-highlight-extension') ? 1n << jn : 0n;
5065
+ highlightLevels[j] = cell.getAttribute('data-highlight-level') ?? '1';
5053
5066
  hasDataCell ||= !isHeadCell;
5054
5067
  if (isHeadCell && !hasDataCell) {
5055
- lHeadCellIdx = jn;
5068
+ lHeadCellIndex = jn;
5056
5069
  }
5057
5070
  if (isHeadCell && hasDataCell) {
5058
- rHeadCellIdx ??= jn;
5071
+ rHeadCellIndex ??= jn;
5059
5072
  }
5060
5073
  const rowSpan = cell.rowSpan;
5061
5074
  if (rowSpan > 1 && !isVirtual) {
@@ -5070,6 +5083,8 @@ function format(rows) {
5070
5083
  (0, array_1.splice)(cells, j + 1, 0, ...Array(colSpan - 1));
5071
5084
  heads |= heads & 1n << jn && ~(~0n << BigInt(colSpan)) << jn;
5072
5085
  highlights |= highlights & 1n << jn && ~(~0n << BigInt(colSpan)) << jn;
5086
+ highlightExtensions |= highlightExtensions & 1n << jn && ~(~0n << BigInt(colSpan)) << jn;
5087
+ (0, array_1.splice)(highlightLevels, j + 1, 0, ...Array(colSpan - 1));
5073
5088
  j += colSpan - 1;
5074
5089
  }
5075
5090
  if (target === thead) {
@@ -5104,21 +5119,36 @@ function format(rows) {
5104
5119
  target.appendChild(row);
5105
5120
  switch (target) {
5106
5121
  case thead:
5107
- verticalHighlights = heads & highlights;
5122
+ verticalHighlightExtensions = highlightExtensions;
5123
+ verticalHighlightLevels = highlightLevels;
5108
5124
  continue;
5109
5125
  case tbody:
5110
- lHeadCellIdx ??= -1n;
5111
- rHeadCellIdx ??= -1n;
5112
- const tHighlights = verticalHighlights;
5113
- const horizontalHighlights = heads & highlights;
5114
- const lHighlight = ~lHeadCellIdx && horizontalHighlights & 1n << lHeadCellIdx;
5115
- const rHighlight = ~rHeadCellIdx && horizontalHighlights & 1n << rHeadCellIdx;
5126
+ lHeadCellIndex ??= -1n;
5127
+ rHeadCellIndex ??= -1n;
5128
+ const tHighlights = verticalHighlightExtensions;
5129
+ const horizontalHighlights = highlightExtensions;
5130
+ const horizontalHighlightLevels = highlightLevels;
5131
+ const lHighlight = ~lHeadCellIndex && horizontalHighlights & 1n << lHeadCellIndex;
5132
+ const rHighlight = ~rHeadCellIndex && horizontalHighlights & 1n << rHeadCellIndex;
5116
5133
  for (let i = 0, m = 1n; i < cells.length; ++i, m <<= 1n) {
5117
5134
  const cell = cells[i];
5118
5135
  if (!cell) continue;
5119
5136
  if (heads & m) continue;
5120
- if (!(lHighlight || rHighlight || tHighlights & m || highlights & m)) continue;
5121
- cell.classList.add('highlight');
5137
+ switch (m) {
5138
+ case highlights & m:
5139
+ (lHighlight || rHighlight) && cell.setAttribute('data-highlight-level', horizontalHighlightLevels[i]);
5140
+ break;
5141
+ case lHighlight && m:
5142
+ case rHighlight && m:
5143
+ cell.classList.add('highlight');
5144
+ break;
5145
+ case tHighlights & m:
5146
+ cell.classList.add('highlight');
5147
+ +verticalHighlightLevels[i] > 1 && cell.setAttribute('data-highlight-level', verticalHighlightLevels[i]);
5148
+ break;
5149
+ default:
5150
+ continue;
5151
+ }
5122
5152
  }
5123
5153
  continue;
5124
5154
  case tfoot:
@@ -5148,12 +5178,12 @@ const dom_1 = __webpack_require__(3252);
5148
5178
  exports.segment = (0, combinator_1.block)((0, combinator_1.validate)('#', (0, combinator_1.focus)(/^#+[^\S\n]+\S[^\n]*(?:\n#+(?!\S)[^\n]*)*(?:$|\n)/, (0, combinator_1.some)((0, combinator_1.line)(({
5149
5179
  source
5150
5180
  }) => [[source], ''])))));
5151
- exports.heading = (0, combinator_1.block)((0, combinator_1.rewrite)(exports.segment, (0, combinator_1.state)(256 /* State.annotation */ | 128 /* State.reference */ | 64 /* State.index */ | 32 /* State.label */ | 16 /* State.link */ | 8 /* State.media */, (0, combinator_1.line)((0, inline_1.indexee)((0, combinator_1.fmap)((0, combinator_1.union)([(0, combinator_1.open)((0, source_1.str)(/^##+/), (0, visibility_1.visualize)((0, visibility_1.trimBlank)((0, combinator_1.some)((0, combinator_1.union)([inline_1.indexer, inline_1.inline])))), true), (0, combinator_1.open)((0, source_1.str)('#'), (0, combinator_1.state)(2 /* State.autolink */, (0, visibility_1.visualize)((0, visibility_1.trimBlank)((0, combinator_1.some)((0, combinator_1.union)([inline_1.indexer, inline_1.inline]))))), true)]), ([h, ...ns]) => [h.length <= 6 ? (0, dom_1.html)(`h${h.length}`, (0, dom_1.defrag)(ns)) : (0, dom_1.html)(`h6`, {
5181
+ exports.heading = (0, combinator_1.block)((0, combinator_1.rewrite)(exports.segment, (0, combinator_1.state)(256 /* State.annotation */ | 128 /* State.reference */ | 64 /* State.index */ | 32 /* State.label */ | 16 /* State.link */ | 8 /* State.media */, (0, combinator_1.line)((0, inline_1.indexee)((0, combinator_1.fmap)((0, combinator_1.union)([(0, combinator_1.open)((0, source_1.str)(/^##+/), (0, visibility_1.visualize)((0, visibility_1.trimBlankStart)((0, combinator_1.some)((0, combinator_1.union)([inline_1.indexer, inline_1.inline])))), true), (0, combinator_1.open)((0, source_1.str)('#'), (0, combinator_1.state)(2 /* State.autolink */, (0, visibility_1.visualize)((0, visibility_1.trimBlankStart)((0, combinator_1.some)((0, combinator_1.union)([inline_1.indexer, inline_1.inline]))))), true)]), ([h, ...ns]) => [h.length <= 6 ? (0, dom_1.html)(`h${h.length}`, (0, visibility_1.trimNodeEnd)((0, dom_1.defrag)(ns))) : (0, dom_1.html)(`h6`, {
5152
5182
  class: 'invalid',
5153
5183
  'data-invalid-syntax': 'heading',
5154
5184
  'data-invalid-type': 'syntax',
5155
5185
  'data-invalid-message': 'Heading level must be up to 6'
5156
- }, (0, dom_1.defrag)(ns))]))))));
5186
+ }, (0, visibility_1.trimNodeEnd)((0, dom_1.defrag)(ns)))]))))));
5157
5187
 
5158
5188
  /***/ }),
5159
5189
 
@@ -5384,7 +5414,7 @@ const combinator_1 = __webpack_require__(2087);
5384
5414
  const inline_1 = __webpack_require__(1160);
5385
5415
  const visibility_1 = __webpack_require__(7618);
5386
5416
  const dom_1 = __webpack_require__(3252);
5387
- exports.paragraph = (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.convert)(source => `\r${source}`, (0, visibility_1.visualize)((0, combinator_1.trimEnd)((0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]))))), ns => [(0, dom_1.html)('p', (0, dom_1.defrag)(ns))]));
5417
+ exports.paragraph = (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.convert)(source => `\r${source}`, (0, visibility_1.visualize)((0, combinator_1.some)((0, combinator_1.union)([inline_1.inline])))), ns => [(0, dom_1.html)('p', (0, visibility_1.trimNodeEnd)((0, dom_1.defrag)(ns)))]));
5388
5418
 
5389
5419
  /***/ }),
5390
5420
 
@@ -5412,7 +5442,7 @@ const dom_1 = __webpack_require__(3252);
5412
5442
  対象をURLで指定すべき(引用ツリーにルートを追加する)場合はない
5413
5443
  対象と引用は1:N(分割)、N:1(統合)のみ可能、N:N(混合)は不可能
5414
5444
  */
5415
- exports.reply = (0, combinator_1.block)((0, combinator_1.validate)('>', (0, combinator_1.fmap)((0, combinator_1.inits)([(0, combinator_1.some)((0, combinator_1.inits)([cite_1.cite, quote_1.quote])), (0, combinator_1.some)((0, combinator_1.subsequence)([(0, combinator_1.some)(quote_1.quote), (0, combinator_1.fmap)((0, combinator_1.rewrite)((0, combinator_1.some)(source_1.anyline, quote_1.syntax), (0, visibility_1.visualize)((0, combinator_1.trimEnd)((0, combinator_1.some)(inline_1.inline)))), ns => (0, array_1.push)(ns, [(0, dom_1.html)('br')]))]))]), ns => [(0, dom_1.html)('p', (0, dom_1.defrag)((0, array_1.pop)(ns)[0]))])));
5445
+ exports.reply = (0, combinator_1.block)((0, combinator_1.validate)('>', (0, combinator_1.fmap)((0, combinator_1.inits)([(0, combinator_1.some)((0, combinator_1.inits)([cite_1.cite, quote_1.quote])), (0, combinator_1.some)((0, combinator_1.subsequence)([(0, combinator_1.some)(quote_1.quote), (0, combinator_1.fmap)((0, combinator_1.rewrite)((0, combinator_1.some)(source_1.anyline, quote_1.syntax), (0, visibility_1.visualize)((0, combinator_1.some)(inline_1.inline))), ns => (0, array_1.push)(ns, [(0, dom_1.html)('br')]))]))]), ns => [(0, dom_1.html)('p', (0, visibility_1.trimNodeEnd)((0, dom_1.defrag)(ns)))])));
5416
5446
 
5417
5447
  /***/ }),
5418
5448
 
@@ -7588,7 +7618,7 @@ exports.stringify = stringify;
7588
7618
  Object.defineProperty(exports, "__esModule", ({
7589
7619
  value: true
7590
7620
  }));
7591
- exports.trimNodeEnd = exports.trimNode = exports.trimBlank = exports.isStartTightNodes = exports.isStartLooseNodes = exports.startTight = exports.startLoose = exports.blankWith = exports.regBlankStart = exports.visualize = void 0;
7621
+ exports.trimNodeEnd = exports.trimNode = exports.trimBlankStart = exports.trimBlank = exports.isStartTightNodes = exports.isStartLooseNodes = exports.startTight = exports.startLoose = exports.blankWith = exports.regBlankStart = exports.visualize = void 0;
7592
7622
  const parser_1 = __webpack_require__(6728);
7593
7623
  const combinator_1 = __webpack_require__(2087);
7594
7624
  const htmlentity_1 = __webpack_require__(1562);
@@ -7724,6 +7754,7 @@ exports.trimBlank = trimBlank;
7724
7754
  function trimBlankStart(parser) {
7725
7755
  return (0, combinator_1.convert)((0, memoize_1.reduce)(source => source.replace(exports.regBlankStart, '')), parser);
7726
7756
  }
7757
+ exports.trimBlankStart = trimBlankStart;
7727
7758
  function trimBlankEnd(parser) {
7728
7759
  return (0, combinator_1.fmap)(parser, trimNodeEnd);
7729
7760
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.270.1",
3
+ "version": "0.271.0",
4
4
  "description": "Secure markdown renderer working on browsers for user input data.",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/falsandtru/securemark",
@@ -1,9 +1,9 @@
1
1
  import { DListParser } from '../block';
2
- import { union, inits, some, creation, state, block, line, validate, rewrite, open, trimEnd, lazy, fmap } from '../../combinator';
2
+ import { union, inits, some, creation, state, block, line, validate, rewrite, open, lazy, fmap } from '../../combinator';
3
3
  import { inline, indexee, indexer } from '../inline';
4
4
  import { anyline } from '../source';
5
5
  import { State } from '../context';
6
- import { visualize, trimBlank } from '../visibility';
6
+ import { visualize, trimBlankStart, trimNodeEnd } from '../visibility';
7
7
  import { push } from 'spica/array';
8
8
  import { html, defrag } from 'typed-dom/dom';
9
9
 
@@ -18,17 +18,17 @@ export const dlist: DListParser = lazy(() => block(fmap(validate(
18
18
 
19
19
  const term: DListParser.TermParser = creation(1, false, line(indexee(fmap(open(
20
20
  /^~[^\S\n]+(?=\S)/,
21
- visualize(trimBlank(some(union([indexer, inline])))),
21
+ visualize(trimBlankStart(some(union([indexer, inline])))),
22
22
  true),
23
- ns => [html('dt', defrag(ns))]))));
23
+ ns => [html('dt', trimNodeEnd(defrag(ns)))]))));
24
24
 
25
25
  const desc: DListParser.DescriptionParser = creation(1, false, block(fmap(open(
26
26
  /^:[^\S\n]+(?=\S)|/,
27
27
  rewrite(
28
28
  some(anyline, /^[~:][^\S\n]+\S/),
29
- visualize(trimEnd(some(union([inline]))))),
29
+ visualize(some(union([inline])))),
30
30
  true),
31
- ns => [html('dd', defrag(ns))]),
31
+ ns => [html('dd', trimNodeEnd(defrag(ns)))]),
32
32
  false));
33
33
 
34
34
  function fillTrailingDescription(es: HTMLElement[]): HTMLElement[] {
@@ -1,5 +1,5 @@
1
1
  import { ExtensionParser } from '../../block';
2
- import { union, inits, sequence, some, state, block, line, fence, rewrite, close, match, convert, trimEnd, fallback, fmap } from '../../../combinator';
2
+ import { union, inits, sequence, some, state, block, line, fence, rewrite, close, match, convert, fallback, fmap } from '../../../combinator';
3
3
  import { str, contentline, emptyline } from '../../source';
4
4
  import { label, segment as seg_label } from '../../inline/extension/label';
5
5
  import { ulist } from '../ulist';
@@ -13,7 +13,7 @@ import { blockquote, segment as seg_blockquote } from '../blockquote';
13
13
  import { placeholder, segment_ as seg_placeholder } from './placeholder';
14
14
  import { inline, media, shortmedia } from '../../inline';
15
15
  import { State } from '../../context';
16
- import { visualize, trimBlank } from '../../visibility';
16
+ import { visualize, trimBlankStart, trimNodeEnd } from '../../visibility';
17
17
  import { memoize } from 'spica/memoize';
18
18
  import { html, defrag } from 'typed-dom/dom';
19
19
 
@@ -66,7 +66,7 @@ export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
66
66
  emptyline,
67
67
  block(
68
68
  state(State.media,
69
- visualize(trimBlank(trimEnd(some(inline)))))),
69
+ visualize(trimBlankStart(some(inline))))),
70
70
  ]),
71
71
  ])),
72
72
  ([label, param, content, ...caption]: [HTMLAnchorElement, string, ...HTMLElement[]]) => [
@@ -75,7 +75,7 @@ export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
75
75
  [
76
76
  html('figcaption', [
77
77
  html('span', { class: 'figindex' }),
78
- html('span', { class: 'figtext' }, defrag(caption)),
78
+ html('span', { class: 'figtext' }, trimNodeEnd(defrag(caption))),
79
79
  ]),
80
80
  html('div', [content]),
81
81
  ])
@@ -296,7 +296,7 @@ describe('Unit: parser/block/extension/table', () => {
296
296
  html('tbody', [
297
297
  html('tr', [
298
298
  html('th', { class: 'highlight' }, '1.1'),
299
- html('td', { class: 'highlight', highlight: 'h' }, '1.2'),
299
+ html('td', '1.2'),
300
300
  ]),
301
301
  ]),
302
302
  html('tfoot'),
@@ -307,7 +307,7 @@ describe('Unit: parser/block/extension/table', () => {
307
307
  html('thead'),
308
308
  html('tbody', [
309
309
  html('tr', [
310
- html('td', { class: 'highlight', highlight: 'h' }, '1.1'),
310
+ html('td', '1.1'),
311
311
  html('th', { class: 'highlight' }, '1.2'),
312
312
  ]),
313
313
  ]),
@@ -319,18 +319,40 @@ describe('Unit: parser/block/extension/table', () => {
319
319
  html('thead', [
320
320
  html('tr', [html('th', { class: 'highlight' }, '1.1')]),
321
321
  ]),
322
+ html('tbody', [
323
+ html('tr', [html('td', '2.1')]),
324
+ ]),
325
+ html('tfoot'),
326
+ ]).outerHTML], '']);
327
+ assert.deepStrictEqual(
328
+ inspect(parser('~~~table\n#! 1.1\n-\n:!+ 2.1\n~~~')),
329
+ [[html('table', [
330
+ html('thead', [
331
+ html('tr', [html('th', { class: 'highlight' }, '1.1')]),
332
+ ]),
333
+ html('tbody', [
334
+ html('tr', [html('td', { class: 'invalid' }, '2.1')]),
335
+ ]),
336
+ html('tfoot'),
337
+ ]).outerHTML], '']);
338
+ assert.deepStrictEqual(
339
+ inspect(parser('~~~table\n#!+ 1.1\n-\n: 2.1\n~~~')),
340
+ [[html('table', [
341
+ html('thead', [
342
+ html('tr', [html('th', { class: 'highlight', 'data-highlight-extension': '+' }, '1.1')]),
343
+ ]),
322
344
  html('tbody', [
323
345
  html('tr', [html('td', { class: 'highlight', highlight: 'v' }, '2.1')]),
324
346
  ]),
325
347
  html('tfoot'),
326
348
  ]).outerHTML], '']);
327
349
  assert.deepStrictEqual(
328
- inspect(parser('~~~table\n#! 1.1\n# 1.2\n: 1.3\n~~~')),
350
+ inspect(parser('~~~table\n#!+ 1.1\n# 1.2\n: 1.3\n~~~')),
329
351
  [[html('table', [
330
352
  html('thead'),
331
353
  html('tbody', [
332
354
  html('tr', [
333
- html('th', { class: 'highlight' }, '1.1'),
355
+ html('th', { class: 'highlight', 'data-highlight-extension': '+' }, '1.1'),
334
356
  html('th', '1.2'),
335
357
  html('td', '1.3'),
336
358
  ]),
@@ -338,23 +360,23 @@ describe('Unit: parser/block/extension/table', () => {
338
360
  html('tfoot'),
339
361
  ]).outerHTML], '']);
340
362
  assert.deepStrictEqual(
341
- inspect(parser('~~~table\n: 1.1\n# 1.2\n#! 1.3\n~~~')),
363
+ inspect(parser('~~~table\n: 1.1\n# 1.2\n#!+ 1.3\n~~~')),
342
364
  [[html('table', [
343
365
  html('thead'),
344
366
  html('tbody', [
345
367
  html('tr', [
346
368
  html('td', '1.1'),
347
369
  html('th', '1.2'),
348
- html('th', { class: 'highlight' }, '1.3'),
370
+ html('th', { class: 'highlight', 'data-highlight-extension': '+' }, '1.3'),
349
371
  ]),
350
372
  ]),
351
373
  html('tfoot'),
352
374
  ]).outerHTML], '']);
353
375
  assert.deepStrictEqual(
354
- inspect(parser('~~~table\n#! 1.1\n-\n# 2.1\n-\n: 3.1\n~~~')),
376
+ inspect(parser('~~~table\n#!+ 1.1\n-\n# 2.1\n-\n: 3.1\n~~~')),
355
377
  [[html('table', [
356
378
  html('thead', [
357
- html('tr', [html('th', { class: 'highlight' }, '1.1')]),
379
+ html('tr', [html('th', { class: 'highlight', 'data-highlight-extension': '+' }, '1.1')]),
358
380
  html('tr', [html('th', '2.1')]),
359
381
  ]),
360
382
  html('tbody', [
@@ -363,22 +385,22 @@ describe('Unit: parser/block/extension/table', () => {
363
385
  html('tfoot'),
364
386
  ]).outerHTML], '']);
365
387
  assert.deepStrictEqual(
366
- inspect(parser('~~~table\n#:2! 1.1\n: 1.3\n~~~')),
388
+ inspect(parser('~~~table\n#:2!+ 1.1\n: 1.3\n~~~')),
367
389
  [[html('table', [
368
390
  html('thead'),
369
391
  html('tbody', [
370
392
  html('tr', [
371
- html('th', { class: 'highlight', colspan: '2' }, '1.1'),
393
+ html('th', { class: 'highlight', colspan: '2', 'data-highlight-extension': '+' }, '1.1'),
372
394
  html('td', { class: 'highlight', highlight: 'h' }, '1.3'),
373
395
  ]),
374
396
  ]),
375
397
  html('tfoot'),
376
398
  ]).outerHTML], '']);
377
399
  assert.deepStrictEqual(
378
- inspect(parser('~~~table\n#2:! 1.1\n-\n: 3.1\n~~~')),
400
+ inspect(parser('~~~table\n#2:!+ 1.1\n-\n: 3.1\n~~~')),
379
401
  [[html('table', [
380
402
  html('thead', [
381
- html('tr', [html('th', { class: 'highlight', rowspan: '2' }, '1.1')]),
403
+ html('tr', [html('th', { class: 'highlight', rowspan: '2', 'data-highlight-extension': '+' }, '1.1')]),
382
404
  ]),
383
405
  html('tbody', [
384
406
  html('tr', [html('td', { class: 'highlight', highlight: 'v' }, '3.1')]),
@@ -386,46 +408,46 @@ describe('Unit: parser/block/extension/table', () => {
386
408
  html('tfoot'),
387
409
  ]).outerHTML], '']);
388
410
  assert.deepStrictEqual(
389
- inspect(parser('~~~table\n-\n# \n#! 1.2\n-\n#! 2.1\n: 2.2\n~~~')),
411
+ inspect(parser('~~~table\n-\n# \n#!+ 1.2\n-\n#!+ 2.1\n: 2.2\n~~~')),
390
412
  [[html('table', [
391
413
  html('thead', [
392
414
  html('tr', [
393
415
  html('th'),
394
- html('th', { class: 'highlight' }, '1.2'),
416
+ html('th', { class: 'highlight', 'data-highlight-extension': '+' }, '1.2'),
395
417
  ]),
396
418
  ]),
397
419
  html('tbody', [
398
420
  html('tr', [
399
- html('th', { class: 'highlight' }, '2.1'),
421
+ html('th', { class: 'highlight', 'data-highlight-extension': '+' }, '2.1'),
400
422
  html('td', { class: 'highlight', highlight: 'v h' }, '2.2'),
401
423
  ]),
402
424
  ]),
403
425
  html('tfoot'),
404
426
  ]).outerHTML], '']);
405
427
  assert.deepStrictEqual(
406
- inspect(parser('~~~table\n-\n# \n#! 1.2\n-\n#! 2.1\n:! 2.2\n~~~')),
428
+ inspect(parser('~~~table\n-\n# \n#!+ 1.2\n-\n#!+ 2.1\n:! 2.2\n~~~')),
407
429
  [[html('table', [
408
430
  html('thead', [
409
431
  html('tr', [
410
432
  html('th'),
411
- html('th', { class: 'highlight' }, '1.2'),
433
+ html('th', { class: 'highlight', 'data-highlight-extension': '+' }, '1.2'),
412
434
  ]),
413
435
  ]),
414
436
  html('tbody', [
415
437
  html('tr', [
416
- html('th', { class: 'highlight' }, '2.1'),
417
- html('td', { class: 'highlight', highlight: 'v h c' }, '2.2'),
438
+ html('th', { class: 'highlight', 'data-highlight-extension': '+' }, '2.1'),
439
+ html('td', { class: 'highlight', 'data-highlight-level': '1', highlight: 'v h c' }, '2.2'),
418
440
  ]),
419
441
  ]),
420
442
  html('tfoot'),
421
443
  ]).outerHTML], '']);
422
444
  assert.deepStrictEqual(
423
- inspect(parser('~~~table\n-\n# 1.1\n#! 1.2\n-\n# 2.1\n:2:2 2.2\n: 2.4\n-\n#! 3.1\n: 3.4\n-\n# 4.1\n: 4.2\n~~~')),
445
+ inspect(parser('~~~table\n-\n# 1.1\n#!+ 1.2\n-\n# 2.1\n:2:2 2.2\n: 2.4\n-\n#!+ 3.1\n: 3.4\n-\n# 4.1\n: 4.2\n~~~')),
424
446
  [[html('table', [
425
447
  html('thead', [
426
448
  html('tr', [
427
449
  html('th', '1.1'),
428
- html('th', { class: 'highlight' }, '1.2'),
450
+ html('th', { class: 'highlight', 'data-highlight-extension': '+' }, '1.2'),
429
451
  ]),
430
452
  ]),
431
453
  html('tbody', [
@@ -435,7 +457,7 @@ describe('Unit: parser/block/extension/table', () => {
435
457
  html('td', '2.4'),
436
458
  ]),
437
459
  html('tr', [
438
- html('th', { class: 'highlight' }, '3.1'),
460
+ html('th', { class: 'highlight', 'data-highlight-extension': '+' }, '3.1'),
439
461
  html('td', { class: 'highlight', highlight: 'h' }, '3.4'),
440
462
  ]),
441
463
  html('tr', [
@@ -446,17 +468,17 @@ describe('Unit: parser/block/extension/table', () => {
446
468
  html('tfoot'),
447
469
  ]).outerHTML], '']);
448
470
  assert.deepStrictEqual(
449
- inspect(parser('~~~table\n-\n# 1.1\n#:2! 1.2\n-\n#2:! 2.1\n: 2.2\n-\n3.2\n3.3\n~~~')),
471
+ inspect(parser('~~~table\n-\n# 1.1\n#:2!+ 1.2\n-\n#2:!+ 2.1\n: 2.2\n-\n3.2\n3.3\n~~~')),
450
472
  [[html('table', [
451
473
  html('thead', [
452
474
  html('tr', [
453
475
  html('th', '1.1'),
454
- html('th', { class: 'highlight', colspan: '2' }, '1.2'),
476
+ html('th', { class: 'highlight', colspan: '2', 'data-highlight-extension': '+' }, '1.2'),
455
477
  ]),
456
478
  ]),
457
479
  html('tbody', [
458
480
  html('tr', [
459
- html('th', { class: 'highlight', rowspan: '2' }, '2.1'),
481
+ html('th', { class: 'highlight', rowspan: '2', 'data-highlight-extension': '+' }, '2.1'),
460
482
  html('td', { class: 'highlight', highlight: 'v h' }, '2.2'),
461
483
  ]),
462
484
  html('tr', [
@@ -470,7 +492,7 @@ describe('Unit: parser/block/extension/table', () => {
470
492
  inspect(parser([
471
493
  '~~~table',
472
494
  `-\n# 1\n${[...Array(32)].map((_, i) => `: ${i + 2}`).join('\n')}`,
473
- `-\n#! 1\n${[...Array(32)].map((_, i) => `: ${i + 2}`).join('\n')}`,
495
+ `-\n#!+ 1\n${[...Array(32)].map((_, i) => `: ${i + 2}`).join('\n')}`,
474
496
  '~~~'
475
497
  ].join('\n'))),
476
498
  [[html('table', [
@@ -481,7 +503,7 @@ describe('Unit: parser/block/extension/table', () => {
481
503
  ...[...Array(32)].map((_, i) => html('td', `${i + 2}`)),
482
504
  ]),
483
505
  html('tr', [
484
- html('th', { class: 'highlight' }, '1'),
506
+ html('th', { class: 'highlight', 'data-highlight-extension': '+' }, '1'),
485
507
  ...[...Array(32)].map((_, i) => html('td', { class: 'highlight', highlight: 'h' }, `${i + 2}`)),
486
508
  ]),
487
509
  ]),
@@ -490,7 +512,7 @@ describe('Unit: parser/block/extension/table', () => {
490
512
  inspect(parser([
491
513
  '~~~table',
492
514
  `-\n${[...Array(32)].map((_, i) => `: ${i + 1}`).join('\n')}\n# 33`,
493
- `-\n${[...Array(32)].map((_, i) => `: ${i + 1}`).join('\n')}\n#! 33`,
515
+ `-\n${[...Array(32)].map((_, i) => `: ${i + 1}`).join('\n')}\n#!+ 33`,
494
516
  '~~~'
495
517
  ].join('\n'))),
496
518
  [[html('table', [
@@ -502,14 +524,14 @@ describe('Unit: parser/block/extension/table', () => {
502
524
  ]),
503
525
  html('tr', [
504
526
  ...[...Array(32)].map((_, i) => html('td', { class: 'highlight', highlight: 'h' }, `${i + 1}`)),
505
- html('th', { class: 'highlight' }, '33'),
527
+ html('th', { class: 'highlight', 'data-highlight-extension': '+' }, '33'),
506
528
  ]),
507
529
  ]),
508
530
  html('tfoot')]).outerHTML], '']);
509
531
  assert.deepStrictEqual(
510
532
  inspect(parser([
511
533
  '~~~table',
512
- `-\n${[...Array(32)].map((_, i) => `# ${i + 1}`).join('\n')}\n#! 33`,
534
+ `-\n${[...Array(32)].map((_, i) => `# ${i + 1}`).join('\n')}\n#!+ 33`,
513
535
  `-\n${[...Array(33)].map((_, i) => `: ${i + 1}`).join('\n')}`,
514
536
  '~~~'
515
537
  ].join('\n'))),
@@ -517,7 +539,7 @@ describe('Unit: parser/block/extension/table', () => {
517
539
  html('thead', [
518
540
  html('tr', [
519
541
  ...[...Array(32)].map((_, i) => html('th', `${i + 1}`)),
520
- html('th', { class: 'highlight' }, '33'),
542
+ html('th', { class: 'highlight', 'data-highlight-extension': '+' }, '33'),
521
543
  ]),
522
544
  ]),
523
545
  html('tbody', [
@@ -537,7 +559,8 @@ describe('Unit: parser/block/extension/table', () => {
537
559
  html('thead', [
538
560
  html('tr', [
539
561
  html('th', { class: 'highlight' }, '1'),
540
- ...[...Array(6)].map((_, i) => html('th', { class: 'invalid' }, `${i + 2}`)),
562
+ ...[...Array(5)].map((_, i) => html('th', { class: 'highlight', 'data-highlight-level': `${i + 2}` }, `${i + 2}`)),
563
+ html('th', { class: 'invalid' }, '7'),
541
564
  ]),
542
565
  ]),
543
566
  html('tbody'),
@@ -561,14 +584,14 @@ describe('Unit: parser/block/extension/table', () => {
561
584
  html('tfoot'),
562
585
  ]).outerHTML], '']);
563
586
  assert.deepStrictEqual(
564
- inspect(parser('~~~table\n#! 1\n: 2\n:! 3\n~~~')),
587
+ inspect(parser('~~~table\n#!+ 1\n: 2\n:! 3\n~~~')),
565
588
  [[html('table', [
566
589
  html('thead'),
567
590
  html('tbody', [
568
591
  html('tr', [
569
- html('th', { class: 'highlight' }, '1'),
592
+ html('th', { class: 'highlight', 'data-highlight-extension': '+' }, '1'),
570
593
  html('td', { class: 'highlight', highlight: 'h' }, '2'),
571
- html('td', { class: 'highlight', highlight: 'h c' }, '3'),
594
+ html('td', { class: 'highlight', 'data-highlight-level': '1', highlight: 'h c' }, '3'),
572
595
  ]),
573
596
  ]),
574
597
  html('tfoot'),
@@ -75,10 +75,10 @@ const align: AlignParser = line(fmap(
75
75
  union([str(alignment)]),
76
76
  ([s]) => s.split('/').map(s => s.split(''))));
77
77
 
78
- const delimiter = /^[-=<>]+(?:\/[-=^v]*)?(?=[^\S\n]*\n)|^[#:](?:(?!:\D|0)\d*:(?!0)\d*)?!*(?=\s)/;
78
+ const delimiter = /^[-=<>]+(?:\/[-=^v]*)?(?=[^\S\n]*\n)|^[#:](?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(?=\s)/;
79
79
 
80
80
  const head: CellParser.HeadParser = creation(1, false, block(fmap(open(
81
- str(/^#(?:(?!:\D|0)\d*:(?!0)\d*)?!*(?=\s)/),
81
+ str(/^#(?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(?=\s)/),
82
82
  rewrite(
83
83
  inits([
84
84
  anyline,
@@ -90,7 +90,7 @@ const head: CellParser.HeadParser = creation(1, false, block(fmap(open(
90
90
  false));
91
91
 
92
92
  const data: CellParser.DataParser = creation(1, false, block(fmap(open(
93
- str(/^:(?:(?!:\D|0)\d*:(?!0)\d*)?!*(?=\s)/),
93
+ str(/^:(?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(?=\s)/),
94
94
  rewrite(
95
95
  inits([
96
96
  anyline,
@@ -110,28 +110,40 @@ const dataline: CellParser.DatalineParser = creation(1, false, line(
110
110
  ]))));
111
111
 
112
112
  function attributes(source: string) {
113
- let [, rowspan = undefined, colspan = undefined, highlight = undefined] = source.match(/^.(?:(\d+)?:(\d+)?)?(!+)?$/) ?? [];
113
+ let [, rowspan = undefined, colspan = undefined, highlight = undefined, extension = undefined] =
114
+ source.match(/^[#:](?:(\d+)?:(\d+)?)?(?:(!+)([+]?))?$/) ?? [];
114
115
  assert(rowspan?.[0] !== '0');
115
116
  assert(colspan?.[0] !== '0');
116
117
  rowspan === '1' ? rowspan = undefined : undefined;
117
118
  colspan === '1' ? colspan = undefined : undefined;
118
119
  rowspan &&= `${max(0, min(+rowspan, 65534))}`;
119
120
  colspan &&= `${max(0, min(+colspan, 1000))}`;
120
- highlight &&= highlight.length > 0 ? `${highlight.length}` : undefined;
121
- const valid = !highlight
122
- || source[0] === '#' && +highlight <= 1
123
- || source[0] === ':' && +highlight <= 6;
121
+ extension ||= undefined;
122
+ const level = highlight?.length ?? 0;
123
+ const validH = !highlight
124
+ || source[0] === '#' && level <= 6
125
+ || source[0] === ':' && level <= 6;
126
+ const validE = source[0] === '#' || extension !== '+';
127
+ const valid = validH && validE;
124
128
  return {
125
129
  class: valid ? highlight && 'highlight' : 'invalid',
126
130
  rowspan,
127
131
  colspan,
128
- ...valid
129
- ? { 'data-highlight-level': +highlight! > 1 ? highlight : undefined }
130
- : {
131
- 'data-invalid-syntax': 'table',
132
- 'data-invalid-type': 'syntax',
133
- 'data-invalid-message': 'Too much highlight level',
134
- },
132
+ ...
133
+ !validH && {
134
+ 'data-invalid-syntax': 'table',
135
+ 'data-invalid-type': 'syntax',
136
+ 'data-invalid-message': 'Too much highlight level',
137
+ } ||
138
+ !validE && {
139
+ 'data-invalid-syntax': 'table',
140
+ 'data-invalid-type': 'syntax',
141
+ 'data-invalid-message': 'Extensible cells are only head cells',
142
+ } ||
143
+ {
144
+ 'data-highlight-level': level > 1 ? `${level}` : undefined,
145
+ 'data-highlight-extension': extension,
146
+ },
135
147
  };
136
148
  }
137
149
 
@@ -143,7 +155,8 @@ function format(rows: Tree<RowParser>[]): HTMLTableSectionElement[] {
143
155
  const valigns: ('middle' | 'top' | 'bottom' | '')[] = [];
144
156
  let target = thead;
145
157
  let ranges: Record<number, Record<number, HTMLTableCellElement>> = {};
146
- let verticalHighlights = 0n;
158
+ let verticalHighlightExtensions = 0n;
159
+ let verticalHighlightLevels: string[] = [];
147
160
  ROW:
148
161
  for (let i = 0; i < rows.length; ++i) {
149
162
  // Copy to make them retryable.
@@ -215,9 +228,11 @@ function format(rows: Tree<RowParser>[]): HTMLTableSectionElement[] {
215
228
  const row = html('tr');
216
229
  let heads = 0n;
217
230
  let highlights = 0n;
231
+ let highlightExtensions = 0n;
232
+ let highlightLevels: string[] = [];
218
233
  let hasDataCell = false;
219
- let lHeadCellIdx: bigint;
220
- let rHeadCellIdx: bigint;
234
+ let lHeadCellIndex: bigint;
235
+ let rHeadCellIndex: bigint;
221
236
  for (let j = 0; j < cells.length; ++j) {
222
237
  const jn = BigInt(j);
223
238
  const isVirtual = !!ranges[i]?.[j];
@@ -225,14 +240,16 @@ function format(rows: Tree<RowParser>[]): HTMLTableSectionElement[] {
225
240
  ? splice(cells, j, 0, undefined) && ranges[i][j]
226
241
  : cells[j];
227
242
  const isHeadCell = cell.tagName === 'TH';
228
- heads |= BigInt(isHeadCell) << jn;
229
- highlights |= BigInt(cell.className === 'highlight') << jn;
243
+ heads |= isHeadCell ? 1n << jn : 0n;
244
+ highlights |= cell.className === 'highlight' ? 1n << jn : 0n;
245
+ highlightExtensions |= cell.getAttribute('data-highlight-extension') ? 1n << jn : 0n;
246
+ highlightLevels[j] = cell.getAttribute('data-highlight-level') ?? '1';
230
247
  hasDataCell ||= !isHeadCell;
231
248
  if (isHeadCell && !hasDataCell) {
232
- lHeadCellIdx = jn;
249
+ lHeadCellIndex = jn;
233
250
  }
234
251
  if (isHeadCell && hasDataCell) {
235
- rHeadCellIdx ??= jn;
252
+ rHeadCellIndex ??= jn;
236
253
  }
237
254
  const rowSpan = cell.rowSpan;
238
255
  assert(rowSpan > 0);
@@ -249,6 +266,8 @@ function format(rows: Tree<RowParser>[]): HTMLTableSectionElement[] {
249
266
  splice(cells, j + 1, 0, ...Array(colSpan - 1));
250
267
  heads |= heads & 1n << jn && ~(~0n << BigInt(colSpan)) << jn;
251
268
  highlights |= highlights & 1n << jn && ~(~0n << BigInt(colSpan)) << jn;
269
+ highlightExtensions |= highlightExtensions & 1n << jn && ~(~0n << BigInt(colSpan)) << jn;
270
+ splice(highlightLevels, j + 1, 0, ...Array(colSpan - 1));
252
271
  j += colSpan - 1;
253
272
  }
254
273
  if (target === thead) {
@@ -285,22 +304,39 @@ function format(rows: Tree<RowParser>[]): HTMLTableSectionElement[] {
285
304
  target.appendChild(row);
286
305
  switch (target) {
287
306
  case thead:
288
- verticalHighlights = heads & highlights;
307
+ verticalHighlightExtensions = highlightExtensions;
308
+ verticalHighlightLevels = highlightLevels;
289
309
  continue;
290
310
  case tbody:
291
- lHeadCellIdx ??= -1n;
292
- rHeadCellIdx ??= -1n;
293
- const tHighlights = verticalHighlights;
294
- const horizontalHighlights = heads & highlights;
295
- const lHighlight = ~lHeadCellIdx && horizontalHighlights & 1n << lHeadCellIdx;
296
- const rHighlight = ~rHeadCellIdx && horizontalHighlights & 1n << rHeadCellIdx;
311
+ lHeadCellIndex ??= -1n;
312
+ rHeadCellIndex ??= -1n;
313
+ const tHighlights = verticalHighlightExtensions;
314
+ const horizontalHighlights = highlightExtensions;
315
+ const horizontalHighlightLevels = highlightLevels;
316
+ const lHighlight = ~lHeadCellIndex && horizontalHighlights & 1n << lHeadCellIndex;
317
+ const rHighlight = ~rHeadCellIndex && horizontalHighlights & 1n << rHeadCellIndex;
297
318
  for (let i = 0, m = 1n; i < cells.length; ++i, m <<= 1n) {
298
319
  const cell = cells[i];
299
320
  if (!cell) continue;
300
321
  if (heads & m) continue;
301
322
  assert(cell.tagName === 'TD');
302
- if (!(lHighlight || rHighlight || tHighlights & m || highlights & m)) continue;
303
- cell.classList.add('highlight');
323
+ switch (m) {
324
+ case highlights & m:
325
+ assert(cell.className === 'highlight');
326
+ assert(horizontalHighlightLevels[i]);
327
+ (lHighlight || rHighlight) && cell.setAttribute('data-highlight-level', horizontalHighlightLevels[i]);
328
+ break;
329
+ case lHighlight && m:
330
+ case rHighlight && m:
331
+ cell.classList.add('highlight');
332
+ break;
333
+ case tHighlights & m:
334
+ cell.classList.add('highlight');
335
+ +verticalHighlightLevels[i] > 1 && cell.setAttribute('data-highlight-level', verticalHighlightLevels[i]);
336
+ break;
337
+ default:
338
+ continue;
339
+ }
304
340
  assert(!+cell.setAttribute('highlight', [
305
341
  '',
306
342
  'c',
@@ -3,7 +3,7 @@ import { union, some, state, block, line, validate, focus, rewrite, open, fmap }
3
3
  import { inline, indexee, indexer } from '../inline';
4
4
  import { str } from '../source';
5
5
  import { State } from '../context';
6
- import { visualize, trimBlank } from '../visibility';
6
+ import { visualize, trimBlankStart, trimNodeEnd } from '../visibility';
7
7
  import { html, defrag } from 'typed-dom/dom';
8
8
 
9
9
  export const segment: HeadingParser.SegmentParser = block(validate('#', focus(
@@ -15,19 +15,19 @@ export const heading: HeadingParser = block(rewrite(segment,
15
15
  line(indexee(fmap(union([
16
16
  open(
17
17
  str(/^##+/),
18
- visualize(trimBlank(some(union([indexer, inline])))), true),
18
+ visualize(trimBlankStart(some(union([indexer, inline])))), true),
19
19
  open(
20
20
  str('#'),
21
21
  state(State.autolink,
22
- visualize(trimBlank(some(union([indexer, inline]))))), true),
22
+ visualize(trimBlankStart(some(union([indexer, inline]))))), true),
23
23
  ]),
24
24
  ([h, ...ns]: [string, ...(HTMLElement | string)[]]) => [
25
25
  h.length <= 6
26
- ? html(`h${h.length as 1}`, defrag(ns))
26
+ ? html(`h${h.length as 1}`, trimNodeEnd(defrag(ns)))
27
27
  : html(`h6`, {
28
28
  class: 'invalid',
29
29
  'data-invalid-syntax': 'heading',
30
30
  'data-invalid-type': 'syntax',
31
31
  'data-invalid-message': 'Heading level must be up to 6',
32
- }, defrag(ns))
32
+ }, trimNodeEnd(defrag(ns)))
33
33
  ]))))));
@@ -1,10 +1,10 @@
1
1
  import { ParagraphParser } from '../block';
2
- import { union, some, block, convert, trimEnd, fmap } from '../../combinator';
2
+ import { union, some, block, convert, fmap } from '../../combinator';
3
3
  import { inline } from '../inline';
4
- import { visualize } from '../visibility';
4
+ import { visualize, trimNodeEnd } from '../visibility';
5
5
  import { html, defrag } from 'typed-dom/dom';
6
6
 
7
7
  export const paragraph: ParagraphParser = block(fmap(
8
8
  convert(source => `\r${source}`,
9
- visualize(trimEnd(some(union([inline]))))),
10
- ns => [html('p', defrag(ns))]));
9
+ visualize(some(union([inline])))),
10
+ ns => [html('p', trimNodeEnd(defrag(ns)))]));
@@ -1,11 +1,11 @@
1
1
  import { ReplyParser } from '../block';
2
- import { inits, subsequence, some, block, validate, rewrite, trimEnd, fmap } from '../../combinator';
2
+ import { inits, subsequence, some, block, validate, rewrite, fmap } from '../../combinator';
3
3
  import { cite } from './reply/cite';
4
4
  import { quote, syntax as delimiter } from './reply/quote';
5
5
  import { inline } from '../inline';
6
6
  import { anyline } from '../source';
7
- import { visualize } from '../visibility';
8
- import { push, pop } from 'spica/array';
7
+ import { visualize, trimNodeEnd } from '../visibility';
8
+ import { push } from 'spica/array';
9
9
  import { html, defrag } from 'typed-dom/dom';
10
10
 
11
11
  /*
@@ -25,8 +25,8 @@ export const reply: ReplyParser = block(validate('>', fmap(
25
25
  some(quote),
26
26
  fmap(rewrite(
27
27
  some(anyline, delimiter),
28
- visualize(trimEnd(some(inline)))),
28
+ visualize(some(inline))),
29
29
  ns => push(ns, [html('br')])),
30
30
  ])),
31
31
  ]),
32
- ns => [html('p', defrag(pop(ns)[0]))])));
32
+ ns => [html('p', trimNodeEnd(defrag(ns)))])));
@@ -146,12 +146,13 @@ function isVisible(node: HTMLElement | string, strpos?: number): boolean {
146
146
  }
147
147
  }
148
148
 
149
+ // デフラグ前の非効率な後方トリムを避けるため必要のない限りtrimBlankStart+trimNodeEndで処理する。
149
150
  export function trimBlank<P extends Parser<HTMLElement | string>>(parser: P): P;
150
151
  export function trimBlank<T extends HTMLElement | string>(parser: Parser<T>): Parser<T> {
151
152
  return trimBlankStart(trimBlankEnd(parser));
152
153
  }
153
- function trimBlankStart<P extends Parser<unknown>>(parser: P): P;
154
- function trimBlankStart<T>(parser: Parser<T>): Parser<T> {
154
+ export function trimBlankStart<P extends Parser<unknown>>(parser: P): P;
155
+ export function trimBlankStart<T>(parser: Parser<T>): Parser<T> {
155
156
  return convert(
156
157
  reduce(source => source.replace(regBlankStart, '')),
157
158
  parser);