diff --git a/CHANGES.md b/CHANGES.md index 9034fcb40d..e6e1f1f4a9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,8 @@ -## Version 10.4.0 (work in process) +## Version 10.4.0 (a work in process) + +Parser: + +- enh(parser) use negative look-ahead for `beginKeywords` support (#2813) [Josh Goebel][] Deprecations: diff --git a/src/lib/mode_compiler.js b/src/lib/mode_compiler.js index d5012d1093..9265be22aa 100644 --- a/src/lib/mode_compiler.js +++ b/src/lib/mode_compiler.js @@ -240,7 +240,7 @@ export function compileLanguage(language) { // TODO: We need negative look-behind support to do this properly /** - * Skip a match if it has a preceding or trailing dot + * Skip a match if it has a preceding dot * * This is used for `beginKeywords` to prevent matching expressions such as * `bob.keyword.do()`. The mode compiler automatically wires this up as a @@ -248,10 +248,9 @@ export function compileLanguage(language) { * @param {RegExpMatchArray} match * @param {CallbackResponse} response */ - function skipIfhasPrecedingOrTrailingDot(match, response) { + function skipIfhasPrecedingDot(match, response) { const before = match.input[match.index - 1]; - const after = match.input[match.index + match[0].length]; - if (before === "." || after === ".") { + if (before === ".") { response.ignoreMatch(); } } @@ -331,8 +330,8 @@ export function compileLanguage(language) { // or whitespace - this does no harm in any case since our keyword engine // doesn't allow spaces in keywords anyways and we still check for the boundary // first - mode.begin = '\\b(' + mode.beginKeywords.split(' ').join('|') + ')(?=\\b|\\s)'; - mode.__beforeBegin = skipIfhasPrecedingOrTrailingDot; + mode.begin = '\\b(' + mode.beginKeywords.split(' ').join('|') + ')(?!\\.)(?=\\b|\\s)'; + mode.__beforeBegin = skipIfhasPrecedingDot; } if (!mode.begin) mode.begin = /\B|\b/; cmode.beginRe = langRe(mode.begin); diff --git a/test/api/index.js b/test/api/index.js index 0e4b596dcb..223fbc0e30 100644 --- a/test/api/index.js +++ b/test/api/index.js @@ -1,16 +1,17 @@ 'use strict'; describe('hljs', function() { - require('./ident'); - require('./underscoreIdent'); - require('./number'); - require('./cNumber'); + require('./autoDetection'); + require('./beginKeywords'); require('./binaryNumber'); - require('./starters'); + require('./cNumber'); + require('./fixmarkup'); require('./getLanguage'); - require('./autoDetection'); require('./highlight'); - require('./fixmarkup'); + require('./ident'); require('./keywords'); + require('./number'); require('./registerAlias'); + require('./starters'); + require('./underscoreIdent'); });