typst 0.14.2.2 → 0.15.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +78 -21
- data/README.typ +83 -21
- data/ext/typst/Cargo.toml +16 -13
- data/ext/typst/src/compiler.rs +28 -19
- data/ext/typst/src/download.rs +3 -15
- data/ext/typst/src/lib.rs +10 -85
- data/ext/typst/src/query.rs +10 -6
- data/ext/typst/src/world.rs +92 -59
- data/lib/base.rb +5 -5
- data/lib/query.rb +2 -2
- data/lib/typst.rb +3 -3
- metadata +4 -19
- data/ext/typst/src/fonts.rs +0 -86
- data/lib/fonts/DejaVuSansMono-Bold.ttf +0 -0
- data/lib/fonts/DejaVuSansMono-BoldOblique.ttf +0 -0
- data/lib/fonts/DejaVuSansMono-Oblique.ttf +0 -0
- data/lib/fonts/DejaVuSansMono.ttf +0 -0
- data/lib/fonts/LinLibertine_R.ttf +0 -0
- data/lib/fonts/LinLibertine_RB.ttf +0 -0
- data/lib/fonts/LinLibertine_RBI.ttf +0 -0
- data/lib/fonts/LinLibertine_RI.ttf +0 -0
- data/lib/fonts/NewCM10-Bold.otf +0 -0
- data/lib/fonts/NewCM10-BoldItalic.otf +0 -0
- data/lib/fonts/NewCM10-Italic.otf +0 -0
- data/lib/fonts/NewCM10-Regular.otf +0 -0
- data/lib/fonts/NewCMMath-Book.otf +0 -0
- data/lib/fonts/NewCMMath-Regular.otf +0 -0
data/ext/typst/src/lib.rs
CHANGED
|
@@ -19,8 +19,8 @@ fn to_html(
|
|
|
19
19
|
input: PathBuf,
|
|
20
20
|
root: Option<PathBuf>,
|
|
21
21
|
font_paths: Vec<PathBuf>,
|
|
22
|
-
resource_path: PathBuf,
|
|
23
22
|
ignore_system_fonts: bool,
|
|
23
|
+
ignore_embedded_fonts: bool,
|
|
24
24
|
sys_inputs: HashMap<String, String>,
|
|
25
25
|
) -> Result<Vec<Vec<u8>>, Error> {
|
|
26
26
|
let input = input.canonicalize()
|
|
@@ -35,22 +35,6 @@ fn to_html(
|
|
|
35
35
|
PathBuf::new()
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
let resource_path = resource_path.canonicalize()
|
|
39
|
-
.map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?;
|
|
40
|
-
|
|
41
|
-
let mut default_fonts = Vec::new();
|
|
42
|
-
for entry in walkdir::WalkDir::new(resource_path.join("fonts")) {
|
|
43
|
-
let path = entry
|
|
44
|
-
.map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?
|
|
45
|
-
.into_path();
|
|
46
|
-
let Some(extension) = path.extension() else {
|
|
47
|
-
continue;
|
|
48
|
-
};
|
|
49
|
-
if extension == "ttf" || extension == "otf" {
|
|
50
|
-
default_fonts.push(path);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
38
|
let mut features = Vec::new();
|
|
55
39
|
features.push(Feature::Html);
|
|
56
40
|
|
|
@@ -72,6 +56,7 @@ fn to_html(
|
|
|
72
56
|
.features(feat)
|
|
73
57
|
.font_paths(font_paths)
|
|
74
58
|
.ignore_system_fonts(ignore_system_fonts)
|
|
59
|
+
.ignore_embedded_fonts(ignore_embedded_fonts)
|
|
75
60
|
.build()
|
|
76
61
|
.map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
|
|
77
62
|
|
|
@@ -87,8 +72,8 @@ fn to_svg(
|
|
|
87
72
|
input: PathBuf,
|
|
88
73
|
root: Option<PathBuf>,
|
|
89
74
|
font_paths: Vec<PathBuf>,
|
|
90
|
-
resource_path: PathBuf,
|
|
91
75
|
ignore_system_fonts: bool,
|
|
76
|
+
ignore_embedded_fonts: bool,
|
|
92
77
|
sys_inputs: HashMap<String, String>,
|
|
93
78
|
) -> Result<Vec<Vec<u8>>, Error> {
|
|
94
79
|
let input = input.canonicalize()
|
|
@@ -103,22 +88,6 @@ fn to_svg(
|
|
|
103
88
|
PathBuf::new()
|
|
104
89
|
};
|
|
105
90
|
|
|
106
|
-
let resource_path = resource_path.canonicalize()
|
|
107
|
-
.map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?;
|
|
108
|
-
|
|
109
|
-
let mut default_fonts = Vec::new();
|
|
110
|
-
for entry in walkdir::WalkDir::new(resource_path.join("fonts")) {
|
|
111
|
-
let path = entry
|
|
112
|
-
.map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?
|
|
113
|
-
.into_path();
|
|
114
|
-
let Some(extension) = path.extension() else {
|
|
115
|
-
continue;
|
|
116
|
-
};
|
|
117
|
-
if extension == "ttf" || extension == "otf" {
|
|
118
|
-
default_fonts.push(path);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
91
|
let mut world = SystemWorld::builder(root, input)
|
|
123
92
|
.inputs(Dict::from_iter(
|
|
124
93
|
sys_inputs
|
|
@@ -127,6 +96,7 @@ fn to_svg(
|
|
|
127
96
|
))
|
|
128
97
|
.font_paths(font_paths)
|
|
129
98
|
.ignore_system_fonts(ignore_system_fonts)
|
|
99
|
+
.ignore_embedded_fonts(ignore_embedded_fonts)
|
|
130
100
|
.build()
|
|
131
101
|
.map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
|
|
132
102
|
|
|
@@ -142,8 +112,8 @@ fn to_png(
|
|
|
142
112
|
input: PathBuf,
|
|
143
113
|
root: Option<PathBuf>,
|
|
144
114
|
font_paths: Vec<PathBuf>,
|
|
145
|
-
resource_path: PathBuf,
|
|
146
115
|
ignore_system_fonts: bool,
|
|
116
|
+
ignore_embedded_fonts: bool,
|
|
147
117
|
sys_inputs: HashMap<String, String>,
|
|
148
118
|
ppi: Option<f32>,
|
|
149
119
|
) -> Result<Vec<Vec<u8>>, Error> {
|
|
@@ -159,22 +129,6 @@ fn to_png(
|
|
|
159
129
|
PathBuf::new()
|
|
160
130
|
};
|
|
161
131
|
|
|
162
|
-
let resource_path = resource_path.canonicalize()
|
|
163
|
-
.map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?;
|
|
164
|
-
|
|
165
|
-
let mut default_fonts = Vec::new();
|
|
166
|
-
for entry in walkdir::WalkDir::new(resource_path.join("fonts")) {
|
|
167
|
-
let path = entry
|
|
168
|
-
.map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?
|
|
169
|
-
.into_path();
|
|
170
|
-
let Some(extension) = path.extension() else {
|
|
171
|
-
continue;
|
|
172
|
-
};
|
|
173
|
-
if extension == "ttf" || extension == "otf" {
|
|
174
|
-
default_fonts.push(path);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
132
|
let mut world = SystemWorld::builder(root, input)
|
|
179
133
|
.inputs(Dict::from_iter(
|
|
180
134
|
sys_inputs
|
|
@@ -183,6 +137,7 @@ fn to_png(
|
|
|
183
137
|
))
|
|
184
138
|
.font_paths(font_paths)
|
|
185
139
|
.ignore_system_fonts(ignore_system_fonts)
|
|
140
|
+
.ignore_embedded_fonts(ignore_embedded_fonts)
|
|
186
141
|
.build()
|
|
187
142
|
.map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
|
|
188
143
|
|
|
@@ -198,8 +153,8 @@ fn to_pdf(
|
|
|
198
153
|
input: PathBuf,
|
|
199
154
|
root: Option<PathBuf>,
|
|
200
155
|
font_paths: Vec<PathBuf>,
|
|
201
|
-
resource_path: PathBuf,
|
|
202
156
|
ignore_system_fonts: bool,
|
|
157
|
+
ignore_embedded_fonts: bool,
|
|
203
158
|
sys_inputs: HashMap<String, String>,
|
|
204
159
|
pdf_standards: Vec<String>,
|
|
205
160
|
) -> Result<Vec<Vec<u8>>, Error> {
|
|
@@ -215,22 +170,6 @@ fn to_pdf(
|
|
|
215
170
|
PathBuf::new()
|
|
216
171
|
};
|
|
217
172
|
|
|
218
|
-
let resource_path = resource_path.canonicalize()
|
|
219
|
-
.map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?;
|
|
220
|
-
|
|
221
|
-
let mut default_fonts = Vec::new();
|
|
222
|
-
for entry in walkdir::WalkDir::new(resource_path.join("fonts")) {
|
|
223
|
-
let path = entry
|
|
224
|
-
.map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?
|
|
225
|
-
.into_path();
|
|
226
|
-
let Some(extension) = path.extension() else {
|
|
227
|
-
continue;
|
|
228
|
-
};
|
|
229
|
-
if extension == "ttf" || extension == "otf" {
|
|
230
|
-
default_fonts.push(path);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
173
|
let mut world = SystemWorld::builder(root, input)
|
|
235
174
|
.inputs(Dict::from_iter(
|
|
236
175
|
sys_inputs
|
|
@@ -239,6 +178,7 @@ fn to_pdf(
|
|
|
239
178
|
))
|
|
240
179
|
.font_paths(font_paths)
|
|
241
180
|
.ignore_system_fonts(ignore_system_fonts)
|
|
181
|
+
.ignore_embedded_fonts(ignore_embedded_fonts)
|
|
242
182
|
.build()
|
|
243
183
|
.map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
|
|
244
184
|
|
|
@@ -287,8 +227,8 @@ fn query(
|
|
|
287
227
|
input: PathBuf,
|
|
288
228
|
root: Option<PathBuf>,
|
|
289
229
|
font_paths: Vec<PathBuf>,
|
|
290
|
-
resource_path: PathBuf,
|
|
291
230
|
ignore_system_fonts: bool,
|
|
231
|
+
ignore_embedded_fonts: bool,
|
|
292
232
|
sys_inputs: HashMap<String, String>,
|
|
293
233
|
) -> Result<String, Error> {
|
|
294
234
|
let format = match format.unwrap().to_ascii_lowercase().as_str() {
|
|
@@ -309,22 +249,6 @@ fn query(
|
|
|
309
249
|
PathBuf::new()
|
|
310
250
|
};
|
|
311
251
|
|
|
312
|
-
let resource_path = resource_path.canonicalize()
|
|
313
|
-
.map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?;
|
|
314
|
-
|
|
315
|
-
let mut default_fonts = Vec::new();
|
|
316
|
-
for entry in walkdir::WalkDir::new(resource_path.join("fonts")) {
|
|
317
|
-
let path = entry
|
|
318
|
-
.map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?
|
|
319
|
-
.into_path();
|
|
320
|
-
let Some(extension) = path.extension() else {
|
|
321
|
-
continue;
|
|
322
|
-
};
|
|
323
|
-
if extension == "ttf" || extension == "otf" {
|
|
324
|
-
default_fonts.push(path);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
|
|
328
252
|
let mut world = SystemWorld::builder(root, input)
|
|
329
253
|
.inputs(Dict::from_iter(
|
|
330
254
|
sys_inputs
|
|
@@ -333,6 +257,7 @@ fn query(
|
|
|
333
257
|
))
|
|
334
258
|
.font_paths(font_paths)
|
|
335
259
|
.ignore_system_fonts(ignore_system_fonts)
|
|
260
|
+
.ignore_embedded_fonts(ignore_embedded_fonts)
|
|
336
261
|
.build()
|
|
337
262
|
.map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
|
|
338
263
|
|
data/ext/typst/src/query.rs
CHANGED
|
@@ -3,8 +3,10 @@ use ecow::{eco_format, EcoString};
|
|
|
3
3
|
use serde::Serialize;
|
|
4
4
|
use typst::diag::{bail, StrResult, Warned};
|
|
5
5
|
use typst::engine::Sink;
|
|
6
|
-
use typst::foundations::{Content, IntoValue, LocatableSelector, Scope};
|
|
7
|
-
use typst::
|
|
6
|
+
use typst::foundations::{Content, Context, IntoValue, LocatableSelector, Scope};
|
|
7
|
+
use typst::introspection::{EmptyIntrospector, Introspector};
|
|
8
|
+
use typst::routines::SpanMode;
|
|
9
|
+
use typst_layout::PagedDocument;
|
|
8
10
|
use typst::syntax::Span;
|
|
9
11
|
use typst::syntax::SyntaxMode;
|
|
10
12
|
use typst::World;
|
|
@@ -73,13 +75,15 @@ fn retrieve(
|
|
|
73
75
|
document: &PagedDocument,
|
|
74
76
|
) -> StrResult<Vec<Content>> {
|
|
75
77
|
let selector = eval_string(
|
|
76
|
-
&typst::ROUTINES,
|
|
77
78
|
world.track(),
|
|
79
|
+
world.library(),
|
|
78
80
|
Sink::new().track_mut(),
|
|
81
|
+
EmptyIntrospector.track(),
|
|
82
|
+
Context::none().track(),
|
|
79
83
|
&command.selector,
|
|
80
|
-
Span::detached(),
|
|
84
|
+
SpanMode::Uniform(Span::detached()),
|
|
81
85
|
SyntaxMode::Code,
|
|
82
|
-
Scope::default()
|
|
86
|
+
Scope::default()
|
|
83
87
|
)
|
|
84
88
|
.map_err(|errors| {
|
|
85
89
|
let mut message = EcoString::from("failed to evaluate selector");
|
|
@@ -93,7 +97,7 @@ fn retrieve(
|
|
|
93
97
|
.map_err(|e| e.message().clone())?;
|
|
94
98
|
|
|
95
99
|
Ok(document
|
|
96
|
-
.introspector
|
|
100
|
+
.introspector()
|
|
97
101
|
.query(&selector.0)
|
|
98
102
|
.into_iter()
|
|
99
103
|
.collect::<Vec<_>>())
|
data/ext/typst/src/world.rs
CHANGED
|
@@ -1,44 +1,34 @@
|
|
|
1
1
|
use std::fs;
|
|
2
2
|
use std::path::{Path, PathBuf};
|
|
3
|
-
use std::sync::{Mutex, OnceLock};
|
|
3
|
+
use std::sync::{Arc, Mutex, OnceLock};
|
|
4
|
+
use std::collections::HashMap;
|
|
4
5
|
|
|
5
|
-
use chrono::{DateTime, Datelike, Local};
|
|
6
|
-
use ecow::eco_format;
|
|
6
|
+
use chrono::{DateTime, Datelike, FixedOffset, Local};
|
|
7
7
|
use typst::diag::{FileError, FileResult, StrResult};
|
|
8
|
-
use typst::foundations::{Bytes, Datetime, Dict};
|
|
9
|
-
use typst::syntax::{FileId, Lines, Source, VirtualPath};
|
|
8
|
+
use typst::foundations::{Bytes, Datetime, Dict, Duration};
|
|
9
|
+
use typst::syntax::{FileId, Lines, Source, VirtualPath, VirtualRoot, RootedPath};
|
|
10
10
|
use typst::text::{Font, FontBook};
|
|
11
11
|
use typst::utils::LazyHash;
|
|
12
12
|
use typst::{Features, Library, LibraryExt, World};
|
|
13
|
-
use typst_kit::{
|
|
14
|
-
|
|
15
|
-
package::PackageStorage,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
use std::collections::HashMap;
|
|
19
|
-
|
|
20
|
-
use crate::download::SlientDownload;
|
|
13
|
+
use typst_kit::fonts::{self, FontStore};
|
|
14
|
+
use typst_kit::packages::{FsPackages, SystemPackages, UniversePackages};
|
|
21
15
|
|
|
22
16
|
/// A world that provides access to the operating system.
|
|
23
17
|
pub struct SystemWorld {
|
|
24
18
|
/// The working directory.
|
|
25
19
|
workdir: Option<PathBuf>,
|
|
26
|
-
/// The canonical path to the input file.
|
|
27
|
-
input: PathBuf,
|
|
28
20
|
/// The root relative to which absolute paths are resolved.
|
|
29
21
|
root: PathBuf,
|
|
30
22
|
/// The input path.
|
|
31
23
|
main: FileId,
|
|
32
24
|
/// Typst's standard library.
|
|
33
25
|
library: LazyHash<Library>,
|
|
34
|
-
/// Metadata about discovered fonts.
|
|
35
|
-
book: LazyHash<FontBook>,
|
|
36
26
|
/// Locations of and storage for lazily loaded fonts.
|
|
37
|
-
fonts:
|
|
27
|
+
fonts: Arc<FontStore>,
|
|
38
28
|
/// Maps file ids to source files and buffers.
|
|
39
29
|
slots: Mutex<HashMap<FileId, FileSlot>>,
|
|
40
30
|
/// Holds information about where packages are stored.
|
|
41
|
-
package_storage:
|
|
31
|
+
package_storage: SystemPackages,
|
|
42
32
|
/// The current datetime if requested. This is stored here to ensure it is
|
|
43
33
|
/// always the same within one compilation. Reset between compilations.
|
|
44
34
|
now: OnceLock<DateTime<Local>>,
|
|
@@ -50,7 +40,7 @@ impl World for SystemWorld {
|
|
|
50
40
|
}
|
|
51
41
|
|
|
52
42
|
fn book(&self) -> &LazyHash<FontBook> {
|
|
53
|
-
&self.book
|
|
43
|
+
&self.fonts.book()
|
|
54
44
|
}
|
|
55
45
|
|
|
56
46
|
fn main(&self) -> FileId {
|
|
@@ -66,21 +56,30 @@ impl World for SystemWorld {
|
|
|
66
56
|
}
|
|
67
57
|
|
|
68
58
|
fn font(&self, index: usize) -> Option<Font> {
|
|
69
|
-
self.fonts
|
|
59
|
+
self.fonts.font(index)
|
|
70
60
|
}
|
|
71
61
|
|
|
72
|
-
fn today(&self, offset: Option<
|
|
62
|
+
fn today(&self, offset: Option<Duration>) -> Option<Datetime> {
|
|
73
63
|
let now = self.now.get_or_init(chrono::Local::now);
|
|
74
64
|
|
|
75
|
-
let
|
|
76
|
-
None => now.
|
|
77
|
-
Some(
|
|
65
|
+
let now = match offset {
|
|
66
|
+
None => now.fixed_offset(),
|
|
67
|
+
Some(offset) => {
|
|
68
|
+
let seconds = offset.seconds().trunc();
|
|
69
|
+
if !seconds.is_finite()
|
|
70
|
+
|| seconds < f64::from(i32::MIN)
|
|
71
|
+
|| seconds > f64::from(i32::MAX)
|
|
72
|
+
{
|
|
73
|
+
return None;
|
|
74
|
+
}
|
|
75
|
+
now.with_timezone(&FixedOffset::east_opt(seconds as i32)?)
|
|
76
|
+
}
|
|
78
77
|
};
|
|
79
78
|
|
|
80
79
|
Datetime::from_ymd(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
now.year(),
|
|
81
|
+
now.month().try_into().ok()?,
|
|
82
|
+
now.day().try_into().ok()?,
|
|
84
83
|
)
|
|
85
84
|
}
|
|
86
85
|
}
|
|
@@ -122,23 +121,20 @@ impl SystemWorld {
|
|
|
122
121
|
self.now.take();
|
|
123
122
|
}
|
|
124
123
|
|
|
125
|
-
/// Return the canonical path to the input file.
|
|
126
|
-
pub fn input(&self) -> &PathBuf {
|
|
127
|
-
&self.input
|
|
128
|
-
}
|
|
129
|
-
|
|
130
124
|
/// Lookup a source file by id.
|
|
131
125
|
#[track_caller]
|
|
132
126
|
pub fn lookup(&self, id: FileId) -> Lines<String> {
|
|
133
|
-
// self.source(id)
|
|
134
|
-
// .expect("file id does not point to any source file")
|
|
135
127
|
self.slot(id, |slot| {
|
|
136
128
|
if let Some(source) = slot.source.get() {
|
|
137
129
|
let source = source.as_ref().expect("file is not valid");
|
|
138
130
|
source.lines().clone()
|
|
139
131
|
} else if let Some(bytes) = slot.file.get() {
|
|
140
132
|
let bytes = bytes.as_ref().expect("file is not valid");
|
|
141
|
-
Lines::
|
|
133
|
+
Lines::new(
|
|
134
|
+
decode_utf8(bytes.as_slice())
|
|
135
|
+
.expect("file is not valid utf-8")
|
|
136
|
+
.to_string(),
|
|
137
|
+
)
|
|
142
138
|
} else {
|
|
143
139
|
panic!("file id does not point to any source file");
|
|
144
140
|
}
|
|
@@ -151,8 +147,11 @@ pub struct SystemWorldBuilder {
|
|
|
151
147
|
main: PathBuf,
|
|
152
148
|
font_paths: Vec<PathBuf>,
|
|
153
149
|
ignore_system_fonts: bool,
|
|
150
|
+
ignore_embedded_fonts: bool,
|
|
154
151
|
inputs: Dict,
|
|
155
152
|
features: Features,
|
|
153
|
+
package_path: Option<PathBuf>,
|
|
154
|
+
package_cache_path: Option<PathBuf>,
|
|
156
155
|
}
|
|
157
156
|
|
|
158
157
|
impl SystemWorldBuilder {
|
|
@@ -162,8 +161,11 @@ impl SystemWorldBuilder {
|
|
|
162
161
|
main,
|
|
163
162
|
font_paths: Vec::new(),
|
|
164
163
|
ignore_system_fonts: false,
|
|
164
|
+
ignore_embedded_fonts: false,
|
|
165
165
|
inputs: Dict::default(),
|
|
166
166
|
features: Features::default(),
|
|
167
|
+
package_path: None,
|
|
168
|
+
package_cache_path: None,
|
|
167
169
|
}
|
|
168
170
|
}
|
|
169
171
|
|
|
@@ -177,6 +179,11 @@ impl SystemWorldBuilder {
|
|
|
177
179
|
self
|
|
178
180
|
}
|
|
179
181
|
|
|
182
|
+
pub fn ignore_embedded_fonts(mut self, ignore: bool) -> Self {
|
|
183
|
+
self.ignore_embedded_fonts = ignore;
|
|
184
|
+
self
|
|
185
|
+
}
|
|
186
|
+
|
|
180
187
|
pub fn inputs(mut self, inputs: Dict) -> Self {
|
|
181
188
|
self.inputs = inputs;
|
|
182
189
|
self
|
|
@@ -188,33 +195,57 @@ impl SystemWorldBuilder {
|
|
|
188
195
|
}
|
|
189
196
|
|
|
190
197
|
pub fn build(self) -> StrResult<SystemWorld> {
|
|
191
|
-
let fonts =
|
|
192
|
-
|
|
193
|
-
|
|
198
|
+
let fonts = Arc::new(build_font_store(self.ignore_system_fonts, self.ignore_embedded_fonts, self.font_paths));
|
|
199
|
+
|
|
200
|
+
let package_storage = system_packages(self.package_path, self.package_cache_path);
|
|
194
201
|
|
|
195
|
-
let input = self.main.canonicalize().map_err(|_| {
|
|
196
|
-
eco_format!("input file not found (searched at {})", self.main.display())
|
|
197
|
-
})?;
|
|
198
202
|
// Resolve the virtual path of the main file within the project root.
|
|
199
|
-
let main_path = VirtualPath::
|
|
200
|
-
.
|
|
203
|
+
let main_path = VirtualPath::virtualize(&self.root, &self.main)
|
|
204
|
+
.map_err(|_| "input file must be contained in project root")?;
|
|
201
205
|
|
|
202
206
|
let world = SystemWorld {
|
|
203
207
|
workdir: std::env::current_dir().ok(),
|
|
204
|
-
input,
|
|
205
208
|
root: self.root,
|
|
206
|
-
main:
|
|
209
|
+
main: RootedPath::new(VirtualRoot::Project, main_path).intern(),
|
|
207
210
|
library: LazyHash::new(Library::builder().with_inputs(self.inputs).with_features(self.features).build()),
|
|
208
|
-
|
|
209
|
-
fonts: fonts.fonts,
|
|
211
|
+
fonts,
|
|
210
212
|
slots: Mutex::default(),
|
|
211
|
-
package_storage
|
|
213
|
+
package_storage,
|
|
212
214
|
now: OnceLock::new(),
|
|
213
215
|
};
|
|
214
216
|
Ok(world)
|
|
215
217
|
}
|
|
216
218
|
}
|
|
217
219
|
|
|
220
|
+
fn build_font_store(ignore_system_fonts: bool, ignore_embedded_fonts: bool, font_paths: Vec<PathBuf>) -> FontStore {
|
|
221
|
+
let mut fonts = FontStore::new();
|
|
222
|
+
if !ignore_system_fonts {
|
|
223
|
+
fonts.extend(fonts::system());
|
|
224
|
+
}
|
|
225
|
+
if !ignore_embedded_fonts {
|
|
226
|
+
fonts.extend(fonts::embedded());
|
|
227
|
+
}
|
|
228
|
+
for path in font_paths {
|
|
229
|
+
fonts.extend(fonts::scan(&path));
|
|
230
|
+
}
|
|
231
|
+
fonts
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
fn system_packages(
|
|
235
|
+
package_path: Option<PathBuf>,
|
|
236
|
+
package_cache_path: Option<PathBuf>,
|
|
237
|
+
) -> SystemPackages {
|
|
238
|
+
SystemPackages::from_parts(
|
|
239
|
+
package_path
|
|
240
|
+
.map(FsPackages::new)
|
|
241
|
+
.or_else(FsPackages::system_data),
|
|
242
|
+
package_cache_path
|
|
243
|
+
.map(FsPackages::new)
|
|
244
|
+
.or_else(FsPackages::system_cache),
|
|
245
|
+
UniversePackages::new(crate::download::downloader()),
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
|
|
218
249
|
/// Holds canonical data for all paths pointing to the same entity.
|
|
219
250
|
///
|
|
220
251
|
/// Both fields can be populated if the file is both imported and read().
|
|
@@ -244,7 +275,7 @@ impl FileSlot {
|
|
|
244
275
|
self.file.reset();
|
|
245
276
|
}
|
|
246
277
|
|
|
247
|
-
fn source(&mut self, root: &Path, package_storage: &
|
|
278
|
+
fn source(&mut self, root: &Path, package_storage: &SystemPackages) -> FileResult<Source> {
|
|
248
279
|
let id = self.id;
|
|
249
280
|
self.source.get_or_init(
|
|
250
281
|
|| system_path(root, id, package_storage),
|
|
@@ -260,7 +291,7 @@ impl FileSlot {
|
|
|
260
291
|
)
|
|
261
292
|
}
|
|
262
293
|
|
|
263
|
-
fn file(&mut self, root: &Path, package_storage: &
|
|
294
|
+
fn file(&mut self, root: &Path, package_storage: &SystemPackages) -> FileResult<Bytes> {
|
|
264
295
|
let id = self.id;
|
|
265
296
|
self.file.get_or_init(
|
|
266
297
|
|| system_path(root, id, package_storage),
|
|
@@ -270,19 +301,21 @@ impl FileSlot {
|
|
|
270
301
|
}
|
|
271
302
|
|
|
272
303
|
/// The path of the slot on the system.
|
|
273
|
-
fn system_path(root: &Path, id: FileId, package_storage: &
|
|
304
|
+
fn system_path(root: &Path, id: FileId, package_storage: &SystemPackages) -> FileResult<PathBuf> {
|
|
274
305
|
// Determine the root path relative to which the file path
|
|
275
306
|
// will be resolved.
|
|
276
|
-
let
|
|
277
|
-
let
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
307
|
+
let package_root;
|
|
308
|
+
let root = match id.root() {
|
|
309
|
+
VirtualRoot::Project => root,
|
|
310
|
+
VirtualRoot::Package(spec) => {
|
|
311
|
+
package_root = package_storage.obtain(spec)?;
|
|
312
|
+
package_root.path()
|
|
313
|
+
}
|
|
314
|
+
};
|
|
282
315
|
|
|
283
316
|
// Join the path to the root. If it tries to escape, deny
|
|
284
317
|
// access. Note: It can still escape via symlinks.
|
|
285
|
-
id.vpath().
|
|
318
|
+
id.vpath().realize(root).map_err(Into::into)
|
|
286
319
|
}
|
|
287
320
|
|
|
288
321
|
/// Lazily processes data for a file.
|
data/lib/base.rb
CHANGED
|
@@ -34,14 +34,14 @@ module Typst
|
|
|
34
34
|
options[:dependencies] ||= {}
|
|
35
35
|
options[:fonts] ||= {}
|
|
36
36
|
options[:sys_inputs] ||= {}
|
|
37
|
-
options[:resource_path] ||= File.dirname(__FILE__)
|
|
38
37
|
options[:ignore_system_fonts] ||= false
|
|
38
|
+
options[:ignore_embedded_fonts] ||= false
|
|
39
39
|
|
|
40
40
|
self.options = options
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def typst_args
|
|
44
|
-
[options[:file], options[:root], options[:font_paths], options[:
|
|
44
|
+
[options[:file], options[:root], options[:font_paths], options[:ignore_system_fonts], options[:ignore_embedded_fonts], options[:sys_inputs].map{ |k,v| [k.to_s,v.to_s] }.to_h]
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
def typst_pdf_args
|
|
@@ -125,14 +125,14 @@ module Typst
|
|
|
125
125
|
query_options = { field: field, one: one, format: format }
|
|
126
126
|
|
|
127
127
|
if self.options.has_key?(:file)
|
|
128
|
-
Typst::Query.new(selector, self.options[:file], **query_options.merge(self.options.slice(:root, :font_paths, :
|
|
128
|
+
Typst::Query.new(selector, self.options[:file], **query_options.merge(self.options.slice(:root, :font_paths, :ignore_system_fonts, :ignore_embedded_fonts, :sys_inputs)))
|
|
129
129
|
elsif self.options.has_key?(:body)
|
|
130
130
|
Typst::build_world_from_s(self.options[:body], **self.options) do |opts|
|
|
131
|
-
Typst::Query.new(selector, opts[:file], **query_options.merge(opts.slice(:root, :font_paths, :
|
|
131
|
+
Typst::Query.new(selector, opts[:file], **query_options.merge(opts.slice(:root, :font_paths, :ignore_system_fonts, :ignore_embedded_fonts, :sys_inputs)))
|
|
132
132
|
end
|
|
133
133
|
elsif self.options.has_key?(:zip)
|
|
134
134
|
Typst::build_world_from_zip(self.options[:zip], **self.options) do |opts|
|
|
135
|
-
Typst::Query.new(selector, opts[:file], **query_options.merge(opts.slice(:root, :font_paths, :
|
|
135
|
+
Typst::Query.new(selector, opts[:file], **query_options.merge(opts.slice(:root, :font_paths, :ignore_system_fonts, :ignore_embedded_fonts, :sys_inputs)))
|
|
136
136
|
end
|
|
137
137
|
else
|
|
138
138
|
raise "No input given"
|
data/lib/query.rb
CHANGED
|
@@ -2,9 +2,9 @@ module Typst
|
|
|
2
2
|
class Query < Base
|
|
3
3
|
attr_accessor :format
|
|
4
4
|
|
|
5
|
-
def initialize(selector, input, field: nil, one: false, format: "json", root: ".", font_paths: [],
|
|
5
|
+
def initialize(selector, input, field: nil, one: false, format: "json", root: ".", font_paths: [], ignore_system_fonts: false, ignore_embedded_fonts: false, sys_inputs: {})
|
|
6
6
|
self.format = format
|
|
7
|
-
@result = Typst::_query(selector, field, one, format, input, root, font_paths,
|
|
7
|
+
@result = Typst::_query(selector, field, one, format, input, root, font_paths, ignore_system_fonts, ignore_embedded_fonts, sys_inputs)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def result(raw: false)
|
data/lib/typst.rb
CHANGED
|
@@ -8,7 +8,7 @@ module Typst
|
|
|
8
8
|
def self.register_format(**format)
|
|
9
9
|
@@formats.merge!(format)
|
|
10
10
|
end
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
def self.formats
|
|
13
13
|
@@formats
|
|
14
14
|
end
|
|
@@ -27,14 +27,14 @@ module Typst
|
|
|
27
27
|
|
|
28
28
|
dependencies.each do |dep_name, dep_source|
|
|
29
29
|
tmp_dep_file = Pathname.new(tmp_dir).join(dep_name)
|
|
30
|
-
File.
|
|
30
|
+
File.binwrite(tmp_dep_file, dep_source)
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
relative_font_path = Pathname.new(tmp_dir).join("fonts")
|
|
34
34
|
relative_font_path.mkpath
|
|
35
35
|
fonts.each do |font_name, font_bytes|
|
|
36
36
|
tmp_font_file = relative_font_path.join(font_name)
|
|
37
|
-
File.
|
|
37
|
+
File.binwrite(tmp_font_file, font_bytes)
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
options[:file] = tmp_main_file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: typst
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.15.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Flinn
|
|
@@ -18,7 +18,7 @@ dependencies:
|
|
|
18
18
|
version: '0.9'
|
|
19
19
|
- - ">="
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: 0.9.
|
|
21
|
+
version: 0.9.128
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -28,7 +28,7 @@ dependencies:
|
|
|
28
28
|
version: '0.9'
|
|
29
29
|
- - ">="
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
|
-
version: 0.9.
|
|
31
|
+
version: 0.9.128
|
|
32
32
|
- !ruby/object:Gem::Dependency
|
|
33
33
|
name: rubyzip
|
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -113,27 +113,12 @@ files:
|
|
|
113
113
|
- ext/typst/extconf.rb
|
|
114
114
|
- ext/typst/src/compiler.rs
|
|
115
115
|
- ext/typst/src/download.rs
|
|
116
|
-
- ext/typst/src/fonts.rs
|
|
117
116
|
- ext/typst/src/lib.rs
|
|
118
117
|
- ext/typst/src/package.rs
|
|
119
118
|
- ext/typst/src/query.rs
|
|
120
119
|
- ext/typst/src/world.rs
|
|
121
120
|
- lib/base.rb
|
|
122
121
|
- lib/document.rb
|
|
123
|
-
- lib/fonts/DejaVuSansMono-Bold.ttf
|
|
124
|
-
- lib/fonts/DejaVuSansMono-BoldOblique.ttf
|
|
125
|
-
- lib/fonts/DejaVuSansMono-Oblique.ttf
|
|
126
|
-
- lib/fonts/DejaVuSansMono.ttf
|
|
127
|
-
- lib/fonts/LinLibertine_R.ttf
|
|
128
|
-
- lib/fonts/LinLibertine_RB.ttf
|
|
129
|
-
- lib/fonts/LinLibertine_RBI.ttf
|
|
130
|
-
- lib/fonts/LinLibertine_RI.ttf
|
|
131
|
-
- lib/fonts/NewCM10-Bold.otf
|
|
132
|
-
- lib/fonts/NewCM10-BoldItalic.otf
|
|
133
|
-
- lib/fonts/NewCM10-Italic.otf
|
|
134
|
-
- lib/fonts/NewCM10-Regular.otf
|
|
135
|
-
- lib/fonts/NewCMMath-Book.otf
|
|
136
|
-
- lib/fonts/NewCMMath-Regular.otf
|
|
137
122
|
- lib/formats/html_experimental.rb
|
|
138
123
|
- lib/formats/pdf.rb
|
|
139
124
|
- lib/formats/png.rb
|
|
@@ -158,7 +143,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
158
143
|
- !ruby/object:Gem::Version
|
|
159
144
|
version: '0'
|
|
160
145
|
requirements: []
|
|
161
|
-
rubygems_version: 4.0.
|
|
146
|
+
rubygems_version: 4.0.15
|
|
162
147
|
specification_version: 4
|
|
163
148
|
summary: Ruby binding to typst, a new markup-based typesetting system that is powerful
|
|
164
149
|
and easy to learn.
|