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
JavaScript
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