Bump cpuguy83/go-md2man to v1.0.8

The biggest motivation for this is proper table rendering; in the
old version it was broken so tables were not rendered at al
(i.e. anything that was put into table was lost, for example,
description of LOG_* log levels in dockerd(8) page).

This also fixes lists, including nested lists. This fixes the
description of behavior in docker-cp(1) which is rendered as a tree:

BEFORE:

```
      Assuming a path separator of /, a first argument of SRC_PATH and second
       argument of DEST_PATH, the behavior is as follows:

       · SRC_PATH specifies a file

       · DEST_PATH does not exist

       · the file is saved to a file created at DEST_PATH

       · DEST_PATH does not exist and ends with /

       · Error condition: the destination directory must exist.

...
```

AFTER:
```
      Assuming a path separator of /, a first argument of SRC_PATH and second
       argument of DEST_PATH, the behavior is as follows:

              · SRC_PATH specifies a file

                · DEST_PATH does not exist

                  · the file is saved to a file created at DEST_PATH

                · DEST_PATH does not exist and ends with /

                  · Error condition: the destination directory must exist.

...
```

Manually checking the diff between the man pages generated by the old
and the new version, there are no changes other than the indentation
(.RS/.RE) for lists, and proper formatting for tables. Formatted man
pages also look decent, nothing seems broken.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
Kir Kolyshkin 2018-02-12 11:41:18 -08:00
parent dcd62981c4
commit 6566f5ff2c
5 changed files with 49 additions and 42 deletions

View File

@ -2,7 +2,7 @@ github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c
github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109
github.com/containerd/continuity 35d55c5e8dd23b32037d56cf97174aff3efdfa83
github.com/coreos/etcd v3.2.1
github.com/cpuguy83/go-md2man a65d4d2de4d5f7c74868dfa9b202a3c8be315aaa
github.com/cpuguy83/go-md2man v1.0.8
github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76
github.com/docker/distribution edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c
github.com/docker/docker e11bf870a3170a1d2b1e177a0d7ccc66200bd643

View File

@ -12,7 +12,10 @@ Uses blackfriday to process markdown into man pages.
### How to contribute
We use [govend](https://github.com/govend/govend) for vendoring Go packages.
We use [dep](https://github.com/golang/dep/) for vendoring Go packages.
See dep documentation for how to update.
How to update dependencies: `govend -v -u --prune`
### TODO
- Needs oh so much testing love
- Look into blackfriday's 2.0 API

View File

@ -24,7 +24,7 @@ func main() {
os.Exit(1)
}
}
defer inFile.Close()
defer inFile.Close() // nolint: errcheck
doc, err := ioutil.ReadAll(inFile)
if err != nil {
@ -41,7 +41,7 @@ func main() {
fmt.Println(err)
os.Exit(1)
}
defer outFile.Close()
defer outFile.Close() // nolint: errcheck
}
_, err = outFile.Write(out)
if err != nil {

View File

@ -4,6 +4,7 @@ import (
"github.com/russross/blackfriday"
)
// Render converts a markdown document into a roff formatted document.
func Render(doc []byte) []byte {
renderer := RoffRenderer(0)
extensions := 0

View File

@ -9,10 +9,12 @@ import (
"github.com/russross/blackfriday"
)
type roffRenderer struct{}
var listCounter int
type roffRenderer struct {
ListCounters []int
}
// RoffRenderer creates a new blackfriday Renderer for generating roff documents
// from markdown
func RoffRenderer(flags int) blackfriday.Renderer {
return &roffRenderer{}
}
@ -55,7 +57,7 @@ func (r *roffRenderer) BlockQuote(out *bytes.Buffer, text []byte) {
out.WriteString("\n.RE\n")
}
func (r *roffRenderer) BlockHtml(out *bytes.Buffer, text []byte) {
func (r *roffRenderer) BlockHtml(out *bytes.Buffer, text []byte) { // nolint: golint
out.Write(text)
}
@ -86,19 +88,20 @@ func (r *roffRenderer) HRule(out *bytes.Buffer) {
func (r *roffRenderer) List(out *bytes.Buffer, text func() bool, flags int) {
marker := out.Len()
if flags&blackfriday.LIST_TYPE_ORDERED != 0 {
listCounter = 1
}
r.ListCounters = append(r.ListCounters, 1)
out.WriteString("\n.RS\n")
if !text() {
out.Truncate(marker)
return
}
r.ListCounters = r.ListCounters[:len(r.ListCounters)-1]
out.WriteString("\n.RE\n")
}
func (r *roffRenderer) ListItem(out *bytes.Buffer, text []byte, flags int) {
if flags&blackfriday.LIST_TYPE_ORDERED != 0 {
out.WriteString(fmt.Sprintf(".IP \"%3d.\" 5\n", listCounter))
listCounter += 1
out.WriteString(fmt.Sprintf(".IP \"%3d.\" 5\n", r.ListCounters[len(r.ListCounters)-1]))
r.ListCounters[len(r.ListCounters)-1]++
} else {
out.WriteString(".IP \\(bu 2\n")
}
@ -118,11 +121,24 @@ func (r *roffRenderer) Paragraph(out *bytes.Buffer, text func() bool) {
}
}
// TODO: This might now work
func (r *roffRenderer) Table(out *bytes.Buffer, header []byte, body []byte, columnData []int) {
out.WriteString(".TS\nallbox;\n")
out.WriteString("\n.TS\nallbox;\n")
maxDelims := 0
lines := strings.Split(strings.TrimRight(string(header), "\n")+"\n"+strings.TrimRight(string(body), "\n"), "\n")
for _, w := range lines {
curDelims := strings.Count(w, "\t")
if curDelims > maxDelims {
maxDelims = curDelims
}
}
out.Write([]byte(strings.Repeat("l ", maxDelims+1) + "\n"))
out.Write([]byte(strings.Repeat("l ", maxDelims+1) + ".\n"))
out.Write(header)
if len(header) > 0 {
out.Write([]byte("\n"))
}
out.Write(body)
out.WriteString("\n.TE\n")
}
@ -132,24 +148,30 @@ func (r *roffRenderer) TableRow(out *bytes.Buffer, text []byte) {
out.WriteString("\n")
}
out.Write(text)
out.WriteString("\n")
}
func (r *roffRenderer) TableHeaderCell(out *bytes.Buffer, text []byte, align int) {
if out.Len() > 0 {
out.WriteString(" ")
out.WriteString("\t")
}
out.Write(text)
out.WriteString(" ")
if len(text) == 0 {
text = []byte{' '}
}
out.Write([]byte("\\fB\\fC" + string(text) + "\\fR"))
}
// TODO: This is probably broken
func (r *roffRenderer) TableCell(out *bytes.Buffer, text []byte, align int) {
if out.Len() > 0 {
out.WriteString("\t")
}
if len(text) > 30 {
text = append([]byte("T{\n"), text...)
text = append(text, []byte("\nT}")...)
}
if len(text) == 0 {
text = []byte{' '}
}
out.Write(text)
out.WriteString("\t")
}
func (r *roffRenderer) Footnotes(out *bytes.Buffer, text func() bool) {
@ -196,7 +218,7 @@ func (r *roffRenderer) Link(out *bytes.Buffer, link []byte, title []byte, conten
r.AutoLink(out, link, 0)
}
func (r *roffRenderer) RawHtmlTag(out *bytes.Buffer, tag []byte) {
func (r *roffRenderer) RawHtmlTag(out *bytes.Buffer, tag []byte) { // nolint: golint
out.Write(tag)
}
@ -217,25 +239,6 @@ func (r *roffRenderer) Entity(out *bytes.Buffer, entity []byte) {
out.WriteString(html.UnescapeString(string(entity)))
}
func processFooterText(text []byte) []byte {
text = bytes.TrimPrefix(text, []byte("% "))
newText := []byte{}
textArr := strings.Split(string(text), ") ")
for i, w := range textArr {
if i == 0 {
w = strings.Replace(w, "(", "\" \"", 1)
w = fmt.Sprintf("\"%s\"", w)
} else {
w = fmt.Sprintf(" \"%s\"", w)
}
newText = append(newText, []byte(w)...)
}
newText = append(newText, []byte(" \"\"")...)
return newText
}
func (r *roffRenderer) NormalText(out *bytes.Buffer, text []byte) {
escapeSpecialChars(out, text)
}