CrowiRenderer.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import marked from 'marked';
  2. import hljs from 'highlight.js';
  3. import MarkdownFixer from './PreProcessor/MarkdownFixer';
  4. import Linker from './PreProcessor/Linker';
  5. import ImageExpander from './PreProcessor/ImageExpander';
  6. import Tsv2Table from './LangProcessor/Tsv2Table';
  7. export default class CrowiRenderer {
  8. constructor(plugins) {
  9. this.preProcessors = [
  10. new MarkdownFixer(),
  11. new Linker(),
  12. new ImageExpander(),
  13. ];
  14. this.langProcessors = {
  15. 'tsv2table': new Tsv2Table(),
  16. 'tsv2table-h': new Tsv2Table({header: true}),
  17. };
  18. this.parseMarkdown = this.parseMarkdown.bind(this);
  19. this.codeRenderer = this.codeRenderer.bind(this);
  20. }
  21. preProcess(markdown) {
  22. for (let i = 0; i < this.preProcessors.length; i++) {
  23. if (!this.preProcessors[i].process) {
  24. continue;
  25. }
  26. markdown = this.preProcessors[i].process(markdown);
  27. }
  28. return markdown;
  29. }
  30. codeRenderer(code, lang, escaped) {
  31. let result = '', hl;
  32. if (lang && this.langProcessors[lang]) {
  33. return this.langProcessors[lang].process(code);
  34. }
  35. if (lang) {
  36. try {
  37. hl = hljs.highlight(lang, code);
  38. result = hl.value;
  39. escaped = true;
  40. } catch (e) {
  41. result = code;
  42. }
  43. result = (escape ? result : Crowi.escape(result, true));
  44. return `<pre><code class="lang-${lang}">${result}\n</code></pre>\n`;
  45. }
  46. // no lang specified
  47. return `<pre><code>${Crowi.escape(code, true)}\n</code></pre>`;
  48. }
  49. parseMarkdown(markdown) {
  50. let parsed = '';
  51. const markedRenderer = new marked.Renderer();
  52. markedRenderer.code = this.codeRenderer;
  53. try {
  54. // TODO
  55. marked.setOptions({
  56. gfm: true,
  57. tables: true,
  58. breaks: true,
  59. pedantic: false,
  60. sanitize: false,
  61. smartLists: true,
  62. smartypants: false,
  63. renderer: markedRenderer,
  64. });
  65. parsed = marked(markdown);
  66. } catch (e) { console.log(e, e.stack); }
  67. return parsed;
  68. }
  69. render(markdown) {
  70. let html = '';
  71. markdown = this.preProcess(markdown);
  72. html = this.parseMarkdown(markdown);
  73. return html;
  74. }
  75. }