module

Noir::OutputFormats

The catalog of -f/--format values, derived from the Noir::OutputFormat annotation each builder carries.

Everything that needs to know which formats exist reads it from here: the scan's report dispatch, --format validation, the -f help text, noir list formats, and the four shell completion generators. A format joins all of them by annotating its builder class — the annotation is the only place its name, description and renderer are written down.

Constants

DEFAULT = "plain"

The format used when -f is absent, and the fallback for a value that reached the runner without passing validation (library callers construct the options hash directly).

ENTRIES = begin {% if true %} [ {% for builder in OutputBuilder.all_subclasses .select(&.annotation(Noir::OutputFormat)) .sort_by do |sub| (sub.annotation(Noir::OutputFormat))[:order] end %} {% format = builder.annotation(Noir::OutputFormat) %} Entry.new({{ format[:name] }}, {{ format[:description] }}, {{ !!format[:structured] }}), {% end %} ] of Entry {% end %} end

Ordered by the annotation's order:, so help output and noir list formats group related formats (structured → command → spec → only-* → diagram) instead of following require order.

NAMES = ENTRIES.map(&.name)
STRUCTURED_NAMES = ENTRIES.select(&.structured).map(&.name).to_set

Formats whose output is a document with an envelope, so "no endpoints" must still render — {"endpoints":[],"passive_results":[]}, a "paths": {} OAS document, a header-only Markdown table, a full HTML shell. Downstream consumers (jq pipelines, Postman importers, CI report uploaders) treat empty or missing output as a hard error.

Command-list and line-list formats (curl, httpie, powershell, adb, simctl, only-*) and plain are deliberately not structured: they have no envelope, so emitting nothing is their correct empty output.

Declared on the builder as structured: true. This used to be a hand-maintained Set in src/cli/commands/scan.cr — a subset of a derived list, which is the shape that silently rots: a new structured format that nobody remembered to add there emitted nothing at all on a zero-endpoint scan, with no error and no failing spec.

Class methods

help_text(indent : String = " ") : String

-f help block for the CLI option parser, indented to sit under the flag's description.

Source
known?(name : String) : Bool
Source
render(format : String, options : Hash(String, YAML::Any), endpoints : Array(Endpoint), passive_results : Array(PassiveScanResult), errors : Array(AnalyzerFailure) = [] of AnalyzerFailure) : Bool

Renders the report in format, returning false when no builder claims that name so the caller can fall back to DEFAULT.

Each when branch instantiates one concrete builder, so the call is resolved per class rather than through the OutputBuilder base type — which is what lets builders keep their own print overloads.

errors reaches the builder as a property rather than a print argument, so the formats with nowhere to put it (every command and only-* format) need no signature change. It defaults to empty for callers that render a report they did not scan for.

Source
structured?(name : String) : Bool

Whether name must still be rendered when a scan found no endpoints.

Source

Nested types