javascript - 如何将不可点击的纯文本 URL 转换为 HTML 源中的链接
问题描述
我想检测 URL 并将它们链接到 HTML 代码中。我搜索了 Stack Overflow,但许多答案都是关于检测和转换文本字符串中的链接。当我这样做时,html代码将无效;IE。img 来源会改变,等等。
PS:关闭投票者:请仔细阅读问题!它不是重复的。
例如; 第 1 行需要转换,第 2 行和第 3 行不需要。
<!-- Sample html source -->
<div>
Line 1 : https://www.google.com/
Line 2 : <a href="https://www.google.com/">https://www.google.com/</a>
Line 3: <img src="http://a-domain.com/lovely-image.jpg">
</div>
我需要:
在 html 正文部分中查找任何 URL
检查它是否可点击:如果没有被 'a'、'img'、'!--' 等包裹。
如果不使其可点击:用'a'包裹
我怎样才能做到这一点?所有 C# 和 JS 版本对我来说都可以。
最新更新将项目构建目标从 4.7.2 更改为 4.5 并返回到 4.7.2 修复了“错误”。
更新:这是我在@jira 帮助下的解决方案这里的问题是节点根本不会改变。我的意思是递归函数完成了这项工作,替换了链接,调试说,但是 html 文档根本不会更新。函数内部的任何修改都不会影响函数外部,我不知道为什么,InnerText 改变 - InnerHtml 没有改变
var htmlVersion = "<html><head></head><body>\r\n"
+ "Some text\r\n"
+ "<div>http://google.com</div>\r\n"
+ " Then later more text: http://500px.com\r\n"
+ "<div>Sub <span>abc</span> Back text</div>\r\n"
+ "And the final text"
+ "</body></html>";
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(htmlVersion);
// Linkify body
var modified = false;
var bodyNode = doc.DocumentNode.SelectSingleNode("//body");
var before = bodyNode.InnerHtml;
bodyNode = Linkify(bodyNode);
modified = modified || bodyNode.InnerHtml != before;
// modified is false !!!
递归 Linkify 函数:
HtmlAgilityPack.HtmlNode Linkify(HtmlAgilityPack.HtmlNode node)
{
if (node.Name == "a") // It's already a link
{
return node;
}
if (node.Name == "#text") // Do replacement here
{
// Create links
// https://stackoverflow.com/a/4750468/627193
node.InnerHtml = Regex.Replace(node.InnerHtml,
@"((http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)",
"<a target='_blank' href='$1'>$1</a>");
}
for (int i = 0; i < node.ChildNodes.Count; i++) // Go for child nodes
{
node.ChildNodes[i] = Linkify(node.ChildNodes[i]);
}
return node;
}
解决方案
使用像HtmlAgility Pack这样的html 解析器。仅选择文本节点,然后在其中搜索链接。这样你就不会触及现有的链接。根据您需要的精确程度,您可以使用正则表达式。
例如
var doc = new HtmlDocument();
doc.LoadHtml(html);
Regex r = new Regex(@"(https?://[^\s]+)");
var textNodes = doc.DocumentNode.SelectNodes("//text()");
foreach (var textNode in textNodes) {
var text = textNode.GetDirectInnerText();
var withLinks = r.Replace(text, "<a href=\"$1\">$1</a>");
textNode.InnerHtml = withLinks;
}
正确检查链接的正则表达式可能会变得相当复杂。在此处查看其他答案。
推荐阅读
- nginx - meidawiki 和 nginx 中的好 URL 给出错误:FastCGI 在标准错误中发送:“主要脚本未知”同时从上游读取响应标头
- vba - VBA Access 2013 表单:如何刷新?
- java - 多键鼠标点击
- css - 具有缩放和移动效果的滑块
- arrays - 浮点数数组不存在 PostgreSQL 运算符
- gradle - 为什么 gradle-clojure 插件会跳过 compileClojure 任务?
- python - 损失函数 Keras out_dim > 1
- joomla - Joomla - 方便的模板升级
- python-2.7 - NameError:全局名称“MyClass”未在 Pepper/Nao 中定义
- c - 使用指针删除链表中的节点