typst 0.15.1.5 → 0.15.1.6

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: a463fc66211965514d27ea8a2867902818e7f4398779b79a4c304a993e4d5e63
4
- data.tar.gz: 484a1cdbecc7ae9381d7de90313a82b0288f053dd7a105974dc80f82d0baa4e3
3
+ metadata.gz: 97e4afa751e5a0bded609e423ea893b263ac5676afe79fe4bcde12761bd242dd
4
+ data.tar.gz: 112c45f8dbebcdcbcec318948b879dc47f44dc5c2bd5a143e4c035928dec6473
5
5
  SHA512:
6
- metadata.gz: 930e9e74d5cd98a50c7f06c181f4104b5ef9325a43008e9b114ae7006b4d13b2445ea57c27c28c3d60f2df5ee07c0734ea2047f52e494c4303df917058a0feed
7
- data.tar.gz: 0e806b7acb6b404e92ae170ce0f78f86743ca56dd99d99f5e365bd62a0f154bb7aebf8efadf4977260a85872325d4055aadde543df199dfa582b8aa07635caf8
6
+ metadata.gz: d825ef788371496a9b354cf1b22d3ea06c9f7fe2e3d1cc56b18310a9af1fede42fe449b23964c20f2b34df98a31155846d21750da0eaed97d146abbd4a7ad425
7
+ data.tar.gz: 0c561636ed80e29170ba849853ecd0c8342cb3abc609fb1d7ffeadc466eda702d537a454e1becd36e61f7339adc320ab6177adaf84d3bd8ef048ba6e7ddab222
data/README.md CHANGED
@@ -1,10 +1,19 @@
1
1
  # typst-rb
2
2
 
3
- Ruby binding to [typst](https://github.com/typst/typst),
3
+ Ruby language binding to [typst](https://github.com/typst/typst),
4
4
  a new markup-based typesetting system that is powerful and easy to learn.
5
5
 
6
+ ## Rubygems
7
+
8
+ Source and native gems are provided for the following platforms: `aarch64-linux` `aarch64-linux-musl` `arm64-darwin` `x64-mingw-ucrt` `x86_64-darwin` `x86_64-linux` `x86_64-linux-musl`. The gems are built from CI [gem-push](https://github.com/actsasflinn/typst-rb/actions/workflows/gem-push.yml) action and can be verified against SHA256SUMS published with the [release](https://github.com/actsasflinn/typst-rb/releases).
9
+
6
10
  ## Installation
7
11
 
12
+ Add the following to your gemfile and `bundle install`
13
+ ```ruby
14
+ gem 'typst', '>= 0.15.1.5'
15
+ ```
16
+ or install from the command line:
8
17
  ```bash
9
18
  gem install typst
10
19
  ```
@@ -13,69 +22,111 @@ gem install typst
13
22
 
14
23
  ```ruby
15
24
  require "typst"
25
+ ```
26
+
27
+ ### Hello World
28
+ This example compiles a typst string to PDF and writes to a file.
29
+ ```ruby
30
+ Typst(body: "= Hello World\nThis is your first typst PDF").compile(:pdf).write("hello_world.pdf")
31
+ ```
16
32
 
17
- # Compile a typst file and write the output to a PDF file
18
- Typst("readme.typ").compile(:pdf).write("readme.pdf")
33
+ ### The basics
34
+ This example initializes a `Typst::Base` object `t` using a string. The `t` object is basically an environment for your typst input and can take a variety of options suitable for your task which you can see in subsequent examples.
35
+ ```ruby
36
+ t = Typst(body: "= Hello World\nThis is your first typst PDF")
37
+ ```
38
+ This step compiles the typst input held in the `t` object and returns a `Typst::Document` object `doc`. In this case we're compiling to PDF so `doc` is a `Typst::PdfDocument` object which holds the PDF bytes and is ready to write to a file, output to a buffer, etc.
39
+ ```ruby
40
+ doc = t.compile(:pdf)
19
41
  ```
42
+ This step writes the output to a local file in your current working directory.
43
+ ```ruby
44
+ doc.write("hello_world.pdf")
45
+ ```
46
+ ### Different ways to setup the typst input
20
47
 
21
- ### Use a typst file `readme.typ`
48
+ #### Use a local typst file named `example.typ`
22
49
  ```ruby
23
- t = Typst("readme.typ")
50
+ t = Typst("example.typ")
24
51
  ```
25
52
 
26
- ### Use a typst string
53
+ #### Use a typst string
27
54
  ```ruby
28
55
  t = Typst(body: %{hello world})
29
56
  ```
30
57
 
31
- ### Use a typst file in a zip file
58
+ #### Use a zipped typst file
32
59
  ```ruby
33
60
  t = Typst(zip: "test/main.typ.zip")
34
61
  ```
35
62
 
36
- ### Compile to PDF
63
+ #### Use a remote typst file
64
+ ```ruby
65
+ require "open-uri"
66
+ URI.open("https://github.com/actsasflinn/typst-rb/raw/refs/heads/main/README.typ") do |u|
67
+ Typst(body: u.read).compile(:pdf).write("remote_readme.pdf")
68
+ end
69
+ ```
70
+
71
+ #### Use a remote zipped typst file
72
+ ```ruby
73
+ require "open-uri"
74
+ URI.open("https://github.com/actsasflinn/typst-rb/raw/refs/heads/main/test/hello.typ.zip") do |u|
75
+ Tempfile.create do |f|
76
+ f.write(u.read)
77
+ f.rewind
78
+ Typst(zip: f).compile(:pdf).write("remote_zipped.pdf")
79
+ end
80
+ end
81
+ ```
82
+
83
+ ### Compiling
84
+
85
+ #### Compile to PDF
37
86
  ```ruby
38
87
  doc = t.compile(:pdf)
39
88
  ```
40
89
 
41
- ### Compile to PDF selecting the typst supported PdfStandard
90
+ #### Compile to PDF selecting the typst supported PdfStandard
42
91
  ```ruby
43
92
  doc = t.compile(:pdf, pdf_standards: ["2.0"])
44
93
  ```
45
94
 
46
- ### Compile to SVG
95
+ #### Compile to SVG
47
96
  ```ruby
48
97
  doc = t.compile(:svg)
49
98
  ```
50
99
 
51
- ### Compile to PNG
100
+ #### Compile to PNG
52
101
  ```ruby
53
102
  doc = t.compile(:png)
54
103
  ```
55
104
 
56
- ### Compile to PNG and set PPI
105
+ #### Compile to PNG and set PPI
57
106
  ```ruby
58
107
  doc = t.compile(:png, ppi: 72)
59
108
  ```
60
109
 
61
- ### Compile to HTML (using Typst expirmental HTML)
110
+ #### Compile to HTML (using Typst expirmental HTML)
62
111
  ```ruby
63
112
  doc = t.compile(:html_experimental)
64
113
  ```
65
114
 
66
- ### Or return content as an array of bytes
115
+ ### Output
116
+
117
+ #### Return compiled content as an array of bytes
67
118
  ```ruby
68
119
  pdf_bytes = Typst("readme.typ").compile(:pdf).bytes
69
120
  # => [37, 80, 68, 70, 45, 49, 46, 55, 10, 37, 128 ...]
70
121
  ```
71
122
 
72
- ### Write the output to a file
73
- 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`
123
+ #### Write compiled output to a file
124
+ Note: for multi-page documents using formats other than PDF and HTML, pages write to multiple files, e.g. `filename_0.png`, `filename_1.png`
74
125
  ```ruby
75
126
  doc.write("filename.pdf")
76
127
  ```
77
128
 
78
- ### Return PDF, SVG, PNG or HTML content as an array of pages
129
+ #### Return PDF, SVG, PNG or HTML content as an array of pages
79
130
  ```ruby
80
131
  Typst("readme.typ").compile(:pdf).pages
81
132
  # => ["%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 ...
@@ -90,7 +141,9 @@ Typst("readme.typ").compile(:html_experimental).pages
90
141
  # => ["<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" ...
91
142
  ```
92
143
 
93
- ### Pass values into typst using sys_inputs
144
+ ### More advanced setups
145
+
146
+ #### Pass values into typst using sys_inputs
94
147
  ```ruby
95
148
  sys_inputs_example = %{
96
149
  #let persons = json(bytes(sys.inputs.persons))
@@ -104,7 +157,7 @@ data = { "persons" => people.to_json }
104
157
  Typst(body: sys_inputs_example, sys_inputs: data).compile(:pdf).write("sys_inputs_example.pdf")
105
158
  ```
106
159
 
107
- ### Apply inputs to typst to product multiple PDFs
160
+ #### Apply inputs to typst to product multiple PDFs
108
161
  ```ruby
109
162
  t = Typst(body: sys_inputs_example)
110
163
  people.each do |person|
@@ -112,7 +165,7 @@ people.each do |person|
112
165
  end
113
166
  ```
114
167
 
115
- ### A more complex example of compiling from string using other dependency typst template, svg and font resources all in memory
168
+ #### A more complex example of compiling from string using other dependency typst template, svg and font resources all in memory
116
169
  ```ruby
117
170
  main = %{
118
171
  #import "template.typ": *
@@ -137,12 +190,12 @@ font_bytes = File.read("Example.ttf")
137
190
  Typst(body: main, dependencies: { "template.typ" => template, "icon.svg" => icon }, fonts: { "Example.ttf" => font_bytes }).compile(:pdf)
138
191
  ```
139
192
 
140
- ### From a zip with a named main typst file
193
+ #### Use a zip file with an alternatively named main typst file
141
194
  ```ruby
142
195
  Typst(zip: "test/main.typ.zip", main_file: "hello.typ").compile(:pdf)
143
196
  ```
144
197
 
145
- ### Use a package from the [Typst Universe](https://typst.app/universe)
198
+ #### Use a package from the [Typst Universe](https://typst.app/universe)
146
199
  Your package_example.typ file...
147
200
  ```typst
148
201
  #import "@preview/wordometer:0.1.5": word-count, total-words
@@ -160,6 +213,25 @@ In this document, there are #total-words words all up.
160
213
  Typst("package_example.typ").compile(:pdf).write("package_example.pdf")
161
214
  ```
162
215
 
216
+ ### Compiler warnings
217
+
218
+ A compile can succeed *and* warn. The most common case is an unknown font
219
+ family: typst substitutes a different face, the document is produced, and
220
+ nothing tells you it is in the wrong typeface. Every compiled document carries
221
+ the warnings that came with it.
222
+
223
+ ```ruby
224
+ doc = Typst(body: %{#set text(font: "Not Installed")\n= Hello}).compile(:pdf)
225
+ doc.warnings?
226
+ # => true
227
+ doc.warnings
228
+ # => ["warning: unknown font family: \"Not Installed\"\n ┌─ /tmp/.../main.typ:1:0\n ..."]
229
+ ```
230
+
231
+ Each entry is one formatted diagnostic, so they can be counted, filtered or
232
+ logged individually. A clean compile returns an empty array. Warnings that
233
+ accompany a compile *error* are still included in the raised message, as before.
234
+
163
235
  ### Query a typst document
164
236
  ```ruby
165
237
  Typst("readme.typ").query("heading").result
@@ -196,7 +268,8 @@ typst-rb is based on [typst-py](https://github.com/messense/typst-py) by [messen
196
268
  clear_cache was contributed by [NRicciVestmark](https://github.com/NRicciVestmark)\
197
269
  CI improvements were contributed by [am1006](https://github.com/am1006)\
198
270
  Defect resolutions by [adam12](https://github.com/adam12) and [walterdavis](https://github.com/walterdavis)\
199
- Design suggestions by [alec-c4](https://github.com/alec-c4)
271
+ Design suggestions by [alec-c4](https://github.com/alec-c4)\
272
+ Compiler warnings were contributed by [TheSoloHacker47](https://github.com/TheSoloHacker47)
200
273
 
201
274
  ## License
202
275
 
data/README.typ CHANGED
@@ -9,10 +9,19 @@
9
9
 
10
10
  = typst-rb
11
11
 
12
- Ruby binding to #link("https://github.com/typst/typst")[typst], a new markup-based typesetting system that is powerful and easy to learn.
12
+ Ruby language binding to #link("https://github.com/typst/typst")[typst], a new markup-based typesetting system that is powerful and easy to learn.
13
+
14
+ == Rubygems
15
+
16
+ Source and native gems are provided for the following platforms: `aarch64-linux` `aarch64-linux-musl` `arm64-darwin` `x64-mingw-ucrt` `x86_64-darwin` `x86_64-linux` `x86_64-linux-musl`. The gems are built from CI #link("https://github.com/actsasflinn/typst-rb/actions/workflows/gem-push.yml")[gem-push] action and can be verified against SHA256SUMS published with the #link("https://github.com/actsasflinn/typst-rb/releases")[release].
13
17
 
14
18
  == Installation
15
19
 
20
+ Add the following to your gemfile and `bundle install`
21
+ ```ruby
22
+ gem 'typst', '>= 0.15.1.5'
23
+ ```
24
+ or install from the command line:
16
25
  ```bash
17
26
  gem install typst
18
27
  ```
@@ -21,69 +30,110 @@ gem install typst
21
30
 
22
31
  ```ruby
23
32
  require "typst"
33
+ ```
24
34
 
25
- # Compile a typst file and write the output to a PDF file
26
- Typst("readme.typ").compile(:pdf).write("readme.pdf")
35
+ === Hello World
36
+ This example compiles a typst string to PDF and writes to a file.
37
+ ```ruby
38
+ Typst(body: "= Hello World\nThis is your first typst PDF").compile(:pdf).write("hello_world.pdf")
39
+ ```
40
+ === The basics
41
+ This example initializes a `Typst::Base` object `t` using a string. The `t` object is basically an environment for your typst input and can take a variety of options suitable for your task which you can see in subsequent examples.
42
+ ```ruby
43
+ t = Typst(body: "= Hello World\nThis is your first typst PDF")
27
44
  ```
45
+ This step compiles the typst input held in the `t` object and returns a `Typst::Document` object `doc`. In this case we're compiling to PDF so `doc` is a `Typst::PdfDocument` object which holds the PDF bytes and is ready to write to a file, output to a buffer, etc.
46
+ ```ruby
47
+ doc = t.compile(:pdf)
48
+ ```
49
+ This step writes the output to a local file in your current working directory.
50
+ ```ruby
51
+ doc.write("hello_world.pdf")
52
+ ```
53
+ === Different ways to setup the typst input
28
54
 
29
- === Use a typst file `readme.typ`
55
+ ==== Use a local typst file named `example.typ`
30
56
  ```ruby
31
- t = Typst("readme.typ")
57
+ t = Typst("example.typ")
32
58
  ```
33
59
 
34
- === Use a typst string
60
+ ==== Use a typst string
35
61
  ```ruby
36
62
  t = Typst(body: %{hello world})
37
63
  ```
38
64
 
39
- === Use a typst file in a zip file
65
+ ==== Use a zipped typst file
40
66
  ```ruby
41
67
  t = Typst(zip: "test/main.typ.zip")
42
68
  ```
43
69
 
44
- === Compile to PDF
70
+ ==== Use a remote typst file
71
+ ```ruby
72
+ require "open-uri"
73
+ URI.open("https://github.com/actsasflinn/typst-rb/raw/refs/heads/main/README.typ") do |u|
74
+ Typst(body: u.read).compile(:pdf).write("remote_readme.pdf")
75
+ end
76
+ ```
77
+
78
+ ==== Use a remote zipped typst file
79
+ ```ruby
80
+ require "open-uri"
81
+ URI.open("https://github.com/actsasflinn/typst-rb/raw/refs/heads/main/test/hello.typ.zip") do |u|
82
+ Tempfile.create do |f|
83
+ f.write(u.read)
84
+ f.rewind
85
+ Typst(zip: f).compile(:pdf).write("remote_zipped.pdf")
86
+ end
87
+ end
88
+ ```
89
+
90
+ === Compiling
91
+
92
+ ==== Compile to PDF
45
93
  ```ruby
46
94
  doc = t.compile(:pdf)
47
95
  ```
48
96
 
49
- === Compile to PDF selecting the typst supported PdfStandard
97
+ ==== Compile to PDF selecting the typst supported PdfStandard
50
98
  ```ruby
51
99
  doc = t.compile(:pdf, pdf_standards: ["2.0"])
52
100
  ```
53
101
 
54
- === Compile to SVG
102
+ ==== Compile to SVG
55
103
  ```ruby
56
104
  doc = t.compile(:svg)
57
105
  ```
58
106
 
59
- === Compile to PNG
107
+ ==== Compile to PNG
60
108
  ```ruby
61
109
  doc = t.compile(:png)
62
110
  ```
63
111
 
64
- === Compile to PNG and set PPI
112
+ ==== Compile to PNG and set PPI
65
113
  ```ruby
66
114
  doc = t.compile(:png, ppi: 72)
67
115
  ```
68
116
 
69
- === Compile to HTML (using Typst expirmental HTML)
117
+ ==== Compile to HTML (using Typst expirmental HTML)
70
118
  ```ruby
71
119
  doc = t.compile(:html_experimental)
72
120
  ```
73
121
 
74
- === Or return content as an array of bytes
122
+ === Output
123
+
124
+ ==== Return compiled content as an array of bytes
75
125
  ```ruby
76
126
  pdf_bytes = Typst("readme.typ").compile(:pdf).bytes
77
127
  # => [37, 80, 68, 70, 45, 49, 46, 55, 10, 37, 128 ...]
78
128
  ```
79
129
 
80
- === Write the output to a file
81
- 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`
130
+ ==== Write compiled output to a file
131
+ Note: for multi-page documents using formats other than PDF and HTML, pages write to multiple files, e.g. `filename_0.png`, `filename_1.png`
82
132
  ```ruby
83
133
  doc.write("filename.pdf")
84
134
  ```
85
135
 
86
- === Return PDF, SVG, PNG or HTML content as an array of pages
136
+ ==== Return PDF, SVG, PNG or HTML content as an array of pages
87
137
  ```ruby
88
138
  Typst("readme.typ").compile(:pdf).pages
89
139
  # => ["%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 ...
@@ -98,7 +148,9 @@ Typst("readme.typ").compile(:html_experimental).pages
98
148
  # => ["<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" ...
99
149
  ```
100
150
 
101
- === Pass values into typst using sys_inputs
151
+ === More advanced setups
152
+
153
+ ==== Pass values into typst using sys_inputs
102
154
  ```ruby
103
155
  sys_inputs_example = %{
104
156
  #let persons = json(bytes(sys.inputs.persons))
@@ -112,7 +164,7 @@ data = { "persons" => people.to_json }
112
164
  Typst(body: sys_inputs_example, sys_inputs: data).compile(:pdf).write("sys_inputs_example.pdf")
113
165
  ```
114
166
 
115
- === Apply inputs to typst to product multiple PDFs
167
+ ==== Apply inputs to typst to product multiple PDFs
116
168
  ```ruby
117
169
  t = Typst(body: sys_inputs_example)
118
170
  people.each do |person|
@@ -120,7 +172,7 @@ people.each do |person|
120
172
  end
121
173
  ```
122
174
 
123
- === A more complex example of compiling from string using other dependency typst template, svg and font resources all in memory
175
+ ==== A more complex example of compiling from string using other dependency typst template, svg and font resources all in memory
124
176
  ```ruby
125
177
  main = %{
126
178
  #import "template.typ": *
@@ -145,12 +197,12 @@ font_bytes = File.read("Example.ttf")
145
197
  Typst(body: main, dependencies: { "template.typ" => template, "icon.svg" => icon }, fonts: { "Example.ttf" => font_bytes }).compile(:pdf)
146
198
  ```
147
199
 
148
- === From a zip with a named main typst file
200
+ ==== Use a zip file with an alternatively named main typst file
149
201
  ```ruby
150
202
  Typst(zip: "test/main.typ.zip", main_file: "hello.typ").compile(:pdf)
151
203
  ```
152
204
 
153
- === Use a package from the #link("https://typst.app/universe")[Typst Universe]
205
+ ==== Use a package from the #link("https://typst.app/universe")[Typst Universe]
154
206
  Your package_example.typ file...
155
207
  ```typst
156
208
  #import "@preview/wordometer:0.1.5": word-count, total-words
@@ -168,6 +220,25 @@ In this document, there are #total-words words all up.
168
220
  Typst("package_example.typ").compile(:pdf).write("package_example.pdf")
169
221
  ```
170
222
 
223
+ === Compiler warnings
224
+
225
+ A compile can succeed *and* warn. The most common case is an unknown font
226
+ family: typst substitutes a different face, the document is produced, and
227
+ nothing tells you it is in the wrong typeface. Every compiled document carries
228
+ the warnings that came with it.
229
+
230
+ ```ruby
231
+ doc = Typst(body: %{#set text(font: "Not Installed")\n= Hello}).compile(:pdf)
232
+ doc.warnings?
233
+ # => true
234
+ doc.warnings
235
+ # => ["warning: unknown font family: \"Not Installed\"\n ┌─ /tmp/.../main.typ:1:0\n ..."]
236
+ ```
237
+
238
+ Each entry is one formatted diagnostic, so they can be counted, filtered or
239
+ logged individually. A clean compile returns an empty array. Warnings that
240
+ accompany a compile *error* are still included in the raised message, as before.
241
+
171
242
  === Query a typst document
172
243
  ```ruby
173
244
  Typst("readme.typ").query("heading").result
@@ -204,7 +275,8 @@ typst-rb is based on #link("https://github.com/messense/typst-py")[typst-py] by
204
275
  clear_cache was contributed by #link("https://github.com/NRicciVestmark")[NRicciVestmark]\
205
276
  CI improvements were contributed by #link("https://github.com/am1006")[am1006]\
206
277
  Defect resolutions by #link("https://github.com/adam12")[adam12] and #link("https://github.com/walterdavis")[walterdavis]\
207
- Design suggestions by #link("https://github.com/alec-c4")[alec-c4]
278
+ Design suggestions by #link("https://github.com/alec-c4")[alec-c4]\
279
+ Compiler warnings were contributed by #link("https://github.com/TheSoloHacker47")[TheSoloHacker47]
208
280
 
209
281
  == License
210
282
 
@@ -22,7 +22,7 @@ impl SystemWorld {
22
22
  pdf_standards: &[typst_pdf::PdfStandard],
23
23
  pretty: bool,
24
24
  render_bleed: bool,
25
- ) -> StrResult<Vec<Vec<u8>>> {
25
+ ) -> StrResult<(Vec<Vec<u8>>, Vec<String>)> {
26
26
  // Reset everything and ensure that the main file is present.
27
27
  self.reset();
28
28
  self.source(self.main()).map_err(|err| err.to_string())?;
@@ -32,7 +32,7 @@ impl SystemWorld {
32
32
  let Warned { output, warnings } = typst::compile::<HtmlDocument>(self);
33
33
  match output {
34
34
  Ok(document) => {
35
- Ok(vec![export_html(&document, self, pretty)?])
35
+ Ok((vec![export_html(&document, self, pretty)?], self.format_warnings(&warnings)))
36
36
  }
37
37
  Err(errors) => Err(format_diagnostics(self, &errors, &warnings).unwrap().into()),
38
38
  }
@@ -43,25 +43,45 @@ impl SystemWorld {
43
43
  // Export the PDF / PNG.
44
44
  Ok(document) => {
45
45
  // Assert format is "pdf" or "png" or "svg"
46
- match format.unwrap_or("pdf").to_ascii_lowercase().as_str() {
47
- "pdf" => Ok(vec![export_pdf(
46
+ let buffers = match format.unwrap_or("pdf").to_ascii_lowercase().as_str() {
47
+ "pdf" => vec![export_pdf(
48
48
  &document,
49
49
  self,
50
50
  typst_pdf::PdfStandards::new(pdf_standards)
51
51
  .map_err(|e| eco_format!("PDF standards error: {:?}", e))
52
52
  .at(Span::detached()).unwrap(),
53
53
  pretty,
54
- )?]),
55
- "png" => Ok(export_image(&document, ImageExportFormat::Png, ppi, pretty, render_bleed)?),
56
- "svg" => Ok(export_image(&document, ImageExportFormat::Svg, ppi, pretty, render_bleed)?),
57
- fmt => Err(eco_format!("unknown format: {fmt}")),
58
- }
54
+ )?],
55
+ "png" => export_image(&document, ImageExportFormat::Png, ppi, pretty, render_bleed)?,
56
+ "svg" => export_image(&document, ImageExportFormat::Svg, ppi, pretty, render_bleed)?,
57
+ fmt => return Err(eco_format!("unknown format: {fmt}")),
58
+ };
59
+ Ok((buffers, self.format_warnings(&warnings)))
59
60
  }
60
61
  Err(errors) => Err(format_diagnostics(self, &errors, &warnings).unwrap().into()),
61
62
  }
62
63
  }
63
64
  }
64
65
  }
66
+
67
+ /// One formatted string per warning.
68
+ ///
69
+ /// A successful compile can still produce warnings — an unknown font
70
+ /// family being the one that bites people, because Typst substitutes a
71
+ /// different face and the document still generates. Previously those were
72
+ /// dropped on the floor: `format_diagnostics` only ever saw them on the
73
+ /// error path. Returning them one per entry (rather than as a single
74
+ /// blob) means a caller can count them, filter them, or attach them to a
75
+ /// log line without parsing.
76
+ fn format_warnings(&self, warnings: &[SourceDiagnostic]) -> Vec<String> {
77
+ warnings
78
+ .iter()
79
+ .map(|warning| {
80
+ format_diagnostics(self, &[], std::slice::from_ref(warning))
81
+ .unwrap_or_else(|_| warning.message.to_string())
82
+ })
83
+ .collect()
84
+ }
65
85
  }
66
86
 
67
87
  /// Export to a PDF.
data/ext/typst/src/lib.rs CHANGED
@@ -24,7 +24,7 @@ fn to_html(
24
24
  render_bleed: bool,
25
25
  pretty: bool,
26
26
  sys_inputs: HashMap<String, String>,
27
- ) -> Result<Vec<Vec<u8>>, Error> {
27
+ ) -> Result<(Vec<Vec<u8>>, Vec<String>), Error> {
28
28
  let input = input.canonicalize()
29
29
  .map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?;
30
30
 
@@ -62,11 +62,11 @@ fn to_html(
62
62
  .build()
63
63
  .map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
64
64
 
65
- let bytes = world
65
+ let compiled = world
66
66
  .compile(Some("html"), None, &Vec::new(), pretty, render_bleed)
67
67
  .map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
68
68
 
69
- Ok(bytes)
69
+ Ok(compiled)
70
70
  }
71
71
 
72
72
  fn to_svg(
@@ -79,7 +79,7 @@ fn to_svg(
79
79
  render_bleed: bool,
80
80
  pretty: bool,
81
81
  sys_inputs: HashMap<String, String>,
82
- ) -> Result<Vec<Vec<u8>>, Error> {
82
+ ) -> Result<(Vec<Vec<u8>>, Vec<String>), Error> {
83
83
  let input = input.canonicalize()
84
84
  .map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?;
85
85
 
@@ -104,11 +104,11 @@ fn to_svg(
104
104
  .build()
105
105
  .map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
106
106
 
107
- let svg_bytes = world
107
+ let compiled = world
108
108
  .compile(Some("svg"), None, &Vec::new(), pretty, render_bleed)
109
109
  .map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
110
110
 
111
- Ok(svg_bytes)
111
+ Ok(compiled)
112
112
  }
113
113
 
114
114
  fn to_png(
@@ -121,7 +121,7 @@ fn to_png(
121
121
  render_bleed: bool,
122
122
  sys_inputs: HashMap<String, String>,
123
123
  ppi: Option<f32>,
124
- ) -> Result<Vec<Vec<u8>>, Error> {
124
+ ) -> Result<(Vec<Vec<u8>>, Vec<String>), Error> {
125
125
  let input = input.canonicalize()
126
126
  .map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?;
127
127
 
@@ -146,11 +146,11 @@ fn to_png(
146
146
  .build()
147
147
  .map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
148
148
 
149
- let bytes = world
149
+ let compiled = world
150
150
  .compile(Some("png"), ppi, &Vec::new(), false, render_bleed)
151
151
  .map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
152
152
 
153
- Ok(bytes)
153
+ Ok(compiled)
154
154
  }
155
155
 
156
156
  fn to_pdf(
@@ -163,7 +163,7 @@ fn to_pdf(
163
163
  pretty: bool,
164
164
  sys_inputs: HashMap<String, String>,
165
165
  pdf_standards: Vec<String>,
166
- ) -> Result<Vec<Vec<u8>>, Error> {
166
+ ) -> Result<(Vec<Vec<u8>>, Vec<String>), Error> {
167
167
  let input = input.canonicalize()
168
168
  .map_err(|err| magnus::Error::new(ruby.exception_arg_error(), err.to_string()))?;
169
169
 
@@ -217,11 +217,11 @@ fn to_pdf(
217
217
  }
218
218
  }
219
219
 
220
- let pdf_bytes = world
220
+ let compiled = world
221
221
  .compile(Some("pdf"), None, &pdf_standards_vec, pretty, true)
222
222
  .map_err(|msg| magnus::Error::new(ruby.exception_arg_error(), msg.to_string()))?;
223
223
 
224
- Ok(pdf_bytes)
224
+ Ok(compiled)
225
225
  }
226
226
 
227
227
  fn query(
data/lib/document.rb CHANGED
@@ -2,8 +2,18 @@ module Typst
2
2
  class Document
3
3
  attr_accessor :bytes
4
4
 
5
- def initialize(bytes)
5
+ # Diagnostics the compiler emitted while *succeeding*. An unknown font
6
+ # family is the common one: Typst substitutes another face, the document
7
+ # generates, and nothing tells you unless you look here.
8
+ attr_accessor :warnings
9
+
10
+ def initialize(bytes, warnings = [])
6
11
  @bytes = bytes
12
+ @warnings = warnings
13
+ end
14
+
15
+ def warnings?
16
+ !warnings.empty?
7
17
  end
8
18
 
9
19
  def write_some(filename)
@@ -2,7 +2,8 @@ module Typst
2
2
  class HtmlExperimental < Base
3
3
  def initialize(*options)
4
4
  super(*options)
5
- @compiled = HtmlExperimentalDocument.new(Typst::_to_html(*self.typst_pretty_args))
5
+ bytes, warnings = Typst::_to_html(*self.typst_pretty_args)
6
+ @compiled = HtmlExperimentalDocument.new(bytes, warnings)
6
7
  end
7
8
  end
8
9
  class HtmlExperimentalDocument < Document
data/lib/formats/pdf.rb CHANGED
@@ -2,7 +2,8 @@ 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_pdf_args))
5
+ bytes, warnings = Typst::_to_pdf(*self.typst_pdf_args)
6
+ @compiled = PdfDocument.new(bytes, warnings)
6
7
  end
7
8
  end
8
9
  class PdfDocument < Document
data/lib/formats/png.rb CHANGED
@@ -2,7 +2,8 @@ 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_png_args))
5
+ bytes, warnings = Typst::_to_png(*self.typst_png_args)
6
+ @compiled = PngDocument.new(bytes, warnings)
6
7
  end
7
8
  end
8
9
  class PngDocument < Document
data/lib/formats/svg.rb CHANGED
@@ -2,7 +2,8 @@ module Typst
2
2
  class Svg < Base
3
3
  def initialize(*options)
4
4
  super(*options)
5
- @compiled = SvgDocument.new(Typst::_to_svg(*self.typst_pretty_args))
5
+ bytes, warnings = Typst::_to_svg(*self.typst_pretty_args)
6
+ @compiled = SvgDocument.new(bytes, warnings)
6
7
  end
7
8
  end
8
9
  class SvgDocument < Document
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.15.1.5
4
+ version: 0.15.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Flinn
@@ -117,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
117
  - !ruby/object:Gem::Version
118
118
  version: '0'
119
119
  requirements: []
120
- rubygems_version: 4.0.17
120
+ rubygems_version: 4.0.19
121
121
  specification_version: 4
122
122
  summary: Ruby binding to typst, a new markup-based typesetting system that is powerful
123
123
  and easy to learn.