npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

css-inliner

v2.0.0

Published

A simple and modern CSS inliner. Optionally supports CSS preprocessors (e.g. Less) and templating languages (e.g. Handlebars).

Downloads

5,041

Readme

CSSInliner

A simple and modern CSS inliner. Optionally supports CSS preprocessors (e.g. Less) and templating languages (e.g. Handlebars).

NPM Changelog Travis.ci

Usage

const inliner = new CSSInliner({
  directory: 'stylesheets'
});

inliner.inlineCSSAsync(html)
  .then(function(result) {
    console.log(result.inlined);
  });

Configuring

First, create a new CSSInliner object. The inliner object serves as a cache for processed stylesheets, inlined documents, and other assets. You don't have to keep it around, but it is useful to speed up processing.

You configure the inliner with the following options:

directory - The base directory from which local stylesheets are loaded. Only files in this directory or its sub-directories are accessible.

plugins - Array of PostCSS plugins to use while processing stylesheets.

precompile - A function that precompiles a stylesheet into CSS. See the preprocessors section.

template - A function that can extract tags from a templating language. See the templates section.

loadAsync - A function that reads a stylesheet reference (path or URL) into a Buffer or string. Recommended only when directory and precompile are not enough.

How It Works

The inliner extracts any style elements appearing in the document, with all their rules. It also extracts any external stylesheets that use relative URLs. All stylesheets are processed using PostCSS and any plugins you opt to use, and cached in memory.

The style elements and link elements to known stylesheet are then removed from the document. Their rules will either be inlined or added back into the document later.

External stylesheets that reference absolute URLs (anything with a hostname, such as //example.com/) are retained in the document. These are expected to resolve when the document is rendered in the browser or email client.

Styles are processed in document order, that is, the order in which the style or link elements appear in the document, such that the early rules take precedence (for the same specificity).

Rules that can be applied to the style attribute of an element (inlined) are applied to any matching element found in the document, if there is one. These are never added back into a style element in the document.

Rules that cannot be inlined include pseudo selectors such as :hover and ::after, as well as all media queries such as @media screen. These can only be applied to a live document when rendered by a browser or email client. Thus they are added back to the document inside a style element.

If a rule has multiple selectors, it may be inlined using one selector, and included in the document with another selector.

Working with preprocessors (Less, Sass, Stylus, etc)

If you're working with a language that compiles to CSS, you need to use the precompile option.

A precompile function for Less is included by default, and you can use it like this:

const precompile  = CSSInliner.less;
const inliner     = new CSSInliner({ precompile });

(Less is an optional dependency, so you need to add it in your package.json if you want to use it.)

The precompile option takes a function that will be called with two arguments: the pathname, and the stylesheet. You can use the pathname to determine the file type based on its extension (e.g. does it end with .less?)

The function should return the compiled CSS in the form of a string or a Buffer, or a promise that resolves to a string or Buffer.

Working with templates (Handlebars, etc)

Inlining requires parsing the document as HTML, and when there are non-HTML tags in the document, they are often parsed incorrectly. Many templating languages use non-HTML tags.

Use the template option with an appropriate template parser. For example, when working with Handlebars templates:

const template  = CSSInliner.handlebars;
const inliner   = new CSSInliner({ template });

(Handlebars is an optional dependency, so you need to add it in your package.json if you want to use it.)

The template handler is a function that will be called with the source template, and must return an array of all template tags found there.

These tags are then replaced with HTML-compatible markers before parsing and inlining, and are restored before resolving to the final document.

Note: you shouldn't use the templating language to define a class inside a class attribute. CSSInliner doesn't run the template - it only inlines styles as if the template tags weren't there. If you need to define an element's class based on a condition:

<!-- Don't do this -->
<div class="{{ active_or_inactive }}"></div>

<!-- Do this instead -->
{{#if active}}
  <div class="active"></div>
{{else}}
  <div class="inactive"></div>
{{/if}}

Watching for warnings

The inliner may report warnings while processing CSS or HTML documents by emitting a warning event.

You can use an event handler to catch and log the warning. You can also halt processing by throwing an error from your event handler. If there are no event handlers, warnings will be logged to stderr.

const inliner = new CSSInliner(options);
inliner.on('warning', function(warning) {
  console.log('So this happened:', warning);
});

References

CSS 3: Calculating a selector's specificity

PostCSS API

PostCSS Selector Parser API