У меня есть сложная проблема. Я работаю над script, который принимает регулярное выражение в качестве ввода. Этот script затем находит все совпадения для этого регулярного выражения в документе и обертывает каждое соответствие в своем собственном <span> элемент. Жесткая часть заключается в том, что текст является форматированным html-документом, поэтому мой script должен перемещаться по DOM и применять регулярное выражение на нескольких текстовых узлах одновременно, выясняя, где он должен разделить текстовые узлы, если это необходимо.
Например, с регулярным выражением, которое фиксирует полные предложения, начинающиеся с заглавной буквы и заканчивающиеся на период, этот документ:
<p>
<b>HTML</b> is a language used to make <b>websites.</b>
It was developed by <i>CERN</i> employees in the early 90s.
<p>
Будет превращено в это:
<p>
<span><b>HTML</b> is a language used to make <b>websites.</b></span>
<span>It was developed by <i>CERN</i> employees in the early 90s.</span>
<p>
script затем возвращает список всех созданных интервалов.
У меня уже есть код, который находит все текстовые узлы и сохраняет их в списке вместе с их позицией по всему документу и их глубине. Вам действительно не нужно понимать, что код, который поможет мне и его рекурсивная структура, может быть немного запутанным. T Вначале я не уверен, как это сделать, это выяснить, какие элементы должны быть включены в диапазон.
function SmartNode(node, depth, start) {
this.node = node;
this.depth = depth;
this.start = start;
}
function findTextNodes(node, depth, start) {
var list = [];
var start = start || 0;
depth = (typeof depth !== "undefined" ? depth : -1);
if(node.nodeType === Node.TEXT_NODE) {
list.push(new SmartNode(node, depth, start));
} else {
for(var i=0; i < node.childNodes.length; ++i) {
list = list.concat(findTextNodes(node.childNodes[i], depth+1, start));
if(list.length) start += list[list.length-1].node.nodeValue.length;
}
}
return list;
}
Я полагаю, что сделаю строку из всего документа, запустим через него регулярное выражение и использую список, чтобы найти, какие узлы соответствуют совпадению регулярных выражений, а затем разбить текстовые узлы соответственно.
Но проблема возникает, когда у меня есть такой документ:
<p>
This program is <a href="beta.html">not stable yet. Do not use this in production yet.</a>
</p>
Там предложение, которое начинается за пределами тега <a>
, но заканчивается внутри него. Теперь я не хочу, чтобы script разделил эту ссылку на два тега. В более сложном документе это может испортить страницу, если это произойдет. Код может либо обернуть два предложения вместе:
<p>
<span>This program is <a href="beta.html">not stable yet. Do not use this in production yet.</a></span>
</p>
Или просто оберните каждую часть в свой собственный элемент:
<p>
<span>This program is </span>
<a href="beta.html">
<span>not stable yet.</span>
<span>Do not use this in production yet.</span>
</a>
</p>
Может быть параметр, чтобы указать, что он должен делать. Я просто не уверен, что как выяснить, когда произойдет невозможное сокращение, и как его восстановить.
Другая проблема возникает, когда у меня есть пробел внутри дочернего элемента вроде:
<p>This is a <b>sentence. </b></p>
Технически совпадение регулярных выражений заканчивается сразу после периода, до конца тега <b>
. Однако было бы гораздо лучше рассмотреть пространство как часть матча и обернуть его следующим образом:
<p><span>This is a <b>sentence. </b></span></p>
Чем это:
<p><span>This is a </span><b><span>sentence.</span> </b></p>
Но это второстепенная проблема. В конце концов, я мог бы просто добавить лишнее белое пространство в регулярное выражение.
Я знаю, что это может звучать как вопрос "сделай это для меня", и это не тот быстрый вопрос, который мы видим на SO на ежедневной основе, но я застрял на нем какое-то время, и это для открытого -source library, над которой я работаю. Решение этой проблемы является последним препятствием. Если вы считаете, что другой сайт SE лучше всего подходит для этого вопроса, перенаправите меня, пожалуйста.