1 | (function (Prism) {
|
---|
2 | // We don't allow for pipes inside parentheses
|
---|
3 | // to not break table pattern |(. foo |). bar |
|
---|
4 | var modifierRegex = /\([^|()\n]+\)|\[[^\]\n]+\]|\{[^}\n]+\}/.source;
|
---|
5 | // Opening and closing parentheses which are not a modifier
|
---|
6 | // This pattern is necessary to prevent exponential backtracking
|
---|
7 | var parenthesesRegex = /\)|\((?![^|()\n]+\))/.source;
|
---|
8 | /**
|
---|
9 | * @param {string} source
|
---|
10 | * @param {string} [flags]
|
---|
11 | */
|
---|
12 | function withModifier(source, flags) {
|
---|
13 | return RegExp(
|
---|
14 | source
|
---|
15 | .replace(/<MOD>/g, function () { return '(?:' + modifierRegex + ')'; })
|
---|
16 | .replace(/<PAR>/g, function () { return '(?:' + parenthesesRegex + ')'; }),
|
---|
17 | flags || '');
|
---|
18 | }
|
---|
19 |
|
---|
20 | var modifierTokens = {
|
---|
21 | 'css': {
|
---|
22 | pattern: /\{[^{}]+\}/,
|
---|
23 | inside: {
|
---|
24 | rest: Prism.languages.css
|
---|
25 | }
|
---|
26 | },
|
---|
27 | 'class-id': {
|
---|
28 | pattern: /(\()[^()]+(?=\))/,
|
---|
29 | lookbehind: true,
|
---|
30 | alias: 'attr-value'
|
---|
31 | },
|
---|
32 | 'lang': {
|
---|
33 | pattern: /(\[)[^\[\]]+(?=\])/,
|
---|
34 | lookbehind: true,
|
---|
35 | alias: 'attr-value'
|
---|
36 | },
|
---|
37 | // Anything else is punctuation (the first pattern is for row/col spans inside tables)
|
---|
38 | 'punctuation': /[\\\/]\d+|\S/
|
---|
39 | };
|
---|
40 |
|
---|
41 |
|
---|
42 | var textile = Prism.languages.textile = Prism.languages.extend('markup', {
|
---|
43 | 'phrase': {
|
---|
44 | pattern: /(^|\r|\n)\S[\s\S]*?(?=$|\r?\n\r?\n|\r\r)/,
|
---|
45 | lookbehind: true,
|
---|
46 | inside: {
|
---|
47 |
|
---|
48 | // h1. Header 1
|
---|
49 | 'block-tag': {
|
---|
50 | pattern: withModifier(/^[a-z]\w*(?:<MOD>|<PAR>|[<>=])*\./.source),
|
---|
51 | inside: {
|
---|
52 | 'modifier': {
|
---|
53 | pattern: withModifier(/(^[a-z]\w*)(?:<MOD>|<PAR>|[<>=])+(?=\.)/.source),
|
---|
54 | lookbehind: true,
|
---|
55 | inside: modifierTokens
|
---|
56 | },
|
---|
57 | 'tag': /^[a-z]\w*/,
|
---|
58 | 'punctuation': /\.$/
|
---|
59 | }
|
---|
60 | },
|
---|
61 |
|
---|
62 | // # List item
|
---|
63 | // * List item
|
---|
64 | 'list': {
|
---|
65 | pattern: withModifier(/^[*#]+<MOD>*\s+\S.*/.source, 'm'),
|
---|
66 | inside: {
|
---|
67 | 'modifier': {
|
---|
68 | pattern: withModifier(/(^[*#]+)<MOD>+/.source),
|
---|
69 | lookbehind: true,
|
---|
70 | inside: modifierTokens
|
---|
71 | },
|
---|
72 | 'punctuation': /^[*#]+/
|
---|
73 | }
|
---|
74 | },
|
---|
75 |
|
---|
76 | // | cell | cell | cell |
|
---|
77 | 'table': {
|
---|
78 | // Modifiers can be applied to the row: {color:red}.|1|2|3|
|
---|
79 | // or the cell: |{color:red}.1|2|3|
|
---|
80 | pattern: withModifier(/^(?:(?:<MOD>|<PAR>|[<>=^~])+\.\s*)?(?:\|(?:(?:<MOD>|<PAR>|[<>=^~_]|[\\/]\d+)+\.|(?!(?:<MOD>|<PAR>|[<>=^~_]|[\\/]\d+)+\.))[^|]*)+\|/.source, 'm'),
|
---|
81 | inside: {
|
---|
82 | 'modifier': {
|
---|
83 | // Modifiers for rows after the first one are
|
---|
84 | // preceded by a pipe and a line feed
|
---|
85 | pattern: withModifier(/(^|\|(?:\r?\n|\r)?)(?:<MOD>|<PAR>|[<>=^~_]|[\\/]\d+)+(?=\.)/.source),
|
---|
86 | lookbehind: true,
|
---|
87 | inside: modifierTokens
|
---|
88 | },
|
---|
89 | 'punctuation': /\||^\./
|
---|
90 | }
|
---|
91 | },
|
---|
92 |
|
---|
93 | 'inline': {
|
---|
94 | // eslint-disable-next-line regexp/no-super-linear-backtracking
|
---|
95 | pattern: withModifier(/(^|[^a-zA-Z\d])(\*\*|__|\?\?|[*_%@+\-^~])<MOD>*.+?\2(?![a-zA-Z\d])/.source),
|
---|
96 | lookbehind: true,
|
---|
97 | inside: {
|
---|
98 | // Note: superscripts and subscripts are not handled specifically
|
---|
99 |
|
---|
100 | // *bold*, **bold**
|
---|
101 | 'bold': {
|
---|
102 | // eslint-disable-next-line regexp/no-super-linear-backtracking
|
---|
103 | pattern: withModifier(/(^(\*\*?)<MOD>*).+?(?=\2)/.source),
|
---|
104 | lookbehind: true
|
---|
105 | },
|
---|
106 |
|
---|
107 | // _italic_, __italic__
|
---|
108 | 'italic': {
|
---|
109 | // eslint-disable-next-line regexp/no-super-linear-backtracking
|
---|
110 | pattern: withModifier(/(^(__?)<MOD>*).+?(?=\2)/.source),
|
---|
111 | lookbehind: true
|
---|
112 | },
|
---|
113 |
|
---|
114 | // ??cite??
|
---|
115 | 'cite': {
|
---|
116 | // eslint-disable-next-line regexp/no-super-linear-backtracking
|
---|
117 | pattern: withModifier(/(^\?\?<MOD>*).+?(?=\?\?)/.source),
|
---|
118 | lookbehind: true,
|
---|
119 | alias: 'string'
|
---|
120 | },
|
---|
121 |
|
---|
122 | // @code@
|
---|
123 | 'code': {
|
---|
124 | // eslint-disable-next-line regexp/no-super-linear-backtracking
|
---|
125 | pattern: withModifier(/(^@<MOD>*).+?(?=@)/.source),
|
---|
126 | lookbehind: true,
|
---|
127 | alias: 'keyword'
|
---|
128 | },
|
---|
129 |
|
---|
130 | // +inserted+
|
---|
131 | 'inserted': {
|
---|
132 | // eslint-disable-next-line regexp/no-super-linear-backtracking
|
---|
133 | pattern: withModifier(/(^\+<MOD>*).+?(?=\+)/.source),
|
---|
134 | lookbehind: true
|
---|
135 | },
|
---|
136 |
|
---|
137 | // -deleted-
|
---|
138 | 'deleted': {
|
---|
139 | // eslint-disable-next-line regexp/no-super-linear-backtracking
|
---|
140 | pattern: withModifier(/(^-<MOD>*).+?(?=-)/.source),
|
---|
141 | lookbehind: true
|
---|
142 | },
|
---|
143 |
|
---|
144 | // %span%
|
---|
145 | 'span': {
|
---|
146 | // eslint-disable-next-line regexp/no-super-linear-backtracking
|
---|
147 | pattern: withModifier(/(^%<MOD>*).+?(?=%)/.source),
|
---|
148 | lookbehind: true
|
---|
149 | },
|
---|
150 |
|
---|
151 | 'modifier': {
|
---|
152 | pattern: withModifier(/(^\*\*|__|\?\?|[*_%@+\-^~])<MOD>+/.source),
|
---|
153 | lookbehind: true,
|
---|
154 | inside: modifierTokens
|
---|
155 | },
|
---|
156 | 'punctuation': /[*_%?@+\-^~]+/
|
---|
157 | }
|
---|
158 | },
|
---|
159 |
|
---|
160 | // [alias]http://example.com
|
---|
161 | 'link-ref': {
|
---|
162 | pattern: /^\[[^\]]+\]\S+$/m,
|
---|
163 | inside: {
|
---|
164 | 'string': {
|
---|
165 | pattern: /(^\[)[^\]]+(?=\])/,
|
---|
166 | lookbehind: true
|
---|
167 | },
|
---|
168 | 'url': {
|
---|
169 | pattern: /(^\])\S+$/,
|
---|
170 | lookbehind: true
|
---|
171 | },
|
---|
172 | 'punctuation': /[\[\]]/
|
---|
173 | }
|
---|
174 | },
|
---|
175 |
|
---|
176 | // "text":http://example.com
|
---|
177 | // "text":link-ref
|
---|
178 | 'link': {
|
---|
179 | // eslint-disable-next-line regexp/no-super-linear-backtracking
|
---|
180 | pattern: withModifier(/"<MOD>*[^"]+":.+?(?=[^\w/]?(?:\s|$))/.source),
|
---|
181 | inside: {
|
---|
182 | 'text': {
|
---|
183 | // eslint-disable-next-line regexp/no-super-linear-backtracking
|
---|
184 | pattern: withModifier(/(^"<MOD>*)[^"]+(?=")/.source),
|
---|
185 | lookbehind: true
|
---|
186 | },
|
---|
187 | 'modifier': {
|
---|
188 | pattern: withModifier(/(^")<MOD>+/.source),
|
---|
189 | lookbehind: true,
|
---|
190 | inside: modifierTokens
|
---|
191 | },
|
---|
192 | 'url': {
|
---|
193 | pattern: /(:).+/,
|
---|
194 | lookbehind: true
|
---|
195 | },
|
---|
196 | 'punctuation': /[":]/
|
---|
197 | }
|
---|
198 | },
|
---|
199 |
|
---|
200 | // !image.jpg!
|
---|
201 | // !image.jpg(Title)!:http://example.com
|
---|
202 | 'image': {
|
---|
203 | pattern: withModifier(/!(?:<MOD>|<PAR>|[<>=])*(?![<>=])[^!\s()]+(?:\([^)]+\))?!(?::.+?(?=[^\w/]?(?:\s|$)))?/.source),
|
---|
204 | inside: {
|
---|
205 | 'source': {
|
---|
206 | pattern: withModifier(/(^!(?:<MOD>|<PAR>|[<>=])*)(?![<>=])[^!\s()]+(?:\([^)]+\))?(?=!)/.source),
|
---|
207 | lookbehind: true,
|
---|
208 | alias: 'url'
|
---|
209 | },
|
---|
210 | 'modifier': {
|
---|
211 | pattern: withModifier(/(^!)(?:<MOD>|<PAR>|[<>=])+/.source),
|
---|
212 | lookbehind: true,
|
---|
213 | inside: modifierTokens
|
---|
214 | },
|
---|
215 | 'url': {
|
---|
216 | pattern: /(:).+/,
|
---|
217 | lookbehind: true
|
---|
218 | },
|
---|
219 | 'punctuation': /[!:]/
|
---|
220 | }
|
---|
221 | },
|
---|
222 |
|
---|
223 | // Footnote[1]
|
---|
224 | 'footnote': {
|
---|
225 | pattern: /\b\[\d+\]/,
|
---|
226 | alias: 'comment',
|
---|
227 | inside: {
|
---|
228 | 'punctuation': /\[|\]/
|
---|
229 | }
|
---|
230 | },
|
---|
231 |
|
---|
232 | // CSS(Cascading Style Sheet)
|
---|
233 | 'acronym': {
|
---|
234 | pattern: /\b[A-Z\d]+\([^)]+\)/,
|
---|
235 | inside: {
|
---|
236 | 'comment': {
|
---|
237 | pattern: /(\()[^()]+(?=\))/,
|
---|
238 | lookbehind: true
|
---|
239 | },
|
---|
240 | 'punctuation': /[()]/
|
---|
241 | }
|
---|
242 | },
|
---|
243 |
|
---|
244 | // Prism(C)
|
---|
245 | 'mark': {
|
---|
246 | pattern: /\b\((?:C|R|TM)\)/,
|
---|
247 | alias: 'comment',
|
---|
248 | inside: {
|
---|
249 | 'punctuation': /[()]/
|
---|
250 | }
|
---|
251 | }
|
---|
252 | }
|
---|
253 | }
|
---|
254 | });
|
---|
255 |
|
---|
256 | var phraseInside = textile['phrase'].inside;
|
---|
257 | var nestedPatterns = {
|
---|
258 | 'inline': phraseInside['inline'],
|
---|
259 | 'link': phraseInside['link'],
|
---|
260 | 'image': phraseInside['image'],
|
---|
261 | 'footnote': phraseInside['footnote'],
|
---|
262 | 'acronym': phraseInside['acronym'],
|
---|
263 | 'mark': phraseInside['mark']
|
---|
264 | };
|
---|
265 |
|
---|
266 | // Only allow alpha-numeric HTML tags, not XML tags
|
---|
267 | textile.tag.pattern = /<\/?(?!\d)[a-z0-9]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i;
|
---|
268 |
|
---|
269 | // Allow some nesting
|
---|
270 | var phraseInlineInside = phraseInside['inline'].inside;
|
---|
271 | phraseInlineInside['bold'].inside = nestedPatterns;
|
---|
272 | phraseInlineInside['italic'].inside = nestedPatterns;
|
---|
273 | phraseInlineInside['inserted'].inside = nestedPatterns;
|
---|
274 | phraseInlineInside['deleted'].inside = nestedPatterns;
|
---|
275 | phraseInlineInside['span'].inside = nestedPatterns;
|
---|
276 |
|
---|
277 | // Allow some styles inside table cells
|
---|
278 | var phraseTableInside = phraseInside['table'].inside;
|
---|
279 | phraseTableInside['inline'] = nestedPatterns['inline'];
|
---|
280 | phraseTableInside['link'] = nestedPatterns['link'];
|
---|
281 | phraseTableInside['image'] = nestedPatterns['image'];
|
---|
282 | phraseTableInside['footnote'] = nestedPatterns['footnote'];
|
---|
283 | phraseTableInside['acronym'] = nestedPatterns['acronym'];
|
---|
284 | phraseTableInside['mark'] = nestedPatterns['mark'];
|
---|
285 |
|
---|
286 | }(Prism));
|
---|