@maizzle/framework 3.7.2 → 4.0.0-alpha.10

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 (84) hide show
  1. package/.github/workflows/nodejs.yml +28 -29
  2. package/bin/maizzle +3 -0
  3. package/package.json +91 -84
  4. package/src/commands/build.js +32 -0
  5. package/src/commands/serve.js +156 -0
  6. package/src/functions/plaintext.js +5 -0
  7. package/src/functions/render.js +5 -0
  8. package/src/generators/output/to-disk.js +120 -79
  9. package/src/generators/output/to-string.js +7 -8
  10. package/src/generators/plaintext.js +49 -52
  11. package/src/generators/postcss.js +29 -0
  12. package/src/generators/posthtml.js +66 -60
  13. package/src/generators/tailwindcss.js +116 -84
  14. package/src/index.js +14 -160
  15. package/src/transformers/{attribute-to-style.js → attributeToStyle.js} +0 -0
  16. package/src/transformers/baseUrl.js +69 -0
  17. package/src/transformers/{extra-attributes.js → extraAttributes.js} +0 -0
  18. package/src/transformers/filters/defaultFilters.js +126 -0
  19. package/src/transformers/filters/index.js +55 -0
  20. package/src/transformers/index.js +63 -57
  21. package/src/transformers/{inline.js → inlineCss.js} +1 -14
  22. package/src/transformers/minify.js +1 -1
  23. package/src/transformers/{posthtml-mso.js → posthtmlMso.js} +0 -0
  24. package/src/transformers/prettify.js +16 -9
  25. package/src/transformers/{prevent-widows.js → preventWidows.js} +0 -0
  26. package/src/transformers/{remove-attributes.js → removeAttributes.js} +1 -1
  27. package/src/transformers/{remove-inline-bgcolor.js → removeInlineBackgroundColor.js} +1 -1
  28. package/src/transformers/{remove-inline-sizes.js → removeInlineSizes.js} +0 -0
  29. package/src/transformers/removeInlinedSelectors.js +70 -0
  30. package/src/transformers/removeUnusedCss.js +40 -0
  31. package/src/transformers/{replace-strings.js → replaceStrings.js} +0 -0
  32. package/src/transformers/{safe-class-names.js → safeClassNames.js} +8 -2
  33. package/src/transformers/shorthandInlineCSS.js +19 -0
  34. package/src/transformers/sixHex.js +33 -0
  35. package/src/transformers/{url-params.js → urlParameters.js} +0 -0
  36. package/src/utils/helpers.js +2 -8
  37. package/test/expected/posthtml/component.html +13 -0
  38. package/test/expected/{inheritance.html → posthtml/extend-template.html} +2 -2
  39. package/test/expected/posthtml/fetch.html +5 -0
  40. package/test/expected/posthtml/layout.html +3 -0
  41. package/test/expected/transformers/atimport-in-style.html +15 -0
  42. package/test/expected/transformers/base-url.html +99 -0
  43. package/test/expected/transformers/filters.html +81 -0
  44. package/test/expected/transformers/preserve-transform-css.html +36 -0
  45. package/test/expected/useConfig.html +9 -0
  46. package/test/fixtures/basic.html +9 -9
  47. package/test/fixtures/posthtml/component.html +19 -0
  48. package/test/fixtures/{inheritance.html → posthtml/extend-template.html} +7 -7
  49. package/test/fixtures/posthtml/fetch.html +9 -0
  50. package/test/fixtures/posthtml/layout.html +11 -0
  51. package/test/fixtures/transformers/atimport-in-style.html +11 -0
  52. package/test/fixtures/transformers/base-url.html +101 -0
  53. package/test/fixtures/transformers/filters.html +87 -0
  54. package/test/fixtures/transformers/preserve-transform-css.html +25 -0
  55. package/test/fixtures/useConfig.html +9 -0
  56. package/test/stubs/components/component.html +5 -0
  57. package/test/stubs/data.json +14 -0
  58. package/test/stubs/layouts/basic.html +1 -0
  59. package/test/stubs/{layout.html → layouts/full.html} +0 -0
  60. package/test/stubs/{layout-basic.html → layouts/template.html} +5 -5
  61. package/test/stubs/post.css +6 -0
  62. package/test/stubs/tailwind/content-source.html +1 -0
  63. package/test/stubs/tailwind/tailwind.css +3 -0
  64. package/test/stubs/template.html +10 -10
  65. package/test/stubs/templates/1.html +1 -1
  66. package/test/stubs/templates/2.test +1 -0
  67. package/test/test-config.js +19 -19
  68. package/test/test-misc.js +8 -8
  69. package/test/test-postcss.js +8 -0
  70. package/test/test-posthtml.js +72 -0
  71. package/test/test-tailwindcss.js +117 -0
  72. package/test/test-todisk.js +142 -49
  73. package/test/test-tostring.js +148 -124
  74. package/test/test-transformers.js +510 -320
  75. package/xo.config.js +22 -19
  76. package/src/transformers/base-image-url.js +0 -9
  77. package/src/transformers/remove-unused-css.js +0 -20
  78. package/src/transformers/six-hex.js +0 -10
  79. package/src/transformers/transform.js +0 -24
  80. package/test/expected/transformers/base-image-url.html +0 -7
  81. package/test/fixtures/transformers/base-image-url.html +0 -7
  82. package/test/stubs/templates/2.html +0 -1
  83. package/test/stubs/templates/3.mzl +0 -1
  84. package/test/test-tailwind.js +0 -73
@@ -0,0 +1,117 @@
1
+ const test = require('ava')
2
+ const ora = require('ora')
3
+ const Tailwind = require('../src/generators/tailwindcss')
4
+
5
+ test('throws on compile error', async t => {
6
+ await t.throwsAsync(async () => {
7
+ const spinner = ora('Compiling Tailwind CSS...').start()
8
+ await Tailwind.compile('.test {@apply inexistent;}', '<div class="test">Test</a>', {}, {}, spinner)
9
+ }, {instanceOf: Error, message: 'Tailwind CSS compilation failed'})
10
+ })
11
+
12
+ test('uses defaults if no config specified', async t => {
13
+ const css = await Tailwind.compile(
14
+ '@tailwind utilities;',
15
+ '<p class="xl:z-0"></p>',
16
+ {},
17
+ {env: 'production'}
18
+ )
19
+
20
+ t.not(css, undefined)
21
+ t.true(css.includes('.xl\\:z-0'))
22
+ })
23
+
24
+ test('uses css file provided in environment config', async t => {
25
+ const config = {
26
+ env: 'production',
27
+ build: {
28
+ tailwind: {
29
+ css: './test/stubs/main.css'
30
+ }
31
+ }
32
+ }
33
+
34
+ const css = await Tailwind.compile('', '<div class="text-center foo">test</div>', {}, config)
35
+
36
+ t.not(css, undefined)
37
+ t.true(css.includes('.text-center'))
38
+ t.true(css.includes('.foo'))
39
+ })
40
+
41
+ test('works with custom `content` sources', async t => {
42
+ const css = await Tailwind.compile(
43
+ '@tailwind utilities;',
44
+ '<div class="hidden"></div>',
45
+ {
46
+ content: ['./test/stubs/tailwind/*.*']
47
+ }
48
+ )
49
+
50
+ t.true(css.includes('.hidden'))
51
+ })
52
+
53
+ test('works with custom `files` sources', async t => {
54
+ const css = await Tailwind.compile(
55
+ '@tailwind utilities;',
56
+ '<div></div>',
57
+ {
58
+ content: {
59
+ files: ['./test/stubs/tailwind/*.*']
60
+ }
61
+ }
62
+ )
63
+
64
+ t.true(css.includes('.hidden'))
65
+ })
66
+
67
+ test('uses maizzle template path as content source', async t => {
68
+ const css = await Tailwind.compile(
69
+ '@tailwind utilities;',
70
+ '<div></div>',
71
+ {},
72
+ {
73
+ build: {
74
+ templates: {
75
+ source: './test/stubs/tailwind'
76
+ }
77
+ }
78
+ }
79
+ )
80
+
81
+ t.true(css.includes('.hidden'))
82
+ })
83
+
84
+ test('uses maizzle template path as content source (single file)', async t => {
85
+ const css = await Tailwind.compile(
86
+ '@tailwind utilities;',
87
+ '<div></div>',
88
+ {},
89
+ {
90
+ build: {
91
+ templates: {
92
+ source: './test/stubs/tailwind/content-source.html'
93
+ }
94
+ }
95
+ }
96
+ )
97
+
98
+ t.true(css.includes('.hidden'))
99
+ })
100
+
101
+ test('uses custom postcss plugins from the maizzle config', async t => {
102
+ const maizzleConfig = {
103
+ env: 'production',
104
+ build: {
105
+ postcss: {
106
+ plugins: [
107
+ require('autoprefixer')({overrideBrowserslist: ['> 0.1%']})
108
+ ]
109
+ }
110
+ }
111
+ }
112
+
113
+ const css = await Tailwind.compile('.test {transform: scale(0.5)}', '<div class="test">Test</a>', {}, maizzleConfig)
114
+
115
+ t.not(css, undefined)
116
+ t.is(css.trim(), '.inline {display: inline !important} .table {display: table !important} .contents {display: contents !important} .truncate {overflow: hidden !important;text-overflow: ellipsis !important;white-space: nowrap !important} .uppercase {text-transform: uppercase !important} .lowercase {text-transform: lowercase !important} .capitalize {text-transform: capitalize !important} .test {-webkit-transform: scale(0.5);transform: scale(0.5)}')
117
+ })
@@ -16,12 +16,12 @@ test.afterEach.always(async t => {
16
16
 
17
17
  test('throws if config cannot be computed', async t => {
18
18
  await t.throwsAsync(async () => {
19
- await Maizzle.build('production')
20
- }, {instanceOf: Error, message: `could not load config.production.js`})
19
+ await Maizzle.build('missing')
20
+ }, {instanceOf: Error, message: `could not load config.missing.js`})
21
21
  })
22
22
 
23
23
  test('skips if no templates found', async t => {
24
- const {files} = await Maizzle.build('production', {
24
+ const {files} = await Maizzle.build('maizzle-ci', {
25
25
  build: {
26
26
  fail: 'silent',
27
27
  templates: {
@@ -43,7 +43,7 @@ test('skips if no templates found', async t => {
43
43
  })
44
44
 
45
45
  test('outputs files at the correct location', async t => {
46
- const {files} = await Maizzle.build('production', {
46
+ const {files: string} = await Maizzle.build('maizzle-ci', {
47
47
  build: {
48
48
  fail: 'silent',
49
49
  templates: {
@@ -51,17 +51,25 @@ test('outputs files at the correct location', async t => {
51
51
  destination: {
52
52
  path: t.context.folder
53
53
  }
54
- },
55
- tailwind: {
56
- config: {
57
- purge: false
54
+ }
55
+ }
56
+ })
57
+
58
+ const {files: array} = await Maizzle.build('maizzle-ci', {
59
+ build: {
60
+ fail: 'silent',
61
+ templates: {
62
+ source: ['test/stubs/templates'],
63
+ destination: {
64
+ path: t.context.folder
58
65
  }
59
66
  }
60
67
  }
61
68
  })
62
69
 
63
- t.true(fs.pathExistsSync(t.context.folder))
64
- t.is(files.length, 3)
70
+ t.true(await fs.pathExists(t.context.folder))
71
+ t.is(string.length, 2)
72
+ t.is(array.length, 2)
65
73
  })
66
74
 
67
75
  test('outputs files at the correct location if multiple template sources are used', async t => {
@@ -85,17 +93,17 @@ test('outputs files at the correct location if multiple template sources are use
85
93
  }
86
94
  })
87
95
 
88
- t.true(fs.pathExistsSync(t.context.folder))
89
- t.is(files.length, 4)
96
+ t.true(await fs.pathExists(t.context.folder))
97
+ t.is(files.length, 3)
90
98
  })
91
99
 
92
100
  test('copies all files in the `filetypes` option to destination', async t => {
93
- const {files} = await Maizzle.build('production', {
101
+ const {files} = await Maizzle.build('maizzle-ci', {
94
102
  build: {
95
103
  fail: 'silent',
96
104
  templates: {
97
105
  source: 'test/stubs/templates',
98
- filetypes: ['html', 'mzl'],
106
+ filetypes: ['html', 'test'],
99
107
  destination: {
100
108
  path: t.context.folder
101
109
  }
@@ -108,12 +116,12 @@ test('copies all files in the `filetypes` option to destination', async t => {
108
116
  }
109
117
  })
110
118
 
111
- t.true(fs.pathExistsSync(t.context.folder))
112
- t.is(files.length, 4)
119
+ t.true(await fs.pathExists(t.context.folder))
120
+ t.is(files.length, 3)
113
121
  })
114
122
 
115
123
  test('outputs files with the correct extension', async t => {
116
- await Maizzle.build('production', {
124
+ await Maizzle.build('maizzle-ci', {
117
125
  build: {
118
126
  fail: 'silent',
119
127
  templates: {
@@ -131,26 +139,28 @@ test('outputs files with the correct extension', async t => {
131
139
  }
132
140
  })
133
141
 
134
- t.true(fs.readdirSync(t.context.folder).includes('1.blade.php'))
142
+ const filelist = await fs.readdir(t.context.folder)
143
+
144
+ t.true(filelist.includes('1.blade.php'))
135
145
  })
136
146
 
137
147
  test('outputs plaintext files', async t => {
138
- const {files} = await Maizzle.build('production', {
148
+ const {files} = await Maizzle.build('maizzle-ci', {
139
149
  fail: 'silent',
140
150
  build: {
141
151
  templates: {
142
152
  source: 'test/stubs/plaintext',
143
153
  destination: {
144
154
  path: t.context.folder
145
- }
155
+ },
156
+ plaintext: true
146
157
  },
147
158
  tailwind: {
148
159
  config: {
149
160
  purge: false
150
161
  }
151
162
  }
152
- },
153
- plaintext: true
163
+ }
154
164
  })
155
165
 
156
166
  const plaintext = files.filter(file => file.includes('.txt'))
@@ -164,13 +174,18 @@ test('outputs plaintext files', async t => {
164
174
  })
165
175
 
166
176
  test('outputs plaintext files (custom path)', async t => {
167
- const {files} = await Maizzle.build('production', {
177
+ const {files} = await Maizzle.build('maizzle-ci', {
168
178
  fail: 'silent',
169
179
  build: {
170
180
  templates: {
171
181
  source: 'test/stubs/plaintext',
172
182
  destination: {
173
183
  path: t.context.folder
184
+ },
185
+ plaintext: {
186
+ destination: {
187
+ path: `${t.context.folder}/nested/plain.text`
188
+ }
174
189
  }
175
190
  },
176
191
  tailwind: {
@@ -178,11 +193,6 @@ test('outputs plaintext files (custom path)', async t => {
178
193
  purge: false
179
194
  }
180
195
  }
181
- },
182
- plaintext: {
183
- destination: {
184
- path: `${t.context.folder}/nested/plain.text`
185
- }
186
196
  }
187
197
  })
188
198
 
@@ -199,7 +209,7 @@ test('renders plaintext string', async t => {
199
209
  })
200
210
 
201
211
  test('copies assets to destination', async t => {
202
- await Maizzle.build('production', {
212
+ await Maizzle.build('maizzle-ci', {
203
213
  build: {
204
214
  fail: 'silent',
205
215
  templates: {
@@ -220,12 +230,14 @@ test('copies assets to destination', async t => {
220
230
  }
221
231
  })
222
232
 
223
- t.is(fs.pathExistsSync(`${t.context.folder}/images`), true)
224
- t.is(fs.readdirSync(`${t.context.folder}/images`).length, 1)
233
+ const filelist = await fs.readdir(`${t.context.folder}/images`)
234
+
235
+ t.is(await fs.pathExists(`${t.context.folder}/images`), true)
236
+ t.is(filelist.length, 1)
225
237
  })
226
238
 
227
239
  test('runs the `beforeCreate` event', async t => {
228
- await Maizzle.build('production', {
240
+ await Maizzle.build('maizzle-ci', {
229
241
  build: {
230
242
  fail: 'silent',
231
243
  templates: {
@@ -247,13 +259,14 @@ test('runs the `beforeCreate` event', async t => {
247
259
  }
248
260
  })
249
261
 
250
- const html = fs.readFileSync(`${t.context.folder}/${fs.readdirSync(t.context.folder)[0]}`, 'utf8').trim()
262
+ const filename = await fs.readdir(t.context.folder)
263
+ const html = await fs.readFile(`${t.context.folder}/${filename[0]}`, 'utf8')
251
264
 
252
- t.is(html, 'Foo is bar')
265
+ t.is(html.trim(), 'Foo is bar')
253
266
  })
254
267
 
255
268
  test('runs the `afterBuild` event', async t => {
256
- const {files} = await Maizzle.build('production', {
269
+ const {files} = await Maizzle.build('maizzle-ci', {
257
270
  build: {
258
271
  fail: 'silent',
259
272
  templates: {
@@ -281,7 +294,7 @@ test('runs the `afterBuild` event', async t => {
281
294
  })
282
295
 
283
296
  test('supports multiple asset paths', async t => {
284
- await Maizzle.build('production', {
297
+ await Maizzle.build('maizzle-ci', {
285
298
  build: {
286
299
  fail: 'silent',
287
300
  templates: {
@@ -302,13 +315,13 @@ test('supports multiple asset paths', async t => {
302
315
  }
303
316
  })
304
317
 
305
- t.true(fs.existsSync(`${t.context.folder}/extras/foo.bar`))
306
- t.true(fs.existsSync(`${t.context.folder}/extras/plaintext.html`))
307
- t.false(fs.existsSync(`${t.context.folder}/extras/invalid`))
318
+ t.true(await fs.pathExists(`${t.context.folder}/extras/foo.bar`))
319
+ t.true(await fs.pathExists(`${t.context.folder}/extras/plaintext.html`))
320
+ t.false(await fs.pathExists(`${t.context.folder}/extras/invalid`))
308
321
  })
309
322
 
310
323
  test('warns if a template cannot be rendered and `fail` option is undefined', async t => {
311
- const {files} = await Maizzle.build('production', {
324
+ const {files} = await Maizzle.build('maizzle-ci', {
312
325
  build: {
313
326
  templates: {
314
327
  source: 'test/stubs/breaking',
@@ -328,7 +341,7 @@ test('warns if a template cannot be rendered and `fail` option is undefined', as
328
341
  })
329
342
 
330
343
  test('warns if a template cannot be rendered and `fail` option is `verbose`', async t => {
331
- const {files} = await Maizzle.build('production', {
344
+ const {files} = await Maizzle.build('maizzle-ci', {
332
345
  build: {
333
346
  fail: 'verbose',
334
347
  templates: {
@@ -349,7 +362,7 @@ test('warns if a template cannot be rendered and `fail` option is `verbose`', as
349
362
  })
350
363
 
351
364
  test('warns if a template cannot be rendered and `fail` option is `silent`', async t => {
352
- const {files} = await Maizzle.build('production', {
365
+ const {files} = await Maizzle.build('maizzle-ci', {
353
366
  build: {
354
367
  fail: 'silent',
355
368
  templates: {
@@ -384,31 +397,42 @@ test('spins up local development server', async t => {
384
397
  }
385
398
  })
386
399
 
387
- t.true(fs.existsSync(t.context.folder))
400
+ t.true(await fs.pathExists(t.context.folder))
388
401
  })
389
402
 
390
403
  test('local server does not compile unwanted file types', async t => {
391
404
  await Maizzle.serve('local', {
392
405
  build: {
406
+ console: {
407
+ clear: true
408
+ },
393
409
  browsersync: {
394
410
  ui: false
395
411
  },
396
412
  templates: {
397
413
  source: 'test/stubs/templates',
398
414
  destination: {
399
- path: t.context.folder
415
+ path: `${t.context.folder}`
400
416
  }
401
417
  }
418
+ },
419
+ events: {
420
+ beforeCreate(config) {
421
+ config.foo = 'bar'
422
+ }
402
423
  }
403
424
  })
404
425
 
405
- fs.outputFileSync(`test/stubs/templates/1.html`, '<a href="https://example.com">Test</a>\n')
406
- fs.outputFileSync(`test/stubs/templates/3.mzl`, '<a href="https://example.com">Test</a>\n')
426
+ t.true(await fs.pathExists(`${t.context.folder}`))
427
+ t.true(await fs.pathExists(`${t.context.folder}/2.test`))
407
428
 
408
- t.is(fs.readFileSync(`${t.context.folder}/1.html`, 'utf8'), '<a href="https://example.com">Test</a>\n')
409
- t.is(fs.readFileSync(`${t.context.folder}/3.mzl`, 'utf8'), '<a href="https://example.com">Test</a>\n')
429
+ // Tests watching changes to files
430
+ await fs.outputFile('test/stubs/templates/1.html', 'html\n')
431
+ t.is(await fs.readFile('test/stubs/templates/1.html', 'utf8'), 'html\n')
410
432
 
411
- fs.removeSync(t.context.folder)
433
+ // Don't trigger rebuilds on files not in filetypes
434
+ await fs.outputFile('test/stubs/templates/2.test', 'test\n')
435
+ t.is(await fs.readFile('test/stubs/templates/2.test', 'utf8'), 'test\n')
412
436
  })
413
437
 
414
438
  test('throws if it cannot spin up local development server', async t => {
@@ -416,3 +440,72 @@ test('throws if it cannot spin up local development server', async t => {
416
440
  await Maizzle.serve('local', {})
417
441
  }, {instanceOf: TypeError})
418
442
  })
443
+
444
+ test('works with templates.source defined as function (string paths)', async t => {
445
+ const {files} = await Maizzle.build('maizzle-ci', {
446
+ build: {
447
+ fail: 'silent',
448
+ templates: {
449
+ source: () => 'test/stubs/templates',
450
+ destination: {
451
+ path: t.context.folder
452
+ }
453
+ }
454
+ }
455
+ })
456
+
457
+ t.true(await fs.pathExists(t.context.folder))
458
+ t.is(files.length, 2)
459
+ })
460
+
461
+ test('works with templates.source defined as function (array paths)', async t => {
462
+ const {files} = await Maizzle.build('maizzle-ci', {
463
+ build: {
464
+ fail: 'silent',
465
+ customSources: ['test/stubs/templates', 'test/stubs/templates'],
466
+ templates: {
467
+ source: config => {
468
+ return config.build.customSources
469
+ },
470
+ destination: {
471
+ path: t.context.folder
472
+ }
473
+ }
474
+ }
475
+ })
476
+
477
+ t.true(await fs.pathExists(t.context.folder))
478
+ t.is(files.length, 2)
479
+ })
480
+
481
+ test('throws if templates path is invalid', async t => {
482
+ await t.throwsAsync(async () => {
483
+ await Maizzle.build('maizzle-ci', {
484
+ build: {
485
+ fail: 'silent',
486
+ templates: {
487
+ source: false,
488
+ destination: {
489
+ path: t.context.folder
490
+ }
491
+ }
492
+ }
493
+ })
494
+ }, {instanceOf: TypeError})
495
+ })
496
+
497
+ test('throws if templates path is invalid (function)', async t => {
498
+ await t.throwsAsync(async () => {
499
+ await Maizzle.build('maizzle-ci', {
500
+ build: {
501
+ fail: 'silent',
502
+ templates: {
503
+ source: () => {},
504
+ destination: {
505
+ path: t.context.folder
506
+ }
507
+ }
508
+ }
509
+ })
510
+ }, {instanceOf: TypeError})
511
+ })