Просмотр исходного кода

Create PostProcessor function for list

https://youtrack.weseek.co.jp/issue/GW-7856
- Remove custom renderer of list
- Create method to process ordered list on postProcessor
Mudana-Grune 3 лет назад
Родитель
Сommit
b3eaad503a

+ 18 - 0
packages/app/src/services/renderer/PostProcessor/OrderedList.ts

@@ -0,0 +1,18 @@
+export default class OrderedList {
+
+  process(html, context) {
+    const { markdown: md } = context;
+    // const parserdHTMLString = context.parsedHTML?.replace('/\\n|\\/g', '');
+    // console.log(parserdHTMLString);
+    const orderedListHTMLxRE = /<li.*\s*\d+[.)]\s*.*[\s\S]+?<\/li>/gm;
+
+
+    const matchAllOrderedListHtml = html.matchAll(orderedListHTMLxRE);
+    const orderedListRE = /^(\s*)(\d+)([.)])(\s*)(.*)/gm;
+    console.log(...matchAllOrderedListHtml);
+
+    // TODO: Create new list from parsed HTML and replace the html
+    return html;
+  }
+
+}

+ 2 - 0
packages/app/src/services/renderer/growi-renderer.ts

@@ -5,6 +5,7 @@ import { CustomWindow } from '~/interfaces/global';
 import { GrowiRendererConfig, RendererSettings } from '~/interfaces/services/renderer';
 import loggerFactory from '~/utils/logger';
 
+import OrderedList from './PostProcessor/OrderedList';
 import CsvToTable from './PreProcessor/CsvToTable';
 import EasyGrid from './PreProcessor/EasyGrid';
 import Linker from './PreProcessor/Linker';
@@ -73,6 +74,7 @@ export default class GrowiRenderer {
         }),
       ];
       this.postProcessors = [
+        new OrderedList(),
       ];
     }
 

+ 0 - 376
packages/app/src/services/renderer/markdown-it/list.ts

@@ -1,376 +0,0 @@
-import { isSpace } from 'markdown-it/lib/common/utils';
-
-
-// Search `[-+*][\n ]`, returns next pos after marker on success
-// or -1 on fail.
-function skipBulletListMarker(state, startLine) {
-  let pos; let
-    ch;
-
-  pos = state.bMarks[startLine] + state.tShift[startLine];
-  const max = state.eMarks[startLine];
-
-  const marker = state.src.charCodeAt(pos++);
-  // Check bullet
-  if (marker !== 0x2A
-      &&/* * */ marker !== 0x2D
-      &&/* - */ marker !== 0x2B/* + */) {
-    return -1;
-  }
-
-  if (pos < max) {
-    ch = state.src.charCodeAt(pos);
-
-    if (!isSpace(ch)) {
-      // " -test " - is not a list item
-      return -1;
-    }
-  }
-
-  return pos;
-}
-
-// Search `\d+[.)][\n ]`, returns next pos after marker on success
-// or -1 on fail.
-function skipOrderedListMarker(state, startLine) {
-  let ch;
-  const start = state.bMarks[startLine] + state.tShift[startLine];
-  let pos = start;
-  const max = state.eMarks[startLine];
-
-  // List marker should have at least 2 chars (digit + dot)
-  if (pos + 1 >= max) { return -1 }
-
-  ch = state.src.charCodeAt(pos++);
-
-  if (ch < 0x30/* 0 */ || ch > 0x39/* 9 */) { return -1 }
-
-  for (;;) {
-    // EOL -> fail
-    if (pos >= max) { return -1 }
-
-    ch = state.src.charCodeAt(pos++);
-
-    if (ch >= 0x30/* 0 */ && ch <= 0x39/* 9 */) {
-
-      // List marker should have no more than 9 digits
-      // (prevents integer overflow in browsers)
-      if (pos - start >= 10) { return -1 }
-
-      continue;
-    }
-
-    // found valid marker
-    if (ch === 0x29/* ) */ || ch === 0x2e/* . */) {
-      break;
-    }
-
-    return -1;
-  }
-
-
-  if (pos < max) {
-    ch = state.src.charCodeAt(pos);
-
-    if (!isSpace(ch)) {
-      // " 1.test " - is not a list item
-      return -1;
-    }
-  }
-  return pos;
-}
-
-function markTightParagraphs(state, idx) {
-  let i; let l;
-  const level = state.level + 2;
-
-  for (i = idx + 2, l = state.tokens.length - 2; i < l; i++) {
-    if (state.tokens[i].level === level && state.tokens[i].type === 'paragraph_open') {
-      state.tokens[i + 2].hidden = true;
-      state.tokens[i].hidden = true;
-      i += 2;
-    }
-  }
-}
-
-export function list(state, startLine, endLine, silent) {
-  let ch;
-  let contentStart;
-  let i;
-  let indent;
-  let indentAfterMarker;
-  let initial;
-  let isOrdered;
-  let itemLines;
-  let l;
-  let listLines;
-  let listTokIdx;
-  let markerCharCode;
-  let markerValue;
-  let max;
-  let nextLine;
-  let offset;
-  let oldListIndent;
-  let oldParentType;
-  let oldSCount;
-  let oldTShift;
-  let oldTight;
-  let pos;
-  let posAfterMarker;
-  let prevEmptyEnd;
-  let start;
-  let terminate;
-  let terminatorRules;
-  let token;
-  let isTerminatingParagraph = false;
-  let tight = true;
-
-  // if it's indented more than 3 spaces, it should be a code block
-  if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
-
-  // Special case:
-  //  - item 1
-  //   - item 2
-  //    - item 3
-  //     - item 4
-  //      - this one is a paragraph continuation
-  if (state.listIndent >= 0
-      && state.sCount[startLine] - state.listIndent >= 4
-      && state.sCount[startLine] < state.blkIndent) {
-    return false;
-  }
-
-  // limit conditions when list can interrupt
-  // a paragraph (validation mode only)
-  if (silent && state.parentType === 'paragraph') {
-    // Next list item should still terminate previous list item;
-    //
-    // This code can fail if plugins use blkIndent as well as lists,
-    // but I hope the spec gets fixed long before that happens.
-    //
-    if (state.tShift[startLine] >= state.blkIndent) {
-      isTerminatingParagraph = true;
-    }
-  }
-
-  // Detect list type and position after marker
-  // eslint-disable-next-line no-cond-assign
-  if ((posAfterMarker = skipOrderedListMarker(state, startLine)) >= 0) {
-    isOrdered = true;
-    start = state.bMarks[startLine] + state.tShift[startLine];
-    markerValue = Number(state.src.substr(start, posAfterMarker - start - 1));
-
-    // If we're starting a new ordered list right after
-    // a paragraph, it should start with 1.
-    if (isTerminatingParagraph && markerValue !== 1) return false;
-
-  }
-  // eslint-disable-next-line no-cond-assign
-  else if ((posAfterMarker = skipBulletListMarker(state, startLine)) >= 0) {
-    isOrdered = false;
-
-  }
-  else {
-    return false;
-  }
-
-  // If we're starting a new unordered list right after
-  // a paragraph, first line should not be empty.
-  if (isTerminatingParagraph) {
-    if (state.skipSpaces(posAfterMarker) >= state.eMarks[startLine]) return false;
-  }
-
-  // We should terminate list on style change. Remember first one to compare.
-  // eslint-disable-next-line prefer-const
-  markerCharCode = state.src.charCodeAt(posAfterMarker - 1);
-
-  // For validation mode we can terminate immediately
-  if (silent) { return true }
-
-  // Start list
-  // eslint-disable-next-line prefer-const
-  listTokIdx = state.tokens.length;
-
-  if (isOrdered) {
-    token = state.push('ordered_list_open', 'ol', 1);
-    if (markerValue !== 1) {
-      token.attrs = [['start', markerValue]];
-    }
-
-  }
-  else {
-    token = state.push('bullet_list_open', 'ul', 1);
-  }
-
-  // eslint-disable-next-line no-multi-assign
-  token.map = listLines = [startLine, 0];
-  token.markup = String.fromCharCode(markerCharCode);
-
-  //
-  // Iterate list items
-  //
-
-  nextLine = startLine;
-  prevEmptyEnd = false;
-  // eslint-disable-next-line prefer-const
-  terminatorRules = state.md.block.ruler.getRules('list');
-
-  // eslint-disable-next-line prefer-const
-  oldParentType = state.parentType;
-  state.parentType = 'list';
-
-  while (nextLine < endLine) {
-    pos = posAfterMarker;
-    max = state.eMarks[nextLine];
-
-    // eslint-disable-next-line no-multi-assign
-    initial = offset = state.sCount[nextLine] + posAfterMarker - (state.bMarks[startLine] + state.tShift[startLine]);
-
-    while (pos < max) {
-      ch = state.src.charCodeAt(pos);
-
-      if (ch === 0x09) {
-        // eslint-disable-next-line no-mixed-operators
-        offset += 4 - (offset + state.bsCount[nextLine]) % 4;
-      }
-      else if (ch === 0x20) {
-        offset++;
-      }
-      else {
-        break;
-      }
-
-      pos++;
-    }
-
-    contentStart = pos;
-
-    if (contentStart >= max) {
-      // trimming space in "-    \n  3" case, indent is 1 here
-      indentAfterMarker = 1;
-    }
-    else {
-      indentAfterMarker = offset - initial;
-    }
-
-    // If we have more than 4 spaces, the indent is 1
-    // (the rest is just indented code block)
-    if (indentAfterMarker > 4) { indentAfterMarker = 1 }
-
-    // "  -  test"
-    //  ^^^^^ - calculating total length of this thing
-    indent = initial + indentAfterMarker;
-
-    // Run subparser & write tokens
-    token = state.push('list_item_open', 'li', 1);
-    token.markup = String.fromCharCode(markerCharCode);
-    // eslint-disable-next-line no-multi-assign
-    token.map = itemLines = [startLine, 0];
-
-    // change current state, then restore it after parser subcall
-    oldTight = state.tight;
-    oldTShift = state.tShift[startLine];
-    oldSCount = state.sCount[startLine];
-
-    //  - example list
-    // ^ listIndent position will be here
-    //   ^ blkIndent position will be here
-    //
-    oldListIndent = state.listIndent;
-    state.listIndent = state.blkIndent;
-    state.blkIndent = indent;
-
-    state.tight = true;
-    state.tShift[startLine] = contentStart - state.bMarks[startLine];
-    state.sCount[startLine] = offset;
-
-    if (contentStart >= max && state.isEmpty(startLine + 1)) {
-      // workaround for this case
-      // (list item is empty, list terminates before "foo"):
-      // ~~~~~~~~
-      //   -
-      //
-      //     foo
-      // ~~~~~~~~
-      state.line = Math.min(state.line + 2, endLine);
-    }
-    else {
-      state.md.block.tokenize(state, startLine, endLine, true);
-    }
-
-    // If any of list item is tight, mark list as tight
-    if (!state.tight || prevEmptyEnd) {
-      tight = false;
-    }
-    // Item become loose if finish with empty line,
-    // but we should filter last element, because it means list finish
-    prevEmptyEnd = (state.line - startLine) > 1 && state.isEmpty(state.line - 1);
-
-    state.blkIndent = state.listIndent;
-    state.listIndent = oldListIndent;
-    state.tShift[startLine] = oldTShift;
-    state.sCount[startLine] = oldSCount;
-    state.tight = oldTight;
-
-    token = state.push('list_item_close', 'li', -1);
-    token.markup = String.fromCharCode(markerCharCode);
-
-    // eslint-disable-next-line no-multi-assign, no-param-reassign
-    nextLine = startLine = state.line;
-    itemLines[1] = nextLine;
-    contentStart = state.bMarks[startLine];
-
-    if (nextLine >= endLine) { break }
-
-    //
-    // Try to check if list is terminated or continued.
-    //
-    if (state.sCount[nextLine] < state.blkIndent) { break }
-
-    // if it's indented more than 3 spaces, it should be a code block
-    if (state.sCount[startLine] - state.blkIndent >= 4) { break }
-
-    // fail if terminating block found
-    terminate = false;
-    for (i = 0, l = terminatorRules.length; i < l; i++) {
-      if (terminatorRules[i](state, nextLine, endLine, true)) {
-        terminate = true;
-        break;
-      }
-    }
-    if (terminate) { break }
-
-    // fail if list has another type
-    if (isOrdered) {
-      posAfterMarker = skipOrderedListMarker(state, nextLine);
-      if (posAfterMarker < 0) { break }
-    }
-    else {
-      posAfterMarker = skipBulletListMarker(state, nextLine);
-      if (posAfterMarker < 0) { break }
-    }
-
-    if (markerCharCode !== state.src.charCodeAt(posAfterMarker - 1)) { break }
-  }
-
-  // Finalize list
-  if (isOrdered) {
-    token = state.push('ordered_list_close', 'ol', -1);
-  }
-  else {
-    token = state.push('bullet_list_close', 'ul', -1);
-  }
-  token.markup = String.fromCharCode(markerCharCode);
-
-  listLines[1] = nextLine;
-  state.line = nextLine;
-
-  state.parentType = oldParentType;
-
-  // mark paragraphs tight if needed
-  if (tight) {
-    markTightParagraphs(state, listTokIdx);
-  }
-
-  return true;
-}