CodeVetter · Repo Unpack · Data flow
prettier/prettier
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: ''.
- 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.
- 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.
- printAstToDoc: prepareToPrint attaches comments (attachComments) and optional printer.preprocess; printEmbeddedLanguages walks the tree; callPluginPrintFunction dispatches printer.print, prettier-ignore via printIgnored, and comment printing.
- 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.
- 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.
- Range format (formatRange) slices AST-calculated rangeStart/rangeEnd, formats with extra alignment, then splices the trimmed result back, converting EOL if needed.
- 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.
- 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).
- 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.
- 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.
- 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.