1 let CleanCSS = require('@ndcode/clean-css')
2 let assert = require('assert')
3 let html_entities = require('html-entities')
4 let html_minifier = require('@ndcode/html-minifier')
5 let node_stringify = require('node-stringify')
6 let uglify_es = require('uglify-es')
8 let clean_css = new CleanCSS({format: 'beautify'})
9 let xml_entities = new html_entities.XmlEntities()
11 let jstize = (text, options) => {
12 options = Object.assign(
13 {indent: 2, initial_indent: 0},
17 let indent = options.indent * options.initial_indent
20 new html_minifier.HTMLParser(
24 start: (tag, attrs, unary) => { //, unarySlash, autoGenerated) {
26 //for (let i = 0; i < attrs.length; ++i) {
27 // out += ` ${attrs[i].name}`
28 // if (attrs[i].value !== undefined)
29 // out += `="${attrs[i].value}"`
36 for (let i = 0; i < attrs.length; ++i) {
37 if (attrs[i].name == 'class') {
38 let fields = xml_entities.decode(attrs[i].value).split(' ')
39 for (let j = 0; j < fields.length; ++j)
41 /([.#])([^.#]*-[0-9]*)$/,
42 (match, sep, name) => sep + node_stringify(name)
45 else if (attrs[i].name == 'id') {
46 let fields = xml_entities.decode(attrs[i].value).split(' ')
47 for (let j = 0; j < fields.length; ++j)
48 out += '#' + fields[j]
51 out1 += prefix + attrs[i].name
52 if (attrs[i].value !== undefined)
54 '=' + JSON.stringify(xml_entities.decode(attrs[i].value))
62 /([.#])(([^.#]*-)?style)$/,
63 (match, sep, name) => sep + node_stringify(name)
67 (unary ? ' {}\n' : ' {\n')
71 indent += options.indent
74 end: tag => { //, attrs, autoGenerated) => {
75 assert(tag === tags.pop())
76 indent -= options.indent
77 //buffer.push(`</${tag}>`)
80 buffer.length && buffer[buffer.length - 1].slice(-2) == '{\n' ?
81 buffer.pop().slice(0, -1) :
87 chars: text => { //, prevTag, nextTag) {
89 if (tags.length && tags[tags.length - 1] === 'script') {
90 let render = uglify_es.minify(
97 indent_level: options.indent,
103 if (render.error !== undefined)
105 //buffer.push(render.code)
106 out = render.code.split('\n')
107 if (out.length && out[out.length - 1].length === 0)
110 else if (tags.length && tags[tags.length - 1] === 'style') {
111 let render = clean_css.minify(text)
112 //for (let i = 0; i < render.warnings.length; ++i)
113 // console.log(`clean-css warning: ${render.warnings[i]}`)
114 //buffer.push(render.styles)
115 out = render.styles.split('\n')
116 if (out.length && out[out.length - 1].length === 0)
121 out = [node_stringify(xml_entities.decode(text))]
122 for (let i = 0; i < out.length; ++i)
123 buffer.push(' '.repeat(indent) + out[i] + '\n')
125 comment: (text, nonStandard) => {
126 let prefix = nonStandard ? '<!' : '<!--'
127 let suffix = nonStandard ? '>' : '-->'
128 let match = text.match(/^(\[if\s[^\]]+]>)([\s\S]*?)(<!\[endif])$/)
131 `${' '.repeat(indent)}_out.push('${prefix}${match[1]}')\n`
135 `${' '.repeat(indent)}_out.push('${match[3]}${suffix}')\n`
140 `${' '.repeat(indent)}_out.push('${prefix}${text}${suffix}')\n`
143 doctype: doctype => {
144 //buffer.push(doctype)
146 `${' '.repeat(indent)}_out.push('${doctype}')\n`
152 parse(html_minifier.minify(text, {collapseWhitespace: true}))
153 assert(tags.length === 0)
154 return buffer.join('')
157 module.exports = jstize