repos
/ orchard main

orchard

mirror

Every site I host, in one repo, along with the Cloudflare Tunnel and Caddy that front them. It's all Go, Vite, and SQLite, and it runs on a desktop at home with nothing listening on an inbound port.

blogbuncaddycloudflare-tunneldockergogolanghomelabhtml-templatemonorepoself-hostedseosqlitestatic-sitetypstuptime-monitoringviteweb-analytics

7.1 KB · 212 lines · HTML Raw History
  1{{define "panel-open"}}
  2<section class="panel" data-panel="{{.Slug}}">
  3  <div class="bracket tl"></div><div class="bracket tr"></div>
  4  <div class="bracket bl"></div><div class="bracket br"></div>
  5  <header class="panel-head">
  6    <span class="idx">{{.Index}}</span>
  7    <h2>{{.Title}}</h2>
  8    <span class="rule"></span>
  9    {{if .Meta}}<span class="panel-meta">{{.Meta}}</span>{{end}}
 10  </header>
 11{{end}}
 12
 13{{define "card"}}
 14<article class="card" data-dir="{{.Direction}}" data-key="{{.Key}}">
 15  <header>
 16    <h3>{{.Label}}</h3>
 17    <span class="sym">{{if .Note}}{{.Note}}{{else}}{{.Symbol}}{{end}}</span>
 18  </header>
 19  {{if .Unavailable}}
 20    <p class="price dim">NO SIGNAL</p>
 21    <p class="move"><span class="pts">&mdash;</span></p>
 22  {{else}}
 23    <p class="price" data-price>{{.Price}}</p>
 24    <p class="move">
 25      <span class="glyph"></span>
 26      <span class="pts">{{.Change}}</span>
 27      <span class="pct">{{.Percent}}</span>
 28    </p>
 29  {{end}}
 30  {{template "spark" .Spark}}
 31</article>
 32{{end}}
 33
 34{{/*
 35  The baseline runs the full width and the line only as far as the session has
 36  got, so the empty right hand side is the rest of the day rather than missing
 37  data. preserveAspectRatio is none, so a circle would come out an ellipse and
 38  the cursor at the live end has to be a vertical rule.
 39*/}}
 40{{define "spark"}}
 41<svg class="spark" viewBox="0 0 100 32" preserveAspectRatio="none" aria-hidden="true" focusable="false">
 42  {{if .Line}}
 43  <path class="spark-area" d="{{path .Area}}"></path>
 44  {{if .HasBase}}<line class="spark-base" x1="0" x2="100" y1="{{.Baseline}}" y2="{{.Baseline}}"></line>{{end}}
 45  <path class="spark-line" d="{{path .Line}}"></path>
 46  {{if .Closed}}<line class="spark-shut" x1="{{.Span}}" x2="{{.Span}}" y1="0" y2="32"></line>
 47  {{else if .Partial}}<line class="spark-now" x1="{{.Span}}" x2="{{.Span}}" y1="0" y2="32"></line>{{end}}
 48  {{end}}
 49</svg>
 50{{end}}
 51
 52{{define "stories"}}
 53<ol class="stories">
 54  {{range $i, $s := .}}
 55  <li>
 56    <span class="rank">{{printf "%02d" (inc $i)}}</span>
 57    <div class="body">
 58      <a class="title" href="{{$s.URL}}" rel="noopener noreferrer" target="_blank">{{$s.Title}}</a>
 59      <div class="meta">
 60        {{if $s.Host}}<span class="host">{{$s.Host}}</span>{{end}}
 61        <span class="pts">{{$s.Points}}<span class="unit">PTS</span></span>
 62        <a class="cmt" href="{{$s.Comments}}" rel="noopener noreferrer" target="_blank">{{$s.Count}}<span class="unit">CMT</span></a>
 63        {{if $s.Age}}<span class="age">{{$s.Age}}</span>{{end}}
 64      </div>
 65    </div>
 66  </li>
 67  {{else}}
 68  <li class="empty"><span class="rank">--</span><div class="body">AWAITING FEED</div></li>
 69  {{end}}
 70</ol>
 71{{end}}
 72
 73{{define "headline"}}
 74<li>
 75  <span class="tag">{{.Source}}</span>
 76  <a href="{{.URL}}" rel="noopener noreferrer" target="_blank">{{.Title}}</a>
 77  <span class="age">{{.Age}}</span>
 78</li>
 79{{end}}
 80
 81{{define "condition"}}
 82<li data-state="{{.State}}">
 83  <span class="k">{{.Label}}</span>
 84  <span class="v">{{.Value}}</span>
 85  <span class="n">{{.Note}}</span>
 86  <span class="meter">
 87    <i class="fill" style="width:{{.Fill}}%"></i>
 88    {{range .Ticks}}<i class="tick" style="left:{{.}}%"></i>{{end}}
 89  </span>
 90</li>
 91{{end}}
 92
 93{{define "earning-reported"}}
 94<li class="done" data-dir="{{.Dir}}">
 95  <span class="tkr">{{.Symbol}}</span>
 96  <span class="co">{{.Name}}</span>
 97  <span class="move">{{.Move}}</span>
 98  <span class="detail">
 99    <b data-verdict="{{.Verdict}}">{{.Verdict}}</b>
100    <span class="figs">{{.Actual}} v {{.Forecast}}</span>
101    <span class="on">{{.Day}}</span>
102    {{if .Note}}<span class="note">{{.Note}}</span>{{end}}
103  </span>
104</li>
105{{end}}
106
107{{define "earning-upcoming"}}
108<li class="next">
109  <span class="tkr">{{.Symbol}}</span>
110  <span class="co">{{.Name}}</span>
111  <span class="day">{{.Day}}{{if .When}} <span class="when">{{.When}}</span>{{end}}</span>
112  <span class="detail">
113    <span class="figs">EST {{.Est}}</span>
114    {{if .Ests}}<span class="on">{{.Ests}} ESTS</span>{{end}}
115  </span>
116</li>
117{{end}}
118
119{{define "outlook"}}
120<li data-verdict="{{.Verdict}}">
121  <div class="head">
122    <span class="d">{{.Day}} {{.Date}}</span>
123    <span class="temps">{{.High}}&deg;<i>/</i>{{.Low}}&deg;</span>
124    <span class="v">{{.Verdict}}</span>
125  </div>
126  <div class="factors">
127    {{range .Factors}}
128    <div class="factor" data-score="{{.Score}}">
129      <span class="fk">{{.Label}}</span>
130      <span class="fbar"></span>
131      <span class="fv">{{.Value}}</span>
132      <span class="fd">{{.Detail}}</span>
133    </div>
134    {{end}}
135  </div>
136</li>
137{{end}}
138
139{{/*
140  The bar is the IMDb score and the tomatometer averaged onto one scale, since
141  the two numbers together are what anyone reads and a bar is quicker to compare
142  down a column than a pair of figures is. Both figures stay underneath it.
143*/}}
144{{define "title"}}
145<li>
146  {{if .URL}}<a class="name" href="{{.URL}}" rel="noopener noreferrer" target="_blank">{{.Name}}</a>{{else}}<span class="name">{{.Name}}</span>{{end}}
147  <span class="svc">{{.Provider}}</span>
148  <span class="rating" data-band="{{.ScoreBand}}">
149    <span class="pct">{{.Score}}%</span>
150    <span class="track"><i style="width:{{.Score}}%"></i></span>
151    <span class="n">{{.ScoreFrom}}</span>
152  </span>
153  <span class="meta">
154    <span class="kind">{{.Kind}}{{if .Year}} {{.Year}}{{end}}</span>
155    <span class="score imdb" data-grade="{{.IMDbState}}">IMDB {{.IMDb}}</span>
156    {{if .Tomato}}<span class="score rt" data-grade="{{.TomatoState}}">RT {{.Tomato}}</span>{{end}}
157  </span>
158</li>
159{{end}}
160
161{{/*
162  The review line is Valve's own verdict and the count behind it, since a
163  percentage on its own says nothing about whether nine people or four hundred
164  thousand produced it.
165*/}}
166{{define "game"}}
167<li>
168  <a href="{{.URL}}" rel="noopener noreferrer" target="_blank">{{.Name}}</a>
169  <span class="pr">{{if gt .Discount 0}}<span class="disc">-{{.Discount}}%</span> {{end}}{{.Price}}</span>
170  {{if .Reviewed}}
171  <span class="rating" data-band="{{band .Rating}}" title="{{.Verdict}}">
172    <span class="pct">{{.Rating}}%</span>
173    <span class="track"><i style="width:{{.Rating}}%"></i></span>
174    <span class="n">{{.Reviews}}</span>
175  </span>
176  {{end}}
177  <span class="meta">
178    {{range .Tags}}<span class="tag">{{.}}</span>{{end}}
179    {{if .Players}}<span class="players">{{.Players}} PLAYING</span>{{end}}
180  </span>
181</li>
182{{end}}
183
184{{/*
185  The figures under one hour of the plot. The bar itself lives in the plot above
186  so that all eight can share a floor and a half way rule, which is what makes a
187  tall one readable rather than only comparable to its neighbours.
188*/}}
189{{define "hour"}}
190<div class="hour" data-warm="{{.Warm}}" data-wet="{{if ge .Rain 50}}yes{{else}}no{{end}}">
191  <span class="hp">{{.Rain}}%</span>
192  <span class="hv">{{.Temp}}&deg;</span>
193  <span class="ht">{{.Label}}</span>
194</div>
195{{end}}
196
197{{define "gauge"}}
198<div class="gauge" data-level="{{.Level}}">
199  <span class="gk">{{.Key}}</span>
200  {{if .Known}}
201    <span class="gv">{{.Value}}</span>
202    <span class="gbar"><i style="width:{{.Fill}}%"></i></span>
203    <span class="gb">{{.Band}}</span>
204    {{if .Note}}<span class="gn">{{.Note}}</span>{{end}}
205  {{else}}
206    <span class="gv dim">&mdash;</span>
207    <span class="gbar"></span>
208    <span class="gb">NO SIGNAL</span>
209  {{end}}
210</div>
211{{end}}