Синтаксический анализ уценки с помощью регулярного выражения - PullRequest
1 голос
/ 12 марта 2019

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

Мне трудно работать с изолированными кодовыми блоками, потому что регулярное выражение сталкивается как с внутренним кодом, так и с абзацами.

Здесьмоя функция:

function parseMd(text) {
    const codeblock = /```([^]+?.*?[^]+?[^]+?)```/g
    const code = /`(.*?)`/g
    const link = /\[(.*?)\]\((.*?)\)/g
    const paragraph = /(.+((\r?\n.+)*))/g

    return text.replace(codeblock, '<pre><code>$1
') .replace (код,' $1 ') .replace (ссылка,' $ 1 ') .replace (абзац,'

$ 1

');}

В идеале, мне нужно было бы code и paragraph регулярные выражения, чтобы игнорировать все, что соответствует codeblock, но так как это многострочное, становится сложно!

Ответы [ 2 ]

1 голос
/ 13 марта 2019

Реализация, представленная ниже, опирается на атрибут innerHTML проверка и редактирование .

Выполняется следующие основные шаги:

  1. Анализ блоков кода сначала до защиты их от дальнейших подстановок;
  2. Внедрение результата в элемент HTML какinnerHTML атрибут, позволяющий браузеру анализировать и превращать его в Node набор (теперь кодовые блоки защищены);
  3. Замените оставшийся текст (которые теперь являются текстовыми узлами) элементами <P>, чтобы проанализировать параграфов и выполнить синтаксический анализ встроенных элементов внутри, чтобы наконец получить ссылки и inline code.

Ниже проверенного фрагмента.

// Some HTML elements used througout the parsing

var resultDiv = document.getElementById("rendered-result")
var resultSrcTA = document.getElementById("resultsrc");

// convert() - Our lite MD parser

function convert() {
  var mdt = document.getElementById("md").value;
  // First we parse the blocks to prevent them to be parsed later on
  parseCodeBlocks(mdt);
  // Then we deal with the remaning text, which are paragraphs
  parseParagraphs();
  resultSrcTA.value = resultDiv.innerHTML;
}

// This function simply performs a regexp substitution on a given text
// and inject it into the result HTML element (resultDiv)
// as an inner HTML string to let the browser parting it

function parseCodeBlocks(text) {
  const codeblock = /```\s*([^]+?.*?[^]+?[^]+?)```/g;
  resultDiv.innerHTML = 
    text.replace(codeblock, '<pre><code>$1
');} // Эта функция заменяет оставшиеся текстовые узлы абзацами // (Сложная часть) function parseParagraphs () {var node = resultDiv.childNodes;// Цикл по узлам для (var i = 0; i элементов ps = createPElementFromMDParagraphs (node ​​[i] .nodeValue);// Обратный цикл по элементам

// Поскольку мы вставляем их сразу после анализируемого текстового узла для (var j = ps.length -1; j> -1; j--) {resultDiv.insertBefore (ps [j], node [i] .nextSibling)} // Мы закончили со вставкой абзаца, пора удалять // анализируемый текстовый узел resultDiv.removeChild (node ​​[i]);// Обновление i: мы добавили n абзаца и удалили один текстовый узел i + = ps.length - 1;}} // Эта функция возвращает для заданного текста массив

, представляющий // функцию содержимого createPElementFromMDParagraphs (text) {const абзац = /(.+)((\r?\n.+)*)/g;const code = /`(.*?)`/g;const link = /\[(.*?)\]\((.*?)\)/g;var ps = [];вар совпадений;// Мы перебираем совпадения с регулярным выражением абзаца // Для каждого соответствия мы создаем элемент

и помещаем его // в массив результатов while ((match = para.exec (text))! == null) {varp = document.createElement ("p");p.appendChild (document.createTextNode (матчи [1]));// И у нас есть здесь возможность отформатировать встроенные элементы // Обратите внимание, что ссылки будут анализироваться внутри элемента кода и будут работать p.innerHTML = p.innerHTML.replace (code, '$1');p.innerHTML = p.innerHTML.replace (ссылка, ' $ 1 ');ps.push (р);} вернуть пс;}

/* Just to get it fancy */

textarea {
  width: 100%;
  height: 15ex;
}

div#rendered-result {
  min-height:10ex;
  height:10ex;
  border: 1px solid black;
  padding:1em;
  font-family:sans-serif;
  overflow-y:auto;
}

div#rendered-result > pre {
  background: #f0f0f0;
  margin: 1em;
  padding:0.5em;
  border: 1px solid #808080;
}

div#rendered-result > pre > code {
  margin: 0;
}

/* To check if this is a well parsed paragraph. */

div#rendered-result > p::first-letter {
  font-weight:bold;
  color:darkred;
}
<p>Type your markdown text below:</p>
<textarea id="md">
The first paragraph.

```
A code block very well catched
Haha this `inline code` wont be parsed.
```

And a sentence with [two](http://stackoverflow.com) [links](http://askbuntu.com).

And another with an `inline code` and a [link](http://superuser.com).

```
And another code block
```

And another with an link as `[inline code](http://superuser.com)`.

Last sentence.
</textarea>
<p>
  <!-- yes it's bad -->
  <button onclick="convert()">Convert it</button>
</p>
<p>Result</p>
<div id="rendered-result">
</div>
<p>Source:</p>
<textarea id="resultsrc">
</textarea>
1 голос
/ 12 марта 2019

Вы можете использовать регулярные выражения в проекте marksjs .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...