From 3117529e88b17a67a50ea7029e352bbed598baa1 Mon Sep 17 00:00:00 2001 From: Michael Schmidt Date: Sat, 22 Dec 2018 22:08:42 +0100 Subject: [PATCH 1/3] Added CSS attribute selector components --- components/prism-css-extras.js | 28 ++- components/prism-css-extras.min.js | 2 +- .../selector_attribute_feature.test | 230 ++++++++++++++++++ .../css!+css-extras/selector_feature.test | 7 - 4 files changed, 258 insertions(+), 9 deletions(-) create mode 100644 tests/languages/css!+css-extras/selector_attribute_feature.test diff --git a/components/prism-css-extras.js b/components/prism-css-extras.js index cf06b57a16..41105cd67e 100644 --- a/components/prism-css-extras.js +++ b/components/prism-css-extras.js @@ -5,7 +5,33 @@ Prism.languages.css.selector = { 'pseudo-class': /:[-\w]+(?:\(.*\))?/, 'class': /\.[-:.\w]+/, 'id': /#[-:.\w]+/, - 'attribute': /\[[^\]]+\]/ + 'attribute': { + pattern: /\[(?:[^[\]"']|("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1)+\]/, + greedy: true, + inside: { + 'punctuation': /^\[|\]$/, + 'case-sensitivity': { + pattern: /( )[si]$/i, + lookbehind: true, + alias: 'keyword' + }, + 'namespace': { + pattern: /^[-*\w\xA0-\uFFFF]*\|(?!=)/, + inside: { + 'punctuation': /\|$/ + } + }, + 'attribute': /^[-\w\xA0-\uFFFF]+/, + 'value': [ + /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, + { + pattern: /(=\s*)[-\w\xA0-\uFFFF]+(?=\s*$)/, + lookbehind: true + } + ], + 'operator': /[|~*^$]?=/ + } + } } }; diff --git a/components/prism-css-extras.min.js b/components/prism-css-extras.min.js index d04698b231..5292a3aa8b 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","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*/i,lookbehind:!0}}),Prism.languages.insertBefore("css","function",{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 +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:{pattern:/\[(?:[^[\]"']|("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1)+\]/,greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/( )[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^[-*\w\xA0-\uFFFF]*\|(?!=)/,inside:{punctuation:/\|$/}},attribute:/^[-\w\xA0-\uFFFF]+/,value:[/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,{pattern:/(=\s*)[-\w\xA0-\uFFFF]+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}}}},Prism.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*/i,lookbehind:!0}}),Prism.languages.insertBefore("css","function",{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/selector_attribute_feature.test b/tests/languages/css!+css-extras/selector_attribute_feature.test new file mode 100644 index 0000000000..89cc99c95c --- /dev/null +++ b/tests/languages/css!+css-extras/selector_attribute_feature.test @@ -0,0 +1,230 @@ +[attr] {} + +[attr=val] {} +[attr="val"] {} +[attr='val'] {} +[attr|=val] {} +[attr~=val] {} +[attr|=val] {} +[attr^=val] {} +[attr$=val] {} +[attr*=val] {} + +[foo|attr][*|attr][|attr] {} +[foo|attr|=val] {} + +[attr = val i] {} +[attr = "val" S] {} + +[attr="i#m :not(a.class)"] {} + +---------------------------------------------------- + +[ + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["operator", "="], + ["value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["operator", "="], + ["value", "\"val\""], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["operator", "="], + ["value", "'val'"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["operator", "|="], + ["value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["operator", "~="], + ["value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["operator", "|="], + ["value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["operator", "^="], + ["value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["operator", "$="], + ["value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["operator", "*="], + ["value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["namespace", [ + "foo", + ["punctuation", "|"] + ]], + ["attribute", "attr"], + ["punctuation", "]"] + ]], + ["attribute", [ + ["punctuation", "["], + ["namespace", [ + "*", + ["punctuation", "|"] + ]], + ["attribute", "attr"], + ["punctuation", "]"] + ]], + ["attribute", [ + ["punctuation", "["], + ["namespace", [ + ["punctuation", "|"] + ]], + ["attribute", "attr"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["namespace", [ + "foo", + ["punctuation", "|"] + ]], + ["attribute", "attr"], + ["operator", "|="], + ["value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["operator", "="], + ["value", "val"], + ["case-sensitivity", "i"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["operator", "="], + ["value", "\"val\""], + ["case-sensitivity", "S"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["operator", "="], + ["value", "\"i#m :not(a.class)\""], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"] +] + +---------------------------------------------------- + +Checks for attributes inside selectors. \ No newline at end of file diff --git a/tests/languages/css!+css-extras/selector_feature.test b/tests/languages/css!+css-extras/selector_feature.test index 3931a66334..475ed1b7c4 100644 --- a/tests/languages/css!+css-extras/selector_feature.test +++ b/tests/languages/css!+css-extras/selector_feature.test @@ -9,8 +9,6 @@ foo#bar { #foo > .bar:not(baz):after { -div[foo="bar"] { - ---------------------------------------------------- [ @@ -45,11 +43,6 @@ div[foo="bar"] { ["class", ".bar"], ["pseudo-class", ":not(baz)"], ["pseudo-element", ":after"] - ]], ["punctuation", "{"], - - ["selector", [ - "div", - ["attribute", "[foo=\"bar\"]"] ]], ["punctuation", "{"] ] From 6509dbe448ee1b104983702776c2c3cc2a18cdda Mon Sep 17 00:00:00 2001 From: Michael Schmidt Date: Sat, 22 Dec 2018 22:33:10 +0100 Subject: [PATCH 2/3] Allowed more spaces --- components/prism-css-extras.js | 8 +++- components/prism-css-extras.min.js | 2 +- .../selector_attribute_feature.test | 43 ++++++++++++++++++- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/components/prism-css-extras.js b/components/prism-css-extras.js index 41105cd67e..e1bf353214 100644 --- a/components/prism-css-extras.js +++ b/components/prism-css-extras.js @@ -16,12 +16,16 @@ Prism.languages.css.selector = { alias: 'keyword' }, 'namespace': { - pattern: /^[-*\w\xA0-\uFFFF]*\|(?!=)/, + pattern: /^(\s*)[-*\w\xA0-\uFFFF]*\|(?!=)/, + lookbehind: true, inside: { 'punctuation': /\|$/ } }, - 'attribute': /^[-\w\xA0-\uFFFF]+/, + 'attribute': { + pattern: /^(\s*)[-\w\xA0-\uFFFF]+/, + lookbehind: true + }, 'value': [ /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, { diff --git a/components/prism-css-extras.min.js b/components/prism-css-extras.min.js index 5292a3aa8b..cfb34eaacd 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:{pattern:/\[(?:[^[\]"']|("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1)+\]/,greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/( )[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^[-*\w\xA0-\uFFFF]*\|(?!=)/,inside:{punctuation:/\|$/}},attribute:/^[-\w\xA0-\uFFFF]+/,value:[/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,{pattern:/(=\s*)[-\w\xA0-\uFFFF]+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}}}},Prism.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*/i,lookbehind:!0}}),Prism.languages.insertBefore("css","function",{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 +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:{pattern:/\[(?:[^[\]"']|("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1)+\]/,greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/( )[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)[-*\w\xA0-\uFFFF]*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},attribute:{pattern:/^(\s*)[-\w\xA0-\uFFFF]+/,lookbehind:!0},value:[/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,{pattern:/(=\s*)[-\w\xA0-\uFFFF]+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}}}},Prism.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*/i,lookbehind:!0}}),Prism.languages.insertBefore("css","function",{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/selector_attribute_feature.test b/tests/languages/css!+css-extras/selector_attribute_feature.test index 89cc99c95c..25d1259f2b 100644 --- a/tests/languages/css!+css-extras/selector_attribute_feature.test +++ b/tests/languages/css!+css-extras/selector_attribute_feature.test @@ -13,8 +13,12 @@ [foo|attr][*|attr][|attr] {} [foo|attr|=val] {} -[attr = val i] {} -[attr = "val" S] {} +[attr=val i] {} +[attr="val" S] {} + +[ attr ] {} +[ attr = val ] {} +[ attr = val i] {} [attr="i#m :not(a.class)"] {} @@ -212,6 +216,41 @@ ["punctuation", "{"], ["punctuation", "}"], + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["operator", "="], + ["value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attribute", "attr"], + ["operator", "="], + ["value", "val"], + ["case-sensitivity", "i"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + ["selector", [ ["attribute", [ ["punctuation", "["], From eef02de10cc49b431e59673251142e783aaa9bd2 Mon Sep 17 00:00:00 2001 From: RunDevelopment Date: Mon, 4 Mar 2019 22:03:44 +0100 Subject: [PATCH 3/3] Minor improvements --- components/prism-css-extras.js | 4 ++-- components/prism-css-extras.min.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/prism-css-extras.js b/components/prism-css-extras.js index e1bf353214..6000210d59 100644 --- a/components/prism-css-extras.js +++ b/components/prism-css-extras.js @@ -6,12 +6,12 @@ Prism.languages.css.selector = { 'class': /\.[-:.\w]+/, 'id': /#[-:.\w]+/, 'attribute': { - pattern: /\[(?:[^[\]"']|("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1)+\]/, + pattern: /\[(?:[^[\]"']|("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1)*\]/, greedy: true, inside: { 'punctuation': /^\[|\]$/, 'case-sensitivity': { - pattern: /( )[si]$/i, + pattern: /(\s)[si]$/i, lookbehind: true, alias: 'keyword' }, diff --git a/components/prism-css-extras.min.js b/components/prism-css-extras.min.js index cfb34eaacd..436e552744 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:{pattern:/\[(?:[^[\]"']|("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1)+\]/,greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/( )[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)[-*\w\xA0-\uFFFF]*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},attribute:{pattern:/^(\s*)[-\w\xA0-\uFFFF]+/,lookbehind:!0},value:[/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,{pattern:/(=\s*)[-\w\xA0-\uFFFF]+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}}}},Prism.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*/i,lookbehind:!0}}),Prism.languages.insertBefore("css","function",{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 +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:{pattern:/\[(?:[^[\]"']|("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1)*\]/,greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)[-*\w\xA0-\uFFFF]*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},attribute:{pattern:/^(\s*)[-\w\xA0-\uFFFF]+/,lookbehind:!0},value:[/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,{pattern:/(=\s*)[-\w\xA0-\uFFFF]+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}}}},Prism.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*/i,lookbehind:!0}}),Prism.languages.insertBefore("css","function",{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