GrowiRenderer.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import MarkdownIt from 'markdown-it';
  2. import * as entities from 'entities';
  3. import Linker from './PreProcessor/Linker';
  4. import CsvToTable from './PreProcessor/CsvToTable';
  5. import XssFilter from './PreProcessor/XssFilter';
  6. import Template from './LangProcessor/Template';
  7. import CommonPluginsConfigurer from './markdown-it/common-plugins';
  8. import EmojiConfigurer from './markdown-it/emoji';
  9. import HeaderLineNumberConfigurer from './markdown-it/header-line-number';
  10. import HeaderConfigurer from './markdown-it/header';
  11. import MathJaxConfigurer from './markdown-it/mathjax';
  12. import PlantUMLConfigurer from './markdown-it/plantuml';
  13. import TableConfigurer from './markdown-it/table';
  14. import TocAndAnchorConfigurer from './markdown-it/toc-and-anchor';
  15. export default class GrowiRenderer {
  16. constructor(crowi) {
  17. this.crowi = crowi;
  18. this.preProcessors = [
  19. new Linker(crowi),
  20. new CsvToTable(crowi),
  21. new XssFilter(crowi),
  22. ];
  23. this.postProcessors = [
  24. ];
  25. this.markdownItConfigurers = [
  26. new CommonPluginsConfigurer(crowi),
  27. new TocAndAnchorConfigurer(crowi),
  28. new HeaderConfigurer(crowi),
  29. new HeaderLineNumberConfigurer(crowi),
  30. new TableConfigurer(crowi),
  31. new EmojiConfigurer(crowi),
  32. new MathJaxConfigurer(crowi),
  33. new PlantUMLConfigurer(crowi),
  34. ];
  35. this.langProcessors = {
  36. 'template': new Template(crowi),
  37. };
  38. this.configure = this.configure.bind(this);
  39. this.configurePlugins = this.configurePlugins.bind(this);
  40. this.parseMarkdown = this.parseMarkdown.bind(this);
  41. this.codeRenderer = this.codeRenderer.bind(this);
  42. this.md = new MarkdownIt();
  43. this.configure(this.crowi.getConfig());
  44. this.configurePlugins(this.crowi.getConfig());
  45. }
  46. /**
  47. * configure markdown-it
  48. * @param {any} config
  49. */
  50. configure(config) {
  51. this.md.set({
  52. html: true,
  53. linkify: true,
  54. breaks: config.isEnabledLineBreaks,
  55. highlight: this.codeRenderer,
  56. });
  57. }
  58. /**
  59. * configure markdown-it plugins
  60. * @param {any} config
  61. */
  62. configurePlugins(config) {
  63. this.markdownItConfigurers.forEach((configurer) => {
  64. configurer.configure(this.md);
  65. });
  66. }
  67. preProcess(markdown) {
  68. for (let i = 0; i < this.preProcessors.length; i++) {
  69. if (!this.preProcessors[i].process) {
  70. continue;
  71. }
  72. markdown = this.preProcessors[i].process(markdown);
  73. }
  74. return markdown;
  75. }
  76. postProcess(html, dom) {
  77. for (let i = 0; i < this.postProcessors.length; i++) {
  78. if (!this.postProcessors[i].process) {
  79. continue;
  80. }
  81. html = this.postProcessors[i].process(html, dom);
  82. }
  83. return html;
  84. }
  85. codeRenderer(code, langExt) {
  86. if (langExt) {
  87. const langAndFn = langExt.split(':');
  88. const lang = langAndFn[0];
  89. const langFn = langAndFn[1] || null;
  90. // process langProcessors
  91. if (this.langProcessors[lang] != null) {
  92. return this.langProcessors[lang].process(code, langExt);
  93. }
  94. if (hljs.getLanguage(lang)) {
  95. let citeTag = (langFn) ? `<cite>${langFn}</cite>` : '';
  96. try {
  97. return `<pre class="hljs">${citeTag}<code class="language-${lang}">${hljs.highlight(lang, code, true).value}</code></pre>`;
  98. } catch (__) {}
  99. }
  100. }
  101. return '';
  102. }
  103. parseMarkdown(markdown, dom, markedOpts) {
  104. let parsed = '';
  105. parsed = this.md.render(markdown);
  106. return parsed;
  107. }
  108. /**
  109. * render
  110. *
  111. * @param {string} markdown
  112. * @param {Element} dom
  113. * @returns
  114. *
  115. * @memberOf CrowiRenderer
  116. */
  117. render(markdown, dom) {
  118. let html = '';
  119. html = this.parseMarkdown(markdown, dom);
  120. html = this.postProcess(html, dom);
  121. return html;
  122. }
  123. }