},
uglify_options: {
compress: commander.compress,
- mangle: commander.mangle
+ mangle: commander.mangle,
+ output: {inline_script: false}
}
}
),
let astring = require('astring')
let transform = require('./transform')
let visitors = require('./visitors')
-let uglify_js = require('uglify-js')
+let uglify_js = require('@ndcode/uglify-js')
let jst = (text, options) => {
options = Object.assign(
}
)
)
- return (
- options.output === 'astring' ?
- astring.generate(ast, options.astring_options) :
- uglify_js.minify(
- uglify_js.AST_Node.from_mozilla_ast(ast),
- options.uglify_options
- ).code
+ if (options.output === 'astring')
+ return astring.generate(ast, options.astring_options)
+ let render = uglify_js.minify(
+ uglify_js.AST_Node.from_mozilla_ast(ast),
+ options.uglify_options
)
+ if (render.error)
+ throw render.error
+ return render.code
}
module.exports = jst
#!/bin/sh
rm -rf node_modules package-lock.json
-npm link @ndcode/build_cache @ndcode/clean-css @ndcode/disk_build
+npm link @ndcode/build_cache @ndcode/clean-css @ndcode/disk_build @ndcode/uglify-js
npm install
npm link
"@ndcode/build_cache": "^0.1.0",
"@ndcode/clean-css": "^0.1.0",
"@ndcode/disk_build": "^0.1.1",
+ "@ndcode/uglify-js": "^3.14.5",
"@rollup/plugin-buble": "^0.21.3",
"@unicode/unicode-14.0.0": "^1.2.1",
"assert": "^1.4.1",
"astring": "^1.8.1",
"commander": "^2.17.0",
- "rollup": "^2.60.2",
- "uglify-js": "^3.14.5"
+ "rollup": "^2.60.2"
},
"scripts": {
"prepare": "rollup -c rollup.config.js"
pp.parseExprSubscripts = function(refDestructuringErrors, forInit, allowHTML) { // Nick allowHTML
let startPos = this.start, startLoc = this.startLoc
let expr = this.parseExprAtom(refDestructuringErrors, forInit)
+
+ // Nick
+ if (
+ allowHTML &&
+ expr.type === "Identifier" &&
+ expr.name === "$" &&
+ this.eat(tt.braceL)
+ ) {
+ let node = this.startNodeAt(startPos, startLoc)
+ node.argument = this.parseExpression()
+ this.expect(tt.braceR)
+ expr = this.finishNode(node, "InterpolateExpression")
+ }
+
if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")")
return expr
let result = this.parseSubscripts(expr, startPos, startLoc, false, forInit, allowHTML) // Nick allowHTML
--- /dev/null
+_out = []
+_out.push('<!doctype html>')
+html(lang="en") {
+ head {
+ _out.push('<!-- Required meta tags -->')
+ meta(charset="utf-8") {}
+ meta(name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no") {}
+ _out.push('<!-- Bootstrap CSS -->')
+ link(rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous") {}
+ title {
+ 'Hello, world!'
+ }
+ }
+ body {
+ h1 {
+ 'Hello, world!'
+ }
+ _out.push('<!-- Optional JavaScript -->')
+ _out.push('<!-- jQuery first, then Popper.js, then Bootstrap JS -->')
+ script(src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous") {}
+ script(src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous") {}
+ script(src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous") {}
+ let hello1 = 'HELLO'
+ let world1 = 'WORLD'
+ script {
+ let hello = ${JSON.stringify(hello1)}
+ let world = ${JSON.stringify(world1)}
+ console.log(`oh, ${hello}, \${world}`)
+ }
+ }
+}
+console.log(_out.join(''))
}
visitors.ReturnStatement =
visitors.YieldExpression =
-visitors.AwaitExpression = (node, st, c) => {
+visitors.AwaitExpression =
+visitors.InterpolateExpression = (node, st, c) => {
if (node.argument) node.argument = c(node.argument, st, 'Expression')
return node
}
let assert = require('assert')
let astring = require('astring')
let transform = require('./transform')
-let uglify_js = require('uglify-js')
+let uglify_js = require('@ndcode/uglify-js')
let expr_to_tag = (node, context, html_allowed, call_allowed) => {
if (node.type === 'Identifier')
prefix +=
value_expr.value
.toString()
- .replace('&', '&')
- .replace('"', '"')
+ .replaceAll('&', '&')
+ .replaceAll('"', '"')
else {
let expr1 = {
type: 'Literal',
},
property: {
type: 'Identifier',
- name: 'replace'
+ name: 'replaceAll'
},
computed: false
},
},
property: {
type: 'Identifier',
- name: 'replace'
+ name: 'replaceAll'
},
computed: false
},
let result = []
let body = c(context.body, st, 'Statement').body
+ let prefix_is_template = false
if (tag === 'script') {
let program = {type: 'Program', body, sourceType: 'script'}
// simple way
// uglified way
let render = uglify_js.minify(
uglify_js.AST_Node.from_mozilla_ast(program),
- {compress: true, mangle: true}
+ {
+ compress: true,
+ mangle: true,
+ output: {interpolate: true}
+ }
)
if (render.error)
throw render.error
- prefix += render.code // we simply assume it does not contain </script> tags, should HTML escape it?
+ let code = render.code
+ if (code.includes('(${')) {
+ prefix = prefix.replaceAll('\\', '\\\\').replaceAll('${', '\\${')
+ prefix_is_template = true
+ }
+ else
+ code = code.replaceAll('\\${', '${').replaceAll('\\\\', '\\')
+ prefix += code
}
else if (body.length !== 0) {
let expr1 = {
)
prefix += '</' + tag + '>'
if (prefix.length !== 0) {
- let expr1 = {
- type: 'Literal',
- value: prefix
- }
+ let expr1 = prefix_is_template ?
+ // note: we are cheating a bit here because prefix contains some (${...})
+ // substitutions to be done by the server, and the contents of those are
+ // meant to be given in AST form in expressions list, but we can get away
+ // with it because UglifyJS uses the raw form of the quasis string which
+ // can distinguish between the (${...)} for server and \${...} for client
+ {
+ type: 'TemplateLiteral',
+ expressions: [],
+ quasis: [
+ {
+ type: 'TemplateExpression',
+ value: {
+ raw: prefix.replaceAll('`', '\\`')
+ },
+ tail: true
+ }
+ ]
+ } :
+ {
+ type: 'Literal',
+ value: prefix
+ }
expr = expr === undefined ? expr1 : {
type: 'BinaryExpression',
left: expr,
value:
node.expression.value
.toString()
- .replace('&', '&')
- .replace('<', '<')
+ .replaceAll('&', '&')
+ .replaceAll('<', '<')
}
]
}
object: c(node.expression, st, 'Expression'),
property: {
type: 'Identifier',
- name: 'replace'
+ name: 'replaceAll'
},
computed: false
},
},
property: {
type: 'Identifier',
- name: 'replace'
+ name: 'replaceAll'
},
computed: false
},