From db814553826604e1f026789d4e3af0c1812f66b0 Mon Sep 17 00:00:00 2001 From: Jonathan Amsterdam Date: Tue, 31 Mar 2026 07:29:07 -0400 Subject: internal/api: factor out common renderer things Change-Id: I5d8a579913942bcdea664af675ff2ef29888281c Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/761400 TryBot-Bypass: Jonathan Amsterdam LUCI-TryBot-Result: Go LUCI Reviewed-by: Hyang-Ah Hana Kim Reviewed-by: Ethan Lee --- internal/api/api.go | 6 ++-- internal/api/render.go | 85 ++++++++++++++++++++------------------------- internal/api/render_test.go | 6 ++-- 3 files changed, 44 insertions(+), 53 deletions(-) diff --git a/internal/api/api.go b/internal/api/api.go index cf771e82..fbc00e61 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -104,11 +104,11 @@ func ServePackage(w http.ResponseWriter, r *http.Request, ds internal.DataSource var sb strings.Builder switch params.Doc { case "text": - r = &textRenderer{fset: gpkg.Fset, w: &sb} + r = newTextRenderer(gpkg.Fset, &sb) case "md", "markdown": - r = &markdownRenderer{fset: gpkg.Fset, w: &sb} + r = newMarkdownRenderer(gpkg.Fset, &sb) case "html": - return errors.New("unimplemented") + r = newHTMLRenderer(gpkg.Fset, &sb) default: return fmt.Errorf("%w: bad doc format: need one of 'text', 'md', 'markdown' or 'html'", derrors.InvalidArgument) } diff --git a/internal/api/render.go b/internal/api/render.go index f8d9dbc7..4001f6ca 100644 --- a/internal/api/render.go +++ b/internal/api/render.go @@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// TODO(jba)? Consider rendering notes separately. Now they appear -// with the doc for each symbol, which is probably better for LLMs, -// but be open to evidence to the contrary. - package api import ( @@ -42,13 +38,34 @@ type renderer interface { emitExample(ex *doc.Example) } +type commonRenderer struct { + fset *token.FileSet + w io.Writer + err error +} + +func (r *commonRenderer) printf(format string, args ...any) { + if r.err != nil { + return + } + if _, err := fmt.Fprintf(r.w, format, args...); err != nil { + r.err = err + } +} + +func (r *commonRenderer) end() error { return r.err } + type textRenderer struct { - fset *token.FileSet - w io.Writer + commonRenderer pkg *doc.Package parser *comment.Parser printer *comment.Printer - err error +} + +func newTextRenderer(fset *token.FileSet, w io.Writer) *textRenderer { + return &textRenderer{ + commonRenderer: commonRenderer{fset: fset, w: w}, + } } func (r *textRenderer) start(pkg *doc.Package) { @@ -71,8 +88,6 @@ func (r *textRenderer) start(pkg *doc.Package) { r.printf("\n") } -func (r *textRenderer) end() error { return r.err } - func (r *textRenderer) startSection(name string) { r.printf("%s\n\n", strings.ToUpper(name)) } @@ -141,24 +156,18 @@ func (r *textRenderer) emitExample(ex *doc.Example) { r.printf("\n") } -// TODO(jba): consolidate this function to avoid duplication. -func (r *textRenderer) printf(format string, args ...any) { - if r.err != nil { - return - } - if _, err := fmt.Fprintf(r.w, format, args...); err != nil { - r.err = err - } -} - type markdownRenderer struct { - fset *token.FileSet - w io.Writer + commonRenderer pkg *doc.Package parser *comment.Parser printer *comment.Printer caser cases.Caser - err error +} + +func newMarkdownRenderer(fset *token.FileSet, w io.Writer) *markdownRenderer { + return &markdownRenderer{ + commonRenderer: commonRenderer{fset: fset, w: w}, + } } func (r *markdownRenderer) start(pkg *doc.Package) { @@ -178,8 +187,6 @@ func (r *markdownRenderer) start(pkg *doc.Package) { r.printf("\n") } -func (r *markdownRenderer) end() error { return r.err } - func (r *markdownRenderer) startSection(name string) { if name == "" { return @@ -239,24 +246,19 @@ func (r *markdownRenderer) emitExample(ex *doc.Example) { r.printf("\n") } -func (r *markdownRenderer) printf(format string, args ...any) { - if r.err != nil { - return - } - if _, err := fmt.Fprintf(r.w, format, args...); err != nil { - r.err = err - } -} - type htmlRenderer struct { - fset *token.FileSet - w io.Writer + commonRenderer pkg *doc.Package parser *comment.Parser printer *comment.Printer caser cases.Caser buf strings.Builder - err error +} + +func newHTMLRenderer(fset *token.FileSet, w io.Writer) *htmlRenderer { + return &htmlRenderer{ + commonRenderer: commonRenderer{fset: fset, w: w}, + } } func (r *htmlRenderer) start(pkg *doc.Package) { @@ -276,8 +278,6 @@ func (r *htmlRenderer) start(pkg *doc.Package) { r.printf("\n") } -func (r *htmlRenderer) end() error { return r.err } - func (r *htmlRenderer) startSection(name string) { if name == "" { return @@ -338,15 +338,6 @@ func (r *htmlRenderer) emitExample(ex *doc.Example) { r.printf("\n") } -func (r *htmlRenderer) printf(format string, args ...any) { - if r.err != nil { - return - } - if _, err := fmt.Fprintf(r.w, format, args...); err != nil { - r.err = err - } -} - // renderDoc renders the documentation for dpkg using the given renderer. func renderDoc(dpkg *doc.Package, r renderer, examples bool) error { r.start(dpkg) diff --git a/internal/api/render_test.go b/internal/api/render_test.go index fdfb8612..5cc826d1 100644 --- a/internal/api/render_test.go +++ b/internal/api/render_test.go @@ -77,7 +77,7 @@ func testRenderDoc(t *testing.T, examples bool) { }) } - check(t, "text", &textRenderer{fset: decoded.Fset, w: &sb}) - check(t, "markdown", &markdownRenderer{fset: decoded.Fset, w: &sb}) - check(t, "html", &htmlRenderer{fset: decoded.Fset, w: &sb}) + check(t, "text", newTextRenderer(decoded.Fset, &sb)) + check(t, "markdown", newMarkdownRenderer(decoded.Fset, &sb)) + check(t, "html", newHTMLRenderer(decoded.Fset, &sb)) } -- cgit v1.3