From a2d445d07da9015f64a29978694a0a06d9da06c8 Mon Sep 17 00:00:00 2001 From: Michael Schmidt Date: Wed, 6 Mar 2019 13:22:08 +0100 Subject: [PATCH] CSS: Selectors can contain any string (#1638) This fixes that certain attribute value strings break the selector pattern. --- components/prism-css.js | 87 ++++++++++++----------- components/prism-css.min.js | 2 +- prism.js | 87 ++++++++++++----------- tests/languages/css/selector_feature.test | 15 +++- 4 files changed, 109 insertions(+), 82 deletions(-) diff --git a/components/prism-css.js b/components/prism-css.js index 4570d8f2f4..7a44e1688f 100644 --- a/components/prism-css.js +++ b/components/prism-css.js @@ -1,44 +1,51 @@ -Prism.languages.css = { - 'comment': /\/\*[\s\S]*?\*\//, - 'atrule': { - pattern: /@[\w-]+?[\s\S]*?(?:;|(?=\s*\{))/i, - inside: { - 'rule': /@[\w-]+/ - // See rest below - } - }, - 'url': /url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i, - 'selector': /[^{}\s][^{};]*?(?=\s*\{)/, - 'string': { - pattern: /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, - greedy: true - }, - 'property': /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i, - 'important': /!important\b/i, - 'function': /[-a-z0-9]+(?=\()/i, - 'punctuation': /[(){};:,]/ -}; +(function (Prism) { -Prism.languages.css['atrule'].inside.rest = Prism.languages.css; + var string = /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/; -if (Prism.languages.markup) { - Prism.languages.markup.tag.addInlined('style', 'css'); - - Prism.languages.insertBefore('inside', 'attr-value', { - 'style-attr': { - pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i, + Prism.languages.css = { + 'comment': /\/\*[\s\S]*?\*\//, + 'atrule': { + pattern: /@[\w-]+?[\s\S]*?(?:;|(?=\s*\{))/i, inside: { - 'attr-name': { - pattern: /^\s*style/i, - inside: Prism.languages.markup.tag.inside + 'rule': /@[\w-]+/ + // See rest below + } + }, + 'url': RegExp('url\\((?:' + string.source + '|.*?)\\)', 'i'), + 'selector': RegExp('[^{}\\s](?:[^{};"\']|' + string.source + ')*?(?=\\s*\\{)'), + 'string': { + pattern: string, + greedy: true + }, + 'property': /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i, + 'important': /!important\b/i, + 'function': /[-a-z0-9]+(?=\()/i, + 'punctuation': /[(){};:,]/ + }; + + Prism.languages.css['atrule'].inside.rest = Prism.languages.css; + + var markup = Prism.languages.markup; + if (markup) { + markup.tag.addInlined('style', 'css'); + + Prism.languages.insertBefore('inside', 'attr-value', { + 'style-attr': { + pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i, + inside: { + 'attr-name': { + pattern: /^\s*style/i, + inside: markup.tag.inside + }, + 'punctuation': /^\s*=\s*['"]|['"]\s*$/, + 'attr-value': { + pattern: /.+/i, + inside: Prism.languages.css + } }, - 'punctuation': /^\s*=\s*['"]|['"]\s*$/, - 'attr-value': { - pattern: /.+/i, - inside: Prism.languages.css - } - }, - alias: 'language-css' - } - }, Prism.languages.markup.tag); -} + alias: 'language-css' + } + }, markup.tag); + } + +}(Prism)); diff --git a/components/prism-css.min.js b/components/prism-css.min.js index 56b69ee0fc..93fbe2db5d 100644 --- a/components/prism-css.min.js +++ b/components/prism-css.min.js @@ -1 +1 @@ -Prism.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?[\s\S]*?(?:;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^{}\s][^{};]*?(?=\s*\{)/,string:{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},Prism.languages.css.atrule.inside.rest=Prism.languages.css,Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("style","css"),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag)); \ No newline at end of file +!function(s){var e=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?[\s\S]*?(?:;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:RegExp("url\\((?:"+e.source+"|.*?)\\)","i"),selector:RegExp("[^{}\\s](?:[^{};\"']|"+e.source+")*?(?=\\s*\\{)"),string:{pattern:e,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var a=s.languages.markup;a&&(a.tag.addInlined("style","css"),s.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:a.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:s.languages.css}},alias:"language-css"}},a.tag))}(Prism); \ No newline at end of file diff --git a/prism.js b/prism.js index 7d45bf3dad..d96b24990c 100644 --- a/prism.js +++ b/prism.js @@ -668,50 +668,57 @@ Prism.languages.svg = Prism.languages.markup; Begin prism-css.js ********************************************** */ -Prism.languages.css = { - 'comment': /\/\*[\s\S]*?\*\//, - 'atrule': { - pattern: /@[\w-]+?[\s\S]*?(?:;|(?=\s*\{))/i, - inside: { - 'rule': /@[\w-]+/ - // See rest below - } - }, - 'url': /url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i, - 'selector': /[^{}\s][^{};]*?(?=\s*\{)/, - 'string': { - pattern: /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, - greedy: true - }, - 'property': /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i, - 'important': /!important\b/i, - 'function': /[-a-z0-9]+(?=\()/i, - 'punctuation': /[(){};:,]/ -}; +(function (Prism) { -Prism.languages.css['atrule'].inside.rest = Prism.languages.css; + var string = /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/; -if (Prism.languages.markup) { - Prism.languages.markup.tag.addInlined('style', 'css'); - - Prism.languages.insertBefore('inside', 'attr-value', { - 'style-attr': { - pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i, + Prism.languages.css = { + 'comment': /\/\*[\s\S]*?\*\//, + 'atrule': { + pattern: /@[\w-]+?[\s\S]*?(?:;|(?=\s*\{))/i, inside: { - 'attr-name': { - pattern: /^\s*style/i, - inside: Prism.languages.markup.tag.inside + 'rule': /@[\w-]+/ + // See rest below + } + }, + 'url': RegExp('url\\((?:' + string.source + '|.*?)\\)', 'i'), + 'selector': RegExp('[^{}\\s](?:[^{};"\']|' + string.source + ')*?(?=\\s*\\{)'), + 'string': { + pattern: string, + greedy: true + }, + 'property': /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i, + 'important': /!important\b/i, + 'function': /[-a-z0-9]+(?=\()/i, + 'punctuation': /[(){};:,]/ + }; + + Prism.languages.css['atrule'].inside.rest = Prism.languages.css; + + var markup = Prism.languages.markup; + if (markup) { + markup.tag.addInlined('style', 'css'); + + Prism.languages.insertBefore('inside', 'attr-value', { + 'style-attr': { + pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i, + inside: { + 'attr-name': { + pattern: /^\s*style/i, + inside: markup.tag.inside + }, + 'punctuation': /^\s*=\s*['"]|['"]\s*$/, + 'attr-value': { + pattern: /.+/i, + inside: Prism.languages.css + } }, - 'punctuation': /^\s*=\s*['"]|['"]\s*$/, - 'attr-value': { - pattern: /.+/i, - inside: Prism.languages.css - } - }, - alias: 'language-css' - } - }, Prism.languages.markup.tag); -} + alias: 'language-css' + } + }, markup.tag); + } + +}(Prism)); /* ********************************************** diff --git a/tests/languages/css/selector_feature.test b/tests/languages/css/selector_feature.test index 5a59720135..227ac755a6 100644 --- a/tests/languages/css/selector_feature.test +++ b/tests/languages/css/selector_feature.test @@ -1,25 +1,38 @@ foo{ + foo + bar { + foo:first-child:hover { + * { + foo, bar{ +[foo="{\"}"] { + ---------------------------------------------------- [ ["selector", "foo"], ["punctuation", "{"], + ["selector", "foo + bar"], ["punctuation", "{"], + ["selector", "foo:first-child:hover"], ["punctuation", "{"], + ["selector", "*"], ["punctuation", "{"], + ["selector", "foo,\r\nbar"], + ["punctuation", "{"], + + ["selector", "[foo=\"{\\\"}\"]"], ["punctuation", "{"] ] ---------------------------------------------------- -Checks for single-line and multi-line selectors. \ No newline at end of file +Checks for single-line and multi-line selectors.