Skip to main content

Fast CSS inlining written in Rust

Reason this release was yanked:

security vulnerability in HTML serialization

Project description

css_inline

Build PyPI Python versions License

Blazing-fast CSS inlining for Python implemented with Mozilla's Servo project components.

Features:

  • Removing style tags after inlining;
  • Resolving external stylesheets (including local files);
  • Control if style tags should be processed;
  • Out-of-document CSS to inline;
  • Inlining multiple documents in parallel (via Rust-level threads)

The project supports CSS Syntax Level 3.

Installation

To install css_inline via pip run the following command:

pip install css_inline

Pre-compiled wheels for most popular platforms are provided. If your platform is not in the support table below, you will need a Rust compiler to build this package from source. The minimum supported Rust version is 1.60.

Usage

To inline CSS in an HTML document:

import css_inline

HTML = """<html>
<head>
    <title>Test</title>
    <style>h1 { color:blue; }</style>
</head>
<body>
    <h1>Big Text</h1>
</body>
</html>"""

inlined = css_inline.inline(HTML)
# HTML becomes this:
#
# <html>
# <head>
#    <title>Test</title>
#    <style>h1 { color:blue; }</style>
# </head>
# <body>
#     <h1 style="color:blue;">Big Text</h1>
# </body>
# </html>

If you want to inline many HTML documents, you can utilize inline_many that processes the input in parallel.

import css_inline

css_inline.inline_many(["<...>", "<...>"])

inline_many will spawn threads on the Rust level; thus, you can expect it's running faster than css_inline.inline via Python's multiprocessing or threading modules.

For customization options use the CSSInliner class:

import css_inline

inliner = css_inline.CSSInliner(remove_style_tags=True)
inliner.inline("...")

If you'd like to skip CSS inlining for an HTML tag, add data-css-inline="ignore" attribute to it:

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

This attribute also allows you to skip link and style tags:

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

If you'd like to load stylesheets from your filesystem, use the file:// scheme:

import css_inline

# styles/email is relative to the current directory
inliner = css_inline.CSSInliner(base_url="file://styles/email/")
inliner.inline("...")

Standards support & restrictions

css-inline is built on top of cssparser and relies on its behavior for CSS parsing. Notably:

  • Only HTML 5, XHTML is not supported;
  • Only CSS 3;
  • Only UTF-8 for string representation. Other document encodings are not yet supported.

If you'd like to work around some XHTML compatibility issues like closing empty tags (<hr> vs. <hr/>), you can use the following snippet that involves lxml:

import css_inline
from lxml import html, etree

document = "..."  # Your HTML document
inlined = css_inline.inline(document)
tree = html.fromstring(inlined)
inlined = etree.tostring(tree).decode(encoding="utf-8")

Performance

Due to the usage of efficient tooling from Mozilla's Servo project (html5ever, rust-cssparser and others) this library has excellent performance characteristics. In comparison with other Python projects, it is usually >10x faster than the nearest alternative.

For inlining CSS in the html document from the Usage section above there is the following breakdown in the benchmarks:

  • css_inline 0.9.0 - 13.58 us
  • premailer 3.10.0 - 310.06 us (x22.83)
  • toronado 0.1.0 - 1.43 ms (x105.32)
  • inlinestyler 0.2.5 - 2.11 ms (x155.46)
  • pynliner 0.8.0 - 2.51 ms (x184.97)

Realistic email 1:

  • css_inline 0.9.0 - 266.53 us
  • premailer 3.10.0 - 2.78 ms (x10.47)
  • toronado 0.1.0 - 31.20 ms (x117.09)
  • inlinestyler 0.2.5 - 52.64 ms (x197.52)
  • pynliner 0.8.0 - 101.14 ms (x379.47)

Realistic email 2:

  • css_inline 0.9.0 - 237.23 us
  • premailer 3.10.0 - 4.07 ms (x17.24)
  • toronado 0.1.0 - Error: Pseudo-elements are not supported
  • inlinestyler 0.2.5 - 33.87 ms (x142.81)
  • pynliner 0.8.0 - Error: No match was found

You can take a look at the benchmarks' code at benches/bench.py file. The results above were measured with stable rustc 1.69.0, Python 3.11.0, Linux x86_64 on i8700K, and 32GB RAM.

Comparison with other libraries

Besides performance, css-inline differs from other Python libraries for CSS inlining.

  • Generally supports more CSS features than other libraries (for example, toronado and pynliner do not support pseudo-elements);
  • It has fewer configuration options and not as flexible as premailer;
  • Works on fewer platforms than LXML-based libraries (premailer, inlinestyler, toronado, and optionally pynliner);
  • Does not have debug logs yet;
  • Supports only HTML 5.

Python support

css_inline supports CPython 3.7, 3.8, 3.9, 3.10, 3.11 and PyPy 3.7, 3.8, 3.9.

Extra materials

If you want to know how this library was created & how it works internally, you could take a look at these articles:

License

The code in this project is licensed under MIT license. By contributing to css_inline, you agree that your contributions will be licensed under its MIT license.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

css_inline-0.9.0.tar.gz (50.0 kB view details)

Uploaded Source

Built Distributions

css_inline-0.9.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.4 MB view details)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

css_inline-0.9.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.3 MB view details)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

css_inline-0.9.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl (1.3 MB view details)

Uploaded PyPy macOS 10.7+ x86-64

css_inline-0.9.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.4 MB view details)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

css_inline-0.9.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.3 MB view details)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

css_inline-0.9.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl (1.3 MB view details)

Uploaded PyPy macOS 10.7+ x86-64

css_inline-0.9.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.4 MB view details)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

css_inline-0.9.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.3 MB view details)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

css_inline-0.9.0-pp37-pypy37_pp73-macosx_10_7_x86_64.whl (1.3 MB view details)

Uploaded PyPy macOS 10.7+ x86-64

css_inline-0.9.0-cp37-abi3-win_amd64.whl (1.3 MB view details)

Uploaded CPython 3.7+ Windows x86-64

css_inline-0.9.0-cp37-abi3-win32.whl (1.2 MB view details)

Uploaded CPython 3.7+ Windows x86

css_inline-0.9.0-cp37-abi3-musllinux_1_2_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.7+ musllinux: musl 1.2+ x86-64

css_inline-0.9.0-cp37-abi3-musllinux_1_2_armv7l.whl (1.4 MB view details)

Uploaded CPython 3.7+ musllinux: musl 1.2+ ARMv7l

css_inline-0.9.0-cp37-abi3-musllinux_1_2_aarch64.whl (1.5 MB view details)

Uploaded CPython 3.7+ musllinux: musl 1.2+ ARM64

css_inline-0.9.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.7+ manylinux: glibc 2.17+ x86-64

css_inline-0.9.0-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.1 MB view details)

Uploaded CPython 3.7+ manylinux: glibc 2.17+ ARMv7l

css_inline-0.9.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.3 MB view details)

Uploaded CPython 3.7+ manylinux: glibc 2.17+ ARM64

css_inline-0.9.0-cp37-abi3-manylinux_2_12_i686.manylinux2010_i686.whl (1.3 MB view details)

Uploaded CPython 3.7+ manylinux: glibc 2.12+ i686

css_inline-0.9.0-cp37-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl (2.5 MB view details)

Uploaded CPython 3.7+ macOS 10.9+ universal2 (ARM64, x86-64) macOS 10.9+ x86-64 macOS 11.0+ ARM64

css_inline-0.9.0-cp37-abi3-macosx_10_7_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.7+ macOS 10.7+ x86-64

File details

Details for the file css_inline-0.9.0.tar.gz.

File metadata

  • Download URL: css_inline-0.9.0.tar.gz
  • Upload date:
  • Size: 50.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.10.6

File hashes

Hashes for css_inline-0.9.0.tar.gz
Algorithm Hash digest
SHA256 5f8473ba656bd462628e53eb6128297ef0b127247f392658bb340b9a7cd4cdb2
MD5 5ca0837b9290fb982e1337e74297e52d
BLAKE2b-256 b68af5f42b7f417e1a8c1e5764caecc6d9f03a4da93449225918f9cf4aa5f590

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 1f92a87f49e0a6ea3caf7b60bf7898dcc1efbb8b622f5e9892237a05779513b9
MD5 c5f740379718a6e0dbd2cfccb47e6262
BLAKE2b-256 250a487837d118a8be6aac32c992fb227697acbb5fd96c90417f6f4300e4319e

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 38158bccb45732c196913dbd03c84a4f241e35f3f264d883a1f48c239bfca7dd
MD5 3cbaff5c40d357bea143b5cff9b98199
BLAKE2b-256 ca1d08057f1aec367a203da9e2fbae42c18015897a19ce9b6d48c809b906eb0f

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl
Algorithm Hash digest
SHA256 77449d65330e7d5f7b24dfa4c2379001da4df69d41340096e8ef8f86ebc3fb99
MD5 1567c21aeb40c7d285b6c8e4265195b8
BLAKE2b-256 db79cfd48e854dff32c2440cf5f38095c69e9c2307b259b795a8cde82688b745

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c73ed7871cecaa8e5a65c529f6208db571739e8295d6596682c32ba2e043fd08
MD5 0c2e87a06648acf16d3a7d891fbb3ef9
BLAKE2b-256 1e8559a1aed1164bbd36b960db05d6984c197e6fd9aaaf9f6290ff3aa678d02a

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 b1be1b03d436a55cb501c3c115e8f3c0ef85b49bf0007723dab75f97f93d8e62
MD5 b6aa8f5bd8d8717638ec55f80caf5bf1
BLAKE2b-256 10e96a19fb52a7cdae81aa6a0f290cc6c9475a3cac78119ea872d436517a2d43

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl
Algorithm Hash digest
SHA256 211c9fc46f7c4f17fafc46eb43b2054593ca8392ea369df8b50b59f9c4064473
MD5 b10eec595d56fb25f873a2225c270d6a
BLAKE2b-256 ba682a35045b39d4f129061b2a0ca24a16d83f75ca6dd98d884b8c1bcaa098ec

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d8848c74a8fe82db238d31df012beb805d3ddfbccf3f1c90aaa84d25273fe03f
MD5 16ce00d0b41007bd610d7a5f4f2f6269
BLAKE2b-256 298bd2610d1e67dd798e87ab726f5b11f463e7b0e8fc65f360fe923de22ccbfe

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 19604b20d7904c44786a9dd9dbd6e831e348ca8d139f325a090a0f478186a3e0
MD5 fe3e9a3be0686016c73bb15cf984d6ef
BLAKE2b-256 86bdacb27d74465fcbe9704a153da51ea76aa7f6d7168209f4baf30c2880e006

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-pp37-pypy37_pp73-macosx_10_7_x86_64.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-pp37-pypy37_pp73-macosx_10_7_x86_64.whl
Algorithm Hash digest
SHA256 515ba927e04fe25e7fc80934c7ee297e431b5232cf8768ffe0e06ed66f3013af
MD5 c5a0f17522a7caaf27d30f422b9c7e3a
BLAKE2b-256 952d8fab07078f398d28dd19016a99fb7d9d825d31e994b6abec198b6c45e663

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-cp37-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-cp37-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 14f5ccbf1eb87cca4795c011018f020c0b525cb1bb304a4080e04e108f9aefca
MD5 7898cd798d15ef63a2cc15a30ef6eb80
BLAKE2b-256 7f5b5bd70b90bea2f4203c9d14f8bba223d3f6540ee5b96e5a833b92f63f6f11

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-cp37-abi3-win32.whl.

File metadata

  • Download URL: css_inline-0.9.0-cp37-abi3-win32.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.7+, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.10.6

File hashes

Hashes for css_inline-0.9.0-cp37-abi3-win32.whl
Algorithm Hash digest
SHA256 8779c1654300305d36bbf382ca5cb335d828df7fe9efe06e66a4a2f0d998bdf8
MD5 83723341f02cfc93379a06cfa0ba0960
BLAKE2b-256 7e353ed828150255a2e7f32af83bd1b39374cde984e79d81dfb16fb5b8af4b7e

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-cp37-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-cp37-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 9e6a5ff4ac4e76357690ff5b73b1601566d126a52342f5fb92ba22aecab3453e
MD5 8ed62ff5118538d140b26eafb10df3ff
BLAKE2b-256 b7899f73f9a34ebe9f8b280a2b7d9c04630d72b8336c84a33f5330c182b2057b

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-cp37-abi3-musllinux_1_2_armv7l.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-cp37-abi3-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 1da3366d8cbff7359989a72f8d6b265045909c40e17484194ca65cc5cefe13f9
MD5 5fe2c5b157715bad3a2c17c14a41441f
BLAKE2b-256 bf821b7cd4c719f20242f6689cc454536d795da6c5dfb0e0fff2321c3c236aa2

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-cp37-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-cp37-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 0c796cb6171c5ea71b52f613abeeb78969bad3d0719af4d27cf6db9434eaff8f
MD5 ea41b02d92348f7d49c09c2f2a01f42d
BLAKE2b-256 5067aac32293e9d843ffb998a9871277fbfb0c29d5996510aae702d95e457f06

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 66656b012cb7f0f6dcf9a0d1d2a0787695326fb28cd5237c08087e6c31837da3
MD5 d6b8f4a2f4e38b803e30736dc27207b7
BLAKE2b-256 51e7f6c1aa46d3f7a88d2301358b192be43326fae0036be8476731c3b892fc93

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 3c25f2ca4586e20a53db701590fb33a96fd773741d4559474fa18e0ed34f4a49
MD5 7326ce1faf0a121764377ce3268665f5
BLAKE2b-256 468647bc5b0ca4072ba760b7c029757956360f3e350f97f1df29ed0c562c584c

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 09eeb2b8da52f6c6a1bce15a7aac46110472e8a88bf5adcc900b6be9509bbab2
MD5 78fc90d9b6be12ba2151163d25aed821
BLAKE2b-256 2f68b200a1df560f1ed9d6f0b8b09bc44741e73f6d11655d14a82b4540a63b07

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-cp37-abi3-manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-cp37-abi3-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 9b835fb01f9570cc55200794ea9dae77a437ba8e3ba5e64d937e1d3700b99c55
MD5 e5432f0cc3ab13551d7bbd7c81851a6c
BLAKE2b-256 428d7cbfef4496adab7d38c41ca158f42fa6c2ca6bac2452d478ce11a51f7ac8

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-cp37-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-cp37-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 a46acd54351a9b2c7bc33e269fdc588f647c059eb2acc60b6a12f497c547e45d
MD5 a7891d4cf623b984c71cd157e955a4e0
BLAKE2b-256 60e230fb318df3210edf8048dfa2d5672ebf681ac9fc4f0da0cb7ab0781b17f7

See more details on using hashes here.

File details

Details for the file css_inline-0.9.0-cp37-abi3-macosx_10_7_x86_64.whl.

File metadata

File hashes

Hashes for css_inline-0.9.0-cp37-abi3-macosx_10_7_x86_64.whl
Algorithm Hash digest
SHA256 49cf75dd3facca412232511727c90105f674eb4d25ffc414797d85d8fdbb43c9
MD5 46cfe4f68c709052474ddb151ed9c122
BLAKE2b-256 1ea4c3edee4edf2d856b1aa0b6cd2b7befc0c860e945fe6847ea661b27bef1c9

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page