sveast 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/README.md +104 -8
- package/core.d.ts +26 -4
- package/core.js +1 -1
- package/entities.js +1 -1
- package/index.d.ts +153 -5
- package/index.js +1 -1
- package/is-valid-type.js +1 -1
- package/lexer.d.ts +79 -0
- package/lexer.js +2 -0
- package/package.json +11 -1
- package/parse-imports-exports.js +1 -0
- package/parse-module.js +1 -1
- package/parse.js +1 -1
- package/{shared-p7c7qbej.js → shared-1xjsv3h6.js} +2 -2
- package/shared-as9can03.js +10 -0
- package/shared-b37zemjd.js +2 -0
- package/shared-drsxcq8p.js +2 -0
- package/{shared-c2k7d7rg.js → shared-g16dt48m.js} +2 -2
- package/shared-gyydaea2.js +3 -0
- package/shared-mwp38arc.js +2 -0
- package/shared-pmkdz7sc.js +3 -0
- package/shared-pt7hcxxy.js +2 -0
- package/shared-pyjcz2f8.js +12 -0
- package/shared-qnfwr59k.js +2 -0
- package/{shared-xw9zc4rz.js → shared-yr6e6h72.js} +2 -2
- package/typescript.js +1 -1
- package/walk.d.ts +1891 -0
- package/walk.js +1 -1
- package/shared-3ca5cgq8.js +0 -2
- package/shared-7q7hyetp.js +0 -3
- package/shared-cx7c0gk3.js +0 -10
- package/shared-da2hc1fx.js +0 -2
- package/shared-kqcn291j.js +0 -2
- package/shared-t6kshmn4.js +0 -12
- package/shared-xvd609sh.js +0 -2
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ sveast is a drop-in for `parse` in most tools: change the import, and pass `loc:
|
|
|
34
34
|
| `loc`, `name_loc` | Always | With `loc: true`; otherwise only `start`/`end` offsets, for a faster parse and a smaller AST |
|
|
35
35
|
| Errors | `CompileError` | `ParseError`: same `code`, `message`, `position`, `start`, `end` and `frame`; no `filename`; `reason`, the message without its link |
|
|
36
36
|
| AST formats | Modern, legacy (`modern: false`), error-tolerant (`loose`) | Modern |
|
|
37
|
-
| Scope | Parsing, `parseCss`, analysis, compilation | Parsing (`parse`, `parseModule`, `isValidType`),
|
|
37
|
+
| Scope | Parsing, `parseCss`, analysis, compilation | Parsing (`parse`, `parseModule`, `parseImportsExports`, `isValidType`), reading imports without a parser (`lexImportsExports`), walking the AST (`walk`, `visitorKeys`), and finding references and bindings (`isReference`, `extractIdentifiers`) |
|
|
38
38
|
| Non-ASCII identifiers | acorn's tables, Unicode 17 | The engine's own Unicode data, which is smaller to ship: the same as acorn's in Node 24 and Bun; an engine on another Unicode version differs on the letters added in between |
|
|
39
39
|
| TypeScript-only errors | Reported, e.g. modifier order or initializers in ambient contexts | Not reported: 108 of the 2,449 TypeScript conformance tests acorn-typescript rejects still parse |
|
|
40
40
|
|
|
@@ -57,20 +57,75 @@ A syntax error throws a `ParseError` with svelte's `code` (e.g. `"block_unclosed
|
|
|
57
57
|
|
|
58
58
|
Parses a JavaScript or TypeScript module, such as a `.ts` file a component imports, the way a component's `<script>` is parsed: estree plus TypeScript nodes, with comments attached as `leadingComments`/`trailingComments`. Options: `typescript` and `loc`, both default `false`, and `comments`, default `true`; with `false`, no node has `leadingComments` or `trailingComments`.
|
|
59
59
|
|
|
60
|
-
### `
|
|
60
|
+
### `parseImportsExports(source, options?) => ModuleDeclaration[]`
|
|
61
61
|
|
|
62
|
-
`
|
|
62
|
+
A module's top-level `import` and `export` statements, without parsing the rest, e.g. to rewrite a component's imports or follow a module graph. Each node is the one `parseModule(source, { comments: false })` has for that statement, so `start`, `end`, `specifiers` (with `imported`, `local` and `importKind`) and `source` are all there: `ImportDeclaration`, `ExportNamedDeclaration`, `ExportDefaultDeclaration` and `ExportAllDeclaration`, and, in TypeScript, `TSImportEqualsDeclaration`, `TSExportAssignment` and `TSNamespaceExportDeclaration`. `import(...)` and `import.meta` are expressions, so they aren't returned. Unlike a regex, it never matches an `import` in a comment, a string, a template or a nested block such as `declare module "a" { ... }`.
|
|
63
|
+
|
|
64
|
+
The rest is skipped by a tokenizer that only tracks strings, comments, templates, regular expressions and brackets, and only the statements it finds are parsed. It stops after the last `import` or `export` word that could start a statement, so the code after a component's imports is never read. A syntax error in one of them throws `parseModule`'s `ParseError`, including a name exported twice; errors elsewhere aren't reported.
|
|
65
|
+
|
|
66
|
+
| Option | Description |
|
|
67
|
+
|:---|:---|
|
|
68
|
+
| `typescript` | Parse TypeScript: `import type`, `export type`, `import a = require("a")`. Default `false`. |
|
|
69
|
+
| `localExports` | Return the exports of the module's own bindings, such as `export let a`, `export function b() {}`, `export { c }` and `export default d`, which are parsed in full. With `false`, only imports and the exports that have a `from` (`export * from "e"`, `export { f } from "f"`, `export import`) are returned, and the rest is skipped. Default `true`. |
|
|
70
|
+
|
|
71
|
+
On Carbon's 327 component scripts, mostly JSDoc-documented `export let` props, it takes 10.7 ms against `parseModule`'s 33.8 ms, and 4.5 ms with `localExports: false`; the largest script, 63 kB, takes 0.37 ms against 2.7 ms. It checks the TypeScript conformance tests, kit, immich and bits-ui against `parseModule`, with an `import` inserted after every top-level statement: the same nodes on all 24,354 modules.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import { parseImportsExports } from "sveast";
|
|
75
|
+
|
|
76
|
+
function dependencies(source: string, typescript = false): string[] {
|
|
77
|
+
return parseImportsExports(source, { typescript, localExports: false }).flatMap(
|
|
78
|
+
(node) => ("source" in node && node.source ? [node.source.value] : []),
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### `lexImportsExports(source) => LexedStatement[]` from `sveast/lexer`
|
|
84
|
+
|
|
85
|
+
A module's top-level `import` statements and `export … from` re-exports, read by hand instead of parsed: for a tool on a hot or eagerly loaded path, such as a preprocessor that rewrites a component's imports, that needs each statement's offsets, its source and its names, and not the AST. `dist/lexer.js` loads neither acorn nor the template parser, and minifies to 3.2 kB gzipped; a fresh Node process imports it in 1.4 ms, against 7.0 ms for `parseImportsExports`. It's also exported from `sveast`.
|
|
86
|
+
|
|
87
|
+
It finds statements the way `parseImportsExports` does with `localExports: false`, skipping comments, strings, templates, `import(...)`, `import.meta` and nested blocks, and stops after the last `import` or `export` that could start one. `export let`, `export function`, `export { a }` and other exports of the module's own bindings aren't returned. On every statement `parseImportsExports` accepts, the offsets, sources and names are the same: the tests check it on the corpus, on mutated modules and on generated statements, and `scripts/compare-imports.ts` on 8,749 files from other Svelte projects. It doesn't check syntax and never throws. A statement it can't read, such as `import { a from "a"` or TypeScript's `import a = require("a")`, has `source: null` and no specifiers and ends where it stopped reading, so leave it as written. `import type` and `type` before a name are always read, as with `typescript: true`.
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { lexImportsExports } from "sveast/lexer";
|
|
91
|
+
|
|
92
|
+
for (const statement of lexImportsExports(source)) {
|
|
93
|
+
statement.kind; // "import" | "export"
|
|
94
|
+
statement.start; // offset of `import` or `export`
|
|
95
|
+
statement.end; // after the `;`, or the last token without one
|
|
96
|
+
statement.source; // { value: "carbon-components-svelte", start, end } (quotes included), or null
|
|
97
|
+
statement.typeOnly; // `import type …` or `export type …`
|
|
98
|
+
statement.specifiers;
|
|
99
|
+
// import: { kind: "default" | "namespace" | "named", imported, local, typeOnly, start, end }
|
|
100
|
+
// export: { kind: "all" | "namespace" | "named", local, exported, typeOnly, start, end }
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
| Specifier | `import` | `export … from` |
|
|
105
|
+
|:---|:---|:---|
|
|
106
|
+
| `a` in `import a` | `default`, `imported: "default"`, `local: "a"` | |
|
|
107
|
+
| `* as a` | `namespace`, `imported: "*"`, `local: "a"` | `namespace`, `local: "*"`, `exported: "a"` |
|
|
108
|
+
| `*` | | `all`, `local: "*"`, `exported: null` |
|
|
109
|
+
| `b as c`, `"b-c" as d` | `named`, `imported: "b"`, `local: "c"` | `named`, `local: "b"`, `exported: "c"` |
|
|
110
|
+
|
|
111
|
+
Names are as the module sees them: escapes decoded, and a string name's value without its quotes. A specifier's `typeOnly` is also `true` in an `import type` or `export type`. Its `start` is that of `type` before the name, if any, and `end` is after the last name; for `export *`, after the `*`.
|
|
112
|
+
|
|
113
|
+
On Carbon's 327 component scripts it takes about 40% of the time `parseImportsExports` with `localExports: false` takes, and on the largest, 63 kB, about an eighth.
|
|
114
|
+
|
|
115
|
+
### `createParser(support?) => { parse, parseModule, parseImportsExports }` from `sveast/core`
|
|
116
|
+
|
|
117
|
+
`parse`, `parseModule` and `parseImportsExports` without the two parts most tools can do without: the TypeScript plugin and the table of HTML's named character references. Together they're about a third of a bundle: `parse` and `parseModule` from `sveast` minify to 57.3 kB gzipped, and from `createParser()` to 40.3 kB. Pass back the parts you need; with both, the parsers are the same as `sveast`'s.
|
|
63
118
|
|
|
64
119
|
```ts
|
|
65
120
|
import { createParser } from "sveast/core";
|
|
66
121
|
import { typescript } from "sveast/typescript";
|
|
67
122
|
|
|
68
|
-
const { parse, parseModule } = createParser({ typescript });
|
|
123
|
+
const { parse, parseModule, parseImportsExports } = createParser({ typescript });
|
|
69
124
|
```
|
|
70
125
|
|
|
71
126
|
| Support | Without it |
|
|
72
127
|
|:---|:---|
|
|
73
|
-
| `typescript` from `sveast/typescript` (+8.8 kB gzipped) | A component with `<script lang="ts">`, or `parseModule` with `typescript: true`, throws an `Error`, not a `ParseError`: a missing import, not a syntax error, and never a JavaScript AST of TypeScript |
|
|
128
|
+
| `typescript` from `sveast/typescript` (+8.8 kB gzipped) | A component with `<script lang="ts">`, or `parseModule` or `parseImportsExports` with `typescript: true`, throws an `Error`, not a `ParseError`: a missing import, not a syntax error, and never a JavaScript AST of TypeScript |
|
|
74
129
|
| `entities` from `sveast/entities` (+10.0 kB gzipped) | Text and attribute values decode numeric references, such as `©`, and `&`, `'`, `>`, `<` and `"`, but leave other names, such as `©`, as written, so `Text.data` differs from svelte's where the source uses them |
|
|
75
130
|
|
|
76
131
|
`sveast/core` also exports `ParseError`, the same class as `sveast`'s, and the types.
|
|
@@ -83,15 +138,56 @@ A `//` comment runs to the end of the line, so `string // the size` is a valid t
|
|
|
83
138
|
|
|
84
139
|
### `walk(node, visitor) => void`
|
|
85
140
|
|
|
86
|
-
Visits `node` and every node under it, depth-first and in source order, calling `visitor.enter(node, parent, key, index)` before a node's children and `visitor.leave(node, parent, key, index)` after them. `parent[key]` is the node, or `parent[key][index]` when the field is an array; all three are `null` for the node you pass. Return `
|
|
141
|
+
Visits `node` and every node under it, depth-first and in source order, calling `visitor.enter(node, parent, key, index)` before a node's children and `visitor.leave(node, parent, key, index)` after them. `parent[key]` is the node, or `parent[key][index]` when the field is an array; all three are `null` for the node you pass. Return `SKIP` from `enter` to skip the node's children; `leave` is still called, so a stack you push in `enter` and pop in `leave` stays balanced. Return `STOP` from `enter` or `leave` to end the walk there: no more `enter` or `leave` calls, not even `leave` on the node's ancestors, e.g. to find the first use of a rune. Return another node from `enter` to put it in this one's place: `walk` writes it to `parent[key]` (or `parent[key][index]`), then calls `enter` on it and visits its children instead, and `leave` gets the replacement. So `return node.expression` on each `TSAsExpression` strips `a as B as C` down to `a`, one layer per `enter`. The node you pass to `walk` can't be replaced. Any other return value, `false` included, is ignored, so an expression-bodied `enter: (node) => node.type === "Component" && names.add(node.name)` still visits every node. Checking `node.type` narrows `node`.
|
|
87
142
|
|
|
88
143
|
It works on any node the parsers return: a component's `Root`, a `Fragment`, an expression, a `parseModule` program, a `<style>`'s rules. It only reads the fields that hold child nodes, so it never descends into `loc`, comments or strings, and it throws on a node type it doesn't know. Two exceptions to source order: a component's sections are visited in scope order, `module`, `instance`, `fragment`, then `css`; and a template literal's `quasis` come before its `expressions`. `Root.options` isn't a node, so `<svelte:options>`'s attributes aren't visited; read them from `ast.options?.attributes`. acorn shares one `Identifier` between both names of `import { a }`, so it's visited once as `imported` and once as `local`, and likewise as `local` and `exported` in `export { a }`.
|
|
89
144
|
|
|
90
145
|
`visitorKeys` is the table `walk` reads: the fields of each node type that hold child nodes, in source order, e.g. `visitorKeys.IfBlock` is `["test", "consequent", "alternate"]`. Use it with another walker, or to write your own.
|
|
91
146
|
|
|
147
|
+
### `isReference(node, parent) => boolean`
|
|
148
|
+
|
|
149
|
+
Whether `node` is an `Identifier` that names a variable, function, class, import or other binding, where it's declared or where it's used, given the `parent` `walk` passes. It's the check svelte's analyzer makes, from the [`is-reference`](https://github.com/Rich-Harris/is-reference) package: `false` for a property or method name (`b` in `a.b`, `{ b: a }` and `class { b() {} }`, unless computed), the renamed side of an import or export (`b` in `import { b as a }` and `export { a as b }`), and labels. Unlike `is-reference`, it's also `false` for `import` and `new` in `import.meta` and `new.target`, an import attribute's key, and `b` in `export * as b from`, and for any node that isn't an `Identifier`.
|
|
150
|
+
|
|
151
|
+
TypeScript nodes hold types, so an `Identifier` whose parent is a TypeScript node isn't a reference (`B` in `let a: B`, `typeof b` in a type, interface and type alias names), except where it's a value: the expression of `as`, `satisfies`, `<T>a`, `a!`, `a<T>` and `export =`, an enum member's initializer, a parameter property (`a` in `constructor(private a)`), an enum's name, and the name and target of `import a = b`. Names of namespaces and of functions without a body (overloads, `declare function`) aren't references.
|
|
152
|
+
|
|
153
|
+
acorn shares one `Identifier` between both names of `import { a }` and `export { a }`, and `walk` visits it twice, so it's a reference on both visits.
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
import { isReference, parseModule, walk } from "sveast";
|
|
157
|
+
|
|
158
|
+
const used = new Set<string>();
|
|
159
|
+
walk(parseModule("const a = b.c({ d: e });"), {
|
|
160
|
+
enter(node, parent) {
|
|
161
|
+
if (node.type === "Identifier" && isReference(node, parent)) used.add(node.name);
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
used; // Set { "a", "b", "e" }
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### `extractIdentifiers(pattern) => Identifier[]`
|
|
168
|
+
|
|
169
|
+
The `Identifier` nodes a pattern binds, in source order, as svelte's `extract_identifiers` returns them: `a`, `c`, `d`, `e` and `f` in `let { a, b: [c, ...d], e = 1, ...f } = x`. Property keys, defaults and type annotations aren't included. It returns nodes rather than names, so you keep their positions; `.map((node) => node.name)` for the names.
|
|
170
|
+
|
|
171
|
+
It takes any binding or assignment target: a declarator's `id`, a function's params, including a parameter property (`a` in `constructor(private a)`), a catch clause's `param`, an each block's `context`, a snippet's `parameters`, or an assignment's `left`. A member expression binds nothing, so `[a.b, c] = x` yields only `c`, as in svelte. On an assignment's `left`, `a!`, `a as T`, `a satisfies T` and `<T>a` yield `a`.
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
import { extractIdentifiers, parseModule } from "sveast";
|
|
175
|
+
|
|
176
|
+
const [declaration] = parseModule("let { a, b: [c] } = x;").body;
|
|
177
|
+
if (declaration.type === "VariableDeclaration") {
|
|
178
|
+
declaration.declarations.flatMap((d) => extractIdentifiers(d.id)).map((node) => node.name); // ["a", "c"]
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
`walk`, `SKIP`, `STOP`, `visitorKeys`, `Visitor`, `isReference`, `extractIdentifiers` and the types are also exported from `sveast/walk`, which loads neither acorn nor the parser: for code that walks ASTs it gets from elsewhere, such as a cache, and must not pay for loading the parser. They're the same values as `sveast`'s.
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
import { STOP, walk } from "sveast/walk";
|
|
186
|
+
```
|
|
187
|
+
|
|
92
188
|
### Types
|
|
93
189
|
|
|
94
|
-
`AST` is svelte's `AST` namespace (`AST.Root`, `AST.RegularElement`, `AST.CSS.Rule`, ...), corrected to match what the parser returns: `name_loc` and a comment's `loc` are optional, `Root.instance`/`module` are absent rather than `null` when there's no such `<script>`, `Root.js` is declared, and every directive has `modifiers`. `ParseOptions` and `
|
|
190
|
+
`AST` is svelte's `AST` namespace (`AST.Root`, `AST.RegularElement`, `AST.CSS.Rule`, ...), corrected to match what the parser returns: `name_loc` and a comment's `loc` are optional, `Root.instance`/`module` are absent rather than `null` when there's no such `<script>`, `Root.js` is declared, and every directive has `modifiers`. `ParseOptions`, `ParseModuleOptions` and `ParseImportsExportsOptions` are exported too, and `lexImportsExports`'s `LexedStatement` (`LexedImport` or `LexedExport`), `LexedImportSpecifier`, `LexedExportSpecifier` and `LexedSource`.
|
|
95
191
|
|
|
96
192
|
The estree node types are exported as well (`Program`, `Node`, `Statement`, `Expression`, `Identifier`, ...), so you don't need `@types/estree`. They're estree's, plus what the parser adds: `start`/`end` on every node, and the TypeScript plugin's nodes (`TSInterfaceDeclaration`, `TSTypeAnnotation`, `TSTypeReference`, ...; `TSNode` is their union) and fields (`typeAnnotation`, `typeParameters`, `typeArguments`, `returnType`, `importKind`/`exportKind`, ...). The TypeScript nodes are in the `Statement`, `Declaration` and `Expression` unions, so checking `node.type` narrows to them. Where the grammar only allows a string, such as an import's `source`, the type is `StringLiteral`, a `Literal` whose `value` is a `string`.
|
|
97
193
|
|
|
@@ -204,7 +300,7 @@ const css = parse(source, { css: false }).css?.content.styles ?? "";
|
|
|
204
300
|
- **TypeScript without acorn-typescript.** The built-in plugin produces the same AST as `@sveltejs/acorn-typescript`, key order and `loc` included, on 6,604 real-world modules and on all but 2 of the 9,586 TypeScript conformance tests that acorn-typescript parses. It rejects the same redeclarations, and supports decorators.
|
|
205
301
|
- **About 2.4× faster than svelte/compiler** (2.2–3.0× depending on the input), and its ASTs retain 47% less memory without `loc`.
|
|
206
302
|
- **Fast to load.** A fresh process imports sveast in about 5 ms, against about 45 ms for `svelte/compiler`.
|
|
207
|
-
- **Zero dependencies,** types included.
|
|
303
|
+
- **Zero dependencies,** types included. 67 kB gzipped, acorn included.
|
|
208
304
|
|
|
209
305
|
## Benchmarks
|
|
210
306
|
|
package/core.d.ts
CHANGED
|
@@ -21,13 +21,16 @@ export interface Parser {
|
|
|
21
21
|
parse(source: string, options?: ParseOptions): AST.Root;
|
|
22
22
|
/** `parseModule` from `sveast`, with only what the parser was created with. */
|
|
23
23
|
parseModule(source: string, options?: ParseModuleOptions): Program;
|
|
24
|
+
/** `parseImportsExports` from `sveast`, with only what the parser was created with. */
|
|
25
|
+
parseImportsExports(source: string, options?: ParseImportsExportsOptions): ModuleDeclaration[];
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
/**
|
|
27
|
-
* Creates `parse` and `
|
|
28
|
-
* the TypeScript plugin and the table of HTML's
|
|
29
|
-
* references are about a third of sveast's size, and a
|
|
30
|
-
* out whichever isn't imported. With both, they're the
|
|
29
|
+
* Creates `parse`, `parseModule` and `parseImportsExports` that bundle
|
|
30
|
+
* only what's passed in: the TypeScript plugin and the table of HTML's
|
|
31
|
+
* named character references are about a third of sveast's size, and a
|
|
32
|
+
* bundler leaves out whichever isn't imported. With both, they're the
|
|
33
|
+
* same as `sveast`'s.
|
|
31
34
|
*
|
|
32
35
|
* ```ts
|
|
33
36
|
* import { createParser } from "sveast/core";
|
|
@@ -87,6 +90,25 @@ export interface ParseModuleOptions {
|
|
|
87
90
|
comments?: boolean;
|
|
88
91
|
}
|
|
89
92
|
|
|
93
|
+
/** Options for {@link parseImportsExports}. */
|
|
94
|
+
export interface ParseImportsExportsOptions {
|
|
95
|
+
/**
|
|
96
|
+
* Parse TypeScript, e.g. `import type`, `export type` and
|
|
97
|
+
* `import a = require("a")`. Default `false`.
|
|
98
|
+
*/
|
|
99
|
+
typescript?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Return the `export` statements that export the module's own bindings,
|
|
102
|
+
* such as `export let a`, `export function b() {}`, `export { c }` and
|
|
103
|
+
* `export default d`. With `false`, only imports and the exports that
|
|
104
|
+
* have a `from`, such as `export * from "e"` and `export { f } from "f"`,
|
|
105
|
+
* are returned, and the rest is skipped like other code, which is faster
|
|
106
|
+
* when most statements are exported, as in a component's props.
|
|
107
|
+
* Default `true`.
|
|
108
|
+
*/
|
|
109
|
+
localExports?: boolean;
|
|
110
|
+
}
|
|
111
|
+
|
|
90
112
|
/** TypeScript support for {@link createParser}, from `sveast/typescript`. */
|
|
91
113
|
export interface TypeScriptSupport {
|
|
92
114
|
readonly support: "typescript";
|
package/core.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{b}from"./shared-gyydaea2.js";import"./shared-as9can03.js";import{e}from"./shared-pyjcz2f8.js";import{Re}from"./shared-g16dt48m.js";import"./shared-pmkdz7sc.js";import{v}from"./shared-b37zemjd.js";import{S}from"./shared-qnfwr59k.js";import{qe,De}from"./shared-pt7hcxxy.js";function u(o={}){let p=qe(o.typescript),s={typescript:p,entityNames:De(o.entities)??Re};return{parse:(t,r)=>b(t,r,s),parseModule:(t,r={})=>v(t,r,p),parseImportsExports:(t,r={})=>S(t,r,p)}}export{e as ParseError,u as createParser};
|
package/entities.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./shared-
|
|
1
|
+
import"./shared-g16dt48m.js";import{C}from"./shared-1xjsv3h6.js";import{$e}from"./shared-pt7hcxxy.js";var p=$e(C);export{p as entities};
|
package/index.d.ts
CHANGED
|
@@ -15,6 +15,86 @@ export declare function isValidType(text: string, options?: {
|
|
|
15
15
|
inline?: boolean;
|
|
16
16
|
}): boolean;
|
|
17
17
|
|
|
18
|
+
/** A module specifier: the string after `from`, or after `import` in `import "a"`. */
|
|
19
|
+
export interface LexedSource {
|
|
20
|
+
/** The string's value, with escapes decoded. */
|
|
21
|
+
value: string;
|
|
22
|
+
/** The offset of the opening quote. */
|
|
23
|
+
start: number;
|
|
24
|
+
/** The offset after the closing quote. */
|
|
25
|
+
end: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** A name an `import` binds. */
|
|
29
|
+
export interface LexedImportSpecifier {
|
|
30
|
+
/** `"default"` for `a` in `import a from`, `"namespace"` for `* as a`, `"named"` for a name in braces. */
|
|
31
|
+
kind: "default" | "namespace" | "named";
|
|
32
|
+
/** The name in the imported module: `"default"`, `"*"` for a namespace, or the name before `as`, with a string's value for `"a-b" as c`. */
|
|
33
|
+
imported: string;
|
|
34
|
+
/** The name it's bound to in this module. */
|
|
35
|
+
local: string;
|
|
36
|
+
/** Whether it's only a type: in `import type`, or with `type` before it. */
|
|
37
|
+
typeOnly: boolean;
|
|
38
|
+
/** The offset of the name, of `*`, or of `type` before the name. */
|
|
39
|
+
start: number;
|
|
40
|
+
/** The offset after the local name. */
|
|
41
|
+
end: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** A name an `export … from` re-exports. */
|
|
45
|
+
export interface LexedExportSpecifier {
|
|
46
|
+
/** `"all"` for `export *`, `"namespace"` for `export * as a`, `"named"` for a name in braces. */
|
|
47
|
+
kind: "all" | "namespace" | "named";
|
|
48
|
+
/** The name in the other module: `"*"` for `all` and `namespace`, or the name before `as`, with a string's value for `"a-b" as c`. */
|
|
49
|
+
local: string;
|
|
50
|
+
/** The name it's exported as, or `null` for `export *`. */
|
|
51
|
+
exported: string | null;
|
|
52
|
+
/** Whether it's only a type: in `export type`, or with `type` before it. */
|
|
53
|
+
typeOnly: boolean;
|
|
54
|
+
/** The offset of the name, of `*`, or of `type` before the name. */
|
|
55
|
+
start: number;
|
|
56
|
+
/** The offset after the exported name, or after `*` for `export *`. */
|
|
57
|
+
end: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface LexedStatementBase {
|
|
61
|
+
/** The offset of `import` or `export`. */
|
|
62
|
+
start: number;
|
|
63
|
+
/** The offset after the statement's `;`, or its last token without one. */
|
|
64
|
+
end: number;
|
|
65
|
+
/** The module it imports from, or `null` for a statement the lexer doesn't recognize. */
|
|
66
|
+
source: LexedSource | null;
|
|
67
|
+
/** Whether it's `import type` or `export type`. */
|
|
68
|
+
typeOnly: boolean;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** An `import` statement. */
|
|
72
|
+
export interface LexedImport extends LexedStatementBase {
|
|
73
|
+
kind: "import";
|
|
74
|
+
specifiers: LexedImportSpecifier[];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** An `export … from` statement. */
|
|
78
|
+
export interface LexedExport extends LexedStatementBase {
|
|
79
|
+
kind: "export";
|
|
80
|
+
specifiers: LexedExportSpecifier[];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export type LexedStatement = LexedImport | LexedExport;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* A module's top-level `import` statements and `export … from`
|
|
87
|
+
* re-exports, read without a parser: each statement's offsets, its
|
|
88
|
+
* source and the names it imports or re-exports. It finds statements as
|
|
89
|
+
* {@link parseImportsExports} does with `localExports: false`, and on
|
|
90
|
+
* every statement that accepts, gives the same offsets, sources and names,
|
|
91
|
+
* but it doesn't check syntax and never throws. A statement it can't read,
|
|
92
|
+
* including TypeScript's `import a = require("a")`, is returned with
|
|
93
|
+
* `source: null` and no specifiers, ending where it stopped reading.
|
|
94
|
+
* TypeScript's `type` forms are always read.
|
|
95
|
+
*/
|
|
96
|
+
export declare function lexImportsExports(source: string): LexedStatement[];
|
|
97
|
+
|
|
18
98
|
/**
|
|
19
99
|
* Options for {@link parse}. The defaults give svelte's own output, minus
|
|
20
100
|
* `loc` and `name_loc`.
|
|
@@ -64,6 +144,25 @@ export interface ParseModuleOptions {
|
|
|
64
144
|
comments?: boolean;
|
|
65
145
|
}
|
|
66
146
|
|
|
147
|
+
/** Options for {@link parseImportsExports}. */
|
|
148
|
+
export interface ParseImportsExportsOptions {
|
|
149
|
+
/**
|
|
150
|
+
* Parse TypeScript, e.g. `import type`, `export type` and
|
|
151
|
+
* `import a = require("a")`. Default `false`.
|
|
152
|
+
*/
|
|
153
|
+
typescript?: boolean;
|
|
154
|
+
/**
|
|
155
|
+
* Return the `export` statements that export the module's own bindings,
|
|
156
|
+
* such as `export let a`, `export function b() {}`, `export { c }` and
|
|
157
|
+
* `export default d`. With `false`, only imports and the exports that
|
|
158
|
+
* have a `from`, such as `export * from "e"` and `export { f } from "f"`,
|
|
159
|
+
* are returned, and the rest is skipped like other code, which is faster
|
|
160
|
+
* when most statements are exported, as in a component's props.
|
|
161
|
+
* Default `true`.
|
|
162
|
+
*/
|
|
163
|
+
localExports?: boolean;
|
|
164
|
+
}
|
|
165
|
+
|
|
67
166
|
/**
|
|
68
167
|
* Parses a Svelte component into svelte's modern AST, the same as
|
|
69
168
|
* `parse(source, { modern: true })` from svelte/compiler. From svelte's
|
|
@@ -1697,6 +1796,21 @@ export interface TSInstantiationExpression extends BaseNode {
|
|
|
1697
1796
|
typeArguments: TSTypeParameterInstantiation;
|
|
1698
1797
|
}
|
|
1699
1798
|
|
|
1799
|
+
/**
|
|
1800
|
+
* Parses only a module's top-level `import` and `export` statements, e.g.
|
|
1801
|
+
* to rewrite or follow its imports, and skips the rest without building
|
|
1802
|
+
* it. Each node is the one {@link parseModule} returns for the statement
|
|
1803
|
+
* with `comments: false`: `ImportDeclaration`, `ExportNamedDeclaration`,
|
|
1804
|
+
* `ExportDefaultDeclaration` and `ExportAllDeclaration`, plus, with
|
|
1805
|
+
* `typescript: true`, `TSImportEqualsDeclaration`, `TSExportAssignment`
|
|
1806
|
+
* and `TSNamespaceExportDeclaration`. `import(...)` and `import.meta`
|
|
1807
|
+
* aren't statements, so they aren't returned.
|
|
1808
|
+
*
|
|
1809
|
+
* Throws a {@link ParseError} (`js_parse_error`) on a syntax error in one
|
|
1810
|
+
* of those statements. Syntax errors in the rest aren't reported.
|
|
1811
|
+
*/
|
|
1812
|
+
export declare function parseImportsExports(source: string, options?: ParseImportsExportsOptions): ModuleDeclaration[];
|
|
1813
|
+
|
|
1700
1814
|
/**
|
|
1701
1815
|
* Parses a JavaScript or TypeScript module, e.g. a `.ts` file a component
|
|
1702
1816
|
* imports, into the same kind of AST as a component's `<script>`:
|
|
@@ -1954,14 +2068,22 @@ export declare const visitorKeys: {
|
|
|
1954
2068
|
*/
|
|
1955
2069
|
export declare const STOP: unique symbol;
|
|
1956
2070
|
|
|
2071
|
+
/**
|
|
2072
|
+
* Return it from `enter` to skip the node's children; `leave` is still
|
|
2073
|
+
* called on the node.
|
|
2074
|
+
*/
|
|
2075
|
+
export declare const SKIP: unique symbol;
|
|
2076
|
+
|
|
1957
2077
|
/** The callbacks {@link walk} calls for each node. */
|
|
1958
2078
|
export interface Visitor {
|
|
1959
2079
|
/**
|
|
1960
|
-
* Called before the node's children. Return
|
|
1961
|
-
* is still called, so the two stay paired. Return {@link STOP} to
|
|
1962
|
-
* walk. Return another node to put it in this one's place: `walk`
|
|
1963
|
-
* to `parent[key]` (or `parent[key][index]`), then calls `enter`
|
|
1964
|
-
* visits its children instead.
|
|
2080
|
+
* Called before the node's children. Return {@link SKIP} to skip them;
|
|
2081
|
+
* `leave` is still called, so the two stay paired. Return {@link STOP} to
|
|
2082
|
+
* end the walk. Return another node to put it in this one's place: `walk`
|
|
2083
|
+
* writes it to `parent[key]` (or `parent[key][index]`), then calls `enter`
|
|
2084
|
+
* on it and visits its children instead. Any other value, `false`
|
|
2085
|
+
* included, is ignored, so `(node) => node.type === "Component" &&
|
|
2086
|
+
* names.add(node.name)` visits every node.
|
|
1965
2087
|
*/
|
|
1966
2088
|
enter?(node: AST.SvelteNode, parent: AST.SvelteNode | null, key: string | null, index: number | null): unknown;
|
|
1967
2089
|
/** Called after the node's children. Return {@link STOP} to end the walk. */
|
|
@@ -1975,3 +2097,29 @@ export interface Visitor {
|
|
|
1975
2097
|
* array; all three are `null` for `node` itself.
|
|
1976
2098
|
*/
|
|
1977
2099
|
export declare function walk(node: AST.SvelteNode, visitor: Visitor): void;
|
|
2100
|
+
|
|
2101
|
+
/**
|
|
2102
|
+
* The `Identifier` nodes a pattern binds, in source order: `a`, `c`, `d`,
|
|
2103
|
+
* `e` and `f` in `{ a, b: [c, ...d], e = 1, ...f }`. Not the property
|
|
2104
|
+
* keys, defaults or type annotations. A member expression, which an
|
|
2105
|
+
* assignment's pattern can hold, as in `[a.b] = c`, binds nothing, so it
|
|
2106
|
+
* yields no identifiers, as in svelte's `extract_identifiers`. Also takes
|
|
2107
|
+
* a function's params as they are, parameter properties included, and an
|
|
2108
|
+
* assignment's `left`, where `a!`, `a as T`, `a satisfies T` and `<T>a`
|
|
2109
|
+
* yield `a`.
|
|
2110
|
+
*/
|
|
2111
|
+
export declare function extractIdentifiers(pattern: Pattern | TSParameterProperty | AssignmentExpression["left"]): Identifier[];
|
|
2112
|
+
|
|
2113
|
+
/**
|
|
2114
|
+
* Whether `node` is an `Identifier` that names a binding in the value
|
|
2115
|
+
* namespace, where it's declared or where it's used, given its `parent`
|
|
2116
|
+
* from `walk`. `false` for a property, method or label name, the
|
|
2117
|
+
* renamed side of an import or export specifier, `import.meta`'s and
|
|
2118
|
+
* `new.target`'s names, an import attribute's key, and every name in a
|
|
2119
|
+
* type. The check svelte's analyzer makes, from the `is-reference` package,
|
|
2120
|
+
* plus TypeScript: an `Identifier` whose parent is a TypeScript node is a
|
|
2121
|
+
* reference only as the expression of `as`, `satisfies`, `<T>x`, `x!`,
|
|
2122
|
+
* `f<T>` or `export =`, an enum member's initializer, a parameter
|
|
2123
|
+
* property, an enum's name, or the name or target of `import a = b`.
|
|
2124
|
+
*/
|
|
2125
|
+
export declare function isReference(node: AST.SvelteNode, parent: AST.SvelteNode | null): boolean;
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isValidType as
|
|
1
|
+
import{isValidType as t}from"./is-valid-type.js";import{lexImportsExports as p}from"./lexer.js";import{parse as x}from"./parse.js";import{parseImportsExports as m}from"./parse-imports-exports.js";import{ParseError as a,parseModule as y}from"./parse-module.js";import{extractIdentifiers as l,isReference as n,SKIP as I,STOP as S,visitorKeys as c,walk as E}from"./walk.js";export{a as ParseError,I as SKIP,S as STOP,l as extractIdentifiers,n as isReference,t as isValidType,p as lexImportsExports,x as parse,m as parseImportsExports,y as parseModule,c as visitorKeys,E as walk};
|
package/is-valid-type.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t}from"./shared-
|
|
1
|
+
import{t}from"./shared-as9can03.js";import{T}from"./shared-yr6e6h72.js";var a=new Set("abstract accessor arguments as asserts async await break case catch class const continue debugger declare default delete do else enum eval export extends false finally for function get global if implements import in infer instanceof interface intrinsic is keyof let module namespace new null of out override package private protected public readonly return satisfies set static super switch this throw true try type typeof unique var void while with yield".split(" ")),c=new Set("any bigint boolean false never null number object string symbol true undefined unknown void".split(" ")),d=new Set("get set new readonly static public private protected".split(" "));function u(e){return e>=97&&e<=122||e>=65&&e<=90||e===95||e===36}function o(e){return e>=48&&e<=57}function h(e){return u(e)||o(e)}class l{text;pos=0;constructor(e){this.text=e}readAll(){if(!this.type())return!1;return this.peek(),this.pos===this.text.length}peek(){let e=this.text,s=this.pos,r=e.charCodeAt(s);while(r===32||r===9)r=e.charCodeAt(++s);return this.pos=s,r}eat(e){if(this.peek()!==e.charCodeAt(0))return!1;return this.pos++,!0}word(){if(!u(this.peek()))return;let e=this.pos,s=e+1;while(h(this.text.charCodeAt(s)))s++;return this.pos=s,this.text.slice(e,s)}name(){let e=this.word();return e!==void 0&&!a.has(e)}string(){let e=this.peek();if(e!==34&&e!==39)return!1;let s=this.text;for(let r=this.pos+1;r<s.length;r++){let i=s.charCodeAt(r);if(i===e)return this.pos=r+1,!0;if(i===92||i===10||i===13||i===8232||i===8233)return!1}return!1}number(){let e=this.text,s=this.pos;if(e.charCodeAt(s)===45)s++;let r=s;while(o(e.charCodeAt(s)))s++;if(s===r||s-r>1&&e.charCodeAt(r)===48)return!1;if(e.charCodeAt(s)===46){let n=++s;while(o(e.charCodeAt(s)))s++;if(s===n)return!1}let i=e.charCodeAt(s);if(h(i)||i===46)return!1;return this.pos=s,!0}type(){if(this.peek()===40){let e=this.pos;if(this.functionType())return!0;this.pos=e}do do if(!this.operatorType())return!1;while(this.eat("&"));while(this.eat("|"));return!0}operatorType(){let e=this.pos;if(this.word()==="keyof")return this.operatorType();if(this.pos=e,!this.primaryType())return!1;while(this.eat("[")){if(this.eat("]"))continue;if(!this.type()||!this.eat("]"))return!1}return!0}primaryType(){let e=this.peek();if(e===40)return this.pos++,this.type()&&this.eat(")");if(e===123)return this.objectType();if(e===91)return this.tupleType();if(e===34||e===39)return this.string();if(e===45||o(e))return this.number();let s=this.word();if(s===void 0)return!1;if(s==="typeof")return this.typeQuery();if(s==="import")return this.importType(!0);if(c.has(s)){let r=this.peek();return r!==46&&r!==60}if(a.has(s))return!1;while(this.eat("."))if(this.word()===void 0)return!1;return!this.eat("<")||this.typeArguments()}typeArguments(){do if(!this.type())return!1;while(this.eat(","));return this.eat(">")}typeQuery(){let e=this.pos;if(this.word()==="import")return this.importType(!1);this.pos=e;do if(!this.name())return!1;while(this.eat("."));return!0}importType(e){if(!this.eat("(")||!this.string()||!this.eat(")"))return!1;while(this.eat("."))if(!this.name())return!1;return!e||!this.eat("<")||this.typeArguments()}objectType(){this.pos++;while(!this.eat("}")){if(!this.typeMember())return!1;if(!this.eat(";")&&!this.eat(",")&&this.peek()!==125)return!1}return!0}typeMember(){let e=this.peek();if(this.eat("[")){let s=this.peek();if(s===34||s===39){if(!this.string()||!this.eat("]"))return!1}else return this.name()&&this.eat(":")&&this.type()&&this.eat("]")&&this.eat(":")&&this.type()}else if(e===34||e===39){if(!this.string())return!1}else{let s=this.word();if(s===void 0||d.has(s))return!1}return this.eat("?"),this.eat(":")&&this.type()}tupleType(){if(this.pos++,this.eat("]"))return!0;do if(!this.type())return!1;while(this.eat(","));return this.eat("]")}functionType(){if(this.pos++,!this.eat(")")){let e=new Set;for(;;){this.peek();let s=this.text.startsWith("...",this.pos);if(s)this.pos+=3;let r=this.word();if(r===void 0||a.has(r)||e.has(r))return!1;if(e.add(r),!s)this.eat("?");if(!this.eat(":")||!this.type())return!1;if(s||!this.eat(","))break}if(!this.eat(")"))return!1}if(this.peek(),!this.text.startsWith("=>",this.pos))return!1;return this.pos+=2,this.type()}}function f(e){return new l(e).readAll()}var y=t.extend(T);function S(e,s={}){return f(e)||m(e,s.inline??!1)}function m(e,s){let r=!1,i=new y(s?{ecmaVersion:16,sourceType:"module",onComment:(n,b,A,p)=>{if(!n&&p===e.length)r=!0}}:{ecmaVersion:16,sourceType:"module"},e);try{return i.parseWholeType(),!r}catch(n){if(n instanceof SyntaxError)return!1;throw n}}export{S as isValidType,m as parsesAsType};
|
package/lexer.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/** A module specifier: the string after `from`, or after `import` in `import "a"`. */
|
|
2
|
+
export interface LexedSource {
|
|
3
|
+
/** The string's value, with escapes decoded. */
|
|
4
|
+
value: string;
|
|
5
|
+
/** The offset of the opening quote. */
|
|
6
|
+
start: number;
|
|
7
|
+
/** The offset after the closing quote. */
|
|
8
|
+
end: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** A name an `import` binds. */
|
|
12
|
+
export interface LexedImportSpecifier {
|
|
13
|
+
/** `"default"` for `a` in `import a from`, `"namespace"` for `* as a`, `"named"` for a name in braces. */
|
|
14
|
+
kind: "default" | "namespace" | "named";
|
|
15
|
+
/** The name in the imported module: `"default"`, `"*"` for a namespace, or the name before `as`, with a string's value for `"a-b" as c`. */
|
|
16
|
+
imported: string;
|
|
17
|
+
/** The name it's bound to in this module. */
|
|
18
|
+
local: string;
|
|
19
|
+
/** Whether it's only a type: in `import type`, or with `type` before it. */
|
|
20
|
+
typeOnly: boolean;
|
|
21
|
+
/** The offset of the name, of `*`, or of `type` before the name. */
|
|
22
|
+
start: number;
|
|
23
|
+
/** The offset after the local name. */
|
|
24
|
+
end: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** A name an `export … from` re-exports. */
|
|
28
|
+
export interface LexedExportSpecifier {
|
|
29
|
+
/** `"all"` for `export *`, `"namespace"` for `export * as a`, `"named"` for a name in braces. */
|
|
30
|
+
kind: "all" | "namespace" | "named";
|
|
31
|
+
/** The name in the other module: `"*"` for `all` and `namespace`, or the name before `as`, with a string's value for `"a-b" as c`. */
|
|
32
|
+
local: string;
|
|
33
|
+
/** The name it's exported as, or `null` for `export *`. */
|
|
34
|
+
exported: string | null;
|
|
35
|
+
/** Whether it's only a type: in `export type`, or with `type` before it. */
|
|
36
|
+
typeOnly: boolean;
|
|
37
|
+
/** The offset of the name, of `*`, or of `type` before the name. */
|
|
38
|
+
start: number;
|
|
39
|
+
/** The offset after the exported name, or after `*` for `export *`. */
|
|
40
|
+
end: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface LexedStatementBase {
|
|
44
|
+
/** The offset of `import` or `export`. */
|
|
45
|
+
start: number;
|
|
46
|
+
/** The offset after the statement's `;`, or its last token without one. */
|
|
47
|
+
end: number;
|
|
48
|
+
/** The module it imports from, or `null` for a statement the lexer doesn't recognize. */
|
|
49
|
+
source: LexedSource | null;
|
|
50
|
+
/** Whether it's `import type` or `export type`. */
|
|
51
|
+
typeOnly: boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** An `import` statement. */
|
|
55
|
+
export interface LexedImport extends LexedStatementBase {
|
|
56
|
+
kind: "import";
|
|
57
|
+
specifiers: LexedImportSpecifier[];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** An `export … from` statement. */
|
|
61
|
+
export interface LexedExport extends LexedStatementBase {
|
|
62
|
+
kind: "export";
|
|
63
|
+
specifiers: LexedExportSpecifier[];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export type LexedStatement = LexedImport | LexedExport;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* A module's top-level `import` statements and `export … from`
|
|
70
|
+
* re-exports, read without a parser: each statement's offsets, its
|
|
71
|
+
* source and the names it imports or re-exports. It finds statements as
|
|
72
|
+
* {@link parseImportsExports} does with `localExports: false`, and on
|
|
73
|
+
* every statement that accepts, gives the same offsets, sources and names,
|
|
74
|
+
* but it doesn't check syntax and never throws. A statement it can't read,
|
|
75
|
+
* including TypeScript's `import a = require("a")`, is returned with
|
|
76
|
+
* `source: null` and no specifiers, ending where it stopped reading.
|
|
77
|
+
* TypeScript's `type` forms are always read.
|
|
78
|
+
*/
|
|
79
|
+
export declare function lexImportsExports(source: string): LexedStatement[];
|
package/lexer.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r,k,h,p,y}from"./shared-pmkdz7sc.js";function g(e){let t=new m(e),i=[];return k(e,!1,(n,s)=>{let a=t.statement(s);return i.push(a),a.end}),i}class m{source;pos=0;end=0;escapeEnd=0;constructor(e){this.source=e}statement(e){this.pos=this.end=e+6;let t=this.source.charCodeAt(e)===105?{kind:"import",start:e,end:0,source:null,typeOnly:!1,specifiers:[]}:{kind:"export",start:e,end:0,source:null,typeOnly:!1,specifiers:[]};if(!(t.kind==="import"?this.import(t):this.export(t)))t.source=null,t.specifiers=[];return t.end=this.end,t}import(e){let t=this.string();if(t!==null)return e.source=t,this.finish();if(this.isWord("type")){let a=this.peek(4);if(a===123||a===42||c(a)&&!this.isWordAfter(4,"from"))e.typeOnly=!0,this.advance(4)}let{specifiers:i,typeOnly:n}=e,s=this.at();if(s!==123&&s!==42){let a=this.pos,o=this.name();if(o===null)return!1;if(this.at()===61)return this.importEquals();if(i.push({kind:"default",imported:"default",local:o,typeOnly:n,start:a,end:this.end}),!this.eat(44))return this.from(e);s=this.at()}if(s===42){let a=this.pos;if(this.advance(1),!this.eatWord("as"))return!1;let o=this.name();if(o===null)return!1;return i.push({kind:"namespace",imported:"*",local:o,typeOnly:n,start:a,end:this.end}),this.from(e)}if(!this.eat(123))return!1;while(!this.eat(125)){let a=this.skip(),o=this.typeModifier()||n,u=this.name(),d=u??this.string()?.value;if(d===void 0)return!1;let l=u;if(this.eatWord("as"))l=this.name();if(l===null)return!1;if(i.push({kind:"named",imported:d,local:l,typeOnly:o,start:a,end:this.end}),!this.eat(44)&&this.at()!==125)return!1}return this.from(e)}export(e){if(this.eatWord("import")){if(this.isWord("type")&&c(this.peek(4))&&!this.isWordAfter(4,"from"))e.typeOnly=!0,this.advance(4);return this.name()!==null&&this.at()===61&&this.importEquals()}if(this.isWord("type")){let n=this.peek(4);if(n===123||n===42)e.typeOnly=!0,this.advance(4)}let{specifiers:t,typeOnly:i}=e;if(this.at()===42){let n=this.pos;this.advance(1);let s=null;if(this.eatWord("as")){if(s=this.moduleExportName(),s===null)return!1}return t.push({kind:s===null?"all":"namespace",local:"*",exported:s,typeOnly:i,start:n,end:this.end}),this.from(e)}if(!this.eat(123))return!1;while(!this.eat(125)){let n=this.skip(),s=this.typeModifier()||i,a=this.moduleExportName();if(a===null)return!1;let o=a;if(this.eatWord("as"))o=this.moduleExportName();if(o===null)return!1;if(t.push({kind:"named",local:a,exported:o,typeOnly:s,start:n,end:this.end}),!this.eat(44)&&this.at()!==125)return!1}return this.from(e)}typeModifier(){if(!this.isWord("type"))return!1;let e=this.peek(4);if(e===34||e===39||c(e)&&!this.isWordAfter(4,"as"))return this.advance(4),!0;return!1}importEquals(){if(this.advance(1),this.isWord("require")&&this.peek(7)===40){if(this.advance(7),this.eat(40),this.string()===null||!this.eat(41))return!1}else do if(this.name()===null)return!1;while(this.eat(46));return this.eat(59),!0}from(e){if(!this.eatWord("from"))return!1;return e.source=this.string(),e.source!==null&&this.finish()}finish(){let e=this.isWord("with")?4:0;if(this.isWord("assert")&&!x(this.source,this.end,this.pos))e=6;if(e!==0&&this.peek(e)===123){this.advance(e),this.eat(123);while(!this.eat(125))if(this.string()===null&&this.name()===null&&!this.eat(58)&&!this.eat(44))return!1}return this.eat(59),!0}skip(){return this.pos=p(this.source,this.pos),this.pos}at(){return this.source.charCodeAt(this.skip())}advance(e){this.pos+=e,this.end=this.pos}peek(e){return this.source.charCodeAt(p(this.source,this.pos+e))}isWordAfter(e,t){return y(this.source,p(this.source,this.pos+e),t)}eat(e){if(this.at()!==e)return!1;return this.advance(1),!0}isWord(e){return y(this.source,this.skip(),e)}eatWord(e){if(!this.isWord(e))return!1;return this.advance(e.length),!0}moduleExportName(){return this.name()??this.string()?.value??null}name(){let e=this.source,t=this.skip();if(!r(e.charCodeAt(t))||h(e.charCodeAt(t)))return null;let i="",n=t,s=t;while(s<e.length){let a=e.charCodeAt(s);if(a===92){if(e.charCodeAt(s+1)!==117)return null;let o=this.unicodeEscape(s+2);if(o===null)return null;i+=e.slice(n,s)+o,s=n=this.escapeEnd}else if(r(a))s++;else break}return this.advance(s-t),i+e.slice(n,s)}string(){let e=this.source,t=this.skip(),i=e.charCodeAt(t);if(i!==34&&i!==39)return null;let n="",s=t+1;for(let a=s;a<e.length;){let o=e.charCodeAt(a);if(o===i)return this.advance(a+1-t),{value:n+e.slice(s,a),start:t,end:a+1};if(o===10||o===13)return null;if(o===92){let u=this.escape(a+1);if(u===null)return null;n+=e.slice(s,a)+u,a=s=this.escapeEnd}else a++}return null}escape(e){let t=this.source.charCodeAt(e);switch(this.escapeEnd=e+1,t){case 110:return`
|
|
2
|
+
`;case 114:return"\r";case 116:return"\t";case 98:return"\b";case 118:return"\v";case 102:return"\f";case 48:return h(this.source.charCodeAt(e+1))?null:"\x00";case 120:return this.hexEscape(e+1,2);case 117:return this.unicodeEscape(e+1);case 13:if(this.source.charCodeAt(e+1)===10)this.escapeEnd++;return"";case 10:case 8232:case 8233:return"";default:return h(t)||e>=this.source.length?null:String.fromCharCode(t)}}unicodeEscape(e){if(this.source.charCodeAt(e)!==123)return this.hexEscape(e,4);let t=0,i=e+1;for(;this.source.charCodeAt(i)!==125;i++){let n=f(this.source.charCodeAt(i));if(n===-1)return null;if(t=t*16+n,t>1114111)return null}if(i===e+1)return null;return this.escapeEnd=i+1,String.fromCodePoint(t)}hexEscape(e,t){let i=0;for(let n=e;n<e+t;n++){let s=f(this.source.charCodeAt(n));if(s===-1)return null;i=i*16+s}return this.escapeEnd=e+t,String.fromCharCode(i)}}function c(e){return e!==92&&r(e)&&!h(e)}function f(e){if(h(e))return e-48;let t=e|32;return t>=97&&t<=102?t-87:-1}function x(e,t,i){for(let n=t;n<i;n++){let s=e.charCodeAt(n);if(s===10||s===13||s===8232||s===8233)return!0}return!1}export{g as lexImportsExports};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sveast",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Zero-dependency Svelte 5 parser, TypeScript included, with svelte/compiler's exact AST, 2-3x faster.",
|
|
6
6
|
"author": "Eric Liu (https://github.com/metonym)",
|
|
@@ -27,6 +27,16 @@
|
|
|
27
27
|
"types": "./entities.d.ts",
|
|
28
28
|
"import": "./entities.js",
|
|
29
29
|
"default": "./entities.js"
|
|
30
|
+
},
|
|
31
|
+
"./walk": {
|
|
32
|
+
"types": "./walk.d.ts",
|
|
33
|
+
"import": "./walk.js",
|
|
34
|
+
"default": "./walk.js"
|
|
35
|
+
},
|
|
36
|
+
"./lexer": {
|
|
37
|
+
"types": "./lexer.d.ts",
|
|
38
|
+
"import": "./lexer.js",
|
|
39
|
+
"default": "./lexer.js"
|
|
30
40
|
}
|
|
31
41
|
},
|
|
32
42
|
"sideEffects": false,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./shared-as9can03.js";import"./shared-pyjcz2f8.js";import"./shared-pmkdz7sc.js";import"./shared-yr6e6h72.js";import{S}from"./shared-qnfwr59k.js";import{s}from"./shared-mwp38arc.js";function e(r,t={}){return S(r,t,s)}export{e as parseImportsExports};
|
package/parse-module.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./shared-
|
|
1
|
+
import"./shared-as9can03.js";import{e}from"./shared-pyjcz2f8.js";import"./shared-yr6e6h72.js";import{v}from"./shared-b37zemjd.js";import{s}from"./shared-mwp38arc.js";function i(r,o={}){return v(r,o,s)}export{e as ParseError,i as parseModule};
|
package/parse.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{b}from"./shared-gyydaea2.js";import"./shared-as9can03.js";import"./shared-pyjcz2f8.js";import"./shared-g16dt48m.js";import"./shared-yr6e6h72.js";import{s}from"./shared-mwp38arc.js";import{C}from"./shared-1xjsv3h6.js";var o={typescript:s,entityNames:C};function m(t,r){return b(t,r,o)}export{m as parse};
|