You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
var Spaces = require('../../options/format').Spaces; var Marker = require('../../tokenizer/marker'); var formatPosition = require('../../utils/format-position');
var CASE_ATTRIBUTE_PATTERN = /[\s"'][iI]\s*\]/; var CASE_RESTORE_PATTERN = /([\d\w])([iI])\]/g; var DOUBLE_QUOTE_CASE_PATTERN = /="([a-zA-Z][a-zA-Z\d\-_]+)"([iI])/g; var DOUBLE_QUOTE_PATTERN = /="([a-zA-Z][a-zA-Z\d\-_]+)"(\s|\])/g; var HTML_COMMENT_PATTERN = /^(?:(?:<!--|-->)\s*)+/; var SINGLE_QUOTE_CASE_PATTERN = /='([a-zA-Z][a-zA-Z\d\-_]+)'([iI])/g; var SINGLE_QUOTE_PATTERN = /='([a-zA-Z][a-zA-Z\d\-_]+)'(\s|\])/g; var RELATION_PATTERN = /[>\+~]/; var WHITESPACE_PATTERN = /\s/;
var ASTERISK_PLUS_HTML_HACK = '*+html '; var ASTERISK_FIRST_CHILD_PLUS_HTML_HACK = '*:first-child+html '; var LESS_THAN = '<';
function hasInvalidCharacters(value) { var isEscaped; var isInvalid = false; var character; var isQuote = false; var i, l;
for (i = 0, l = value.length; i < l; i++) { character = value[i];
if (isEscaped) { // continue as always
} else if (character == Marker.SINGLE_QUOTE || character == Marker.DOUBLE_QUOTE) { isQuote = !isQuote; } else if (!isQuote && (character == Marker.CLOSE_CURLY_BRACKET || character == Marker.EXCLAMATION || character == LESS_THAN || character == Marker.SEMICOLON)) { isInvalid = true; break; } else if (!isQuote && i === 0 && RELATION_PATTERN.test(character)) { isInvalid = true; break; }
isEscaped = character == Marker.BACK_SLASH; }
return isInvalid; }
function removeWhitespace(value, format) { var stripped = []; var character; var isNewLineNix; var isNewLineWin; var isEscaped; var wasEscaped; var isQuoted; var isSingleQuoted; var isDoubleQuoted; var isAttribute; var isRelation; var isWhitespace; var roundBracketLevel = 0; var wasRelation = false; var wasWhitespace = false; var withCaseAttribute = CASE_ATTRIBUTE_PATTERN.test(value); var spaceAroundRelation = format && format.spaces[Spaces.AroundSelectorRelation]; var i, l;
for (i = 0, l = value.length; i < l; i++) { character = value[i];
isNewLineNix = character == Marker.NEW_LINE_NIX; isNewLineWin = character == Marker.NEW_LINE_NIX && value[i - 1] == Marker.CARRIAGE_RETURN; isQuoted = isSingleQuoted || isDoubleQuoted; isRelation = !isAttribute && !isEscaped && roundBracketLevel === 0 && RELATION_PATTERN.test(character); isWhitespace = WHITESPACE_PATTERN.test(character);
if (wasEscaped && isQuoted && isNewLineWin) { // swallow escaped new windows lines in comments
stripped.pop(); stripped.pop(); } else if (isEscaped && isQuoted && isNewLineNix) { // swallow escaped new *nix lines in comments
stripped.pop(); } else if (isEscaped) { stripped.push(character); } else if (character == Marker.OPEN_SQUARE_BRACKET && !isQuoted) { stripped.push(character); isAttribute = true; } else if (character == Marker.CLOSE_SQUARE_BRACKET && !isQuoted) { stripped.push(character); isAttribute = false; } else if (character == Marker.OPEN_ROUND_BRACKET && !isQuoted) { stripped.push(character); roundBracketLevel++; } else if (character == Marker.CLOSE_ROUND_BRACKET && !isQuoted) { stripped.push(character); roundBracketLevel--; } else if (character == Marker.SINGLE_QUOTE && !isQuoted) { stripped.push(character); isSingleQuoted = true; } else if (character == Marker.DOUBLE_QUOTE && !isQuoted) { stripped.push(character); isDoubleQuoted = true; } else if (character == Marker.SINGLE_QUOTE && isQuoted) { stripped.push(character); isSingleQuoted = false; } else if (character == Marker.DOUBLE_QUOTE && isQuoted) { stripped.push(character); isDoubleQuoted = false; } else if (isWhitespace && wasRelation && !spaceAroundRelation) { continue; } else if (!isWhitespace && wasRelation && spaceAroundRelation) { stripped.push(Marker.SPACE); stripped.push(character); } else if (isWhitespace && (isAttribute || roundBracketLevel > 0) && !isQuoted) { // skip space
} else if (isWhitespace && wasWhitespace && !isQuoted) { // skip extra space
} else if ((isNewLineWin || isNewLineNix) && (isAttribute || roundBracketLevel > 0) && isQuoted) { // skip newline
} else if (isRelation && wasWhitespace && !spaceAroundRelation) { stripped.pop(); stripped.push(character); } else if (isRelation && !wasWhitespace && spaceAroundRelation) { stripped.push(Marker.SPACE); stripped.push(character); } else if (isWhitespace) { stripped.push(Marker.SPACE); } else { stripped.push(character); }
wasEscaped = isEscaped; isEscaped = character == Marker.BACK_SLASH; wasRelation = isRelation; wasWhitespace = isWhitespace; }
return withCaseAttribute ? stripped.join('').replace(CASE_RESTORE_PATTERN, '$1 $2]') : stripped.join(''); }
function removeQuotes(value) { if (value.indexOf('\'') == -1 && value.indexOf('"') == -1) { return value; }
return value .replace(SINGLE_QUOTE_CASE_PATTERN, '=$1 $2') .replace(SINGLE_QUOTE_PATTERN, '=$1$2') .replace(DOUBLE_QUOTE_CASE_PATTERN, '=$1 $2') .replace(DOUBLE_QUOTE_PATTERN, '=$1$2'); }
function tidyRules(rules, removeUnsupported, adjacentSpace, format, warnings) { var list = []; var repeated = [];
function removeHTMLComment(rule, match) { warnings.push('HTML comment \'' + match + '\' at ' + formatPosition(rule[2][0]) + '. Removing.'); return ''; }
for (var i = 0, l = rules.length; i < l; i++) { var rule = rules[i]; var reduced = rule[1];
reduced = reduced.replace(HTML_COMMENT_PATTERN, removeHTMLComment.bind(null, rule));
if (hasInvalidCharacters(reduced)) { warnings.push('Invalid selector \'' + rule[1] + '\' at ' + formatPosition(rule[2][0]) + '. Ignoring.'); continue; }
reduced = removeWhitespace(reduced, format); reduced = removeQuotes(reduced);
if (adjacentSpace && reduced.indexOf('nav') > 0) { reduced = reduced.replace(/\+nav(\S|$)/, '+ nav$1'); }
if (removeUnsupported && reduced.indexOf(ASTERISK_PLUS_HTML_HACK) > -1) { continue; }
if (removeUnsupported && reduced.indexOf(ASTERISK_FIRST_CHILD_PLUS_HTML_HACK) > -1) { continue; }
if (reduced.indexOf('*') > -1) { reduced = reduced .replace(/\*([:#\.\[])/g, '$1') .replace(/^(\:first\-child)?\+html/, '*$1+html'); }
if (repeated.indexOf(reduced) > -1) { continue; }
rule[1] = reduced; repeated.push(reduced); list.push(rule); }
if (list.length == 1 && list[0][1].length === 0) { warnings.push('Empty selector \'' + list[0][1] + '\' at ' + formatPosition(list[0][2][0]) + '. Ignoring.'); list = []; }
return list; }
module.exports = tidyRules;
|