Repository: maizzle/framework
Pull request #362 (2020-11-11 00:05:41)

feat: export transformers
This PR exports Transformers methods so you can use any of them in Node, even if you're not using Maizzle to build your emails 🤯

### Usage

It's recommended that you import only the Transformers that you need:

```js
const {removeUnusedCSS} = require('@maizzle/framework')

const html = removeUnusedCSS('html string', options).then(html => html)
```

### Available Transformers

All Maizzle Transformers are available:

- [`attributeToStyle`](https://maizzle.com/docs/css-inlining#attributetostyle)
- [`applyBaseImageUrl`](https://maizzle.com/docs/base-image-url/)
- [`applyExtraAttributes`](https://maizzle.com/docs/extra-attributes/)
- [`inlineCSS`](https://maizzle.com/docs/css-inlining)
- [`minify`](https://maizzle.com/docs/minify/)
- [`markdown`](https://maizzle.com/docs/markdown/)
- [`prettify`](https://maizzle.com/docs/prettify/)
- [`preventWidows`](https://maizzle.com/docs/widows/)
- [`removeAttributes`](https://maizzle.com/docs/code-cleanup/#removeattributes)
- [`removeInlineBgColor`](https://maizzle.com/docs/css-inlining/#preferbgcolorattribute)
- [`removeInlineSizes`](https://maizzle.com/docs/css-inlining/#keeponlyattributesizes)
- [`removeUnusedCSS`](https://maizzle.com/docs/code-cleanup/#removeunusedcss)
- [`replaceStrings`](https://maizzle.com/docs/code-cleanup/#replacestrings)
- [`safeClassNames`](https://maizzle.com/docs/code-cleanup/#safeclassnames)
- [`ensureSixHEX`](https://maizzle.com/docs/code-cleanup/#six-digit-hex)
- [`transformContents`](https://maizzle.com/docs/transform/)
- [`addURLParams`](https://maizzle.com/docs/url-parameters/)


Patch:
diff --git a/src/index.js b/src/index.js
index d85f45f..7cbb871 100644
--- a/src/index.js
+++ b/src/index.js
@@ -4,9 +4,11 @@ const fs = require('fs-extra')
 const bs = require('browser-sync')
 const {get, merge} = require('lodash')
 const Output = require('./generators/output')
+const transformers = require('./transformers')
 const Plaintext = require('./generators/plaintext')
 
 const self = module.exports = { // eslint-disable-line
+  ...transformers,
   build: async (env = 'local', config = {}) => {
     const start = new Date()
     const spinner = ora('Building emails...').start()
diff --git a/src/transformers/attribute-to-style.js b/src/transformers/attribute-to-style.js
index ba558c8..bce38c6 100644
--- a/src/transformers/attribute-to-style.js
+++ b/src/transformers/attribute-to-style.js
@@ -2,11 +2,19 @@ const posthtml = require('posthtml')
 const parseAttrs = require('posthtml-attrs-parser')
 const {get, forEach, intersection, keys, isEmpty} = require('lodash')
 
-module.exports = async (html, config) => {
+module.exports = async (html, config = {}, direct = false) => {
+  if (direct) {
+    return posthtml([
+      attributesToStyle({
+        attributes: Array.isArray(config) ? config : []
+      })
+    ]).process(html).then(result => result.html)
+  }
+
   const posthtmlOptions = get(config, 'build.posthtml.options', {})
   const attributes = get(config, 'inlineCSS.attributeToStyle', false)
 
-  if ((typeof attributes === 'boolean' && attributes)) {
+  if (typeof attributes === 'boolean' && attributes) {
     return posthtml([attributesToStyle()]).process(html, posthtmlOptions).then(result => result.html)
   }
 
diff --git a/src/transformers/base-image-url.js b/src/transformers/base-image-url.js
index 98076f2..e120697 100644
--- a/src/transformers/base-image-url.js
+++ b/src/transformers/base-image-url.js
@@ -1,5 +1,5 @@
-module.exports = async (html, config) => {
-  const url = config.baseImageURL
+module.exports = async (html, config = {}, direct = false) => {
+  const url = direct ? config : config.baseImageURL
 
   if (url) {
     return html.replace(/(background="|src=")(?!\s+|url\('?'?\)|"|https?:\/\/)\/?/gi, '$1' + url)
diff --git a/src/transformers/extra-attributes.js b/src/transformers/extra-attributes.js
index b3d651e..71d5d29 100644
--- a/src/transformers/extra-attributes.js
+++ b/src/transformers/extra-attributes.js
@@ -2,7 +2,9 @@ const posthtml = require('posthtml')
 const {get, isObject} = require('lodash')
 const addAttributes = require('posthtml-extra-attributes')
 
-module.exports = async (html, config) => {
+module.exports = async (html, config = {}, direct = false) => {
+  const posthtmlOptions = get(config, 'build.posthtml.options', {})
+
   let attributes = {
     table: {
       cellpadding: 0,
@@ -14,13 +16,7 @@ module.exports = async (html, config) => {
     }
   }
 
-  if (isObject(config.extraAttributes)) {
-    attributes = {...attributes, ...config.extraAttributes}
-  }
-
-  const posthtmlOptions = get(config, 'build.posthtml.options', {})
-
-  html = posthtml([addAttributes({attributes})]).process(html, posthtmlOptions).then(result => result.html)
+  attributes = direct ? {...attributes, ...config} : (isObject(config.extraAttributes) ? {...attributes, ...config.extraAttributes} : {})
 
-  return html
+  return posthtml([addAttributes({attributes})]).process(html, posthtmlOptions).then(result => result.html)
 }
diff --git a/src/transformers/index.js b/src/transformers/index.js
index b00b09b..7e70d97 100644
--- a/src/transformers/index.js
+++ b/src/transformers/index.js
@@ -11,10 +11,10 @@ const safeClassNames = require('./safe-class-names')
 const applyBaseImageUrl = require('./base-image-url')
 const removeUnusedCSS = require('./remove-unused-css')
 const removeAttributes = require('./remove-attributes')
+const attributeToStyle = require('./attribute-to-style')
 const removeInlineSizes = require('./remove-inline-sizes')
 const applyExtraAttributes = require('./extra-attributes')
 const removeInlineBgColor = require('./remove-inline-bgcolor')
-const attributeToStyle = require('./attribute-to-style')
 
 exports.process = async (html, config) => {
   html = await safeClassNames(html, config)
@@ -37,3 +37,21 @@ exports.process = async (html, config) => {
 
   return html
 }
+
+exports.inlineCSS = (html, config) => inline(html, config, true)
+exports.minify = (html, config) => minify(html, config, true)
+exports.markdown = (html, config) => markdown(html, config, true)
+exports.prettify = (html, config) => prettify(html, config, true)
+exports.ensureSixHEX = html => ensureSixHEX(html)
+exports.addURLParams = (html, config) => addURLParams(html, config, true)
+exports.transformContents = (html, config) => transformContents(html, config, true)
+exports.preventWidows = (html, config) => preventWidows(html, config, true)
+exports.replaceStrings = (html, config) => replaceStrings(html, config, true)
+exports.safeClassNames = (html, config) => safeClassNames(html, config, true)
+exports.applyBaseImageUrl = (html, config) => applyBaseImageUrl(html, config, true)
+exports.removeUnusedCSS = (html, config) => removeUnusedCSS(html, config, true)
+exports.removeAttributes = (html, config) => removeAttributes(html, config, true)
+exports.removeInlineSizes = (html, config) => removeInlineSizes(html, config, true)
+exports.applyExtraAttributes = (html, config) => applyExtraAttributes(html, config, true)
+exports.removeInlineBgColor = (html, config) => removeInlineBgColor(html, config, true)
+exports.attributeToStyle = (html, config) => attributeToStyle(html, config, true)
diff --git a/src/transformers/inline.js b/src/transformers/inline.js
index f438e15..f06c903 100644
--- a/src/transformers/inline.js
+++ b/src/transformers/inline.js
@@ -3,9 +3,10 @@ const posthtml = require('posthtml')
 const {get, isObject, isEmpty} = require('lodash')
 const mergeLonghand = require('posthtml-postcss-merge-longhand')
 
-module.exports = async (html, config) => {
-  const options = get(config, 'inlineCSS', {})
+module.exports = async (html, config = {}, direct = false) => {
+  const options = direct ? {...config, enabled: true} : get(config, 'inlineCSS', {})
   const removeStyleTags = get(options, 'removeStyleTags', true)
+  const css = get(config, 'customCSS', false)
 
   if (get(options, 'enabled', false)) {
     juice.styleToAttribute = get(options, 'styleToAttribute', {'vertical-align': 'valign'})
@@ -23,7 +24,7 @@ module.exports = async (html, config) => {
       })
     }
 
-    html = juice(html, {removeStyleTags})
+    html = css ? juice.inlineContent(html, css, {removeStyleTags}) : juice(html, {removeStyleTags})
 
     const posthtmlOptions = get(config, 'build.posthtml.options', {})
     const mergeLonghandConfig = get(options, 'mergeLonghand', {enabled: false})
diff --git a/src/transformers/markdown.js b/src/transformers/markdown.js
index 0e68c1a..e5f2cc8 100644
--- a/src/transformers/markdown.js
+++ b/src/transformers/markdown.js
@@ -2,8 +2,8 @@ const posthtml = require('posthtml')
 const {get, merge} = require('lodash')
 const markdown = require('posthtml-markdownit')
 
-module.exports = async (html, config) => {
-  const userMarkdownOptions = get(config, 'markdown', {})
+module.exports = async (html, config = {}, direct = false) => {
+  const userMarkdownOptions = direct ? config : get(config, 'markdown', {})
   const posthtmlOptions = get(config, 'build.posthtml.options', {})
   const markdownOptions = merge({markdownit: {html: true}}, userMarkdownOptions)
 
diff --git a/src/transformers/minify.js b/src/transformers/minify.js
index 0cd4122..1530e93 100644
--- a/src/transformers/minify.js
+++ b/src/transformers/minify.js
@@ -1,9 +1,18 @@
 const {get} = require('lodash')
 const {crush} = require('html-crush')
 
-module.exports = async (html, config) => {
-  if (get(config, 'minify.enabled', false)) {
-    html = crush(html, {removeLineBreaks: true, ...config.minify}).result
+module.exports = async (html, config = {}, direct = false) => {
+  const shouldMinify = direct ? true : get(config, 'minify.enabled', false)
+
+  config = direct ? {
+    lineLengthLimit: 500,
+    removeIndentations: true,
+    removeLineBreaks: true,
+    ...config
+  } : get(config, 'minify', {})
+
+  if (shouldMinify) {
+    html = crush(html, {removeLineBreaks: true, ...config}).result
   }
 
   return html
diff --git a/src/transformers/plaintext.js b/src/transformers/plaintext.js
index 6a5f729..2873aea 100644
--- a/src/transformers/plaintext.js
+++ b/src/transformers/plaintext.js
@@ -1,7 +1,7 @@
 const {get} = require('lodash')
 const posthtml = require('posthtml')
 
-module.exports = (html, config) => {
+module.exports = (html, config = {}) => {
   const posthtmlOptions = get(config, 'build.posthtml.options', {})
 
   return posthtml([plaintext()]).process(html, {...posthtmlOptions, sync: true}).html
diff --git a/src/transformers/prettify.js b/src/transformers/prettify.js
index 92c9cf6..19aea31 100644
--- a/src/transformers/prettify.js
+++ b/src/transformers/prettify.js
@@ -1,8 +1,12 @@
+const {get} = require('lodash')
 const pretty = require('pretty')
 
-module.exports = async (html, config) => {
-  if (config.prettify && config.prettify.enabled) {
-    return pretty(html, config.prettify)
+module.exports = async (html, config = {}, direct = false) => {
+  const shouldPrettify = direct ? true : get(config, 'prettify.enabled', false)
+  config = direct ? config : get(config, 'prettify', {})
+
+  if (shouldPrettify) {
+    return pretty(html, config)
   }
 
   return html
diff --git a/src/transformers/prevent-widows.js b/src/transformers/prevent-widows.js
index dd9ff90..ffd2797 100644
--- a/src/transformers/prevent-widows.js
+++ b/src/transformers/prevent-widows.js
@@ -2,8 +2,12 @@ const {get} = require('lodash')
 const posthtml = require('posthtml')
 const preventWidows = require('prevent-widows')
 
-module.exports = async (html, config) => {
+module.exports = async (html, config = {}, direct = false) => {
   const posthtmlOptions = get(config, 'build.posthtml.options', {})
 
+  if (direct) {
+    return preventWidows(html)
+  }
+
   return posthtml([preventWidows.posthtml()]).process(html, posthtmlOptions).then(result => result.html)
 }
diff --git a/src/transformers/remove-attributes.js b/src/transformers/remove-attributes.js
index b9e17b4..2977fa2 100644
--- a/src/transformers/remove-attributes.js
+++ b/src/transformers/remove-attributes.js
@@ -2,8 +2,8 @@ const {get} = require('lodash')
 const posthtml = require('posthtml')
 const removeAttributes = require('posthtml-remove-attributes')
 
-module.exports = async (html, config) => {
-  const attributes = get(config, 'removeAttributes', [])
+module.exports = async (html, config = {}, direct = false) => {
+  const attributes = direct ? (Array.isArray(config) ? [...config] : []) : get(config, 'removeAttributes', [])
   const posthtmlOptions = get(config, 'build.posthtml.options', {})
 
   attributes.push({name: 'style'})
@@ -13,7 +13,5 @@ module.exports = async (html, config) => {
     attr.value = attr.value || ''
   })
 
-  html = await posthtml([removeAttributes(attributes)]).process(html, posthtmlOptions).then(result => result.html)
-
-  return html
+  return posthtml([removeAttributes(attributes)]).process(html, posthtmlOptions).then(result => result.html)
 }
diff --git a/src/transformers/remove-inline-bgcolor.js b/src/transformers/remove-inline-bgcolor.js
index 6108812..62cc5dd 100644
--- a/src/transformers/remove-inline-bgcolor.js
+++ b/src/transformers/remove-inline-bgcolor.js
@@ -2,9 +2,12 @@ const {get} = require('lodash')
 const posthtml = require('posthtml')
 const parseAttrs = require('posthtml-attrs-parser')
 
-module.exports = async (html, config) => {
+module.exports = async (html, config = {}, direct = false) => {
   const posthtmlOptions = get(config, 'build.posthtml.options', {})
-  const prefers = get(config, 'inlineCSS.preferBgColorAttribute', false)
+  const prefers = direct ? {
+    enabled: true,
+    tags: (Array.isArray(config) ? [...config] : false)
+  } : get(config, 'inlineCSS.preferBgColorAttribute', false)
 
   if ((typeof prefers === 'boolean' && prefers)) {
     return posthtml([removeInlineBGColor()]).process(html, posthtmlOptions).then(result => result.html)
diff --git a/src/transformers/remove-inline-sizes.js b/src/transformers/remove-inline-sizes.js
index df58a72..c2549ae 100644
--- a/src/transformers/remove-inline-sizes.js
+++ b/src/transformers/remove-inline-sizes.js
@@ -2,12 +2,12 @@ const posthtml = require('posthtml')
 const {get, isEmpty} = require('lodash')
 const parseAttrs = require('posthtml-attrs-parser')
 
-module.exports = async (html, config) => {
-  const settings = get(config, 'inlineCSS.keepOnlyAttributeSizes', {})
+module.exports = async (html, config = {}, direct = false) => {
+  const settings = direct ? config : get(config, 'inlineCSS.keepOnlyAttributeSizes', {})
 
   if (!isEmpty(settings)) {
     const posthtmlOptions = get(config, 'build.posthtml.options', {})
-    html = await posthtml([removeInlineSizes(settings)]).process(html, posthtmlOptions).then(result => result.html)
+    return posthtml([removeInlineSizes(settings)]).process(html, posthtmlOptions).then(result => result.html)
   }
 
   return html
diff --git a/src/transformers/remove-unused-css.js b/src/transformers/remove-unused-css.js
index 1825344..2cca6dd 100644
--- a/src/transformers/remove-unused-css.js
+++ b/src/transformers/remove-unused-css.js
@@ -1,9 +1,9 @@
 const {comb} = require('email-comb')
 
-module.exports = async (html, config) => {
-  const options = config.removeUnusedCSS || {}
+module.exports = async (html, config = {}, direct = false) => {
+  const options = direct ? config : config.removeUnusedCSS || {}
 
-  if (options.enabled) {
+  if (options.enabled || direct) {
     return comb(html, options).result
   }
 
diff --git a/src/transformers/replace-strings.js b/src/transformers/replace-strings.js
index 000269b..f6137d6 100644
--- a/src/transformers/replace-strings.js
+++ b/src/transformers/replace-strings.js
@@ -1,8 +1,10 @@
-const {isObject, isEmpty} = require('lodash')
+const {isEmpty, get} = require('lodash')
 
-module.exports = async (html, config) => {
-  if (isObject(config.replaceStrings) && !isEmpty(config.replaceStrings)) {
-    Object.entries(config.replaceStrings).forEach(([k, v]) => {
+module.exports = async (html, config = {}, direct = false) => {
+  const replacements = direct ? config : get(config, 'replaceStrings', {})
+
+  if (!isEmpty(replacements)) {
+    Object.entries(replacements).forEach(([k, v]) => {
       const regex = new RegExp(k, 'gi')
       html = html.replace(regex, v)
     })
diff --git a/src/transformers/safe-class-names.js b/src/transformers/safe-class-names.js
index b9ada12..825bec0 100644
--- a/src/transformers/safe-class-names.js
+++ b/src/transformers/safe-class-names.js
@@ -2,17 +2,17 @@ const {get} = require('lodash')
 const posthtml = require('posthtml')
 const safeClassNames = require('posthtml-safe-class-names')
 
-module.exports = async (html, config) => {
+module.exports = async (html, config = {}, direct = false) => {
   if (typeof config.safeClassNames === 'boolean' && !config.safeClassNames) {
     return html
   }
 
-  if (typeof config.env === 'string' && config.env !== 'local') {
-    const replacements = get(config, 'safeClassNames', {})
-    const posthtmlOptions = get(config, 'build.posthtml.options', {})
-
-    html = posthtml([safeClassNames({replacements})]).process(html, posthtmlOptions).then(result => result.html)
+  if (config.env === 'local') {
+    return html
   }
 
-  return html
+  const posthtmlOptions = get(config, 'build.posthtml.options', {})
+  const replacements = direct ? config : get(config, 'safeClassNames', {})
+
+  return posthtml([safeClassNames({replacements})]).process(html, posthtmlOptions).then(result => result.html)
 }
diff --git a/src/transformers/transform.js b/src/transformers/transform.js
index 744178b..e347991 100644
--- a/src/transformers/transform.js
+++ b/src/transformers/transform.js
@@ -1,10 +1,10 @@
 const {get} = require('lodash')
 const posthtml = require('posthtml')
-const Tailwind = require('../generators/tailwindcss')
 const posthtmlContent = require('posthtml-content')
+const Tailwind = require('../generators/tailwindcss')
 
-module.exports = async (html, config) => {
-  const replacements = config.transform || {}
+module.exports = async (html, config = {}, direct = false) => {
+  const replacements = direct ? config : get(config, 'transform', {})
   const posthtmlOptions = get(config, 'build.posthtml.options', {})
 
   replacements.postcss = css => Tailwind.compile(css, html, {}, config)
diff --git a/src/transformers/url-params.js b/src/transformers/url-params.js
index 3742716..933d14e 100644
--- a/src/transformers/url-params.js
+++ b/src/transformers/url-params.js
@@ -1,11 +1,11 @@
 const posthtml = require('posthtml')
-const {get, isObject, isEmpty} = require('lodash')
+const {get, isEmpty} = require('lodash')
 const urlParams = require('posthtml-url-parameters')
 
-module.exports = async (html, config) => {
-  const urlParameters = get(config, 'urlParameters', {})
+module.exports = async (html, config = {}, direct = false) => {
+  const urlParameters = direct ? config : get(config, 'urlParameters', {})
 
-  if (isObject(urlParameters) && !isEmpty(urlParameters)) {
+  if (!isEmpty(urlParameters)) {
     const {_options, ...parameters} = urlParameters
     const {tags, qs} = _options || {tags: ['a'], qs: {encode: false}}
     const posthtmlOptions = get(config, 'build.posthtml.options', {})


Test patch:
diff --git a/test/expected/attribute-to-style-tags.html b/test/expected/attribute-to-style-tags.html
deleted file mode 100644
index a665e07..0000000
--- a/test/expected/attribute-to-style-tags.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-
-
-  </head>
-<body>
-  <table class="text-xl" width="100%" height="600" bgcolor="#f0f0f0" background="https://example.com/image.jpg" align="left" style="width: 100%; font-size: 1.25rem;" cellpadding="0" cellspacing="0" role="presentation">
-    <tr>
-      <th valign="top">Test TH</th>
-      <th width="200" style="width: 200px">Empty</th>
-    </tr>
-    <tr>
-      <td width="600" height="600" bgcolor="#f0f0f0" background="https://example.com/image.jpg" align="center" valign="middle" style="width: 600px">
-        <img src="https://example.com/image.jpg" width="300" height="200" style="width: 300px" alt="">
-      </td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/test/expected/attribute-to-style.html b/test/expected/attribute-to-style.html
deleted file mode 100644
index 8261b7a..0000000
--- a/test/expected/attribute-to-style.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-
-
-  </head>
-<body>
-  <table class="text-xl" width="100%" height="600" bgcolor="#f0f0f0" background="https://example.com/image.jpg" align="center" style="width: 100%; height: 600px; background-color: #f0f0f0; background-image: url('https://example.com/image.jpg'); margin-left: auto; margin-right: auto; font-size: 1.25rem;" cellpadding="0" cellspacing="0" role="presentation">
-    <tr>
-      <th valign="top" style="vertical-align: top">Test TH</th>
-      <th width="200" style="width: 200px">Empty</th>
-    </tr>
-    <tr>
-      <td width="600" height="600" bgcolor="#f0f0f0" background="https://example.com/image.jpg" align="center" valign="middle" style="width: 600px; height: 600px; background-color: #f0f0f0; background-image: url('https://example.com/image.jpg'); text-align: center; vertical-align: middle">
-        <img src="https://example.com/image.jpg" width="300" height="200" style="width: 300px; height: 200px" alt="">
-      </td>
-    </tr>
-  </table>
-  <table align="left" style="float: left" cellpadding="0" cellspacing="0" role="presentation">
-    <tr>
-      <td>Float left table</td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/test/expected/base-image-url.html b/test/expected/base-image-url.html
deleted file mode 100644
index d1ad2ba..0000000
--- a/test/expected/base-image-url.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<img src="https://example.com/test.jpg" alt="">
-
-<div style="background-image: url('https://example.com/test.jpg')">Test</div>
-
-<div style="background-image: url(https://example.com/test.jpg)">Test</div>
-
-<table background="https://example.com/test.jpg" cellpadding="0" cellspacing="0" role="presentation">
-  <tr>
-    <td>Test</td>
-  </tr>
-</table>
diff --git a/test/expected/basic.html b/test/expected/basic.html
deleted file mode 100644
index 179f993..0000000
--- a/test/expected/basic.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<div>test</div>
diff --git a/test/expected/email-comb.html b/test/expected/email-comb.html
deleted file mode 100644
index 952d98b..0000000
--- a/test/expected/email-comb.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <style>.w-full {
-  width: 100% !important
-}
-.text-center {
-  text-align: center !important
-}
-      /*
-        @tab Page
-        @section Body Background
-        @tip Set the background colour for the email body.
-      */
-      table {
-        /*@editable*/background-color: #eeeeee !important;
-      }</style>
-  </head>
-<body>
-  <!-- An HTML comment to preserve -->
-  <table class="w-full" cellpadding="0" cellspacing="0" role="presentation">
-    <tr>
-      <td class="preserve-it text-center">Test</td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/test/expected/extra-attributes.html b/test/expected/extra-attributes.html
deleted file mode 100644
index 78f5523..0000000
--- a/test/expected/extra-attributes.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<div role="article" class="text-center">Test</div>
-
-<div role="article" class="text-center">Test</div>
diff --git a/test/expected/inline.html b/test/expected/inline.html
deleted file mode 100644
index 83d0724..0000000
--- a/test/expected/inline.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-
-    <style>.w-full {
-  width: 100% !important
-}
-
-.align-middle {
-  vertical-align: middle !important
-}
-
-.text-center {
-  text-align: center !important
-}
-
-.px-2 {
-  padding-left: 0.5rem !important;
-  padding-right: 0.5rem !important
-}
-
-.py-4 {
-  padding-top: 1rem !important;
-  padding-bottom: 1rem !important
-}
-
-.mx-2 {
-  margin-left: 0.5rem !important;
-  margin-right: 0.5rem !important
-}
-
-.my-4 {
-  margin-top: 1rem !important;
-  margin-bottom: 1rem !important
-}
-
-.h-full {
-  height: 100% !important
-}
-
-.table {
-  display: table !important
-}
-
-.cursor-move {
-  cursor: move !important
-}</style>
-  </head>
-<body>
-  <table class="w-full cursor-move text-center" style="width: 100%; text-align: center;" width="100%" align="center" cellpadding="0" cellspacing="0" role="presentation">
-    <tr>
-      <td class="h-full align-middle" style="vertical-align: middle; height: 100%;" height="100%">Test</td>
-    </tr>
-    <tr>
-      <td class="px-2 py-4" style="padding: 1rem 0.5rem;">
-        <div class="mx-2 my-4" style="margin: 1rem 0.5rem;">Test</div>
-        <p class="mx-2 my-4" style="margin-left: 0.5rem; margin-right: 0.5rem; margin-top: 1rem; margin-bottom: 1rem;">Test</p>
-      </td>
-    </tr>
-  </table>
-  <!--[if mso]><div class="text-center" style="text-align: center;">foo</div><![endif]-->
-</body>
-</html>
diff --git a/test/expected/minify.html b/test/expected/minify.html
deleted file mode 100644
index e173475..0000000
--- a/test/expected/minify.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<!DOCTYPE html><html><head><style>.w-full{width:100%!important}.table{display:table!important}</style></head><body>
-<table class="w-full" cellpadding="0" cellspacing="0" role="presentation"><tr><td>Test</td></tr></table></body></html>
diff --git a/test/expected/plaintext.html b/test/expected/plaintext.html
deleted file mode 100644
index 5e85b0a..0000000
--- a/test/expected/plaintext.html
+++ /dev/null
@@ -1,2 +0,0 @@
-
-<div>Will be preserved</div>
diff --git a/test/expected/prettify.html b/test/expected/prettify.html
deleted file mode 100644
index ab2e693..0000000
--- a/test/expected/prettify.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-
-  <head>
-
-    <style>
-      .w-full {
-        width: 100% !important
-      }
-
-      .table {
-        display: table !important
-      }
-    </style>
-  </head>
-
-  <body>
-    <table class="w-full" cellpadding="0" cellspacing="0" role="presentation">
-      <tr>
-        <td>Test</td>
-      </tr>
-    </table>
-  </body>
-
-</html>
diff --git a/test/expected/remove-attributes.html b/test/expected/remove-attributes.html
deleted file mode 100644
index 018cc25..0000000
--- a/test/expected/remove-attributes.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<div>Test</div>
diff --git a/test/expected/remove-inline-bgcolor-tags.html b/test/expected/remove-inline-bgcolor-tags.html
deleted file mode 100644
index 65ab4df..0000000
--- a/test/expected/remove-inline-bgcolor-tags.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-
-
-  </head>
-<body>
-  <table class="bg-blue-500" style="background-color: #4299e1;" bgcolor="#4299e1" cellpadding="0" cellspacing="0" role="presentation">
-    <tr>
-      <td class="bg-blue-500" bgcolor="#4299e1">Test</td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/test/expected/remove-inline-bgcolor.html b/test/expected/remove-inline-bgcolor.html
deleted file mode 100644
index a451774..0000000
--- a/test/expected/remove-inline-bgcolor.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-
-
-  </head>
-<body>
-  <table class="bg-blue-500" bgcolor="#4299e1" cellpadding="0" cellspacing="0" role="presentation">
-    <tr>
-      <td class="bg-blue-500" bgcolor="#4299e1">Test</td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/test/expected/remove-inline-sizes.html b/test/expected/remove-inline-sizes.html
deleted file mode 100644
index b977c36..0000000
--- a/test/expected/remove-inline-sizes.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-
-
-  </head>
-<body>
-  <table class="w-full" width="100%" cellpadding="0" cellspacing="0" role="presentation">
-    <tr>
-      <td class="h-full" height="100%">Test</td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/test/expected/replace-strings.html b/test/expected/replace-strings.html
deleted file mode 100644
index 78d2c2e..0000000
--- a/test/expected/replace-strings.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<div>replace strings test</div>
-
-<%= replace strings test %>
diff --git a/test/expected/safe-class-names-disabled.html b/test/expected/safe-class-names-disabled.html
deleted file mode 100644
index 1d006a4..0000000
--- a/test/expected/safe-class-names-disabled.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<div class="sm:w-full">test</div>
diff --git a/test/expected/safe-class-names.html b/test/expected/safe-class-names.html
deleted file mode 100644
index 8f64409..0000000
--- a/test/expected/safe-class-names.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<div class="sm-w-full">test</div>
diff --git a/test/expected/six-hex.html b/test/expected/six-hex.html
deleted file mode 100644
index b005179..0000000
--- a/test/expected/six-hex.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<div style="background: #000000;">test</div>
diff --git a/test/expected/transform.html b/test/expected/transform.html
deleted file mode 100644
index 4cc8369..0000000
--- a/test/expected/transform.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<div class="foo">LOREM IPSUM DOLOR SIT AMET</div>
diff --git a/test/expected/url-params.html b/test/expected/url-params.html
deleted file mode 100644
index 2915e35..0000000
--- a/test/expected/url-params.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<a href="https://example.com?campaign=@CampaignName@&source=email">Test</a>
diff --git a/test/fixtures/attribute-to-style-tags.html b/test/fixtures/attribute-to-style-tags.html
deleted file mode 100644
index 58e958e..0000000
--- a/test/fixtures/attribute-to-style-tags.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <if condition="page.css">
-    <style>{{{ page.css }}}</style>
-  </if>
-</head>
-<body>
-  <table class="text-xl" width="100%" height="600" bgcolor="#f0f0f0" background="https://example.com/image.jpg" align="left">
-    <tr>
-      <th valign="top">Test TH</th>
-      <th width="200">Empty</th>
-    </tr>
-    <tr>
-      <td width="600" height="600" bgcolor="#f0f0f0" background="https://example.com/image.jpg" align="center" valign="middle">
-        <img src="https://example.com/image.jpg" width="300" height="200">
-      </td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/test/fixtures/attribute-to-style.html b/test/fixtures/attribute-to-style.html
deleted file mode 100644
index fecfa52..0000000
--- a/test/fixtures/attribute-to-style.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <if condition="page.css">
-    <style>{{{ page.css }}}</style>
-  </if>
-</head>
-<body>
-  <table class="text-xl" width="100%" height="600" bgcolor="#f0f0f0" background="https://example.com/image.jpg" align="center">
-    <tr>
-      <th valign="top">Test TH</th>
-      <th width="200">Empty</th>
-    </tr>
-    <tr>
-      <td width="600" height="600" bgcolor="#f0f0f0" background="https://example.com/image.jpg" align="center" valign="middle">
-        <img src="https://example.com/image.jpg" width="300" height="200">
-      </td>
-    </tr>
-  </table>
-  <table align="left">
-    <tr>
-      <td>Float left table</td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/test/fixtures/base-image-url.html b/test/fixtures/base-image-url.html
deleted file mode 100644
index 4aff7c5..0000000
--- a/test/fixtures/base-image-url.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<img src="test.jpg" alt="">
-
-<div style="background-image: url('test.jpg')">Test</div>
-
-<div style="background-image: url(test.jpg)">Test</div>
-
-<table background="test.jpg">
-  <tr>
-    <td>Test</td>
-  </tr>
-</table>
diff --git a/test/fixtures/basic.html b/test/fixtures/basic.html
deleted file mode 100644
index 179f993..0000000
--- a/test/fixtures/basic.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<div>test</div>
diff --git a/test/fixtures/email-comb.html b/test/fixtures/email-comb.html
deleted file mode 100644
index 938bcab..0000000
--- a/test/fixtures/email-comb.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <if condition="page.css">
-    <style>
-      {{{ page.css }}}
-
-      /*
-        @tab Page
-        @section Body Background
-        @tip Set the background colour for the email body.
-      */
-      table {
-        /*@editable*/background-color: #EEEEEE !important;
-      }
-    </style>
-  </if>
-</head>
-<body>
-  <!-- An HTML comment to preserve -->
-  <table class="w-full">
-    <tr>
-      <td class="inexistent preserve-it text-center">Test</td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/test/fixtures/extra-attributes.html b/test/fixtures/extra-attributes.html
deleted file mode 100644
index f8a4cc0..0000000
--- a/test/fixtures/extra-attributes.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<div>Test</div>
-
-<div role="article">Test</div>
diff --git a/test/fixtures/inline.html b/test/fixtures/inline.html
deleted file mode 100644
index 0b0aed9..0000000
--- a/test/fixtures/inline.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <if condition="page.css">
-    <style>{{{ page.css }}}</style>
-  </if>
-</head>
-<body>
-  <table class="w-full cursor-move text-center">
-    <tr>
-      <td class="h-full align-middle">Test</td>
-    </tr>
-    <tr>
-      <td class="px-2 py-4">
-        <div class="mx-2 my-4">Test</div>
-        <p class="mx-2 my-4">Test</p>
-      </td>
-    </tr>
-  </table>
-  <outlook><div class="text-center">foo</div></outlook>
-</body>
-</html>
diff --git a/test/fixtures/minify.html b/test/fixtures/minify.html
deleted file mode 100644
index 6584741..0000000
--- a/test/fixtures/minify.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <if condition="page.css">
-    <style>{{{ page.css }}}</style>
-  </if>
-</head>
-<body>
-  <table class="w-full">
-    <tr>
-      <td>Test</td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/test/fixtures/plaintext.html b/test/fixtures/plaintext.html
deleted file mode 100644
index cc24301..0000000
--- a/test/fixtures/plaintext.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<plaintext>Will be removed</plaintext>
-<div>Will be preserved</div>
diff --git a/test/fixtures/prettify.html b/test/fixtures/prettify.html
deleted file mode 100644
index 3628ff8..0000000
--- a/test/fixtures/prettify.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <if condition="page.css">
-      <style>{{{ page.css }}}</style>
-    </if>
-  </head>
-<body>
-<table class="w-full">
-  <tr>
-    <td>Test</td>
-  </tr>
-</table>
-</body>
-</html>
diff --git a/test/fixtures/remove-attributes.html b/test/fixtures/remove-attributes.html
deleted file mode 100644
index 19b7516..0000000
--- a/test/fixtures/remove-attributes.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<div role="article" contenteditable>Test</div>
diff --git a/test/fixtures/remove-inline-bgcolor-tags.html b/test/fixtures/remove-inline-bgcolor-tags.html
deleted file mode 100644
index ddc55de..0000000
--- a/test/fixtures/remove-inline-bgcolor-tags.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <if condition="page.css">
-    <style>{{{ page.css }}}</style>
-  </if>
-</head>
-<body>
-  <table class="bg-blue-500">
-    <tr>
-      <td class="bg-blue-500">Test</td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/test/fixtures/remove-inline-bgcolor.html b/test/fixtures/remove-inline-bgcolor.html
deleted file mode 100644
index ddc55de..0000000
--- a/test/fixtures/remove-inline-bgcolor.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <if condition="page.css">
-    <style>{{{ page.css }}}</style>
-  </if>
-</head>
-<body>
-  <table class="bg-blue-500">
-    <tr>
-      <td class="bg-blue-500">Test</td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/test/fixtures/remove-inline-sizes.html b/test/fixtures/remove-inline-sizes.html
deleted file mode 100644
index 65bdd88..0000000
--- a/test/fixtures/remove-inline-sizes.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <if condition="page.css">
-    <style>{{{ page.css }}}</style>
-  </if>
-</head>
-<body>
-  <table class="w-full">
-    <tr>
-      <td class="h-full">Test</td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/test/fixtures/replace-strings.html b/test/fixtures/replace-strings.html
deleted file mode 100644
index 2839320..0000000
--- a/test/fixtures/replace-strings.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<div>test</div>
-
-{head} test {tail}
diff --git a/test/fixtures/safe-class-names-disabled.html b/test/fixtures/safe-class-names-disabled.html
deleted file mode 100644
index 1d006a4..0000000
--- a/test/fixtures/safe-class-names-disabled.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<div class="sm:w-full">test</div>
diff --git a/test/fixtures/safe-class-names.html b/test/fixtures/safe-class-names.html
deleted file mode 100644
index 1d006a4..0000000
--- a/test/fixtures/safe-class-names.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<div class="sm:w-full">test</div>
diff --git a/test/fixtures/six-hex.html b/test/fixtures/six-hex.html
deleted file mode 100644
index c51d152..0000000
--- a/test/fixtures/six-hex.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<div style="background: #000;">test</div>
diff --git a/test/fixtures/transform.html b/test/fixtures/transform.html
deleted file mode 100644
index 6e944b9..0000000
--- a/test/fixtures/transform.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<div class="foo" upper>Lorem ipsum dolor sit amet</div>
diff --git a/test/fixtures/url-params.html b/test/fixtures/url-params.html
deleted file mode 100644
index 8201b62..0000000
--- a/test/fixtures/url-params.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<a href="https://example.com">Test</a>
diff --git a/test/test-tostring.js b/test/test-tostring.js
index bff32fb..2af8a1a 100644
--- a/test/test-tostring.js
+++ b/test/test-tostring.js
@@ -10,10 +10,10 @@ const expected = file => readFileSync(path.join(__dirname, 'expected', `${file}.
 const renderString = (string, options = {}) => Maizzle.render(string, options).then(({html}) => html)
 
 test('compiles HTML string if no options are passed', async t => {
-  let html = await renderString(fixture('basic'))
+  let html = await renderString('<div>test</div>')
   html = html.replace(/[^\S\r\n]+$/gm, '').trim()
 
-  t.is(html, expected('basic').trim())
+  t.is(html, '<div>test</div>')
 })
 
 test('inheritance', async t => {
diff --git a/test/test-transformers.js b/test/test-transformers.js
index 311983c..aca09ba 100644
--- a/test/test-transformers.js
+++ b/test/test-transformers.js
@@ -2,224 +2,219 @@ const test = require('ava')
 const Maizzle = require('../src')
 const removePlaintextTags = require('../src/transformers/plaintext')
 
-const path = require('path')
-const {readFileSync} = require('fs')
-
-const fixture = file => readFileSync(path.join(__dirname, 'fixtures', `${file}.html`), 'utf8')
-const expected = file => readFileSync(path.join(__dirname, 'expected', `${file}.html`), 'utf8')
-
-const clean = html => html.replace(/[^\S\n]+$/gm, '').trim()
-
-const maizzleConfig = (options = {}) => {
-  return {
-    tailwind: {
-      config: {
-        corePlugins: {
-          animation: false,
-          backgroundOpacity: false,
-          borderOpacity: false,
-          divideOpacity: false,
-          placeholderOpacity: false,
-          textOpacity: false
-        }
-      }
-    },
-    maizzle: {
-      env: 'node',
-      ...options
-    }
+test('remove inline sizes', async t => {
+  const options = {
+    width: ['TD'],
+    height: ['TD']
   }
-}
 
-const processFile = (t, name, options = {}, log = false) => {
-  return Maizzle.render(fixture(name), {...options})
-    .then(({html}) => log ? console.log(html) : clean(html))
-    .then(html => t.is(html, expected(name).trim()))
-}
+  const html = await Maizzle.removeInlineSizes('<td style="width:100%;height:10px;">test</td>', options)
 
-test('remove inline sizes', t => {
-  return processFile(t, 'remove-inline-sizes', maizzleConfig({
-    inlineCSS: {
-      enabled: true,
-      applyWidthAttributes: ['TABLE'],
-      applyHeightAttributes: ['TD'],
-      keepOnlyAttributeSizes: {
-        width: ['TABLE'],
-        height: ['TD']
-      }
-    }
-  }))
+  t.is(html, '<td style="">test</td>')
 })
 
-test('remove inline background-color', t => {
-  return processFile(t, 'remove-inline-bgcolor', maizzleConfig({
-    inlineCSS: {
-      enabled: true,
-      styleToAttribute: {
-        'background-color': 'bgcolor'
-      },
-      preferBgColorAttribute: true
-    }
-  }))
+test('remove inline background-color', async t => {
+  const html = await Maizzle.removeInlineBgColor(`<td style="background-color: red" bgcolor="red">test</td>`)
+
+  t.is(html, '<td style="" bgcolor="red">test</td>')
 })
 
-test('remove inline background-color (with tags)', t => {
-  return processFile(t, 'remove-inline-bgcolor-tags', maizzleConfig({
-    inlineCSS: {
-      enabled: true,
-      styleToAttribute: {
-        'background-color': 'bgcolor'
-      },
-      preferBgColorAttribute: {
-        enabled: true,
-        tags: ['td']
-      }
-    }
-  }))
+test('remove inline background-color (with tags)', async t => {
+  const html = await Maizzle.removeInlineBgColor(`<table style="background-color: red"><tr><td style="background-color: red">test</td></tr></table>`, ['table'])
+
+  t.is(html, '<table style="" bgcolor="red"><tr><td style="background-color: red">test</td></tr></table>')
 })
 
-test('inline CSS', t => {
-  return processFile(t, 'inline', maizzleConfig({
-    inlineCSS: {
+test('inline CSS', async t => {
+  const html = `<div class="foo bar px-2 py-2"><% code %></div>`
+  const css = `
+    .foo {color: red}
+    .bar {cursor: pointer}
+    .px-2 {
+      padding-left: 2px;
+      padding-right: 2px;
+    }
+    .py-2 {
+      padding-top: 2px;
+      padding-bottom: 2px;
+    }
+  `
+
+  const result = await Maizzle.inlineCSS(html, {
+    enabled: true,
+    customCSS: css,
+    removeStyleTags: false,
+    styleToAttribute: {
+      'text-align': 'align'
+    },
+    applyWidthAttributes: ['TABLE'],
+    applyHeightAttributes: ['TD'],
+    mergeLonghand: {
       enabled: true,
-      removeStyleTags: false,
-      styleToAttribute: {
-        'text-align': 'align'
-      },
-      applyWidthAttributes: ['TABLE'],
-      applyHeightAttributes: ['TD'],
-      mergeLonghand: {
-        enabled: true,
-        tags: ['td', 'div']
-      },
-      excludedProperties: ['cursor'],
-      codeBlocks: {
-        ASP: {
-          start: '<%',
-          end: '%>'
-        }
+      tags: ['div']
+    },
+    excludedProperties: ['cursor'],
+    codeBlocks: {
+      ASP: {
+        start: '<%',
+        end: '%>'
       }
     }
-  }))
+  })
+
+  t.is(result, '<div class="foo bar px-2 py-2" style="color: red; padding: 2px;"><% code %></div>')
 })
 
-test('remove unused CSS', t => {
-  return processFile(t, 'email-comb', maizzleConfig({
-    removeUnusedCSS: {
-      enabled: true,
-      removeHTMLComments: false,
-      removeCSSComments: false,
-      whitelist: ['.preserve*']
-    }
-  }))
+test('remove unused CSS', async t => {
+  const html = `
+  <!DOCTYPE html>
+  <html>
+    <head>
+      <style>
+        .foo {color: red}
+        .bar-baz {color: blue}
+        .baz {color: white}
+      </style>
+    </head>
+    <body>
+      <div class="foo">test div with some text</div>
+    </body>
+  </html>
+  `
+
+  const result = await Maizzle.removeUnusedCSS(html, {whitelist: ['.bar*']})
+
+  t.is(result, `<!DOCTYPE html>
+  <html>
+    <head>
+      <style>
+        .foo {color: red}
+        .bar-baz {color: blue}
+      </style>
+    </head>
+    <body>
+      <div class="foo">test div with some text</div>
+    </body>
+  </html>`)
 })
 
-test('remove attributes', t => {
-  return processFile(t, 'remove-attributes', maizzleConfig({
-    removeAttributes: [
-      {name: 'role', value: 'article'},
-      {name: 'contenteditable'}
-    ]
-  }))
+test('remove attributes', async t => {
+  const html = await Maizzle.removeAttributes(`<div style="" role="article"></div>`, [{name: 'role', value: 'article'}])
+
+  t.is(html, '<div></div>')
 })
 
-test('extra attributes', t => {
-  return processFile(t, 'extra-attributes', maizzleConfig({
-    extraAttributes: {
-      div: {
-        role: 'article',
-        class: 'text-center'
-      }
-    }
-  }))
+test('extra attributes', async t => {
+  const html = await Maizzle.applyExtraAttributes('<div />', {div: {role: 'article'}})
+
+  t.is(html, '<div role="article"></div>')
 })
 
-test('base image URL', t => {
-  return processFile(t, 'base-image-url', maizzleConfig({
-    baseImageURL: 'https://example.com/'
-  }))
+test('base image URL', async t => {
+  const html = await Maizzle.applyBaseImageUrl('<img src="example.jpg">', 'https://example.com/')
+
+  t.is(html, '<img src="https://example.com/example.jpg">')
 })
 
-test('prettify', t => {
-  return processFile(t, 'prettify', maizzleConfig({
-    prettify: {
-      enabled: true,
-      indent_inner_html: true // eslint-disable-line
-    }
-  }))
+test('prettify', async t => {
+  // eslint-disable-next-line
+  const html = await Maizzle.prettify('<div><p>test</p></div>', {indent_inner_result: true})
+
+  t.is(html, '<div>\n  <p>test</p>\n</div>')
 })
 
-test('minify', t => {
-  return processFile(t, 'minify', maizzleConfig({
-    minify: {
-      enabled: true,
-      breakToTheLeftOf: ['<table']
-    }
-  }))
+test('minify', async t => {
+  const html = await Maizzle.minify('<div>\n\n<p>\n\ntest</p></div>', {lineLengthLimit: 10})
+  const expected = '<div><p>\ntest</p>\n</div>'
+
+  t.is(html, expected)
 })
 
 test('removes plaintext tag', t => {
-  let html = removePlaintextTags(fixture('plaintext'), {})
+  let html = removePlaintextTags('<plaintext>Removed</plaintext><div>Preserved</div>')
   html = html.replace(/[^\S\r\n]+$/gm, '').trim()
 
-  t.is(html, expected('plaintext').trim())
+  t.is(html, '<div>Preserved</div>')
 })
 
-test('replace strings', t => {
-  return processFile(t, 'replace-strings', maizzleConfig({
-    replaceStrings: {
-      test: 'replace strings test',
-      '{head}': '<%=',
-      '{tail}': '%>'
-    }
-  }))
+test('replace strings', async t => {
+  const html = await Maizzle.replaceStrings('initial text', {initial: 'updated'})
+
+  t.is(html, 'updated text')
 })
 
-test('safe class names', t => {
-  return processFile(t, 'safe-class-names', maizzleConfig())
+test('safe class names', async t => {
+  const html = await Maizzle.safeClassNames('<div class="sm:text-left w-1.5">foo</div>', {'.': '_dot_'})
+
+  t.is(html, '<div class="sm-text-left w-1_dot_5">foo</div>')
 })
 
-test('safe class names (disabled)', t => {
-  return processFile(t, 'safe-class-names-disabled', maizzleConfig({
-    safeClassNames: false
-  }))
+test('safe class names (disabled)', async t => {
+  const html = await Maizzle.safeClassNames('<div class="sm:text-left">foo</div>', {safeClassNames: false})
+
+  t.is(html, '<div class="sm:text-left">foo</div>')
 })
 
-test('six digit hex', t => {
-  return processFile(t, 'six-hex', maizzleConfig())
+test('six digit hex', async t => {
+  const html = await Maizzle.ensureSixHEX('<td style="color: #ffc" bgcolor="#000"></td>')
+
+  t.is(html, '<td style="color: #ffffcc" bgcolor="#000000"></td>');
 })
 
-test('transform contents', t => {
-  return processFile(t, 'transform', maizzleConfig({
-    transform: {
-      upper: text => text.toUpperCase()
-    }
-  }))
+test('transform contents', async t => {
+  const html = await Maizzle.transformContents('<div uppercase>test</div>', {uppercase: string => string.toUpperCase()})
+
+  t.is(html, '<div>TEST</div>')
 })
 
-test('url parameters', t => {
-  return processFile(t, 'url-params', maizzleConfig({
-    urlParameters: {
-      source: 'email',
-      campaign: '@CampaignName@'
-    }
-  }))
+test('url parameters', async t => {
+  const html = await Maizzle.addURLParams('<a href="https://example.com">test</a>', {bar: 'baz', qix: 'qux'})
+
+  t.is(html, '<a href="https://example.com?bar=baz&qix=qux">test</a>')
 })
 
-test('attribute to style', t => {
-  return processFile(t, 'attribute-to-style', maizzleConfig({
-    inlineCSS: {
-      enabled: true,
-      attributeToStyle: true
-    }
-  }))
+test('attribute to style', async t => {
+  const html = `<table width="100%" height="600" align="left" bgcolor="#FFFFFF" background="https://example.com/image.jpg">
+    <tr>
+      <td align="center" valign="top"></td>
+    </tr>
+  </table>`
+
+  const expected = `<table width="100%" height="600" align="left" bgcolor="#FFFFFF" background="https://example.com/image.jpg" style="width: 100%; height: 600px; float: left; background-color: #FFFFFF; background-image: url('https://example.com/image.jpg')">
+    <tr style="">
+      <td align="center" valign="top" style="text-align: center; vertical-align: top"></td>
+    </tr>
+  </table>`
+
+  const expectedWithAttrs = `<table width="100%" height="600" align="left" bgcolor="#FFFFFF" background="https://example.com/image.jpg" style="width: 100%">
+    <tr style="">
+      <td align="center" valign="top" style=""></td>
+    </tr>
+  </table>`
+
+  const html2 = `<table align="center">
+    <tr>
+      <td></td>
+    </tr>
+  </table>`
+
+  const expected2 = `<table align="center" style="margin-left: auto; margin-right: auto">
+    <tr style="">
+      <td style=""></td>
+    </tr>
+  </table>`
+
+  const result = await Maizzle.attributeToStyle(html, ['width', 'height', 'bgcolor', 'background', 'align', 'valign'])
+  const result2 = await Maizzle.attributeToStyle(html2, ['align'])
+  const withAttrs = await Maizzle.attributeToStyle(html, ['width'])
+
+  t.is(result, expected)
+  t.is(result2, expected2)
+  t.is(withAttrs, expectedWithAttrs)
 })
 
-test('attribute to style (with tags)', t => {
-  return processFile(t, 'attribute-to-style-tags', maizzleConfig({
-    inlineCSS: {
-      enabled: true,
-      attributeToStyle: ['width']
-    }
-  }))
+test('prevent widows', async t => {
+  const html = await Maizzle.preventWidows('lorem ipsum dolor')
+
+  t.is(html, 'lorem ipsum&nbsp;dolor')
 })