Skip to content

Commit

Permalink
Reworked beautify and minify options to align more to the new mjml-cl…
Browse files Browse the repository at this point in the history
…i and removing the associated deprecation message
  • Loading branch information
adrianrudnik committed Sep 17, 2023
1 parent 753672f commit 63b918c
Show file tree
Hide file tree
Showing 5 changed files with 2,910 additions and 2,013 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ RUN set -ex \
&& apk --no-cache upgrade \
&& apk --no-cache add curl ca-certificates \
&& update-ca-certificates \
&& npm install
&& npm --env=production install

COPY index.js ./index.js

Expand Down
151 changes: 90 additions & 61 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,105 +2,134 @@

'use strict'

const express = require('express'),
bodyParser = require('body-parser'),
os = require('os'),
mjml2html = require('mjml'),
program = require('commander')
const express = require('express')
const bodyParser = require('body-parser')
const os = require('os')
const mjml2html = require('mjml')
const program = require('commander')
const beautifyHtml = require('js-beautify').html
const minifyHtml = require('html-minifier').minify

program.usage('[options]').parse(process.argv)

const app = express()

app.use(bodyParser.text({
app.use(
bodyParser.text({
inflate: true,
limit: '2048kb',
type: '*/*',
}))
type: '*/*'
})
)

const opts = {
keepComments: (process.env.MJML_KEEP_COMMENTS === 'true'),
minify: (process.env.MJML_MINIFY === 'true'),
beautify: (process.env.MJML_BEAUTIFY === 'true'),
validationLevel: (['soft', 'strict', 'skip'].includes(process.env.MJML_VALIDATION_LEVEL) ? process.env.MJML_VALIDATION_LEVEL : 'soft'),
healthchecks: (process.env.HEALTHCHECK === 'true')
keepComments: process.env.MJML_KEEP_COMMENTS === 'true',
validationLevel: ['soft', 'strict', 'skip']
.includes(process.env.MJML_VALIDATION_LEVEL)
? process.env.MJML_VALIDATION_LEVEL
: 'soft',
healthchecks: process.env.HEALTHCHECK === 'true'
}

const charsetOpts = {
write: (process.env.CHARSET),
contentType: (process.env.DEFAULT_RESPONSE_CONTENT_TYPE)
write: process.env.CHARSET,
contentType: process.env.DEFAULT_RESPONSE_CONTENT_TYPE || 'text/html; charset=utf-8'
}

const doBeautify = process.env.MJML_BEAUTIFY === 'true'
const doMinifiy = process.env.MJML_MINIFY === 'true'

app.all('*', function (req, res) {
// enable cors
if (process.env.CORS) {
res.header('Access-Control-Allow-Origin', process.env.CORS)
res.header('Access-Control-Allow-Headers', '*')
res.header('Access-Control-Allow-Methods', 'POST')
res.header('Access-Control-Max-Age', '-1')
// enable cors
if (process.env.CORS) {
res.header('Access-Control-Allow-Origin', process.env.CORS)
res.header('Access-Control-Allow-Headers', '*')
res.header('Access-Control-Allow-Methods', 'POST')
res.header('Access-Control-Max-Age', '-1')
}

// ensure content type is set
if (!req.headers['content-type']) {
res.status(500).send('Content-Type must be set, use text/plain if unsure')
return
}

try {
const result = mjml2html(req.body || '', opts)

if (doBeautify) {
result.html = beautifyHtml(result.html, {
indent_size: 2,
wrap_attributes_indent_size: 2,
max_preserve_newline: 0,
preserve_newlines: false,
end_with_newline: true
})
}

if (doMinifiy) {
result.html = minifyHtml(result.html, {
collapseWhitespace: true,
minifyCSS: false,
caseSensitive: true,
removeEmptyAttributes: true
})
}

// ensure content type is set
if (!req.headers['content-type']) {
res.status(500).send('Content-Type must be set, use text/plain if unsure')
return
if (charsetOpts.contentType !== '') {
res.writeHead(200, { 'Content-Type': charsetOpts.contentType })
} else {
// fall back
res.writeHead(200, { 'Content-Type': 'text/html' })
}

try {
const result = mjml2html(req.body || '', opts)
if (charsetOpts.contentType != "") {
res.writeHead(200, {'Content-Type': charsetOpts.contentType})
} else {
// fall back
res.writeHead(200, {'Content-Type': 'text/html'})
}
if (charsetOpts.write != "") {
res.write(result.html, charsetOpts.write)
} else {
res.write(result.html)
}

res.end()
} catch (ex) {
// print error details
console.log(req.body || '')
console.error(ex)
console.log('')

res.writeHead(400, {'Content-Type': 'text/plain'})
res.end(ex.message)
if (charsetOpts.write !== '') {
res.write(result.html, charsetOpts.write)
} else {
res.write(result.html)
}

res.end()
} catch (ex) {
// print error details
console.log(req.body || '')
console.error(ex)
console.log('')

res.writeHead(400, { 'Content-Type': 'text/plain' })
res.end(ex.message)
}
})

const server = app.listen(process.env.PORT || 80)

const signals = {
'SIGHUP': 1,
'SIGINT': 2,
'SIGTERM': 15,
SIGHUP: 1,
SIGINT: 2,
SIGTERM: 15
}

const shutdown = (signal, value) => {
server.close(() => {
console.log(`app stopped by ${signal} with value ${value}`)
process.exit(128 + value)
})
server.close(() => {
console.log(`app stopped by ${signal} with value ${value}`)
process.exit(128 + value)
})
}

Object.keys(signals).forEach((signal) => {
process.on(signal, () => {
console.log(`process received a ${signal} signal`)
shutdown(signal, signals[signal])
})
process.on(signal, () => {
console.log(`process received a ${signal} signal`)
shutdown(signal, signals[signal])
})
})

console.log('self: ' + os.hostname() + ':' + server.address().port)
console.log('cors: ' + (process.env.CORS || 'n/a'))
console.log('healthchecks: ' + opts.healthchecks)
console.log('mjml keep comments: ' + opts.keepComments)
console.log('mjml validation level: ' + opts.validationLevel)
console.log('mjml minify: ' + opts.minify)
console.log('mjml beautify: ' + opts.beautify)
console.log('mjml beautify: ' + doBeautify)
console.log('mjml minify: ' + doMinifiy)
console.log('node default content-type:' + charsetOpts.contentType)
console.log('node write charset:' + charsetOpts.write)
console.log('')
Expand Down
Loading

0 comments on commit 63b918c

Please sign in to comment.