1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
//! The compiler for the _Typst_ markup language.
//!
//! # Steps
//! - **Parsing:**
//! The compiler first transforms a plain string into an iterator of [tokens].
//! This token stream is [parsed] into a [syntax tree]. The tree itself is
//! untyped, but the [AST] module provides a typed layer over it.
//! - **Evaluation:**
//! The next step is to [evaluate] the markup. This produces a [module],
//! consisting of a scope of values that were exported by the code and
//! [content], a hierarchical, styled representation of what was written in
//! the source file. The elements of the content tree are well structured and
//! order-independent and thus much better suited for further processing than
//! the raw markup.
//! - **Typesetting:**
//! Next, the content is [typeset] into a [document] containing one [frame]
//! per page with items at fixed positions.
//! - **Exporting:**
//! These frames can finally be exported into an output format (currently
//! supported are [PDF] and [raster images]).
//!
//! [tokens]: syntax::SyntaxKind
//! [parsed]: syntax::parse
//! [syntax tree]: syntax::SyntaxNode
//! [AST]: syntax::ast
//! [evaluate]: eval::eval
//! [module]: eval::Module
//! [content]: model::Content
//! [typeset]: model::typeset
//! [document]: doc::Document
//! [frame]: doc::Frame
//! [PDF]: export::pdf
//! [raster images]: export::render
#![recursion_limit = "1000"]
#![allow(clippy::comparison_chain)]
extern crate self as typst;
#[macro_use]
pub mod util;
#[macro_use]
pub mod diag;
#[macro_use]
pub mod eval;
pub mod doc;
pub mod export;
pub mod file;
pub mod font;
pub mod geom;
pub mod ide;
pub mod image;
pub mod model;
pub mod syntax;
use comemo::{Prehashed, Track, TrackedMut};
use ecow::EcoString;
use crate::diag::{FileResult, SourceResult};
use crate::doc::Document;
use crate::eval::{Datetime, Library, Route, Tracer};
use crate::file::{FileId, PackageSpec};
use crate::font::{Font, FontBook};
use crate::syntax::Source;
use crate::util::Bytes;
/// Compile a source file into a fully layouted document.
#[tracing::instrument(skip(world))]
pub fn compile(world: &dyn World) -> SourceResult<Document> {
let route = Route::default();
let mut tracer = Tracer::default();
// Call `track` just once to keep comemo's ID stable.
let world = world.track();
let mut tracer = tracer.track_mut();
// Evaluate the source file into a module.
tracing::info!("Starting evaluation");
let module = eval::eval(
world,
route.track(),
TrackedMut::reborrow_mut(&mut tracer),
&world.main(),
)?;
// Typeset the module's contents.
model::typeset(world, tracer, &module.content())
}
/// The environment in which typesetting occurs.
///
/// All loading functions (`main`, `source`, `file`, `font`) should perform
/// internal caching so that they are relatively cheap on repeated invocations
/// with the same argument. [`Source`], [`Bytes`], and [`Font`] are
/// all reference-counted and thus cheap to clone.
///
/// The compiler doesn't do the caching itself because the world has much more
/// information on when something can change. For example, fonts typically don't
/// change and can thus even be cached across multiple compilations (for
/// long-running applications like `typst watch`). Source files on the other
/// hand can change and should thus be cleared after. Advanced clients like
/// language servers can also retain the source files and [edited](Source::edit)
/// them in-place to benefit from better incremental performance.
#[comemo::track]
pub trait World {
/// The standard library.
fn library(&self) -> &Prehashed<Library>;
/// Metadata about all known fonts.
fn book(&self) -> &Prehashed<FontBook>;
/// Access the main source file.
fn main(&self) -> Source;
/// Try to access the specified source file.
///
/// The returned `Source` file's [id](Source::id) does not have to match the
/// given `id`. Due to symlinks, two different file id's can point to the
/// same on-disk file. Implementors can deduplicate and return the same
/// `Source` if they want to, but do not have to.
fn source(&self, id: FileId) -> FileResult<Source>;
/// Try to access the specified file.
fn file(&self, id: FileId) -> FileResult<Bytes>;
/// Try to access the font with the given index in the font book.
fn font(&self, index: usize) -> Option<Font>;
/// Get the current date.
///
/// If no offset is specified, the local date should be chosen. Otherwise,
/// the UTC date should be chosen with the corresponding offset in hours.
///
/// If this function returns `None`, Typst's `datetime` function will
/// return an error.
fn today(&self, offset: Option<i64>) -> Option<Datetime>;
/// A list of all available packages and optionally descriptions for them.
///
/// This function is optional to implement. It enhances the user experience
/// by enabling autocompletion for packages. Details about packages from the
/// `@preview` namespace are available from
/// `https://packages.typst.org/preview/index.json`.
fn packages(&self) -> &[(PackageSpec, Option<EcoString>)] {
&[]
}
}
|