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

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

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

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

// Map the list of component tags and extract data from them
return generateComponentList(data).map((component) => {
    console.log(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.log(chalk.green(component[1], 'processing complete.'))
    })

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

Проблема, с которой я столкнулся, состоит в том, что тег CodeExample существует дважды, тег идентичен, но содержимое отличается, однако, поскольку matchRecursive не имеет функции обратного вызова, он просто выполняет сопоставление для всех экземпляры этого компонента одновременно, поэтому не имеет значения, если есть 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
]

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

1 Ответ

0 голосов
/ 12 ноября 2018

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

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
...