...

Source file src/github.com/jedib0t/go-pretty/v6/table/render_html.go

Documentation: github.com/jedib0t/go-pretty/v6/table

     1  package table
     2  
     3  import (
     4  	"fmt"
     5  	"html"
     6  	"strings"
     7  )
     8  
     9  const (
    10  	// DefaultHTMLCSSClass stores the css-class to use when none-provided via
    11  	// SetHTMLCSSClass(cssClass string).
    12  	DefaultHTMLCSSClass = "go-pretty-table"
    13  )
    14  
    15  // RenderHTML renders the Table in HTML format. Example:
    16  //  <table class="go-pretty-table">
    17  //    <thead>
    18  //    <tr>
    19  //      <th align="right">#</th>
    20  //      <th>First Name</th>
    21  //      <th>Last Name</th>
    22  //      <th align="right">Salary</th>
    23  //      <th>&nbsp;</th>
    24  //    </tr>
    25  //    </thead>
    26  //    <tbody>
    27  //    <tr>
    28  //      <td align="right">1</td>
    29  //      <td>Arya</td>
    30  //      <td>Stark</td>
    31  //      <td align="right">3000</td>
    32  //      <td>&nbsp;</td>
    33  //    </tr>
    34  //    <tr>
    35  //      <td align="right">20</td>
    36  //      <td>Jon</td>
    37  //      <td>Snow</td>
    38  //      <td align="right">2000</td>
    39  //      <td>You know nothing, Jon Snow!</td>
    40  //    </tr>
    41  //    <tr>
    42  //      <td align="right">300</td>
    43  //      <td>Tyrion</td>
    44  //      <td>Lannister</td>
    45  //      <td align="right">5000</td>
    46  //      <td>&nbsp;</td>
    47  //    </tr>
    48  //    </tbody>
    49  //    <tfoot>
    50  //    <tr>
    51  //      <td align="right">&nbsp;</td>
    52  //      <td>&nbsp;</td>
    53  //      <td>Total</td>
    54  //      <td align="right">10000</td>
    55  //      <td>&nbsp;</td>
    56  //    </tr>
    57  //    </tfoot>
    58  //  </table>
    59  func (t *Table) RenderHTML() string {
    60  	t.initForRender()
    61  
    62  	var out strings.Builder
    63  	if t.numColumns > 0 {
    64  		out.WriteString("<table class=\"")
    65  		if t.htmlCSSClass != "" {
    66  			out.WriteString(t.htmlCSSClass)
    67  		} else {
    68  			out.WriteString(t.style.HTML.CSSClass)
    69  		}
    70  		out.WriteString("\">\n")
    71  		t.htmlRenderTitle(&out)
    72  		t.htmlRenderRowsHeader(&out)
    73  		t.htmlRenderRows(&out, t.rows, renderHint{})
    74  		t.htmlRenderRowsFooter(&out)
    75  		t.htmlRenderCaption(&out)
    76  		out.WriteString("</table>")
    77  	}
    78  	return t.render(&out)
    79  }
    80  
    81  func (t *Table) htmlGetColStrAndTag(row rowStr, colIdx int, hint renderHint) (string, string) {
    82  	// get the column contents
    83  	var colStr string
    84  	if colIdx < len(row) {
    85  		colStr = row[colIdx]
    86  	}
    87  
    88  	// header uses "th" instead of "td"
    89  	colTagName := "td"
    90  	if hint.isHeaderRow {
    91  		colTagName = "th"
    92  	}
    93  
    94  	return colStr, colTagName
    95  }
    96  
    97  func (t *Table) htmlRenderCaption(out *strings.Builder) {
    98  	if t.caption != "" {
    99  		out.WriteString("  <caption class=\"caption\" style=\"caption-side: bottom;\">")
   100  		out.WriteString(t.caption)
   101  		out.WriteString("</caption>\n")
   102  	}
   103  }
   104  
   105  func (t *Table) htmlRenderColumn(out *strings.Builder, colStr string) {
   106  	if t.style.HTML.EscapeText {
   107  		colStr = html.EscapeString(colStr)
   108  	}
   109  	if t.style.HTML.Newline != "\n" {
   110  		colStr = strings.Replace(colStr, "\n", t.style.HTML.Newline, -1)
   111  	}
   112  	out.WriteString(colStr)
   113  }
   114  
   115  func (t *Table) htmlRenderColumnAttributes(out *strings.Builder, row rowStr, colIdx int, hint renderHint) {
   116  	// determine the HTML "align"/"valign" property values
   117  	align := t.getAlign(colIdx, hint).HTMLProperty()
   118  	vAlign := t.getVAlign(colIdx, hint).HTMLProperty()
   119  	// determine the HTML "class" property values for the colors
   120  	class := t.getColumnColors(colIdx, hint).HTMLProperty()
   121  
   122  	if align != "" {
   123  		out.WriteRune(' ')
   124  		out.WriteString(align)
   125  	}
   126  	if class != "" {
   127  		out.WriteRune(' ')
   128  		out.WriteString(class)
   129  	}
   130  	if vAlign != "" {
   131  		out.WriteRune(' ')
   132  		out.WriteString(vAlign)
   133  	}
   134  }
   135  
   136  func (t *Table) htmlRenderColumnAutoIndex(out *strings.Builder, hint renderHint) {
   137  	if hint.isHeaderRow {
   138  		out.WriteString("    <th>")
   139  		out.WriteString(t.style.HTML.EmptyColumn)
   140  		out.WriteString("</th>\n")
   141  	} else if hint.isFooterRow {
   142  		out.WriteString("    <td>")
   143  		out.WriteString(t.style.HTML.EmptyColumn)
   144  		out.WriteString("</td>\n")
   145  	} else {
   146  		out.WriteString("    <td align=\"right\">")
   147  		out.WriteString(fmt.Sprint(hint.rowNumber))
   148  		out.WriteString("</td>\n")
   149  	}
   150  }
   151  
   152  func (t *Table) htmlRenderRow(out *strings.Builder, row rowStr, hint renderHint) {
   153  	out.WriteString("  <tr>\n")
   154  	for colIdx := 0; colIdx < t.numColumns; colIdx++ {
   155  		// auto-index column
   156  		if colIdx == 0 && t.autoIndex {
   157  			t.htmlRenderColumnAutoIndex(out, hint)
   158  		}
   159  
   160  		colStr, colTagName := t.htmlGetColStrAndTag(row, colIdx, hint)
   161  		// write the row
   162  		out.WriteString("    <")
   163  		out.WriteString(colTagName)
   164  		t.htmlRenderColumnAttributes(out, row, colIdx, hint)
   165  		out.WriteString(">")
   166  		if len(colStr) == 0 {
   167  			out.WriteString(t.style.HTML.EmptyColumn)
   168  		} else {
   169  			t.htmlRenderColumn(out, colStr)
   170  		}
   171  		out.WriteString("</")
   172  		out.WriteString(colTagName)
   173  		out.WriteString(">\n")
   174  	}
   175  	out.WriteString("  </tr>\n")
   176  }
   177  
   178  func (t *Table) htmlRenderRows(out *strings.Builder, rows []rowStr, hint renderHint) {
   179  	if len(rows) > 0 {
   180  		// determine that tag to use based on the type of the row
   181  		rowsTag := "tbody"
   182  		if hint.isHeaderRow {
   183  			rowsTag = "thead"
   184  		} else if hint.isFooterRow {
   185  			rowsTag = "tfoot"
   186  		}
   187  
   188  		var renderedTagOpen, shouldRenderTagClose bool
   189  		for idx, row := range rows {
   190  			hint.rowNumber = idx + 1
   191  			if len(row) > 0 {
   192  				if !renderedTagOpen {
   193  					out.WriteString("  <")
   194  					out.WriteString(rowsTag)
   195  					out.WriteString(">\n")
   196  					renderedTagOpen = true
   197  				}
   198  				t.htmlRenderRow(out, row, hint)
   199  				shouldRenderTagClose = true
   200  			}
   201  		}
   202  		if shouldRenderTagClose {
   203  			out.WriteString("  </")
   204  			out.WriteString(rowsTag)
   205  			out.WriteString(">\n")
   206  		}
   207  	}
   208  }
   209  
   210  func (t *Table) htmlRenderRowsFooter(out *strings.Builder) {
   211  	if len(t.rowsFooter) > 0 {
   212  		t.htmlRenderRows(out, t.rowsFooter, renderHint{isFooterRow: true})
   213  	}
   214  }
   215  
   216  func (t *Table) htmlRenderRowsHeader(out *strings.Builder) {
   217  	if len(t.rowsHeader) > 0 {
   218  		t.htmlRenderRows(out, t.rowsHeader, renderHint{isHeaderRow: true})
   219  	} else if t.autoIndex {
   220  		hint := renderHint{isAutoIndexRow: true, isHeaderRow: true}
   221  		t.htmlRenderRows(out, []rowStr{t.getAutoIndexColumnIDs()}, hint)
   222  	}
   223  }
   224  
   225  func (t *Table) htmlRenderTitle(out *strings.Builder) {
   226  	if t.title != "" {
   227  		align := t.style.Title.Align.HTMLProperty()
   228  		colors := t.style.Title.Colors.HTMLProperty()
   229  		title := t.style.Title.Format.Apply(t.title)
   230  
   231  		out.WriteString("  <caption class=\"title\"")
   232  		if align != "" {
   233  			out.WriteRune(' ')
   234  			out.WriteString(align)
   235  		}
   236  		if colors != "" {
   237  			out.WriteRune(' ')
   238  			out.WriteString(colors)
   239  		}
   240  		out.WriteRune('>')
   241  		out.WriteString(title)
   242  		out.WriteString("</caption>\n")
   243  	}
   244  }
   245  

View as plain text