@singapore-editor/tree-sitter-x 0.28.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/LICENSE +21 -0
- package/README.md +250 -0
- package/debug/web-tree-sitter.cjs +2923 -0
- package/debug/web-tree-sitter.cjs.map +7 -0
- package/debug/web-tree-sitter.js +2871 -0
- package/debug/web-tree-sitter.js.map +7 -0
- package/debug/web-tree-sitter.wasm +0 -0
- package/package.json +108 -0
- package/web-tree-sitter.cjs +2923 -0
- package/web-tree-sitter.cjs.map +7 -0
- package/web-tree-sitter.d.cts +1095 -0
- package/web-tree-sitter.d.cts.map +69 -0
- package/web-tree-sitter.d.ts +1095 -0
- package/web-tree-sitter.d.ts.map +69 -0
- package/web-tree-sitter.js +2871 -0
- package/web-tree-sitter.js.map +7 -0
- package/web-tree-sitter.wasm +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 Max Brunsfeld
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# Tree-sitter-x for JavaScript
|
|
2
|
+
|
|
3
|
+
WASI bindings for [tree-sitter-x](https://github.com/ShaulLavo/tree-sitter-x), with shared text buffers and C extensions.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @singapore-editor/tree-sitter-x
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
import { Parser, Language } from '@singapore-editor/tree-sitter-x';
|
|
13
|
+
await Parser.init();
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
CommonJS is also supported:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
const { Parser, Language } = require('@singapore-editor/tree-sitter-x');
|
|
20
|
+
Parser.init().then(() => {
|
|
21
|
+
const parser = new Parser();
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The package includes `web-tree-sitter.wasm`. Browser bundles must serve that asset alongside the runtime or pass its bytes to `Parser.init({ wasmBinary })`.
|
|
26
|
+
|
|
27
|
+
Import `@singapore-editor/tree-sitter-x/debug` for the build with debug symbols and assertions.
|
|
28
|
+
|
|
29
|
+
### Basic Usage
|
|
30
|
+
|
|
31
|
+
First, create a parser:
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
const parser = new Parser();
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Then assign a language to the parser. Tree-sitter languages are packaged as individual `.wasm` files (more on this below):
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
const { Language } = require('@singapore-editor/tree-sitter-x');
|
|
41
|
+
const JavaScript = await Language.load('/path/to/tree-sitter-javascript.wasm');
|
|
42
|
+
parser.setLanguage(JavaScript);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Now you can parse source code:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
const sourceCode = 'let x = 1; console.log(x);';
|
|
49
|
+
const tree = parser.parse(sourceCode);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
and inspect the syntax tree.
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
console.log(tree.rootNode.toString());
|
|
56
|
+
|
|
57
|
+
// (program
|
|
58
|
+
// (lexical_declaration
|
|
59
|
+
// (variable_declarator (identifier) (number)))
|
|
60
|
+
// (expression_statement
|
|
61
|
+
// (call_expression
|
|
62
|
+
// (member_expression (identifier) (property_identifier))
|
|
63
|
+
// (arguments (identifier)))))
|
|
64
|
+
|
|
65
|
+
const callExpression = tree.rootNode.child(1).firstChild;
|
|
66
|
+
console.log(callExpression);
|
|
67
|
+
|
|
68
|
+
// { type: 'call_expression',
|
|
69
|
+
// startPosition: {row: 0, column: 16},
|
|
70
|
+
// endPosition: {row: 0, column: 30},
|
|
71
|
+
// startIndex: 0,
|
|
72
|
+
// endIndex: 30 }
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Editing
|
|
76
|
+
|
|
77
|
+
If your source code *changes*, you can update the syntax tree. This will take less time than the first parse.
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
// Replace 'let' with 'const'
|
|
81
|
+
const newSourceCode = 'const x = 1; console.log(x);';
|
|
82
|
+
|
|
83
|
+
tree.edit({
|
|
84
|
+
startIndex: 0,
|
|
85
|
+
oldEndIndex: 3,
|
|
86
|
+
newEndIndex: 5,
|
|
87
|
+
startPosition: {row: 0, column: 0},
|
|
88
|
+
oldEndPosition: {row: 0, column: 3},
|
|
89
|
+
newEndPosition: {row: 0, column: 5},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const newTree = parser.parse(newSourceCode, tree);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Parsing Text From a Custom Data Structure
|
|
96
|
+
|
|
97
|
+
If your text is stored in a data structure other than a single string, you can parse it by supplying a callback to `parse`
|
|
98
|
+
instead of a string:
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
const sourceLines = [
|
|
102
|
+
'let x = 1;',
|
|
103
|
+
'console.log(x);'
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
const tree = parser.parse((index, position) => {
|
|
107
|
+
let line = sourceLines[position.row];
|
|
108
|
+
if (line) return line.slice(position.column);
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Getting the `.wasm` language files
|
|
113
|
+
|
|
114
|
+
There are several options on how to get the `.wasm` files for the languages you want to parse.
|
|
115
|
+
|
|
116
|
+
#### From npmjs.com
|
|
117
|
+
|
|
118
|
+
The recommended way is to just install the package from npm. For example, to parse JavaScript, you can install the `tree-sitter-javascript`
|
|
119
|
+
package:
|
|
120
|
+
|
|
121
|
+
```sh
|
|
122
|
+
npm install tree-sitter-javascript
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Then you can find the `.wasm` file in the `node_modules/tree-sitter-javascript` directory.
|
|
126
|
+
|
|
127
|
+
#### From GitHub
|
|
128
|
+
|
|
129
|
+
You can also download the `.wasm` files from GitHub releases, so long as the repository uses our reusable workflow to publish
|
|
130
|
+
them.
|
|
131
|
+
For example, you can download the JavaScript `.wasm` file from the tree-sitter-javascript [releases page][gh release js].
|
|
132
|
+
|
|
133
|
+
#### Generating `.wasm` files
|
|
134
|
+
|
|
135
|
+
You can also generate the `.wasm` file for your desired grammar. Shown below is an example of how to generate the `.wasm`
|
|
136
|
+
file for the JavaScript grammar.
|
|
137
|
+
|
|
138
|
+
> [!NOTE]
|
|
139
|
+
> Since v0.26.1, `tree-sitter build --wasm` uses [wasi-sdk][] and will automatically download it on first use.
|
|
140
|
+
> No additional tools need to be installed.
|
|
141
|
+
|
|
142
|
+
First install `tree-sitter-cli`, and the tree-sitter language for which to generate `.wasm`
|
|
143
|
+
(`tree-sitter-javascript` in this example):
|
|
144
|
+
|
|
145
|
+
```sh
|
|
146
|
+
npm install --save-dev tree-sitter-cli tree-sitter-javascript
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Then just use tree-sitter cli tool to generate the `.wasm`.
|
|
150
|
+
|
|
151
|
+
```sh
|
|
152
|
+
npx tree-sitter build --wasm node_modules/tree-sitter-javascript
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
If everything is fine, file `tree-sitter-javascript.wasm` should be generated in current directory.
|
|
156
|
+
|
|
157
|
+
### Wasm compatibility
|
|
158
|
+
|
|
159
|
+
`web-tree-sitter` supports the same parser ABI versions as the corresponding tree-sitter library:
|
|
160
|
+
|
|
161
|
+
| web-tree-sitter version | Min parser ABI version | Max parser ABI version |
|
|
162
|
+
|-------------------------|------------------------|------------------------|
|
|
163
|
+
| 0.24.x | 13 | 14 |
|
|
164
|
+
| >= 0.25.0 | 13 | 15 |
|
|
165
|
+
|
|
166
|
+
> [!WARNING]
|
|
167
|
+
> Some prebuilt `.wasm` files use an older dynamic-linking format that newer versions of `web-tree-sitter` cannot
|
|
168
|
+
> load, even if their parser ABI is supported. Rebuild these files using a current tree-sitter CLI.
|
|
169
|
+
|
|
170
|
+
### Running .wasm in Node.js
|
|
171
|
+
|
|
172
|
+
Notice that executing `.wasm` files in Node.js is considerably slower than running [Node.js bindings][node bindings].
|
|
173
|
+
However, this could be useful for testing purposes:
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
const Parser = require('@singapore-editor/tree-sitter-x');
|
|
177
|
+
|
|
178
|
+
(async () => {
|
|
179
|
+
await Parser.init();
|
|
180
|
+
const parser = new Parser();
|
|
181
|
+
const Lang = await Parser.Language.load('tree-sitter-javascript.wasm');
|
|
182
|
+
parser.setLanguage(Lang);
|
|
183
|
+
const tree = parser.parse('let x = 1;');
|
|
184
|
+
console.log(tree.rootNode.toString());
|
|
185
|
+
})();
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Loading a pre-compiled WebAssembly module
|
|
189
|
+
|
|
190
|
+
Some environments, such as Cloudflare Workers and Vercel Edge Functions, import
|
|
191
|
+
`.wasm` files as `WebAssembly.Module` objects. You can pass those modules to `Language.loadSync`:
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
import treeSitterJavaScript from 'tree-sitter-javascript.wasm';
|
|
195
|
+
// treeSitterJavaScript is of type `WebAssembly.Module`
|
|
196
|
+
const JavaScript = Language.loadSync(treeSitterJavaScript);
|
|
197
|
+
parser.setLanguage(JavaScript);
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Running .wasm in browser
|
|
201
|
+
|
|
202
|
+
`web-tree-sitter` can run in the browser, but there are some common pitfalls.
|
|
203
|
+
|
|
204
|
+
#### Loading the .wasm file
|
|
205
|
+
|
|
206
|
+
`web-tree-sitter` needs to load the `tree-sitter.wasm` file. By default, it assumes that this file is available in the
|
|
207
|
+
same path as the JavaScript code. Therefore, if the code is being served from `http://localhost:3000/bundle.js`, then
|
|
208
|
+
the Wasm file should be at `http://localhost:3000/tree-sitter.wasm`.
|
|
209
|
+
|
|
210
|
+
For server side frameworks like NextJS, this can be tricky as pages are often served from a path such as
|
|
211
|
+
`http://localhost:3000/_next/static/chunks/pages/index.js`. The loader will therefore look for the Wasm file at
|
|
212
|
+
`http://localhost:3000/_next/static/chunks/pages/tree-sitter.wasm`. The solution is to pass a `locateFile` function in
|
|
213
|
+
the `moduleOptions` argument to `Parser.init()`:
|
|
214
|
+
|
|
215
|
+
```javascript
|
|
216
|
+
await Parser.init({
|
|
217
|
+
locateFile(scriptName: string, scriptDirectory: string) {
|
|
218
|
+
return scriptName;
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`locateFile` takes in two parameters, `scriptName`, i.e. the Wasm file name, and `scriptDirectory`, i.e. the directory
|
|
224
|
+
where the loader expects the script to be. It returns the path where the loader will look for the Wasm file. In the NextJS
|
|
225
|
+
case, we want to return just the `scriptName` so that the loader will look at `http://localhost:3000/tree-sitter.wasm`
|
|
226
|
+
and not `http://localhost:3000/_next/static/chunks/pages/tree-sitter.wasm`.
|
|
227
|
+
|
|
228
|
+
`Parser.init` also accepts `wasmBinary`: the runtime's bytes or a compiled `WebAssembly.Module`, instead of fetching it.
|
|
229
|
+
|
|
230
|
+
#### "Can't resolve 'fs' in 'node_modules/web-tree-sitter"
|
|
231
|
+
|
|
232
|
+
Most bundlers will notice that the `web-tree-sitter.js` file is attempting to import `fs`, i.e. node's file system library.
|
|
233
|
+
Since this doesn't exist in the browser, the bundlers will get confused. For Webpack, you can fix this by adding the
|
|
234
|
+
following to your webpack config:
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
{
|
|
238
|
+
resolve: {
|
|
239
|
+
fallback: {
|
|
240
|
+
fs: false
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
[gh release]: https://github.com/tree-sitter/tree-sitter/releases/latest
|
|
247
|
+
[gh release js]: https://github.com/tree-sitter/tree-sitter-javascript/releases/latest
|
|
248
|
+
[node bindings]: https://github.com/tree-sitter/node-tree-sitter
|
|
249
|
+
[npm module]: https://www.npmjs.com/package/@singapore-editor/tree-sitter-x
|
|
250
|
+
[wasi-sdk]: https://github.com/WebAssembly/wasi-sdk
|