als-replace-between
als-replace-between
is a library designed to simplify the process of replacing content within nested structures. This tool is particularly useful in scenarios where you need to manipulate text or data that is deeply nested or structured in a hierarchical manner, such as HTML, XML, or any string-based nested data. It provides an efficient way to navigate through these structures and apply changes exactly where needed. The library is available for both browser and Node.js environments.
Installation
To install als-replace-between
, use the following npm command:
npm i als-replace-between
This command will download and install the library into your project's node_modules
directory.
Importing
To use als-replace-between
in your project, you need to import it:
In Node.js
const ReplaceBetween = require('als-replace-between');
In the Browser
Include the library directly in your HTML through a <script>
tag:
<script src="node_modules/als-replace-between/replace-between.js"></script>
This script tag will load the library, and you will be able to access ReplaceBetween
globally in your browser scripts.
Quick Start
This section provides a basic guide to quickly start using the als-replace-between
library in your project. After installing and importing the library as described above, you can immediately begin transforming your nested text or data structures.
Basic Usage Example
Here is a simple example to demonstrate how you can use ReplaceBetween
to add CSS classes to HTML elements based on their content:
const htmlContent = "<div>Hello, <span>user</span>!</div>";
const transformer = new ReplaceBetween(htmlContent, /<span>/, /<\/span>/);
transformer.walkNodes([node => {
if (node.inner.trim() === 'user') {
node.open = '<span class="username">';
}
}]);
console.log(transformer.outer);
In this example, ReplaceBetween
is initialized with HTML content and modifies the <span>
tag to include a CSS class if its content matches the string "user". The outer
getter is then used to retrieve and display the modified HTML content.
Steps to Modify Content
- Initialize ReplaceBetween: Create a new instance by passing the text or data, along with the start and end delimiters (regular expressions) to identify the segments you want to manipulate.
- Apply Modifications: Use the
walk
, walkNodes
, or walkTextNodes
methods to apply modifications to the identified segments. - Retrieve Modified Content: Use the
outer
or inner
getters to retrieve the modified content for further use or output.
With these simple steps, you can effectively manipulate nested and structured text or data according to your specific needs.
Advanced Usage Example
This example demonstrates how to use als-replace-between
to dynamically replace template variables within an HTML structure. This is particularly useful for templating purposes where you need to inject dynamic content based on some data source.
Example Setup
Let's assume you have the following user object and HTML content with placeholders for user information:
const user = {name: 'Alex', age: 15};
const text = `
<div>
<h1>User</h1>
<div>Name: <span> {{ name }} !</span></div>
<div>Age: <span> {{ age }} !</span></div>
</div>
`;
Dynamic Replacement
To replace the placeholders {{ name }}
and {{ age }}
with actual user data, we use ReplaceBetween
as follows:
const transformer = new ReplaceBetween(text, /<\w[\s\S]*?>/g, /<\/\w[\s\S]*?>/g);
transformer.walkTextNodes([
(textNode) => {
if (textNode.outer.trim().length === 0) return;
const varReplacer = new ReplaceBetween(textNode.outer, /\{\{/, /\}\}/);
if (varReplacer.children.length === 0) return;
varReplacer.walkTextNodes([t => {
t.outer = user[t.outer.trim()] || t.outer;
}]);
varReplacer.walkNodes([t => {
t.open = '';
t.close = '';
}]);
textNode.outer = varReplacer.outer;
}
]);
console.log(transformer.outer);
Result
After executing the above code, the placeholders in the HTML content are replaced with actual user data, resulting in the following output:
<div>
<h1>User</h1>
<div>Name: <span> Alex !</span></div>
<div>Age: <span> 15 !</span></div>
</div>
This approach can be adapted to any data-driven templating task where you need to interpolate strings within complex structures.
Constructor
The ReplaceBetween
constructor is designed to parse and manipulate nested structures based on the provided start and end patterns. It accepts the following parameters:
content
(String): The string content that needs to be processed.startR
(RegExp): A regular expression defining the start of a segment to target for replacement or manipulation.endR
(RegExp): A regular expression defining the end of a segment.
Behavior
When an instance of ReplaceBetween
is created, it immediately parses the content
string to identify all segments that match the defined startR
and endR
patterns. It builds a tree-like structure where each matched segment is a node. This structure includes not only the content within the matches but also any text outside of these matches as part of the before
and after
properties:
before
: Contains all content before the first matched segment.after
: Contains all content after the last matched segment.children
: An array of nodes representing the nested or sequential segments found between the provided startR
and endR
.
The tree construction allows for complex nested and hierarchical manipulations using the provided methods like walk
.
Classes
ReplaceBetween
utilizes three types of classes to manage and manipulate the structure:
-
ReplaceBetween: The main class that includes:
before
: Text before the first matched segment.after
: Text after the last matched segment.children
: An array of Node
or TextNode
objects representing structured content.get outer()
: A getter that returns the full content includes the before
, children
, and after
.get inner()
: A getter that returns the full content without before
and after
.set inner(value)
: replace all children with single TextNode including valueset inner(value)
: sets inner and assigns empty string to before and afterwalk([functions])
: A method that applies one or more modifier functions to every node and text node within the structure.walkNodes([functions])
: Same as walk
, but only for nodes.walkTextNodes([functions])
: Same as walk
, but only for text nodes.
-
Node: Represents a segment of content with potential nested structure. Each Node
includes:
children
: An array of child nodes that may contain further nested Node
or TextNode
objects.outer
: Getter that returns the complete content of the node including all children.inner
: Getter that returns only the content inside this node, excluding any wrappers or nested structures.set inner(value)
: replace all children with single TextNode including valueset inner(value)
: sets inner and assigns empty string to open and closeprev()
: A getter for the previous sibling node.next()
: A getter for the next sibling node.walk
,walkNodes
,walkTextNodes
- same as in ReplaceBetween
-
TextNode: Represents plain text within or between nodes. It includes:
outer
: The text content of this node.prev()
: A getter for the previous sibling node or text node.next()
: A getter for the next sibling node or text node.
Each class is designed to facilitate specific types of interactions within the parsed content, enabling detailed and flexible manipulation of the text or data structure.
Tree Example
const text = "Before text<tag>First<tag>some child</tag></tag> Between tags <tag>Second</tag><tag>Third</tag>After text";
const tree = new ReplaceBetween(text,/\<\w[\s\S]*?\>/,/\<\/\w[\s\S]*?\>/)
This example constructs a parsed tree structure of the provided text. Each tag and text segment is represented as a node in the tree:
const self = ReplaceBetween {
content:"Before text<tag>First<tag>some child</tag></tag> Between tags <tag>Second</tag><tag>Third</tag>After text",
startR:new RegExp("\<\w[\s\S]*?\>", ""),
endR:new RegExp("\<\/\w[\s\S]*?\>", ""),
children:[
Node {
parent:self,
index:0,
root:self,
children:[
TextNode {
outer:"First",
parent:self.children[0],
index:0,
open:"",
close:""
},
Node {
parent:self.children[0],
index:1,
root:self,
children:[
TextNode {
outer:"some child",
parent:self.children[0].children[1],
index:0,
open:"",
close:""
}
],
open:"<tag>",
close:"</tag>"
}
],
open:"<tag>",
close:"</tag>"
},
TextNode {
outer:" Between tags ",
parent:self,
index:1,
open:"",
close:""
},
Node {
parent:self,
index:2,
root:self,
children:[
{
outer:"Second",
parent:self.children[2],
index:0,
open:"",
close:""
}
],
open:"<tag>",
close:"</tag>"
},
Node {
parent:self,
index:3,
root:self,
children:[
TextNode {
outer:"Third",
parent:self.children[3],
index:0,
open:"",
close:""
}
],
open:"<tag>",
close:"</tag>"
}
],
before:"Before text",
after:"After text"
}
Methods
walkNodes
The walkNodes
method is designed to traverse and apply functions to Node objects within the tree structure created by ReplaceBetween
. This method affects only the Node
instances, skipping any TextNode
instances.
Usage
tree.walkNodes([node => {
node.open = node.open.toLowerCase();
node.close = node.close.toLowerCase();
}]);
This method iterates over each node in the structure, providing access to modify properties like open
and close
, which represent the opening and closing tags of the node, respectively. Modifying these properties allows for comprehensive control over how the tags are rendered, which can be useful for tasks such as standardizing tag case or adjusting tag attributes.
walkTextNodes
The walkTextNodes
method specifically targets TextNode
objects in the tree, allowing for transformations or manipulations of the textual content within the nodes.
Usage
tree.walkTextNodes([textNode => {
textNode.outer = textNode.outer.toUpperCase();
}]);
This method is ideal for performing text-based modifications, such as changing case, inserting content, or any text-specific adjustments.
walk
The walk
method applies one or more functions to every node in the tree, allowing comprehensive modifications across the entire structure. This method is versatile and can target both Node
and TextNode
elements.
Usage
tree.walk([(element,isNode) => {
if (isNode && element.inner.includes('specific word')) {
element.open = `<div class='highlight'>${element.open}`;
element.close = `${element.close}</div>`;
}
}]);
This method is useful when you need consistent modifications across all elements of the structure, or when the modifications depend on the type of the element. It ensures that every element is processed, making it ideal for global updates.