JSPM

  • Created
  • Published
  • Downloads 26
  • Score
    100M100P100Q50410F
  • License MIT

Gulp plugin to remove unused CSS classes/id's from styles in HTML HEAD and inline within BODY

Package Exports

  • gulp-email-remove-unused-css

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (gulp-email-remove-unused-css) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

gulp-email-remove-unused-css

Gulp plugin to remove unused CSS classes/id's from styles in HTML HEAD and inline within BODY

Minimum Node version required Repository is on BitBucket Coverage View dependencies as 2D chart Downloads/Month Code style: prettier MIT License

If you have any difficulties with the output of this plugin, please use the email-comb issue tracker.

Table of Contents

Install

Install using npm:

npm i gulp-email-remove-unused-css

Example

var gulp = require("gulp");
var remove = require("gulp-email-remove-unused-css");

gulp.task("default", function() {
  return gulp
    .src("src/*.html")
    .pipe(
      remove({
        whitelist: [
          ".ExternalClass",
          ".ReadMsgBody",
          ".yshortcuts",
          ".Mso*",
          ".maxwidth-apple-mail-fix",
          "#outlook",
          ".module-*"
        ]
      })
    )
    .pipe(gulp.dest("./dist"));
});

⬆ back to top

Options

Since the main purpose of this library is to clean email HTML, it needs to cater for email code specifics. One of them is that CSS styles will contain fix or hack styles, meant for email software. For example, here are few of them:

#outlook a { padding:0; } .ExternalClass, .ReadMsgBody { width:100%; }
.ExternalClass, .ExternalClass div, .ExternalClass font, .ExternalClass p,
.ExternalClass span, .ExternalClass td { line-height:100%; }

Obviously, you will not be using the above classes and id's in the <body> of your HTML code, what means they would get removed — they are present in <head> only. To avoid that, pass the classes and id's in the whitelist key's value, as an array, for example:

.pipe(remove({
  whitelist: ['.ExternalClass', '.ReadMsgBody', '.yshortcuts', '.Mso*', '.maxwidth-apple-mail-fix', '#outlook']
}))

You can also use a glob, for example in order to whitelist classes module-1, module-2 ... module-99, module-100, you can simply whitelist them as module-*:

.pipe(remove({
  whitelist: ['.ExternalClass', '.ReadMsgBody', '.yshortcuts', '.Mso*', '.maxwidth-apple-mail-fix', '#outlook', '.module-*']
}))
// => all class names that begin with ".module-" will not be touched by this library.

⬆ back to top

Next level

If you start to overgrow the plugin's baby shirt and want to work with HTML directly, as string, stop using this library and use the API library of it instead.

The idea is the following: in Gulp, everything flows as a vinyl Buffer streams. You tap the stream, convert it to string, perform the operations, then convert it back to Buffer and place it back. I wanted to come up with a visual analogy example using waste pipes but thought I'd rather won't.

Code-wise, here's the idea:

const tap = require('gulp-tap')
const removeUnused = require('email-remove-unused-css')
const util = require('gulp-util')
const whitelist = ['.External*', '.ReadMsgBody', '.yshortcuts', '.Mso*', '#outlook', '.module*']

gulp.task('build', () => {
  return gulp.src('emails/*.html')
    .pipe(tap((file) => {
      const cleanedHtmlResult = removeUnused(file.contents.toString(), { whitelist })
      util.log(util.colors.green(`\nremoved ${cleanedHtmlResult.deletedFromHead.length} from head: ${cleanedHtmlResult.deletedFromHead.join(' ')}`))
      util.log(util.colors.green(`\nremoved ${cleanedHtmlResult.deletedFromBody.length} from body: ${cleanedHtmlResult.deletedFromBody.join(' ')}`))
      file.contents = Buffer.from(cleanedHtmlResult.result)
}))

⬆ back to top

Regarding removing unused CSS from web pages & competition

This library is meant to be used on any HTML where there are no external stylesheets and there are no JavaScript which could add or remove classes or id's dynamically. It's quite rare to find a web page that would be like that, but it's the case for all email newsletters and this library is aimed at cleaning email HTML code. If your website's HTML is like that, this library will work perfectly fine on it as well. Email HTML and website HTML are both the same markup language.

If you need more advanced CSS removal tools, check out uncss and gulp-uncss which runs a headless browser and are capable to parse external stylesheets. However, it's by magnitude slower and it's definitely an overkill for email HTML code.

There's also more direct competitor, postcss-remove-unused which uses Cheerio, but:

  1. postcss-remove-unused is tied with PostCSS and can't be used outside of it. Its testing is also tied to PostCSS and dependent on it. On other hand, this library is only a Gulp wrapper for email-comb which is tool-independent (reads string, outputs string). I'm a strong believer that core functionality should be decoupled from the wrappers, PostHTML, PostCSS, Gulp, Grunt, font-end interfaces or anything else. In the past I decoupled Detergent's core from its front-end.

  2. postcss-remove-unused doesn't remove id's, while this library does. It's important because some of email code hacks are based on id's, for example, #outlook a {padding: 0; } which causes "View in browser" toolbar menu link to appear on Outlook 2010. Style cleaning library must recognise id's in order to white-list them.

⬆ back to top

Contributing

  • If you see an error, raise an issue.
  • If you want a new feature but can't code it up yourself, also raise an issue. Let's discuss it.
  • If you tried to use this package, but something didn't work out, also raise an issue. We'll try to help.
  • If you want to contribute some code, fork the monorepo via BitBucket, then write code, then file a pull request via BitBucket. We'll merge it in and release.

In monorepo, npm libraries are located in packages/ folder. Inside, the source code is located either in src/ folder (normal npm library) or in the root, cli.js (if it's a command line application).

The npm script "dev", the "dev": "rollup -c --dev --silent" builds the development version retaining all console.logs with row numbers. It's handy to have js-row-num-cli installed globally so you can automatically update the row numbers on all console.logs.

⬆ back to top

Licence

MIT License

Copyright (c) 2015-2019 Roy Revelt and other contributors