Supported files and syntax
Use this page to determine what Yamark selects and what it does with a specific construct. Formatting settings describes how to change the output.
Files and regions
| Input | What Yamark formats | Selection |
|---|---|---|
.yaml and .yml |
The whole YAML stream. | Automatic for path-aware formatting. |
.md, .qmd, .Rmd, and .rmd |
Markdown, YAML front matter, and recognized fenced content. | Automatic, except constructs described as preserved below. |
.py, .R, and .r |
#| hashpipe YAML blocks, marked Markdown comments or strings, and marked external-formatter targets. |
Hashpipe blocks are automatic; other targets require a fmt: directive. Surrounding source code is unchanged. |
.json, .jsonc, .json5, .jsonl, and .ndjson |
A YAML projection of the whole JSON-family input. | Explicit through yamark to-yaml or Yamark: View JSON as YAML. Normal formatting does not select these files. |
Markdown fences named yaml, yml, markdown, or md |
YAML, or recursively formatted Markdown. | Automatic unless the fence is locally skipped. |
| Markdown source fences | Python, R, JSON, GraphQL, CSS, HTML, JavaScript, TypeScript, and related aliases. | Delegated when a matching embedded formatter is available. |
YAML scalars tagged !markdown or !md |
The scalar value as Markdown. | Explicit tag. |
YAML scalars following # fmt: markdown |
The scalar value as Markdown. | Explicit directive. |
YAML literal scalars following # fmt: <name> or # fmt: embedded <name> |
The scalar value through a built-in or configured embedded formatter. | Explicit directive. |
Extension matching is ASCII case-insensitive. In path mode, unsupported extensions are counted as skipped and do not make the run fail. An unsupported --stdin-file-path is an error because stdin mode requires file-aware behavior.
Directory traversal skips hidden paths and respects .gitignore, .ignore, and global Git ignore files. Passing a hidden path explicitly selects it.
JSON-to-YAML projection
Formatting preserves the source language and produces output that can replace the input. JSON-to-YAML projection has a different contract: it parses a JSON-family input and emits formatted YAML for inspection or conversion.
Use yamark to-yaml --stdin-file-path to project JSON-family input from stdin to formatted YAML on stdout:
yamark to-yaml --stdin-file-path data.json < data.jsonThe command does not read or write the path. It uses the extension to select one exact input grammar:
| Extension | Accepted input |
|---|---|
.json |
Strict JSON. |
.jsonc |
JSON with line comments, block comments, and trailing commas. Other JSON5 syntax is rejected. |
.json5 |
JSON5 strings, identifiers, numbers, comments, and trailing commas. |
.jsonl and .ndjson |
One strict JSON value per physical line. Blank records are rejected. |
Object member order and duplicate names are preserved. JSON and JSONC keep the source spelling of numbers. JSON5 spellings that YAML would interpret differently are normalized, including 0X hexadecimal prefixes, leading or trailing decimal points, unary plus, Infinity, and NaN. Negative hexadecimal integers are emitted in decimal because YAML would otherwise treat them as strings.
JSONC and JSON5 comments become YAML comments. JSONL and NDJSON output a YAML document-start marker before every record. A record may be an object, array, or scalar; this does not change how ordinary YAML such as 1\n2 is interpreted by yamark format.
String escapes are decoded before YAML emission. Lone UTF-16 surrogate escapes are rejected because they do not represent Unicode scalar values. All JSON-family inputs reject nesting deeper than 256 levels. JSON5 also rejects legacy numeric escapes such as \1, invalid escaped identifier characters, and U+0085 as whitespace. Characters that YAML cannot carry inside a comment are shown as visible hexadecimal escapes.
Projection does not scan JSON strings or comments for embedded Markdown or formatter directives, and it does not dispatch to Prettier or another embedded formatter.
yamark format continues to skip JSON-family paths and never rewrites them. Yamark: View JSON as YAML in VS Code and Positron uses the same JSON-to-YAML projection.
Markdown
| Construct | Result | Details |
|---|---|---|
| Paragraphs | Formats | Wraps by column, paragraph, sentence, or not at all, according to the active Markdown settings. |
| ATX headings | Formats | Normalizes spacing. Preserves and, when safe, compacts heading attributes. |
| Lists and task lists | Formats | Reflows list paragraphs with container indentation accounted for. Preserves GFM task markers. |
| Blockquotes | Formats when supported | Wraps supported blockquote shapes recursively. |
| Footnote blocks | Formats or preserves | Wraps definitions by default. A preserve setting keeps definitions byte-for-byte. |
| Reference links | Formats around | Treats reference-style links as atomic wrapping tokens. Preserves reference definitions without relocation. |
| Nested image links | Formats when safe | Normalizes and wraps simple nested image labels and long destinations. |
| Pandoc citations | Formats around | Protects citation spans such as [@key] and [-@key] while wrapping. |
| Quarto divs | Formats when supported | Formats supported fenced div bodies recursively. |
| YAML fences | Formats | Formats fenced yaml and yml blocks as YAML unless locally skipped. |
| Markdown fences | Formats | Formats fenced markdown and md blocks recursively. |
| Source fences | Delegates | Can run embedded formatters for Python, R, JSON, GraphQL, CSS, HTML, JavaScript, TypeScript, and related aliases. |
| Long Quarto fence openings | Formats when safe | Promotes simple comma-separated options such as echo=FALSE to #| echo: false lines for a supported fence when wrapping is not none and the opening exceeds the configured column, or 72 in paragraph and sentence modes. For a delegated language, the embedded formatter must succeed; a missing, failed, or disabled formatter preserves the original opening. |
Quarto source fences with #| fmt: skip |
Preserves | Leaves the fenced chunk unchanged when the directive appears anywhere in the initial consecutive #| option block. |
| Document Markdown options | Reads | Applies editor_options.markdown.{wrap,canonical,footnotes} to the body and nested Markdown that follows. |
| GFM pipe tables | Formats | Aligns supported tables by display width. Git clean/smudge filters use compact pipe-table output. |
| Pandoc tables | Formats when supported | Normalizes supported simple, grid, and multiline tables. |
| Definition lists | Formats when supported | Normalizes marker spacing and wraps definitions. |
| Display math | Preserves | Keeps own-line $$ display math blocks byte-for-byte. |
| Raw HTML, TeX, Hugo shortcodes, table captions, and line blocks | Preserves | Leaves the construct unchanged when Yamark does not have a safe rewrite. |
| Template spans | Preserves | Recognizes default and configured template delimiters. |
For Quarto header promotion, a supported fence is a YAML or Markdown fence, a language with a built-in or configured formatter, or one of the opaque languages Yamark preserves safely: bash, sh, shell, zsh, ojs, text, console, rust, toml, lua, mermaid, ini, julia, sql, java, c, tex, latex, output, powershell, and cmd.
YAML
| Construct | Result | Details |
|---|---|---|
| Block mappings and sequences | Formats | Normalizes indentation and spacing. Does not reorder keys. |
| Flow mappings and sequences | Formats | Normalizes spacing. Expands multiline or over-width collections to block style when safe. |
| Compact collections | Formats when enabled | Collapses eligible block collections to flow style with --compact, [format].compact, or fmt: compact. |
| Scalar folding | Formats when safe | Can emit and rewrap folded prose scalars at the active prose width. |
| Literal scalars | Preserves by default | Changes a literal scalar only when it is explicitly marked as Markdown or an embedded formatter target. |
| Quoted scalars with hard newlines | Formats when safe | Can emit literal block style when the YAML value stays unchanged. |
| Unsafe plain scalars | Quotes | Quotes scalars whose meaning would change in block or flow context. |
| Core booleans and nulls | Formats | Normalizes plain values to YAML 1.2 spellings such as true, false, and null. Normalizes explicit core tags when safe. |
| Tags and anchors | Preserves | Preserves custom tags, anchors, aliases, and tag/anchor order. May remove a redundant core collection tag when syntax already implies the type. |
| Comments and directives | Preserves and reads | Preserves comments around supported nodes. Reads fmt: comments as local controls. |
| Duplicate keys | Formats around | Does not validate or reorder duplicate keys. May format their values. |
| UTF-8 BOM and line endings | Preserves | Preserves a UTF-8 BOM and the dominant CRLF or CR line ending. Rejects UTF-16 BOM input. |
| Tab indentation | Preserves or rejects | Preserves tab-indented YAML when no active target requires interpreting it. Rejects targeted formatting that would need to parse the unsupported indentation. |
JSON Lines (JSONL) as YAML streams
Path-aware formatting recognizes a .yaml or .yml stream made of two or more unmarked, one-line YAML flow-mapping roots, one per physical line with no separate trivia lines. It inserts the --- document-start marker before every record, including the first.
JSON objects are the common case, but the trigger is based on YAML shape and is not restricted to strict JSON objects.
Normal --line-width rules still determine whether each record and its nested collections stay in flow style or expand to block style. A single flow-mapping root or a stream containing any non-flow-mapping root follows the normal YAML path instead.
See the generated JSON Lines example.
Python and R source files
| Construct | Result | Details |
|---|---|---|
Consecutive own-line #| comments |
Formats | Parses the comment body as YAML and emits it with the original hashpipe prefix. |
| Marked Markdown comments and strings | Formats | Formats supported own-line comment blocks and supported multiline string literals, accounting for their prefix or indentation. |
| Marked external source strings | Delegates | Sends a supported multiline string literal to the named built-in or configured formatter and re-indents the result. |
| Surrounding Python or R | Preserves | Does not format source outside recognized or explicitly marked targets. |
Every non-empty line in a comment target must use the same comment prefix; empty comment lines may omit its trailing space. Python string targets use triple quotes with no prefix, or an r, f, rf, or fr prefix; the closing delimiter must be on a later line. R targets use a multiline standard or raw string. Markdown formatting rejects backslashes in non-raw Python and R strings because rewriting them could change the host-language value.
The generated hashpipe YAML example shows the automatic source-file transformation.
Embedded formatter dispatch
External formatters run only for explicit targets or recognized Markdown fence languages. Built-in aliases include ruff, air, mdformat, and the prettier family.
| Target name or fence language | Built-in formatter |
|---|---|
python, ruff |
Ruff |
r, air |
Air |
mdformat |
mdformat |
json, prettier-json |
Prettier with a .json path |
jsonc, prettier-jsonc |
Prettier with a .jsonc path |
json5, prettier-json5 |
Prettier with a .json5 path |
graphql, gql, graphqls, prettier-graphql |
Prettier with a .graphql path |
css, prettier-css |
Prettier with a .css path |
scss, prettier-scss |
Prettier with a .scss path |
less, prettier-less |
Prettier with a .less path |
postcss, pcss, prettier-postcss |
Prettier with a .pcss path |
html, prettier-html |
Prettier with a .html path |
js, javascript, prettier-js |
Prettier with a .js path |
jsx, prettier-jsx |
Prettier with a .jsx path |
ts, typescript, prettier-ts |
Prettier with a .ts path |
tsx, prettier-tsx |
Prettier with a .tsx path |
Markdown fences named markdown or md are formatted recursively instead of using mdformat. An [embedded.<name>] entry replaces the built-in mapping for that exact name.
The default aliases are optional. A configured formatter is also optional when its command’s first argv item is exactly ruff, air, mdformat, or prettier. A missing executable or nonzero exit preserves the target for either kind. Yamark reports the reason as a note only with --diagnostics.
A successful process that writes to stderr is an error. Any other configured formatter is strict: a missing executable or nonzero exit is an error. These formatter errors happen before Yamark writes the formatted file. See the [embedded] schema and --skip-embedded-formatters.
Layout repair
Yamark recognizes two narrow layout cues. Only the unmatched opener is a repair for ill-formed input:
- An unmatched
[or{where a block sequence or mapping begins as a mapping value or sequence item asks Yamark to collapse that one collection to flow style. - A physical newline inside a complete flow collection is valid multiline YAML. It asks Yamark to expand that collection to block style. Compact mode suppresses this multiline intent.
The opener may be on the value line or on the following line after an empty mapping value header. Adjacent forms such as tags:[ and tags:{ are not layout hints.
When the requested flow form fits the available --line-width, Yamark removes the unmatched opener and emits the collection in flow style. Otherwise it preserves the hinted collection as typed. It does not fail solely because the requested flow form is too wide, and surrounding YAML may still be formatted. The layout examples show each accepted gesture before and after formatting.
Failure behavior
Yamark is a formatter, not a general validator. It formats supported regions and leaves unsupported regions unchanged when they are not explicitly targeted and it has no safe rewrite.
Yamark parses YAML before formatting. For Markdown and Markdown-valued YAML scalars, it emits only transformations supported by its parser. An embedded formatter can change only a recognized fence or an explicitly marked source or YAML target.
An explicit directive instead requires a supported target. A missing or unsupported target or an unknown formatter name is an error for that file. Formatter execution follows the optional and strict failure rules above.
Input-decoding, parsing, formatting, file-read, and external-formatter errors happen before Yamark writes that file, so these errors leave its original content unchanged. A write error is reported, but writes are direct rather than atomic; Yamark does not promise rollback after a write begins.
A multi-file write run is not transactional. Other files can be written even when one input fails.