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

styliner

v1.1.0

Published

Applies external CSS stylesheets to HTML emails to work with Gmail.

Downloads

4,830

Readme

Styliner

Styliner is a Node.js library that reads CSS rules from external stylesheets and converts them to inline style="" attributes in an HTML document.

Styliner is intended for use with HTML emails. With it, you can write regular CSS or LESS (with the Styliner-less package) stylesheets, then merge them into your HTML and create emails that work with Gmail (which drops all <style> tags). Unfortunately, though, you'll still need to use <table>s to get complex layout.

You can also use advanced features ("dynamic rules") like :hover selectors or media queries, and Styliner will leave them in a <style> tag. This way, you can build interactive emails that will light up when viewed in an email client that supports <style> tags, while still maintaining Gmail support.

In effect, you get graceful degradation for your email designs.

Usage

Styliner uses the Q promise library.

var styliner = new Styliner(baseDir, { options });
styliner.processHTML(htmlSource, directory)
    .then(function(source) { ... });
//Pass filePath to processHTML
styliner.parseFile(filePath)
      .then(function(source) { ... });

The baseDir parameter specifies the base directory for relative paths. When processing an HTML source file, you can optionally specify a directory for that source, and any relative paths within the file will be treated as relative to that directory (instead of relative to the Styliner instance's baseDir).
The processHTML method returns a Q promise of the inlined HTML source.

You can pass an options hash as the second parameter to the Styliner constructor with the following options: (all options default to false):

  • compact: true
    • True to minify all output. This option removes all extraneous whitespace from the generated HTML (including any remaining inline stylesheets)
  • noCSS: true
    • True to not emit <style> tags for rules that cannot be inlined. This option will completely drop any dynamic CSS rules. (such as media queries, pseudo-elements, or @font-faces)
  • keepRules: true
    • True to keep all rules in <style> tags instead of inlining static rules into elements. This results in smaller files, but will not work with Gmail.
  • fixYahooMQ: true
    • True to add an attribute/ID selector to all rules in media queries to fix a bug in Yahoo Mail. Yahoo Mail drops all media queries, converting their contents to regular rules that will always be applied. This option adds a workaround for that.
  • keepInvalid: true
    • Don't skip properties that parserlib reports as invalid. (all invalid properties are always logged as winston errors)
    • Pass this option if you're using features that parser doesn't recognize, or if you come across a bug in parserlib
    • This option breaks Acid2, which tests that valid properties from earlier rules replace invalid properties from later rules. (see also the first known issue)
  • urlPrefix: "dir/"
    • The path containing referenced URLs. All non-absolute URLs in <a> tags, <img> tags, and stylesheets will have this path prepended. For greater flexibility, pass a url() function instead.
  • url: function(path, type)
    • A function called to resolve URLs. All non-absolute URLs in HTML or CSS will be replaced by the return value of this function. The function is passed the relative path to the file and the source of the URL ("img" or "a" or other HTML tags; URLs from CSS pass "img"). It can return a promise or a string

Known Issues

  • Browser property fallbacks don't cascade
    • If you specify background: red; in one rule, and background: linear-gradient(...) in a more specific rule, Styliner will replace the property from the first rule with the more specific one. This means that browsers that don't support linear-gradient() won't see any background at all.
    • Instead, put both properties in the same rule, and Styliner will know to keep both of them. To make this easier, you can use a LESS mixin
  • Except for margin and padding, shorthand inlined properties that are overridden by non-inlined non-shorthand counterparts will not be overridden correctly.
    • To fix this, add splitter methods in Preprocessor.js to split other shorthand properties.
  • If one element receives a property from a soft-dynamic (pseudo-class) rule and a static rule, and a different element receives a property from an earlier static rule that overrides that soft-dynamic rule, the soft-dynamic rule will incorrectly override the static rule on the second element.
    • This happens because I need to make the dynamic rule !important in order to override the inlined static rule on the first element.
    • I could do another pass to find the and !important-ize the inline property in the second element, but that would leave an unfixable problem if there is another dynamic rule that should override that property on the second element.
  • Similarly, if one element receives a property from a soft-dynamic (pseudo-class) rule and a static rule, and a different element receives a property from an later static rule that overrides that soft-dynamic rule, but is in turn overridden by a second soft-dynamic rule, the second soft-dynamic rule will be incorrectly overridden.
    • This happens because the inlined property from its static rule is made !important to override the already-!important-ized less-specific soft-dynamic rule. It is then impossible to make the more-specific soft-dynamic rule override the inlined property.
    • This is impossible to fix. This issue could be flipped (to match the previous issue) by only setting important = true after the first pass.
  • These issues could be made fixable by adding additional levels of importance to the CSS spec (!important1, !important2, etc), and changing Styliner to keep running additional passes and making overridden rules more and more important until it stabilizes.

Acid Test Issues

Acid3 doesn't work because most of its rules need to be applied dynamically (for elements created in Javascript). I can fix this by adding .js to those rules.

Acid2 has the following issues:

  • background: red pink (which is an invalid value) incorrectly overrides the valid background: yellow for .parser, resulting in a white background.

  • This happens because parserlib does not validate the background property at all. (this would be a complex validation rule to add)

  • width: 200 (which is an invalid value) incorrectly overrides the valid width: 2em for .parser, resulting in the element stretching to fit the browser.

  • This is fixed by parserlib#48, which has not been merged.

  • * html .parser incorrectly matches .parser, resulting in a gray background.

  • This is caused by CSSselect#8 and cheerio#162.

License

MIT