diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..08d9f87 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +test_template diff --git a/lib.typ b/lib.typ deleted file mode 100644 index 8b13789..0000000 --- a/lib.typ +++ /dev/null @@ -1 +0,0 @@ - diff --git a/lib/custom_html.typ b/lib/custom_html.typ new file mode 100644 index 0000000..3892db7 --- /dev/null +++ b/lib/custom_html.typ @@ -0,0 +1,7 @@ +#let meta-og(property: "", content: "") = { + // "property" attr is not supported by html.meta ? + html.elem("meta", attrs: (property: property, content: content)) +} + +#let site-wrapper = html.elem.with("site-wrapper") +#let site-container = html.elem.with("site-container") diff --git a/lib/html_body.typ b/lib/html_body.typ new file mode 100644 index 0000000..2c1086e --- /dev/null +++ b/lib/html_body.typ @@ -0,0 +1,30 @@ +#import "./custom_html.typ" as chtml + +/// Make the body of the webpage +#let html_body( + /// The visible header of the page + header: [], + /// Logo of the site, must be an url (TODO) + logo, + /// Logo alt-text + logo_alt, + body +) = { + html.body({ + chtml.site-wrapper({ + chtml.site-container({ + html.header(style: "display: flex; flex-wrap: wrap-reverse;", { + html.hgroup({ + header + }) + // typst `image` function embed the image in the html, which is not great, + // and logo is also used for icon, so it's necessarily an url + if logo != none { + html.img(src: logo, alt: logo_alt, height: 100) // TODO: height bad + } + }) + body + }) + }) + }) +} diff --git a/lib/html_head.typ b/lib/html_head.typ new file mode 100644 index 0000000..11a0efc --- /dev/null +++ b/lib/html_head.typ @@ -0,0 +1,103 @@ +#import "./custom_html.typ" as chtml + +/// Generate the html element for the page. +#let html_head( + /// Page url, + url, + /// Title of the page + title, + /// Path to the icon (TODO: /!\ must be an url, typst image not yet supported) + icon, + /// Type of the page for open-graph data + og-type: "website", + /// Name of the site for metadata of the page + site-name: none, + /// Description of the site for metadata #TODO default to document.description + description: none, + /// Author of the site for metadata #TODO default to document.author + author: none, + /// Additional stylesheet for the page: must be a list of url + stylesheets: (), + /// List of related sites for metadata + me-links: (), +) = { + html.head({ + html.meta(charset: "utf-8") + html.title(title) + // html.meta(http-equiv: "Content-Language", content: "en") Obsolet, now use the html tag attr "lang" instead + + // The width=device-width part sets the width of the page to follow the screen-width of the device (which will vary depending on the device). + // The initial-scale=1.0 part sets the initial zoom level when the page is first loaded by the browser. + html.meta(name: "viewport", content: "width=device-width, initial-scale=1.0") + + // Only set the Referer header for out request to the same origin + html.meta(name: "referrer", content: "same-origin") + + if icon != none { + html.link(rel: "icon", type: "image/png", href: icon) + } + + // Open Graph (https://ogp.me/), used by social media for link previsualisation + chtml.meta-og(property: "og:title", content: repr(title)) + chtml.meta-og(property: "og:type", content: og-type) + chtml.meta-og(property: "og:url", content: url) + if icon != none { + chtml.meta-og(property: "og:image", content: icon) // TODO: right now the logo need to be the full URL + } + if site-name != none { + chtml.meta-og(property: "og:site_name", content: site-name) + } + if description != none { + chtml.meta-og(property: "og:description", content: description) + } + + // Check https://www.w3schools.com/tags/att_link_rel.asp for other interesting link rel + for stylesheet in stylesheets { + html.link(rel: "stylesheet", type: "text/css", href: stylesheet) + } + for me-link in me-links { + html.elem("link", attrs: (rel: "me", href: me-link)) + } + if description != none { + html.meta(name: "description", content: description) + } + if author != none { + html.meta(name: "author", content: author) + } + + ```raw-css + :root { + color-scheme: light dark; + &:has(#theme-light:checked) { + color-scheme: light; + } + &:has(#theme-dark:checked) { + color-scheme: dark; + } + + --color-border: light-dark(#414868, #414868); + } + site-wrapper { + display: flex; + flex-wrap: wrap; + width: 100%; + justify-content: center; + + site-container { + width: 1050px; + padding: 0 20px; + + header { + // display: flex + // flex-wrap: wrap; + justify-content: space-between; + align-items: center; + padding: 15px 5px; + border-bottom: solid 1px var(--color-border); + margin-top: 15px; + } + } + } + ``` + }) +} diff --git a/lib/html_utils.typ b/lib/html_utils.typ new file mode 100644 index 0000000..7314573 --- /dev/null +++ b/lib/html_utils.typ @@ -0,0 +1,4 @@ +#let html_show(body) = { + show raw.where(lang: "raw-css"): it => html.style(it.text) + body +} diff --git a/lib/main.typ b/lib/main.typ new file mode 100644 index 0000000..64d3d6d --- /dev/null +++ b/lib/main.typ @@ -0,0 +1,61 @@ +#import "./html_head.typ": html_head +#import "./html_body.typ": html_body +#import "./html_utils.typ": html_show + + +/// Mail template function +#let webpage( + /// Page url + url, + /// Page logo, also used for icon, so it *needs* to be path (TODO: fix when typst support multi-file out) + logo, + /// Alt-text for the log + logo-alt, + /// Title of the page, default to document.title + title: none, + /// Page header + header: [], + /// Use only for html 'lang' attribute. + lang: "en", + //-- only args -- + /// Type of the page for open-graph data + og-type: "website", + /// Name of the site for metadata of the page + site-name: none, + /// Description of the site for metadata #TODO default to document.description + description: none, + /// Author of the site for metadata #TODO default to document.author + author: none, + /// Additional stylesheet for the page: must be a list of url + stylesheets: (), + /// List of related sites for metadata + me-links: (), + //-- Body -- + /// Body of the page + body +) = { + show: html_show + + if title == none { + title = context document.title + } + html.html(lang: lang, { + html_head( + url, + title, + logo, + og-type: og-type, + site-name: site-name, + description: description, + author: author, + stylesheets: stylesheets, + me-links: me-links + ) + html_body( + logo, + logo-alt, + header: header, + body + ) + }) +} diff --git a/typst.toml b/typst.toml index d5aaefc..5b8f648 100644 --- a/typst.toml +++ b/typst.toml @@ -1,7 +1,7 @@ [package] name = "template-web" version = "0.0.1" -entrypoint = "lib.typ" +entrypoint = "lib/main.typ" authors = ["Jean-Marie 'Histausse' Mineau "] license = "MIT" description = "A typst template for web."