diff --git a/package-lock.json b/package-lock.json index bb6106a..0353020 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,15 @@ { "name": "@thefarce/loom", - "version": "0.0.2", + "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@thefarce/loom", - "version": "0.0.2", + "version": "0.1.0", "dependencies": { "unist-util-is": "^6.0.0", + "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1" }, "devDependencies": { @@ -4527,6 +4528,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-visit-parents": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", diff --git a/package.json b/package.json index 86008e8..f9f5a5f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@thefarce/loom", - "version": "0.1.0", + "version": "0.1.1", "description": "A module for weaving form data with content data", "type": "module", "main": "index.mjs", @@ -16,6 +16,7 @@ }, "dependencies": { "unist-util-is": "^6.0.0", + "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1" } } diff --git a/src/transform.mjs b/src/transform.mjs index 22e3928..3dcb312 100644 --- a/src/transform.mjs +++ b/src/transform.mjs @@ -4,7 +4,7 @@ * (ASTs). */ -import { visitParents } from 'unist-util-visit-parents'; +import { visit, SKIP } from 'unist-util-visit'; import { isAstNode } from './util.mjs'; import { is } from 'unist-util-is'; @@ -25,7 +25,10 @@ export function transform (ast, ...transformers) { // AST and stop processing it. If the function returns an AST node, // replace the node with that AST node and continue processing with the // new node. - visitParents(tree, (node, ancestors) => { + visit(tree, (node, index, parent) => { + let replaced = false; + let removed = false; + let transformed = transformers.reduce((workingNode, transformer) => { // If the current node is null, just skip any further processing. if (workingNode === null) { @@ -35,10 +38,11 @@ export function transform (ast, ...transformers) { // Process the working node through the current function. Make sure // the transformer function knows not only the node but also its // ancestors. - let result = transformer(workingNode, ancestors); + let result = transformer(workingNode); // If the function returned null, just skip any further processing. if (result === null) { + removed = true; return null; } // If the function returned 'undefined', this means that there's no @@ -51,6 +55,7 @@ export function transform (ast, ...transformers) { // If the function returned an AST node, we replace the working node // with that AST node and continue processing with the new node. else if (isAstNode(result)) { + replaced = true; return result; } @@ -58,37 +63,19 @@ export function transform (ast, ...transformers) { throw new Error(`Invalid transformer result: ${JSON.stringify(result)}`); }, node); - let parent = ancestors[ancestors.length - 1]; - - if (!parent) { - return; + // If we need to replace the node, do it here. + if (replaced && transformed && parent) { + parent.children.splice(index, 1, transformed); } - // Loop through the first most recent ancestor and replace the current - // node with the transformed node. If transformed is null, just delete - // the current node. - if (transformed === null) { - let index = -1; - parent.children.forEach((child, i) => { - if (is(child, node)) { - index = i; - } - }) - + if (removed && parent) { parent.children.splice(index, 1); + // This is special magick required by unist. It hints to the visit + // function that we removed this node from the tree, so skip it when + // walking further.. + return [SKIP, index]; } - // If the transformed node is the same as the current node, do nothing. - else if (is(node, transformed)) { - // do nothing - } - // Finally, replace the current node with the transformed node. - else { - parent.children.forEach((child, index) => { - if (is(child, node)) { - parent.children[index] = transformed; - } - }); - } + }); return tree;