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 +4 -4
- data/README.md +96 -23
- data/README.typ +95 -23
- data/ext/typst/src/compiler.rs +29 -9
- data/ext/typst/src/lib.rs +12 -12
- data/lib/document.rb +11 -1
- data/lib/formats/html_experimental.rb +2 -1
- data/lib/formats/pdf.rb +2 -1
- data/lib/formats/png.rb +2 -1
- data/lib/formats/svg.rb +2 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 97e4afa751e5a0bded609e423ea893b263ac5676afe79fe4bcde12761bd242dd
|
|
4
|
+
data.tar.gz: 112c45f8dbebcdcbcec318948b879dc47f44dc5c2bd5a143e4c035928dec6473
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
|
|
18
|
-
Typst
|
|
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
|
-
|
|
48
|
+
#### Use a local typst file named `example.typ`
|
|
22
49
|
```ruby
|
|
23
|
-
t = Typst("
|
|
50
|
+
t = Typst("example.typ")
|
|
24
51
|
```
|
|
25
52
|
|
|
26
|
-
|
|
53
|
+
#### Use a typst string
|
|
27
54
|
```ruby
|
|
28
55
|
t = Typst(body: %{hello world})
|
|
29
56
|
```
|
|
30
57
|
|
|
31
|
-
|
|
58
|
+
#### Use a zipped typst file
|
|
32
59
|
```ruby
|
|
33
60
|
t = Typst(zip: "test/main.typ.zip")
|
|
34
61
|
```
|
|
35
62
|
|
|
36
|
-
|
|
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
|
-
|
|
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
|
-
|
|
95
|
+
#### Compile to SVG
|
|
47
96
|
```ruby
|
|
48
97
|
doc = t.compile(:svg)
|
|
49
98
|
```
|
|
50
99
|
|
|
51
|
-
|
|
100
|
+
#### Compile to PNG
|
|
52
101
|
```ruby
|
|
53
102
|
doc = t.compile(:png)
|
|
54
103
|
```
|
|
55
104
|
|
|
56
|
-
|
|
105
|
+
#### Compile to PNG and set PPI
|
|
57
106
|
```ruby
|
|
58
107
|
doc = t.compile(:png, ppi: 72)
|
|
59
108
|
```
|
|
60
109
|
|
|
61
|
-
|
|
110
|
+
#### Compile to HTML (using Typst expirmental HTML)
|
|
62
111
|
```ruby
|
|
63
112
|
doc = t.compile(:html_experimental)
|
|
64
113
|
```
|
|
65
114
|
|
|
66
|
-
###
|
|
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
|
-
|
|
73
|
-
Note: for multi-page documents using formats other than PDF and HTML, pages write to multiple files, e.g. `
|
|
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
|
-
|
|
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
|
-
###
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
26
|
-
|
|
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
|
-
|
|
55
|
+
==== Use a local typst file named `example.typ`
|
|
30
56
|
```ruby
|
|
31
|
-
t = Typst("
|
|
57
|
+
t = Typst("example.typ")
|
|
32
58
|
```
|
|
33
59
|
|
|
34
|
-
|
|
60
|
+
==== Use a typst string
|
|
35
61
|
```ruby
|
|
36
62
|
t = Typst(body: %{hello world})
|
|
37
63
|
```
|
|
38
64
|
|
|
39
|
-
|
|
65
|
+
==== Use a zipped typst file
|
|
40
66
|
```ruby
|
|
41
67
|
t = Typst(zip: "test/main.typ.zip")
|
|
42
68
|
```
|
|
43
69
|
|
|
44
|
-
|
|
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
|
-
|
|
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
|
-
|
|
102
|
+
==== Compile to SVG
|
|
55
103
|
```ruby
|
|
56
104
|
doc = t.compile(:svg)
|
|
57
105
|
```
|
|
58
106
|
|
|
59
|
-
|
|
107
|
+
==== Compile to PNG
|
|
60
108
|
```ruby
|
|
61
109
|
doc = t.compile(:png)
|
|
62
110
|
```
|
|
63
111
|
|
|
64
|
-
|
|
112
|
+
==== Compile to PNG and set PPI
|
|
65
113
|
```ruby
|
|
66
114
|
doc = t.compile(:png, ppi: 72)
|
|
67
115
|
```
|
|
68
116
|
|
|
69
|
-
|
|
117
|
+
==== Compile to HTML (using Typst expirmental HTML)
|
|
70
118
|
```ruby
|
|
71
119
|
doc = t.compile(:html_experimental)
|
|
72
120
|
```
|
|
73
121
|
|
|
74
|
-
===
|
|
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
|
-
|
|
81
|
-
Note: for multi-page documents using formats other than PDF and HTML, pages write to multiple files, e.g. `
|
|
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
|
-
|
|
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
|
-
===
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
data/ext/typst/src/compiler.rs
CHANGED
|
@@ -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" =>
|
|
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" =>
|
|
56
|
-
"svg" =>
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|