From ff024740a4cf8a52eb1e8b51baf641761706f801 Mon Sep 17 00:00:00 2001 From: Jean-Marie 'Histausse' Mineau Date: Mon, 20 Apr 2026 14:13:32 +0200 Subject: [PATCH] add support for page summary and summary cards --- lib/custom_html.typ | 7 +++ lib/html_body.typ | 2 +- lib/main.typ | 4 +- lib/summary.typ | 136 +++++++++++++++++++++++++++++++++++++++++ test_template/main.typ | 34 +++++++++-- 5 files changed, 176 insertions(+), 7 deletions(-) create mode 100644 lib/summary.typ diff --git a/lib/custom_html.typ b/lib/custom_html.typ index 6ae24c1..64d666b 100644 --- a/lib/custom_html.typ +++ b/lib/custom_html.typ @@ -24,3 +24,10 @@ html.elem("image-magnifier-group", attrs: (role: "radiogroup"), body) } #let image-alt-group = html.elem.with("image-alt-group") + +#let summary-card = html.elem.with("summary-card") +#let summary-card-preview = html.elem.with("summary-card-preview") +#let summary-card-description = html.elem.with("summary-card-description") +#let summary-card-details = html.elem.with("summary-card-details") + +#let summary-card-list = html.elem.with("summary-card-list") diff --git a/lib/html_body.typ b/lib/html_body.typ index 98e4e56..334629d 100644 --- a/lib/html_body.typ +++ b/lib/html_body.typ @@ -65,7 +65,7 @@ site-container { display: flex; flex-direction: column; - width: 1050px; + max-width: 1510px; padding: 0 20px; header { diff --git a/lib/main.typ b/lib/main.typ index fa4ec47..0a6db10 100644 --- a/lib/main.typ +++ b/lib/main.typ @@ -1,12 +1,13 @@ #import "./html_head.typ": html_head #import "./html_body.typ": html_body #import "./html_utils.typ": html_show +#import "./summary.typ": summary, card-list /// Mail template function #let webpage( /// Page url - url, + url: none, /// Title of the page, default to document.title title: none, /// Use only for html 'lang' attribute. @@ -41,6 +42,7 @@ /// Body of the page body ) = { + assert(type(url) == str, message: "A page must have an url") show: html_show html.html(lang: lang, { html_head( diff --git a/lib/summary.typ b/lib/summary.typ new file mode 100644 index 0000000..0685db9 --- /dev/null +++ b/lib/summary.typ @@ -0,0 +1,136 @@ +#import "./custom_html.typ" as chtml + +/// Generate a "card" fom a page summary. +#let gen_summary_card(summ) = { + ```raw-css + summary-card { + display: flex; + flex-direction: column; + max-width: 400px; + + a { + color: inherit; + text-decoration: inherit; + } + + padding: 1em; + margin: 1em; + border: solid; + border-radius: 1em; + + p { + margin: 0; + } + + summary-card-preview { + display: block; + width: 100%; + + img { + width: 100%; + height: 100%; + object-fit: contain; + } + } + + summary-card-description { + display: flex; + flex-direction: column; + text-align: left; + height: 100%; + + h3 { + text-align: center; + margin: 0.5em; + } + + summary-card-details { + margin-top: auto; + padding-top: 0.5em; + } + } + + } + ``` + chtml.summary-card({ + chtml.summary-card-preview( + html.a(href: summ.template-args.url, summ.preview-image) + ) + chtml.summary-card-description({ + heading(level: 2, html.a(href: summ.template-args.url, summ.document-args.title)) + + html.a(href: summ.template-args.url, summ.document-args.description) + + chtml.summary-card-details(summ.document-args.date.display()) + }) + }) +} + +/// Summary of a page. +/// 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. +#let summary( + /// The url of the page + url: none, + /// The title of the page + title: none, + /// The image preview of the page. + /// Right now, this cannot be used for link preview because open graph expect an url for the image, and typst inline + /// the images directly in the html file in base64. + preview-image: none, + /// The author or authors of the page + author: none, + /// A description of the page + description: none, + /// The date of publication (or maybe update?) of the page. + date: none, +) = { + assert(type(url) == str, message: "summary() must have an url") + 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(author) != none, message: "summary() must have at least one author") + assert(type(description) != none, message: "summary() must have a description") + assert(type(date) != none, message: "summary() must have a date") + + let summ = ( + document-args: ( + title: title, + author: author, + description: description, + date: date, + ), + template-args: ( + url: url, + ), + preview-image: preview-image, + card: [] + ) + summ.card = gen_summary_card(summ) + return summ +} + +/// Display a list of summary cards. +/// +/// min-width is the minimum width of the cards, in px. +#let card-list(min-width: 400, summs) = { + let class-name = "summary-card-list-" + str(min-width) + raw( + ``` + summary-card-list. { + display: grid; + width: 100%; + grid-template-columns: repeat(auto-fill, minmax(min(100%, px), 1fr)); + + summary-card { + max-width: none; + } + } + ```.text.replace("", class-name).replace("", str(min-width)), + lang: "raw-css", + ) + chtml.summary-card-list(attrs: (class: class-name), { + for summ in summs { + summ.card + } + }) +} diff --git a/test_template/main.typ b/test_template/main.typ index 12023e6..51de1f8 100644 --- a/test_template/main.typ +++ b/test_template/main.typ @@ -1,15 +1,22 @@ #import "@local/template-web:0.0.1": * -#set document( +#let summ = summary( + url: "http://test.example.com", title: "TeTyTe", + preview-image: image( + "./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.", + ), author: "Me!", description: "Test of the TTT template", date: datetime(year: 1942, month: 4, day: 1), ) - +#set document( + ..summ.document-args +) #show: webpage.with( - "http://test.example.com", + ..summ.template-args, home: link( "http://test.example.com", image( @@ -51,6 +58,8 @@ #lorem(400) +#summ.card + Test, `this is not a code block`, end test. ```python @@ -66,7 +75,7 @@ def plopliplop(n: int) print(i) ``` - +/* #figure({ show table: set text(size: 0.80em) table( @@ -97,6 +106,7 @@ def plopliplop(n: int) caption: [Comparison of API methods between documentation and emulators], ) +*/ ```raw-css table { @@ -117,7 +127,7 @@ thead { border-bottom: 1px solid #999999; } ``` - +/* #table( columns: 5, //inset: (x: 0% + 5pt, y: 0% + 2pt), @@ -135,6 +145,7 @@ thead { [34], [605106], [605098], [26], [18], table.hline(), ) +*/ #figure( image( @@ -150,3 +161,16 @@ thead { ), caption: [A Big Platypus!] ) + +#card-list( + range(1, 21).map(i => + summary( + url: "http://test.example.com", + title: "Card " + str(i), + preview-image: summ.preview-image, + author: "Me!", + description: lorem(10 * calc.rem(i * 123, 10)), + date: datetime(year: 2000, month: 12, day: i), + ) + ) +)