-
Notifications
You must be signed in to change notification settings - Fork 920
manifesto:0.1.0 #3936
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
manifesto:0.1.0 #3936
Changes from all commits
1d84f0e
012d95f
e50cec1
913ca2e
c74f4b9
3e4d705
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| MIT License | ||
|
|
||
| Copyright (c) 2026 Louis Grange | ||
|
|
||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
|
|
||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| # Manifesto for Typst | ||
|
|
||
| **Manifesto** 📚 is the first HTML Typst documentation template for packages, built to be very easy to use. It is **100% written in Typst, responsive** and directly uses your `typst.toml` to automatically get your package information. | ||
|
|
||
| [Report a bug](https://github.com/l0uisgrange/manifesto/issues?new) — [Forum](https://github.com/l0uisgrange/manifesto/discussions/categories/q-a) | ||
|
|
||
| You are free to check either [this example](https://bone.grangelouis.ch) from `bone` or [this one](https://zap.grangelouis.ch) from `zap`. | ||
|
|
||
| <img width="1232" height="758" alt="Capture d’écran 2026-01-22 à 18 39 15" src="https://github.com/user-attachments/assets/076e3071-6feb-4453-8b44-e5de1a32ec53" /> | ||
|
|
||
| ## Quick usage | ||
|
|
||
| The template is very easy to use, and will transform your whole project into a stunning online documentation in just a second. | ||
|
|
||
| ```typst | ||
| #import "@preview/manifesto:0.1.0" | ||
|
|
||
| #show: it => template(it, title: "MyAwesomePackage", toml: "PATH_TO/typst.toml") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't test but I think |
||
|
|
||
| = Introduction | ||
|
|
||
| Lorem ipsum | ||
| ``` | ||
|
|
||
| ## Options | ||
|
|
||
| The `template` function accepts a few parameters to customize the data displayed on the website. | ||
|
|
||
| | Option | Default value | Description | | ||
| | --- | --- | --- | | ||
| | `title` (required) | | The title of your package | | ||
| | `toml` | `none` | The path to the `typst.toml` file | | ||
| | `version` | `none` | Your package version | | ||
| | `description` | `none` | Your package description | | ||
| | `repository` | `none` | Your package repository URL (e.g. GitHub) | | ||
| | `universe` | `none` | Your package name on Typst universe name | | ||
| | `license` | `none` | Your package license | | ||
|
|
||
| Note that giving the `toml` file is aready enough, and will fill in the other options. | ||
|
|
||
| ## Contributing | ||
|
|
||
| I highly welcome contributions 🌱! Creating and maintaining this template takes time and love. If you'd like to help, don't hesitate to join the journey 🤩! | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| #let qa-icon = html.elem( | ||
|
Check failure on line 1 in packages/preview/manifesto/0.1.0/icons.typ
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be nice to provide some fallback when compiling to PDF, even if the template is supposed to be HTML-only. PDF export is still the default and it would be a bad experience to get a non-working template by default. Simply displaying a non-editable page that says "This template is HTML-only" (with a bit of styling if you feel like it) would be enough. You would also have to take care of not using If what I'm saying is not clear I can try to give a more explicit example, let me know. |
||
| "svg", | ||
| attrs: ( | ||
| class: "fill-current size-6 dark:fill-zinc-400", | ||
| xmlns: "http://www.w3.org/2000/svg", | ||
| viewBox: "0 0 640 640", | ||
| ), | ||
| html.elem( | ||
| "path", | ||
| attrs: ( | ||
| d: "M416 208C416 305.2 330 384 224 384C197.3 384 171.9 379 148.8 370L67.2 413.2C57.9 418.1 46.5 416.4 39 409C31.5 401.6 29.8 390.1 34.8 380.8L70.4 313.6C46.3 284.2 32 247.6 32 208C32 110.8 118 32 224 32C330 32 416 110.8 416 208zM416 576C321.9 576 243.6 513.9 227.2 432C347.2 430.5 451.5 345.1 463 229.3C546.3 248.5 608 317.6 608 400C608 439.6 593.7 476.2 569.6 505.6L605.2 572.8C610.1 582.1 608.4 593.5 601 601C593.6 608.5 582.1 610.2 572.8 605.2L491.2 562C468.1 571 442.7 576 416 576z", | ||
| ), | ||
| ), | ||
| ) | ||
|
|
||
| #let bug-icon = html.elem( | ||
| "svg", | ||
| attrs: ( | ||
| class: "fill-current size-6 dark:fill-zinc-400", | ||
| xmlns: "http://www.w3.org/2000/svg", | ||
| viewBox: "0 0 640 640", | ||
| ), | ||
| )[ | ||
| #html.elem( | ||
| "path", | ||
| attrs: ( | ||
| d: "M210.5 559.2C203 568.8 189.5 571.3 179.2 564.5C168.9 557.7 165.5 544 170.9 533L172.1 530.8L208.3 472.8L208.3 431.8L208.6 427.8C209.2 423.9 210.8 420.1 213.2 416.9L252.5 364.7L186.3 424.2C169.3 439.5 147.3 447.9 124.4 448L116.3 448C69.7 448 31.9 410.2 31.9 363.6C31.9 320.6 64.3 284.4 107 279.7L237.5 265.2L192.7 226.9L190.3 224.5C185 218.5 183 210.1 185 202.2L198.3 148.8L172.4 109.9L171.1 107.8C165.3 97 168.4 83.2 178.5 76.1C188.6 69 202.2 71 209.9 80.4L211.4 82.4L243.4 130.4L244.8 132.6C247.6 137.9 248.3 144.2 246.9 150.2L234.6 199.4L287.9 245.1L287.9 216.3C287.9 204.5 294.4 194.2 303.9 188.6L303.9 128.1L304.2 124.8C305.7 117.5 312.2 112.1 319.9 112.1C327.6 112.1 334.1 117.6 335.6 124.8L335.9 128L335.9 188.5C345.5 194 351.9 204.3 351.9 216.2L351.9 245.1L405.3 199.3L393 150.1C391.5 144.2 392.3 137.9 395.1 132.5L396.5 130.3L428.5 82.3L430 80.3C437.7 70.9 451.3 68.8 461.4 76C471.5 83.1 474.5 96.9 468.8 107.7L467.5 109.8L441.6 148.7L454.9 202.1C456.9 210.1 454.8 218.4 449.6 224.4L447.2 226.8L402.5 265.1L533 279.6C575.8 284.4 608.1 320.5 608.1 363.5C608.1 410.1 570.3 447.9 523.7 447.9L515.6 447.9C492.8 447.9 470.7 439.4 453.7 424.1L387.6 364.6L426.8 416.8C429.2 420 430.8 423.8 431.4 427.7L431.7 431.7L431.7 472.7L467.9 530.7L469.1 532.8C474.5 543.8 471.1 557.5 460.8 564.3C450.5 571.1 437 568.7 429.5 559L428.1 557L388.1 493L386.5 489.9C385.1 486.8 384.4 483.3 384.4 479.8L384.4 440L352 396.9L352 471.6C352 489.3 337.7 503.6 320 503.6C302.3 503.6 288 489.3 288 471.6L288 397L255.7 440L255.7 479.8C255.7 483.3 255 486.7 253.6 489.9L252 493L212 557L210.6 559z", | ||
| ), | ||
| ) | ||
| ] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,191 @@ | ||
| #import "icons.typ": bug-icon, qa-icon | ||
|
|
||
| #let detoml = toml | ||
|
|
||
| #let template(doc, title: none, toml: none, copyright: true, version: none, notices: (), links: (), description: none, repository: none, universe: none, license: none) = [ | ||
|
|
||
| #let title = if toml != none { detoml(toml).package.name } else { title } | ||
| #let version = if toml != none { detoml(toml).package.at("version", default: none) } else { version } | ||
| #let universe = if toml != none { detoml(toml).package.at("name", default: none) } else { universe } | ||
| #let license = if toml != none { detoml(toml).package.at("license", default: none) } else { license } | ||
| #let repository = if toml != none { detoml(toml).package.at("repository", default: none) } else { repository } | ||
| #let description = if toml != none { detoml(toml).package.at("description", default: none) } else { description } | ||
| #html.elem("html", attrs: (lang: "en", class: "scroll-smooth"))[ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you are using the untyped |
||
| #html.elem("head")[ | ||
| #html.elem("meta", attrs: (charset: "UTF-8")) | ||
| #html.elem("meta", attrs: (name: "viewport", content: "width=device-width, initial-scale=1.0")) | ||
| #html.elem("title")[#context document.title] | ||
| // Styling sources | ||
| #html.elem("script", attrs: (src: "https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio,container-queries")) | ||
| #html.elem("link", attrs: (rel: "preconnect", href: "https://fonts.googleapis.com")) | ||
| #html.elem("link", attrs: (rel: "preconnect", href: "https://fonts.gstatic.com", crossorigin: "anonymous")) | ||
| #html.elem("link", attrs: (rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=Mona+Sans:ital,wght@0,200..900;1,200..900&display=swap")) | ||
| ] | ||
| #html.elem("body", attrs: (style: "font-family: 'Mona Sans', sans-serif", class: "bg-zinc-50 dark:bg-zinc-950"))[ | ||
| // Configuration | ||
| #set heading(numbering: none) | ||
| // Raw blocks styling | ||
| #show raw.where(block: false): it => { | ||
| html.elem("span", attrs: (class: "border-t px-1 py-0.5 border-none rounded dark:bg-zinc-800 bg-zinc-200/60 text-xs *:not-prose not-prose font-mono"), it) | ||
| } | ||
| #show raw.where(block: true): it => { | ||
| html.elem("div", attrs: (class: "p-4 border bg-zinc-100/30 dark:bg-zinc-900/20 dark:border-zinc-800 not-prose text-[.85rem] rounded-md"), it) | ||
| } | ||
| // Article | ||
| #html.elem( | ||
| "article", | ||
| attrs: (class: "max-w-[95rem] mx-auto grid md:grid-cols-[max-content_auto_max-content] relative gap-10 p-5 !antialised"), | ||
| )[ | ||
| // Navigation | ||
| #html.elem("div", attrs: (class: "order-1 md:w-60 prose overflow-visible"))[ | ||
| #html.elem("div", attrs: (class: "sticky top-5"))[ | ||
| #html.elem("div", attrs: ( | ||
| class: "dark:prose-invert prose-zinc dark:text-white prose-li:first:mt-0 prose-ol:p-0 prose-a:underline-offset-2 prose-li:p-0 prose-ol:m-0", | ||
| ))[ | ||
| #html.elem( | ||
| "h1", | ||
| attrs: ( | ||
| class: if version != none { "rounded-bl-none " } else { "" } | ||
| + "capitalize bg-zinc-800 mb-0 text-white max-w-max rounded-md px-2 py-0.5 text-3xl font-medium mb-0", | ||
| ), | ||
| title, | ||
| ) | ||
| #if version != none { | ||
| html.elem("div", attrs: (class: "text-xs py-0.5 px-2 max-w-max rounded-md rounded-t-none bg-zinc-700 mb-8 text-white"))[v#version] | ||
| } | ||
| #description | ||
| #let provider = if "github" in repository { "GitHub" } else if "gitlab" in repository { "Gitlab" } else { "Source" } | ||
| #table( | ||
| columns: 2, | ||
| if repository != none { [Repository] }, link(repository, provider), | ||
| [Typst Universe], link("https://typst.app/universe/package/"+ universe, title), | ||
| [License], [#license], | ||
| [Last update], [#datetime.today().display()] | ||
| ) | ||
| #html.elem("div", attrs: (class: "grid grid-cols-2 lg:grid-cols-1 mt-8"))[ | ||
| #if "qa" in notices [ | ||
| #html.elem("div")[ | ||
| #qa-icon | ||
| #html.elem("div", attrs: (class: "prose-sm mb-6 mt-2.5"))[ | ||
| Got a question? \ | ||
| Ask it on the #link(notices.qa)[community forum]. | ||
| ] | ||
| ] | ||
| ] | ||
| #if "bug" in notices [ | ||
| #html.elem("div")[ | ||
| #bug-icon | ||
| #html.elem("div", attrs: (class: "prose-sm mt-2"))[ | ||
| Experienced a bug? \ | ||
| Please #link(notices.bug)[report] it. | ||
| ] | ||
| ] | ||
| ] | ||
| ] | ||
| ] | ||
| ] | ||
| ] | ||
| #html.elem("article", attrs: ( | ||
| class: "order-3 md:order-2 flex-auto !max-w-4xl prose dark:prose-invert overflow-hidden prose-zinc prose-a:underline-offset-2 prose-td:align-middle prose-headings:scroll-my-7 prose-headings:font-medium prose-strong:font-medium", | ||
| ))[ | ||
| #doc | ||
| ] | ||
| #html.elem("div", attrs: (class: "order-2 md:order-3 w-60 flex-none prose overflow-visible"))[ | ||
| #html.elem("div", attrs: (class: "sticky top-5"))[ | ||
| #html.elem("div", attrs: ( | ||
| class: "dark:prose-invert prose-zinc dark:text-white prose-li:first:mt-0 prose-ol:p-0 prose-a:underline-offset-2 prose-li:p-0 prose-ol:m-0", | ||
| ))[ | ||
| #html.elem( | ||
| "div", | ||
| attrs: ( | ||
| class: "prose-a:text-current *:*:*:mb-0.5 prose-a:font-normal prose-a:decoration-0 mb-12", | ||
| ), | ||
| outline(depth: 1, title: none), | ||
| ) | ||
| ] | ||
| ] | ||
| ] | ||
| ] | ||
|
|
||
| #html.elem("div", attrs: (class: "border-t antialised dark:border-zinc-800"))[ | ||
| #html.elem("div", attrs: (class: "p-5"))[ | ||
| #if copyright [ | ||
| #html.elem("span", attrs: (class: "text-zinc-500 text-sm"))[Made with #link("https://github.com/l0uisgrange/manifesto")[Manifesto] from Typst Universe] | ||
| ] | ||
| ] | ||
| ] | ||
| ] | ||
| ] | ||
| ] | ||
|
|
||
| #let warning(content, title: "Warning", ..params) = block( | ||
| ..params, | ||
| html.elem("div", attrs: (class: "px-3 py-2.5 rounded-md bg-orange-600/10"), { | ||
| html.elem("span", attrs: (class: "flex items-center gap-2 not-prose"), { | ||
| html.elem("svg", attrs: (class: "size-5", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 640 640"), html.elem( | ||
| "path", | ||
| attrs: ( | ||
| class: "fill-orange-600", | ||
| d: "M256.5 37.6C265.8 29.8 279.5 30.1 288.4 38.5C300.7 50.1 311.7 62.9 322.3 75.9C335.8 92.4 352 114.2 367.6 140.1C372.8 133.3 377.6 127.3 381.8 122.2C382.9 120.9 384 119.5 385.1 118.1C393 108.3 402.8 96 415.9 96C429.3 96 438.7 107.9 446.7 118.1C448 119.8 449.3 121.4 450.6 122.9C460.9 135.3 474.6 153.2 488.3 175.3C515.5 219.2 543.9 281.7 543.9 351.9C543.9 475.6 443.6 575.9 319.9 575.9C196.2 575.9 96 475.7 96 352C96 260.9 137.1 182 176.5 127C196.4 99.3 216.2 77.1 231.1 61.9C239.3 53.5 247.6 45.2 256.6 37.7zM321.7 480C347 480 369.4 473 390.5 459C432.6 429.6 443.9 370.8 418.6 324.6C414.1 315.6 402.6 315 396.1 322.6L370.9 351.9C364.3 359.5 352.4 359.3 346.2 351.4C328.9 329.3 297.1 289 280.9 268.4C275.5 261.5 265.7 260.4 259.4 266.5C241.1 284.3 207.9 323.3 207.9 370.8C207.9 439.4 258.5 480 321.6 480z", | ||
| ), | ||
| )) | ||
| html.elem("span", attrs: (class: "font-medium text-orange-600 *:p-0 !*:m-0 "), title) | ||
| }) | ||
| content | ||
| }), | ||
| ) | ||
|
|
||
| #let tip(content, title: "Tip", ..params) = block( | ||
| ..params, | ||
| html.elem("div", attrs: (class: "px-3 py-2.5 rounded-md bg-green-600/10"), { | ||
| html.elem("span", attrs: (class: "flex items-center gap-2 not-prose"), { | ||
| html.elem("svg", attrs: (class: "size-5", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 640 640"), html.elem( | ||
| "path", | ||
| attrs: ( | ||
| class: "fill-green-600", | ||
| d: "M420.9 448C428.2 425.7 442.8 405.5 459.3 388.1C492 353.7 512 307.2 512 256C512 150 426 64 320 64C214 64 128 150 128 256C128 307.2 148 353.7 180.7 388.1C197.2 405.5 211.9 425.7 219.1 448L420.8 448zM416 496L224 496L224 512C224 556.2 259.8 592 304 592L336 592C380.2 592 416 556.2 416 512L416 496zM312 176C272.2 176 240 208.2 240 248C240 261.3 229.3 272 216 272C202.7 272 192 261.3 192 248C192 181.7 245.7 128 312 128C325.3 128 336 138.7 336 152C336 165.3 325.3 176 312 176z", | ||
| ), | ||
| )) | ||
| html.elem("span", attrs: (class: "font-medium text-green-600 *:p-0 !*:m-0 "), title) | ||
| }) | ||
| content | ||
| }), | ||
| ) | ||
|
|
||
|
|
||
| #let info(content, title: "Info", ..params) = block( | ||
| ..params, | ||
| html.elem("div", attrs: (class: "px-3 py-2.5 rounded-md bg-blue-600/10"), { | ||
| html.elem("span", attrs: (class: "flex items-center gap-2 not-prose"), { | ||
| html.elem("svg", attrs: (class: "size-5", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 640 640"), html.elem( | ||
| "path", | ||
| attrs: ( | ||
| class: "fill-blue-600", | ||
| d: "M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM288 224C288 206.3 302.3 192 320 192C337.7 192 352 206.3 352 224C352 241.7 337.7 256 320 256C302.3 256 288 241.7 288 224zM280 288L328 288C341.3 288 352 298.7 352 312L352 400L360 400C373.3 400 384 410.7 384 424C384 437.3 373.3 448 360 448L280 448C266.7 448 256 437.3 256 424C256 410.7 266.7 400 280 400L304 400L304 336L280 336C266.7 336 256 325.3 256 312C256 298.7 266.7 288 280 288z", | ||
| ), | ||
| [], | ||
| )) | ||
| html.elem("span", attrs: (class: "font-medium text-blue-600 *:p-0 !*:m-0 "), title) | ||
| }) | ||
| content | ||
| }), | ||
| ) | ||
|
|
||
| #let circ(drawing) = html.elem("div", attrs: (class: "mb-7 rounded-md border dark:border-zinc-800 overflow-hidden flex-col flex *:m-0 *:block *:w-full *:even:rounded-t-none"), { | ||
| html.elem("div", attrs: (class: "p-7 bg-white rounded-t-md dark:invert dark:hue-rotate-180"))[ | ||
| #html.frame[ | ||
| #eval(drawing.text, mode: "markup") | ||
| ] | ||
| ] | ||
| html.elem("div", attrs: (class: "*:rounded-t-none *:border-none border-t dark:border-zinc-800 *:border-none overflow-x-scroll"), raw( | ||
| drawing.text.split("\n").slice(2).join("\n"), | ||
| block: true, | ||
| lang: "typst", | ||
| )) | ||
| }) | ||
|
|
||
| #let schema(drawing) = html.elem("div", attrs: (class: "mb-7 rounded-md border dark:border-zinc-800 overflow-hidden flex-col flex *:m-0 *:block *:w-full *:even:rounded-t-none"), { | ||
| html.elem("div", attrs: (class: "p-7 bg-white rounded-md dark:invert dark:hue-rotate-180"))[ | ||
| #html.frame(drawing) | ||
| ] | ||
| }) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| [package] | ||
| name = "manifesto" | ||
| version = "0.1.0" | ||
| compiler = "0.14.2" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This corresponds to the lowest version number this package works with, so unless you depend on a fix that was introduced in 0.14.2, it should probably be 0.14.0 or even lower. |
||
| description = "Create stunning documentation websites using native HTML export" | ||
| repository = "https://github.com/l0uisgrange/manifesto" | ||
| categories = ["layout", "visualization"] | ||
| disciplines = ["design", "education"] | ||
| keywords = ["documentation", "docs", "html", "website", "site", "static", "online"] | ||
| exclude = [".github"] | ||
| entrypoint = "template.typ" | ||
| authors = ["Louis Grange <https://github.com/l0uisgrange>"] | ||
| license = "MIT" | ||
|
|
||
| [template] | ||
| path = "" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Your template should be in its own subdirectory. Only files in that directory will be copied to the user project. The "library" part of your package should contain utility and templating functions you don't expect the user to modify, while the template files should contain some default content. |
||
| thumbnail = "thumbnail.png" | ||
|
Check failure on line 17 in packages/preview/manifesto/0.1.0/typst.toml
|
||
| entrypoint = "template.typ" | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you write an actual alternative text please?