sveast 0.9.6 → 0.9.8

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 CHANGED
@@ -35,7 +35,8 @@ ast.fragment.nodes; // [Text, RegularElement]
35
35
  | [`walk`, `visitorKeys`, `markupVisitorKeys`, `valueVisitorKeys`, `skipTypeWrappers`](#walknode-visitor-keys--void) | Visit, skip, stop at or replace nodes, in the whole AST, only the markup, or everything but TypeScript's types | `sveast`, `sveast/walk` |
36
36
  | [`children`, `forEachChild`](#childrennode-keys--node-and-foreachchildnode-callback-keys--void) | A node's children, cached or without allocating | `sveast`, `sveast/walk` |
37
37
  | [`isReference`](#isreferencenode-parent--boolean), [`extractIdentifiers`](#extractidentifierspattern--identifier) | Which identifiers are references, and which ones a pattern declares | `sveast`, `sveast/walk` |
38
- | [`analyzeScopes`](#analyzescopesast--scopes) | Which declaration each name refers to, and every read and write of it | `sveast`, `sveast/scope` |
38
+ | [`analyzeScopes`](#analyzescopesast-options--scopes) | Which declaration each name refers to, and every read and write of it | `sveast`, `sveast/scope` |
39
+ | [`a11yWarnings`](#a11ywarningsast-options--a11ywarning) | svelte's accessibility warnings, without compiling | `sveast/a11y` |
39
40
  | [`createLocator`, `locate`](#createlocatorsource--offset--position) | Lines and columns for the nodes you report, without parsing with `loc` | `sveast`, `sveast/walk` |
40
41
 
41
42
  ## Migrating from svelte/compiler
@@ -382,7 +383,7 @@ if (declaration.type === "VariableDeclaration") {
382
383
  }
383
384
  ```
384
385
 
385
- ### `analyzeScopes(ast) => Scopes`
386
+ ### `analyzeScopes(ast, options?) => Scopes`
386
387
 
387
388
  Finds the scopes of a component, its scripts and markup together, or of a module: which declaration each name refers to, and where each binding is read, written or subscribed to. It resolves names as svelte's analyzer does, which `tests/scope.test.ts` checks on the corpus: on 12,548 components from the corpus, svelte's tests and the Svelte projects listed under parity, they agree on all 208,797 names they both resolve, but for a class expression's name inside its body, a snippet's own name and a `var` declared twice, where sveast follows JavaScript.
388
389
 
@@ -407,7 +408,7 @@ size?.references.some((reference) => reference.writes || reference.mutates); //
407
408
 
408
409
  It returns:
409
410
 
410
- - **`module`** and **`instance`**, the scopes of `<script module>` and `<script>` (one scope, for a module). A `Scope` has the `node` that makes it, its `parent`, its `declarations` by name, and `get(name)`, the binding a name refers to there, or `null` for a global.
411
+ - **`module`** and **`instance`**, the scopes of `<script module>` and `<script>` (one scope, for a module). A `Scope` has the `node` that makes it, its `parent`, its `declarations` by name, and `get(name)`, the binding a name refers to there, or `null` for a global. With `types: true`, its `types` holds its `type`, `interface` and type parameter bindings, and `getType(name)` is the binding a name refers to in a type.
411
412
  - **`scopeOf(node)`**, the scope a node is in; `null` in a type, the `<style>` or another AST. The first call walks the AST again to record every node's scope, so a tool that only resolves names doesn't keep a map of every node.
412
413
  - **`bindingOf(identifier)`**, the binding an `Identifier` declares or refers to; `null` for a global, a property key or a name in a type.
413
414
  - **`referenceOf(identifier)`**, the `Reference` an `Identifier` is, to tell a read from a write or a store subscription; `null` for one that declares a binding or isn't a reference.
@@ -428,6 +429,42 @@ The markup's scopes are svelte's:
428
429
 
429
430
  Names in TypeScript's types aren't references, and `type` and `interface` declare nothing; it skips them with `valueVisitorKeys`. Enums, enum members and namespaces are declared. It doesn't change the AST, and takes less than half as long as parsing it.
430
431
 
432
+ | Option | Default | Description |
433
+ |:---|:---|:---|
434
+ | `types` | `false` | Resolve the names in types too, for a tool that asks which declarations some code uses, such as one that copies a statement with the imports it needs. |
435
+
436
+ With `types: true`, `type` and `interface` declare bindings of those kinds, and a type parameter or `infer U` one of kind `"type-param"`, in a scope's `types`, apart from its values, so `type A` and `const A` are two bindings. A name in a type is a `Reference` with `type: true` that neither reads, writes nor mutates: `A` in `let a: A`, `a` in `typeof a`, `I` in `implements I` and `extends I`, `N` in `N.T`, and the local name in `export type { A }`. A name in a type refers to a type, an import, a class or an enum; `typeof a` to a value; `N` in `N.T` to a namespace, an enum or an import, so `import type { A }` and `import { type A }` get the references. Property and method names in type literals and interfaces aren't references, but for a computed key's value. Type parameters are in scope for their function, class, method, type alias, interface or function type, `infer U` for its conditional type's true branch, and the parameters of a function type or signature are bindings of kind `"param"`, for `typeof x` and `x is T`. `<script generics="...">`'s names aren't declared. The value references are those it finds without `types`.
437
+
438
+ ```ts
439
+ const ast = parse(`<script lang="ts">
440
+ import type { DataTableHeader } from "carbon-components-svelte";
441
+ let headers: DataTableHeader[] = [];
442
+ </script>`);
443
+ const { instance } = analyzeScopes(ast, { types: true });
444
+ instance.get("DataTableHeader")?.references[0]?.type; // true
445
+ ```
446
+
447
+ ### `a11yWarnings(ast, options?) => A11yWarning[]`
448
+
449
+ From `sveast/a11y`. The `a11y_…` warnings svelte's compiler gives for a component, with the same `code`, `message` and offsets, and without the ones a `<!-- svelte-ignore -->` comment before an element, or one of its ancestors, silences. For a linter that already has the AST: on Carbon's 2,202 components it takes 60 ms, against 735 ms for `compile(source, { generate: false })`. It loads neither acorn nor the parser.
450
+
451
+ | Option | Default | Description |
452
+ |:---|:---|:---|
453
+ | `runes` | `false` | Whether the component compiles in runes mode, as [`isRunesMode`](#isrunesmodesource--boolean) says. In runes mode, `svelte-ignore` takes only svelte 5's codes, separated by commas; in legacy mode, svelte 4's `a11y-…` codes too, as svelte does. |
454
+
455
+ ```ts
456
+ import { isRunesMode, parse } from "sveast";
457
+ import { a11yWarnings } from "sveast/a11y";
458
+
459
+ for (const warning of a11yWarnings(parse(source), { runes: isRunesMode(source) })) {
460
+ warning.code; // "a11y_missing_attribute"
461
+ warning.message; // "`<img>` element should have an alt attribute\nhttps://svelte.dev/e/a11y_missing_attribute"
462
+ warning.start; // offsets of the element or attribute
463
+ }
464
+ ```
465
+
466
+ The ARIA tables come from svelte's, which read aria-query and axobject-query, generated into the package, so it has no dependencies. On svelte's tests, carbon-components-svelte, bits-ui, shadcn-svelte, skeleton, flowbite-svelte, svelte.dev, immich and SvelteKit, it gives the warnings `compile` gives for all 13,276 components both accept, 899 warnings, and for 13,163 with their `svelte-ignore` comments and common a11y attributes removed, 2,185 warnings.
467
+
431
468
  ### `createLocator(source) => (offset) => Position`
432
469
 
433
470
  A function from an offset to its `{ line, column }`, line from 1 and column from 0, as `loc: true` gives them: for a tool that parses without `loc`, which is faster, and needs lines only for what it reports. Lines are found on the first call, and each lookup starts its search at the line found last, so lookups in source order are fastest. Lines end at `\n`, as in the markup's `loc` and `ParseError`; acorn's `loc` in scripts and modules also ends them at a lone `\r`, U+2028 and U+2029. `parse` drops a leading byte order mark, so pass the source without one.