Datastar expression formatter for HTML, JSX, and TSX. A thin adapter around the OXC formatter engine used by oxfmt.
cargo install --locked --git https://github.com/hyperpuncher/dsfmtRequires Rust 1.96 or newer.
# Format a file (prints to stdout)
dsfmt src/components/slider.tsx
# Write changes back
dsfmt --write src/components/slider.tsx
# Format all supported files in a directory
dsfmt --write src/
# Check if files are formatted (exit code 1 if changes needed)
dsfmt --check src/
# Read from stdin
cat file.html | dsfmt --stdin-filepath file.html| Flag | Default | Description |
|---|---|---|
--stdin-filepath |
none | Use the filename to select HTML or JSX/TSX when reading stdin |
--line-width |
90 | Expression print width |
--use-spaces |
false | Use spaces instead of tabs |
--tab-width |
4 | Positive number of spaces per indent level |
--write, -w |
false | Atomically write changes, preserving permissions and symlinks |
--check |
false | Report all changed files or stdin, without writing or printing source |
- Detects current Datastar and Rocket attributes, including
data-star-*aliases - Ignores generic non-Datastar attributes like
data-testid - Adapts Datastar actions (
@post, etc.) to JavaScript for OXC, then restores them - Delegates expression wrapping, objects, arrays, statements, comments, and indentation to OXC
- Keeps delimiters attached to object/array boundaries and single-statement templates; gives statement lists and other multiline expressions separate delimiter lines
- Preserves comma expressions rather than converting them to statements
- Preserves literal-valued attributes, multiline literal contents, and CRLF line endings
- Leaves unsupported expressions (including host-interpolated templates and kebab-case signals), unquoted HTML values, encoded expressions, and malformed tags intact
- Replaces only Datastar string/template value spans. Native JSX expressions, tag layout, ordinary attributes, and all other source bytes are untouched
Run dsfmt before oxfmt: dsfmt handles embedded Datastar expressions, while oxfmt owns host-file formatting. For stdin/editor integration, pass --stdin-filepath so the host language is selected without guessing.
HTML (including .htm), JSX, TSX, Templ, HEEx, Blade. Extensions are case-insensitive.
--write and --check are mutually exclusive. Read, write, and directory-walk failures exit nonzero. Directory scans respect ignore files and skip hidden files by default.
just full # read-only formatting check, strict lint, and all tests
just fix # apply formatting and lint fixes
just build # locked release build
just bench # repeatable release-mode formatter benchmark
just update # update dependency lockfileThe benchmark uses seven batches and reports median whole-format times for the fixtures and generated 100/1,000-attribute tags. It is not a timing assertion in the test suite.
The formatter does not implement its own expression splitting or tag reflow. Unsupported syntax is preserved rather than sent through a handwritten fallback.
Release notes are generated by scripts/release-notes.sh, grouped by conventional commit type.