@konomanoasa/tree-sitter-gitattributes 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "konomanoasa-tree-sitter-gitattributes"
3
- version = "0.5.0"
3
+ version = "0.7.0"
4
4
  description = "Tree-sitter grammar for gitattributes."
5
5
  readme = "README.md"
6
6
  license = "MIT"
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  [![npm](https://img.shields.io/npm/v/@konomanoasa/tree-sitter-gitattributes)](https://www.npmjs.com/package/@konomanoasa/tree-sitter-gitattributes)
6
6
 
7
7
  [Tree-sitter](https://tree-sitter.github.io/tree-sitter/) grammar for
8
- Git attributes files 2.55.0.
8
+ Git attributes files 2.56.0.
9
9
 
10
10
  ## Installation
11
11
 
@@ -23,8 +23,8 @@ npm test
23
23
 
24
24
  ## Specifications
25
25
 
26
- - [Git 2.55.0 gitattributes manual](https://git-scm.com/docs/gitattributes/2.55.0)
27
- - [Git 2.55.0 gitignore manual](https://git-scm.com/docs/gitignore/2.55.0)
26
+ - [Git 2.56.0 gitattributes manual](https://git-scm.com/docs/gitattributes/2.56.0)
27
+ - [Git 2.56.0 gitignore manual](https://git-scm.com/docs/gitignore/2.56.0)
28
28
 
29
29
  ## License
30
30
 
package/binding.gyp ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "targets": [
3
+ {
4
+ "target_name": "tree_sitter_gitattributes_binding",
5
+ "sources": [
6
+ "bindings/node/binding.cc",
7
+ "src/parser.c",
8
+ "src/scanner.c"
9
+ ],
10
+ "include_dirs": ["src"],
11
+ "dependencies": [
12
+ "<!(node -p \"require('node-addon-api').targets\"):node_addon_api_except"
13
+ ],
14
+ "cflags_c": ["-std=c17"],
15
+ "cflags_cc": ["-std=c++17"],
16
+ "msvs_settings": {
17
+ "VCCLCompilerTool": {
18
+ "AdditionalOptions": ["/utf-8"],
19
+ "AdditionalOptions!": ["-std:c++20"],
20
+ "LanguageStandard": "stdcpp17",
21
+ "LanguageStandard_C": "stdc17"
22
+ }
23
+ },
24
+ "target_conditions": [
25
+ [
26
+ "OS==\"mac\"",
27
+ {
28
+ "xcode_settings": {
29
+ "CLANG_CXX_LANGUAGE_STANDARD": "c++17",
30
+ "GCC_C_LANGUAGE_STANDARD": "c17",
31
+ "MACOSX_DEPLOYMENT_TARGET": "14.0"
32
+ }
33
+ }
34
+ ]
35
+ ]
36
+ }
37
+ ]
38
+ }
@@ -0,0 +1,25 @@
1
+ #include <napi.h>
2
+
3
+ struct TSLanguage;
4
+ extern "C" const TSLanguage *tree_sitter_gitattributes();
5
+
6
+ namespace {
7
+
8
+ constexpr napi_type_tag language_type_tag = {
9
+ 0x8AF2E5212AD58ABF,
10
+ 0xD5006CAD83ABBA16
11
+ };
12
+
13
+ Napi::Object Init(Napi::Env env, Napi::Object exports) {
14
+ auto language = Napi::External<TSLanguage>::New(
15
+ env,
16
+ const_cast<TSLanguage *>(tree_sitter_gitattributes())
17
+ );
18
+ language.TypeTag(&language_type_tag);
19
+ exports["language"] = language;
20
+ return exports;
21
+ }
22
+
23
+ }
24
+
25
+ NODE_API_MODULE(tree_sitter_gitattributes_binding, Init)
@@ -0,0 +1,7 @@
1
+ import type { Language } from "tree-sitter";
2
+
3
+ declare const binding: Language & {
4
+ HIGHLIGHTS_QUERY: string;
5
+ };
6
+
7
+ export default binding;
@@ -0,0 +1,14 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { fileURLToPath } from "node:url";
3
+ import load from "node-gyp-build";
4
+
5
+ const binding = load(fileURLToPath(new URL("../..", import.meta.url)));
6
+ binding.nodeTypeInfo = JSON.parse(
7
+ readFileSync(new URL("../../src/node-types.json", import.meta.url), "utf8"),
8
+ );
9
+ binding.HIGHLIGHTS_QUERY = readFileSync(
10
+ new URL("../../queries/highlights.scm", import.meta.url),
11
+ "utf8",
12
+ );
13
+
14
+ export default binding;
@@ -1,6 +1,6 @@
1
1
  #include <Python.h>
2
2
 
3
- #include "tree_sitter/parser.h"
3
+ #include "../../src/tree_sitter/parser.h"
4
4
 
5
5
  const TSLanguage *tree_sitter_gitattributes(void);
6
6
 
package/grammar.js CHANGED
@@ -1,3 +1,72 @@
1
+ const missingKinds = (name) => [
2
+ [`missing_${name}`, "invalid_syntax", `missing_${name}`],
3
+ [`incomplete_${name}`, "incomplete_syntax", `missing_${name}`],
4
+ ];
5
+ const issueKinds = [
6
+ ...missingKinds("set_close"),
7
+ ["invalid_encoding", "invalid_syntax", "invalid_encoding"],
8
+ ["negative_pattern", "invalid_syntax", "negative_pattern"],
9
+ ["ended_escape", "invalid_syntax", "incomplete_escape"],
10
+ ["incomplete_escape", "incomplete_syntax", "incomplete_escape"],
11
+ ["invalid_quoted_escape", "invalid_syntax", "invalid_quoted_escape"],
12
+ ["ended_quoted_escape", "invalid_syntax", "incomplete_quoted_escape"],
13
+ ["incomplete_quoted_escape", "incomplete_syntax", "incomplete_quoted_escape"],
14
+ ...missingKinds("quote_close"),
15
+ [
16
+ "missing_attribute_separator",
17
+ "invalid_syntax",
18
+ "missing_attribute_separator",
19
+ ],
20
+ ...missingKinds("attribute_name"),
21
+ ["invalid_name_character", "invalid_syntax", "invalid_name_character"],
22
+ ["incomplete_name_character", "incomplete_syntax", "invalid_name_character"],
23
+ [
24
+ "invalid_name_escape",
25
+ "invalid_syntax",
26
+ "invalid_name_character",
27
+ "quoted_escape",
28
+ ],
29
+ ];
30
+ const quotedEscapeIssues = [
31
+ "invalid_quoted_escape",
32
+ "ended_quoted_escape",
33
+ "incomplete_quoted_escape",
34
+ ];
35
+
36
+ const issueRules = Object.fromEntries(
37
+ issueKinds.flatMap(([token, outcome, reason, child]) => [
38
+ ...(child
39
+ ? [[`_${token}_reason`, ($) => alias($[`_${token}`], $[child])]]
40
+ : []),
41
+ [
42
+ `_${token}_outcome`,
43
+ ($) => alias($[child ? `_${token}_reason` : `_${token}`], $[reason]),
44
+ ],
45
+ [`_${token}_issue`, ($) => alias($[`_${token}_outcome`], $[outcome])],
46
+ ]),
47
+ );
48
+ const issue = ($, name) =>
49
+ field("issue", alias($[`_${name}_issue`], $.syntax_issue));
50
+ const issues = ($, ...names) => names.map((name) => issue($, name));
51
+ const missing = ($, name) =>
52
+ choice(issue($, `missing_${name}`), issue($, `incomplete_${name}`));
53
+ const heldPrefix = ($, ...names) =>
54
+ seq($._escape_prefix, choice(...issues($, ...names)));
55
+ const quoteClose = ($) =>
56
+ optional(choice(field("closing", $.quote_close), missing($, "quote_close")));
57
+ const attributeName = ($) =>
58
+ choice(field("name", $.attribute_name), missing($, "attribute_name"));
59
+ const globIssues = ($) => [
60
+ ...issues(
61
+ $,
62
+ "invalid_encoding",
63
+ "ended_escape",
64
+ "incomplete_escape",
65
+ ...quotedEscapeIssues,
66
+ ),
67
+ heldPrefix($, "invalid_encoding", ...quotedEscapeIssues),
68
+ ];
69
+
1
70
  export default grammar({
2
71
  name: "gitattributes",
3
72
  externals: ($) => [
@@ -7,6 +76,7 @@ export default grammar({
7
76
  $._rule_start,
8
77
  $._macro_start,
9
78
  $._eof,
79
+ $.line_ending,
10
80
  $._layout,
11
81
  $._separator,
12
82
  $._attribute_start,
@@ -35,6 +105,7 @@ export default grammar({
35
105
  $.path_separator,
36
106
  $.escape,
37
107
  $.quoted_escape,
108
+ $._escape_prefix,
38
109
  $.set_open,
39
110
  $.set_negation,
40
111
  $.set_text,
@@ -47,52 +118,59 @@ export default grammar({
47
118
  $._class_open,
48
119
  $.class_name,
49
120
  $._class_close,
121
+ ...issueKinds.map(([name]) => $[`_${name}`]),
50
122
  $._error_sentinel,
51
123
  ],
52
- extras: () => [],
124
+ extras: ($) => [$._unmatchable],
53
125
  rules: {
54
- document: ($) => repeat($._line),
55
- _line: ($) =>
56
- seq(
57
- $._line_start,
58
- choice($.blank_line, $.comment, $.attribute_rule, $.macro_definition),
126
+ document: ($) =>
127
+ repeat(
128
+ seq(
129
+ $._line_start,
130
+ choice($.blank_line, $.comment, $.attribute_rule, $.macro_definition),
131
+ ),
59
132
  ),
60
- line_ending: () => /\r?\n/,
133
+ _unmatchable: () => token(seq(/[\s\S]/, /[^\s\S]/)),
61
134
  _end: ($) => seq(optional($._layout), choice($.line_ending, $._eof)),
62
135
  blank_line: ($) => seq($._blank_start, $._end),
63
136
  comment: ($) =>
64
- seq($._comment_start, $.comment_marker, optional($.comment_text), $._end),
137
+ seq(
138
+ $._comment_start,
139
+ $.comment_marker,
140
+ repeat(choice($.comment_text, issue($, "invalid_encoding"))),
141
+ $._end,
142
+ ),
65
143
  attribute_rule: ($) =>
66
144
  seq(
67
145
  $._rule_start,
68
146
  field("pattern", $.pattern),
69
- repeat($._attribute),
147
+ optional($._attributes),
70
148
  $._end,
71
149
  ),
72
150
  macro_definition: ($) =>
73
151
  seq(
74
152
  $._macro_start,
75
- choice(
76
- $._macro_name,
77
- seq(
78
- field("opening", $.quote_open),
79
- $._macro_name,
80
- field("closing", $.quote_close),
81
- ),
82
- ),
83
- repeat($._attribute),
153
+ optional(field("opening", $.quote_open)),
154
+ field("marker", $.macro_marker),
155
+ attributeName($),
156
+ quoteClose($),
157
+ optional($._attributes),
84
158
  $._end,
85
159
  ),
86
- _macro_name: ($) =>
87
- seq(field("marker", $.macro_marker), field("name", $.attribute_name)),
88
- _attribute: ($) => seq($._separator, $.attribute),
160
+ _attributes: ($) =>
161
+ repeat1(
162
+ seq(
163
+ choice($._separator, issue($, "missing_attribute_separator")),
164
+ $.attribute,
165
+ ),
166
+ ),
89
167
  attribute: ($) =>
90
168
  seq(
91
169
  $._attribute_start,
92
170
  optional(
93
171
  field("modifier", choice($.unset_marker, $.unspecified_marker)),
94
172
  ),
95
- field("name", $.attribute_name),
173
+ attributeName($),
96
174
  optional(
97
175
  seq(
98
176
  field("operator", $.assignment_operator),
@@ -104,56 +182,73 @@ export default grammar({
104
182
  attribute_name: ($) =>
105
183
  seq(
106
184
  $._name_start,
107
- repeat1(choice($.name_text, $.quoted_escape)),
185
+ repeat1(
186
+ choice(
187
+ $.name_text,
188
+ $.quoted_escape,
189
+ ...issues(
190
+ $,
191
+ "invalid_encoding",
192
+ "invalid_name_character",
193
+ "incomplete_name_character",
194
+ "invalid_name_escape",
195
+ ...quotedEscapeIssues,
196
+ ),
197
+ heldPrefix($, "invalid_encoding"),
198
+ ),
199
+ ),
108
200
  $._name_end,
109
201
  ),
110
- attribute_value: ($) => seq($._value_start, $.value_text, $._value_end),
111
- pattern: ($) =>
202
+ attribute_value: ($) =>
112
203
  seq(
113
- choice(
114
- repeat1($._glob),
115
- seq(
116
- field("opening", $.quote_open),
117
- repeat($._glob),
118
- field("closing", $.quote_close),
119
- ),
120
- ),
121
- $._pattern_end,
204
+ $._value_start,
205
+ repeat1(choice($.value_text, issue($, "invalid_encoding"))),
206
+ $._value_end,
122
207
  ),
123
- _glob: ($) =>
124
- choice(
125
- $.glob_literal,
126
- seq(
127
- $._glob_start,
208
+ pattern: ($) =>
209
+ seq(
210
+ optional(field("opening", $.quote_open)),
211
+ repeat(
128
212
  choice(
129
- $.wildcard,
130
- $.recursive_wildcard,
131
- $.single_character,
132
- $.path_separator,
133
- $.escape,
134
- $.quoted_escape,
135
- $.character_set,
213
+ $.glob_literal,
214
+ seq(
215
+ $._glob_start,
216
+ choice(
217
+ $.wildcard,
218
+ $.recursive_wildcard,
219
+ $.single_character,
220
+ $.path_separator,
221
+ $.escape,
222
+ $.quoted_escape,
223
+ $.character_set,
224
+ issue($, "negative_pattern"),
225
+ ...globIssues($),
226
+ ),
227
+ ),
136
228
  ),
137
229
  ),
230
+ quoteClose($),
231
+ $._pattern_end,
138
232
  ),
139
233
  glob_literal: ($) => $._literal,
140
234
  character_set: ($) =>
141
235
  seq(
142
236
  field("opening", $.set_open),
143
237
  optional(field("negation", $.set_negation)),
144
- repeat($._set_item),
145
- field("closing", $.set_close),
146
- ),
147
- _set_item: ($) =>
148
- seq(
149
- $._set_item_start,
150
- choice(
151
- $.set_text,
152
- $.escape,
153
- $.quoted_escape,
154
- $.character_range,
155
- $.character_class,
238
+ repeat(
239
+ seq(
240
+ $._set_item_start,
241
+ choice(
242
+ $.set_text,
243
+ $.escape,
244
+ $.quoted_escape,
245
+ $.character_range,
246
+ $.character_class,
247
+ ...globIssues($),
248
+ ),
249
+ ),
156
250
  ),
251
+ choice(field("closing", $.set_close), missing($, "set_close")),
157
252
  ),
158
253
  character_range: ($) =>
159
254
  seq(
@@ -167,10 +262,21 @@ export default grammar({
167
262
  seq(
168
263
  alias($._compound_open, "["),
169
264
  alias($._class_open, ":"),
170
- repeat($._class_piece),
265
+ repeat(
266
+ choice(
267
+ field("name", choice($.class_name, $.quoted_escape)),
268
+ ...issues(
269
+ $,
270
+ "invalid_encoding",
271
+ "invalid_quoted_escape",
272
+ "ended_quoted_escape",
273
+ ),
274
+ heldPrefix($, "invalid_encoding"),
275
+ ),
276
+ ),
171
277
  alias($._class_close, ":"),
172
278
  alias($._compound_close, "]"),
173
279
  ),
174
- _class_piece: ($) => field("name", choice($.class_name, $.quoted_escape)),
280
+ ...issueRules,
175
281
  },
176
282
  });
package/package.json CHANGED
@@ -1,12 +1,22 @@
1
1
  {
2
2
  "name": "@konomanoasa/tree-sitter-gitattributes",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Tree-sitter grammar for gitattributes.",
5
5
  "license": "MIT",
6
6
  "repository": "git+https://github.com/konomanoasa/tree-sitter-gitattributes.git",
7
7
  "type": "module",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./bindings/node/index.d.ts",
11
+ "default": "./bindings/node/index.js"
12
+ }
13
+ },
8
14
  "files": [
9
15
  "Cargo.toml",
16
+ "binding.gyp",
17
+ "bindings/node/*.cc",
18
+ "bindings/node/*.js",
19
+ "bindings/node/*.ts",
10
20
  "bindings/python/*.c",
11
21
  "bindings/python/*.py",
12
22
  "bindings/python/*.pyi",
@@ -26,23 +36,33 @@
26
36
  "access": "public"
27
37
  },
28
38
  "scripts": {
29
- "build": "npm run tree-sitter -- build-all",
39
+ "build": "node-gyp rebuild && node-gyp configure -- -f compile_commands_json && npm run tree-sitter -- build-all",
30
40
  "check": "biome check . && tsc",
31
41
  "check:queries": "npm run tree-sitter -- check-queries",
32
42
  "format": "biome format --write .",
33
43
  "generate": "npm run tree-sitter -- generate-all",
34
- "test": "npm run tree-sitter -- test-corpus --rebuild && node --test --test-concurrency=1 test/build.test.js test/cst.test.js test/highlight.test.js test/incremental.test.js test/parser.test.js && node scripts/check-c.js --test",
44
+ "install": "node-gyp-build",
45
+ "test": "npm run tree-sitter -- test-corpus --rebuild && node --test --test-concurrency=1 test/bindings.test.js test/build.test.js test/cst.test.js test/highlight.test.js test/incremental.test.js test/parser.test.js && node scripts/check-c.js --test",
35
46
  "test:fuzz": "npm run tree-sitter -- fuzz-all --iterations 100 --edits 5",
36
47
  "test:sanitize": "node scripts/check-c.js --sanitize",
37
48
  "tree-sitter": "node scripts/tree-sitter.js"
38
49
  },
50
+ "dependencies": {
51
+ "node-addon-api": "8.9.2",
52
+ "node-gyp-build": "4.8.4"
53
+ },
54
+ "peerDependencies": {
55
+ "tree-sitter": "0.25.1"
56
+ },
39
57
  "devDependencies": {
40
- "@biomejs/biome": "2.6.2",
41
- "@types/node": "26.6.5",
58
+ "@biomejs/biome": "2.6.4",
59
+ "@types/node": "26.6.6",
60
+ "node-gyp": "13.1.0",
42
61
  "tree-sitter-cli": "0.27.1",
43
62
  "typescript": "7.0.2"
44
63
  },
45
64
  "allowScripts": {
65
+ "tree-sitter": true,
46
66
  "tree-sitter-cli": true
47
67
  }
48
68
  }
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "konomanoasa-tree-sitter-gitattributes"
3
- version = "0.5.0"
3
+ version = "0.7.0"
4
4
  description = "Tree-sitter grammar for gitattributes."
5
5
  readme = "README.md"
6
6
  license = "MIT"