|  | 
|  | 1 | +<template> | 
|  | 2 | +  <div class="markdown-body" ref="markdown-it-vue-container"></div> | 
|  | 3 | +</template> | 
|  | 4 | + | 
|  | 5 | +<script> | 
|  | 6 | +import MarkdownIt from 'markdown-it' | 
|  | 7 | +import MarkdownItEmoji from 'markdown-it-emoji' | 
|  | 8 | +import MarkdownItSubscript from 'markdown-it-sub' | 
|  | 9 | +import MarkdownItSuperscript from 'markdown-it-sup' | 
|  | 10 | +import MarkdownItFootnote from 'markdown-it-footnote' | 
|  | 11 | +import MarkdownItDeflist from 'markdown-it-deflist' | 
|  | 12 | +import MarkdownItAbbreviation from 'markdown-it-abbr' | 
|  | 13 | +import MarkdownItInsert from 'markdown-it-ins' | 
|  | 14 | +import MarkdownItMark from 'markdown-it-mark' | 
|  | 15 | +import MarkdownItKatex from 'markdown-it-katex' | 
|  | 16 | +import MarkdownItTasklists from 'markdown-it-task-lists' | 
|  | 17 | +import MarkdownItLatex from 'markdown-it-latex' | 
|  | 18 | +import MarkdownItContainer from 'markdown-it-container' | 
|  | 19 | +import MarkdownItGithubToc from 'markdown-it-github-toc' | 
|  | 20 | +import MarkdownItSourceMap from 'markdown-it-source-map' | 
|  | 21 | +import MarkdownItLinkAttributes from './markdown-it-link-attributes' | 
|  | 22 | +import MarkdownItFlowchart from './markdown-it-plugin-flowchart' | 
|  | 23 | +import MarkdownItFontAwsome from './markdown-it-font-awsome' | 
|  | 24 | +import 'github-markdown-css' | 
|  | 25 | +import 'markdown-it-latex/dist/index.css' | 
|  | 26 | +
 | 
|  | 27 | +import flowchart from 'flowchart.js' | 
|  | 28 | +
 | 
|  | 29 | +const DEFAULT_OPTIONS_LINK_ATTRIBUTES = { | 
|  | 30 | +  attrs: { | 
|  | 31 | +    target: '_blank', | 
|  | 32 | +    rel: 'noopener' | 
|  | 33 | +  } | 
|  | 34 | +} | 
|  | 35 | +const DEFAULT_OPTIONS_KATEX = { throwOnError: false, errorColor: '#cc0000' } | 
|  | 36 | +const DEFAULT_OPTIONS_TASKLISTS = null | 
|  | 37 | +const DEFAULT_OPTIONS_GITHUBTOC = { | 
|  | 38 | +  tocFirstLevel: 2, | 
|  | 39 | +  tocLastLevel: 3, | 
|  | 40 | +  tocClassName: 'toc', | 
|  | 41 | +  anchorLinkSymbol: '', | 
|  | 42 | +  anchorLinkSpace: false, | 
|  | 43 | +  anchorClassName: 'anchor', | 
|  | 44 | +  anchorLinkSymbolClassName: 'octicon octicon-link' | 
|  | 45 | +} | 
|  | 46 | +
 | 
|  | 47 | +export default { | 
|  | 48 | +  name: 'markdown-it-vue-light', | 
|  | 49 | +  props: { | 
|  | 50 | +    content: { | 
|  | 51 | +      type: String | 
|  | 52 | +    }, | 
|  | 53 | +    options: { | 
|  | 54 | +      type: Object, | 
|  | 55 | +      default() { | 
|  | 56 | +        return { | 
|  | 57 | +          markdownIt: { | 
|  | 58 | +            linkify: true | 
|  | 59 | +          }, | 
|  | 60 | +          linkAttributes: DEFAULT_OPTIONS_LINK_ATTRIBUTES, | 
|  | 61 | +          katex: DEFAULT_OPTIONS_KATEX, | 
|  | 62 | +          tasklists: DEFAULT_OPTIONS_TASKLISTS, | 
|  | 63 | +          githubToc: DEFAULT_OPTIONS_GITHUBTOC | 
|  | 64 | +        } | 
|  | 65 | +      } | 
|  | 66 | +    } | 
|  | 67 | +  }, | 
|  | 68 | +  watch: { | 
|  | 69 | +    content: { | 
|  | 70 | +      immediate: true, | 
|  | 71 | +      handler(val) { | 
|  | 72 | +        this.$nextTick(() => { | 
|  | 73 | +          this.$refs['markdown-it-vue-container'].innerHTML = this.md.render( | 
|  | 74 | +            val | 
|  | 75 | +          ) | 
|  | 76 | +          // render flowchart | 
|  | 77 | +          document.querySelectorAll('.md-flowchart').forEach(element => { | 
|  | 78 | +            try { | 
|  | 79 | +              let code = element.textContent | 
|  | 80 | +              let chart = flowchart.parse(code) | 
|  | 81 | +              element.textContent = '' | 
|  | 82 | +              chart.drawSVG(element) | 
|  | 83 | +            } catch (e) { | 
|  | 84 | +              element.outerHTML = `<pre>flowchart complains: ${e}</pre>` | 
|  | 85 | +            } | 
|  | 86 | +          }) | 
|  | 87 | +
 | 
|  | 88 | +          // emit event | 
|  | 89 | +          this.$emit('render-complete') | 
|  | 90 | +        }) | 
|  | 91 | +      } | 
|  | 92 | +    } | 
|  | 93 | +  }, | 
|  | 94 | +  data() { | 
|  | 95 | +    const optMarkdownIt = this.options.markdownIt | 
|  | 96 | +    const linkAttributes = this.options.linkAttributes || DEFAULT_OPTIONS_LINK_ATTRIBUTES | 
|  | 97 | +    const optKatex = this.options.katex || DEFAULT_OPTIONS_KATEX | 
|  | 98 | +    const optTasklists = this.options.tasklists || DEFAULT_OPTIONS_TASKLISTS | 
|  | 99 | +    const optGithubToc = this.options.githubToc || DEFAULT_OPTIONS_GITHUBTOC | 
|  | 100 | +
 | 
|  | 101 | +    let md = new MarkdownIt(optMarkdownIt) | 
|  | 102 | +      .use(MarkdownItEmoji) | 
|  | 103 | +      .use(MarkdownItSubscript) | 
|  | 104 | +      .use(MarkdownItSuperscript) | 
|  | 105 | +      .use(MarkdownItFootnote) | 
|  | 106 | +      .use(MarkdownItDeflist) | 
|  | 107 | +      .use(MarkdownItAbbreviation) | 
|  | 108 | +      .use(MarkdownItInsert) | 
|  | 109 | +      .use(MarkdownItMark) | 
|  | 110 | +      .use(MarkdownItLatex) | 
|  | 111 | +      .use(MarkdownItFlowchart) | 
|  | 112 | +      .use(MarkdownItSourceMap) | 
|  | 113 | +      .use(MarkdownItLinkAttributes, linkAttributes) | 
|  | 114 | +      .use(MarkdownItKatex, optKatex) | 
|  | 115 | +      .use(MarkdownItTasklists, optTasklists) | 
|  | 116 | +      .use(MarkdownItFontAwsome) | 
|  | 117 | +      .use(MarkdownItGithubToc, optGithubToc) | 
|  | 118 | +      .use(MarkdownItContainer, 'warning', { | 
|  | 119 | +        validate: function(params) { | 
|  | 120 | +          return params.trim() === 'warning' | 
|  | 121 | +        }, | 
|  | 122 | +        render: (tokens, idx) => { | 
|  | 123 | +          if (tokens[idx].nesting === 1) { | 
|  | 124 | +            const icon = `<i class="markdown-it-vue-alert-icon markdown-it-vue-alert-icon-warning"><svg viewBox="64 64 896 896" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 0 1 0-96 48.01 48.01 0 0 1 0 96z"></path></svg></i>` | 
|  | 125 | +            return `<div class="markdown-it-vue-alter markdown-it-vue-alter-warning">${icon}` | 
|  | 126 | +          } else { | 
|  | 127 | +            return '</div>' | 
|  | 128 | +          } | 
|  | 129 | +        } | 
|  | 130 | +      }) | 
|  | 131 | +      .use(MarkdownItContainer, 'info', { | 
|  | 132 | +        validate: function(params) { | 
|  | 133 | +          return params.trim() === 'info' | 
|  | 134 | +        }, | 
|  | 135 | +        render: (tokens, idx) => { | 
|  | 136 | +          if (tokens[idx].nesting === 1) { | 
|  | 137 | +            const icon = `<i class="markdown-it-vue-alert-icon markdown-it-vue-alert-icon-info"><svg viewBox="64 64 896 896" data-icon="info-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm32 664c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V456c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272zm-32-344a48.01 48.01 0 0 1 0-96 48.01 48.01 0 0 1 0 96z"></path></svg></i>` | 
|  | 138 | +            return `<div class="markdown-it-vue-alter markdown-it-vue-alter-info">${icon}` | 
|  | 139 | +          } else { | 
|  | 140 | +            return '</div>' | 
|  | 141 | +          } | 
|  | 142 | +        } | 
|  | 143 | +      }) | 
|  | 144 | +      .use(MarkdownItContainer, 'success', { | 
|  | 145 | +        validate: function(params) { | 
|  | 146 | +          return params.trim() === 'success' | 
|  | 147 | +        }, | 
|  | 148 | +        render: (tokens, idx) => { | 
|  | 149 | +          if (tokens[idx].nesting === 1) { | 
|  | 150 | +            const icon = `<i class="markdown-it-vue-alert-icon markdown-it-vue-alert-icon-success"><svg viewBox="64 64 896 896" data-icon="check-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 0 1-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"></path></svg></i>` | 
|  | 151 | +            return `<div class="markdown-it-vue-alter markdown-it-vue-alter-success">${icon}` | 
|  | 152 | +          } else { | 
|  | 153 | +            return '</div>' | 
|  | 154 | +          } | 
|  | 155 | +        } | 
|  | 156 | +      }) | 
|  | 157 | +      .use(MarkdownItContainer, 'error', { | 
|  | 158 | +        validate: function(params) { | 
|  | 159 | +          return params.trim() === 'error' | 
|  | 160 | +        }, | 
|  | 161 | +        render: (tokens, idx) => { | 
|  | 162 | +          if (tokens[idx].nesting === 1) { | 
|  | 163 | +            const icon = `<i class="markdown-it-vue-alert-icon markdown-it-vue-alert-icon-error"><svg viewBox="64 64 896 896" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 0 1-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path></svg></i>` | 
|  | 164 | +            return `<div class="markdown-it-vue-alter markdown-it-vue-alter-error">${icon}` | 
|  | 165 | +          } else { | 
|  | 166 | +            return '</div>' | 
|  | 167 | +          } | 
|  | 168 | +        } | 
|  | 169 | +      }) | 
|  | 170 | +    return { | 
|  | 171 | +      md: md | 
|  | 172 | +    } | 
|  | 173 | +  }, | 
|  | 174 | +  methods: { | 
|  | 175 | +    use(plugin, options) { | 
|  | 176 | +      this.md.use(plugin, options) | 
|  | 177 | +    }, | 
|  | 178 | +    get() { | 
|  | 179 | +      return this.md | 
|  | 180 | +    } | 
|  | 181 | +  } | 
|  | 182 | +} | 
|  | 183 | +</script> | 
|  | 184 | + | 
|  | 185 | +<style lange="scss"> | 
|  | 186 | +.markdown-it-vue-alter-info { | 
|  | 187 | +  border: 1px solid #91d5ff; | 
|  | 188 | +  background-color: #e6f7ff; | 
|  | 189 | +} | 
|  | 190 | +.markdown-it-vue-alert-icon-info { | 
|  | 191 | +  color: #1890ff; | 
|  | 192 | +} | 
|  | 193 | +.markdown-it-vue-alter-success { | 
|  | 194 | +  border: 1px solid #b7eb8f; | 
|  | 195 | +  background-color: #f6ffed; | 
|  | 196 | +} | 
|  | 197 | +.markdown-it-vue-alert-icon-success { | 
|  | 198 | +  color: #52c41a; | 
|  | 199 | +} | 
|  | 200 | +.markdown-it-vue-alter-error { | 
|  | 201 | +  border: 1px solid #f5222d; | 
|  | 202 | +  background-color: #fff1f0; | 
|  | 203 | +} | 
|  | 204 | +.markdown-it-vue-alert-icon-error { | 
|  | 205 | +  color: #f5222d; | 
|  | 206 | +} | 
|  | 207 | +.markdown-it-vue-alter-warning { | 
|  | 208 | +  border: 1px solid #ffe58f; | 
|  | 209 | +  background-color: #fffbe6; | 
|  | 210 | +} | 
|  | 211 | +.markdown-it-vue-alert-icon-warning { | 
|  | 212 | +  color: #faad14; | 
|  | 213 | +} | 
|  | 214 | +.markdown-it-vue-alter { | 
|  | 215 | +  border-radius: 0; | 
|  | 216 | +  border: 0; | 
|  | 217 | +  margin-bottom: 0; | 
|  | 218 | +  display: inline-flex; | 
|  | 219 | +  font-family: 'Chinese Quote', -apple-system, BlinkMacSystemFont, 'Segoe UI', | 
|  | 220 | +    'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Helvetica Neue', | 
|  | 221 | +    Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', | 
|  | 222 | +    'Segoe UI Symbol'; | 
|  | 223 | +  font-size: 14px; | 
|  | 224 | +  font-variant: tabular-nums; | 
|  | 225 | +  line-height: 1.5; | 
|  | 226 | +  color: rgba(0, 0, 0, 0.65); | 
|  | 227 | +  box-sizing: border-box; | 
|  | 228 | +  padding: 0; | 
|  | 229 | +  list-style: none; | 
|  | 230 | +  position: relative; | 
|  | 231 | +  padding: 8px 15px 8px 37px; | 
|  | 232 | +  border-radius: 4px; | 
|  | 233 | +  width: 100%; | 
|  | 234 | +  margin-bottom: 16px; | 
|  | 235 | +} | 
|  | 236 | +.markdown-it-vue-alter p { | 
|  | 237 | +  margin-bottom: 2px; | 
|  | 238 | +} | 
|  | 239 | +
 | 
|  | 240 | +.markdown-it-vue-alert-icon { | 
|  | 241 | +  top: 11.5px; | 
|  | 242 | +  left: 16px; | 
|  | 243 | +  position: absolute; | 
|  | 244 | +} | 
|  | 245 | +</style> | 
0 commit comments