{"id":47758951,"url":"https://github.com/leanprover/verso-slides","last_synced_at":"2026-04-03T05:01:51.633Z","repository":{"id":344747320,"uuid":"1167602933","full_name":"leanprover/verso-slides","owner":"leanprover","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-30T13:27:41.000Z","size":604,"stargazers_count":5,"open_issues_count":4,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-30T14:36:12.465Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lean","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leanprover.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-26T13:31:57.000Z","updated_at":"2026-03-30T13:27:43.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/leanprover/verso-slides","commit_stats":null,"previous_names":["leanprover/verso-slides"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/leanprover/verso-slides","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanprover%2Fverso-slides","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanprover%2Fverso-slides/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanprover%2Fverso-slides/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanprover%2Fverso-slides/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leanprover","download_url":"https://codeload.github.com/leanprover/verso-slides/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanprover%2Fverso-slides/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31335169,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-03T04:42:29.251Z","status":"ssl_error","status_checked_at":"2026-04-03T04:42:12.667Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-03T05:00:48.683Z","updated_at":"2026-04-03T05:01:51.628Z","avatar_url":"https://github.com/leanprover.png","language":"Lean","funding_links":[],"categories":[],"sub_categories":[],"readme":"# VersoSlides\n\nVersoSlides is a Verso genre that generates reveal.js slide\npresentations from Lean 4 documents. All third-party dependencies\n(reveal.js, KaTeX, marked) are vendored and embedded at compile time,\nso the generated output works fully offline. The output includes full\nsupport for Verso's elaborated Lean code blocks, including syntax\nhighlighting and hover-based documentation tooltips.\n\nThe [demo slides](./Demo.lean) can be seen at\n[this repository's GitHub pages](https://leanprover.github.io/verso-slides/).\n\n## Requirements\n\nVersoSlides requires the Lean 4 toolchain specified in\n`lean-toolchain` and pulls Verso as a Lake dependency.\n\n## Building and Running\n\nBuild the project with Lake, then run the executable to generate\nslides:\n\n```\nlake build\nlake exe demo-slides\n```\n\nThe output is written to `_slides/` by default, containing\n`index.html` and a `lib/` directory with the vendored reveal.js,\nKaTeX, and marked assets. To view the presentation, serve the output\ndirectory over HTTP:\n\n```\npython3 -m http.server -d _slides\n```\n\nYou can override the output directory and theme from the command line:\n\n```\nlake exe demo-slides --output path/to/dir --theme white\n```\n\n## Writing a Presentation\n\nA presentation is a Verso document declared with the `Slides` genre.\nThe document title becomes the HTML page title. Each top-level heading\n(`#`) becomes a horizontal slide, and the content under it forms the\nslide body.\n\n```\nimport VersoSlides\nimport Verso.Doc.Concrete\n\nopen VersoSlides\n\n#doc (Slides) \"My Presentation\" =\u003e\n\n# First Slide\n\nContent of the first slide.\n\n# Second Slide\n\nContent of the second slide.\n```\n\nThe document module must be imported in `Main.lean`, where the\n`slidesMain` function generates the output. Document-level\nconfiguration (theme, transition style, slide numbering, etc.) is set\nin a `%%%` metadata block at the top of the document rather than in\n`Main.lean`.\n\n### Vertical Slides\n\nWhen a top-level section has `vertical := some true` in its metadata\nblock, its subsections (`##`) become vertical sub-slides arranged in a\ncolumn beneath the parent. Without this setting, subsections are\nflattened into the parent slide without their own `\u003csection\u003e`\nwrappers.\n\n```\n# Vertical Group\n\n%%%\nvertical := some true\n%%%\n\nContent on the first vertical sub-slide.\n\n## Second Sub-slide\n\nThis appears below the first when navigating down.\n```\n\n### Slide Metadata\n\nEach slide can carry per-slide metadata in a `%%%` block immediately\nafter its heading. All fields are optional and fall back to\ndocument-level defaults or reveal.js defaults when omitted. The\nmetadata is written as Lean structure field syntax.\n\n```\n# My Slide\n\n%%%\ntransition := some \"zoom\"\nbackgroundColor := some \"#2d1b69\"\nautoAnimate := some true\n%%%\n```\n\nThe available metadata fields are listed below. Each one maps directly\nto a `data-*` attribute on the slide's `\u003csection\u003e` element.\n\n| Field                   | Type            | reveal.js attribute                                                 |\n| ----------------------- | --------------- | ------------------------------------------------------------------- |\n| `vertical`              | `Option Bool`   | Controls vertical sub-slide grouping (not rendered as an attribute) |\n| `transition`            | `Option String` | `data-transition`                                                   |\n| `transitionSpeed`       | `Option String` | `data-transition-speed`                                             |\n| `backgroundColor`       | `Option String` | `data-background-color`                                             |\n| `backgroundImage`       | `Option String` | `data-background-image`                                             |\n| `backgroundSize`        | `Option String` | `data-background-size`                                              |\n| `backgroundPosition`    | `Option String` | `data-background-position`                                          |\n| `backgroundRepeat`      | `Option String` | `data-background-repeat`                                            |\n| `backgroundOpacity`     | `Option Float`  | `data-background-opacity`                                           |\n| `backgroundVideo`       | `Option String` | `data-background-video`                                             |\n| `backgroundVideoLoop`   | `Option Bool`   | `data-background-video-loop`                                        |\n| `backgroundVideoMuted`  | `Option Bool`   | `data-background-video-muted`                                       |\n| `backgroundIframe`      | `Option String` | `data-background-iframe`                                            |\n| `backgroundGradient`    | `Option String` | `data-background-gradient`                                          |\n| `backgroundTransition`  | `Option String` | `data-background-transition`                                        |\n| `backgroundInteractive` | `Option Bool`   | `data-background-interactive`                                       |\n| `autoAnimate`           | `Option Bool`   | `data-auto-animate`                                                 |\n| `autoAnimateId`         | `Option String` | `data-auto-animate-id`                                              |\n| `autoAnimateEasing`     | `Option String` | `data-auto-animate-easing`                                          |\n| `autoAnimateDuration`   | `Option Float`  | `data-auto-animate-duration`                                        |\n| `autoAnimateUnmatched`  | `Option Bool`   | `data-auto-animate-unmatched`                                       |\n| `autoAnimateRestart`    | `Option Bool`   | `data-auto-animate-restart`                                         |\n| `timing`                | `Option Nat`    | `data-timing`                                                       |\n| `visibility`            | `Option String` | `data-visibility`                                                   |\n| `state`                 | `Option String` | `data-state`                                                        |\n\n## Directives\n\nDirectives are block-level constructs delimited by `:::` fences. They\napply reveal.js features to their content.\n\n### Speaker Notes\n\nThe `notes` directive wraps its content in an `\u003caside class=\"notes\"\u003e`\nelement, which reveal.js displays in the speaker view (opened with the\nS key).\n\n```\n:::notes\nRemember to explain this point carefully.\n:::\n```\n\n### Fragments\n\nThe `fragment` directive makes its content appear incrementally. Each\nchild block receives the fragment class individually, so a directive\nwrapping multiple paragraphs produces multiple independent animation\nsteps.\n\nAn optional positional argument sets the animation style. The style\nname is written in camelCase and converted to the corresponding\nreveal.js class (for example, `fadeUp` becomes `fade-up`). A named\n`index` argument controls the ordering of fragment steps.\n\n```\n:::fragment fadeUp (index := 2)\nThis paragraph fades up at step 2.\n:::\n```\n\nThe built-in animation styles include `fadeUp`, `fadeDown`,\n`fadeLeft`, `fadeRight`, `fadeIn`, `fadeOut`, `currentVisible`,\n`highlightRed`, `highlightGreen`, `highlightBlue`, and others defined\nby reveal.js.\n\n### Fit Text, Stretch, and Frame\n\nThree named directives apply common reveal.js utility classes to their\ncontent.\n\nThe `fitText` directive causes reveal.js to scale the text to fill the\nslide width. The `stretch` directive causes an element to expand to\nfill the remaining vertical space on the slide. The `frame` directive\nadds a default styled border around the content.\n\n```\n:::fitText\nLarge heading text\n:::\n```\n\n### Layout: `stack`, `hstack`, `vstack`\n\nThe `stack`, `hstack`, and `vstack` directives wrap their children in\na container `\u003cdiv\u003e` with the corresponding reveal.js layout class.\nUnlike the push-down directives described above, these create a\nwrapper element around all the content rather than applying attributes\nto each child individually.\n\nThe `stack` directive stacks elements on top of one another (useful\nfor layered animations). The `hstack` directive arranges elements\nhorizontally, and `vstack` arranges them vertically.\n\n```\n:::hstack\nLeft column content.\n\nRight column content.\n:::\n```\n\n### CSS Classes and IDs\n\nThe `class` directive pushes one or more CSS classes onto each child\nblock. Class names are given as positional string arguments and are\nmerged with any existing classes on the element.\n\n```\n:::class \"custom-highlight\" \"another-class\"\nThis paragraph receives both classes.\n:::\n```\n\nThe `id` directive similarly pushes an `id` attribute onto each child\nblock. It takes a single positional string argument.\n\n```\n:::id \"important-paragraph\"\nThis paragraph has the given ID.\n:::\n```\n\n### Generic Attributes\n\nThe `attr` directive pushes arbitrary HTML attributes onto each child\nblock. Attribute names and values are given as named arguments.\nBecause Verso's argument parser uses Lean identifier syntax, attribute\nnames that contain hyphens (such as `data-id`) must be escaped with\nguillemets.\n\n```\n:::attr («data-id» := \"box\") (style := \"color: red\")\nThis paragraph receives both attributes.\n:::\n```\n\nThis directive is particularly useful for auto-animate element\nmatching, where paired elements across adjacent slides need matching\n`data-id` attributes.\n\n### Nesting Directives\n\nDirectives can be nested by using a longer fence for the outer\ndirective. The inner directive uses the standard three-colon fence,\nand the outer directive uses a fence with more colons to avoid\nambiguity.\n\n```\n:::::fitText\n:::attr («data-id» := \"title\")\nScaled and tracked text.\n:::\n:::::\n```\n\n## Inline Roles\n\nRoles are inline constructs written as `{roleName args}[content]`.\nThey wrap their content in a `\u003cspan\u003e` element with the appropriate\nattributes.\n\n### Inline Fragments\n\nThe `fragment` role wraps inline content in a `\u003cspan\u003e` with the\nfragment class. Unlike the block directive, the role uses named\narguments for the style and index.\n\n```\nThis is {fragment (style := highlightRed)}[highlighted] text.\n```\n\n### Inline Classes, IDs, and Attributes\n\nThe `class`, `id`, and `attr` roles are the inline counterparts of the\ncorresponding block directives. They wrap their content in a `\u003cspan\u003e`\nwith the specified attributes.\n\n```\nThis word is {class \"custom\"}[styled] differently.\n\nThis has an {id \"target\"}[identified span].\n\nThis is {attr («data-id» := \"word\")}[tracked] across slides.\n```\n\n## Lean Code Blocks\n\nFenced code blocks tagged with `lean` are elaborated by the Lean\ncompiler and rendered with full syntax highlighting and hover\ndocumentation. The code is type-checked at build time, so any errors\nare caught before the slides are generated.\n\n````\n```lean\ndef factorial : Nat → Nat\n  | 0 =\u003e 1\n  | n + 1 =\u003e (n + 1) * factorial n\n```\n````\n\nThe generated HTML includes the necessary CSS and JavaScript for\nVerso's highlighting system.\n\nInstead of hovers, information about code is revealed on click. This\nis to allow the presenter to point using the mouse without hover boxes\npopping up over content.\n\n### Tips\n\nUse the `-show` flag to include Lean code that is not rendered. This\ncan set options, define variables, or create helpers:\n\n````\n```lean -show\nsection\nset_option pp.all true\nvariable {α : Type} [ToString α]\n```\n```lean\n#check List α\n```\n```lean -show\nend\n```\n````\n\n### Progressive Code Reveal\n\nInside elaborated Lean code blocks, special comments control how code\nis revealed incrementally using `reveal.js` fragments. There are three\nkinds of control comments: fragment breaks, click targets, and hidden\nregions.\n\n#### Fragment Breaks\n\nA line comment of the form `-- !fragment` splits the code block at\nthat point. Everything from the break to the next break (or the end of\nthe block) appears as a separate `reveal.js` fragment, so successive\npresses of the advance key reveal successive portions of the code.\n\nAn optional style name and numeric index may follow the keyword. The\nstyle name is any identifier recognized by `reveal.js` (for example,\n`fadeUp`), and the index controls the ordering of animation steps\nacross the slide.\n\n````\n```lean\ndef f := 1\n-- !fragment\ndef g := 2\n-- !fragment fadeUp 3\ndef h := 3\n```\n````\n\n#### Click Targets\n\nA line comment of the form `-- ^ !click` marks the token on the\npreceding line at the column of the caret (`^`) as a \"click target.\"\nWhen that fragment step is reached, information about the code at that\nposition is revealed. An optional numeric index controls the ordering.\n\n````\n```lean\ntheorem foo : True := by\n  intro n\n-- ^ !click\n  trivial\n```\n````\n\nIn this example, `intro n` is revealed normally, and then on the next\nadvance, the token at the caret column on the preceding line (here,\n`intro`) receives a click highlight, resulting in the proof state for\n`intro n` being revealed.\n\n#### Hidden Regions\n\nCode that should be elaborated but not displayed in the slides can be\nwrapped in a hide region. The block comment `/- !hide -/` opens a\nhidden region, and `/- !end hide -/` closes it. Everything between the\ntwo markers is type-checked as usual but omitted from the rendered\noutput. This is useful for auxiliary definitions or imports that the\naudience does not need to see.\n\n````\n```lean\n/- !hide -/\ndef helper := 42\n/- !end hide -/\ntheorem uses_helper : helper = 42 := rfl\n```\n````\n\nHide markers can appear inline (on the same line as code) or on their\nown lines. They can also be nested: an inner `/- !hide -/` inside an\nalready-hidden region increments a depth counter, and the\ncorresponding `/- !end hide -/` decrements it. Code is only shown once\nall hide regions have been closed.\n\n#### Inline Fragment Regions\n\nBlock comments of the form `/- !fragment -/` and `/- !end fragment -/`\ndelimit an inline fragment region within a line. Unlike line-level\nfragment breaks, which split the code block vertically, inline\nfragment regions wrap a horizontal span of code in a reveal.js\nfragment. An optional style name and index may appear between\n`!fragment` and the closing `-/`.\n\n````\n```lean\ndef f := /- !fragment -/42/- !end fragment -/\n```\n````\n\n## Document-Level Configuration\n\nDocument-level `reveal.js` settings are specified in a `%%%` metadata\nblock at the top of the document (before the first `#` heading). These\nserve as defaults that individual slides can override through their\nown metadata blocks.\n\n```\n#doc (Slides) \"My Presentation\" =\u003e\n\n%%%\ntheme := some \"black\"\nslideNumber := some true\ntransition := some \"slide\"\n%%%\n\n# First Slide\n...\n```\n\nThe available document-level fields are `theme`, `transition`,\n`width`, `height`, `margin`, `controls`, `progress`, `slideNumber`,\n`hash`, `center`, and `navigationMode`. The `--output` and `--theme`\ncommand-line flags can further override the output directory and\ntheme.\n\nThe generated HTML loads the Notes, Highlight, and KaTeX Math plugins\nautomatically. All plugin assets are vendored and written to the\noutput directory, so no internet connection is required.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleanprover%2Fverso-slides","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleanprover%2Fverso-slides","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleanprover%2Fverso-slides/lists"}