@bhsd/codemirror-mediawiki 1.1.12 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +1 -0
- package/mediawiki.css +34 -24
- package/package.json +25 -12
- package/config.json +0 -388
- package/mediawiki.js +0 -917
package/mediawiki.js
DELETED
|
@@ -1,917 +0,0 @@
|
|
|
1
|
-
( function ( CodeMirror ) {
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
const permittedHtmlTags = new Set( [
|
|
5
|
-
'b', 'bdi', 'bdo', 'del', 'i', 'ins', 'img', 'u', 'font', 'big', 'small', 'sub', 'sup', 'h1', 'h2', 'h3',
|
|
6
|
-
'h4', 'h5', 'h6', 'cite', 'code', 'em', 's', 'strike', 'strong', 'tt', 'var', 'div', 'center', 'blockquote',
|
|
7
|
-
'q', 'ol', 'ul', 'dl', 'table', 'caption', 'pre', 'ruby', 'rb', 'rp', 'rt', 'rtc', 'p', 'span', 'abbr',
|
|
8
|
-
'dfn', 'kbd', 'samp', 'data', 'time', 'mark', 'br', 'wbr', 'hr', 'li', 'dt', 'dd', 'td', 'th', 'tr',
|
|
9
|
-
'noinclude', 'includeonly', 'onlyinclude', 'translate'
|
|
10
|
-
] ),
|
|
11
|
-
voidHtmlTags = new Set( [ 'br', 'hr', 'wbr', 'img' ] ),
|
|
12
|
-
span = typeof document === 'object' && document.createElement( 'span' ); // used for isEntity()
|
|
13
|
-
let mwConfig, urlProtocols;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* add background
|
|
17
|
-
*/
|
|
18
|
-
function makeLocalStyle( style, state, endGround ) {
|
|
19
|
-
let ground = '';
|
|
20
|
-
switch ( state.nTemplate ) {
|
|
21
|
-
case 0:
|
|
22
|
-
break;
|
|
23
|
-
case 1:
|
|
24
|
-
ground += '-template';
|
|
25
|
-
break;
|
|
26
|
-
case 2:
|
|
27
|
-
ground += '-template2';
|
|
28
|
-
break;
|
|
29
|
-
default:
|
|
30
|
-
ground += '-template3';
|
|
31
|
-
}
|
|
32
|
-
switch ( state.nExt ) {
|
|
33
|
-
case 0:
|
|
34
|
-
break;
|
|
35
|
-
case 1:
|
|
36
|
-
ground += '-ext';
|
|
37
|
-
break;
|
|
38
|
-
case 2:
|
|
39
|
-
ground += '-ext2';
|
|
40
|
-
break;
|
|
41
|
-
default:
|
|
42
|
-
ground += '-ext3';
|
|
43
|
-
}
|
|
44
|
-
if ( state.nLink > 0 ) {
|
|
45
|
-
ground += '-link';
|
|
46
|
-
}
|
|
47
|
-
if ( endGround ) {
|
|
48
|
-
state[ endGround ]--;
|
|
49
|
-
}
|
|
50
|
-
return style + ( ground && ` mw${ ground }-ground` );
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function makeStyle( style, state, endGround ) {
|
|
54
|
-
return makeLocalStyle( style + ( state.isBold ? ' strong' : '' ), state, endGround );
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function isEntity( str ) {
|
|
58
|
-
if ( !span ) {
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
span.innerHTML = str;
|
|
62
|
-
return span.textContent.length === 1;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* simply eat HTML entities
|
|
67
|
-
*/
|
|
68
|
-
function eatMnemonic( stream, style ) {
|
|
69
|
-
// no dangerous character should appear in results
|
|
70
|
-
const entity = stream.match( /^(?:#x[a-f\d]+|#\d+|[a-z\d]+);/i );
|
|
71
|
-
return entity && isEntity( `&${ entity[ 0 ] }` ) ? `${ style } mw-mnemonic` : style;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* simply eat until a block ends with specified terminator
|
|
76
|
-
*/
|
|
77
|
-
function eatBlock( style, terminator ) {
|
|
78
|
-
return function ( stream, state ) {
|
|
79
|
-
if ( !stream.skipTo( terminator ) ) {
|
|
80
|
-
stream.skipToEnd();
|
|
81
|
-
} else {
|
|
82
|
-
stream.match( terminator );
|
|
83
|
-
state.tokenize = state.stack.pop();
|
|
84
|
-
}
|
|
85
|
-
return makeLocalStyle( style, state );
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* simply eat until the end of line
|
|
91
|
-
*/
|
|
92
|
-
function eatEnd( style ) {
|
|
93
|
-
return function ( stream, state ) {
|
|
94
|
-
stream.skipToEnd();
|
|
95
|
-
state.tokenize = state.stack.pop();
|
|
96
|
-
return makeLocalStyle( style, state );
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* simply eat characters if they must be there
|
|
102
|
-
*/
|
|
103
|
-
function eatChars( n, style ) {
|
|
104
|
-
return function ( stream, state ) {
|
|
105
|
-
for ( let i = 0; i < n; i++ ) {
|
|
106
|
-
stream.next();
|
|
107
|
-
}
|
|
108
|
-
state.tokenize = state.stack.pop();
|
|
109
|
-
return makeLocalStyle( style, state );
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function eatWikiText( style ) {
|
|
114
|
-
return function ( stream, state ) {
|
|
115
|
-
let tmp, mt, name, isCloseTag, tagname;
|
|
116
|
-
const sol = stream.sol();
|
|
117
|
-
|
|
118
|
-
if ( sol ) { // reset bold status in every new line
|
|
119
|
-
state.isBold = false;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if ( stream.match( '//' ) ) {
|
|
123
|
-
return makeStyle( style, state );
|
|
124
|
-
} else if ( stream.match( urlProtocols ) ) { // highlight free external links, bug T108448
|
|
125
|
-
state.stack.push( state.tokenize );
|
|
126
|
-
state.tokenize = eatFreeExternalLink;
|
|
127
|
-
state.lpar = false;
|
|
128
|
-
return makeStyle( 'mw-free-extlink-protocol', state );
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const ch = stream.next();
|
|
132
|
-
if ( sol ) {
|
|
133
|
-
switch ( ch ) {
|
|
134
|
-
case '-':
|
|
135
|
-
if ( stream.match( /^-{3,}/ ) ) {
|
|
136
|
-
return 'mw-hr';
|
|
137
|
-
}
|
|
138
|
-
break;
|
|
139
|
-
case '=':
|
|
140
|
-
tmp = stream.match( /^(={0,5})(.+?(=\1\s*))$/u );
|
|
141
|
-
if ( tmp ) { // Title
|
|
142
|
-
stream.backUp( tmp[ 2 ].length );
|
|
143
|
-
state.stack.push( state.tokenize );
|
|
144
|
-
state.tokenize = eatSectionHeader( tmp[ 3 ].length );
|
|
145
|
-
return makeLocalStyle( `mw-section-header line-cm-mw-section-${ tmp[ 1 ].length + 1 }`, state );
|
|
146
|
-
}
|
|
147
|
-
break;
|
|
148
|
-
case '*':
|
|
149
|
-
case '#':
|
|
150
|
-
mt = stream.match( /^[*#;:]*/ );
|
|
151
|
-
if ( mt[ 0 ].includes( ';' ) ) {
|
|
152
|
-
state.isBold = true;
|
|
153
|
-
}
|
|
154
|
-
return makeLocalStyle( 'mw-list', state );
|
|
155
|
-
case ';':
|
|
156
|
-
state.isBold = true;
|
|
157
|
-
stream.match( /^[*#;:]*/ );
|
|
158
|
-
return makeLocalStyle( 'mw-list', state );
|
|
159
|
-
case ':':
|
|
160
|
-
if ( mt = stream.match( /^:*\s*(\{\||\{\{\{\s*!\s*\}\}|\{\{\s*\(!\s*\}\})/u ) ) { // Highlight indented tables :{|, bug T108454
|
|
161
|
-
const [ , { length } ] = mt;
|
|
162
|
-
state.stack.push( state.tokenize );
|
|
163
|
-
state.tokenize = eatStartTable( length );
|
|
164
|
-
stream.backUp( length );
|
|
165
|
-
return makeLocalStyle( 'mw-list', state );
|
|
166
|
-
}
|
|
167
|
-
mt = stream.match( /^[*#;:]*/ );
|
|
168
|
-
if ( mt[ 0 ].includes( ';' ) ) {
|
|
169
|
-
state.isBold = true;
|
|
170
|
-
}
|
|
171
|
-
return makeLocalStyle( 'mw-list', state );
|
|
172
|
-
case ' ':
|
|
173
|
-
if ( mt = stream.match( /^\s*(:+\s*)?(\{\||\{\{\{\s*!\s*\}\}|\{\{\s*\(!\s*\}\})/u ) ) { // Leading spaces is the correct syntax for a table, bug T108454
|
|
174
|
-
if ( mt[ 1 ] ) { // ::{|
|
|
175
|
-
const [ ,, { length } ] = mt;
|
|
176
|
-
state.stack.push( state.tokenize );
|
|
177
|
-
state.tokenize = eatStartTable( length );
|
|
178
|
-
stream.backUp( length );
|
|
179
|
-
return makeLocalStyle( 'mw-list', state );
|
|
180
|
-
}
|
|
181
|
-
state.stack.push( state.tokenize );
|
|
182
|
-
state.tokenize = inTableDefinition;
|
|
183
|
-
return makeLocalStyle( 'mw-table-bracket', state );
|
|
184
|
-
}
|
|
185
|
-
return 'mw-skipformatting';
|
|
186
|
-
case '{':
|
|
187
|
-
if ( stream.match( /^(?:\||\{\{\s*!\s*\}\}|\{\s*\(!\s*\}\})\s*/u ) ) {
|
|
188
|
-
state.stack.push( state.tokenize );
|
|
189
|
-
state.tokenize = inTableDefinition;
|
|
190
|
-
return makeLocalStyle( 'mw-table-bracket', state );
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
switch ( ch ) {
|
|
196
|
-
case '&':
|
|
197
|
-
return makeStyle( eatMnemonic( stream, style ), state );
|
|
198
|
-
case '\'':
|
|
199
|
-
if ( stream.match( /^'*(?='{5})/ ) || stream.match( /^'''(?!')/, false ) ) { // skip the irrelevant apostrophes ( >5 or =4 )
|
|
200
|
-
break;
|
|
201
|
-
} else if ( stream.match( '\'\'' ) ) { // bold
|
|
202
|
-
return makeLocalStyle( 'mw-apostrophes-bold', state );
|
|
203
|
-
} else if ( stream.eat( '\'' ) ) { // italic
|
|
204
|
-
return makeLocalStyle( 'mw-apostrophes-italic', state );
|
|
205
|
-
}
|
|
206
|
-
break;
|
|
207
|
-
case '[':
|
|
208
|
-
if ( stream.eat( '[' ) ) { // Link Example: [[ Foo | Bar ]]
|
|
209
|
-
stream.eatSpace();
|
|
210
|
-
if ( /[^\]|[]/.test( stream.peek() ) ) {
|
|
211
|
-
state.nLink++;
|
|
212
|
-
state.stack.push( state.tokenize );
|
|
213
|
-
const nsIds = typeof mw === 'object' ? mw.config.get( 'wgNamespaceIds' ) : { File: 6 },
|
|
214
|
-
nsFile = Object.keys( nsIds ).filter( function ( ns ) {
|
|
215
|
-
return nsIds[ ns ] === 6;
|
|
216
|
-
} ).join( '|' ),
|
|
217
|
-
nsFileRegex = new RegExp( `^\\s*(${ nsFile })\\s*:`, 'iu' );
|
|
218
|
-
state.tokenize = stream.match( nsFileRegex, false ) ? inFileLink : inLink;
|
|
219
|
-
return makeLocalStyle( 'mw-link-bracket', state );
|
|
220
|
-
}
|
|
221
|
-
} else {
|
|
222
|
-
mt = stream.match( urlProtocols, false );
|
|
223
|
-
if ( mt ) {
|
|
224
|
-
state.nLink++;
|
|
225
|
-
state.stack.push( state.tokenize );
|
|
226
|
-
state.tokenize = eatExternalLinkProtocol( mt[ 0 ].length );
|
|
227
|
-
return makeLocalStyle( 'mw-extlink-bracket', state );
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
break;
|
|
231
|
-
case '{':
|
|
232
|
-
if ( !stream.match( '{{{{', false ) && stream.match( '{{' ) ) { // Template parameter (skip parameters inside a template transclusion, Bug: T108450)
|
|
233
|
-
stream.eatSpace();
|
|
234
|
-
state.stack.push( state.tokenize );
|
|
235
|
-
state.tokenize = inVariable;
|
|
236
|
-
return makeLocalStyle( 'mw-templatevariable-bracket', state );
|
|
237
|
-
} else if ( stream.match( /^\{\s*/u ) ) {
|
|
238
|
-
if ( stream.peek() === '#' ) { // Parser function
|
|
239
|
-
state.nExt++;
|
|
240
|
-
state.stack.push( state.tokenize );
|
|
241
|
-
state.tokenize = inParserFunctionName;
|
|
242
|
-
return makeLocalStyle( 'mw-parserfunction-bracket', state );
|
|
243
|
-
}
|
|
244
|
-
// Check for parser function without '#'
|
|
245
|
-
name = stream.match( /^([^\s}[\]<{'|&:]+)(:|\s*)(\}\}?)?(.)?/u, false );
|
|
246
|
-
if ( name ) {
|
|
247
|
-
if ( ( name[ 2 ] === ':' || name[ 4 ] === undefined || name[ 3 ] === '}}' ) && ( name[ 1 ].toLowerCase() in mwConfig.functionSynonyms[ 0 ] || name[ 1 ] in mwConfig.functionSynonyms[ 1 ] ) ) {
|
|
248
|
-
state.nExt++;
|
|
249
|
-
state.stack.push( state.tokenize );
|
|
250
|
-
state.tokenize = inParserFunctionName;
|
|
251
|
-
return makeLocalStyle( 'mw-parserfunction-bracket', state );
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
// Template
|
|
255
|
-
state.nTemplate++;
|
|
256
|
-
state.stack.push( state.tokenize );
|
|
257
|
-
state.tokenize = eatTemplatePageName( false );
|
|
258
|
-
return makeLocalStyle( 'mw-template-bracket', state );
|
|
259
|
-
}
|
|
260
|
-
break;
|
|
261
|
-
case '<':
|
|
262
|
-
isCloseTag = Boolean( stream.eat( '/' ) );
|
|
263
|
-
tagname = stream.match( /^[^>/\s.*,[\]{}$^+?|\\'`~<=!@#%&()-]+/u, false );
|
|
264
|
-
if ( stream.match( '!--' ) ) { // comment
|
|
265
|
-
state.stack.push( state.tokenize );
|
|
266
|
-
state.tokenize = eatBlock( 'mw-comment', '-->' );
|
|
267
|
-
return makeLocalStyle( 'mw-comment', state );
|
|
268
|
-
} else if ( tagname ) {
|
|
269
|
-
tagname = tagname[ 0 ].toLowerCase();
|
|
270
|
-
if ( tagname in mwConfig.tags ) { // Parser function
|
|
271
|
-
if ( isCloseTag === true ) {
|
|
272
|
-
// @todo message
|
|
273
|
-
return makeLocalStyle( 'error', state );
|
|
274
|
-
}
|
|
275
|
-
state.stack.push( state.tokenize );
|
|
276
|
-
state.tokenize = eatTagName( tagname.length, isCloseTag, false );
|
|
277
|
-
return makeLocalStyle( 'mw-exttag-bracket', state );
|
|
278
|
-
} else if ( permittedHtmlTags.has( tagname ) ) { // Html tag
|
|
279
|
-
if ( isCloseTag === true && tagname !== state.InHtmlTag.pop() ) {
|
|
280
|
-
// @todo message
|
|
281
|
-
return makeLocalStyle( 'error', state );
|
|
282
|
-
} else if ( isCloseTag === true && voidHtmlTags.has( tagname ) ) {
|
|
283
|
-
// @todo message
|
|
284
|
-
return makeLocalStyle( 'error', state );
|
|
285
|
-
}
|
|
286
|
-
state.stack.push( state.tokenize );
|
|
287
|
-
// || ( voidHtmlTags.has( tagname ) ) because opening void tags should also be treated as the closing tag.
|
|
288
|
-
state.tokenize = eatTagName( tagname.length, isCloseTag || voidHtmlTags.has( tagname ), true );
|
|
289
|
-
return makeLocalStyle( 'mw-htmltag-bracket', state );
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
break;
|
|
293
|
-
case '~':
|
|
294
|
-
if ( stream.match( /^~{2,4}/ ) ) {
|
|
295
|
-
return 'mw-signature';
|
|
296
|
-
}
|
|
297
|
-
break;
|
|
298
|
-
case '_': // Maybe double undescored Magic Word as __TOC__
|
|
299
|
-
tmp = 1;
|
|
300
|
-
while ( stream.eat( '_' ) ) { // Optimize processing of many underscore symbols
|
|
301
|
-
tmp++;
|
|
302
|
-
}
|
|
303
|
-
if ( tmp > 2 ) { // Many underscore symbols
|
|
304
|
-
if ( !stream.eol() ) {
|
|
305
|
-
stream.backUp( 2 ); // Leave last two underscore symbols for processing again in next iteration
|
|
306
|
-
}
|
|
307
|
-
return makeStyle( style, state ); // Optimization: skip regex function at the end for EOL and backuped symbols
|
|
308
|
-
} else if ( tmp === 2 ) { // Check on double underscore Magic Word
|
|
309
|
-
name = stream.match( /^\w+__/ ); // The same as the end of function except '_' inside and with '__' at the end of string
|
|
310
|
-
if ( name ) {
|
|
311
|
-
const behavior = `__${ name[ 0 ] }`;
|
|
312
|
-
if ( behavior.toLowerCase() in mwConfig.doubleUnderscore[ 0 ] || behavior in mwConfig.doubleUnderscore[ 1 ] ) {
|
|
313
|
-
return 'mw-doubleUnderscore';
|
|
314
|
-
} else if ( !stream.eol() ) {
|
|
315
|
-
stream.backUp( 2 ); // Two underscore symbols at the end can be begining of other double undescored Magic Word
|
|
316
|
-
}
|
|
317
|
-
return makeStyle( style, state ); // Optimization: skip regex function at the end for EOL and backuped symbols
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
if ( /[\p{L}\d_]/u.test( ch ) || !/[a-z]/i.test( stream.peek() ) ) {
|
|
322
|
-
stream.match( /^.*?(?=[&'[\]{}<>~"/|=!-]|__|[^\p{L}\d_][a-z])/iu );
|
|
323
|
-
}
|
|
324
|
-
return makeStyle( style, state );
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
function eatFreeExternalLink( stream, state ) {
|
|
329
|
-
let mt;
|
|
330
|
-
if ( stream.eol() ) {
|
|
331
|
-
// @todo error message
|
|
332
|
-
} else if ( mt = stream.match( /^[^[\]<>"\0-\x1F\x7F\p{Zs}\uFFFD~{'),;.:!?]+/u ) ) {
|
|
333
|
-
state.lpar = state.lpar || mt[ 0 ].includes( '(' );
|
|
334
|
-
return makeStyle( 'mw-free-extlink', state );
|
|
335
|
-
} else {
|
|
336
|
-
const ch = stream.next(),
|
|
337
|
-
next = stream.peek();
|
|
338
|
-
switch ( ch ) {
|
|
339
|
-
case '~': {
|
|
340
|
-
if ( next !== '~' ) {
|
|
341
|
-
return makeStyle( 'mw-free-extlink', state );
|
|
342
|
-
}
|
|
343
|
-
stream.next();
|
|
344
|
-
if ( stream.peek() !== '~' ) {
|
|
345
|
-
return makeStyle( 'mw-free-extlink', state );
|
|
346
|
-
}
|
|
347
|
-
stream.backUp( 1 );
|
|
348
|
-
break;
|
|
349
|
-
}
|
|
350
|
-
case '{':
|
|
351
|
-
if ( next !== '{' ) {
|
|
352
|
-
return makeStyle( 'mw-free-extlink', state );
|
|
353
|
-
}
|
|
354
|
-
break;
|
|
355
|
-
case '\'':
|
|
356
|
-
if ( next !== '\'' ) {
|
|
357
|
-
return makeStyle( 'mw-free-extlink', state );
|
|
358
|
-
}
|
|
359
|
-
break;
|
|
360
|
-
case ')':
|
|
361
|
-
if ( state.lpar ) {
|
|
362
|
-
return makeStyle( 'mw-free-extlink', state );
|
|
363
|
-
}
|
|
364
|
-
// fall through
|
|
365
|
-
case ',':
|
|
366
|
-
case ';':
|
|
367
|
-
case '.':
|
|
368
|
-
case ':':
|
|
369
|
-
case '!':
|
|
370
|
-
case '?':
|
|
371
|
-
if ( mt = stream.match( /^[),;.:!?]*(?:[^[\]<>"\0-\x1F\x7F\p{Zs}\uFFFD~{'),;.:!?]+|~{1,2}(?!~)|\{(?!\{)|'(?!'))/u ) ) {
|
|
372
|
-
state.lpar = state.lpar || mt[ 0 ].includes( '(' );
|
|
373
|
-
return makeStyle( 'mw-free-extlink', state );
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
stream.backUp( 1 );
|
|
378
|
-
state.tokenize = state.stack.pop();
|
|
379
|
-
return makeStyle( 'mw-free-extlink', state );
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
function eatSectionHeader( count ) {
|
|
383
|
-
return function ( stream, state ) {
|
|
384
|
-
if ( stream.match( /^[^&<[{~_']+/ ) ) {
|
|
385
|
-
if ( stream.eol() ) {
|
|
386
|
-
stream.backUp( count );
|
|
387
|
-
state.tokenize = eatEnd( 'mw-section-header' );
|
|
388
|
-
}
|
|
389
|
-
return makeLocalStyle( '', state );
|
|
390
|
-
}
|
|
391
|
-
return eatWikiText( '' )( stream, state );
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
function eatStartTable( n ) {
|
|
396
|
-
return function ( stream, state ) {
|
|
397
|
-
for ( let i = 0; i < n; i++ ) {
|
|
398
|
-
stream.next();
|
|
399
|
-
}
|
|
400
|
-
state.tokenize = inTableDefinition;
|
|
401
|
-
return makeLocalStyle( 'mw-table-bracket', state );
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
function inTableDefinition( stream, state ) {
|
|
406
|
-
if ( stream.sol() ) {
|
|
407
|
-
state.tokenize = inTable;
|
|
408
|
-
return inTable( stream, state );
|
|
409
|
-
}
|
|
410
|
-
return eatWikiText( 'mw-table-definition' )( stream, state );
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
function inTable( stream, state ) {
|
|
414
|
-
if ( stream.sol() ) {
|
|
415
|
-
stream.eatSpace();
|
|
416
|
-
if ( stream.match( /^\{\{\s*!-\s*\}\}-*\s*/u ) ) {
|
|
417
|
-
state.tokenize = inTableDefinition;
|
|
418
|
-
return makeLocalStyle( 'mw-table-delimiter', state );
|
|
419
|
-
} else if ( stream.match( /^\{\{\s*!\)\s*\}\}/u ) ) {
|
|
420
|
-
state.tokenize = state.stack.pop();
|
|
421
|
-
return makeLocalStyle( 'mw-table-bracket', state );
|
|
422
|
-
} else if ( stream.match( /^(?:\||\{\{\s*!\s*\}\})/u ) ) {
|
|
423
|
-
if ( stream.match( /^-+\s*/u ) ) {
|
|
424
|
-
state.tokenize = inTableDefinition;
|
|
425
|
-
return makeLocalStyle( 'mw-table-delimiter', state );
|
|
426
|
-
} else if ( stream.eat( '+' ) ) {
|
|
427
|
-
stream.eatSpace();
|
|
428
|
-
state.tokenize = inTableCaption;
|
|
429
|
-
return makeLocalStyle( 'mw-table-delimiter', state );
|
|
430
|
-
} else if ( stream.eat( '}' ) ) {
|
|
431
|
-
state.tokenize = state.stack.pop();
|
|
432
|
-
return makeLocalStyle( 'mw-table-bracket', state );
|
|
433
|
-
}
|
|
434
|
-
stream.eatSpace();
|
|
435
|
-
state.tokenize = eatTableRow( true, false );
|
|
436
|
-
return makeLocalStyle( 'mw-table-delimiter', state );
|
|
437
|
-
} else if ( stream.eat( '!' ) ) {
|
|
438
|
-
stream.eatSpace();
|
|
439
|
-
state.tokenize = eatTableRow( true, true );
|
|
440
|
-
return makeLocalStyle( 'mw-table-delimiter', state );
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
return eatWikiText( '' )( stream, state );
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
function inTableCaption( stream, state ) {
|
|
447
|
-
if ( stream.sol() && stream.match( /^\s*(?:[|!]|\{\{\s*![!)-]?\s*\}\})/u, false ) ) {
|
|
448
|
-
state.tokenize = inTable;
|
|
449
|
-
return inTable( stream, state );
|
|
450
|
-
}
|
|
451
|
-
return eatWikiText( 'mw-table-caption' )( stream, state );
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
function eatTableRow( expectAttr, isHead ) {
|
|
455
|
-
return function ( stream, state ) {
|
|
456
|
-
if ( stream.sol() ) {
|
|
457
|
-
if ( stream.match( /^\s*(?:[|!]|\{\{\s*![!)-]?\s*\}\})/u, false ) ) {
|
|
458
|
-
state.tokenize = inTable;
|
|
459
|
-
return inTable( stream, state );
|
|
460
|
-
}
|
|
461
|
-
} else if ( stream.match( /^[^'{[<&~!|]+/ ) ) {
|
|
462
|
-
return makeLocalStyle( isHead ? 'strong' : '', state );
|
|
463
|
-
} else if ( stream.match( /^(?:(?:\||\{\{\s*!\s*\}\}){2}|\{\{\s*!!\s*\}\})/u ) || isHead && stream.match( '!!' ) ) {
|
|
464
|
-
state.tokenize = eatTableRow( true, isHead );
|
|
465
|
-
return makeLocalStyle( 'mw-table-delimiter', state );
|
|
466
|
-
} else if ( expectAttr && stream.match( /^(?:\||\{\{\s*!\s*\}\})/u ) ) {
|
|
467
|
-
state.tokenize = eatTableRow( false, isHead );
|
|
468
|
-
return makeLocalStyle( 'mw-table-delimiter2', state );
|
|
469
|
-
}
|
|
470
|
-
return eatWikiText( isHead ? 'strong' : '' )( stream, state );
|
|
471
|
-
};
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
function inVariable( stream, state ) {
|
|
475
|
-
if ( stream.match( /^[^{}|]+/ ) ) {
|
|
476
|
-
return makeLocalStyle( 'mw-templatevariable-name', state );
|
|
477
|
-
} else if ( stream.eat( '|' ) ) {
|
|
478
|
-
state.tokenize = inVariableDefault;
|
|
479
|
-
return makeLocalStyle( 'mw-templatevariable-delimiter', state );
|
|
480
|
-
} else if ( stream.match( '}}}' ) ) {
|
|
481
|
-
state.tokenize = state.stack.pop();
|
|
482
|
-
return makeLocalStyle( 'mw-templatevariable-bracket', state );
|
|
483
|
-
} else if ( stream.match( '{{{' ) ) {
|
|
484
|
-
state.stack.push( state.tokenize );
|
|
485
|
-
return makeLocalStyle( 'mw-templatevariable-bracket', state );
|
|
486
|
-
}
|
|
487
|
-
stream.next();
|
|
488
|
-
return makeLocalStyle( 'mw-templatevariable-name', state );
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
function inVariableDefault( stream, state ) {
|
|
492
|
-
if ( stream.match( /^[^{}[<&~]+/ ) ) {
|
|
493
|
-
return makeLocalStyle( 'mw-templatevariable', state );
|
|
494
|
-
} else if ( stream.match( '}}}' ) ) {
|
|
495
|
-
state.tokenize = state.stack.pop();
|
|
496
|
-
return makeLocalStyle( 'mw-templatevariable-bracket', state );
|
|
497
|
-
}
|
|
498
|
-
return eatWikiText( 'mw-templatevariable' )( stream, state );
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
function inParserFunctionName( stream, state ) {
|
|
502
|
-
if ( stream.match( /^[^:}{~|<>[\]]+/ ) ) { // FIXME: {{#name}} and {{uc}} are wrong, must have ':'
|
|
503
|
-
return makeLocalStyle( 'mw-parserfunction-name', state );
|
|
504
|
-
} else if ( stream.eat( ':' ) ) {
|
|
505
|
-
state.tokenize = inParserFunctionArguments;
|
|
506
|
-
return makeLocalStyle( 'mw-parserfunction-delimiter', state );
|
|
507
|
-
} else if ( stream.match( '}}' ) ) {
|
|
508
|
-
state.tokenize = state.stack.pop();
|
|
509
|
-
return makeLocalStyle( 'mw-parserfunction-bracket', state, 'nExt' );
|
|
510
|
-
}
|
|
511
|
-
return eatWikiText( 'error' )( stream, state );
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
function inParserFunctionArguments( stream, state ) {
|
|
515
|
-
if ( stream.match( /^[^|}{[<&~]+/ ) ) {
|
|
516
|
-
return makeLocalStyle( 'mw-parserfunction', state );
|
|
517
|
-
} else if ( stream.eat( '|' ) ) {
|
|
518
|
-
return makeLocalStyle( 'mw-parserfunction-delimiter', state );
|
|
519
|
-
} else if ( stream.match( '}}' ) ) {
|
|
520
|
-
state.tokenize = state.stack.pop();
|
|
521
|
-
return makeLocalStyle( 'mw-parserfunction-bracket', state, 'nExt' );
|
|
522
|
-
}
|
|
523
|
-
return eatWikiText( 'mw-parserfunction' )( stream, state );
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
function eatTemplatePageName( haveAte ) {
|
|
527
|
-
return function ( stream, state ) {
|
|
528
|
-
if ( stream.match( /^\s*\|\s*/u ) ) {
|
|
529
|
-
state.tokenize = eatTemplateArgument( true );
|
|
530
|
-
return makeLocalStyle( 'mw-template-delimiter', state );
|
|
531
|
-
} else if ( stream.match( /^\s*\}\}/u ) ) {
|
|
532
|
-
state.tokenize = state.stack.pop();
|
|
533
|
-
return makeLocalStyle( 'mw-template-bracket', state, 'nTemplate' );
|
|
534
|
-
} else if ( stream.match( /^\s*<!--.*?-->/u ) ) {
|
|
535
|
-
return makeLocalStyle( 'mw-comment', state );
|
|
536
|
-
} else if ( haveAte && stream.sol() ) {
|
|
537
|
-
// @todo error message
|
|
538
|
-
state.nTemplate--;
|
|
539
|
-
state.tokenize = state.stack.pop();
|
|
540
|
-
return '';
|
|
541
|
-
} else if ( stream.match( /^\s*[^\s|&~#<>[\]{}]+/u ) ) {
|
|
542
|
-
state.tokenize = eatTemplatePageName( true );
|
|
543
|
-
return makeLocalStyle( 'mw-template-name mw-pagename', state );
|
|
544
|
-
} else if ( stream.eatSpace() ) {
|
|
545
|
-
return stream.eol()
|
|
546
|
-
? makeLocalStyle( 'mw-template-name', state )
|
|
547
|
-
: makeLocalStyle( 'mw-template-name mw-pagename', state );
|
|
548
|
-
} else if ( !stream.match( '{{', false ) && stream.eat( /[#<>[\]{}]/ ) ) {
|
|
549
|
-
return makeLocalStyle( 'error', state );
|
|
550
|
-
}
|
|
551
|
-
return eatWikiText( 'mw-template-name mw-pagename' )( stream, state );
|
|
552
|
-
};
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
function eatTemplateArgument( expectArgName ) {
|
|
556
|
-
return function ( stream, state ) {
|
|
557
|
-
if ( expectArgName && stream.eatWhile( /[^=|}{[<&~]/ ) ) {
|
|
558
|
-
if ( stream.eat( '=' ) ) {
|
|
559
|
-
state.tokenize = eatTemplateArgument( false );
|
|
560
|
-
return makeLocalStyle( 'mw-template-argument-name', state );
|
|
561
|
-
}
|
|
562
|
-
return makeLocalStyle( 'mw-template', state );
|
|
563
|
-
} else if ( stream.eatWhile( /[^|}{[<&~]/ ) ) {
|
|
564
|
-
return makeLocalStyle( 'mw-template', state );
|
|
565
|
-
} else if ( stream.eat( '|' ) ) {
|
|
566
|
-
state.tokenize = eatTemplateArgument( true );
|
|
567
|
-
return makeLocalStyle( 'mw-template-delimiter', state );
|
|
568
|
-
} else if ( stream.match( '}}' ) ) {
|
|
569
|
-
state.tokenize = state.stack.pop();
|
|
570
|
-
return makeLocalStyle( 'mw-template-bracket', state, 'nTemplate' );
|
|
571
|
-
}
|
|
572
|
-
return eatWikiText( 'mw-template' )( stream, state );
|
|
573
|
-
};
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
function eatExternalLinkProtocol( chars ) {
|
|
577
|
-
return function ( stream, state ) {
|
|
578
|
-
for ( let i = 0; i < chars; i++ ) {
|
|
579
|
-
stream.next();
|
|
580
|
-
}
|
|
581
|
-
if ( stream.eol() ) {
|
|
582
|
-
state.nLink--;
|
|
583
|
-
// @todo error message
|
|
584
|
-
state.tokenize = state.stack.pop();
|
|
585
|
-
} else {
|
|
586
|
-
state.tokenize = inExternalLink;
|
|
587
|
-
}
|
|
588
|
-
return makeLocalStyle( 'mw-extlink-protocol', state );
|
|
589
|
-
};
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
function inExternalLink( stream, state ) {
|
|
593
|
-
if ( stream.sol() ) {
|
|
594
|
-
state.nLink--;
|
|
595
|
-
// @todo error message
|
|
596
|
-
state.tokenize = state.stack.pop();
|
|
597
|
-
return '';
|
|
598
|
-
} else if ( stream.match( /^\s*\]/u ) ) {
|
|
599
|
-
state.tokenize = state.stack.pop();
|
|
600
|
-
return makeLocalStyle( 'mw-extlink-bracket', state, 'nLink' );
|
|
601
|
-
} else if ( stream.eatSpace() ) {
|
|
602
|
-
state.tokenize = inExternalLinkText;
|
|
603
|
-
return makeLocalStyle( '', state );
|
|
604
|
-
} else if ( stream.match( /^[^\s\]{&~']+/u ) || stream.eatSpace() ) {
|
|
605
|
-
if ( stream.peek() === '\'' ) {
|
|
606
|
-
if ( stream.match( '\'\'', false ) ) {
|
|
607
|
-
state.tokenize = inExternalLinkText;
|
|
608
|
-
} else {
|
|
609
|
-
stream.next();
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
return makeLocalStyle( 'mw-extlink', state );
|
|
613
|
-
}
|
|
614
|
-
return eatWikiText( 'mw-extlink' )( stream, state );
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
function inExternalLinkText( stream, state ) {
|
|
618
|
-
if ( stream.sol() ) {
|
|
619
|
-
state.nLink--;
|
|
620
|
-
// @todo error message
|
|
621
|
-
state.tokenize = state.stack.pop();
|
|
622
|
-
return '';
|
|
623
|
-
} else if ( stream.eat( ']' ) ) {
|
|
624
|
-
state.tokenize = state.stack.pop();
|
|
625
|
-
return makeLocalStyle( 'mw-extlink-bracket', state, 'nLink' );
|
|
626
|
-
} else if ( stream.match( /^[^'\]{&~<]+/ ) ) {
|
|
627
|
-
return makeStyle( 'mw-extlink-text', state );
|
|
628
|
-
}
|
|
629
|
-
return eatWikiText( 'mw-extlink-text' )( stream, state );
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
function inLink( stream, state ) {
|
|
633
|
-
if ( stream.sol() ) {
|
|
634
|
-
state.nLink--;
|
|
635
|
-
// @todo error message
|
|
636
|
-
state.tokenize = state.stack.pop();
|
|
637
|
-
return '';
|
|
638
|
-
} else if ( stream.match( /^\s*#\s*/u ) ) {
|
|
639
|
-
state.tokenize = inLinkToSection();
|
|
640
|
-
return makeLocalStyle( 'mw-link', state );
|
|
641
|
-
} else if ( stream.match( /^\s*\|\s*/u ) ) {
|
|
642
|
-
state.tokenize = eatLinkText();
|
|
643
|
-
return makeLocalStyle( 'mw-link-delimiter', state );
|
|
644
|
-
} else if ( stream.match( /^\s*\]\]/u ) ) {
|
|
645
|
-
state.tokenize = state.stack.pop();
|
|
646
|
-
return makeLocalStyle( 'mw-link-bracket', state, 'nLink' );
|
|
647
|
-
} else if ( stream.match( /^\s*[^\s|&~#<>[\]{}]+/u ) || stream.eatSpace() ) { // FIXME '{{' brokes Link, sample [[z{{page]]
|
|
648
|
-
return makeLocalStyle( 'mw-link-pagename mw-pagename', state );
|
|
649
|
-
} else if ( !stream.match( '{{', false ) && stream.eat( /[<>[\]{}]/ ) ) {
|
|
650
|
-
return makeLocalStyle( 'error', state );
|
|
651
|
-
}
|
|
652
|
-
return eatWikiText( 'mw-link-pagename mw-pagename' )( stream, state );
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
function inLinkToSection() {
|
|
656
|
-
return function ( stream, state ) {
|
|
657
|
-
if ( stream.sol() ) {
|
|
658
|
-
// @todo error message
|
|
659
|
-
state.nLink--;
|
|
660
|
-
state.tokenize = state.stack.pop();
|
|
661
|
-
return '';
|
|
662
|
-
} else if ( stream.match( /^[^|\]&~{}]+/ ) ) { // FIXME '{{' brokes Link, sample [[z{{page]]
|
|
663
|
-
return makeLocalStyle( 'mw-link-tosection', state );
|
|
664
|
-
} else if ( stream.eat( '|' ) ) {
|
|
665
|
-
state.tokenize = eatLinkText();
|
|
666
|
-
return makeLocalStyle( 'mw-link-delimiter', state );
|
|
667
|
-
} else if ( stream.match( ']]' ) ) {
|
|
668
|
-
state.tokenize = state.stack.pop();
|
|
669
|
-
return makeLocalStyle( 'mw-link-bracket', state, 'nLink' );
|
|
670
|
-
}
|
|
671
|
-
return eatWikiText( 'mw-link-tosection' )( stream, state );
|
|
672
|
-
};
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
function inFileLink( stream, state ) {
|
|
676
|
-
if ( stream.sol() ) {
|
|
677
|
-
state.nLink--;
|
|
678
|
-
// @todo error message
|
|
679
|
-
state.tokenize = state.stack.pop();
|
|
680
|
-
return '';
|
|
681
|
-
} else if ( stream.match( /^\s*\|\s*/u ) ) {
|
|
682
|
-
state.tokenize = eatLinkText( true );
|
|
683
|
-
return makeLocalStyle( 'mw-link-delimiter', state );
|
|
684
|
-
} else if ( stream.match( /^\s*\]\]/u ) ) {
|
|
685
|
-
state.tokenize = state.stack.pop();
|
|
686
|
-
return makeLocalStyle( 'mw-link-bracket', state, 'nLink' );
|
|
687
|
-
} else if ( stream.match( /^\s*[^\s|&~#<>[\]{}]+/u ) || stream.eatSpace() ) { // FIXME '{{' brokes Link, sample [[z{{page]]
|
|
688
|
-
return makeLocalStyle( 'mw-link-pagename mw-pagename', state );
|
|
689
|
-
} else if ( !stream.match( '{{', false ) && stream.eat( /[#<>[\]{}]/ ) ) {
|
|
690
|
-
return makeLocalStyle( 'error', state );
|
|
691
|
-
}
|
|
692
|
-
return eatWikiText( 'mw-link-pagename mw-pagename' )( stream, state );
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
function eatLinkText( isFile, bracketEaten ) {
|
|
696
|
-
return function ( stream, state ) {
|
|
697
|
-
const tmpstyle = 'mw-link-text',
|
|
698
|
-
regex = isFile ? /^[^'\]{&~<|[]+/ : /^[^'\]{&~<]+/;
|
|
699
|
-
if ( stream.match( ']]' ) ) {
|
|
700
|
-
if ( !bracketEaten && stream.peek() === ']' ) {
|
|
701
|
-
stream.backUp( 1 );
|
|
702
|
-
state.tokenize = eatLinkText( isFile, true );
|
|
703
|
-
return makeLocalStyle( tmpstyle, state );
|
|
704
|
-
}
|
|
705
|
-
state.tokenize = state.stack.pop();
|
|
706
|
-
return makeLocalStyle( 'mw-link-bracket', state, 'nLink' );
|
|
707
|
-
} else if ( isFile && stream.eat( '|' ) ) {
|
|
708
|
-
return makeLocalStyle( 'mw-link-delimiter', state );
|
|
709
|
-
} else if ( stream.match( '\'\'\'' ) ) {
|
|
710
|
-
return makeLocalStyle( 'mw-link-text mw-apostrophes-bold', state );
|
|
711
|
-
} else if ( stream.match( '\'\'' ) ) {
|
|
712
|
-
return makeLocalStyle( 'mw-link-text mw-apostrophes-italic', state );
|
|
713
|
-
} else if ( stream.match( regex ) ) {
|
|
714
|
-
return makeLocalStyle( tmpstyle, state );
|
|
715
|
-
}
|
|
716
|
-
return eatWikiText( tmpstyle )( stream, state );
|
|
717
|
-
};
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
function eatTagName( chars, isCloseTag, isHtmlTag ) {
|
|
721
|
-
return function ( stream, state ) {
|
|
722
|
-
let name = '';
|
|
723
|
-
for ( let i = 0; i < chars; i++ ) {
|
|
724
|
-
name += stream.next();
|
|
725
|
-
}
|
|
726
|
-
name = name.toLowerCase();
|
|
727
|
-
stream.eatSpace();
|
|
728
|
-
|
|
729
|
-
if ( isHtmlTag ) {
|
|
730
|
-
state.tokenize = eatHtmlTagAttribute( name, isCloseTag && !voidHtmlTags.has( name ) );
|
|
731
|
-
return makeLocalStyle( 'mw-htmltag-name', state );
|
|
732
|
-
} // it is the extension tag
|
|
733
|
-
if ( isCloseTag ) {
|
|
734
|
-
state.tokenize = eatChars( 1, 'mw-exttag-bracket' );
|
|
735
|
-
} else {
|
|
736
|
-
state.tokenize = eatExtTagAttribute( name );
|
|
737
|
-
}
|
|
738
|
-
return makeLocalStyle( 'mw-exttag-name', state );
|
|
739
|
-
};
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
function eatHtmlTagAttribute( name, isCloseTag ) {
|
|
743
|
-
const style = `mw-htmltag-attribute${ isCloseTag ? ' error' : '' }`;
|
|
744
|
-
return function ( stream, state ) {
|
|
745
|
-
if ( stream.match( /^[^>/<{&~]+/ ) ) {
|
|
746
|
-
return makeLocalStyle( style, state );
|
|
747
|
-
} else if ( stream.eat( '>' ) ) {
|
|
748
|
-
if ( !( voidHtmlTags.has( name ) || isCloseTag ) ) {
|
|
749
|
-
state.InHtmlTag.push( name );
|
|
750
|
-
}
|
|
751
|
-
state.tokenize = state.stack.pop();
|
|
752
|
-
return makeLocalStyle( 'mw-htmltag-bracket', state );
|
|
753
|
-
} else if ( stream.match( '/>' ) ) {
|
|
754
|
-
if ( !( voidHtmlTags.has( name ) || isCloseTag ) ) { // HTML5 standard
|
|
755
|
-
state.InHtmlTag.push( name );
|
|
756
|
-
}
|
|
757
|
-
state.tokenize = state.stack.pop();
|
|
758
|
-
return makeLocalStyle( `mw-htmltag-bracket${ voidHtmlTags.has( name ) ? '' : ' error' }`, state );
|
|
759
|
-
}
|
|
760
|
-
return eatWikiText( style )( stream, state );
|
|
761
|
-
};
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
function eatExtTagAttribute( name ) {
|
|
765
|
-
return function ( stream, state ) {
|
|
766
|
-
if ( stream.match( /^(?:"[^">]*"|'[^'>]*'|[^>/<{&~])+/ ) ) {
|
|
767
|
-
return makeLocalStyle( 'mw-exttag-attribute', state );
|
|
768
|
-
} else if ( stream.eat( '>' ) ) {
|
|
769
|
-
state.extName = name;
|
|
770
|
-
if ( name in mwConfig.tagModes ) {
|
|
771
|
-
state.extMode = CodeMirror.getMode( { mode: 'mediawiki', mwConfig }, mwConfig.tagModes[ name ] );
|
|
772
|
-
state.extState = CodeMirror.startState( state.extMode );
|
|
773
|
-
}
|
|
774
|
-
state.tokenize = eatExtTagArea( name );
|
|
775
|
-
return makeLocalStyle( 'mw-exttag-bracket', state );
|
|
776
|
-
} else if ( stream.match( '/>' ) ) {
|
|
777
|
-
state.tokenize = state.stack.pop();
|
|
778
|
-
return makeLocalStyle( 'mw-exttag-bracket', state );
|
|
779
|
-
}
|
|
780
|
-
return eatWikiText( 'mw-exttag-attribute' )( stream, state );
|
|
781
|
-
};
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
function eatExtTagArea( name ) {
|
|
785
|
-
return function ( stream, state ) {
|
|
786
|
-
const { pos: from } = stream,
|
|
787
|
-
pattern = new RegExp( `</${ name }\\s*>`, 'iu' ),
|
|
788
|
-
m = pattern.exec( from ? stream.string.slice( from ) : stream.string );
|
|
789
|
-
let origString = false,
|
|
790
|
-
to;
|
|
791
|
-
|
|
792
|
-
if ( m ) {
|
|
793
|
-
if ( m.index === 0 ) {
|
|
794
|
-
state.tokenize = eatExtCloseTag( name );
|
|
795
|
-
state.extName = false;
|
|
796
|
-
if ( state.extMode !== false ) {
|
|
797
|
-
state.extMode = false;
|
|
798
|
-
state.extState = false;
|
|
799
|
-
}
|
|
800
|
-
return state.tokenize( stream, state );
|
|
801
|
-
}
|
|
802
|
-
to = m.index + from;
|
|
803
|
-
origString = stream.string;
|
|
804
|
-
stream.string = origString.slice( 0, to );
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
state.stack.push( state.tokenize );
|
|
808
|
-
state.tokenize = eatExtTokens( origString );
|
|
809
|
-
return state.tokenize( stream, state );
|
|
810
|
-
};
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
function eatExtCloseTag( name ) {
|
|
814
|
-
return function ( stream, state ) {
|
|
815
|
-
stream.next(); // eat <
|
|
816
|
-
stream.next(); // eat /
|
|
817
|
-
state.tokenize = eatTagName( name.length, true, false );
|
|
818
|
-
return makeLocalStyle( 'mw-exttag-bracket', state );
|
|
819
|
-
};
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
function eatExtTokens( origString ) {
|
|
823
|
-
return function ( stream, state ) {
|
|
824
|
-
let ret;
|
|
825
|
-
if ( state.extMode === false ) {
|
|
826
|
-
ret = 'mw-exttag';
|
|
827
|
-
stream.skipToEnd();
|
|
828
|
-
} else {
|
|
829
|
-
ret = `mw-tag-${ state.extName } ${ state.extMode.token( stream, state.extState, origString === false ) }`;
|
|
830
|
-
}
|
|
831
|
-
if ( stream.eol() ) {
|
|
832
|
-
if ( origString !== false ) {
|
|
833
|
-
stream.string = origString;
|
|
834
|
-
}
|
|
835
|
-
state.tokenize = state.stack.pop();
|
|
836
|
-
}
|
|
837
|
-
return makeLocalStyle( ret, state );
|
|
838
|
-
};
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
CodeMirror.defineMode( 'mediawiki', function ( config /* , parserConfig */ ) {
|
|
842
|
-
( { mwConfig } = config );
|
|
843
|
-
urlProtocols = new RegExp( `^(?:${ mwConfig.urlProtocols })`, 'i' );
|
|
844
|
-
|
|
845
|
-
return {
|
|
846
|
-
startState() {
|
|
847
|
-
return {
|
|
848
|
-
tokenize: eatWikiText( '' ), stack: [], InHtmlTag: [], extName: false, extMode: false,
|
|
849
|
-
extState: false, nTemplate: 0, nLink: 0, nExt: 0, isBold: false, lpar: false
|
|
850
|
-
};
|
|
851
|
-
},
|
|
852
|
-
copyState( state ) {
|
|
853
|
-
return {
|
|
854
|
-
tokenize: state.tokenize,
|
|
855
|
-
stack: state.stack.concat( [] ),
|
|
856
|
-
InHtmlTag: state.InHtmlTag.concat( [] ),
|
|
857
|
-
extName: state.extName,
|
|
858
|
-
extMode: state.extMode,
|
|
859
|
-
extState: state.extMode !== false && CodeMirror.copyState( state.extMode, state.extState ),
|
|
860
|
-
nTemplate: state.nTemplate,
|
|
861
|
-
nLink: state.nLink,
|
|
862
|
-
nExt: state.nExt,
|
|
863
|
-
isBold: false,
|
|
864
|
-
lpar: false
|
|
865
|
-
};
|
|
866
|
-
},
|
|
867
|
-
token( stream, state ) {
|
|
868
|
-
return state.tokenize( stream, state ); // get token style
|
|
869
|
-
}
|
|
870
|
-
};
|
|
871
|
-
} );
|
|
872
|
-
|
|
873
|
-
CodeMirror.defineMIME( 'text/mediawiki', 'mediawiki' );
|
|
874
|
-
|
|
875
|
-
function eatPre( stream, state ) {
|
|
876
|
-
if ( stream.match( /^[^&<]+/ ) ) {
|
|
877
|
-
return '';
|
|
878
|
-
} else if ( stream.eat( '<' ) ) {
|
|
879
|
-
if ( !state.nowiki && stream.match( 'nowiki>' ) || state.nowiki && stream.match( '/nowiki>' ) ) {
|
|
880
|
-
state.nowiki = !state.nowiki;
|
|
881
|
-
return 'mw-comment';
|
|
882
|
-
}
|
|
883
|
-
return '';
|
|
884
|
-
}
|
|
885
|
-
stream.next(); // eat &
|
|
886
|
-
return eatMnemonic( stream, '' );
|
|
887
|
-
}
|
|
888
|
-
|
|
889
|
-
function eatNowiki( stream ) {
|
|
890
|
-
if ( stream.match( /^[^&]+/ ) ) {
|
|
891
|
-
return '';
|
|
892
|
-
}
|
|
893
|
-
stream.next(); // eat &
|
|
894
|
-
return eatMnemonic( stream, '' );
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
CodeMirror.defineMode( 'mw-tag-pre', function ( /* config, parserConfig */ ) {
|
|
898
|
-
return {
|
|
899
|
-
startState() {
|
|
900
|
-
return { nowiki: false };
|
|
901
|
-
},
|
|
902
|
-
copyState( state ) {
|
|
903
|
-
return { nowiki: state.nowiki };
|
|
904
|
-
},
|
|
905
|
-
token: eatPre
|
|
906
|
-
};
|
|
907
|
-
} );
|
|
908
|
-
|
|
909
|
-
CodeMirror.defineMode( 'mw-tag-nowiki', function ( /* config, parserConfig */ ) {
|
|
910
|
-
return {
|
|
911
|
-
startState() {
|
|
912
|
-
return {};
|
|
913
|
-
},
|
|
914
|
-
token: eatNowiki
|
|
915
|
-
};
|
|
916
|
-
} );
|
|
917
|
-
}( CodeMirror ) );
|