@maizzle/framework 4.1.2 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maizzle/framework",
3
- "version": "4.1.2",
3
+ "version": "4.2.0",
4
4
  "description": "Maizzle is a framework that helps you quickly build HTML emails with Tailwind CSS.",
5
5
  "license": "MIT",
6
6
  "main": "src/index.js",
@@ -3,7 +3,6 @@ const fs = require('fs-extra')
3
3
  const glob = require('glob-promise')
4
4
  const {get, isEmpty, merge} = require('lodash')
5
5
  const {asyncForEach} = require('../../utils/helpers')
6
- const removePlaintextTags = require('../../transformers/plaintext')
7
6
 
8
7
  const Config = require('../config')
9
8
  const Tailwind = require('../tailwindcss')
@@ -123,7 +122,8 @@ module.exports = async (env, spinner, config) => {
123
122
  * tags from the markup before outputting the file.
124
123
  */
125
124
 
126
- const plaintextConfig = get(templateConfig, 'plaintext')
125
+ // Check if plaintext: true globally, fallback to template's front matter
126
+ const plaintextConfig = get(templateConfig, 'plaintext', get(compiled.config, 'plaintext', false))
127
127
  const plaintextPath = get(plaintextConfig, 'destination.path', config.permalink || file)
128
128
 
129
129
  if (Boolean(plaintextConfig) || !isEmpty(plaintextConfig)) {
@@ -133,11 +133,12 @@ module.exports = async (env, spinner, config) => {
133
133
  plaintextPath,
134
134
  merge(plaintextConfig, {filepath: file})
135
135
  )
136
- .then(({plaintext, destination}) => fs.outputFile(destination, plaintext))
136
+ .then(async ({html, plaintext, destination}) => {
137
+ compiled.html = html
138
+ await fs.outputFile(destination, plaintext)
139
+ })
137
140
  }
138
141
 
139
- compiled.html = removePlaintextTags(compiled.html, config)
140
-
141
142
  /**
142
143
  * Output file
143
144
  */
@@ -1,49 +1,84 @@
1
1
  const path = require('path')
2
2
  const {get} = require('lodash')
3
+ const posthtml = require('posthtml')
3
4
  const {stripHtml} = require('string-strip-html')
4
5
 
5
- module.exports.generate = async (html, destination, config) => {
6
- const configDestinationPath = get(config, 'destination.path')
7
- const extension = get(config, 'destination.extension', 'txt')
6
+ const self = {
7
+ handleCustomTags: (html, config = {}) => {
8
+ const posthtmlOptions = get(config, 'build.posthtml.options', {})
8
9
 
9
- const plaintext = stripHtml(html, {
10
- dumpLinkHrefsNearby: {
11
- enabled: true
12
- },
13
- ...get(config, 'options', {})
14
- }).result
10
+ const posthtmlPlugin = () => tree => {
11
+ const process = node => {
12
+ if (node.tag === 'plaintext') {
13
+ return {
14
+ tag: false,
15
+ content: ['']
16
+ }
17
+ }
15
18
 
16
- // If we set plaintext.destination.path in config/fm
17
- if (configDestinationPath) {
18
- /**
19
- * Using a file path will generate a single plaintext file,
20
- * no matter how many templates there are.
21
- *
22
- * It will be based on the last-processed template.
23
- */
24
- if (path.extname(configDestinationPath)) {
25
- destination = configDestinationPath
19
+ if (node.tag === 'not-plaintext') {
20
+ return {
21
+ tag: false,
22
+ content: tree.render(node.content)
23
+ }
24
+ }
25
+
26
+ return node
27
+ }
28
+
29
+ return tree.walk(process)
30
+ }
31
+
32
+ return posthtml([posthtmlPlugin()]).process(html, {...posthtmlOptions, sync: true}).html
33
+ },
34
+ generate: async (html, destination, config) => {
35
+ const configDestinationPath = get(config, 'destination.path')
36
+ const extension = get(config, 'destination.extension', 'txt')
37
+
38
+ const plaintext = stripHtml(html, {
39
+ dumpLinkHrefsNearby: {
40
+ enabled: true
41
+ },
42
+ stripTogetherWithTheirContents: ['script', 'style', 'xml', 'not-plaintext'],
43
+ ...get(config, 'options', {})
44
+ }).result
45
+
46
+ html = self.handleCustomTags(html, config)
26
47
 
27
- return {plaintext, destination}
48
+ // If we set plaintext.destination.path in config/fm
49
+ if (configDestinationPath) {
50
+ /**
51
+ * Using a file path will generate a single plaintext file,
52
+ * no matter how many templates there are.
53
+ *
54
+ * It will be based on the last-processed template.
55
+ */
56
+ if (path.extname(configDestinationPath)) {
57
+ destination = configDestinationPath
58
+
59
+ return {html, plaintext, destination}
60
+ }
61
+
62
+ /**
63
+ * Using a directory-like path for plaintext.destination.path
64
+ */
65
+ destination = path.join(configDestinationPath, path.basename(config.filepath, path.extname(config.filepath)) + '.' + extension)
66
+
67
+ return {html, plaintext, destination}
28
68
  }
29
69
 
30
70
  /**
31
- * Using a directory-like path for plaintext.destination.path
71
+ * Use template's `permalink` Front Matter key,
72
+ * fall back to the original `destination`.
32
73
  */
33
- destination = path.join(configDestinationPath, path.basename(config.filepath, path.extname(config.filepath)) + '.' + extension)
34
-
35
- return {plaintext, destination}
36
- }
74
+ destination = get(config, 'permalink', destination)
37
75
 
38
- /**
39
- * Use template's `permalink` Front Matter key,
40
- * fall back to the original `destination`.
41
- */
42
- destination = get(config, 'permalink', destination)
76
+ if (typeof destination === 'string') {
77
+ destination = path.join(path.dirname(destination), path.basename(destination, path.extname(destination)) + '.' + extension)
78
+ }
43
79
 
44
- if (typeof destination === 'string') {
45
- destination = path.join(path.dirname(destination), path.basename(destination, path.extname(destination)) + '.' + extension)
80
+ return {html, plaintext, destination}
46
81
  }
47
-
48
- return {plaintext, destination}
49
82
  }
83
+
84
+ module.exports = self
@@ -0,0 +1,9 @@
1
+ ---
2
+ plaintext: true
3
+ ---
4
+
5
+ <div>Show in HTML</div>
6
+ <plaintext>Show in plaintext</plaintext>
7
+ <not-plaintext>
8
+ <table><tr><td>Remove from plaintext</td></tr></table>
9
+ </not-plaintext>
@@ -1,2 +1,5 @@
1
1
  <div>Show in HTML</div>
2
2
  <plaintext>Show in plaintext</plaintext>
3
+ <not-plaintext>
4
+ <table><tr><td>Remove from plaintext</td></tr></table>
5
+ </not-plaintext>
@@ -94,7 +94,7 @@ test('outputs files at the correct location if multiple template sources are use
94
94
  })
95
95
 
96
96
  t.true(await fs.pathExists(t.context.folder))
97
- t.is(files.length, 3)
97
+ t.is(files.length, 5)
98
98
  })
99
99
 
100
100
  test('copies all files in the `filetypes` option to destination', async t => {
@@ -154,23 +154,49 @@ test('outputs plaintext files', async t => {
154
154
  path: t.context.folder
155
155
  },
156
156
  plaintext: true
157
- },
158
- tailwind: {
159
- config: {
160
- purge: false
157
+ }
158
+ },
159
+ extraAttributes: false
160
+ })
161
+
162
+ t.true(files.includes(`${t.context.folder}/plaintext.txt`))
163
+
164
+ t.is(
165
+ await fs.readFile(`${t.context.folder}/plaintext.txt`, 'utf8'),
166
+ 'Show in HTML\nShow in plaintext'
167
+ )
168
+
169
+ t.is(
170
+ await fs.readFile(`${t.context.folder}/plaintext.html`, 'utf8'),
171
+ '<div>Show in HTML</div>\n\n\n <table><tr><td>Remove from plaintext</td></tr></table>\n\n'
172
+ )
173
+ })
174
+
175
+ test('outputs plaintext files (front matter)', async t => {
176
+ const {files} = await Maizzle.build('maizzle-ci', {
177
+ fail: 'silent',
178
+ build: {
179
+ templates: {
180
+ source: 'test/stubs/plaintext',
181
+ destination: {
182
+ path: t.context.folder
161
183
  }
162
184
  }
163
- }
185
+ },
186
+ extraAttributes: false
164
187
  })
165
188
 
166
- const plaintext = files.filter(file => file.includes('.txt'))
167
- const html = files.filter(file => file.includes('.html'))
168
- const plaintextContent = await fs.readFile(plaintext[0], 'utf8')
169
- const htmlContent = await fs.readFile(html[0], 'utf8')
189
+ t.true(files.includes(`${t.context.folder}/front-matter.txt`))
170
190
 
171
- t.is(plaintext[0], `${t.context.folder}/plaintext.txt`)
172
- t.is(plaintextContent, 'Show in HTML\nShow in plaintext')
173
- t.is(htmlContent, '<div>Show in HTML</div>\n\n')
191
+ t.is(
192
+ await fs.readFile(`${t.context.folder}/front-matter.txt`, 'utf8'),
193
+ 'Show in HTML\nShow in plaintext'
194
+ )
195
+
196
+ t.is(
197
+ await fs.readFile(`${t.context.folder}/front-matter.html`, 'utf8'),
198
+ '<div>Show in HTML</div>\n\n\n <table><tr><td>Remove from plaintext</td></tr></table>\n\n'
199
+ )
174
200
  })
175
201
 
176
202
  test('outputs plaintext files (custom path)', async t => {
@@ -187,18 +213,11 @@ test('outputs plaintext files (custom path)', async t => {
187
213
  path: `${t.context.folder}/nested/plain.text`
188
214
  }
189
215
  }
190
- },
191
- tailwind: {
192
- config: {
193
- purge: false
194
- }
195
216
  }
196
217
  }
197
218
  })
198
219
 
199
- const plaintext = files.filter(file => file.includes('.text'))
200
-
201
- t.is(plaintext[0], `${t.context.folder}/nested/plain.text`)
220
+ t.true(files.includes(`${t.context.folder}/nested/plain.text`))
202
221
  })
203
222
 
204
223
  test('renders plaintext string', async t => {
@@ -1,6 +1,5 @@
1
1
  const test = require('ava')
2
2
  const Maizzle = require('../src')
3
- const removePlaintextTags = require('../src/transformers/plaintext')
4
3
 
5
4
  const path = require('path')
6
5
  const fs = require('fs')
@@ -232,13 +231,6 @@ test('minify (disabled)', async t => {
232
231
  t.is(html, '<div>\n\n<p>\n\ntest</p></div>')
233
232
  })
234
233
 
235
- test('removes plaintext tag', t => {
236
- let html = removePlaintextTags('<plaintext>Removed</plaintext><div>Preserved</div>')
237
- html = html.replace(/[^\S\r\n]+$/gm, '').trim()
238
-
239
- t.is(html, '<div>Preserved</div>')
240
- })
241
-
242
234
  test('replace strings', async t => {
243
235
  const html = await Maizzle.replaceStrings('initial text', {initial: 'updated'})
244
236
 
@@ -1,23 +0,0 @@
1
- const {get} = require('lodash')
2
- const posthtml = require('posthtml')
3
-
4
- module.exports = (html, config = {}) => {
5
- const posthtmlOptions = get(config, 'build.posthtml.options', {})
6
-
7
- return posthtml([plaintext()]).process(html, {...posthtmlOptions, sync: true}).html
8
- }
9
-
10
- const plaintext = () => tree => {
11
- const process = node => {
12
- if (node.tag === 'plaintext') {
13
- return {
14
- tag: false,
15
- content: ['']
16
- }
17
- }
18
-
19
- return node
20
- }
21
-
22
- return tree.walk(process)
23
- }