diff --git a/CHANGELOG.md b/CHANGELOG.md index 350f5178..064a9c78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Added + +- `keep_at_rules` option [#265](https://github.com/Stranger6667/css-inline/issues/265) + ## [0.16.0] - 2025-07-16 ### Added diff --git a/README.md b/README.md index 309768dc..a37eafff 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,7 @@ fn main() -> css_inline::Result<()> { - `inline_style_tags`. Specifies whether to inline CSS from "style" tags. Default: `true` - `keep_style_tags`. Specifies whether to keep "style" tags after inlining. Default: `false` - `keep_link_tags`. Specifies whether to keep "link" tags after inlining. Default: `false` +- `keep_at_rules`. Specifies whether to keep "at-rules" (starting with `@`) after inlining. Default: `false` - `base_url`. The base URL used to resolve relative URLs. If you'd like to load stylesheets from your filesystem, use the `file://` scheme. Default: `None` - `load_remote_stylesheets`. Specifies whether remote stylesheets should be loaded. Default: `true` - `cache`. Specifies cache for external stylesheets. Default: `None` @@ -157,7 +158,8 @@ The `data-css-inline="ignore"` attribute also allows you to skip `link` and `sty ``` Alternatively, you may keep `style` from being removed by using the `data-css-inline="keep"` attribute. -This is useful if you want to keep `@media` queries for responsive emails in separate `style` tags: +This is useful if you want to keep `@media` queries for responsive emails in separate `style` tags. +Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is set to `false`. ```html @@ -169,7 +171,20 @@ This is useful if you want to keep `@media` queries for responsive emails in sep ``` -Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is set to `false`. +Another possibility is to set `keep_at_rules` option to `true`. At-rules cannot be inlined into HTML therefore they +get removed by default. This is useful if you want to keep at-rules, e.g. `@media` queries for responsive emails in +separate `style` tags but inline any styles which can be inlined. +Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is explicitly set to `false`. + +```html + + + + + +

Big Text

+ +``` If you'd like to load stylesheets from your filesystem, use the `file://` scheme: diff --git a/bindings/c/CHANGELOG.md b/bindings/c/CHANGELOG.md index 8f6095bf..ce2e730d 100644 --- a/bindings/c/CHANGELOG.md +++ b/bindings/c/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Added + +- `keep_at_rules` option [#265](https://github.com/Stranger6667/css-inline/issues/265) + ## [0.16.0] - 2025-07-16 ### Changed diff --git a/bindings/c/README.md b/bindings/c/README.md index 8af5497d..924deb35 100644 --- a/bindings/c/README.md +++ b/bindings/c/README.md @@ -153,6 +153,7 @@ Possible configurations: - `inline_style_tags`. Specifies whether to inline CSS from "style" tags. Default: `true` - `keep_style_tags`. Specifies whether to keep "style" tags after inlining. Default: `false` - `keep_link_tags`. Specifies whether to keep "link" tags after inlining. Default: `false` +- `keep_at_rules`. Specifies whether to keep "at-rules" (starting with `@`) after inlining. Default: `false` - `base_url`. The base URL used to resolve relative URLs. If you'd like to load stylesheets from your filesystem, use the `file://` scheme. Default: `NULL` - `load_remote_stylesheets`. Specifies whether remote stylesheets should be loaded. Default: `true` - `cache`. Specifies caching options for external stylesheets. Default: `NULL` @@ -186,7 +187,8 @@ The `data-css-inline="ignore"` attribute also allows you to skip `link` and `sty ``` Alternatively, you may keep `style` from being removed by using the `data-css-inline="keep"` attribute. -This is useful if you want to keep `@media` queries for responsive emails in separate `style` tags: +This is useful if you want to keep `@media` queries for responsive emails in separate `style` tags. +Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is set to `false`. ```html @@ -198,7 +200,20 @@ This is useful if you want to keep `@media` queries for responsive emails in sep ``` -Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is set to `false`. +Another possibility is to set `keep_at_rules` option to `true`. At-rules cannot be inlined into HTML therefore they +get removed by default. This is useful if you want to keep at-rules, e.g. `@media` queries for responsive emails in +separate `style` tags but inline any styles which can be inlined. +Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is explicitly set to `false`. + +```html + + + + + +

Big Text

+ +``` You can also cache external stylesheets to avoid excessive network requests: diff --git a/bindings/c/src/lib.rs b/bindings/c/src/lib.rs index e13622df..7f48a1dc 100644 --- a/bindings/c/src/lib.rs +++ b/bindings/c/src/lib.rs @@ -82,6 +82,8 @@ pub struct CssInlinerOptions { pub keep_style_tags: bool, /// Keep "link" tags after inlining. pub keep_link_tags: bool, + /// Keep "at-rules" after inlining. + pub keep_at_rules: bool, /// Whether remote stylesheets should be loaded or not. pub load_remote_stylesheets: bool, /// Cache for external stylesheets. @@ -183,6 +185,7 @@ pub extern "C" fn css_inliner_default_options() -> CssInlinerOptions { inline_style_tags: true, keep_style_tags: false, keep_link_tags: false, + keep_at_rules: false, base_url: ptr::null(), load_remote_stylesheets: true, cache: std::ptr::null(), @@ -225,6 +228,7 @@ impl TryFrom<&CssInlinerOptions> for InlineOptions<'_> { inline_style_tags: value.inline_style_tags, keep_style_tags: value.keep_style_tags, keep_link_tags: value.keep_link_tags, + keep_at_rules: value.keep_at_rules, base_url: match base_url { Some(url) => Some(Url::parse(url).map_err(|_| InlineOptionsError::InvalidUrl)?), None => None, diff --git a/bindings/java/CHANGELOG.md b/bindings/java/CHANGELOG.md index db1828e5..c264a7fc 100644 --- a/bindings/java/CHANGELOG.md +++ b/bindings/java/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Added + +- `keep_at_rules` option [#265](https://github.com/Stranger6667/css-inline/issues/265) + ## [0.16.0] - 2025-07-16 ### Changed diff --git a/bindings/java/README.md b/bindings/java/README.md index bebece4f..a0accd70 100644 --- a/bindings/java/README.md +++ b/bindings/java/README.md @@ -146,6 +146,7 @@ public class ConfigExample { - **`setInlineStyleTags(boolean)`** - Inline CSS from ` + + +

Big Text

+ +``` ## Performance diff --git a/bindings/java/src/main/java/org/cssinline/CssInlineConfig.java b/bindings/java/src/main/java/org/cssinline/CssInlineConfig.java index 557e2b15..043da02a 100644 --- a/bindings/java/src/main/java/org/cssinline/CssInlineConfig.java +++ b/bindings/java/src/main/java/org/cssinline/CssInlineConfig.java @@ -11,6 +11,9 @@ public class CssInlineConfig { /** Keep "link" tags after inlining. */ public final boolean keepLinkTags; + /** Keep "at-rules" after inlining. */ + public final boolean keepAtRules; + /** Whether remote stylesheets should be loaded or not. */ public final boolean loadRemoteStylesheets; @@ -27,11 +30,12 @@ public class CssInlineConfig { public final int preallocateNodeCapacity; private CssInlineConfig(boolean inlineStyleTags, boolean keepStyleTags, boolean keepLinkTags, - boolean loadRemoteStylesheets, String baseUrl, String extraCss, int cacheSize, + boolean keepAtRules, boolean loadRemoteStylesheets, String baseUrl, String extraCss, int cacheSize, int preallocateNodeCapacity) { this.inlineStyleTags = inlineStyleTags; this.keepStyleTags = keepStyleTags; this.keepLinkTags = keepLinkTags; + this.keepAtRules = keepAtRules; this.loadRemoteStylesheets = loadRemoteStylesheets; this.baseUrl = baseUrl; this.extraCss = extraCss; @@ -46,6 +50,7 @@ public static class Builder { private boolean inlineStyleTags = true; private boolean keepStyleTags = false; private boolean keepLinkTags = false; + private boolean keepAtRules = false; private boolean loadRemoteStylesheets = true; private String baseUrl = null; private String extraCss = null; @@ -94,6 +99,17 @@ public Builder setKeepLinkTags(boolean b) { return this; } + /** + * Keep "at-rules" after inlining. + * + * @param b true to preserve at-rules, false to remove them + * @return this builder instance for method chaining + */ + public Builder setKeepAtRules(boolean b) { + this.keepAtRules = b; + return this; + } + /** * Whether remote stylesheets should be loaded or not. * @@ -168,7 +184,7 @@ public Builder setPreallocateNodeCapacity(int cap) { * @return a new immutable configuration instance */ public CssInlineConfig build() { - return new CssInlineConfig(inlineStyleTags, keepStyleTags, keepLinkTags, loadRemoteStylesheets, baseUrl, + return new CssInlineConfig(inlineStyleTags, keepStyleTags, keepLinkTags, keepAtRules, loadRemoteStylesheets, baseUrl, extraCss, cacheSize, preallocateNodeCapacity); } } diff --git a/bindings/java/src/main/rust/lib.rs b/bindings/java/src/main/rust/lib.rs index 3a1b3615..6be63a69 100644 --- a/bindings/java/src/main/rust/lib.rs +++ b/bindings/java/src/main/rust/lib.rs @@ -74,6 +74,7 @@ fn build_inliner( let inline_style_tags = env.get_bool_field(&cfg, "inlineStyleTags")?; let keep_style_tags = env.get_bool_field(&cfg, "keepStyleTags")?; let keep_link_tags = env.get_bool_field(&cfg, "keepLinkTags")?; + let keep_at_rules = env.get_bool_field(&cfg, "keepAtRules")?; let load_remote_stylesheets = env.get_bool_field(&cfg, "loadRemoteStylesheets")?; let cache_size = env.get_int_field(&cfg, "cacheSize")?; let preallocate_node_capacity = env.get_int_field(&cfg, "preallocateNodeCapacity")?; @@ -84,6 +85,7 @@ fn build_inliner( .inline_style_tags(inline_style_tags) .keep_style_tags(keep_style_tags) .keep_link_tags(keep_link_tags) + .keep_at_rules(keep_at_rules) .load_remote_stylesheets(load_remote_stylesheets) .extra_css(extra_css.map(Cow::Owned)) .preallocate_node_capacity(preallocate_node_capacity as usize); diff --git a/bindings/javascript/CHANGELOG.md b/bindings/javascript/CHANGELOG.md index e001fef2..14b5da33 100644 --- a/bindings/javascript/CHANGELOG.md +++ b/bindings/javascript/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Added + +- `keep_at_rules` option [#265](https://github.com/Stranger6667/css-inline/issues/265) + ## [0.16.0] - 2025-07-16 ### Changed diff --git a/bindings/javascript/README.md b/bindings/javascript/README.md index b7501b01..23aeccd6 100644 --- a/bindings/javascript/README.md +++ b/bindings/javascript/README.md @@ -116,6 +116,7 @@ var inlined = inlineFragment( - `inlineStyleTags`. Specifies whether to inline CSS from "style" tags. Default: `true` - `keepStyleTags`. Specifies whether to keep "style" tags after inlining. Default: `false` - `keepLinkTags`. Specifies whether to keep "link" tags after inlining. Default: `false` +- `keep_at_rules`. Specifies whether to keep "at-rules" (starting with `@`) after inlining. Default: `false` - `baseUrl`. The base URL used to resolve relative URLs. If you'd like to load stylesheets from your filesystem, use the `file://` scheme. Default: `null` - `loadRemoteStylesheets`. Specifies whether remote stylesheets should be loaded. Default: `true` - `cache`. Specifies caching options for external stylesheets (for example, `{size: 5}`). Default: `null` @@ -148,7 +149,8 @@ The `data-css-inline="ignore"` attribute also allows you to skip `link` and `sty ``` Alternatively, you may keep `style` from being removed by using the `data-css-inline="keep"` attribute. -This is useful if you want to keep `@media` queries for responsive emails in separate `style` tags: +This is useful if you want to keep `@media` queries for responsive emails in separate `style` tags. +Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is set to `false`. ```html @@ -160,7 +162,20 @@ This is useful if you want to keep `@media` queries for responsive emails in sep ``` -Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is set to `false`. +Another possibility is to set `keep_at_rules` option to `true`. At-rules cannot be inlined into HTML therefore they +get removed by default. This is useful if you want to keep at-rules, e.g. `@media` queries for responsive emails in +separate `style` tags but inline any styles which can be inlined. +Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is explicitly set to `false`. + +```html + + + + + +

Big Text

+ +``` You can also cache external stylesheets to avoid excessive network requests: diff --git a/bindings/javascript/src/lib.rs b/bindings/javascript/src/lib.rs index 8c1b03e2..abea8da2 100644 --- a/bindings/javascript/src/lib.rs +++ b/bindings/javascript/src/lib.rs @@ -74,6 +74,7 @@ const INLINE: &'static str = r#"export interface InlineOptions { inlineStyleTags?: boolean, keepStyleTags?: boolean, keepLinkTags?: boolean, + keepAtRules?: boolean, baseUrl?: string, loadRemoteStylesheets?: boolean, extraCss?: string, diff --git a/bindings/javascript/src/options.rs b/bindings/javascript/src/options.rs index c3c7f064..37cd60c7 100644 --- a/bindings/javascript/src/options.rs +++ b/bindings/javascript/src/options.rs @@ -40,6 +40,8 @@ pub struct Options { pub keep_style_tags: Option, /// Keep "link" tags after inlining. pub keep_link_tags: Option, + /// Keep "at-rules" after inlining. + pub keep_at_rules: Option, /// Used for loading external stylesheets via relative URLs. pub base_url: Option, /// Whether remote stylesheets should be loaded or not. @@ -62,6 +64,7 @@ impl TryFrom for css_inline::InlineOptions<'_> { inline_style_tags: value.inline_style_tags.unwrap_or(true), keep_style_tags: value.keep_style_tags.unwrap_or(false), keep_link_tags: value.keep_link_tags.unwrap_or(false), + keep_at_rules: value.keep_at_rules.unwrap_or(false), base_url: parse_url(value.base_url)?, load_remote_stylesheets: value.load_remote_stylesheets.unwrap_or(true), extra_css: value.extra_css.map(Cow::Owned), diff --git a/bindings/javascript/wasm/index.d.ts b/bindings/javascript/wasm/index.d.ts index ba0b3540..82705066 100644 --- a/bindings/javascript/wasm/index.d.ts +++ b/bindings/javascript/wasm/index.d.ts @@ -1,4 +1,4 @@ -// Generated by dts-bundle-generator v9.1.0 +// Generated by dts-bundle-generator v9.5.1 /* tslint:disable */ /* eslint-disable */ @@ -6,6 +6,7 @@ export interface InlineOptions { inlineStyleTags?: boolean; keepStyleTags?: boolean; keepLinkTags?: boolean; + keepAtRules?: boolean; baseUrl?: string; loadRemoteStylesheets?: boolean; extraCss?: string; diff --git a/bindings/javascript/wasm/index.js b/bindings/javascript/wasm/index.js index e6861221..256e609c 100644 --- a/bindings/javascript/wasm/index.js +++ b/bindings/javascript/wasm/index.js @@ -120,8 +120,7 @@ function passStringToWasm0(arg, malloc, realloc) { let offset = 0; for (; offset < len; offset++) { const code = arg.charCodeAt(offset); - if (code > 127) - break; + if (code > 127) break; mem[ptr + offset] = code; } if (offset !== len) { @@ -373,8 +372,7 @@ function __wbg_finalize_init(instance, module2) { return wasm; } async function __wbg_init(module_or_path) { - if (wasm !== void 0) - return wasm; + if (wasm !== void 0) return wasm; if (typeof module_or_path !== "undefined") { if (Object.getPrototypeOf(module_or_path) === Object.prototype) { ({ module_or_path } = module_or_path); diff --git a/bindings/javascript/wasm/index.mjs b/bindings/javascript/wasm/index.mjs index 7c1ac156..0bdc2625 100644 --- a/bindings/javascript/wasm/index.mjs +++ b/bindings/javascript/wasm/index.mjs @@ -91,8 +91,7 @@ function passStringToWasm0(arg, malloc, realloc) { let offset = 0; for (; offset < len; offset++) { const code = arg.charCodeAt(offset); - if (code > 127) - break; + if (code > 127) break; mem[ptr + offset] = code; } if (offset !== len) { @@ -344,8 +343,7 @@ function __wbg_finalize_init(instance, module) { return wasm; } async function __wbg_init(module_or_path) { - if (wasm !== void 0) - return wasm; + if (wasm !== void 0) return wasm; if (typeof module_or_path !== "undefined") { if (Object.getPrototypeOf(module_or_path) === Object.prototype) { ({ module_or_path } = module_or_path); diff --git a/bindings/javascript/wasm/index_bg.wasm b/bindings/javascript/wasm/index_bg.wasm index 8d6a0b64..4a37decf 100644 Binary files a/bindings/javascript/wasm/index_bg.wasm and b/bindings/javascript/wasm/index_bg.wasm differ diff --git a/bindings/python/CHANGELOG.md b/bindings/python/CHANGELOG.md index 9fa53fb9..cda8ec37 100644 --- a/bindings/python/CHANGELOG.md +++ b/bindings/python/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Added + +- `keep_at_rules` option [#265](https://github.com/Stranger6667/css-inline/issues/265) + ## [0.16.0] - 2025-07-16 ### Changed diff --git a/bindings/python/README.md b/bindings/python/README.md index 4761e49f..2e8d7803 100644 --- a/bindings/python/README.md +++ b/bindings/python/README.md @@ -148,6 +148,7 @@ inliner.inline("...") - `inline_style_tags`. Specifies whether to inline CSS from "style" tags. Default: `True` - `keep_style_tags`. Specifies whether to keep "style" tags after inlining. Default: `False` - `keep_link_tags`. Specifies whether to keep "link" tags after inlining. Default: `False` +- `keep_at_rules`. Specifies whether to keep "at-rules" (starting with `@`) after inlining. Default: `False` - `base_url`. The base URL used to resolve relative URLs. If you'd like to load stylesheets from your filesystem, use the `file://` scheme. Default: `None` - `load_remote_stylesheets`. Specifies whether remote stylesheets should be loaded. Default: `True` - `cache`. Specifies caching options for external stylesheets (for example, `StylesheetCache(size=5)`). Default: `None` @@ -179,7 +180,8 @@ The `data-css-inline="ignore"` attribute also allows you to skip `link` and `sty ``` Alternatively, you may keep `style` from being removed by using the `data-css-inline="keep"` attribute. -This is useful if you want to keep `@media` queries for responsive emails in separate `style` tags: +This is useful if you want to keep `@media` queries for responsive emails in separate `style` tags. +Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is set to `false`. ```html @@ -191,7 +193,20 @@ This is useful if you want to keep `@media` queries for responsive emails in sep ``` -Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is set to `false`. +Another possibility is to set `keep_at_rules` option to `true`. At-rules cannot be inlined into HTML therefore they +get removed by default. This is useful if you want to keep at-rules, e.g. `@media` queries for responsive emails in +separate `style` tags but inline any styles which can be inlined. +Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is explicitly set to `false`. + +```html + + + + + +

Big Text

+ +``` If you'd like to load stylesheets from your filesystem, use the `file://` scheme: diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index 6f09b4e2..f958411d 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -99,7 +99,7 @@ impl StylesheetCache { } } -/// CSSInliner(inline_style_tags=True, keep_style_tags=False, keep_link_tags=False, base_url=None, load_remote_stylesheets=True, cache=None, extra_css=None, preallocate_node_capacity=32) +/// CSSInliner(inline_style_tags=True, keep_style_tags=False, keep_link_tags=False, keep_at_rules=False, base_url=None, load_remote_stylesheets=True, cache=None, extra_css=None, preallocate_node_capacity=32) /// /// Customizable CSS inliner. #[pyclass] @@ -108,11 +108,12 @@ struct CSSInliner { } macro_rules! inliner { - ($inline_style_tags:expr, $keep_style_tags:expr, $keep_link_tags:expr, $base_url:expr, $load_remote_stylesheets:expr, $cache:expr, $extra_css:expr, $preallocate_node_capacity:expr) => {{ + ($inline_style_tags:expr, $keep_style_tags:expr, $keep_link_tags:expr, $keep_at_rules:expr, $base_url:expr, $load_remote_stylesheets:expr, $cache:expr, $extra_css:expr, $preallocate_node_capacity:expr) => {{ let options = rust_inline::InlineOptions { inline_style_tags: $inline_style_tags.unwrap_or(true), keep_style_tags: $keep_style_tags.unwrap_or(false), keep_link_tags: $keep_link_tags.unwrap_or(false), + keep_at_rules: $keep_at_rules.unwrap_or(false), base_url: $crate::parse_url($base_url)?, load_remote_stylesheets: $load_remote_stylesheets.unwrap_or(true), cache: { @@ -136,13 +137,14 @@ macro_rules! inliner { impl CSSInliner { #[new] #[pyo3( - signature = (inline_style_tags=true, keep_style_tags=false, keep_link_tags=false, base_url=None, load_remote_stylesheets=true, cache=None, extra_css=None, preallocate_node_capacity=32) + signature = (inline_style_tags=true, keep_style_tags=false, keep_link_tags=false, keep_at_rules=false, base_url=None, load_remote_stylesheets=true, cache=None, extra_css=None, preallocate_node_capacity=32) )] #[allow(clippy::too_many_arguments)] fn new( inline_style_tags: Option, keep_style_tags: Option, keep_link_tags: Option, + keep_at_rules: Option, base_url: Option, load_remote_stylesheets: Option, cache: Option, @@ -153,6 +155,7 @@ impl CSSInliner { inline_style_tags, keep_style_tags, keep_link_tags, + keep_at_rules, base_url, load_remote_stylesheets, cache, @@ -202,12 +205,12 @@ impl CSSInliner { } } -/// inline(html, inline_style_tags=True, keep_style_tags=False, keep_link_tags=False, base_url=None, load_remote_stylesheets=True, cache=None, extra_css=None, preallocate_node_capacity=32) +/// inline(html, inline_style_tags=True, keep_style_tags=False, keep_link_tags=False, keep_at_rules=False, base_url=None, load_remote_stylesheets=True, cache=None, extra_css=None, preallocate_node_capacity=32) /// /// Inline CSS in the given HTML document #[pyfunction] #[pyo3( - signature = (html, inline_style_tags=true, keep_style_tags=false, keep_link_tags=false, base_url=None, load_remote_stylesheets=true, cache=None, extra_css=None, preallocate_node_capacity=32) + signature = (html, inline_style_tags=true, keep_style_tags=false, keep_link_tags=false, keep_at_rules=false, base_url=None, load_remote_stylesheets=true, cache=None, extra_css=None, preallocate_node_capacity=32) )] #[allow(clippy::too_many_arguments)] fn inline( @@ -215,6 +218,7 @@ fn inline( inline_style_tags: Option, keep_style_tags: Option, keep_link_tags: Option, + keep_at_rules: Option, base_url: Option, load_remote_stylesheets: Option, cache: Option, @@ -225,6 +229,7 @@ fn inline( inline_style_tags, keep_style_tags, keep_link_tags, + keep_at_rules, base_url, load_remote_stylesheets, cache, @@ -234,12 +239,12 @@ fn inline( Ok(inliner.inline(html).map_err(InlineErrorWrapper)?) } -/// inline_fragment(html, css, inline_style_tags=True, keep_style_tags=False, keep_link_tags=False, base_url=None, load_remote_stylesheets=True, cache=None, extra_css=None, preallocate_node_capacity=32) +/// inline_fragment(html, css, inline_style_tags=True, keep_style_tags=False, keep_link_tags=False, keep_at_rules=False, base_url=None, load_remote_stylesheets=True, cache=None, extra_css=None, preallocate_node_capacity=32) /// /// Inline CSS in the given HTML fragment #[pyfunction] #[pyo3( - signature = (html, css, inline_style_tags=true, keep_style_tags=false, keep_link_tags=false, base_url=None, load_remote_stylesheets=true, cache=None, extra_css=None, preallocate_node_capacity=32) + signature = (html, css, inline_style_tags=true, keep_style_tags=false, keep_link_tags=false, keep_at_rules=false, base_url=None, load_remote_stylesheets=true, cache=None, extra_css=None, preallocate_node_capacity=32) )] #[allow(clippy::too_many_arguments)] fn inline_fragment( @@ -248,6 +253,7 @@ fn inline_fragment( inline_style_tags: Option, keep_style_tags: Option, keep_link_tags: Option, + keep_at_rules: Option, base_url: Option, load_remote_stylesheets: Option, cache: Option, @@ -258,6 +264,7 @@ fn inline_fragment( inline_style_tags, keep_style_tags, keep_link_tags, + keep_at_rules, base_url, load_remote_stylesheets, cache, @@ -269,12 +276,12 @@ fn inline_fragment( .map_err(InlineErrorWrapper)?) } -/// inline_many(htmls, inline_style_tags=True, keep_style_tags=False, keep_link_tags=False, base_url=None, load_remote_stylesheets=True, cache=None, extra_css=None, preallocate_node_capacity=32) +/// inline_many(htmls, inline_style_tags=True, keep_style_tags=False, keep_link_tags=False, keep_at_rules=False, base_url=None, load_remote_stylesheets=True, cache=None, extra_css=None, preallocate_node_capacity=32) /// /// Inline CSS in multiple HTML documents #[pyfunction] #[pyo3( - signature = (htmls, inline_style_tags=true, keep_style_tags=false, keep_link_tags=false, base_url=None, load_remote_stylesheets=true, cache=None, extra_css=None, preallocate_node_capacity=32) + signature = (htmls, inline_style_tags=true, keep_style_tags=false, keep_link_tags=false, keep_at_rules=false, base_url=None, load_remote_stylesheets=true, cache=None, extra_css=None, preallocate_node_capacity=32) )] #[allow(clippy::too_many_arguments)] fn inline_many( @@ -282,6 +289,7 @@ fn inline_many( inline_style_tags: Option, keep_style_tags: Option, keep_link_tags: Option, + keep_at_rules: Option, base_url: Option, load_remote_stylesheets: Option, cache: Option, @@ -292,6 +300,7 @@ fn inline_many( inline_style_tags, keep_style_tags, keep_link_tags, + keep_at_rules, base_url, load_remote_stylesheets, cache, @@ -314,12 +323,12 @@ fn inline_many_impl( Ok(output.map_err(InlineErrorWrapper)?) } -/// inline_many_fragments(htmls, css, inline_style_tags=True, keep_style_tags=False, keep_link_tags=False, base_url=None, load_remote_stylesheets=True, cache=None, extra_css=None, preallocate_node_capacity=32) +/// inline_many_fragments(htmls, css, inline_style_tags=True, keep_style_tags=False, keep_link_tags=False, keep_at_rules=False, base_url=None, load_remote_stylesheets=True, cache=None, extra_css=None, preallocate_node_capacity=32) /// /// Inline CSS in multiple HTML fragments #[pyfunction] #[pyo3( - signature = (htmls, css, inline_style_tags=true, keep_style_tags=false, keep_link_tags=false, base_url=None, load_remote_stylesheets=true, cache=None, extra_css=None, preallocate_node_capacity=32) + signature = (htmls, css, inline_style_tags=true, keep_style_tags=false, keep_link_tags=false, keep_at_rules=false, base_url=None, load_remote_stylesheets=true, cache=None, extra_css=None, preallocate_node_capacity=32) )] #[allow(clippy::too_many_arguments)] fn inline_many_fragments( @@ -328,6 +337,7 @@ fn inline_many_fragments( inline_style_tags: Option, keep_style_tags: Option, keep_link_tags: Option, + keep_at_rules: Option, base_url: Option, load_remote_stylesheets: Option, cache: Option, @@ -338,6 +348,7 @@ fn inline_many_fragments( inline_style_tags, keep_style_tags, keep_link_tags, + keep_at_rules, base_url, load_remote_stylesheets, cache, diff --git a/bindings/ruby/CHANGELOG.md b/bindings/ruby/CHANGELOG.md index eb2de8ad..c1a694ed 100644 --- a/bindings/ruby/CHANGELOG.md +++ b/bindings/ruby/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Added + +- `keep_at_rules` option [#265](https://github.com/Stranger6667/css-inline/issues/265) + ## [0.16.0] - 2025-07-16 ### Changed diff --git a/bindings/ruby/Cargo.lock b/bindings/ruby/Cargo.lock index 359b62ae..19f9224a 100644 --- a/bindings/ruby/Cargo.lock +++ b/bindings/ruby/Cargo.lock @@ -105,9 +105,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.29" +version = "1.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362" +checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" dependencies = [ "shlex", ] @@ -172,17 +172,6 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "css-inline" version = "0.16.0" -dependencies = [ - "css-inline 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "magnus", - "rayon", -] - -[[package]] -name = "css-inline" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029829f1a34f85c62c0e5e376c3aa5195308fb5f6c04ec1480188e578574bc4b" dependencies = [ "cssparser", "html5ever", @@ -196,6 +185,15 @@ dependencies = [ "url", ] +[[package]] +name = "css-inline-ruby" +version = "0.16.0" +dependencies = [ + "css-inline", + "magnus", + "rayon", +] + [[package]] name = "cssparser" version = "0.35.0" @@ -506,9 +504,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f66d5bd4c6f02bf0542fad85d626775bab9258cf795a4256dcaf3161114d1df" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" dependencies = [ "base64", "bytes", @@ -522,7 +520,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.0", "tokio", "tower-service", "tracing", @@ -647,9 +645,9 @@ dependencies = [ [[package]] name = "io-uring" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" dependencies = [ "bitflags", "cfg-if", @@ -1015,7 +1013,7 @@ dependencies = [ "quinn-udp", "rustc-hash 2.1.1", "rustls", - "socket2", + "socket2 0.5.10", "thiserror", "tokio", "tracing", @@ -1031,7 +1029,7 @@ dependencies = [ "bytes", "getrandom 0.3.3", "lru-slab", - "rand 0.9.1", + "rand 0.9.2", "ring", "rustc-hash 2.1.1", "rustls", @@ -1052,7 +1050,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2", + "socket2 0.5.10", "tracing", "windows-sys 0.59.0", ] @@ -1083,9 +1081,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha", "rand_core 0.9.3", @@ -1168,9 +1166,9 @@ checksum = "a35802679f07360454b418a5d1735c89716bde01d35b1560fc953c1415a0b3bb" [[package]] name = "redox_syscall" -version = "0.5.13" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +checksum = "7e8af0dde094006011e6a740d4879319439489813bd0bcdc7d821beaeeff48ec" dependencies = [ "bitflags", ] @@ -1376,9 +1374,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" dependencies = [ "itoa", "memchr", @@ -1447,6 +1445,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1584,7 +1592,7 @@ dependencies = [ "mio", "pin-project-lite", "slab", - "socket2", + "socket2 0.5.10", "windows-sys 0.52.0", ] @@ -1832,9 +1840,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8782dd5a41a24eed3a4f40b606249b3e236ca61adf1f25ea4d45c73de122b502" +checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" dependencies = [ "rustls-pki-types", ] diff --git a/bindings/ruby/README.md b/bindings/ruby/README.md index de053476..2aa9b690 100644 --- a/bindings/ruby/README.md +++ b/bindings/ruby/README.md @@ -135,6 +135,7 @@ inliner.inline("...") - `inline_style_tags`. Specifies whether to inline CSS from "style" tags. Default: `true` - `keep_style_tags`. Specifies whether to keep "style" tags after inlining. Default: `false` - `keep_link_tags`. Specifies whether to keep "link" tags after inlining. Default: `false` +- `keep_at_rules`. Specifies whether to keep "at-rules" (starting with `@`) after inlining. Default: `false` - `base_url`. The base URL used to resolve relative URLs. If you'd like to load stylesheets from your filesystem, use the `file://` scheme. Default: `nil` - `load_remote_stylesheets`. Specifies whether remote stylesheets should be loaded. Default: `true` - `cache`. Specifies caching options for external stylesheets (for example, `StylesheetCache(size: 5)`). Default: `nil` @@ -166,7 +167,8 @@ The `data-css-inline="ignore"` attribute also allows you to skip `link` and `sty ``` Alternatively, you may keep `style` from being removed by using the `data-css-inline="keep"` attribute. -This is useful if you want to keep `@media` queries for responsive emails in separate `style` tags: +This is useful if you want to keep `@media` queries for responsive emails in separate `style` tags. +Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is set to `false`. ```html @@ -178,7 +180,20 @@ This is useful if you want to keep `@media` queries for responsive emails in sep ``` -Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is set to `false`. +Another possibility is to set `keep_at_rules` option to `true`. At-rules cannot be inlined into HTML therefore they +get removed by default. This is useful if you want to keep at-rules, e.g. `@media` queries for responsive emails in +separate `style` tags but inline any styles which can be inlined. +Such tags will be kept in the resulting HTML even if the `keep_style_tags` option is explicitly set to `false`. + +```html + + + + + +

Big Text

+ +``` If you'd like to load stylesheets from your filesystem, use the `file://` scheme: diff --git a/bindings/ruby/ext/css_inline/Cargo.lock b/bindings/ruby/ext/css_inline/Cargo.lock index 359b62ae..19f9224a 100644 --- a/bindings/ruby/ext/css_inline/Cargo.lock +++ b/bindings/ruby/ext/css_inline/Cargo.lock @@ -105,9 +105,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.29" +version = "1.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362" +checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" dependencies = [ "shlex", ] @@ -172,17 +172,6 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "css-inline" version = "0.16.0" -dependencies = [ - "css-inline 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "magnus", - "rayon", -] - -[[package]] -name = "css-inline" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029829f1a34f85c62c0e5e376c3aa5195308fb5f6c04ec1480188e578574bc4b" dependencies = [ "cssparser", "html5ever", @@ -196,6 +185,15 @@ dependencies = [ "url", ] +[[package]] +name = "css-inline-ruby" +version = "0.16.0" +dependencies = [ + "css-inline", + "magnus", + "rayon", +] + [[package]] name = "cssparser" version = "0.35.0" @@ -506,9 +504,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f66d5bd4c6f02bf0542fad85d626775bab9258cf795a4256dcaf3161114d1df" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" dependencies = [ "base64", "bytes", @@ -522,7 +520,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.0", "tokio", "tower-service", "tracing", @@ -647,9 +645,9 @@ dependencies = [ [[package]] name = "io-uring" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" dependencies = [ "bitflags", "cfg-if", @@ -1015,7 +1013,7 @@ dependencies = [ "quinn-udp", "rustc-hash 2.1.1", "rustls", - "socket2", + "socket2 0.5.10", "thiserror", "tokio", "tracing", @@ -1031,7 +1029,7 @@ dependencies = [ "bytes", "getrandom 0.3.3", "lru-slab", - "rand 0.9.1", + "rand 0.9.2", "ring", "rustc-hash 2.1.1", "rustls", @@ -1052,7 +1050,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2", + "socket2 0.5.10", "tracing", "windows-sys 0.59.0", ] @@ -1083,9 +1081,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha", "rand_core 0.9.3", @@ -1168,9 +1166,9 @@ checksum = "a35802679f07360454b418a5d1735c89716bde01d35b1560fc953c1415a0b3bb" [[package]] name = "redox_syscall" -version = "0.5.13" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +checksum = "7e8af0dde094006011e6a740d4879319439489813bd0bcdc7d821beaeeff48ec" dependencies = [ "bitflags", ] @@ -1376,9 +1374,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" dependencies = [ "itoa", "memchr", @@ -1447,6 +1445,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1584,7 +1592,7 @@ dependencies = [ "mio", "pin-project-lite", "slab", - "socket2", + "socket2 0.5.10", "windows-sys 0.52.0", ] @@ -1832,9 +1840,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8782dd5a41a24eed3a4f40b606249b3e236ca61adf1f25ea4d45c73de122b502" +checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" dependencies = [ "rustls-pki-types", ] diff --git a/bindings/ruby/ext/css_inline/Cargo.toml b/bindings/ruby/ext/css_inline/Cargo.toml index 31615d49..e98b7e9e 100644 --- a/bindings/ruby/ext/css_inline/Cargo.toml +++ b/bindings/ruby/ext/css_inline/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "css-inline" +name = "css-inline-ruby" version = "0.16.0" authors = ["Dmitry Dygalo "] edition = "2021" @@ -20,6 +20,7 @@ magnus = "0.7" rayon = "1" [dependencies.css-inline] -version = "0.16" +path = "../../../../css-inline" +version = "*" default-features = false features = ["http", "file", "stylesheet-cache"] diff --git a/bindings/ruby/ext/css_inline/src/lib.rs b/bindings/ruby/ext/css_inline/src/lib.rs index 9fa506cb..734cf2f1 100644 --- a/bindings/ruby/ext/css_inline/src/lib.rs +++ b/bindings/ruby/ext/css_inline/src/lib.rs @@ -52,6 +52,7 @@ fn parse_options( Option, Option, Option, + Option, Option, Option, Option>, @@ -66,6 +67,7 @@ fn parse_options( "inline_style_tags", "keep_style_tags", "keep_link_tags", + "keep_at_rules", "base_url", "load_remote_stylesheets", "cache", @@ -78,13 +80,14 @@ fn parse_options( inline_style_tags: kwargs.0.unwrap_or(true), keep_style_tags: kwargs.1.unwrap_or(false), keep_link_tags: kwargs.2.unwrap_or(false), - base_url: parse_url(kwargs.3)?, - load_remote_stylesheets: kwargs.4.unwrap_or(true), + keep_at_rules: kwargs.3.unwrap_or(false), + base_url: parse_url(kwargs.4)?, + load_remote_stylesheets: kwargs.5.unwrap_or(true), cache: kwargs - .5 + .6 .map(|cache| Mutex::new(rust_inline::StylesheetCache::new(cache.size))), - extra_css: kwargs.6.map(Cow::Owned), - preallocate_node_capacity: kwargs.7.unwrap_or(32), + extra_css: kwargs.7.map(Cow::Owned), + preallocate_node_capacity: kwargs.8.unwrap_or(32), resolver: Arc::new(rust_inline::DefaultStylesheetResolver), }) } diff --git a/bindings/ruby/lib/css_inline.rb b/bindings/ruby/lib/css_inline.rb deleted file mode 100644 index 8d5fc2ee..00000000 --- a/bindings/ruby/lib/css_inline.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -begin - require "css_inline/#{RUBY_VERSION.to_f}/css_inline" -rescue LoadError - require "css_inline/css_inline" -end diff --git a/css-inline/src/html/document.rs b/css-inline/src/html/document.rs index 482afc6d..717b9595 100644 --- a/css-inline/src/html/document.rs +++ b/css-inline/src/html/document.rs @@ -288,9 +288,18 @@ impl Document { styles: DocumentStyleMap<'_>, keep_style_tags: bool, keep_link_tags: bool, + at_rules: Option<&String>, mode: InliningMode, ) -> Result<(), InlineError> { - serialize_to(self, writer, styles, keep_style_tags, keep_link_tags, mode) + serialize_to( + self, + writer, + styles, + keep_style_tags, + keep_link_tags, + at_rules, + mode, + ) } /// Filter this node iterator to elements matching the given selectors. @@ -341,6 +350,7 @@ mod tests { IndexMap::default(), false, false, + None, InliningMode::Document, ) .expect("Failed to serialize"); diff --git a/css-inline/src/html/serializer.rs b/css-inline/src/html/serializer.rs index f5997c2d..3d7b1fba 100644 --- a/css-inline/src/html/serializer.rs +++ b/css-inline/src/html/serializer.rs @@ -15,6 +15,7 @@ pub(crate) fn serialize_to( styles: DocumentStyleMap<'_>, keep_style_tags: bool, keep_link_tags: bool, + at_rules: Option<&String>, mode: InliningMode, ) -> Result<(), InlineError> { let sink = Sink::new( @@ -22,6 +23,7 @@ pub(crate) fn serialize_to( NodeId::document_id(), keep_style_tags, keep_link_tags, + at_rules, mode, ); let mut ser = HtmlSerializer::new(writer, styles); @@ -34,6 +36,7 @@ struct Sink<'a> { node: NodeId, keep_style_tags: bool, keep_link_tags: bool, + at_rules: Option<&'a String>, inlining_mode: InliningMode, } @@ -43,6 +46,7 @@ impl<'a> Sink<'a> { node: NodeId, keep_style_tags: bool, keep_link_tags: bool, + at_rules: Option<&'a String>, inlining_mode: InliningMode, ) -> Sink<'a> { Sink { @@ -50,6 +54,7 @@ impl<'a> Sink<'a> { node, keep_style_tags, keep_link_tags, + at_rules, inlining_mode, } } @@ -60,6 +65,7 @@ impl<'a> Sink<'a> { node, self.keep_style_tags, self.keep_link_tags, + self.at_rules, self.inlining_mode, ) } @@ -114,6 +120,14 @@ impl<'a> Sink<'a> { serializer.start_elem(&element.name, &element.attributes, style_node_id)?; + if element.name.local == local_name!("head") { + if let Some(at_rules) = &self.at_rules { + if !at_rules.is_empty() { + serializer.write_at_rules_style(at_rules)?; + } + } + } + self.serialize_children(serializer)?; serializer.end_elem(&element.name)?; @@ -363,6 +377,13 @@ impl<'a, W: Write> HtmlSerializer<'a, W> { Ok(()) } + fn write_at_rules_style(&mut self, at_rules: &str) -> Result<(), InlineError> { + self.writer.write_all(b"")?; + Ok(()) + } + fn write_comment(&mut self, text: &str) -> Result<(), InlineError> { self.writer.write_all(b"