magical markdown slides

initial commit

+21
.gitignore
··· 1 + # Generated by Cargo 2 + # will have compiled files and executables 3 + debug 4 + target 5 + 6 + # These are backup files generated by rustfmt 7 + **/*.rs.bk 8 + 9 + # MSVC Windows builds of rustc generate these, which store debugging information 10 + *.pdb 11 + 12 + # Generated by cargo mutants 13 + # Contains mutation testing data 14 + **/mutants.out*/ 15 + 16 + # RustRover 17 + # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 18 + # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 19 + # and can be added to the global gitignore or merged into this file. For a more nuclear 20 + # option (not recommended) you can uncomment the following to ignore the entire idea folder. 21 + #.idea/
+4
.markdownlint.json
··· 1 + { 2 + "MD033": false, 3 + "MD013": false 4 + }
+15
Cargo.lock
··· 1 + # This file is automatically @generated by Cargo. 2 + # It is not intended for manual editing. 3 + version = 4 4 + 5 + [[package]] 6 + name = "slides-cli" 7 + version = "0.1.0" 8 + 9 + [[package]] 10 + name = "slides-core" 11 + version = "0.1.0" 12 + 13 + [[package]] 14 + name = "slides-tui" 15 + version = "0.1.0"
+3
Cargo.toml
··· 1 + [workspace] 2 + resolver = "2" 3 + members = ["cli", "core", "ui"]
+20
README.md
··· 1 + # slides.rs 2 + 3 + > A modern, fast, terminal presentation tool inspired by [`maaslalani/slides`](https://github.com/maaslalani/slides), built with Rust. 4 + 5 + ## Design Principles 6 + 7 + __Color as Data:__ 8 + All color use flows through typed wrappers using `owo-colors`. No ad-hoc ANSI escapes. 9 + 10 + __Themeable:__ 11 + Themes unify visual (Syntect) and terminal (owo) layers. 12 + 13 + __Reproducible:__ 14 + Everything is reproducible in plain text — decks can render without TUI (using `slides print`). 15 + 16 + __Composable:__ 17 + Parser → Model → Renderer are independent modules with tests and traits. 18 + 19 + __Portable:__ 20 + Runs on any terminal supporting UTF-8; dependencies limited to core crates.
+82
ROADMAP.md
··· 1 + # Slides 2 + 3 + ## Plumbing 4 + 5 + __Objective:__ Establish a clean, testable core with `clap` and a minimal `ratatui` loop. 6 + 7 + | Task | Description | Key Crates | 8 + | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | 9 + | __Project Scaffolding__ | Initialize workspace with `slides-core`, `slides-cli`, and `slides-tui` crates. Use `cargo-generate` and a `justfile` for scripts. | `cargo`, `just`, `clap` | 10 + | __CLI Definition__ | Implement root command `slides` with subcommands:<br>• `present` (TUI)<br>• `print` (stdout)<br>• `init` (scaffold deck)<br>• `check` (lint slides). | [`clap`](https://docs.rs/clap/latest/clap/) | 11 + | __Logging and Colors__ | Integrate structured logs via `tracing`.<br>Use __owo-colors__ for color abstraction (no dynamic dispatch). | [`owo-colors`](https://docs.rs/owo-colors/latest/owo_colors/), `tracing` | 12 + | __Terminal & Event Setup__ | Configure alternate screen, raw mode, input loop, resize handler. | [`crossterm`](https://docs.rs/crossterm/latest/crossterm/), `ratatui` | 13 + | __CI/CD + Tooling__ | Setup `cargo fmt`, `clippy`, `test`, and `cross` matrix CI. | GitHub Actions | 14 + 15 + ## Data Model (Parser & Slides) 16 + 17 + __Objective:__ Parse markdown documents into a rich `Slide` struct. 18 + 19 + | Task | Description | Key Crates | 20 + | ---------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | 21 + | __Parser Core__ | Split files on `---` separators.<br>Detect title blocks, lists, and code fences.<br>Represent as `Vec<Slide>`. | [`pulldown-cmark`](https://docs.rs/pulldown-cmark/latest/pulldown_cmark/) | 22 + | __Slide Model__ | Define structs: `Slide`, `Block`, `TextSpan`, `CodeBlock`, etc. | Internal | 23 + | __Metadata Parsing__ | Optional front matter (YAML/TOML) for theme, author, etc. | [`serde_yaml`](https://docs.rs/serde_yaml) | 24 + | __Error & Validation__ | Provide friendly parser errors with file/line info. | [`thiserror`](https://docs.rs/thiserror) | 25 + | __Basic CLI UX__ | `slides present file.md` runs full TUI.<br>`slides print` renders to stdout with width constraint. | `clap` | 26 + 27 + --- 28 + 29 + ## Rendering & Navigation 30 + 31 + __Objective:__ Build the interactive slide renderer with navigation. 32 + 33 + | Task | Description | Key Crates | 34 + | ----------------------- | --------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | 35 + | __Ratatui Integration__ | Build basic slide viewer using layout, blocks, paragraphs. | [`ratatui`](https://docs.rs/ratatui/latest/ratatui/) | 36 + | __Input & State__ | Support `←/→`, `j/k`, `q`, numeric jumps, and window resize. | `crossterm`, `ratatui` | 37 + | __Status Bar__ | Display slide count, filename, clock, and theme name. | `ratatui` | 38 + | __Color Styling__ | Apply consistent color palette via `owo-colors`. Define traits like `ThemeColor` for strong typing. | `owo-colors` | 39 + | __Configurable Themes__ | Support themes via TOML files mapping semantic roles (`heading`, `body`, `accent`) → color pairs. | `toml`, `serde` | 40 + 41 + ## Code Highlighting via Syntect 42 + 43 + __Objective:__ Add first-class syntax highlighting using Syntect. 44 + 45 + | Task | Description | Key Crates | 46 + | --------------- | ------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------- | 47 + | __Syntect__ | Load `.tmTheme` / `.sublime-syntax` definitions on startup.<br>Cache `SyntaxSet` + `ThemeSet`. | [`syntect`](https://docs.rs/syntect/latest/syntect/) | 48 + | __Code Blocks__ | Detect fenced code blocks with language tags.<br>Render syntax-highlighted text with color spans mapped to `owo-colors`. | `syntect`, `owo-colors` | 49 + | __Theming__ | Map terminal theme choice to Syntect theme (e.g., `"OneDark"`, `"SolarizedDark"`, `"Monokai"`). | `syntect` | 50 + | __Performance__ | Lazy-load themes and syntaxes; use `once_cell` for caching. | `once_cell` | 51 + | __Mode__ | Render to ANSI-colored plain text output (for `slides print`). | `owo-colors` | 52 + 53 + ## Presenter 54 + 55 + __Objective:__ Introduce features for live presentations and authoring convenience. 56 + 57 + | Task | Description | Key Crates | 58 + | -------------------- | ------------------------------------------------------------- | ------------------------------------------------- | 59 + | __Speaker Notes__ | `n` toggles speaker notes (parsed via `::: notes`). | `ratatui` | 60 + | __Timer & Progress__ | Session timer + per-slide progress bar. | `ratatui`, `chrono` | 61 + | __Live Reload__ | File watcher auto-refreshes content. | [`notify`](https://docs.rs/notify/latest/notify/) | 62 + | __Search__. | Fuzzy find slide titles via `ctrl+f`. | [`fuzzy-matcher`](https://docs.rs/fuzzy-matcher) | 63 + | __Theme Commands__ | CLI flag `--theme <name>` switches both Syntect + owo themes. | `clap`, internal `ThemeRegistry` | 64 + 65 + ## Markdown Extension 66 + 67 + __Objective:__ Add richness and visual polish to text and layout. 68 + 69 + | Task | Description | Key Crates | 70 + | -------------------- | ------------------------------------------------------------ | ----------------------------- | 71 + | __Tables & Lists__ | Render GitHub-style tables, bullets, and task lists. | `pulldown-cmark`, `ratatui` | 72 + | __Admonitions__ | Highlighted boxes with icons | `owo-colors`, internal glyphs | 73 + | __Horizontal Rules__ | Use box-drawing (`─`, `═`) and shading (`░`, `▓`). | Unicode constants | 74 + | __Generators__. | `slides init` scaffolds an example deck with code and notes. | `include_str!`, `fs` | 75 + 76 + ## RC 77 + 78 + | Task | Description | Key Crates | 79 + | -------------------- | ------------------------------------------------------------------ | ---------------------------- | 80 + | __Config Discovery__ | Read from `$XDG_CONFIG_HOME/slides/config.toml` for defaults. | `dirs`, `serde` | 81 + | __Theme Registry__ | Built-in theme manifest (e.g., `onedark`, `solarized`, `plain`). | Internal | 82 + | __Release__ | Tag `v1.0.0-rc.1` with changelog and binaries for major platforms. | `cargo-dist`, GitHub Actions |
+6
cli/Cargo.toml
··· 1 + [package] 2 + name = "slides-cli" 3 + version = "0.1.0" 4 + edition = "2024" 5 + 6 + [dependencies]
+3
cli/src/main.rs
··· 1 + fn main() { 2 + println!("Hello, world!"); 3 + }
+6
core/Cargo.toml
··· 1 + [package] 2 + name = "slides-core" 3 + version = "0.1.0" 4 + edition = "2024" 5 + 6 + [dependencies]
+14
core/src/lib.rs
··· 1 + pub fn add(left: u64, right: u64) -> u64 { 2 + left + right 3 + } 4 + 5 + #[cfg(test)] 6 + mod tests { 7 + use super::*; 8 + 9 + #[test] 10 + fn it_works() { 11 + let result = add(2, 2); 12 + assert_eq!(result, 4); 13 + } 14 + }
+79
docs/symbols.md
··· 1 + # Unicode Symbols 2 + 3 + ## Icons/Signage 4 + 5 + | Symbol | Name / Usage | Code | Notes. | 6 + | ------ | ------------------------------------ | ------ | ---------------------------------- | 7 + | ✓ | Check mark | U+2713 | For "done", success, yes | 8 + | ✗ | Cross / X | U+2717 | For "error", no, wrong | 9 + | → | Right arrow | U+2192 | Navigation / "next" | 10 + | ← | Left arrow | U+2190 | Back / "previous" | 11 + | ↑ | Up arrow | U+2191 | Scroll up / move up | 12 + | ↓ | Down arrow | U+2193 | Scroll down / move down | 13 + | • | Bullet | U+2022 | List item, emphasis | 14 + | … | Ellipsis | U+2026 | Continuation, truncation : | 15 + | – | En dash | U+2013 | Ranges, short break | 16 + | — | Em dash | U+2014 | Strong break, parenthetical clause | 17 + | ‒ | Figure dash | U+2012 | Fixed width dash | 18 + | § | Section sign | U+00A7 | For "section", referencing parts | 19 + | ¶ | Pilcrow / paragraph | U+00B6 | Denote paragraph or break | 20 + | ↑↓ | Up-down arrows | U+2195 | Bidirectional movement / toggle | 21 + | ☐ | Empty checkbox | U+2610 | Unchecked box | 22 + | ☑ | Checked checkbox | U+2611 | Checked box | 23 + | ☒ | Crossed checkbox | U+2612 | Marked "X" in box | 24 + | ⚠ | Warning sign | U+26A0 | Warning / caution | 25 + | ⚗ | Alembic symbol | U+2697 | Science / chemistry motif | 26 + | ✳ | Eight-spoked asterisk | U+2733 | Decorative, emphasis | 27 + | ✴ | Eight-pointed star | U+2734 | Decorative bullet / highlight | 28 + | ★ | Black star | U+2605 | Favorite / highlight | 29 + | ☆ | White star | U+2606 | Unselected star | 30 + | ► | Black right-pointing triangle | U+25BA | Play / next marker | 31 + | ▸ | Small black right-pointing triangle | U+25B8 | Sub-indicator | 32 + | ▪ | Small black square | U+25AA | Bullet / small filler | 33 + | ▬ | Black horizontal bar | U+25AC | Divider line | 34 + | ▀ | Upper half block | U+2580 | Block drawing / shading | 35 + | ▄ | Lower half block | U+2584 | Block drawing / shading | 36 + | ▱ | White square with black small square | U+25F1 | Decorative / status | 37 + | ± | Plus-minus | U+00B1 | Variation, tolerance | 38 + | × | Multiplication sign | U+00D7 | Multiplication or "times" | 39 + | ÷ | Division sign | U+00F7 | Division / ratio | 40 + | ¬ | Logical NOT / negation | U+00AC | Logical operator | 41 + 42 + ## Lines & Blocks 43 + 44 + | Symbol | Name / Usage | Code | Notes | 45 + | ------ | ---------------------------------------- | ------ | --------------------------------- | 46 + | ─ | Box Drawings Light Horizontal | U+2500 | Single horizontal line | 47 + | │ | Box Drawings Light Vertical | U+2502 | Single vertical line | 48 + | ┌ | Box Drawings Light Down + Right | U+250C | Top-left corner | 49 + | ┐ | Box Drawings Light Down + Left | U+2510 | Top-right corner | 50 + | └ | Box Drawings Light Up + Right | U+2514 | Bottom-left corner | 51 + | ┘ | Box Drawings Light Up + Left | U+2518 | Bottom-right corner | 52 + | ├ | Box Drawings Light Vertical + Right | U+251C | T junction to the right | 53 + | ┤ | Box Drawings Light Vertical + Left | U+2524 | T junction to the left | 54 + | ┬ | Box Drawings Light Down + Horizontal | U+252C | T junction downward | 55 + | ┴ | Box Drawings Light Up + Horizontal | U+2534 | T junction upward | 56 + | ┼ | Box Drawings Light Vertical + Horizontal | U+253C | Cross intersection | 57 + | ═ | Box Drawings Double Horizontal | U+2550 | Thicker horizontal line | 58 + | ║ | Box Drawings Double Vertical | U+2551 | Thicker vertical line | 59 + | ╔ | Box Drawings Double Down + Right | U+2554 | Double border top-left corner | 60 + | ╗ | Box Drawings Double Down + Left | U+2557 | Double border top-right corner | 61 + | ╚ | Box Drawings Double Up + Right | U+255A | Double border bottom-left corner | 62 + | ╝ | Box Drawings Double Up + Left | U+255D | Double border bottom-right corner | 63 + | ▀ | Upper half block | U+2580 | Fill / shading top half of a cell | 64 + | ▄ | Lower half block | U+2584 | Fill / shading bottom half | 65 + | ▌ | Left half block | U+258C | Fill left half of a cell | 66 + | ▐ | Right half block | U+2590 | Fill right half of a cell | 67 + | ░ | Light shade | U+2591 | Light shading / patterns | 68 + | ▒ | Medium shade | U+2592 | Medium shading | 69 + | ▓ | Dark shade | U+2593 | Dark shading | 70 + | ▉ | Large block / heavy fill | U+2589 | More filled block | 71 + | ▊ | Block | U+258A | Slightly less than full fill | 72 + | ▋ | Block | U+258B | Slightly less than above | 73 + | █ | Full block | U+2588 | Fully filled block | 74 + | ▮ | Black vertical rectangle | U+25AE | Narrow block / bar | 75 + | ▬ | Black horizontal bar | U+25AC | Horizontal bar, divider | 76 + | ╭ | Box Drawings Light Arc Down + Right | U+256D | Rounded corner style | 77 + | ╮ | Box Drawings Light Arc Down + Left | U+256E | Rounded corner | 78 + | ╯ | Box Drawings Light Arc Up + Left | U+256F | Rounded corner | 79 + | ╰ | Box Drawings Light Arc Up + Right | U+2570 | Rounded corner |
+9
rustfmt.toml
··· 1 + max_width = 120 2 + fn_params_layout = "Compressed" 3 + fn_single_line = true 4 + fn_args_layout = "Compressed" 5 + format_strings = true 6 + single_line_if_else_max_width = 100 7 + single_line_let_else_max_width = 100 8 + struct_field_align_threshold = 20 9 + use_field_init_shorthand = true
+6
ui/Cargo.toml
··· 1 + [package] 2 + name = "slides-tui" 3 + version = "0.1.0" 4 + edition = "2024" 5 + 6 + [dependencies]
+14
ui/src/lib.rs
··· 1 + pub fn add(left: u64, right: u64) -> u64 { 2 + left + right 3 + } 4 + 5 + #[cfg(test)] 6 + mod tests { 7 + use super::*; 8 + 9 + #[test] 10 + fn it_works() { 11 + let result = add(2, 2); 12 + assert_eq!(result, 4); 13 + } 14 + }