The code and data behind xeiaso.net
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

internal/lume: make pages for post series

I'm probably reading something wrong in the documentation for Lume, but
I wasn't able to find an obvious way to generate pages for each of the post
series programmatically.

This is a bit of a hacky workaround that makes the Lume driver write
individual JSX files for each series defined in the Dhall source. It
should work for my needs though.

Signed-off-by: Xe Iaso <me@xeiaso.net>

Xe Iaso df59f21f 782faa8d

+90
+61
internal/lume/lume.go
··· 5 5 "encoding/json" 6 6 "expvar" 7 7 "fmt" 8 + "html/template" 8 9 "io/fs" 9 10 "log" 10 11 "log/slog" ··· 339 340 } 340 341 } 341 342 343 + if err := f.writeSeriesPages(); err != nil { 344 + return err 345 + } 346 + 342 347 return nil 343 348 } 344 349 ··· 347 352 defer f.lock.RUnlock() 348 353 return f.conf.ClackSet 349 354 } 355 + 356 + func (f *FS) writeSeriesPages() error { 357 + seriesPageDir := filepath.Join(f.repoDir, f.opt.StaticSiteDir, "src", "blog", "series") 358 + 359 + for k, v := range f.conf.SeriesDescMap { 360 + fname := filepath.Join(seriesPageDir, fmt.Sprintf("%s.jsx", k)) 361 + 362 + fout, err := os.Create(fname) 363 + if err != nil { 364 + return fmt.Errorf("can't open %s: %w", fname, err) 365 + } 366 + defer fout.Close() 367 + 368 + if err := seriesPageTemplate.Execute(fout, struct { 369 + Series string 370 + Desc string 371 + }{ 372 + Series: k, 373 + Desc: v, 374 + }); err != nil { 375 + return fmt.Errorf("can't write %s: %w", fname, err) 376 + } 377 + } 378 + 379 + return nil 380 + } 381 + 382 + const seriesPageTemplateStr = `export const title = "{{.Series}}"; 383 + export const layout = "base.njk"; 384 + 385 + export default ({ search }) => { 386 + const dateOptions = { year: "numeric", month: "2-digit", day: "2-digit" }; 387 + 388 + return ( 389 + <div> 390 + <h1 className="text-3xl mb-4">{title}</h1> 391 + <p className="mb-4"> 392 + {{.Desc}} 393 + </p> 394 + 395 + <ul class="list-disc ml-4 mb-4"> 396 + {search.pages("series={{.Series}}", "order date=desc").map((post) => { 397 + const url = post.data.redirect_to ? post.data.redirect_to : post.data.url; 398 + return ( 399 + <li> 400 + <span className="font-mono">{post.data.date.toLocaleDateString("en-US", dateOptions)}</span> -{" "} 401 + <a href={url}>{post.data.title}</a> 402 + </li> 403 + ); 404 + })} 405 + </ul> 406 + </div> 407 + ); 408 + };` 409 + 410 + var seriesPageTemplate = template.Must(template.New("seriesPage.jsx.tmpl").Parse(seriesPageTemplateStr)) 350 411 351 412 func (f *FS) buildResume(ctx context.Context) error { 352 413 t0 := time.Now()
+2
lume/src/blog/series/.gitignore
··· 1 + *.jsx 2 + !index.jsx
+1
lume/src/blog/series/_data.yml
··· 1 + type: info
+26
lume/src/blog/series/index.jsx
··· 1 + export const title = "Post Series"; 2 + export const layout = "base.njk"; 3 + 4 + export default ({ seriesDescriptions }) => { 5 + const dateOptions = { year: "numeric", month: "2-digit", day: "2-digit" }; 6 + 7 + return ( 8 + <> 9 + <h1 className="text-3xl mb-4">{title}</h1> 10 + <p className="mb-4"> 11 + TODO: filler text here 12 + </p> 13 + 14 + <ul class="list-disc ml-4 mb-4"> 15 + {Object 16 + .keys(seriesDescriptions) 17 + .map((k) => [k, seriesDescriptions[k]]) 18 + .map(([k, v]) => ( 19 + <li> 20 + <a href={`/blog/series/${k}`}>{k}</a>: {v} 21 + </li> 22 + ))} 23 + </ul> 24 + </> 25 + ); 26 + };