|
|
@@ -6,9 +6,9 @@ const convert = require('xml-js');
|
|
|
|
|
|
defaultOptions = {
|
|
|
collapseWhitespace: true,
|
|
|
- minifyCSS:true,
|
|
|
- minifySVG:true,
|
|
|
- svgOptions:{
|
|
|
+ minifyCSS: true,
|
|
|
+ minifySVG: true,
|
|
|
+ svgOptions: {
|
|
|
plugins: svgo.extendDefaultPlugins([
|
|
|
{
|
|
|
name: 'removeViewBox',
|
|
|
@@ -23,31 +23,31 @@ defaultOptions = {
|
|
|
* @param {XMLElement} elt
|
|
|
* @returns {XMLElement} tranform XML tree by stringifying element containing the token
|
|
|
*/
|
|
|
- const toCData = function(elt,token){
|
|
|
+const toCData = function (elt, token) {
|
|
|
let transform = elt.name == token;
|
|
|
- if(elt.type=="text" && elt.text.includes(token)){
|
|
|
+ if (elt.type == "text" && elt.text.includes(token)) {
|
|
|
transform = true
|
|
|
- }else if ("attributes" in elt ){
|
|
|
+ } else if ("attributes" in elt) {
|
|
|
for (const k of Object.keys(elt.attributes)) {
|
|
|
- if (k.includes(token)){
|
|
|
+ if (k.includes(token)) {
|
|
|
transform = true;
|
|
|
- }else if(elt.attributes[k].includes(token)){
|
|
|
+ } else if (elt.attributes[k].includes(token)) {
|
|
|
transform = true
|
|
|
}
|
|
|
- if(transform){
|
|
|
+ if (transform) {
|
|
|
break
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- if (transform){
|
|
|
+ if (transform) {
|
|
|
const newElt = {
|
|
|
- type:"cdata",
|
|
|
- cdata:token + JSON.stringify(elt)
|
|
|
+ type: "cdata",
|
|
|
+ cdata: token + JSON.stringify(elt)
|
|
|
}
|
|
|
return newElt
|
|
|
- }else{
|
|
|
- if ('elements' in elt){
|
|
|
- elt.elements = elt.elements.map(e=>toCData(e,token))
|
|
|
+ } else {
|
|
|
+ if ('elements' in elt) {
|
|
|
+ elt.elements = elt.elements.map(e => toCData(e, token))
|
|
|
}
|
|
|
return elt
|
|
|
}
|
|
|
@@ -58,61 +58,65 @@ defaultOptions = {
|
|
|
* @param {XMLElement} elt
|
|
|
* @returns {XMLElement} restored XML tree
|
|
|
*/
|
|
|
-const fromCData = function(elt,token){
|
|
|
- if (elt.type == "cdata" && elt.cdata.startsWith(token)){
|
|
|
- return JSON.parse(elt.cdata.substr(token.length))
|
|
|
- }else{
|
|
|
- if ('elements' in elt){
|
|
|
- elt.elements = elt.elements.map(e=>fromCData(e,token))
|
|
|
+const fromCData = function (elt, token) {
|
|
|
+ if (elt.type == "cdata" && elt.cdata.startsWith(token)) {
|
|
|
+ return JSON.parse(elt.cdata.substr(token.length))
|
|
|
+ } else {
|
|
|
+ if ('elements' in elt) {
|
|
|
+ elt.elements = elt.elements.map(e => fromCData(e, token))
|
|
|
}
|
|
|
return elt
|
|
|
}
|
|
|
}
|
|
|
+const processASTNode = function(node,htmlOptions,cssOptions,svgOptions){
|
|
|
+ if (node instanceof U2.AST_Template
|
|
|
+ && node.tag
|
|
|
+ && ['html', 'css', 'svg'].includes(node.tag.name)) {
|
|
|
+ const templateContent = node.strings.map(s => s.replace(/[\n|\r]/gm, ' '))
|
|
|
+ if (node.tag.name == "html") {
|
|
|
|
|
|
-module.exports = function (code, options){
|
|
|
- let mergedOptions = {...defaultOptions, ...options}
|
|
|
- const ast = U2.parse(code)
|
|
|
+ const input = templateContent.join('${}');
|
|
|
+ const output = htmlMinify(input, htmlOptions)
|
|
|
+ node.strings = output.split("${}");
|
|
|
+
|
|
|
+ } else if (node.tag.name == "css" && cssOptions) {
|
|
|
+ if (templateContent.length > 1) {
|
|
|
+ throw new Error("css literal cannot use template.\r\nMore info https://lit-element.polymer-project.org/api/modules/_lit_element_.html#css ")
|
|
|
+ }
|
|
|
+ const input = templateContent[0];
|
|
|
+ const output = new CleanCSS(cssOptions).minify(input).styles
|
|
|
+ node.strings = [output];
|
|
|
+ } else if (node.tag.name == "svg" && svgOptions) {
|
|
|
+ const token = 'validTokenMlet'
|
|
|
+ const input = templateContent.join(token);
|
|
|
+ // Parse XML
|
|
|
+ let obj = convert.xml2js(input)
|
|
|
+ // Transform elements containing template to CData elt
|
|
|
+ obj = toCData(obj, token)
|
|
|
+ // Optimise svg (it does not affect Cdata elements)
|
|
|
+ let xml = convert.js2xml(obj);
|
|
|
+ xml = svgo.optimize(xml, svgOptions).data
|
|
|
+ // Revert CData elt to their original form
|
|
|
+ obj = convert.xml2js(xml)
|
|
|
+ obj = fromCData(obj, token)
|
|
|
+ // Reconstruct template
|
|
|
+ node.strings = convert.js2xml(obj).split(token);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+module.exports = function (code, options) {
|
|
|
+ let mergedOptions = { ...defaultOptions, ...options }
|
|
|
+
|
|
|
let cssOptions = false;
|
|
|
- if (mergedOptions.minifyCSS){
|
|
|
- cssOptions = typeof mergedOptions.minifyCSS == 'object' ? mergedOptions.minifyCSS:{}
|
|
|
- }
|
|
|
+ if (mergedOptions.minifyCSS) {
|
|
|
+ cssOptions = typeof mergedOptions.minifyCSS == 'object' ? mergedOptions.minifyCSS : {}
|
|
|
+ }
|
|
|
let svgOptions = false;
|
|
|
- if (mergedOptions.minifySVG){
|
|
|
- svgOptions = mergedOptions.svgOptions ? mergedOptions.svgOptions : {};
|
|
|
+ if (mergedOptions.minifySVG) {
|
|
|
+ svgOptions = mergedOptions.svgOptions ? mergedOptions.svgOptions : {};
|
|
|
}
|
|
|
- ast.walk(new U2.TreeWalker( (node)=>{
|
|
|
- if (node instanceof U2.AST_Template && node.tag && ['html','css','svg'].includes(node.tag.name)){
|
|
|
- const templateContent = node.strings.map(s=>s.replace(/[\n|\r]/gm, ' '))
|
|
|
- if(node.tag.name =="html"){
|
|
|
-
|
|
|
- const input = templateContent.join('${}');
|
|
|
- const output = htmlMinify(input, mergedOptions)
|
|
|
- node.strings = output.split("${}");
|
|
|
-
|
|
|
- } else if(node.tag.name == "css" && cssOptions){
|
|
|
- if (templateContent.length>1){
|
|
|
- throw new Error("css literal cannot use template.\r\nMore info https://lit-element.polymer-project.org/api/modules/_lit_element_.html#css ")
|
|
|
- }
|
|
|
- const input = templateContent[0];
|
|
|
- const output = new CleanCSS(cssOptions).minify(input).styles
|
|
|
- node.strings = [output];
|
|
|
- } else if(node.tag.name == "svg" && svgOptions){
|
|
|
- const token = 'validTokenMlet'
|
|
|
- const input = templateContent.join(token);
|
|
|
- // Parse XML
|
|
|
- let obj = convert.xml2js(input)
|
|
|
- // Transform elements containing template to CData elt
|
|
|
- obj = toCData(obj, token)
|
|
|
- // Optimise svg (it does not affect Cdata elements)
|
|
|
- let xml = convert.js2xml(obj);
|
|
|
- xml = svgo.optimize(xml, svgOptions).data
|
|
|
- // Revert CData elt to their original form
|
|
|
- obj = convert.xml2js(xml)
|
|
|
- obj = fromCData(obj,token)
|
|
|
- // Reconstruct template
|
|
|
- node.strings = convert.js2xml(obj).split(token);
|
|
|
- }
|
|
|
- }
|
|
|
- }))
|
|
|
+ const walker = new U2.TreeWalker((node)=>processASTNode(node,mergedOptions,cssOptions,svgOptions));
|
|
|
+ const ast = U2.parse(code)
|
|
|
+ ast.walk(walker)
|
|
|
return ast.print_to_string({ beautify: false });;
|
|
|
}
|