diff --git a/grammars/tree-sitter-html.cson b/grammars/tree-sitter-html.cson index de8641a..1a0b422 100644 --- a/grammars/tree-sitter-html.cson +++ b/grammars/tree-sitter-html.cson @@ -34,3 +34,23 @@ scopes: 'attribute_name': 'entity.other.attribute-name' 'attribute_value': 'string.html' 'comment': 'comment.block.html' + + ' + start_tag > "<", + end_tag > " ">", + end_tag > ">" + ': 'punctuation.definition.tag.end' + + 'attribute > "="': 'punctuation.separator.key-value.html' + + # quoted_attribute_value has three child nodes: ", attribute_value, and ". + # Target the first and last. + # Single quotes and double quotes are targeted in separate selectors because + # of quote-escaping difficulties. + "quoted_attribute_value > '\"':nth-child(0)": 'punctuation.definition.string.begin' + 'quoted_attribute_value > "\'":nth-child(0)': 'punctuation.definition.string.begin' + "quoted_attribute_value > '\"':nth-child(2)": 'punctuation.definition.string.end' + 'quoted_attribute_value > "\'":nth-child(2)': 'punctuation.definition.string.end' diff --git a/package.json b/package.json index 3cf9d93..6ad6e8c 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,11 @@ }, "dependencies": { "atom-grammar-test": "^0.6.3", - "tree-sitter-html": "^0.15.0", - "tree-sitter-embedded-template": "^0.15.0" + "tree-sitter-embedded-template": "^0.15.0", + "tree-sitter-html": "^0.15.0" }, "devDependencies": { - "coffeelint": "^1.10.1" + "coffeelint": "^1.10.1", + "dedent": "^0.7.0" } } diff --git a/spec/tree-sitter-spec.js b/spec/tree-sitter-spec.js new file mode 100644 index 0000000..df13e18 --- /dev/null +++ b/spec/tree-sitter-spec.js @@ -0,0 +1,81 @@ +const dedent = require('dedent') + +describe('Tree-sitter HTML grammar', () => { + + beforeEach(async () => { + atom.config.set('core.useTreeSitterParsers', true) + await atom.packages.activatePackage('language-html') + }) + + it('tokenizes punctuation in HTML tags and attributes', async () => { + const editor = await atom.workspace.open(`test.html`) + + editor.setText(dedent` + + + + + + + + `) + + // Tag punctuation. + expect(editor.scopeDescriptorForBufferPosition([0, 0]).toString()).toBe( + '.text.html.basic .source.html .punctuation.definition.tag.begin' + ) + + expect(editor.scopeDescriptorForBufferPosition([0, 15]).toString()).toBe( + '.text.html.basic .source.html .punctuation.definition.tag.end' + ) + + expect(editor.scopeDescriptorForBufferPosition([6, 0]).toString()).toBe( + '.text.html.basic .source.html .punctuation.definition.tag.begin' + ) + + expect(editor.scopeDescriptorForBufferPosition([6, 6]).toString()).toBe( + '.text.html.basic .source.html .punctuation.definition.tag.end' + ) + + // Attribute-value pair punctuation. + expect(editor.scopeDescriptorForBufferPosition([0, 10]).toString()).toBe( + '.text.html.basic .source.html .punctuation.separator.key-value.html' + ) + + expect(editor.scopeDescriptorForBufferPosition([2, 18]).toString()).toBe( + '.text.html.basic .source.html .punctuation.definition.string.begin' + ) + + expect(editor.scopeDescriptorForBufferPosition([2, 24]).toString()).toBe( + '.text.html.basic .source.html .punctuation.definition.string.end' + ) + + // Ensure an attribute value delimited by single-quotes won't mark a + // double-quote in the value as punctuation. + expect(editor.scopeDescriptorForBufferPosition([3, 15]).toString()).toBe( + '.text.html.basic .source.html .punctuation.definition.string.begin' + ) + + expect(editor.scopeDescriptorForBufferPosition([3, 16]).toString()).toBe( + '.text.html.basic .source.html .string.html' + ) + + expect(editor.scopeDescriptorForBufferPosition([3, 17]).toString()).toBe( + '.text.html.basic .source.html .punctuation.definition.string.end' + ) + + // Ensure an attribute value delimited by double-quotes won't mark a + // single-quote in the value as punctuation. + expect(editor.scopeDescriptorForBufferPosition([3, 27]).toString()).toBe( + '.text.html.basic .source.html .punctuation.definition.string.begin' + ) + + expect(editor.scopeDescriptorForBufferPosition([3, 32]).toString()).toBe( + '.text.html.basic .source.html .string.html' + ) + + expect(editor.scopeDescriptorForBufferPosition([3, 66]).toString()).toBe( + '.text.html.basic .source.html .punctuation.definition.string.end' + ) + }) +})