Skip to content

style: adapt prettier markdown formatting - #1689

Merged
jetersen merged 5 commits into
mainfrom
chore/prettier-embedded-js-style
Jul 30, 2026
Merged

jetersen merged 5 commits into
mainfrom
chore/prettier-embedded-js-style

Conversation

@jetersen

@jetersen jetersen commented Jul 29, 2026 •

Copy link
Copy Markdown
Member

Summary

Follow-up to #1688. That PR left Prettier formatting code inside fenced blocks, which is desirable — but Prettier formats it with its own defaults, not Biome's. Nothing on main exposed the gap, because every fence here is YAML. A JavaScript fence does:

-import { draftRelease } from 'release-drafter'
+import { draftRelease } from "release-drafter";

Double quotes and semicolons, contradicting biome.jsonc (quoteStyle: single, semicolons: asNeeded) — the style of the very code the example documents. This surfaced while rebasing #1684, which adds the first js fence to the README.

Fix

Mirror javascript.formatter from biome.jsonc in .prettierrc.yml, with a comment noting the two must stay in sync.

Why the YAML examples changed

Prettier applies singleQuote to YAML too, and it cannot scope quote style per embedded language — so this normalizes the config examples to single quotes. That is a real 168-line diff, and worth reviewing deliberately, but it moves the docs toward the repository's own convention:

single-quoted double-quoted
repo .yml/.yaml files 260 38
README examples (before) 4 58
README examples (after) 61 1

.github/release-drafter.yml — the canonical instance of the config the README documents — is single-quoted throughout, so the examples now match what maintainers actually write.

Quoting that carries meaning is preserved

In YAML, single quotes do not process escapes, so a blind conversion would corrupt values. Prettier is value-aware and does not do that:

$ npx prettier --config .prettierrc.yml sample.md
change-authors-separator: "\n"   # left alone — escape would break
plain: 'hello'                   # converted

README.md:322 keeps change-authors-separator: "\n " double-quoted for exactly this reason. No line containing a backslash appears anywhere in the diff.

Alternative considered

embeddedLanguageFormatting: 'off' would fix the JS problem with zero churn, but gives up machine-formatted YAML examples entirely. Mirroring the style keeps the examples enforced and consistent with the codebase.

Verification

npm run all passes, npm run check:clean exits 0, and npm run format:md:check is idempotent.

Note

Align fenced code block formatting with repo code style via Prettier config

Adds a .prettierrc.yml config to enforce single quotes, no semicolons, trailing commas, and consistent bracket/arrow formatting across JS/TS. Updates code examples in README.md and docs/configuration-loading.md to match the new style.

Changes since #1689 opened

  • Configured Prettier to process only Markdown files repository-wide [88df273]
  • Modified .prettierignore to simplify ignore patterns by removing explicit directory and file exclusions while maintaining global ignore with selective re-inclusion of markdown files [9f0555b]
  • Reformatted the last-not-found.md markdown template to include blank lines after blockquote markers and reflowed long lines into multiple wrapped lines [9f0555b]
  • Changed Prettier configuration to preserve authored line breaks in prose [1256f9a]
  • Reformatted last-not-found.md Markdown template and updated corresponding test snapshots [1256f9a]
  • Removed trailing spaces after Markdown admonition markers [edbd46e]

Macroscope summarized c83b0ad.

#1688 left Prettier formatting code inside fenced blocks with Prettier's own
defaults rather than Biome's. Nothing on main revealed it, because every fence
here was YAML, but a JavaScript example rewrites to double quotes and
semicolons — contradicting the style of the very code it documents.

Mirror `javascript.formatter` from biome.jsonc in `.prettierrc.yml`. Prettier
applies `singleQuote` to YAML as well, and it cannot scope quote style per
embedded language, so the config examples normalize to single quotes. That
matches the repository's own YAML, which runs 260 single-quoted values to 38,
including the `.github/release-drafter.yml` that the README documents.

Quoting that carries meaning is untouched: Prettier keeps
`change-authors-separator: "\n    "` double-quoted, since single quotes in YAML
do not process escapes.

@cchanche cchanche left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not scope prettier to .md files only ?

.prettierignore

# Ignore everything
*

# ...except markdown files:
!**/*.md

Per review: make the ignore file, not just the script globs, enforce that
Prettier only ever touches Markdown.

Two adjustments to the suggested pattern. `!*/` is required, because gitignore
semantics cannot re-include a file whose parent directory is excluded, so `*`
plus `!**/*.md` alone silently skips every Markdown file outside the repository
root — 5 of 8 files here. And `!**/*.md` re-includes the release note templates
under build-release-payload/static, which ship to users as content, so those are
excluded again afterwards.
The template was excluded from Prettier because formatting it broke the output.
Both alert markers sat directly above their prose, so `proseWrap: always` pulled
them into the paragraph, and GitHub stopped rendering the alerts entirely —
2 alert blocks became 0, leaving a literal `[!WARNING]` in the release body.
This is release content, not documentation: build-release-payload splices it into
the body whenever no previous release is found.

Separate the markers with a blank quote line, which is stable under Prettier, so
the file can be formatted like every other Markdown file. Verified against
GitHub's own renderer: both alerts still render and the rendered text is
identical before and after, including after `$OWNER/$REPOSITORY` substitution.

Also simplify the ignore file. `!*.md` matches at any depth, so the explicit
generated directories were unnecessary — none of them contain Markdown, and the
`*` baseline already excludes everything that is not re-included.

Inline snapshots for the four affected e2e release bodies updated accordingly.
@jetersen

Copy link
Copy Markdown
Member Author

Followed up on the static/ exclusion rather than leaving it in — pushed as 9f0555b.

Why it was excluded, concretely

The template is two GitHub alerts whose markers sat directly above their prose, which is exactly what proseWrap: always joins. Formatting it destroyed both alerts, confirmed against GitHub's own renderer:

alerts rendered
before 2 — markdown-alert-warning, markdown-alert-important
formatted, unfixed 0 — plain <blockquote>

Users would have seen the literal marker text in their release notes. This is release content rather than documentation: build-release-payload.ts imports it with ?raw and splices it into the body whenever there is no previous release.

Fix

Separating the markers with a blank quote line makes the file stable under Prettier, so it no longer needs excluding. Verified through gh api /markdown:

  • both alerts still render, with titles
  • rendered text is identical before and after, including after $OWNER/$REPOSITORY substitution

The four affected e2e inline snapshots were regenerated; the diff is confined to the template region.

Ignore file simplified

Down to three lines:

# Markdown only; `!*/` lets the negation reach files below the root.
*
!*/
!*.md

!*.md matches at any depth, so !**/*.md was redundant, and the explicit dist / coverage / .licenses / logs entries were too — none contain Markdown, and the * baseline already excludes everything not re-included. Verified all 9 Markdown files are picked up and every non-Markdown file is ignored.

On the question of a config-level way to express "Markdown only": there isn't one. Prettier's full option list from --support-info has no include/scope key, so CLI globs and the ignore file are the only mechanisms.

`proseWrap: always` rewrapped prose that read fine as written, and because a URL
cannot be broken, it pushed long links onto a line of their own. No print width
avoids that: the "open an issue" line in the release note template is 167
characters, so it only survives intact at printWidth 200.

Switch to `preserve`. Prettier still normalizes structure — table alignment,
list markers, escaping — but leaves authored line breaks alone. Every Markdown
file in the repository is already byte-identical under it, so there is no churn.

This also removes the reason the release note template needed reflowing, so
9f0555b's changes to it, and to the four e2e snapshots that assert its text, are
reverted: the template, the snapshots, and the bundle are back to their previous
bytes. The template no longer needs excluding either, since `preserve` cannot
join `> [!WARNING]` into the prose that follows it — the alert-breaking hazard
does not exist without reflowing.

Wrap width is no longer machine-enforced for prose. Raising it was measured at
roughly 550 reflowed lines and would also desync fenced code from Biome's
lineWidth of 80, since printWidth governs both.
@jetersen

Copy link
Copy Markdown
Member Author

Switched to proseWrap: preserve in 1256f9a, which supersedes the template work in 9f0555b.

Why no width setting fixes it

Prettier breaks before a long link because it cannot break inside a URL. The "open an issue" line in the release note template is 167 characters, so no sensible width keeps it intact:

printWidth result
80 2 lines
120 2 lines
160 2 lines
200 1 line

Raising the width is also not free in general: measured at roughly 550 reflowed lines across the docs, and since printWidth governs fenced code as well as prose, it would desync code examples from Biome's lineWidth: 80 — the very thing c83b0ad aligned. Verified: a 78-character js statement in a fence stays one line at width 100 and breaks at 80.

What preserve gives us

Prettier still normalizes structure while leaving authored line breaks alone:

  • misaligned tables → still padded and aligned
  • a 120-character prose line → left exactly as written
  • > [!note] above its prose → no longer joined, so the alert-breaking hazard disappears at the root

Every Markdown file in the repo is already byte-identical under it, so there is zero churn.

Consequences

Because reflowing is what broke the release note template, 9f0555b is reverted: the template, the four e2e snapshots asserting its text, and the bundle are back to their previous bytes. The template no longer needs excluding either — preserve cannot join the marker into the prose. Net change against 88df273 is now just the two config files.

The tradeoff, stated plainly: wrap width is no longer machine-enforced for prose, so a long line stays long until someone wraps it. The existing docs are all within 80 already.

Four alert markers ended in two spaces, a markdown hard break that existed to
stop `proseWrap: always` joining the marker into the prose below it. With
`proseWrap: preserve` nothing joins, so the hard break protects nothing and is
just invisible whitespace that any editor trimming trailing space would remove.

Verified against GitHub's renderer: all four markers still render as alerts, and
the rendered text of both files is byte-identical before and after. These were
the only trailing-whitespace hard breaks in any Markdown file in the repository.
@jetersen

Copy link
Copy Markdown
Member Author

I ended up fixing the configs and ignore. Hopefully this aligns better with what you asked for @cchanche

@jetersen jetersen changed the title style: align fenced code formatting with the repo's code style style: add prettier markdown formatter Jul 30, 2026
@jetersen jetersen changed the title style: add prettier markdown formatter style: adapt prettier markdown formatting Jul 30, 2026
@jetersen
jetersen merged commit c03148e into main Jul 30, 2026
8 checks passed
@jetersen
jetersen deleted the chore/prettier-embedded-js-style branch July 30, 2026 13:10
@cchanche

Copy link
Copy Markdown
Collaborator

Thank you !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants