Yuki Takei 3 лет назад
Родитель
Сommit
7b2feb8ef5
23 измененных файлов с 5 добавлено и 929 удалено
  1. 0 137
      packages/app/src/components/Page/RevisionRenderer.tsx
  2. 0 0
      packages/app/src/services/renderer/PostProcessor/.keep
  3. 0 23
      packages/app/src/services/renderer/PreProcessor/CsvToTable.js
  4. 0 14
      packages/app/src/services/renderer/PreProcessor/Linker.js
  5. 0 29
      packages/app/src/services/renderer/PreProcessor/XssFilter.ts
  6. 0 139
      packages/app/src/services/renderer/interceptor/detach-code-blocks.js
  7. 0 0
      packages/app/src/services/renderer/markdown-it/PreProcessor/EasyGrid.js
  8. 0 9
      packages/app/src/services/renderer/markdown-it/drawio-viewer.js
  9. 0 66
      packages/app/src/services/renderer/markdown-it/emoji-mart-data.ts
  10. 0 12
      packages/app/src/services/renderer/markdown-it/emoji.js
  11. 0 7
      packages/app/src/services/renderer/markdown-it/footernote.js
  12. 0 34
      packages/app/src/services/renderer/markdown-it/header-line-number.js
  13. 0 13
      packages/app/src/services/renderer/markdown-it/header-with-edit-link.js
  14. 0 33
      packages/app/src/services/renderer/markdown-it/header.js
  15. 0 48
      packages/app/src/services/renderer/markdown-it/link-by-relative-path.ts
  16. 0 7
      packages/app/src/services/renderer/markdown-it/mathjax.js
  17. 0 28
      packages/app/src/services/renderer/markdown-it/plantuml.ts
  18. 0 16
      packages/app/src/services/renderer/markdown-it/table-with-handsontable-button.js
  19. 0 9
      packages/app/src/services/renderer/markdown-it/table.js
  20. 0 14
      packages/app/src/services/renderer/markdown-it/task-lists.js
  21. 0 27
      packages/app/src/services/renderer/markdown-it/toc-and-anchor.js
  22. 5 238
      packages/app/src/services/renderer/renderer.tsx
  23. 0 26
      packages/app/src/stores/renderer.tsx

+ 0 - 137
packages/app/src/components/Page/RevisionRenderer.tsx

@@ -23,7 +23,6 @@ const RevisionRenderer = React.memo((props: Props): JSX.Element => {
 
 
   return (
   return (
     <ReactMarkdown
     <ReactMarkdown
-      data-testid="wiki"
       {...rendererOptions}
       {...rendererOptions}
       className={`wiki ${additionalClassName ?? ''}`}
       className={`wiki ${additionalClassName ?? ''}`}
     >
     >
@@ -31,142 +30,6 @@ const RevisionRenderer = React.memo((props: Props): JSX.Element => {
     </ReactMarkdown>
     </ReactMarkdown>
   );
   );
 
 
-  // const [html, setHtml] = useState('');
-
-  // const { data: interceptorManager } = useInterceptorManager();
-  // const { data: editorSettings } = useEditorSettings();
-  // const { data: currentPathname } = useCurrentPathname();
-
-  // const currentRenderingContext = useMemo(() => {
-  //   return {
-  //     markdown,
-  //     parsedHTML: '',
-  //     pagePath,
-  //     renderDrawioInRealtime: editorSettings?.renderDrawioInRealtime,
-  //     currentPathname: decodeURIComponent(currentPathname ?? '/'),
-  //   };
-  // }, [editorSettings?.renderDrawioInRealtime, markdown, pagePath]);
-
-
-  // const renderHtml = useCallback(async() => {
-  //   if (interceptorManager == null) {
-  //     return;
-  //   }
-
-  //   const context = currentRenderingContext;
-
-  //   await interceptorManager.process('preRender', context);
-  //   await interceptorManager.process('prePreProcess', context);
-  //   context.markdown = growiRenderer.preProcess(context.markdown, context);
-  //   await interceptorManager.process('postPreProcess', context);
-  //   context.parsedHTML = growiRenderer.process(context.markdown, context);
-  //   await interceptorManager.process('prePostProcess', context);
-  //   context.parsedHTML = growiRenderer.postProcess(context.parsedHTML, context);
-
-  //   const isMarkdownEmpty = context.markdown.trim().length === 0;
-  //   if (highlightKeywords != null && !isMarkdownEmpty) {
-  //     context.parsedHTML = getHighlightedBody(context.parsedHTML, highlightKeywords);
-  //   }
-  //   await interceptorManager.process('postPostProcess', context);
-  //   await interceptorManager.process('preRenderHtml', context);
-
-  //   setHtml(context.parsedHTML);
-  // }, [currentRenderingContext, growiRenderer, highlightKeywords, interceptorManager]);
-
-  // useEffect(() => {
-  //   if (interceptorManager == null) {
-  //     return;
-  //   }
-
-  //   renderHtml()
-  //     .then(() => {
-  //       // const HeaderLink = document.getElementsByClassName('revision-head-link');
-  //       // const HeaderLinkArray = Array.from(HeaderLink);
-  //       // addSmoothScrollEvent(HeaderLinkArray as HTMLAnchorElement[], blinkElem);
-
-  //       // interceptorManager.process('postRenderHtml', currentRenderingContext);
-  //     });
-
-  // }, [currentRenderingContext, interceptorManager, renderHtml]);
-
-  // const config = props.appContainer.getConfig();
-  // const isMathJaxEnabled = !!config.env.MATHJAX;
-
-  // return (
-  //   <RevisionBody
-  //     html={html}
-  //     isMathJaxEnabled={isMathJaxEnabled}
-  //     additionalClassName={props.additionalClassName}
-  //     renderMathJaxOnInit
-  //   />
-  // );
-
-  // const [html, setHtml] = useState('');
-
-  // const { data: interceptorManager } = useInterceptorManager();
-  // const { data: editorSettings } = useEditorSettings();
-  // const { data: currentPathname } = useCurrentPathname();
-
-  // const currentRenderingContext = useMemo(() => {
-  //   return {
-  //     markdown,
-  //     parsedHTML: '',
-  //     pagePath,
-  //     renderDrawioInRealtime: editorSettings?.renderDrawioInRealtime,
-  //     currentPathname: decodeURIComponent(currentPathname ?? '/'),
-  //   };
-  // }, [editorSettings?.renderDrawioInRealtime, markdown, pagePath]);
-
-
-  // const renderHtml = useCallback(async() => {
-  //   if (interceptorManager == null) {
-  //     return;
-  //   }
-
-  //   const context = currentRenderingContext;
-
-  //   await interceptorManager.process('preRender', context);
-  //   await interceptorManager.process('prePreProcess', context);
-  //   context.markdown = growiRenderer.preProcess(context.markdown, context);
-  //   await interceptorManager.process('postPreProcess', context);
-  //   context.parsedHTML = growiRenderer.process(context.markdown, context);
-  //   await interceptorManager.process('prePostProcess', context);
-  //   context.parsedHTML = growiRenderer.postProcess(context.parsedHTML, context);
-
-  //   const isMarkdownEmpty = context.markdown.trim().length === 0;
-  //   if (highlightKeywords != null && !isMarkdownEmpty) {
-  //     context.parsedHTML = getHighlightedBody(context.parsedHTML, highlightKeywords);
-  //   }
-  //   await interceptorManager.process('postPostProcess', context);
-  //   await interceptorManager.process('preRenderHtml', context);
-
-  //   setHtml(context.parsedHTML);
-  // }, [currentRenderingContext, growiRenderer, highlightKeywords, interceptorManager]);
-
-  // useEffect(() => {
-  //   if (interceptorManager == null) {
-  //     return;
-  //   }
-
-  //   renderHtml()
-  //     .then(() => {
-  //       // const HeaderLink = document.getElementsByClassName('revision-head-link');
-  //       // const HeaderLinkArray = Array.from(HeaderLink);
-  //       // addSmoothScrollEvent(HeaderLinkArray as HTMLAnchorElement[], blinkElem);
-
-  //       // interceptorManager.process('postRenderHtml', currentRenderingContext);
-  //     });
-
-  // }, [currentRenderingContext, interceptorManager, renderHtml]);
-
-  // return (
-  //   <RevisionBody
-  //     html={html}
-  //     additionalClassName={props.additionalClassName}
-  //     renderMathJaxOnInit
-  //   />
-  // );
-
 });
 });
 RevisionRenderer.displayName = 'RevisionRenderer';
 RevisionRenderer.displayName = 'RevisionRenderer';
 
 

+ 0 - 0
packages/app/src/services/renderer/PostProcessor/.keep


+ 0 - 23
packages/app/src/services/renderer/PreProcessor/CsvToTable.js

@@ -1,23 +0,0 @@
-import csvToMarkdownTable from 'csv-to-markdown-table';
-
-export default class CsvToTable {
-
-  process(markdown) {
-    // see: https://regex101.com/r/WR6IvX/3
-    return markdown.replace(/:::\s*(\S+)[\r\n]((.|[\r\n])*?)[\r\n]:::/gm, (all, group1, group2) => {
-      switch (group1) {
-        case 'tsv':
-          return csvToMarkdownTable(group2, '\t');
-        case 'tsv-h':
-          return csvToMarkdownTable(group2, '\t', true);
-        case 'csv':
-          return csvToMarkdownTable(group2, ',');
-        case 'csv-h':
-          return csvToMarkdownTable(group2, ',', true);
-        default:
-          return all;
-      }
-    });
-  }
-
-}

+ 0 - 14
packages/app/src/services/renderer/PreProcessor/Linker.js

@@ -1,14 +0,0 @@
-
-export default class Linker {
-
-  process(markdown) {
-    return markdown
-      // process angle branckets like '</Level1/Level2>'
-      // see: https://regex101.com/r/rxAy4F/2
-      .replace(/<((\/[^>\n]+?){2,})>/g, '<a href="$1">$1</a>') // ページ間リンク: <> でかこまれてて / から始まり、 / が2個以上
-      // process square branckets like '[/Level1]'
-      // see: https://regex101.com/r/QSt1yu/5
-      .replace(/\[(\/[^\]\n]+?)\](?!\()/g, '<a href="$1">$1</a>');
-  }
-
-}

+ 0 - 29
packages/app/src/services/renderer/PreProcessor/XssFilter.ts

@@ -1,29 +0,0 @@
-import Xss from '~/services/xss';
-import XssOption, { XssOptionConfig } from '~/services/xss/xssOption';
-
-export default class XssFilter {
-
-  xssOption: XssOption;
-
-  xss;
-
-  config: XssOptionConfig;
-
-  constructor(config: XssOptionConfig) {
-    this.config = config;
-
-    if (config.isEnabledXssPrevention) {
-      this.xssOption = new XssOption(config);
-      this.xss = new Xss(this.xssOption);
-    }
-  }
-
-  process(markdown) {
-    if (this.config.isEnabledXssPrevention) {
-      return this.xss.process(markdown);
-    }
-
-    return markdown;
-  }
-
-}

+ 0 - 139
packages/app/src/services/renderer/interceptor/detach-code-blocks.js

@@ -1,139 +0,0 @@
-import { BasicInterceptor } from '@growi/core';
-
-import loggerFactory from '~/utils/logger';
-
-class DetachCodeBlockUtil {
-
-  static createReplaceStr(replaceId) {
-    return `<pre class="detached-code-block">${replaceId}</pre>`;
-  }
-
-}
-
-/**
- * The interceptor that detach code blocks
- */
-export class DetachCodeBlockInterceptor extends BasicInterceptor {
-
-  constructor() {
-    super();
-    this.logger = loggerFactory('growi:interceptor:DetachCodeBlockInterceptor');
-  }
-
-  /**
-   * @inheritdoc
-   */
-  isInterceptWhen(contextName) {
-    return /^prePreProcess|prePostProcess$/.test(contextName);
-  }
-
-  getTargetKey(contextName) {
-    if (contextName === 'prePreProcess') {
-      return 'markdown';
-    }
-    if (contextName === 'prePostProcess') {
-      return 'parsedHTML';
-    }
-  }
-
-  /**
-   * @inheritdoc
-   */
-  process(contextName, ...args) {
-    this.logger.debug(`processing: 'contextName'=${contextName}`);
-
-    const context = Object.assign(args[0]); // clone
-    const targetKey = this.getTargetKey(contextName);
-
-    context.dcbContextMap = {};
-
-    // see: https://regex101.com/r/8PAEcC/5
-    // eslint-disable-next-line max-len
-    context[targetKey] = context[targetKey].replace(/(^(```|~~~)(.|[\r\n])*?(```|~~~)$)|(`[^\r\n]*?`)|(<pre>(.|[\r\n])*?<\/pre>)|(<pre\s[^>]*>(.|[\r\n])*?<\/pre>)/gm, (all) => {
-      // create ID
-      const replaceId = `dcb-${this.createRandomStr(8)}`;
-      this.logger.debug(`'replaceId'=${replaceId} : `, all);
-
-      // register to context
-      const dcbContext = {};
-      dcbContext.content = all;
-      dcbContext.substituteContent = DetachCodeBlockUtil.createReplaceStr(replaceId);
-      context.dcbContextMap[replaceId] = dcbContext;
-
-      // return substituteContent
-      return dcbContext.substituteContent;
-    });
-
-    // resolve
-    return Promise.resolve(context);
-  }
-
-  /**
-   * @see http://qiita.com/ryounagaoka/items/4736c225bdd86a74d59c
-   *
-   * @param {number} length
-   * @return random strings
-   */
-  createRandomStr(length) {
-    const bag = 'abcdefghijklmnopqrstuvwxyz0123456789';
-    let generated = '';
-    for (let i = 0; i < length; i++) {
-      generated += bag[Math.floor(Math.random() * bag.length)];
-    }
-    return generated;
-  }
-
-}
-
-
-/**
- * The interceptor that restore detached code blocks
- */
-export class RestoreCodeBlockInterceptor extends BasicInterceptor {
-
-  constructor() {
-    super();
-    this.logger = loggerFactory('growi:interceptor:DetachCodeBlockInterceptor');
-  }
-
-  /**
-   * @inheritdoc
-   */
-  isInterceptWhen(contextName) {
-    return /^postPreProcess|preRenderHtml|preRenderPreviewHtml|preRenderCommentHtml|preRenderCommentPreviewHtml$/.test(contextName);
-  }
-
-  getTargetKey(contextName) {
-    if (contextName === 'postPreProcess') {
-      return 'markdown';
-    }
-    if (contextName === 'preRenderHtml' || contextName === 'preRenderPreviewHtml'
-        || contextName === 'preRenderCommentHtml' || contextName === 'preRenderCommentPreviewHtml') {
-      return 'parsedHTML';
-    }
-  }
-
-  /**
-   * @inheritdoc
-   */
-  process(contextName, ...args) {
-    this.logger.debug(`processing: 'contextName'=${contextName}`);
-
-    const context = Object.assign(args[0]); // clone
-    const targetKey = this.getTargetKey(contextName);
-
-    // forEach keys of dcbContextMap
-    Object.keys(context.dcbContextMap).forEach((replaceId) => {
-      // get context object from context
-      const dcbContext = context.dcbContextMap[replaceId];
-
-      // replace it with content by using getter function so that the doller sign does not work
-      // see: https://github.com/weseek/growi/issues/285
-      context[targetKey] = context[targetKey].replace(dcbContext.substituteContent, () => { return dcbContext.content });
-    });
-
-    // resolve
-    return Promise.resolve(context);
-  }
-
-}

+ 0 - 0
packages/app/src/services/renderer/PreProcessor/EasyGrid.js → packages/app/src/services/renderer/markdown-it/PreProcessor/EasyGrid.js


+ 0 - 9
packages/app/src/services/renderer/markdown-it/drawio-viewer.js

@@ -1,9 +0,0 @@
-export default class DrawioViewerConfigurer {
-
-  configure(md) {
-    // md.use(require('markdown-it-drawio-viewer'), {
-    //   marker: ':::',
-    // });
-  }
-
-}

+ 0 - 66
packages/app/src/services/renderer/markdown-it/emoji-mart-data.ts

@@ -1,66 +0,0 @@
-import { Emoji } from 'emoji-mart';
-import data from 'emoji-mart/data/apple.json';
-
-const DEFAULT_EMOJI_SIZE = 24;
-
-
-type EmojiMap = {
-  [key: string]: string,
-};
-
-/**
- *
- * Get native emoji with skin tone
- * @param skin number
- * @returns emoji data with skin tone
- */
-const getEmojiSkinTone = (emojiName: string): EmojiMap => {
-  const emojiData = {};
-  [...Array(6).keys()].forEach((index) => {
-    if (index > 0) {
-      const elem = Emoji({
-        emoji: emojiName,
-        skin: index + 1,
-        size: DEFAULT_EMOJI_SIZE,
-      });
-      if (elem) {
-        emojiData[`${emojiName}::skin-tone-${index + 1}`] = elem.props['aria-label'].split(',')[0];
-      }
-    }
-  });
-  return emojiData;
-};
-
-/**
- * Get native emoji from emoji array
- * @returns emoji data
- */
-
-const getNativeEmoji = (): EmojiMap => {
-  const emojiData = {};
-  Object.entries(data.emojis).forEach((emoji) => {
-    const emojiName = emoji[0];
-    const hasSkinVariation = 'skin_variations' in emoji[1];
-
-    const elem = Emoji({
-      emoji: emojiName,
-      size: DEFAULT_EMOJI_SIZE,
-    });
-
-    if (elem != null) {
-      emojiData[emojiName] = elem.props['aria-label'].split(',')[0];
-      if (hasSkinVariation) {
-        const emojiWithSkinTone = getEmojiSkinTone(emojiName);
-        Object.assign(emojiData, emojiWithSkinTone);
-      }
-    }
-  });
-
-  return emojiData;
-};
-
-/**
- * Get native emoji mart data
- * @returns native emoji mart data
- */
-export const emojiMartData = getNativeEmoji();

+ 0 - 12
packages/app/src/services/renderer/markdown-it/emoji.js

@@ -1,12 +0,0 @@
-// import markdownItEmojiMart from 'markdown-it-emoji-mart';
-
-import { emojiMartData } from './emoji-mart-data';
-
-
-export default class EmojiConfigurer {
-
-  configure(md) {
-    // md.use(markdownItEmojiMart, { defs: emojiMartData });
-  }
-
-}

+ 0 - 7
packages/app/src/services/renderer/markdown-it/footernote.js

@@ -1,7 +0,0 @@
-export default class FooternoteConfigurer {
-
-  configure(md) {
-    // md.use(require('markdown-it-footnote'));
-  }
-
-}

+ 0 - 34
packages/app/src/services/renderer/markdown-it/header-line-number.js

@@ -1,34 +0,0 @@
-export default class HeaderLineNumberConfigurer {
-
-  constructor() {
-    this.firstLine = 0;
-  }
-
-  configure(md) {
-    for (const renderName of ['paragraph_open', 'heading_open', 'image', 'code_block', 'blockquote_open', 'list_item_open']) {
-      this.addLineNumberRenderer(md, renderName);
-    }
-  }
-
-  /**
-   * Add line numbers for sync scroll
-   * @see https://github.com/Microsoft/vscode/blob/6e8d4d057bd1152d49a1e9780ec6db6363593855/extensions/markdown/src/markdownEngine.ts#L118
-   */
-  addLineNumberRenderer(md, ruleName) {
-    const original = md.renderer.rules[ruleName];
-    md.renderer.rules[ruleName] = (tokens, idx, options, env, self) => {
-      const token = tokens[idx];
-      if (token.map && token.map.length) {
-        token.attrSet('data-line', this.firstLine + token.map[0]);
-        token.attrJoin('class', 'code-line');
-      }
-
-      if (original) {
-        return original(tokens, idx, options, env, self);
-      }
-
-      return self.renderToken(tokens, idx, options, env, self);
-    };
-  }
-
-}

+ 0 - 13
packages/app/src/services/renderer/markdown-it/header-with-edit-link.js

@@ -1,13 +0,0 @@
-export default class HeaderWithEditLinkConfigurer {
-
-  configure(md) {
-    md.renderer.rules.heading_close = (tokens, idx) => {
-      return `<span class="revision-head-edit-button">
-                <a href="#edit" onClick="Crowi.setCaretLine(parseInt(this.parentNode.parentNode.dataset.line, 10))">
-                  <i class="icon-note"></i>
-                </a>
-              </span></${tokens[idx].tag}>`;
-    };
-  }
-
-}

+ 0 - 33
packages/app/src/services/renderer/markdown-it/header.js

@@ -1,33 +0,0 @@
-export default class HeaderConfigurer {
-
-  constructor() {
-    this.injectRevisionHeadClass = this.injectRevisionHeadClass.bind(this);
-  }
-
-  configure(md) {
-    const rules = md.renderer.rules;
-    const original = rules.heading_open;
-    // combine rule and set
-    // rules.heading_open = this.combineRules(this.injectRevisionHeadClass, headingOpenOrg);
-    rules.heading_open = (tokens, idx, options, env, self) => {
-      // Inject 'revision-head' class
-      this.injectRevisionHeadClass(tokens, idx, options, env, self);
-
-      if (original) {
-        return original(tokens, idx, options, env, self);
-      }
-
-      return self.renderToken(tokens, idx, options, env, self);
-    };
-  }
-
-  /**
-   * Inject 'revision-head' class
-   */
-  injectRevisionHeadClass(tokens, idx, options, env, slf) {
-    if (tokens[idx].map && tokens[idx].level === 0) {
-      tokens[idx].attrJoin('class', 'revision-head');
-    }
-  }
-
-}

+ 0 - 48
packages/app/src/services/renderer/markdown-it/link-by-relative-path.ts

@@ -1,48 +0,0 @@
-import path from 'path';
-
-// https://regex101.com/r/vV8LUe/1
-const PATTERN_RELATIVE_PATH = new RegExp(/^(\.{1,2})(\/.*)?$/);
-
-export default class LinkerByRelativePathConfigurer {
-
-  pagePath: string;
-
-  constructor(pagePath: string) {
-    this.pagePath = pagePath;
-  }
-
-  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
-  configure(md): void {
-    const pagePath = this.pagePath;
-
-    // Remember old renderer, if overridden, or proxy to default renderer
-    const defaultRender = md.renderer.rules.link_open || function(tokens, idx, options, env, self) {
-      return self.renderToken(tokens, idx, options);
-    };
-
-    md.renderer.rules.link_open = function(tokens, idx, options, env, self) {
-      if (tokens[idx] == null || (typeof tokens[idx].attrIndex !== 'function')) {
-        return defaultRender(tokens, idx, options, env, self);
-      }
-
-      // get href
-      const hrefIndex = tokens[idx].attrIndex('href');
-
-      if (hrefIndex != null && hrefIndex >= 0) {
-        const href: string = tokens[idx].attrs[hrefIndex][1];
-        const currentPath: string | null = pagePath;
-
-        // resolve relative path and replace
-        if (PATTERN_RELATIVE_PATH.test(href) && currentPath != null) {
-          const newHref = path.resolve(path.dirname(currentPath), href);
-          tokens[idx].attrs[hrefIndex][1] = newHref;
-        }
-      }
-
-      // pass token to default renderer.
-      return defaultRender(tokens, idx, options, env, self);
-    };
-
-  }
-
-}

+ 0 - 7
packages/app/src/services/renderer/markdown-it/mathjax.js

@@ -1,7 +0,0 @@
-export default class MathJaxConfigurer {
-
-  configure(md) {
-    // md.use(require('markdown-it-mathjax')());
-  }
-
-}

+ 0 - 28
packages/app/src/services/renderer/markdown-it/plantuml.ts

@@ -1,28 +0,0 @@
-import plantumlEncoder from 'plantuml-encoder';
-import urljoin from 'url-join';
-
-import { RendererConfig } from '~/interfaces/services/renderer';
-
-export default class PlantUMLConfigurer {
-
-  serverUrl: string;
-
-  constructor(config: RendererConfig) {
-    // Do NOT use HTTPS URL because plantuml.com refuse request except from members
-    this.serverUrl = config.plantumlUri || 'http://plantuml.com/plantuml';
-
-    this.generateSource = this.generateSource.bind(this);
-  }
-
-  configure(md) {
-    // md.use(require('markdown-it-plantuml'), {
-    //   generateSource: this.generateSource,
-    // });
-  }
-
-  generateSource(umlCode) {
-    const zippedCode = plantumlEncoder.encode(`@startuml\n${umlCode}\n@enduml`);
-    return urljoin(this.serverUrl, 'svg', zippedCode);
-  }
-
-}

+ 0 - 16
packages/app/src/services/renderer/markdown-it/table-with-handsontable-button.js

@@ -1,16 +0,0 @@
-export default class TableWithHandsontableButtonConfigurer {
-
-  configure(md) {
-    md.renderer.rules.table_open = (tokens, idx) => {
-      const beginLine = tokens[idx].map[0] + 1;
-      const endLine = tokens[idx].map[1];
-      // eslint-disable-next-line max-len
-      return `<div class="editable-with-handsontable"><button class="handsontable-modal-trigger" onClick="globalEmitter.emit('launchHandsontableModal', ${beginLine}, ${endLine})"><i class="icon-note"></i></button><table class="table table-bordered">`;
-    };
-
-    md.renderer.rules.table_close = (tokens, idx) => {
-      return '</table></div>';
-    };
-  }
-
-}

+ 0 - 9
packages/app/src/services/renderer/markdown-it/table.js

@@ -1,9 +0,0 @@
-export default class TableConfigurer {
-
-  configure(md) {
-    md.renderer.rules.table_open = (tokens, idx) => {
-      return '<table class="table table-bordered">';
-    };
-  }
-
-}

+ 0 - 14
packages/app/src/services/renderer/markdown-it/task-lists.js

@@ -1,14 +0,0 @@
-export default class TaskListsConfigurer {
-
-  configure(md) {
-    // md.use(require('markdown-it-task-checkbox'), {
-    //   disabled: true,
-    //   divWrap: true,
-    //   divClass: 'checkbox checkbox-primary',
-    //   idPrefix: 'cbx_',
-    //   ulClass: 'task-list',
-    //   liClass: 'task-list-item',
-    // });
-  }
-
-}

+ 0 - 27
packages/app/src/services/renderer/markdown-it/toc-and-anchor.js

@@ -1,27 +0,0 @@
-// import markdownItEmojiMart from 'markdown-it-emoji-mart';
-// import markdownItToc from 'markdown-it-toc-and-anchor-with-slugid';
-
-import { emojiMartData } from './emoji-mart-data';
-
-export default class TocAndAnchorConfigurer {
-
-  configure(md) {
-    // md.use(markdownItEmojiMart, { defs: emojiMartData })
-    //   .use(markdownItToc, {
-    //     tocLastLevel: 3,
-    //     anchorLinkBefore: false,
-    //     anchorLinkSymbol: '',
-    //     anchorLinkSymbolClassName: 'icon-link',
-    //     anchorClassName: 'revision-head-link',
-    //   });
-
-    // set toc render function
-    md.set({
-      tocCallback: (tocMarkdown, tocArray, tocHtml) => {
-        // eslint-disable-next-line no-undef
-        globalEmitter.emit('renderTocHtml', tocHtml);
-      },
-    });
-  }
-
-}

+ 5 - 238
packages/app/src/services/renderer/renderer.tsx

@@ -44,199 +44,12 @@ import { pukiwikiLikeLinker } from './remark-plugins/pukiwiki-like-linker';
 import * as table from './remark-plugins/table';
 import * as table from './remark-plugins/table';
 import * as xsvToTable from './remark-plugins/xsv-to-table';
 import * as xsvToTable from './remark-plugins/xsv-to-table';
 
 
-// import CsvToTable from './PreProcessor/CsvToTable';
 // import EasyGrid from './PreProcessor/EasyGrid';
 // import EasyGrid from './PreProcessor/EasyGrid';
-// import Linker from './PreProcessor/Linker';
-// import XssFilter from './PreProcessor/XssFilter';
 // import BlockdiagConfigurer from './markdown-it/blockdiag';
 // import BlockdiagConfigurer from './markdown-it/blockdiag';
-// import DrawioViewerConfigurer from './markdown-it/drawio-viewer';
-// import EmojiConfigurer from './markdown-it/emoji';
-// import FooternoteConfigurer from './markdown-it/footernote';
-// import HeaderConfigurer from './markdown-it/header';
-// import HeaderLineNumberConfigurer from './markdown-it/header-line-number';
-// import HeaderWithEditLinkConfigurer from './markdown-it/header-with-edit-link';
-// import LinkerByRelativePathConfigurer from './markdown-it/link-by-relative-path';
-// import MathJaxConfigurer from './markdown-it/mathjax';
-// import PlantUMLConfigurer from './markdown-it/plantuml';
-// import TableConfigurer from './markdown-it/table';
-// import TableWithHandsontableButtonConfigurer from './markdown-it/table-with-handsontable-button';
-// import TaskListsConfigurer from './markdown-it/task-lists';
-// import TocAndAnchorConfigurer from './markdown-it/toc-and-anchor';
 
 
 
 
 const logger = loggerFactory('growi:util:GrowiRenderer');
 const logger = loggerFactory('growi:util:GrowiRenderer');
 
 
-// declare const hljs;
-
-// type MarkdownSettings = {
-//   breaks?: boolean,
-// };
-
-// export default class GrowiRenderer {
-
-//   RendererConfig: RendererConfig;
-
-//   constructor(RendererConfig: RendererConfig, pagePath?: Nullable<string>) {
-//     this.RendererConfig = RendererConfig;
-//     this.pagePath = pagePath;
-
-//     if (isClient() && (window as CustomWindow).growiRenderer != null) {
-//       this.preProcessors = (window as CustomWindow).growiRenderer.preProcessors;
-//       this.postProcessors = (window as CustomWindow).growiRenderer.postProcessors;
-//     }
-//     else {
-//       this.preProcessors = [
-//         new EasyGrid(),
-//         new Linker(),
-//         new CsvToTable(),
-//         new XssFilter({
-//           isEnabledXssPrevention: this.RendererConfig.isEnabledXssPrevention,
-//           tagWhiteList: this.RendererConfig.tagWhiteList,
-//           attrWhiteList: this.RendererConfig.attrWhiteList,
-//         }),
-//       ];
-//       this.postProcessors = [
-//       ];
-//     }
-
-//     this.init = this.init.bind(this);
-//     this.addConfigurers = this.addConfigurers.bind(this);
-//     this.setMarkdownSettings = this.setMarkdownSettings.bind(this);
-//     this.configure = this.configure.bind(this);
-//     this.process = this.process.bind(this);
-//     this.codeRenderer = this.codeRenderer.bind(this);
-//   }
-
-//   init() {
-//     let parser: Processor = unified().use(parse);
-//     this.remarkPlugins.forEach((item) => {
-//       parser = applyPlugin(parser, item);
-//     });
-
-//     let rehype: Processor = parser.use(remark2rehype);
-//     this.rehypePlugins.forEach((item) => {
-//       rehype = applyPlugin(rehype, item);
-//     });
-
-//     this.processor = rehype.use(rehype2react, {
-//       createElement: React.createElement,
-//       components: {
-//         // a: NextLink,
-//       },
-//     });
-//   }
-
-//   init() {
-//     // init markdown-it
-//     this.md = new MarkdownIt({
-//       html: true,
-//       linkify: true,
-//       highlight: this.codeRenderer,
-//     });
-
-//     this.isMarkdownItConfigured = false;
-
-//     this.markdownItConfigurers = [
-//       new TaskListsConfigurer(),
-//       new HeaderConfigurer(),
-//       new EmojiConfigurer(),
-//       new MathJaxConfigurer(),
-//       new DrawioViewerConfigurer(),
-//       new PlantUMLConfigurer(this.RendererConfig),
-//       new BlockdiagConfigurer(this.RendererConfig),
-//     ];
-
-//     if (this.pagePath != null) {
-//       this.markdownItConfigurers.push(
-//         new LinkerByRelativePathConfigurer(this.pagePath),
-//       );
-//     }
-//   }
-
-//   addConfigurers(configurers: any[]): void {
-//     this.markdownItConfigurers.push(...configurers);
-//   }
-
-//   setMarkdownSettings(settings: MarkdownSettings): void {
-//     this.md.set(settings);
-//   }
-
-//   configure(): void {
-//     if (!this.isMarkdownItConfigured) {
-//       this.markdownItConfigurers.forEach((configurer) => {
-//         configurer.configure(this.md);
-//       });
-//     }
-//   }
-
-//   preProcess(markdown, context) {
-//     let processed = markdown;
-//     for (let i = 0; i < this.preProcessors.length; i++) {
-//       if (!this.preProcessors[i].process) {
-//         continue;
-//       }
-//       processed = this.preProcessors[i].process(processed, context);
-//     }
-
-//     return processed;
-//   }
-
-//   process(markdown, context) {
-//     return this.md.render(markdown, context);
-//   }
-
-//   postProcess(html, context) {
-//     let processed = html;
-//     for (let i = 0; i < this.postProcessors.length; i++) {
-//       if (!this.postProcessors[i].process) {
-//         continue;
-//       }
-//       processed = this.postProcessors[i].process(processed, context);
-//     }
-
-//     return processed;
-//   }
-
-//   codeRenderer(code, langExt) {
-//     const noborder = (!this.RendererConfig.highlightJsStyleBorder) ? 'hljs-no-border' : '';
-
-//     let citeTag = '';
-//     let hljsLang = 'plaintext';
-//     let showLinenumbers = false;
-
-//     if (langExt) {
-//       // https://regex101.com/r/qGs7eZ/3
-//       const match = langExt.match(/^([^:=\n]+)?(=([^:=\n]*))?(:([^:=\n]*))?(=([^:=\n]*))?$/);
-
-//       const lang = match[1];
-//       const fileName = match[5] || null;
-//       showLinenumbers = (match[2] != null) || (match[6] != null);
-
-//       if (fileName != null) {
-//         citeTag = `<cite>${fileName}</cite>`;
-//       }
-//       if (hljs.getLanguage(lang)) {
-//         hljsLang = lang;
-//       }
-//     }
-
-//     let highlightCode = code;
-//     try {
-//       highlightCode = hljs.highlight(hljsLang, code, true).value;
-
-//       // add line numbers
-//       if (showLinenumbers) {
-//         highlightCode = hljs.lineNumbersValue((highlightCode));
-//       }
-//     }
-//     catch (err) {
-//       logger.error(err);
-//     }
-
-//     return `<pre class="hljs ${noborder}">${citeTag}<code>${highlightCode}</code></pre>`;
-//   }
-
-// }
 
 
 type SanitizePlugin = PluginTuple<[SanitizeOption]>;
 type SanitizePlugin = PluginTuple<[SanitizeOption]>;
 export type RendererOptions = Omit<ReactMarkdownOptions, 'remarkPlugins' | 'rehypePlugins' | 'components' | 'children'> & {
 export type RendererOptions = Omit<ReactMarkdownOptions, 'remarkPlugins' | 'rehypePlugins' | 'components' | 'children'> & {
@@ -290,7 +103,7 @@ const verifySanitizePlugin = (options: RendererOptions, shouldBeTheLastItem = tr
   throw new Error('The specified options does not have sanitize plugin in \'rehypePlugins\'');
   throw new Error('The specified options does not have sanitize plugin in \'rehypePlugins\'');
 };
 };
 
 
-const generateCommonOptions = (pagePath: string|undefined, config: RendererConfig): RendererOptions => {
+const generateCommonOptions = (pagePath: string|undefined): RendererOptions => {
   return {
   return {
     remarkPlugins: [
     remarkPlugins: [
       gfm,
       gfm,
@@ -319,7 +132,7 @@ export const generateViewOptions = (
     storeTocNode: (toc: HtmlElementNode) => void,
     storeTocNode: (toc: HtmlElementNode) => void,
 ): RendererOptions => {
 ): RendererOptions => {
 
 
-  const options = generateCommonOptions(pagePath, config);
+  const options = generateCommonOptions(pagePath);
 
 
   const { remarkPlugins, rehypePlugins, components } = options;
   const { remarkPlugins, rehypePlugins, components } = options;
 
 
@@ -350,9 +163,6 @@ export const generateViewOptions = (
     rehypeSanitizePlugin,
     rehypeSanitizePlugin,
     katex,
     katex,
     [toc.rehypePluginStore, { storeTocNode }],
     [toc.rehypePluginStore, { storeTocNode }],
-    // [autoLinkHeadings, {
-    //   behavior: 'append',
-    // }]
   );
   );
 
 
   // add components
   // add components
@@ -365,18 +175,6 @@ export const generateViewOptions = (
     components.table = TableWithEditButton;
     components.table = TableWithEditButton;
   }
   }
 
 
-  // // Add configurers for viewer
-  // renderer.addConfigurers([
-  //   new FooternoteConfigurer(),
-  //   new TocAndAnchorConfigurer(),
-  //   new HeaderLineNumberConfigurer(),
-  //   new HeaderWithEditLinkConfigurer(),
-  //   new TableWithHandsontableButtonConfigurer(),
-  // ]);
-
-  // renderer.setMarkdownSettings({ breaks: rendererSettings.isEnabledLinebreaks });
-  // renderer.configure();
-
   if (config.isEnabledXssPrevention) {
   if (config.isEnabledXssPrevention) {
     verifySanitizePlugin(options, false);
     verifySanitizePlugin(options, false);
   }
   }
@@ -385,14 +183,13 @@ export const generateViewOptions = (
 
 
 export const generateTocOptions = (config: RendererConfig, tocNode: HtmlElementNode | undefined): RendererOptions => {
 export const generateTocOptions = (config: RendererConfig, tocNode: HtmlElementNode | undefined): RendererOptions => {
 
 
-  const options = generateCommonOptions(undefined, config);
+  const options = generateCommonOptions(undefined);
 
 
   const { rehypePlugins } = options;
   const { rehypePlugins } = options;
 
 
   // add remark plugins
   // add remark plugins
   // remarkPlugins.push();
   // remarkPlugins.push();
 
 
-
   const rehypeSanitizePlugin: Pluggable<any[]> | (() => void) = config.isEnabledXssPrevention
   const rehypeSanitizePlugin: Pluggable<any[]> | (() => void) = config.isEnabledXssPrevention
     ? [sanitize, deepmerge(
     ? [sanitize, deepmerge(
       commonSanitizeOption,
       commonSanitizeOption,
@@ -404,9 +201,6 @@ export const generateTocOptions = (config: RendererConfig, tocNode: HtmlElementN
     [toc.rehypePluginRestore, { tocNode }],
     [toc.rehypePluginRestore, { tocNode }],
     rehypeSanitizePlugin,
     rehypeSanitizePlugin,
   );
   );
-  // renderer.rehypePlugins.push([autoLinkHeadings, {
-  //   behavior: 'append',
-  // }]);
 
 
   if (config.isEnabledXssPrevention) {
   if (config.isEnabledXssPrevention) {
     verifySanitizePlugin(options);
     verifySanitizePlugin(options);
@@ -415,7 +209,7 @@ export const generateTocOptions = (config: RendererConfig, tocNode: HtmlElementN
 };
 };
 
 
 export const generateSimpleViewOptions = (config: RendererConfig, pagePath: string, highlightKeywords?: string | string[]): RendererOptions => {
 export const generateSimpleViewOptions = (config: RendererConfig, pagePath: string, highlightKeywords?: string | string[]): RendererOptions => {
-  const options = generateCommonOptions(pagePath, config);
+  const options = generateCommonOptions(pagePath);
 
 
   const { remarkPlugins, rehypePlugins, components } = options;
   const { remarkPlugins, rehypePlugins, components } = options;
 
 
@@ -462,7 +256,7 @@ export const generateSimpleViewOptions = (config: RendererConfig, pagePath: stri
 };
 };
 
 
 export const generatePreviewOptions = (config: RendererConfig, pagePath: string): RendererOptions => {
 export const generatePreviewOptions = (config: RendererConfig, pagePath: string): RendererOptions => {
-  const options = generateCommonOptions(pagePath, config);
+  const options = generateCommonOptions(pagePath);
 
 
   const { remarkPlugins, rehypePlugins, components } = options;
   const { remarkPlugins, rehypePlugins, components } = options;
 
 
@@ -509,33 +303,6 @@ export const generatePreviewOptions = (config: RendererConfig, pagePath: string)
   return options;
   return options;
 };
 };
 
 
-export const generateOthersOptions = (config: RendererConfig): RendererOptions => {
-  const options = generateCommonOptions(undefined, config);
-  const { rehypePlugins } = options;
-
-  // renderer.addConfigurers([
-  //   new TableConfigurer(),
-  // ]);
-
-  // renderer.setMarkdownSettings({ breaks: rendererSettings.isEnabledLinebreaks });
-  // renderer.configure();
-
-  const rehypeSanitizePlugin: Pluggable<any[]> | (() => void) = config.isEnabledXssPrevention
-    ? [sanitize, deepmerge(commonSanitizeOption)]
-    : () => {};
-
-  // add rehype plugins
-  rehypePlugins.push(
-    rehypeSanitizePlugin,
-  );
-
-  if (config.isEnabledXssPrevention) {
-    verifySanitizePlugin(options);
-  }
-  return options;
-};
-
-
 // register to facade
 // register to facade
 if (isClient()) {
 if (isClient()) {
   registerGrowiFacade({
   registerGrowiFacade({

+ 0 - 26
packages/app/src/stores/renderer.tsx

@@ -2,7 +2,6 @@ import { HtmlElementNode } from 'rehype-toc';
 import useSWR, { SWRResponse } from 'swr';
 import useSWR, { SWRResponse } from 'swr';
 import useSWRImmutable from 'swr/immutable';
 import useSWRImmutable from 'swr/immutable';
 
 
-import { RendererConfig } from '~/interfaces/services/renderer';
 import {
 import {
   RendererOptions,
   RendererOptions,
   generateSimpleViewOptions, generatePreviewOptions,
   generateSimpleViewOptions, generatePreviewOptions,
@@ -17,31 +16,6 @@ import {
 import { useCurrentPagePath } from './page';
 import { useCurrentPagePath } from './page';
 import { useCurrentPageTocNode } from './ui';
 import { useCurrentPageTocNode } from './ui';
 
 
-interface ReactMarkdownOptionsGenerator {
-  (config: RendererConfig): RendererOptions
-}
-
-// The base hook with common processes
-const _useOptionsBase = (
-    rendererId: string, generator: ReactMarkdownOptionsGenerator,
-): SWRResponse<RendererOptions, Error> => {
-  const { data: rendererConfig } = useRendererConfig();
-
-  const isAllDataValid = rendererConfig != null;
-
-  const key = isAllDataValid
-    ? [rendererId, rendererConfig]
-    : null;
-
-  const swrResult = useSWRImmutable<RendererOptions, Error>(key);
-
-  if (isAllDataValid && swrResult.data == null) {
-    swrResult.mutate(generator(rendererConfig));
-  }
-
-  // call useSWRImmutable again to foce to update cache
-  return useSWRImmutable<RendererOptions, Error>(key);
-};
 
 
 export const useViewOptions = (storeTocNodeHandler: (toc: HtmlElementNode) => void): SWRResponse<RendererOptions, Error> => {
 export const useViewOptions = (storeTocNodeHandler: (toc: HtmlElementNode) => void): SWRResponse<RendererOptions, Error> => {
   const { data: currentPagePath } = useCurrentPagePath();
   const { data: currentPagePath } = useCurrentPagePath();