Prettier 10 ๐จ Parser Inference โ How file extensions map to parsers
Prettier does not require a parser option in most cases. When it formats a file, it looks at the file’s extension and infers which parser to use. A .ts file uses the TypeScript parser. A .css file uses the CSS parser. A .md file uses the Markdown parser. The parser option exists as an override for the cases where the extension is ambiguous, the file is passed through stdin, or the content does not match the extension. But placing parser at the top level of a configuration file disables the inference entirely and forces every file through one parser, which is almost always a mistake.
This chapter covers the inference mechanism, the extension-to-parser mapping for the major languages, the cases where inference fails and an explicit parser is required, and the rule that parser belongs inside overrides, never at the top level.
Key point: Prettier infers the parser from the file extension by default. A top-level parser setting disables that inference and forces every file to use the specified parser, which breaks formatting for every other file type in the project.
Why parser inference exists
The configuration problem. A project contains JavaScript, TypeScript, CSS, JSON, Markdown, and YAML files. Each language needs a different parser. If every file required an explicit parser option, the configuration would need an overrides entry for every file type, and adding a new file type would require a configuration change. The extension-based inference removes that burden: the file name carries the information, and Prettier reads it .
The API problem. The prettier.format() function receives source text, not a file path. Without a file path, Prettier has no way to infer the parser. The filepath option provides the path, and Prettier uses the extension to select the parser. The --stdin-filepath CLI flag does the same for piped input . A file that is passed through stdin without a filepath must specify the parser explicitly, because there is no extension to inspect.
The ambiguity problem. Some extensions are ambiguous. A .html file could be standard HTML, an Angular template, or a Lightning Web Component. A .json file could be plain JSON, JSON with Comments (JSONC), or JSON5. Prettier maps the extension to a default parser, and the overrides mechanism handles the cases where the default is wrong for a specific file pattern.
a. The extension-to-parser mapping
Prettier’s built-in parsers map to extensions through the language definitions in its support information. The getSupportInfo() API returns the full list, including the extensions and filenames for each language . The major mappings are:
| Extension | Parser | Language |
|---|---|---|
.js, .mjs, .cjs | babel | JavaScript |
.jsx | babel | JSX |
.ts, .mts, .cts | typescript | TypeScript |
.tsx | typescript | TSX |
.json | json | JSON |
.jsonc, .json5 | json or json5 | JSON variants |
.css | css | CSS |
.scss | scss | SCSS |
.less | less | Less |
.html | html | HTML |
.vue | vue | Vue SFC |
.md, .markdown | markdown | Markdown |
.mdx | mdx | MDX |
.yaml, .yml | yaml | YAML |
.graphql, .gql | graphql | GraphQL |
The mapping is not exhaustive. Prettier also recognizes well-known filenames like package.json, tsconfig.json, and .prettierrc as JSON, and .editorconfig as INI. The filenames field in the support information covers these cases .
b. The top-level parser mistake
The parser option is documented as an override for the rare case where the extension is not sufficient. The documentation is explicit: do not put parser at the top level of the configuration. A top-level parser: "babel" forces every fileโincluding CSS, JSON, and Markdownโto be parsed as JavaScript. The CSS file fails to parse, the JSON file fails to parse, and the Markdown file fails to parse. The error messages are confusing because they point at syntax that is valid in its own language but invalid in JavaScript .
The correct placement is inside an overrides entry, where the files pattern scopes the parser to the files it applies to.
{
"overrides": [
{
"files": "*.component.html",
"options": {
"parser": "angular"
}
}
]
}
The *.component.html pattern selects Angular component templates, and the parser: "angular" tells Prettier to use the Angular parser for those files instead of the default HTML parser. Every other file in the project continues to use extension-based inference.
c. When inference fails
Inference fails in three situations, and each has a different remedy.
Stdin without a filepath. Piping a file into Prettier without specifying the file path leaves Prettier with no extension to inspect. The --stdin-filepath flag provides the path, and inference works normally. Without the flag, the --parser flag is required.
cat foo.css | prettier --stdin-filepath foo.css
A non-standard extension. A file with an extension that Prettier does not recognize, such as .tpl or .myext, has no default parser. The overrides mechanism maps the extension to a parser.
An extension with multiple possible parsers. The .html extension is the most common case. Prettier defaults to the standard HTML parser, but Angular templates and Lightning Web Components use different parsers. The overrides mechanism selects the correct parser based on the file path or a naming convention like *.component.html.
The getFileInfo() API is what editor extensions use to determine whether a file needs formatting and which parser it would use. It returns inferredParser: string | null, where null means the file is ignored or the parser cannot be inferred. The editor can then fall back to an explicit parser or skip formatting .
Complete Example Session
// ============================================
// PART 1: THE API INFERENCE
// ============================================
await prettier.format("const x = 1", { filepath: "foo.js" })
// Prettier infers the babel parser from .js.
// ============================================
// PART 2: THE API WITHOUT A FILEPATH
// ============================================
await prettier.format("const x = 1", { parser: "babel" })
// No filepath, so the parser must be specified.
# ============================================
# PART 3: THE STDIN FILEPATH
# ============================================
cat foo.css | prettier --stdin-filepath foo.css
# The CSS parser is inferred from the extension.
# ============================================
# PART 4: THE STDIN WITHOUT FILEPATH
# ============================================
cat foo.css | prettier --parser css
# The parser must be specified explicitly.
// ============================================
// PART 5: THE TOP-LEVEL MISTAKE
// ============================================
{
"parser": "babel"
}
// Every file is parsed as JavaScript.
// CSS, JSON, and Markdown fail.
// ============================================
// PART 6: THE CORRECT OVERRIDE
// ============================================
{
"overrides": [
{
"files": "*.component.html",
"options": { "parser": "angular" }
}
]
}
// Only Angular templates use the Angular parser.
// ============================================
// PART 7: THE MULTIPLE OVERRIDES
// ============================================
{
"overrides": [
{ "files": "*.component.html", "options": { "parser": "angular" } },
{ "files": "*.jsonc", "options": { "parser": "json" } }
]
}
// Each override scopes its parser to a file pattern.
// ============================================
// PART 8: THE GETFILEINFO API
// ============================================
const info = await prettier.getFileInfo("foo.css")
// { ignored: false, inferredParser: "css" }
// ============================================
// PART 9: THE IGNORED FILE
// ============================================
const info = await prettier.getFileInfo("node_modules/foo.js")
// { ignored: true, inferredParser: null }
// ============================================
// PART 10: THE SUPPORT INFO
// ============================================
const info = await prettier.getSupportInfo()
// info.languages contains the extensions and filenames
// for every supported language.
The ten parts covered the API inference, the API without a filepath, the stdin filepath, the stdin without a filepath, the top-level mistake, the correct override, multiple overrides, the getFileInfo API, the ignored file, and the support info.
Quick Reference
Inference mechanisms
| Context | Inference source |
|---|---|
| CLI file argument | File extension |
| CLI stdin | --stdin-filepath |
API format() | filepath option |
| API without filepath | parser option required |
Extension mapping (selected)
| Extension | Parser |
|---|---|
.js | babel |
.ts | typescript |
.jsx | babel |
.tsx | typescript |
.css | css |
.scss | scss |
.html | html |
.vue | vue |
.md | markdown |
.json | json |
.yaml | yaml |
Parser placement
| Location | Effect |
|---|---|
| Top level | Disables inference, forces one parser for all files |
overrides[].options.parser | Scoped to the files pattern |
CLI --parser | Forces the parser for the current invocation |
API functions
| Function | Purpose |
|---|---|
format() | Format text; infer from filepath |
getFileInfo() | Return ignored and inferredParser |
getSupportInfo() | Return languages, extensions, parsers |
Best Practices
โ Do This:
// Use overrides for non-standard extensions
{
"overrides": [
{ "files": "*.component.html", "options": { "parser": "angular" } }
]
} // โ
# Provide the filepath for stdin
cat foo.css | prettier --stdin-filepath foo.css // โ
// Provide the filepath for the API
prettier.format(text, { filepath: "foo.ts" }) // โ
โ Don’t Do This:
// Put parser at the top level
{ "parser": "babel" } // โ
# Pipe without a filepath or parser
cat foo.css | prettier // โ (no parser)
// Use parser for a file type that has a default
{ "parser": "typescript" } // unnecessary for .ts files // โ
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| CSS/JSON files fail to parse | Top-level parser: "babel" | Move the parser into an overrides entry |
| Stdin formatting fails | No filepath and no parser | Add --stdin-filepath or --parser |
| Angular template formatted as HTML | Default .html parser is used | Add an override for *.component.html |
| Editor does not format a file | getFileInfo returns null | Check the extension or add an override |
| Unknown extension is skipped | No parser inferred | Add an override mapping the extension |
Real-World Examples
1. API with filepath
prettier.format(text, { filepath: "foo.ts" })
2. API with parser
prettier.format(text, { parser: "typescript" })
3. Stdin with filepath
cat foo.css | prettier --stdin-filepath foo.css
4. Stdin with parser
cat foo.css | prettier --parser css
5. Top-level mistake
{ "parser": "babel" }
6. Correct override
{ "overrides": [{ "files": "*.component.html", "options": { "parser": "angular" } }] }
7. Multiple overrides
{ "overrides": [{ "files": "*.jsonc", "options": { "parser": "json" } }] }
8. getFileInfo
const info = await prettier.getFileInfo("foo.css")
9. Ignored file
const info = await prettier.getFileInfo("node_modules/foo.js")
10. Support info
const info = await prettier.getSupportInfo()
Visual
Inference flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ FILE EXTENSION โ
โ โ โ
โ โโโ .ts โโโบ typescript parser โ
โ โโโ .css โโโบ css parser โ
โ โโโ .md โโโบ markdown parser โ
โ โโโ unknown โโโบ no parser inferred โ
โ โ
โ No explicit parser option is needed. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The top-level mistake
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ { "parser": "babel" } โ
โ โ
โ foo.ts โโโบ babel parser โโโบ TypeScript syntax fails โ
โ foo.css โโโบ babel parser โโโบ CSS syntax fails โ
โ foo.md โโโบ babel parser โโโบ Markdown syntax fails โ
โ โ
โ One parser forced on every file. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The override
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ { โ
โ "overrides": [ โ
โ { โ
โ "files": "*.component.html", โ
โ "options": { "parser": "angular" } โ
โ } โ
โ ] โ
โ } โ
โ โ
โ Only *.component.html uses the angular parser. โ
โ Every other file uses extension-based inference. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Stdin
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ cat foo.css | prettier --stdin-filepath foo.css โ
โ โ โ
โ โโโ filepath provides the .css extension โ
โ โโโ css parser inferred โ
โ โ
โ cat foo.css | prettier --parser css โ
โ โ โ
โ โโโ parser specified explicitly โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| Default behavior | Infer parser from file extension |
| CLI stdin | --stdin-filepath for inference, --parser for explicit |
| API stdin | filepath option for inference, parser for explicit |
| Override location | overrides[].options.parser |
| Top-level parser | Disables inference, breaks other file types |
| Ambiguous extensions | Handled with overrides |
getFileInfo | Returns inferredParser or null |
getSupportInfo | Returns the full extension mapping |
Key takeaways:
- Prettier infers the parser from the file extension by default. A
.tsfile uses the TypeScript parser, a.cssfile uses the CSS parser, and a.mdfile uses the Markdown parser. Noparseroption is needed for files with standard extensions . - A top-level
parsersetting disables inference. The documentation states explicitly thatparsershould never be placed at the top level of a configuration file. It forces every file through one parser, which breaks CSS, JSON, Markdown, and every other file type that is not the specified language . - The
parseroption belongs insideoverrides. When an extension is ambiguous or non-standard, anoverridesentry with afilespattern scopes the parser to the files it applies to. The rest of the project continues to use inference . - Stdin requires a filepath or a parser. A piped file has no extension unless
--stdin-filepathprovides one. Without it, the--parserflag is required. The API behaves the same way with thefilepathoption . getFileInfo()is how editors decide whether and how to format. It returnsignoredandinferredParser. Anullparser means the file is ignored or the extension is not recognized. The editor can then fall back to an explicit parser or skip formatting .
Remember: Parser inference is the default because the file extension is the most reliable signal of the language. The parser option is an override for the cases where the extension is not enough: stdin without a path, a non-standard extension, or an extension that maps to multiple parsers. Put the override inside overrides, never at the top level. A top-level parser is not a configuration shortcut; it is a way to break every file type that is not the one you specified.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!