Commit 5fcee96675103f16fc4668501aee502194d449a2

Rex Zeng 2018-12-03T20:55:22

Identify CSS units and variables (#1450) Assume CSS unit is a word or `%` after a number, CSS variable is a word inside `var()`. `%` is not recognized as a part of number, but the leading `-` is. When using minus operator in `calc` function, we must type a space in both sides of `-` (value like `calc(100%-5px)` is wrong), so if we met a pattern like `-[\d.]` in a CSS value (not in selector, rule or variable), it must be the start of a negative number.

diff --git a/components/prism-css-extras.js b/components/prism-css-extras.js
index 3b4261f..254688b 100644
--- a/components/prism-css-extras.js
+++ b/components/prism-css-extras.js
@@ -10,7 +10,19 @@ Prism.languages.css.selector = {
 };
 
 Prism.languages.insertBefore('css', 'function', {
+	'variable': {
+		pattern: /(var\()[^)]+(?=\))/,
+		lookbehind: true
+	},
+	'operator': {
+		pattern: /(\s)[+\-*\/](?=\s)/,
+		lookbehind: true
+	},
 	'hexcode': /#[\da-f]{3,8}/i,
 	'entity': /\\[\da-f]{1,8}/i,
-	'number': /[\d%.]+/
+	'unit': {
+		pattern: /(\d)(?:%|[a-z]+)/,
+		lookbehind: true
+	},
+	'number': /-?[\d.]+/
 });
diff --git a/components/prism-css-extras.min.js b/components/prism-css-extras.min.js
index f3d252f..34a2226 100644
--- a/components/prism-css-extras.min.js
+++ b/components/prism-css-extras.min.js
@@ -1 +1 @@
-Prism.languages.css.selector={pattern:Prism.languages.css.selector,inside:{"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+(?:\(.*\))?/,"class":/\.[-:.\w]+/,id:/#[-:.\w]+/,attribute:/\[[^\]]+\]/}},Prism.languages.insertBefore("css","function",{hexcode:/#[\da-f]{3,8}/i,entity:/\\[\da-f]{1,8}/i,number:/[\d%.]+/});
\ No newline at end of file
+Prism.languages.css.selector={pattern:Prism.languages.css.selector,inside:{"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+(?:\(.*\))?/,"class":/\.[-:.\w]+/,id:/#[-:.\w]+/,attribute:/\[[^\]]+\]/}},Prism.languages.insertBefore("css","function",{variable:{pattern:/(var\()[^)]+(?=\))/,lookbehind:!0},operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:/#[\da-f]{3,8}/i,entity:/\\[\da-f]{1,8}/i,unit:{pattern:/(\d)(?:%|[a-z]+)/,lookbehind:!0},number:/-?[\d.]+/});
\ No newline at end of file
diff --git a/tests/languages/css!+css-extras/number_feature.test b/tests/languages/css!+css-extras/number_feature.test
index 24ed530..ef58e62 100644
--- a/tests/languages/css!+css-extras/number_feature.test
+++ b/tests/languages/css!+css-extras/number_feature.test
@@ -1,15 +1,15 @@
 42
 3.14159
-42%
-3.14%
+-42
+-3.14
 
 ----------------------------------------------------
 
 [
 	["number", "42"],
 	["number", "3.14159"],
-	["number", "42%"],
-	["number", "3.14%"]
+	["number", "-42"],
+	["number", "-3.14"]
 ]
 
 ----------------------------------------------------
diff --git a/tests/languages/css!+css-extras/operator_feature.test b/tests/languages/css!+css-extras/operator_feature.test
new file mode 100644
index 0000000..0df7612
--- /dev/null
+++ b/tests/languages/css!+css-extras/operator_feature.test
@@ -0,0 +1,71 @@
+width: calc(100% + 20px);
+width: calc(100% - 20px);
+width: calc(5px * 2);
+width: calc(10px / 2);
+height: -20px;
+content: 'this - is not an operator';
+
+----------------------------------------------------
+
+[
+	["property", "width"],
+	["punctuation", ":"],
+	["function", "calc"],
+	["punctuation", "("],
+	["number", "100"],
+	["unit", "%"],
+	["operator", "+"],
+	["number", "20"],
+	["unit", "px"],
+	["punctuation", ")"],
+	["punctuation", ";"],
+
+	["property", "width"],
+	["punctuation", ":"],
+	["function", "calc"],
+	["punctuation", "("],
+	["number", "100"],
+	["unit", "%"],
+	["operator", "-"],
+	["number", "20"],
+	["unit", "px"],
+	["punctuation", ")"],
+	["punctuation", ";"],
+
+	["property", "width"],
+	["punctuation", ":"],
+	["function", "calc"],
+	["punctuation", "("],
+	["number", "5"],
+	["unit", "px"],
+	["operator", "*"],
+	["number", "2"],
+	["punctuation", ")"],
+	["punctuation", ";"],
+
+	["property", "width"],
+	["punctuation", ":"],
+	["function", "calc"],
+	["punctuation", "("],
+	["number", "10"],
+	["unit", "px"],
+	["operator", "/"],
+	["number", "2"],
+	["punctuation", ")"],
+	["punctuation", ";"],
+
+	["property", "height"],
+	["punctuation", ":"],
+	["number", "-20"],
+	["unit", "px"],
+	["punctuation", ";"],
+
+	["property", "content"],
+	["punctuation", ":"],
+	["string", "'this - is not an operator'"],
+	["punctuation", ";"]
+]
+
+----------------------------------------------------
+
+Checks for operators.
diff --git a/tests/languages/css!+css-extras/unit_feature.test b/tests/languages/css!+css-extras/unit_feature.test
new file mode 100644
index 0000000..6d5c15c
--- /dev/null
+++ b/tests/languages/css!+css-extras/unit_feature.test
@@ -0,0 +1,21 @@
+100%
+1rem
+500ms
+.5s
+-3px
+-0.618vw
+
+----------------------------------------------------
+
+[
+	["number", "100"], ["unit", "%"],
+	["number", "1"], ["unit", "rem"],
+	["number", "500"], ["unit", "ms"],
+	["number", ".5"], ["unit", "s"],
+	["number", "-3"], ["unit", "px"],
+	["number", "-0.618"], ["unit", "vw"]
+]
+
+----------------------------------------------------
+
+Checks for units.
diff --git a/tests/languages/css!+css-extras/variable_feature.test b/tests/languages/css!+css-extras/variable_feature.test
new file mode 100644
index 0000000..d17053a
--- /dev/null
+++ b/tests/languages/css!+css-extras/variable_feature.test
@@ -0,0 +1,34 @@
+var(--color-primary)
+var(--level-3)
+calc(100% - var(--margin-size) * 2)
+
+----------------------------------------------------
+
+[
+	["function", "var"],
+	["punctuation", "("],
+	["variable", "--color-primary"],
+	["punctuation", ")"],
+
+	["function", "var"],
+	["punctuation", "("],
+	["variable", "--level-3"],
+	["punctuation", ")"],
+
+	["function", "calc"],
+	["punctuation", "("],
+	["number", "100"],
+	["unit", "%"],
+	["operator", "-"],
+	["function", "var"],
+	["punctuation", "("],
+	["variable", "--margin-size"],
+	["punctuation", ")"],
+	["operator", "*"],
+	["number", "2"],
+	["punctuation", ")"]
+]
+
+----------------------------------------------------
+
+Checks for variables.