Skip to main content

vecslide_core/
lib.rs

1//! # vecslide-core
2//!
3//! Core library for the **`.vecslide`** format — vector presentations with
4//! synchronized Opus audio, playable from a single self-contained HTML file.
5//!
6//! A `.vecslide` file is a ZIP archive that bundles:
7//! - a `manifest.yaml` describing slides, timestamps, animations, pointer trail,
8//! - one or more SVG slides (or a single Typst source split by `----`),
9//! - an optional Opus audio track (OGG container),
10//! - optional author-only annotations (stripped on HTML export).
11//!
12//! This crate is UI-free and has no hard dependency on the filesystem:
13//! the default feature set is **WASM-safe** and is what powers the web
14//! authoring tool. Native tooling enables extra features behind feature flags.
15//!
16//! ## Feature flags
17//!
18//! | Feature             | Adds                                        | Typical consumer     |
19//! |---------------------|---------------------------------------------|----------------------|
20//! | _(default)_         | `manifest`, `compile_html`, `validation`, `pointer`, `typst_split` | WASM app             |
21//! | `zip-io`            | In-memory ZIP read/write (`pack`, `unpack`) via `miniz_oxide`      | WASM app, browser    |
22//! | `native`            | `zip-io` + Typst compilation + bundled fonts + `std::fs` helpers   | CLI, server-side     |
23//!
24//! `native` is a superset of `zip-io`. Enabling `native` on WASM is **not** supported.
25//!
26//! ## Quick start: parse a manifest
27//!
28//! ```ignore
29//! use vecslide_core::manifest::Presentation;
30//!
31//! let yaml = r#"
32//! title: "Cell Anatomy"
33//! slides:
34//!   - id: slide_01
35//!     time_start: 0
36//!     svg_file: vector_assets/01.svg
37//! "#;
38//! let p: Presentation = serde_norway::from_str(yaml)?;
39//! assert_eq!(p.title, "Cell Anatomy");
40//! # Ok::<_, serde_norway::Error>(())
41//! ```
42//!
43//! ## Quick start: unpack a `.vecslide` in memory (requires `zip-io`)
44//!
45//! ```ignore
46//! use vecslide_core::unpack_from_reader;
47//!
48//! let bytes = std::fs::read("lesson.vecslide")?;
49//! let unpacked = unpack_from_reader(std::io::Cursor::new(bytes))?;
50//! println!("{} slides", unpacked.presentation.slides.len());
51//! # Ok::<_, vecslide_core::VecslideError>(())
52//! ```
53//!
54//! ## Quick start: compile to a single self-contained HTML
55//!
56//! ```ignore
57//! use vecslide_core::{unpack_from_reader, compile_html::compile};
58//!
59//! let bytes = std::fs::read("lesson.vecslide")?;
60//! let unpacked = unpack_from_reader(std::io::Cursor::new(bytes))?;
61//! let html: String = compile(&unpacked)?;
62//! std::fs::write("lesson.html", html)?;
63//! # Ok::<_, vecslide_core::VecslideError>(())
64//! ```
65//!
66//! ## Modules at a glance
67//!
68//! | Module          | Purpose                                                                  |
69//! |-----------------|--------------------------------------------------------------------------|
70//! | [`manifest`]    | Data structures + YAML/JSON serde for `manifest.yaml`                    |
71//! | [`validation`]  | Consistency checks (ordered timestamps, referenced files, durations)     |
72//! | [`compile_html`]| Compile an [`UnpackedPresentation`] into a single self-contained HTML    |
73//! | [`pointer`]     | Pointer-trail logic: movement threshold, decimation, fading opacity      |
74//! | [`player_template`] | Embedded HTML/CSS/JS viewer template (`include_str!`)                |
75//! | [`theme`]       | Theme tokens shared between editor and viewer                            |
76//! | [`typst_split`] | Split a `.typ` source into per-slide sections separated by `----`        |
77//! | [`pack`]        | Fold a source folder into a `.vecslide` ZIP (requires `zip-io`)          |
78//! | [`unpack`]      | Read a `.vecslide` ZIP into memory (requires `zip-io`)                   |
79//! | [`typst_render`]| Compile Typst sources to SVG (requires `native`)                         |
80//! | [`typst_fonts`] | Fonts bundled for Typst compilation (requires `native`)                  |
81//!
82//! ## Companion crates
83//!
84//! - [`vecslide`](https://crates.io/crates/vecslide) — thin facade re-exporting this crate under a shorter name.
85//!
86//! ## License
87//!
88//! Licensed under either of [MIT](https://opensource.org/license/mit) or
89//! [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) at your option.
90
91#![cfg_attr(docsrs, feature(doc_cfg))]
92
93pub mod compile_html;
94pub mod error;
95pub mod manifest;
96pub mod player_template;
97pub mod pointer;
98pub mod theme;
99pub mod typst_fonts;
100pub mod typst_split;
101pub mod validation;
102
103#[cfg(feature = "zip-io")]
104#[cfg_attr(docsrs, doc(cfg(feature = "zip-io")))]
105pub mod pack;
106#[cfg(feature = "zip-io")]
107#[cfg_attr(docsrs, doc(cfg(feature = "zip-io")))]
108pub mod unpack;
109
110#[cfg(feature = "native")]
111#[cfg_attr(docsrs, doc(cfg(feature = "native")))]
112pub mod typst_render;
113
114pub use compile_html::UnpackedPresentation;
115pub use error::VecslideError;
116
117#[cfg(feature = "zip-io")]
118#[cfg_attr(docsrs, doc(cfg(feature = "zip-io")))]
119pub use pack::pack_to_writer;
120#[cfg(feature = "zip-io")]
121#[cfg_attr(docsrs, doc(cfg(feature = "zip-io")))]
122pub use unpack::unpack_from_reader;