Docker compose libs update

This commit is contained in:
2026-04-05 01:32:17 -04:00
parent 128a73d5e1
commit cbcd0fbc7b
5 changed files with 71 additions and 65 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ RUN npm run build
# Build Backend # Build Backend
FROM rust:alpine AS backend-builder FROM rust:alpine AS backend-builder
WORKDIR /app 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 RUN git clone -b v0.14.2 --single-branch https://github.com/typst/typst.git typst
COPY server/Cargo.* server/ COPY server/Cargo.* server/
COPY server/src server/src COPY server/src server/src
+1 -1
View File
@@ -22,7 +22,6 @@ ecow = "0.2"
typst = { version = "0.14.2", path = "../typst/crates/typst" } typst = { version = "0.14.2", path = "../typst/crates/typst" }
typst-kit = { path = "../typst/crates/typst-kit", features = ["downloads", "packages", "embed-fonts"] } 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-pdf = { path = "../typst/crates/typst-pdf" }
typst-render = { path = "../typst/crates/typst-render" } typst-render = { path = "../typst/crates/typst-render" }
typst-svg = { path = "../typst/crates/typst-svg" } typst-svg = { path = "../typst/crates/typst-svg" }
@@ -30,3 +29,4 @@ typst-svg = { path = "../typst/crates/typst-svg" }
yrs = "0.18.8" yrs = "0.18.8"
yrs-axum = "0.8" yrs-axum = "0.8"
typst-assets = "0.14.2"
+4 -8
View File
@@ -1,7 +1,7 @@
use crate::world::MemoryWorld; use crate::world::MemoryWorld;
use std::collections::HashMap; use std::collections::HashMap;
use typst::diag::{SourceDiagnostic, Warned}; use typst::diag::{SourceDiagnostic, Warned};
use typst_layout::PagedDocument; use typst::layout::PagedDocument;
use typst_pdf::{pdf, PdfOptions}; use typst_pdf::{pdf, PdfOptions};
use typst_render::render; use typst_render::render;
@@ -23,12 +23,8 @@ impl TypstCompiler {
output: Ok(doc), output: Ok(doc),
warnings: _, warnings: _,
} => { } => {
let svgs = doc let svgs = doc.pages.iter().map(|page| typst_svg::svg(page)).collect();
.pages() let thumbnail = if let Some(page) = doc.pages.first() {
.iter()
.map(|page| typst_svg::svg(page))
.collect();
let thumbnail = if let Some(page) = doc.pages().first() {
typst_svg::svg(page) typst_svg::svg(page)
} else { } else {
String::new() String::new()
@@ -80,7 +76,7 @@ impl TypstCompiler {
output: Ok(doc), output: Ok(doc),
warnings: _, warnings: _,
} => { } => {
if let Some(page) = doc.pages().first() { if let Some(page) = doc.pages.first() {
let pixmap = render(page, 2.0); let pixmap = render(page, 2.0);
if let Ok(encoded) = pixmap.encode_png() { if let Ok(encoded) = pixmap.encode_png() {
return Ok(encoded); return Ok(encoded);
+64 -54
View File
@@ -2,63 +2,70 @@ use chrono::Datelike;
use std::collections::HashMap; use std::collections::HashMap;
use typst::diag::{FileError, FileResult}; use typst::diag::{FileError, FileResult};
use typst::foundations::{Bytes, Datetime, Duration}; use typst::foundations::{Bytes, Datetime};
use typst::syntax::{FileId, RootedPath, Source, VirtualPath, VirtualRoot}; use typst::syntax::{FileId, Source, VirtualPath};
use typst_kit::download::{Downloader, ProgressSink};
use typst_kit::package::PackageStorage;
use typst::text::{Font, FontBook}; use typst::text::{Font, FontBook};
use typst::World; use typst::World;
use typst::{Library, LibraryExt}; use typst::{Library, LibraryExt};
use typst_kit::downloader::SystemDownloader;
use typst_kit::fonts::FontStore;
use typst_kit::packages::SystemPackages;
pub struct MemoryWorld { pub struct MemoryWorld {
library: typst::utils::LazyHash<Library>, library: typst::utils::LazyHash<Library>,
main: FileId, main: FileId,
source: Source, source: Source,
files: HashMap<String, Vec<u8>>, files: HashMap<String, Vec<u8>>,
fonts: std::sync::LazyLock<FontStore, Box<dyn Fn() -> FontStore + Send + Sync>>, book: typst::utils::LazyHash<FontBook>,
packages: SystemPackages, fonts: Vec<Font>,
packages: PackageStorage,
} }
impl MemoryWorld { impl MemoryWorld {
pub fn new(text: String, files: HashMap<String, Vec<u8>>) -> Self { pub fn new(text: String, files: HashMap<String, Vec<u8>>) -> Self {
let main = FileId::new(RootedPath::new( let main = FileId::new(None, VirtualPath::new("main.typ"));
VirtualRoot::Project,
VirtualPath::new("main.typ").unwrap(),
));
let source = Source::new(main, text); let source = Source::new(main, text);
let files_clone = files.clone(); let downloader = Downloader::new("TypstDrive (typst-kit)");
let downloader = SystemDownloader::new("TypstDrive (typst-kit)"); let packages = PackageStorage::new(None, None, downloader);
let packages = SystemPackages::new(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 { Self {
library: typst::utils::LazyHash::new(Library::builder().build()), library: typst::utils::LazyHash::new(Library::builder().build()),
main, main,
source, source,
fonts: std::sync::LazyLock::new(Box::new(move || { files,
let mut store = FontStore::new(); book: typst::utils::LazyHash::new(book),
store.extend(typst_kit::fonts::embedded()); fonts,
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,
packages, packages,
} }
} }
@@ -70,7 +77,7 @@ impl World for MemoryWorld {
} }
fn book(&self) -> &typst::utils::LazyHash<FontBook> { fn book(&self) -> &typst::utils::LazyHash<FontBook> {
self.fonts.book() &self.book
} }
fn main(&self) -> FileId { fn main(&self) -> FileId {
@@ -80,17 +87,18 @@ impl World for MemoryWorld {
fn source(&self, id: FileId) -> FileResult<Source> { fn source(&self, id: FileId) -> FileResult<Source> {
if id == self.main { if id == self.main {
Ok(self.source.clone()) Ok(self.source.clone())
} else if let typst::syntax::VirtualRoot::Package(package) = id.root() { } else if let Some(package) = id.package() {
let root = self let dir = self
.packages .packages
.obtain(package) .prepare_package(package, &mut ProgressSink)
.map_err(|e| FileError::Other(Some(e.to_string().into())))?; .map_err(|e| FileError::Other(Some(e.to_string().into())))?;
let data = root.load(id.vpath())?; let path = id.vpath().resolve(&dir).ok_or_else(|| FileError::NotFound(id.vpath().as_rootless_path().into()))?;
let text = String::from_utf8(data.to_vec()).map_err(|_| FileError::InvalidUtf8)?; 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)) Ok(Source::new(id, text))
} else { } else {
Err(FileError::NotFound( 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<Bytes> { fn file(&self, id: FileId) -> FileResult<Bytes> {
if id == self.main { if id == self.main {
Ok(Bytes::from_string(self.source.text().to_string())) Ok(Bytes::from_string(self.source.text().to_string()))
} else if let typst::syntax::VirtualRoot::Package(package) = id.root() { } else if let Some(package) = id.package() {
let root = self let dir = self
.packages .packages
.obtain(package) .prepare_package(package, &mut ProgressSink)
.map_err(|e| FileError::Other(Some(e.to_string().into())))?; .map_err(|e| FileError::Other(Some(e.to_string().into())))?;
root.load(id.vpath()) let path = id.vpath().resolve(&dir).ok_or_else(|| FileError::NotFound(id.vpath().as_rootless_path().into()))?;
} else if let Some(data) = self.files.get(id.vpath().get_without_slash()) { 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())) Ok(Bytes::new(data.clone()))
} else { } else {
Err(FileError::NotFound( 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<Font> { fn font(&self, index: usize) -> Option<Font> {
self.fonts.font(index) self.fonts.get(index).cloned()
} }
fn today(&self, offset: Option<Duration>) -> Option<Datetime> { fn today(&self, offset: Option<i64>) -> Option<Datetime> {
let now = chrono::Local::now(); let now = chrono::Local::now();
let date = if let Some(offset) = offset { 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() now.with_timezone(&offset).date_naive()
} else { } else {
now.date_naive() now.date_naive()
+1 -1
Submodule typst updated: d6848a802e...b33de9de11