Browse Source

refactor minifyTemplate

tripeur 4 years ago
parent
commit
19d7156d13
2 changed files with 68 additions and 64 deletions
  1. 67 63
      minifyTemplate.js
  2. 1 1
      test/template.test.js

+ 67 - 63
minifyTemplate.js

@@ -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 });;
 }

+ 1 - 1
test/template.test.js

@@ -6,7 +6,7 @@ test('Test html string with template', () => {
 });
 
 test('Test html string with nested template', () => {
-    expect(templateMinify("let echo = 1;\r html`\r\r\n <div> html test ${echo ? html`<div>\r\nEcho\r\n</div>`:``}\r</div> `",{collapseWhitespace: true}))
+    expect(templateMinify("let echo = 1;\r html`\r\r\n <div> html test ${echo ? html`<div>\r\nEcho\r\n</div>` : ``}\r</div> `",{collapseWhitespace: true}))
                     .toBe("let echo=1;html`<div>html test ${echo?html`<div>Echo</div>`:``}</div>`;");
 });