@maizzle/framework 4.2.4 → 4.3.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.
Files changed (53) hide show
  1. package/README.md +5 -5
  2. package/package.json +8 -4
  3. package/src/generators/tailwindcss.js +1 -1
  4. package/src/transformers/filters/index.js +4 -0
  5. package/src/transformers/index.js +1 -1
  6. package/src/transformers/inlineCss.js +8 -3
  7. package/src/transformers/removeInlineSizes.js +2 -3
  8. package/src/transformers/removeUnusedCss.js +6 -2
  9. package/.editorconfig +0 -9
  10. package/.github/CONTRIBUTING.md +0 -33
  11. package/.github/ISSUE_TEMPLATE.md +0 -2
  12. package/.github/PULL_REQUEST_TEMPLATE.md +0 -9
  13. package/.github/dependabot.yml +0 -11
  14. package/.github/media/logo-dark.svg +0 -1
  15. package/.github/media/logo-light.svg +0 -1
  16. package/.github/workflows/nodejs.yml +0 -28
  17. package/test/expected/posthtml/component.html +0 -13
  18. package/test/expected/transformers/base-url.html +0 -99
  19. package/test/expected/transformers/filters.html +0 -81
  20. package/test/fixtures/basic.html +0 -9
  21. package/test/fixtures/posthtml/component.html +0 -19
  22. package/test/fixtures/transformers/base-url.html +0 -101
  23. package/test/fixtures/transformers/filters.html +0 -87
  24. package/test/stubs/assets/foo.bar +0 -1
  25. package/test/stubs/breaking/bad.html +0 -5
  26. package/test/stubs/components/component.html +0 -5
  27. package/test/stubs/config/config.js +0 -10
  28. package/test/stubs/config/config.maizzle-ci.js +0 -10
  29. package/test/stubs/data.json +0 -14
  30. package/test/stubs/empty/empty.html +0 -0
  31. package/test/stubs/events/before-create.html +0 -1
  32. package/test/stubs/layouts/basic.html +0 -1
  33. package/test/stubs/layouts/full.html +0 -12
  34. package/test/stubs/layouts/template.html +0 -5
  35. package/test/stubs/main.css +0 -5
  36. package/test/stubs/plaintext/front-matter.html +0 -9
  37. package/test/stubs/plaintext/plaintext.html +0 -5
  38. package/test/stubs/post.css +0 -6
  39. package/test/stubs/tailwind/content-source.html +0 -1
  40. package/test/stubs/tailwind/tailwind.css +0 -3
  41. package/test/stubs/template.html +0 -10
  42. package/test/stubs/templates/1.html +0 -1
  43. package/test/stubs/templates/2.html +0 -1
  44. package/test/stubs/templates/2.test +0 -1
  45. package/test/test-config.js +0 -19
  46. package/test/test-misc.js +0 -8
  47. package/test/test-postcss.js +0 -8
  48. package/test/test-posthtml.js +0 -112
  49. package/test/test-tailwindcss.js +0 -115
  50. package/test/test-todisk.js +0 -493
  51. package/test/test-tostring.js +0 -164
  52. package/test/test-transformers.js +0 -626
  53. package/xo.config.js +0 -22
@@ -1,493 +0,0 @@
1
- const test = require('ava')
2
- const fs = require('fs-extra')
3
- const Maizzle = require('../src')
4
-
5
- test.beforeEach(t => {
6
- t.context.folder = '_temp_' + Math.random().toString(36).slice(2, 9)
7
- t.context.log = console.log()
8
- })
9
-
10
- test.afterEach.always(async t => {
11
- if (t.context.folder) {
12
- await fs.remove(t.context.folder)
13
- delete t.context.folder
14
- }
15
- })
16
-
17
- test('throws if config cannot be computed', async t => {
18
- await t.throwsAsync(async () => {
19
- await Maizzle.build('missing')
20
- }, {instanceOf: Error, message: `could not load config.missing.js`})
21
- })
22
-
23
- test('skips if no templates found', async t => {
24
- const {files} = await Maizzle.build('maizzle-ci', {
25
- build: {
26
- fail: 'silent',
27
- templates: {
28
- source: 'test/stubs/templates',
29
- filetypes: 'fake',
30
- destination: {
31
- path: t.context.folder
32
- }
33
- }
34
- }
35
- })
36
-
37
- t.is(files.length, 0)
38
- })
39
-
40
- test('outputs files at the correct location', async t => {
41
- const {files: string} = await Maizzle.build('maizzle-ci', {
42
- build: {
43
- fail: 'silent',
44
- templates: {
45
- source: 'test/stubs/templates',
46
- destination: {
47
- path: t.context.folder
48
- }
49
- }
50
- }
51
- })
52
-
53
- const {files: array} = await Maizzle.build('maizzle-ci', {
54
- build: {
55
- fail: 'silent',
56
- templates: {
57
- source: ['test/stubs/templates'],
58
- destination: {
59
- path: t.context.folder
60
- }
61
- }
62
- }
63
- })
64
-
65
- t.true(await fs.pathExists(t.context.folder))
66
- t.is(string.length, 3)
67
- t.is(array.length, 3)
68
- })
69
-
70
- test('outputs files at the correct location if multiple template sources are used', async t => {
71
- const {files} = await Maizzle.build('local', {
72
- build: {
73
- fail: 'silent',
74
- templates: [
75
- {
76
- source: 'test/stubs/templates',
77
- destination: {
78
- path: t.context.folder
79
- }
80
- },
81
- {
82
- source: 'test/stubs/plaintext',
83
- destination: {
84
- path: t.context.folder
85
- }
86
- }
87
- ]
88
- }
89
- })
90
-
91
- t.true(await fs.pathExists(t.context.folder))
92
- t.is(files.length, 6)
93
- })
94
-
95
- test('copies all files in the `filetypes` option to destination', async t => {
96
- const {files} = await Maizzle.build('maizzle-ci', {
97
- build: {
98
- fail: 'silent',
99
- templates: {
100
- source: 'test/stubs/templates',
101
- filetypes: ['html', 'test'],
102
- destination: {
103
- path: t.context.folder
104
- }
105
- }
106
- }
107
- })
108
-
109
- t.true(await fs.pathExists(t.context.folder))
110
- t.is(files.length, 3)
111
- })
112
-
113
- test('outputs files with the correct extension', async t => {
114
- await Maizzle.build('maizzle-ci', {
115
- build: {
116
- fail: 'silent',
117
- templates: {
118
- source: 'test/stubs/templates',
119
- destination: {
120
- path: t.context.folder,
121
- extension: 'blade.php'
122
- }
123
- }
124
- }
125
- })
126
-
127
- const filelist = await fs.readdir(t.context.folder)
128
-
129
- t.true(filelist.includes('1.blade.php'))
130
- })
131
-
132
- test('outputs plaintext files', async t => {
133
- const {files} = await Maizzle.build('maizzle-ci', {
134
- fail: 'silent',
135
- build: {
136
- templates: {
137
- source: 'test/stubs/plaintext',
138
- destination: {
139
- path: t.context.folder
140
- },
141
- plaintext: true
142
- }
143
- },
144
- extraAttributes: false
145
- })
146
-
147
- t.true(files.includes(`${t.context.folder}/plaintext.txt`))
148
-
149
- t.is(
150
- await fs.readFile(`${t.context.folder}/plaintext.txt`, 'utf8'),
151
- 'Show in HTML\nShow in plaintext'
152
- )
153
-
154
- t.is(
155
- await fs.readFile(`${t.context.folder}/plaintext.html`, 'utf8'),
156
- '<div>Show in HTML</div>\n\n\n <p>Do not show <a href="url">this</a> in plaintext.</p>\n\n'
157
- )
158
- })
159
-
160
- test('outputs plaintext files (front matter)', async t => {
161
- const {files} = await Maizzle.build('maizzle-ci', {
162
- fail: 'silent',
163
- build: {
164
- templates: {
165
- source: 'test/stubs/plaintext',
166
- destination: {
167
- path: t.context.folder
168
- }
169
- }
170
- },
171
- extraAttributes: false
172
- })
173
-
174
- t.true(files.includes(`${t.context.folder}/front-matter.txt`))
175
-
176
- t.is(
177
- await fs.readFile(`${t.context.folder}/front-matter.txt`, 'utf8'),
178
- 'Show in HTML\nShow in plaintext'
179
- )
180
-
181
- t.is(
182
- await fs.readFile(`${t.context.folder}/front-matter.html`, 'utf8'),
183
- '<div>Show in HTML</div>\n\n\n <table><tr><td>Remove from plaintext</td></tr></table>\n\n'
184
- )
185
- })
186
-
187
- test('outputs plaintext files (custom path)', async t => {
188
- const {files} = await Maizzle.build('maizzle-ci', {
189
- fail: 'silent',
190
- build: {
191
- templates: {
192
- source: 'test/stubs/plaintext',
193
- destination: {
194
- path: t.context.folder
195
- },
196
- plaintext: {
197
- destination: {
198
- path: `${t.context.folder}/nested/plain.text`
199
- }
200
- }
201
- }
202
- }
203
- })
204
-
205
- t.true(files.includes(`${t.context.folder}/nested/plain.text`))
206
- })
207
-
208
- test('renders plaintext string', async t => {
209
- const html = await fs.readFile('test/stubs/plaintext/plaintext.html', 'utf8')
210
- const {plaintext} = await Maizzle.plaintext(html)
211
-
212
- t.is(plaintext, 'Show in HTML\nShow in plaintext')
213
- })
214
-
215
- test('copies assets to destination', async t => {
216
- await Maizzle.build('maizzle-ci', {
217
- build: {
218
- fail: 'silent',
219
- templates: {
220
- source: 'test/stubs/templates',
221
- destination: {
222
- path: t.context.folder
223
- },
224
- assets: {
225
- source: 'test/stubs/assets',
226
- destination: 'images'
227
- }
228
- }
229
- }
230
- })
231
-
232
- const filelist = await fs.readdir(`${t.context.folder}/images`)
233
-
234
- t.is(await fs.pathExists(`${t.context.folder}/images`), true)
235
- t.is(filelist.length, 1)
236
- })
237
-
238
- test('runs the `beforeCreate` event', async t => {
239
- await Maizzle.build('maizzle-ci', {
240
- build: {
241
- fail: 'silent',
242
- templates: {
243
- source: 'test/stubs/events',
244
- destination: {
245
- path: t.context.folder
246
- }
247
- }
248
- },
249
- events: {
250
- beforeCreate(config) {
251
- config.foo = 'bar'
252
- }
253
- }
254
- })
255
-
256
- const filename = await fs.readdir(t.context.folder)
257
- const html = await fs.readFile(`${t.context.folder}/${filename[0]}`, 'utf8')
258
-
259
- t.is(html.trim(), '<div class="inline">Foo is bar</div>')
260
- })
261
-
262
- test('runs the `afterBuild` event', async t => {
263
- const {files} = await Maizzle.build('maizzle-ci', {
264
- build: {
265
- fail: 'silent',
266
- templates: {
267
- source: 'test/stubs/templates',
268
- destination: {
269
- path: t.context.folder
270
- }
271
- }
272
- },
273
- events: {
274
- afterBuild(files) {
275
- t.context.afterBuild = files
276
- }
277
- }
278
- })
279
-
280
- const getIntersection = (a, ...array) => [...new Set(a)].filter(v => array.every(b => b.includes(v)))
281
-
282
- t.deepEqual(getIntersection(t.context.afterBuild, files), files)
283
- })
284
-
285
- test('supports multiple asset paths', async t => {
286
- await Maizzle.build('maizzle-ci', {
287
- build: {
288
- fail: 'silent',
289
- templates: {
290
- source: 'test/stubs/templates',
291
- destination: {
292
- path: t.context.folder
293
- },
294
- assets: {
295
- source: ['test/stubs/assets', 'test/stubs/plaintext', 'test/stubs/invalid'],
296
- destination: 'extras'
297
- }
298
- }
299
- }
300
- })
301
-
302
- t.true(await fs.pathExists(`${t.context.folder}/extras/foo.bar`))
303
- t.true(await fs.pathExists(`${t.context.folder}/extras/plaintext.html`))
304
- t.false(await fs.pathExists(`${t.context.folder}/extras/invalid`))
305
- })
306
-
307
- test('warns if a template cannot be rendered and `fail` option is undefined', async t => {
308
- const {files} = await Maizzle.build('maizzle-ci', {
309
- build: {
310
- templates: {
311
- source: 'test/stubs/breaking',
312
- destination: {
313
- path: t.context.folder
314
- }
315
- }
316
- }
317
- })
318
-
319
- t.false(files.includes('empty.html'))
320
- })
321
-
322
- test('warns if a template cannot be rendered and `fail` option is `verbose`', async t => {
323
- const {files} = await Maizzle.build('maizzle-ci', {
324
- build: {
325
- fail: 'verbose',
326
- templates: {
327
- source: 'test/stubs/breaking',
328
- destination: {
329
- path: t.context.folder
330
- }
331
- }
332
- }
333
- })
334
-
335
- t.false(files.includes('empty.html'))
336
- })
337
-
338
- test('warns if a template cannot be rendered and `fail` option is `silent`', async t => {
339
- const {files} = await Maizzle.build('maizzle-ci', {
340
- build: {
341
- fail: 'silent',
342
- templates: {
343
- source: 'test/stubs/breaking',
344
- destination: {
345
- path: t.context.folder
346
- }
347
- }
348
- }
349
- })
350
-
351
- t.false(files.includes('empty.html'))
352
- })
353
-
354
- test('local server does not compile unwanted file types', async t => {
355
- await Maizzle.serve('local', {
356
- build: {
357
- console: {
358
- clear: true
359
- },
360
- browsersync: {
361
- ui: false
362
- },
363
- templates: {
364
- source: 'test/stubs/templates',
365
- destination: {
366
- path: `${t.context.folder}`
367
- }
368
- }
369
- },
370
- events: {
371
- beforeCreate(config) {
372
- config.foo = 'bar'
373
- }
374
- }
375
- })
376
-
377
- t.true(await fs.pathExists(`${t.context.folder}`))
378
- t.true(await fs.pathExists(`${t.context.folder}/2.test`))
379
-
380
- // Tests watching changes to files
381
- await fs.outputFile('test/stubs/templates/2.html', '<div class="inline">html modified</div>')
382
- t.is(await fs.readFile('test/stubs/templates/2.html', 'utf8'), '<div class="inline">html modified</div>')
383
-
384
- // Don't trigger rebuilds on files not in `filetypes`
385
- await fs.outputFile('test/stubs/templates/2.test', 'test')
386
- t.is(await fs.readFile('test/stubs/templates/2.test', 'utf8'), 'test')
387
- })
388
-
389
- test('throws if it cannot spin up local development server', async t => {
390
- await t.throwsAsync(async () => {
391
- await Maizzle.serve('local', {})
392
- }, {instanceOf: TypeError})
393
- })
394
-
395
- test('works with templates.source defined as function (string paths)', async t => {
396
- const {files} = await Maizzle.build('maizzle-ci', {
397
- build: {
398
- fail: 'silent',
399
- templates: {
400
- source: () => 'test/stubs/templates',
401
- destination: {
402
- path: t.context.folder
403
- }
404
- }
405
- }
406
- })
407
-
408
- t.true(await fs.pathExists(t.context.folder))
409
- t.is(files.length, 3)
410
- })
411
-
412
- test('works with templates.source defined as function (array paths)', async t => {
413
- const {files} = await Maizzle.build('maizzle-ci', {
414
- build: {
415
- fail: 'silent',
416
- customSources: ['test/stubs/templates', 'test/stubs/templates'],
417
- templates: {
418
- source: config => {
419
- return config.build.customSources
420
- },
421
- destination: {
422
- path: t.context.folder
423
- }
424
- }
425
- }
426
- })
427
-
428
- t.true(await fs.pathExists(t.context.folder))
429
- t.is(files.length, 3)
430
- })
431
-
432
- test('throws if templates path is invalid', async t => {
433
- await t.throwsAsync(async () => {
434
- await Maizzle.build('maizzle-ci', {
435
- build: {
436
- fail: 'silent',
437
- templates: {
438
- source: false,
439
- destination: {
440
- path: t.context.folder
441
- }
442
- }
443
- }
444
- })
445
- }, {instanceOf: TypeError})
446
- })
447
-
448
- test('throws if templates path is invalid (function)', async t => {
449
- await t.throwsAsync(async () => {
450
- await Maizzle.build('maizzle-ci', {
451
- build: {
452
- fail: 'silent',
453
- templates: {
454
- source: () => {},
455
- destination: {
456
- path: t.context.folder
457
- }
458
- }
459
- }
460
- })
461
- }, {instanceOf: TypeError})
462
- })
463
-
464
- test('sets config.build.current.path', async t => {
465
- await Maizzle.build('maizzle-ci', {
466
- build: {
467
- fail: 'silent',
468
- templates: {
469
- source: 'test/stubs/templates',
470
- destination: {
471
- path: t.context.folder
472
- }
473
- }
474
- },
475
- events: {
476
- beforeRender(html, config) {
477
- t.context.current = config.build.current
478
-
479
- return html
480
- }
481
- }
482
- })
483
-
484
- t.deepEqual(t.context.current, {
485
- path: {
486
- root: '',
487
- dir: t.context.folder,
488
- base: '2.html',
489
- ext: '.html',
490
- name: '2'
491
- }
492
- })
493
- })
@@ -1,164 +0,0 @@
1
- const test = require('ava')
2
- const Maizzle = require('../src')
3
-
4
- const renderString = (string, options = {}) => Maizzle.render(string, options).then(({html}) => html)
5
-
6
- test('uses environment config file(s) if available', async t => {
7
- const source = `<div class="inline">{{ page.mail }}</div>`
8
-
9
- const html = await renderString(source, {
10
- maizzle: {
11
- mail: 'puzzle'
12
- }
13
- })
14
-
15
- t.is(html, '<div class="inline">puzzle</div>')
16
- })
17
-
18
- test('throws if first argument is not an HTML string', async t => {
19
- await t.throwsAsync(async () => {
20
- await renderString()
21
- }, {instanceOf: TypeError, message: 'first argument must be an HTML string, received undefined'})
22
- })
23
-
24
- test('throws if first argument is an empty string', async t => {
25
- await t.throwsAsync(async () => {
26
- await renderString('')
27
- }, {instanceOf: RangeError, message: 'received empty string'})
28
- })
29
-
30
- test('runs the `beforeRender` event', async t => {
31
- const html = await renderString(`<div class="inline">{{ page.foo }}</div>`, {
32
- beforeRender(html, config) {
33
- config.foo = 'bar'
34
-
35
- return html
36
- }
37
- })
38
-
39
- t.is(html, `<div class="inline">bar</div>`)
40
- })
41
-
42
- test('runs the `afterRender` event', async t => {
43
- const result = await renderString(`<div class="inline">foo</div>`, {
44
- afterRender(html, config) {
45
- config.replaceStrings = {
46
- foo: 'baz'
47
- }
48
-
49
- return html
50
- }
51
- })
52
-
53
- t.is(result, `<div class="inline">baz</div>`)
54
- })
55
-
56
- test('runs the `afterTransformers` event', async t => {
57
- const result = await renderString(`<div class="inline">foo</div>`, {
58
- maizzle: {
59
- title: 'bar'
60
- },
61
- afterTransformers(html, config) {
62
- return html.replace('foo', config.title)
63
- }
64
- })
65
-
66
- t.is(result, `<div class="inline">bar</div>`)
67
- })
68
-
69
- test('locals work when defined in all supported places', async t => {
70
- const result = await renderString(`{{ page.one }}, {{ two }}, {{ three }}, {{ inline }}`, {
71
- maizzle: {
72
- one: 1,
73
- build: {
74
- posthtml: {
75
- expressions: {
76
- locals: {
77
- two: 2
78
- }
79
- }
80
- }
81
- },
82
- locals: {
83
- three: 3
84
- }
85
- }
86
- })
87
-
88
- t.is(result, `1, 2, 3, undefined`)
89
- })
90
-
91
- test('prevents overwriting page object', async t => {
92
- const result = await renderString(`{{ page.one }}, {{ two }}, {{ three }}, {{ inline }}`, {
93
- maizzle: {
94
- one: 1,
95
- build: {
96
- posthtml: {
97
- expressions: {
98
- locals: {
99
- page: {
100
- two: 2
101
- }
102
- }
103
- }
104
- }
105
- },
106
- locals: {
107
- page: {
108
- three: 3
109
- }
110
- }
111
- }
112
- })
113
-
114
- t.is(result, `1, undefined, undefined, undefined`)
115
- })
116
-
117
- test('preserves css in marked style tags (tailwindcss)', async t => {
118
- const source = `<html>
119
- <head>
120
- <style tailwindcss preserve>
121
- div {
122
- @apply uppercase;
123
- }
124
- [data-ogsc] .inexistent {
125
- color: #ef4444;
126
- }
127
- [data-ogsc] .ogsc:hidden {
128
- display: none;
129
- }
130
- div > u + .body .gmail-android-block {
131
- display: block !important;
132
- }
133
- u + #body a {
134
- color: inherit;
135
- }
136
- </style>
137
- </head>
138
- <body>
139
- <div>test</div>
140
- </body>
141
- </html>`
142
-
143
- const html = await renderString(source, {
144
- // So that we don't compile twice
145
- tailwind: {
146
- compiled: ''
147
- }
148
- })
149
-
150
- t.true(html.includes('[data-ogsc] .ogsc:hidden'))
151
- t.false(html.includes('[data-ogsc] .inexistent'))
152
-
153
- t.true(html.includes('div > u + .body .gmail-android-block'))
154
- t.true(html.includes('u + #body a'))
155
- })
156
-
157
- test('@import css files in marked style tags', async t => {
158
- const source = `<style class="inline" postcss>@import "test/stubs/post.css";</style>`
159
- const html = await renderString(source)
160
-
161
- t.is(html, `<style class="inline">div {
162
- margin: 1px 2px 3px 4px;
163
- }</style>`)
164
- })