Prettier 3.9 Overhauls Five Parsers: micromark for Markdown, yaml v2, GraphQL.js v17, a Rust-Based Flow Parser, and Angular

Prettier 3.9 Overhauls Five Parsers: micromark for Markdown, yaml v2, GraphQL.js v17, a Rust-Based Flow Parser, and Angular

lschvn

Prettier 3.9.0, released June 27, 2026 in a 37-minute blog post by Fisker Cheung, is unusual for a Prettier release: the headline is not a new config option or a speedier CLI, it is five parser upgrades landing at once. Markdown, YAML, GraphQL, Flow, and Angular all move to newer upstream parsers, and the JavaScript and TypeScript printer gets a rework that will show up as a diff in most repos. If you treat Prettier output as stable, 3.9 is a release to land deliberately and pin the exact version.

Five parsers, one release

The Markdown change is the one most users will feel. Prettier's Markdown parser moves from the outdated remark-parse v8 to micromark v4, the modern CommonMark parser. The release notes frame this as "significantly enhanced CommonMark and GFM compliance" plus "numerous long-standing parsing bugs" resolved, and it lays a cleaner foundation for future work. There is one caveat: the MDX parser migration is not yet complete, and the team is asking for contributors familiar with the unified and micromark ecosystem to finish it.

YAML moves to yaml v2, which fixes many long-standing parse issues, with thanks to ota-meshi's work on yaml-unist-parser. GraphQL moves to GraphQL.js v17, which adds support for newer syntax: fragment arguments (...dynamicProfilePic(size: $size)) and directives on directive definitions and extend directive, both of which errored or misparsed on 3.8.

The Flow upgrade is the performance story. Prettier now uses the new Rust-based (oxidized) Flow parser released by the Flow team. In Prettier's local parser-only benchmarks, the new parser formatted Prettier's valid Flow fixtures in a 266.4ms median versus 422.6ms for the old parser, and parsed flow_parser.js in 1298.0ms versus 2269.6ms. That is roughly 37% and 43% faster, and it is the same Rust-native-frontend direction the project has explored through its OXC and Hermes plugins and that the wider ecosystem has been taking with Oxc and SWC.

The JavaScript and TypeScript printer changed

The parser upgrades are half the release; the other half is a batch of printer changes that will produce a diff. The most notable is a long-standing --no-semi idempotency bug. On 3.8, a break or continue followed by a line comment produced different output on the first and second format, so running Prettier twice could keep changing the file. On 3.9, the comment handling around break and continue is stable across formats.

A short list of the other printer changes:

  • Redundant parentheses removed in return statements, so return (a, b) is no longer rewritten to return ((a, b)).
  • Embedded-template interpolations realigned in tagged templates, avoiding unexpected line breaks and fixing alignment in CSS-in-template-literal blocks.
  • Logical-not inlining: !(...) in if/while/do..while conditions is inlined to reduce diff when a condition flips to its negated form, fixing a real-world double-paren case inside the Prettier codebase itself.
  • JSDoc trailing double spaces preserved, because some tooling treats them as meaningful.
  • Comment placement around empty call argument lists and parenthesized callees is corrected.

None of this is a config change, but together they mean a prettier --write . after upgrading will reformat files.

The one real breaking change: import assertions

The release drops support for the legacy import ... assert {} syntax:

- import foo from "./foo.json" assert { type: "json" };
+ import foo from "./foo.json" with { type: "json" };

The reason is upstream: Babel 8 completely removed support for the legacy assert keyword (the old parser plugin is gone), and without Babel parser support Prettier can no longer reliably parse or format that syntax. The current standard is the with keyword from the import attributes proposal. If your codebase still uses assert, migrate before upgrading; Prettier links to its disclaimer about non-standard syntax for context.

CLI fixes worth knowing

A few CLI fixes round out the release. --cache-strategy content was silently broken: file-entry-cache v11 renamed the useChecksum option to useCheckSum (capital S), and Prettier was still passing the old casing, so content-based cache comparison was disabled and only file size was compared. That is now fixed, so content-based caching actually works again.

Prettier also stops searching for EditorConfig files above Git worktrees: a .git file (used in worktrees and submodules) is now treated as a project root marker alongside a .git directory, so an EditorConfig from a parent directory no longer leaks into worktree formatting. Two crash fixes handle directory and file names with special characters (bracketed names like username[repo-name], and leading quotes), and the experimental CLI sees updates.

What to watch

The practical advice is straightforward: pin the exact version. The release notes repeat the standing recommendation to use "prettier": "3.9.0" rather than ^3.9.0, because the Markdown, YAML, GraphQL, and JS/TS changes all produce output diffs, and a caret range can pull a new minor that reformats a whole project on a fresh install. If you use @prettier/plugin-oxc or @prettier/plugin-hermes, upgrade them at the same time so the new formatting rules apply.

Two things to test before committing the upgrade: any Markdown or MDX documentation (the micromark switch is the broadest change), and any Flow-typed or GraphQL-heavy code. The MDX migration is still open, so MDX output in particular is worth a careful diff. The full changelog is on the compare view, and 3.9.1 followed on the same day with follow-up fixes.

Frequently Asked Questions

Related articles

More coverage with overlapping topics and tags.

Biome 2.5 Ships with `@biomejs/js-api` v6.0.0: A Major Bump for the JS API
tooling

Biome 2.5 Ships with `@biomejs/js-api` v6.0.0: A Major Bump for the JS API

Biome's CLI hits 2.5.0 and the JavaScript API moves to a major v6.0.0. The headline is a new spanInBytesToSpanInCodeUnits helper that fixes a real bug in non-ASCII text extraction, plus a long list of SCSS, JSON, linter, and CLI improvements.
Vite+: One CLI to Rule Them All, Or Just Another Layer of Hype?
tooling

Vite+: One CLI to Rule Them All, Or Just Another Layer of Hype?

VoidZero's Vite+ promises to unify runtime, package manager, bundler, linter, formatter, and test runner under a single command. We read the announcements, benchmarked the claims, and talked to people using it in production. Here is what we found.
pnpm 11.8 Ships `install --dry-run`, Node.js Package Maps, and Per-Package SBOM
tooling

pnpm 11.8 Ships `install --dry-run`, Node.js Package Maps, and Per-Package SBOM

pnpm 11.8.0 (June 18, 2026) adds a long-requested `--dry-run` for `pnpm install`, experimental Node.js package maps at `node_modules/.package-map.json`, CycloneDX devDependencies scope and per-package SBOM generation, and a macOS Gatekeeper fix that strips quarantine from native binaries. It also closes a configDependencies path-traversal advisory (GHSA-qrv3-253h-g69c) three days after the 11.7 lockfile hardening.

Comments

Log in Log in to join the conversation.

No comments yet. Be the first to share your thoughts.