Docker compose libs update
This commit is contained in:
+1
-1
@@ -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
@@ -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"
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
+52
-42
@@ -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);
|
|
||||||
|
|
||||||
Self {
|
let mut book = FontBook::new();
|
||||||
library: typst::utils::LazyHash::new(Library::builder().build()),
|
let mut fonts = Vec::new();
|
||||||
main,
|
|
||||||
source,
|
|
||||||
fonts: std::sync::LazyLock::new(Box::new(move || {
|
|
||||||
let mut store = FontStore::new();
|
|
||||||
store.extend(typst_kit::fonts::embedded());
|
|
||||||
|
|
||||||
|
// 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 {
|
for (name, data) in &files {
|
||||||
if name.ends_with(".ttf") || name.ends_with(".otf") {
|
if name.ends_with(".ttf") || name.ends_with(".otf") {
|
||||||
for font in Font::iter(Bytes::new(data.clone())) {
|
for font in Font::iter(Bytes::new(data.clone())) {
|
||||||
let info = font.info().clone();
|
let info = font.info().clone();
|
||||||
store.push((font.clone(), info.clone()));
|
book.push(info.clone());
|
||||||
|
fonts.push(font.clone());
|
||||||
|
|
||||||
let mut custom_info = info;
|
let mut custom_info = info;
|
||||||
if let Some(stem) = std::path::Path::new(name).file_stem() {
|
if let Some(stem) = std::path::Path::new(name).file_stem() {
|
||||||
if let Some(stem_str) = stem.to_str() {
|
if let Some(stem_str) = stem.to_str() {
|
||||||
custom_info.family = stem_str.to_string();
|
custom_info.family = stem_str.to_string();
|
||||||
store.push((font, custom_info));
|
book.push(custom_info);
|
||||||
|
fonts.push(font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
store
|
Self {
|
||||||
})),
|
library: typst::utils::LazyHash::new(Library::builder().build()),
|
||||||
files: files_clone,
|
main,
|
||||||
|
source,
|
||||||
|
files,
|
||||||
|
book: typst::utils::LazyHash::new(book),
|
||||||
|
fonts,
|
||||||
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
Reference in New Issue
Block a user