Add support for CSS links in generated HTML outputs

This commit is contained in:
2026-06-13 22:16:15 -05:00
parent c84d8868d1
commit b10a8bd194
11 changed files with 213 additions and 13 deletions

View File

@@ -123,7 +123,7 @@ func (t *Transformer) render(ctx context.Context, req transform.Request, sourceF
if err := t.renderer.Convert(data, &rendered); err != nil {
return nil, fmt.Errorf("render markdown source %q: %w", sourceFile, err)
}
return wrapHTML(rendered.Bytes()), nil
return wrapHTML(rendered.Bytes(), req.Markdown.CssHref), nil
}
func markdownMode(mode string) string {

View File

@@ -40,6 +40,43 @@ func TestGenerateMarkdownSidecar(t *testing.T) {
}
}
func TestGenerateMarkdownWithoutCSSHrefPreservesWrapper(t *testing.T) {
backend, sourceBundle := markdownFixture(t, "# Title\n\nHello.\n")
outputs, err := New().Generate(context.Background(), transform.Request{SourceBackend: backend, SourceBundle: sourceBundle})
if err != nil {
t.Fatalf("Generate() error = %v", err)
}
want := "<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title></title>\n</head>\n<body>\n<h1>Title</h1>\n<p>Hello.</p>\n</body>\n</html>\n"
if got := string(outputs[0].Data); got != want {
t.Fatalf("html = %q, want existing wrapper %q", got, want)
}
}
func TestGenerateMarkdownSidecarWithCSSHref(t *testing.T) {
backend, sourceBundle := markdownFixture(t, "# Title\n\nHello.\n")
outputs, err := New().Generate(context.Background(), transform.Request{
SourceBackend: backend,
SourceBundle: sourceBundle,
Markdown: transform.MarkdownOptions{CssHref: "/assets/report.css?v=1&theme=main"},
})
if err != nil {
t.Fatalf("Generate() error = %v", err)
}
output := outputs[0]
html := string(output.Data)
wantLink := "<meta charset=\"utf-8\">\n<link rel=\"stylesheet\" href=\"/assets/report.css?v=1&amp;theme=main\">\n<title></title>"
if !strings.Contains(html, wantLink) {
t.Fatalf("html = %q, want stylesheet link %q", html, wantLink)
}
if output.SHA256 != bundle.FileDigest(output.Data) || output.Size != int64(len(output.Data)) {
t.Fatalf("digest/size metadata = %s/%d", output.SHA256, output.Size)
}
}
func TestGenerateMarkdownIndexExplicitInput(t *testing.T) {
backend := fake.New()
sourceBundle := testutil.WriteFakeSourceBundle(t, backend, "", testutil.BundleOptions{
@@ -74,6 +111,29 @@ func TestGenerateMarkdownIndexExplicitInput(t *testing.T) {
}
}
func TestGenerateMarkdownIndexWithCSSHref(t *testing.T) {
backend, sourceBundle := markdownFixture(t, "# Title\n\nHello.\n")
outputs, err := New().Generate(context.Background(), transform.Request{
SourceBackend: backend,
SourceBundle: sourceBundle,
Markdown: transform.MarkdownOptions{
Mode: transform.MarkdownModeIndex,
CssHref: "https://example.com/assets/report.css",
},
})
if err != nil {
t.Fatalf("Generate() error = %v", err)
}
if got, want := outputs[0].Path, "index.html"; got != want {
t.Fatalf("path = %q, want %q", got, want)
}
if !strings.Contains(string(outputs[0].Data), `<link rel="stylesheet" href="https://example.com/assets/report.css">`) {
t.Fatalf("html = %q, want stylesheet link", outputs[0].Data)
}
}
func TestGenerateMarkdownIndexSelectsOnlyMarkdownFile(t *testing.T) {
backend, sourceBundle := markdownFixture(t, "# Title\n\nHello.\n")

View File

@@ -1,10 +1,19 @@
package markdown
import "bytes"
import (
"bytes"
"html"
)
func wrapHTML(body []byte) []byte {
func wrapHTML(body []byte, cssHref string) []byte {
var buf bytes.Buffer
buf.WriteString("<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title></title>\n</head>\n<body>\n")
buf.WriteString("<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n")
if cssHref != "" {
buf.WriteString("<link rel=\"stylesheet\" href=\"")
buf.WriteString(html.EscapeString(cssHref))
buf.WriteString("\">\n")
}
buf.WriteString("<title></title>\n</head>\n<body>\n")
buf.Write(body)
buf.WriteString("</body>\n</html>\n")
return buf.Bytes()