--- /dev/null
+#!/usr/bin/env node
+
+let CleanCSS = require('@ndcode/clean-css')
+let assert = require('assert')
+let fs = require('fs')
+let html_minifier = require('@ndcode/html-minifier')
+let uglify_es = require('uglify-es')
+
+let clean_css = new CleanCSS({format: 'beautify'})
+
+let tags = []
+let indent = []
+let buffer = []
+let parse = text => {
+ new html_minifier.HTMLParser(
+ text,
+ {
+ html5: true,
+ start: (tag, attrs, unary) => { //, unarySlash, autoGenerated) {
+ //let out = `<${tag}`
+ //for (let i = 0; i < attrs.length; ++i) {
+ // out += ` ${attrs[i].name}`
+ // if (attrs[i].value !== undefined)
+ // out += `="${attrs[i].value}"`
+ //}
+ //out += '>'
+ let out = tag
+ let out1 = ''
+ let prefix = '('
+ let suffix = ''
+ for (let i = 0; i < attrs.length; ++i) {
+ if (attrs[i].name == 'class') {
+ let fields = attrs[i].value.split(' ')
+ for (let j = 0; j < fields.length; ++j)
+ out = out.replace(
+ /([.#])([^.#]*-[0-9]*)$/,
+ (match, sep, name) => `${sep}'${name}'`
+ ) + '.' + fields[j]
+ }
+ else if (attrs[i].name == 'id') {
+ let fields = attrs[i].value.split(' ')
+ for (let j = 0; j < fields.length; ++j)
+ out += '#' + fields[j]
+ }
+ else {
+ out1 += prefix + attrs[i].name
+ if (attrs[i].value !== undefined)
+ out1 += `="${attrs[i].value}"`
+ prefix = ' '
+ suffix = ')'
+ }
+ }
+ out = out.replace(
+ /([.#])style$/,
+ (match, sep) => `${sep}'style'`
+ ).replace(
+ /([.#])([^.#]*-style)$/,
+ (match, sep, name) => `${sep}'${name}'`
+ )
+ buffer.push(
+ indent.join('') + out + out1 + suffix + (unary ? ' {}\n' : ' {\n')
+ )
+ if (!unary) {
+ tags.push(tag)
+ indent.push(' ')
+ }
+ },
+ end: tag => { //, attrs, autoGenerated) => {
+ assert(tag === tags.pop())
+ indent.pop()
+ //buffer.push(`</${tag}>`)
+ buffer.push(
+ (
+ buffer.length && buffer[buffer.length - 1].slice(-2) == '{\n' ?
+ buffer.pop().slice(0, -1) :
+ indent.join('')
+ ) +
+ '}\n'
+ )
+ },
+ chars: text => { //, prevTag, nextTag) {
+ let out
+ if (tags.length && tags[tags.length - 1] === 'script') {
+ let render = uglify_es.minify(
+ text,
+ {
+ compress: false,
+ //ecma: undefined,
+ //ie8: false,
+ //keep_classnames: undefined,
+ //keep_fnames: false,
+ //mangle: {},
+ //nameCache: null,
+ output: {
+ //ascii_only : false,
+ beautify : true, //false,
+ //bracketize : false,
+ //comments : false,
+ //ecma : 5,
+ //ie8 : false,
+ indent_level : 2, //4,
+ //indent_start : 0,
+ //inline_script : true,
+ //keep_quoted_props: false,
+ //max_line_len : false,
+ //preamble : null,
+ //preserve_line : false,
+ //quote_keys : false,
+ //quote_style : 0,
+ //safari10 : false,
+ //semicolons : true,
+ shebang : false //true,
+ //shorthand : undefined,
+ //source_map : null,
+ //webkit : false,
+ //width : 80,
+ //wrap_iife : false
+ },
+ //parse: {
+ //bare_returns : false,
+ //ecma : 8,
+ //expression : false,
+ //filename : null,
+ //html5_comments : true,
+ //shebang : true,
+ //strict : false,
+ //toplevel : null
+ //},
+ //rename: undefined,
+ //safari10: false,
+ //sourceMap: false,
+ //timings: false,
+ toplevel: true //false,
+ //warnings: false,
+ //wrap: false
+ }
+ )
+ if (render.error !== undefined)
+ throw render.error
+ //buffer.push(render.code)
+ out = render.code.split('\n')
+ if (out.length && out[out.length - 1].length === 0)
+ out.pop()
+ }
+ else if (tags.length && tags[tags.length - 1] === 'style') {
+ let render = clean_css.minify(text)
+ //for (let i = 0; i < render.warnings.length; ++i)
+ // console.log(`clean-css warning: ${render.warnings[i]}`)
+ //buffer.push(render.styles)
+ out = render.styles.split('\n')
+ if (out.length && out[out.length - 1].length === 0)
+ out.pop()
+ }
+ else
+ //buffer.push(text)
+ out = [`'${text}'`]
+ for (let i = 0; i < out.length; ++i)
+ buffer.push(indent.join('') + out[i] + '\n')
+ },
+ comment: (text, nonStandard) => {
+ let prefix = nonStandard ? '<!' : '<!--'
+ let suffix = nonStandard ? '>' : '-->'
+ let match = text.match(/^(\[if\s[^\]]+]>)([\s\S]*?)(<!\[endif])$/)
+ if (match) {
+ buffer.push(
+ `${indent.join('')}_out.push('${prefix}${match[1]}')\n`
+ )
+ parse(match[2])
+ buffer.push(
+ `${indent.join('')}_out.push('${match[3]}${suffix}')\n`
+ )
+ }
+ else
+ buffer.push(
+ `${indent.join('')}_out.push('${prefix}${text}${suffix}')\n`
+ )
+ },
+ doctype: doctype => {
+ //buffer.push(doctype)
+ buffer.push(
+ `${indent.join('')}_out.push('${doctype}')\n`
+ )
+ }
+ }
+ )
+}
+parse(
+ html_minifier.minify(
+ fs.readFileSync(0, {encoding: 'utf-8'}),
+ {collapseWhitespace: true}
+ )
+)
+fs.writeSync(1, buffer.join(''), {encoding: 'utf-8'})