summaryrefslogtreecommitdiff
path: root/src/lib.rs
blob: 051a58f3c12dd256c8e7fbfb0482f579af56935f (plain) (blame)
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
//! The compiler for the _Typst_ typesetting language.
//!
//! # Steps
//! - **Parsing:** The parsing step first transforms a plain string into an
//!   [iterator of tokens][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 the text,
//!   structure, layouts, etc. of the module. The nodes of the content tree are
//!   well structured and order-independent and thus much better suited for
//!   layouting than the raw markup.
//! - **Layouting:** Next, the content is layouted into a portable version of
//!   the typeset document. The output of this is a collection of [`Frame`]s
//!   (one per page), ready for exporting.
//! - **Exporting:** The finished layout can be exported into a supported
//!   format. Currently, the only supported output format is [PDF].
//!
//! [tokens]: syntax::Tokens
//! [parsed]: syntax::parse
//! [syntax tree]: syntax::SyntaxNode
//! [AST]: syntax::ast
//! [evaluate]: model::eval
//! [module]: model::Module
//! [content]: model::Content
//! [PDF]: export::pdf

#![allow(clippy::len_without_is_empty)]
#![allow(clippy::or_fun_call)]
#![allow(clippy::try_err)]

#[macro_use]
pub mod util;
#[macro_use]
pub mod geom;
#[macro_use]
pub mod diag;
#[macro_use]
pub mod model;
pub mod export;
pub mod font;
pub mod frame;
pub mod image;
pub mod library;
pub mod syntax;

use std::num::NonZeroUsize;
use std::path::{Path, PathBuf};

use comemo::{Prehashed, Track};

use crate::diag::{FileResult, SourceResult};
use crate::font::{Font, FontBook};
use crate::frame::Frame;
use crate::model::{Content, Route, Scope, StyleMap};
use crate::syntax::{Source, SourceId};
use crate::util::{Buffer, EcoString};

/// Typeset a source file into a collection of layouted frames.
///
/// Returns either a vector of frames representing individual pages or
/// diagnostics in the form of a vector of error message with file and span
/// information.
pub fn typeset(
    world: &(dyn World + 'static),
    main: SourceId,
) -> SourceResult<Vec<Frame>> {
    let route = Route::default();
    let module = model::eval(world.track(), route.track(), main)?;
    library::layout::Layout::layout(&module.content, world.track())
}

/// The environment in which typesetting occurs.
#[comemo::track]
pub trait World {
    /// Access the global configuration.
    fn config(&self) -> &Prehashed<Config>;

    /// Metadata about all known fonts.
    fn book(&self) -> &Prehashed<FontBook>;

    /// Try to access the font with the given id.
    fn font(&self, id: usize) -> Option<Font>;

    /// Try to access a file at a path.
    fn file(&self, path: &Path) -> FileResult<Buffer>;

    /// Try to resolve the unique id of a source file.
    fn resolve(&self, path: &Path) -> FileResult<SourceId>;

    /// Access a source file by id.
    fn source(&self, id: SourceId) -> &Source;
}

/// The global configuration for typesetting.
#[derive(Debug, Clone, Hash)]
pub struct Config {
    /// The compilation root, relative to which absolute paths are.
    ///
    /// Default: Empty path.
    pub root: PathBuf,
    /// The scope containing definitions that are available everywhere.
    ///
    /// Default: Typst's standard library.
    pub std: Scope,
    /// Defines which standard library items fulfill which syntactical roles.
    ///
    /// Default: Typst's standard library's language map.
    pub items: LangItems,
    /// The default properties for page size, font selection and so on.
    ///
    /// Default: Empty style map.
    pub styles: StyleMap,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            root: PathBuf::new(),
            std: library::scope(),
            items: library::items(),
            styles: StyleMap::new(),
        }
    }
}

/// Definition of certain standard library items the language is aware of.
#[derive(Debug, Clone, Hash)]
pub struct LangItems {
    pub space: fn() -> Content,
    pub linebreak: fn(justify: bool) -> Content,
    pub text: fn(text: EcoString) -> Content,
    pub smart_quote: fn(double: bool) -> Content,
    pub parbreak: fn() -> Content,
    pub strong: fn(body: Content) -> Content,
    pub emph: fn(body: Content) -> Content,
    pub raw: fn(text: EcoString, tag: Option<EcoString>, block: bool) -> Content,
    pub link: fn(label: EcoString) -> Content,
    pub ref_: fn(target: EcoString) -> Content,
    pub heading: fn(level: NonZeroUsize, body: Content) -> Content,
    pub list_item: fn(body: Content) -> Content,
    pub enum_item: fn(number: Option<usize>, body: Content) -> Content,
    pub desc_item: fn(term: Content, body: Content) -> Content,
}