#css #html-css #html #样式表 #电子邮件 #内联

bin+lib css-inline

高性能库,用于将 CSS 内联到 HTML 'style' 属性中

36 个版本 (12 个重大更改)

0.14.1 2024 年 4 月 27 日
0.13.0 2024 年 1 月 19 日
0.12.0 2023 年 12 月 28 日
0.11.0 2023 年 9 月 26 日
0.4.0 2020 年 7 月 13 日

#91 in Web 编程

Download history 780/week @ 2024-05-03 930/week @ 2024-05-10 886/week @ 2024-05-17 943/week @ 2024-05-24 1124/week @ 2024-05-31 985/week @ 2024-06-07 840/week @ 2024-06-14 1124/week @ 2024-06-21 1291/week @ 2024-06-28 1469/week @ 2024-07-05 1184/week @ 2024-07-12 1764/week @ 2024-07-19 1664/week @ 2024-07-26 1099/week @ 2024-08-02 1767/week @ 2024-08-09 989/week @ 2024-08-16

每月下载量 5,806
用于 6 库(直接使用 2 个)

MIT 许可证

135KB
3K SLoC

css-inline

build status crates.io docs.rs codecov.io gitter

css_inline 是一个高性能库,用于将 CSS 内联到 HTML 'style' 属性中。

此库适用于准备 HTML 邮件或将 HTML 嵌入第三方网页等场景。

例如,该库可以将 HTML 转换为

<html>
  <head>
    <style>h1 { color:blue; }</style>
  </head>
  <body>
    <h1>Big Text</h1>
  </body>
</html>

<html>
  <head></head>
  <body>
    <h1 style="color:blue;">Big Text</h1>
  </body>
</html>
  • 使用来自 Mozilla 的 Servo 项目的可靠组件
  • stylelink 标签中内联 CSS
  • 删除 stylelink 标签
  • 解析外部样式表(包括本地文件)
  • 可选地缓存外部样式表
  • 在 Linux、Windows 和 macOS 上工作
  • 支持 HTML5 & CSS3
  • PythonRubyJavaScriptC 提供绑定,以及一个 WebAssembly 模块,以便在浏览器中运行。
  • 命令行界面

沙盒

如果您想尝试 css-inline,您可以通过 WebAssembly 驱动的 沙盒 立即查看结果。

安装

要将它包含到您的项目中,请将以下行添加到项目 Cargo.toml 文件中的依赖项部分

[dependencies]
css-inline = "0.14"

最低支持的 Rust 版本是 1.65。

使用方法

const HTML: &str = r#"<html>
<head>
    <style>h1 { color:blue; }</style>
</head>
<body>
    <h1>Big Text</h1>
</body>
</html>"#;

fn main() -> css_inline::Result<()> {
    let inlined = css_inline::inline(HTML)?;
    // Do something with inlined HTML, e.g. send an email
    Ok(())
}

请注意,css-inline 会自动添加缺少的 htmlbody 标签,因此输出是一个有效的 HTML 文档。

或者,您可以将 CSS 内联到 HTML 片段中,保留原始结构

const FRAGMENT: &str = r#"<main>
<h1>Hello</h1>
<section>
<p>who am i</p>
</section>
</main>"#;

const CSS: &str = r#"
p {
    color: red;
}

h1 {
    color: blue;
}
"#;

fn main() -> css_inline::Result<()> {
    let inlined = css_inline::inline_fragment(FRAGMENT, CSS)?;
    Ok(())
}

配置

css-inline 可以通过使用实现 Builder 模式的 CSSInliner::options() 进行配置

const HTML: &str = "...";

fn main() -> css_inline::Result<()> {
    let inliner = css_inline::CSSInliner::options()
        .load_remote_stylesheets(false)
        .build();
    let inlined = inliner.inline(HTML)?;
    // Do something with inlined HTML, e.g. send an email
    Ok(())
}
  • inline_style_tags。指定是否内联 "style" 标签中的 CSS。默认值:true
  • keep_style_tags。指定是否在内联后保留 "style" 标签。默认值:false
  • keep_link_tags。指定是否在内联后保留 "link" 标签。默认值:false
  • base_url。用于解析相对 URL 的基本 URL。如果您想从文件系统中加载样式表,请使用 file:// 方案。默认值:None
  • load_remote_stylesheets。指定是否加载远程样式表。默认值:true
  • cache。指定外部样式表的缓存。默认值:None
  • extra_css。要内联的额外 CSS。默认值:None
  • preallocate_node_capacity。**高级**。在解析过程中预分配 HTML 节点的容量。如果您对 HTML 文档中的节点数量有一个估计,这可以提高性能。默认值:32

您还可以通过给 HTML 标签添加 data-css-inline="ignore" 属性来跳过 CSS 内联

<head>
  <style>h1 { color:blue; }</style>
</head>
<body>
  <!-- The tag below won't receive additional styles -->
  <h1 data-css-inline="ignore">Big Text</h1>
</body>

data-css-inline="ignore" 属性还允许您跳过 linkstyle 标签

<head>
  <!-- Styles below are ignored -->
  <style data-css-inline="ignore">h1 { color:blue; }</style>
</head>
<body>
  <h1>Big Text</h1>
</body>

或者,您可以使用 data-css-inline="keep" 属性来保留 style,这样如果您想保留响应式电子邮件中的 @media 查询并在单独的 style 标签中保留它们,这会很有用

<head>
  <!-- Styles below are not removed -->
  <style data-css-inline="keep">h1 { color:blue; }</style>
</head>
<body>
  <h1>Big Text</h1>
</body>

即使将 keep_style_tags 选项设置为 false,这些标签也将保留在生成的 HTML 中。

如果您想从文件系统中加载样式表,请使用 file:// 方案

const HTML: &str = "...";

fn main() -> css_inline::Result<()> {
    let base_url = css_inline::Url::parse("file://styles/email/").expect("Invalid URL");
    let inliner = css_inline::CSSInliner::options()
        .base_url(Some(base_url))
        .build();
    let inlined = inliner.inline(HTML);
    // Do something with inlined HTML, e.g. send an email
    Ok(())
}

对于解析远程样式表,可以实现自定义解析器

#[derive(Debug, Default)]
pub struct CustomStylesheetResolver;

impl css_inline::StylesheetResolver for CustomStylesheetResolver {
    fn retrieve(&self, location: &str) -> css_inline::Result<String> {
        Err(self.unsupported("External stylesheets are not supported"))
    }
}

fn main() -> css_inline::Result<()> {
    let inliner = css_inline::CSSInliner::options()
        .resolver(std::sync::Arc::new(CustomStylesheetResolver))
        .build();
    Ok(())
}

您还可以缓存外部样式表以避免过度的网络请求

use std::num::NonZeroUsize;

#[cfg(feature = "stylesheet-cache")]
fn main() -> css_inline::Result<()> {
    let inliner = css_inline::CSSInliner::options()
        .cache(
            // This is an LRU cache
            css_inline::StylesheetCache::new(
                NonZeroUsize::new(5).expect("Invalid cache size")
            )
        )
        .build();
    Ok(())
}

// This block is here for testing purposes
#[cfg(not(feature = "stylesheet-cache"))]
fn main() -> css_inline::Result<()> {
    Ok(())
}

默认情况下禁用缓存。

性能

css-inline 通常在几百微秒内内联 HTML 电子邮件,尽管结果可能因输入复杂性而有所不同。

css-inline==0.14.0 的基准测试

  • 基本:6.72 µs,230 字节
  • 现实-1:132.59 µs,8.58 KB
  • 现实-2:86.01 µs,4.3 KB
  • GitHub 页面:228.97 ms,1.81 MB

这些基准测试,使用 rustc 1.77.1 进行,可以在 css-inline/benches/inliner.rs 中找到。

命令行界面

安装

使用 cargo 进行安装

cargo install css-inline

使用方法

以下命令可以在多个文档中并行内联CSS。结果文件将保存为 inlined.email1.htmlinlined.email2.html

css-inline email1.html email2.html

有关可用选项的完整详细信息,您可以使用 --help 标志

css-inline --help

进一步阅读

如果您想了解这个库是如何创建的以及它是如何内部工作的,请查看这些文章

支持

如果您对这个库有任何问题或讨论,请加入我们的 gitter

许可

本项目根据 MIT许可协议 许可。

依赖项

~4–16MB
~231K SLoC