Commit b04cbafe3bde12ec16375ee7b3188312ec44c515

Michael Schmidt 2020-10-13T14:26:34

CSS: Better HTML `style` attribute tokenization (#2569)

diff --git a/components/prism-css.js b/components/prism-css.js
index b0b56eb..870b208 100644
--- a/components/prism-css.js
+++ b/components/prism-css.js
@@ -52,19 +52,29 @@
 
 		Prism.languages.insertBefore('inside', 'attr-value', {
 			'style-attr': {
-				pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,
+				pattern: /(^|["'\s])style\s*=\s*(?:"[^"]*"|'[^']*')/i,
+				lookbehind: true,
 				inside: {
-					'attr-name': {
-						pattern: /^\s*style/i,
-						inside: markup.tag.inside
-					},
-					'punctuation': /^\s*=\s*['"]|['"]\s*$/,
 					'attr-value': {
-						pattern: /.+/i,
-						inside: Prism.languages.css
-					}
-				},
-				alias: 'language-css'
+						pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,
+						inside: {
+							'style': {
+								pattern: /(["'])[\s\S]+(?=["']$)/,
+								lookbehind: true,
+								alias: 'language-css',
+								inside: Prism.languages.css
+							},
+							'punctuation': [
+								{
+									pattern: /^=/,
+									alias: 'attr-equals'
+								},
+								/"|'/
+							]
+						}
+					},
+					'attr-name': /^style/i
+				}
 			}
 		}, markup.tag);
 	}
diff --git a/components/prism-css.min.js b/components/prism-css.min.js
index f2197a3..eac2569 100644
--- a/components/prism-css.min.js
+++ b/components/prism-css.min.js
@@ -1 +1 @@
-!function(e){var s=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\((?!\s*\))\s*)(?:[^()]|\((?:[^()]|\([^()]*\))*\))+?(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+s.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+s.source+"$"),alias:"url"}}},selector:RegExp("[^{}\\s](?:[^{};\"']|"+s.source+")*?(?=\\s*\\{)"),string:{pattern:s,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var t=e.languages.markup;t&&(t.tag.addInlined("style","css"),e.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:t.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:e.languages.css}},alias:"language-css"}},t.tag))}(Prism);
\ No newline at end of file
+!function(e){var t=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\((?!\s*\))\s*)(?:[^()]|\((?:[^()]|\([^()]*\))*\))+?(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:RegExp("[^{}\\s](?:[^{};\"']|"+t.source+")*?(?=\\s*\\{)"),string:{pattern:t,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var s=e.languages.markup;s&&(s.tag.addInlined("style","css"),e.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/(^|["'\s])style\s*=\s*(?:"[^"]*"|'[^']*')/i,lookbehind:!0,inside:{"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{style:{pattern:/(["'])[\s\S]+(?=["']$)/,lookbehind:!0,alias:"language-css",inside:e.languages.css},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},"attr-name":/^style/i}}},s.tag))}(Prism);
\ No newline at end of file
diff --git a/prism.js b/prism.js
index 8688659..487be2b 100644
--- a/prism.js
+++ b/prism.js
@@ -1384,19 +1384,29 @@ Prism.languages.rss = Prism.languages.xml;
 
 		Prism.languages.insertBefore('inside', 'attr-value', {
 			'style-attr': {
-				pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,
+				pattern: /(^|["'\s])style\s*=\s*(?:"[^"]*"|'[^']*')/i,
+				lookbehind: true,
 				inside: {
-					'attr-name': {
-						pattern: /^\s*style/i,
-						inside: markup.tag.inside
-					},
-					'punctuation': /^\s*=\s*['"]|['"]\s*$/,
 					'attr-value': {
-						pattern: /.+/i,
-						inside: Prism.languages.css
-					}
-				},
-				alias: 'language-css'
+						pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,
+						inside: {
+							'style': {
+								pattern: /(["'])[\s\S]+(?=["']$)/,
+								lookbehind: true,
+								alias: 'language-css',
+								inside: Prism.languages.css
+							},
+							'punctuation': [
+								{
+									pattern: /^=/,
+									alias: 'attr-equals'
+								},
+								/"|'/
+							]
+						}
+					},
+					'attr-name': /^style/i
+				}
 			}
 		}, markup.tag);
 	}
diff --git a/tests/languages/markup!+css/css_inclusion.test b/tests/languages/markup!+css/css_inclusion.test
index 69264db..a29a6f6 100644
--- a/tests/languages/markup!+css/css_inclusion.test
+++ b/tests/languages/markup!+css/css_inclusion.test
@@ -98,17 +98,18 @@ foo {
 			"foo"
 		]],
 		["style-attr", [
-			["attr-name", [
-				["attr-name", ["style"]]
-			]],
-			["punctuation", "=\""],
+			["attr-name", "style"],
 			["attr-value", [
-				["property", "bar"],
-				["punctuation", ":"],
-				"baz",
-				["punctuation", ";"]
-			]],
-			["punctuation", "\""]
+				["punctuation", "="],
+				["punctuation", "\""],
+				["style", [
+					["property", "bar"],
+					["punctuation", ":"],
+					"baz",
+					["punctuation", ";"]
+				]],
+				["punctuation", "\""]
+			]]
 		]],
 		["punctuation", ">"]
 	]]
diff --git a/tests/languages/markup+css+wiki/table-tag_feature.test b/tests/languages/markup+css+wiki/table-tag_feature.test
index e3965f9..8f8f61e 100644
--- a/tests/languages/markup+css+wiki/table-tag_feature.test
+++ b/tests/languages/markup+css+wiki/table-tag_feature.test
@@ -68,15 +68,18 @@ baz
 	["punctuation", "!"],
 	["table-tag", [
 		["style-attr", [
-			["attr-name", [["attr-name", ["style"]]]],
-			["punctuation", "=\""],
+			["attr-name", "style"],
 			["attr-value", [
-				["property", "text-align"],
-				["punctuation", ":"],
-				"left",
-				["punctuation", ";"]
-			]],
-			["punctuation", "\""]
+				["punctuation", "="],
+				["punctuation", "\""],
+				["style", [
+					["property", "text-align"],
+					["punctuation", ":"],
+					"left",
+					["punctuation", ";"]
+				]],
+				["punctuation", "\""]
+			]]
 		]],
 		["table-bar", "|"]
 	]], " Foo\r\n",
@@ -92,30 +95,36 @@ baz
 	["punctuation", "!"],
 	["table-tag", [
 		["style-attr", [
-			["attr-name", [["attr-name", ["style"]]]],
-			["punctuation", "=\""],
+			["attr-name", "style"],
 			["attr-value", [
-				["property", "color"],
-				["punctuation", ":"],
-				"red",
-				["punctuation", ";"]
-			]],
-			["punctuation", "\""]
+				["punctuation", "="],
+				["punctuation", "\""],
+				["style", [
+					["property", "color"],
+					["punctuation", ":"],
+					"red",
+					["punctuation", ";"]
+				]],
+				["punctuation", "\""]
+			]]
 		]],
 		["table-bar", "|"]
 	]], " Foo ",
 	["punctuation", "!!"],
 	["table-tag", [
 		["style-attr", [
-			["attr-name", [["attr-name", ["style"]]]],
-			["punctuation", "=\""],
+			["attr-name", "style"],
 			["attr-value", [
-				["property", "color"],
-				["punctuation", ":"],
-				"blue",
-				["punctuation", ";"]
-			]],
-			["punctuation", "\""]
+				["punctuation", "="],
+				["punctuation", "\""],
+				["style", [
+					["property", "color"],
+					["punctuation", ":"],
+					"blue",
+					["punctuation", ";"]
+				]],
+				["punctuation", "\""]
+			]]
 		]],
 		["table-bar", "|"]
 	]], " Bar ",
@@ -125,15 +134,18 @@ baz
 	["punctuation", "||"],
 	["table-tag", [
 		["style-attr", [
-			["attr-name", [["attr-name", ["style"]]]],
-			["punctuation", "=\""],
+			["attr-name", "style"],
 			["attr-value", [
-				["property", "font-weight"],
-				["punctuation", ":"],
-				"bold",
-				["punctuation", ";"]
-			]],
-			["punctuation", "\""]
+				["punctuation", "="],
+				["punctuation", "\""],
+				["style", [
+					["property", "font-weight"],
+					["punctuation", ":"],
+					"bold",
+					["punctuation", ";"]
+				]],
+				["punctuation", "\""]
+			]]
 		]],
 		["table-bar", "|"]
 	]], " bar ",
@@ -144,4 +156,4 @@ baz
 ----------------------------------------------------
 
 Checks for tables and cell attributes.
-Note: Markup is loaded before CSS so that inline styles are added into grammar.
\ No newline at end of file
+Note: Markup is loaded before CSS so that inline styles are added into grammar.
diff --git a/tests/languages/php!+css-extras/issue2008.test b/tests/languages/php!+css-extras/issue2008.test
index 4710e4a..3dc9d01 100644
--- a/tests/languages/php!+css-extras/issue2008.test
+++ b/tests/languages/php!+css-extras/issue2008.test
@@ -9,31 +9,30 @@
 			"img"
 		]],
 		["style-attr", [
-			["attr-name", [
-				["attr-name", [
-					"style"
-				]]
-			]],
-			["punctuation", "=\""],
+			["attr-name", "style"],
 			["attr-value", [
-				["property", "width"],
-				["punctuation", ":"],
-				["php", [
-					["delimiter", "<?php"],
-					["keyword", "echo"],
-					["punctuation", "("],
-					["number", "80"],
-					["operator", "/"],
-					["function", "count"],
-					["punctuation", "("],
-					["variable", "$images"],
-					["punctuation", ")"],
-					["punctuation", ")"],
-					["delimiter", "?>"]
+				["punctuation", "="],
+				["punctuation", "\""],
+				["style", [
+					["property", "width"],
+					["punctuation", ":"],
+					["php", [
+						["delimiter", "<?php"],
+						["keyword", "echo"],
+						["punctuation", "("],
+						["number", "80"],
+						["operator", "/"],
+						["function", "count"],
+						["punctuation", "("],
+						["variable", "$images"],
+						["punctuation", ")"],
+						["punctuation", ")"],
+						["delimiter", "?>"]
+					]],
+					"%"
 				]],
-				"%"
-			]],
-			["punctuation", "\""]
+				["punctuation", "\""]
+			]]
 		]],
 		["punctuation", "/>"]
 	]]