UNPKG

7.29 kBJavaScriptView Raw
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+.+/.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+)+\.)?[^|]*)+\|/.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 pattern: withModifier(/(^|[^a-zA-Z\d])(\*\*|__|\?\?|[*_%@+\-^~])<MOD>*.+?\2(?![a-zA-Z\d])/.source),
95 lookbehind: true,
96 inside: {
97 // Note: superscripts and subscripts are not handled specifically
98
99 // *bold*, **bold**
100 'bold': {
101 pattern: withModifier(/(^(\*\*?)<MOD>*).+?(?=\2)/.source),
102 lookbehind: true
103 },
104
105 // _italic_, __italic__
106 'italic': {
107 pattern: withModifier(/(^(__?)<MOD>*).+?(?=\2)/.source),
108 lookbehind: true
109 },
110
111 // ??cite??
112 'cite': {
113 pattern: withModifier(/(^\?\?<MOD>*).+?(?=\?\?)/.source),
114 lookbehind: true,
115 alias: 'string'
116 },
117
118 // @code@
119 'code': {
120 pattern: withModifier(/(^@<MOD>*).+?(?=@)/.source),
121 lookbehind: true,
122 alias: 'keyword'
123 },
124
125 // +inserted+
126 'inserted': {
127 pattern: withModifier(/(^\+<MOD>*).+?(?=\+)/.source),
128 lookbehind: true
129 },
130
131 // -deleted-
132 'deleted': {
133 pattern: withModifier(/(^-<MOD>*).+?(?=-)/.source),
134 lookbehind: true
135 },
136
137 // %span%
138 'span': {
139 pattern: withModifier(/(^%<MOD>*).+?(?=%)/.source),
140 lookbehind: true
141 },
142
143 'modifier': {
144 pattern: withModifier(/(^\*\*|__|\?\?|[*_%@+\-^~])<MOD>+/.source),
145 lookbehind: true,
146 inside: modifierTokens
147 },
148 'punctuation': /[*_%?@+\-^~]+/
149 }
150 },
151
152 // [alias]http://example.com
153 'link-ref': {
154 pattern: /^\[[^\]]+\]\S+$/m,
155 inside: {
156 'string': {
157 pattern: /(\[)[^\]]+(?=\])/,
158 lookbehind: true
159 },
160 'url': {
161 pattern: /(\])\S+$/,
162 lookbehind: true
163 },
164 'punctuation': /[\[\]]/
165 }
166 },
167
168 // "text":http://example.com
169 // "text":link-ref
170 'link': {
171 pattern: withModifier(/"<MOD>*[^"]+":.+?(?=[^\w/]?(?:\s|$))/.source),
172 inside: {
173 'text': {
174 pattern: withModifier(/(^"<MOD>*)[^"]+(?=")/.source),
175 lookbehind: true
176 },
177 'modifier': {
178 pattern: withModifier(/(^")<MOD>+/.source),
179 lookbehind: true,
180 inside: modifierTokens
181 },
182 'url': {
183 pattern: /(:).+/,
184 lookbehind: true
185 },
186 'punctuation': /[":]/
187 }
188 },
189
190 // !image.jpg!
191 // !image.jpg(Title)!:http://example.com
192 'image': {
193 pattern: withModifier(/!(?:<MOD>|<PAR>|[<>=])*[^!\s()]+(?:\([^)]+\))?!(?::.+?(?=[^\w/]?(?:\s|$)))?/.source),
194 inside: {
195 'source': {
196 pattern: withModifier(/(^!(?:<MOD>|<PAR>|[<>=])*)[^!\s()]+(?:\([^)]+\))?(?=!)/.source),
197 lookbehind: true,
198 alias: 'url'
199 },
200 'modifier': {
201 pattern: withModifier(/(^!)(?:<MOD>|<PAR>|[<>=])+/.source),
202 lookbehind: true,
203 inside: modifierTokens
204 },
205 'url': {
206 pattern: /(:).+/,
207 lookbehind: true
208 },
209 'punctuation': /[!:]/
210 }
211 },
212
213 // Footnote[1]
214 'footnote': {
215 pattern: /\b\[\d+\]/,
216 alias: 'comment',
217 inside: {
218 'punctuation': /\[|\]/
219 }
220 },
221
222 // CSS(Cascading Style Sheet)
223 'acronym': {
224 pattern: /\b[A-Z\d]+\([^)]+\)/,
225 inside: {
226 'comment': {
227 pattern: /(\()[^)]+(?=\))/,
228 lookbehind: true
229 },
230 'punctuation': /[()]/
231 }
232 },
233
234 // Prism(C)
235 'mark': {
236 pattern: /\b\((?:TM|R|C)\)/,
237 alias: 'comment',
238 inside: {
239 'punctuation': /[()]/
240 }
241 }
242 }
243 }
244 });
245
246 var phraseInside = textile['phrase'].inside;
247 var nestedPatterns = {
248 'inline': phraseInside['inline'],
249 'link': phraseInside['link'],
250 'image': phraseInside['image'],
251 'footnote': phraseInside['footnote'],
252 'acronym': phraseInside['acronym'],
253 'mark': phraseInside['mark']
254 };
255
256 // Only allow alpha-numeric HTML tags, not XML tags
257 textile.tag.pattern = /<\/?(?!\d)[a-z0-9]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i;
258
259 // Allow some nesting
260 var phraseInlineInside = phraseInside['inline'].inside;
261 phraseInlineInside['bold'].inside = nestedPatterns;
262 phraseInlineInside['italic'].inside = nestedPatterns;
263 phraseInlineInside['inserted'].inside = nestedPatterns;
264 phraseInlineInside['deleted'].inside = nestedPatterns;
265 phraseInlineInside['span'].inside = nestedPatterns;
266
267 // Allow some styles inside table cells
268 var phraseTableInside = phraseInside['table'].inside;
269 phraseTableInside['inline'] = nestedPatterns['inline'];
270 phraseTableInside['link'] = nestedPatterns['link'];
271 phraseTableInside['image'] = nestedPatterns['image'];
272 phraseTableInside['footnote'] = nestedPatterns['footnote'];
273 phraseTableInside['acronym'] = nestedPatterns['acronym'];
274 phraseTableInside['mark'] = nestedPatterns['mark'];
275
276}(Prism));