Files
any2anexoj/internal/writing/html/fragment.go
T
natercio 3dfc7bd6a7
Generate check / check-changes (pull_request) Successful in 26s
Generate check / verify-generate (pull_request) Skipped
Quality / check-changes (pull_request) Successful in 2s
Quality / static-checks (pull_request) Failing after 16s
Quality / run-tests (pull_request) Failing after 56s
better domain isolation
2026-10-05 14:56:27 +01:00

70 lines
2.7 KiB
Go

package html
import (
"fmt"
"strings"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/nmoniz/any2anexoj/internal"
"github.com/nmoniz/any2anexoj/internal/writing/internal/tabledef"
)
// htmlCSSClass is the CSS class list put on the rendered report table.
const htmlCSSClass = "table table-striped table-hover table-bordered"
// widthIndex is the weight of the auto-index (row number) column; the other
// column weights come from tabledef's width budgets.
const widthIndex = 6
// htmlColumnWeights lists one weight per rendered column, starting with the
// auto-index column, mirroring the column order of tabledef.Build so the
// HTML table keeps columns in the same strict proportion to each other as
// the terminal layout.
var htmlColumnWeights = []int{
widthIndex,
tabledef.WidthCountry, tabledef.WidthOther, tabledef.WidthOther, tabledef.WidthOther, tabledef.WidthOther, tabledef.WidthEuros,
tabledef.WidthOther, tabledef.WidthOther, tabledef.WidthOther, tabledef.WidthEuros,
tabledef.WidthEuros, tabledef.WidthEuros, tabledef.WidthCountry,
}
// renderTableFragment renders aw as the Bootstrap-styled HTML <table>
// fragment embedded in the document. The table gets a fixed layout with
// strictly proportional column widths, so the browser — not this package —
// decides when a header or cell wraps: on wide screens everything fits on
// one line, on narrow ones it wraps automatically.
func (hw *Writer) renderTableFragment(aw *internal.AggregatorWriter) string {
t := tabledef.Build(hw.translator, aw)
t.Style().HTML = table.HTMLOptions{
CSSClass: htmlCSSClass,
EscapeText: true,
Newline: "<br/>",
EmptyColumn: "&nbsp;",
}
html := t.RenderHTML()
// go-pretty cannot emit table-level attributes or a <colgroup>, so splice
// them into its output: the fixed layout makes the colgroup's relative
// widths authoritative instead of content-driven column sizing.
openTag := `<table class="` + htmlCSSClass + `">`
fixedTag := `<table class="` + htmlCSSClass + `" style="table-layout: fixed">` + "\n" + colgroupHTML()
return strings.Replace(html, openTag, fixedTag, 1)
}
// colgroupHTML returns a <colgroup> with one <col> per rendered column, each
// sized strictly in proportion to its weight. With the fixed table layout
// applied in renderTableFragment these widths are authoritative: wide
// viewports fit headers on a single line, narrow ones wrap automatically.
func colgroupHTML() string {
var total int
for _, w := range htmlColumnWeights {
total += w
}
var sb strings.Builder
sb.WriteString("<colgroup>")
for _, w := range htmlColumnWeights {
fmt.Fprintf(&sb, `<col style="width: %.2f%%">`, float64(w)/float64(total)*100)
}
sb.WriteString("</colgroup>")
return sb.String()
}