From cbcd0fbc7b33ddcb1e0538b0b0fa2c95c25f4802 Mon Sep 17 00:00:00 2001 From: SirBlobby Date: Sun, 5 Apr 2026 01:32:17 -0400 Subject: [PATCH] Docker compose libs update --- Dockerfile | 2 +- server/Cargo.toml | 2 +- server/src/compiler.rs | 12 ++--- server/src/world.rs | 118 ++++++++++++++++++++++------------------- typst | 2 +- 5 files changed, 71 insertions(+), 65 deletions(-) diff --git a/Dockerfile b/Dockerfile index e709a0e..98fb7d9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ RUN npm run build # Build Backend FROM rust:alpine AS backend-builder WORKDIR /app -RUN apk add --no-cache musl-dev sqlite-dev openssl-dev pkgconfig git +RUN apk add --no-cache musl-dev sqlite-dev openssl-dev openssl-libs-static pkgconfig git RUN git clone -b v0.14.2 --single-branch https://github.com/typst/typst.git typst COPY server/Cargo.* server/ COPY server/src server/src diff --git a/server/Cargo.toml b/server/Cargo.toml index a21dc91..ee405a2 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -22,7 +22,6 @@ ecow = "0.2" typst = { version = "0.14.2", path = "../typst/crates/typst" } typst-kit = { path = "../typst/crates/typst-kit", features = ["downloads", "packages", "embed-fonts"] } -typst-layout = { path = "../typst/crates/typst-layout" } typst-pdf = { path = "../typst/crates/typst-pdf" } typst-render = { path = "../typst/crates/typst-render" } typst-svg = { path = "../typst/crates/typst-svg" } @@ -30,3 +29,4 @@ typst-svg = { path = "../typst/crates/typst-svg" } yrs = "0.18.8" yrs-axum = "0.8" +typst-assets = "0.14.2" diff --git a/server/src/compiler.rs b/server/src/compiler.rs index 6ba0f7f..2667b59 100644 --- a/server/src/compiler.rs +++ b/server/src/compiler.rs @@ -1,7 +1,7 @@ use crate::world::MemoryWorld; use std::collections::HashMap; use typst::diag::{SourceDiagnostic, Warned}; -use typst_layout::PagedDocument; +use typst::layout::PagedDocument; use typst_pdf::{pdf, PdfOptions}; use typst_render::render; @@ -23,12 +23,8 @@ impl TypstCompiler { output: Ok(doc), warnings: _, } => { - let svgs = doc - .pages() - .iter() - .map(|page| typst_svg::svg(page)) - .collect(); - let thumbnail = if let Some(page) = doc.pages().first() { + let svgs = doc.pages.iter().map(|page| typst_svg::svg(page)).collect(); + let thumbnail = if let Some(page) = doc.pages.first() { typst_svg::svg(page) } else { String::new() @@ -80,7 +76,7 @@ impl TypstCompiler { output: Ok(doc), warnings: _, } => { - if let Some(page) = doc.pages().first() { + if let Some(page) = doc.pages.first() { let pixmap = render(page, 2.0); if let Ok(encoded) = pixmap.encode_png() { return Ok(encoded); diff --git a/server/src/world.rs b/server/src/world.rs index 24e6d83..92a31e8 100644 --- a/server/src/world.rs +++ b/server/src/world.rs @@ -2,63 +2,70 @@ use chrono::Datelike; use std::collections::HashMap; use typst::diag::{FileError, FileResult}; -use typst::foundations::{Bytes, Datetime, Duration}; -use typst::syntax::{FileId, RootedPath, Source, VirtualPath, VirtualRoot}; +use typst::foundations::{Bytes, Datetime}; +use typst::syntax::{FileId, Source, VirtualPath}; +use typst_kit::download::{Downloader, ProgressSink}; +use typst_kit::package::PackageStorage; use typst::text::{Font, FontBook}; use typst::World; use typst::{Library, LibraryExt}; -use typst_kit::downloader::SystemDownloader; -use typst_kit::fonts::FontStore; -use typst_kit::packages::SystemPackages; pub struct MemoryWorld { library: typst::utils::LazyHash, main: FileId, source: Source, files: HashMap>, - fonts: std::sync::LazyLock FontStore + Send + Sync>>, - packages: SystemPackages, + book: typst::utils::LazyHash, + fonts: Vec, + packages: PackageStorage, } impl MemoryWorld { pub fn new(text: String, files: HashMap>) -> Self { - let main = FileId::new(RootedPath::new( - VirtualRoot::Project, - VirtualPath::new("main.typ").unwrap(), - )); + let main = FileId::new(None, VirtualPath::new("main.typ")); let source = Source::new(main, text); - let files_clone = files.clone(); - let downloader = SystemDownloader::new("TypstDrive (typst-kit)"); - let packages = SystemPackages::new(downloader); + let downloader = Downloader::new("TypstDrive (typst-kit)"); + let packages = PackageStorage::new(None, None, downloader); + + let mut book = FontBook::new(); + let mut fonts = Vec::new(); + + // Add embedded fonts + for data in typst_assets::fonts() { + let buffer = Bytes::new(data); + for font in Font::iter(buffer) { + book.push(font.info().clone()); + fonts.push(font); + } + } + + // Add custom fonts from files + for (name, data) in &files { + if name.ends_with(".ttf") || name.ends_with(".otf") { + for font in Font::iter(Bytes::new(data.clone())) { + let info = font.info().clone(); + book.push(info.clone()); + fonts.push(font.clone()); + + let mut custom_info = info; + if let Some(stem) = std::path::Path::new(name).file_stem() { + if let Some(stem_str) = stem.to_str() { + custom_info.family = stem_str.to_string(); + book.push(custom_info); + fonts.push(font); + } + } + } + } + } Self { library: typst::utils::LazyHash::new(Library::builder().build()), main, source, - fonts: std::sync::LazyLock::new(Box::new(move || { - let mut store = FontStore::new(); - store.extend(typst_kit::fonts::embedded()); - - for (name, data) in &files { - if name.ends_with(".ttf") || name.ends_with(".otf") { - for font in Font::iter(Bytes::new(data.clone())) { - let info = font.info().clone(); - store.push((font.clone(), info.clone())); - - let mut custom_info = info; - if let Some(stem) = std::path::Path::new(name).file_stem() { - if let Some(stem_str) = stem.to_str() { - custom_info.family = stem_str.to_string(); - store.push((font, custom_info)); - } - } - } - } - } - - store - })), - files: files_clone, + files, + book: typst::utils::LazyHash::new(book), + fonts, packages, } } @@ -70,7 +77,7 @@ impl World for MemoryWorld { } fn book(&self) -> &typst::utils::LazyHash { - self.fonts.book() + &self.book } fn main(&self) -> FileId { @@ -80,17 +87,18 @@ impl World for MemoryWorld { fn source(&self, id: FileId) -> FileResult { if id == self.main { Ok(self.source.clone()) - } else if let typst::syntax::VirtualRoot::Package(package) = id.root() { - let root = self + } else if let Some(package) = id.package() { + let dir = self .packages - .obtain(package) + .prepare_package(package, &mut ProgressSink) .map_err(|e| FileError::Other(Some(e.to_string().into())))?; - let data = root.load(id.vpath())?; - let text = String::from_utf8(data.to_vec()).map_err(|_| FileError::InvalidUtf8)?; + let path = id.vpath().resolve(&dir).ok_or_else(|| FileError::NotFound(id.vpath().as_rootless_path().into()))?; + let data = std::fs::read(&path).map_err(|_| FileError::NotFound(id.vpath().as_rootless_path().into()))?; + let text = String::from_utf8(data).map_err(|_| FileError::InvalidUtf8)?; Ok(Source::new(id, text)) } else { Err(FileError::NotFound( - std::path::Path::new(id.vpath().get_without_slash()).into(), + id.vpath().as_rootless_path().into(), )) } } @@ -98,29 +106,31 @@ impl World for MemoryWorld { fn file(&self, id: FileId) -> FileResult { if id == self.main { Ok(Bytes::from_string(self.source.text().to_string())) - } else if let typst::syntax::VirtualRoot::Package(package) = id.root() { - let root = self + } else if let Some(package) = id.package() { + let dir = self .packages - .obtain(package) + .prepare_package(package, &mut ProgressSink) .map_err(|e| FileError::Other(Some(e.to_string().into())))?; - root.load(id.vpath()) - } else if let Some(data) = self.files.get(id.vpath().get_without_slash()) { + let path = id.vpath().resolve(&dir).ok_or_else(|| FileError::NotFound(id.vpath().as_rootless_path().into()))?; + let data = std::fs::read(&path).map_err(|_| FileError::NotFound(id.vpath().as_rootless_path().into()))?; + Ok(Bytes::new(data)) + } else if let Some(data) = self.files.get(&id.vpath().as_rootless_path().to_string_lossy().to_string().replace("\\", "/")) { Ok(Bytes::new(data.clone())) } else { Err(FileError::NotFound( - std::path::Path::new(id.vpath().get_without_slash()).into(), + id.vpath().as_rootless_path().into(), )) } } fn font(&self, index: usize) -> Option { - self.fonts.font(index) + self.fonts.get(index).cloned() } - fn today(&self, offset: Option) -> Option { + fn today(&self, offset: Option) -> Option { let now = chrono::Local::now(); let date = if let Some(offset) = offset { - let offset = chrono::FixedOffset::east_opt(offset.seconds() as i32)?; + let offset = chrono::FixedOffset::east_opt(offset as i32)?; now.with_timezone(&offset).date_naive() } else { now.date_naive() diff --git a/typst b/typst index d6848a8..b33de9d 160000 --- a/typst +++ b/typst @@ -1 +1 @@ -Subproject commit d6848a802e86a6269300f9768c054a641c2da77f +Subproject commit b33de9de113c91c184214b299bd7a8eb3070c3ab