562 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			562 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import { fileURLToPath as __cjs_fileURLToPath } from 'node:url';
 | |
| import { dirname as __cjs_dirname } from 'node:path';
 | |
| import { createRequire as __cjs_createRequire } from 'node:module';
 | |
| 
 | |
| const __filename = __cjs_fileURLToPath(import.meta.url);
 | |
| const __dirname = __cjs_dirname(__filename);
 | |
| const require = __cjs_createRequire(import.meta.url);
 | |
| const __require = require;
 | |
| 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;
 | |
| 
 | |
| var parse$1 = 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;
 | |
| };
 | |
| 
 | |
| var walk$1 = 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);
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| 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$1(node.nodes, custom);
 | |
|     if (type !== "function") {
 | |
|       return buf;
 | |
|     }
 | |
|     return (
 | |
|       value +
 | |
|       "(" +
 | |
|       (node.before || "") +
 | |
|       buf +
 | |
|       (node.after || "") +
 | |
|       (node.unclosed ? "" : ")")
 | |
|     );
 | |
|   }
 | |
|   return value;
 | |
| }
 | |
| 
 | |
| function stringify$1(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);
 | |
| }
 | |
| 
 | |
| var stringify_1 = stringify$1;
 | |
| 
 | |
| var unit;
 | |
| var hasRequiredUnit;
 | |
| 
 | |
| function requireUnit () {
 | |
| 	if (hasRequiredUnit) return unit;
 | |
| 	hasRequiredUnit = 1;
 | |
| 	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
 | |
| 	unit = 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)
 | |
| 	  };
 | |
| 	};
 | |
| 	return unit;
 | |
| }
 | |
| 
 | |
| var parse = parse$1;
 | |
| var walk = walk$1;
 | |
| var stringify = stringify_1;
 | |
| 
 | |
| 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 = requireUnit();
 | |
| 
 | |
| ValueParser.walk = walk;
 | |
| 
 | |
| ValueParser.stringify = stringify;
 | |
| 
 | |
| var lib = ValueParser;
 | |
| 
 | |
| export { lib as l };
 |