Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(javascript) fix regex inside parens after a non-regex #2531

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Expand Up @@ -15,6 +15,8 @@ Deprecations:
- `endSameAsBegin` is now deprecated. (#2261) [Josh Goebel][]

Language Improvements:

- fix(javascript) fix regex inside parens after a non-regex (#2530) [Josh Goebel][]
- enh(typescript) use identifier to match potential keywords, preventing false positivites (#2519) [Josh Goebel][]
- enh(javascript) use identifier to match potential keywords, preventing false positivites (#2519) [Josh Goebel][]
- [enh] Add `OPTIMIZE:` and `HACK:` to the labels highlighted inside comments [Josh Goebel][]
Expand Down
25 changes: 21 additions & 4 deletions src/languages/javascript.js
Expand Up @@ -6,6 +6,7 @@ Website: https://developer.mozilla.org/en-US/docs/Web/JavaScript
*/

import * as ECMAScript from "./lib/ecmascript";
import * as regex from "../lib/regex";

export default function(hljs) {
var IDENT_RE = ECMAScript.IDENT_RE;
Expand Down Expand Up @@ -149,13 +150,29 @@ export default function(hljs) {
hljs.C_BLOCK_COMMENT_MODE,
NUMBER,
{ // object attr container
begin: /[{,\n]\s*/, relevance: 0,
begin: regex.concat(/[{,\n]\s*/,
// we need to look ahead to make sure that we actually have an
// attribute coming up so we don't steal a comma from a potential
// "value" container
//
// NOTE: this might not work how you think. We don't actually always
// enter this mode and stay. Instead it might merely match `,
// <comments up next>` and then immediately end after the , because it
// fails to find any actual attrs. But this still does the job because
// it prevents the value contain rule from grabbing this instead and
// prevening this rule from firing when we actually DO have keys.
regex.lookahead(regex.concat(
// we also need to allow for multiple possible comments inbetween
// the first key:value pairing
/(((\/\/.*)|(\/\*(.|\n)*\*\/))\s*)*/,
IDENT_RE + '\\s*:'))),
relevance: 0,
contains: [
{
begin: IDENT_RE + '\\s*:', returnBegin: true,
className: 'attr',
begin: IDENT_RE + regex.lookahead('\\s*:'),
relevance: 0,
contains: [{className: 'attr', begin: IDENT_RE, relevance: 0}]
}
},
]
},
{ // "value" container
Expand Down
4 changes: 4 additions & 0 deletions src/lib/regex.js
Expand Up @@ -8,6 +8,10 @@ export function source(re) {
return (re && re.source) || re;
}

export function lookahead(regex) {
return concat('(?=', regex, ')');
}

export function concat(...args) {
const joined = args.map((x) => source(x)).join("");
return joined;
Expand Down
10 changes: 9 additions & 1 deletion test/markup/javascript/object-attr.expect.txt
@@ -1,6 +1,14 @@
{
<span class="hljs-attr">key</span>: value, <span class="hljs-comment">// with comment</span>
<span class="hljs-attr">key2</span>: value,
<span class="hljs-attr">key2clone</span>: value,
<span class="hljs-string">'key-3'</span>: value,
<span class="hljs-attr">key4</span>: <span class="hljs-literal">false</span> ? <span class="hljs-literal">undefined</span> : <span class="hljs-literal">true</span>
<span class="hljs-attr">key4</span>: <span class="hljs-literal">false</span> ? <span class="hljs-literal">undefined</span> : <span class="hljs-literal">true</span>,
<span class="hljs-attr">key5</span>: value, <span class="hljs-comment">/* with a multiline comment */</span>
<span class="hljs-attr">key6</span>: value,
<span class="hljs-attr">key7</span>: value, <span class="hljs-comment">/* with a multiline comment */</span> <span class="hljs-comment">// another comment</span>
<span class="hljs-attr">key8</span>: value,
<span class="hljs-attr">key9</span>: value, <span class="hljs-comment">/* with a REAL multiline
comment */</span>
<span class="hljs-attr">key10</span>: value,
}
11 changes: 10 additions & 1 deletion test/markup/javascript/object-attr.txt
@@ -1,6 +1,15 @@
{
key: value, // with comment
key2: value,
key2clone: value,
'key-3': value,
key4: false ? undefined : true
key4: false ? undefined : true,
key5: value, /* with a multiline comment */
key6: value,
key7: value, /* with a multiline comment */ // another comment
key8: value,
key9: value, /* with a REAL multiline
comment */
key10: value,
}