better domain isolation
Generate check / check-changes (pull_request) Successful in 2s
Generate check / verify-generate (pull_request) Skipped
Quality / check-changes (pull_request) Successful in 2s
Quality / static-checks (pull_request) Failing after 13s
Quality / run-tests (pull_request) Failing after 54s

This commit is contained in:
natercio committed 2026-10-05 15:08:26 +01:00
1 parent e167627ac3
commit 5c146ad60f
10 files changed
+342 -242

No files matched your search

+12 -24
View File
@@ -1,8 +1,8 @@
// Package html renders an internal.AggregatorWriter as a complete,
// standalone HTML document built around the same table fragment produced by
// table.Printer.RenderHTML. The document includes the Bootstrap 5.3
// stylesheet via CDN and embeds the raw table fragment without HTML-escaping
// it so the result opens directly in a browser.
// standalone HTML document: the report table fragment (built from the
// shared table definition in internal/writing/internal/tabledef, so it can
// never drift from the terminal layout) embedded in a Bootstrap-styled page
// with a translated title and generation timestamp.
package html
import (
@@ -13,15 +13,9 @@ import (
"time"
"github.com/nmoniz/any2anexoj/internal"
"github.com/nmoniz/any2anexoj/internal/writing/table"
"github.com/nmoniz/any2anexoj/internal/writing/internal/tabledef"
)
// translator is the contract the HTML writer relies on for localized
// document text such as the page title. *writing.Localizer satisfies it.
type translator interface {
Translate(key string, count int, values map[string]any) string
}
// bootstrapCSSURL is the jsDelivr CDN URL for Bootstrap 5.3.3.
const bootstrapCSSURL = "https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
@@ -31,20 +25,17 @@ const bootstrapIntegrity = "sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bR
// Writer writes a complete HTML document for an AggregatorWriter.
type Writer struct {
output io.Writer
printer *table.Printer
translator translator
translator tabledef.Translator
lang string
}
// NewWriter builds a Writer that writes a complete HTML document to
// w. The printer is used purely as a source for the raw <table> fragment via
// RenderHTML; this writer never invokes Render or any method that writes to
// printer's own io.Writer. The document title is looked up from the
// "report_title" translation via tr, so callers never pass a pre-baked title.
func NewWriter(w io.Writer, printer *table.Printer, tr translator, lang string) *Writer {
// NewWriter builds a Writer that writes a complete HTML document to w. The
// report table is rendered from the shared table definition via tr, and the
// document title is looked up from the "report_title" translation via tr,
// so callers never pass a pre-baked title.
func NewWriter(w io.Writer, tr tabledef.Translator, lang string) *Writer {
return &Writer{
output: w,
printer: printer,
translator: tr,
lang: lang,
}
@@ -63,10 +54,7 @@ var documentTemplate = template.Must(template.New("html").Parse(documentTemplate
// fragment from aw so the rendered <tr> count reflects aw's current items and
// no rows are duplicated across invocations.
func (hw *Writer) Render(aw *internal.AggregatorWriter) error {
if hw.printer == nil {
return fmt.Errorf("html: nil printer")
}
fragment := hw.printer.RenderHTML(aw)
fragment := hw.renderTableFragment(aw)
title := hw.translator.Translate("report_title", 1, nil)
data := struct {
Lang string