XRegexP.matchRecursive - добавить функцию обратного вызова, чтобы разрешить несколько идентичных экземпляров

Я использую XRegexP для анализа текстового файла специально, чтобы найти содержимое между двумя наборами предопределенных тегов комментариев, я не могу изменить эти теги, поэтому мне нужно найти способ заставить его работать с предоставленным текстом.

Я нахожу список всех тегов с использованием предоставленного регулярного выражения (пример в ссылке также включает образец содержимого): https://regex101.com/r/kCwyok/1/

Затем я использовал функцию XRegexP matchRecursive, чтобы получить весь контент между открывающим и закрывающим тегами, и все это работает - почти - идеально.

// Map the list of component tags and extract data from them
return generateComponentList(data).map((component) => {
    console.info(chalk.blue('Processing', component[1], 'component.'))
    const contents = XRegExp.matchRecursive(data, '<!-- @\\[' + component[1] + '\\][.\\w-_+]* -->', '<!-- @\\[/' + component[1] + '\\] -->', 'g')
    let body = ''
    let classes = ''

    contents.map((content) => {
      const filteredContent = filterContent(content)
      body = filteredContent.value
      classes = cleanClasses(component[2])
      console.info(chalk.green(component[1], 'processing complete.'))
    })

    // Output the content as a JSON object
    return {
      componentName: component[1],
      classes,
      body
    }
  })

У меня проблема в том, что тег CodeExample существует дважды, тег идентичен, но содержимое отличается, однако, поскольку matchRecursive не имеет функции обратного вызова, он просто выполняет сопоставление для всех экземпляров этого компонента одновременно. time, поэтому не имеет значения, есть ли 1 или 10 экземпляров CodeExample, возвращается контент для всех из них.

Есть ли способ добавить какой-то обратный вызов для matchRecursive? В противном случае есть ли способ заставить JavaScript понять, какой экземпляр CodeExample просматривается, чтобы я мог просто напрямую ссылаться на позицию массива? Я предполагаю, что XRegexP знает, на какой номер тега CodeExample он смотрит, так есть ли способ его захватить?

Вот полный код для ясности: https://pastebin.com/2MpdvdNA

Желаемый результат, который я хочу, - это файл JSON со следующими данными:

[
{
 componentName: "hero",
 classes: "",
 body: "# Creating new contexts"
},
{
 componentName: "CodeExample",
 classes: "",
 body: "## Usage example

    ```javascript
      Import { ICON_NAME } from 'Icons'
    ```"
},
{
 componentName: "ArticleSection",
 classes: "",
 body: // This section is massive and not relevant to question so skipping
},
{
 componentName: "NoteBlock",
 classes: ["warning"],
 body: "> #### Be Careful
> Eu laboris eiusmod ut exercitation minim laboris ipsum magna consectetur est [commodo](/nope)."
},
{
 componentName: "CodeExample",
 classes: "",
 body: "#### Code example
```javascript
  class ScrollingList extends React.Component {
      constructor(props) {
        super(props);
        this.listRef = React.createRef();
      }

      render() {
        return (
          &#60;div ref = {this.listRef}&#62;{/* ...contents... */}&#60;/div&#62;
        );
      }
    }
```"
}
// Skipping the rest as not relevant to question
]

Извините, если я не объяснил это четко, я слишком долго смотрел на это.

🤔 А знаете ли вы, что...
Синтаксис JavaScript схож с синтаксисом языка программирования Java, но они не связаны.


144
1

Ответ:

Решено

Вот как это было решено в итоге:

import XRegExp from 'xregexp'

const extractComponents = data => {
  const components = []
  const re = '<!-- @\\[(\\w+)\\]([.\\w-_+]+)* -->'

  XRegExp.forEach(data, XRegExp(re, 'g'), match => {
    const name = match[1]
    const classes = match[2]

    const count = components.filter(item => item.name === name).length
    const instance = count ? count : 0

    components.push({
      name,
      classes,
      instance
    })
  })

  return components
}

const cleanClasses = classes => {
  const filteredClasses = classes ? classes.split('.') : []
  filteredClasses.shift()

  return filteredClasses
}

const extractContent = (data, component) => {
  const re = `<!-- @\\[${component.name}\\][.\\w-_+]* -->`
  const re2 = `<!-- @\\[/${component.name}\\] -->`

  return XRegExp.matchRecursive(
    data, 
    re, re2, 'g'
  )[component.instance]
}

const parseComponents = data => {
  return extractComponents(data).map(component => {
    return {
      componentName: component.name,
      classes: cleanClasses(component.classes),
      body: extractContent(data, component)
    }
  })
}

export default parseComponents