mermaidjs.html.j2 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. {%- macro mermaid_js(
  2. url="https://cdnjs.cloudflare.com/ajax/libs/mermaid/11.10.0/mermaid.esm.min.mjs",
  3. elk_url="https://cdnjs.cloudflare.com/ajax/libs/mermaid-layout-elk/0.1.9/mermaid-layout-elk.esm.min.mjs"
  4. ) -%}
  5. <script type="module">
  6. document.addEventListener("DOMContentLoaded", async () => {
  7. const diagrams = document.querySelectorAll(".jp-Mermaid > pre.mermaid");
  8. // do not load mermaidjs if not needed
  9. if (!diagrams.length) {
  10. return;
  11. }
  12. const mermaid = (await import("{{ url }}")).default;
  13. const elkUrl = "{{ elk_url | default('') }}";
  14. if(elkUrl) {
  15. const elkLayouts = (await import(elkUrl)).default;
  16. mermaid.registerLayoutLoaders(elkLayouts);
  17. }
  18. const parser = new DOMParser();
  19. mermaid.initialize({
  20. maxTextSize: 100000,
  21. maxEdges: 100000,
  22. startOnLoad: false,
  23. fontFamily: window
  24. .getComputedStyle(document.body)
  25. .getPropertyValue("--jp-ui-font-family"),
  26. theme: document.querySelector("body[data-jp-theme-light='true']")
  27. ? "default"
  28. : "dark",
  29. });
  30. let _nextMermaidId = 0;
  31. function makeMermaidImage(svg) {
  32. const img = document.createElement("img");
  33. const doc = parser.parseFromString(svg, "image/svg+xml");
  34. const svgEl = doc.querySelector("svg");
  35. const { maxWidth } = svgEl?.style || {};
  36. const firstTitle = doc.querySelector("title");
  37. const firstDesc = doc.querySelector("desc");
  38. img.setAttribute("src", `data:image/svg+xml,${encodeURIComponent(svg)}`);
  39. if (maxWidth) {
  40. img.width = parseInt(maxWidth);
  41. }
  42. if (firstTitle) {
  43. img.setAttribute("alt", firstTitle.textContent);
  44. }
  45. if (firstDesc) {
  46. const caption = document.createElement("figcaption");
  47. caption.className = "sr-only";
  48. caption.textContent = firstDesc.textContent;
  49. return [img, caption];
  50. }
  51. return [img];
  52. }
  53. async function makeMermaidError(text) {
  54. let errorMessage = "";
  55. try {
  56. await mermaid.parse(text);
  57. } catch (err) {
  58. errorMessage = `${err}`;
  59. }
  60. const result = document.createElement("details");
  61. result.className = 'jp-RenderedMermaid-Details';
  62. const summary = document.createElement("summary");
  63. summary.className = 'jp-RenderedMermaid-Summary';
  64. const pre = document.createElement("pre");
  65. const code = document.createElement("code");
  66. code.innerText = text;
  67. pre.appendChild(code);
  68. summary.appendChild(pre);
  69. result.appendChild(summary);
  70. const warning = document.createElement("pre");
  71. warning.innerText = errorMessage;
  72. result.appendChild(warning);
  73. return [result];
  74. }
  75. async function renderOneMarmaid(src) {
  76. const id = `jp-mermaid-${_nextMermaidId++}`;
  77. const parent = src.parentNode;
  78. let raw = src.textContent.trim();
  79. const el = document.createElement("div");
  80. el.style.visibility = "hidden";
  81. document.body.appendChild(el);
  82. let results = null;
  83. let output = null;
  84. try {
  85. let { svg } = await mermaid.render(id, raw, el);
  86. svg = cleanMermaidSvg(svg);
  87. results = makeMermaidImage(svg);
  88. output = document.createElement("figure");
  89. results.map(output.appendChild, output);
  90. } catch (err) {
  91. parent.classList.add("jp-mod-warning");
  92. results = await makeMermaidError(raw);
  93. output = results[0];
  94. } finally {
  95. el.remove();
  96. }
  97. parent.classList.add("jp-RenderedMermaid");
  98. parent.appendChild(output);
  99. }
  100. /**
  101. * Post-process to ensure mermaid diagrams contain only valid SVG and XHTML.
  102. */
  103. function cleanMermaidSvg(svg) {
  104. svg = svg.replace(RE_VOID_ELEMENT, replaceVoidElement);
  105. return `${SVG_XML_HEADER}${svg}`;
  106. }
  107. /**
  108. * A regular expression for all void elements, which may include attributes and
  109. * a slash.
  110. *
  111. * @see https://developer.mozilla.org/en-US/docs/Glossary/Void_element
  112. *
  113. * Of these, only `<br>` is generated by Mermaid in place of `\n`,
  114. * but _any_ "malformed" tag will break the SVG rendering entirely.
  115. */
  116. const RE_VOID_ELEMENT =
  117. /<\s*(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)\s*([^>]*?)\s*>/gi;
  118. /**
  119. * Ensure a void element is closed with a slash, preserving any attributes.
  120. */
  121. function replaceVoidElement(match, tag, rest) {
  122. rest = rest.trim();
  123. if (!rest.endsWith('/')) {
  124. rest = `${rest} /`;
  125. }
  126. return `<${tag} ${rest}>`;
  127. }
  128. /**
  129. * Named HTML entities with their decimal equivalent codes.
  130. *
  131. * @see https://www.w3.org/TR/WD-html40-970708/sgml/entities.html
  132. * */
  133. const HTML_ENTITIES = `<!ENTITY Aacute "&#193;">
  134. <!ENTITY aacute "&#225;">
  135. <!ENTITY Acirc "&#194;">
  136. <!ENTITY acirc "&#226;">
  137. <!ENTITY acute "&#180;">
  138. <!ENTITY AElig "&#198;">
  139. <!ENTITY aelig "&#230;">
  140. <!ENTITY Agrave "&#192;">
  141. <!ENTITY agrave "&#224;">
  142. <!ENTITY alefsym "&#8501;">
  143. <!ENTITY Alpha "&#913;">
  144. <!ENTITY alpha "&#945;">
  145. <!ENTITY amp "&#38;">
  146. <!ENTITY and "&#8869;">
  147. <!ENTITY ang "&#8736;">
  148. <!ENTITY Aring "&#197;">
  149. <!ENTITY aring "&#229;">
  150. <!ENTITY asymp "&#8776;">
  151. <!ENTITY Atilde "&#195;">
  152. <!ENTITY atilde "&#227;">
  153. <!ENTITY Auml "&#196;">
  154. <!ENTITY auml "&#228;">
  155. <!ENTITY bdquo "&#8222;">
  156. <!ENTITY Beta "&#914;">
  157. <!ENTITY beta "&#946;">
  158. <!ENTITY brvbar "&#166;">
  159. <!ENTITY bull "&#8226;">
  160. <!ENTITY cap "&#8745;">
  161. <!ENTITY Ccedil "&#199;">
  162. <!ENTITY ccedil "&#231;">
  163. <!ENTITY cedil "&#184;">
  164. <!ENTITY cent "&#162;">
  165. <!ENTITY Chi "&#935;">
  166. <!ENTITY chi "&#967;">
  167. <!ENTITY circ "&#710;">
  168. <!ENTITY clubs "&#9827;">
  169. <!ENTITY cong "&#8773;">
  170. <!ENTITY copy "&#169;">
  171. <!ENTITY crarr "&#8629;">
  172. <!ENTITY cup "&#8746;">
  173. <!ENTITY curren "&#164;">
  174. <!ENTITY dagger "&#8224;">
  175. <!ENTITY Dagger "&#8225;">
  176. <!ENTITY darr "&#8595;">
  177. <!ENTITY dArr "&#8659;">
  178. <!ENTITY deg "&#176;">
  179. <!ENTITY Delta "&#916;">
  180. <!ENTITY delta "&#948;">
  181. <!ENTITY diams "&#9830;">
  182. <!ENTITY divide "&#247;">
  183. <!ENTITY Eacute "&#201;">
  184. <!ENTITY eacute "&#233;">
  185. <!ENTITY Ecirc "&#202;">
  186. <!ENTITY ecirc "&#234;">
  187. <!ENTITY Egrave "&#200;">
  188. <!ENTITY egrave "&#232;">
  189. <!ENTITY empty "&#8709;">
  190. <!ENTITY emsp "&#8195;">
  191. <!ENTITY ensp "&#8194;">
  192. <!ENTITY epsilon "&#949;">
  193. <!ENTITY Epsilon "&#917;">
  194. <!ENTITY equiv "&#8801;">
  195. <!ENTITY Eta "&#919;">
  196. <!ENTITY eta "&#951;">
  197. <!ENTITY ETH "&#208;">
  198. <!ENTITY eth "&#240;">
  199. <!ENTITY Euml "&#203;">
  200. <!ENTITY euml "&#235;">
  201. <!ENTITY exist "&#8707;">
  202. <!ENTITY fnof "&#402;">
  203. <!ENTITY forall "&#8704;">
  204. <!ENTITY frac12 "&#189;">
  205. <!ENTITY frac14 "&#188;">
  206. <!ENTITY frac34 "&#190;">
  207. <!ENTITY frasl "&#8260;">
  208. <!ENTITY Gamma "&#915;">
  209. <!ENTITY gamma "&#947;">
  210. <!ENTITY ge "&#8805;">
  211. <!ENTITY gt "&#62;">
  212. <!ENTITY harr "&#8596;">
  213. <!ENTITY hArr "&#8660;">
  214. <!ENTITY hearts "&#9829;">
  215. <!ENTITY hellip "&#8230;">
  216. <!ENTITY Iacute "&#205;">
  217. <!ENTITY iacute "&#237;">
  218. <!ENTITY Icirc "&#206;">
  219. <!ENTITY icirc "&#238;">
  220. <!ENTITY iexcl "&#161;">
  221. <!ENTITY Igrave "&#204;">
  222. <!ENTITY igrave "&#236;">
  223. <!ENTITY image "&#8465;">
  224. <!ENTITY infin "&#8734;">
  225. <!ENTITY int "&#8747;">
  226. <!ENTITY Iota "&#921;">
  227. <!ENTITY iota "&#953;">
  228. <!ENTITY iquest "&#191;">
  229. <!ENTITY isin "&#8712;">
  230. <!ENTITY Iuml "&#207;">
  231. <!ENTITY iuml "&#239;">
  232. <!ENTITY Kappa "&#922;">
  233. <!ENTITY kappa "&#954;">
  234. <!ENTITY Lambda "&#923;">
  235. <!ENTITY lambda "&#955;">
  236. <!ENTITY lang "&#9001;">
  237. <!ENTITY laquo "&#171;">
  238. <!ENTITY larr "&#8592;">
  239. <!ENTITY lArr "&#8656;">
  240. <!ENTITY lceil "&#8968;">
  241. <!ENTITY ldquo "&#8220;">
  242. <!ENTITY le "&#8804;">
  243. <!ENTITY lfloor "&#8970;">
  244. <!ENTITY lowast "&#8727;">
  245. <!ENTITY loz "&#9674;">
  246. <!ENTITY lrm "&#8206;">
  247. <!ENTITY lsaquo "&#8249;">
  248. <!ENTITY lsquo "&#8216;">
  249. <!ENTITY lt "&#60;">
  250. <!ENTITY macr "&#175;">
  251. <!ENTITY mdash "&#8212;">
  252. <!ENTITY micro "&#181;">
  253. <!ENTITY middot "&#183;">
  254. <!ENTITY minus "&#8722;">
  255. <!ENTITY Mu "&#924;">
  256. <!ENTITY mu "&#956;">
  257. <!ENTITY nabla "&#8711;">
  258. <!ENTITY nbsp "&#160;">
  259. <!ENTITY ndash "&#8211;">
  260. <!ENTITY ne "&#8800;">
  261. <!ENTITY ni "&#8715;">
  262. <!ENTITY not "&#172;">
  263. <!ENTITY notin "&#8713;">
  264. <!ENTITY nsub "&#8836;">
  265. <!ENTITY Ntilde "&#209;">
  266. <!ENTITY ntilde "&#241;">
  267. <!ENTITY Nu "&#925;">
  268. <!ENTITY nu "&#957;">
  269. <!ENTITY Oacute "&#211;">
  270. <!ENTITY oacute "&#243;">
  271. <!ENTITY Ocirc "&#212;">
  272. <!ENTITY ocirc "&#244;">
  273. <!ENTITY OElig "&#338;">
  274. <!ENTITY oelig "&#339;">
  275. <!ENTITY Ograve "&#210;">
  276. <!ENTITY ograve "&#242;">
  277. <!ENTITY oline "&#8254;">
  278. <!ENTITY Omega "&#937;">
  279. <!ENTITY omega "&#969;">
  280. <!ENTITY Omicron "&#927;">
  281. <!ENTITY omicron "&#959;">
  282. <!ENTITY oplus "&#8853;">
  283. <!ENTITY or "&#8870;">
  284. <!ENTITY ordf "&#170;">
  285. <!ENTITY ordm "&#186;">
  286. <!ENTITY Oslash "&#216;">
  287. <!ENTITY oslash "&#248;">
  288. <!ENTITY Otilde "&#213;">
  289. <!ENTITY otilde "&#245;">
  290. <!ENTITY otimes "&#8855;">
  291. <!ENTITY Ouml "&#214;">
  292. <!ENTITY ouml "&#246;">
  293. <!ENTITY para "&#182;">
  294. <!ENTITY part "&#8706;">
  295. <!ENTITY permil "&#8240;">
  296. <!ENTITY perp "&#8869;">
  297. <!ENTITY Phi "&#934;">
  298. <!ENTITY phi "&#966;">
  299. <!ENTITY Pi "&#928;">
  300. <!ENTITY pi "&#960;">
  301. <!ENTITY piv "&#982;">
  302. <!ENTITY plusmn "&#177;">
  303. <!ENTITY pound "&#163;">
  304. <!ENTITY prime "&#8242;">
  305. <!ENTITY Prime "&#8243;">
  306. <!ENTITY prod "&#8719;">
  307. <!ENTITY prop "&#8733;">
  308. <!ENTITY Psi "&#936;">
  309. <!ENTITY psi "&#968;">
  310. <!ENTITY quot "&#34;">
  311. <!ENTITY radic "&#8730;">
  312. <!ENTITY rang "&#9002;">
  313. <!ENTITY raquo "&#187;">
  314. <!ENTITY rarr "&#8594;">
  315. <!ENTITY rArr "&#8658;">
  316. <!ENTITY rceil "&#8969;">
  317. <!ENTITY rdquo "&#8221;">
  318. <!ENTITY real "&#8476;">
  319. <!ENTITY reg "&#174;">
  320. <!ENTITY rfloor "&#8971;">
  321. <!ENTITY Rho "&#929;">
  322. <!ENTITY rho "&#961;">
  323. <!ENTITY rlm "&#8207;">
  324. <!ENTITY rsaquo "&#8250;">
  325. <!ENTITY rsquo "&#8217;">
  326. <!ENTITY sbquo "&#8218;">
  327. <!ENTITY Scaron "&#352;">
  328. <!ENTITY scaron "&#353;">
  329. <!ENTITY sdot "&#8901;">
  330. <!ENTITY sect "&#167;">
  331. <!ENTITY shy "&#173;">
  332. <!ENTITY Sigma "&#931;">
  333. <!ENTITY sigma "&#963;">
  334. <!ENTITY sigmaf "&#962;">
  335. <!ENTITY sim "&#8764;">
  336. <!ENTITY spades "&#9824;">
  337. <!ENTITY sub "&#8834;">
  338. <!ENTITY sube "&#8838;">
  339. <!ENTITY sum "&#8721;">
  340. <!ENTITY sup "&#8835;">
  341. <!ENTITY sup1 "&#185;">
  342. <!ENTITY sup2 "&#178;">
  343. <!ENTITY sup3 "&#179;">
  344. <!ENTITY supe "&#8839;">
  345. <!ENTITY szlig "&#223;">
  346. <!ENTITY Tau "&#932;">
  347. <!ENTITY tau "&#964;">
  348. <!ENTITY there4 "&#8756;">
  349. <!ENTITY Theta "&#920;">
  350. <!ENTITY theta "&#952;">
  351. <!ENTITY thetasym "&#977;">
  352. <!ENTITY thinsp "&#8201;">
  353. <!ENTITY THORN "&#222;">
  354. <!ENTITY thorn "&#254;">
  355. <!ENTITY tilde "&#732;">
  356. <!ENTITY times "&#215;">
  357. <!ENTITY trade "&#8482;">
  358. <!ENTITY Uacute "&#218;">
  359. <!ENTITY uacute "&#250;">
  360. <!ENTITY uarr "&#8593;">
  361. <!ENTITY uArr "&#8657;">
  362. <!ENTITY Ucirc "&#219;">
  363. <!ENTITY ucirc "&#251;">
  364. <!ENTITY Ugrave "&#217;">
  365. <!ENTITY ugrave "&#249;">
  366. <!ENTITY uml "&#168;">
  367. <!ENTITY upsih "&#978;">
  368. <!ENTITY Upsilon "&#933;">
  369. <!ENTITY upsilon "&#965;">
  370. <!ENTITY Uuml "&#220;">
  371. <!ENTITY uuml "&#252;">
  372. <!ENTITY weierp "&#8472;">
  373. <!ENTITY Xi "&#926;">
  374. <!ENTITY xi "&#958;">
  375. <!ENTITY Yacute "&#221;">
  376. <!ENTITY yacute "&#253;">
  377. <!ENTITY yen "&#165;">
  378. <!ENTITY Yuml "&#376;">
  379. <!ENTITY yuml "&#255;">
  380. <!ENTITY Zeta "&#918;">
  381. <!ENTITY zeta "&#950;">
  382. <!ENTITY zwj "&#8205;">
  383. <!ENTITY zwnj "&#8204;">`.replace(/\n/g, ' ');
  384. /**
  385. * A reasonably strict xml declaration.
  386. */
  387. const XML_DECL = '<?xml version="1.0" standalone="no"?>';
  388. /**
  389. * The beginning of the XML doctype declaration.
  390. */
  391. const DOCTYPE_START = `<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [`;
  392. /**
  393. * The end of the XML docype declaration.
  394. */
  395. const DOCTYPE_END = ']>';
  396. /**
  397. * A full header for an SVG XML document.
  398. */
  399. const SVG_XML_HEADER = `${XML_DECL}
  400. ${DOCTYPE_START}${HTML_ENTITIES}${DOCTYPE_END}`;
  401. void Promise.all([...diagrams].map(renderOneMarmaid));
  402. });
  403. </script>
  404. <style>
  405. .jp-Mermaid:not(.jp-RenderedMermaid) {
  406. display: none;
  407. }
  408. .jp-RenderedMermaid {
  409. overflow: auto;
  410. display: flex;
  411. }
  412. .jp-RenderedMermaid.jp-mod-warning {
  413. width: auto;
  414. padding: 0.5em;
  415. margin-top: 0.5em;
  416. border: var(--jp-border-width) solid var(--jp-warn-color2);
  417. border-radius: var(--jp-border-radius);
  418. color: var(--jp-ui-font-color1);
  419. font-size: var(--jp-ui-font-size1);
  420. white-space: pre-wrap;
  421. word-wrap: break-word;
  422. }
  423. .jp-RenderedMermaid figure {
  424. margin: 0;
  425. overflow: auto;
  426. max-width: 100%;
  427. }
  428. .jp-RenderedMermaid img {
  429. max-width: 100%;
  430. }
  431. .jp-RenderedMermaid-Details > pre {
  432. margin-top: 1em;
  433. }
  434. .jp-RenderedMermaid-Summary {
  435. color: var(--jp-warn-color2);
  436. }
  437. .jp-RenderedMermaid:not(.jp-mod-warning) pre {
  438. display: none;
  439. }
  440. .jp-RenderedMermaid-Summary > pre {
  441. display: inline-block;
  442. white-space: normal;
  443. }
  444. </style>
  445. <!-- End of mermaid configuration -->
  446. {%- endmacro %}