Output Formats¶
rumdl writes results in a configurable format. Select it with --output-format
<name> on check or fmt, the output-format key in configuration, or the
RUMDL_OUTPUT_FORMAT environment variable.
Formats fall into three groups with different stability guarantees (see Stability and Compatibility):
- Machine-readable (committed surfaces):
json,json-lines,sarif,junit - Integration (track their target platform):
github,gitlab,azure,pylint - Human-readable (not a stable surface, do not parse):
text(default),full,concise,grouped
For the machine-readable formats, fields may be added in a backward-compatible
way; removing or renaming a field requires a deprecation note. Consumers should
ignore unknown fields. Severity is one of error, warning, or info.
These contracts follow rumdl's version: after 1.0, an incompatible schema or semantic change requires a new major release. Whitespace, object-key order, diagnostic order, rule message wording, and elapsed-time values are not stable. Pin the rumdl version if byte-identical output matters.
Paths are relative to the project root (or current directory) by default and use
/ separators on every platform. --show-full-path requests absolute paths,
shown the same way in every format: on Windows C:/Users/dev/docs/guide.md,
without the \\?\ prefix a resolved path carries internally.
Line and column numbers are 1-based; columns count Unicode characters, not UTF-8
bytes or terminal display cells.
json¶
A single JSON array of warning objects, emitted as [] when there are no
violations.
The normative JSON Schema is published with
the documentation. Its #/$defs/jsonLineWarning definition describes each
json-lines record.
| Field | Type | Notes |
|---|---|---|
file |
string | Relative by default; absolute with --show-full-path |
line |
integer | 1-based line number |
column |
integer | 1-based column number |
rule |
string | Rule ID, e.g. MD009 |
message |
string | Human-readable description |
severity |
string | error, warning, or info |
fixable |
boolean | Whether rumdl can auto-fix this violation |
fix |
object | Present only when an automatic fix is available; otherwise omitted |
fix.range.start |
integer | Start byte offset (0-based) of the span to replace |
fix.range.end |
integer | End byte offset (exclusive) |
fix.replacement |
string | Text that replaces the span |
fix.additional_edits |
array | Optional edits with the same shape, applied atomically |
Fix ranges address the original UTF-8 input bytes, including their original line
endings. For a multi-edit fix, every range addresses that same input. Consumers
should validate all ranges, then apply the primary edit and every
additional_edits entry as one operation; applying edits from the highest start
offset to the lowest prevents earlier edits from shifting later ranges.
[
{
"file": "README.md",
"line": 5,
"column": 21,
"rule": "MD009",
"message": "3 trailing spaces found",
"severity": "warning",
"fixable": true,
"fix": { "range": { "start": 51, "end": 54 }, "replacement": "" }
}
]
json-lines¶
One JSON object per line (newline-delimited JSON), suitable for streaming. Each
object carries the same core fields as json except the fix object is
omitted; use json when you need fix details. The fixable boolean is still
present. A clean run emits zero records (an empty stream).
{"file":"README.md","line":5,"column":21,"rule":"MD009","message":"3 trailing spaces found","severity":"warning","fixable":true}
sarif¶
SARIF 2.1.0 for static-analysis tooling such as GitHub code scanning. Shape:
$schemaandversion("2.1.0").runs[0].tool.driver:name(rumdl),version,informationUri, andrules[](the deduplicated set of rules that fired; array order is not significant).runs[0].results[]: one entry per violation, each withruleId,level(severity mapped:error->error,warning->warning,info->note),message.text, andlocations[].physicalLocationcontainingartifactLocation.uri,region.startLine, andregion.startColumn.
Fix information is not represented in SARIF.
artifactLocation.uri is a URI reference: reserved characters and Unicode in
paths are percent-encoded, relative paths remain relative, and absolute paths are
emitted as file: URIs. $schema names the immutable official OASIS schema.
{
"$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "rumdl",
"version": "0.2.62",
"informationUri": "https://github.com/rvben/rumdl",
"rules": [{ "id": "MD009", "name": "MD009" }]
}
},
"results": [
{
"ruleId": "MD009",
"level": "warning",
"message": { "text": "3 trailing spaces found" },
"locations": [
{
"physicalLocation": {
"artifactLocation": { "uri": "README.md" },
"region": { "startLine": 5, "startColumn": 21 }
}
}
]
}
]
}
]
}
junit¶
JUnit XML for CI test reporters. One <testsuite> per file, each containing a
single <testcase> whose <failure> children are the violations:
<testsuites name="rumdl" tests failures errors time><testsuite name="<file>" tests failures errors time><testcase name="Lint <file>" classname="rumdl" time><failure type="<ruleId>" message="<message>">with body text<message> at line <n>, column <n>
Special characters in paths and messages are XML-escaped. Source characters that
XML 1.0 forbids are replaced with U+FFFD, keeping the report well-formed.
tests counts checked files and failures counts files with one or more
violations, not individual <failure> elements.
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="rumdl" tests="1" failures="1" errors="0" time="0.004">
<testsuite name="README.md" tests="1" failures="1" errors="0" time="0.000">
<testcase name="Lint README.md" classname="rumdl" time="0.000">
<failure type="MD009" message="3 trailing spaces found">3 trailing spaces found at line 5, column 21</failure>
</testcase>
</testsuite>
</testsuites>
Fix mode and output streams¶
In normal check mode, results go to stdout; --stderr moves them to stderr. For
check --fix --stdin and fmt --stdin, stdout belongs to the rewritten Markdown,
so diagnostics go to stderr. Fix mode reports only violations that remain after
fixing. Batch formats still emit a complete empty document when none remain:
[] for json, an empty SARIF run, or a passing JUnit testcase.
Integration and human-readable formats¶
github, gitlab, azure, and pylint emit the annotation or report format
expected by their target platform. They are stable but track upstream format
changes.
text (the default), full, concise, and grouped are human-readable and may
be adjusted for readability at any time. Do not parse them; use a machine-readable
format instead.