把 HTML 中混着的 URL 转成<a>标签,各位有什么优雅的实现方法吗?

2022-05-31 03:44:23 +08:00
 mashirozx

前提:HTML 原来就包括一些<a>标签和<img>标签,现在要做的是把剩下的不在任何标签内的 URL 转为<a>标签。

尝试过写正则,反向匹配所有满足条件的,但是太复杂,遂放弃。

最后考虑先把标签内的 URL 转义,然后替换剩下的所有 URL ,最后再把转义的转回来,代码如下:

但是真的太丑了,而且存在明显的 bug ,无奈又想不出别的办法,还望大佬们给点思路

1571 次点击
所在节点    算法
8 条回复
vance123
2022-05-31 04:11:15 +08:00
先解析成 Dom ,然后再用正则替换文本怎么样
GeruzoniAnsasu
2022-05-31 04:35:33 +08:00
ruby 不熟,库就更不了解了

你需要一个 dom visitor ,然后遍历每个节点,把节点里的 text 正则替换成<a>
Girlphobia
2022-05-31 04:54:15 +08:00
首先解析 DOM ,然后对 DOM tree 递归遍历节点:
如果是 <a> ,跳过当前节点及所有子节点;
如果是 Text ( https://developer.mozilla.org/en-US/docs/Web/API/Text ) ,匹配 URL 正则,替换为 <a> (这里的替换实现细节可以取决于 URL 是可信的还是用户提供的,可能需要考虑 input sanitization );
如果是其他元素,用以上逻辑递归处理所有子元素。
wd
2022-05-31 07:17:29 +08:00
你把 html 解析成 document 之后,应该就可以直接替换所有 text 里面的 url 了吧?
ho121
2022-05-31 07:26:39 +08:00
如果有 inline 的元素,比如
<p>http<span>://</span>www.qq.com</p>
这种的,页面上看起来是连续的内容,实际 Dom 树是有层级的,这种还不太好处理
xiangyuecn
2022-05-31 07:44:37 +08:00
有多难,还解析 dom ?

1. 直接取出 body ,过滤掉 head 干扰
2. 换行符全部用占位符替换掉,比如" __换行__ " 这种不容易冲突的(首尾带空格),转成单行
3. 替换掉所有 <.*?> 包裹的内容,用占位符替换掉,内容存入 map ,比如 " __替换:123__ "(首尾带空格),map[123]="<替换掉的内容>"
4. 剩下的文本不就随便你搞了,全是纯的文本节点,简单的一个正则就能完成替换工作
5. 恢复占位符对应的内容

性能消耗完全可以忽略不计
GeruzoniAnsasu
2022-05-31 07:54:08 +08:00
@xiangyuecn

<pre> if (a <=3 || a > 5) </pre>
xiangyuecn
2022-05-31 08:14:01 +08:00
@GeruzoniAnsasu 并不影响,后面会恢复回来。url 的匹配不容易误杀,url 没有空格

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/856340

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX