2023-08-02 18:39:57 +00:00
|
|
|
// @ts-check
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A node path is an array of indices that can traverse a Node tree.
|
|
|
|
*
|
|
|
|
* For example, given the following tree:
|
|
|
|
*
|
|
|
|
* ```javascript
|
|
|
|
* {
|
|
|
|
* name: "top",
|
|
|
|
* children: [
|
|
|
|
* { name: "first" },
|
|
|
|
* { name: "second", children: [{ name: "grandchild" }] },
|
|
|
|
* ],
|
|
|
|
* }
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* `[]` is "top", `[0]` is "first", `[1]` is "second", and `[1, 0]` is "grandchild".
|
|
|
|
*
|
|
|
|
* @typedef {number[]} NodePath
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {unknown} value
|
|
|
|
* @returns {null | NodePath} The parsed node path, or null if invalid.
|
|
|
|
*/
|
|
|
|
export const parse = (value) => {
|
|
|
|
if (typeof value !== "string") return null;
|
2023-08-02 19:49:25 +00:00
|
|
|
if (!value) return [];
|
|
|
|
return value.split(",").map((str) => {
|
|
|
|
const result = parseInt(str, 10);
|
|
|
|
if (Number.isFinite(result)) return result;
|
|
|
|
throw new Error(`Invalid node path: ${value}`);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {NodePath} a
|
|
|
|
* @param {NodePath} b
|
|
|
|
* @returns {boolean}
|
|
|
|
*/
|
|
|
|
export const isEqualTo = (a, b) => a.length === b.length && isSupersetOf(a, b);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {NodePath} smaller
|
|
|
|
* @param {NodePath} bigger
|
|
|
|
* @returns {boolean}
|
|
|
|
*/
|
|
|
|
export const isSupersetOf = (smaller, bigger) => {
|
|
|
|
for (let i = 0; i < smaller.length; i++) {
|
|
|
|
if (smaller[i] !== bigger[i]) return false;
|
|
|
|
}
|
|
|
|
return true;
|
2023-08-02 18:39:57 +00:00
|
|
|
};
|