Browse Source

feat: mermaid support for markdown

pull/1641/head
NGPixel 4 years ago
parent
commit
1d16a3fc71
5 changed files with 163 additions and 3 deletions
  1. 22
      client/components/editor/editor-markdown.vue
  2. 7
      client/themes/default/components/page.vue
  3. 1
      package.json
  4. 5
      server/modules/rendering/html-mermaid/renderer.js
  5. 131
      yarn.lock

22
client/components/editor/editor-markdown.vue

@ -222,6 +222,9 @@ import twemoji from 'twemoji'
// Prism (Syntax Highlighting)
import Prism from 'prismjs'
// Mermaid
import mermaid from 'mermaid'
// Helpers
import katexHelper from './common/katex'
@ -331,6 +334,8 @@ md.renderer.rules.emoji = (token, idx) => {
// Vue Component
// ========================================
let mermaidId = 0
export default {
components: {
markdownHelp
@ -367,6 +372,7 @@ export default {
previewShown (newValue, oldValue) {
if (newValue && !oldValue) {
this.$nextTick(() => {
this.renderMermaidDiagrams()
Prism.highlightAllUnder(this.$refs.editorPreview)
Array.from(this.$refs.editorPreview.querySelectorAll('pre.line-numbers')).forEach(pre => pre.classList.add('prismjs'))
})
@ -387,6 +393,7 @@ export default {
this.$store.set('editor/content', newContent)
this.previewHTML = md.render(newContent)
this.$nextTick(() => {
this.renderMermaidDiagrams()
Prism.highlightAllUnder(this.$refs.editorPreview)
Array.from(this.$refs.editorPreview.querySelectorAll('pre.line-numbers')).forEach(pre => pre.classList.add('prismjs'))
this.scrollSync(this.cm)
@ -528,6 +535,15 @@ export default {
this.$nextTick(() => {
this.cm.refresh()
})
},
renderMermaidDiagrams () {
document.querySelectorAll('.editor-markdown-preview pre.line-numbers > code.language-mermaid').forEach(elm => {
mermaidId++
const mermaidDef = elm.innerText
const mmElm = document.createElement('div')
mmElm.innerHTML = `<div id="mermaid-id-${mermaidId}">${mermaid.render(`mermaid-id-${mermaidId}`, mermaidDef)}</div>`
elm.parentElement.replaceWith(mmElm)
})
}
},
mounted() {
@ -537,6 +553,12 @@ export default {
this.$store.set('editor/content', '# Header\nYour content here')
}
// Initialize Mermaid API
mermaid.initialize({
startOnLoad: false,
theme: this.$vuetify.theme.dark ? `dark` : `default`
})
// Initialize CodeMirror
this.cm = CodeMirror.fromTextArea(this.$refs.cm, {

7
client/themes/default/components/page.vue

@ -249,6 +249,7 @@
<script>
import { StatusIndicator } from 'vue-status-indicator'
import Prism from 'prismjs'
import mermaid from 'mermaid'
import { get } from 'vuex-pathify'
import _ from 'lodash'
import ClipboardJS from 'clipboard'
@ -432,6 +433,12 @@ export default {
// -> Highlight Code Blocks
Prism.highlightAllUnder(this.$refs.container)
// -> Render Mermaid diagrams
mermaid.mermaidAPI.initialize({
startOnLoad: true,
theme: this.$vuetify.theme.dark ? `dark` : `default`
})
// -> Handle anchor scrolling
this.$nextTick(() => {
if (window.location.hash && window.location.hash.length > 1) {

1
package.json

@ -248,6 +248,7 @@
"ignore-loader": "0.1.2",
"jest": "25.1.0",
"js-cookie": "2.2.1",
"mermaid": "8.4.8",
"mini-css-extract-plugin": "0.9.0",
"moment-duration-format": "2.3.2",
"offline-plugin": "5.0.7",

5
server/modules/rendering/html-mermaid/renderer.js

@ -1,5 +1,8 @@
module.exports = {
init($, config) {
$('pre.prismjs > code.language-mermaid').each((i, elm) => {
const mermaidContent = $(elm).html()
$(elm).parent().replaceWith(`<div class="mermaid">${mermaidContent}</div>`)
})
}
}

131
yarn.lock

@ -1662,6 +1662,11 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@braintree/sanitize-url@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-3.1.0.tgz#8ff71d51053cd5ee4981e5a501d80a536244f7fd"
integrity sha512-GcIY79elgB+azP74j8vqkiXz8xLFfIzbQJdlwOPisgbKT00tviJQuEghOXSMVxJ00HoYJbGswr4kcllUc4xCcg==
"@bugsnag/browser@^6.5.2":
version "6.5.2"
resolved "https://registry.yarnpkg.com/@bugsnag/browser/-/browser-6.5.2.tgz#3f8f911dd739d2ace056fd5a38d5d25283ca4bfc"
@ -4551,7 +4556,7 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
clean-css@4.2.3:
clean-css@4.2.3, clean-css@^4.1.6:
version "4.2.3"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78"
integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==
@ -5190,6 +5195,18 @@ crypto-browserify@^3.11.0:
randombytes "^2.0.0"
randomfill "^1.0.3"
crypto-random-string@^3.0.1:
version "3.2.0"
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-3.2.0.tgz#d513ef0c2ac6ff7cad5769de585d9bf2ad5a2b4d"
integrity sha512-8vPu5bsKaq2uKRy3OL7h1Oo7RayAWB8sYexLKAqvCXVib8SxgbmoF1IN4QMKjBv8uI8mp5gPPMbiRah25GMrVQ==
dependencies:
type-fest "^0.8.1"
css-b64-images@~0.2.5:
version "0.2.5"
resolved "https://registry.yarnpkg.com/css-b64-images/-/css-b64-images-0.2.5.tgz#42005d83204b2b4a5d93b6b1a5644133b5927a02"
integrity sha1-QgBdgyBLK0pdk7axpWRBM7WSegI=
css-blank-pseudo@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5"
@ -5659,7 +5676,7 @@ d3-zoom@1:
d3-selection "1"
d3-transition "1"
d3@5.15.0:
d3@5.15.0, d3@^5.14, d3@^5.7.0:
version "5.15.0"
resolved "https://registry.yarnpkg.com/d3/-/d3-5.15.0.tgz#ffd44958e6a3cb8a59a84429c45429b8bca5677a"
integrity sha512-C+E80SL2nLLtmykZ6klwYj5rPqB5nlfN5LdWEAVdWPppqTD8taoJi2PxLZjPeYT8FFRR2yucXq+kBlOnnvZeLg==
@ -5704,6 +5721,24 @@ d@1, d@^1.0.1:
es5-ext "^0.10.50"
type "^1.0.1"
dagre-d3@^0.6.4:
version "0.6.4"
resolved "https://registry.yarnpkg.com/dagre-d3/-/dagre-d3-0.6.4.tgz#0728d5ce7f177ca2337df141ceb60fbe6eeb7b29"
integrity sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==
dependencies:
d3 "^5.14"
dagre "^0.8.5"
graphlib "^2.1.8"
lodash "^4.17.15"
dagre@^0.8.4, dagre@^0.8.5:
version "0.8.5"
resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee"
integrity sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==
dependencies:
graphlib "^2.1.8"
lodash "^4.17.15"
dashdash@^1.12.0, dashdash@^1.14.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
@ -6384,6 +6419,11 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
escaper@^2.5.3:
version "2.5.3"
resolved "https://registry.yarnpkg.com/escaper/-/escaper-2.5.3.tgz#8b8fe90ba364054151ab7eff18b4ce43b1e13ab5"
integrity sha512-QGb9sFxBVpbzMggrKTX0ry1oiI4CSDAl9vIL702hzl1jGW8VZs7qfqTRX7WDOjoNDoEVGcEtu1ZOQgReSfT2kQ==
escodegen@^1.11.1:
version "1.13.0"
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.13.0.tgz#c7adf9bd3f3cc675bb752f202f79a720189cab29"
@ -7448,6 +7488,13 @@ graceful-fs@^4.2.3:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
graphlib@^2.1.7, graphlib@^2.1.8:
version "2.1.8"
resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da"
integrity sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==
dependencies:
lodash "^4.17.15"
graphql-anywhere@^3.0.1:
version "3.1.0"
resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-3.1.0.tgz#3ea0d8e8646b5cee68035016a9a7557c15c21e96"
@ -8393,6 +8440,11 @@ is-regex@^1.0.3, is-regex@^1.0.4:
dependencies:
has "^1.0.1"
is-regexp@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk=
is-relative@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d"
@ -9849,6 +9901,23 @@ merge-stream@^2.0.0:
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
mermaid@8.4.8:
version "8.4.8"
resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-8.4.8.tgz#8adcfdbc505d6bca52df167cff690427c9727b60"
integrity sha512-sumTNBFwMX7oMQgogdr3NhgTeQOiwcEsm23rQ4KHGW7tpmvMwER1S+1gjCSSnqlmM/zw7Ga7oesYCYicKboRwQ==
dependencies:
"@braintree/sanitize-url" "^3.1.0"
crypto-random-string "^3.0.1"
d3 "^5.7.0"
dagre "^0.8.4"
dagre-d3 "^0.6.4"
graphlib "^2.1.7"
he "^1.2.0"
lodash "^4.17.11"
minify "^4.1.1"
moment-mini "^2.22.1"
scope-css "^1.2.1"
methods@^1.1.1, methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
@ -9953,6 +10022,19 @@ mini-css-extract-plugin@0.9.0:
schema-utils "^1.0.0"
webpack-sources "^1.1.0"
minify@^4.1.1:
version "4.1.3"
resolved "https://registry.yarnpkg.com/minify/-/minify-4.1.3.tgz#58467922d14303f55a3a28fa79641371955b8fbd"
integrity sha512-ykuscavxivSmVpcCzsXmsVTukWYLUUtPhHj0w2ILvHDGqC+hsuTCihBn9+PJBd58JNvWTNg9132J9nrrI2anzA==
dependencies:
clean-css "^4.1.6"
css-b64-images "~0.2.5"
debug "^4.1.0"
html-minifier "^4.0.0"
terser "^4.0.0"
try-catch "^2.0.0"
try-to-catch "^1.0.2"
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
@ -10036,6 +10118,11 @@ moment-duration-format@2.3.2:
resolved "https://registry.yarnpkg.com/moment-duration-format/-/moment-duration-format-2.3.2.tgz#5fa2b19b941b8d277122ff3f87a12895ec0d6212"
integrity sha512-cBMXjSW+fjOb4tyaVHuaVE/A5TqkukDWiOfxxAjY+PEqmmBQlLwn+8OzwPiG3brouXKY5Un4pBjAeB6UToXHaQ==
moment-mini@^2.22.1:
version "2.24.0"
resolved "https://registry.yarnpkg.com/moment-mini/-/moment-mini-2.24.0.tgz#fa68d98f7fe93ae65bf1262f6abb5fb6983d8d18"
integrity sha512-9ARkWHBs+6YJIvrIp0Ik5tyTTtP9PoV0Ssu2Ocq5y9v8+NOOpWiRshAp8c4rZVWTOe+157on/5G+zj5pwIQFEQ==
moment-timezone@0.5.28:
version "0.5.28"
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.28.tgz#f093d789d091ed7b055d82aa81a82467f72e4338"
@ -13693,6 +13780,15 @@ scim-query-filter-parser@2.0.4:
dependencies:
apg-lib "^3.2.0"
scope-css@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/scope-css/-/scope-css-1.2.1.tgz#c35768bc900cad030a3e0d663a818c0f6a57f40e"
integrity sha512-UjLRmyEYaDNiOS673xlVkZFlVCtckJR/dKgr434VMm7Lb+AOOqXKdAcY7PpGlJYErjXXJzKN7HWo4uRPiZZG0Q==
dependencies:
escaper "^2.5.3"
slugify "^1.3.1"
strip-css-comments "^3.0.0"
script-ext-html-webpack-plugin@2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/script-ext-html-webpack-plugin/-/script-ext-html-webpack-plugin-2.1.4.tgz#7c309354e310bf78523e1b84ca96fd374ceb9880"
@ -13921,6 +14017,11 @@ slice-ansi@^2.1.0:
astral-regex "^1.0.0"
is-fullwidth-code-point "^2.0.0"
slugify@^1.3.1:
version "1.4.0"
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.4.0.tgz#c9557c653c54b0c7f7a8e786ef3431add676d2cb"
integrity sha512-FtLNsMGBSRB/0JOE2A0fxlqjI6fJsgHGS13iTuVT28kViI4JjUiNqp/vyis0ZXYcMnpR3fzGNkv+6vRlI2GwdQ==
snapdragon-node@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
@ -14380,6 +14481,13 @@ strip-bom@^4.0.0:
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==
strip-css-comments@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-css-comments/-/strip-css-comments-3.0.0.tgz#7a5625eff8a2b226cf8947a11254da96e13dae89"
integrity sha1-elYl7/iisibPiUehElTaluE9rok=
dependencies:
is-regexp "^1.0.0"
strip-eof@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
@ -14635,6 +14743,15 @@ terser@4.6.6:
source-map "~0.6.1"
source-map-support "~0.5.12"
terser@^4.0.0:
version "4.6.7"
resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.7.tgz#478d7f9394ec1907f0e488c5f6a6a9a2bad55e72"
integrity sha512-fmr7M1f7DBly5cX2+rFDvmGBAaaZyPrHYK4mMdHEDAdNTqXSZgSOfqsfGq2HqPGT/1V0foZZuCZFx8CHKgAk3g==
dependencies:
commander "^2.20.0"
source-map "~0.6.1"
source-map-support "~0.5.12"
terser@^4.1.2:
version "4.3.1"
resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.1.tgz#09820bcb3398299c4b48d9a86aefc65127d0ed65"
@ -14851,6 +14968,16 @@ truncate-utf8-bytes@^1.0.0:
dependencies:
utf8-byte-length "^1.0.1"
try-catch@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/try-catch/-/try-catch-2.0.1.tgz#a35d354187c422f291a0bcfd9eb77e3a4f90c1e5"
integrity sha512-LsOrmObN/2WdM+y2xG+t16vhYrQsnV8wftXIcIOWZhQcBJvKGYuamJGwnU98A7Jxs2oZNkJztXlphEOoA0DWqg==
try-to-catch@^1.0.2:
version "1.1.1"
resolved "https://registry.yarnpkg.com/try-to-catch/-/try-to-catch-1.1.1.tgz#770162dd13b9a0e55da04db5b7f888956072038a"
integrity sha512-ikUlS+/BcImLhNYyIgZcEmq4byc31QpC+46/6Jm5ECWkVFhf8SM2Fp/0pMVXPX6vk45SMCwrP4Taxucne8I0VA==
tryer@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"

Loading…
Cancel
Save