我有一个在HTML DOM中预处理文本节点的函数。
目的主要是执行一些插值或字符串模板化。
该函数基本上检查与正则表达式/\${([^}]*)}/g
和/{{([^}]*)}/g
匹配的事件。
示例:${foo + 1}
和{{foo + 2}}
这一切都有效。
但我的目标是用新节点(例如span
)替换这些事件,这些节点由Knockout绑定表达式组成,其中包含来自正则表达式的匹配的内部值。职位是正确的。保留它们出现的空格。
像这样:
<span ko-text="foo" />
的{p> ${foo}
(注意:自定义绑定语法)
我不能用TextNode.splitText
包围我的头。
我如何实现这一目标?
这是我到目前为止的代码:
preprocessNode(node: Element) {
if ("nodeValue" in node && node.nodeValue !== null) {
var value = node.nodeValue;
var match = value.matchAll(/\${([^}]*)}/g);
if (!match) {
match = value.matchAll(/{{([^}]*)}/g);
}
if (match !== null && match.length > 0) {
var parentNode = node.parentNode;
for (let entry of match) {
var offset = node.nodeValue.indexOf(entry[0]);
var oldNode = node;
node = node.splitText(offset);
var newNode = document.createElement("span");
newNode.setAttribute("ko-text", entry[1]);
node.parentNode.appendChild(newNode);
}
return [parentNode, parentNode];
}
}
return null;
}
函数matchAll
是一个自定义函数。
答案 0 :(得分:0)
Disclaimer: I don't know JavaScript! This is just a suggestion.
# /^\$\{([^{}]+)\}|\{\{([^{}]+)\}\}|((?:(?!^\$\{[^{}]+\}|\{\{[^{}]+\}\})[\S\s])+)/
^ \$\{
( [^{}]+ ) # (1)
\}
|
\{\{
( [^{}]+ ) # (2)
\}\}
|
( # (3 start)
(?:
(?!
^ \$\{ [^{}]+ \}
| \{\{ [^{}]+ \}\}
)
[\S\s]
)+
) # (3 end)
Pseudo-code:
if ( regex_find ( /^\$\{[^{}]+\}|\{\{[^{}]+\}\}/, value ) )
{
var found = false;
while ( regex_search ( /^\$\{([^{}]+)\}|\{\{([^{}]+)\}\}|((?:(?!^\$\{[^{}]+\}|\{\{[^{}]+\}\})[\S\s])+)/g, match, value ) )
{
if ( match[1] != null )
{
// Found '${..}' form
found = true;
var newNode = document.createElement("span");
newNode.setAttribute("ko-text", match[1]);
// Append newNode
}
else
if ( match[2] != null )
{
// Found '{{..}}' form
found = true;
var newNode = document.createElement("span");
newNode.setAttribute("ko-text", match[2]);
// Append newNode
}
else
if ( match[3] != null )
{
// Found '...' normal text
found = true;
var newNode = document.createTextNode( match[3] );
// Append newNode
}
}
if ( found )
{
// Clear or delete the original text node
// ...
}
}
答案 1 :(得分:0)
经过多次考虑后,我就是这样解决的:
if (match !== null && match.length > 0) {
var parentNode = node.parentNode;
var nodes = [];
var textString = value;
var i = 0;
for (let entry of match) {
var startOffset = node.nodeValue.indexOf(entry[0]);
var endOffset = startOffset + entry[0].length;
var length = startOffset - i;
if (length > 0) {
var str = textString.substr(i, length);
var textNode = document.createTextNode(str);
parentNode.insertBefore(textNode, node);
}
var newNode2 = document.createElement("span");
newNode2.setAttribute("ko-text", entry[1]);
parentNode.insertBefore(newNode2, node);
nodes.push(newNode2);
i = endOffset;
}
var length = textString.length - i;
if (length > 0) {
var str = textString.substr(i, length);
var textNode = document.createTextNode(str);
parentNode.insertBefore(textNode, node);
}
parentNode.removeChild(node);
return nodes;
}
当然可以改善。
答案 2 :(得分:0)
var textNodesWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);
var node;
while (node = textNodesWalker.nextNode()) {
var newNodes = [];
var execResult = MY_REG_EXP.exec(node.nodeValue);
var start = 0;
while (execResult) {
newNodes.push(document.createTextNode(node.nodeValue.substring(start, execResult.index)));
var generatedElement = ...; // create element (document.createElement) based on execResult
newNodes.push(generatedElement);
start = execResult.index + execResult[0].length;
execResult = MY_REG_EXP.exec(node.nodeValue);
}
if (newNodes.length == 0) {
continue;
}
newNodes.push(document.createTextNode(node.nodeValue.substring(start, node.nodeValue.length)));
for (var i=0; i<newNodes.length; i++) {
node.parentNode.insertBefore(newNodes[i], node)
}
node.parentNode.removeChild(node);
}
假设我们有模式/asdf/g
,而不是需要加粗。我的代码将转换为html:
<p>Begin asdf End</p>
到
<p>Begin <b>asdf</b> End</p>