[d24f17c] | 1 | /**
|
---|
| 2 | * @param {string} value
|
---|
| 3 | * @returns {RegExp}
|
---|
| 4 | * */
|
---|
| 5 |
|
---|
| 6 | /**
|
---|
| 7 | * @param {RegExp | string } re
|
---|
| 8 | * @returns {string}
|
---|
| 9 | */
|
---|
| 10 | function source(re) {
|
---|
| 11 | if (!re) return null;
|
---|
| 12 | if (typeof re === "string") return re;
|
---|
| 13 |
|
---|
| 14 | return re.source;
|
---|
| 15 | }
|
---|
| 16 |
|
---|
| 17 | /**
|
---|
| 18 | * @param {...(RegExp | string) } args
|
---|
| 19 | * @returns {string}
|
---|
| 20 | */
|
---|
| 21 | function concat(...args) {
|
---|
| 22 | const joined = args.map((x) => source(x)).join("");
|
---|
| 23 | return joined;
|
---|
| 24 | }
|
---|
| 25 |
|
---|
| 26 | /*
|
---|
| 27 | Language: Markdown
|
---|
| 28 | Requires: xml.js
|
---|
| 29 | Author: John Crepezzi <john.crepezzi@gmail.com>
|
---|
| 30 | Website: https://daringfireball.net/projects/markdown/
|
---|
| 31 | Category: common, markup
|
---|
| 32 | */
|
---|
| 33 |
|
---|
| 34 | function markdown(hljs) {
|
---|
| 35 | const INLINE_HTML = {
|
---|
| 36 | begin: /<\/?[A-Za-z_]/,
|
---|
| 37 | end: '>',
|
---|
| 38 | subLanguage: 'xml',
|
---|
| 39 | relevance: 0
|
---|
| 40 | };
|
---|
| 41 | const HORIZONTAL_RULE = {
|
---|
| 42 | begin: '^[-\\*]{3,}',
|
---|
| 43 | end: '$'
|
---|
| 44 | };
|
---|
| 45 | const CODE = {
|
---|
| 46 | className: 'code',
|
---|
| 47 | variants: [
|
---|
| 48 | // TODO: fix to allow these to work with sublanguage also
|
---|
| 49 | {
|
---|
| 50 | begin: '(`{3,})[^`](.|\\n)*?\\1`*[ ]*'
|
---|
| 51 | },
|
---|
| 52 | {
|
---|
| 53 | begin: '(~{3,})[^~](.|\\n)*?\\1~*[ ]*'
|
---|
| 54 | },
|
---|
| 55 | // needed to allow markdown as a sublanguage to work
|
---|
| 56 | {
|
---|
| 57 | begin: '```',
|
---|
| 58 | end: '```+[ ]*$'
|
---|
| 59 | },
|
---|
| 60 | {
|
---|
| 61 | begin: '~~~',
|
---|
| 62 | end: '~~~+[ ]*$'
|
---|
| 63 | },
|
---|
| 64 | {
|
---|
| 65 | begin: '`.+?`'
|
---|
| 66 | },
|
---|
| 67 | {
|
---|
| 68 | begin: '(?=^( {4}|\\t))',
|
---|
| 69 | // use contains to gobble up multiple lines to allow the block to be whatever size
|
---|
| 70 | // but only have a single open/close tag vs one per line
|
---|
| 71 | contains: [
|
---|
| 72 | {
|
---|
| 73 | begin: '^( {4}|\\t)',
|
---|
| 74 | end: '(\\n)$'
|
---|
| 75 | }
|
---|
| 76 | ],
|
---|
| 77 | relevance: 0
|
---|
| 78 | }
|
---|
| 79 | ]
|
---|
| 80 | };
|
---|
| 81 | const LIST = {
|
---|
| 82 | className: 'bullet',
|
---|
| 83 | begin: '^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)',
|
---|
| 84 | end: '\\s+',
|
---|
| 85 | excludeEnd: true
|
---|
| 86 | };
|
---|
| 87 | const LINK_REFERENCE = {
|
---|
| 88 | begin: /^\[[^\n]+\]:/,
|
---|
| 89 | returnBegin: true,
|
---|
| 90 | contains: [
|
---|
| 91 | {
|
---|
| 92 | className: 'symbol',
|
---|
| 93 | begin: /\[/,
|
---|
| 94 | end: /\]/,
|
---|
| 95 | excludeBegin: true,
|
---|
| 96 | excludeEnd: true
|
---|
| 97 | },
|
---|
| 98 | {
|
---|
| 99 | className: 'link',
|
---|
| 100 | begin: /:\s*/,
|
---|
| 101 | end: /$/,
|
---|
| 102 | excludeBegin: true
|
---|
| 103 | }
|
---|
| 104 | ]
|
---|
| 105 | };
|
---|
| 106 | const URL_SCHEME = /[A-Za-z][A-Za-z0-9+.-]*/;
|
---|
| 107 | const LINK = {
|
---|
| 108 | variants: [
|
---|
| 109 | // too much like nested array access in so many languages
|
---|
| 110 | // to have any real relevance
|
---|
| 111 | {
|
---|
| 112 | begin: /\[.+?\]\[.*?\]/,
|
---|
| 113 | relevance: 0
|
---|
| 114 | },
|
---|
| 115 | // popular internet URLs
|
---|
| 116 | {
|
---|
| 117 | begin: /\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/,
|
---|
| 118 | relevance: 2
|
---|
| 119 | },
|
---|
| 120 | {
|
---|
| 121 | begin: concat(/\[.+?\]\(/, URL_SCHEME, /:\/\/.*?\)/),
|
---|
| 122 | relevance: 2
|
---|
| 123 | },
|
---|
| 124 | // relative urls
|
---|
| 125 | {
|
---|
| 126 | begin: /\[.+?\]\([./?&#].*?\)/,
|
---|
| 127 | relevance: 1
|
---|
| 128 | },
|
---|
| 129 | // whatever else, lower relevance (might not be a link at all)
|
---|
| 130 | {
|
---|
| 131 | begin: /\[.+?\]\(.*?\)/,
|
---|
| 132 | relevance: 0
|
---|
| 133 | }
|
---|
| 134 | ],
|
---|
| 135 | returnBegin: true,
|
---|
| 136 | contains: [
|
---|
| 137 | {
|
---|
| 138 | className: 'string',
|
---|
| 139 | relevance: 0,
|
---|
| 140 | begin: '\\[',
|
---|
| 141 | end: '\\]',
|
---|
| 142 | excludeBegin: true,
|
---|
| 143 | returnEnd: true
|
---|
| 144 | },
|
---|
| 145 | {
|
---|
| 146 | className: 'link',
|
---|
| 147 | relevance: 0,
|
---|
| 148 | begin: '\\]\\(',
|
---|
| 149 | end: '\\)',
|
---|
| 150 | excludeBegin: true,
|
---|
| 151 | excludeEnd: true
|
---|
| 152 | },
|
---|
| 153 | {
|
---|
| 154 | className: 'symbol',
|
---|
| 155 | relevance: 0,
|
---|
| 156 | begin: '\\]\\[',
|
---|
| 157 | end: '\\]',
|
---|
| 158 | excludeBegin: true,
|
---|
| 159 | excludeEnd: true
|
---|
| 160 | }
|
---|
| 161 | ]
|
---|
| 162 | };
|
---|
| 163 | const BOLD = {
|
---|
| 164 | className: 'strong',
|
---|
| 165 | contains: [], // defined later
|
---|
| 166 | variants: [
|
---|
| 167 | {
|
---|
| 168 | begin: /_{2}/,
|
---|
| 169 | end: /_{2}/
|
---|
| 170 | },
|
---|
| 171 | {
|
---|
| 172 | begin: /\*{2}/,
|
---|
| 173 | end: /\*{2}/
|
---|
| 174 | }
|
---|
| 175 | ]
|
---|
| 176 | };
|
---|
| 177 | const ITALIC = {
|
---|
| 178 | className: 'emphasis',
|
---|
| 179 | contains: [], // defined later
|
---|
| 180 | variants: [
|
---|
| 181 | {
|
---|
| 182 | begin: /\*(?!\*)/,
|
---|
| 183 | end: /\*/
|
---|
| 184 | },
|
---|
| 185 | {
|
---|
| 186 | begin: /_(?!_)/,
|
---|
| 187 | end: /_/,
|
---|
| 188 | relevance: 0
|
---|
| 189 | }
|
---|
| 190 | ]
|
---|
| 191 | };
|
---|
| 192 | BOLD.contains.push(ITALIC);
|
---|
| 193 | ITALIC.contains.push(BOLD);
|
---|
| 194 |
|
---|
| 195 | let CONTAINABLE = [
|
---|
| 196 | INLINE_HTML,
|
---|
| 197 | LINK
|
---|
| 198 | ];
|
---|
| 199 |
|
---|
| 200 | BOLD.contains = BOLD.contains.concat(CONTAINABLE);
|
---|
| 201 | ITALIC.contains = ITALIC.contains.concat(CONTAINABLE);
|
---|
| 202 |
|
---|
| 203 | CONTAINABLE = CONTAINABLE.concat(BOLD, ITALIC);
|
---|
| 204 |
|
---|
| 205 | const HEADER = {
|
---|
| 206 | className: 'section',
|
---|
| 207 | variants: [
|
---|
| 208 | {
|
---|
| 209 | begin: '^#{1,6}',
|
---|
| 210 | end: '$',
|
---|
| 211 | contains: CONTAINABLE
|
---|
| 212 | },
|
---|
| 213 | {
|
---|
| 214 | begin: '(?=^.+?\\n[=-]{2,}$)',
|
---|
| 215 | contains: [
|
---|
| 216 | {
|
---|
| 217 | begin: '^[=-]*$'
|
---|
| 218 | },
|
---|
| 219 | {
|
---|
| 220 | begin: '^',
|
---|
| 221 | end: "\\n",
|
---|
| 222 | contains: CONTAINABLE
|
---|
| 223 | }
|
---|
| 224 | ]
|
---|
| 225 | }
|
---|
| 226 | ]
|
---|
| 227 | };
|
---|
| 228 |
|
---|
| 229 | const BLOCKQUOTE = {
|
---|
| 230 | className: 'quote',
|
---|
| 231 | begin: '^>\\s+',
|
---|
| 232 | contains: CONTAINABLE,
|
---|
| 233 | end: '$'
|
---|
| 234 | };
|
---|
| 235 |
|
---|
| 236 | return {
|
---|
| 237 | name: 'Markdown',
|
---|
| 238 | aliases: [
|
---|
| 239 | 'md',
|
---|
| 240 | 'mkdown',
|
---|
| 241 | 'mkd'
|
---|
| 242 | ],
|
---|
| 243 | contains: [
|
---|
| 244 | HEADER,
|
---|
| 245 | INLINE_HTML,
|
---|
| 246 | LIST,
|
---|
| 247 | BOLD,
|
---|
| 248 | ITALIC,
|
---|
| 249 | BLOCKQUOTE,
|
---|
| 250 | CODE,
|
---|
| 251 | HORIZONTAL_RULE,
|
---|
| 252 | LINK,
|
---|
| 253 | LINK_REFERENCE
|
---|
| 254 | ]
|
---|
| 255 | };
|
---|
| 256 | }
|
---|
| 257 |
|
---|
| 258 | module.exports = markdown;
|
---|