2
0

GrowiRenderer.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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, option) {
  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.langProcessors = {
  26. 'template': new Template(crowi),
  27. };
  28. this.configure = this.configure.bind(this);
  29. this.configureMarkdownIt = this.configureMarkdownIt.bind(this);
  30. this.process = this.process.bind(this);
  31. this.codeRenderer = this.codeRenderer.bind(this);
  32. this.md = new MarkdownIt();
  33. this.configure(this.crowi.getConfig());
  34. this.configureMarkdownIt(option);
  35. }
  36. configureMarkdownIt(option) {
  37. const crowi = this.crowi;
  38. let configurers = [
  39. new CommonPluginsConfigurer(crowi),
  40. new HeaderConfigurer(crowi),
  41. new TableConfigurer(crowi),
  42. new EmojiConfigurer(crowi),
  43. new MathJaxConfigurer(crowi),
  44. new PlantUMLConfigurer(crowi),
  45. ];
  46. if (option != null) {
  47. const mode = option.mode;
  48. switch (mode) {
  49. case 'page':
  50. configurers = configurers.concat([
  51. new TocAndAnchorConfigurer(crowi, option.renderToc),
  52. new HeaderLineNumberConfigurer(crowi),
  53. ]);
  54. break;
  55. case 'editor':
  56. configurers = configurers.concat([
  57. new HeaderLineNumberConfigurer(crowi)
  58. ]);
  59. break;
  60. case 'timeline':
  61. break;
  62. case 'searchresult':
  63. break;
  64. }
  65. }
  66. configurers.forEach((configurer) => {
  67. configurer.configure(this.md);
  68. });
  69. }
  70. /**
  71. * configure with crowi config
  72. * @param {any} config
  73. */
  74. configure(config) {
  75. this.md.set({
  76. html: true,
  77. linkify: true,
  78. breaks: config.isEnabledLineBreaks,
  79. highlight: this.codeRenderer,
  80. });
  81. }
  82. preProcess(markdown) {
  83. for (let i = 0; i < this.preProcessors.length; i++) {
  84. if (!this.preProcessors[i].process) {
  85. continue;
  86. }
  87. markdown = this.preProcessors[i].process(markdown);
  88. }
  89. return markdown;
  90. }
  91. process(markdown) {
  92. return this.md.render(markdown);
  93. }
  94. postProcess(html, dom) {
  95. for (let i = 0; i < this.postProcessors.length; i++) {
  96. if (!this.postProcessors[i].process) {
  97. continue;
  98. }
  99. html = this.postProcessors[i].process(html, dom);
  100. }
  101. return html;
  102. }
  103. codeRenderer(code, langExt) {
  104. if (langExt) {
  105. const langAndFn = langExt.split(':');
  106. const lang = langAndFn[0];
  107. const langFn = langAndFn[1] || null;
  108. // process langProcessors
  109. if (this.langProcessors[lang] != null) {
  110. return this.langProcessors[lang].process(code, langExt);
  111. }
  112. if (hljs.getLanguage(lang)) {
  113. let citeTag = (langFn) ? `<cite>${langFn}</cite>` : '';
  114. try {
  115. return `<pre class="hljs">${citeTag}<code class="language-${lang}">${hljs.highlight(lang, code, true).value}</code></pre>`;
  116. } catch (__) {}
  117. }
  118. }
  119. return '';
  120. }
  121. }