source: node_modules/refractor/lang/markdown.js

main
Last change on this file was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 12.9 KB
Line 
1'use strict'
2
3module.exports = markdown
4markdown.displayName = 'markdown'
5markdown.aliases = ['md']
6function markdown(Prism) {
7 ;(function (Prism) {
8 // Allow only one line break
9 var inner = /(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source
10 /**
11 * This function is intended for the creation of the bold or italic pattern.
12 *
13 * This also adds a lookbehind group to the given pattern to ensure that the pattern is not backslash-escaped.
14 *
15 * _Note:_ Keep in mind that this adds a capturing group.
16 *
17 * @param {string} pattern
18 * @returns {RegExp}
19 */
20 function createInline(pattern) {
21 pattern = pattern.replace(/<inner>/g, function () {
22 return inner
23 })
24 return RegExp(/((?:^|[^\\])(?:\\{2})*)/.source + '(?:' + pattern + ')')
25 }
26 var tableCell = /(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/
27 .source
28 var tableRow =
29 /\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(
30 /__/g,
31 function () {
32 return tableCell
33 }
34 )
35 var tableLine =
36 /\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/
37 .source
38 Prism.languages.markdown = Prism.languages.extend('markup', {})
39 Prism.languages.insertBefore('markdown', 'prolog', {
40 'front-matter-block': {
41 pattern: /(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,
42 lookbehind: true,
43 greedy: true,
44 inside: {
45 punctuation: /^---|---$/,
46 'front-matter': {
47 pattern: /\S+(?:\s+\S+)*/,
48 alias: ['yaml', 'language-yaml'],
49 inside: Prism.languages.yaml
50 }
51 }
52 },
53 blockquote: {
54 // > ...
55 pattern: /^>(?:[\t ]*>)*/m,
56 alias: 'punctuation'
57 },
58 table: {
59 pattern: RegExp(
60 '^' + tableRow + tableLine + '(?:' + tableRow + ')*',
61 'm'
62 ),
63 inside: {
64 'table-data-rows': {
65 pattern: RegExp(
66 '^(' + tableRow + tableLine + ')(?:' + tableRow + ')*$'
67 ),
68 lookbehind: true,
69 inside: {
70 'table-data': {
71 pattern: RegExp(tableCell),
72 inside: Prism.languages.markdown
73 },
74 punctuation: /\|/
75 }
76 },
77 'table-line': {
78 pattern: RegExp('^(' + tableRow + ')' + tableLine + '$'),
79 lookbehind: true,
80 inside: {
81 punctuation: /\||:?-{3,}:?/
82 }
83 },
84 'table-header-row': {
85 pattern: RegExp('^' + tableRow + '$'),
86 inside: {
87 'table-header': {
88 pattern: RegExp(tableCell),
89 alias: 'important',
90 inside: Prism.languages.markdown
91 },
92 punctuation: /\|/
93 }
94 }
95 }
96 },
97 code: [
98 {
99 // Prefixed by 4 spaces or 1 tab and preceded by an empty line
100 pattern:
101 /((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,
102 lookbehind: true,
103 alias: 'keyword'
104 },
105 {
106 // ```optional language
107 // code block
108 // ```
109 pattern: /^```[\s\S]*?^```$/m,
110 greedy: true,
111 inside: {
112 'code-block': {
113 pattern: /^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,
114 lookbehind: true
115 },
116 'code-language': {
117 pattern: /^(```).+/,
118 lookbehind: true
119 },
120 punctuation: /```/
121 }
122 }
123 ],
124 title: [
125 {
126 // title 1
127 // =======
128 // title 2
129 // -------
130 pattern: /\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,
131 alias: 'important',
132 inside: {
133 punctuation: /==+$|--+$/
134 }
135 },
136 {
137 // # title 1
138 // ###### title 6
139 pattern: /(^\s*)#.+/m,
140 lookbehind: true,
141 alias: 'important',
142 inside: {
143 punctuation: /^#+|#+$/
144 }
145 }
146 ],
147 hr: {
148 // ***
149 // ---
150 // * * *
151 // -----------
152 pattern: /(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,
153 lookbehind: true,
154 alias: 'punctuation'
155 },
156 list: {
157 // * item
158 // + item
159 // - item
160 // 1. item
161 pattern: /(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,
162 lookbehind: true,
163 alias: 'punctuation'
164 },
165 'url-reference': {
166 // [id]: http://example.com "Optional title"
167 // [id]: http://example.com 'Optional title'
168 // [id]: http://example.com (Optional title)
169 // [id]: <http://example.com> "Optional title"
170 pattern:
171 /!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,
172 inside: {
173 variable: {
174 pattern: /^(!?\[)[^\]]+/,
175 lookbehind: true
176 },
177 string:
178 /(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,
179 punctuation: /^[\[\]!:]|[<>]/
180 },
181 alias: 'url'
182 },
183 bold: {
184 // **strong**
185 // __strong__
186 // allow one nested instance of italic text using the same delimiter
187 pattern: createInline(
188 /\b__(?:(?!_)<inner>|_(?:(?!_)<inner>)+_)+__\b|\*\*(?:(?!\*)<inner>|\*(?:(?!\*)<inner>)+\*)+\*\*/
189 .source
190 ),
191 lookbehind: true,
192 greedy: true,
193 inside: {
194 content: {
195 pattern: /(^..)[\s\S]+(?=..$)/,
196 lookbehind: true,
197 inside: {} // see below
198 },
199 punctuation: /\*\*|__/
200 }
201 },
202 italic: {
203 // *em*
204 // _em_
205 // allow one nested instance of bold text using the same delimiter
206 pattern: createInline(
207 /\b_(?:(?!_)<inner>|__(?:(?!_)<inner>)+__)+_\b|\*(?:(?!\*)<inner>|\*\*(?:(?!\*)<inner>)+\*\*)+\*/
208 .source
209 ),
210 lookbehind: true,
211 greedy: true,
212 inside: {
213 content: {
214 pattern: /(^.)[\s\S]+(?=.$)/,
215 lookbehind: true,
216 inside: {} // see below
217 },
218 punctuation: /[*_]/
219 }
220 },
221 strike: {
222 // ~~strike through~~
223 // ~strike~
224 // eslint-disable-next-line regexp/strict
225 pattern: createInline(/(~~?)(?:(?!~)<inner>)+\2/.source),
226 lookbehind: true,
227 greedy: true,
228 inside: {
229 content: {
230 pattern: /(^~~?)[\s\S]+(?=\1$)/,
231 lookbehind: true,
232 inside: {} // see below
233 },
234 punctuation: /~~?/
235 }
236 },
237 'code-snippet': {
238 // `code`
239 // ``code``
240 pattern:
241 /(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,
242 lookbehind: true,
243 greedy: true,
244 alias: ['code', 'keyword']
245 },
246 url: {
247 // [example](http://example.com "Optional title")
248 // [example][id]
249 // [example] [id]
250 pattern: createInline(
251 /!?\[(?:(?!\])<inner>)+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\])<inner>)+\])/
252 .source
253 ),
254 lookbehind: true,
255 greedy: true,
256 inside: {
257 operator: /^!/,
258 content: {
259 pattern: /(^\[)[^\]]+(?=\])/,
260 lookbehind: true,
261 inside: {} // see below
262 },
263 variable: {
264 pattern: /(^\][ \t]?\[)[^\]]+(?=\]$)/,
265 lookbehind: true
266 },
267 url: {
268 pattern: /(^\]\()[^\s)]+/,
269 lookbehind: true
270 },
271 string: {
272 pattern: /(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,
273 lookbehind: true
274 }
275 }
276 }
277 })
278 ;['url', 'bold', 'italic', 'strike'].forEach(function (token) {
279 ;['url', 'bold', 'italic', 'strike', 'code-snippet'].forEach(function (
280 inside
281 ) {
282 if (token !== inside) {
283 Prism.languages.markdown[token].inside.content.inside[inside] =
284 Prism.languages.markdown[inside]
285 }
286 })
287 })
288 Prism.hooks.add('after-tokenize', function (env) {
289 if (env.language !== 'markdown' && env.language !== 'md') {
290 return
291 }
292 function walkTokens(tokens) {
293 if (!tokens || typeof tokens === 'string') {
294 return
295 }
296 for (var i = 0, l = tokens.length; i < l; i++) {
297 var token = tokens[i]
298 if (token.type !== 'code') {
299 walkTokens(token.content)
300 continue
301 }
302 /*
303 * Add the correct `language-xxxx` class to this code block. Keep in mind that the `code-language` token
304 * is optional. But the grammar is defined so that there is only one case we have to handle:
305 *
306 * token.content = [
307 * <span class="punctuation">```</span>,
308 * <span class="code-language">xxxx</span>,
309 * '\n', // exactly one new lines (\r or \n or \r\n)
310 * <span class="code-block">...</span>,
311 * '\n', // exactly one new lines again
312 * <span class="punctuation">```</span>
313 * ];
314 */
315 var codeLang = token.content[1]
316 var codeBlock = token.content[3]
317 if (
318 codeLang &&
319 codeBlock &&
320 codeLang.type === 'code-language' &&
321 codeBlock.type === 'code-block' &&
322 typeof codeLang.content === 'string'
323 ) {
324 // this might be a language that Prism does not support
325 // do some replacements to support C++, C#, and F#
326 var lang = codeLang.content
327 .replace(/\b#/g, 'sharp')
328 .replace(/\b\+\+/g, 'pp') // only use the first word
329 lang = (/[a-z][\w-]*/i.exec(lang) || [''])[0].toLowerCase()
330 var alias = 'language-' + lang // add alias
331 if (!codeBlock.alias) {
332 codeBlock.alias = [alias]
333 } else if (typeof codeBlock.alias === 'string') {
334 codeBlock.alias = [codeBlock.alias, alias]
335 } else {
336 codeBlock.alias.push(alias)
337 }
338 }
339 }
340 }
341 walkTokens(env.tokens)
342 })
343 Prism.hooks.add('wrap', function (env) {
344 if (env.type !== 'code-block') {
345 return
346 }
347 var codeLang = ''
348 for (var i = 0, l = env.classes.length; i < l; i++) {
349 var cls = env.classes[i]
350 var match = /language-(.+)/.exec(cls)
351 if (match) {
352 codeLang = match[1]
353 break
354 }
355 }
356 var grammar = Prism.languages[codeLang]
357 if (!grammar) {
358 if (codeLang && codeLang !== 'none' && Prism.plugins.autoloader) {
359 var id =
360 'md-' +
361 new Date().valueOf() +
362 '-' +
363 Math.floor(Math.random() * 1e16)
364 env.attributes['id'] = id
365 Prism.plugins.autoloader.loadLanguages(codeLang, function () {
366 var ele = document.getElementById(id)
367 if (ele) {
368 ele.innerHTML = Prism.highlight(
369 ele.textContent,
370 Prism.languages[codeLang],
371 codeLang
372 )
373 }
374 })
375 }
376 } else {
377 env.content = Prism.highlight(
378 textContent(env.content.value),
379 grammar,
380 codeLang
381 )
382 }
383 })
384 var tagPattern = RegExp(Prism.languages.markup.tag.pattern.source, 'gi')
385 /**
386 * A list of known entity names.
387 *
388 * This will always be incomplete to save space. The current list is the one used by lowdash's unescape function.
389 *
390 * @see {@link https://github.com/lodash/lodash/blob/2da024c3b4f9947a48517639de7560457cd4ec6c/unescape.js#L2}
391 */
392 var KNOWN_ENTITY_NAMES = {
393 amp: '&',
394 lt: '<',
395 gt: '>',
396 quot: '"'
397 } // IE 11 doesn't support `String.fromCodePoint`
398 var fromCodePoint = String.fromCodePoint || String.fromCharCode
399 /**
400 * Returns the text content of a given HTML source code string.
401 *
402 * @param {string} html
403 * @returns {string}
404 */
405 function textContent(html) {
406 // remove all tags
407 var text = html.replace(tagPattern, '') // decode known entities
408 text = text.replace(/&(\w{1,8}|#x?[\da-f]{1,8});/gi, function (m, code) {
409 code = code.toLowerCase()
410 if (code[0] === '#') {
411 var value
412 if (code[1] === 'x') {
413 value = parseInt(code.slice(2), 16)
414 } else {
415 value = Number(code.slice(1))
416 }
417 return fromCodePoint(value)
418 } else {
419 var known = KNOWN_ENTITY_NAMES[code]
420 if (known) {
421 return known
422 } // unable to decode
423 return m
424 }
425 })
426 return text
427 }
428 Prism.languages.md = Prism.languages.markdown
429 })(Prism)
430}
Note: See TracBrowser for help on using the repository browser.