showdown.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. var renderer = new showdown.Converter({simplifiedAutoLink: 'true',
  2. excludeTrailingPunctuationFromURLs: 'true',
  3. strikethrough: 'true',
  4. tables: 'true',
  5. tasklists: 'true',
  6. literalMidWordUnderscores: 'true',
  7. extensions: ['headinganchor']
  8. });
  9. var toc = []; // Table of contents as a list
  10. // Parse the html's headings and construct toc[].
  11. var parseHeadings = function(html) {
  12. toc = [];
  13. var parser = new DOMParser();
  14. var htmlDoc = parser.parseFromString(html, 'text/html');
  15. var eles = htmlDoc.querySelectorAll("h1, h2, h3, h4, h5, h6");
  16. for (var i = 0; i < eles.length; ++i) {
  17. var ele = eles[i];
  18. var level = parseInt(ele.tagName.substr(1));
  19. toc.push({
  20. level: level,
  21. anchor: ele.id,
  22. title: escapeHtml(ele.textContent)
  23. });
  24. }
  25. delete parser;
  26. };
  27. var markdownToHtml = function(markdown, needToc) {
  28. var html = renderer.makeHtml(markdown);
  29. // Parse the html to init toc[].
  30. parseHeadings(html);
  31. if (needToc) {
  32. return html.replace(/<p>\[TOC\]<\/p>/ig, '<div class="vnote-toc"></div>');
  33. } else {
  34. return html;
  35. }
  36. };
  37. var mdHasTocSection = function(markdown) {
  38. var n = markdown.search(/(\n|^)\[toc\]/i);
  39. return n != -1;
  40. };
  41. var highlightCodeBlocks = function(doc,
  42. enableMermaid,
  43. enableFlowchart,
  44. enableMathJax,
  45. enablePlantUML,
  46. enableGraphviz) {
  47. var codes = doc.getElementsByTagName('code');
  48. for (var i = 0; i < codes.length; ++i) {
  49. var code = codes[i];
  50. if (code.parentElement.tagName.toLowerCase() == 'pre') {
  51. if (enableMermaid && code.classList.contains('language-mermaid')) {
  52. // Mermaid code block.
  53. continue;
  54. } else if (enableFlowchart
  55. && (code.classList.contains('language-flowchart')
  56. || code.classList.contains('language-flow'))) {
  57. // Flowchart code block.
  58. continue;
  59. } else if (enableMathJax && code.classList.contains('language-mathjax')) {
  60. // MathJax code block.
  61. continue;
  62. } else if (enablePlantUML && code.classList.contains('language-puml')) {
  63. // PlantUML code block.
  64. continue;
  65. } else if (enableGraphviz && code.classList.contains('language-dot')) {
  66. // Graphviz code block.
  67. continue;
  68. }
  69. if (listContainsRegex(code.classList, /language-.*/)) {
  70. hljs.highlightBlock(code);
  71. }
  72. }
  73. }
  74. };
  75. var updateText = function(text) {
  76. if (VAddTOC) {
  77. text = "[TOC]\n\n" + text;
  78. }
  79. startFreshRender();
  80. // There is at least one async job for MathJax.
  81. asyncJobsCount = 1;
  82. var needToc = mdHasTocSection(text);
  83. var html = markdownToHtml(text, needToc);
  84. contentDiv.innerHTML = html;
  85. handleToc(needToc);
  86. insertImageCaption();
  87. setupImageView();
  88. highlightCodeBlocks(document,
  89. VEnableMermaid,
  90. VEnableFlowchart,
  91. VEnableMathjax,
  92. VPlantUMLMode != 0,
  93. VEnableGraphviz);
  94. renderMermaid('language-mermaid');
  95. renderFlowchart(['language-flowchart', 'language-flow']);
  96. renderPlantUML('language-puml');
  97. renderGraphviz('language-dot');
  98. addClassToCodeBlock();
  99. renderCodeBlockLineNumber();
  100. // If you add new logics after handling MathJax, please pay attention to
  101. // finishLoading logic.
  102. if (VEnableMathjax) {
  103. try {
  104. MathJax.Hub.Queue(["Typeset", MathJax.Hub, contentDiv, postProcessMathJax]);
  105. } catch (err) {
  106. content.setLog("err: " + err);
  107. finishOneAsyncJob();
  108. }
  109. } else {
  110. finishOneAsyncJob();
  111. }
  112. };
  113. var highlightText = function(text, id, timeStamp) {
  114. var html = renderer.makeHtml(text);
  115. var parser = new DOMParser();
  116. var htmlDoc = parser.parseFromString("<div id=\"showdown-container\">" + html + "</div>", 'text/html');
  117. highlightCodeBlocks(htmlDoc, false, false, false, false, false);
  118. html = htmlDoc.getElementById('showdown-container').innerHTML;
  119. delete parser;
  120. content.highlightTextCB(html, id, timeStamp);
  121. }
  122. var textToHtml = function(identifier, id, timeStamp, text, inlineStyle) {
  123. var html = renderer.makeHtml(text);
  124. var parser = new DOMParser();
  125. var htmlDoc = parser.parseFromString("<div id=\"showdown-container\">" + html + "</div>", 'text/html');
  126. highlightCodeBlocks(htmlDoc, false, false, false, false, false);
  127. html = htmlDoc.getElementById('showdown-container').innerHTML;
  128. delete parser;
  129. if (inlineStyle) {
  130. var container = textHtmlDiv;
  131. container.innerHTML = html;
  132. html = getHtmlWithInlineStyles(container);
  133. container.innerHTML = "";
  134. }
  135. content.textToHtmlCB(identifier, id, timeStamp, html);
  136. }