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