UNPKG

css-purge

Version:

A CSS tool written in Node JS as a command line app or library for the purging, burning, reducing, shortening, compressing, cleaning, trimming and formatting of duplicate, extra, excess or bloated CSS.

1,662 lines (1,415 loc) 235 kB
const clc = require('cli-color'), fs = require('fs'), path = require('path'), css = require('css'), parseCssFont = require('parse-css-font'), read = fs.readFileSync, write = fs.writeFileSync, appendToFileSync = fs.appendFileSync, validUrl = require('valid-url'), request = require('request'); const jsdom = require("jsdom"); const { JSDOM } = jsdom; var success = clc.greenBright, success2 = clc.green, info = clc.xterm(123), error = clc.red, error2 = clc.redBright, warning = clc.yellow, awesome = clc.magentaBright, logoRed = clc.xterm(197), cool = clc.xterm(105); const EventEmitter = require('events'); const crypto = require('crypto'); var hash; class CSSPurgeEmitter extends EventEmitter {} function CSSPurge() { var timeLabel = null; var CPEVENTS = new CSSPurgeEmitter(); var CONFIG = { "options": { "css": ["demo/test1.css"], "new_reduce_common_into_parent": false, "trim": true, "trim_keep_non_standard_inline_comments": false, "trim_removed_rules_previous_comment": false, "trim_comments": false, "trim_whitespace": false, "trim_breaklines": false, "trim_last_semicolon": false, "bypass_media_rules": true, "bypass_document_rules": false, "bypass_supports_rules": false, "bypass_page_rules": false, "bypass_charset": false, "shorten": true, "shorten_zero": false, "shorten_hexcolor": false, "shorten_hexcolor_extended_names": false, "shorten_hexcolor_UPPERCASE": false, "shorten_font": false, "shorten_background": false, "shorten_background_min": 2, "shorten_margin": false, "shorten_padding": false, "shorten_list_style": false, "shorten_outline": false, "shorten_border": false, "shorten_border_top": false, "shorten_border_right": false, "shorten_border_bottom": false, "shorten_border_left": false, "shorten_border_radius": false, "format": true, "format_font_family": false, "format_4095_rules_legacy_limit": false, "special_convert_rem": false, "special_convert_rem_browser_default_px": "16", "special_convert_rem_desired_html_px": "10", "special_convert_rem_font_size": true, "special_reduce_with_html" : false, "special_reduce_with_html_ignore_selectors" : [ "@-ms-", ":-ms-", "::", ":valid", ":invalid", "+.", ":-" ], "generate_report": false, "report_file_location": "css_purge_report.json", "verbose": false, "zero_units": "em, ex, %, px, cm, mm, in, pt, pc, ch, rem, vh, vw, vmin, vmax", "zero_ignore_declaration": ["filter"], "reduce_declarations_file_location": "config_reduce_declarations.json" } }; var OPTIONS = { css_output: CONFIG.options.css_output, css: CONFIG.options.css, html: CONFIG.options.html, js: CONFIG.options.js, new_reduce_common_into_parent: CONFIG.options.new_reduce_common_into_parent, trim: CONFIG.options.trim, trim_keep_non_standard_inline_comments: CONFIG.options.trim_keep_non_standard_inline_comments, trim_removed_rules_previous_comment: CONFIG.options.trim_removed_rules_previous_comment, trim_comments: CONFIG.options.trim_comments, trim_whitespace: CONFIG.options.trim_whitespace, trim_breaklines: CONFIG.options.trim_breaklines, trim_last_semicolon: CONFIG.options.trim_last_semicolon, bypass_media_rules: CONFIG.options.bypass_media_rules, bypass_document_rules: CONFIG.options.bypass_document_rules, bypass_supports_rules: CONFIG.options.bypass_supports_rules, bypass_page_rules: CONFIG.options.bypass_page_rules, bypass_charset: CONFIG.options.bypass_charset, shorten: CONFIG.options.shorten, shorten_zero: CONFIG.options.shorten_zero, shorten_hexcolor: CONFIG.options.shorten_hexcolor, shorten_hexcolor_extended_names: CONFIG.options.shorten_hexcolor_extended_names, shorten_hexcolor_UPPERCASE: CONFIG.options.shorten_hexcolor_UPPERCASE, shorten_font: CONFIG.options.shorten_font, shorten_background: CONFIG.options.shorten_background, shorten_background_min: CONFIG.options.shorten_background_min, shorten_margin: CONFIG.options.shorten_margin, shorten_padding: CONFIG.options.shorten_padding, shorten_list_style: CONFIG.options.shorten_list_style, shorten_outline: CONFIG.options.shorten_outline, shorten_border: CONFIG.options.shorten_border, shorten_border_top: CONFIG.options.shorten_border_top, shorten_border_right: CONFIG.options.shorten_border_right, shorten_border_bottom: CONFIG.options.shorten_border_bottom, shorten_border_left: CONFIG.options.shorten_border_left, shorten_border_radius: CONFIG.options.shorten_border_radius, format: CONFIG.options.format, format_font_family: CONFIG.options.format_font_family, format_4095_rules_legacy_limit: CONFIG.options.format_4095_rules_legacy_limit, special_convert_rem: CONFIG.options.special_convert_rem, special_convert_rem_browser_default_px: CONFIG.options.special_convert_rem_browser_default_px, special_convert_rem_desired_html_px: CONFIG.options.special_convert_rem_desired_html_px, special_convert_rem_font_size: CONFIG.options.special_convert_rem_font_size, special_reduce_with_html: CONFIG.options.special_reduce_with_html, special_reduce_with_html_ignore_selectors: CONFIG.options.special_reduce_with_html_ignore_selectors, generate_report: CONFIG.options.generate_report, verbose: CONFIG.options.verbose, zero_units: CONFIG.options.zero_units, zero_ignore_declaration: CONFIG.options.zero_ignore_declaration, report_file_location: CONFIG.options.report_file_location, reduce_declarations_file_location: CONFIG.options.reduce_declarations_file_location }; var currentConfig = null; var dataCSSIn = []; var dataHTMLIn = []; var dataJSIn = []; var tmpCSSPaths = []; var tmpHTMLPaths = []; var tmpJSPaths = []; var jsDom = null, jsDomWindow = null, jsDomDoc = null, resultsCount = 0; var REPORT_DUPLICATE_CSS = CONFIG.options.report_file_location; var summary = { "files" : { "input": [], "output": [], "input_html": [], "input_js": [] }, "options_used" : { "new_reduce_common_into_parent" : OPTIONS.new_reduce_common_into_parent, "trim" : OPTIONS.trim, "trim_comments" : OPTIONS.trim_comments, "trim_keep_non_standard_inline_comments" : OPTIONS.trim_keep_non_standard_inline_comments, "trim_removed_rules_previous_comment" : OPTIONS.trim_removed_rules_previous_comment, "trim_whitespace" : OPTIONS.trim_whitespace, "trim_breaklines" : OPTIONS.trim_breaklines, "trim_last_semicolon" : OPTIONS.trim_last_semicolon, "shorten" : OPTIONS.shorten, "shorten_zero" : OPTIONS.shorten_zero, "shorten_hexcolor" : OPTIONS.shorten_hexcolor, "shorten_hexcolor_extended_names" : OPTIONS.shorten_hexcolor_extended_names, "shorten_hexcolor_UPPERCASE" : OPTIONS.shorten_hexcolor_UPPERCASE, "shorten_font": OPTIONS.shorten_font, "shorten_background": OPTIONS.shorten_background, "shorten_margin": OPTIONS.shorten_margin, "shorten_padding": OPTIONS.shorten_padding, "shorten_list_style": OPTIONS.shorten_list_style, "shorten_outline": OPTIONS.shorten_outline, "shorten_border": OPTIONS.shorten_border, "shorten_border_top": OPTIONS.shorten_border_top, "shorten_border_right": OPTIONS.shorten_border_right, "shorten_border_bottom": OPTIONS.shorten_border_bottom, "shorten_border_left": OPTIONS.shorten_border_left, "shorten_border_radius": OPTIONS.shorten_border_radius, "format": OPTIONS.format, "format_font_family": OPTIONS.format_font_family, "format_4095_rules_legacy_limit": OPTIONS.format_4095_rules_legacy_limit, "special_convert_rem": OPTIONS.special_convert_rem, "special_convert_rem_browser_default_px": OPTIONS.special_convert_rem_browser_default_px, "special_convert_rem_desired_html_px": OPTIONS.special_convert_rem_desired_html_px, "special_convert_rem_font_size": OPTIONS.special_convert_rem_font_size, "generate_report" : OPTIONS.generate_report, "verbose" : OPTIONS.verbose, "bypass_media_rules" : OPTIONS.bypass_media_rules, "bypass_document_rules" : OPTIONS.bypass_document_rules, "bypass_supports_rules" : OPTIONS.bypass_supports_rules, "bypass_page_rules" : OPTIONS.bypass_page_rules, "bypass_charset" : OPTIONS.bypass_charset, "special_reduce_with_html" : OPTIONS.special_reduce_with_html, "special_reduce_with_html_ignore_selectors" : OPTIONS.special_reduce_with_html_ignore_selectors }, "stats" : {}, "duplicate_rules" : [], "duplicate_declarations" : [], 'empty_declarations' : [], "selectors_removed" : [] }; //stats var stats = { files: { css: [], html: [], js: [] }, before: { totalFileSizeKB: 0, noNodes : 0, noRules : 0, noDeclarations : 0, noComments : 0, noCharset : 0, noCustomMedia : 0, noDocument : 0, noFontFace : 0, noHost : 0, noImport : 0, noKeyframes : 0, noKeyframe : 0, noMedia : 0, noNamespace : 0, noPage : 0, noSupports : 0 }, after: { totalFileSizeKB: 0, noNodes : 0, noRules : 0, noDeclarations : 0, noComments : 0, noCharset : 0, noCustomMedia : 0, noDocument : 0, noFontFace : 0, noHost : 0, noImport : 0, noKeyframes : 0, noKeyframe : 0, noMedia : 0, noNamespace : 0, noPage : 0, noSupports : 0 }, summary: { savingsKB: 0, savingsPercentage: 0, noDuplicateRules : 0, noDuplicateDeclarations : 0, noZerosShortened: 0, noNamedColorsShortened: 0, noHexColorsShortened: 0, noRGBColorsShortened: 0, noHSLColorsShortened: 0, noFontsShortened: 0, noBackgroundsShortened: 0, noMarginsShortened: 0, noPaddingsShortened: 0, noListStylesShortened: 0, noOutlinesShortened: 0, noBordersShortened: 0, noBorderTopsShortened: 0, noBorderRightsShortened: 0, noBorderBottomsShortened: 0, noBorderLeftsShortened: 0, noBorderRadiusShortened: 0, noLastSemiColonsTrimmed: 0, noInlineCommentsTrimmed: 0, noReductions: { noNodes : 0, noRules : 0, noDeclarations : 0, noComments : 0, noCharset : 0, noCustomMedia : 0, noDocument : 0, noFontFace : 0, noHost : 0, noImport : 0, noKeyframes : 0, noKeyframe : 0, noMedia : 0, noNamespace : 0, noPage : 0, noSupports : 0 } } }; /* read declaration reduce lists */ var CONFIG_REDUCE_DECLARATIONS = 'config_reduce_declarations.json'; var hasReadReduceDeclarations = false; var reduceRulesListSelector = ''; var reduceRulesListSelectorPName = []; var reduceRulesListSelectorCount = 0; var reduceRulesListName = [ "font", "margin", "padding", "list-style", "outline", "border", "border-top", "border-right", "border-bottom", "border-left", "border-radius", "border-color", "border-top-color", "border-right-color", "border-bottom-color", "border-left-color", "color", "background-color", "font-color", "outline-color", "box-shadow", "text-shadow", "float", "font-family", "font-size", "font-weight", "font-style", "font-variant", "font-stretch" ]; var reduceRulesListNameCount = reduceRulesListName.length; var configFileLocation = 'config_css.json'; var fileLocation = 'demo/test1.css'; var outputFileLocation = 'demo/test1_out.css'; var htmlFileLocation = ''; var readStream; var readHTMLStream; var readJSStream; var readCSSFileCount = 0; var readHTMLFileCount = 0; var readJSFileCount = 0; var filesizeKB = 0; var filesizeKBHTML = 0; var filesizeKBJS = 0; var tokenex = null; var font = null, fontProps = null, fontValues = null, fontIndex = 0, hasFont = false, fontPropsOutput = [], fontValuesOutput = [], fontTmpIdx = null, fontTmpVal = null, fontVal = null, fontHasImportant = false, fontHasInherit = false; var background = null, backgroundProps = null, backgroundValues = null, backgroundIndex = 0, backgroundTmp = null, backgroundTmp2 = null, hasBackground = false, hasMultipleBackgrounds = false, hasGradient = false, backgroundHasImportant = false, backgroundPropsOutput = [], backgroundValuesOutput = [], backgroundTmpIdx = null, backgroundHasInherit = false; var margin = null, marginProps = null, marginValues = null, marginIndex = 0, marginLeftIdx = null, marginRightIdx = null, marginRightLeftVal = null, marginTopIdx = null, marginBottomIdx = null, marginTopBottomVal = null, marginSingleMerge = false, marginTmp = null, hasMargin = false, marginPropsOutput = [], marginValuesOutput = [], marginTmpIdx = null, marginTmpVal = null, marginHasImportant = false, marginHasInherit = false; var padding = null, paddingProps = null, paddingValues = null, paddingIndex = 0, paddingLeftIdx = null, paddingRightIdx = null, paddingRightLeftVal = null, paddingTopIdx = null, paddingBottomIdx = null, paddingTopBottomVal = null, paddingSingleMerge = false, paddingTmp = null, hasPadding = false, paddingPropsOutput = [], paddingValuesOutput = [], paddingTmpIdx = null, paddingHasImportant = false, paddingHasInherit = false; var listStyle = null, listStyleProps = null, listStyleValues = null, listStyleIndex = 0, listStyleTmp = null, listStyleTmp2 = null, hasListStyle = false, listStylePropsOutput = [], listStyleValuesOutput = [], listStyleTmpIdx = null, listStyleHasImportant = false, listStyleHasInherit = false; var outline = null, outlineProps = null, outlineValues = null, outlineIndex = 0, outlineTmp = null, outlineTmp2 = null, hasOutline = false, outlinePropsOutput = [], outlineValuesOutput = [], outlineTmpIdx = null, outlineHasImportant = false, outlineHasInherit = false; var border = null, borderProps = null, borderValues = null, borderIndex = 0, borderTmp = null, borderTmp2 = null, hasBorder = false, borderPropsOutput = [], borderValuesOutput = [], borderTmpIdx = null borderIsBeforeAfter = null, borderHasImportant = false, borderHasInherit = false; var borderTop = null, borderTopProps = null, borderTopValues = null, borderTopIndex = 0, borderTopTmp = null, borderTopTmp2 = null, hasBorderTop = false, borderTopPropsOutput = [], borderTopValuesOutput = [], borderTopTmpIdx = null, borderTopHasImportant = false, borderTopHasInherit = false; var borderRight = null, borderRightProps = null, borderRightValues = null, borderRightIndex = 0, borderRightTmp = null, borderRightTmp2 = null, hasBorderRight = false, borderRightPropsOutput = [], borderRightValuesOutput = [], borderRightTmpIdx = null, borderRightHasImportant = false, borderRightHasInherit = false; var borderBottom = null, borderBottomProps = null, borderBottomValues = null, borderBottomIndex = 0, borderBottomTmp = null, borderBottomTmp2 = null, hasBorderBottom = false, borderBottomPropsOutput = [], borderBottomValuesOutput = [], borderBottomTmpIdx = null, borderBottomHasImportant = false, borderBottomHasInherit = false; var borderLeft = null, borderLeftProps = null, borderLeftValues = null, borderLeftIndex = 0, borderLeftTmp = null, borderLeftTmp2 = null, hasBorderLeft = false, borderLeftPropsOutput = [], borderLeftValuesOutput = [], borderLeftTmpIdx = null, borderLeftHasImportant = false, borderLeftHasInherit = false; var borderRadius = null, borderRadiusProps = null, borderRadiusValues = null, borderRadiusIndex = 0, borderRadiusLeftIdx = null, borderRadiusRightIdx = null, borderRadiusRightLeftVal = null, borderRadiusTopIdx = null, borderRadiusBottomIdx = null, borderRadiusTopBottomVal = null, borderRadiusSingleMerge = false, borderRadiusTmp = null, borderRadiusTmp2 = null, hasBorderRadius = false, borderRadiusPropsOutput = [], borderRadiusValuesOutput = [], borderRadiusTmpIdx = null, borderRadiusHasImportant = false, borderRadiusHasInherit = false; var tmpVal = 0; var tokens_comments = []; var token3_chars = []; var token4_vals = []; var token5_vals = []; var token6_vals = []; var token7_vals = []; var g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, o = 0, dCount = 0, rCount = 0, cCount = 0; var ilen = 0, jlen = 0, klen = 0, llen = 0, mlen = 0, olen = 0; var colors = { 'aqua' : '#0ff', '#00ffff' : '#0ff', 'black' : '#000', '#000000' : '#000', 'blue' : '#00f', '#0000ff' : '#00f', 'fuchsia' : '#f0f', '#ff00ff' : '#f0f', 'grey' : 'grey', 'green' : 'green', '#808080' : 'grey', //grey / gray '#008000' : 'green', 'lime' : '#0f0', '#00ff00' : '#0f0', '#800000' : 'maroon', '#000080' : 'navy', '#808000' : 'olive', '#800080' : 'purple', '#ff0000' : 'red', 'maroon' : 'maroon', 'navy' : 'navy', 'olive' : 'olive', 'purple' : 'purple', 'red' : 'red', '#f00' : 'red', 'silver' : 'silver', 'teal' : 'teal', '#c0c0c0' : 'silver', '#008080' : 'teal', 'white' : '#fff', '#ffffff' : '#fff', 'yellow': '#ff0', '#ffff00': '#ff0' }; var extended_colors = { 'aliceblue' : '#f0f8ff', 'antiquewhite': '#faebd7', 'aquamarine': '#7fffd4', 'azure': 'azure', 'beige': 'beige', 'bisque': 'bisque', '#f0ffff': 'azure', '#f5f5dc': 'beige', '#ffe4c4': 'bisque', 'blanchedalmond': '#ffebcd', 'blueviolet': '#8a2be2', 'brown': 'brown', '#a52a2a': 'brown', 'burlywood': '#deb887', 'cadetblue': '#5f9ea0', 'chartreuse': '#7fff00', 'chocolate': '#d2691e', 'coral': 'coral', '#ff7f50': 'coral', 'cornflowerblue': '#6495ed', 'cornsilk': '#fff8dc', 'crimson': '#dc143c', 'cyan': '#0ff', 'darkblue': '#00008b', 'darkcyan': '#008b8b', 'darkgoldenrod': '#b8860b', 'darkgray': '#a9a9a9', 'darkgreen': '#006400', 'darkgrey': '#a9a9a9', 'darkkhaki': '#bdb76b', 'darkmagenta': '#8b008b', 'darkolivegreen': '#556b2f', 'darkorange': '#ff8c00', 'darkorchid': '#9932cc', 'darkred': '#8b0000', 'darksalmon': '#e9967a', 'darkseagreen': '#8fbc8f', 'darkslateblue': '#483d8b', 'darkslategray': '#2f4f4f', 'darkslategrey': '#2f4f4f', 'darkturquoise': '#00ced1', 'darkviolet': '#9400d3', 'deeppink': '#ff1493', 'deepskyblue': '#00bfff', 'dimgray': '#696969', 'dimgrey': '#696969', 'dodgerblue': '#1e90ff', 'firebrick': '#b22222', 'floralwhite': '#fffaf0', 'forestgreen': '#228b22', 'gainsboro': '#dcdcdc', 'ghostwhite': '#f8f8ff', 'gold': 'gold', '#ffd700': 'gold', 'goldenrod': '#daa520', 'greenyellow': '#adff2f', 'honeydew': '#f0fff0', 'hotpink': '#ff69b4', 'indianred': '#cd5c5c', 'indigo': 'indigo', 'ivory': 'ivory', 'khaki': 'khaki', '#4b0082': 'indigo', '#fffff0': 'ivory', '#f0e68c': 'khaki', 'lavender': '#e6e6fa', 'lavenderblush': '#fff0f5', 'lawngreen': '#7cfc00', 'lemonchiffon': '#fffacd', 'lightblue': '#add8e6', 'lightcoral': '#f08080', 'lightcyan': '#e0ffff', 'lightgoldenrodyellow': '#fafad2', 'lightgray': '#d3d3d3', 'lightgreen': '#90ee90', 'lightgrey': '#d3d3d3', 'lightpink': '#ffb6c1', 'lightsalmon': '#ffa07a', 'lightseagreen': '#20b2aa', 'lightskyblue': '#87cefa', 'lightslategray': '#789', 'lightslategrey': '#789', 'lightsteelblue': '#b0c4de', 'lightyellow': '#ffffe0', 'limegreen': '#32cd32', 'linen': 'linen', '#faf0e6': 'linen', 'magenta': '#ff00ff', 'mediumaquamarine': '#66cdaa', 'mediumblue': '#0000cd', 'mediumorchid': '#ba55d3', 'mediumpurple': '#9370db', 'mediumseagreen': '#3cb371', 'mediumslateblue': '#7b68ee', 'mediumspringgreen': '#00fa9a', 'mediumturquoise': '#48d1cc', 'mediumvioletred': '#c71585', 'midnightblue': '#191970', 'mintcream': '#f5fffa', 'mistyrose': '#ffe4e1', 'moccasin': '#ffe4b5', 'navajowhite': '#ffdead', 'oldlace': '#fdf5e6', 'olivedrab': '#6b8e23', 'orange': '#ffa500', 'orangered': '#ff4500', 'orchid': '#da70d6', 'palegoldenrod': '#eee8aa', 'palegreen': '#98fb98', 'paleturquoise': '#afeeee', 'palevioletred': '#db7093', 'papayawhip': '#ffefd5', 'peachpuff': '#ffdab9', 'peru': 'peru', 'pink': 'pink', 'plum': 'plum', '#cd853f': 'peru', '#ffc0cb': 'pink', '#dda0dd': 'plum', 'powderblue': '#b0e0e6', 'rebeccapurple': '#639', 'rosybrown': '#bc8f8f', 'royalblue': '#4169e1', 'saddlebrown': '#8b4513', 'salmon': 'salmon', '#fa8072': 'salmon', 'sandybrown': '#f4a460', 'seagreen': '#2e8b57', 'seashell': '#fff5ee', 'sienna': 'sienna', '#a0522d': 'sienna', 'skyblue': '#87ceeb', 'slateblue': '#6a5acd', 'slategray': '#708090', 'slategrey': '#708090', 'snow': 'snow', '#fffafa': 'snow', 'springgreen': '#00ff7f', 'steelblue': '#4682b4', 'tan': 'tan', '#d2b48c': 'tan', 'thistle': '#d8bfd8', 'tomato': 'tomato', '#ff6347': 'tomato', 'turquoise': '#40e0d0', 'violet': 'violet', '#ee82ee': 'violet', 'wheat': 'wheat', '#f5deb3': 'wheat', 'whitesmoke': '#f5f5f5', 'yellowgreen': '#9acd32' }; var rgbRes = null, hslRes = null; var cnum = 0, cr = 0, cg = 0, cb = 0, ch = 0, cs = 0, cl = 0; var has_changed = false, colorPos = 0, key = null; var colorex = null; var hexMatch = null; var valueInBefore = null; function processColor(valueIn, selectorsIn = '') { if (valueIn !== undefined) { has_changed = false; colorPos = 0; //named if (OPTIONS.shorten_hexcolor_extended_names || OPTIONS.shorten) { for (key in extended_colors) { if (!extended_colors.hasOwnProperty(key)) continue; colorPos = valueIn.toLowerCase().indexOf(key, colorPos); while (colorPos != -1) { colorex = new RegExp(key + "(?![\"\'.a-zA-Z0-9_-])", "g"); //global for multiple colors e.g. gradient valueInBefore = valueIn; valueIn = valueIn.replace(colorex, function(capture){ capture = capture.trim(); return '' + (capture.substring(0,1) == '(' ? '(' : '') + ((OPTIONS.shorten_hexcolor_UPPERCASE) ? extended_colors[key].toUpperCase() : extended_colors[key]) + (capture.substring(capture.length-1,capture.length) == ',' ? ',' : '') + (capture.substring(capture.length-1,capture.length) == ')' ? ')' : '') ; }); valueIn = valueIn.trim(); colorPos = valueIn.toLowerCase().indexOf(colorex, colorPos); if (valueInBefore != valueIn) { has_changed = true; summary.stats.summary.noNamedColorsShortened += 1; if (OPTIONS.verbose) { console.log(success('Process - Values - Named Color : ' + (selectorsIn ? selectorsIn.join(', ') : ''))); } } } colorPos = 0; } } for (key in colors) { if (!colors.hasOwnProperty(key)) continue; colorPos = valueIn.toLowerCase().indexOf(key, colorPos); while (colorPos != -1) { colorex = new RegExp(key + "(?![\"\'.a-zA-Z0-9_-])", "g"); //global for multiple colors e.g. gradient valueInBefore = valueIn; valueIn = valueIn.replace(colorex, function(capture){ capture = capture.trim(); return '' + (capture.substring(0,1) == '(' ? '(' : '') + ((OPTIONS.shorten_hexcolor_UPPERCASE) ? colors[key].toUpperCase() : colors[key] ) + (capture.substring(capture.length-1,capture.length) == ',' ? ',' : '') + (capture.substring(capture.length-1,capture.length) == ')' ? ')' : '') ; }); valueIn = valueIn.trim(); colorPos = valueIn.toLowerCase().indexOf(colorex, colorPos); if (valueInBefore != valueIn) { has_changed = true; summary.stats.summary.noNamedColorsShortened += 1; if (OPTIONS.verbose) { console.log(success('Process - Values - Named Color : ' + (selectorsIn ? selectorsIn.join(', ') : ''))); } } } colorPos = 0; } if (!has_changed) { //rgb to hex if (rgbRes=/(rgb)[(]\s*([\d.]+\s*%?)\s*,\s*([\d.]+\s*%?)\s*,\s*([\d.]+\s*%?)\s*(?:,\s*([\d.]+)\s*)?[)]/g.exec(valueIn)) { cr = componentFromStr(rgbRes[2], 255); cg = componentFromStr(rgbRes[3], 255); cb = componentFromStr(rgbRes[4], 255); valueIn = "#" + ((1 << 24) + (cr << 16) + (cg << 8) + cb).toString(16).slice(1); summary.stats.summary.noRGBColorsShortened += 1; if (OPTIONS.shorten_hexcolor_UPPERCASE) { valueIn = valueIn.toUpperCase(); } if (OPTIONS.verbose) { console.log(success('Process - Values - RGB Color : ' + (selectorsIn ? selectorsIn.join(', ') : ''))); } } //hsl to hex if (hslRes=/(hsl)[(]\s*([\d.]+\s*%?)\s*,\s*([\d.]+\s*%?)\s*,\s*([\d.]+\s*%?)\s*(?:,\s*([\d.]+)\s*)?[)]$/.exec(valueIn)) { ch = componentFromStr(hslRes[2], 360); cs = componentFromStr(hslRes[3], 100); cl = componentFromStr(hslRes[4], 100); rgbRes = hslToRgb(ch/360,cs/100,cl/100); cr = rgbRes[0]; cg = rgbRes[1]; cb = rgbRes[2]; valueIn = "#" + ((1 << 24) + (cr << 16) + (cg << 8) + cb).toString(16).slice(1); summary.stats.summary.noHSLColorsShortened += 1; if (OPTIONS.shorten_hexcolor_UPPERCASE) { valueIn = valueIn.toUpperCase(); } if (OPTIONS.verbose) { console.log(success('Process - Values - HSL Color : ' + (selectorsIn ? selectorsIn.join(', ') : ''))); } } //hex if (hexMatch = /#(.)\1\1\1\1\1/.exec(valueIn)) { //#aaaaaa valueIn = valueIn.replace(hexMatch[0], hexMatch[0].substr(0,4)); //#aaa summary.stats.summary.noHexColorsShortened += 1; if (OPTIONS.shorten_hexcolor_UPPERCASE) { valueIn = valueIn.toUpperCase(); } if (OPTIONS.verbose) { console.log(success('Process - Values - Hex Color : ' + (selectorsIn ? selectorsIn.join(', ') : ''))); } } //hex pairs if ( hexMatch = /(#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2}))/.exec(valueIn) ) { if ( hexMatch[2][0] == hexMatch[2][1] && hexMatch[3][0] == hexMatch[3][1] && hexMatch[4][0] == hexMatch[4][1] ) { valueIn = valueIn.replace(hexMatch[0], '#' + hexMatch[2][0] + hexMatch[3][0] + hexMatch[4][0]); //#aaa summary.stats.summary.noHexColorsShortened += 1; if (OPTIONS.shorten_hexcolor_UPPERCASE) { valueIn = valueIn.toUpperCase(); } if (OPTIONS.verbose) { console.log(success('Process - Values - Hex Color : ' + (selectorsIn ? selectorsIn.join(', ') : ''))); } } } } } return valueIn; } function componentFromStr(numStr, max) { cnum = 0; if (/%$/g.test(numStr)) { //is percentage cnum = Math.floor(max * (parseFloat(numStr) / 100.0)); } else { cnum = parseInt(numStr); } return cnum; } /** * Converts an HSL color value to RGB. Conversion formula * adapted from http://en.wikipedia.org/wiki/HSL_color_space. * Assumes h, s, and l are contained in the set [0, 1] and * returns r, g, and b in the set [0, 255]. * * @param {number} h The hue * @param {number} s The saturation * @param {number} l The lightness * @return {Array} The RGB representation */ function hslToRgb(h, s, l){ var r, g, b; if(s == 0){ r = g = b = l; // achromatic }else{ var hue2rgb = function hue2rgb(p, q, t){ if(t < 0) t += 1; if(t > 1) t -= 1; if(t < 1/6.0) return p + (q - p) * 6 * t; if(t < 1/2.0) return q; if(t < 2/3.0) return p + (q - p) * (2/3.0 - t) * 6; return p; } var q = l < 0.5 ? l * (1 + s) : l + s - l * s; var p = 2 * l - q; r = hue2rgb(p, q, h + 1/3.0); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1/3.0); } return [ Math.min(Math.floor(r*256),255), Math.min(Math.floor(g*256),255), Math.min(Math.floor(b*256),255) ]; } // function function getValueOfFontProp(valueIn, prop, position) { if (valueIn !== '') { try { var value = parseCssFont(valueIn)[prop]; value = (value == 'normal') ? '' : value; return value; } catch(err) { if ( err.message.indexOf('Missing required font-size.') != -1 // && prop != 'size' ) { return 'check size'; } else if ( err.message.indexOf('Missing required font-family.') != -1 // && prop != 'family' ) { return 'check family'; } else { console.log(error('Error Parsing Font Declaration')); console.log(error2('Source: ' + position.source)) console.log(error2('Line: ' + position.start.line + ', column: ' + position.start.column)) console.log(err) process.exit(1); } } } return ''; } function getValueOfTriProp(valueIn, prop) { // console.log(valueIn, prop) switch(prop) { case 'type': var value = valueIn.match(/\bnone\b|\bcircle\b|\bdisc\b|\bsquare\b|\barmenian\b|\bcjk-ideographic\b|\bdecimal\b|\bdecimal-leading-zero\b|\bgeorgian\b|\bhebrew\b|\bhiragana\b|\bhiragana-iroha\b|\bkatakana\b|\bkatakana-iroha\b|\blower-alpha\b|\blower-greek\b|\blower-latin\b|\blower-roman\b|\bupper-alpha\b|\bupper-greek\b|\bupper-latin\b|\bupper-roman\b/g); if (value !== null) { return value[0]; } else { return ''; } break; case 'position': var value = valueIn.match(/\binside\b|\boutside\b/g); if (value !== null) { return value[0]; } else { return ''; } break; case 'image': var value = valueIn.match(/(url\()(.*)(\))|\bnone\b/g); if (value !== null) { return value[0]; } else { return ''; } break; case 'style': var value = valueIn.match(/\bnone\b|\bhidden\b|\bdotted\b|\bdashed\b|\bsolid\b|\bdouble\b|\bgroove\b|\bridge\b|\binset\b|\boutset\b/g); if (value !== null) { return value[0]; } else { return ''; } break; case 'color': //check for hex, rgb, hsl var value = valueIn.match(/\btransparent\b|(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d\.]+%?\))/i); if (value !== null) { return value[0]; } //check extended colors for (o in extended_colors) { colorex = new RegExp( "(^|[^\"\'.a-z0-9_-])" + o + "([^\"\'.a-z0-9_-]|$)"); if (valueIn.match(colorex) !== null) { return o; } } //check normal colors for (o in colors) { colorex = new RegExp( "(^|[^\"\'.a-z0-9_-])" + o + "([^\"\'.a-z0-9_-]|$)"); if (valueIn.match(colorex) !== null) { return o; } } return ''; break; case 'width': var value = valueIn.match(/\bmedium\b|\bthin\b|\bthick\b|\b0\b|(([0-9][.]?)+(pt|pc|px|in|cm|mm|q|cap|em|ex|rem|ic|lh|rlh|vh|vw|vi|vb|vmin|vmax))/g); if (value !== null) { return value[0]; } else { return ''; } break; default: return ''; break; } } function getValueOfSquareProp(valueIn, side) { var value = valueIn.split(' '); switch(value.length) { case 1: return value[0]; break; case 2: switch(side) { case 'top': case 'topleft': case 'bottom': case 'bottomright': return value[0]; break; case 'right': case 'topright': case 'left': case 'bottomleft': return value[1]; break; } break; case 3: switch(side) { case 'top': case 'topleft': return value[0]; break; case 'right': case 'topright': case 'left': case 'bottomleft': return value[1]; break; case 'bottom': case 'bottomright': return value[2]; break; } break; case 4: switch(side) { case 'top': case 'topleft': return value[0]; break; case 'right': case 'topright': return value[1]; break; case 'bottom': case 'bottomright': return value[2]; break; case 'left': case 'bottomleft': return value[3]; break; } break; } return ''; } function getBackgroundProp(backgroundStrIn, prop) { // console.log(backgroundStrIn, prop); switch(prop) { case 'image': var value = backgroundStrIn.match(/(url\()(.*)(\))|\bnone\b/g); if (value !== null) { return value[0]; } else { return ''; } break; case 'repeat': var value = backgroundStrIn.match(/\brepeat-x\b|\brepeat-y\b|(\brepeat|\bspace\b|\bround\b|\bno-repeat\b){1,2}/g); if (value !== null) { return value[0]; } else { return ''; } break; case 'attachment': var value = backgroundStrIn.match(/\bscroll\b|\bfixed\b|\blocal\b/g); if (value !== null) { return value[0]; } else { return ''; } break; case 'position': if (backgroundStrIn.indexOf('#') == -1) { var value = backgroundStrIn.match(/(\bleft\b|\bcenter\b|\bright\b|\btop\b|\bbottom\b|\b0\b|((([0-9][.]?)+(pt|pc|px|in|cm|mm|q|cap|em|ex|rem|ic|lh|rlh|vh|vw|vi|vb|vmin|vmax))|(([0-9][.]?)+%)))|((\bleft\b|\bcenter\b|\bright\b|\b0\b|((([0-9][.]?)+(pt|pc|px|in|cm|mm|q|cap|em|ex|rem|ic|lh|rlh|vh|vw|vi|vb|vmin|vmax))|(([0-9][.]?)+%))) (\btop\b|\bcenter\b|\bbottom\b|\b0\b|((([0-9][.]?)+(pt|pc|px|in|cm|mm|q|cap|em|ex|rem|ic|lh|rlh|vh|vw|vi|vb|vmin|vmax))|(([0-9][.]?)+%))))|(\bcenter\b|(\bleft\b|\bright\b \b0\b|((([0-9][.]?)+(pt|pc|px|in|cm|mm|q|cap|em|ex|rem|ic|lh|rlh|vh|vw|vi|vb|vmin|vmax))|(([0-9][.]?)+%))))(\bcenter\b|(\btop\b|\bbottom\b \b0\b|((([0-9][.]?)+(pt|pc|px|in|cm|mm|q|cap|em|ex|rem|ic|lh|rlh|vh|vw|vi|vb|vmin|vmax))|(([0-9][.]?)+%))))/g); } else { var value = null; } var value2 = ''; if (value !== null) { for (o in value) { if (value[o] == '0') { value2 += value[o] + ' '; } } if (value2 != '') { return value2.trim(); } return value[0]; } else { return ''; } break; case 'color': //check for hex, rgb, hsl var value = backgroundStrIn.match(/\btransparent\b|(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d\.]+%?\))/i); if (value !== null) { return value[0]; } //check extended colors for (o in extended_colors) { colorex = new RegExp( "(^|[^\"\'.a-z0-9_-])" + o + "([^\"\'.a-z0-9_-]|$)"); if (backgroundStrIn.match(colorex) !== null) { return o; } } //check normal colors for (o in colors) { colorex = new RegExp( "(^|[^\"\'.a-z0-9_-])" + o + "([^\"\'.a-z0-9_-]|$)"); if (backgroundStrIn.match(colorex) !== null) { return o; } } return ''; break; default: return ''; break; } } function replaceAt(str,index,chr) { if(index > str.length-1) return str; return str.substr(0,index) + chr + str.substr(index+2); } function moveArrayEl(array, from, to) { array.splice(to, 0, array.splice(from, 1)[0]); } function getFilesizeInKiloBytes(filename) { var stats = fs.statSync(filename); var fileSizeInBytes = stats["size"]; return (fileSizeInBytes ? fileSizeInBytes : 0) / 1000; } //UTF8 assumed function kiloByteLength(str) { // returns the byte length of an utf8 string var s = str.length; for (var i=str.length-1; i>=0; i--) { var code = str.charCodeAt(i); if (code > 0x7f && code <= 0x7ff) s++; else if (code > 0x7ff && code <= 0xffff) s+=2; if (code >= 0xDC00 && code <= 0xDFFF) i--; //trail surrogate } return (s ? s : 0) / 1000; } RegExp.escape= function(s) { return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); }; function roundTo(n, digits) { if (digits === undefined) { digits = 0; } var multiplicator = Math.pow(10, digits); n = parseFloat((n * multiplicator).toFixed(11)); var test =(Math.round(n) / multiplicator); return +(test.toFixed(digits)); } function trimCSS(outputCSSIn) { //imports - move imports to top of page var imports = ''; outputCSSIn = outputCSSIn.replace(/@import.*(([\n\r\t]*)(\s*)\/\*(_cssp_sc).\*\/)?([\n\r\t])+/gm, function (match, capture) { imports += match.substr(0, match.length-1) + ""; return ''; }); outputCSSIn = imports + outputCSSIn; //charset - move charset to top of page charset = ''; outputCSSIn = outputCSSIn.replace(/@charset.*(([\n\r\t]*)(\s*)\/\*(_cssp_sc).\*\/)?([\n\r\t])+/gm, function (match, capture) { charset += match + ""; return ''; }); outputCSSIn = charset + outputCSSIn; if (OPTIONS.trim_breaklines || OPTIONS.trim) { outputCSSIn = outputCSSIn.replace(/\r?\n|\r/g,''); } if (OPTIONS.trim_whitespace || OPTIONS.trim) { if (OPTIONS.trim_comments || OPTIONS.trim) { // remove any left over comments and tabs outputCSSIn = outputCSSIn.replace( /\/\*(?:(?!\*\/)[\s\S])*\*\/|[\t]+/g, '' ); } // remove single adjacent spaces outputCSSIn = outputCSSIn.replace( / {2,}/g, ' ' ); outputCSSIn = outputCSSIn.replace( / ([{:}]) /g, '$1' ); outputCSSIn = outputCSSIn.replace( /([{:}]) /g, '$1' ); outputCSSIn = outputCSSIn.replace( /([;,]) /g, '$1' ); outputCSSIn = outputCSSIn.replace( /\(\s*/g, '(' ); outputCSSIn = outputCSSIn.replace( /\s*\)/g, ')' ); outputCSSIn = outputCSSIn.replace( / !/g, '!' ); } if (OPTIONS.trim_last_semicolon || OPTIONS.trim) { outputCSSIn = outputCSSIn.replace(/{([^}]*)}/gm, function (match, capture) { summary.stats.summary.noLastSemiColonsTrimmed += 1; // console.log(capture) // return "{" + capture + "}"; return "{" + capture.replace(/\;(?=[^;]*$)/, '') + "}"; }); } return outputCSSIn; } function restoreHacks(outputCSSIn) { //tokens ////hacks ///**/ outputCSSIn = outputCSSIn.replace(/(_1token_hck)/g, '/**/'); ///*\**/ outputCSSIn = outputCSSIn.replace(/(_2token_hck)/g, '/*\\**/'); //(specialchar)property outputCSSIn = outputCSSIn.replace(/(_3token_hck_([0-9]*): ;)/g, function(match){ tmpVal = token3_chars[match.substring(12, match.length-3)-1]; return tmpVal.substring(0, tmpVal.length) + ';'; }); //(; outputCSSIn = outputCSSIn.replace(/(_4token_hck_)[0-9]*[:][\s]*[;]/g, function(match){ tmpVal = token4_vals[match.substring(12,match.length-3)-1]; return tmpVal.substring(0, tmpVal.length-2); }); //[; outputCSSIn = outputCSSIn.replace(/(_5token_hck_)[0-9]*[:][\s]*[;]/g, function(match){ tmpVal = token5_vals[match.substring(12,match.length-3)-1]; return tmpVal.substring(0, tmpVal.length-2); }); ////end of hacks //tokens - data:image outputCSSIn = outputCSSIn.replace(/(_6token_dataimage_)[0-9]*[:][\s]*/g, function(match){ tmpVal = token6_vals[match.substring(18,match.length-1)-1]; return tmpVal.substring(0, tmpVal.length) + ';'; }); //tokens - allow multi-keyframe selectors outputCSSIn = outputCSSIn.replace(/(@keyframes _7token_)[0-9]*[\s]*/g, function(match){ tmpVal = token7_vals[match.substring(19,match.length)-1]; tmpVal = trimCSS(tmpVal); return tmpVal.substring(0, tmpVal.length) + ''; }); //tokens - replace side comments for (key in tokens_comments) { tokenex = new RegExp("([\\n\\r\\t]*)(\\s*)\\/\\*(" + key + ")\\*\\/", "gm"); outputCSSIn = outputCSSIn.replace(tokenex, tokens_comments[key]); } //tokens - end of replace side comments return outputCSSIn; } function processHTMLSelectors(cssSelectors, htmlDataIn = null, htmlOptionsIn = null) { if (OPTIONS.verbose) { console.log(info('Process - HTML - Determine Rules to Remove')); } var htmlData = dataHTMLIn.join(""); if (htmlDataIn !== null && htmlDataIn !== undefined) { htmlData = htmlDataIn; } if (htmlOptionsIn !== null && htmlOptionsIn !== undefined) { for (key in htmlOptionsIn) { OPTIONS.html[key] = htmlOptionsIn[key]; } } //find values in ids results = []; results1 = htmlData.match(/\bid\b[=](["'])(?:(?=(\\?))\2.)*?\1/gm); if (results1 !== null) { for (i = 0, ilen = results1.length; i < ilen; ++i) { if (results1[i] !== null) { results1[i] = results1[i].split('=')[1].replace(/['"]+/g, ''); } } results1 = Array.from(new Set(results1)); results = results.concat(results1); } //find values in classes results2 = htmlData.match(/\bclass\b[=](["'])(?:(?=(\\?))\2.)*?\1/gm); if (results2 !== null) { for (i = 0, ilen = results2.length; i < ilen; ++i) { if (results2[i] !== null) { results2[i] = results2[i].split('=')[1].replace(/['"]+/g, ''); } } results2 = Array.from(new Set(results2)); results = results.concat(results2); } //find values in internal selectors results3 = htmlData.match(/<style([\S\s]*?)>([\S\s]*?)<\/style>/gi); if (results3 !== null) { results4 = []; for (i = 0, ilen = results3.length; i < ilen; ++i) { if (results3[i] !== null) { results3[i] = results3[i].split('</')[0].split('>')[1]; results4 = results4.concat(results3[i].match(/([#}.])([^0-9])([\S\s]*?){/g)); } } results3 = []; for (i = 0, ilen = results4.length; i < ilen; ++i) { if (results4[i] !== null) { results4[i] = results4[i].replace(/\r?\n|\r|\s/g, ''); results4[i] = results4[i].replace('{', ''); results4[i] = results4[i].replace('}', ''); results3 = results3.concat(results4[i].split(',')); } } results3 = Array.from(new Set(results3)); results = results.concat(results3); } //find values in the dom jsDom = new JSDOM(htmlData, {contentType: "text/html"}); jsDomWindow = jsDom.window; jsDomDoc = jsDomWindow.document; for (i = 0, resultsCount = cssSelectors.length; i < resultsCount; ++i) { for (j = 0, jlen = results.length; j < jlen; ++j) { if (cssSelectors[i] == results[j]) { cssSelectors.splice(i, 1); resultsCount -= 1; i -= 1; break; } } if (jsDomDoc.querySelector(cssSelectors[i]) != null) { cssSelectors.splice(i, 1); resultsCount -= 1; i -= 1; } } return cssSelectors; } //end of processHTMLSelectors function processHTML(cssSelectors = [], htmlDataIn = null, htmlOptionsIn = null) { //read html files if (OPTIONS.html !== '' && OPTIONS.html !== undefined && OPTIONS.special_reduce_with_html) { var htmlFiles = OPTIONS.html; tmpHTMLPaths = []; //check for file or files switch (typeof htmlFiles) { case 'object': case 'array': for (i = 0; i < htmlFiles.length; ++i) { getFilePaths(htmlFiles[i], ['.html','.htm']); } if (tmpHTMLPaths.length) { htmlFiles = tmpHTMLPaths; } break; case 'string': //formats htmlFiles = htmlFiles.replace(/ /g, ''); // comma delimited list - filename1.html, filename2.html if (htmlFiles.indexOf(',') > -1) { htmlFiles = htmlFiles.replace(/^\s+|\s+$/g,'').split(','); tmpStr = ''; for (i = 0; i < htmlFiles.length; ++i) { getFilePaths(htmlFiles[i], ['.html','.htm']); } //end of for if (tmpHTMLPaths.length) { htmlFiles = tmpHTMLPaths; } } else { //string path getFilePaths(htmlFiles, ['.html','.htm']); if (tmpHTMLPaths.length) { htmlFiles = tmpHTMLPaths; } } break; } //end of switch htmlFileLocation = (htmlFiles)?htmlFiles.toString():htmlFiles; readHTMLFile(htmlFiles); CPEVENTS.on('HTML_READ_AGAIN', function(){ //process selectors processHTMLSelectors(cssSelectors, htmlDataIn, htmlOptionsIn); //read next file dataHTMLIn = []; readHTMLFile(htmlFiles); }); CPEVENTS.on('HTML_READ_END', function(){ //process selectors processHTMLSelectors(cssSelectors, htmlDataIn, htmlOptionsIn); dataHTMLIn = []; CPEVENTS.emit('HTML_RESULTS_END', cssSelectors); }); } //end of html files check } function readHTMLFile(files = []) { if (OPTIONS.verbose) { console.log(info('Input - HTML File : ' + files[readHTMLFileCount])); } if (validUrl.isUri(files[readHTMLFileCount])) { request({ url: files[readHTMLFileCount], method: "GET" }, function(err, headRes, body) { if (headRes !== undefined) { var size = headRes.headers['content-length']; if (size == undefined || size == 0) { filesizeKBHTML = kiloByteLength(body); } else { filesizeKBHTML = size/1000; } } else { var size = kiloByteLength(body); filesizeKBHTML = size/1000; } stats.files.html.push({ "filename" : files[readHTMLFileCount], "filesizeKB" : filesizeKBHTML }); }); } else { filesizeKBHTML = getFilesizeInKiloBytes(files[readHTMLFileCount]); stats.files.html.push({ "filename" : files[readHTMLFileCount], "filesizeKB" : filesizeKBHTML }); } summary.files.input_html.push(files[readHTMLFileCount]); if (validUrl.isUri(files[readHTMLFileCount])) { request(files[readHTMLFileCount], function (err, response, body) { if (response === undefined) { //try again request(files[readHTMLFileCount], function (err, response, body) { if (response.statusCode == 200) { dataHTMLIn.push(body); readHTMLFileCount += 1; if (readHTMLFileCount < files.length) { CPEVENTS.emit('HTML_READ_AGAIN'); } else { CPEVENTS.emit('HTML_READ_END'); } } else { CPEVENTS.emit('HTML_READ_ERROR'); console.log(error("HTML File read error: check your HTML files and please try again.")); console.log(err) process.exit(1); } }); } else if (response.statusCode == 200) { dataHTMLIn.push(body); readHTMLFileCount += 1; if (readHTMLFileCount < files.length) { CPEVENTS.emit('HTML_READ_AGAIN'); } else { CPEVENTS.emit('HTML_READ_END'); } } else { CPEVENTS.emit('HTML_READ_ERROR'); console.log(error("HTML File read error: check your HTML files and please try again.")); console.log(err) process.exit(1); } }); } else { readHTMLStream = fs.createReadStream(files[readHTMLFileCount], 'utf8'); readHTMLStream.on('data', function(chunk) { dataHTMLIn.push(chunk); }).on('end', function() { readHTMLFileCount += 1; if (readHTMLFileCount < files.length) { CPEVENTS.emit('HTML_READ_AGAIN'); } else { CPEVENTS.emit('HTML_READ_END'); } }).on('error', function(e) { CPEVENTS.emit('HTML_READ_ERROR'); console.log(error("HTML File read error: Something went wrong while reading the file(s), check your HTML files and please try again.")); console.log(e); process.exit(1); }); } } //end of readHTMLFile function readReduceDeclarations(jsonConfigIn = '') { if (jsonConfigIn) { jsonConfig = jsonConfigIn; reduceRulesListName = jsonConfig.declaration_names; reduceRulesListSelector = jsonConfig.selectors; switch (typeof reduceRulesListSelector) { case 'string': if (reduceRulesListSelector.length) { reduceRulesListSelector = reduceRulesListSelector.replace(/^\s+|\s+$/g,''); reduceRulesListSelector = reduceRulesListSelector.replace(/\r?\n|\r/g,''); reduceRulesListSelector = reduceRulesListSelector.split(','); reduceRulesListSelectorCount = reduceRulesListSelector.length; } else { reduceRulesListSelector = null; } break; case 'object': // reduceRulesListSelectorPName var tmp = []; for (var i in reduceRulesListSelector) { tmp.push(i); reduceRulesListSelectorPName[i] = reduceRulesListSelector[i].replace(/^\s+|\s+$/g,'').replace(/\r?\n|\r/g,'').split(','); } reduceRulesListSelector = tmp; reduceRulesListSelectorCount = reduceRulesListSelector.length; break; } //by name if (reduceRulesListName.length) { if (typeof reduceRulesListName == 'string') { reduceRulesListName = reduceRulesListName.replace(/^\s+|\s+$/g,''); reduceRulesListName = reduceRulesListName.split(','); reduceRulesListNameCount = reduceRulesListName.length; } else if (typeof reduceRulesListName == 'object' || typeof reduceRulesListName == 'array') { reduceRulesListName = reduceRulesListName.filter(function(entry) { return entry.trim() !== ''; }); reduceRulesListNameCount = reduceRulesListName.length; } } else { reduceRulesListName = null; } hasReadReduceDeclarations = true; CPEVENTS.emit('CONFIG_READ_REDUCE_PROPS_END', OPTIONS); } else { var jsonConfig = ''; readStream = fs.createReadStream(CONFIG_REDUCE_DECLARATIONS, 'utf8'); readStream.on('data', function(chunk) { jsonConfig += chunk; }).on('end', function() { jsonConfig = JSON.parse(jsonConfig); reduceRulesListName = jsonConfig.declaration_names; reduceRulesListSelector = jsonConfig.selectors; switch (typeof reduceRulesListSelector) { case 'string': if (reduceRulesListSelector.length) { reduceRulesListSelector = reduceRulesListSelector.replace(/^\s+|\s+$/g,''); reduceRulesListSelector = reduceRulesListSelector.replace(/\r?\n|\r/g,''); reduceRulesListSelector = reduceRulesListSelector.split(','); reduceRulesListSelectorCount = reduceRulesListSelector.length; } else { reduceRulesListSelector = null; } break; case 'object': // reduceRulesListSelectorPName var tmp = []; for (var i in reduceRulesListSelector) { tmp.push(i); reduceRulesListSelectorPName[i] = reduceRulesListSelector[i].replace(/^\s+|\s+$/g,'').replace(/\r?\n|\r/g,'').split(','); } reduceRulesListSelector = tmp; reduceRulesListSelectorCount = reduceRulesListSelector.length; break; } //by name if (reduceRulesListName.length) { if (typeof reduceRulesListName == 'string') { reduceRulesListName = reduceRulesListName.replace(/^\s+|\s+$/g,''); reduceRulesListName = reduceRulesListName.split(','); reduceRulesListNameCount = reduceRules