@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.
- package/.github/workflows/nodejs.yml +28 -29
- package/bin/maizzle +3 -0
- package/package.json +91 -84
- package/src/commands/build.js +32 -0
- package/src/commands/serve.js +156 -0
- package/src/functions/plaintext.js +5 -0
- package/src/functions/render.js +5 -0
- package/src/generators/output/to-disk.js +120 -79
- package/src/generators/output/to-string.js +7 -8
- package/src/generators/plaintext.js +49 -52
- package/src/generators/postcss.js +29 -0
- package/src/generators/posthtml.js +66 -60
- package/src/generators/tailwindcss.js +116 -84
- package/src/index.js +14 -160
- package/src/transformers/{attribute-to-style.js → attributeToStyle.js} +0 -0
- package/src/transformers/baseUrl.js +69 -0
- package/src/transformers/{extra-attributes.js → extraAttributes.js} +0 -0
- package/src/transformers/filters/defaultFilters.js +126 -0
- package/src/transformers/filters/index.js +55 -0
- package/src/transformers/index.js +63 -57
- package/src/transformers/{inline.js → inlineCss.js} +1 -14
- package/src/transformers/minify.js +1 -1
- package/src/transformers/{posthtml-mso.js → posthtmlMso.js} +0 -0
- package/src/transformers/prettify.js +16 -9
- package/src/transformers/{prevent-widows.js → preventWidows.js} +0 -0
- package/src/transformers/{remove-attributes.js → removeAttributes.js} +1 -1
- package/src/transformers/{remove-inline-bgcolor.js → removeInlineBackgroundColor.js} +1 -1
- package/src/transformers/{remove-inline-sizes.js → removeInlineSizes.js} +0 -0
- package/src/transformers/removeInlinedSelectors.js +70 -0
- package/src/transformers/removeUnusedCss.js +40 -0
- package/src/transformers/{replace-strings.js → replaceStrings.js} +0 -0
- package/src/transformers/{safe-class-names.js → safeClassNames.js} +8 -2
- package/src/transformers/shorthandInlineCSS.js +19 -0
- package/src/transformers/sixHex.js +33 -0
- package/src/transformers/{url-params.js → urlParameters.js} +0 -0
- package/src/utils/helpers.js +2 -8
- package/test/expected/posthtml/component.html +13 -0
- package/test/expected/{inheritance.html → posthtml/extend-template.html} +2 -2
- package/test/expected/posthtml/fetch.html +5 -0
- package/test/expected/posthtml/layout.html +3 -0
- package/test/expected/transformers/atimport-in-style.html +15 -0
- package/test/expected/transformers/base-url.html +99 -0
- package/test/expected/transformers/filters.html +81 -0
- package/test/expected/transformers/preserve-transform-css.html +36 -0
- package/test/expected/useConfig.html +9 -0
- package/test/fixtures/basic.html +9 -9
- package/test/fixtures/posthtml/component.html +19 -0
- package/test/fixtures/{inheritance.html → posthtml/extend-template.html} +7 -7
- package/test/fixtures/posthtml/fetch.html +9 -0
- package/test/fixtures/posthtml/layout.html +11 -0
- package/test/fixtures/transformers/atimport-in-style.html +11 -0
- package/test/fixtures/transformers/base-url.html +101 -0
- package/test/fixtures/transformers/filters.html +87 -0
- package/test/fixtures/transformers/preserve-transform-css.html +25 -0
- package/test/fixtures/useConfig.html +9 -0
- package/test/stubs/components/component.html +5 -0
- package/test/stubs/data.json +14 -0
- package/test/stubs/layouts/basic.html +1 -0
- package/test/stubs/{layout.html → layouts/full.html} +0 -0
- package/test/stubs/{layout-basic.html → layouts/template.html} +5 -5
- package/test/stubs/post.css +6 -0
- package/test/stubs/tailwind/content-source.html +1 -0
- package/test/stubs/tailwind/tailwind.css +3 -0
- package/test/stubs/template.html +10 -10
- package/test/stubs/templates/1.html +1 -1
- package/test/stubs/templates/2.test +1 -0
- package/test/test-config.js +19 -19
- package/test/test-misc.js +8 -8
- package/test/test-postcss.js +8 -0
- package/test/test-posthtml.js +72 -0
- package/test/test-tailwindcss.js +117 -0
- package/test/test-todisk.js +142 -49
- package/test/test-tostring.js +148 -124
- package/test/test-transformers.js +510 -320
- package/xo.config.js +22 -19
- package/src/transformers/base-image-url.js +0 -9
- package/src/transformers/remove-unused-css.js +0 -20
- package/src/transformers/six-hex.js +0 -10
- package/src/transformers/transform.js +0 -24
- package/test/expected/transformers/base-image-url.html +0 -7
- package/test/fixtures/transformers/base-image-url.html +0 -7
- package/test/stubs/templates/2.html +0 -1
- package/test/stubs/templates/3.mzl +0 -1
- package/test/test-tailwind.js +0 -73
|
@@ -1,29 +1,28 @@
|
|
|
1
|
-
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
|
2
|
-
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
|
3
|
-
|
|
4
|
-
name: Node.js CI
|
|
5
|
-
|
|
6
|
-
on:
|
|
7
|
-
push:
|
|
8
|
-
branches: [master]
|
|
9
|
-
pull_request:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
- run: npm
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
CI: true
|
|
1
|
+
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
|
2
|
+
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
|
3
|
+
|
|
4
|
+
name: Node.js CI
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [master]
|
|
9
|
+
pull_request:
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
node-version: [14, 16, 17]
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v2
|
|
21
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
22
|
+
uses: actions/setup-node@v1
|
|
23
|
+
with:
|
|
24
|
+
node-version: ${{ matrix.node-version }}
|
|
25
|
+
- run: npm install
|
|
26
|
+
- run: npm test
|
|
27
|
+
env:
|
|
28
|
+
CI: true
|
package/bin/maizzle
ADDED
package/package.json
CHANGED
|
@@ -1,84 +1,91 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@maizzle/framework",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Maizzle is a framework that helps you quickly build HTML emails with Tailwind CSS.",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"main": "src/index.js",
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"email
|
|
21
|
-
"email-
|
|
22
|
-
"email-
|
|
23
|
-
"email-
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"posthtml
|
|
56
|
-
"posthtml-
|
|
57
|
-
"posthtml-
|
|
58
|
-
"posthtml-
|
|
59
|
-
"posthtml-
|
|
60
|
-
"posthtml-
|
|
61
|
-
"posthtml-
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
"
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@maizzle/framework",
|
|
3
|
+
"version": "4.0.0-alpha.10",
|
|
4
|
+
"description": "Maizzle is a framework that helps you quickly build HTML emails with Tailwind CSS.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"maizzle": "bin/maizzle"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/maizzle/framework.git"
|
|
13
|
+
},
|
|
14
|
+
"bugs": "https://github.com/maizzle/framework/issues",
|
|
15
|
+
"homepage": "https://maizzle.com",
|
|
16
|
+
"author": "Cosmin Popovici (https://github.com/cossssmin)",
|
|
17
|
+
"keywords": [
|
|
18
|
+
"maizzle",
|
|
19
|
+
"tailwindcss",
|
|
20
|
+
"responsive-email",
|
|
21
|
+
"email-framework",
|
|
22
|
+
"email-template",
|
|
23
|
+
"email-marketing",
|
|
24
|
+
"email-campaigns",
|
|
25
|
+
"email-newsletter",
|
|
26
|
+
"email-boilerplate",
|
|
27
|
+
"html-emails"
|
|
28
|
+
],
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"test": "c8 ava -s",
|
|
34
|
+
"pretest": "xo",
|
|
35
|
+
"style": "xo",
|
|
36
|
+
"release": "np"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@maizzle/cli": "^1.4.0",
|
|
40
|
+
"autoprefixer": "^10.4.0",
|
|
41
|
+
"browser-sync": "^2.26.13",
|
|
42
|
+
"color-shorthand-hex-to-six-digit": "^3.0.2",
|
|
43
|
+
"email-comb": "^5.2.0",
|
|
44
|
+
"front-matter": "^4.0.0",
|
|
45
|
+
"fs-extra": "^10.0.0",
|
|
46
|
+
"glob-promise": "^4.1.0",
|
|
47
|
+
"html-crush": "^4.0.0",
|
|
48
|
+
"is-url-superb": "^5.0.0",
|
|
49
|
+
"juice": "^8.0.0",
|
|
50
|
+
"lodash": "^4.17.20",
|
|
51
|
+
"ora": "^5.1.0",
|
|
52
|
+
"postcss": "^8.4.4",
|
|
53
|
+
"postcss-import": "^14.0.0",
|
|
54
|
+
"postcss-merge-longhand": "^5.0.1",
|
|
55
|
+
"posthtml": "^0.16.6",
|
|
56
|
+
"posthtml-attrs-parser": "^0.1.1",
|
|
57
|
+
"posthtml-base-url": "^1.0.1",
|
|
58
|
+
"posthtml-content": "^0.1.0",
|
|
59
|
+
"posthtml-expressions": "^1.8.1",
|
|
60
|
+
"posthtml-extend": "^0.6.0",
|
|
61
|
+
"posthtml-extra-attributes": "^1.0.0",
|
|
62
|
+
"posthtml-fetch": "^2.2.0",
|
|
63
|
+
"posthtml-markdownit": "^1.3.0",
|
|
64
|
+
"posthtml-match-helper": "^1.0.3",
|
|
65
|
+
"posthtml-modules": "^0.9.0",
|
|
66
|
+
"posthtml-mso": "^1.0.4",
|
|
67
|
+
"posthtml-postcss-merge-longhand": "^1.0.2",
|
|
68
|
+
"posthtml-remove-attributes": "^1.0.0",
|
|
69
|
+
"posthtml-safe-class-names": "^1.0.8",
|
|
70
|
+
"posthtml-url-parameters": "^1.0.4",
|
|
71
|
+
"pretty": "^2.0.0",
|
|
72
|
+
"prevent-widows": "^1.0.2",
|
|
73
|
+
"query-string": "^7.1.0",
|
|
74
|
+
"string-strip-html": "^8.2.0",
|
|
75
|
+
"tailwindcss": "^3.0.0"
|
|
76
|
+
},
|
|
77
|
+
"devDependencies": {
|
|
78
|
+
"ava": "^4.0.1",
|
|
79
|
+
"c8": "^7.11.0",
|
|
80
|
+
"np": "*",
|
|
81
|
+
"xo": "0.39.1"
|
|
82
|
+
},
|
|
83
|
+
"engines": {
|
|
84
|
+
"node": ">=14.0.0"
|
|
85
|
+
},
|
|
86
|
+
"ava": {
|
|
87
|
+
"files": [
|
|
88
|
+
"test/**/test*.js"
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const ora = require('ora')
|
|
2
|
+
const {get} = require('lodash')
|
|
3
|
+
const Output = require('../generators/output')
|
|
4
|
+
const {clearConsole} = require('../utils/helpers')
|
|
5
|
+
|
|
6
|
+
const build = async (env = 'local', config = {}) => {
|
|
7
|
+
const start = new Date()
|
|
8
|
+
const spinner = ora('Building emails...').start()
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
const {files, parsed} = await Output.toDisk(env, spinner, config)
|
|
12
|
+
|
|
13
|
+
const elapsedSeconds = (Date.now() - start) / 1000
|
|
14
|
+
|
|
15
|
+
if (get(config, 'build.command') === 'serve') {
|
|
16
|
+
if (get(config, 'build.console.clear')) {
|
|
17
|
+
clearConsole()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
spinner.succeed(`Re-built ${parsed.length} templates in ${elapsedSeconds}s`)
|
|
21
|
+
} else {
|
|
22
|
+
spinner.succeed(`Built ${parsed.length} templates in ${elapsedSeconds}s`)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return {files}
|
|
26
|
+
} catch (error) {
|
|
27
|
+
spinner.fail(error.message)
|
|
28
|
+
throw error
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = build
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
const ora = require('ora')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const fs = require('fs-extra')
|
|
4
|
+
|
|
5
|
+
const Config = require('../generators/config')
|
|
6
|
+
const buildToFile = require('../commands/build')
|
|
7
|
+
const renderToString = require('../functions/render')
|
|
8
|
+
|
|
9
|
+
const {get, merge, isObject} = require('lodash')
|
|
10
|
+
const {clearConsole} = require('../utils/helpers')
|
|
11
|
+
|
|
12
|
+
const browsersync = () => {
|
|
13
|
+
if (!global.cachedBrowserSync) {
|
|
14
|
+
const bs = require('browser-sync')
|
|
15
|
+
global.cachedBrowserSync = bs.create()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return global.cachedBrowserSync
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const serve = async (env = 'local', config = {}) => {
|
|
22
|
+
config = merge(
|
|
23
|
+
config,
|
|
24
|
+
await Config.getMerged(env),
|
|
25
|
+
{
|
|
26
|
+
build: {
|
|
27
|
+
command: 'serve'
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
const spinner = ora()
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
await buildToFile(env, config)
|
|
36
|
+
|
|
37
|
+
let templates = get(config, 'build.templates')
|
|
38
|
+
templates = Array.isArray(templates) ? templates : [templates]
|
|
39
|
+
|
|
40
|
+
const templatePaths = [...new Set(templates.map(config => `${get(config, 'source', 'src')}/**`))]
|
|
41
|
+
const globalPaths = [
|
|
42
|
+
'src/**',
|
|
43
|
+
get(config, 'build.tailwind.config', 'tailwind.config.js'),
|
|
44
|
+
...new Set(get(config, 'build.browsersync.watch', []))
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
// Watch for Template file changes
|
|
48
|
+
browsersync()
|
|
49
|
+
.watch(templatePaths)
|
|
50
|
+
.on('change', async file => {
|
|
51
|
+
if (config.events && typeof config.events.beforeCreate === 'function') {
|
|
52
|
+
await config.events.beforeCreate(config)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Don't render if file type is not configured
|
|
56
|
+
// eslint-disable-next-line
|
|
57
|
+
const filetypes = templates.reduce((acc, template) => {
|
|
58
|
+
return [...acc, ...get(template, 'filetypes', ['html'])]
|
|
59
|
+
}, [])
|
|
60
|
+
|
|
61
|
+
if (!filetypes.includes(path.extname(file).slice(1))) {
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (get(config, 'build.console.clear')) {
|
|
66
|
+
clearConsole()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const start = new Date()
|
|
70
|
+
|
|
71
|
+
spinner.start('Building email...')
|
|
72
|
+
|
|
73
|
+
file = file.replace(/\\/g, '/')
|
|
74
|
+
|
|
75
|
+
const renderOptions = {
|
|
76
|
+
maizzle: config,
|
|
77
|
+
...config.events
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
renderToString(
|
|
81
|
+
await fs.readFile(file, 'utf8'),
|
|
82
|
+
renderOptions
|
|
83
|
+
)
|
|
84
|
+
.then(async ({html, config}) => {
|
|
85
|
+
let source = ''
|
|
86
|
+
let dest = ''
|
|
87
|
+
let ext = ''
|
|
88
|
+
|
|
89
|
+
if (Array.isArray(config.build.templates)) {
|
|
90
|
+
const match = config.build.templates.find(template => template.source === path.parse(file).dir)
|
|
91
|
+
source = get(match, 'source')
|
|
92
|
+
dest = get(match, 'destination.path', 'build_local')
|
|
93
|
+
ext = get(match, 'destination.ext', 'html')
|
|
94
|
+
} else if (isObject(config.build.templates)) {
|
|
95
|
+
source = get(config, 'build.templates.source')
|
|
96
|
+
dest = get(config, 'build.templates.destination.path', 'build_local')
|
|
97
|
+
ext = get(config, 'build.templates.destination.ext', 'html')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const fileDir = path.parse(file).dir.replace(source, '')
|
|
101
|
+
const finalDestination = path.join(dest, fileDir, `${path.parse(file).name}.${ext}`)
|
|
102
|
+
|
|
103
|
+
await fs.outputFile(config.permalink || finalDestination, html)
|
|
104
|
+
})
|
|
105
|
+
.then(() => {
|
|
106
|
+
browsersync().reload()
|
|
107
|
+
spinner.succeed(`Compiled in ${(Date.now() - start) / 1000}s [${file}]`)
|
|
108
|
+
})
|
|
109
|
+
.catch(() => spinner.warn(`Received empty HTML, please save your file again [${file}]`))
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
// Watch for changes in all other files
|
|
113
|
+
browsersync()
|
|
114
|
+
.watch(globalPaths, {ignored: templatePaths})
|
|
115
|
+
.on('change', () => buildToFile(env, config).then(() => browsersync().reload()))
|
|
116
|
+
.on('unlink', () => buildToFile(env, config).then(() => browsersync().reload()))
|
|
117
|
+
|
|
118
|
+
// Watch for changes in config files
|
|
119
|
+
browsersync()
|
|
120
|
+
.watch('config*.js')
|
|
121
|
+
.on('change', async file => {
|
|
122
|
+
const parsedEnv = path.parse(file).name.split('.')[1] || 'local'
|
|
123
|
+
|
|
124
|
+
Config
|
|
125
|
+
.getMerged(parsedEnv)
|
|
126
|
+
.then(config => buildToFile(parsedEnv, config).then(() => browsersync().reload()))
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
// Browsersync options
|
|
130
|
+
const baseDir = templates.map(t => t.destination.path)
|
|
131
|
+
|
|
132
|
+
// Initialize Browsersync
|
|
133
|
+
browsersync()
|
|
134
|
+
.init(
|
|
135
|
+
merge(
|
|
136
|
+
{
|
|
137
|
+
notify: false,
|
|
138
|
+
open: false,
|
|
139
|
+
port: 3000,
|
|
140
|
+
server: {
|
|
141
|
+
baseDir,
|
|
142
|
+
directory: true
|
|
143
|
+
},
|
|
144
|
+
tunnel: false,
|
|
145
|
+
ui: {port: 3001},
|
|
146
|
+
logFileChanges: false
|
|
147
|
+
},
|
|
148
|
+
get(config, 'build.browsersync', {})
|
|
149
|
+
), () => {})
|
|
150
|
+
} catch (error) {
|
|
151
|
+
spinner.fail(error)
|
|
152
|
+
throw error
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = serve
|