From 4ba71eee8d8991c95028df40cb784cb9cb2e964d Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Thu, 10 Sep 2020 20:40:34 +0200 Subject: Convert indent test for css-mode into automatic test * test/lisp/textmodes/css-mode-tests.el (css-mode-test-indent): New test. (css-mode-tests-data-dir): New variable. * test/manual/indent/css-mode.css: Move from here... * test/lisp/textmodes/css-mode-resources/test-indent.css: ...to here. --- .../textmodes/css-mode-resources/test-indent.css | 100 +++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 test/lisp/textmodes/css-mode-resources/test-indent.css (limited to 'test/lisp/textmodes/css-mode-resources') diff --git a/test/lisp/textmodes/css-mode-resources/test-indent.css b/test/lisp/textmodes/css-mode-resources/test-indent.css new file mode 100644 index 00000000000..041aeec1b15 --- /dev/null +++ b/test/lisp/textmodes/css-mode-resources/test-indent.css @@ -0,0 +1,100 @@ +/* asdfasdf */ + +.xxx +{ +} + +article[role="main"] { + width: 60%; +} + +a, b:hover, c { + color: black !important; +} + +a, b:hover { /* bug:20282 */ + c { + color: black; + } + color: black; +} + +a.b:c,d.e:f,g[h]:i,j[k]:l,.m.n:o,.p.q:r,.s[t]:u,.v[w]:x { /* bug:20282 */ + background-color: white; +} + +/* asdfasdf */ +@foo x2 { + bla:toto; +} +.x2 +{ + /* foo: bar; */ foo2: bar2; + bar1: url("http://toto/titi"); + bar2: url('http://toto/titi'); + bar3: url(http://toto/titi); +} + +div.x3 +{ +} + +article:hover +{ + color: black; +} + +/* bug:13425 */ +div:first-child, +div:last-child, +div[disabled], +div::before { + font: 15px "Helvetica Neue", + Helvetica, + Arial, + "Nimbus Sans L", + sans-serif; + font: 15px "Helvetica Neue", Helvetica, Arial, + "Nimbus Sans L", sans-serif; + background: no-repeat right + 5px center; + transform: matrix(1.0, 2.0, + 3.0, 4.0, + 5.0, 6.0); + transform: matrix( + 1.0, 2.0, + 3.0, 4.0, + 5.0, 6.0 + ); +} + +/* Multi-line selector including both a pseudo-class and + parenthesis. */ +.form-group:not(.required) label, +.birth-date .row > * { + &::after { + display: inline; + font-weight: normal; + } +} + +@font-face { + src: url("Sans-Regular.eot") format("eot"), + url("Sans-Regular.woff") format("woff"), + url("Sans-Regular.ttf") format("truetype"); +} + +@font-face { + src: + url("Sans-Regular.eot") format("eot"), + url("Sans-Regular.woff") format("woff"); +} + +.foo-bar--baz { + --foo-variable: 5px; + --_variable_with_underscores: #fff; + --_variable-starting-with-underscore: none; + margin: var(--foo-variable); + color: var(--_variable_with_underscores); + display: var(--_variable-starting-with-underscore); +} -- cgit v1.2.3 From 0da7689b167dd92c0ac307122be0a742a10abfb4 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sun, 15 May 2022 14:13:14 +0200 Subject: Don't freeze Emacs on colour codes in sccs-mode * lisp/textmodes/css-mode.el (css--font-lock-keywords): Don't freeze Emacs on #ffffff #ffffff, and be more strict in parsing selectors (bug#53203). --- lisp/textmodes/css-mode.el | 56 +++++++++++------- .../textmodes/css-mode-resources/css-selectors.txt | 56 ++++++++++++++++++ .../css-mode-resources/scss-selectors.txt | 6 ++ test/lisp/textmodes/css-mode-tests.el | 69 ++++++++++++++++++++++ 4 files changed, 166 insertions(+), 21 deletions(-) create mode 100644 test/lisp/textmodes/css-mode-resources/css-selectors.txt create mode 100644 test/lisp/textmodes/css-mode-resources/scss-selectors.txt (limited to 'test/lisp/textmodes/css-mode-resources') diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el index ef7debc4bdb..99b4482dc53 100644 --- a/lisp/textmodes/css-mode.el +++ b/lisp/textmodes/css-mode.el @@ -928,6 +928,32 @@ cannot be completed sensibly: `custom-ident', (defface css-proprietary-property '((t :inherit (css-property italic))) "Face to use for vendor-specific properties.") +(defun css--selector-regexp (sassy) + (concat + "\\(?:" + (if (not sassy) + "[-_%*#.>[:alnum:]]+" + ;; Same as for non-sassy except we do want to allow { and } + ;; chars in selectors in the case of #{$foo} + ;; variable interpolation! + (concat "\\(?:[-_%*#.>[:alnum:]]*" scss--hash-re + "\\|[-_%*#.>[:alnum:]]+\\)")) + ;; Even though pseudo-elements should be prefixed by ::, a + ;; single colon is accepted for backward compatibility. + "\\(?:\\(:" (regexp-opt (append css-pseudo-class-ids + css-pseudo-element-ids) + t) + "\\|::" (regexp-opt css-pseudo-element-ids t) "\\)\\)?" + ;; Braces after selectors. + "\\(?:\\[[^]\n]+\\]\\)?" + ;; Parentheses after selectors. + "\\(?:([^)]+)\\)?" + ;; Main bit over. But perhaps just [target]? + "\\|\\[[^]\n]+\\]" + ;; :root, ::marker and the like. + "\\|::?[[:alnum:]]+\\(?:([^)]+)\\)?" + "\\)")) + (defun css--font-lock-keywords (&optional sassy) `((,(concat "!\\s-*" (regexp-opt css--bang-ids)) (0 font-lock-builtin-face)) @@ -948,28 +974,16 @@ cannot be completed sensibly: `custom-ident', ;; selector between [...] should simply not be highlighted. (,(concat "^[ \t]*\\(" - (if (not sassy) - ;; We don't allow / as first char, so as not to - ;; take a comment as the beginning of a selector. - "[^@/:{}() \t\n][^:{}()]*" - ;; Same as for non-sassy except we do want to allow { and } - ;; chars in selectors in the case of #{$foo} - ;; variable interpolation! - (concat "\\(?:" scss--hash-re - "\\|[^@/:{}() \t\n#]\\)" - "[^:{}()#]*\\(?:" scss--hash-re "[^:{}()#]*\\)*")) - ;; Even though pseudo-elements should be prefixed by ::, a - ;; single colon is accepted for backward compatibility. - "\\(?:\\(:" (regexp-opt (append css-pseudo-class-ids - css-pseudo-element-ids) - t) - "\\|::" (regexp-opt css-pseudo-element-ids t) "\\)" - "\\(?:([^)]+)\\)?" - (if (not sassy) - "[^:{}()\n]*" - (concat "[^:{}()\n#]*\\(?:" scss--hash-re "[^:{}()\n#]*\\)*")) + ;; We have at least one selector. + (css--selector-regexp sassy) + ;; And then possibly more. + "\\(?:" + ;; Separators between selectors. + "[ \n\t,+~>]+" + (css--selector-regexp sassy) "\\)*" - "\\)\\(?:\n[ \t]*\\)*{") + ;; And then a brace. + "\\)[ \n\t]*{") (1 'css-selector keep)) ;; In the above rule, we allow the open-brace to be on some subsequent ;; line. This will only work if we properly mark the intervening text diff --git a/test/lisp/textmodes/css-mode-resources/css-selectors.txt b/test/lisp/textmodes/css-mode-resources/css-selectors.txt new file mode 100644 index 00000000000..5b3d990f279 --- /dev/null +++ b/test/lisp/textmodes/css-mode-resources/css-selectors.txt @@ -0,0 +1,56 @@ +#firstname +* +p +p.intro +div, p +div p +div > p +div + p +p ~ ul +[target] +[target=_blank] +[title~=flower] +[lang|=en] +a[href^="https"] +a[href$=".pdf"] +a[href*="w3schools"] +a:active +p::after +p::before +input:checked +input:default +input:disabled +p:empty +input:enabled +p:first-child +p::first-letter +p::first-line +p:first-of-type +input:focus +:fullscreen +a:hover +input:in-range +input:indeterminate +input:invalid +p:lang(it) +p:last-child +p:last-of-type +a:link +::marker +:not(p) +p:nth-child(2) +p:nth-last-child(2) +p:nth-last-of-type(2) +p:nth-of-type(2) +p:only-of-type +p:only-child +input:optional +input:out-of-range +input:read-only +input:read-write +input:required +:root +::selection +#news:target +input:valid +a:visited diff --git a/test/lisp/textmodes/css-mode-resources/scss-selectors.txt b/test/lisp/textmodes/css-mode-resources/scss-selectors.txt new file mode 100644 index 00000000000..86e58110b72 --- /dev/null +++ b/test/lisp/textmodes/css-mode-resources/scss-selectors.txt @@ -0,0 +1,6 @@ +p.#{$name} var +p.#{$name}:active var +p.#{$name}::after var +f.#{$bar}::after p::after +p.#{$name} f.#{$bar} k.var #{$bar} #{$bar} +p.#{$name} diff --git a/test/lisp/textmodes/css-mode-tests.el b/test/lisp/textmodes/css-mode-tests.el index 0ae1593508d..555a73c3bbe 100644 --- a/test/lisp/textmodes/css-mode-tests.el +++ b/test/lisp/textmodes/css-mode-tests.el @@ -419,5 +419,74 @@ (indent-region (point-min) (point-max)) (should (equal (buffer-string) orig))))) +(ert-deftest css-mode-test-selectors () + (let ((selectors + (with-temp-buffer + (insert-file-contents (ert-resource-file "css-selectors.txt")) + (string-lines (buffer-string))))) + (with-suppressed-warnings ((interactive font-lock-debug-fontif)) + (dolist (selector selectors) + (with-temp-buffer + (css-mode) + (insert selector " {\n}\n") + (font-lock-debug-fontify) + (goto-char (point-min)) + (unless (eq (get-text-property (point) 'face) + 'css-selector) + (should-not (format "Didn't recognize %s as a selector" + (buffer-substring-no-properties + (point) (line-end-position))))))) + ;; Test many selectors. + (dolist (selector selectors) + (with-temp-buffer + (css-mode) + (insert selector " ") + (dotimes (_ (random 5)) + (insert (seq-random-elt '(" , " " > " " + ")) + (seq-random-elt selectors))) + (insert "{\n}\n") + (font-lock-debug-fontify) + (goto-char (point-min)) + (unless (eq (get-text-property (point) 'face) + 'css-selector) + (should-not (format "Didn't recognize %s as a selector" + (buffer-substring-no-properties + (point) (line-end-position))))))) + ;; Test wrong separators. + (dolist (selector selectors) + (with-temp-buffer + (css-mode) + (insert selector " ") + (dotimes (_ (1+ (random 5))) + (insert (seq-random-elt '("=" " @ ")) + (seq-random-elt selectors))) + (insert "{\n}\n") + (font-lock-debug-fontify) + (goto-char (point-min)) + (when (eq (get-text-property (point) 'face) + 'css-selector) + (should-not (format "Recognized %s as a selector" + (buffer-substring-no-properties + (point) (line-end-position)))))))))) + +(ert-deftest scss-mode-test-selectors () + (let ((selectors + (with-temp-buffer + (insert-file-contents (ert-resource-file "scss-selectors.txt")) + (string-lines (buffer-string))))) + (with-suppressed-warnings ((interactive font-lock-debug-fontif)) + (dolist (selector selectors) + (with-temp-buffer + (scss-mode) + (insert selector " {\n}\n") + (font-lock-debug-fontify) + (goto-char (point-min)) + (unless (eq (get-text-property (point) 'face) + 'css-selector) + (should-not (format "Didn't recognize %s as a selector" + (buffer-substring-no-properties + (point) (line-end-position)))))))))) + + (provide 'css-mode-tests) ;;; css-mode-tests.el ends here -- cgit v1.2.3 From 4aa811585597884398b5be13d92f4af0a06de3e1 Mon Sep 17 00:00:00 2001 From: Simen Heggestøyl Date: Sun, 15 May 2022 16:22:14 +0200 Subject: Recognize some more SCSS selectors * lisp/textmodes/css-mode.el (css--selector-regexp): Recognize some more SCSS selectors. * test/lisp/textmodes/css-mode-resources/scss-selectors.txt: Add tests for them. --- lisp/textmodes/css-mode.el | 4 ++-- test/lisp/textmodes/css-mode-resources/scss-selectors.txt | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'test/lisp/textmodes/css-mode-resources') diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el index 99b4482dc53..a2a7774aba7 100644 --- a/lisp/textmodes/css-mode.el +++ b/lisp/textmodes/css-mode.el @@ -936,8 +936,8 @@ cannot be completed sensibly: `custom-ident', ;; Same as for non-sassy except we do want to allow { and } ;; chars in selectors in the case of #{$foo} ;; variable interpolation! - (concat "\\(?:[-_%*#.>[:alnum:]]*" scss--hash-re - "\\|[-_%*#.>[:alnum:]]+\\)")) + (concat "\\(?:[-_%*#.>&+~[:alnum:]]*" scss--hash-re + "\\|[-_%*#.>&+~[:alnum:]]+\\)")) ;; Even though pseudo-elements should be prefixed by ::, a ;; single colon is accepted for backward compatibility. "\\(?:\\(:" (regexp-opt (append css-pseudo-class-ids diff --git a/test/lisp/textmodes/css-mode-resources/scss-selectors.txt b/test/lisp/textmodes/css-mode-resources/scss-selectors.txt index 86e58110b72..3e05191a910 100644 --- a/test/lisp/textmodes/css-mode-resources/scss-selectors.txt +++ b/test/lisp/textmodes/css-mode-resources/scss-selectors.txt @@ -4,3 +4,7 @@ p.#{$name}::after var f.#{$bar}::after p::after p.#{$name} f.#{$bar} k.var #{$bar} #{$bar} p.#{$name} +&:hover +> li ++ li +~ li -- cgit v1.2.3