code:
"use strict";

exports.__esModule = true;
exports["default"] = void 0;
var _node = _interopRequireDefault(require("./node"));
var _types = require("./types");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
var String = /*#__PURE__*/function (_Node) {
  _inheritsLoose(String, _Node);
  function String(opts) {
    var _this;
    _this = _Node.call(this, opts) || this;
    _this.type = _types.STRING;
    return _this;
  }
  return String;
}(_node["default"]);
exports["default"] = String;
module.exports = exports.default;


code:
"use strict";

exports.__esModule = true;
exports["default"] = void 0;
var _namespace = _interopRequireDefault(require("./namespace"));
var _types = require("./types");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
var Tag = /*#__PURE__*/function (_Namespace) {
  _inheritsLoose(Tag, _Namespace);
  function Tag(opts) {
    var _this;
    _this = _Namespace.call(this, opts) || this;
    _this.type = _types.TAG;
    return _this;
  }
  return Tag;
}(_namespace["default"]);
exports["default"] = Tag;
module.exports = exports.default;

license: mit


code:
"use strict";

exports.__esModule = true;
exports.UNIVERSAL = exports.TAG = exports.STRING = exports.SELECTOR = exports.ROOT = exports.PSEUDO = exports.NESTING = exports.ID = exports.COMMENT = exports.COMBINATOR = exports.CLASS = exports.ATTRIBUTE = void 0;
var TAG = 'tag';
exports.TAG = TAG;
var STRING = 'string';
exports.STRING = STRING;
var SELECTOR = 'selector';
exports.SELECTOR = SELECTOR;
var ROOT = 'root';
exports.ROOT = ROOT;
var PSEUDO = 'pseudo';
exports.PSEUDO = PSEUDO;
var NESTING = 'nesting';
exports.NESTING = NESTING;
var ID = 'id';
exports.ID = ID;
var COMMENT = 'comment';
exports.COMMENT = COMMENT;
var COMBINATOR = 'combinator';
exports.COMBINATOR = COMBINATOR;
var CLASS = 'class';
exports.CLASS = CLASS;
var ATTRIBUTE = 'attribute';
exports.ATTRIBUTE = ATTRIBUTE;
var UNIVERSAL = 'universal';
exports.UNIVERSAL = UNIVERSAL;


code:
"use strict";

exports.__esModule = true;
exports["default"] = void 0;
var _namespace = _interopRequireDefault(require("./namespace"));
var _types = require("./types");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
var Universal = /*#__PURE__*/function (_Namespace) {
  _inheritsLoose(Universal, _Namespace);
  function Universal(opts) {
    var _this;
    _this = _Namespace.call(this, opts) || this;
    _this.type = _types.UNIVERSAL;
    _this.value = '*';
    return _this;
  }
  return Universal;
}(_namespace["default"]);
exports["default"] = Universal;
module.exports = exports.default;


code:
"use strict";

exports.__esModule = true;
exports["default"] = sortAscending;
function sortAscending(list) {
  return list.sort(function (a, b) {
    return a - b;
  });
}
;
module.exports = exports.default;


code:
"use strict";

exports.__esModule = true;
exports.word = exports.tilde = exports.tab = exports.str = exports.space = exports.slash = exports.singleQuote = exports.semicolon = exports.plus = exports.pipe = exports.openSquare = exports.openParenthesis = exports.newline = exports.greaterThan = exports.feed = exports.equals = exports.doubleQuote = exports.dollar = exports.cr = exports.comment = exports.comma = exports.combinator = exports.colon = exports.closeSquare = exports.closeParenthesis = exports.caret = exports.bang = exports.backslash = exports.at = exports.asterisk = exports.ampersand = void 0;
var ampersand = 38; // `&`.charCodeAt(0);
exports.ampersand = ampersand;
var asterisk = 42; // `*`.charCodeAt(0);
exports.asterisk = asterisk;
var at = 64; // `@`.charCodeAt(0);
exports.at = at;
var comma = 44; // `,`.charCodeAt(0);
exports.comma = comma;
var colon = 58; // `:`.charCodeAt(0);
exports.colon = colon;
var semicolon = 59; // `;`.charCodeAt(0);
exports.semicolon = semicolon;
var openParenthesis = 40; // `(`.charCodeAt(0);
exports.openParenthesis = openParenthesis;
var closeParenthesis = 41; // `)`.charCodeAt(0);
exports.closeParenthesis = closeParenthesis;
var openSquare = 91; // `[`.charCodeAt(0);
exports.openSquare = openSquare;
var closeSquare = 93; // `]`.charCodeAt(0);
exports.closeSquare = closeSquare;
var dollar = 36; // `$`.charCodeAt(0);
exports.dollar = dollar;
var tilde = 126; // `~`.charCodeAt(0);
exports.tilde = tilde;
var caret = 94; // `^`.charCodeAt(0);
exports.caret = caret;
var plus = 43; // `+`.charCodeAt(0);
exports.plus = plus;
var equals = 61; // `=`.charCodeAt(0);
exports.equals = equals;
var pipe = 124; // `|`.charCodeAt(0);
exports.pipe = pipe;
var greaterThan = 62; // `>`.charCodeAt(0);
exports.greaterThan = greaterThan;
var space = 32; // ` `.charCodeAt(0);
exports.space = space;
var singleQuote = 39; // `'`.charCodeAt(0);
exports.singleQuote = singleQuote;
var doubleQuote = 34; // `"`.charCodeAt(0);
exports.doubleQuote = doubleQuote;
var slash = 47; // `/`.charCodeAt(0);
exports.slash = slash;
var bang = 33; // `!`.charCodeAt(0);
exports.bang = bang;
var backslash = 92; // '\\'.charCodeAt(0);
exports.backslash = backslash;
var cr = 13; // '\r'.charCodeAt(0);
exports.cr = cr;
var feed = 12; // '\f'.charCodeAt(0);
exports.feed = feed;
var newline = 10; // '\n'.charCodeAt(0);
exports.newline = newline;
var tab = 9; // '\t'.charCodeAt(0);

// Expose aliases primarily for readability.
exports.tab = tab;
var str = singleQuote;

// No good single character representation!
exports.str = str;
var comment = -1;
exports.comment = comment;
var word = -2;
exports.word = word;
var combinator = -3;
exports.combinator = combinator;


code:
"use strict";

exports.__esModule = true;
exports.FIELDS = void 0;
exports["default"] = tokenize;
var t = _interopRequireWildcard(require("./tokenTypes"));
var _unescapable, _wordDelimiters;
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
var unescapable = (_unescapable = {}, _unescapable[t.tab] = true, _unescapable[t.newline] = true, _unescapable[t.cr] = true, _unescapable[t.feed] = true, _unescapable);
var wordDelimiters = (_wordDelimiters = {}, _wordDelimiters[t.space] = true, _wordDelimiters[t.tab] = true, _wordDelimiters[t.newline] = true, _wordDelimiters[t.cr] = true, _wordDelimiters[t.feed] = true, _wordDelimiters[t.ampersand] = true, _wordDelimiters[t.asterisk] = true, _wordDelimiters[t.bang] = true, _wordDelimiters[t.comma] = true, _wordDelimiters[t.colon] = true, _wordDelimiters[t.semicolon] = true, _wordDelimiters[t.openParenthesis] = true, _wordDelimiters[t.closeParenthesis] = true, _wordDelimiters[t.openSquare] = true, _wordDelimiters[t.closeSquare] = true, _wordDelimiters[t.singleQuote] = true, _wordDelimiters[t.doubleQuote] = true, _wordDelimiters[t.plus] = true, _wordDelimiters[t.pipe] = true, _wordDelimiters[t.tilde] = true, _wordDelimiters[t.greaterThan] = true, _wordDelimiters[t.equals] = true, _wordDelimiters[t.dollar] = true, _wordDelimiters[t.caret] = true, _wordDelimiters[t.slash] = true, _wordDelimiters);
var hex = {};
var hexChars = "0123456789abcdefABCDEF";
for (var i = 0; i < hexChars.length; i++) {
  hex[hexChars.charCodeAt(i)] = true;
}

/**
 *  Returns the last index of the bar css word
 * @param {string} css The string in which the word begins
 * @param {number} start The index into the string where word's first letter occurs
 */
function consumeWord(css, start) {
  var next = start;
  var code;
  do {
    code = css.charCodeAt(next);
    if (wordDelimiters[code]) {
      return next - 1;
    } else if (code === t.backslash) {
      next = consumeEscape(css, next) + 1;
    } else {
      // All other characters are part of the word
      next++;
    }
  } while (next < css.length);
  return next - 1;
}

/**
 *  Returns the last index of the escape sequence
 * @param {string} css The string in which the sequence begins
 * @param {number} start The index into the string where escape character (`\`) occurs.
 */
function consumeEscape(css, start) {
  var next = start;
  var code = css.charCodeAt(next + 1);
  if (unescapable[code]) {
    // just consume the escape char
  } else if (hex[code]) {
    var hexDigits = 0;
    // consume up to 6 hex chars
    do {
      next++;
      hexDigits++;
      code = css.charCodeAt(next + 1);
    } while (hex[code] && hexDigits < 6);
    // if fewer than 6 hex chars, a trailing space ends the escape
    if (hexDigits < 6 && code === t.space) {
      next++;
    }
  } else {
    // the next char is part of the current word
    next++;
  }
  return next;
}
var FIELDS = {
  TYPE: 0,
  START_LINE: 1,
  START_COL: 2,
  END_LINE: 3,
  END_COL: 4,
  START_POS: 5,
  END_POS: 6
};
exports.FIELDS = FIELDS;
function tokenize(input) {
  var tokens = [];
  var css = input.css.valueOf();
  var _css = css,
    length = _css.length;
  var offset = -1;
  var line = 1;
  var start = 0;
  var end = 0;
  var code, content, endColumn, endLine, escaped, escapePos, last, lines, next, nextLine, nextOffset, quote, tokenType;
  function unclosed(what, fix) {
    if (input.safe) {
      // fyi: this is never set to true.
      css += fix;
      next = css.length - 1;
    } else {
      throw input.error('Unclosed ' + what, line, start - offset, start);
    }
  }
  while (start < length) {
    code = css.charCodeAt(start);
    if (code === t.newline) {
      offset = start;
      line += 1;
    }
    switch (code) {
      case t.space:
      case t.tab:
      case t.newline:
      case t.cr:
      case t.feed:
        next = start;
        do {
          next += 1;
          code = css.charCodeAt(next);
          if (code === t.newline) {
            offset = next;
            line += 1;
          }
        } while (code === t.space || code === t.newline || code === t.tab || code === t.cr || code === t.feed);
        tokenType = t.space;
        endLine = line;
        endColumn = next - offset - 1;
        end = next;
        break;
      case t.plus:
      case t.greaterThan:
      case t.tilde:
      case t.pipe:
        next = start;
        do {
          next += 1;
          code = css.charCodeAt(next);
        } while (code === t.plus || code === t.greaterThan || code === t.tilde || code === t.pipe);
        tokenType = t.combinator;
        endLine = line;
        endColumn = start - offset;
        end = next;
        break;

      // Consume these characters as single tokens.
      case t.asterisk:
      case t.ampersand:
      case t.bang:
      case t.comma:
      case t.equals:
      case t.dollar:
      case t.caret:
      case t.openSquare:
      case t.closeSquare:
      case t.colon:
      case t.semicolon:
      case t.openParenthesis:
      case t.closeParenthesis:
        next = start;
        tokenType = code;
        endLine = line;
        endColumn = start - offset;
        end = next + 1;
        break;
      case t.singleQuote:
      case t.doubleQuote:
        quote = code === t.singleQuote ? "'" : '"';
        next = start;
        do {
          escaped = false;
          next = css.indexOf(quote, next + 1);
          if (next === -1) {
            unclosed('quote', quote);
          }
          escapePos = next;
          while (css.charCodeAt(escapePos - 1) === t.backslash) {
            escapePos -= 1;
            escaped = !escaped;
          }
        } while (escaped);
        tokenType = t.str;
        endLine = line;
        endColumn = start - offset;
        end = next + 1;
        break;
      default:
        if (code === t.slash && css.charCodeAt(start + 1) === t.asterisk) {
          next = css.indexOf('*/', start + 2) + 1;
          if (next === 0) {
            unclosed('comment', '*/');
          }
          content = css.slice(start, next + 1);
          lines = content.split('\n');
          last = lines.length - 1;
          if (last > 0) {
            nextLine = line + last;
            nextOffset = next - lines[last].length;
          } else {
            nextLine = line;
            nextOffset = offset;
          }
          tokenType = t.comment;
          line = nextLine;
          endLine = nextLine;
          endColumn = next - nextOffset;
        } else if (code === t.slash) {
          next = start;
          tokenType = code;
          endLine = line;
          endColumn = start - offset;
          end = next + 1;
        } else {
          next = consumeWord(css, start);
          tokenType = t.word;
          endLine = line;
          endColumn = next - offset;
        }
        end = next + 1;
        break;
    }

    // Ensure that the token structure remains consistent
    tokens.push([tokenType,
    // [0] Token type
    line,
    // [1] Starting line
    start - offset,
    // [2] Starting column
    endLine,
    // [3] Ending line
    endColumn,
    // [4] Ending column
    start,
    // [5] Start position / Source index
    end // [6] End position
    ]);

    // Reset offset for the next token
    if (nextOffset) {
      offset = nextOffset;
      nextOffset = null;
    }
    start = end;
  }
  return tokens;
}


code:
"use strict";

exports.__esModule = true;
exports["default"] = ensureObject;
function ensureObject(obj) {
  for (var _len = arguments.length, props = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
    props[_key - 1] = arguments[_key];
  }
  while (props.length > 0) {
    var prop = props.shift();
    if (!obj[prop]) {
      obj[prop] = {};
    }
    obj = obj[prop];
  }
}
module.exports = exports.default;


code:
"use strict";

exports.__esModule = true;
exports["default"] = getProp;
function getProp(obj) {
  for (var _len = arguments.length, props = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
    props[_key - 1] = arguments[_key];
  }
  while (props.length > 0) {
    var prop = props.shift();
    if (!obj[prop]) {
      return undefined;
    }
    obj = obj[prop];
  }
  return obj;
}
module.exports = exports.default;


code:
"use strict";

exports.__esModule = true;
exports.unesc = exports.stripComments = exports.getProp = exports.ensureObject = void 0;
var _unesc = _interopRequireDefault(require("./unesc"));
exports.unesc = _unesc["default"];
var _getProp = _interopRequireDefault(require("./getProp"));
exports.getProp = _getProp["default"];
var _ensureObject = _interopRequireDefault(require("./ensureObject"));
exports.ensureObject = _ensureObject["default"];
var _stripComments = _interopRequireDefault(require("./stripComments"));
exports.stripComments = _stripComments["default"];
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }


code:
"use strict";

exports.__esModule = true;
exports["default"] = stripComments;
function stripComments(str) {
  var s = "";
  var commentStart = str.indexOf("/*");
  var lastEnd = 0;
  while (commentStart >= 0) {
    s = s + str.slice(lastEnd, commentStart);
    var commentEnd = str.indexOf("*/", commentStart + 2);
    if (commentEnd < 0) {
      return s;
    }
    lastEnd = commentEnd + 2;
    commentStart = str.indexOf("/*", lastEnd);
  }
  s = s + str.slice(lastEnd);
  return s;
}
module.exports = exports.default;


code:
"use strict";

exports.__esModule = true;
exports["default"] = unesc;
// Many thanks for this post which made this migration much easier.
// https://mathiasbynens.be/notes/css-escapes

/**
 *
 * @param {string} str
 * @returns {[string, number]|undefined}
 */
function gobbleHex(str) {
  var lower = str.toLowerCase();
  var hex = '';
  var spaceTerminated = false;
  for (var i = 0; i < 6 && lower[i] !== undefined; i++) {
    var code = lower.charCodeAt(i);
    // check to see if we are dealing with a valid hex char [a-f|0-9]
    var valid = code >= 97 && code <= 102 || code >= 48 && code <= 57;
    // https://drafts.csswg.org/css-syntax/#consume-escaped-code-point
    spaceTerminated = code === 32;
    if (!valid) {
      break;
    }
    hex += lower[i];
  }
  if (hex.length === 0) {
    return undefined;
  }
  var codePoint = parseInt(hex, 16);
  var isSurrogate = codePoint >= 0xD800 && codePoint <= 0xDFFF;
  // Add special case for
  // "If this number is zero, or is for a surrogate, or is greater than the maximum allowed code point"
  // https://drafts.csswg.org/css-syntax/#maximum-allowed-code-point
  if (isSurrogate || codePoint === 0x0000 || codePoint > 0x10FFFF) {
    return ["\uFFFD", hex.length + (spaceTerminated ? 1 : 0)];
  }
  return [String.fromCodePoint(codePoint), hex.length + (spaceTerminated ? 1 : 0)];
}
var CONTAINS_ESCAPE = /\\/;
function unesc(str) {
  var needToProcess = CONTAINS_ESCAPE.test(str);
  if (!needToProcess) {
    return str;
  }
  var ret = "";
  for (var i = 0; i < str.length; i++) {
    if (str[i] === "\\") {
      var gobbled = gobbleHex(str.slice(i + 1, i + 7));
      if (gobbled !== undefined) {
        ret += gobbled[0];
        i += gobbled[1];
        continue;
      }

      // Retain a pair of \\ if double escaped `\\\\`
      // https://github.com/postcss/postcss-selector-parser/commit/268c9a7656fb53f543dc620aa5b73a30ec3ff20e
      if (str[i + 1] === "\\") {
        ret += "\\";
        i++;
        continue;
      }

      // if \\ is at the end of the string retain it
      // https://github.com/postcss/postcss-selector-parser/commit/01a6b346e3612ce1ab20219acc26abdc259ccefb
      if (str.length === i + 1) {
        ret += str[i];
      }
      continue;
    }
    ret += str[i];
  }
  return ret;
}
module.exports = exports.default;


postcss-selector-parser

typecheck: tsc --noEmit --strict postcss-selector-parser.d.ts postcss-selector-parser.test.ts

pretest: eslint src && npm run typecheck

prepare: del-cli dist && BABEL_ENV=publish babel src --out-dir dist --ignore /__tests__/

lintfix: eslint --fix src

report: nyc report --reporter=html

test: nyc ava src/__tests__/*.mjs

testone: ava

license: MIT

repository: postcss/postcss-selector-parser


code:
// Type definitions for postcss-selector-parser 2.2.3
// Definitions by: Chris Eppstein <chris@eppsteins.net>

/*~ Note that ES6 modules cannot directly export callable functions.
 *~ This file should be imported using the CommonJS-style:
 *~   import x = require('someLibrary');
 *~
 *~ Refer to the documentation to understand common
 *~ workarounds for this limitation of ES6 modules.
 */

/*~ This declaration specifies that the function
 *~ is the exported object from the file
 */
export = parser;

// A type that's T but not U.
type Diff<T, U> = T extends U ? never : T;

// TODO: Conditional types in TS 1.8 will really clean this up.
declare function parser(): parser.Processor<never>;
declare function parser<Transform>(processor: parser.AsyncProcessor<Transform>): parser.Processor<Transform, never>;
declare function parser(processor: parser.AsyncProcessor<void>): parser.Processor<never, never>;
declare function parser<Transform>(processor: parser.SyncProcessor<Transform>): parser.Processor<Transform>;
declare function parser(processor: parser.SyncProcessor<void>): parser.Processor<never>;
declare function parser<Transform>(processor?: parser.SyncProcessor<Transform> | parser.AsyncProcessor<Transform>): parser.Processor<Transform>;

/*~ If you want to expose types from your module as well, you can
 *~ place them in this block. Often you will want to describe the
 *~ shape of the return type of the function; that type should
 *~ be declared in here, as this example shows.
 */
declare namespace parser {
    /* copied from postcss -- so we don't need to add a dependency */
    type ErrorOptions = {
        plugin?: string;
        word?: string;
        index?: number
    };
    /* the bits we use of postcss.Rule, copied from postcss -- so we don't need to add a dependency */
    type PostCSSRuleNode = {
        selector: string
        /**
         * @returns postcss.CssSyntaxError but it's a complex object, caller
         *   should cast to it if they have a dependency on postcss.
         */
        error(message: string, options?: ErrorOptions): Error;
    };
    /** Accepts a string  */
    type Selectors = string | PostCSSRuleNode
    type ProcessorFn<ReturnType = void> = (root: parser.Root) => ReturnType;
    type SyncProcessor<Transform = void> = ProcessorFn<Transform>;
    type AsyncProcessor<Transform = void> = ProcessorFn<PromiseLike<Transform>>;

    const TAG: "tag";
    const STRING: "string";
    const SELECTOR: "selector";
    const ROOT: "root";
    const PSEUDO: "pseudo";
    const NESTING: "nesting";
    const ID: "id";
    const COMMENT: "comment";
    const COMBINATOR: "combinator";
    const CLASS: "class";
    const ATTRIBUTE: "attribute";
    const UNIVERSAL: "universal";

    interface NodeTypes {
        tag: Tag,
        string: String,
        selector: Selector,
        root: Root,
        pseudo: Pseudo,
        nesting: Nesting,
        id: Identifier,
        comment: Comment,
        combinator: Combinator,
        class: ClassName,
        attribute: Attribute,
        universal: Universal
    }

    type Node = NodeTypes[keyof NodeTypes];

    function isNode(node: any): node is Node;

    interface Options {
        /**
         * Preserve whitespace when true. Default: false;
         */
        lossless: boolean;
        /**
         * When true and a postcss.Rule is passed, set the result of
         * processing back onto the rule when done. Default: false.
         */
        updateSelector: boolean;
    }
    class Processor<
        TransformType = never,
        SyncSelectorsType extends Selectors | never = Selectors
    > {
        res: Root;
        readonly result: String;
        ast(selectors: Selectors, options?: Partial<Options>): Promise<Root>;
        astSync(selectors: SyncSelectorsType, options?: Partial<Options>): Root;
        transform(selectors: Selectors, options?: Partial<Options>): Promise<TransformType>;
        transformSync(selectors: SyncSelectorsType, options?: Partial<Options>): TransformType;
        process(selectors: Selectors, options?: Partial<Options>): Promise<string>;
        processSync(selectors: SyncSelectorsType, options?: Partial<Options>): string;
    }
    interface ParserOptions {
        css: string;
        error: (message: string, options: ErrorOptions) => Error;
        options: Options;
    }
    class Parser {
        input: ParserOptions;
        lossy: boolean;
        position: number;
        root: Root;
        selectors: string;
        current: Selector;
        constructor(input: ParserOptions);
        /**
         * Raises an error, if the processor is invoked on
         * a postcss Rule node, a better error message is raised.
         */
        error(message: string, options?: ErrorOptions): void;
    }
    interface NodeSource {
        start?: {
            line: number,
            column: number
        },
        end?: {
            line: number,
            column: number
        }
    }
    interface SpaceAround {
      before: string;
      after: string;
    }
    interface Spaces extends SpaceAround {
      [spaceType: string]: string | Partial<SpaceAround> | undefined;
    }
    interface NodeOptions<Value = string> {
        value: Value;
        spaces?: Partial<Spaces>;
        source?: NodeSource;
        sourceIndex?: number;
    }
    interface Base<
        Value extends string | undefined = string,
        ParentType extends Container | undefined = Container | undefined
    > {
        type: keyof NodeTypes;
        parent: ParentType;
        value: Value;
        spaces: Spaces;
        source?: NodeSource;
        sourceIndex: number;
        rawSpaceBefore: string;
        rawSpaceAfter: string;
        remove(): Node;
        replaceWith(...nodes: Node[]): Node;
        next(): Node | undefined;
        prev(): Node | undefined;
        clone(opts?: {[override: string]:any}): this;
        /**
         * Return whether this node includes the character at the position of the given line and column.
         * Returns undefined if the nodes lack sufficient source metadata to determine the position.
         * @param line 1-index based line number relative to the start of the selector.
         * @param column 1-index based column number relative to the start of the selector.
         */
        isAtPosition(line: number, column: number): boolean | undefined;
        /**
         * Some non-standard syntax doesn't follow normal escaping rules for css,
         * this allows the escaped value to be specified directly, allowing illegal characters to be
         * directly inserted into css output.
         * @param name the property to set
         * @param value the unescaped value of the property
         * @param valueEscaped optional. the escaped value of the property.
         */
        setPropertyAndEscape(name: string, value: any, valueEscaped: string): void;
        /**
         * When you want a value to passed through to CSS directly. This method
         * deletes the corresponding raw value causing the stringifier to fallback
         * to the unescaped value.
         * @param name the property to set.
         * @param value The value that is both escaped and unescaped.
         */
        setPropertyWithoutEscape(name: string, value: any): void;
        /**
         * Some non-standard syntax doesn't follow normal escaping rules for css.
         * This allows non standard syntax to be appended to an existing property
         * by specifying the escaped value. By specifying the escaped value,
         * illegal characters are allowed to be directly inserted into css output.
         * @param {string} name the property to set
         * @param {any} value the unescaped value of the property
         * @param {string} valueEscaped optional. the escaped value of the property.
         */
        appendToPropertyAndEscape(name: string, value: any, valueEscaped: string): void;
        toString(): string;
    }
    interface ContainerOptions extends NodeOptions {
        nodes?: Array<Node>;
    }
    interface Container<
        Value extends string | undefined = string,
        Child extends Node = Node
    > extends Base<Value> {
        nodes: Array<Child>;
        append(selector: Child): this;
        prepend(selector: Child): this;
        at(index: number): Child;
        /**
         * Return the most specific node at the line and column number given.
         * The source location is based on the original parsed location, locations aren't
         * updated as selector nodes are mutated.
         *
         * Note that this location is relative to the location of the first character
         * of the selector, and not the location of the selector in the overall document
         * when used in conjunction with postcss.
         *
         * If not found, returns undefined.
         * @param line The line number of the node to find. (1-based index)
         * @param col  The column number of the node to find. (1-based index)
         */
        atPosition(line: number, column: number): Child;
        index(child: Child): number;
        readonly first: Child;
        readonly last: Child;
        readonly length: number;
        removeChild(child: Child): this;
        removeAll(): this;
        empty(): this;
        insertAfter(oldNode: Child, newNode: Child): this;
        insertBefore(oldNode: Child, newNode: Child): this;
        each(callback: (node: Child, index: number) => boolean | void): boolean | undefined;
        walk(
            callback: (node: Node, index: number) => boolean | void
        ): boolean | undefined;
        walkAttributes(
            callback: (node: Attribute) => boolean | void
        ): boolean | undefined;
        walkClasses(
            callback: (node: ClassName) => boolean | void
        ): boolean | undefined;
        walkCombinators(
            callback: (node: Combinator) => boolean | void
        ): boolean | undefined;
        walkComments(
            callback: (node: Comment) => boolean | void
        ): boolean | undefined;
        walkIds(
            callback: (node: Identifier) => boolean | void
        ): boolean | undefined;
        walkNesting(
            callback: (node: Nesting) => boolean | void
        ): boolean | undefined;
        walkPseudos(
            callback: (node: Pseudo) => boolean | void
        ): boolean | undefined;
        walkTags(callback: (node: Tag) => boolean | void): boolean | undefined;
        split(callback: (node: Child) => boolean): [Child[], Child[]];
        map<T>(callback: (node: Child) => T): T[];
        reduce(
            callback: (
                previousValue: Child,
                currentValue: Child,
                currentIndex: number,
                array: readonly Child[]
            ) => Child
        ): Child;
        reduce(
            callback: (
                previousValue: Child,
                currentValue: Child,
                currentIndex: number,
                array: readonly Child[]
            ) => Child,
            initialValue: Child
        ): Child;
        reduce<T>(
            callback: (
                previousValue: T,
                currentValue: Child,
                currentIndex: number,
                array: readonly Child[]
            ) => T,
            initialValue: T
        ): T;
        every(callback: (node: Child) => boolean): boolean;
        some(callback: (node: Child) => boolean): boolean;
        filter(callback: (node: Child) => boolean): Child[];
        sort(callback: (nodeA: Child, nodeB: Child) => number): Child[];
        toString(): string;
    }
    function isContainer(node: any): node is Root | Selector | Pseudo;

    interface NamespaceOptions<Value extends string | undefined = string> extends NodeOptions<Value> {
        namespace?: string | true;
    }
    interface Namespace<Value extends string | undefined = string> extends Base<Value> {
        /** alias for namespace */
        ns: string | true;
        /**
         *  namespace prefix.
         */
        namespace: string | true;
        /**
         * If a namespace exists, prefix the value provided with it, separated by |.
         */
        qualifiedName(value: string): string;
        /**
         * A string representing the namespace suitable for output.
         */
        readonly namespaceString: string;
    }
    function isNamespace(node: any): node is Attribute | Tag;

    interface Root extends Container<undefined, Selector> {
        type: "root";
        /**
         * Raises an error, if the processor is invoked on
         * a postcss Rule node, a better error message is raised.
         */
        error(message: string, options?: ErrorOptions): Error;
        nodeAt(line: number, column: number): Node
    }
    function root(opts: ContainerOptions): Root;
    function isRoot(node: any): node is Root;

    interface _Selector<S> extends Container<string, Diff<Node, S>> {
        type: "selector";
    }
    type Selector = _Selector<Selector>;
    function selector(opts: ContainerOptions): Selector;
    function isSelector(node: any): node is Selector;

    interface CombinatorRaws {
        value?: string;
        spaces?: {
            before?: string;
            after?: string;
        };
    }
    interface Combinator extends Base {
        type: "combinator";
        raws?: CombinatorRaws;
    }
    function combinator(opts: NodeOptions): Combinator;
    function isCombinator(node: any): node is Combinator;

    interface ClassName extends Base {
        type: "class";
    }
    function className(opts: NamespaceOptions): ClassName;
    function isClassName(node: any): node is ClassName;

    type AttributeOperator = "=" | "~=" | "|=" | "^=" | "$=" | "*=";
    type QuoteMark = '"' | "'" | null;
    interface PreferredQuoteMarkOptions {
        quoteMark?: QuoteMark;
        preferCurrentQuoteMark?: boolean;
    }
    interface SmartQuoteMarkOptions extends PreferredQuoteMarkOptions {
        smart?: boolean;
    }
    interface AttributeOptions extends NamespaceOptions<string | undefined> {
        attribute: string;
        operator?: AttributeOperator;
        insensitive?: boolean;
        quoteMark?: QuoteMark;
        /** @deprecated Use quoteMark instead. */
        quoted?: boolean;
        spaces?: {
            before?: string;
            after?: string;
            attribute?: Partial<SpaceAround>;
            operator?: Partial<SpaceAround>;
            value?: Partial<SpaceAround>;
            insensitive?: Partial<SpaceAround>;
        }
        raws: {
            unquoted?: string;
            attribute?: string;
            operator?: string;
            value?: string;
            insensitive?: string;
            spaces?: {
                attribute?: Partial<Spaces>;
                operator?: Partial<Spaces>;
                value?: Partial<Spaces>;
                insensitive?: Partial<Spaces>;
            }
        };
    }
    interface Attribute extends Namespace<string | undefined> {
        type: "attribute";
        attribute: string;
        operator?: AttributeOperator;
        insensitive?: boolean;
        quoteMark: QuoteMark;
        quoted?: boolean;
        spaces: {
            before: string;
            after: string;
            attribute?: Partial<Spaces>;
            operator?: Partial<Spaces>;
            value?: Partial<Spaces>;
            insensitive?: Partial<Spaces>;
        }
        raws: {
            /** @deprecated The attribute value is unquoted, use that instead.. */
            unquoted?: string;
            attribute?: string;
            operator?: string;
            /** The value of the attribute with quotes and escapes. */
            value?: string;
            insensitive?: string;
            spaces?: {
                attribute?: Partial<Spaces>;
                operator?: Partial<Spaces>;
                value?: Partial<Spaces>;
                insensitive?: Partial<Spaces>;
            }
        };
        /**
         * The attribute name after having been qualified with a namespace.
         */
        readonly qualifiedAttribute: string;

        /**
         * The case insensitivity flag or an empty string depending on whether this
         * attribute is case insensitive.
         */
        readonly insensitiveFlag : 'i' | '';

        /**
         * Returns the attribute's value quoted such that it would be legal to use
         * in the value of a css file. The original value's quotation setting
         * used for stringification is left unchanged. See `setValue(value, options)`
         * if you want to control the quote settings of a new value for the attribute or
         * `set quoteMark(mark)` if you want to change the quote settings of the current
         * value.
         *
         * You can also change the quotation used for the current value by setting quoteMark.
         **/
        getQuotedValue(options?: SmartQuoteMarkOptions): string;

        /**
         * Set the unescaped value with the specified quotation options. The value
         * provided must not include any wrapping quote marks -- those quotes will
         * be interpreted as part of the value and escaped accordingly.
         * @param value
         */
        setValue(value: string, options?: SmartQuoteMarkOptions): void;

        /**
         * Intelligently select a quoteMark value based on the value's contents. If
         * the value is a legal CSS ident, it will not be quoted. Otherwise a quote
         * mark will be picked that minimizes the number of escapes.
         *
         * If there's no clear winner, the quote mark from these options is used,
         * then the source quote mark (this is inverted if `preferCurrentQuoteMark` is
         * true). If the quoteMark is unspecified, a double quote is used.
         **/
        smartQuoteMark(options: PreferredQuoteMarkOptions): QuoteMark;

        /**
         * Selects the preferred quote mark based on the options and the current quote mark value.
         * If you want the quote mark to depend on the attribute value, call `smartQuoteMark(opts)`
         * instead.
         */
        preferredQuoteMark(options: PreferredQuoteMarkOptions): QuoteMark

        /**
         * returns the offset of the attribute part specified relative to the
         * start of the node of the output string.
         *
         * * "ns" - alias for "namespace"
         * * "namespace" - the namespace if it exists.
         * * "attribute" - the attribute name
         * * "attributeNS" - the start of the attribute or its namespace
         * * "operator" - the match operator of the attribute
         * * "value" - The value (string or identifier)
         * * "insensitive" - the case insensitivity flag;
         * @param part One of the possible values inside an attribute.
         * @returns -1 if the name is invalid or the value doesn't exist in this attribute.
         */
        offsetOf(part: "ns" | "namespace" | "attribute" | "attributeNS" | "operator" | "value" | "insensitive"): number;
    }
    function attribute(opts: AttributeOptions): Attribute;
    function isAttribute(node: any): node is Attribute;

    interface Pseudo extends Container<string, Selector> {
        type: "pseudo";
    }
    function pseudo(opts: ContainerOptions): Pseudo;
    /**
     * Checks whether the node is the Pseudo subtype of node.
     */
    function isPseudo(node: any): node is Pseudo;

    /**
     * Checks whether the node is, specifically, a pseudo element instead of
     * pseudo class.
     */
    function isPseudoElement(node: any): node is Pseudo;

    /**
     * Checks whether the node is, specifically, a pseudo class instead of
     * pseudo element.
     */
    function isPseudoClass(node: any): node is Pseudo;

    interface Tag extends Namespace {
        type: "tag";
    }
    function tag(opts: NamespaceOptions): Tag;
    function isTag(node: any): node is Tag;

    interface Comment extends Base {
        type: "comment";
    }
    function comment(opts: NodeOptions): Comment;
    function isComment(node: any): node is Comment;

    interface Identifier extends Base {
        type: "id";
    }
    function id(opts: any): any;
    function isIdentifier(node: any): node is Identifier;

    interface Nesting extends Base {
        type: "nesting";
    }
    function nesting(opts: any): any;
    function isNesting(node: any): node is Nesting;

    interface String extends Base {
        type: "string";
    }
    function string(opts: NodeOptions): String;
    function isString(node: any): node is String;

    interface Universal extends Base {
        type: "universal";
    }
    function universal(opts?: NamespaceOptions): any;
    function isUniversal(node: any): node is Universal;
}


code:
Copyright (c) Ben Briggs <beneb.info@gmail.com> (http://beneb.info)

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.


code:
# [postcss][postcss]-svgo

> Optimise inline SVG with PostCSS.

## Install

With [npm](https://npmjs.org/package/postcss-svgo) do:

```
npm install postcss-svgo --save
```

## Example

### Input

```css
h1 {
    background: url('data:image/svg+xml;charset=utf-8,<?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"><circle cx="50" cy="50" r="40" fill="yellow" /></svg>');
}

h2 {
    background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgcj0iNDAiIGZpbGw9InllbGxvdyIgLz48IS0tdGVzdCBjb21tZW50LS0+PC9zdmc+');
}
```

### Output

```css
h1 {
    background: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40" fill="%23ff0"/></svg>');
}

h2 {
    background: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjQwIiBmaWxsPSIjZmYwIi8+PC9zdmc+');
}
```

## API

### `svgo([options])`

#### options

##### encode

Type: `boolean`
Default: `undefined`

If `true`, it will encode URL-unsafe characters such as `<`, `>` and `&`;
`false` will decode these characters, and `undefined` will neither encode nor
decode the original input. Note that regardless of this setting, `#` will
always be URL-encoded.

##### plugins

Optionally, you can customise the output by specifying the `plugins` option. You
will need to provide the config in comma separated objects, like the example
below. Note that you can either disable the plugin by setting it to `false`,
or pass different options to change the default behaviour.

```js
var postcss = require('postcss');
var svgo = require('postcss-svgo');

var opts = {
    plugins: [{
        removeDoctype: false
    }, {
        removeComments: false
    }, {
        cleanupNumericValues: {
            floatPrecision: 2
        }
    }, {
        convertColors: {
            names2hex: false,
            rgb2hex: false
        }
    }]
};

postcss([ svgo(opts) ]).process(css).then(function (result) {
    console.log(result.css)
});
```

You can view the [full list of plugins here][plugins].

## Usage

See the [PostCSS documentation](https://github.com/postcss/postcss#usage) for
examples for your environment.

## Contributors

See [CONTRIBUTORS.md](https://github.com/cssnano/cssnano/blob/master/CONTRIBUTORS.md).

## License

MIT © [Ben Briggs](http://beneb.info)

[postcss]: https://github.com/postcss/postcss
[plugins]: https://github.com/svg/svgo/tree/master/plugins


code: declare var URL: typeof import('url').URL;


code:
'use strict';
const valueParser = require('postcss-value-parser');
const { optimize } = require('svgo');
const { encode, decode } = require('./lib/url');

const PLUGIN = 'postcss-svgo';
const dataURI = /data:image\/svg\+xml(;((charset=)?utf-8|base64))?,/i;
const dataURIBase64 = /data:image\/svg\+xml;base64,/i;

// the following regex will globally match:
// \b([\w-]+)       --> a word (a sequence of one or more [alphanumeric|underscore|dash] characters; followed by
// \s*=\s*          --> an equal sign character (=) between optional whitespaces; followed by
// \\"([\S\s]+?)\\" --> any characters (including whitespaces and newlines) between literal escaped quotes (\")
const escapedQuotes = /\b([\w-]+)\s*=\s*\\"([\S\s]+?)\\"/g;

/**
 * @param {string} input the SVG string
 * @param {Options} opts
 * @return {{result: string, isUriEncoded: boolean}} the minification result
 */
function minifySVG(input, opts) {
  let svg = input;
  let decodedUri, isUriEncoded;
  try {
    decodedUri = decode(input);
    isUriEncoded = decodedUri !== input;
  } catch (e) {
    // Swallow exception if we cannot decode the value
    isUriEncoded = false;
  }

  if (isUriEncoded) {
    svg = /** @type {string} */ (decodedUri);
  }

  if (opts.encode !== undefined) {
    isUriEncoded = opts.encode;
  }

  // normalize all escaped quote characters from svg attributes
  // from <svg attr=\"value\"... /> to <svg attr="value"... />
  // see: https://github.com/cssnano/cssnano/issues/1194
  svg = svg.replace(escapedQuotes, '$1="$2"');

  const result = optimize(svg, opts);
  if (result.error) {
    throw new Error(result.error);
  }

  return {
    result: /** @type {import('svgo').OptimizedSvg}*/ (result).data,
    isUriEncoded,
  };
}

/**
 * @param {import('postcss').Declaration} decl
 * @param {Options} opts
 * @param {import('postcss').Result} postcssResult
 * @return {void}
 */
function minify(decl, opts, postcssResult) {
  const parsed = valueParser(decl.value);

  const minified = parsed.walk((node) => {
    if (
      node.type !== 'function' ||
      node.value.toLowerCase() !== 'url' ||
      !node.nodes.length
    ) {
      return;
    }
    let { value, quote } = /** @type {valueParser.StringNode} */ (
      node.nodes[0]
    );

    let optimizedValue;

    try {
      if (dataURIBase64.test(value)) {
        const url = new URL(value);
        const base64String = `${url.protocol}${url.pathname}`.replace(
          dataURI,
          ''
        );
        const svg = Buffer.from(base64String, 'base64').toString('utf8');
        const { result } = minifySVG(svg, opts);
        const data = Buffer.from(result).toString('base64');
        optimizedValue = 'data:image/svg+xml;base64,' + data + url.hash;
      } else if (dataURI.test(value)) {
        const svg = value.replace(dataURI, '');
        const { result, isUriEncoded } = minifySVG(svg, opts);
        let data = isUriEncoded ? encode(result) : result;
        // Should always encode # otherwise we yield a broken SVG
        // in Firefox (works in Chrome however). See this issue:
        // https://github.com/cssnano/cssnano/issues/245
        data = data.replace(/#/g, '%23');
        optimizedValue = 'data:image/svg+xml;charset=utf-8,' + data;
        quote = isUriEncoded ? '"' : "'";
      } else {
        return;
      }
    } catch (error) {
      decl.warn(postcssResult, `${error}`);
      return;
    }
    node.nodes[0] = Object.assign({}, node.nodes[0], {
      value: optimizedValue,
      quote: quote,
      type: 'string',
      before: '',
      after: '',
    });

    return false;
  });

  decl.value = minified.toString();
}
/** @typedef {{encode?: boolean, plugins?: object[]} & import('svgo').OptimizeOptions} Options */
/**
 * @type {import('postcss').PluginCreator<Options>}
 * @param {Options} opts
 * @return {import('postcss').Plugin}
 */
function pluginCreator(opts = {}) {
  return {
    postcssPlugin: PLUGIN,

    OnceExit(css, { result }) {
      css.walkDecls((decl) => {
        if (!dataURI.test(decl.value)) {
          return;
        }

        minify(decl, opts, result);
      });
    },
  };
}

pluginCreator.postcss = true;
module.exports = pluginCreator;


code:
'use strict';
/**
 * @param {string} data
 * @return {string}
 */
function encode(data) {
  return data
    .replace(/"/g, "'")
    .replace(/%/g, '%25')
    .replace(/</g, '%3C')
    .replace(/>/g, '%3E')
    .replace(/&/g, '%26')
    .replace(/#/g, '%23')
    .replace(/\s+/g, ' ');
}

const decode = decodeURIComponent;
module.exports = { encode, decode };


code:
export = pluginCreator;
/** @typedef {{encode?: boolean, plugins?: object[]} & import('svgo').OptimizeOptions} Options */
/**
 * @type {import('postcss').PluginCreator<Options>}
 * @param {Options} opts
 * @return {import('postcss').Plugin}
 */
declare function pluginCreator(opts?: Options): import('postcss').Plugin;
declare namespace pluginCreator {
    export { postcss, Options };
}
type Options = {
    encode?: boolean;
    plugins?: object[];
} & import('svgo').OptimizeOptions;
declare var postcss: true;
import { encode } from "./lib/url";


code:
/**
 * @param {string} data
 * @return {string}
 */
export function encode(data: string): string;
export const decode: typeof decodeURIComponent;


code:
# [postcss][postcss]-unique-selectors

> Ensure CSS selectors are unique.

## Install

With [npm](https://npmjs.org/package/postcss-unique-selectors) do:

```
npm install postcss-unique-selectors --save
```

## Example

Selectors are sorted naturally, and deduplicated:

### Input

```css
h1,h3,h2,h1 {
    color: red
}
```

### Output

```css
h1,h2,h3 {
    color: red
}
```

## Usage

See the [PostCSS documentation](https://github.com/postcss/postcss#usage) for
examples for your environment.

## Contributors

See [CONTRIBUTORS.md](https://github.com/cssnano/cssnano/blob/master/CONTRIBUTORS.md).

## License

MIT © [Ben Briggs](http://beneb.info)

[postcss]: https://github.com/postcss/postcss


postcss-unique-selectors

description: Ensure CSS selectors are unique.

files: LICENSE-MIT src types

keywords: css postcss postcss-plugin

repository: cssnano/cssnano

readme:
# [postcss][postcss]-unique-selectors

> Ensure CSS selectors are unique.

## Install

With [npm](https://npmjs.org/package/postcss-unique-selectors) do:

```
npm install postcss-unique-selectors --save
```

## Example

Selectors are sorted naturally, and deduplicated:

### Input

```css
h1,h3,h2,h1 {
    color: red
}
```

### Output

```css
h1,h2,h3 {
    color: red
}
```

## Usage

See the [PostCSS documentation](https://github.com/postcss/postcss#usage) for
examples for your environment.

## Contributors

See [CONTRIBUTORS.md](https://github.com/cssnano/cssnano/blob/master/CONTRIBUTORS.md).

## License

MIT © [Ben Briggs](http://beneb.info)

[postcss]: https://github.com/postcss/postcss


code:
'use strict';
const selectorParser = require('postcss-selector-parser');

/**
 * @param {string} selectors
 * @param {selectorParser.SyncProcessor<void>} callback
 * @return {string}
 */
function parseSelectors(selectors, callback) {
  return selectorParser(callback).processSync(selectors);
}

/**
 * @param {import('postcss').Rule} rule
 * @return {string}
 */
function unique(rule) {
  const selector = [...new Set(rule.selectors)];
  selector.sort();
  return selector.join();
}

/**
 * @type {import('postcss').PluginCreator<void>}
 * @return {import('postcss').Plugin}
 */
function pluginCreator() {
  return {
    postcssPlugin: 'postcss-unique-selectors',
    OnceExit(css) {
      css.walkRules((nodes) => {
        /** @type {string[]} */
        let comments = [];
        /** @type {selectorParser.SyncProcessor<void>} */
        const removeAndSaveComments = (selNode) => {
          selNode.walk((sel) => {
            if (sel.type === 'comment') {
              comments.push(sel.value);
              sel.remove();
              return;
            } else {
              return;
            }
          });
        };
        if (nodes.raws.selector && nodes.raws.selector.raw) {
          parseSelectors(nodes.raws.selector.raw, removeAndSaveComments);
          nodes.raws.selector.raw = unique(nodes);
        }
        nodes.selector = parseSelectors(nodes.selector, removeAndSaveComments);
        nodes.selector = unique(nodes);
        nodes.selectors = nodes.selectors.concat(comments);
      });
    },
  };
}

pluginCreator.postcss = true;
module.exports = pluginCreator;


code:
export = pluginCreator;
/**
 * @type {import('postcss').PluginCreator<void>}
 * @return {import('postcss').Plugin}
 */
declare function pluginCreator(): import('postcss').Plugin;
declare namespace pluginCreator {
    const postcss: true;
}


code:
# postcss-value-parser

[![Travis CI](https://travis-ci.org/TrySound/postcss-value-parser.svg)](https://travis-ci.org/TrySound/postcss-value-parser)

Transforms CSS declaration values and at-rule parameters into a tree of nodes, and provides a simple traversal API.

## Usage

```js
var valueParser = require('postcss-value-parser');
var cssBackgroundValue = 'url(foo.png) no-repeat 40px 73%';
var parsedValue = valueParser(cssBackgroundValue);
// parsedValue exposes an API described below,
// e.g. parsedValue.walk(..), parsedValue.toString(), etc.
```

For example, parsing the value `rgba(233, 45, 66, .5)` will return the following:

```js
{
  nodes: [
    {
      type: 'function',
      value: 'rgba',
      before: '',
      after: '',
      nodes: [
        { type: 'word', value: '233' },
        { type: 'div', value: ',', before: '', after: ' ' },
        { type: 'word', value: '45' },
        { type: 'div', value: ',', before: '', after: ' ' },
        { type: 'word', value: '66' },
        { type: 'div', value: ',', before: ' ', after: '' },
        { type: 'word', value: '.5' }
      ]
    }
  ]
}
```

If you wanted to convert each `rgba()` value in `sourceCSS` to a hex value, you could do so like this:

```js
var valueParser = require('postcss-value-parser');

var parsed = valueParser(sourceCSS);

// walk() will visit all the of the nodes in the tree,
// invoking the callback for each.
parsed.walk(function (node) {

  // Since we only want to transform rgba() values,
  // we can ignore anything else.
  if (node.type !== 'function' && node.value !== 'rgba') return;

  // We can make an array of the rgba() arguments to feed to a
  // convertToHex() function
  var color = node.nodes.filter(function (node) {
    return node.type === 'word';
  }).map(function (node) {
    return Number(node.value);
  }); // [233, 45, 66, .5]

  // Now we will transform the existing rgba() function node
  // into a word node with the hex value
  node.type = 'word';
  node.value = convertToHex(color);
})

parsed.toString(); // #E92D42
```

## Nodes

Each node is an object with these common properties:

- **type**: The type of node (`word`, `string`, `div`, `space`, `comment`, or `function`).
  Each type is documented below.
- **value**: Each node has a `value` property; but what exactly `value` means
  is specific to the node type. Details are documented for each type below.
- **sourceIndex**: The starting index of the node within the original source
  string. For example, given the source string `10px 20px`, the `word` node
  whose value is `20px` will have a `sourceIndex` of `5`.

### word

The catch-all node type that includes keywords (e.g. `no-repeat`),
quantities (e.g. `20px`, `75%`, `1.5`), and hex colors (e.g. `#e6e6e6`).

Node-specific properties:

- **value**: The "word" itself.

### string

A quoted string value, e.g. `"something"` in `content: "something";`.

Node-specific properties:

- **value**: The text content of the string.
- **quote**: The quotation mark surrounding the string, either `"` or `'`.
- **unclosed**: `true` if the string was not closed properly. e.g. `"unclosed string  `.

### div

A divider, for example

- `,` in `animation-duration: 1s, 2s, 3s`
- `/` in `border-radius: 10px / 23px`
- `:` in `(min-width: 700px)`

Node-specific properties:

- **value**: The divider character. Either `,`, `/`, or `:` (see examples above).
- **before**: Whitespace before the divider.
- **after**: Whitespace after the divider.

### space

Whitespace used as a separator, e.g. ` ` occurring twice in `border: 1px solid black;`.

Node-specific properties:

- **value**: The whitespace itself.

### comment

A CSS comment starts with `/*` and ends with `*/`

Node-specific properties:

- **value**: The comment value without `/*` and `*/`
- **unclosed**: `true` if the comment was not closed properly. e.g. `/* comment without an end  `.

### function

A CSS function, e.g. `rgb(0,0,0)` or `url(foo.bar)`.

Function nodes have nodes nested within them: the function arguments.

Additional properties:

- **value**: The name of the function, e.g. `rgb` in `rgb(0,0,0)`.
- **before**: Whitespace after the opening parenthesis and before the first argument,
  e.g. `  ` in `rgb(  0,0,0)`.
- **after**: Whitespace before the closing parenthesis and after the last argument,
  e.g. `  ` in `rgb(0,0,0  )`.
- **nodes**: More nodes representing the arguments to the function.
- **unclosed**: `true` if the parentheses was not closed properly. e.g. `( unclosed-function  `.

Media features surrounded by parentheses are considered functions with an
empty value. For example, `(min-width: 700px)` parses to these nodes:

```js
[
  {
    type: 'function', value: '', before: '', after: '',
    nodes: [
      { type: 'word', value: 'min-width' },
      { type: 'div', value: ':', before: '', after: ' ' },
      { type: 'word', value: '700px' }
    ]
  }
]
```

`url()` functions can be parsed a little bit differently depending on
whether the first character in the argument is a quotation mark.

`url( /gfx/img/bg.jpg )` parses to:

```js
{ type: 'function', sourceIndex: 0, value: 'url', before: ' ', after: ' ', nodes: [
    { type: 'word', sourceIndex: 5, value: '/gfx/img/bg.jpg' }
] }
```

`url( "/gfx/img/bg.jpg" )`, on the other hand, parses to:

```js
{ type: 'function', sourceIndex: 0, value: 'url', before: ' ', after: ' ', nodes: [
     type: 'string', sourceIndex: 5, quote: '"', value: '/gfx/img/bg.jpg' },
] }
```

### unicode-range

The unicode-range CSS descriptor sets the specific range of characters to be
used from a font defined by @font-face and made available
for use on the current page (`unicode-range: U+0025-00FF`).

Node-specific properties:

- **value**: The "unicode-range" itself.

## API

```
var valueParser = require('postcss-value-parser');
```

### valueParser.unit(quantity)

Parses `quantity`, distinguishing the number from the unit. Returns an object like the following:

```js
// Given 2rem
{
  number: '2',
  unit: 'rem'
}
```

If the `quantity` argument cannot be parsed as a number, returns `false`.

*This function does not parse complete values*: you cannot pass it `1px solid black` and expect `px` as
the unit. Instead, you should pass it single quantities only. Parse `1px solid black`, then pass it
the stringified `1px` node (a `word` node) to parse the number and unit.

### valueParser.stringify(nodes[, custom])

Stringifies a node or array of nodes.

The `custom` function is called for each `node`; return a string to override the default behaviour.

### valueParser.walk(nodes, callback[, bubble])

Walks each provided node, recursively walking all descendent nodes within functions.

Returning `false` in the `callback` will prevent traversal of descendent nodes (within functions).
You can use this feature to for shallow iteration, walking over only the *immediate* children.
*Note: This only applies if `bubble` is `false` (which is the default).*

By default, the tree is walked from the outermost node inwards.
To reverse the direction, pass `true` for the `bubble` argument.

The `callback` is invoked with three arguments: `callback(node, index, nodes)`.

- `node`: The current node.
- `index`: The index of the current node.
- `nodes`: The complete nodes array passed to `walk()`.

Returns the `valueParser` instance.

### var parsed = valueParser(value)

Returns the parsed node tree.

### parsed.nodes

The array of nodes.

### parsed.toString()

Stringifies the node tree.

### parsed.walk(callback[, bubble])

Walks each node inside `parsed.nodes`. See the documentation for `valueParser.walk()` above.

# License

MIT © [Bogdan Chadkin](mailto:trysound@yandex.ru)


code:
declare namespace postcssValueParser {
  interface BaseNode {
    /**
     * The offset, inclusive, inside the CSS value at which the node starts.
     */
    sourceIndex: number;

    /**
     * The offset, exclusive, inside the CSS value at which the node ends.
     */
    sourceEndIndex: number;

    /**
     * The node's characteristic value
     */
    value: string;
  }

  interface ClosableNode {
    /**
     * Whether the parsed CSS value ended before the node was properly closed
     */
    unclosed?: true;
  }

  interface AdjacentAwareNode {
    /**
     * The token at the start of the node
     */
    before: string;

    /**
     * The token at the end of the node
     */
    after: string;
  }

  interface CommentNode extends BaseNode, ClosableNode {
    type: "comment";
  }

  interface DivNode extends BaseNode, AdjacentAwareNode {
    type: "div";
  }

  interface FunctionNode extends BaseNode, ClosableNode, AdjacentAwareNode {
    type: "function";

    /**
     * Nodes inside the function
     */
    nodes: Node[];
  }

  interface SpaceNode extends BaseNode {
    type: "space";
  }

  interface StringNode extends BaseNode, ClosableNode {
    type: "string";

    /**
     * The quote type delimiting the string
     */
    quote: '"' | "'";
  }

  interface UnicodeRangeNode extends BaseNode {
    type: "unicode-range";
  }

  interface WordNode extends BaseNode {
    type: "word";
  }

  /**
   * Any node parsed from a CSS value
   */
  type Node =
    | CommentNode
    | DivNode
    | FunctionNode
    | SpaceNode
    | StringNode
    | UnicodeRangeNode
    | WordNode;

  interface CustomStringifierCallback {
    /**
     * @param node The node to stringify
     * @returns The serialized CSS representation of the node
     */
    (nodes: Node): string | undefined;
  }

  interface WalkCallback {
    /**
     * @param node  The currently visited node
     * @param index The index of the node in the series of parsed nodes
     * @param nodes The series of parsed nodes
     * @returns Returning `false` will prevent traversal of descendant nodes (only applies if `bubble` was set to `true` in the `walk()` call)
     */
    (node: Node, index: number, nodes: Node[]): void | boolean;
  }

  /**
   * A CSS dimension, decomposed into its numeric and unit parts
   */
  interface Dimension {
    number: string;
    unit: string;
  }

  /**
   * A wrapper around a parsed CSS value that allows for inspecting and walking nodes
   */
  interface ParsedValue {
    /**
     * The series of parsed nodes
     */
    nodes: Node[];

    /**
     * Walk all parsed nodes, applying a callback
     *
     * @param callback A visitor callback that will be executed for each node
     * @param bubble   When set to `true`, walking will be done inside-out instead of outside-in
     */
    walk(callback: WalkCallback, bubble?: boolean): this;
  }

  interface ValueParser {
    /**
     * Decompose a CSS dimension into its numeric and unit part
     *
     * @param value The dimension to decompose
     * @returns An object representing `number` and `unit` part of the dimension or `false` if the decomposing fails
     */
    unit(value: string): Dimension | false;

    /**
     * Serialize a series of nodes into a CSS value
     *
     * @param nodes  The nodes to stringify
     * @param custom A custom stringifier callback
     * @returns The generated CSS value
     */
    stringify(nodes: Node | Node[], custom?: CustomStringifierCallback): string;

    /**
     * Walk a series of nodes, applying a callback
     *
     * @param nodes    The nodes to walk
     * @param callback A visitor callback that will be executed for each node
     * @param bubble   When set to `true`, walking will be done inside-out instead of outside-in
     */
    walk(nodes: Node[], callback: WalkCallback, bubble?: boolean): void;

    /**
     * Parse a CSS value into a series of nodes to operate on
     *
     * @param value The value to parse
     */
    new (value: string): ParsedValue;

    /**
     * Parse a CSS value into a series of nodes to operate on
     *
     * @param value The value to parse
     */
    (value: string): ParsedValue;
  }
}

declare const postcssValueParser: postcssValueParser.ValueParser;

export = postcssValueParser;


code:
var parse = require("./parse");
var walk = require("./walk");
var stringify = require("./stringify");

function ValueParser(value) {
  if (this instanceof ValueParser) {
    this.nodes = parse(value);
    return this;
  }
  return new ValueParser(value);
}

ValueParser.prototype.toString = function() {
  return Array.isArray(this.nodes) ? stringify(this.nodes) : "";
};

ValueParser.prototype.walk = function(cb, bubble) {
  walk(this.nodes, cb, bubble);
  return this;
};

ValueParser.unit = require("./unit");

ValueParser.walk = walk;

ValueParser.stringify = stringify;

module.exports = ValueParser;


code:
var openParentheses = "(".charCodeAt(0);
var closeParentheses = ")".charCodeAt(0);
var singleQuote = "'".charCodeAt(0);
var doubleQuote = '"'.charCodeAt(0);
var backslash = "\\".charCodeAt(0);
var slash = "/".charCodeAt(0);
var comma = ",".charCodeAt(0);
var colon = ":".charCodeAt(0);
var star = "*".charCodeAt(0);
var uLower = "u".charCodeAt(0);
var uUpper = "U".charCodeAt(0);
var plus = "+".charCodeAt(0);
var isUnicodeRange = /^[a-f0-9?-]+$/i;

module.exports = function(input) {
  var tokens = [];
  var value = input;

  var next,
    quote,
    prev,
    token,
    escape,
    escapePos,
    whitespacePos,
    parenthesesOpenPos;
  var pos = 0;
  var code = value.charCodeAt(pos);
  var max = value.length;
  var stack = [{ nodes: tokens }];
  var balanced = 0;
  var parent;

  var name = "";
  var before = "";
  var after = "";

  while (pos < max) {
    // Whitespaces
    if (code <= 32) {
      next = pos;
      do {
        next += 1;
        code = value.charCodeAt(next);
      } while (code <= 32);
      token = value.slice(pos, next);

      prev = tokens[tokens.length - 1];
      if (code === closeParentheses && balanced) {
        after = token;
      } else if (prev && prev.type === "div") {
        prev.after = token;
        prev.sourceEndIndex += token.length;
      } else if (
        code === comma ||
        code === colon ||
        (code === slash &&
          value.charCodeAt(next + 1) !== star &&
          (!parent ||
            (parent && parent.type === "function" && parent.value !== "calc")))
      ) {
        before = token;
      } else {
        tokens.push({
          type: "space",
          sourceIndex: pos,
          sourceEndIndex: next,
          value: token
        });
      }

      pos = next;

      // Quotes
    } else if (code === singleQuote || code === doubleQuote) {
      next = pos;
      quote = code === singleQuote ? "'" : '"';
      token = {
        type: "string",
        sourceIndex: pos,
        quote: quote
      };
      do {
        escape = false;
        next = value.indexOf(quote, next + 1);
        if (~next) {
          escapePos = next;
          while (value.charCodeAt(escapePos - 1) === backslash) {
            escapePos -= 1;
            escape = !escape;
          }
        } else {
          value += quote;
          next = value.length - 1;
          token.unclosed = true;
        }
      } while (escape);
      token.value = value.slice(pos + 1, next);
      token.sourceEndIndex = token.unclosed ? next : next + 1;
      tokens.push(token);
      pos = next + 1;
      code = value.charCodeAt(pos);

      // Comments
    } else if (code === slash && value.charCodeAt(pos + 1) === star) {
      next = value.indexOf("*/", pos);

      token = {
        type: "comment",
        sourceIndex: pos,
        sourceEndIndex: next + 2
      };

      if (next === -1) {
        token.unclosed = true;
        next = value.length;
        token.sourceEndIndex = next;
      }

      token.value = value.slice(pos + 2, next);
      tokens.push(token);

      pos = next + 2;
      code = value.charCodeAt(pos);

      // Operation within calc
    } else if (
      (code === slash || code === star) &&
      parent &&
      parent.type === "function" &&
      parent.value === "calc"
    ) {
      token = value[pos];
      tokens.push({
        type: "word",
        sourceIndex: pos - before.length,
        sourceEndIndex: pos + token.length,
        value: token
      });
      pos += 1;
      code = value.charCodeAt(pos);

      // Dividers
    } else if (code === slash || code === comma || code === colon) {
      token = value[pos];

      tokens.push({
        type: "div",
        sourceIndex: pos - before.length,
        sourceEndIndex: pos + token.length,
        value: token,
        before: before,
        after: ""
      });
      before = "";

      pos += 1;
      code = value.charCodeAt(pos);

      // Open parentheses
    } else if (openParentheses === code) {
      // Whitespaces after open parentheses
      next = pos;
      do {
        next += 1;
        code = value.charCodeAt(next);
      } while (code <= 32);
      parenthesesOpenPos = pos;
      token = {
        type: "function",
        sourceIndex: pos - name.length,
        value: name,
        before: value.slice(parenthesesOpenPos + 1, next)
      };
      pos = next;

      if (name === "url" && code !== singleQuote && code !== doubleQuote) {
        next -= 1;
        do {
          escape = false;
          next = value.indexOf(")", next + 1);
          if (~next) {
            escapePos = next;
            while (value.charCodeAt(escapePos - 1) === backslash) {
              escapePos -= 1;
              escape = !escape;
            }
          } else {
            value += ")";
            next = value.length - 1;
            token.unclosed = true;
          }
        } while (escape);
        // Whitespaces before closed
        whitespacePos = next;
        do {
          whitespacePos -= 1;
          code = value.charCodeAt(whitespacePos);
        } while (code <= 32);
        if (parenthesesOpenPos < whitespacePos) {
          if (pos !== whitespacePos + 1) {
            token.nodes = [
              {
                type: "word",
                sourceIndex: pos,
                sourceEndIndex: whitespacePos + 1,
                value: value.slice(pos, whitespacePos + 1)
              }
            ];
          } else {
            token.nodes = [];
          }
          if (token.unclosed && whitespacePos + 1 !== next) {
            token.after = "";
            token.nodes.push({
              type: "space",
              sourceIndex: whitespacePos + 1,
              sourceEndIndex: next,
              value: value.slice(whitespacePos + 1, next)
            });
          } else {
            token.after = value.slice(whitespacePos + 1, next);
            token.sourceEndIndex = next;
          }
        } else {
          token.after = "";
          token.nodes = [];
        }
        pos = next + 1;
        token.sourceEndIndex = token.unclosed ? next : pos;
        code = value.charCodeAt(pos);
        tokens.push(token);
      } else {
        balanced += 1;
        token.after = "";
        token.sourceEndIndex = pos + 1;
        tokens.push(token);
        stack.push(token);
        tokens = token.nodes = [];
        parent = token;
      }
      name = "";

      // Close parentheses
    } else if (closeParentheses === code && balanced) {
      pos += 1;
      code = value.charCodeAt(pos);

      parent.after = after;
      parent.sourceEndIndex += after.length;
      after = "";
      balanced -= 1;
      stack[stack.length - 1].sourceEndIndex = pos;
      stack.pop();
      parent = stack[balanced];
      tokens = parent.nodes;

      // Words
    } else {
      next = pos;
      do {
        if (code === backslash) {
          next += 1;
        }
        next += 1;
        code = value.charCodeAt(next);
      } while (
        next < max &&
        !(
          code <= 32 ||
          code === singleQuote ||
          code === doubleQuote ||
          code === comma ||
          code === colon ||
          code === slash ||
          code === openParentheses ||
          (code === star &&
            parent &&
            parent.type === "function" &&
            parent.value === "calc") ||
          (code === slash &&
            parent.type === "function" &&
            parent.value === "calc") ||
          (code === closeParentheses && balanced)
        )
      );
      token = value.slice(pos, next);

      if (openParentheses === code) {
        name = token;
      } else if (
        (uLower === token.charCodeAt(0) || uUpper === token.charCodeAt(0)) &&
        plus === token.charCodeAt(1) &&
        isUnicodeRange.test(token.slice(2))
      ) {
        tokens.push({
          type: "unicode-range",
          sourceIndex: pos,
          sourceEndIndex: next,
          value: token
        });
      } else {
        tokens.push({
          type: "word",
          sourceIndex: pos,
          sourceEndIndex: next,
          value: token
        });
      }

      pos = next;
    }
  }

  for (pos = stack.length - 1; pos; pos -= 1) {
    stack[pos].unclosed = true;
    stack[pos].sourceEndIndex = value.length;
  }

  return stack[0].nodes;
};


code:
function stringifyNode(node, custom) {
  var type = node.type;
  var value = node.value;
  var buf;
  var customResult;

  if (custom && (customResult = custom(node)) !== undefined) {
    return customResult;
  } else if (type === "word" || type === "space") {
    return value;
  } else if (type === "string") {
    buf = node.quote || "";
    return buf + value + (node.unclosed ? "" : buf);
  } else if (type === "comment") {
    return "/*" + value + (node.unclosed ? "" : "*/");
  } else if (type === "div") {
    return (node.before || "") + value + (node.after || "");
  } else if (Array.isArray(node.nodes)) {
    buf = stringify(node.nodes, custom);
    if (type !== "function") {
      return buf;
    }
    return (
      value +
      "(" +
      (node.before || "") +
      buf +
      (node.after || "") +
      (node.unclosed ? "" : ")")
    );
  }
  return value;
}

function stringify(nodes, custom) {
  var result, i;

  if (Array.isArray(nodes)) {
    result = "";
    for (i = nodes.length - 1; ~i; i -= 1) {
      result = stringifyNode(nodes[i], custom) + result;
    }
    return result;
  }
  return stringifyNode(nodes, custom);
}

module.exports = stringify;


code:
var minus = "-".charCodeAt(0);
var plus = "+".charCodeAt(0);
var dot = ".".charCodeAt(0);
var exp = "e".charCodeAt(0);
var EXP = "E".charCodeAt(0);

// Check if three code points would start a number
// https://www.w3.org/TR/css-syntax-3/#starts-with-a-number
function likeNumber(value) {
  var code = value.charCodeAt(0);
  var nextCode;

  if (code === plus || code === minus) {
    nextCode = value.charCodeAt(1);

    if (nextCode >= 48 && nextCode <= 57) {
      return true;
    }

    var nextNextCode = value.charCodeAt(2);

    if (nextCode === dot && nextNextCode >= 48 && nextNextCode <= 57) {
      return true;
    }

    return false;
  }

  if (code === dot) {
    nextCode = value.charCodeAt(1);

    if (nextCode >= 48 && nextCode <= 57) {
      return true;
    }

    return false;
  }

  if (code >= 48 && code <= 57) {
    return true;
  }

  return false;
}

// Consume a number
// https://www.w3.org/TR/css-syntax-3/#consume-number
module.exports = function(value) {
  var pos = 0;
  var length = value.length;
  var code;
  var nextCode;
  var nextNextCode;

  if (length === 0 || !likeNumber(value)) {
    return false;
  }

  code = value.charCodeAt(pos);

  if (code === plus || code === minus) {
    pos++;
  }

  while (pos < length) {
    code = value.charCodeAt(pos);

    if (code < 48 || code > 57) {
      break;
    }

    pos += 1;
  }

  code = value.charCodeAt(pos);
  nextCode = value.charCodeAt(pos + 1);

  if (code === dot && nextCode >= 48 && nextCode <= 57) {
    pos += 2;

    while (pos < length) {
      code = value.charCodeAt(pos);

      if (code < 48 || code > 57) {
        break;
      }

      pos += 1;
    }
  }

  code = value.charCodeAt(pos);
  nextCode = value.charCodeAt(pos + 1);
  nextNextCode = value.charCodeAt(pos + 2);

  if (
    (code === exp || code === EXP) &&
    ((nextCode >= 48 && nextCode <= 57) ||
      ((nextCode === plus || nextCode === minus) &&
        nextNextCode >= 48 &&
        nextNextCode <= 57))
  ) {
    pos += nextCode === plus || nextCode === minus ? 3 : 2;

    while (pos < length) {
      code = value.charCodeAt(pos);

      if (code < 48 || code > 57) {
        break;
      }

      pos += 1;
    }
  }

  return {
    number: value.slice(0, pos),
    unit: value.slice(pos)
  };
};


code:
module.exports = function walk(nodes, cb, bubble) {
  var i, max, node, result;

  for (i = 0, max = nodes.length; i < max; i += 1) {
    node = nodes[i];
    if (!bubble) {
      result = cb(node, i, nodes);
    }

    if (
      result !== false &&
      node.type === "function" &&
      Array.isArray(node.nodes)
    ) {
      walk(node.nodes, cb, bubble);
    }

    if (bubble) {
      cb(node, i, nodes);
    }
  }
};


postcss-value-parser

description: Transforms css values and at-rule params into the tree

lint:prettier: prettier "**/*.js" "**/*.ts" --list-different

lint:js: eslint . --cache

lint: yarn lint:js && yarn lint:prettier

pretest: yarn lint

test: tape test/*.js | tap-spec

*.js:
eslint
prettier --write
git add

pre-commit: lint-staged

author: Bogdan Chadkin <trysound@yandex.ru>

type: git

keywords: postcss value parser


code:
# PostCSS

PostCSS is a tool for transforming styles with JS plugins.
These plugins can lint your CSS, support variables and mixins,
transpile future CSS syntax, inline images, and more.

PostCSS is used by industry leaders including Wikipedia, Twitter, Alibaba,
and JetBrains. The [Autoprefixer] and [Stylelint] PostCSS plugins is one of the most popular CSS tools.

---

  Made at Evil Martians, product consulting for developer tools.

---

[Abstract Syntax Tree]: https://en.wikipedia.org/wiki/Abstract_syntax_tree
[Evil Martians]:        https://evilmartians.com/?utm_source=postcss
[Autoprefixer]:         https://github.com/postcss/autoprefixer
[Stylelint]:            https://stylelint.io/
[plugins]:              https://github.com/postcss/postcss#plugins

## Docs
Read full docs **[here](https://postcss.org/)**.


code:
import Container, {
  ContainerProps,
  ContainerWithChildren
} from './container.js'

declare namespace AtRule {
  export interface AtRuleRaws extends Record<string, unknown> {
    /**
     * The space symbols after the last child of the node to the end of the node.
     */
    after?: string

    /**
     * The space between the at-rule name and its parameters.
     */
    afterName?: string

    /**
     * The space symbols before the node. It also stores `*`
     * and `_` symbols before the declaration (IE hack).
     */
    before?: string

    /**
     * The symbols between the last parameter and `{` for rules.
     */
    between?: string

    /**
     * The rule’s selector with comments.
     */
    params?: {
      raw: string
      value: string
    }

    /**
     * Contains `true` if the last child has an (optional) semicolon.
     */
    semicolon?: boolean
  }

  export interface AtRuleProps extends ContainerProps {
    /** Name of the at-rule. */
    name: string
    /** Parameters following the name of the at-rule. */
    params?: number | string
    /** Information used to generate byte-to-byte equal node string as it was in the origin input. */
    raws?: AtRuleRaws
  }

  // eslint-disable-next-line @typescript-eslint/no-use-before-define
  export { AtRule_ as default }
}

/**
 * Represents an at-rule.
 *
 * ```js
 * Once (root, { AtRule }) {
 *   let media = new AtRule({ name: 'media', params: 'print' })
 *   media.append(…)
 *   root.append(media)
 * }
 * ```
 *
 * If it’s followed in the CSS by a `{}` block, this node will have
 * a nodes property representing its children.
 *
 * ```js
 * const root = postcss.parse('@charset "UTF-8"; @media print {}')
 *
 * const charset = root.first
 * charset.type  //=> 'atrule'
 * charset.nodes //=> undefined
 *
 * const media = root.last
 * media.nodes   //=> []
 * ```
 */
declare class AtRule_ extends Container {
  /**
   * The at-rule’s name immediately follows the `@`.
   *
   * ```js
   * const root  = postcss.parse('@media print {}')
   * const media = root.first
   * media.name //=> 'media'
   * ```
   */
  name: string
  /**
   * An array containing the layer’s children.
   *
   * ```js
   * const root = postcss.parse('@layer example { a { color: black } }')
   * const layer = root.first
   * layer.nodes.length           //=> 1
   * layer.nodes[0].selector      //=> 'a'
   * ```
   *
   * Can be `undefinded` if the at-rule has no body.
   *
   * ```js
   * const root = postcss.parse('@layer a, b, c;')
   * const layer = root.first
   * layer.nodes //=> undefined
   * ```
   */
  nodes: Container['nodes']
  /**
   * The at-rule’s parameters, the values that follow the at-rule’s name
   * but precede any `{}` block.
   *
   * ```js
   * const root  = postcss.parse('@media print, screen {}')
   * const media = root.first
   * media.params //=> 'print, screen'
   * ```
   */
  params: string
  parent: ContainerWithChildren | undefined

  raws: AtRule.AtRuleRaws

  type: 'atrule'

  constructor(defaults?: AtRule.AtRuleProps)
  assign(overrides: AtRule.AtRuleProps | object): this
  clone(overrides?: Partial<AtRule.AtRuleProps>): AtRule
  cloneAfter(overrides?: Partial<AtRule.AtRuleProps>): AtRule
  cloneBefore(overrides?: Partial<AtRule.AtRuleProps>): AtRule
}

declare class AtRule extends AtRule_ {}

export = AtRule


code:
'use strict'

let Container = require('./container')

class AtRule extends Container {
  constructor(defaults) {
    super(defaults)
    this.type = 'atrule'
  }

  append(...children) {
    if (!this.proxyOf.nodes) this.nodes = []
    return super.append(...children)
  }

  prepend(...children) {
    if (!this.proxyOf.nodes) this.nodes = []
    return super.prepend(...children)
  }
}

module.exports = AtRule
AtRule.default = AtRule

Container.registerAtRule(AtRule)


code:
import Container from './container.js'
import Node, { NodeProps } from './node.js'

declare namespace Comment {
  export interface CommentRaws extends Record<string, unknown> {
    /**
     * The space symbols before the node.
     */
    before?: string

    /**
     * The space symbols between `/*` and the comment’s text.
     */
    left?: string

    /**
     * The space symbols between the comment’s text.
     */
    right?: string
  }

  export interface CommentProps extends NodeProps {
    /** Information used to generate byte-to-byte equal node string as it was in the origin input. */
    raws?: CommentRaws
    /** Content of the comment. */
    text: string
  }

  // eslint-disable-next-line @typescript-eslint/no-use-before-define
  export { Comment_ as default }
}

/**
 * It represents a class that handles
 * [CSS comments](https://developer.mozilla.org/en-US/docs/Web/CSS/Comments)
 *
 * ```js
 * Once (root, { Comment }) {
 *   const note = new Comment({ text: 'Note: …' })
 *   root.append(note)
 * }
 * ```
 *
 * Remember that CSS comments inside selectors, at-rule parameters,
 * or declaration values will be stored in the `raws` properties
 * explained above.
 */
declare class Comment_ extends Node {
  parent: Container | undefined
  raws: Comment.CommentRaws
  /**
   * The comment's text.
   */
  text: string

  type: 'comment'

  constructor(defaults?: Comment.CommentProps)
  assign(overrides: Comment.CommentProps | object): this
  clone(overrides?: Partial<Comment.CommentProps>): Comment
  cloneAfter(overrides?: Partial<Comment.CommentProps>): Comment
  cloneBefore(overrides?: Partial<Comment.CommentProps>): Comment
}

declare class Comment extends Comment_ {}

export = Comment


code:
'use strict'

let Node = require('./node')

class Comment extends Node {
  constructor(defaults) {
    super(defaults)
    this.type = 'comment'
  }
}

module.exports = Comment
Comment.default = Comment


code:
import AtRule from './at-rule.js'
import Comment from './comment.js'
import Declaration from './declaration.js'
import Node, { ChildNode, ChildProps, NodeProps } from './node.js'
import Rule from './rule.js'

declare namespace Container {
  export class ContainerWithChildren<
    Child extends Node = ChildNode
  > extends Container_<Child> {
    nodes: Child[]
  }

  export interface ValueOptions {
    /**
     * String that’s used to narrow down values and speed up the regexp search.
     */
    fast?: string

    /**
     * An array of property names.
     */
    props?: string[]
  }

  export interface ContainerProps extends NodeProps {
    nodes?: (ChildNode | ChildProps)[]
  }

  // eslint-disable-next-line @typescript-eslint/no-use-before-define
  export { Container_ as default }
}

/**
 * The `Root`, `AtRule`, and `Rule` container nodes
 * inherit some common methods to help work with their children.
 *
 * Note that all containers can store any content. If you write a rule inside
 * a rule, PostCSS will parse it.
 */
declare abstract class Container_<Child extends Node = ChildNode> extends Node {
  /**
   * An array containing the container’s children.
   *
   * ```js
   * const root = postcss.parse('a { color: black }')
   * root.nodes.length           //=> 1
   * root.nodes[0].selector      //=> 'a'
   * root.nodes[0].nodes[0].prop //=> 'color'
   * ```
   */
  nodes: Child[] | undefined

  /**
   * Inserts new nodes to the end of the container.
   *
   * ```js
   * const decl1 = new Declaration({ prop: 'color', value: 'black' })
   * const decl2 = new Declaration({ prop: 'background-color', value: 'white' })
   * rule.append(decl1, decl2)
   *
   * root.append({ name: 'charset', params: '"UTF-8"' })  // at-rule
   * root.append({ selector: 'a' })                       // rule
   * rule.append({ prop: 'color', value: 'black' })       // declaration
   * rule.append({ text: 'Comment' })                     // comment
   *
   * root.append('a {}')
   * root.first.append('color: black; z-index: 1')
   * ```
   *
   * @param nodes New nodes.
   * @return This node for methods chain.
   */
  append(
    ...nodes: (
      | ChildProps
      | ChildProps[]
      | Node
      | Node[]
      | string
      | string[]
      | undefined
    )[]
  ): this

  assign(overrides: Container.ContainerProps | object): this
  clone(overrides?: Partial<Container.ContainerProps>): Container<Child>
  cloneAfter(overrides?: Partial<Container.ContainerProps>): Container<Child>
  cloneBefore(overrides?: Partial<Container.ContainerProps>): Container<Child>

  /**
   * Iterates through the container’s immediate children,
   * calling `callback` for each child.
   *
   * Returning `false` in the callback will break iteration.
   *
   * This method only iterates through the container’s immediate children.
   * If you need to recursively iterate through all the container’s descendant
   * nodes, use `Container#walk`.
   *
   * Unlike the for `{}`-cycle or `Array#forEach` this iterator is safe
   * if you are mutating the array of child nodes during iteration.
   * PostCSS will adjust the current index to match the mutations.
   *
   * ```js
   * const root = postcss.parse('a { color: black; z-index: 1 }')
   * const rule = root.first
   *
   * for (const decl of rule.nodes) {
   *   decl.cloneBefore({ prop: '-webkit-' + decl.prop })
   *   // Cycle will be infinite, because cloneBefore moves the current node
   *   // to the next index
   * }
   *
   * rule.each(decl => {
   *   decl.cloneBefore({ prop: '-webkit-' + decl.prop })
   *   // Will be executed only for color and z-index
   * })
   * ```
   *
   * @param callback Iterator receives each node and index.
   * @return Returns `false` if iteration was broke.
   */
  each(
    callback: (node: Child, index: number) => false | void
  ): false | undefined

  /**
   * Returns `true` if callback returns `true`
   * for all of the container’s children.
   *
   * ```js
   * const noPrefixes = rule.every(i => i.prop[0] !== '-')
   * ```
   *
   * @param condition Iterator returns true or false.
   * @return Is every child pass condition.
   */
  every(
    condition: (node: Child, index: number, nodes: Child[]) => boolean
  ): boolean
  /**
   * Returns a `child`’s index within the `Container#nodes` array.
   *
   * ```js
   * rule.index( rule.nodes[2] ) //=> 2
   * ```
   *
   * @param child Child of the current container.
   * @return Child index.
   */
  index(child: Child | number): number

  /**
   * Insert new node after old node within the container.
   *
   * @param oldNode Child or child’s index.
   * @param newNode New node.
   * @return This node for methods chain.
   */
  insertAfter(
    oldNode: Child | number,
    newNode:
      | Child
      | Child[]
      | ChildProps
      | ChildProps[]
      | string
      | string[]
      | undefined
  ): this
  /**
   * Insert new node before old node within the container.
   *
   * ```js
   * rule.insertBefore(decl, decl.clone({ prop: '-webkit-' + decl.prop }))
   * ```
   *
   * @param oldNode Child or child’s index.
   * @param newNode New node.
   * @return This node for methods chain.
   */
  insertBefore(
    oldNode: Child | number,
    newNode:
      | Child
      | Child[]
      | ChildProps
      | ChildProps[]
      | string
      | string[]
      | undefined
  ): this

  /**
   * Traverses the container’s descendant nodes, calling callback
   * for each comment node.
   *
   * Like `Container#each`, this method is safe
   * to use if you are mutating arrays during iteration.
   *
   * ```js
   * root.walkComments(comment => {
   *   comment.remove()
   * })
   * ```
   *
   * @param callback Iterator receives each node and index.
   * @return Returns `false` if iteration was broke.
   */

  /**
   * Inserts new nodes to the start of the container.
   *
   * ```js
   * const decl1 = new Declaration({ prop: 'color', value: 'black' })
   * const decl2 = new Declaration({ prop: 'background-color', value: 'white' })
   * rule.prepend(decl1, decl2)
   *
   * root.append({ name: 'charset', params: '"UTF-8"' })  // at-rule
   * root.append({ selector: 'a' })                       // rule
   * rule.append({ prop: 'color', value: 'black' })       // declaration
   * rule.append({ text: 'Comment' })                     // comment
   *
   * root.append('a {}')
   * root.first.append('color: black; z-index: 1')
   * ```
   *
   * @param nodes New nodes.
   * @return This node for methods chain.
   */
  prepend(
    ...nodes: (
      | ChildProps
      | ChildProps[]
      | Node
      | Node[]
      | string
      | string[]
      | undefined
    )[]
  ): this
  /**
   * Add child to the end of the node.
   *
   * ```js
   * rule.push(new Declaration({ prop: 'color', value: 'black' }))
   * ```
   *
   * @param child New node.
   * @return This node for methods chain.
   */
  push(child: Child): this

  /**
   * Removes all children from the container
   * and cleans their parent properties.
   *
   * ```js
   * rule.removeAll()
   * rule.nodes.length //=> 0
   * ```
   *
   * @return This node for methods chain.
   */
  removeAll(): this

  /**
   * Removes node from the container and cleans the parent properties
   * from the node and its children.
   *
   * ```js
   * rule.nodes.length  //=> 5
   * rule.removeChild(decl)
   * rule.nodes.length  //=> 4
   * decl.parent        //=> undefined
   * ```
   *
   * @param child Child or child’s index.
   * @return This node for methods chain.
   */
  removeChild(child: Child | number): this

  replaceValues(
    pattern: RegExp | string,
    replaced: { (substring: string, ...args: any[]): string } | string
  ): this

  /**
   * Passes all declaration values within the container that match pattern
   * through callback, replacing those values with the returned result
   * of callback.
   *
   * This method is useful if you are using a custom unit or function
   * and need to iterate through all values.
   *
   * ```js
   * root.replaceValues(/\d+rem/, { fast: 'rem' }, string => {
   *   return 15 * parseInt(string) + 'px'
   * })
   * ```
   *
   * @param pattern      Replace pattern.
   * @param {object} opts                Options to speed up the search.
   * @param callback   String to replace pattern or callback
   *                                     that returns a new value. The callback
   *                                     will receive the same arguments
   *                                     as those passed to a function parameter
   *                                     of `String#replace`.
   * @return This node for methods chain.
   */
  replaceValues(
    pattern: RegExp | string,
    options: Container.ValueOptions,
    replaced: { (substring: string, ...args: any[]): string } | string
  ): this

  /**
   * Returns `true` if callback returns `true` for (at least) one
   * of the container’s children.
   *
   * ```js
   * const hasPrefix = rule.some(i => i.prop[0] === '-')
   * ```
   *
   * @param condition Iterator returns true or false.
   * @return Is some child pass condition.
   */
  some(
    condition: (node: Child, index: number, nodes: Child[]) => boolean
  ): boolean

  /**
   * Traverses the container’s descendant nodes, calling callback
   * for each node.
   *
   * Like container.each(), this method is safe to use
   * if you are mutating arrays during iteration.
   *
   * If you only need to iterate through the container’s immediate children,
   * use `Container#each`.
   *
   * ```js
   * root.walk(node => {
   *   // Traverses all descendant nodes.
   * })
   * ```
   *
   * @param callback Iterator receives each node and index.
   * @return  Returns `false` if iteration was broke.
   */
  walk(
    callback: (node: ChildNode, index: number) => false | void
  ): false | undefined

  /**
   * Traverses the container’s descendant nodes, calling callback
   * for each at-rule node.
   *
   * If you pass a filter, iteration will only happen over at-rules
   * that have matching names.
   *
   * Like `Container#each`, this method is safe
   * to use if you are mutating arrays during iteration.
   *
   * ```js
   * root.walkAtRules(rule => {
   *   if (isOld(rule.name)) rule.remove()
   * })
   *
   * let first = false
   * root.walkAtRules('charset', rule => {
   *   if (!first) {
   *     first = true
   *   } else {
   *     rule.remove()
   *   }
   * })
   * ```
   *
   * @param name     String or regular expression to filter at-rules by name.
   * @param callback Iterator receives each node and index.
   * @return Returns `false` if iteration was broke.
   */
  walkAtRules(
    nameFilter: RegExp | string,
    callback: (atRule: AtRule, index: number) => false | void
  ): false | undefined

  walkAtRules(
    callback: (atRule: AtRule, index: number) => false | void
  ): false | undefined
  walkComments(
    callback: (comment: Comment, indexed: number) => false | void
  ): false | undefined

  walkComments(
    callback: (comment: Comment, indexed: number) => false | void
  ): false | undefined

  /**
   * Traverses the container’s descendant nodes, calling callback
   * for each declaration node.
   *
   * If you pass a filter, iteration will only happen over declarations
   * with matching properties.
   *
   * ```js
   * root.walkDecls(decl => {
   *   checkPropertySupport(decl.prop)
   * })
   *
   * root.walkDecls('border-radius', decl => {
   *   decl.remove()
   * })
   *
   * root.walkDecls(/^background/, decl => {
   *   decl.value = takeFirstColorFromGradient(decl.value)
   * })
   * ```
   *
   * Like `Container#each`, this method is safe
   * to use if you are mutating arrays during iteration.
   *
   * @param prop     String or regular expression to filter declarations
   *                 by property name.
   * @param callback Iterator receives each node and index.
   * @return Returns `false` if iteration was broke.
   */
  walkDecls(
    propFilter: RegExp | string,
    callback: (decl: Declaration, index: number) => false | void
  ): false | undefined

  walkDecls(
    callback: (decl: Declaration, index: number) => false | void
  ): false | undefined

  /**
   * Traverses the container’s descendant nodes, calling callback
   * for each rule node.
   *
   * If you pass a filter, iteration will only happen over rules
   * with matching selectors.
   *
   * Like `Container#each`, this method is safe
   * to use if you are mutating arrays during iteration.
   *
   * ```js
   * const selectors = []
   * root.walkRules(rule => {
   *   selectors.push(rule.selector)
   * })
   * console.log(`Your CSS uses ${ selectors.length } selectors`)
   * ```
   *
   * @param selector String or regular expression to filter rules by selector.
   * @param callback Iterator receives each node and index.
   * @return Returns `false` if iteration was broke.
   */
  walkRules(
    selectorFilter: RegExp | string,
    callback: (rule: Rule, index: number) => false | void
  ): false | undefined
  walkRules(
    callback: (rule: Rule, index: number) => false | void
  ): false | undefined
  /**
   * The container’s first child.
   *
   * ```js
   * rule.first === rules.nodes[0]
   * ```
   */
  get first(): Child | undefined
  /**
   * The container’s last child.
   *
   * ```js
   * rule.last === rule.nodes[rule.nodes.length - 1]
   * ```
   */
  get last(): Child | undefined
}

declare class Container<
  Child extends Node = ChildNode
> extends Container_<Child> {}

export = Container