diff --git a/resources/codemirror.mediawiki.js b/resources/codemirror.mediawiki.js index d757139b..f3ef10be 100644 --- a/resources/codemirror.mediawiki.js +++ b/resources/codemirror.mediawiki.js @@ -725,7 +725,7 @@ class CodeMirrorModeMediaWiki { } eatFreeExternalLink( stream, state ) { - if ( stream.eol() ) { + if ( stream.sol() ) { // @todo error message } else if ( stream.match( /^[^\s\u00a0{[\]<>~).,']*/ ) ) { if ( stream.peek() === '~' ) { @@ -819,16 +819,17 @@ class CodeMirrorModeMediaWiki { return this.eatList( stream, state ); case ':': // Highlight indented tables :{|, bug T108454 - if ( stream.match( /^:*{\|/, false ) ) { + if ( stream.match( /^:*[\s\u00a0]*{\|/, false ) ) { state.stack.push( state.tokenize ); state.tokenize = this.eatStartTable.bind( this ); } return this.eatList( stream, state ); case ' ': // Leading spaces is valid syntax for tables, bug T108454 - if ( stream.match( /^[\s\u00a0]*:*{\|/, false ) ) { + if ( stream.match( /^[\s\u00a0]*(?::+[\s\u00a0]*)?{\|/, false ) ) { stream.eatSpace(); if ( stream.match( /^:+/ ) ) { // ::{| + stream.eatSpace(); state.stack.push( state.tokenize ); state.tokenize = this.eatStartTable.bind( this ); return mwModeConfig.tags.indenting; @@ -916,15 +917,21 @@ class CodeMirrorModeMediaWiki { ); } // Check for parser function without '#' - - name = stream.match( /^([^\s\u00a0}[\]<{'|&:]+)(:|[\s\u00a0]*)(\}\}?)?(.)?/ ); + name = stream.match( /^([^}[\]<{|:]+)(.)?/, false ); if ( name ) { - stream.backUp( name[ 0 ].length ); + const [ , f, delimiter ] = name, + ff = delimiter === ':' ? f : f.trim(), + ffLower = ff.toLowerCase(), + { config: { functionSynonyms } } = this; if ( - ( name[ 2 ] === ':' || name[ 4 ] === undefined || name[ 3 ] === '}}' ) && + ( !delimiter || delimiter === ':' || delimiter === '}' ) && ( - name[ 1 ].toLowerCase() in this.config.functionSynonyms[ 0 ] || - name[ 1 ] in this.config.functionSynonyms[ 1 ] + Object.prototype.hasOwnProperty.call( + functionSynonyms[ 0 ], ffLower + ) || + Object.prototype.hasOwnProperty.call( + functionSynonyms[ 1 ], ff + ) ) ) { state.nExt++; @@ -944,11 +951,11 @@ class CodeMirrorModeMediaWiki { } break; case '<': - isCloseTag = !!stream.eat( '/' ); - tagname = stream.match( /^[^>/\s\u00a0.*,[\]{}$^+?|/\\'`~<=!@#%&()-]+/ ); if ( stream.match( '!--' ) ) { // comment return chain( this.eatBlock( mwModeConfig.tags.comment, '-->' ) ); } + isCloseTag = !!stream.eat( '/' ); + tagname = stream.match( /^[a-z][^>/\s\u00a0]*/i ); if ( tagname ) { tagname = tagname[ 0 ].toLowerCase(); if ( tagname in this.config.tags ) { diff --git a/tests/jest/codemirror.mediawiki.test.js b/tests/jest/codemirror.mediawiki.test.js index fc5c9c17..5e5f5c6e 100644 --- a/tests/jest/codemirror.mediawiki.test.js +++ b/tests/jest/codemirror.mediawiki.test.js @@ -24,8 +24,8 @@ const testCases = [ }, { title: 'indented table with caption and inline headings', - input: ' ::{| class="wikitable"\n |+ Caption\n |-\n ! Uno !! Dos\n |-\n | Foo || Bar\n |}', - output: '
::{| class="wikitable"
|+ Caption
|-
! Uno !! Dos
|-
| Foo || Bar
|}
' + input: ':{|\n|}\n :: {| class="wikitable"\n |+ Caption\n |-\n ! Uno !! Dos\n |-\n | Foo || Bar\n |}', + output: '
:{|
|}
:: {| class="wikitable"
|+ Caption
|-
! Uno !! Dos
|-
| Foo || Bar
|}
' }, { title: 'apostrophe before italic', @@ -34,8 +34,8 @@ const testCases = [ }, { title: 'free external links', - input: 'https://wikimedia.org [ftp://foo.bar FOO] //archive.org', - output: '
https://wikimedia.org [ftp://foo.bar FOO] //archive.org
' + input: '//archive.org [ftp://foo.bar FOO] https://wikimedia.org/~\nx', + output: '
//archive.org [ftp://foo.bar FOO] https://wikimedia.org/~
x
' }, { title: 'not free external links', @@ -162,6 +162,16 @@ const testCases = [ title: 'Nested template calls', input: '{{foo|{{bar|[[Test]]|{{baz|[[Test2]]}}}}}}', output: '
{{foo|{{bar|[[Test]]|{{baz|[[Test2]]}}}}}}
' + }, + { + title: 'Tag name followed by punctuations', + input: '<pre-foobar><p? ><b!-- ' + }, + { + title: 'Localized parser function', + input: '{{מיון רגיל:AAA}}', + output: '
{{מיון רגיל:AAA}}
' } ]; @@ -176,7 +186,8 @@ const mwLang = mediaWikiLang( {}, { __notoc__: 'notoc' } ], functionSynonyms: [ {}, { - '!': '!' + '!': '!', + 'מיון רגיל': 'defaultsort' } ], tags: { nowiki: true,