UNPKG

7.38 kBJavaScriptView Raw
1import markdownIt from 'markdown-it'
2import emoji from 'markdown-it-emoji'
3import subscript from 'markdown-it-sub'
4import superscript from 'markdown-it-sup'
5import footnote from 'markdown-it-footnote'
6import deflist from 'markdown-it-deflist'
7import abbreviation from 'markdown-it-abbr'
8import insert from 'markdown-it-ins'
9import mark from 'markdown-it-mark'
10import toc from 'markdown-it-toc-and-anchor'
11import katex from 'markdown-it-katex-newcommand'
12import tasklists from 'markdown-it-task-lists'
13import container from 'markdown-it-container'
14import prism from 'markdown-it-prism'
15import preWrapper from '@mathssyfy/markdown-it-prewrapper'
16import anchorPlugin from 'markdown-it-anchor'
17import tocPlugin from 'markdown-it-table-of-contents'
18
19//tests
20import lineNumbers from './lineNumbers' //Probleme avec babel
21import hightlightLines from './hightlightLines'//Meme problème
22
23///
24
25import './scss/theme.scss'
26
27
28export default {
29 md: new markdownIt(),
30
31 template: '<div><slot></slot></div>',
32
33 data() {
34 return {
35 sourceData: this.source,
36 }
37 },
38
39 props: {
40 watches: {
41 type: Array,
42 default: () => ['source', 'show', 'toc'],
43 },
44 source: {
45 type: String,
46 default: ``,
47 },
48 lineNumbers: {
49 type: Boolean,
50 default: false,
51 },
52 show: {
53 type: Boolean,
54 default: true,
55 },
56 highlight: {
57 type: Boolean,
58 default: true
59 },
60 html: {
61 type: Boolean,
62 default: true,
63 },
64 xhtmlOut: {
65 type: Boolean,
66 default: true,
67 },
68 breaks: {
69 type: Boolean,
70 default: true,
71 },
72 linkify: {
73 type: Boolean,
74 default: true,
75 },
76 emoji: {
77 type: Boolean,
78 default: true,
79 },
80 typographer: {
81 type: Boolean,
82 default: true,
83 },
84 langPrefix: {
85 type: String,
86 default: 'language-',
87 },
88 quotes: {
89 type: String,
90 default: '“”‘’',
91 },
92 tableClass: {
93 type: String,
94 default: 'table',
95 },
96 taskLists: {
97 type: Boolean,
98 default: true
99 },
100 toc: {
101 type: Boolean,
102 default: true,
103 },
104 tocId: {
105 type: String,
106 },
107 tocClass: {
108 type: String,
109 default: 'table-of-contents',
110 },
111 tocFirstLevel: {
112 type: Number,
113 default: 2,
114 },
115 tocLastLevel: {
116 type: Number,
117 },
118 tocAnchorLink: {
119 type: Boolean,
120 default: true,
121 },
122 tocAnchorClass: {
123 type: String,
124 default: 'toc-anchor',
125 },
126 tocAnchorLinkSymbol: {
127 type: String,
128 default: '#',
129 },
130 tocAnchorLinkSpace: {
131 type: Boolean,
132 default: true,
133 },
134 tocAnchorLinkClass: {
135 type: String,
136 default: 'toc-anchor-link',
137 },
138 anchorAttributes: {
139 type: Object,
140 default: () => ({})
141 },
142 prerender: {
143 type: Function,
144 default: (sourceData) => { return sourceData }
145 },
146 postrender: {
147 type: Function,
148 default: (htmlData) => { return htmlData }
149 }
150 },
151
152 computed: {
153 tocLastLevelComputed() {
154 return this.tocLastLevel > this.tocFirstLevel ? this.tocLastLevel : this.tocFirstLevel + 1
155 }
156 },
157
158 render(createElement) {
159 this.md = new markdownIt()
160 .use(subscript)
161 .use(superscript)
162 .use(footnote)
163 .use(deflist)
164 .use(abbreviation)
165 .use(insert)
166 .use(mark)
167 .use(prism)
168 .use(hightlightLines)
169 .use(preWrapper)
170
171
172 .use(anchorPlugin, [Object.assign({
173 permalink: true,
174 permalinkBefore: true,
175 permalinkSymbol: '#'
176 })])
177 .use(tocPlugin,[Object.assign({
178 includeLevel: [1, 2, 3],
179 }, toc)])
180 .use(katex, { "throwOnError": false, "errorColor": " #cc0000" })
181 .use(tasklists, { enabled: this.taskLists })
182 .use(...createContainer('tip', 'TIP'))
183 .use(...createContainer('attention', 'ATTENTION'))
184 .use(...createContainer('danger', 'DANGER'))
185 .use(...createContainer('warning', 'WARNING'))
186 .use(...createContainer('astuce', 'ASTUCE'))
187
188 if (this.emoji) {
189 this.md.use(emoji)
190 }
191 if (this.lineNumbers) {
192 this.md.use(lineNumbers)
193 }
194
195 this.md.set({
196 html: this.html,
197 xhtmlOut: this.xhtmlOut,
198 breaks: this.breaks,
199 linkify: this.linkify,
200 typographer: this.typographer,
201 langPrefix: this.langPrefix,
202 quotes: this.quotes,
203 })
204 this.md.renderer.rules.table_open = () => `<table class="${this.tableClass}">\n`
205 let defaultLinkRenderer = this.md.renderer.rules.link_open ||
206 function (tokens, idx, options, env, self) {
207 return self.renderToken(tokens, idx, options)
208 }
209 this.md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
210 Object.keys(this.anchorAttributes).map((attribute) => {
211 let aIndex = tokens[idx].attrIndex(attribute)
212 let value = this.anchorAttributes[attribute]
213 if (aIndex < 0) {
214 tokens[idx].attrPush([attribute, value]) // add new attribute
215 } else {
216 tokens[idx].attrs[aIndex][1] = value
217 }
218 })
219 return defaultLinkRenderer(tokens, idx, options, env, self)
220 }
221
222 if (this.toc) {
223 this.md.use(toc, {
224 tocClassName: this.tocClass,
225 tocFirstLevel: this.tocFirstLevel,
226 tocLastLevel: this.tocLastLevelComputed,
227 anchorLink: this.tocAnchorLink,
228 anchorLinkSymbol: this.tocAnchorLinkSymbol,
229 anchorLinkSpace: this.tocAnchorLinkSpace,
230 anchorClassName: this.tocAnchorClass,
231 anchorLinkSymbolClassName: this.tocAnchorLinkClass,
232 tocCallback: (tocMarkdown, tocArray, tocHtml) => {
233 if (tocHtml) {
234 if (this.tocId && document.getElementById(this.tocId)) {
235 document.getElementById(this.tocId).innerHTML = tocHtml
236 }
237
238 this.$emit('toc-rendered', tocHtml)
239 }
240 },
241 })
242 }
243
244 let outHtml = this.show ?
245 this.md.render(
246 this.prerender(this.sourceData)
247 ) : ''
248 outHtml = this.postrender(outHtml);
249
250 this.$emit('rendered', outHtml)
251 return createElement(
252 'div', {
253 domProps: {
254 innerHTML: outHtml,
255 },
256 },
257 )
258 },
259
260 beforeMount() {
261 if (this.$slots.default) {
262 this.sourceData = ''
263 for (let slot of this.$slots.default) {
264 this.sourceData += slot.text
265 }
266 }
267
268 this.$watch('source', () => {
269 this.sourceData = this.prerender(this.source)
270 this.$forceUpdate()
271 })
272
273 this.watches.forEach((v) => {
274 this.$watch(v, () => {
275 this.$forceUpdate()
276 })
277 })
278 },
279}
280
281// makdown-it-container
282function createContainer (klass, defaultTitle) {
283 return [container, klass, {
284 render (tokens, idx) {
285 const token = tokens[idx]
286 const info = token.info.trim().slice(klass.length).trim()
287 if (token.nesting === 1) {
288 return `<div class="${klass} custom-block"><p class="custom-block-title">${info || defaultTitle}</p>\n`
289 } else {
290 return `</div>\n`
291 }
292 }
293 }]
294}
\No newline at end of file