123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- /*
- Language: Markdown
- Requires: xml.js
- Author: John Crepezzi <john.crepezzi@gmail.com>
- Website: https://daringfireball.net/projects/markdown/
- Category: common, markup
- */
- function markdown(hljs) {
- const regex = hljs.regex;
- const INLINE_HTML = {
- begin: /<\/?[A-Za-z_]/,
- end: '>',
- subLanguage: 'xml',
- relevance: 0
- };
- const HORIZONTAL_RULE = {
- begin: '^[-\\*]{3,}',
- end: '$'
- };
- const CODE = {
- className: 'code',
- variants: [
- // TODO: fix to allow these to work with sublanguage also
- { begin: '(`{3,})[^`](.|\\n)*?\\1`*[ ]*' },
- { begin: '(~{3,})[^~](.|\\n)*?\\1~*[ ]*' },
- // needed to allow markdown as a sublanguage to work
- {
- begin: '```',
- end: '```+[ ]*$'
- },
- {
- begin: '~~~',
- end: '~~~+[ ]*$'
- },
- { begin: '`.+?`' },
- {
- begin: '(?=^( {4}|\\t))',
- // use contains to gobble up multiple lines to allow the block to be whatever size
- // but only have a single open/close tag vs one per line
- contains: [
- {
- begin: '^( {4}|\\t)',
- end: '(\\n)$'
- }
- ],
- relevance: 0
- }
- ]
- };
- const LIST = {
- className: 'bullet',
- begin: '^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)',
- end: '\\s+',
- excludeEnd: true
- };
- const LINK_REFERENCE = {
- begin: /^\[[^\n]+\]:/,
- returnBegin: true,
- contains: [
- {
- className: 'symbol',
- begin: /\[/,
- end: /\]/,
- excludeBegin: true,
- excludeEnd: true
- },
- {
- className: 'link',
- begin: /:\s*/,
- end: /$/,
- excludeBegin: true
- }
- ]
- };
- const URL_SCHEME = /[A-Za-z][A-Za-z0-9+.-]*/;
- const LINK = {
- variants: [
- // too much like nested array access in so many languages
- // to have any real relevance
- {
- begin: /\[.+?\]\[.*?\]/,
- relevance: 0
- },
- // popular internet URLs
- {
- begin: /\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/,
- relevance: 2
- },
- {
- begin: regex.concat(/\[.+?\]\(/, URL_SCHEME, /:\/\/.*?\)/),
- relevance: 2
- },
- // relative urls
- {
- begin: /\[.+?\]\([./?&#].*?\)/,
- relevance: 1
- },
- // whatever else, lower relevance (might not be a link at all)
- {
- begin: /\[.*?\]\(.*?\)/,
- relevance: 0
- }
- ],
- returnBegin: true,
- contains: [
- {
- // empty strings for alt or link text
- match: /\[(?=\])/ },
- {
- className: 'string',
- relevance: 0,
- begin: '\\[',
- end: '\\]',
- excludeBegin: true,
- returnEnd: true
- },
- {
- className: 'link',
- relevance: 0,
- begin: '\\]\\(',
- end: '\\)',
- excludeBegin: true,
- excludeEnd: true
- },
- {
- className: 'symbol',
- relevance: 0,
- begin: '\\]\\[',
- end: '\\]',
- excludeBegin: true,
- excludeEnd: true
- }
- ]
- };
- const BOLD = {
- className: 'strong',
- contains: [], // defined later
- variants: [
- {
- begin: /_{2}(?!\s)/,
- end: /_{2}/
- },
- {
- begin: /\*{2}(?!\s)/,
- end: /\*{2}/
- }
- ]
- };
- const ITALIC = {
- className: 'emphasis',
- contains: [], // defined later
- variants: [
- {
- begin: /\*(?![*\s])/,
- end: /\*/
- },
- {
- begin: /_(?![_\s])/,
- end: /_/,
- relevance: 0
- }
- ]
- };
- // 3 level deep nesting is not allowed because it would create confusion
- // in cases like `***testing***` because where we don't know if the last
- // `***` is starting a new bold/italic or finishing the last one
- const BOLD_WITHOUT_ITALIC = hljs.inherit(BOLD, { contains: [] });
- const ITALIC_WITHOUT_BOLD = hljs.inherit(ITALIC, { contains: [] });
- BOLD.contains.push(ITALIC_WITHOUT_BOLD);
- ITALIC.contains.push(BOLD_WITHOUT_ITALIC);
- let CONTAINABLE = [
- INLINE_HTML,
- LINK
- ];
- [
- BOLD,
- ITALIC,
- BOLD_WITHOUT_ITALIC,
- ITALIC_WITHOUT_BOLD
- ].forEach(m => {
- m.contains = m.contains.concat(CONTAINABLE);
- });
- CONTAINABLE = CONTAINABLE.concat(BOLD, ITALIC);
- const HEADER = {
- className: 'section',
- variants: [
- {
- begin: '^#{1,6}',
- end: '$',
- contains: CONTAINABLE
- },
- {
- begin: '(?=^.+?\\n[=-]{2,}$)',
- contains: [
- { begin: '^[=-]*$' },
- {
- begin: '^',
- end: "\\n",
- contains: CONTAINABLE
- }
- ]
- }
- ]
- };
- const BLOCKQUOTE = {
- className: 'quote',
- begin: '^>\\s+',
- contains: CONTAINABLE,
- end: '$'
- };
- return {
- name: 'Markdown',
- aliases: [
- 'md',
- 'mkdown',
- 'mkd'
- ],
- contains: [
- HEADER,
- INLINE_HTML,
- LIST,
- BOLD,
- ITALIC,
- BLOCKQUOTE,
- CODE,
- HORIZONTAL_RULE,
- LINK,
- LINK_REFERENCE
- ]
- };
- }
- export { markdown as default };
|