Repository: maizzle/framework
Pull request #789 (2022-10-10 15:30:06)

refactor: use default posthtml options
This PR adds default PostHTML options, helping fix an issue with valueless attributes like `<div data-id>` being rewritten to contain an empty value, i.e. `<div data-id=""`.


Patch:
diff --git a/src/generators/plaintext.js b/src/generators/plaintext.js
index 8379082..46b03db 100644
--- a/src/generators/plaintext.js
+++ b/src/generators/plaintext.js
@@ -1,11 +1,12 @@
 const path = require('path')
-const {get} = require('lodash')
 const posthtml = require('posthtml')
+const {get, merge} = require('lodash')
 const {stripHtml} = require('string-strip-html')
+const defaultConfig = require('./posthtml/defaultConfig')
 
 const self = {
   handleCustomTags: (html, config = {}) => {
-    const posthtmlOptions = get(config, 'build.posthtml.options', {})
+    const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
 
     const posthtmlPlugin = () => tree => {
       const process = node => {
diff --git a/src/generators/posthtml/defaultConfig.js b/src/generators/posthtml/defaultConfig.js
new file mode 100644
index 0000000..5ce8007
--- /dev/null
+++ b/src/generators/posthtml/defaultConfig.js
@@ -0,0 +1,3 @@
+module.exports = {
+  recognizeNoValueAttribute: true
+}
diff --git a/src/generators/posthtml.js b/src/generators/posthtml/index.js
similarity index 92%
rename from src/generators/posthtml.js
rename to src/generators/posthtml/index.js
index 2a3d6d3..9824831 100644
--- a/src/generators/posthtml.js
+++ b/src/generators/posthtml/index.js
@@ -4,6 +4,7 @@ const {get, merge} = require('lodash')
 const fetch = require('posthtml-fetch')
 const layouts = require('posthtml-extend')
 const modules = require('posthtml-modules')
+const defaultConfig = require('./defaultConfig')
 const expressions = require('posthtml-expressions')
 
 module.exports = async (html, config) => {
@@ -14,7 +15,7 @@ module.exports = async (html, config) => {
   const modulesRoot = modulesOptions.root || './'
   const modulesFrom = modulesOptions.from || `${modulesRoot}/fake`
 
-  const posthtmlOptions = merge({recognizeNoValueAttribute: true}, get(config, 'build.posthtml.options', {}))
+  const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
   const posthtmlPlugins = get(config, 'build.posthtml.plugins', [])
 
   const expressionsOptions = merge({strictMode: false}, get(config, 'build.posthtml.expressions', {}))
diff --git a/src/transformers/attributeToStyle.js b/src/transformers/attributeToStyle.js
index 16f643a..e39a734 100644
--- a/src/transformers/attributeToStyle.js
+++ b/src/transformers/attributeToStyle.js
@@ -1,9 +1,10 @@
 const posthtml = require('posthtml')
 const parseAttrs = require('posthtml-attrs-parser')
-const {get, forEach, intersection, keys, isEmpty} = require('lodash')
+const defaultConfig = require('../generators/posthtml/defaultConfig')
+const {get, merge, forEach, intersection, keys, isEmpty} = require('lodash')
 
 module.exports = async (html, config = {}, direct = false) => {
-  const posthtmlOptions = get(config, 'build.posthtml.options', {})
+  const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
   const attributes = get(config, 'inlineCSS.attributeToStyle', false)
 
   if (typeof attributes === 'boolean' && attributes) {
diff --git a/src/transformers/baseUrl.js b/src/transformers/baseUrl.js
index 59abac0..023251c 100644
--- a/src/transformers/baseUrl.js
+++ b/src/transformers/baseUrl.js
@@ -1,7 +1,33 @@
 const posthtml = require('posthtml')
 const isUrl = require('is-url-superb')
 const baseUrl = require('posthtml-base-url')
-const {get, isObject, isEmpty} = require('lodash')
+const {get, merge, isObject, isEmpty} = require('lodash')
+const defaultConfig = require('../generators/posthtml/defaultConfig')
+
+module.exports = async (html, config = {}, direct = false) => {
+  const url = direct ? config : get(config, 'baseURL')
+  const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
+
+  // Handle `baseUrl` as a string
+  if (typeof url === 'string' && url.length > 0) {
+    html = rewriteVMLs(html, url)
+
+    return posthtml([
+      baseUrl({url, allTags: true, styleTag: true, inlineCss: true})
+    ])
+      .process(html, posthtmlOptions)
+      .then(result => result.html)
+  }
+
+  // Handle `baseUrl` as an object
+  if (isObject(url) && !isEmpty(url)) {
+    html = rewriteVMLs(html, url.url)
+
+    return posthtml([baseUrl(url)]).process(html, posthtmlOptions).then(result => result.html)
+  }
+
+  return html
+}
 
 /**
  * VML backgrounds must be handled with regex because
@@ -42,28 +68,3 @@ const rewriteVMLs = (html, url) => {
 
   return html
 }
-
-module.exports = async (html, config = {}, direct = false) => {
-  const url = direct ? config : get(config, 'baseURL')
-  const posthtmlOptions = get(config, 'build.posthtml.options', {})
-
-  // Handle `baseUrl` as a string
-  if (typeof url === 'string' && url.length > 0) {
-    html = rewriteVMLs(html, url)
-
-    return posthtml([
-      baseUrl({url, allTags: true, styleTag: true, inlineCss: true})
-    ])
-      .process(html, posthtmlOptions)
-      .then(result => result.html)
-  }
-
-  // Handle `baseUrl` as an object
-  if (isObject(url) && !isEmpty(url)) {
-    html = rewriteVMLs(html, url.url)
-
-    return posthtml([baseUrl(url)]).process(html, posthtmlOptions).then(result => result.html)
-  }
-
-  return html
-}
diff --git a/src/transformers/extraAttributes.js b/src/transformers/extraAttributes.js
index 1a7f423..c4725f1 100644
--- a/src/transformers/extraAttributes.js
+++ b/src/transformers/extraAttributes.js
@@ -1,13 +1,14 @@
 const posthtml = require('posthtml')
-const {get, isObject} = require('lodash')
+const {get, merge, isObject} = require('lodash')
 const addAttributes = require('posthtml-extra-attributes')
+const defaultConfig = require('../generators/posthtml/defaultConfig')
 
 module.exports = async (html, config = {}, direct = false) => {
   if (get(config, 'extraAttributes') === false) {
     return html
   }
 
-  const posthtmlOptions = get(config, 'build.posthtml.options', {})
+  const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
 
   let attributes = {
     table: {
diff --git a/src/transformers/filters/index.js b/src/transformers/filters/index.js
index 495ccb1..83e7e94 100644
--- a/src/transformers/filters/index.js
+++ b/src/transformers/filters/index.js
@@ -5,13 +5,14 @@ const PostCSS = require('../../generators/postcss')
 const posthtmlContent = require('posthtml-content')
 const Tailwind = require('../../generators/tailwindcss')
 const safeClassNames = require('posthtml-safe-class-names')
+const defaultConfig = require('../../generators/posthtml/defaultConfig')
 
 module.exports = async (html, config = {}, direct = false) => {
   const filters = direct ?
     merge(defaultFilters, config) :
     merge(defaultFilters, get(config, 'filters', {}))
 
-  const posthtmlOptions = get(config, 'build.posthtml.options', {})
+  const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
 
   /**
    * Compile CSS in <style {post|tailwind}css> tags
diff --git a/src/transformers/markdown.js b/src/transformers/markdown.js
index 664ee64..43397e0 100644
--- a/src/transformers/markdown.js
+++ b/src/transformers/markdown.js
@@ -1,6 +1,7 @@
 const posthtml = require('posthtml')
 const {get, merge} = require('lodash')
 const markdown = require('posthtml-markdownit')
+const defaultConfig = require('../generators/posthtml/defaultConfig')
 
 module.exports = async (html, config = {}, direct = false) => {
   if (get(config, 'markdown') === false) {
@@ -8,7 +9,7 @@ module.exports = async (html, config = {}, direct = false) => {
   }
 
   const userMarkdownOptions = direct ? config : get(config, 'markdown', {})
-  const posthtmlOptions = get(config, 'build.posthtml.options', {})
+  const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
   const markdownOptions = merge({markdownit: {html: true}}, userMarkdownOptions)
 
   return posthtml([
diff --git a/src/transformers/posthtmlMso.js b/src/transformers/posthtmlMso.js
index c2b4c83..f7b589f 100644
--- a/src/transformers/posthtmlMso.js
+++ b/src/transformers/posthtmlMso.js
@@ -1,10 +1,11 @@
-const {get} = require('lodash')
 const posthtml = require('posthtml')
+const {get, merge} = require('lodash')
 const outlook = require('posthtml-mso')
+const defaultConfig = require('../generators/posthtml/defaultConfig')
 
 module.exports = async (html, config) => {
   const outlookOptions = get(config, 'build.posthtml.outlook', {})
-  const posthtmlOptions = get(config, 'build.posthtml.options', {})
+  const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
 
   return posthtml([outlook({...outlookOptions})]).process(html, posthtmlOptions).then(result => result.html)
 }
diff --git a/src/transformers/preventWidows.js b/src/transformers/preventWidows.js
index 4bc02b7..5a0e3d9 100644
--- a/src/transformers/preventWidows.js
+++ b/src/transformers/preventWidows.js
@@ -1,13 +1,14 @@
 const posthtml = require('posthtml')
-const {get, isEmpty} = require('lodash')
+const {get, merge, isEmpty} = require('lodash')
 const {removeWidows} = require('string-remove-widows')
+const defaultConfig = require('../generators/posthtml/defaultConfig')
 
 module.exports = async (html, config = {}) => {
   if (isEmpty(config)) {
     return removeWidows(html).res
   }
 
-  const posthtmlOptions = get(config, 'build.posthtml.options', {recognizeNoValueAttribute: true})
+  const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
 
   return posthtml([removeWidowsPlugin(config)]).process(html, posthtmlOptions).then(result => result.html)
 }
diff --git a/src/transformers/removeAttributes.js b/src/transformers/removeAttributes.js
index e34d293..9e7024e 100644
--- a/src/transformers/removeAttributes.js
+++ b/src/transformers/removeAttributes.js
@@ -1,10 +1,11 @@
-const {get} = require('lodash')
 const posthtml = require('posthtml')
+const {get, merge} = require('lodash')
 const removeAttributes = require('posthtml-remove-attributes')
+const defaultConfig = require('../generators/posthtml/defaultConfig')
 
 module.exports = async (html, config = {}, direct = false) => {
   const attributes = direct ? (Array.isArray(config) ? [...config] : []) : get(config, 'removeAttributes', [])
-  const posthtmlOptions = get(config, 'build.posthtml.options', {})
+  const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
 
   attributes.push({name: 'style'}, {name: 'class'})
 
diff --git a/src/transformers/removeInlineBackgroundColor.js b/src/transformers/removeInlineBackgroundColor.js
index a649657..777f99c 100644
--- a/src/transformers/removeInlineBackgroundColor.js
+++ b/src/transformers/removeInlineBackgroundColor.js
@@ -1,10 +1,11 @@
 const posthtml = require('posthtml')
-const {get, isEmpty} = require('lodash')
+const {get, merge, isEmpty} = require('lodash')
 const parseAttrs = require('posthtml-attrs-parser')
 const {toStyleString} = require('../utils/helpers')
+const defaultConfig = require('../generators/posthtml/defaultConfig')
 
 module.exports = async (html, config = {}, direct = false) => {
-  const posthtmlOptions = get(config, 'build.posthtml.options', {})
+  const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
 
   if (isEmpty(config)) {
     return posthtml([removeInlineBGColor()]).process(html, posthtmlOptions).then(result => result.html)
diff --git a/src/transformers/removeInlineSizes.js b/src/transformers/removeInlineSizes.js
index 98392d7..2fc377a 100644
--- a/src/transformers/removeInlineSizes.js
+++ b/src/transformers/removeInlineSizes.js
@@ -1,13 +1,15 @@
 const posthtml = require('posthtml')
-const {get, isEmpty} = require('lodash')
+const {get, merge, isEmpty} = require('lodash')
 const parseAttrs = require('posthtml-attrs-parser')
 const {toStyleString} = require('../utils/helpers')
+const defaultConfig = require('../generators/posthtml/defaultConfig')
 
 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', {})
+    const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
+
     return posthtml([removeInlineSizes(settings)]).process(html, posthtmlOptions).then(result => result.html)
   }
 
diff --git a/src/transformers/removeInlinedSelectors.js b/src/transformers/removeInlinedSelectors.js
index ec484ae..b76f256 100644
--- a/src/transformers/removeInlinedSelectors.js
+++ b/src/transformers/removeInlinedSelectors.js
@@ -1,15 +1,17 @@
-const {get, has, remove} = require('lodash')
 const postcss = require('postcss')
 const posthtml = require('posthtml')
+const {get, merge, has, remove} = require('lodash')
 const parseAttrs = require('posthtml-attrs-parser')
 const matchHelper = require('posthtml-match-helper')
+const defaultConfig = require('../generators/posthtml/defaultConfig')
 
 module.exports = async (html, config = {}) => {
   if (get(config, 'removeInlinedClasses') === false) {
     return html
   }
 
-  const posthtmlOptions = get(config, 'build.posthtml.options', {})
+  const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
+
   return posthtml([plugin(posthtmlOptions)]).process(html, posthtmlOptions).then(result => result.html)
 }
 
diff --git a/src/transformers/replaceStrings.js b/src/transformers/replaceStrings.js
index f6137d6..767cce0 100644
--- a/src/transformers/replaceStrings.js
+++ b/src/transformers/replaceStrings.js
@@ -1,4 +1,4 @@
-const {isEmpty, get} = require('lodash')
+const {get, isEmpty} = require('lodash')
 
 module.exports = async (html, config = {}, direct = false) => {
   const replacements = direct ? config : get(config, 'replaceStrings', {})
diff --git a/src/transformers/safeClassNames.js b/src/transformers/safeClassNames.js
index cc996fd..7987d69 100644
--- a/src/transformers/safeClassNames.js
+++ b/src/transformers/safeClassNames.js
@@ -1,6 +1,7 @@
-const {get} = require('lodash')
 const posthtml = require('posthtml')
+const {get, merge} = require('lodash')
 const safeClassNames = require('posthtml-safe-class-names')
+const defaultConfig = require('../generators/posthtml/defaultConfig')
 
 module.exports = async (html, config = {}, direct = false) => {
   const option = get(config, 'safeClassNames')
@@ -17,7 +18,7 @@ module.exports = async (html, config = {}, direct = false) => {
     return html
   }
 
-  const posthtmlOptions = get(config, 'build.posthtml.options', {})
+  const posthtmlOptions = merge(defaultConfig, 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/shorthandInlineCSS.js b/src/transformers/shorthandInlineCSS.js
index ef7b65f..47d1ebf 100644
--- a/src/transformers/shorthandInlineCSS.js
+++ b/src/transformers/shorthandInlineCSS.js
@@ -1,11 +1,12 @@
 const posthtml = require('posthtml')
-const {get, isObject, isEmpty} = require('lodash')
+const {get, merge, isObject, isEmpty} = require('lodash')
 const mergeLonghand = require('posthtml-postcss-merge-longhand')
+const defaultConfig = require('../generators/posthtml/defaultConfig')
 
 module.exports = async (html, config, direct = false) => {
   config = direct ? (isObject(config) ? config : true) : get(config, 'shorthandInlineCSS', [])
 
-  const posthtmlOptions = get(config, 'build.posthtml.options', {})
+  const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
 
   if (typeof config === 'boolean' && config) {
     html = await posthtml([mergeLonghand()]).process(html, posthtmlOptions).then(result => result.html)
diff --git a/src/transformers/sixHex.js b/src/transformers/sixHex.js
index 966fb03..145e0c0 100644
--- a/src/transformers/sixHex.js
+++ b/src/transformers/sixHex.js
@@ -1,13 +1,15 @@
-const {get} = require('lodash')
 const posthtml = require('posthtml')
+const {get, merge} = require('lodash')
 const {conv} = require('color-shorthand-hex-to-six-digit')
+const defaultConfig = require('../generators/posthtml/defaultConfig')
 
 module.exports = async (html, config = {}) => {
   if (get(config, 'sixHex') === false) {
     return html
   }
 
-  const posthtmlOptions = get(config, 'build.posthtml.options', {})
+  const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
+
   return posthtml([sixHex()]).process(html, posthtmlOptions).then(result => result.html)
 }
 
diff --git a/src/transformers/urlParameters.js b/src/transformers/urlParameters.js
index b57bf84..56e1629 100644
--- a/src/transformers/urlParameters.js
+++ b/src/transformers/urlParameters.js
@@ -1,12 +1,13 @@
 const posthtml = require('posthtml')
-const {get, isEmpty} = require('lodash')
+const {get, merge, isEmpty} = require('lodash')
 const urlParams = require('posthtml-url-parameters')
+const defaultConfig = require('../generators/posthtml/defaultConfig')
 
 module.exports = async (html, config = {}, direct = false) => {
   const urlParameters = direct ? config : get(config, 'urlParameters', {})
 
   if (!isEmpty(urlParameters)) {
-    const posthtmlOptions = get(config, 'build.posthtml.options', {})
+    const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
     const {_options, ...parameters} = urlParameters
     const tags = get(_options, 'tags', ['a'])
     const strict = get(_options, 'strict', true)


Test patch:
diff --git a/test/expected/transformers/base-url.html b/test/expected/transformers/base-url.html
index a6bc3c1..133f4da 100644
--- a/test/expected/transformers/base-url.html
+++ b/test/expected/transformers/base-url.html
@@ -39,7 +39,7 @@
     <video width="250" poster="https://example.com/flower.jpg">
       <source src="https://example.com/media/flower.webm" type="video/webm">
       <source src="https://example.tv/media/flower.mp4" type="video/mp4">
-      <track default="" kind="captions" srclang="en" src="https://example.com/media/tracks/friday.vtt">
+      <track default kind="captions" srclang="en" src="https://example.com/media/tracks/friday.vtt">
     </video>
 
     <audio src="https://example.com/media/sample.mp3">
diff --git a/test/test-transformers.js b/test/test-transformers.js
index 1f07991..b2b649e 100644
--- a/test/test-transformers.js
+++ b/test/test-transformers.js
@@ -534,10 +534,8 @@ test('remove inlined selectors', async t => {
 
   const basic = await Maizzle.removeInlinedClasses(html)
 
-  const expectedBasic = expectedWithOptions.replace('no-value', 'no-value=""')
-
   t.is(withPostHTMLOptions, expectedWithOptions)
-  t.is(basic, expectedBasic)
+  t.is(basic, expectedWithOptions)
 })
 
 test('remove inlined selectors (disabled)', async t => {