markdown-it.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. var nameCounter = 0;
  2. var toc = []; // Table of Content as a list
  3. var getHeadingLevel = function(h) {
  4. var level = 1;
  5. switch (h) {
  6. case 'h1':
  7. break;
  8. case 'h2':
  9. level += 1;
  10. break;
  11. case 'h3':
  12. level += 2;
  13. break;
  14. case 'h4':
  15. level += 3;
  16. break;
  17. case 'h5':
  18. level += 4;
  19. break;
  20. case 'h6':
  21. level += 5;
  22. break;
  23. default:
  24. level += 6;
  25. break;
  26. }
  27. return level;
  28. }
  29. // There is a VMarkdownitOption struct passed in.
  30. // var VMarkdownitOption = { html, breaks, linkify, sub, sup };
  31. var mdit = window.markdownit({
  32. html: VMarkdownitOption.html,
  33. breaks: VMarkdownitOption.breaks,
  34. linkify: VMarkdownitOption.linkify,
  35. typographer: false,
  36. langPrefix: 'lang-',
  37. highlight: function(str, lang) {
  38. if (lang && (!specialCodeBlock(lang) || highlightSpecialBlocks)) {
  39. if (hljs.getLanguage(lang)) {
  40. return hljs.highlight(lang, str, true).value;
  41. } else {
  42. return hljs.highlightAuto(str).value;
  43. }
  44. }
  45. // Use external default escaping.
  46. return '';
  47. }
  48. });
  49. mdit = mdit.use(window.markdownitHeadingAnchor, {
  50. anchorClass: 'vnote-anchor',
  51. addHeadingID: true,
  52. addHeadingAnchor: true,
  53. slugify: function(md, s) {
  54. return 'toc_' + nameCounter++;
  55. },
  56. headingHook: function(openToken, inlineToken, anchor) {
  57. toc.push({
  58. level: getHeadingLevel(openToken.tag),
  59. anchor: anchor,
  60. title: mdit.utils.escapeHtml(inlineToken.content)
  61. });
  62. }
  63. });
  64. // Enable file: scheme.
  65. var validateLinkMDIT = mdit.validateLink;
  66. var fileSchemeRE = /^file:/;
  67. mdit.validateLink = function(url) {
  68. var str = url.trim().toLowerCase();
  69. return fileSchemeRE.test(str) ? true : validateLinkMDIT(url);
  70. };
  71. mdit = mdit.use(window.markdownitTaskLists);
  72. if (VMarkdownitOption.sub) {
  73. mdit = mdit.use(window.markdownitSub);
  74. }
  75. if (VMarkdownitOption.sup) {
  76. mdit = mdit.use(window.markdownitSup);
  77. }
  78. var metaDataText = null;
  79. if (VMarkdownitOption.metadata) {
  80. mdit = mdit.use(window.markdownitFrontMatter, function(text){
  81. metaDataText = text;
  82. });
  83. }
  84. if (VMarkdownitOption.emoji) {
  85. mdit = mdit.use(window.markdownitEmoji);
  86. mdit.renderer.rules.emoji = function(token, idx) {
  87. return '<span class="emoji emoji_' + token[idx].markup + '">' + token[idx].content + '</span>';
  88. };
  89. }
  90. mdit = mdit.use(window.markdownitFootnote);
  91. mdit = mdit.use(window["markdown-it-imsize.js"]);
  92. if (typeof texmath != 'undefined') {
  93. mdit = mdit.use(texmath, { delimiters: ['dollars', 'raw'] });
  94. }
  95. var mdHasTocSection = function(markdown) {
  96. var n = markdown.search(/(\n|^)\[toc\]/i);
  97. return n != -1;
  98. };
  99. var markdownToHtml = function(markdown, needToc) {
  100. toc = [];
  101. nameCounter = 0;
  102. var html = mdit.render(markdown);
  103. if (needToc) {
  104. return html.replace(/<p>\[TOC\]<\/p>/ig, '<div class="vnote-toc"></div>');
  105. } else {
  106. return html;
  107. }
  108. };
  109. var updateText = function(text) {
  110. if (VAddTOC) {
  111. text = "[TOC]\n\n" + text;
  112. }
  113. startFreshRender();
  114. // There is at least one async job for MathJax.
  115. asyncJobsCount = 1;
  116. metaDataText = null;
  117. var needToc = mdHasTocSection(text);
  118. var html = markdownToHtml(text, needToc);
  119. contentDiv.innerHTML = html;
  120. handleToc(needToc);
  121. insertImageCaption();
  122. setupImageView();
  123. handleMetaData();
  124. renderMermaid('lang-mermaid');
  125. renderFlowchart(['lang-flowchart', 'lang-flow']);
  126. renderPlantUML('lang-puml');
  127. renderGraphviz('lang-dot');
  128. addClassToCodeBlock();
  129. renderCodeBlockLineNumber();
  130. // If you add new logics after handling MathJax, please pay attention to
  131. // finishLoading logic.
  132. if (VEnableMathjax) {
  133. var texToRender = document.getElementsByClassName('tex-to-render');
  134. var nrTex = texToRender.length;
  135. if (nrTex == 0) {
  136. finishOneAsyncJob();
  137. return;
  138. }
  139. var eles = [];
  140. for (var i = 0; i < nrTex; ++i) {
  141. eles.push(texToRender[i]);
  142. }
  143. try {
  144. MathJax.Hub.Queue(["resetEquationNumbers",MathJax.InputJax.TeX],
  145. ["Typeset", MathJax.Hub, eles, postProcessMathJax]);
  146. } catch (err) {
  147. content.setLog("err: " + err);
  148. finishOneAsyncJob();
  149. }
  150. } else {
  151. finishOneAsyncJob();
  152. }
  153. };
  154. var highlightText = function(text, id, timeStamp) {
  155. highlightSpecialBlocks = true;
  156. var html = mdit.render(text);
  157. highlightSpecialBlocks = false;
  158. content.highlightTextCB(html, id, timeStamp);
  159. };
  160. var textToHtml = function(identifier, id, timeStamp, text, inlineStyle) {
  161. var html = mdit.render(text);
  162. if (inlineStyle) {
  163. var container = textHtmlDiv;
  164. container.innerHTML = html;
  165. html = getHtmlWithInlineStyles(container);
  166. container.innerHTML = "";
  167. }
  168. content.textToHtmlCB(identifier, id, timeStamp, html);
  169. };
  170. // Add a PRE containing metaDataText if it is not empty.
  171. var handleMetaData = function() {
  172. if (!metaDataText || metaDataText.length == 0) {
  173. return;
  174. }
  175. var pre = document.createElement('pre');
  176. var code = document.createElement('code');
  177. code.classList.add(VMetaDataCodeClass);
  178. var text = hljs.highlight('yaml', metaDataText, true).value;
  179. code.innerHTML = text;
  180. pre.appendChild(code);
  181. contentDiv.insertAdjacentElement('afterbegin', pre);
  182. };
  183. var postProcessMathJaxWhenMathjaxReady = function() {
  184. var all = MathJax.Hub.getAllJax();
  185. for (var i = 0; i < all.length; ++i) {
  186. var node = all[i].SourceElement().parentNode;
  187. if (VRemoveMathjaxScript) {
  188. // Remove the SourceElement.
  189. try {
  190. node.removeChild(all[i].SourceElement());
  191. } catch (err) {
  192. content.setLog("err: " + err);
  193. }
  194. }
  195. if (node.tagName.toLowerCase() == 'code') {
  196. var pre = node.parentNode;
  197. var p = document.createElement('p');
  198. p.innerHTML = node.innerHTML;
  199. pre.parentNode.replaceChild(p, pre);
  200. }
  201. }
  202. };
  203. var handleMathjaxReady = function() {
  204. if (!VEnableMathjax) {
  205. return;
  206. }
  207. var texToRender = document.getElementsByClassName('tex-to-render');
  208. var nrTex = texToRender.length;
  209. if (nrTex == 0) {
  210. return;
  211. }
  212. var eles = [];
  213. for (var i = 0; i < nrTex; ++i) {
  214. eles.push(texToRender[i]);
  215. }
  216. try {
  217. MathJax.Hub.Queue(["resetEquationNumbers",MathJax.InputJax.TeX],
  218. ["Typeset", MathJax.Hub, eles, postProcessMathJaxWhenMathjaxReady]);
  219. } catch (err) {
  220. content.setLog("err: " + err);
  221. finishOneAsyncJob();
  222. }
  223. };