typst 0.14.2.3 → 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/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
- 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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0a438a6f795f22c5957eeaefbde3b825e7bf8e8634d75bc402de95321bc0e28d
|
|
4
|
+
data.tar.gz: 192a0dafec2d0b226674eabda64cc71926cc491444f2c2f391a868936c68f044
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2df9d3457d9e2293132e1b528c646c74f00974cc27cb1d3d35801fc8989ee9d9c5fe1b83a615cc245a8ca3f04349f356d385d1dd653b6dba8d4d5ac77ab285ee
|
|
7
|
+
data.tar.gz: 447e18da8b0678394bcde2f5ef6fe25235e8d4d3c9e484375944a0f1054786739dec77bcce2291a252360dc284d40062dcac4dcd2de94e73fa4f190741887401
|
data/ext/typst/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "typst"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.15.0"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
|
|
6
6
|
[lib]
|
|
@@ -12,7 +12,7 @@ chrono = { version = "0.4.42", default-features = false, features = [
|
|
|
12
12
|
"std",
|
|
13
13
|
] }
|
|
14
14
|
codespan-reporting = "0.13"
|
|
15
|
-
comemo = "0.5.
|
|
15
|
+
comemo = "0.5.1"
|
|
16
16
|
dirs = "5" #
|
|
17
17
|
ecow = "0.2"
|
|
18
18
|
env_logger = "0.10.1" #
|
|
@@ -29,18 +29,21 @@ tar = "0.4" #
|
|
|
29
29
|
serde = { version = "1.0.228", features = ["derive"] }
|
|
30
30
|
serde_json = "1"
|
|
31
31
|
serde_yaml = "0.9"
|
|
32
|
-
typst = "0.
|
|
33
|
-
typst-library = "0.
|
|
34
|
-
typst-kit = { version = "0.
|
|
35
|
-
"
|
|
36
|
-
"
|
|
32
|
+
typst = "0.15.0"
|
|
33
|
+
typst-library = "0.15.0"
|
|
34
|
+
typst-kit = { version = "0.15.0", features = [
|
|
35
|
+
"embedded-fonts",
|
|
36
|
+
"scan-fonts",
|
|
37
|
+
"system-downloader",
|
|
38
|
+
"system-packages",
|
|
37
39
|
"vendor-openssl",
|
|
38
40
|
] }
|
|
39
|
-
typst-pdf = "0.
|
|
40
|
-
typst-svg = "0.
|
|
41
|
-
typst-html = "0.
|
|
42
|
-
typst-render = "0.
|
|
43
|
-
typst-eval = "0.
|
|
41
|
+
typst-pdf = "0.15.0"
|
|
42
|
+
typst-svg = "0.15.0"
|
|
43
|
+
typst-html = "0.15.0"
|
|
44
|
+
typst-render = "0.15.0"
|
|
45
|
+
typst-eval = "0.15.0"
|
|
46
|
+
typst-layout = "0.15.0"
|
|
44
47
|
ureq = { version = "2", default-features = false, features = [
|
|
45
48
|
"gzip",
|
|
46
49
|
"socks-proxy",
|
|
@@ -49,4 +52,4 @@ walkdir = "2.4.0"
|
|
|
49
52
|
|
|
50
53
|
# enable rb-sys feature to test against Ruby head. This is only needed if you
|
|
51
54
|
# want to work with the unreleased, in-development, next version of Ruby
|
|
52
|
-
rb-sys = { version = "0.9.
|
|
55
|
+
rb-sys = { version = "0.9.128", default-features = false, features = ["stable-api-compiled-fallback"] }
|
data/ext/typst/src/compiler.rs
CHANGED
|
@@ -2,11 +2,11 @@ use chrono::{Datelike, Timelike};
|
|
|
2
2
|
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
|
3
3
|
use codespan_reporting::term::{self, termcolor};
|
|
4
4
|
use ecow::{eco_format, EcoString};
|
|
5
|
-
use typst::diag::{Severity, SourceDiagnostic, StrResult, Warned};
|
|
5
|
+
use typst::diag::{At, Severity, SourceDiagnostic, StrResult, Warned};
|
|
6
6
|
use typst::foundations::Datetime;
|
|
7
7
|
use typst_html::HtmlDocument;
|
|
8
|
-
use
|
|
9
|
-
use typst::syntax::{FileId, Lines, Span};
|
|
8
|
+
use typst_layout::PagedDocument;
|
|
9
|
+
use typst::syntax::{DiagSpan, FileId, Lines, Span};
|
|
10
10
|
use typst::{World, WorldExt};
|
|
11
11
|
|
|
12
12
|
use crate::world::SystemWorld;
|
|
@@ -45,7 +45,9 @@ impl SystemWorld {
|
|
|
45
45
|
"pdf" => Ok(vec![export_pdf(
|
|
46
46
|
&document,
|
|
47
47
|
self,
|
|
48
|
-
typst_pdf::PdfStandards::new(pdf_standards)
|
|
48
|
+
typst_pdf::PdfStandards::new(pdf_standards)
|
|
49
|
+
.map_err(|e| eco_format!("PDF standards error: {:?}", e))
|
|
50
|
+
.at(Span::detached()).unwrap()
|
|
49
51
|
)?]),
|
|
50
52
|
"png" => Ok(export_image(&document, ImageExportFormat::Png, ppi)?),
|
|
51
53
|
"svg" => Ok(export_image(&document, ImageExportFormat::Svg, ppi)?),
|
|
@@ -65,7 +67,7 @@ fn export_html(
|
|
|
65
67
|
document: &HtmlDocument,
|
|
66
68
|
world: &SystemWorld,
|
|
67
69
|
) -> StrResult<Vec<u8>> {
|
|
68
|
-
let html = typst_html::html(document)
|
|
70
|
+
let html = typst_html::html(document, &typst_html::HtmlOptions::default())
|
|
69
71
|
.map_err(|e| match format_diagnostics(world, &e, &[]) {
|
|
70
72
|
Ok(e) => EcoString::from(e),
|
|
71
73
|
Err(err) => eco_format!("failed to print diagnostics ({err})"),
|
|
@@ -81,11 +83,10 @@ fn export_pdf(
|
|
|
81
83
|
world: &SystemWorld,
|
|
82
84
|
standards: typst_pdf::PdfStandards,
|
|
83
85
|
) -> StrResult<Vec<u8>> {
|
|
84
|
-
let ident = world.input().to_string_lossy();
|
|
85
86
|
let buffer = typst_pdf::pdf(
|
|
86
87
|
document,
|
|
87
88
|
&typst_pdf::PdfOptions {
|
|
88
|
-
ident: typst::foundations::Smart::
|
|
89
|
+
ident: typst::foundations::Smart::Auto,
|
|
89
90
|
timestamp: now().map(typst_pdf::Timestamp::new_utc),
|
|
90
91
|
standards,
|
|
91
92
|
..Default::default()
|
|
@@ -95,7 +96,7 @@ fn export_pdf(
|
|
|
95
96
|
Ok(e) => EcoString::from(e),
|
|
96
97
|
Err(err) => eco_format!("failed to print diagnostics ({err})"),
|
|
97
98
|
})?;
|
|
98
|
-
Ok(buffer)
|
|
99
|
+
Ok(buffer.into())
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
/// Get the current date and time in UTC.
|
|
@@ -124,13 +125,19 @@ fn export_image(
|
|
|
124
125
|
ppi: Option<f32>,
|
|
125
126
|
) -> StrResult<Vec<Vec<u8>>> {
|
|
126
127
|
let mut buffers = Vec::new();
|
|
127
|
-
for page in
|
|
128
|
+
for page in document.pages() {
|
|
128
129
|
let buffer = match fmt {
|
|
129
|
-
ImageExportFormat::Png => typst_render::render(
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
ImageExportFormat::Png => typst_render::render(
|
|
131
|
+
page,
|
|
132
|
+
&typst_render::RenderOptions {
|
|
133
|
+
pixel_per_pt: typst::utils::Scalar::new(f64::from(ppi.unwrap_or(144.0) / 72.0)),
|
|
134
|
+
render_bleed: false,
|
|
135
|
+
},
|
|
136
|
+
)
|
|
137
|
+
.encode_png()
|
|
138
|
+
.map_err(|err| eco_format!("failed to write PNG file ({err})"))?,
|
|
132
139
|
ImageExportFormat::Svg => {
|
|
133
|
-
let svg = typst_svg::svg(page);
|
|
140
|
+
let svg = typst_svg::svg(page, &typst_svg::SvgOptions::default());
|
|
134
141
|
svg.as_bytes().to_vec()
|
|
135
142
|
}
|
|
136
143
|
};
|
|
@@ -162,7 +169,7 @@ pub fn format_diagnostics(
|
|
|
162
169
|
diagnostic
|
|
163
170
|
.hints
|
|
164
171
|
.iter()
|
|
165
|
-
.map(|e| (eco_format!("hint: {
|
|
172
|
+
.map(|e| (eco_format!("hint: {}", e.v)).into())
|
|
166
173
|
.collect(),
|
|
167
174
|
)
|
|
168
175
|
.with_labels(label(world, diagnostic.span).into_iter().collect());
|
|
@@ -185,7 +192,8 @@ pub fn format_diagnostics(
|
|
|
185
192
|
}
|
|
186
193
|
|
|
187
194
|
/// Create a label for a span.
|
|
188
|
-
fn label(world: &SystemWorld, span:
|
|
195
|
+
fn label(world: &SystemWorld, span: impl Into<DiagSpan>) -> Option<Label<FileId>> {
|
|
196
|
+
let span = span.into();
|
|
189
197
|
Some(Label::primary(span.id()?, world.range(span)?))
|
|
190
198
|
}
|
|
191
199
|
|
|
@@ -196,15 +204,16 @@ impl<'a> codespan_reporting::files::Files<'a> for SystemWorld {
|
|
|
196
204
|
|
|
197
205
|
fn name(&'a self, id: FileId) -> CodespanResult<Self::Name> {
|
|
198
206
|
let vpath = id.vpath();
|
|
199
|
-
Ok(if let
|
|
200
|
-
format!("{package}{}", vpath.
|
|
207
|
+
Ok(if let typst::syntax::VirtualRoot::Package(package) = id.root() {
|
|
208
|
+
format!("{package}{}", vpath.get_with_slash())
|
|
201
209
|
} else {
|
|
202
210
|
// Try to express the path relative to the working directory.
|
|
203
211
|
vpath
|
|
204
|
-
.
|
|
212
|
+
.realize(self.root())
|
|
213
|
+
.ok()
|
|
205
214
|
.and_then(|abs| pathdiff::diff_paths(abs, self.workdir()))
|
|
206
215
|
.as_deref()
|
|
207
|
-
.unwrap_or_else(|| vpath.
|
|
216
|
+
.unwrap_or_else(|| std::path::Path::new(vpath.get_without_slash()))
|
|
208
217
|
.to_string_lossy()
|
|
209
218
|
.into()
|
|
210
219
|
})
|
data/ext/typst/src/download.rs
CHANGED
|
@@ -1,19 +1,7 @@
|
|
|
1
|
-
use
|
|
2
|
-
|
|
3
|
-
use typst_kit::download::{DownloadState, Downloader, Progress};
|
|
4
|
-
|
|
5
|
-
pub struct SlientDownload<T>(pub T);
|
|
6
|
-
|
|
7
|
-
impl<T: Display> Progress for SlientDownload<T> {
|
|
8
|
-
fn print_start(&mut self) {}
|
|
9
|
-
|
|
10
|
-
fn print_progress(&mut self, _state: &DownloadState) {}
|
|
11
|
-
|
|
12
|
-
fn print_finish(&mut self, _state: &DownloadState) {}
|
|
13
|
-
}
|
|
1
|
+
use typst_kit::downloader::{Downloader, SystemDownloader};
|
|
14
2
|
|
|
15
3
|
/// Returns a new downloader.
|
|
16
|
-
pub fn downloader() -> Downloader {
|
|
4
|
+
pub fn downloader() -> impl Downloader {
|
|
17
5
|
let user_agent = concat!("typst-rb/", env!("CARGO_PKG_VERSION"));
|
|
18
|
-
|
|
6
|
+
SystemDownloader::new(user_agent)
|
|
19
7
|
}
|
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)
|
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.
|
data/ext/typst/src/fonts.rs
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
use std::cell::OnceCell;
|
|
2
|
-
use std::fs::{self};
|
|
3
|
-
use std::path::PathBuf;
|
|
4
|
-
|
|
5
|
-
use fontdb::{Database, Source};
|
|
6
|
-
use typst::font::{Font, FontBook, FontInfo};
|
|
7
|
-
|
|
8
|
-
/// Searches for fonts.
|
|
9
|
-
pub struct FontSearcher {
|
|
10
|
-
// Metadata about all discovered fonts.
|
|
11
|
-
pub book: FontBook,
|
|
12
|
-
/// Slots that the fonts are loaded into.
|
|
13
|
-
pub fonts: Vec<FontSlot>,
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/// Holds details about the location of a font and lazily the font itself.
|
|
17
|
-
pub struct FontSlot {
|
|
18
|
-
/// The path at which the font can be found on the system.
|
|
19
|
-
path: PathBuf,
|
|
20
|
-
/// The index of the font in its collection. Zero if the path does not point
|
|
21
|
-
/// to a collection.
|
|
22
|
-
index: u32,
|
|
23
|
-
/// The lazily loaded font.
|
|
24
|
-
font: OnceCell<Option<Font>>,
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
impl FontSlot {
|
|
28
|
-
/// Get the font for this slot.
|
|
29
|
-
pub fn get(&self) -> Option<Font> {
|
|
30
|
-
self.font
|
|
31
|
-
.get_or_init(|| {
|
|
32
|
-
let data = fs::read(&self.path).ok()?.into();
|
|
33
|
-
Font::new(data, self.index)
|
|
34
|
-
})
|
|
35
|
-
.clone()
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
impl FontSearcher {
|
|
40
|
-
/// Create a new, empty system searcher.
|
|
41
|
-
pub fn new() -> Self {
|
|
42
|
-
Self {
|
|
43
|
-
book: FontBook::new(),
|
|
44
|
-
fonts: vec![],
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/// Search everything that is available.
|
|
49
|
-
pub fn search(&mut self, font_dirs: &[PathBuf], font_files: &[PathBuf]) {
|
|
50
|
-
let mut db = Database::new();
|
|
51
|
-
|
|
52
|
-
// Font paths have highest priority.
|
|
53
|
-
for path in font_dirs {
|
|
54
|
-
db.load_fonts_dir(path);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// System fonts have second priority.
|
|
58
|
-
db.load_system_fonts();
|
|
59
|
-
|
|
60
|
-
for path in font_files {
|
|
61
|
-
let _ret = db.load_font_file(path).ok();
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
for face in db.faces() {
|
|
65
|
-
let path = match &face.source {
|
|
66
|
-
Source::File(path) | Source::SharedFile(path, _) => path,
|
|
67
|
-
// We never add binary sources to the database, so there
|
|
68
|
-
// shouln't be any.
|
|
69
|
-
Source::Binary(_) => continue,
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
let info = db
|
|
73
|
-
.with_face_data(face.id, FontInfo::new)
|
|
74
|
-
.expect("database must contain this font");
|
|
75
|
-
|
|
76
|
-
if let Some(info) = info {
|
|
77
|
-
self.book.push(info);
|
|
78
|
-
self.fonts.push(FontSlot {
|
|
79
|
-
path: path.clone(),
|
|
80
|
-
index: face.index,
|
|
81
|
-
font: OnceCell::new(),
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/lib/fonts/NewCM10-Bold.otf
DELETED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|