CSS grammar for tree-sitter.
References
CSS grammar for Tree-sitter
License: MIT License
CSS grammar for tree-sitter.
References
I'm trying to run Atom in development mode using an extension that has tree-sitter-css as a dependency. I can't do that because of the above error. Is there a way to get this to work on Windows?
body {
top: 3px;
left: -2px;
}
Negative numbers should be integer_value
or float_value
instead of plain_value
.
I've noticed some weird highlighting issues with the grid-template
shorthand:
.grid {
display: grid;
grid-template:
[header-left] "header header header" 8rem [header-right]
[main-left] "nav article aside" 1fr [main-right]
[footer-left] "footer footer footer" 8rem [footer-right]
/ 20% 60% 20%;
min-height: 100vh;
max-width: 100vw;
}
The grid-template
shorthand makes highlighting go funky through to the rest of the block. I think perhaps it's the line names that are causing it? I don't think it likes the square brackets.
I'm attempting to do this to create a Less parser:
const css = require('tree-sitter-css/grammar')
module.exports = grammar(css, { ...
This throws the Undefined symbols
error on tree-sitter parse
and tree-sitter test
. Is this a tree-sitter
issue or an issue with the implementation in this repo? Related: tree-sitter/tree-sitter#1497
ast-grep is using a lot of tree-sitter grammars and is going to upgrading the tree-sitter parser library.
However, tree-sitter-css's dependency range is blocking the upgrade.
I do think this will be a more ecosystem breaking change without all parsers upgrading at the same time.
Release a new tree-sitter 0.21 compatible version
Make the dependency more compatible by relaxing the version range
No response
Tree sitter considers below code error, due to spacing between property name & colon.
* {
margin : 0;
padding : 0;
box-sizing : border-box;
}
This isn't cosidered as error.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
This makes whole file have red error line, which is annoying.
Neovim 0.5. Latest tree sitter.
Would be rad to support the upcoming CSS Nesting syntax in tree sitter
tree-sitter --version
)tree-sitter 0.22.6
If you start with something like this (similar to the test in the corpuse):
============================
Strings
============================
a {
b: '';
c: '\'hi\'';
d: 'hello}';
}
---
(stylesheet
(rule_set
(selectors
(tag_name))
(block
(declaration
(property_name)
(string_value))
(declaration
(property_name)
(string_value))
(declaration
(property_name)
(string_value)))))
But then change the string to now include a {
token, it errors like:
============================
Strings
============================
a {
b: '';
c: '\'hi\'';
d: '{hello}';
}
I'm not sure if this is a CSS feature or if it's a bug in the parser (it seems to be a bug in the parser though)
Described above
It should just return a string_value without error
.foo {
color: '{hello}';
}
tree-sitter --version
)tree-sitter 0.20.8 (0c49d6745b3fc4822ab02e0018770cd6383a779c)
Apply directive with rem
unit
.hl-title {
@apply text-[2.5rem];
}
AST:
(rule_set) ; [1:1 - 3:1]
(selectors) ; [1:1 - 9]
(class_selector) ; [1:1 - 9]
(class_name) ; [1:2 - 9]
(block) ; [1:11 - 3:1]
(apply_directive) ; [2:3 - 23]
(class_name) ; [2:10 - 22]
(identifier) ; [2:10 - 14]
(ERROR) ; [2:16 - 17]
(integer_value) ; [2:18 - 21]
(unit) ; [2:19 - 21]
rem unit should be parsed
.hl-title {
@apply text-[2.5rem];
}
Fails to compile on node 12
Expected behavior:
Compile successfully
Actual behavior:
The following errors are thrown
../src/binding.cc:13:6: error: variable has incomplete type 'void'
void Init(Handle<Object> exports, Handle<Object> module) {
^
../src/binding.cc:13:11: error: use of undeclared identifier 'Handle'
void Init(Handle<Object> exports, Handle<Object> module) {
^
../src/binding.cc:13:18: error: 'Object' does not refer to a value
void Init(Handle<Object> exports, Handle<Object> module) {
^
/Users/musaibrahim/Library/Caches/node-gyp/12.13.1/include/node/v8.h:3400:17: note:
declared here
class V8_EXPORT Object : public Value {
^
../src/binding.cc:13:26: error: use of undeclared identifier 'exports'
void Init(Handle<Object> exports, Handle<Object> module) {
^
../src/binding.cc:13:35: error: use of undeclared identifier 'Handle'
void Init(Handle<Object> exports, Handle<Object> module) {
^
../src/binding.cc:13:42: error: 'Object' does not refer to a value
void Init(Handle<Object> exports, Handle<Object> module) {
^
/Users/musaibrahim/Library/Caches/node-gyp/12.13.1/include/node/v8.h:3400:17: note:
declared here
class V8_EXPORT Object : public Value {
^
../src/binding.cc:13:50: error: use of undeclared identifier 'module'
void Init(Handle<Object> exports, Handle<Object> module) {
^
../src/binding.cc:13:57: error: expected ';' after top level declarator
void Init(Handle<Object> exports, Handle<Object> module) {
^
;
Reproduces how often:
100%
Here's the piece of the code that exhibits the issue
@media screen {
a:visited {
color: var(--fg-link-visited);
}
a:hover {
text-decoration: underline;
text-underline-offset: var(--space-5xs);
}
a:active {
color: var(--fg-link-visited);
}
}
code,
pre,
kbd,
samp,
var {
font-family: var(--mono-font);
}
Here's the video that showcases the issue
This is noticeable when comparing the default css highlighting with the one from this TS parser:
default css syntax highlighting
the white color is simply a color scheme issue – the parser issue is that both, the classes in the selector and the property, both get the same group @property
, which I checked with TS playground:
Overall, this leads to worse syntax highlighting, regardless the theme.
The latest stable release (tag) is over two years ago. Please release/tag a new version.
@media screen and (color) and (color: 8) {}
The first color
is keyword_query
whereas the second is feature_name
. Both should be feature_name
.
Hello!
I'm using Tailwind, which supports this syntax:
.selector {
@apply variable-a meta-variable-b lots-of-combined-properties-c;
}
but with the current parser, I get a squiggly on everything after variable-a
Is PostCSS / varying grammars in scope for tree-sitter-css?
tree-sitter --version
)No response
In an editor, I noticed that a class selector gets marked as an error if I use non-ASCII letters. Looking at the source code here, it seems that identifiers are constrained to ASCII. This is not correct; CSS allows basically any non-ASCII character in identifiers.
Use a non-ASCII character in an identifier. One example is the letter á.
Non-ASCII letters should not appear as errors.
/* Example code that fails to parse */
.skráning {
background-color: white;
}
master seems to work with last API changes. Any chance for an stable release for this grammar? ;)
Expected:
URLs inside the url()
function that do not include quotation marks are perfectly valid.
Current behaviour:
URLs inside the url()
function that do not include quotation marks are considered errors.
reference: https://developer.mozilla.org/en-US/docs/Web/CSS/url#syntax
The following are all valid and equivalent:
<css_property>: url("https://example.com/image.png") <css_property>: url('https://example.com/image.png') <css_property>: url(https://example.com/image.png)
The recent changes to the scanner with handling of colons for pseudo classes I believe broke parsing in certain circumstances including this example in the atom.io.css example file.
@media screen and (min-width: 0 0) {
.tooltipped-multiline: after {
width: 250px;
}
}.tooltipped-sticky:before, .tooltipped-sticky:after {
Hi,
not sure where is the best place to ask about it. Feel free to delete it if that's not the right place.
I extensively work with scss
and would really like to have tree sitter parser for it. Could support for sass/scss
be added to this parser or does new one need to be created?
Thanks.
The ::slotted(element)
selector does not parse up properly.
::slotted(button) {}
actual:
(stylesheet
(rule_set
(selectors
(pseudo_element_selector
(tag_name)))
(ERROR
(UNEXPECTED 'u')
(to)
(UNEXPECTED '))
(block)))
expected (initial draft)
(stylesheet
(rule_set
(selectors
(pseudo_element_selector
(tag_name)
(arguments (tag_name)))
{
"type": "StyleSheet",
"loc": {
"source": "<unknown>",
"start": {
"offset": 0,
"line": 1,
"column": 1
},
"end": {
"offset": 20,
"line": 1,
"column": 21
}
},
"children": [
{
"type": "Rule",
"loc": {
"source": "<unknown>",
"start": {
"offset": 0,
"line": 1,
"column": 1
},
"end": {
"offset": 20,
"line": 1,
"column": 21
}
},
"prelude": {
"type": "SelectorList",
"loc": {
"source": "<unknown>",
"start": {
"offset": 0,
"line": 1,
"column": 1
},
"end": {
"offset": 17,
"line": 1,
"column": 18
}
},
"children": [
{
"type": "Selector",
"loc": {
"source": "<unknown>",
"start": {
"offset": 0,
"line": 1,
"column": 1
},
"end": {
"offset": 17,
"line": 1,
"column": 18
}
},
"children": [
{
"type": "PseudoElementSelector",
"loc": {
"source": "<unknown>",
"start": {
"offset": 0,
"line": 1,
"column": 1
},
"end": {
"offset": 17,
"line": 1,
"column": 18
}
},
"name": "slotted",
"children": [
{
"type": "Selector",
"loc": {
"source": "<unknown>",
"start": {
"offset": 10,
"line": 1,
"column": 11
},
"end": {
"offset": 16,
"line": 1,
"column": 17
}
},
"children": [
{
"type": "TypeSelector",
"loc": {
"source": "<unknown>",
"start": {
"offset": 10,
"line": 1,
"column": 11
},
"end": {
"offset": 16,
"line": 1,
"column": 17
}
},
"name": "button"
}
]
}
]
}
]
}
]
},
"block": {
"type": "Block",
"loc": {
"source": "<unknown>",
"start": {
"offset": 18,
"line": 1,
"column": 19
},
"end": {
"offset": 20,
"line": 1,
"column": 21
}
},
"children": []
}
}
]
}
span:nth-child(even),
tr:nth-child(2n+1),
div:nth-child(4) {}
Arguments for pseudo-classes should have appropriate scopes.
This may be the incorrect place to post this so I might cross post on the nvim-treesitter repository as well. I was messing around with neovim but received an notification from windows defender about a possible trojan (Trojan:Win64/Cobaltstrike.RDA!MTB). The file specifically was located here: "nvim-treesitter\parser\css.so".
I can only assume that this file was created after I installed css language support with nvim-treesitter.
I uploaded it to virus total (https://www.virustotal.com/gui/file/6898b45039bfd4bcb56fa9a82a359d07b8fcd688ba68ce06913c224d04c60aea/behavior) and while it didn't suggest that it was malicious it did mention some odd behavior.
I'm hoping this is a false positive but you never know. My apologies if this is something more specific to my setup.
The namespace declarations work as expected but the namespace selectors do not:
@namespace svg url(http://www.w3.org/2000/svg);
@namespace xl "http://www.w3.org/1999/xlink";
svg|a {}
[xl|href] {}
namespace_statement [0, 0] - [0, 47]
namespace_name [0, 11] - [0, 14]
call_expression [0, 15] - [0, 46]
function_name [0, 15] - [0, 18]
arguments [0, 18] - [0, 46]
plain_value [0, 19] - [0, 45]
namespace_statement [1, 0] - [1, 45]
namespace_name [1, 11] - [1, 13]
string_value [1, 14] - [1, 44]
rule_set [3, 0] - [3, 8]
selectors [3, 0] - [3, 3]
tag_name [3, 0] - [3, 3]
ERROR [3, 3] - [3, 5]
ERROR [3, 3] - [3, 5]
block [3, 6] - [3, 8]
rule_set [5, 0] - [5, 12]
selectors [5, 0] - [5, 9]
attribute_selector [5, 0] - [5, 9]
attribute_name [5, 1] - [5, 3]
ERROR [5, 3] - [5, 8]
ERROR [5, 3] - [5, 8]
block [5, 10] - [5, 12]
div {
transition: width 2s ease;
transition-property: opacity;
}
Transitioned properties (width
, opacity
, etc.) should be property_name
instead of plain_value
.
Let's define an incomplete selector as a CSS selector that the user is in the process of typing which doesn't yet have any trailing braces.
This is the current behavior of tree-sitter-css
. In these examples, assume we’re in an otherwise empty file:
div
stylesheet [0, 0] - [1, 0]
ERROR [0, 0] - [0, 3]
attribute_name [0, 0] - [0, 3]
div:foo
stylesheet [0, 0] - [1, 0]
declaration [0, 0] - [0, 7]
property_name [0, 0] - [0, 3]
plain_value [0, 4] - [0, 7]
MISSING ; [0, 7] - [0, 7]
:foo
stylesheet [0, 0] - [1, 0]
ERROR [0, 0] - [0, 4]
pseudo_class_selector [0, 0] - [0, 4]
class_name [0, 1] - [0, 4]
div[foo]
stylesheet [0, 0] - [1, 0]
ERROR [0, 0] - [0, 8]
attribute_selector [0, 0] - [0, 8]
tag_name [0, 0] - [0, 3]
attribute_name [0, 4] - [0, 7]
For the most part, there’s a logic to these examples that I can reason through:
div:foo
. It makes more sense to me for the parser to interpret it as a selector until it has more information.What’s tricky about these examples is that they all behave differently in an empty file — or at the very end of a file — than they do if the incomplete selector is being typed in the middle of an existing file…
div
div {}
…in which case the parser joins it to the following selector and parses it less ambiguously.
I found all this while trying to adapt Pulsar’s autocomplete-css
, which never properly worked with the Tree-sitter CSS grammar. If a user is typing a selector in a brand-new CSS file, we can’t accurately highlight certain selectors until the user types {
; not ideal, but understandable.
But it also means that autocompletion suggestions will be either missing or flat-out wrong. My wish is that tree-sitter-css
be able to parse these incomplete selectors well enough for us to be able to use that output to offer accurate contextual completions.
My suggested fixes for the first two examples would be something like this:
div
stylesheet [0, 0] - [1, 0]
ERROR [0, 0] - [0, 3]
tag_name [0, 0] - [0, 3]
div:foo
stylesheet [0, 0] - [1, 0]
ERROR [0, 0] - [0, 7]
pseudo_class_selector [0, 0] - [0, 7]
tag_name [0, 0] - [0, 3]
class_name [0, 4] - [0, 7]
In other words, the parser should assume that arbitrary text at the root of a document is a selector — even when it isn’t yet valid — until that text is unambigously something else.
In the example of a user typing div:foo
, I’d want the parser to assume it’s dealing with a CSS selector after every keystroke. If the user instead typed div: foo
, I’d expect the parser to change its mind after the space character, and no earlier.
I think this behavior could be introduced without breaking any existing CSS parsing — even in, for example, a case where someone wants to highlight
display: block;
as CSS on a blog post without having to place it inside a selector.
I might try to contribute a PR for this one day if I get more comfortable working with parsers.
tree-sitter --version
)No response
Only certain kinds of selectors fail to be parsed within a :has
— class_selector
and id_selector
when they have tag names.
This parses correctly:
div.myclass:has(li) {}
(stylesheet [0, 0] - [1, 0]
(rule_set [0, 0] - [0, 22]
(selectors [0, 0] - [0, 19]
(pseudo_class_selector [0, 0] - [0, 19]
(class_selector [0, 0] - [0, 11]
(tag_name [0, 0] - [0, 3])
(class_name [0, 4] - [0, 11]))
(class_name [0, 12] - [0, 15])
(arguments [0, 15] - [0, 19]
(tag_name [0, 16] - [0, 18]))))
(block [0, 20] - [0, 22])))
This does not:
div.myclass:has(li.foo) {}
(stylesheet [0, 0] - [0, 30]
(rule_set [0, 0] - [0, 30]
(selectors [0, 0] - [0, 27]
(pseudo_class_selector [0, 0] - [0, 27]
(class_selector [0, 0] - [0, 11]
(tag_name [0, 0] - [0, 3])
(class_name [0, 4] - [0, 11]))
(class_name [0, 12] - [0, 15])
(arguments [0, 15] - [0, 27]
(plain_value [0, 16] - [0, 26]))))
(block [0, 28] - [0, 30])))
Here are some other examples that parse exactly as expected:
div.myclass:has(#foo) {}
div.myclass:has(.bar) {}
div.myclass:has(foo[bar]) {}
div.myclass:has(li ~ p) {}
div.myclass:has(li p) {}
div.myclass:has(p li.foo) {} /* (weirdly enough) */
And here are some which are interpreted as plain_value
:
div.myclass:has(li#foo) {}
div.myclass:has(li.foo) {}
div.myclass:has(li.foo p) {}
div.myclass:has(p.bar li.foo) {}
In each of these cases, the plain_value
should instead be a selectors
node. :has
can accept selectors of arbitrary complexity, much like :not
.
No response
p[data-foo]::before {
content: attr(data-foo);
}
The argument passed to attr()
should be attribute_name
instead of plain_value
.
I'm doing some tree-sitter work and wanted to use the languages, but I noticed this one doesn't have a license. All the other ones I've looked at (tree-sitter-html, tree-sitter-css, etc) are MIT licensed. Could you add one here whenever you get a chance?
I noticed that this language is not published to crates.io while many other tree sitter languages are. Is there a reason for that?
There is no way to differentiate a tag from a pseudo-element. Consider:
tag::element {}
element
is pseudo_element_selector
> tag_name
tag
is also pseudo_element_selector
> tag_name
div {
all:unset;
display: flex;
justify-content: center;
}
generates
rule_set [0, 0] - [4, 1]
selectors [0, 0] - [0, 3]
tag_name [0, 0] - [0, 3]
block [0, 4] - [4, 1]
ERROR [1, 2] - [3, 26]
descendant_selector [1, 2] - [3, 25]
descendant_selector [1, 2] - [3, 17]
descendant_selector [1, 2] - [2, 15]
descendant_selector [1, 2] - [2, 9]
pseudo_class_selector [1, 2] - [1, 11]
tag_name [1, 2] - [1, 5]
class_name [1, 6] - [1, 11]
ERROR [1, 11] - [1, 12]
tag_name [2, 2] - [2, 9]
ERROR [2, 9] - [2, 10]
tag_name [2, 11] - [2, 15]
ERROR [2, 15] - [2, 16]
tag_name [3, 2] - [3, 17]
ERROR [3, 17] - [3, 18]
tag_name [3, 19] - [3, 25]
As oppesed to the case where there is a space following the all::
div {
all: unset;
display: flex;
justify-content: center;
}
rule_set [0, 0] - [4, 1]
selectors [0, 0] - [0, 3]
tag_name [0, 0] - [0, 3]
block [0, 4] - [4, 1]
declaration [1, 2] - [1, 13]
property_name [1, 2] - [1, 5]
plain_value [1, 7] - [1, 12]
declaration [2, 2] - [2, 16]
property_name [2, 2] - [2, 9]
plain_value [2, 11] - [2, 15]
declaration [3, 2] - [3, 26]
property_name [3, 2] - [3, 17]
plain_value [3, 19] - [3, 25]
tree-sitter --version
)tree-sitter 0.22.1
The psuedo-element selector test fails on the latest master, with tree-sitter 0.22.1.
declarations:
✓ Function calls
✓ Calls where each argument has multiple values
✓ Color literals
✓ Numbers
✓ Binary arithmetic operators
✓ Strings
✓ URLs
✓ Important declarations
✓ Declarations without trailing semicolons
✓ Comments right after numbers
✓ Declarations at the top level
✓ Spaces after colons in property declarations
✓ No spaces after colons
✓ PostCSS
selectors:
✓ Universal selectors
✓ Type selectors
✓ Class selectors
✓ Id selectors
✓ Attribute selectors
✓ Pseudo-class selectors
✗ Pseudo-element selectors
✓ Child selectors
✓ Descendant selectors
✓ Nesting selectors
✓ Sibling selectors
✓ The :not selector
statements:
✓ Import statements
✓ Namespace statements
✓ Keyframes statements
✓ Media statements
✓ Supports statements
✓ Charset statements
✓ Other at-statements
stylesheets:
✓ Rule sets
1 failure:
correct / expected / unexpected
1. Pseudo-element selectors:
(stylesheet
(rule_set
(selectors
(pseudo_element_selector
(tag_name)
(tag_name)))
(block))
(rule_set
(selectors
(descendant_selector
(descendant_selector
(descendant_selector
(descendant_selector
(tag_name)
(ERROR
(attribute_name)
(attribute_name)
(attribute_name)
(attribute_name)
(attribute_name)
(attribute_name)
(attribute_name))
(pseudo_element_selector
(tag_name)))
(tag_name))
(tag_name))
(ERROR)
(pseudo_element_selector
(tag_name)
(arguments
(tag_name)))))
(arguments
(tag_name))))
(block)))
npm i
in the tree-sitter-css directory as this will install tree-sitter 0.20.8.tree-sitter test
Test pass.
No response
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.