refactor md rendering
This commit is contained in:
parent
a6332946e5
commit
ab279fadb9
192
markdown.go
192
markdown.go
@ -8,35 +8,24 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func mdTextToString(text Txt) (string, error) {
|
func mdTextToString(text Txt) string {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
w := newMDWriter(&b, true)
|
renderMDText(&b, text)
|
||||||
renderMDText(w, text)
|
return b.String()
|
||||||
w.flush()
|
|
||||||
if w.err != nil {
|
|
||||||
return "", w.err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.String(), nil
|
func mdCellTexts(rows []TableRow) [][]string {
|
||||||
}
|
|
||||||
|
|
||||||
func mdCellTexts(rows []TableRow) ([][]string, error) {
|
|
||||||
var texts [][]string
|
var texts [][]string
|
||||||
for _, row := range rows {
|
for _, row := range rows {
|
||||||
var rowTexts []string
|
var rowTexts []string
|
||||||
for _, cell := range row.cells {
|
for _, cell := range row.cells {
|
||||||
txt, err := mdTextToString(cell.text)
|
rowTexts = append(rowTexts, mdTextToString(cell.text))
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
rowTexts = append(rowTexts, txt)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
texts = append(texts, rowTexts)
|
texts = append(texts, rowTexts)
|
||||||
}
|
}
|
||||||
|
|
||||||
return texts, nil
|
return texts
|
||||||
}
|
}
|
||||||
|
|
||||||
func mdEnsureHeaderTexts(h []string) []string {
|
func mdEnsureHeaderTexts(h []string) []string {
|
||||||
@ -52,11 +41,11 @@ func mdEnsureHeaderTexts(h []string) []string {
|
|||||||
return hh
|
return hh
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDText(w writer, text Txt) {
|
func renderMDText(w io.Writer, text Txt) {
|
||||||
if len(text.cat) > 0 {
|
if len(text.cat) > 0 {
|
||||||
for i, tc := range text.cat {
|
for i, tc := range text.cat {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
w.write(" ")
|
write(w, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMDText(w, tc)
|
renderMDText(w, tc)
|
||||||
@ -70,73 +59,70 @@ func renderMDText(w writer, text Txt) {
|
|||||||
text.link = editString(text.link, singleLine())
|
text.link = editString(text.link, singleLine())
|
||||||
text.link = editString(text.link, escapeMarkdown())
|
text.link = editString(text.link, escapeMarkdown())
|
||||||
if text.bold {
|
if text.bold {
|
||||||
w.write("**")
|
write(w, "**")
|
||||||
}
|
}
|
||||||
|
|
||||||
if text.italic {
|
if text.italic {
|
||||||
w.write("_")
|
write(w, "_")
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if text.italic {
|
if text.italic {
|
||||||
w.write("_")
|
write(w, "_")
|
||||||
}
|
}
|
||||||
|
|
||||||
if text.bold {
|
if text.bold {
|
||||||
w.write("**")
|
write(w, "**")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if text.link != "" {
|
if text.link != "" {
|
||||||
if text.text != "" {
|
if text.text != "" {
|
||||||
w.write("[")
|
write(w, "[")
|
||||||
w.write(text.text)
|
write(w, text.text)
|
||||||
w.write("](")
|
write(w, "](")
|
||||||
w.write(text.link)
|
write(w, text.link)
|
||||||
w.write(")")
|
write(w, ")")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.write(text.link)
|
write(w, text.link)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.write(text.text)
|
write(w, text.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDTitle(w writer, e Entry) {
|
func renderMDTitle(w io.Writer, e Entry) {
|
||||||
hashes := e.titleLevel + 1
|
hashes := e.titleLevel + 1
|
||||||
if hashes > 6 {
|
if hashes > 6 {
|
||||||
hashes = 6
|
hashes = 6
|
||||||
}
|
}
|
||||||
|
|
||||||
w.write(timesn("#", hashes), " ")
|
write(w, timesn("#", hashes), " ")
|
||||||
renderMDText(w, e.text)
|
renderMDText(w, e.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDParagraphIndent(w writer, e Entry) {
|
func renderMDParagraphIndent(w io.Writer, e Entry) {
|
||||||
txt, err := mdTextToString(e.text)
|
var f func() (io.Writer, error)
|
||||||
if err != nil {
|
|
||||||
w.setErr(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
indentFirst := e.indent + e.indentFirst
|
|
||||||
if e.wrapWidth > 0 {
|
if e.wrapWidth > 0 {
|
||||||
txt = editString(txt, wrapIndent(indentFirst, e.indent, e.wrapWidth, e.wrapWidth))
|
indentFirst := e.indent + e.indentFirst
|
||||||
} else {
|
w, f = writeWith(w, wrapIndent(indentFirst, e.indent, e.wrapWidth, e.wrapWidth))
|
||||||
// txt = editString(txt, indent(indentFirst, e.indent))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
w.write(txt)
|
renderMDText(w, e.text)
|
||||||
|
if f != nil {
|
||||||
|
f()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDParagraph(w writer, e Entry) {
|
func renderMDParagraph(w io.Writer, e Entry) {
|
||||||
e.indent = 0
|
e.indent = 0
|
||||||
e.indentFirst = 0
|
e.indentFirst = 0
|
||||||
renderMDParagraphIndent(w, e)
|
renderMDParagraphIndent(w, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDList(w writer, e Entry) {
|
func renderMDList(w io.Writer, e Entry) {
|
||||||
e.indent = 2
|
e.indent = 2
|
||||||
e.indentFirst = -2
|
e.indentFirst = -2
|
||||||
if e.wrapWidth > 2 {
|
if e.wrapWidth > 2 {
|
||||||
@ -145,16 +131,16 @@ func renderMDList(w writer, e Entry) {
|
|||||||
|
|
||||||
for i, item := range e.items {
|
for i, item := range e.items {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
w.write("\n")
|
write(w, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
w.write("- ")
|
write(w, "- ")
|
||||||
p := itemToParagraph(e, item.text)
|
p := itemToParagraph(e, item.text)
|
||||||
renderMDParagraphIndent(w, p)
|
renderMDParagraphIndent(w, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDNumberedList(w writer, e Entry) {
|
func renderMDNumberedList(w io.Writer, e Entry) {
|
||||||
maxDigits := numDigits(len(e.items))
|
maxDigits := numDigits(len(e.items))
|
||||||
e.indent = maxDigits + 2
|
e.indent = maxDigits + 2
|
||||||
e.indentFirst = 0 - maxDigits - 2
|
e.indentFirst = 0 - maxDigits - 2
|
||||||
@ -164,16 +150,16 @@ func renderMDNumberedList(w writer, e Entry) {
|
|||||||
|
|
||||||
for i, item := range e.items {
|
for i, item := range e.items {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
w.write("\n")
|
write(w, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
w.write(padRight(fmt.Sprintf("%d.", i+1), maxDigits+2))
|
write(w, padRight(fmt.Sprintf("%d.", i+1), maxDigits+2))
|
||||||
p := itemToParagraph(e, item.text)
|
p := itemToParagraph(e, item.text)
|
||||||
renderMDParagraphIndent(w, p)
|
renderMDParagraphIndent(w, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDDefinitions(w writer, e Entry) {
|
func renderMDDefinitions(w io.Writer, e Entry) {
|
||||||
for _, d := range e.definitions {
|
for _, d := range e.definitions {
|
||||||
e.items = append(
|
e.items = append(
|
||||||
e.items,
|
e.items,
|
||||||
@ -184,7 +170,7 @@ func renderMDDefinitions(w writer, e Entry) {
|
|||||||
renderMDList(w, e)
|
renderMDList(w, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDNumberedDefinitions(w writer, e Entry) {
|
func renderMDNumberedDefinitions(w io.Writer, e Entry) {
|
||||||
for _, d := range e.definitions {
|
for _, d := range e.definitions {
|
||||||
e.items = append(
|
e.items = append(
|
||||||
e.items,
|
e.items,
|
||||||
@ -195,25 +181,15 @@ func renderMDNumberedDefinitions(w writer, e Entry) {
|
|||||||
renderMDNumberedList(w, e)
|
renderMDNumberedList(w, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDTable(w writer, e Entry) {
|
func renderMDTable(w io.Writer, e Entry) {
|
||||||
e.rows = normalizeTable(e.rows)
|
e.rows = normalizeTable(e.rows)
|
||||||
e.rows = ensureHeader(e.rows)
|
e.rows = ensureHeader(e.rows)
|
||||||
if len(e.rows) == 0 || len(e.rows[0].cells) == 0 {
|
if len(e.rows) == 0 || len(e.rows[0].cells) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
headerTexts, err := mdCellTexts(e.rows[:1])
|
headerTexts := mdCellTexts(e.rows[:1])
|
||||||
if err != nil {
|
cellTexts := mdCellTexts(e.rows[1:])
|
||||||
w.setErr(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cellTexts, err := mdCellTexts(e.rows[1:])
|
|
||||||
if err != nil {
|
|
||||||
w.setErr(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
headerTexts[0] = mdEnsureHeaderTexts(headerTexts[0])
|
headerTexts[0] = mdEnsureHeaderTexts(headerTexts[0])
|
||||||
columns := columnWidths(headerTexts)
|
columns := columnWidths(headerTexts)
|
||||||
cellColumns := columnWidths(cellTexts)
|
cellColumns := columnWidths(cellTexts)
|
||||||
@ -225,66 +201,66 @@ func renderMDTable(w writer, e Entry) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
w.write("|")
|
write(w, "|")
|
||||||
for i, h := range headerTexts[0] {
|
for i, h := range headerTexts[0] {
|
||||||
w.write(" ", padRight(h, columns[i]))
|
write(w, " ", padRight(h, columns[i]))
|
||||||
w.write(" |")
|
write(w, " |")
|
||||||
}
|
}
|
||||||
|
|
||||||
w.write("\n|")
|
write(w, "\n|")
|
||||||
for _, c := range columns {
|
for _, c := range columns {
|
||||||
w.write(timesn("-", c+1))
|
write(w, timesn("-", c+1))
|
||||||
w.write("-|")
|
write(w, "-|")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, row := range cellTexts {
|
for _, row := range cellTexts {
|
||||||
w.write("\n|")
|
write(w, "\n|")
|
||||||
for i, cell := range row {
|
for i, cell := range row {
|
||||||
w.write(" ", padRight(cell, columns[i]))
|
write(w, " ", padRight(cell, columns[i]))
|
||||||
w.write(" |")
|
write(w, " |")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDCode(w writer, e Entry) {
|
func renderMDCode(w io.Writer, e Entry) {
|
||||||
w.write("```\n")
|
write(w, "```\n")
|
||||||
w.write(e.text.text)
|
write(w, e.text.text)
|
||||||
w.write("\n```")
|
write(w, "\n```")
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDMultiple(w writer, s SyntaxItem) {
|
func renderMDMultiple(w io.Writer, s SyntaxItem) {
|
||||||
s.topLevel = false
|
s.topLevel = false
|
||||||
s.multiple = false
|
s.multiple = false
|
||||||
renderMDSyntaxItem(w, s)
|
renderMDSyntaxItem(w, s)
|
||||||
w.write("...")
|
write(w, "...")
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDRequired(w writer, s SyntaxItem) {
|
func renderMDRequired(w io.Writer, s SyntaxItem) {
|
||||||
s.delimited = true
|
s.delimited = true
|
||||||
s.topLevel = false
|
s.topLevel = false
|
||||||
s.required = false
|
s.required = false
|
||||||
w.write("<")
|
write(w, "<")
|
||||||
renderMDSyntaxItem(w, s)
|
renderMDSyntaxItem(w, s)
|
||||||
w.write(">")
|
write(w, ">")
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDOptional(w writer, s SyntaxItem) {
|
func renderMDOptional(w io.Writer, s SyntaxItem) {
|
||||||
s.delimited = true
|
s.delimited = true
|
||||||
s.topLevel = false
|
s.topLevel = false
|
||||||
s.optional = false
|
s.optional = false
|
||||||
w.write("[")
|
write(w, "[")
|
||||||
renderMDSyntaxItem(w, s)
|
renderMDSyntaxItem(w, s)
|
||||||
w.write("]")
|
write(w, "]")
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDSequence(w writer, s SyntaxItem) {
|
func renderMDSequence(w io.Writer, s SyntaxItem) {
|
||||||
if !s.delimited && !s.topLevel {
|
if !s.delimited && !s.topLevel {
|
||||||
w.write("(")
|
write(w, "(")
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, item := range s.sequence {
|
for i, item := range s.sequence {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
w.write(" ")
|
write(w, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
item.delimited = false
|
item.delimited = false
|
||||||
@ -292,13 +268,13 @@ func renderMDSequence(w writer, s SyntaxItem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !s.delimited && !s.topLevel {
|
if !s.delimited && !s.topLevel {
|
||||||
w.write(")")
|
write(w, ")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDChoice(w writer, s SyntaxItem) {
|
func renderMDChoice(w io.Writer, s SyntaxItem) {
|
||||||
if !s.delimited && !s.topLevel {
|
if !s.delimited && !s.topLevel {
|
||||||
w.write("(")
|
write(w, "(")
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, item := range s.choice {
|
for i, item := range s.choice {
|
||||||
@ -308,7 +284,7 @@ func renderMDChoice(w writer, s SyntaxItem) {
|
|||||||
separator = "\n"
|
separator = "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
w.write(separator)
|
write(w, separator)
|
||||||
}
|
}
|
||||||
|
|
||||||
item.delimited = false
|
item.delimited = false
|
||||||
@ -316,15 +292,17 @@ func renderMDChoice(w writer, s SyntaxItem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !s.delimited && !s.topLevel {
|
if !s.delimited && !s.topLevel {
|
||||||
w.write(")")
|
write(w, ")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDSymbol(w writer, s SyntaxItem) {
|
func renderMDSymbol(w io.Writer, s SyntaxItem) {
|
||||||
w.write(editString(s.symbol, escapeMarkdown()))
|
w, f := writeWith(w, escapeMarkdown())
|
||||||
|
write(w, s.symbol)
|
||||||
|
f()
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDSyntaxItem(w writer, s SyntaxItem) {
|
func renderMDSyntaxItem(w io.Writer, s SyntaxItem) {
|
||||||
switch {
|
switch {
|
||||||
|
|
||||||
// foo...
|
// foo...
|
||||||
@ -353,23 +331,19 @@ func renderMDSyntaxItem(w writer, s SyntaxItem) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMDSyntax(w writer, e Entry) {
|
func renderMDSyntax(w io.Writer, e Entry) {
|
||||||
s := e.syntax
|
s := e.syntax
|
||||||
s.topLevel = true
|
s.topLevel = true
|
||||||
w.write("```\n")
|
write(w, "```\n")
|
||||||
renderMDSyntaxItem(w, s)
|
renderMDSyntaxItem(w, s)
|
||||||
w.write("\n```")
|
write(w, "\n```")
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderMarkdown(out io.Writer, d Document) error {
|
func renderMarkdown(out io.Writer, d Document) error {
|
||||||
w := newMDWriter(out, false)
|
w, f := writeWith(out, mdNBSP(), errorHandler)
|
||||||
for i, e := range d.entries {
|
for i, e := range d.entries {
|
||||||
if err := w.error(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
w.write("\n\n")
|
write(w, "\n\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
switch e.typ {
|
switch e.typ {
|
||||||
@ -397,9 +371,9 @@ func renderMarkdown(out io.Writer, d Document) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(d.entries) > 0 {
|
if len(d.entries) > 0 {
|
||||||
w.write("\n")
|
write(w, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
w.flush()
|
_, err := f()
|
||||||
return w.err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user