css_inline 0.22.0-aarch64-linux → 0.23.0-aarch64-linux
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 +118 -87
- data/lib/css_inline/3.2/css_inline.so +0 -0
- data/lib/css_inline/3.3/css_inline.so +0 -0
- data/lib/css_inline/3.4/css_inline.so +0 -0
- data/lib/css_inline/4.0/css_inline.so +0 -0
- data/src/lib.rs +325 -0
- metadata +5 -6
- data/Cargo.lock +0 -1947
- data/Cargo.toml +0 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5afaeed32beccd785ec395587e277e5c52a2090770931a83527a060538591531
|
|
4
|
+
data.tar.gz: 92af0aa71a9a68c240619ee4e64865ae5ffee515b114041843323177d4497b60
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bd769ed0b9c12ccaa52ddb7e4ce4760d0b0127b35b81a3ee386aebcd3cbcfb0383d795ccc3165a2af52ffbec48aad9641e7acefb3d85303606b7a6809c472451
|
|
7
|
+
data.tar.gz: 2fb13ec52e3eb2d47872a1cdbc54d0d37cb68e55a47b26c543c4434944ed166d182d48fc91d658894b33c323d9e255165a55ccdf067222cdaf1af996dea579e7
|
data/README.md
CHANGED
|
@@ -5,11 +5,10 @@
|
|
|
5
5
|
[<img alt="codecov.io" src="https://img.shields.io/codecov/c/gh/Stranger6667/css-inline?logo=codecov&style=flat-square&token=tOzvV4kDY0" height="20">](https://app.codecov.io/github/Stranger6667/css-inline)
|
|
6
6
|
[<img alt="gitter" src="https://img.shields.io/gitter/room/Stranger6667/css-inline?style=flat-square" height="20">](https://gitter.im/Stranger6667/css-inline)
|
|
7
7
|
|
|
8
|
-
`css_inline`
|
|
8
|
+
`css_inline` moves CSS from `<style>` and `<link>` tags into HTML `style` attributes.
|
|
9
|
+
Use it to prepare HTML emails or to embed HTML into third-party web pages.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
For instance, the library transforms HTML like this:
|
|
11
|
+
It turns this HTML:
|
|
13
12
|
|
|
14
13
|
```html
|
|
15
14
|
<html>
|
|
@@ -28,36 +27,45 @@ into:
|
|
|
28
27
|
<html>
|
|
29
28
|
<head></head>
|
|
30
29
|
<body>
|
|
31
|
-
<h1 style="color:blue;">Big Text</h1>
|
|
30
|
+
<h1 style="color: blue;">Big Text</h1>
|
|
32
31
|
</body>
|
|
33
32
|
</html>
|
|
34
33
|
```
|
|
35
34
|
|
|
36
|
-
-
|
|
35
|
+
- Parses and matches CSS with components from Mozilla's Servo project
|
|
37
36
|
- Inlines CSS from `style` and `link` tags
|
|
38
37
|
- Removes `style` and `link` tags
|
|
39
38
|
- Resolves external stylesheets (including local files)
|
|
40
|
-
-
|
|
39
|
+
- Caches external stylesheets (opt-in)
|
|
41
40
|
- Can process multiple documents in parallel
|
|
42
41
|
- Works on Linux, Windows, and macOS
|
|
43
42
|
- Supports HTML5 & CSS3
|
|
44
|
-
- Tested on Ruby 3.2, 3.3,
|
|
43
|
+
- Tested on Ruby 3.2, 3.3, 3.4, and 4.0
|
|
45
44
|
|
|
46
45
|
## Playground
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
Try `css-inline` in the WebAssembly-powered [playground](https://css-inline.org/).
|
|
49
48
|
|
|
50
49
|
## Installation
|
|
51
50
|
|
|
52
|
-
Add this line to your application's `Gemfile`:
|
|
51
|
+
Add this line to your application's `Gemfile` and run `bundle install`:
|
|
53
52
|
|
|
54
|
-
```
|
|
53
|
+
```ruby
|
|
55
54
|
gem 'css_inline'
|
|
56
55
|
```
|
|
57
56
|
|
|
57
|
+
Or install it directly:
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
gem install css_inline
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
RubyGems ships precompiled native gems for Ruby 3.2 to 4.0 on Linux (x86_64, aarch64, glibc and musl), macOS (x86_64, arm64) and Windows (x64 UCRT).
|
|
64
|
+
On other platforms, `gem install` builds the extension from source and needs a Rust toolchain.
|
|
65
|
+
|
|
58
66
|
## Usage
|
|
59
67
|
|
|
60
|
-
|
|
68
|
+
Inline CSS in an HTML document:
|
|
61
69
|
|
|
62
70
|
```ruby
|
|
63
71
|
require 'css_inline'
|
|
@@ -66,39 +74,39 @@ html = "<html><head><style>h1 { color:blue; }</style></head><body><h1>Big Text</
|
|
|
66
74
|
inlined = CSSInline.inline(html)
|
|
67
75
|
|
|
68
76
|
puts inlined
|
|
69
|
-
#
|
|
77
|
+
# <html><head></head><body><h1 style="color: blue;">Big Text</h1></body></html>
|
|
70
78
|
```
|
|
71
79
|
|
|
72
|
-
|
|
80
|
+
`css-inline` adds missing `html`, `head` and `body` tags, so the output is a valid HTML document.
|
|
73
81
|
|
|
74
|
-
|
|
82
|
+
To inline CSS into an HTML fragment, use `inline_fragment`. It strips structural tags (`<html>`, `<head>`, `<body>`) from the output and keeps their contents. Use `CSSInline.inline` to keep the full document structure:
|
|
75
83
|
|
|
76
84
|
```ruby
|
|
77
85
|
require 'css_inline'
|
|
78
86
|
|
|
79
|
-
fragment =
|
|
80
|
-
<main>
|
|
81
|
-
<h1>Hello</h1>
|
|
82
|
-
<section>
|
|
83
|
-
<p>who am i</p>
|
|
84
|
-
</section>
|
|
85
|
-
</main>
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
css =
|
|
89
|
-
p {
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
h1 {
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
87
|
+
fragment = <<~HTML
|
|
88
|
+
<main>
|
|
89
|
+
<h1>Hello</h1>
|
|
90
|
+
<section>
|
|
91
|
+
<p>who am i</p>
|
|
92
|
+
</section>
|
|
93
|
+
</main>
|
|
94
|
+
HTML
|
|
95
|
+
|
|
96
|
+
css = <<~CSS
|
|
97
|
+
p {
|
|
98
|
+
color: red;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
h1 {
|
|
102
|
+
color: blue;
|
|
103
|
+
}
|
|
104
|
+
CSS
|
|
97
105
|
|
|
98
106
|
inlined = CSSInline.inline_fragment(fragment, css)
|
|
99
107
|
|
|
100
108
|
puts inlined
|
|
101
|
-
#
|
|
109
|
+
# Output:
|
|
102
110
|
# <main>
|
|
103
111
|
# <h1 style="color: blue;">Hello</h1>
|
|
104
112
|
# <section>
|
|
@@ -107,23 +115,27 @@ puts inlined
|
|
|
107
115
|
# </main>
|
|
108
116
|
```
|
|
109
117
|
|
|
110
|
-
|
|
111
|
-
This feature allows for concurrent processing of several inputs, significantly improving performance when dealing with a large number of documents.
|
|
118
|
+
To inline many documents in parallel, use `inline_many` and `inline_many_fragments`:
|
|
112
119
|
|
|
113
120
|
```ruby
|
|
114
121
|
require 'css_inline'
|
|
115
122
|
|
|
116
123
|
inlined = CSSInline.inline_many(["...", "..."])
|
|
124
|
+
inlined = CSSInline.inline_many_fragments(["<h1>...</h1>", "<p>...</p>"], ["h1 { color: blue; }", "p { color: red; }"])
|
|
117
125
|
```
|
|
118
126
|
|
|
119
|
-
|
|
120
|
-
|
|
127
|
+
`inline_many_fragments` pairs HTML and CSS by index.
|
|
128
|
+
|
|
129
|
+
**Warning**: pass arrays of equal length. If they differ, `inline_many_fragments` drops the extra items of the longer array without an error.
|
|
121
130
|
|
|
122
|
-
|
|
131
|
+
If one input fails, the whole call raises and returns no results.
|
|
132
|
+
|
|
133
|
+
Both functions process inputs on a Rust thread pool ([rayon](https://github.com/rayon-rs/rayon)), one thread per CPU core.
|
|
134
|
+
Ruby threads can't run this CPU-bound work in parallel because of the Global VM Lock, so `inline_many` gains over a Ruby loop only on a multicore machine.
|
|
123
135
|
|
|
124
136
|
## Configuration
|
|
125
137
|
|
|
126
|
-
|
|
138
|
+
Pass options as keyword arguments to `CSSInline::CSSInliner.new`:
|
|
127
139
|
|
|
128
140
|
```ruby
|
|
129
141
|
require 'css_inline'
|
|
@@ -132,21 +144,26 @@ inliner = CSSInline::CSSInliner.new(keep_style_tags: true)
|
|
|
132
144
|
inliner.inline("...")
|
|
133
145
|
```
|
|
134
146
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
- `
|
|
140
|
-
- `
|
|
141
|
-
- `
|
|
142
|
-
- `
|
|
143
|
-
- `
|
|
144
|
-
- `
|
|
145
|
-
- `
|
|
146
|
-
- `
|
|
147
|
-
- `
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
A `CSSInliner` instance has the same four methods as the module: `inline`, `inline_fragment`, `inline_many` and `inline_many_fragments`.
|
|
148
|
+
Reuse one instance to share its stylesheet cache across calls.
|
|
149
|
+
The module functions accept the same keyword arguments, for example `CSSInline.inline(html, keep_style_tags: true)`.
|
|
150
|
+
|
|
151
|
+
- `inline_style_tags`. Inline CSS from `style` tags. Default: `true`
|
|
152
|
+
- `keep_style_tags`. Keep `style` tags after inlining. Default: `false`
|
|
153
|
+
- `keep_link_tags`. Keep `link` tags after inlining. Default: `false`
|
|
154
|
+
- `keep_at_rules`. Keep at-rules (starting with `@`) after inlining. Default: `false`
|
|
155
|
+
- `minify_css`. Remove trailing semicolons and spaces between properties and values. Default: `false`
|
|
156
|
+
- `base_url`. Base URL for resolving relative URLs. Use the `file://` scheme to load stylesheets from the filesystem. Default: `nil`
|
|
157
|
+
- `load_remote_stylesheets`. Load stylesheets from `link` tags, over the network or from `file://` paths. Default: `true`
|
|
158
|
+
- `cache`. Cache for external stylesheets, for example `CSSInline::StylesheetCache.new(size: 5)`. Default: `nil`
|
|
159
|
+
- `extra_css`. Extra CSS to inline. Default: `nil`
|
|
160
|
+
- `preallocate_node_capacity`. **Advanced**. Number of HTML nodes to preallocate during parsing. Set it to your expected node count to avoid reallocations. Default: `32`
|
|
161
|
+
- `remove_inlined_selectors`. Remove inlined selectors from `<style>` blocks. Default: `false`
|
|
162
|
+
- `apply_width_attributes`. Add `width` HTML attributes from CSS `width` properties on `table`, `td`, `th` and `img`. Default: `false`
|
|
163
|
+
- `apply_height_attributes`. Add `height` HTML attributes from CSS `height` properties on `table`, `td`, `th` and `img`. Default: `false`
|
|
164
|
+
- `resolve_css_variables`. Replace `var()` references with the values of the custom properties they refer to and drop the `--*` declarations. Default: `false`
|
|
165
|
+
|
|
166
|
+
To skip CSS inlining for an HTML tag, add the `data-css-inline="ignore"` attribute to it:
|
|
150
167
|
|
|
151
168
|
```html
|
|
152
169
|
<head>
|
|
@@ -158,7 +175,7 @@ You can also skip CSS inlining for an HTML tag by adding the `data-css-inline="i
|
|
|
158
175
|
</body>
|
|
159
176
|
```
|
|
160
177
|
|
|
161
|
-
The
|
|
178
|
+
The same attribute on a `link` or `style` tag skips that stylesheet:
|
|
162
179
|
|
|
163
180
|
```html
|
|
164
181
|
<head>
|
|
@@ -170,9 +187,9 @@ The `data-css-inline="ignore"` attribute also allows you to skip `link` and `sty
|
|
|
170
187
|
</body>
|
|
171
188
|
```
|
|
172
189
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
190
|
+
To keep a `style` tag in the output, add the `data-css-inline="keep"` attribute.
|
|
191
|
+
Use it to keep `@media` queries for responsive emails in separate `style` tags.
|
|
192
|
+
`css-inline` keeps such tags even when `keep_style_tags` is `false`.
|
|
176
193
|
|
|
177
194
|
```html
|
|
178
195
|
<head>
|
|
@@ -184,14 +201,13 @@ Such tags will be kept in the resulting HTML even if the `keep_style_tags` optio
|
|
|
184
201
|
</body>
|
|
185
202
|
```
|
|
186
203
|
|
|
187
|
-
Another
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is explicitly set to `false`.
|
|
204
|
+
Another way is the `keep_at_rules` option. At-rules can't go into `style` attributes, so `css-inline` removes them by default.
|
|
205
|
+
With `keep_at_rules: true`, it inlines regular rules and keeps at-rules, such as `@media` queries, in `style` tags.
|
|
206
|
+
It keeps these tags even when `keep_style_tags` is `false`.
|
|
191
207
|
|
|
192
208
|
```html
|
|
193
209
|
<head>
|
|
194
|
-
<!-- With keep_at_rules
|
|
210
|
+
<!-- With keep_at_rules: true, "color:blue" will get inlined into <h1> but @media will be kept in <style> -->
|
|
195
211
|
<style>h1 { color: blue; } @media (max-width: 600px) { h1 { font-size: 18px; } }</style>
|
|
196
212
|
</head>
|
|
197
213
|
<body>
|
|
@@ -199,12 +215,11 @@ Such tags will be kept in the resulting HTML even if the `keep_style_tags` optio
|
|
|
199
215
|
</body>
|
|
200
216
|
```
|
|
201
217
|
|
|
202
|
-
|
|
203
|
-
and spaces between properties and values.
|
|
218
|
+
With `minify_css: true`, `css-inline` removes trailing semicolons and spaces between properties and values in inlined styles.
|
|
204
219
|
|
|
205
220
|
```html
|
|
206
221
|
<head>
|
|
207
|
-
<!-- With minify_css
|
|
222
|
+
<!-- With minify_css: true, the <h1> will have `style="color:blue;font-weight:bold"` -->
|
|
208
223
|
<style>h1 { color: blue; font-weight: bold; }</style>
|
|
209
224
|
</head>
|
|
210
225
|
<body>
|
|
@@ -212,17 +227,20 @@ and spaces between properties and values.
|
|
|
212
227
|
</body>
|
|
213
228
|
```
|
|
214
229
|
|
|
215
|
-
|
|
230
|
+
To load stylesheets from the filesystem, use the `file://` scheme.
|
|
231
|
+
`css-inline` treats a `file://` URL without a third slash, such as `file://styles/email/`, as a path relative to the current working directory.
|
|
232
|
+
Standard URL parsers read `styles` there as a host, so this form is specific to `css-inline`.
|
|
233
|
+
For an absolute path, use three slashes: `file:///path/to/styles/`.
|
|
216
234
|
|
|
217
235
|
```ruby
|
|
218
236
|
require 'css_inline'
|
|
219
237
|
|
|
220
|
-
# styles/email
|
|
238
|
+
# Loads stylesheets from ./styles/email/
|
|
221
239
|
inliner = CSSInline::CSSInliner.new(base_url: "file://styles/email/")
|
|
222
240
|
inliner.inline("...")
|
|
223
241
|
```
|
|
224
242
|
|
|
225
|
-
|
|
243
|
+
To avoid repeated network requests, cache external stylesheets:
|
|
226
244
|
|
|
227
245
|
```ruby
|
|
228
246
|
require 'css_inline'
|
|
@@ -233,32 +251,45 @@ inliner = CSSInline::CSSInliner.new(
|
|
|
233
251
|
inliner.inline("...")
|
|
234
252
|
```
|
|
235
253
|
|
|
236
|
-
|
|
254
|
+
The cache covers every `link` stylesheet, `file://` included. `size` is the number of stylesheets to keep (default: `8`). When the cache is full, it evicts the least recently used stylesheet.
|
|
255
|
+
Caching is off by default.
|
|
237
256
|
|
|
238
|
-
##
|
|
257
|
+
## Errors
|
|
239
258
|
|
|
240
|
-
|
|
241
|
-
Performance benchmarks show 50-100x faster execution than `roadie` and `premailer`.
|
|
259
|
+
All functions raise `ArgumentError` when they can't load a stylesheet (missing file, network error), can't parse one, or get an invalid `base_url`:
|
|
242
260
|
|
|
243
|
-
|
|
261
|
+
```ruby
|
|
262
|
+
require 'css_inline'
|
|
244
263
|
|
|
245
|
-
|
|
264
|
+
begin
|
|
265
|
+
CSSInline.inline('<link rel="stylesheet" href="missing.css"><h1>Hi</h1>')
|
|
266
|
+
rescue ArgumentError => e
|
|
267
|
+
puts e.message
|
|
268
|
+
# Missing stylesheet file: missing.css
|
|
269
|
+
end
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Performance
|
|
273
|
+
|
|
274
|
+
`css_inline` runs 8.1x to 354x faster than `roadie` and 57x to 123x faster than `premailer` on these documents:
|
|
275
|
+
|
|
276
|
+
| | Size | `css_inline 0.22.0` | `roadie 5.2.1` | `premailer 1.27.0` |
|
|
246
277
|
|-------------------|---------|---------------------|-------------------------|-------------------------|
|
|
247
|
-
| Basic usage | 230 B |
|
|
248
|
-
| Realistic email 1 | 8.58 KB |
|
|
249
|
-
| Realistic email 2 | 4.
|
|
250
|
-
| GitHub Page | 1.81 MB |
|
|
278
|
+
| Basic usage | 230 B | 5.84 µs | 168.88 µs (**28.92x**) | 331.07 µs (**56.69x**) |
|
|
279
|
+
| Realistic email 1 | 8.58 KB | 87.66 µs | 713.78 µs (**8.14x**) | 6.95 ms (**79.28x**) |
|
|
280
|
+
| Realistic email 2 | 4.30 KB | 50.45 µs | 1.98 ms (**39.25x**) | ERROR |
|
|
281
|
+
| GitHub Page | 1.81 MB | 19.01 ms | 6.73 s (**354.02x**) | 2.34 s (**123.09x**) |
|
|
251
282
|
|
|
252
|
-
|
|
253
|
-
The results displayed above were measured using stable `rustc 1.91` on Ruby `3.4.7`.
|
|
283
|
+
`premailer` fails on "Realistic email 2" with `ArgumentError: Cannot parse 0 calc((100% - 500px) / 2)`.
|
|
254
284
|
|
|
255
|
-
|
|
285
|
+
Inputs come from [`benchmarks/benchmarks.json`](https://github.com/Stranger6667/css-inline/blob/master/benchmarks/benchmarks.json): Basic usage is `simple`, Realistic email 1 and 2 are `big_email_1` and `big_email_2`, GitHub Page is `big_page`.
|
|
286
|
+
The benchmark code is in [`test/bench.rb`](https://github.com/Stranger6667/css-inline/blob/master/crates/css-inline-ruby/test/bench.rb) and uses [`benchmark-ips`](https://github.com/evanphx/benchmark-ips) (5 s per case; `roadie` completes one run on the GitHub page in that time).
|
|
287
|
+
We measured these results with stable `rustc 1.99` on Ruby `3.4.8`, Ryzen 9 9950X.
|
|
256
288
|
|
|
257
|
-
|
|
289
|
+
## Further reading
|
|
258
290
|
|
|
259
|
-
- [Rust crate](https://dygalo.dev/blog/rust-for-a-pythonista-2/)
|
|
260
|
-
- [Python bindings](https://dygalo.dev/blog/rust-for-a-pythonista-3/)
|
|
291
|
+
- [How the Rust crate works](https://dygalo.dev/blog/rust-for-a-pythonista-2/)
|
|
261
292
|
|
|
262
293
|
## License
|
|
263
294
|
|
|
264
|
-
|
|
295
|
+
[MIT license](https://opensource.org/licenses/MIT).
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|