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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77a2b80d3ddc7e3b8a2fd44c365b3a7c9464383894bb3a61e869d87085baa8a2
4
- data.tar.gz: ce2e709afe2b9b76f73292ec13df74815ac0ff7dc7fc4636a58d73b7122ad391
3
+ metadata.gz: 0e902865d606a53619b4af115102284997f623a128bc06405f5300c4c2b4c687
4
+ data.tar.gz: a33d506d802a470779eb60c2d075a0c6cf9babf50756b8633d87e297d05cc1fd
5
5
  SHA512:
6
- metadata.gz: b0e845ea82c232ed88b4dd6c159b814aad54199ff85829a7edb18a42346abf887e138345efca9e1ab1a2ca8b379b161bda3448162cd128f811b342815a7f0b85
7
- data.tar.gz: 73c99e328ea7aa5ba58d574b7b7770b86355f97787e2df6de4a4578913ae7d72082e11309309ae2ccd2f3882ceba26a482e60de8b25dc188a78e678ca41c99b7
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
- f = t.compile(:pdf)
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
- f = t.compile(:svg)
36
+ doc = t.compile(:svg)
34
37
 
35
38
  # Compile to PNG
36
- f = t.compile(:png)
39
+ doc = t.compile(:png)
37
40
 
38
- # Compile to SVGs enveloped in HTML
39
- # Depracation warning: this feature will go away once Typst HTML moves out of experimental
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
- f = t.compile(:html_experimental)
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
- f.write("filename.pdf")
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, HTML or PNG content as an array of pages
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::Query.new("heading", "readme.typ").result
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::Query.new("heading", "readme.typ", format: "json").result(raw: true)
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::Query.new("heading", "readme.typ", format: "yaml").result(raw: true)
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
- f = t.compile(:pdf)
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
- f = t.compile(:svg)
39
+ doc = t.compile(:svg)
37
40
 
38
41
  # Compile to PNG
39
- f = t.compile(:png)
42
+ doc = t.compile(:png)
40
43
 
41
- # Compile to SVGs enveloped in HTML
42
- # Depracation warning: this feature will go away once Typst HTML moves out of experimental
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
- f = t.compile(:html_experimental)
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
- f.write("filename.pdf")
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, HTML or PNG content as an array of pages
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::Query.new("heading", "readme.typ").result
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::Query.new("heading", "readme.typ", format: "json").result(raw: true)
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::Query.new("heading", "readme.typ", format: "yaml").result(raw: true)
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
 
@@ -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
 
@@ -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-py/", env!("CARGO_PKG_VERSION"));
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"), None, &Vec::new())
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, &Vec::new())
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, 6))?;
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, 6))?;
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
  }
@@ -8,7 +8,7 @@ use typst::layout::PagedDocument;
8
8
  use typst::syntax::Span;
9
9
  use typst::syntax::SyntaxMode;
10
10
  use typst::World;
11
- use typst_eval::eval_string; //{eval_string, EvalMode};
11
+ use typst_eval::eval_string;
12
12
 
13
13
  use crate::world::SystemWorld;
14
14
 
@@ -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], File.dirname(__FILE__), false, options[:sys_inputs].map{ |k,v| [k.to_s,v.to_s] }.to_h]
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 self.from_s(main_source, **options)
46
- dependencies = options[:dependencies] ||= {}
47
- fonts = options[:fonts] ||= {}
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
- options[:file] = tmp_main_file
66
- options[:root] = tmp_dir
67
- options[:font_paths] = [relative_font_path]
52
+ def typst_png_args
53
+ [*typst_args, options[:ppi]]
54
+ end
68
55
 
69
- if options[:format]
70
- Typst::formats[options[:format]].new(**options)
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(**options)
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 = nil, **options)
78
- options[:dependencies] ||= {}
79
- options[:fonts] ||= {}
80
-
81
- Zip::File.open(zip_file_path) do |zipfile|
82
- file_names = zipfile.dir.glob("*").collect{ |f| f.name }
83
- case
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::formats[format].from_s(options[:body], **options).compiled
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
- Typst::formats[format].from_zip(options[:zip], options[:main_file], **options).compiled
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 write(output)
150
- STDERR.puts "DEPRECATION WARNING: this method will go away in a future version"
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
- def bytes
160
- STDERR.puts "DEPRECATION WARNING: this method will go away in a future version"
161
- compiled.bytes
162
- end
163
-
164
- def pages
165
- STDERR.puts "DEPRECATION WARNING: this method will go away in a future version"
166
- compiled.pages
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 write(out)
9
+ def write_some(filename)
10
10
  if pages.size == 1
11
- File.write(out, pages.first, mode: "wb")
11
+ write_one(filename)
12
12
  else
13
- pages.each_with_index do |page, i|
14
- fn = File.basename(out, ".*") + "_{{n}}" + File.extname(out) unless out.include?("{{n}}")
15
- fn = fn.gsub("{{n}}", (i+1).to_s)
16
- File.write(fn, page, mode: "wb")
17
- end
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; end
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.typst_args))
5
+ @compiled = PdfDocument.new(Typst::_to_pdf(*self.typst_pdf_args))
6
6
  end
7
7
  end
8
- class PdfDocument < Document; end
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.typst_args))
5
+ @compiled = PngDocument.new(Typst::_to_png(*self.typst_png_args))
6
6
  end
7
7
  end
8
- class PngDocument < Document; end
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
@@ -5,7 +5,9 @@ module Typst
5
5
  @compiled = SvgDocument.new(Typst::_to_svg(*self.typst_args))
6
6
  end
7
7
  end
8
- class SvgDocument < Document; end
8
+ class SvgDocument < Document
9
+ alias_method :write, :write_some
10
+ end
9
11
 
10
12
  register_format(svg: Svg)
11
13
  end
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, File.dirname(__FILE__), false, sys_inputs)
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 => e
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.1
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.123
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.123
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: 3.6.9
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
Binary file