package comment
import (
"bytes"
"fmt"
"strings"
)
type mdPrinter struct {
*Printer
headingPrefix string
raw bytes .Buffer
}
func (p *Printer ) Markdown (d *Doc ) []byte {
mp := &mdPrinter {
Printer : p ,
headingPrefix : strings .Repeat ("#" , p .headingLevel ()) + " " ,
}
var out bytes .Buffer
for i , x := range d .Content {
if i > 0 {
out .WriteByte ('\n' )
}
mp .block (&out , x )
}
return out .Bytes ()
}
func (p *mdPrinter ) block (out *bytes .Buffer , x Block ) {
switch x := x .(type ) {
default :
fmt .Fprintf (out , "?%T" , x )
case *Paragraph :
p .text (out , x .Text )
out .WriteString ("\n" )
case *Heading :
out .WriteString (p .headingPrefix )
p .text (out , x .Text )
if id := p .headingID (x ); id != "" {
out .WriteString (" {#" )
out .WriteString (id )
out .WriteString ("}" )
}
out .WriteString ("\n" )
case *Code :
md := x .Text
for md != "" {
var line string
line , md , _ = strings .Cut (md , "\n" )
if line != "" {
out .WriteString ("\t" )
out .WriteString (line )
}
out .WriteString ("\n" )
}
case *List :
loose := x .BlankBetween ()
for i , item := range x .Items {
if i > 0 && loose {
out .WriteString ("\n" )
}
if n := item .Number ; n != "" {
out .WriteString (" " )
out .WriteString (n )
out .WriteString (". " )
} else {
out .WriteString (" - " )
}
for i , blk := range item .Content {
const fourSpace = " "
if i > 0 {
out .WriteString ("\n" + fourSpace )
}
p .text (out , blk .(*Paragraph ).Text )
out .WriteString ("\n" )
}
}
}
}
func (p *mdPrinter ) text (out *bytes .Buffer , x []Text ) {
p .raw .Reset ()
p .rawText (&p .raw , x )
line := bytes .TrimSpace (p .raw .Bytes ())
if len (line ) == 0 {
return
}
switch line [0 ] {
case '+' , '-' , '*' , '#' :
out .WriteByte ('\\' )
case '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' :
i := 1
for i < len (line ) && '0' <= line [i ] && line [i ] <= '9' {
i ++
}
if i < len (line ) && (line [i ] == '.' || line [i ] == ')' ) {
out .Write (line [:i ])
out .WriteByte ('\\' )
line = line [i :]
}
}
out .Write (line )
}
func (p *mdPrinter ) rawText (out *bytes .Buffer , x []Text ) {
for _ , t := range x {
switch t := t .(type ) {
case Plain :
p .escape (out , string (t ))
case Italic :
out .WriteString ("*" )
p .escape (out , string (t ))
out .WriteString ("*" )
case *Link :
out .WriteString ("[" )
p .rawText (out , t .Text )
out .WriteString ("](" )
out .WriteString (t .URL )
out .WriteString (")" )
case *DocLink :
url := p .docLinkURL (t )
if url != "" {
out .WriteString ("[" )
}
p .rawText (out , t .Text )
if url != "" {
out .WriteString ("](" )
url = strings .ReplaceAll (url , "(" , "%28" )
url = strings .ReplaceAll (url , ")" , "%29" )
out .WriteString (url )
out .WriteString (")" )
}
}
}
}
func (p *mdPrinter ) escape (out *bytes .Buffer , s string ) {
start := 0
for i := 0 ; i < len (s ); i ++ {
switch s [i ] {
case '\n' :
out .WriteString (s [start :i ])
out .WriteByte (' ' )
start = i + 1
continue
case '`' , '_' , '*' , '[' , '<' , '\\' :
out .WriteString (s [start :i ])
out .WriteByte ('\\' )
out .WriteByte (s [i ])
start = i + 1
}
}
out .WriteString (s [start :])
}
The pages are generated with Golds v0.7.3 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .