Skip to content

Commit 1afd436

Browse files
committed
feat: Non-blocking stylesheet resolving
1 parent a52171c commit 1afd436

25 files changed

+705
-510
lines changed

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Added
66

77
- A way to customize resolving remote stylesheets.
8+
- Non-blocking stylesheet resolving by default.
89

910
### Changed
1011

Diff for: README.md

+36-6
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,21 @@ const HTML: &str = r#"<html>
7070
</body>
7171
</html>"#;
7272

73+
#[tokio::main]
74+
async fn main() -> css_inline::Result<()> {
75+
let inlined = css_inline::inline(HTML).await?;
76+
// Do something with inlined HTML, e.g. send an email
77+
Ok(())
78+
}
79+
```
80+
81+
There is also a "blocking" API for inlining:
82+
83+
```rust
84+
const HTML: &str = "...";
85+
7386
fn main() -> css_inline::Result<()> {
74-
let inlined = css_inline::inline(HTML)?;
87+
let inlined = css_inline::blocking::inline(HTML)?;
7588
// Do something with inlined HTML, e.g. send an email
7689
Ok(())
7790
}
@@ -84,11 +97,12 @@ fn main() -> css_inline::Result<()> {
8497
```rust
8598
const HTML: &str = "...";
8699

87-
fn main() -> css_inline::Result<()> {
100+
#[tokio::main]
101+
async fn main() -> css_inline::Result<()> {
88102
let inliner = css_inline::CSSInliner::options()
89103
.load_remote_stylesheets(false)
90104
.build();
91-
let inlined = inliner.inline(HTML)?;
105+
let inlined = inliner.inline(HTML).await?;
92106
// Do something with inlined HTML, e.g. send an email
93107
Ok(())
94108
}
@@ -131,12 +145,28 @@ If you'd like to load stylesheets from your filesystem, use the `file://` scheme
131145
```rust
132146
const HTML: &str = "...";
133147

134-
fn main() -> css_inline::Result<()> {
148+
#[tokio::main]
149+
async fn main() -> css_inline::Result<()> {
135150
let base_url = css_inline::Url::parse("file://styles/email/").expect("Invalid URL");
136151
let inliner = css_inline::CSSInliner::options()
137152
.base_url(Some(base_url))
138153
.build();
139-
let inlined = inliner.inline(HTML);
154+
let inlined = inliner.inline(HTML).await?;
155+
// Do something with inlined HTML, e.g. send an email
156+
Ok(())
157+
}
158+
```
159+
160+
The blocking version is available as well:
161+
162+
```rust
163+
const HTML: &str = "...";
164+
165+
fn main() -> css_inline::Result<()> {
166+
let inliner = css_inline::blocking::CSSInliner::options()
167+
.load_remote_stylesheets(false)
168+
.build();
169+
let inlined = inliner.inline(HTML)?;
140170
// Do something with inlined HTML, e.g. send an email
141171
Ok(())
142172
}
@@ -149,7 +179,7 @@ For resolving remote stylesheets it is possible to implement a custom resolver:
149179
pub struct CustomStylesheetResolver;
150180

151181
impl css_inline::StylesheetResolver for CustomStylesheetResolver {
152-
fn retrieve(&self, location: &str) -> css_inline::Result<String> {
182+
fn retrieve_blocking(&self, location: &str) -> css_inline::Result<String> {
153183
Err(self.unsupported("External stylesheets are not supported"))
154184
}
155185
}

Diff for: bindings/c/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ cbindgen = "0.26"
1818
path = "../../css-inline"
1919
version = "*"
2020
default-features = false
21-
features = ["http", "file"]
21+
features = ["http-blocking", "file"]

Diff for: bindings/c/src/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use css_inline::{CSSInliner, DefaultStylesheetResolver, InlineError, InlineOptions, Url};
1+
use css_inline::{
2+
blocking::{CSSInliner, InlineOptions},
3+
DefaultStylesheetResolver, InlineError, Url,
4+
};
25
use libc::{c_char, size_t};
36
use std::{borrow::Cow, cmp, ffi::CStr, io::Write, ptr, sync::Arc};
47

Diff for: bindings/javascript/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ serde = { version = "1", features = ["derive"], default-features = false }
3232
path = "../../css-inline"
3333
version = "*"
3434
default-features = false
35-
features = ["http", "file"]
35+
features = ["http-blocking", "file"]
3636

3737
[target.'cfg(target_arch = "wasm32")'.dependencies.css-inline]
3838
path = "../../css-inline"

Diff for: bindings/javascript/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,6 @@ export function inline(html: string, options?: InlineOptions): string;
6060
export function version(): string;"#;
6161

6262
fn inline_inner(html: String, options: Options) -> std::result::Result<String, errors::JsError> {
63-
let inliner = css_inline::CSSInliner::new(options.try_into()?);
63+
let inliner = css_inline::blocking::CSSInliner::new(options.try_into()?);
6464
Ok(inliner.inline(&html).map_err(errors::InlineError)?)
6565
}

Diff for: bindings/javascript/src/options.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ pub struct Options {
4242
pub preallocate_node_capacity: Option<u32>,
4343
}
4444

45-
impl TryFrom<Options> for css_inline::InlineOptions<'_> {
45+
impl TryFrom<Options> for css_inline::blocking::InlineOptions<'_> {
4646
type Error = JsError;
4747

4848
fn try_from(value: Options) -> std::result::Result<Self, Self::Error> {
49-
Ok(css_inline::InlineOptions {
49+
Ok(css_inline::blocking::InlineOptions {
5050
inline_style_tags: value.inline_style_tags.unwrap_or(true),
5151
keep_style_tags: value.keep_style_tags.unwrap_or(false),
5252
keep_link_tags: value.keep_link_tags.unwrap_or(false),
@@ -75,7 +75,7 @@ impl TryFrom<Options> for css_inline::InlineOptions<'_> {
7575
pub struct UnsupportedResolver;
7676

7777
impl css_inline::StylesheetResolver for UnsupportedResolver {
78-
fn retrieve(&self, location: &str) -> css_inline::Result<String> {
78+
fn retrieve_blocking(&self, location: &str) -> css_inline::Result<String> {
7979
let message = if location.starts_with("https")
8080
| location.starts_with("http")
8181
{

Diff for: bindings/javascript/wasm/index.js

+15-15
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ heap.push(void 0, null, true, false);
3333
function getObject(idx) {
3434
return heap[idx];
3535
}
36+
var heap_next = heap.length;
37+
function dropObject(idx) {
38+
if (idx < 132)
39+
return;
40+
heap[idx] = heap_next;
41+
heap_next = idx;
42+
}
43+
function takeObject(idx) {
44+
const ret = getObject(idx);
45+
dropObject(idx);
46+
return ret;
47+
}
3648
var WASM_VECTOR_LEN = 0;
3749
var cachedUint8Memory0 = null;
3850
function getUint8Memory0() {
@@ -104,7 +116,6 @@ function getStringFromWasm0(ptr, len) {
104116
ptr = ptr >>> 0;
105117
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
106118
}
107-
var heap_next = heap.length;
108119
function addHeapObject(obj) {
109120
if (heap_next === heap.length)
110121
heap.push(heap.length + 1);
@@ -113,17 +124,6 @@ function addHeapObject(obj) {
113124
heap[idx] = obj;
114125
return idx;
115126
}
116-
function dropObject(idx) {
117-
if (idx < 132)
118-
return;
119-
heap[idx] = heap_next;
120-
heap_next = idx;
121-
}
122-
function takeObject(idx) {
123-
const ret = getObject(idx);
124-
dropObject(idx);
125-
return ret;
126-
}
127127
var cachedFloat64Memory0 = null;
128128
function getFloat64Memory0() {
129129
if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) {
@@ -261,6 +261,9 @@ function __wbg_get_imports() {
261261
const ret = getObject(arg0) === void 0;
262262
return ret;
263263
};
264+
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
265+
takeObject(arg0);
266+
};
264267
imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
265268
const obj = getObject(arg1);
266269
const ret = typeof obj === "string" ? obj : void 0;
@@ -303,9 +306,6 @@ function __wbg_get_imports() {
303306
const ret = +getObject(arg0);
304307
return ret;
305308
};
306-
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
307-
takeObject(arg0);
308-
};
309309
imports.wbg.__wbg_length_1d25fa9e4ac21ce7 = function(arg0) {
310310
const ret = getObject(arg0).length;
311311
return ret;

Diff for: bindings/javascript/wasm/index.min.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)