A real recursive-descent parser — compiled from Dart to JavaScript — formats your Blade templates in milliseconds. No regex. No child processes. No compromises.
Every built-in: @if, @foreach, @forelse, @auth, @guest, @switch, @push, @section, @extends, @yield, @component, and more.
Full <x-component> support with named slots, attributes, and deeply nested content. Properly indents <x-slot:name> blocks.
x-data, @click, :bind, x-show, x-transition, wire:model, wire:click, wire:poll — all modifiers handled correctly.
Format once or a hundred times — identical output. No trailing spaces, no oscillating blank lines, no second-save diffs.
Respects printWidth. Choose auto, always, or never. Configurable closing bracket position and self-closing style.
Quote style, directive spacing, slot formatting, slot name style, slot spacing, wrap attributes, attribute sorting, closing bracket, self-closing, echo spacing, HTML block spacing, trailing newline.
| This plugin | stillat | shufo | chisel | |
|---|---|---|---|---|
| Package size | ~160 KB | 777 KB | 12+ MB | ~2.6 MB |
| Avg format time | 0.66 ms | 13.23 ms | 16.55 ms | -- ms |
| Parser | Recursive-descent AST | TypeScript AST (Prettier IR) | Heuristic-based (no AST) | TypeScript AST (Prettier IR) |
| Idempotent | 219/228 | 207/228 | 224/228 | 224/228 |
| Dependencies | None | None | blade-formatter, php-parser | 3 (html-tags, parse-srcset, html-element-attributes) |
| Trailing whitespace | ✓ None | ✗ Present | ✓ None | ✓ None |
| Quote handling | Dedicated option (preserve/single/double) | Uses Prettier's singleQuote | Uses Prettier's singleQuote | Uses Prettier's singleQuote |
| Nested directives | ✓ Correct hierarchy | ✓ Correct | ✗ Collapses levels | ✓ Correct |
| <x-slot> formatting | ✓ Fully expanded | Keeps inline | ✗ Misaligned | ✓ Fully expanded |
| PHP formatting | ✗ Not supported | Via Laravel Pint | Via blade-formatter | ✓ Built-in (safe/aggressive) |
| Alpine.js value formatting | ✓ Via Prettier | ✗ | x-data only (via js_beautify) | ✓ Via Prettier |
| Component prefixes | x- only | x- only | x- only | ✓ Configurable (x, flux, livewire…) |
| Architecture | Compiled Dart (dart2js) | TypeScript → Prettier IR | blade-formatter wrapper | TypeScript (ground-up rewrite) |
| Links | GitHub · npm | GitHub · npm | GitHub · npm | GitHub · npm |
| Option | Default | Choices | Description |
|---|---|---|---|
| bladeQuoteStyle | "preserve" | single, double, preserve | ' vs " in attribute values |
| bladeDirectiveSpacing | "between_blocks" | between_blocks, none, preserve | Blank lines between @if, @foreach, etc. |
| bladeSlotFormatting | "compact" | compact, block | Extra newlines inside <x-slot> blocks |
| bladeSlotNameStyle | "colon" | colon, attribute, preserve | <x-slot:name> vs <x-slot name="..."> |
| bladeSlotSpacing | "after" | none, after, before, around | Blank lines before/after <x-slot> tags |
| bladeWrapAttributes | "auto" | auto, always, never | Multi-line attributes when line is too long |
| bladeAttributeSort | "none" | none, alphabetical, by_type | Reorder attributes (HTML → Alpine → Livewire) |
| bladeClosingBracketStyle | "same_line" | same_line, new_line | Where > sits when attributes wrap |
| bladeSelfClosingStyle | "preserve" | preserve, always, never | <x-icon /> vs <x-icon></x-icon> for empty tags |
| bladeHtmlBlockSpacing | "between_blocks" | between_blocks, none, preserve | Blank lines between block-level HTML siblings |
| bladeEchoSpacing | "spaced" | spaced, compact, preserve | Spacing inside {{ }} and {!! !!} braces |
| bladeTrailingNewline | true | true, false | Add trailing newline at end of output |
Works with Prettier 3.x. Just add the plugin to your .prettierrc.
# Install npm install --save-dev prettier-plugin-laravel-blade prettier # Add to .prettierrc echo '{ "plugins": ["prettier-plugin-laravel-blade"] }' > .prettierrc # Format npx prettier --write "**/*.blade.php" # Check (CI) npx prettier --check "**/*.blade.php"