-#!/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
+let jstize = text => {
+ 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}'`
)
- 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`
+ indent.join('') + out + out1 + suffix + (unary ? ' {}\n' : ' {\n')
)
- parse(match[2])
+ if (!unary) {
+ tags.push(tag)
+ indent.push(' ')
+ }
+ },
+ end: tag => { //, attrs, autoGenerated) => {
+ assert(tag === tags.pop())
+ indent.pop()
+ //buffer.push(`</${tag}>`)
buffer.push(
- `${indent.join('')}_out.push('${match[3]}${suffix}')\n`
+ (
+ buffer.length && buffer[buffer.length - 1].slice(-2) == '{\n' ?
+ buffer.pop().slice(0, -1) :
+ indent.join('')
+ ) +
+ '}\n'
)
- }
- else
+ },
+ chars: text => { //, prevTag, nextTag) {
+ let out
+ if (tags.length && tags[tags.length - 1] === 'script') {
+ let render = uglify_es.minify(
+ text,
+ {
+ compress: false,
+ output: {
+ beautify: true,
+ indent_level: 2,
+ shebang: false
+ },
+ toplevel: true
+ }
+ )
+ 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('${prefix}${text}${suffix}')\n`
+ `${indent.join('')}_out.push('${doctype}')\n`
)
- },
- doctype: doctype => {
- //buffer.push(doctype)
- buffer.push(
- `${indent.join('')}_out.push('${doctype}')\n`
- )
+ }
}
- }
- )
+ )
+ }
+ parse(html_minifier.minify(text, {collapseWhitespace: true}))
+ return buffer.join('')
}
-parse(
- html_minifier.minify(
- fs.readFileSync(0, {encoding: 'utf-8'}),
- {collapseWhitespace: true}
- )
-)
-fs.writeSync(1, buffer.join(''), {encoding: 'utf-8'})
+
+module.exports = jstize