Skip to content

Commit 726bab5

Browse files
committedJul 15, 2022
docs: render markdown documentation [wip]
1 parent 1ae3b4c commit 726bab5

File tree

5 files changed

+157
-2
lines changed

5 files changed

+157
-2
lines changed
 

‎docs/docs.go

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package docs
2+
3+
import (
4+
"bytes"
5+
"embed"
6+
"fmt"
7+
"io"
8+
"net/http"
9+
"strings"
10+
11+
"github.com/Depado/bfchroma/v2"
12+
"github.com/alecthomas/chroma/v2/formatters/html"
13+
bf "github.com/russross/blackfriday/v2"
14+
"gopkg.in/yaml.v3"
15+
)
16+
17+
//go:embed docs.yml *.md **/*.md
18+
var sources embed.FS
19+
20+
type page struct {
21+
Title string
22+
Breadcrumbs []string
23+
Body string
24+
File string
25+
Route string
26+
Children []*page
27+
}
28+
29+
var root = func() page {
30+
structure, err := sources.Open("docs.yml")
31+
if err != nil {
32+
panic(err)
33+
}
34+
defer structure.Close()
35+
36+
var menu page
37+
dec := yaml.NewDecoder(structure)
38+
dec.KnownFields(true)
39+
if err := dec.Decode(&menu); err != nil {
40+
panic(err)
41+
}
42+
43+
menu.init()
44+
return menu
45+
}()
46+
47+
func (pg *page) init(crumbs ...string) {
48+
if pg.File != "" {
49+
if r := strings.TrimSuffix(pg.File, ".md"); r == "index" {
50+
pg.Route = ""
51+
} else {
52+
pg.Route = "/" + r
53+
}
54+
55+
pg.parseFile()
56+
}
57+
if pg.Title != "" {
58+
pg.Breadcrumbs = append(pg.Breadcrumbs, pg.Title)
59+
}
60+
for _, child := range pg.Children {
61+
child.init(pg.Breadcrumbs...)
62+
}
63+
}
64+
65+
func (pg *page) parseFile() {
66+
body, err := sources.ReadFile(pg.File)
67+
if err != nil {
68+
panic(err)
69+
}
70+
71+
r := bfchroma.NewRenderer(
72+
bfchroma.WithoutAutodetect(),
73+
bfchroma.ChromaOptions(
74+
html.WithLineNumbers(true),
75+
),
76+
bfchroma.Extend(bf.NewHTMLRenderer(bf.HTMLRendererParameters{
77+
Flags: bf.CommonHTMLFlags & ^bf.UseXHTML & ^bf.CompletePage,
78+
})),
79+
)
80+
parser := bf.New(
81+
bf.WithExtensions(bf.CommonExtensions),
82+
bf.WithRenderer(r),
83+
)
84+
85+
ast := parser.Parse(body)
86+
var buf bytes.Buffer
87+
var inH1 bool
88+
89+
ast.Walk(func(node *bf.Node, entering bool) bf.WalkStatus {
90+
switch node.Type {
91+
case bf.Heading:
92+
inH1 = entering && node.HeadingData.Level == 1 && pg.Title == ""
93+
case bf.Text:
94+
if inH1 {
95+
pg.Title = string(node.Literal)
96+
}
97+
case bf.Link:
98+
if entering && bytes.HasPrefix(node.LinkData.Destination, []byte("./")) {
99+
node.LinkData.Destination = bytes.TrimSuffix(node.LinkData.Destination, []byte(".md"))
100+
}
101+
}
102+
return r.RenderNode(&buf, node, entering)
103+
})
104+
105+
pg.Body = buf.String()
106+
}
107+
108+
func (pg *page) Dump(w io.Writer) {
109+
fmt.Fprintf(w, "- %s (%s)\n", pg.Title, pg.Route)
110+
fmt.Fprintln(w, pg.Body)
111+
fmt.Fprintln(w)
112+
113+
for _, c := range pg.Children {
114+
c.Dump(w)
115+
}
116+
}
117+
118+
func Handler() http.Handler {
119+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
120+
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
121+
w.Header().Set("X-Content-Type-Options", "nosniff")
122+
w.WriteHeader(http.StatusOK)
123+
124+
fmt.Fprintf(w, "%#v\n\n", r.URL)
125+
126+
root.Dump(w)
127+
})
128+
}

‎docs/docs.yml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
file: index.md
3+
children:
4+
- file: operation-modes.md
5+
- file: cli-options.md
6+
- title: HTTP API
7+
children:
8+
- file: http-api/render.md
9+
- file: http-api/status.md
10+
- file: http-api/metrics.md
11+
- file: http-api/web-ui.md
12+
- file: reference-store.md
13+
- file: history.md
14+
- file: future.md

‎go.mod

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ module github.com/digineo/texd
33
go 1.18
44

55
require (
6+
github.com/Depado/bfchroma/v2 v2.0.0
7+
github.com/alecthomas/chroma/v2 v2.2.0
68
github.com/bahlo/generic-list-go v0.2.0
79
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d
810
github.com/docker/docker v20.10.17+incompatible
@@ -12,11 +14,13 @@ require (
1214
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
1315
github.com/opencontainers/image-spec v1.0.2
1416
github.com/prometheus/client_golang v1.12.2
17+
github.com/russross/blackfriday/v2 v2.1.0
1518
github.com/spf13/afero v1.8.2
1619
github.com/spf13/pflag v1.0.5
1720
github.com/stretchr/testify v1.8.0
1821
github.com/thediveo/enumflag v0.10.1
1922
go.uber.org/zap v1.21.0
23+
gopkg.in/yaml.v3 v3.0.1
2024
)
2125

2226
require (
@@ -25,6 +29,7 @@ require (
2529
github.com/beorn7/perks v1.0.1 // indirect
2630
github.com/cespare/xxhash/v2 v2.1.2 // indirect
2731
github.com/davecgh/go-spew v1.1.1 // indirect
32+
github.com/dlclark/regexp2 v1.4.0 // indirect
2833
github.com/docker/distribution v2.8.1+incompatible // indirect
2934
github.com/docker/go-connections v0.4.0 // indirect
3035
github.com/felixge/httpsnoop v1.0.3 // indirect
@@ -54,7 +59,6 @@ require (
5459
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
5560
google.golang.org/protobuf v1.28.0 // indirect
5661
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
57-
gopkg.in/yaml.v3 v3.0.1 // indirect
5862
gotest.tools/v3 v3.1.0 // indirect
5963
)
6064

‎go.sum

+8-1
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,14 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOEl
4040
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
4141
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
4242
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
43+
github.com/Depado/bfchroma/v2 v2.0.0 h1:IRpN9BPkNwEpR6w1ectIcNWOuhDSLx+8f1pn83fzxx8=
44+
github.com/Depado/bfchroma/v2 v2.0.0/go.mod h1:wFwW/Pw8Tnd0irzgO9Zxtxgzp3aPS8qBWlyadxujxmw=
4345
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
4446
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
4547
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
48+
github.com/alecthomas/chroma/v2 v2.2.0 h1:Aten8jfQwUqEdadVFFjNyjx7HTexhKP0XuqBG67mRDY=
49+
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
50+
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae h1:zzGwJfFlFGD94CyyYwCJeSuD32Gj9GTaSi5y9hoVzdY=
4651
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
4752
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
4853
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -60,7 +65,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
6065
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d h1:pVrfxiGfwelyab6n21ZBkbkmbevaf+WvMIiR7sr97hw=
6166
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
6267
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
63-
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
6468
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
6569
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
6670
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
@@ -89,6 +93,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
8993
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
9094
github.com/digineo/afero v1.8.3-0.20220715171204-b7c01b3e0267 h1:yjyMHADZ7cyDMxzJdF09tVdowOTwfb+cys5WdtU/5k4=
9195
github.com/digineo/afero v1.8.3-0.20220715171204-b7c01b3e0267/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
96+
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
97+
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
9298
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
9399
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
94100
github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE=
@@ -304,6 +310,7 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T
304310
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
305311
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
306312
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
313+
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
307314
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
308315
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
309316
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=

‎service/service.go

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"net/http"
1010
"time"
1111

12+
"github.com/digineo/texd/docs"
1213
"github.com/digineo/texd/exec"
1314
"github.com/digineo/texd/metrics"
1415
"github.com/digineo/texd/refstore"
@@ -87,6 +88,7 @@ func (svc *service) routes() http.Handler {
8788
r := mux.NewRouter()
8889
r.HandleFunc("/", HandleUI).Methods(http.MethodGet)
8990
r.PathPrefix("/assets/").Handler(HandleAssets()).Methods(http.MethodGet)
91+
r.PathPrefix("/docs").Handler(http.StripPrefix("/docs", docs.Handler())).Methods(http.MethodGet)
9092

9193
render := http.Handler(http.HandlerFunc(svc.HandleRender))
9294
if max := svc.maxJobSize; max > 0 {

0 commit comments

Comments
 (0)
Please sign in to comment.