repos / pgit

static site generator for git
git clone https://github.com/picosh/pgit.git

commit
c02493d
parent
41f93ba
author
Eric Bower
date
2024-01-14 22:48:02 +0000 UTC
changes
6 files changed,  +624, -28
M Makefile
+7, -2
 1@@ -1,6 +1,10 @@
 2 REV=$(shell git rev-parse --short HEAD)
 3 PROJECT="git-pgit-$(REV)"
 4 
 5+smol:
 6+	curl https://pico.sh/smol.css -o ./static/smol.css
 7+.PHONY: smol
 8+
 9 clean:
10 	rm -rf ./public
11 .PHONY: clean
12@@ -28,6 +32,7 @@ static: build clean
13 .PHONY:
14 
15 deploy:
16-	rsync -rv ./public/* erock@pgs.sh:/$(PROJECT)
17-	ssh erock@pgs.sh link git-pgit $(PROJECT) --write
18+	rsync -rv ./public/* hey@pgs.sh:/git-pgit-local
19+	# $(PROJECT)
20+	# ssh hey@pgs.sh link git-pgit $(PROJECT) --write
21 .PHONY: deploy
M html/base.layout.tmpl
+1, -2
 1@@ -10,8 +10,7 @@
 2 
 3     {{template "meta" .}}
 4 
 5-    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/devicon.min.css">
 6-    <link rel="stylesheet" href="https://pico.sh/smol.css" />
 7+    <link rel="stylesheet" href="/smol.css" />
 8     <link rel="stylesheet" href="/main.css" />
 9   </head>
10   <body>
M html/tree.page.tmpl
+5, -3
 1@@ -16,14 +16,16 @@
 2     </div>
 3 
 4     {{range .Tree.Items}}
 5-      <div class="flex justify-between items-center gap p-sm border-b tree-row">
 6+      <div class="flex justify-between items-center gap-2 p tree-row border-b">
 7         <div class="flex-1 tree-path flex items-center gap">
 8           {{if .IsDir}}
 9-            <svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 512 512">
10+            <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" height="16" width="16" viewBox="0 0 512 512">
11               <path d="M0 96C0 60.7 28.7 32 64 32H196.1c19.1 0 37.4 7.6 50.9 21.1L289.9 96H448c35.3 0 64 28.7 64 64V416c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V96zM64 80c-8.8 0-16 7.2-16 16V416c0 8.8 7.2 16 16 16H448c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16H286.6c-10.6 0-20.8-4.2-28.3-11.7L213.1 87c-4.5-4.5-10.6-7-17-7H64z"/>
12             </svg>
13           {{else}}
14-          <i class="{{.Icon}}"></i>
15+            <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" height="16" width="16" viewBox="0 0 384 512">
16+              <path d="M320 464c8.8 0 16-7.2 16-16V160H256c-17.7 0-32-14.3-32-32V48H64c-8.8 0-16 7.2-16 16V448c0 8.8 7.2 16 16 16H320zM0 64C0 28.7 28.7 0 64 0H229.5c17 0 33.3 6.7 45.3 18.7l90.5 90.5c12 12 18.7 28.3 18.7 45.3V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V64z"/>
17+            </svg>
18           {{end}}
19 
20           <a href="{{.URL}}">{{.Name}}</a>
M main.go
+32, -21
 1@@ -24,11 +24,8 @@ import (
 2 	"go.uber.org/zap"
 3 )
 4 
 5-//go:embed static/main.css
 6-var mainCss []byte
 7-
 8-//go:embed static/syntax.css
 9-var syntaxCss []byte
10+//go:embed static/*
11+var sfs embed.FS
12 
13 //go:embed html/*.tmpl
14 var efs embed.FS
15@@ -120,7 +117,7 @@ type TreeItem struct {
16 	Size       string
17 	NumLines   int
18 	Name       string
19-	Icon string
20+	Icon       string
21 	Path       string
22 	URL        template.URL
23 	CommitID   string
24@@ -335,10 +332,25 @@ func (c *Config) writeHtml(writeData *WriteData) {
25 	bail(err)
26 }
27 
28-func (c *Config) copyStatic(dst string, data []byte) {
29-	c.Logger.Infof("writing (%s)", dst)
30-	err := os.WriteFile(dst, data, 0755)
31+func (c *Config) copyStatic() error {
32+	dir := "static"
33+	entries, err := sfs.ReadDir(dir)
34 	bail(err)
35+
36+	for _, e := range entries {
37+		infp := filepath.Join(dir, e.Name())
38+		if e.IsDir() {
39+			continue
40+		}
41+
42+		w, err := os.ReadFile(infp)
43+		bail(err)
44+		fp := filepath.Join(c.Outdir, e.Name())
45+		c.Logger.Infof("writing (%s)", fp)
46+		os.WriteFile(fp, w, 0755)
47+	}
48+
49+	return nil
50 }
51 
52 func (c *Config) writeRootSummary(data *PageData, readme template.HTML) {
53@@ -740,15 +752,18 @@ func FilenameToDevIcon(filename string) string {
54 	ext := filepath.Ext(filename)
55 	extMappr := map[string]string{
56 		".html": "html5",
57-		".go": "go",
58-		".py": "python",
59-		".css": "css3",
60-		".js": "javascript",
61-		".md": "markdown",
62+		".go":   "go",
63+		".py":   "python",
64+		".css":  "css3",
65+		".js":   "javascript",
66+		".md":   "markdown",
67+		".ts":   "typescript",
68+		".tsx":  "react",
69+		".jsx":  "react",
70 	}
71 
72-	nameMappr := map[string]string {
73-		"Makefile": "cmake",
74+	nameMappr := map[string]string{
75+		"Makefile":   "cmake",
76 		"Dockerfile": "docker",
77 	}
78 
79@@ -890,9 +905,7 @@ func (c *Config) writeRevision(repo *git.Repository, pageData *PageData, refs []
80 		if pageSize == 0 {
81 			pageSize = 5000
82 		}
83-		fmt.Println("grabbing commits")
84 		commits, err := repo.CommitsByPage(pageData.RevData.ID(), 0, pageSize)
85-		fmt.Println("got commits")
86 		bail(err)
87 
88 		logs := []*CommitData{}
89@@ -1058,9 +1071,7 @@ func main() {
90 	}
91 
92 	config.writeRepo()
93-
94-	config.copyStatic(filepath.Join(config.Outdir, "main.css"), mainCss)
95-	config.copyStatic(filepath.Join(config.Outdir, "syntax.css"), syntaxCss)
96+	config.copyStatic()
97 
98 	url := filepath.Join("/", "index.html")
99 	config.Logger.Info(url)
M static/main.css
+4, -0
1@@ -1,3 +1,7 @@
2+.border-b {
3+  border-bottom: 1px solid var(--grey);
4+}
5+
6 body {
7   max-width: 900px;
8 }
A static/smol.css
+575, -0
  1@@ -0,0 +1,575 @@
  2+*,
  3+::before,
  4+::after {
  5+  box-sizing: border-box;
  6+}
  7+
  8+::-moz-focus-inner {
  9+  border-style: none;
 10+  padding: 0;
 11+}
 12+:-moz-focusring {
 13+  outline: 1px dotted ButtonText;
 14+}
 15+:-moz-ui-invalid {
 16+  box-shadow: none;
 17+}
 18+
 19+@media (prefers-color-scheme: light) {
 20+  :root {
 21+    --main-hue: 250;
 22+    --white: #6a737d;
 23+    --code: #fff8d3;
 24+    --code-border: #f0d547;
 25+    --pre: #f6f8fa;
 26+    --bg-color: #fff;
 27+    --text-color: #24292f;
 28+    --link-color: #005cc5;
 29+    --visited: #6f42c1;
 30+    --blockquote: #005cc5;
 31+    --blockquote-bg: #fff;
 32+    --hover: #d73a49;
 33+    --grey: #ccc;
 34+    --grey-light: #6a708e;
 35+    --shadow: #252525;
 36+  }
 37+}
 38+
 39+@media (prefers-color-scheme: dark) {
 40+  :root {
 41+    --main-hue: 250;
 42+    --white: #f2f2f2;
 43+    --code: #414558;
 44+    --code-border: #252525;
 45+    --pre: #252525;
 46+    --bg-color: #282a36;
 47+    --text-color: #f2f2f2;
 48+    --link-color: #8be9fd;
 49+    --visited: #bd93f9;
 50+    --blockquote: #bd93f9;
 51+    --blockquote-bg: #414558;
 52+    --hover: #ff80bf;
 53+    --grey: #414558;
 54+    --grey-light: #6a708e;
 55+    --shadow: #252525;
 56+  }
 57+}
 58+
 59+html {
 60+  background-color: var(--bg-color);
 61+  color: var(--text-color);
 62+  font-size: 18px;
 63+  line-height: 1.5;
 64+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
 65+    Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Arial,
 66+    sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
 67+  -webkit-text-size-adjust: 100%;
 68+  -moz-tab-size: 4;
 69+  tab-size: 4;
 70+}
 71+
 72+body {
 73+  margin: 0 auto;
 74+}
 75+
 76+img {
 77+  max-width: 100%;
 78+  height: auto;
 79+}
 80+
 81+b,
 82+strong {
 83+  font-weight: bold;
 84+}
 85+
 86+code,
 87+kbd,
 88+samp,
 89+pre {
 90+  font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo,
 91+    monospace;
 92+}
 93+
 94+code,
 95+kbd,
 96+samp {
 97+  background-color: var(--code);
 98+  border: 1px solid var(--code-border);
 99+}
100+
101+pre > code {
102+  background-color: inherit;
103+  padding: 0;
104+  border: none;
105+}
106+
107+code {
108+  border-radius: 0.3rem;
109+  padding: 0.15rem 0.2rem 0.05rem;
110+}
111+
112+pre {
113+  border-radius: 5px;
114+  padding: 1rem;
115+  margin: 1rem 0;
116+  overflow-x: auto;
117+  background-color: var(--pre) !important;
118+}
119+
120+small {
121+  font-size: 0.8rem;
122+}
123+
124+summary {
125+  display: list-item;
126+}
127+
128+h1,
129+h2,
130+h3 {
131+  margin: 0;
132+  padding: 0.6rem 0 0 0;
133+  border: 0;
134+  font-style: normal;
135+  font-weight: inherit;
136+  font-size: inherit;
137+}
138+
139+h1 > code {
140+  font-size: inherit;
141+}
142+
143+h2 > code {
144+  font-size: inherit;
145+}
146+
147+h3 > code {
148+  font-size: inherit;
149+}
150+
151+path {
152+  fill: var(--text-color);
153+  stroke: var(--text-color);
154+}
155+
156+hr {
157+  color: inherit;
158+  border: 0;
159+  margin: 0;
160+  height: 1px;
161+  background: var(--grey);
162+  margin: 1rem auto;
163+  text-align: center;
164+}
165+
166+a {
167+  text-decoration: underline;
168+  color: var(--link-color);
169+}
170+
171+a:hover,
172+a:visited:hover {
173+  color: var(--hover);
174+}
175+
176+a:visited {
177+  color: var(--visited);
178+}
179+
180+a.link-grey {
181+  text-decoration: underline;
182+  color: var(--white);
183+}
184+
185+a.link-grey:visited {
186+  color: var(--white);
187+}
188+
189+section {
190+  margin-bottom: 1.4rem;
191+}
192+
193+section:last-child {
194+  margin-bottom: 0;
195+}
196+
197+header {
198+  margin: 1rem auto;
199+}
200+
201+p {
202+  margin: 0.8rem 0;
203+}
204+
205+article {
206+  overflow-wrap: break-word;
207+}
208+
209+blockquote {
210+  border-left: 5px solid var(--blockquote);
211+  background-color: var(--blockquote-bg);
212+  padding: 0.8rem;
213+  margin: 1rem 0;
214+}
215+
216+blockquote > p {
217+  margin: 0;
218+}
219+
220+ul,
221+ol {
222+  padding: 0 0 0 2rem;
223+  list-style-position: outside;
224+}
225+
226+ul[style*="list-style-type: none;"] {
227+  padding: 0;
228+}
229+
230+li {
231+  margin: 0.5rem 0;
232+}
233+
234+li > pre {
235+  padding: 0;
236+}
237+
238+footer {
239+  text-align: center;
240+  margin-bottom: 4rem;
241+}
242+
243+dt {
244+  font-weight: bold;
245+}
246+
247+dd {
248+  margin-left: 0;
249+}
250+
251+dd:not(:last-child) {
252+  margin-bottom: 0.5rem;
253+}
254+
255+figure {
256+  margin: 0;
257+}
258+
259+.container {
260+  max-width: 900px;
261+  width: 100%;
262+}
263+
264+.container-center {
265+  width: 100%;
266+  height: 100%;
267+  display: flex;
268+  justify-content: center;
269+}
270+
271+.text-3xl {
272+  font-size: 3rem;
273+}
274+
275+.text-2xl {
276+  font-size: 1.85rem;
277+  line-height: 1.15;
278+}
279+
280+.text-xl {
281+  font-size: 1.55rem;
282+  line-height: 1.15;
283+}
284+
285+.text-lg {
286+  font-size: 1.35rem;
287+  line-height: 1.15;
288+}
289+
290+.text-md {
291+  font-size: 1.15rem;
292+  line-height: 1.15;
293+}
294+
295+.text-sm {
296+  font-size: 0.875rem;
297+}
298+
299+.text-center {
300+  text-align: center;
301+}
302+
303+.text-underline {
304+  border-bottom: 3px solid var(--text-color);
305+  padding-bottom: 3px;
306+}
307+
308+.font-bold {
309+  font-weight: bold;
310+}
311+
312+.font-italic {
313+  font-style: italic;
314+}
315+
316+.inline {
317+  display: inline;
318+}
319+
320+.inline-block {
321+  display: inline-block;
322+}
323+
324+.max-w-half {
325+  max-width: 50%;
326+}
327+
328+.flex {
329+  display: flex;
330+}
331+
332+.flex-col {
333+  flex-direction: column;
334+}
335+
336+.items-center {
337+  align-items: center;
338+}
339+
340+.m-0 {
341+  margin: 0;
342+}
343+
344+.mt {
345+  margin-top: 0.5rem;
346+}
347+
348+.mt-2 {
349+  margin-top: 1rem;
350+}
351+
352+.mt-4 {
353+  margin-top: 2rem;
354+}
355+
356+.mt-8 {
357+  margin-top: 4rem;
358+}
359+
360+.mb {
361+  margin-bottom: 0.5rem;
362+}
363+
364+.mb-2 {
365+  margin-bottom: 1rem;
366+}
367+
368+.mb-4 {
369+  margin-bottom: 2rem;
370+}
371+
372+.mb-8 {
373+  margin-bottom: 4rem;
374+}
375+
376+.mb-16 {
377+  margin-bottom: 8rem;
378+}
379+
380+.mr {
381+  margin-right: 0.5rem;
382+}
383+
384+.ml-sm {
385+  margin-left: 0.25rem;
386+}
387+
388+.ml {
389+  margin-left: 0.5rem;
390+}
391+
392+.my {
393+  margin-top: 0.5rem;
394+  margin-bottom: 0.5rem;
395+}
396+
397+.my-2 {
398+  margin-top: 1rem;
399+  margin-bottom: 1rem;
400+}
401+
402+.my-4 {
403+  margin-top: 2rem;
404+  margin-bottom: 2rem;
405+}
406+
407+.my-8 {
408+  margin-top: 4rem;
409+  margin-bottom: 4rem;
410+}
411+
412+.mx {
413+  margin-left: 0.5rem;
414+  margin-right: 0.5rem;
415+}
416+
417+.mx-2 {
418+  margin-left: 1rem;
419+  margin-right: 1rem;
420+}
421+
422+.p-0 {
423+  padding: 0;
424+}
425+
426+.py {
427+  padding-top: 0.5rem;
428+  padding-bottom: 0.5rem;
429+}
430+
431+.py-2 {
432+  padding-top: 1rem;
433+  padding-bottom: 1rem;
434+}
435+
436+.py-4 {
437+  padding-top: 2rem;
438+  padding-bottom: 2rem;
439+}
440+
441+.py-8 {
442+  padding-top: 4rem;
443+  padding-bottom: 4rem;
444+}
445+
446+.justify-between {
447+  justify-content: space-between;
448+}
449+
450+.justify-center {
451+  justify-content: center;
452+}
453+
454+.gap {
455+  gap: 0.5rem;
456+}
457+
458+.gap-2 {
459+  gap: 1rem;
460+}
461+
462+.group {
463+  display: flex;
464+  flex-direction: column;
465+  gap: 0.5rem;
466+}
467+
468+.group-h {
469+  display: flex;
470+  gap: 0.5rem;
471+  align-items: center;
472+}
473+
474+.flex-1 {
475+  flex: 1;
476+}
477+
478+.items-end {
479+  align-items: end;
480+}
481+
482+.items-start {
483+  align-items: start;
484+}
485+
486+.justify-end {
487+  justify-content: end;
488+}
489+
490+.font-grey-light {
491+  color: var(--grey-light);
492+}
493+
494+.hidden {
495+  display: none;
496+}
497+
498+.align-right {
499+  text-align: right;
500+}
501+
502+/* ==== HELPERS ==== */
503+
504+.logo-header {
505+  line-height: 1;
506+  display: inline-block;
507+  background-image: linear-gradient(to right, #FF5555, #FF79C6, #F8F859);
508+  color: transparent;
509+  background-clip: text;
510+  border: 3px solid #FF79C6;
511+  padding: 8px 10px 10px 10px;
512+  border-radius: 10px;
513+  box-shadow: 0px 5px 0px 0px var(--shadow);
514+}
515+
516+.btn-icon {
517+  border: 3px solid hsl(var(--main-hue), 92%, 66%);
518+  background-color: hsl(var(--main-hue), 92%, 66%);
519+  padding: 0.25rem 0.3rem;
520+  border-radius: 0.25rem;
521+  box-shadow: 0px 5px 0px 0px var(--shadow);
522+  color: var(--white);
523+  cursor: pointer;
524+}
525+
526+.btn-link {
527+  border: 3px solid hsl(var(--main-hue), 92%, 66%);
528+  background-color: hsl(var(--main-hue), 92%, 66%);
529+  padding: 0.5rem 1rem;
530+  border-radius: 0.25rem;
531+  box-shadow: 0px 5px 0px 0px var(--shadow);
532+  color: var(--white);
533+  text-decoration: none;
534+  font-weight: bold;
535+}
536+
537+.btn-link:visited:hover,
538+.btn-link:hover {
539+  border: 3px solid hsl(260, 92%, 66%);
540+  background-color: hsl(260, 92%, 66%);
541+  color: var(--white);
542+  transform: scale(.98, .98);
543+}
544+
545+.btn-link:visited {
546+  color: var(--white);
547+}
548+
549+.box {
550+  border: 2px solid var(--grey-light);
551+  border-radius: .5rem;
552+  padding: 1rem;
553+  text-decoration: none;
554+  box-shadow: 0px 5px 0px 0px var(--shadow);
555+  color: var(--white);
556+}
557+
558+.box:hover {
559+  border: 2px solid var(--white);
560+}
561+
562+.box:visited,
563+.box:visited:hover,
564+.box:hover {
565+  color: var(--white);
566+}
567+
568+@media only screen and (max-width: 600px) {
569+  body {
570+    padding: 0 1rem;
571+  }
572+
573+  header {
574+    margin: 0;
575+  }
576+}