Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Release

on:
push:
tags:
- "v*"
workflow_dispatch:

jobs:
build-macos:
name: Build macOS .app
runs-on: macos-latest
steps:
- uses: actions/checkout@v4

- name: Install Rust 1.92.0
uses: dtolnay/rust-toolchain@1.92.0

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22"

- name: Install npm dependencies
run: npm ci --prefix apps/desktop

- name: Build the macOS .app (ad-hoc signed)
run: npm run tauri:build --prefix apps/desktop
env:
# Ad-hoc signing (no Apple Developer account needed). The "-"
# identity signs locally without notarization. Users right-click
# → Open to bypass Gatekeeper on first launch.
APPLE_SIGNING_IDENTITY: "-"

- name: Upload .app artifact
uses: actions/upload-artifact@v4
with:
name: 900Slides-macos
path: apps/desktop/src-tauri/target/release/bundle/macos/*.app
if-no-files-found: error

build-linux:
name: Build Linux .deb and .AppImage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install Rust 1.92.0
uses: dtolnay/rust-toolchain@1.92.0

- name: Install Linux system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22"

- name: Install npm dependencies
run: npm ci --prefix apps/desktop

- name: Build Linux bundles
run: npm run tauri:build --prefix apps/desktop

- name: Upload .deb artifact
uses: actions/upload-artifact@v4
with:
name: 900Slides-linux-deb
path: apps/desktop/src-tauri/target/release/bundle/deb/*.deb
if-no-files-found: warn

- name: Upload .AppImage artifact
uses: actions/upload-artifact@v4
with:
name: 900Slides-linux-appimage
path: apps/desktop/src-tauri/target/release/bundle/appimage/*.AppImage
if-no-files-found: warn
23 changes: 22 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,31 @@ This section tracks work toward v0.2.0 (editor completeness). See
[`docs/sprint-records/wave-10.md`](docs/sprint-records/wave-10.md), and
[`docs/sprint-records/wave-11.md`](docs/sprint-records/wave-11.md), and
[`docs/sprint-records/wave-12.md`](docs/sprint-records/wave-12.md), and
[`docs/sprint-records/wave-13.md`](docs/sprint-records/wave-13.md).
[`docs/sprint-records/wave-13.md`](docs/sprint-records/wave-13.md), and
[`docs/sprint-records/wave-14.md`](docs/sprint-records/wave-14.md).

## [v0.3.0 — in progress]

### Added — Wave 14 (ODP import / export)

- The `slides-odp` crate (no longer a stub) supports **opening `.odp`
files** (OpenDocument Presentation) into the `slides-core` model and
**exporting decks to `.odp`**. ODP is a ZIP+XML format using ODF
namespaces (`draw:page`, `draw:frame`, `text:p`).
- **Reader** (`load`): unzips the archive, parses `content.xml`, maps
`draw:frame` elements to model shapes (TextBox, Image, Geometric, Table).
Converts ODP units (cm) to EMU. Unrecognized elements fall back to
Passthrough (no panic).
- **Writer** (`save`): builds a valid ODP archive with `mimetype`,
`content.xml`, `META-INF/manifest.xml`, `styles.xml`, `meta.xml`, and
`Pictures/`. Maps model shapes to `draw:frame` elements. Deterministic
output (fixed metadata date, stable ZIP entry order).
- Round-trip test (save → load → structural equality) verifies text, image,
geometric, and table shapes survive the conversion.
- 17 unit tests (8 reader, 9 writer) including determinism and passthrough
safety.
- `docs/sprint-records/wave-14.md` documenting the wave scope.

### Added — Wave 13 (projector CSS filter panel)

- The presenter gains a **projector compensation filter panel**: invert,
Expand Down
6 changes: 6 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ the deck model, lossless PPTX editing, a basic editor, and recovery.

What v0.1.0 does:

- Opens `.pptx` files and edits **text boxes**: paragraphs, bold, italic,
- Opens `.pptx` files and **`.odp`** files (OpenDocument Presentation) and
edits **text boxes**: paragraphs, bold, italic,
underline, strikethrough, super/subscript, inline code, links, headings
(H1-H6), blockquotes, fenced code blocks (with stepped line-range
highlighting), and indent levels.
Expand Down Expand Up @@ -167,7 +168,7 @@ application:
apps/desktop/ Desktop UI and Tauri command boundary
crates/slides-core/ Deck model, commands, undo, theme
crates/slides-pptx/ PPTX load and save (native format)
crates/slides-odp/ ODP import / export conversion boundary (stub)
crates/slides-odp/ ODP (OpenDocument Presentation) import and export
crates/slides-pdf/ SVG, PNG, and PDF export
crates/slides-render/ Deterministic slide rendering to SVG
crates/slides-animation/ Deterministic build-in timeline and CSS playback
Expand Down
6 changes: 5 additions & 1 deletion apps/desktop/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@
}
},
"bundle": {
"active": false
"active": true,
"targets": ["app"],
"macOS": {
"signingIdentity": "-"
}
},
"plugins": {}
}
6 changes: 6 additions & 0 deletions crates/slides-odp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ edition.workspace = true
license.workspace = true
authors.workspace = true
description = "ODP import / export conversion boundary"

[dependencies]
slides-core = { workspace = true }
zip = { workspace = true }
quick-xml = { workspace = true }
thiserror = { workspace = true }
32 changes: 32 additions & 0 deletions crates/slides-odp/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//! Error types for the ODP reader.

use thiserror::Error;

/// Errors returned by the ODP loader.
#[derive(Debug, Error)]
pub enum Error {
/// A ZIP read/write error.
#[error("odp zip error: {0}")]
Zip(#[from] zip::result::ZipError),
/// A generic I/O error.
#[error("odp io error: {0}")]
Io(#[from] std::io::Error),
/// XML parsing failed.
#[error("odp xml error: {0}")]
Xml(String),
/// The package does not contain the required part.
#[error("odp missing part: {0}")]
MissingPart(String),
/// The package has an unsupported structure.
#[error("odp unsupported format: {0}")]
UnsupportedFormat(String),
}

impl From<quick_xml::Error> for Error {
fn from(value: quick_xml::Error) -> Self {
Error::Xml(value.to_string())
}
}

/// Result type alias for ODP loading.
pub type Result<T> = std::result::Result<T, Error>;
7 changes: 7 additions & 0 deletions crates/slides-odp/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
//! ODP import / export conversion boundary.

mod error;
mod load;
mod save;

pub use load::load;
pub use save::save;

/// Returns the crate version.
pub fn version() -> &'static str {
env!("CARGO_PKG_VERSION")
Expand Down
Loading
Loading