From 9eee4b13c313106a71c7c8ebbb55b7d42beac2c2 Mon Sep 17 00:00:00 2001 From: Christian Muehlhaeuser Date: Tue, 26 Nov 2019 04:21:22 +0100 Subject: [PATCH] Table rendering (#40) Renders markdown tables. --- elements.go | 19 ++++++++++++----- go.mod | 1 + go.sum | 6 ++++++ gold.go | 27 +++++++++++++++++++----- table.go | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 table.go diff --git a/elements.go b/elements.go index d8d235f..58c477a 100644 --- a/elements.go +++ b/elements.go @@ -12,10 +12,15 @@ type ElementRenderer interface { Render(w io.Writer, node *bf.Node, tr *TermRenderer) error } +type ElementFinisher interface { + Finish(w io.Writer, node *bf.Node, tr *TermRenderer) error +} + type Element struct { Entering string Exiting string Renderer ElementRenderer + Finisher ElementFinisher } func (tr *TermRenderer) NewElement(node *bf.Node) Element { @@ -147,18 +152,22 @@ func (tr *TermRenderer) NewElement(node *bf.Node) Element { case bf.Table: return Element{ Entering: "\n", - Exiting: "\n", + Renderer: &TableElement{}, + Finisher: &TableElement{}, } case bf.TableCell: - return Element{} + return Element{ + Renderer: &TableCellElement{}, + } case bf.TableHead: - return Element{} + return Element{ + Finisher: &TableHeadElement{}, + } case bf.TableBody: return Element{} case bf.TableRow: return Element{ - Entering: "\n", - Exiting: "\n", + Finisher: &TableRowElement{}, } default: diff --git a/go.mod b/go.mod index 8d9a62c..f3b1e66 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/mattn/go-isatty v0.0.10 github.com/microcosm-cc/bluemonday v1.0.2 github.com/muesli/go-wordwrap v1.0.1-0.20191125090158-10bc5504e2a8 + github.com/olekukonko/tablewriter v0.0.3 github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/spf13/cobra v0.0.5 gopkg.in/russross/blackfriday.v2 v2.0.0 diff --git a/go.sum b/go.sum index 4207938..f6663f1 100644 --- a/go.sum +++ b/go.sum @@ -49,6 +49,12 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/muesli/go-wordwrap v1.0.1-0.20191125090158-10bc5504e2a8 h1:pkJGPjqhekH0hq/lJABlh5EhzU7eU/+VdFq9ZMOae2E= github.com/muesli/go-wordwrap v1.0.1-0.20191125090158-10bc5504e2a8/go.mod h1:isHWaQQfvQ38DUiq7ugbuPZowGJ+9gPmACGc3tDUN4M= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= +github.com/mattn/go-runewidth v0.0.6 h1:V2iyH+aX9C5fsYCpK60U8BYIvmhqxuOL3JZcqc1NB7k= +github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/olekukonko/tablewriter v0.0.3 h1:i0LBnzgiChAWHJYTQAZJDOgf8MNxAVYZJ2m63SIDimI= +github.com/olekukonko/tablewriter v0.0.3/go.mod h1:YZeBtGzYYEsCHp2LST/u/0NDwGkRoBtmn1cIWCJiS6M= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= diff --git a/gold.go b/gold.go index 7b427f6..547e9e4 100644 --- a/gold.go +++ b/gold.go @@ -10,6 +10,7 @@ import ( "os" "github.com/microcosm-cc/bluemonday" + "github.com/olekukonko/tablewriter" bf "gopkg.in/russross/blackfriday.v2" ) @@ -17,9 +18,16 @@ var ( stripper = bluemonday.StrictPolicy() ) +type TableData struct { + table *tablewriter.Table + tableHeader []string + tableCell []string +} + type TermRenderer struct { - BaseURL string - style map[StyleType]*ElementStyle + BaseURL string + style map[StyleType]*ElementStyle + tableData TableData } func Render(in string, stylePath string) ([]byte, error) { @@ -88,10 +96,19 @@ func (tr *TermRenderer) RenderNode(w io.Writer, node *bf.Node, entering bool) bf if !entering && e.Exiting != "" { fmt.Fprintf(w, "%s", e.Exiting) } - if isChild(node) { + + if !entering { + if e.Finisher != nil { + err := e.Finisher.Finish(w, node, tr) + if err != nil { + fmt.Println(err) + return bf.Terminate + } + } return bf.GoToNext } - if !entering { + + if isChild(node) { return bf.GoToNext } @@ -117,7 +134,7 @@ func isChild(node *bf.Node) bool { return false } switch node.Parent.Type { - case bf.Heading, bf.Link, bf.Image, bf.Emph, bf.Strong: + case bf.Heading, bf.Link, bf.Image, bf.TableCell, bf.Emph, bf.Strong: return true default: return false diff --git a/table.go b/table.go new file mode 100644 index 0000000..522be0c --- /dev/null +++ b/table.go @@ -0,0 +1,61 @@ +package gold + +import ( + "io" + + "github.com/olekukonko/tablewriter" + bf "gopkg.in/russross/blackfriday.v2" +) + +type TableElement struct { +} + +type TableRowElement struct { +} + +type TableHeadElement struct { +} + +type TableCellElement struct { +} + +func (e *TableElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error { + tr.tableData.table = tablewriter.NewWriter(w) + return nil +} + +func (e *TableElement) Finish(w io.Writer, node *bf.Node, tr *TermRenderer) error { + tr.tableData.table.Render() + tr.tableData = TableData{} + return nil +} + +func (e *TableRowElement) Finish(w io.Writer, node *bf.Node, tr *TermRenderer) error { + tr.tableData.table.Append(tr.tableData.tableCell) + tr.tableData.tableCell = []string{} + return nil +} + +func (e *TableHeadElement) Finish(w io.Writer, node *bf.Node, tr *TermRenderer) error { + tr.tableData.table.SetHeader(tr.tableData.tableHeader) + tr.tableData.tableHeader = []string{} + return nil +} + +func (e *TableCellElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error { + s := "" + n := node.FirstChild + for n != nil { + s += string(n.Literal) + s += string(n.LinkData.Destination) + n = n.Next + } + + if node.Parent.Parent.Type == bf.TableHead { + tr.tableData.tableHeader = append(tr.tableData.tableHeader, s) + } else { + tr.tableData.tableCell = append(tr.tableData.tableCell, s) + } + + return nil +}