Skip to content

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:

  • $schema and version ("2.1.0").
  • runs[0].tool.driver: name (rumdl), version, informationUri, and rules[] (the deduplicated set of rules that fired; array order is not significant).
  • runs[0].results[]: one entry per violation, each with ruleId, level (severity mapped: error -> error, warning -> warning, info -> note), message.text, and locations[].physicalLocation containing artifactLocation.uri, region.startLine, and region.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.

gitlab writes a Code Quality report. rumdl severities map onto GitLab's scale as error to major, warning to minor, and info to info.

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.