generate the summary and the document objects from inside the webpage() function

This commit is contained in:
Jean-Marie 'Histausse' Mineau 2026-06-17 23:25:39 +02:00
parent 500a6ad181
commit f7db139b0d
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
10 changed files with 234 additions and 144 deletions

View file

@ -2,7 +2,7 @@
#import "./html_body.typ": html-body #import "./html_body.typ": html-body
#import "./html_utils.typ": html-show, reset-page-states #import "./html_utils.typ": html-show, reset-page-states
#import "./summary.typ": summary, card-list #import "./summary.typ": summary, card-list
#import "./states.typ": current-page-label #import "./states.typ": current-page-label, state-page-summaries
#import "./pyscript.typ": state-use-pyscript, state-pyscript-data-list, state-pyscript-version, state-pyscript-interpreters, state-pyscript-default-interpreter, pyscript-show, pyscript-data #import "./pyscript.typ": state-use-pyscript, state-pyscript-data-list, state-pyscript-version, state-pyscript-interpreters, state-pyscript-default-interpreter, pyscript-show, pyscript-data
#import "./rss.typ": rss #import "./rss.typ": rss
#import "./icons.typ" #import "./icons.typ"
@ -14,10 +14,18 @@
base-url: none, base-url: none,
/// The url path of the page (full url of the page is base-url + path), eg: "/index.html" /// The url path of the page (full url of the page is base-url + path), eg: "/index.html"
path: none, path: none,
/// Title of the page, default to document.title /// Title of the page
title: none, title: none,
/// Use only for html 'lang' attribute. /// Use only for html 'lang' attribute.
lang: "en", lang: "en",
/// Date of publication
date: none,
/// Label of the page (for links)
page-label: none,
/// Preview image
preview-image: [],
/// The copyright for the preview image
preview-img-copyright: none,
//-- <head> only args -- //-- <head> only args --
/// Website icon, *needs* to be path (TODO: fix when typst support multi-file out) /// Website icon, *needs* to be path (TODO: fix when typst support multi-file out)
icon: none, icon: none,
@ -25,9 +33,9 @@
og-type: "website", og-type: "website",
/// Name of the site for metadata of the page /// Name of the site for metadata of the page
site-name: none, site-name: none,
/// Description of the site for metadata, default to document.description /// Description of the site for metadata
description: none, description: none,
/// Author of the site for metadata, default to document.author /// Author of the site for metadata
author: none, author: none,
/// Tags describing the content of the page /// Tags describing the content of the page
tags: (), tags: (),
@ -35,8 +43,6 @@
stylesheets: (), stylesheets: (),
/// List of related sites for metadata /// List of related sites for metadata
me-links: (), me-links: (),
/// Label of the page (for links)
page-label: none,
/// Dictionnary of available pyscript-data for each versions of pyscript /// Dictionnary of available pyscript-data for each versions of pyscript
/// expected in the form of ("<version>": pyscript-data-list("<url>", { html.link(...) }), ...) /// expected in the form of ("<version>": pyscript-data-list("<url>", { html.link(...) }), ...)
pyscript-data-list: (:), pyscript-data-list: (:),
@ -63,7 +69,39 @@
) = { ) = {
assert(type(base-url) == str, message: "A page must have a base url") assert(type(base-url) == str, message: "A page must have a base url")
assert(type(path) == str, message: "A page must have a path") assert(type(path) == str, message: "A page must have a path")
assert(type(title) == str or type(title) == content, message: "A page must have title")
//assert(type(preview-image) != none, message: "summary() must have a preview-image")
assert(author != none, message: "A page must have at least one author")
assert(description != none, message: "A page must have a description")
assert(date != none, message: "A page must have a date")
if page-label == none {
page-label = label(path)
}
state-page-summaries.update(
x => x + (
summary(
url: base-url + path,
title: title,
preview-image: preview-image,
img-copyright: preview-img-copyright,
author: author,
description: description,
date: date,
tags: tags,
page-label: page-label,
)
,)
)
[#document(
path,
title: title,
//author: author,
description: description,
date: date,
{
context { context {
state-pyscript-data-list.update(x => pyscript-data-list) state-pyscript-data-list.update(x => pyscript-data-list)
state-pyscript-interpreters.update(x => pyscript-interpreters) state-pyscript-interpreters.update(x => pyscript-interpreters)
@ -102,3 +140,5 @@
reset-page-states() reset-page-states()
}) })
} }
) #page-label]
}

View file

@ -63,12 +63,12 @@
).map(it => xml-tag( ).map(it => xml-tag(
"item", "item",
children: ( children: (
xml-tag("title", body: it.document-args.title), xml-tag("title", body: it.title),
xml-tag("link", body: it.template-args.base-url + it.template-args.path), xml-tag("link", body: it.url),
xml-tag("guid", body: it.template-args.base-url + it.template-args.path), xml-tag("guid", body: it.url),
xml-tag("description", body: it.document-args.description), xml-tag("description", body: it.description),
xml-tag("pubDate", body: it.document-args.date.display(date-format-rfc822)), xml-tag("pubDate", body: it.date.display(date-format-rfc822)),
) + it.template-args.tags.map(tag => xml-tag("category", body: tag)) ) + it.tags.map(tag => xml-tag("category", body: tag))
)) ))
xml-tag( xml-tag(
"rss", "rss",

View file

@ -61,3 +61,6 @@
reset-pyscript-page-states() reset-pyscript-page-states()
} }
// Site wide state
#let state-page-summaries = state("state-page-summaries", ())

View file

@ -81,18 +81,18 @@
``` ```
chtml.summary-card({ chtml.summary-card({
chtml.summary-card-preview({ chtml.summary-card-preview({
link(summ.template-args.page-label, summ.preview-image) link(summ.page-label, summ.preview-image)
if summ.img-copyright != none { if summ.img-copyright != none {
html.small[Image: #sym.copyright #summ.img-copyright] html.small[Image: #sym.copyright #summ.img-copyright]
} }
}) })
chtml.summary-card-description({ chtml.summary-card-description({
heading(level: 2, link(summ.template-args.page-label, summ.document-args.title)) heading(level: 2, link(summ.page-label, summ.title))
link(summ.template-args.page-label, summ.document-args.description) link(summ.page-label, summ.description)
chtml.summary-card-details(summ.document-args.date.display()) chtml.summary-card-details(summ.date.display())
chtml.tag-box(for tag in summ.template-args.tags { html.span(class: ("tag",), "#" + tag) }) chtml.tag-box(for tag in summ.tags { html.span(class: ("tag",), "#" + tag) })
}) })
}) })
} }
@ -101,10 +101,8 @@
/// Store data form `set document(...)` and `show: webpage.with(...)` in `summ.document-args` and `summ.template-args`, /// Store data form `set document(...)` and `show: webpage.with(...)` in `summ.document-args` and `summ.template-args`,
/// and generate a summary card that can be used as a link for the page. /// and generate a summary card that can be used as a link for the page.
#let summary( #let summary(
/// The base url of the site (eg: "http://test.example.com") /// The url of the page
base-url: none, url: none,
/// The url path of the page (full url of the page is base-url + path), eg: "/index.html"
path: none,
/// The title of the page /// The title of the page
title: none, title: none,
/// The image preview of the page. /// The image preview of the page.
@ -124,31 +122,24 @@
/// Label of the page (for links) /// Label of the page (for links)
page-label: none, page-label: none,
) = { ) = {
assert(type(base-url) == str, message: "summary() must have a base url") assert(type(url) == str, message: "summary() must have an url")
assert(type(path) == str, message: "summary() must have a path")
assert(type(title) == str or type(title) == content, message: "summary() must have title") assert(type(title) == str or type(title) == content, message: "summary() must have title")
assert(type(preview-image) != none, message: "summary() must have a preview-image") assert(type(preview-image) != none, message: "summary() must have a preview-image")
assert(type(author) != none, message: "summary() must have at least one author") assert(author != none, message: "summary() must have at least one author")
assert(type(description) != none, message: "summary() must have a description") assert(description != none, message: "summary() must have a description")
assert(type(date) != none, message: "summary() must have a date") assert(date != none, message: "summary() must have a date")
if page-label == none { if page-label == none {
page-label = label(path) page-label = label(path)
} }
let summ = ( let summ = (
document-args: ( url: url,
title: title, title: title,
author: author,
description: description, description: description,
date: date, date: date,
),
template-args: (
base-url: base-url,
path: path,
tags: tags, tags: tags,
page-label: page-label, page-label: page-label,
),
path: path, path: path,
preview-image: preview-image, preview-image: preview-image,
img-copyright: img-copyright, img-copyright: img-copyright,
@ -159,9 +150,9 @@
} }
#let summary-sort-key(summ) = -( #let summary-sort-key(summ) = -(
summ.document-args.date.day()-1 + 31 * ( summ.date.day()-1 + 31 * (
(summ.document-args.date.month()-1) + (summ.date.month()-1) +
12 * summ.document-args.date.year() 12 * summ.date.year()
) )
) )

View file

@ -1,12 +1,14 @@
#import "@local/template-web:0.0.1": webpage as webpage-org, icons #import "@local/template-web:0.0.1": webpage as webpage-org, icons
#let webpage = webpage-org.with( #let webpage = webpage-org.with(
base-url: "http://test.example.com",
logo: image( logo: image(
"/assets/platypus.png", "/assets/platypus.png",
alt: "A drawing of a blue-ish round-ish platypus with big eyes, holding a laptop. This platypus is quite cute, but I might be biased.", alt: "A drawing of a blue-ish round-ish platypus with big eyes, holding a laptop. This platypus is quite cute, but I might be biased.",
height: 100pt, height: 100pt,
width: 100pt, // TODO 0.15 regression? in 0.14 setting the height was enough width: 100pt, // TODO 0.15 regression? in 0.14 setting the height was enough
), ),
author: "Me!",
footer: context [ footer: context [
#sym.copyright #document.date.display("[year]") Histausse \ #sym.copyright #document.date.display("[year]") Histausse \
@ -22,7 +24,7 @@
height: 2em, height: 2em,
) )
),*/ ),*/
html.a(href: "http://test.example.com", aria-label: "Home", icons.home-icon), // /!\ aria-label is important for accessibility /!\ html.a(href: "/", aria-label: "Home", icons.home-icon), // /!\ aria-label is important for accessibility /!\
html.a(href: "/feed.rss", aria-label: "RSS feed", icons.rss-icon), html.a(href: "/feed.rss", aria-label: "RSS feed", icons.rss-icon),
), ),
menu: [ menu: [

View file

@ -1,26 +1,8 @@
#import "@local/template-web:0.0.1": rss #import "@local/template-web:0.0.1": rss, state-page-summaries
#import "pages/index.typ": summ as summ-index
#document(
"index.html",
..summ-index.document-args,
include "/pages/index.typ"
) <index-page>
#import "pages/pyscript.typ": summ as summ-pyscript
#document(
"pycript.html",
..summ-pyscript.document-args,
include "/pages/pyscript.typ"
) <pyscript-page>
#import "pages/cards.typ": summ as summ-cards, summaries
#document(
"cards.html",
..summ-cards.document-args,
include "/pages/cards.typ"
) <cards-page>
#include "/pages/index.typ"
#include "/pages/pyscript.typ"
#include "/pages/cards.typ"
#asset( #asset(
"/img/platypus.png", "/img/platypus.png",
@ -35,14 +17,14 @@
read("assets/isn_s_cube-0.1.0-py3-none-any.whl", encoding: none), read("assets/isn_s_cube-0.1.0-py3-none-any.whl", encoding: none),
) )
#asset( #context asset(
"feed.rss", "feed.rss",
rss( rss(
"TeTyTe test typst template", "TeTyTe test typst template",
"https://test.example.com", "https://test.example.com",
"Test of the TTT template", "Test of the TTT template",
"https://test.example.com/rss.rss", "https://test.example.com/rss.rss",
summaries, state-page-summaries.final(),
webmaster: "me@example.com (Me)", webmaster: "me@example.com (Me)",
) )
) )

File diff suppressed because one or more lines are too long

View file

@ -1,23 +1,18 @@
#import "@local/template-web:0.0.1": * #import "@local/template-web:0.0.1": *
#import "/lib.typ": webpage #import "/lib.typ": webpage
#let summ = summary( #let preview-image = image(
base-url: "http://test.example.com",
path: "/cards.html",
title: "Summary cards",
page-label: <cards-page>,
preview-image: image(
"/assets/platypus.png", "/assets/platypus.png",
alt: "A drawing of a blue-ish round-ish platypus with big eyes, holding a laptop. This platypus is quite cute, but I might be biased.", alt: "A drawing of a blue-ish round-ish platypus with big eyes, holding a laptop. This platypus is quite cute, but I might be biased.",
), )
author: "Me!", #show: webpage.with(
tags: ("test", "html/css", "typst"), path: "/cards.html",
title: "Summary cards",
description: "Showcase the summary card system", description: "Showcase the summary card system",
date: datetime(year: 1942, month: 4, day: 1), date: datetime(year: 1942, month: 4, day: 1),
) tags: ("test", "html/css", "typst"),
page-label: <cards-page>,
#show: webpage.with( preview-image: preview-image,
..summ.template-args,
header: [ header: [
= Summary Cards = Summary Cards
Showcase summary cards Showcase summary cards
@ -25,21 +20,20 @@
) )
#summ.card #context state-page-summaries.at(here()).last().card
#let perm = (17, 6, 20, 19, 15, 5, 13, 11, 14, 12, 16, 10, 2, 3, 1, 9, 7, 4, 18, 8) #let perm = (17, 6, 20, 19, 15, 5, 13, 11, 14, 12, 16, 10, 2, 3, 1, 9, 7, 4, 18, 8)
#let summaries = range(20).map(i => #let summaries = range(20).map(i =>
summary( summary(
base-url: "http://test.example.com", url: "https://example.com/tst/" + str(perm.at(i)),
path: "/tst/" + str(perm.at(i)),
title: "Card " + str(perm.at(i)), title: "Card " + str(perm.at(i)),
tags: if perm.at(i) == 20 { tags: if perm.at(i) == 20 {
("tag2", "tag5","loooooonnnnnnnnnnnnnng-tag","some-tag","some-other-tag") ("tag2", "tag5","loooooonnnnnnnnnnnnnng-tag","some-tag","some-other-tag")
} else { } else {
(2, 3, 5, 7).filter(j => calc.rem(perm.at(i), j) == 0).map(j => "tag" + str(j)) (2, 3, 5, 7).filter(j => calc.rem(perm.at(i), j) == 0).map(j => "tag" + str(j))
}, },
preview-image: summ.preview-image, preview-image: preview-image,
img-copyright: if calc.rem(i, 3) == 0 { [Histausse ] } else { none }, img-copyright: if calc.rem(i, 3) == 0 { [Histausse ] } else { none },
author: "Me!", author: "Me!",
description: lorem(10 * calc.rem(i * 123, 10)), description: lorem(10 * calc.rem(i * 123, 10)),

View file

@ -1,29 +1,28 @@
#import "@local/template-web:0.0.1": * #import "@local/template-web:0.0.1": *
#import "/lib.typ": webpage #import "/lib.typ": webpage
#let summ = summary( #show: webpage.with(
base-url: "http://test.example.com",
path: "/index.html", path: "/index.html",
page-label: <index-page>,
title: "TeTyTe", title: "TeTyTe",
description: "Test of the TTT template",
date: datetime(year: 1942, month: 4, day: 1),
tags: ("test", "html/css", "typst"),
page-label: <index-page>,
preview-image: image( preview-image: image(
"/assets/platypus.png", "/assets/platypus.png",
alt: "A drawing of a blue-ish round-ish platypus with big eyes, holding a laptop. This platypus is quite cute, but I might be biased.", alt: "A drawing of a blue-ish round-ish platypus with big eyes, holding a laptop. This platypus is quite cute, but I might be biased.",
), ),
author: "Me!",
tags: ("test", "html/css", "typst"),
description: "Test of the TTT template",
date: datetime(year: 1942, month: 4, day: 1),
)
#show: webpage.with(
..summ.template-args,
header: [ header: [
= Test TeTyTe = Test TeTyTe
Hello World! Hello World!
], ],
) )
#context card-list(
min-width: 200,
state-page-summaries.final(),
)
#lorem(400) #lorem(400)

View file

@ -1,23 +1,17 @@
#import "@local/template-web:0.0.1": * #import "@local/template-web:0.0.1": *
#import "/lib.typ": webpage #import "/lib.typ": webpage
#let summ = summary( #show: webpage.with(
base-url: "http://test.example.com",
path: "/pycript.html", path: "/pycript.html",
title: "TeTyTe", title: "TeTyTe",
page-label: <pyscript-label>, description: "Demonstrate how to use pyscript to run python in the browser",
tags: ("test", "html/css", "typst", "python"),
date: datetime(year: 1942, month: 4, day: 1),
page-label: <pyscript-page>,
preview-image: image( preview-image: image(
"/assets/platypus.png", "/assets/platypus.png",
alt: "A drawing of a blue-ish round-ish platypus with big eyes, holding a laptop. This platypus is quite cute, but I might be biased.", alt: "A drawing of a blue-ish round-ish platypus with big eyes, holding a laptop. This platypus is quite cute, but I might be biased.",
), ),
author: "Me!",
tags: ("test", "html/css", "typst", "pyscript"),
description: "Demonstrate how to use pyscript to run python in the browser",
date: datetime(year: 1942, month: 4, day: 1),
)
#show: webpage.with(
..summ.template-args,
header: [ header: [
= Showcase Pyscript = Showcase Pyscript
Show how to run Python in the browser Show how to run Python in the browser
@ -109,4 +103,3 @@ pprint([(k, v["title"]) for k, v in data.items()][:10])
from isn_s_cube import wasm from isn_s_cube import wasm
await wasm() await wasm()
``` ```