v0.3.0
·
64 commits
to main
since this release
Immutable
release. Only release title and notes can be modified.
- breaking feat: native binaries, both CLI and JS lib — install
@fuzdev/tsv(N-API addon plus
the real nativetsvCLI;npx tsvexecs the binary) over@fuzdev/tsv-<triple>platform
packages for Linux (x64 gnu and musl, arm64 gnu), macOS arm64, and Windows x64; API-compatible
with@fuzdev/tsv_wasm(minus the WASM-onlyinit/init_sync/wasm_module/reinstantiateand
IgnoreStack'sfree()), which stays the universal fallback. The same CLI binaries are attached
to each GitHub Release with aSHA256SUMS, every asset carrying a Sigstore build provenance
attestation, for use without npm
(#717, #718,
#720, #725,
#726, #1035) - breaking chore: every package now requires Node >=22 (was >=20)
(#725) - breaking feat: every parse/format export takes an optional acorn-style options object —
parse_*(source, {locations?, sourceType?})andformat_*(source, {sourceType?}), replacing the
flat*_no_locations/*_with_goalnames; unknown keys throw,sourceTypeis TypeScript-only,
andParseOptions/FormatOptions(plus theirTypeScript*variants) are exported types. The CLI
flag is--source-type(was--goal), and naming one for a Svelte or CSS input is an error rather
than ignored (#645,
#713) - breaking feat: the exported
IgnoreStacksplitspush_tsvintopush_formatignore/
push_prettierignore,heuristic_shadow_warningbecomesshadow_warning(returningundefined
when there's nothing to warn), and it gains the per-path queries the CLIs use —
path_shadow_warning,unsupported_extension_error,excluded_argument_warning,
gitignore_symlink_warning,unresolvable_root_error— so an embedder reproduces exactly what
tsv formatwould touch - breaking feat: strictness follows the spec —
sourceType: 'script'parses a sloppy script
(strict only under its own"use strict"prologue, sowithand legacy octal literals and
escapes parse there), a module is always strict (legacy string escapes now reject in one), and
formatwith nosourceTypeparses as a module and retries as a script only if that fails, so
legacy scripts format from a baretsv format(.mjs/.mtsexcepted);withis a reserved word
in every mode, so it no longer parses as a name - breaking fix: the parsers reject what their oracles reject — TypeScript: a raw newline inside
a string literal, the[no LineTerminator here]positions,for awaitwithoutof, a definite
!on aforheader's declaration,typeof 5, a compound operator inside a destructuring or
fortarget ([a += b] = xs, which used to parse and drop the operator); Svelte: a duplicate
{:else}, a block tag in attribute position, an unterminated quoted attribute (each of which used
to parse and corrupt the document), an unknown<svelte:*>name, a nested<svelte:options>—
and accept what they accept: strict-mode-reserved words as binding names (let,yield,
implements),letas a reference inforheads, type-assertedfor-in/oftargets
(for (a! of xs)), decorator type arguments, ambient generator/async declarations,
declare module 'x'with no;, and the tsc corpus's remaining over-rejections
(#618, #619,
#621, #628,
#629, #630,
#638, #640,
#673, #705,
#708, #710,
#711, #736,
#737, #776,
#778, #812,
#814, #872,
#877, #878,
#881, #893,
#894, #895,
#912, #915) - breaking fix: parse output tracks its canonical oracles — CSS roots gain
comments: CSSComment[]and::part()/::slotted()gain anargs: SelectorList
(#766), Svelte components withoutlang="ts"emit
vanilla acorn's wire shape in every expression island, not just<script>—
ImportExpression.optionsinstead ofarguments, get/setPropertykey order
(#774) — comment attachment reaches every island node
(#891, #896),
acorn-typescript alignments through 1.0.13 (#702,
#764), span, loc and key-order alignments
(#583, #625,
#882, #885,
#888, #889,
#919), Svelte and CSS offsets counted past a leading
BOM as their parsers strip it (TypeScript keeps file coordinates, as acorn does), a template
element'sraw/cookedfolding a literal<CR><LF>to<LF>per the spec
(#727), JS-exact numeric literal values
(#553), and corrected legacy-octal-escape and HTML
character-reference decoding (#633,
#635) - fix: the bundled
tsv_ast.d.tsnow types the whole wire outside the CSS subtree and is gated
against the fixture corpus —Script.contentis aProgram(wasunknown),
Program.sourceTypeis'script' | 'module',LogicalExpression,WithStatementand the
Svelte-built node shapes are declared, acorn nodes inside a Svelte component carry
leadingComments/trailingComments, and the never-emittedTSInterfaceHeritageand
TSMappedTypeParameterare gone
(#890) - breaking fix: a path named on the command line is bounded by the ignore files like a walked
one — a file or directory a.gitignorerule excludes is skipped with a warning that gives the
re-include lines, one a.formatignore/.prettierignorerule excludes is skipped quietly (as
prettier does), and a run whose every argument was an excluded file exits 0; a symlinked argument
is graded as the link git sees, not its target. Naming a file tsv doesn't format
(tsv format some.json) is now an upfront argument error instead of being parsed as TypeScript
(#709) - breaking feat:
format-ignore/prettier-ignoreare honored in many more positions (type
members, parameters, arguments, declarators, statement and declaration heads, Svelte braced
heads), and only an own-line directive acts — one sharing its line with code is an ordinary
comment (#572,
#913); a frozen statement keeps its ASI semicolon and
required parens so the output reparses
(#897), and a-start/-endrange no longer prints a
<script>/<style>inside it twice (#610) - feat: more formatting that takes advantage of Svelte 5 whitespace changes
(#558, #563,
#600, #601,
#606, #607,
#609, #750,
#768, #905,
#906, #907,
#908, #909,
#910, #911,
#918, #1006) - fix: many formatting fixes
- fix: no comment is dropped or double-printed, and a
//no longer swallows the code after it
into an output that doesn't reparse; an embedded body in a language tsv doesn't format
(<script lang="coffee">,<template lang="pug">,type="application/json") is copied verbatim
instead of being parsed or re-indented (#875,
#879) - feat: the JS CLIs format directories in parallel on
node:worker_threads—--jobsis no longer
ignored. The Node entry exportswasm_moduleand the./workersubpath initializes a worker from
it without recompiling. On every CLI, an explicit--jobspast4 × logical CPUsclamps with a
warning and a thread the OS refuses narrows the pool instead of failing the run
(#873, #883,
#884) - fix: both CLIs survive a closed or non-blocking pipe (
tsv format . | headno longer aborts or
loses its report of what changed), and the JS CLI refuses to rewrite a file whose bytes aren't
valid UTF-8 rather than writing U+FFFD back over it - fix: a panic no longer breaks the engine — the WASM instance stays callable after a trap
(#616) and the native addon throws a JS error instead of
aborting the host (#717); the one trap that does poison
a WASM instance, a stack overflow (~2,500 nesting levels), is recoverable through the new
reinstantiate()export (objects from the old instance are invalidated;free()on one is a safe
no-op), which thetsvbin calls automatically (#886);
every nativetsvCLI route and thread runs on one stated 32 MiB stack
(#874) - fix: every
<CR>/<CR><LF>in formatted output folds to<LF>, verbatim-copied regions included
(#880);tsv parse --prettyno longer fails on deeply
nested input (#1001); the CSS printer keeps a comma
closing a declaration value (transition: a,) rather than dropping it
(#615) - feat:
tsv --version(#726); thelocationshelper
rebuilds Sveltename_loc(#582) and throws, rather
than guessing, on the two Svelte shapes the span-only wire can't disambiguate
(#885);.d.tsrelative specifiers carry.js, so the
packages type undermoduleResolution: node16/nodenext
(#873)