Update the regular expression pattern to extract nested tags and store them in an array of objects

For my small application, I am working on creating a regex pattern to identify "faux" html tags. The goal is to capture these tags within curly brackets and output them into an array of objects.

Below is the code snippet with the current regex pattern:

{
  {key : value}, 
  {key : value}
}

let str = "{p}This is a paragraph{/p} {img}(path/to/image) {ul}{li}This is a list item{/li}{li}Another list item{/li}{/ul}";

let regex = /\{(\w+)}(?:\()?([^\{\)]+)(?:\{\/1})?/g;
let match;
let matches = [];

while (match = regex.exec(str)) {
    matches.push({ [match[1]]: match[2]})
}

console.log(matches)

Link to JSbin

I now need the regex pattern to handle nested groups as well and format them into an array. For example, for the given string above, the desired result would be:

[
  {p : "This is a paragraph"},
  {img : "path/to/image"},
  {ul : ["This is a list item", "Another List item"]}
]

The objective is to match each tag in sequence so that they correspond to their order of appearance in the string.

If you have any suggestions on how I could adjust the regex pattern for this purpose, I would greatly appreciate your input. Thank you!

Answer №1

Recursion is not natively supported in regular expressions within JavaScript, creating limitations for potential solutions.

An alternative approach would involve utilizing the DOMParser functionality available in browsers, or similar modules in Node environment.

In order to make use of this method, it is essential to have an XML-formatted string. If your content includes characters like `<`, they must be replaced with `<` to ensure proper formatting.

Additionally, when dealing with tags like `{img}`, they should ideally have a closing tag format rather than parentheses. Therefore, specific replacements are required for such cases.

Once these adjustments are made, converting the XML into a DOM becomes straightforward. You can further simplify the structure using a recursive function:

const str = "{p}This is a paragraph{/p} {img}(path/to/image) {ul}{li}This is a list item{/li}{li}Another list item{/li}{/ul}";

const xml = str.replace(/\{img\}\((.*?)\)/g, "{img}$1{/img}") 
               .replace(/</g, "&lt;")
               .replace(/\{/g, "<").replace(/\}/g, ">");
const parser = new DOMParser();
const dom = parser.parseFromString("<root>" + xml + "</root>", "application/xml").firstChild;
const parse = dom => dom.nodeType === 3 ? dom.nodeValue.trim() : {
    [dom.nodeName]: dom.children.length
                ? Array.from(dom.childNodes, parse).filter(Boolean)
                : dom.firstChild.nodeValue
};
const result = parse(dom).root;
console.log(result);

The resultant output closely aligns with the intended structure, although the `li` elements may appear as { li: "...." } objects due to the parsing method.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Testing Vue with Jest - Unable to test the window.scrollTo function

Is there a way to improve test coverage for a simple scroll to element function using getBoundingClientRect and window.scrollTo? Currently, the Jest tests only provide 100% branch coverage, with all other areas at 0. Function that needs testing: export de ...

Modify the transition and design of two progress bars

I'm having an issue with merging two Bootstrap progress bars into one. Initially, the first progress bar appears when the page loads and hides after data is loaded. At the same time, the second progress bar shows up. However, the transition animation ...

Is there a way to generate a fresh array by filtering an array of objects based on a single value?

I am currently working with an array of objects: const dummyLinkRows = [ { id: 'entity:link/1:en', categories: [ { name: 'Human Resources' }, { name: 'Social' } ], nam ...

Exploring the capabilities of Angular through filter functions and ng-bind-html

I created an angular filter called 'strLimit' to restrict the number of characters in a string: mod.filter('strLimit', ['$filter', function ($filter) { return function (input, limit) { if (!input) return; if (input.le ...

Searching for nicknames in a worldwide Jest arrangement?

Before running all test cases, I need to execute certain tasks only once. To achieve this, I have created a global function and specified the globalSetup field in my Jest configuration: globalSetup: path.resolve(srcPath, 'TestUtils', 'global ...

Customize numbers in JavaScript with a Unity-inspired design changer

I am currently working on implementing a number input feature that allows users to adjust values by clicking and holding the mouse button while moving the cursor left and right, similar to Unity's editor number adjuster: https://youtu.be/uY9PAcNMu8s?t ...

Bootstrap Tags Input is unable to function properly with data stored locally

I am currently working on developing a Project Manager tool that allows for the addition of multiple individuals to a single project. To accomplish this, I decided to incorporate the use of Bootstrap Tags Input by following the examples provided for Typeah ...

Use $.ajax to display the menu by capturing an array of elements {0}

Whenever I click on one of the DIV elements, a menu pops out on the side displaying more information about the clicked element. I can determine which element I'm clicking on, but I'm struggling to pass that information from jQuery to the PHP pag ...

Adjust image size as the page is resized

My challenge is to resize images that are typically too large for the current window size, ensuring they fit within 85% of the client window. I tried creating a function utilizing onload and onresize events but encountered issues. function adjustImages(){ ...

Customizing event colors in Full Calendar

My interactive calendar is created using : $('#calendar').fullCalendar({ height: 300, //............. events: jsonData, month: firstMonth }) I am looking to dynamically change the color of an event based on certain conditions ...

Having difficulty removing new or existing lines on StackBlitz

I attempted to experiment with React on StackBlitz, but I encountered a problem where I couldn't delete any lines of code. It seems that while I can add new lines of code, deleting them is not an option. Even when logging in with GitHub, the issue per ...

Is it possible to extract an attribute value from a parent element using ReactJS?

https://i.stack.imgur.com/OXBB7.png Whenever I select a particular button, my goal is to capture the {country} prop that is linked to it. I attempted the following approach import React, { useState, useEffect } from 'react' import axios from &ap ...

Stop the submission of a form using jQuery based on its unique identifier

When using the jQuery Ajax function to verify if a user email exists in the database during a jQuery change event, there are two possible outcomes in the Ajax response. If the user email does exist, an error message is displayed. In this scenario, I aim ...

Installing v8-profiler on Windows 8 (64 bit) through npm: a step-by-step guide

The v8-profiler module is widely recognized as the go-to tool for identifying memory leaks in node.js applications. However, attempting to install it with npm install v8-profiler results in an error message related to compatibility issues between 32bit an ...

Looking for a specific item within a nested object in MongoDB to carry out an update

I have a JSON dataset containing information about individuals, including their children: { "name": ":John", "age": 35, "kids": [ { "name": "tom", "age": 5 }, { "name": "tina", "age": 3 } ] } My goal is to ...

Encountering an issue with Angular2 where it is unable to load a JSON file, presenting the error message: "Cannot resolve all parameters

I've been trying to incorporate a json file into my Angular app, but I can't seem to pinpoint the issue. The error message keeps indicating that it cannot resolve all parameters of my component. (I had no trouble loading data directly from the c ...

Extract all 8-digit numerical values from a dataset

For a current assignment, I am tasked with extracting all the 8-digit numbers from a text file. After converting the text file into a dataframe, I now have a table with 67 columns and 18000 rows, some of which contain empty cells. Scattered throughout thi ...

Creating JSON in Python by combining data from two lists of lists involves merging the elements from both lists into a single JSON format

Having two csv files(semi-colon delimited) with the structure and sample data below: File 1: qid;question 1.0;How can I find specific content 2.0;How do I modify content 2.0;How can I edit items 2.0;I need to change some answers 3.0;How do I troubleshoot ...

The deletion of Webpack Clean- /public/js has been successfully completed

I am utilizing the clean-webpack-plugin to empty the contents of my public/js directory. https://www.npmjs.com/package/clean-webpack-plugin Despite trying various methods, I keep encountering the message /public/js has been removed plugins: [ new CleanW ...

The ternary operator, also known as the conditional operator

One feature I have implemented is a button that can generate a random color and update the color state with this value. The color state is then used to define the background color of the div. Within the div, there is a lock/unlock button that toggles the ...