# prettier/prettier — codebase unpack

> Canonical page: https://codevetter.com/unpack/prettier

This is a deterministic Repo Unpack scan of prettier/prettier — a structural map, not a review, security audit, or maintainer-endorsed description.

- Scanned commit: 1a36a7defdcccfc4967e99bbf9517a02ab2345b2 (2026-09-22)
- Last upstream commit: Support configuration files with UTF-8 BOM (#20127)
- Generated by codevetter 1.12.0 on 2026-09-22
- 3999 files scanned · 7.7 MB

## Languages

- JavaScript: 5136 files
- TypeScript: 692 files
- Markdown: 478 files
- YAML: 395 files
- HTML: 251 files
- CSS: 185 files
- JSON: 112 files
- Vue: 99 files

## Repository structure

- tests/ — 3036 files
- src/ — 542 files
- website/ — 182 files
- scripts/ — 79 files
- changelog_unreleased/ — 65 files
- docs/ — 24 files
- .github/ — 23 files
- packages/ — 12 files

Probable source entrypoint: `index.js` (inferred from the tree, not upstream docs)

## Source layout — src/

- src/cli/ — 24 files
- src/common/ — 7 files
- src/config/ — 9 files
- src/document/ — 29 files
- src/experimental-cli/ — 3 files
- src/language-css/ — 29 files
- src/language-graphql/ — 0 files
- src/constants.js — 1 file
- src/index.cjs — 1 file
- src/index.d.ts — 1 file
- src/index.js — 1 file

## Package

- package.json: prettier v3.10.0-dev — 80 declared dependencies

## Structural health signals

Average score 7.2/10 across 96 files; 19 hotspots. These are deterministic review leads, not proof of a bug.

## Recent history

- 1a36a7defdcc (2026-09-22) Support configuration files with UTF-8 BOM (#20127)
- 6bc99db278c8 (2026-09-21) Prevent comment after head of member chain move around (#20125)
- 0bab82ffb8ca (2026-09-21) Update dependency oxc-parser to v0.151.0 (#20124)
- 31c1ad8abe20 (2026-09-21) Update dependency eslint-plugin-unicorn to v76 (#20118)
- 51ed2cbbf3b4 (2026-09-20) Simplify `interpolation` handling in `ngNonBindable` (#20115)

## Overview

Prettier 3.10.0-dev is an opinionated, plugin-based code formatter: it parses source into an AST, attaches comments, converts that AST to a Wadler-style Doc IR, then pretty-prints to a string. The public Node API in src/index.js is fully async (format, check, formatWithCursor, resolveConfig, getFileInfo, getSupportInfo); the CLI enters through bin/prettier.cjs into src/cli/index.js, with an opt-in rewrite re-exported from @prettier/cli. Built-in languages (JS/TS/Flow, JSON, CSS/Less/SCSS, HTML/Vue/Angular/LWC/MJML, GraphQL, Markdown/MDX, YAML, Handlebars) are themselves plugins, lazily loaded, and last-registered plugins win when resolving parsers and printers.

## System map

The runtime has three public surfaces: the Node ESM/CJS API (src/index.js / src/index.cjs), the CLI (bin/prettier.cjs → src/cli), and a browser standalone bundle (src/standalone.js, no config/plugin autoload). Formatting is owned by src/main/core.js; languages live under src/language-*; plugins are assembled by src/main/plugins and the generated builtin registries. Config search/load lives in src/config; the Doc printer in src/document. Development requires Node >=22 and Yarn 4; production tests still exercise dist/ down to Node 14. The website is a Docusaurus + Vite playground published via Netlify; npm packages are built by scripts/build/build.js into dist/.
- package.json names the project prettier 3.10.0-dev, sets type module, engines.node >=22, bin to ./bin/prettier.cjs, main to ./src/index.cjs, and exports '.' (types src/index.d.ts, require src/index.cjs, default src/index.js), './standalone' to src/standalone.js, and './plugins/*' to src/plugins/*.js. — [package.json#L1-34](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json#L1-L34)
- The published browser/unpkg entry is standalone.js; package.json also defines #universal import maps that swap src/universal/*.browser.js in browsers versus src/universal/*.js on Node. — [package.json#L13-24](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json#L13-L24) [src/standalone.js#L1-55](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/standalone.js#L1-L55) [docs/browser.md#L8-16](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/browser.md#L8-L16)
- bin/prettier.cjs is the real CLI bootstrap: it optionally enables Node compile cache, rejects Node versions below package.json engines.node, strips --experimental-cli / PRETTIER_EXPERIMENTAL_CLI, then dynamically imports either src/experimental-cli/index.js or src/cli/index.js and calls cli.run(). — [bin/prettier.cjs#L7-70](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/bin/prettier.cjs#L7-L70) [bin/prettier.js#L1-10](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/bin/prettier.js#L1-L10) [src/experimental-cli/index.js#L1](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/experimental-cli/index.js#L1)
- src/index.js is the Node API: withPlugins loads builtin plus user plugins, then format/check/formatWithCursor/getSupportInfo/inferParser wrap src/main/core.js; it also exports resolveConfig, getFileInfo, doc, util, version, __debug, and __internal (shared with the CLI). — [src/index.js#L44-144](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/index.js#L44-L144) [src/index.cjs#L1-77](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/index.cjs#L1-L77)
- src/standalone.js reimplements withPlugins without filesystem plugin loading: plugins may be an array or an object (prettierPlugins); there is no resolveConfig/getFileInfo. — [src/standalone.js#L4-55](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/standalone.js#L4-L55) [docs/browser.md#L8-26](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/browser.md#L8-L26)
- Builtin plugins are generated (do NOT edit) by scripts/generate-builtin-plugins.js into development-plugins.js (language-* modules) and production-plugins.js (src/plugins/*.js bundles), then lazy-loaded via toLazyLoadPlugins. loadBuiltinPlugins() picks production vs development based on NODE_ENV. — [scripts/generate-builtin-plugins.js#L13-31](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/scripts/generate-builtin-plugins.js#L13-L31) [src/main/plugins/load-builtin-plugins.js#L1-13](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/plugins/load-builtin-plugins.js#L1-L13) [src/main/plugins/builtin-plugins/development-plugins.js#L1-84](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/plugins/builtin-plugins/development-plugins.js#L1-L84) [src/main/plugins/builtin-plugins/utilities.js#L15-65](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/plugins/builtin-plugins/utilities.js#L15-L65)
- Language implementations live in src/language-{js,json,css,html,graphql,handlebars,markdown,yaml}; each exports languages, parsers, printers, and options. JS printers are a single estree printer; HTML covers angular/html/lwc/mjml/vue parsers with one html printer. — [src/language-js/index.js#L1-4](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-js/index.js#L1-L4) [src/language-js/printers.js#L15-41](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-js/printers.js#L15-L41) [src/language-html/index.js#L1-7](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-html/index.js#L1-L7) [src/language-html/languages.evaluate.js#L4-39](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-html/languages.evaluate.js#L4-L39)
- The build is node ./scripts/build/build.js; scripts/build/packages/index.js emits four packages (prettier, plugin-hermes, plugin-oxc, plugin-yuku) into dist/. prepublishOnly exits 1 so the source tree cannot be published. — [package.json#L200-231](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json#L200-L231) [scripts/build/build.js#L1-11](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/scripts/build/build.js#L1-L11) [scripts/build/packages/index.js#L1-11](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/scripts/build/packages/index.js#L1-L11) [scripts/build/packages/prettier.js#L32-37](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/scripts/build/packages/prettier.js#L32-L37)
- The website is Docusaurus 3 plus a separate Vite/Vue playground (website/vite.config.mjs, website/playground/). Netlify builds with yarn build:website and publishes website/build/. Playground formatting runs in a Worker at /worker.mjs. — [website/package.json#L1-16](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/website/package.json#L1-L16) [website/vite.config.mjs#L27-50](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/website/vite.config.mjs#L27-L50) [website/README.md#L7-45](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/website/README.md#L7-L45) [netlify.toml#L1-7](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/netlify.toml#L1-L7) [website/playground/composables/prettier-worker.js#L10-69](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/website/playground/composables/prettier-worker.js#L10-L69)
- CI is GitHub Actions: Dev runs yarn test (and c8 coverage) on Node 22/26; Prod first yarn build --clean then tests dist/ across Node 14–26, OS matrix, standalone, and Chrome/Firefox ESM+UMD via Puppeteer; Lint runs deps/tsc/eslint/prettier/cspell/changelog/format-test plus actionlint. — [.github/workflows/dev-test.yml#L20-69](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/.github/workflows/dev-test.yml#L20-L69) [.github/workflows/prod-test.yml#L20-202](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/.github/workflows/prod-test.yml#L20-L202) [.github/workflows/_build.yml#L9-32](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/.github/workflows/_build.yml#L9-L32) [.github/workflows/lint.yml#L21-67](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/.github/workflows/lint.yml#L21-L67)
- Config resolution is src/config/resolve-config.js: searchPrettierConfig + optional EditorConfig (editorconfig-without-wasm), mergeOverrides via micromatch, and relative plugin paths resolved against the config file directory. — [src/config/resolve-config.js#L69-127](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/config/resolve-config.js#L69-L127) [src/config/prettier-config/index.js#L52-62](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/config/prettier-config/index.js#L52-L62) [src/config/editorconfig/index.js#L23-47](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/config/editorconfig/index.js#L23-L47)
- The experimental CLI is a thin re-export of @prettier/cli/bin (and worker from @prettier/cli/dist/prettier_serial.js), selected by --experimental-cli or PRETTIER_EXPERIMENTAL_CLI rather than a first-party implementation in src/cli. — [src/experimental-cli/index.js#L1](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/experimental-cli/index.js#L1) [src/experimental-cli/worker.js#L1](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/experimental-cli/worker.js#L1) [bin/prettier.cjs#L33-66](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/bin/prettier.cjs#L33-L66) [package.json#L53](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json#L53)

## Feature catalog

Users format via CLI, Node API, or browser standalone. The CLI writes, checks, lists, caches, and inspects files; the API formats text, maps cursor offsets, resolves config, and infers parsers. Built-in languages cover the web stack with multiple JS parsers (babel/acorn/espree/meriyah/oxc/yuku/typescript/flow/hermes). Plugins, EditorConfig, ignore files, pragmas, range format, and a playground are first-class. Prettier refuses new formatting options by policy.
- prettier.format(text, options) is withPlugins(core.formatWithCursor) with cursorOffset -1; prettier.check is format === text; prettier.formatWithCursor returns {formatted, cursorOffset, comments}. — [src/index.js#L67-79](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/index.js#L67-L79) [docs/api.md#L14-36](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/api.md#L14-L36) [src/main/core.js#L321-364](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/core.js#L321-L364)
- Public Node APIs also include resolveConfig, resolveConfigFile, clearConfigCache, getFileInfo, getSupportInfo, plus prettier.doc and prettier.util. All public APIs are async; src/index.d.ts is the shipped types. — [src/index.js#L130-144](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/index.js#L130-L144) [docs/api.md#L8-12](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/api.md#L8-L12) [src/index.d.ts#L1-15](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/index.d.ts#L1-L15) [src/common/get-file-info.js#L19-41](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/common/get-file-info.js#L19-L41)
- CLI surface from src/cli/cli-options.evaluate.js includes --write/-w, --check/-c, --list-different/-l, --cache, --cache-location, --cache-strategy content|metadata, --config/--no-config, --config-precedence cli-override|file-override|prefer-file, --editorconfig, --ignore-path (default .gitignore and .prettierignore), --ignore-unknown/-u, --with-node-modules, --file-info, --find-config-path, --support-info, --help, --version. — [src/cli/cli-options.evaluate.js#L63-242](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/cli-options.evaluate.js#L63-L242) [docs/cli.md#L8-141](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/cli.md#L8-L141)
- Debug CLI flags --debug-print-doc, --debug-print-ast, --debug-print-comments, --debug-check, --debug-benchmark, --debug-repeat (and PRETTIER_PERF_REPEAT) short-circuit the format path in src/cli/format.js. — [src/cli/format.js#L102-209](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/format.js#L102-L209) [src/cli/context.js#L57-85](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/context.js#L57-L85) [src/cli/cli-options.evaluate.js#L138-159](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/cli-options.evaluate.js#L138-L159)
- Core format options in src/main/core-options.evaluate.js include parser, plugins (--plugin, array), printWidth (80), tabWidth (2), useTabs, endOfLine (lf|crlf|cr|auto), filepath/--stdin-filepath, rangeStart/rangeEnd, cursorOffset, insertPragma, requirePragma, checkIgnorePragma. — [src/main/core-options.evaluate.js#L47-197](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/core-options.evaluate.js#L47-L197)
- JS builtin parsers registered in development-plugins.js include babel, babel-flow, babel-ts, acorn, espree, meriyah, oxc, oxc-ts, typescript, flow, hermes, yuku, yuku-ts plus internal __js_expression / __vue_* / __ng_* parsers. — [src/main/plugins/builtin-plugins/development-plugins.js#L54-84](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/plugins/builtin-plugins/development-plugins.js#L54-L84) [src/language-js/parse/index.js#L1-10](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-js/parse/index.js#L1-L10) [src/language-js/languages.evaluate.js#L4-78](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-js/languages.evaluate.js#L4-L78)
- Non-JS builtins: css/less/scss (postcss), graphql, glimmer/handlebars, html/angular/lwc/mjml/vue, json/json-stringify/json5/jsonc, markdown/mdx/remark, yaml. Parser names are also listed as core option choices. — [src/main/plugins/builtin-plugins/development-plugins.js#L22-113](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/plugins/builtin-plugins/development-plugins.js#L22-L113) [src/main/core-options.evaluate.js#L107-140](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/core-options.evaluate.js#L107-L140)
- Official in-repo extra packages @prettier/plugin-oxc, @prettier/plugin-hermes, and @prettier/plugin-yuku wrap the corresponding JS parsers, set a distinct astFormat (estree-oxc/estree-hermes/estree-yuku), and reuse the estree printer. — [packages/plugin-oxc/index.js#L1-18](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/packages/plugin-oxc/index.js#L1-L18) [packages/plugin-hermes/index.js#L1-18](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/packages/plugin-hermes/index.js#L1-L18) [packages/plugin-yuku/index.js#L1-18](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/packages/plugin-yuku/index.js#L1-L18) [packages/plugin-oxc/package.json#L1-14](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/packages/plugin-oxc/package.json#L1-L14)
- Plugin loading is documented for CLI --plugin, API options.plugins, and config plugins; plugin modules export languages, parsers, printers, options, defaultOptions. Strings go through import() / importFromDirectory. — [docs/plugins.md#L8-144](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/plugins.md#L8-L144) [src/main/plugins/load-plugin.js#L11-55](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/plugins/load-plugin.js#L11-L55) [src/main/core-options.evaluate.js#L142-153](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/core-options.evaluate.js#L142-L153)
- Config files searched in order: package.json prettier key, package.yaml, .prettierrc, .prettierrc.json/yml/yaml/json5, .prettierrc.js/ts and prettier.config.js/ts, mjs/mts, cjs/cts, .prettierrc.toml. JS/TS configs are executed via import(pathToFileURL). — [src/config/prettier-config/config-searcher.js#L16-61](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/config/prettier-config/config-searcher.js#L16-L61) [src/config/prettier-config/loaders.js#L19-111](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/config/prettier-config/loaders.js#L19-L111) [docs/configuration.md#L7-14](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/configuration.md#L7-L14)
- CLI --cache uses FormatResultsCache (file-entry-cache) at node_modules/.cache/prettier/.prettier-cache by default, keyed by prettier version + Node version + stable-stringified options, strategy content (checksum) or metadata (mtime). Cache is forbidden with stdin. — [src/cli/format-results-cache.js#L35-70](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/format-results-cache.js#L35-L70) [src/cli/find-cache-file.js#L7-46](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/find-cache-file.js#L7-L46) [src/cli/index.js#L102-105](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/index.js#L102-L105) [src/cli/cli-options.evaluate.js#L64-86](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/cli-options.evaluate.js#L64-L86)
- The playground (website/playground/PrettierFormat.js) posts {type:'format', version, code, options, settings} to a versioned Worker; docs/technical-details.md notes a special parser value doc-explorer for inspecting the Doc IR. Prettier will not accept PRs that add formatting options. — [website/playground/PrettierFormat.js#L13-20](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/website/playground/PrettierFormat.js#L13-L20) [website/playground/composables/prettier-worker.js#L59-69](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/website/playground/composables/prettier-worker.js#L59-L69) [docs/technical-details.md#L8-12](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/technical-details.md#L8-L12) [docs/option-philosophy.md#L8-42](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/option-philosophy.md#L8-L42) [CONTRIBUTING.md#L87-89](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/CONTRIBUTING.md#L87-L89)

## Data flow

Text enters via CLI files/stdin or the format() API. Options are normalized, a parser is inferred or selected, plugins are loaded, and the parser produces an AST. Comments are attached, embedded languages may be re-parsed, printers emit a Doc, and printDocToString measures/breaks groups to a string. CLI then writes, diffs, or caches that string. Config, ignore, and EditorConfig are filesystem side channels that never run in standalone.
- formatWithCursor in src/main/core.js: normalizeFormatOptions → normalizeInputAndOptions (BOM strip, EOL guess/normalize, index clamp) → optional pragma skip → formatRange or coreFormat → re-add BOM. Empty/whitespace-only input short-circuits to formatted: ''. — [src/main/core.js#L27-32](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/core.js#L27-L32) [src/main/core.js#L267-364](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/core.js#L267-L364) [src/main/normalize-format-options.js#L22-73](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/normalize-format-options.js#L22-L73)
- normalizeFormatOptions infers parser from filepath via inferParser if options.parser is missing, then initParser/initPrinter, copies locStart/locEnd/getVisitorKeys/astFormat onto options, and fills defaults from getSupportInfo. Throws UndefinedParserError if neither parser nor filepath is usable. — [src/main/normalize-format-options.js#L22-73](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/normalize-format-options.js#L22-L73) [src/utilities/infer-parser.js#L16-31](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/utilities/infer-parser.js#L16-L31) [src/common/errors.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/common/errors.js)
- parse() in src/main/parse.js resolves the parser, optional parser.preprocess, then parser.parse(text, options, options) (third arg kept for v3 compat, slated for removal in v4). Parse errors with loc get a @babel/code-frame attached. — [src/main/parse.js#L4-48](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/parse.js#L4-L48)
- printAstToDoc: prepareToPrint attaches comments (attachComments) and optional printer.preprocess; printEmbeddedLanguages walks the tree; callPluginPrintFunction dispatches printer.print, prettier-ignore via printIgnored, and comment printing. — [src/main/ast-to-doc.js#L33-161](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/ast-to-doc.js#L33-L161) [src/main/comments/attach.js#L17-50](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/comments/attach.js#L17-L50) [src/main/multiparser.js#L7-53](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/multiparser.js#L7-L53)
- The Doc IR (string | Doc[] | commands such as group/fill/ifBreak/indent/line/cursor) is printed by src/document/printer/printer.js using MODE_FLAT vs MODE_BREAK and a fits() probe against remainingWidth. Public builders are re-exported as prettier.doc. — [src/document/builders/index.js#L15-32](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/document/builders/index.js#L15-L32) [src/document/printer/printer.js#L38-96](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/document/printer/printer.js#L38-L96) [src/document/public.js#L39-77](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/document/public.js#L39-L77) [commands.md#L1-27](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/commands.md#L1-L27)
- Cursor preservation: getCursorLocation finds cursorNode/nodeBeforeCursor/nodeAfterCursor; print wraps those nodes with the cursor symbol; coreFormat diffs old vs new region with diffArrays to compute the new cursorOffset. — [src/main/core.js#L34-176](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/core.js#L34-L176) [src/main/ast-to-doc.js#L56-128](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/ast-to-doc.js#L56-L128) [src/main/get-cursor-node.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/get-cursor-node.js)
- Range format (formatRange) slices AST-calculated rangeStart/rangeEnd, formats with extra alignment, then splices the trimmed result back, converting EOL if needed. — [src/main/core.js#L181-243](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/core.js#L181-L243) [src/main/range.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/range.js)
- CLI file input: expandPatterns (literal file, recursive dir **/*, or fast-glob; followSymbolicLinks:false; skip .git/.svn/.hg/.jj/.sl and node_modules unless --with-node-modules) → ignore() from .gitignore/.prettierignore → getOptionsForFile → formatWithCursor → optional fs.writeFile. — [src/cli/expand-patterns.js#L14-120](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/expand-patterns.js#L14-L120) [src/cli/directory-ignorer.js#L1-42](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/directory-ignorer.js#L1-L42) [src/utilities/ignore.js#L35-76](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/utilities/ignore.js#L35-L76) [src/cli/format.js#L273-467](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/format.js#L273-L467)
- getOptionsForFile: resolveConfig (unless --no-config) with editorconfig flag, then applyConfigPrecedence (cli-override default), temporarily pushContextPlugins if the config lists plugins. Invalid config process.exit(2). — [src/cli/options/get-options-for-file.js#L56-132](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/options/get-options-for-file.js#L56-L132) [src/cli/index.js#L42-47](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/index.js#L42-L47)
- Config loaders execute user JS/TS/MJS/CJS via import(pathToFileURL); JSON via parse-json; JSON5 via @bybrave/json5; TOML via smol-toml; YAML via the yaml plugin's __parsePrettierYamlConfig. A string prettier field is treated as an external package and loaded with requireFromFile then importFromFile. — [src/config/prettier-config/loaders.js#L8-111](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/config/prettier-config/loaders.js#L8-L111) [src/config/prettier-config/load-config.js#L8-50](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/config/prettier-config/load-config.js#L8-L50) [src/config/prettier-config/load-external-config.js#L10-33](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/config/prettier-config/load-external-config.js#L10-L33)
- Standalone/browser path never searches the filesystem: plugins must be passed in; docs/browser.md states no config, ignore, CLI, or automatic plugin loading. withPlugins only Object.values(plugins) if not an array. — [src/standalone.js#L4-20](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/standalone.js#L4-L20) [docs/browser.md#L8-26](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/browser.md#L8-L26)
- Embedded-language formatting (printer.embed) is skipped unless embeddedLanguageFormatting === 'auto' (default). Embed errors are swallowed unless PRETTIER_DEBUG is set. Plugins using the old embed arity throw with a v3 migration URL. — [src/main/multiparser.js#L7-53](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/multiparser.js#L7-L53) [src/main/multiparser.js#L95-100](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/multiparser.js#L95-L100)

## Behavior traces

Three user-visible flows were walked in source. CLI startup validates Node, builds a Context from argv/plugins, then dispatches to version/help/support/config-path/file-info, stdin, or formatFiles. Formatting a file expands globs, resolves per-file options, optionally hits cache, then runs the parse→doc→string pipeline. Persistence is either in-place write via mockable.writeFormattedFile, stdout, or a check/list-different exit code.
- CLI startup order: bin/prettier.cjs run() → version check against engines.node → shouldEnableExperimentalCli → import src/cli/index.js → cli.run(process.argv.slice(2)). — [bin/prettier.cjs#L33-70](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/bin/prettier.cjs#L33-L70) [src/cli/index.js#L13-37](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/index.js#L13-L37)
- src/cli/index.js run(): parseArgvWithoutPlugins for log-level → new Context → context.init() (parse --plugin, getContextOptions, parseArgv, filePatterns=argv._) → main(context) with mutually exclusive flag checks. — [src/cli/index.js#L13-67](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/index.js#L13-L67) [src/cli/context.js#L24-41](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/context.js#L24-L41)
- main() dispatch: --version prints prettier.version; --help uses createUsage/createDetailedUsage; --support-info → printSupportInfo; --find-config-path → logResolvedConfigPathOrDie; --file-info → logFileInfoOrDie; else stdin if no patterns and (stdin not TTY or --stdin-filepath); else formatFiles; else usage + exitCode 1. — [src/cli/index.js#L39-118](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/index.js#L39-L118)
- formatFiles: createIsIgnoredFromContextOrDie → optional FormatResultsCache → for await expandPatterns → skip ignored in write/check/list-different/debug-check → getOptionsForFile → fs.readFile utf8 → cache hit returns input unchanged else format() → maybe mockable.writeFormattedFile → set/remove cache → check summary + exitCode 1 if unformatted and not --write. — [src/cli/format.js#L273-504](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/format.js#L273-L504) [src/cli/mockable.js#L8-14](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/mockable.js#L8-L14)
- format() inner function: debugPrintDoc → __debug.printToDoc then formatDoc; debugPrintComments → formatWithCursor.comments JSON; debugPrintAst → JSON.stringify(ast); debugCheck double-formats and compares massaged ASTs; else performance loop or prettier.formatWithCursor. — [src/cli/format.js#L102-211](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/format.js#L102-L211)
- API format path: prettier.format → formatWithCursor(cursorOffset:-1) → withPlugins loads loadBuiltinPlugins()+loadPlugins(plugins) → core.formatWithCursor → coreFormat: parseText → printAstToDoc → printDocToStringWithoutNormalizeOptions. — [src/index.js#L44-75](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/index.js#L44-L75) [src/main/core.js#L27-49](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/core.js#L27-L49) [src/main/core.js#L321-352](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/core.js#L321-L352)
- Parser/printer resolve loops plugins.findLast so later plugins override builtins (comment: temporarily solution, see #13729). Missing parser/printer throws ConfigError; in PRETTIER_TARGET=universal the message says plugins must be added to the standalone bundle. — [src/main/parser-and-printer.js#L13-57](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/parser-and-printer.js#L13-L57)
- JS print dispatch in printWithoutParentheses tries printAngular, printJsx, printFlow, printTypescript, then printEstree in order, returning the first defined Doc. — [src/language-js/print/index.js#L22-35](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-js/print/index.js#L22-L35)
- JS babel parser is createParser(createParse(...)) over @babel/parser with errorRecovery, a long plugin list (doExpressions, decorators, pipelineOperator combinations, etc.), then postprocess. Tests for those plugins live in tests/format/js/babel-plugins/ and are generated by scripts/update-babel-plugin-tests.js. — [src/language-js/parse/babel.js#L15-80](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-js/parse/babel.js#L15-L80) [src/language-js/parse/babel.js#L33-40](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-js/parse/babel.js#L33-L40)
- oxc parser uses oxc-parser parseSync with preserveParens:true, maps labels to Prettier loc errors via index-to-position, and shares postprocess/createParser with other JS parsers. — [src/language-js/parse/oxc.js#L1-50](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-js/parse/oxc.js#L1-L50)
- Playground flow: PrettierFormat setup() watches code/options/version → worker.format → WorkerApi posts to /worker.mjs?version=… → worker replies {uid, message, error}. Website README requires yarn build:website so UMD bundles exist in static/lib/. — [website/playground/PrettierFormat.js#L6-31](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/website/playground/PrettierFormat.js#L6-L31) [website/playground/composables/prettier-worker.js#L10-69](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/website/playground/composables/prettier-worker.js#L10-L69) [website/README.md#L7-45](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/website/README.md#L7-L45)
- Config persistence is not a write of Prettier state: --write overwrites source files; --cache writes .prettier-cache JSON via file-entry-cache.reconcile(); clearConfigCache clears prettier-config, editorconfig, and plugin import caches. — [src/cli/format.js#L412-469](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/format.js#L412-L469) [src/index.js#L81-85](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/index.js#L81-L85) [src/config/resolve-config.js#L14-17](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/config/resolve-config.js#L14-L17) [src/main/plugins/load-plugin.js#L57-59](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/plugins/load-plugin.js#L57-L59)

## Testing signals

Jest 30 with jest-light-runner drives four suites: snapshot format tests, CLI/API integration tests, unit tests, and dts tests. Format tests are directory fixtures plus runFormatTest, which implicitly adds extra JS parsers and, under FULL_TEST=1, AST-compare, second-format, EOL, and BOM checks. Production tests install dist/prettier and also run standalone and browser (Puppeteer) matrices. Unit tests are skipped in production; integration tests are skipped in standalone/browser.
- jest.config.js testMatch: tests/format/**/format.test.js, tests/integration/__tests__/**/*.js, tests/unit/**/*.js, tests/dts/unit/**/*.js. Runner is jest-light-runner (child-process unless ENABLE_CODE_COVERAGE). Snapshot serializers: jest-snapshot-serializer-raw and -ansi. — [jest.config.js#L83-131](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/jest.config.js#L83-L131) [package.json#L169-173](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json#L169-L173)
- runFormatTest(import.meta, parsers, options) is the format-test DSL. getParsers implicitly adds acorn/espree/meriyah/oxc/yuku when babel is listed under tests/format/js|jsx; babel-ts/oxc-ts/yuku-ts when typescript is listed; hermes when flow is listed; __babel_estree when babel is listed. — [tests/config/format-test/run-format-test.js#L38-82](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/config/format-test/run-format-test.js#L38-L82) [tests/config/format-test/get-parsers.js#L4-36](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/config/format-test/get-parsers.js#L4-L36) [CONTRIBUTING.md#L11-76](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/CONTRIBUTING.md#L11-L76)
- test-format.js snapshots eolVisualizedOutput via createSnapshot; expectFail directories use toThrowErrorMatchingSnapshot. Additional FULL_TEST checks are described in CONTRIBUTING.md (compare AST, second format, CRLF/CR, BOM) and implemented under tests/config/format-test/. — [tests/config/format-test/test-format.js#L14-48](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/config/format-test/test-format.js#L14-L48) [CONTRIBUTING.md#L144-153](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/CONTRIBUTING.md#L144-L153) [tests/config/format-test/test-ast-compare.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/config/format-test/test-ast-compare.js) [tests/config/format-test/test-second-format.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/config/format-test/test-second-format.js)
- tests/format is partitioned by language (js, jsx, typescript, flow, css, scss, less, html, vue, angular, markdown, mdx, yaml, graphql, handlebars, json, mjml, lwc, misc) with per-directory __snapshots__/format.test.js.snap. Flow’s tests/format/flow/flow-repo/ is synced via scripts/sync-flow-tests.cjs, not edited by hand. — [tests/format](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/format) [CONTRIBUTING.md#L78](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/CONTRIBUTING.md#L78) [scripts/sync-flow-tests.cjs](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/scripts/sync-flow-tests.cjs)
- Integration tests cover CLI behaviors (check, write, cache, patterns, ignore, stdin, plugins, config-resolution, experimental-cli, node-version-check, help-options) with snapshot files under tests/integration/__tests__/__snapshots__/. — [tests/integration/__tests__/check.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/integration/__tests__/check.js) [tests/integration/__tests__/write.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/integration/__tests__/write.js) [tests/integration/__tests__/cache.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/integration/__tests__/cache.js) [tests/integration/__tests__/experimental-cli.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/integration/__tests__/experimental-cli.js) [tests/integration/__tests__/config-resolution.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/integration/__tests__/config-resolution.js)
- Unit tests (tests/unit/) cover doc-printer, doc-builders, ast-path, visitor-keys, config-loader, resolve-parser, builtin-plugins, editorconfig-to-prettier, massage-ast; they are ignored when NODE_ENV=production. Bundle tests are ignored in development. — [tests/unit/doc-printer.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/unit/doc-printer.js) [tests/unit/resolve-parser.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/unit/resolve-parser.js) [tests/unit/config-loader.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/unit/config-loader.js) [jest.config.js#L36-46](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/jest.config.js#L36-L46)
- Production Jest installs the built package via tests/config/install-prettier.js into a temp node_modules/prettier (unless SKIP_PRODUCTION_INSTALL); TEST_STANDALONE and TEST_RUNTIME=browser remap the entry and skip tests/integration/. Browser tests skip several plugin/front-matter format tests. — [jest.config.js#L7-60](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/jest.config.js#L7-L60) [tests/config/install-prettier.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/config/install-prettier.js) [tests/config/prettier-entry.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/config/prettier-entry.js)
- package.json test scripts: test=jest; test:dev-package=INSTALL_PACKAGE=1; test:production=NODE_ENV=production; test:production-standalone=TEST_STANDALONE=1; test:production:browser with TEST_RUNTIME_BROWSER chrome|firefox and TEST_BUNDLE_FORMAT umd. Coverage via c8 include src/** and bin/**. — [package.json#L202-210](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json#L202-L210) [package.json#L240-260](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json#L240-L260) [.github/workflows/dev-test.yml#L63-78](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/.github/workflows/dev-test.yml#L63-L78)
- Lint CI also runs yarn lint:format-test (scripts/format-test-lint.js), prettier check on docs with PRETTIER_DEBUG=true so embedded format errors throw, yarn lint:deps, tsc, knip (separate lint:knip script), and codecov upload of coverage/lcov.info. — [.github/workflows/lint.yml#L37-62](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/.github/workflows/lint.yml#L37-L62) [package.json#L216-224](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json#L216-L224) [jest.config.js#L110-116](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/jest.config.js#L110-L116)
- Release-script tests live in scripts/release/tests/; dts tests in tests/dts/unit/run.js (skipped on Node <=14). Dummy plugins under tests/config/prettier-plugins/ exercise embed/async printer/missing comments. — [scripts/release/tests](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/scripts/release/tests) [tests/dts/unit/run.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/dts/unit/run.js) [tests/config/prettier-plugins/prettier-plugin-uppercase-rocks/index.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/config/prettier-plugins/prettier-plugin-uppercase-rocks/index.js) [jest.config.js#L70-80](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/jest.config.js#L70-L80)
- Prod CLI job runs dist/prettier on Node v0.10.48 solely to assert the engines check message 'Prettier requires at least version 14 of Node.js' — the production engine floor advertised by that job is 14, while package.json engines.node is >=22 for this source tree. — [.github/workflows/prod-test.yml#L204-238](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/.github/workflows/prod-test.yml#L204-L238) [package.json#L35-37](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json#L35-L37) [bin/prettier.cjs#L43-56](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/bin/prettier.cjs#L43-L56)

## Risk map

The largest security surface is intentional code execution: config files and plugins are imported from user-controlled paths, and --write overwrites arbitrary matched files. Plugin last-wins lets a later plugin replace builtin parsers/printers. Cache writes with restrictAccessToCwd:false. Generated plugin registries and the dist/ publish boundary are easy to edit in the wrong place. Option policy and the removed custom-parser API are social/API traps, not memory-safety bugs.
- loadPlugin/importPlugin will import() a URL, an absolute path, a cwd-relative file, or a node_modules specifier via importFromDirectory (import-meta-resolve from a fake noop.js parent). This is how --plugin and config plugins run third-party code in-process. — [src/main/plugins/load-plugin.js#L11-55](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/plugins/load-plugin.js#L11-L55) [src/utilities/import-from-directory.js#L1-8](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/utilities/import-from-directory.js#L1-L8) [src/utilities/import-from-file.js#L1-8](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/utilities/import-from-file.js#L1-L8)
- JS/TS Prettier configs are executed, not parsed: loaders['.js'|'.mjs'|'.cjs'|'.ts'|'.mts'|'.cts'] = importModuleDefault via import(pathToFileURL(file)). External string configs try requireFromFile first then importFromFile. — [src/config/prettier-config/loaders.js#L19-109](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/config/prettier-config/loaders.js#L19-L109) [src/config/prettier-config/load-external-config.js#L10-33](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/config/prettier-config/load-external-config.js#L10-L33)
- --write calls mockable.writeFormattedFile(filename, output) which is fs.writeFile; expandPatterns can match any non-ignored file under cwd. docs/cli.md warns this overwrites files. process.exitCode is set per-file rather than aborting the whole run on a single IO error. — [src/cli/mockable.js#L8-14](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/mockable.js#L8-L14) [src/cli/format.js#L412-433](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/format.js#L412-L433) [docs/cli.md#L18-28](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/cli.md#L18-L28)
- FormatResultsCache constructs file-entry-cache with restrictAccessToCwd: false. --cache-location can point anywhere that is not a directory; default falls back to os.tmpdir() if find-cache-directory fails. — [src/cli/format-results-cache.js#L42-51](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/format-results-cache.js#L42-L51) [src/cli/find-cache-file.js#L10-34](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/find-cache-file.js#L10-L34)
- Parser/printer lookup uses plugins.findLast, so a user or config plugin can silently replace babel/estree/html printers. Integration tests exist for plugin-override-builtin-printers and plugin-override-buitin-plugins (filename typo). — [src/main/parser-and-printer.js#L18-47](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/parser-and-printer.js#L18-L47) [tests/integration/__tests__/plugin-override-builtin-printers.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/integration/__tests__/plugin-override-builtin-printers.js) [tests/integration/__tests__/plugin-override-buitin-plugins.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/integration/__tests__/plugin-override-buitin-plugins.js)
- scripts/release/release.js uses child_process.exec(command) for git fetch --tags and yarn before importing run.js. The comment says it cannot use dependencies because they may not be installed yet. This is maintainer-only, not the formatter runtime. — [scripts/release/release.js#L1-30](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/scripts/release/release.js#L1-L30)
- development-plugins.js and production-plugins.js are generated ('do NOT edit'); editing them by hand will be overwritten by yarn generate-builtin-plugins. Production plugin graph (src/plugins/*.js) is a different split than language-* modules. — [src/main/plugins/builtin-plugins/development-plugins.js#L1-4](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/plugins/builtin-plugins/development-plugins.js#L1-L4) [src/main/plugins/builtin-plugins/production-plugins.js#L1-4](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/plugins/builtin-plugins/production-plugins.js#L1-L4) [scripts/generate-builtin-plugins.js#L13-31](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/scripts/generate-builtin-plugins.js#L13-L31) [src/plugins/babel.js#L1-5](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/plugins/babel.js#L1-L5)
- src/index.cjs in non-production throws if prettier.util or prettier.doc is accessed (ESM-only in dev CJS). Production CJS requires those files directly. Mixing NODE_ENV and CJS consumers is a support trap. — [src/index.cjs#L41-75](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/index.cjs#L41-L75)
- Custom Parser API was removed in v3.0.0 (docs/api.md); plugins must use the Plugin API. printer.embed with >2 parameters throws, telling authors the v3 plugin API changed. — [docs/api.md#L141-149](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/api.md#L141-L149) [src/main/multiparser.js#L25-28](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/multiparser.js#L25-L28)
- No-new-options policy is enforced socially: CONTRIBUTING.md and docs/option-philosophy.md say option-request PRs are closed without discussion. Agents that add a formatting flag will be rejected. — [CONTRIBUTING.md#L87-89](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/CONTRIBUTING.md#L87-L89) [docs/option-philosophy.md#L8-42](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/option-philosophy.md#L8-L42)
- handleError maps UndefinedParserError to exit 2 (or ignore with --ignore-unknown); ConfigError/validation calls process.exit(1) immediately (fails the whole CLI); parse errors set exitCode 2 and continue. Check mode uses exit 1 for unformatted files. — [src/cli/format.js#L26-72](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/format.js#L26-L72) [src/cli/format.js#L496-504](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/format.js#L496-L504) [docs/cli.md#L94-102](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/cli.md#L94-L102)
- Website playground Worker loads /worker.mjs?version= and production Vite aliases npm deps to esm.sh CDN URLs (website/vite.config.mjs buildCdnAlias). That is a supply-chain/runtime dependency of prettier.io, not of the formatter library. (inferred) — [website/playground/composables/prettier-worker.js#L10-17](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/website/playground/composables/prettier-worker.js#L10-L17) [website/vite.config.mjs#L53-79](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/website/vite.config.mjs#L53-L79)

## Extension points

New languages are plugins: export languages/parsers/printers/options and load via --plugin, options.plugins, or config. Builtins are the same API, registered in the generated lazy-load tables. JS syntax work lands in src/language-js/parse and the printAngular/printJsx/printFlow/printTypescript/printEstree chain. Doc commands are the IR extension point. CLI flags are two tables (cli-options.evaluate.js and core-options.evaluate.js). Config file names are the CONFIG_FILES array.
- A plugin is a module (default or named exports) with languages, parsers (parse/astFormat/locStart/locEnd/hasPragma/preprocess), printers (print/embed/massageAstNode/hasPrettierIgnore/getVisitorKeys), options, defaultOptions. — [docs/plugins.md#L96-144](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/plugins.md#L96-L144) [src/main/parser-and-printer.js#L64-78](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/parser-and-printer.js#L64-L78) [src/language-js/printers.js#L24-41](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-js/printers.js#L24-L41)
- toLazyLoadPlugin turns {name, load, parsers[], printers[]} into objects whose parsers/printers entries are async thunks that import() the real module on first use — the intended way builtins stay tree-shakeable. — [src/main/plugins/builtin-plugins/utilities.js#L15-65](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/plugins/builtin-plugins/utilities.js#L15-L65)
- Adding a production-bundled parser means adding src/plugins/<name>.js (see src/plugins/babel.js re-exporting language-js/parse/babel plus json parsers) and regenerating production-plugins.js. Dev mode loads language-*/index.js instead. — [src/plugins/babel.js#L1-5](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/plugins/babel.js#L1-L5) [src/plugins/estree.js#L1-20](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/plugins/estree.js#L1-L20) [scripts/generate-builtin-plugins.js#L13-31](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/scripts/generate-builtin-plugins.js#L13-L31)
- JS printer extension: add a node-type handler in src/language-js/print/{estree,jsx,typescript,flow,angular}.js; printWithoutParentheses tries those five in order. Comment attachment hooks are canAttachComment/handleComments/willPrintOwnComments on the estree printer. — [src/language-js/print/index.js#L22-35](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-js/print/index.js#L22-L35) [src/language-js/printers.js#L1-41](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-js/printers.js#L1-L41)
- JS parser extension: export from src/language-js/parse/<engine>.js via createParser, then re-export from parse/index.js. babel.js documents the add/remove plugin checklist (tests/format/js/babel-plugins + scripts/update-babel-plugin-tests.js). — [src/language-js/parse/index.js#L1-10](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-js/parse/index.js#L1-L10) [src/language-js/parse/babel.js#L15-40](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-js/parse/babel.js#L15-L40) [src/language-js/parse/utilities/create-parser.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-js/parse/utilities/create-parser.js)
- Doc IR extension for printers is the builders in src/document/builders (group, fill, ifBreak, indent, line, cursor, label, trim, …) plus printer.printDocToString. prettier.doc.utils exposes traverseDoc/mapDoc/willBreak. concat is a deprecated alias for identity on arrays, TODO remove in v4. — [src/document/builders/index.js#L35-48](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/document/builders/index.js#L35-L48) [src/document/public.js#L39-76](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/document/public.js#L39-L76) [commands.md#L1-27](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/commands.md#L1-L27)
- CLI option tables: src/cli/cli-options.evaluate.js (CLI-only) merged with API options from getSupportInfo via apiOptionToCliOption in get-context-options.js. New forwarded flags belong in core-options.evaluate.js with cliName/cliCategory. — [src/cli/cli-options.evaluate.js#L63-70](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/cli-options.evaluate.js#L63-L70) [src/cli/options/get-context-options.js#L10-60](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/options/get-context-options.js#L10-L60) [src/main/core-options.evaluate.js#L45-153](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/core-options.evaluate.js#L45-L153)
- CONFIG_FILES in config-searcher.js is the ordered list of config filenames; loaders.js maps extensions to load functions. Adding a config format means both arrays. Search uses search-closest FileSearcher with a stopDirectory mockable. — [src/config/prettier-config/config-searcher.js#L16-67](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/config/prettier-config/config-searcher.js#L16-L67) [src/config/prettier-config/loaders.js#L95-111](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/config/prettier-config/loaders.js#L95-L111) [src/config/prettier-config/index.js#L52-61](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/config/prettier-config/index.js#L52-L61)
- Language metadata is linguist-languages plus createLanguage() in each languages.evaluate.js (extensions, filenames, vscodeLanguageIds, interpreters). inferParser matches basename, then extension, then shebang interpreter. — [src/language-js/languages.evaluate.js#L1-39](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-js/languages.evaluate.js#L1-L39) [src/language-html/languages.evaluate.js#L1-39](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/language-html/languages.evaluate.js#L1-L39) [src/utilities/infer-parser.js#L16-77](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/utilities/infer-parser.js#L16-L77)
- In-repo extra plugins under packages/plugin-{oxc,hermes,yuku} are the template for shipping an alternate JS parser as a separate npm package: remap astFormat, reuse estree printer, export languages/options from the core tree. They are included in the dist build package list. — [packages/plugin-oxc/index.js#L1-18](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/packages/plugin-oxc/index.js#L1-L18) [packages/plugin-hermes/index.js#L1-18](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/packages/plugin-hermes/index.js#L1-L18) [scripts/build/packages/index.js#L1-11](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/scripts/build/packages/index.js#L1-L11)
- __debug APIs (parse, formatAST, formatDoc, printToDoc, printDocToString) and __internal (shared with CLI) are the in-tree hooks tests and the CLI use; they are not documented as stable public API. mockable objects in src/common/mockable.js and src/cli/mockable.js exist so tests can stub writeFormattedFile/isTTY/getTimestamp. — [src/index.js#L94-128](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/index.js#L94-L128) [src/cli/prettier-internal.js#L1-17](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/prettier-internal.js#L1-L17) [src/cli/mockable.js#L1-17](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/cli/mockable.js#L1-L17)
- changelog_unreleased/<area>/<pr>.md plus yarn generate-changelog is the required contributor extension point for user-facing changes; PRs without it may be closed. — [CONTRIBUTING.md#L91-97](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/CONTRIBUTING.md#L91-L97) [changelog_unreleased/TEMPLATE.md](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/changelog_unreleased/TEMPLATE.md)

## Contributor handoff

Read src/index.js, src/main/core.js, and the language module you are touching before editing. Do not add formatting options. Do not hand-edit generated builtin-plugin files; run generate-builtin-plugins. Format tests are snapshots — yarn test -u then git diff. Prefer small, reviewable diffs. Dev Node is >=22; production behavior is what dist/ does after yarn build. Run the matching tests/format/<lang> directory plus yarn test tests/unit if you change Doc/parser resolve.
- Must-read first files for any change: package.json (scripts/exports), src/index.js (API), src/main/core.js (pipeline), src/main/parser-and-printer.js (plugin resolve), and CONTRIBUTING.md (test DSL + no-new-options). — [package.json](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json) [src/index.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/index.js) [src/main/core.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/core.js) [src/main/parser-and-printer.js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/parser-and-printer.js) [CONTRIBUTING.md](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/CONTRIBUTING.md)
- Language work: edit src/language-<lang>/ (parse, print, embed, comments) and add a tests/format/<lang>/<topic>/ directory with format.test.js calling runFormatTest(import.meta, [parser]). Never add files next to format.test.js that you do not want snapshotted. — [CONTRIBUTING.md#L11-47](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/CONTRIBUTING.md#L11-L47) [tests/config/format-test/run-format-test.js#L38-48](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/config/format-test/run-format-test.js#L38-L48) [tests/format/js](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/format/js)
- After changing languages.evaluate.js, options.js, or plugin parser/printer exports, run yarn generate-builtin-plugins (or yarn fix:builtin-plugins) so development-plugins.js and production-plugins.js stay in sync. — [package.json#L228-234](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json#L228-L234) [scripts/generate-builtin-plugins.js#L1-12](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/scripts/generate-builtin-plugins.js#L1-L12) [src/main/plugins/builtin-plugins/development-plugins.js#L1-4](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/plugins/builtin-plugins/development-plugins.js#L1-L4)
- Safe edit boundaries: src/language-* printers and tests/format snapshots are the normal contributor surface. Avoid src/index.cjs dual ESM/CJS shim, bin/prettier.cjs version gate, and scripts/build/hacks/* unless the change is specifically about bundling. (inferred) — [src/index.cjs](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/index.cjs) [bin/prettier.cjs](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/bin/prettier.cjs) [scripts/build/packages/prettier.js#L39-80](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/scripts/build/packages/prettier.js#L39-L80) [scripts/build/hacks](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/scripts/build/hacks)
- Tests to run locally: yarn test <path> for a focused directory; yarn test -u to update snapshots; FULL_TEST=1 yarn test for AST/second-format/EOL/BOM. Production: yarn build then yarn test:production. Do not use yarn test:production without a dist/. — [CONTRIBUTING.md#L4-12](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/CONTRIBUTING.md#L4-L12) [CONTRIBUTING.md#L144-153](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/CONTRIBUTING.md#L144-L153) [package.json#L202-210](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json#L202-L210)
- yarn debug <file> runs bin/prettier.js with --ignore-path=.prettierignore against the source tree (no dist needed). yarn perf / perf:inspect / perf:benchmark require a production build. — [package.json#L213-238](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json#L213-L238) [CONTRIBUTING.md#L80-118](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/CONTRIBUTING.md#L80-L118)
- Trap: plugins listed last win. Tests that list ['babel','flow','typescript'] also run oxc/yuku/hermes/acorn/espree/meriyah implicitly — a JS print change can fail snapshots in those extra parsers even if babel looks fine. — [tests/config/format-test/get-parsers.js#L16-33](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/tests/config/format-test/get-parsers.js#L16-L33) [src/main/parser-and-printer.js#L18-25](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/parser-and-printer.js#L18-L25) [CONTRIBUTING.md#L60-70](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/CONTRIBUTING.md#L60-L70)
- Trap: standalone and website need explicit plugins (estree must be loaded to print JS). Node API autoloads builtins; copying Node samples into src/standalone.js consumers will fail with ConfigError 'Plugins must be explicitly added to the standalone bundle.' — [src/standalone.js#L4-20](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/standalone.js#L4-L20) [src/main/parser-and-printer.js#L30-36](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/main/parser-and-printer.js#L30-L36) [docs/browser.md#L19-26](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/docs/browser.md#L19-L26)
- Trap: prettier.util/doc are unavailable from the development CJS build. package.json main points at src/index.cjs, so require('prettier') in this checkout without NODE_ENV=production cannot use those namespaces. — [src/index.cjs#L41-75](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/src/index.cjs#L41-L75) [package.json#L12-12](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json#L12-L12)
- PRs must follow .github/PULL_REQUEST_TEMPLATE.md and add changelog_unreleased/<area>/<id>.md. AI-generated low-quality PRs are closed. ESLint + Prettier are required (yarn fix). — [CONTRIBUTING.md#L91-97](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/CONTRIBUTING.md#L91-L97) [CONTRIBUTING.md#L155-160](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/CONTRIBUTING.md#L155-L160) [package.json#L225-227](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json#L225-L227)
- This repo’s own prettier.config.js forces parser meriyah for **/*.{js,mjs,cjs}, trailingComma none for bin/prettier.cjs, and jsonc for .vscode/*.json and tsconfig.json — dogfooding, not defaults for users. — [prettier.config.js#L1-27](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/prettier.config.js#L1-L27)
- Coverage tooling (c8 in package.json, codecov in Dev workflow) excludes src/standalone.js, src/index.cjs, src/plugins/**, and src/universal/*.browser.js — those paths can regress without coverage signal. — [package.json#L240-260](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/package.json#L240-L260) [jest.config.js#L112-115](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/jest.config.js#L112-L115) [.github/workflows/dev-test.yml#L67-78](https://github.com/prettier/prettier/blob/1a36a7defdcccfc4967e99bbf9517a02ab2345b2/.github/workflows/dev-test.yml#L67-L78)

Source repository: https://github.com/prettier/prettier
Full evidence corpus: https://github.com/Codevetter/codevetter/tree/main/benchmarks/repo-unpacks/prettier.json

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
