UNPKG

expand-value

Version:

Get deeply nested values from an object, like dot-prop and get-value, but with support for advanced features like bracket-notation and more.

297 lines (291 loc) 7.64 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); // src/nodes/Location.ts var Position = class { static { __name(this, "Position"); } index; line; col; constructor(loc) { this.index = loc.index; this.line = loc.line; this.col = loc.col; } }; var Location = class { static { __name(this, "Location"); } start; end; constructor(start, end) { this.start = start; this.end = end; } slice(input) { return input.slice(...this.range); } get range() { return [this.start.index, this.end.index]; } get lines() { return [this.start.line, this.end.line]; } }; var location = /* @__PURE__ */ __name((loc) => { const start = new Position(loc); return (node) => { node.loc = new Location(start, new Position(loc)); return node; }; }, "location"); location.Position = Position; location.Location = Location; location.location = location; // src/utils.ts import isNumber from "is-number"; import { Segmenter } from "intl-segmenter"; var { defineProperty } = Reflect; var isObject = /* @__PURE__ */ __name((val) => val && typeof val === "object" && !Array.isArray(val), "isObject"); var define = /* @__PURE__ */ __name((node, key, value) => { defineProperty(node, key, { configurable: true, enumerable: false, writable: true, value }); }, "define"); // src/nodes/Node.ts var Node = class { static { __name(this, "Node"); } type; value; output; symbol; parent; constructor(node) { this.type = node.type; this.value = node.value || ""; if (node.output != null && node.output !== "") { this.output = node.output; } if (node.symbol) { this.symbol = node.symbol; } define(this, "alt", node.alt); define(this, "match", node.match); define(this, "loc", node.loc); } get siblings() { return this.parent?.nodes || []; } }; // src/nodes/Block.ts var Block = class extends Node { static { __name(this, "Block"); } nodes; constructor(node) { super(node); this.nodes = node.nodes || []; } append(input) { this.parent && this.parent.append(input); this.output = this.output || ""; this.output += input; } push(node) { define(node, "parent", this); this.nodes.push(node); } }; // src/nodes/Token.ts var { defineProperty: defineProperty2 } = Reflect; var Token = class { static { __name(this, "Token"); } type; value; loc; match; constructor(token) { this.type = token.type; this.value = token.value; defineProperty2(this, "loc", { value: token.loc, writable: true }); defineProperty2(this, "match", { value: token.match }); } }; // src/parse.ts var QUOTED_STRING = /^(['"`])((?:\\.|(?!\1)[\s\S])*?)(\1)/; var IDENT_DOT = /^([a-zA-Z_][-a-zA-Z0-9_.]*(?<!\.))/; var IDENT = /^([a-zA-Z_$][a-zA-Z0-9_$-]*(?<!-))/; var NUMBER = /^(-?[0-9]+(?:\.[0-9]+)?|-?Infinity|NaN)/; var RANGE = /^\.\.(?=[0-9a-z])/i; var SYMBOL = /^Symbol\((.*?)\)/; var parse = /* @__PURE__ */ __name((input = "", options = {}) => { if (!isObject(options)) options = {}; const loc = { index: 0, line: 1, col: 0, row: 1 }; let pos = location(loc); const str = String(input); const ast = new Block({ type: "root" }); ast.output = ""; const stack = [ast]; const stash = []; const tokens = []; let remaining = str; let block = ast; let token; let match; let prev; let separator = /^\./; let IDENTITY = IDENT; if (typeof options.separator === "string") { separator = new RegExp(`^\\${options.separator.replace(/^[\\^]+/, "")}`); IDENTITY = IDENT_DOT; } const eos = /* @__PURE__ */ __name(() => remaining === void 0 || remaining === "", "eos"); const scan = /* @__PURE__ */ __name((regex, type = "text") => { if (match = regex.exec(remaining)) { consume(match[0]); return new Token({ type, value: match[0], match }); } }, "scan"); const updateLocation = /* @__PURE__ */ __name((value, len) => { const i = value.lastIndexOf("\n"); loc.index += len; loc.col = ~i ? len - i : loc.col + len; loc.row += Math.max(0, value.split("\n").length - 1); }, "updateLocation"); const consume = /* @__PURE__ */ __name((value, len = value.length) => { updateLocation(value, len); remaining = remaining.slice(len); return value; }, "consume"); const drop = /* @__PURE__ */ __name(() => { if (stash.length) { block.push(stash.shift()); } }, "drop"); const shouldPush = /* @__PURE__ */ __name((node) => { return node.type !== "newline" || options.newlines !== false; }, "shouldPush"); const push = /* @__PURE__ */ __name((node) => { pos(node); if (prev?.type === "ident" && node.type === "ident") { block.append(node.output || node.match[0]); prev.value += node.value; return; } if (!shouldPush(node)) return; block.push(node); if (node.nodes) { stack.push(node); block = node; } else { block.append(node.output || node.match[0]); tokens.push(node); } pos = location(loc); prev = node; if (block.type === "root") { drop(); } }, "push"); const pop = /* @__PURE__ */ __name(() => { const parent = stack.pop(); block = stack[stack.length - 1]; return parent; }, "pop"); const advance = /* @__PURE__ */ __name(() => { if (token = scan(/^\\+/, "escaped")) { if (token.value.length % 2 === 1) { token.value += consume(remaining[0]); } if (token.value === "\\.") { token.type = "ident"; token.value = "."; token.output = "\\."; } push(new Node(token)); return; } if (token = scan(SYMBOL, "symbol")) { token.value = token.match[1]; token.symbol = Symbol.for(token.value); push(new Node(token)); return; } if (token = scan(/^\[/, "left_bracket")) { token.index = tokens.length; push(new Block({ type: "bracket" })); push(new Node(token)); return; } if (token = scan(/^\]/, "right_bracket")) { push(new Node(token)); if (block.type === "bracket") { pop(); } return; } if (token = scan(/^\(/, "left_paren")) { token.index = tokens.length; push(new Block({ type: "paren" })); push(new Node(token)); return; } if (token = scan(/^\)/, "right_paren")) { push(new Node(token)); if (block.type === "paren") { pop(); } return; } if (block.type === "bracket" && (token = scan(RANGE, "range"))) { push(new Node(token)); return; } if (!options.separator && (token = scan(separator, "separator"))) { push(new Node(token)); return; } if (token = scan(/^[0-9]+/, "integer")) { push(new Node(token)); return; } if (token = scan(IDENTITY, "ident")) { push(new Node(token)); return; } if (options.separator && options.separator !== ".") { if (token = scan(separator, "separator")) { push(new Node(token)); return; } } if (token = scan(QUOTED_STRING, "quoted")) { push(new Node(token)); return; } if (token = scan(NUMBER, "number")) { if (token.value === "-0") { token.alt = "0"; } push(new Node(token)); return; } push(new Node(scan(/^(.)/, "text"))); }, "advance"); while (!eos()) advance(); return { ast, tokens, output: ast.output }; }, "parse"); export { parse }; //# sourceMappingURL=parse.mjs.map