Markdown descriptions
A multi-line swagger:description normally folds its body with the Option B
rule: contiguous prose lines up to the first blank line, each trimmed. That’s
right for a paragraph of prose, but it destroys markdown — a blank line ends the
description, and leading indentation and table pipes are stripped. So a table or
a multi-paragraph body never survives the trip into the spec.
Ending the annotation line with a lone | — the YAML literal block-scalar
marker — opts the body into verbatim capture instead. Everything below is
taken exactly as written — blank lines, indentation, table pipes and --- all
preserved — until the next annotation or the end of the comment. It is opt-in
per annotation; a plain swagger:description (no |) keeps the Option B
behaviour unchanged.
Plain prose vs a verbatim body
These two models carry the same markdown body. The first uses an ordinary
annotation; the second adds the | marker:
// Plain uses an ordinary description annotation.
//
// swagger:description
// Option B folds prose up to the first blank line, so only this sentence
// survives — the markdown table below never reaches the spec.
//
// | name | purpose |
// |------|---------|
// | foo | bars |
//
// swagger:model Plain
type Plain struct {
Name string `json:"name"`
}Full source: docs/examples/shaping/markdowndesc/markdowndesc.go
// Markdown opts into a verbatim body with the literal block marker.
//
// swagger:description |
// The body is captured **verbatim** — pipes, blank lines and all:
//
// | name | purpose |
// |------|---------|
// | foo | bars |
//
// - point one
// - point two
//
// swagger:model Markdown
type Markdown struct {
// Name of the widget.
//
// swagger:description |
// The name must be:
//
// 1. unique
// 2. lowercase
Name string `json:"name"`
}Full source: docs/examples/shaping/markdowndesc/markdowndesc.go
The emitted descriptions diverge sharply:
{
"description": "Option B folds prose up to the first blank line, so only this sentence\nsurvives — the markdown table below never reaches the spec.",
"type": "object",
"title": "Plain uses an ordinary description annotation.",
"properties": {
"name": {
"type": "string",
"x-go-name": "Name"
}
},
"x-go-package": "github.com/go-openapi/codescan/docs/examples/shaping/markdowndesc"
}
Full source: docs/examples/shaping/markdowndesc/testdata/plain.json
{
"description": "The body is captured **verbatim** — pipes, blank lines and all:\n\n| name | purpose |\n|------|---------|\n| foo | bars |\n\n- point one\n- point two",
"type": "object",
"title": "Markdown opts into a verbatim body with the literal block marker.",
"properties": {
"name": {
"description": "The name must be:\n\n 1. unique\n 2. lowercase",
"type": "string",
"x-go-name": "Name"
}
},
"x-go-package": "github.com/go-openapi/codescan/docs/examples/shaping/markdowndesc"
}
Full source: docs/examples/shaping/markdowndesc/testdata/markdown.json
- Option B stops at the first blank line. The plain model’s description is just the opening sentence — the table that follows the blank line is dropped entirely (the original go-swagger#3211 grievance).
- The
|body is captured whole. Table leading pipes, the significant blank line, and the bullet list after it all ride through verbatim. - The marker never leaks. The trailing
|, theswagger:descriptionline itself, and the single godoc//convention space per line are all stripped; interior indentation and trailing whitespace (markdown hard breaks) are kept. - The title is unaffected. It still comes from the godoc preamble above the annotation — only the description body becomes verbatim.
It works on a field description just the same — the name property above
keeps the indentation of its ordered list ( 1. unique).
Where the block ends
The literal block runs until the next annotation at the start of a line, or
the end of the doc comment. In the examples above, the trailing
swagger:model Widget line closes the block.
A swagger: token mid-line is ordinary prose and stays in the body — only a
line that begins with an annotation terminates. Indentation doesn’t shield
such a line, though: the comment prefix and leading whitespace are stripped
before the check, so a line-leading swagger: inside an indented markdown code
block still ends the block. Keep annotation-looking lines out of the verbatim
body, or place them before the | annotation.
Note
This reframes go-swagger#3211:
markdown is authored explicitly via swagger:description |, never recovered
from ambient godoc prose. A plain doc comment stays plain — godoc and the spec
keep their separate conventions.
What’s next
- Overriding titles & descriptions
— the
swagger:title/swagger:descriptionoverrides this builds on. - Single-line comments as descriptions — route short comments to the description without a marker.