CSS inliner
CSS inlined into HTML for email: style blocks and extra CSS written into each element's style attribute, with nothing ever fetched.
Version 1.0.0 · 3 functions · 1 crate
Functions
What use css_inline.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use css_inline, css_inline_with from css_inline (Quillo 0.6).
css_inline(html: str) → stror an errorThe HTML with its <style> rules inlined into style attributes (specificity and !important respected), the <style> blocks then removed. <link rel="stylesheet"> to other files are not fetched. Media queries cannot be inlined: use css_inline_with with keep_style_tags to keep them for clients that read them.
css_inline_with(html: str, extra_css: str, keep_style_tags: bool) → stror an errorAs css_inline, with extra_css applied as well (your email theme, kept apart from the templates; "" for none), and the <style> blocks kept when keep_style_tags (for @media rules in clients that support them).
css_inline_fragment(html: str, css: str) → stror an errorA fragment of HTML (no <html> or <head>, as a template part or a CMS block) with css inlined into it: gives the fragment back, styled.
Get it
$ quillo install css_inline # css_inline.qwer into this folder$ quillo install css_inline --example # and its example, css_inline.qweOr with curl:
$ curl -O https://quillolang.org/plugins/files/css_inline.qwer$ curl -O https://quillolang.org/plugins/files/css_inline.qweThen, in your program, all of it or only what you call:
use css_inline.qweruse css_inline, css_inline_with from css_inline // Quillo 0.6: only theseIt uses this crate, which cargo fetches the first time the plugin is built:
css-inline = { version = "0.14", default-features = false }Example
// An order email written with a <style> block and classes, as a designer would, and inlined// before it is sent, as email clients need.//// quillo run css_inline.qwe then open http://localhost:8080/emailuse "css_inline.qwer"let EMAIL = `<html><head><style> body { font-family: Helvetica, Arial, sans-serif; color: #222; } .button { background: #1a73e8; color: #fff !important; padding: 12px 20px; text-decoration: none; } td.total { font-weight: bold; text-align: right; } p { margin: 0 0 12px; } @media (max-width: 600px) { .wide { width: 100% !important; } }</style></head><body><p>Thanks for your order, Ada.</p><table class="wide"><tr><td>Notebook × 2</td><td class="total">€9.98</td></tr></table><p><a class="button" href="https://shop.example/orders/1042" style="color: yellow">See your order</a></p></body></html>`route GET /email = respond(200, css_inline(EMAIL)?, { "content-type": "text/html; charset=utf-8" })route GET /themed = respond(200, css_inline_with("<html><body><h1>Hello</h1><p class=note>Small print</p></body></html>", "h1 { color: #0a7; margin: 0 } .note { font-size: 12px; color: #888 }", false)?, { "content-type": "text/plain" })route GET /fragment = { html: css_inline_fragment("<p class=lead>Big news</p><p>Details</p>", "p { margin: 0 } .lead { font-size: 20px }")? }$ quillo run css_inline.qwe$ curl 'localhost:8080/email'$ curl 'localhost:8080/themed'$ curl 'localhost:8080/fragment'Source
//! CSS inlined into HTML for email: the rules of `<style>` blocks (and extra CSS you give) written into each element's `style` attribute, as Gmail and Outlook need. It never fetches anything: remote stylesheets are left out.//! version: 1.0.0//!//! [dependencies]//! css-inline = { version = "0.14", default-features = false }use std::borrow::Cow;const MAX_HTML: usize = 16 << 20;fn size(html: &str, css: &str) -> Result<(), String> { if html.len() + css.len() > MAX_HTML { return Err("the HTML and CSS are at most 16 MB".into()); } Ok(())}/// The HTML with its `<style>` rules inlined into `style` attributes (specificity and `!important` respected), the `<style>` blocks then removed./// `<link rel="stylesheet">` to other files are not fetched. Media queries cannot be inlined: use `css_inline_with` with `keep_style_tags` to keep them for clients that read them.pub fn css_inline(html: &str) -> Result<String, String> { size(html, "")?; css_inline::CSSInliner::options().load_remote_stylesheets(false).build().inline(html).map_err(|e| e.to_string())}/// As `css_inline`, with `extra_css` applied as well (your email theme, kept apart from the templates; "" for none), and the `<style>` blocks kept when `keep_style_tags` (for `@media` rules in clients that support them).pub fn css_inline_with(html: &str, extra_css: &str, keep_style_tags: bool) -> Result<String, String> { size(html, extra_css)?; let extra = if extra_css.trim().is_empty() { None } else { Some(Cow::Borrowed(extra_css)) }; css_inline::CSSInliner::options() .load_remote_stylesheets(false) .keep_style_tags(keep_style_tags) .extra_css(extra) .build() .inline(html) .map_err(|e| e.to_string())}/// A fragment of HTML (no `<html>` or `<head>`, as a template part or a CMS block) with `css` inlined into it: gives the fragment back, styled.pub fn css_inline_fragment(html: &str, css: &str) -> Result<String, String> { size(html, css)?; // Inlined as a whole page around the fragment, then the body's content taken back out // (the crate's own fragment mode kept only the first element of a fragment). let css = css.replace("</style", "<\\/style"); let page = format!("<html><head><style>{}</style></head><body>{}</body></html>", css, html); let out = css_inline::CSSInliner::options().load_remote_stylesheets(false).build().inline(&page).map_err(|e| e.to_string())?; let start = out.find("<body").and_then(|i| out[i..].find('>').map(|j| i + j + 1)).ok_or("the fragment could not be read back")?; let end = out.rfind("</body>").unwrap_or(out.len()); Ok(out[start..end.max(start)].to_string())}Related
mjml.qwer · 1.0.0MJML email templates rendered to responsive HTML email for Gmail, Outlook and Apple Mail, with placeholders filled in and escaped; no Node needed.8 views · 9 downloadsTemplates templates.qwer · 1.0.0Jinja templates your users can edit for emails, invoices and pages: sandboxed, escaped for HTML, with filters such as money and truncate, and checked before they are saved.7 views · 8 downloadsLink finder link_extract.qwer · 1.0.0URLs and emails found in plain text, with trailing punctuation handled, and the text turned into safe HTML with clickable, nofollow links.7 views · 6 downloadsMinify HTML minify_html.qwer · 1.0.0HTML made smaller for sending: spaces, comments and optional tags out, and the CSS and JavaScript inside minified too.5 views · 9 downloadsHTML to text html_text.qwer · 1.0.0HTML as readable plain text for the text part of an email: headings, lists and tables laid out, links listed at the end, and one-line previews.7 views · 7 downloadsCSS minifier css_minify.qwer · 1.0.0CSS made small and ready for the browsers you support (lightningcss): minified with rules merged, vendor prefixes added and nesting and new syntax lowered for a browserslist query, and errors reported by line.8 views · 7 downloadsThread 0 posts
On CSS inliner: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.