typst 0.14.2.1 → 0.14.2.2
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 +34 -24
- data/README.typ +35 -25
- data/ext/typst/src/compiler.rs +0 -1
- data/ext/typst/src/download.rs +1 -1
- data/ext/typst/src/lib.rs +41 -4
- data/ext/typst/src/query.rs +1 -1
- data/ext/typst/src/world.rs +0 -1
- data/lib/base.rb +45 -72
- data/lib/document.rb +15 -7
- data/lib/formats/html_experimental.rb +3 -1
- data/lib/formats/pdf.rb +4 -2
- data/lib/formats/png.rb +4 -2
- data/lib/formats/svg.rb +3 -1
- data/lib/query.rb +6 -3
- data/lib/typst.rb +67 -4
- metadata +32 -6
- data/lib/formats/html.rb +0 -35
- data/lib/typst/typst.bundle +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0e902865d606a53619b4af115102284997f623a128bc06405f5300c4c2b4c687
|
|
4
|
+
data.tar.gz: a33d506d802a470779eb60c2d075a0c6cf9babf50756b8633d87e297d05cc1fd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: baa7a4a6b87a9ba92b821f061e53dd4a45f014a45d672c68dd9cc6c08c4b1fd90a60c548c5d87a4fa41f1d5c024c5f916691fb122aafa5705259dbdfcc8ee7c2
|
|
7
|
+
data.tar.gz: c208d4cf87db4672ba0e9bfc40f63b1b8152dadb5e42c42f270d57172318a7194189c5c208f2a91b44c3933ec6f15bc84ebf465edcedb7cf8b35f4e33158bec4
|
data/README.md
CHANGED
|
@@ -27,43 +27,40 @@ t = Typst(body: %{hello world})
|
|
|
27
27
|
t = Typst(zip: "test/main.typ.zip")
|
|
28
28
|
|
|
29
29
|
# Compile to PDF
|
|
30
|
-
|
|
30
|
+
doc = t.compile(:pdf)
|
|
31
|
+
|
|
32
|
+
# Compile to PDF selecting the typst supported PdfStandard
|
|
33
|
+
doc = t.compile(:pdf, pdf_standards: ["2.0"])
|
|
31
34
|
|
|
32
35
|
# Compile to SVG
|
|
33
|
-
|
|
36
|
+
doc = t.compile(:svg)
|
|
34
37
|
|
|
35
38
|
# Compile to PNG
|
|
36
|
-
|
|
39
|
+
doc = t.compile(:png)
|
|
37
40
|
|
|
38
|
-
# Compile to
|
|
39
|
-
|
|
40
|
-
f = t.compile(:html, title: "Typst+Ruby")
|
|
41
|
+
# Compile to PNG and set PPI
|
|
42
|
+
doc = t.compile(:png, ppi: 72)
|
|
41
43
|
|
|
42
44
|
# Compile to HTML (using Typst expirmental HTML)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
# Access PDF or HTML output as a string
|
|
46
|
-
# Note: For PDF and PNG this will give data, for SVG and HTML this will give markup
|
|
47
|
-
Typst("readme.typ").compile(:pdf).document
|
|
48
|
-
# => "%PDF-1.7\n%\x80\x80\x80\x80\n\n4 0 obj\n<<\n /Type /Font\n /Subtype ..."
|
|
49
|
-
Typst("readme.typ").compile(:html).document
|
|
50
|
-
# => "\n<!DOCTYPE html>\n<html>\n<head>\n<title>main</title>\n</head>\n<body>\n<svg class=\"typst-doc\" ...
|
|
45
|
+
doc = t.compile(:html_experimental)
|
|
51
46
|
|
|
52
47
|
# Or return content as an array of bytes
|
|
53
48
|
pdf_bytes = Typst("readme.typ").compile(:pdf).bytes
|
|
54
49
|
# => [37, 80, 68, 70, 45, 49, 46, 55, 10, 37, 128 ...]
|
|
55
50
|
|
|
56
51
|
# Write the output to a file
|
|
57
|
-
# Note: for multi-page documents using formats other than PDF, pages write to multiple files, e.g. `readme_0.png`, `readme_1.png`
|
|
58
|
-
|
|
52
|
+
# Note: for multi-page documents using formats other than PDF and HTML, pages write to multiple files, e.g. `readme_0.png`, `readme_1.png`
|
|
53
|
+
doc.write("filename.pdf")
|
|
59
54
|
|
|
60
|
-
# Return SVG,
|
|
55
|
+
# Return PDF, SVG, PNG or HTML content as an array of pages
|
|
56
|
+
Typst("readme.typ").compile(:pdf).pages
|
|
57
|
+
# => ["%PDF-1.7\n%\x80\x80\x80\x80\n\n1 0 obj\n<<\n /Type /Pages\n /Count 3\n /Kids [160 0 R 162 ...
|
|
61
58
|
Typst("readme.typ").compile(:svg).pages
|
|
62
|
-
# => ["<svg class=\"typst-doc\" viewBox=\"0 0 595.2764999999999 841.89105\" ...
|
|
63
|
-
Typst("readme.typ").compile(:html).pages
|
|
64
|
-
# => ["<svg class=\"typst-doc\" viewBox=\"0 0 595.2764999999999 841.89105\" ..."
|
|
59
|
+
# => ["<svg class=\"typst-doc\" viewBox=\"0 0 595.2764999999999 841.89105\" ...
|
|
65
60
|
Typst("readme.typ").compile(:png).pages
|
|
66
61
|
# => ["\x89PNG\r\n\x1A\n\x00\x00\x00\rIHDR\x00\x00\x04\xA7\x00\x00\x06\x94\b\ ...
|
|
62
|
+
Typst("readme.typ").compile(:html_experimental).pages
|
|
63
|
+
# => ["<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" ...
|
|
67
64
|
|
|
68
65
|
# Pass values into typst using sys_inputs
|
|
69
66
|
sys_inputs_example = %{
|
|
@@ -110,23 +107,36 @@ Typst(body: main, dependencies: { "template.typ" => template, "icon.svg" => icon
|
|
|
110
107
|
# From a zip with a named main typst file
|
|
111
108
|
Typst(zip: "test/main.typ.zip", main_file: "hello.typ").compile(:pdf)
|
|
112
109
|
|
|
113
|
-
Typst
|
|
110
|
+
Typst("readme.typ").query("heading").result
|
|
114
111
|
# =>
|
|
115
112
|
# [{"func" => "heading",
|
|
116
113
|
# "level" => 1,
|
|
117
114
|
# "depth" => 1,
|
|
118
115
|
# ...
|
|
119
116
|
|
|
120
|
-
Typst
|
|
117
|
+
Typst("readme.typ").query("heading", format: "json").result(raw: true)
|
|
121
118
|
# => "[\n {\n \"func\": \"heading\",\n \"level\": 1,\n \"depth\": ..."
|
|
122
119
|
|
|
123
|
-
Typst
|
|
120
|
+
Typst("readme.typ").query("heading", format: "yaml").result(raw: true)
|
|
124
121
|
# => "- func: heading\n level: 1\n depth: 1\n offset: 0\n numbering: ..."
|
|
125
122
|
|
|
123
|
+
# Query results as JSON string
|
|
124
|
+
Typst("test/test.typ").query("heading").to_s
|
|
125
|
+
=> "[\n {\n \"func\": \"heading\",\n \"level\": 1,\n \"depth\": 1,\n \"offset\": 0,\n ...
|
|
126
|
+
|
|
127
|
+
# Query results as YAML string
|
|
128
|
+
Typst("test/test.typ").query("heading", format: "yaml").to_s
|
|
129
|
+
=> "- func: heading\n level: 1\n depth: 1\n offset: 0\n numbering: null\n supplement:\n ...
|
|
130
|
+
|
|
131
|
+
# clear the compilation cache
|
|
132
|
+
# Evict all entries whose age is larger than or equal to `max_age`
|
|
133
|
+
max_age = 10
|
|
134
|
+
Typst::clear_cache(max_age)
|
|
126
135
|
```
|
|
127
136
|
|
|
128
137
|
## Contributors & Acknowledgements
|
|
129
|
-
typst-rb is based on [typst-py](https://github.com/messense/typst-py) by [messense](https://github.com/messense)
|
|
138
|
+
typst-rb is based on [typst-py](https://github.com/messense/typst-py) by [messense](https://github.com/messense)\
|
|
139
|
+
clear_cache was contributed by [NRicciVestmark](https://github.com/NRicciVestmark)
|
|
130
140
|
|
|
131
141
|
## License
|
|
132
142
|
|
data/README.typ
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
#set document(title: [typst.rb README])
|
|
2
2
|
#show link: underline
|
|
3
3
|
#show link: set text(blue)
|
|
4
4
|
|
|
@@ -30,43 +30,40 @@ t = Typst(body: %{hello world})
|
|
|
30
30
|
t = Typst(zip: "test/main.typ.zip")
|
|
31
31
|
|
|
32
32
|
# Compile to PDF
|
|
33
|
-
|
|
33
|
+
doc = t.compile(:pdf)
|
|
34
|
+
|
|
35
|
+
# Compile to PDF selecting the typst supported PdfStandard
|
|
36
|
+
doc = t.compile(:pdf, pdf_standards: ["2.0"])
|
|
34
37
|
|
|
35
38
|
# Compile to SVG
|
|
36
|
-
|
|
39
|
+
doc = t.compile(:svg)
|
|
37
40
|
|
|
38
41
|
# Compile to PNG
|
|
39
|
-
|
|
42
|
+
doc = t.compile(:png)
|
|
40
43
|
|
|
41
|
-
# Compile to
|
|
42
|
-
|
|
43
|
-
f = t.compile(:html, title: "Typst+Ruby")
|
|
44
|
+
# Compile to PNG and set PPI
|
|
45
|
+
doc = t.compile(:png, ppi: 72)
|
|
44
46
|
|
|
45
47
|
# Compile to HTML (using Typst expirmental HTML)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
# Access PDF or HTML output as a string
|
|
49
|
-
# Note: For PDF and PNG this will give data, for SVG and HTML this will give markup
|
|
50
|
-
Typst("readme.typ").compile(:pdf).document
|
|
51
|
-
# => "%PDF-1.7\n%\x80\x80\x80\x80\n\n4 0 obj\n<<\n /Type /Font\n /Subtype ..."
|
|
52
|
-
Typst("readme.typ").compile(:html).document
|
|
53
|
-
# => "\n<!DOCTYPE html>\n<html>\n<head>\n<title>main</title>\n</head>\n<body>\n<svg class=\"typst-doc\" ...
|
|
48
|
+
doc = t.compile(:html_experimental)
|
|
54
49
|
|
|
55
50
|
# Or return content as an array of bytes
|
|
56
51
|
pdf_bytes = Typst("readme.typ").compile(:pdf).bytes
|
|
57
52
|
# => [37, 80, 68, 70, 45, 49, 46, 55, 10, 37, 128 ...]
|
|
58
53
|
|
|
59
54
|
# Write the output to a file
|
|
60
|
-
# Note: for multi-page documents using formats other than PDF, pages write to multiple files, e.g. `readme_0.png`, `readme_1.png`
|
|
61
|
-
|
|
55
|
+
# Note: for multi-page documents using formats other than PDF and HTML, pages write to multiple files, e.g. `readme_0.png`, `readme_1.png`
|
|
56
|
+
doc.write("filename.pdf")
|
|
62
57
|
|
|
63
|
-
# Return SVG,
|
|
58
|
+
# Return PDF, SVG, PNG or HTML content as an array of pages
|
|
59
|
+
Typst("readme.typ").compile(:pdf).pages
|
|
60
|
+
# => ["%PDF-1.7\n%\x80\x80\x80\x80\n\n1 0 obj\n<<\n /Type /Pages\n /Count 3\n /Kids [160 0 R 162 ...
|
|
64
61
|
Typst("readme.typ").compile(:svg).pages
|
|
65
|
-
# => ["<svg class=\"typst-doc\" viewBox=\"0 0 595.2764999999999 841.89105\" ...
|
|
66
|
-
Typst("readme.typ").compile(:html).pages
|
|
67
|
-
# => ["<svg class=\"typst-doc\" viewBox=\"0 0 595.2764999999999 841.89105\" ..."
|
|
62
|
+
# => ["<svg class=\"typst-doc\" viewBox=\"0 0 595.2764999999999 841.89105\" ...
|
|
68
63
|
Typst("readme.typ").compile(:png).pages
|
|
69
64
|
# => ["\x89PNG\r\n\x1A\n\x00\x00\x00\rIHDR\x00\x00\x04\xA7\x00\x00\x06\x94\b\ ...
|
|
65
|
+
Typst("readme.typ").compile(:html_experimental).pages
|
|
66
|
+
# => ["<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" ...
|
|
70
67
|
|
|
71
68
|
# Pass values into typst using sys_inputs
|
|
72
69
|
sys_inputs_example = %{
|
|
@@ -113,23 +110,36 @@ Typst(body: main, dependencies: { "template.typ" => template, "icon.svg" => icon
|
|
|
113
110
|
# From a zip with a named main typst file
|
|
114
111
|
Typst(zip: "test/main.typ.zip", main_file: "hello.typ").compile(:pdf)
|
|
115
112
|
|
|
116
|
-
Typst
|
|
113
|
+
Typst("readme.typ").query("heading").result
|
|
117
114
|
# =>
|
|
118
115
|
# [{"func" => "heading",
|
|
119
116
|
# "level" => 1,
|
|
120
117
|
# "depth" => 1,
|
|
121
118
|
# ...
|
|
122
119
|
|
|
123
|
-
Typst
|
|
120
|
+
Typst("readme.typ").query("heading", format: "json").result(raw: true)
|
|
124
121
|
# => "[\n {\n \"func\": \"heading\",\n \"level\": 1,\n \"depth\": ..."
|
|
125
122
|
|
|
126
|
-
Typst
|
|
123
|
+
Typst("readme.typ").query("heading", format: "yaml").result(raw: true)
|
|
127
124
|
# => "- func: heading\n level: 1\n depth: 1\n offset: 0\n numbering: ..."
|
|
128
125
|
|
|
126
|
+
# Query results as JSON string
|
|
127
|
+
Typst("test/test.typ").query("heading").to_s
|
|
128
|
+
=> "[\n {\n \"func\": \"heading\",\n \"level\": 1,\n \"depth\": 1,\n \"offset\": 0,\n ...
|
|
129
|
+
|
|
130
|
+
# Query results as YAML string
|
|
131
|
+
Typst("test/test.typ").query("heading", format: "yaml").to_s
|
|
132
|
+
=> "- func: heading\n level: 1\n depth: 1\n offset: 0\n numbering: null\n supplement:\n ...
|
|
133
|
+
|
|
134
|
+
# clear the compilation cache
|
|
135
|
+
# Evict all entries whose age is larger than or equal to `max_age`
|
|
136
|
+
max_age = 10
|
|
137
|
+
Typst::clear_cache(max_age)
|
|
129
138
|
```
|
|
130
139
|
|
|
131
140
|
== Contributors & Acknowledgements
|
|
132
|
-
typst-rb is based on #link("https://github.com/messense/typst-py")[typst-py] by #link("https://github.com/messense")[messense]
|
|
141
|
+
typst-rb is based on #link("https://github.com/messense/typst-py")[typst-py] by #link("https://github.com/messense")[messense]\
|
|
142
|
+
clear_cache was contributed by #link("https://github.com/NRicciVestmark")[NRicciVestmark]
|
|
133
143
|
|
|
134
144
|
== License
|
|
135
145
|
|
data/ext/typst/src/compiler.rs
CHANGED
|
@@ -6,7 +6,6 @@ use typst::diag::{Severity, SourceDiagnostic, StrResult, Warned};
|
|
|
6
6
|
use typst::foundations::Datetime;
|
|
7
7
|
use typst_html::HtmlDocument;
|
|
8
8
|
use typst::layout::PagedDocument;
|
|
9
|
-
//use typst::syntax::{FileId, Source, Span};
|
|
10
9
|
use typst::syntax::{FileId, Lines, Span};
|
|
11
10
|
use typst::{World, WorldExt};
|
|
12
11
|
|
data/ext/typst/src/download.rs
CHANGED
|
@@ -14,6 +14,6 @@ impl<T: Display> Progress for SlientDownload<T> {
|
|
|
14
14
|
|
|
15
15
|
/// Returns a new downloader.
|
|
16
16
|
pub fn downloader() -> Downloader {
|
|
17
|
-
let user_agent = concat!("typst-
|
|
17
|
+
let user_agent = concat!("typst-rb/", env!("CARGO_PKG_VERSION"));
|
|
18
18
|
Downloader::new(user_agent)
|
|
19
19
|
}
|
data/ext/typst/src/lib.rs
CHANGED
|
@@ -6,6 +6,7 @@ use std::collections::HashMap;
|
|
|
6
6
|
use query::{query as typst_query, QueryCommand, SerializationFormat};
|
|
7
7
|
use typst::foundations::{Dict, Value};
|
|
8
8
|
use typst_library::Feature;
|
|
9
|
+
use typst_pdf::PdfStandard;
|
|
9
10
|
use world::SystemWorld;
|
|
10
11
|
|
|
11
12
|
mod compiler;
|
|
@@ -144,6 +145,7 @@ fn to_png(
|
|
|
144
145
|
resource_path: PathBuf,
|
|
145
146
|
ignore_system_fonts: bool,
|
|
146
147
|
sys_inputs: HashMap<String, String>,
|
|
148
|
+
ppi: Option<f32>,
|
|
147
149
|
) -> Result<Vec<Vec<u8>>, Error> {
|
|
148
150
|
let input = input.canonicalize()
|
|
149
151
|
.map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?;
|
|
@@ -185,7 +187,7 @@ fn to_png(
|
|
|
185
187
|
.map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
|
|
186
188
|
|
|
187
189
|
let bytes = world
|
|
188
|
-
.compile(Some("png"),
|
|
190
|
+
.compile(Some("png"), ppi, &Vec::new())
|
|
189
191
|
.map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
|
|
190
192
|
|
|
191
193
|
Ok(bytes)
|
|
@@ -199,6 +201,7 @@ fn to_pdf(
|
|
|
199
201
|
resource_path: PathBuf,
|
|
200
202
|
ignore_system_fonts: bool,
|
|
201
203
|
sys_inputs: HashMap<String, String>,
|
|
204
|
+
pdf_standards: Vec<String>,
|
|
202
205
|
) -> Result<Vec<Vec<u8>>, Error> {
|
|
203
206
|
let input = input.canonicalize()
|
|
204
207
|
.map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?;
|
|
@@ -239,8 +242,37 @@ fn to_pdf(
|
|
|
239
242
|
.build()
|
|
240
243
|
.map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
|
|
241
244
|
|
|
245
|
+
let pdf_standards_lookup: HashMap::<&str, PdfStandard> = HashMap::from([
|
|
246
|
+
("1.4", PdfStandard::V_1_4),
|
|
247
|
+
("1.5", PdfStandard::V_1_5),
|
|
248
|
+
("1.6", PdfStandard::V_1_6),
|
|
249
|
+
("1.7", PdfStandard::V_1_7),
|
|
250
|
+
("2.0", PdfStandard::V_2_0),
|
|
251
|
+
("a-1a", PdfStandard::A_1a),
|
|
252
|
+
("a-1b", PdfStandard::A_1b),
|
|
253
|
+
("a-2a", PdfStandard::A_2a),
|
|
254
|
+
("a-2b", PdfStandard::A_2b),
|
|
255
|
+
("a-2u", PdfStandard::A_2u),
|
|
256
|
+
("a-3a", PdfStandard::A_3a),
|
|
257
|
+
("a-3b", PdfStandard::A_3b),
|
|
258
|
+
("a-3u", PdfStandard::A_3u),
|
|
259
|
+
("a-4", PdfStandard::A_4),
|
|
260
|
+
("a-4e", PdfStandard::A_4e),
|
|
261
|
+
("a-4f", PdfStandard::A_4f),
|
|
262
|
+
("ua-1", PdfStandard::Ua_1),
|
|
263
|
+
]);
|
|
264
|
+
|
|
265
|
+
let mut pdf_standards_vec = Vec::<PdfStandard>::new();
|
|
266
|
+
for pdf_standard in pdf_standards.iter() {
|
|
267
|
+
let result = pdf_standards_lookup.get(pdf_standard.as_str());
|
|
268
|
+
match result {
|
|
269
|
+
Some(value) => pdf_standards_vec.push(*value),
|
|
270
|
+
_ => return Err(magnus::Error::new(ruby.exception_arg_error(), "Unknown PdfStandard")),
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
242
274
|
let pdf_bytes = world
|
|
243
|
-
.compile(Some("pdf"), None, &
|
|
275
|
+
.compile(Some("pdf"), None, &pdf_standards_vec)
|
|
244
276
|
.map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
|
|
245
277
|
|
|
246
278
|
Ok(pdf_bytes)
|
|
@@ -320,15 +352,20 @@ fn query(
|
|
|
320
352
|
}
|
|
321
353
|
}
|
|
322
354
|
|
|
355
|
+
fn clear_cache(_ruby: &Ruby, max_age: usize) {
|
|
356
|
+
comemo::evict(max_age);
|
|
357
|
+
}
|
|
358
|
+
|
|
323
359
|
#[magnus::init]
|
|
324
360
|
fn init(ruby: &Ruby) -> Result<(), Error> {
|
|
325
361
|
env_logger::init();
|
|
326
362
|
|
|
327
363
|
let module = ruby.define_module("Typst")?;
|
|
328
|
-
module.define_singleton_method("_to_pdf", function!(to_pdf,
|
|
364
|
+
module.define_singleton_method("_to_pdf", function!(to_pdf, 7))?;
|
|
329
365
|
module.define_singleton_method("_to_svg", function!(to_svg, 6))?;
|
|
330
|
-
module.define_singleton_method("_to_png", function!(to_png,
|
|
366
|
+
module.define_singleton_method("_to_png", function!(to_png, 7))?;
|
|
331
367
|
module.define_singleton_method("_to_html", function!(to_html, 6))?;
|
|
332
368
|
module.define_singleton_method("_query", function!(query, 10))?;
|
|
369
|
+
module.define_singleton_method("_clear_cache", function!(clear_cache, 1))?;
|
|
333
370
|
Ok(())
|
|
334
371
|
}
|
data/ext/typst/src/query.rs
CHANGED
data/ext/typst/src/world.rs
CHANGED
|
@@ -3,7 +3,6 @@ use std::path::{Path, PathBuf};
|
|
|
3
3
|
use std::sync::{Mutex, OnceLock};
|
|
4
4
|
|
|
5
5
|
use chrono::{DateTime, Datelike, Local};
|
|
6
|
-
//use rustc_hash::FxHashMap;
|
|
7
6
|
use ecow::eco_format;
|
|
8
7
|
use typst::diag::{FileError, FileResult, StrResult};
|
|
9
8
|
use typst::foundations::{Bytes, Datetime, Dict};
|
data/lib/base.rb
CHANGED
|
@@ -34,74 +34,44 @@ module Typst
|
|
|
34
34
|
options[:dependencies] ||= {}
|
|
35
35
|
options[:fonts] ||= {}
|
|
36
36
|
options[:sys_inputs] ||= {}
|
|
37
|
+
options[:resource_path] ||= File.dirname(__FILE__)
|
|
38
|
+
options[:ignore_system_fonts] ||= false
|
|
37
39
|
|
|
38
40
|
self.options = options
|
|
39
41
|
end
|
|
40
42
|
|
|
41
43
|
def typst_args
|
|
42
|
-
[options[:file], options[:root], options[:font_paths],
|
|
44
|
+
[options[:file], options[:root], options[:font_paths], options[:resource_path], options[:ignore_system_fonts], options[:sys_inputs].map{ |k,v| [k.to_s,v.to_s] }.to_h]
|
|
43
45
|
end
|
|
44
46
|
|
|
45
|
-
def
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Dir.mktmpdir do |tmp_dir|
|
|
50
|
-
tmp_main_file = Pathname.new(tmp_dir).join("main.typ")
|
|
51
|
-
File.write(tmp_main_file, main_source)
|
|
52
|
-
|
|
53
|
-
dependencies.each do |dep_name, dep_source|
|
|
54
|
-
tmp_dep_file = Pathname.new(tmp_dir).join(dep_name)
|
|
55
|
-
File.write(tmp_dep_file, dep_source)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
relative_font_path = Pathname.new(tmp_dir).join("fonts")
|
|
59
|
-
fonts.each do |font_name, font_bytes|
|
|
60
|
-
Pathname.new(relative_font_path).mkpath
|
|
61
|
-
tmp_font_file = relative_font_path.join(font_name)
|
|
62
|
-
File.write(tmp_font_file, font_bytes)
|
|
63
|
-
end
|
|
47
|
+
def typst_pdf_args
|
|
48
|
+
options[:pdf_standards] ||= []
|
|
49
|
+
[*typst_args, options[:pdf_standards]]
|
|
50
|
+
end
|
|
64
51
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
52
|
+
def typst_png_args
|
|
53
|
+
[*typst_args, options[:ppi]]
|
|
54
|
+
end
|
|
68
55
|
|
|
69
|
-
|
|
70
|
-
|
|
56
|
+
def self.from_s(main_source, **options)
|
|
57
|
+
Typst::build_world_from_s(main_source, **options) do |opts|
|
|
58
|
+
from_options = options.merge(opts)
|
|
59
|
+
if from_options[:format]
|
|
60
|
+
Typst::formats[from_options[:format]].new(**from_options)
|
|
71
61
|
else
|
|
72
|
-
new(**
|
|
62
|
+
new(**from_options)
|
|
73
63
|
end
|
|
74
64
|
end
|
|
75
65
|
end
|
|
76
66
|
|
|
77
|
-
def self.from_zip(zip_file_path, main_file =
|
|
78
|
-
options
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
when file_names.include?(main_file) then tmp_main_file = main_file
|
|
85
|
-
when file_names.include?("main.typ") then tmp_main_file = "main.typ"
|
|
86
|
-
when file_names.size == 1 then tmp_main_file = file_names.first
|
|
87
|
-
else raise "no main file found"
|
|
88
|
-
end
|
|
89
|
-
main_source = zipfile.file.read(tmp_main_file)
|
|
90
|
-
file_names.delete(tmp_main_file)
|
|
91
|
-
file_names.delete("fonts/")
|
|
92
|
-
|
|
93
|
-
file_names.each do |dep_name|
|
|
94
|
-
options[:dependencies][dep_name] = zipfile.file.read(dep_name)
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
font_file_names = zipfile.dir.glob("fonts/*").collect{ |f| f.name }
|
|
98
|
-
font_file_names.each do |font_name|
|
|
99
|
-
options[:fonts][Pathname.new(font_name).basename.to_s] = zipfile.file.read(font_name)
|
|
67
|
+
def self.from_zip(zip_file_path, main_file = "main.typ", **options)
|
|
68
|
+
Typst::build_world_from_zip(zip_file_path, main_file, **options) do |opts|
|
|
69
|
+
from_options = options.merge(opts)
|
|
70
|
+
if from_options[:format]
|
|
71
|
+
Typst::formats[from_options[:format]].new(**from_options)
|
|
72
|
+
else
|
|
73
|
+
new(**from_options)
|
|
100
74
|
end
|
|
101
|
-
|
|
102
|
-
options[:main_file] = tmp_main_file
|
|
103
|
-
|
|
104
|
-
from_s(main_source, **options)
|
|
105
75
|
end
|
|
106
76
|
end
|
|
107
77
|
|
|
@@ -138,32 +108,35 @@ module Typst
|
|
|
138
108
|
if options.has_key?(:file)
|
|
139
109
|
Typst::formats[format].new(**options).compiled
|
|
140
110
|
elsif options.has_key?(:body)
|
|
141
|
-
Typst::
|
|
111
|
+
Typst::build_world_from_s(self.options[:body], **options) do |opts|
|
|
112
|
+
Typst::formats[format].new(**options.merge(opts)).compiled
|
|
113
|
+
end
|
|
142
114
|
elsif options.has_key?(:zip)
|
|
143
|
-
|
|
115
|
+
main_file = options[:main_file]
|
|
116
|
+
Typst::build_world_from_zip(options[:zip], main_file, **options) do |opts|
|
|
117
|
+
Typst::formats[format].new(**options.merge(opts)).compiled
|
|
118
|
+
end
|
|
144
119
|
else
|
|
145
120
|
raise "No input given"
|
|
146
121
|
end
|
|
147
122
|
end
|
|
148
123
|
|
|
149
|
-
def
|
|
150
|
-
|
|
151
|
-
compiled.write(output)
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
def document
|
|
155
|
-
STDERR.puts "DEPRECATION WARNING: this method will go away in a future version"
|
|
156
|
-
compiled.document
|
|
157
|
-
end
|
|
124
|
+
def query(selector, field: nil, one: false, format: "json")
|
|
125
|
+
query_options = { field: field, one: one, format: format }
|
|
158
126
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
127
|
+
if self.options.has_key?(:file)
|
|
128
|
+
Typst::Query.new(selector, self.options[:file], **query_options.merge(self.options.slice(:root, :font_paths, :resource_path, :ignore_system_fonts, :sys_inputs)))
|
|
129
|
+
elsif self.options.has_key?(:body)
|
|
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, :resource_path, :ignore_system_fonts, :sys_inputs)))
|
|
132
|
+
end
|
|
133
|
+
elsif self.options.has_key?(:zip)
|
|
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, :resource_path, :ignore_system_fonts, :sys_inputs)))
|
|
136
|
+
end
|
|
137
|
+
else
|
|
138
|
+
raise "No input given"
|
|
139
|
+
end
|
|
167
140
|
end
|
|
168
141
|
end
|
|
169
142
|
end
|
data/lib/document.rb
CHANGED
|
@@ -6,15 +6,23 @@ module Typst
|
|
|
6
6
|
@bytes = bytes
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
def
|
|
9
|
+
def write_some(filename)
|
|
10
10
|
if pages.size == 1
|
|
11
|
-
|
|
11
|
+
write_one(filename)
|
|
12
12
|
else
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
write_paged(filename)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def write_one(filename)
|
|
18
|
+
File.write(filename, pages.first, mode: "wb")
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def write_paged(base_filename)
|
|
22
|
+
pages.each_with_index do |page, i|
|
|
23
|
+
paged_filename = File.basename(base_filename, ".*") + "_{{n}}" + File.extname(base_filename) unless base_filename.include?("{{n}}")
|
|
24
|
+
paged_filename = paged_filename.gsub("{{n}}", (i+1).to_s)
|
|
25
|
+
File.write(paged_filename, page, mode: "wb")
|
|
18
26
|
end
|
|
19
27
|
end
|
|
20
28
|
|
|
@@ -5,7 +5,9 @@ module Typst
|
|
|
5
5
|
@compiled = HtmlExperimentalDocument.new(Typst::_to_html(*self.typst_args))
|
|
6
6
|
end
|
|
7
7
|
end
|
|
8
|
-
class HtmlExperimentalDocument < Document
|
|
8
|
+
class HtmlExperimentalDocument < Document
|
|
9
|
+
alias_method :write, :write_one
|
|
10
|
+
end
|
|
9
11
|
|
|
10
12
|
register_format(html_experimental: HtmlExperimental)
|
|
11
13
|
end
|
data/lib/formats/pdf.rb
CHANGED
|
@@ -2,10 +2,12 @@ module Typst
|
|
|
2
2
|
class Pdf < Base
|
|
3
3
|
def initialize(*options)
|
|
4
4
|
super(*options)
|
|
5
|
-
@compiled = PdfDocument.new(Typst::_to_pdf(*self.
|
|
5
|
+
@compiled = PdfDocument.new(Typst::_to_pdf(*self.typst_pdf_args))
|
|
6
6
|
end
|
|
7
7
|
end
|
|
8
|
-
class PdfDocument < Document
|
|
8
|
+
class PdfDocument < Document
|
|
9
|
+
alias_method :write, :write_one
|
|
10
|
+
end
|
|
9
11
|
|
|
10
12
|
register_format(pdf: Pdf)
|
|
11
13
|
end
|
data/lib/formats/png.rb
CHANGED
|
@@ -2,10 +2,12 @@ module Typst
|
|
|
2
2
|
class Png < Base
|
|
3
3
|
def initialize(*options)
|
|
4
4
|
super(*options)
|
|
5
|
-
@compiled = PngDocument.new(Typst::_to_png(*self.
|
|
5
|
+
@compiled = PngDocument.new(Typst::_to_png(*self.typst_png_args))
|
|
6
6
|
end
|
|
7
7
|
end
|
|
8
|
-
class PngDocument < Document
|
|
8
|
+
class PngDocument < Document
|
|
9
|
+
alias_method :write, :write_some
|
|
10
|
+
end
|
|
9
11
|
|
|
10
12
|
register_format(png: Png)
|
|
11
13
|
end
|
data/lib/formats/svg.rb
CHANGED
data/lib/query.rb
CHANGED
|
@@ -2,10 +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: [], sys_inputs: {})
|
|
6
|
-
super(input, root: root, font_paths: font_paths, sys_inputs: sys_inputs)
|
|
5
|
+
def initialize(selector, input, field: nil, one: false, format: "json", root: ".", font_paths: [], resource_path: ".", ignore_system_fonts: false, sys_inputs: {})
|
|
7
6
|
self.format = format
|
|
8
|
-
@result = Typst::_query(selector, field, one, format, input, root, font_paths,
|
|
7
|
+
@result = Typst::_query(selector, field, one, format, input, root, font_paths, resource_path, ignore_system_fonts, sys_inputs)
|
|
9
8
|
end
|
|
10
9
|
|
|
11
10
|
def result(raw: false)
|
|
@@ -15,5 +14,9 @@ module Typst
|
|
|
15
14
|
else @result
|
|
16
15
|
end
|
|
17
16
|
end
|
|
17
|
+
|
|
18
|
+
def to_s
|
|
19
|
+
@result
|
|
20
|
+
end
|
|
18
21
|
end
|
|
19
22
|
end
|
data/lib/typst.rb
CHANGED
|
@@ -12,19 +12,83 @@ module Typst
|
|
|
12
12
|
def self.formats
|
|
13
13
|
@@formats
|
|
14
14
|
end
|
|
15
|
-
end
|
|
16
15
|
|
|
16
|
+
def self.clear_cache(max_age = 0)
|
|
17
|
+
Typst::_clear_cache(max_age)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.build_world_from_s(main_source, **options, &blk)
|
|
21
|
+
dependencies = options[:dependencies] ||= {}
|
|
22
|
+
fonts = options[:fonts] ||= {}
|
|
23
|
+
|
|
24
|
+
Dir.mktmpdir do |tmp_dir|
|
|
25
|
+
tmp_main_file = Pathname.new(tmp_dir).join("main.typ")
|
|
26
|
+
File.write(tmp_main_file, main_source)
|
|
27
|
+
|
|
28
|
+
dependencies.each do |dep_name, dep_source|
|
|
29
|
+
tmp_dep_file = Pathname.new(tmp_dir).join(dep_name)
|
|
30
|
+
File.write(tmp_dep_file, dep_source)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
relative_font_path = Pathname.new(tmp_dir).join("fonts")
|
|
34
|
+
relative_font_path.mkpath
|
|
35
|
+
fonts.each do |font_name, font_bytes|
|
|
36
|
+
tmp_font_file = relative_font_path.join(font_name)
|
|
37
|
+
File.write(tmp_font_file, font_bytes)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
options[:file] = tmp_main_file
|
|
41
|
+
options[:root] = tmp_dir
|
|
42
|
+
options[:font_paths] = [relative_font_path]
|
|
43
|
+
|
|
44
|
+
blk.call(options)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.build_world_from_zip(zip_file_path, main_file = "main.typ", **options, &blk)
|
|
49
|
+
options[:dependencies] ||= {}
|
|
50
|
+
options[:fonts] ||= {}
|
|
51
|
+
|
|
52
|
+
Zip::File.open(zip_file_path) do |zipfile|
|
|
53
|
+
file_names = zipfile.dir.glob("*").collect{ |f| f.name }
|
|
54
|
+
case
|
|
55
|
+
when file_names.include?(main_file) then tmp_main_file = main_file
|
|
56
|
+
when file_names.include?("main.typ") then tmp_main_file = "main.typ"
|
|
57
|
+
when file_names.size == 1 then tmp_main_file = file_names.first
|
|
58
|
+
else raise "no main file found"
|
|
59
|
+
end
|
|
60
|
+
main_source = zipfile.file.read(tmp_main_file)
|
|
61
|
+
file_names.delete(tmp_main_file)
|
|
62
|
+
file_names.delete("fonts/")
|
|
63
|
+
|
|
64
|
+
file_names.each do |dep_name|
|
|
65
|
+
options[:dependencies][dep_name] = zipfile.file.read(dep_name)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
font_file_names = zipfile.dir.glob("fonts/*").collect{ |f| f.name }
|
|
69
|
+
font_file_names.each do |font_name|
|
|
70
|
+
options[:fonts][Pathname.new(font_name).basename.to_s] = zipfile.file.read(font_name)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
options[:main_file] = tmp_main_file
|
|
74
|
+
|
|
75
|
+
build_world_from_s(main_source, **options, &blk)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
17
79
|
|
|
18
|
-
require "cgi"
|
|
80
|
+
require "cgi/escape"
|
|
19
81
|
require "pathname"
|
|
20
82
|
require "tmpdir"
|
|
21
83
|
require "zip/filesystem"
|
|
84
|
+
require "json"
|
|
85
|
+
require "yaml"
|
|
22
86
|
|
|
23
87
|
begin
|
|
24
88
|
# native precompiled gems package shared libraries in <gem_dir>/lib/typst/<ruby_version>
|
|
25
89
|
RUBY_VERSION =~ /(\d+\.\d+)/
|
|
26
90
|
require_relative "typst/#{Regexp.last_match(1)}/typst"
|
|
27
|
-
rescue LoadError
|
|
91
|
+
rescue LoadError
|
|
28
92
|
require_relative "typst/typst"
|
|
29
93
|
end
|
|
30
94
|
|
|
@@ -34,5 +98,4 @@ require_relative "document"
|
|
|
34
98
|
require_relative "formats/pdf"
|
|
35
99
|
require_relative "formats/svg"
|
|
36
100
|
require_relative "formats/png"
|
|
37
|
-
require_relative "formats/html"
|
|
38
101
|
require_relative "formats/html_experimental"
|
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.14.2.
|
|
4
|
+
version: 0.14.2.2
|
|
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.124
|
|
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.124
|
|
32
32
|
- !ruby/object:Gem::Dependency
|
|
33
33
|
name: rubyzip
|
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -71,6 +71,34 @@ dependencies:
|
|
|
71
71
|
- - "~>"
|
|
72
72
|
- !ruby/object:Gem::Version
|
|
73
73
|
version: '3.6'
|
|
74
|
+
- !ruby/object:Gem::Dependency
|
|
75
|
+
name: os
|
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
|
77
|
+
requirements:
|
|
78
|
+
- - "~>"
|
|
79
|
+
- !ruby/object:Gem::Version
|
|
80
|
+
version: '1.1'
|
|
81
|
+
type: :development
|
|
82
|
+
prerelease: false
|
|
83
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
84
|
+
requirements:
|
|
85
|
+
- - "~>"
|
|
86
|
+
- !ruby/object:Gem::Version
|
|
87
|
+
version: '1.1'
|
|
88
|
+
- !ruby/object:Gem::Dependency
|
|
89
|
+
name: pngcheck
|
|
90
|
+
requirement: !ruby/object:Gem::Requirement
|
|
91
|
+
requirements:
|
|
92
|
+
- - "~>"
|
|
93
|
+
- !ruby/object:Gem::Version
|
|
94
|
+
version: '0.3'
|
|
95
|
+
type: :development
|
|
96
|
+
prerelease: false
|
|
97
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
98
|
+
requirements:
|
|
99
|
+
- - "~>"
|
|
100
|
+
- !ruby/object:Gem::Version
|
|
101
|
+
version: '0.3'
|
|
74
102
|
email: flinn@actsasflinn.com
|
|
75
103
|
executables: []
|
|
76
104
|
extensions:
|
|
@@ -106,14 +134,12 @@ files:
|
|
|
106
134
|
- lib/fonts/NewCM10-Regular.otf
|
|
107
135
|
- lib/fonts/NewCMMath-Book.otf
|
|
108
136
|
- lib/fonts/NewCMMath-Regular.otf
|
|
109
|
-
- lib/formats/html.rb
|
|
110
137
|
- lib/formats/html_experimental.rb
|
|
111
138
|
- lib/formats/pdf.rb
|
|
112
139
|
- lib/formats/png.rb
|
|
113
140
|
- lib/formats/svg.rb
|
|
114
141
|
- lib/query.rb
|
|
115
142
|
- lib/typst.rb
|
|
116
|
-
- lib/typst/typst.bundle
|
|
117
143
|
homepage: https://github.com/actsasflinn/typst-rb
|
|
118
144
|
licenses:
|
|
119
145
|
- Apache-2.0
|
|
@@ -132,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
132
158
|
- !ruby/object:Gem::Version
|
|
133
159
|
version: '0'
|
|
134
160
|
requirements: []
|
|
135
|
-
rubygems_version:
|
|
161
|
+
rubygems_version: 4.0.3
|
|
136
162
|
specification_version: 4
|
|
137
163
|
summary: Ruby binding to typst, a new markup-based typesetting system that is powerful
|
|
138
164
|
and easy to learn.
|
data/lib/formats/html.rb
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
module Typst
|
|
2
|
-
class Html < Base
|
|
3
|
-
def initialize(*options)
|
|
4
|
-
super(*options)
|
|
5
|
-
title = CGI::escapeHTML(@options[:title] || File.basename(@options[:file], ".*"))
|
|
6
|
-
@compiled = HtmlDocument.new(Typst::_to_svg(*self.typst_args), title)
|
|
7
|
-
end
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
class HtmlDocument < Document
|
|
11
|
-
attr_accessor :title
|
|
12
|
-
|
|
13
|
-
def initialize(bytes, title)
|
|
14
|
-
super(bytes)
|
|
15
|
-
self.title = title
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def markup
|
|
19
|
-
%{
|
|
20
|
-
<!DOCTYPE html>
|
|
21
|
-
<html>
|
|
22
|
-
<head>
|
|
23
|
-
<title>#{title}</title>
|
|
24
|
-
</head>
|
|
25
|
-
<body>
|
|
26
|
-
#{pages.join("<br />")}
|
|
27
|
-
</body>
|
|
28
|
-
</html>
|
|
29
|
-
}
|
|
30
|
-
end
|
|
31
|
-
alias_method :document, :markup
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
register_format(html: Html)
|
|
35
|
-
end
|
data/lib/typst/typst.bundle
DELETED
|
Binary file
|