| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 | 
							- 'use strict';
 
- /**
 
-  * @typedef {import('../lib/types').XastElement} XastElement
 
-  */
 
- const csso = require('csso');
 
- exports.type = 'visitor';
 
- exports.name = 'minifyStyles';
 
- exports.active = true;
 
- exports.description =
 
-   'minifies styles and removes unused styles based on usage data';
 
- /**
 
-  * Minifies styles (<style> element + style attribute) using CSSO
 
-  *
 
-  * @author strarsis <strarsis@gmail.com>
 
-  *
 
-  * @type {import('../lib/types').Plugin<csso.MinifyOptions & Omit<csso.CompressOptions, 'usage'> & {
 
-  *   usage?: boolean | {
 
-  *     force?: boolean,
 
-  *     ids?: boolean,
 
-  *     classes?: boolean,
 
-  *     tags?: boolean
 
-  *   }
 
-  * }>}
 
-  */
 
- exports.fn = (_root, { usage, ...params }) => {
 
-   let enableTagsUsage = true;
 
-   let enableIdsUsage = true;
 
-   let enableClassesUsage = true;
 
-   // force to use usage data even if it unsafe (document contains <script> or on* attributes)
 
-   let forceUsageDeoptimized = false;
 
-   if (typeof usage === 'boolean') {
 
-     enableTagsUsage = usage;
 
-     enableIdsUsage = usage;
 
-     enableClassesUsage = usage;
 
-   } else if (usage) {
 
-     enableTagsUsage = usage.tags == null ? true : usage.tags;
 
-     enableIdsUsage = usage.ids == null ? true : usage.ids;
 
-     enableClassesUsage = usage.classes == null ? true : usage.classes;
 
-     forceUsageDeoptimized = usage.force == null ? false : usage.force;
 
-   }
 
-   /**
 
-    * @type {Array<XastElement>}
 
-    */
 
-   const styleElements = [];
 
-   /**
 
-    * @type {Array<XastElement>}
 
-    */
 
-   const elementsWithStyleAttributes = [];
 
-   let deoptimized = false;
 
-   /**
 
-    * @type {Set<string>}
 
-    */
 
-   const tagsUsage = new Set();
 
-   /**
 
-    * @type {Set<string>}
 
-    */
 
-   const idsUsage = new Set();
 
-   /**
 
-    * @type {Set<string>}
 
-    */
 
-   const classesUsage = new Set();
 
-   return {
 
-     element: {
 
-       enter: (node) => {
 
-         // detect deoptimisations
 
-         if (node.name === 'script') {
 
-           deoptimized = true;
 
-         }
 
-         for (const name of Object.keys(node.attributes)) {
 
-           if (name.startsWith('on')) {
 
-             deoptimized = true;
 
-           }
 
-         }
 
-         // collect tags, ids and classes usage
 
-         tagsUsage.add(node.name);
 
-         if (node.attributes.id != null) {
 
-           idsUsage.add(node.attributes.id);
 
-         }
 
-         if (node.attributes.class != null) {
 
-           for (const className of node.attributes.class.split(/\s+/)) {
 
-             classesUsage.add(className);
 
-           }
 
-         }
 
-         // collect style elements or elements with style attribute
 
-         if (node.name === 'style' && node.children.length !== 0) {
 
-           styleElements.push(node);
 
-         } else if (node.attributes.style != null) {
 
-           elementsWithStyleAttributes.push(node);
 
-         }
 
-       },
 
-     },
 
-     root: {
 
-       exit: () => {
 
-         /**
 
-          * @type {csso.Usage}
 
-          */
 
-         const cssoUsage = {};
 
-         if (deoptimized === false || forceUsageDeoptimized === true) {
 
-           if (enableTagsUsage && tagsUsage.size !== 0) {
 
-             cssoUsage.tags = Array.from(tagsUsage);
 
-           }
 
-           if (enableIdsUsage && idsUsage.size !== 0) {
 
-             cssoUsage.ids = Array.from(idsUsage);
 
-           }
 
-           if (enableClassesUsage && classesUsage.size !== 0) {
 
-             cssoUsage.classes = Array.from(classesUsage);
 
-           }
 
-         }
 
-         // minify style elements
 
-         for (const node of styleElements) {
 
-           if (
 
-             node.children[0].type === 'text' ||
 
-             node.children[0].type === 'cdata'
 
-           ) {
 
-             const cssText = node.children[0].value;
 
-             const minified = csso.minify(cssText, {
 
-               ...params,
 
-               usage: cssoUsage,
 
-             }).css;
 
-             // preserve cdata if necessary
 
-             // TODO split cdata -> text optimisation into separate plugin
 
-             if (cssText.indexOf('>') >= 0 || cssText.indexOf('<') >= 0) {
 
-               node.children[0].type = 'cdata';
 
-               node.children[0].value = minified;
 
-             } else {
 
-               node.children[0].type = 'text';
 
-               node.children[0].value = minified;
 
-             }
 
-           }
 
-         }
 
-         // minify style attributes
 
-         for (const node of elementsWithStyleAttributes) {
 
-           // style attribute
 
-           const elemStyle = node.attributes.style;
 
-           node.attributes.style = csso.minifyBlock(elemStyle, {
 
-             ...params,
 
-           }).css;
 
-         }
 
-       },
 
-     },
 
-   };
 
- };
 
 
  |