From c40f604714182fdec56d6f2d5955f2c2995a5758 Mon Sep 17 00:00:00 2001 From: Michael Schmidt Date: Sun, 19 Aug 2018 20:28:57 +0200 Subject: [PATCH] Highlighting of supposed classes and functions (#1482) Fixes #1471. It also extends function-variable to include object properties. e.g. ```js {foo: function() {}} ``` --- components/prism-javascript.js | 10 +++-- components/prism-javascript.min.js | 2 +- prism.js | 10 +++-- .../javascript/function-variable_feature.test | 5 ++- .../javascript/supposed-classes_feature.test | 22 +++++++++++ .../javascript/supposed-function_feature.test | 38 +++++++++++++++++++ 6 files changed, 79 insertions(+), 8 deletions(-) create mode 100644 tests/languages/javascript/supposed-classes_feature.test create mode 100644 tests/languages/javascript/supposed-function_feature.test diff --git a/components/prism-javascript.js b/components/prism-javascript.js index 47853d3e0b..2c919b1b29 100644 --- a/components/prism-javascript.js +++ b/components/prism-javascript.js @@ -1,4 +1,8 @@ Prism.languages.javascript = Prism.languages.extend('clike', { + 'class-name': [ + Prism.languages.clike['class-name'], + /[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/ + ], 'keyword': [ { pattern: /((?:^|})\s*)(?:catch|finally)\b/, @@ -8,11 +12,11 @@ Prism.languages.javascript = Prism.languages.extend('clike', { ], 'number': /\b(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|NaN|Infinity)\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/, // Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444) - 'function': /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\()/i, + 'function': /[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\(|\.(?:apply|bind|call)\()/, 'operator': /-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/ }); -Prism.languages.javascript['class-name'].pattern = /(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/ +Prism.languages.javascript['class-name'][0].pattern = /(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/ Prism.languages.insertBefore('javascript', 'keyword', { 'regex': { @@ -22,7 +26,7 @@ Prism.languages.insertBefore('javascript', 'keyword', { }, // This must be declared before keyword because we use "function" inside the look-forward 'function-variable': { - pattern: /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=\s*(?:function\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i, + pattern: /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:function\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i, alias: 'function' }, 'constant': /\b[A-Z][A-Z\d_]*\b/ diff --git a/components/prism-javascript.min.js b/components/prism-javascript.min.js index 29cfee7d0a..cf4284b8a1 100644 --- a/components/prism-javascript.min.js +++ b/components/prism-javascript.min.js @@ -1 +1 @@ -Prism.languages.javascript=Prism.languages.extend("clike",{keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},/\b(?:as|async|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/],number:/\b(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|NaN|Infinity)\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,"function":/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\()/i,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),Prism.languages.javascript["class-name"].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[[^\]\r\n]+]|\\.|[^\/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})\]]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=\s*(?:function\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i,alias:"function"},constant:/\b[A-Z][A-Z\d_]*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${[^}]+}|[^\\`])*`/,greedy:!0,inside:{interpolation:{pattern:/\${[^}]+}/,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript",greedy:!0}}),Prism.languages.js=Prism.languages.javascript; \ No newline at end of file +Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],/[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},/\b(?:as|async|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/],number:/\b(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|NaN|Infinity)\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,"function":/[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\(|\.(?:apply|bind|call)\()/,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[[^\]\r\n]+]|\\.|[^\/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})\]]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:function\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i,alias:"function"},constant:/\b[A-Z][A-Z\d_]*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${[^}]+}|[^\\`])*`/,greedy:!0,inside:{interpolation:{pattern:/\${[^}]+}/,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript",greedy:!0}}),Prism.languages.js=Prism.languages.javascript; \ No newline at end of file diff --git a/prism.js b/prism.js index b48a825af2..a0bc986557 100644 --- a/prism.js +++ b/prism.js @@ -725,6 +725,10 @@ Prism.languages.clike = { ********************************************** */ Prism.languages.javascript = Prism.languages.extend('clike', { + 'class-name': [ + Prism.languages.clike['class-name'], + /[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/ + ], 'keyword': [ { pattern: /((?:^|})\s*)(?:catch|finally)\b/, @@ -734,11 +738,11 @@ Prism.languages.javascript = Prism.languages.extend('clike', { ], 'number': /\b(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|NaN|Infinity)\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/, // Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444) - 'function': /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\()/i, + 'function': /[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\(|\.(?:apply|bind|call)\()/, 'operator': /-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/ }); -Prism.languages.javascript['class-name'].pattern = /(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/ +Prism.languages.javascript['class-name'][0].pattern = /(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/ Prism.languages.insertBefore('javascript', 'keyword', { 'regex': { @@ -748,7 +752,7 @@ Prism.languages.insertBefore('javascript', 'keyword', { }, // This must be declared before keyword because we use "function" inside the look-forward 'function-variable': { - pattern: /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=\s*(?:function\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i, + pattern: /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:function\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i, alias: 'function' }, 'constant': /\b[A-Z][A-Z\d_]*\b/ diff --git a/tests/languages/javascript/function-variable_feature.test b/tests/languages/javascript/function-variable_feature.test index c27095e703..689fb4e923 100644 --- a/tests/languages/javascript/function-variable_feature.test +++ b/tests/languages/javascript/function-variable_feature.test @@ -1,4 +1,5 @@ foo = function () {} +{foo: function () {}} bar = function baz () {} fooBar = x => x ಠ_ಠ = () => {} @@ -9,6 +10,8 @@ fooBar = x => x [ ["function-variable", "foo"], ["operator", "="], ["keyword", "function"], ["punctuation", "("], ["punctuation", ")"], ["punctuation", "{"], ["punctuation", "}"], + ["punctuation", "{"], ["function-variable", "foo"], ["punctuation", ":"], ["keyword", "function"], + ["punctuation", "("], ["punctuation", ")"], ["punctuation", "{"],["punctuation","}"],["punctuation","}"], ["function-variable", "bar"], ["operator", "="], ["keyword", "function"], ["function", "baz"], ["punctuation", "("], ["punctuation", ")"], ["punctuation", "{"], ["punctuation", "}"], ["function-variable", "fooBar"], ["operator", "="], " x ", ["operator", "=>"], " x\r\n", @@ -21,4 +24,4 @@ fooBar = x => x ---------------------------------------------------- -Checks for variables obviously containing functions. \ No newline at end of file +Checks for variables obviously containing functions. diff --git a/tests/languages/javascript/supposed-classes_feature.test b/tests/languages/javascript/supposed-classes_feature.test new file mode 100644 index 0000000000..8d0570873e --- /dev/null +++ b/tests/languages/javascript/supposed-classes_feature.test @@ -0,0 +1,22 @@ +Foo.prototype.bar; +Bar.constructor; + +---------------------------------------------------- + +[ + ["class-name", "Foo"], + ["punctuation", "."], + "prototype", + ["punctuation", "."], + "bar", + ["punctuation", ";"], + + ["class-name", "Bar"], + ["punctuation", "."], + "constructor", + ["punctuation", ";"] +] + +---------------------------------------------------- + +Checks for supposed function variables based on standard function invocations or modifications. diff --git a/tests/languages/javascript/supposed-function_feature.test b/tests/languages/javascript/supposed-function_feature.test new file mode 100644 index 0000000000..7568de9b79 --- /dev/null +++ b/tests/languages/javascript/supposed-function_feature.test @@ -0,0 +1,38 @@ +foo.apply(thisArg, args); +bar.call(...args); +fooBar.bind(thisArg); + +---------------------------------------------------- + +[ + ["function", "foo"], + ["punctuation", "."], + ["function", "apply"], + ["punctuation", "("], + "thisArg", + ["punctuation", ","], + " args", + ["punctuation", ")"], + ["punctuation", ";"], + + ["function", "bar"], + ["punctuation", "."], + ["function", "call"], + ["punctuation", "("], + ["operator", "..."], + "args", + ["punctuation", ")"], + ["punctuation", ";"], + + ["function", "fooBar"], + ["punctuation", "."], + ["function", "bind"], + ["punctuation", "("], + "thisArg", + ["punctuation", ")"], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Checks for supposed function variables based on standard function invocations or modifications.