Skip to content

Commit

Permalink
Update typst to 0.10.0
Browse files Browse the repository at this point in the history
  • Loading branch information
messense committed Dec 5, 2023
1 parent bafa454 commit eca3227
Show file tree
Hide file tree
Showing 11 changed files with 410 additions and 509 deletions.
740 changes: 331 additions & 409 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ ecow = "0.2"
env_proxy = "0.4"
filetime = "0.2.22"
flate2 = "1"
fontdb = "0.15.0"
fontdb = "0.16.0"
pathdiff = "0.2"
pyo3 = { version = "0.20.0", features = ["abi3-py37"] }
same-file = "1"
siphasher = "1.0"
tar = "0.4"
typst = { git = "https://github.com/typst/typst.git", tag = "v0.9.0" }
typst-library = { git = "https://github.com/typst/typst.git", tag = "v0.9.0" }
typst = { git = "https://github.com/typst/typst.git", tag = "v0.10.0" }
typst-pdf = { git = "https://github.com/typst/typst.git", tag = "v0.10.0" }
ureq = { version = "2", default-features = false, features = [
"gzip",
"socks-proxy",
Expand Down
Binary file modified python/typst/fonts/NewCM10-Bold.otf
Binary file not shown.
Binary file modified python/typst/fonts/NewCM10-BoldItalic.otf
Binary file not shown.
Binary file modified python/typst/fonts/NewCM10-Italic.otf
Binary file not shown.
Binary file modified python/typst/fonts/NewCM10-Regular.otf
Binary file not shown.
Binary file modified python/typst/fonts/NewCMMath-Book.otf
Binary file not shown.
Binary file modified python/typst/fonts/NewCMMath-Regular.otf
Binary file not shown.
8 changes: 5 additions & 3 deletions src/compiler.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use chrono::{Datelike, Timelike};
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::term::{self, termcolor};
use ecow::eco_format;
use typst::diag::{Severity, SourceDiagnostic, StrResult};
use typst::doc::Document;
use typst::eval::{eco_format, Datetime, Tracer};
use typst::eval::Tracer;
use typst::foundations::Datetime;
use typst::model::Document;
use typst::syntax::{FileId, Source, Span};
use typst::{World, WorldExt};

Expand Down Expand Up @@ -34,7 +36,7 @@ impl SystemWorld {
#[inline]
fn export_pdf(document: &Document, world: &SystemWorld) -> StrResult<Vec<u8>> {
let ident = world.input().to_string_lossy();
let buffer = typst::export::pdf(document, Some(&ident), now());
let buffer = typst_pdf::pdf(document, Some(&ident), now());
Ok(buffer)
}

Expand Down
2 changes: 1 addition & 1 deletion src/fonts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::fs::{self};
use std::path::PathBuf;

use fontdb::{Database, Source};
use typst::font::{Font, FontBook, FontInfo};
use typst::text::{Font, FontBook, FontInfo};

/// Searches for fonts.
pub struct FontSearcher {
Expand Down
163 changes: 70 additions & 93 deletions src/world.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
use std::cell::{Cell, OnceCell, RefCell, RefMut};
use std::collections::HashMap;
use std::fs;
use std::hash::Hash;
use std::path::{Path, PathBuf};

use chrono::{DateTime, Datelike, Local};
use comemo::Prehashed;
use filetime::FileTime;
use same_file::Handle;
use siphasher::sip128::{Hasher128, SipHasher13};
use ecow::eco_format;
use typst::diag::{FileError, FileResult, StrResult};
use typst::eval::{eco_format, Bytes, Datetime, Library};
use typst::font::{Font, FontBook};
use typst::foundations::{Bytes, Datetime};
use typst::syntax::{FileId, Source, VirtualPath};
use typst::World;
use typst::text::{Font, FontBook};
use typst::{Library, World};

use crate::fonts::{FontSearcher, FontSlot};
use crate::package::prepare_package;
Expand All @@ -34,12 +31,8 @@ pub struct SystemWorld {
book: Prehashed<FontBook>,
/// Locations of and storage for lazily loaded fonts.
fonts: Vec<FontSlot>,
/// Maps package-path combinations to canonical hashes. All package-path
/// combinations that point to the same file are mapped to the same hash. To
/// be used in conjunction with `paths`.
hashes: RefCell<HashMap<FileId, FileResult<PathHash>>>,
/// Maps canonical path hashes to source files and buffers.
slots: RefCell<HashMap<PathHash, PathSlot>>,
/// Maps file ids to source files and buffers.
slots: RefCell<HashMap<FileId, FileSlot>>,
/// The current datetime if requested. This is stored here to ensure it is
/// always the same within one compilation. Reset between compilations.
now: OnceCell<DateTime<Local>>,
Expand All @@ -59,11 +52,11 @@ impl World for SystemWorld {
}

fn source(&self, id: FileId) -> FileResult<Source> {
self.slot(id)?.source()
self.slot(id)?.source(&self.root)
}

fn file(&self, id: FileId) -> FileResult<Bytes> {
self.slot(id)?.file()
self.slot(id)?.file(&self.root)
}

fn font(&self, index: usize) -> Option<Font> {
Expand Down Expand Up @@ -92,33 +85,9 @@ impl SystemWorld {
}

/// Access the canonical slot for the given file id.
fn slot(&self, id: FileId) -> FileResult<RefMut<PathSlot>> {
let mut system_path = PathBuf::new();
let hash = self
.hashes
.borrow_mut()
.entry(id)
.or_insert_with(|| {
// Determine the root path relative to which the file path
// will be resolved.
let buf;
let mut root = &self.root;
if let Some(spec) = id.package() {
buf = prepare_package(spec)?;
root = &buf;
}
// Join the path to the root. If it tries to escape, deny
// access. Note: It can still escape via symlinks.
system_path = id.vpath().resolve(root).ok_or(FileError::AccessDenied)?;

PathHash::new(&system_path)
})
.clone()?;

Ok(RefMut::map(self.slots.borrow_mut(), |paths| {
paths
.entry(hash)
.or_insert_with(|| PathSlot::new(id, system_path))
fn slot(&self, id: FileId) -> FileResult<RefMut<FileSlot>> {
Ok(RefMut::map(self.slots.borrow_mut(), |slots| {
slots.entry(id).or_insert_with(|| FileSlot::new(id))
}))
}

Expand All @@ -139,7 +108,6 @@ impl SystemWorld {

/// Reset the compilation state in preparation of a new compilation.
pub fn reset(&mut self) {
self.hashes.borrow_mut().clear();
for slot in self.slots.borrow_mut().values_mut() {
slot.reset();
}
Expand Down Expand Up @@ -202,10 +170,9 @@ impl SystemWorldBuilder {
input,
root: self.root,
main: FileId::new(None, main_path),
library: Prehashed::new(typst_library::build()),
library: Prehashed::new(Library::build()),
book: Prehashed::new(searcher.book),
fonts: searcher.fonts,
hashes: RefCell::default(),
slots: RefCell::default(),
now: OnceCell::new(),
};
Expand All @@ -216,23 +183,20 @@ impl SystemWorldBuilder {
/// Holds canonical data for all paths pointing to the same entity.
///
/// Both fields can be populated if the file is both imported and read().
struct PathSlot {
struct FileSlot {
/// The slot's canonical file id.
id: FileId,
/// The slot's path on the system.
path: PathBuf,
/// The lazily loaded and incrementally updated source file.
source: SlotCell<Source>,
/// The lazily loaded raw byte buffer.
file: SlotCell<Bytes>,
}

impl PathSlot {
impl FileSlot {
/// Create a new path slot.
fn new(id: FileId, path: PathBuf) -> Self {
fn new(id: FileId) -> Self {
Self {
id,
path,
file: SlotCell::new(),
source: SlotCell::new(),
}
Expand All @@ -245,27 +209,50 @@ impl PathSlot {
self.file.reset();
}

fn source(&self) -> FileResult<Source> {
self.source.get_or_init(&self.path, |data, prev| {
let text = decode_utf8(&data)?;
if let Some(mut prev) = prev {
prev.replace(text);
Ok(prev)
} else {
Ok(Source::new(self.id, text.into()))
}
})
fn source(&self, root: &Path) -> FileResult<Source> {
self.source.get_or_init(
|| self.system_path(root),
|data, prev| {
let text = decode_utf8(&data)?;
if let Some(mut prev) = prev {
prev.replace(text);
Ok(prev)
} else {
Ok(Source::new(self.id, text.into()))
}
},
)
}

fn file(&self, root: &Path) -> FileResult<Bytes> {
self.file
.get_or_init(|| self.system_path(root), |data, _| Ok(data.into()))
}

fn file(&self) -> FileResult<Bytes> {
self.file.get_or_init(&self.path, |data, _| Ok(data.into()))
/// The path of the slot on the system.
fn system_path(&self, root: &Path) -> FileResult<PathBuf> {
// Determine the root path relative to which the file path
// will be resolved.
let buf;
let mut root = root;
if let Some(spec) = self.id.package() {
buf = prepare_package(spec)?;
root = &buf;
}

// Join the path to the root. If it tries to escape, deny
// access. Note: It can still escape via symlinks.
self.id.vpath().resolve(root).ok_or(FileError::AccessDenied)
}
}

/// Lazily processes data for a file.
struct SlotCell<T> {
/// The processed data.
data: RefCell<Option<FileResult<T>>>,
refreshed: Cell<FileTime>,
/// A hash of the raw file contents / access error.
fingerprint: Cell<u128>,
/// Whether the slot has been accessed in the current compilation.
accessed: Cell<bool>,
}

Expand All @@ -274,7 +261,7 @@ impl<T: Clone> SlotCell<T> {
fn new() -> Self {
Self {
data: RefCell::new(None),
refreshed: Cell::new(FileTime::zero()),
fingerprint: Cell::new(0),
accessed: Cell::new(false),
}
}
Expand All @@ -288,44 +275,34 @@ impl<T: Clone> SlotCell<T> {
/// Gets the contents of the cell or initialize them.
fn get_or_init(
&self,
path: &Path,
path: impl FnOnce() -> FileResult<PathBuf>,
f: impl FnOnce(Vec<u8>, Option<T>) -> FileResult<T>,
) -> FileResult<T> {
let mut borrow = self.data.borrow_mut();
if let Some(data) = &*borrow {
if self.accessed.replace(true) || self.current(path) {

// If we accessed the file already in this compilation, retrieve it.
if self.accessed.replace(true) {
if let Some(data) = &*borrow {
return data.clone();
}
}

// Read and hash the file.
let result = path().and_then(|p| read(&p));
let fingerprint = typst::util::hash128(&result);

// If the file contents didn't change, yield the old processed data.
if self.fingerprint.replace(fingerprint) == fingerprint {
if let Some(data) = &*borrow {
return data.clone();
}
}

self.accessed.set(true);
self.refreshed.set(FileTime::now());
let prev = borrow.take().and_then(Result::ok);
let value = read(path).and_then(|data| f(data, prev));
let value = result.and_then(|data| f(data, prev));
*borrow = Some(value.clone());
value
}

/// Whether the cell contents are still up to date with the file system.
fn current(&self, path: &Path) -> bool {
fs::metadata(path).map_or(false, |meta| {
let modified = FileTime::from_last_modification_time(&meta);
modified < self.refreshed.get()
})
}
}

/// A hash that is the same for all paths pointing to the same entity.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
struct PathHash(u128);

impl PathHash {
fn new(path: &Path) -> FileResult<Self> {
let f = |e| FileError::from_io(e, path);
let handle = Handle::from_path(path).map_err(f)?;
let mut state = SipHasher13::new();
handle.hash(&mut state);
Ok(Self(state.finish128().as_u128()))
value
}
}

Expand Down

0 comments on commit eca3227

Please sign in to comment.