Hexo 支持 Markdown == 高亮扩展语法

零风PLFJY Lv2

借助GPT弄了个js脚本,增加到header就行,它可以自动监听swup的页面切换事件并替换==<mark></mark>,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
(function () {
'use strict';

// 要跳过的标签(不在这些标签内进行替换)
const SKIP_TAGS = new Set(['CODE', 'PRE', 'SCRIPT', 'STYLE', 'TEXTAREA']);

// 非贪婪匹配 ==...==,允许跨空格和特殊字符
const MARK_RE = /==([\s\S]+?)==/g;

// 判断节点是否在我们需要跳过的标签内
function isInsideSkippedTag(node) {
while (node) {
if (node.nodeType === 1 && SKIP_TAGS.has(node.tagName)) return true;
node = node.parentNode;
}
return false;
}

// 将单个文本节点里的所有 ==...== 替换为 <mark>...</mark>
function replaceInTextNode(textNode) {
const text = textNode.nodeValue;
if (!text || text.indexOf('==') === -1) return;

MARK_RE.lastIndex = 0;
let match;
let lastIndex = 0;
const frag = document.createDocumentFragment();

while ((match = MARK_RE.exec(text)) !== null) {
const before = text.slice(lastIndex, match.index);
if (before) frag.appendChild(document.createTextNode(before));

const mark = document.createElement('mark');
// 只设置 textContent,保持 HTML 安全
mark.textContent = match[1];
frag.appendChild(mark);

lastIndex = MARK_RE.lastIndex;
}

const after = text.slice(lastIndex);
if (after) frag.appendChild(document.createTextNode(after));

// 用片段替换原文本节点
textNode.parentNode.replaceChild(frag, textNode);
}

// 在 root 上处理所有可见文本节点
function process(root = document.body) {
if (!root) return;
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
acceptNode(node) {
if (!node.nodeValue) return NodeFilter.FILTER_REJECT;
if (node.nodeValue.indexOf('==') === -1) return NodeFilter.FILTER_REJECT;
// 如果仅包含空白(回车空格),跳过
if (node.nodeValue.trim() === '') return NodeFilter.FILTER_REJECT;
return NodeFilter.FILTER_ACCEPT;
}
}, false);

const nodes = [];
while (walker.nextNode()) nodes.push(walker.currentNode);

for (const n of nodes) {
// 跳过 code/pre 等
if (!isInsideSkippedTag(n.parentNode)) {
replaceInTextNode(n);
}
}
}

// 在初次加载时运行一次
function onReadyRun() {
process();
}

if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', onReadyRun);
} else {
onReadyRun();
}

// swup 支持:
// 1) 如果存在全局 swup 实例并且有 on 方法,使用它
// 2) 兼容 swup 自定义 DOM 事件(document 上的 'swup:contentReplaced')
if (window.swup && typeof window.swup.on === 'function') {
try { window.swup.on('contentReplaced', () => process()); } catch (e) { /* ignore */ }
}
document.addEventListener('swup:contentReplaced', () => process());

// 兜底:监听 DOM 的新插入(节流)
let idleTimer = null;
const observer = new MutationObserver(() => {
if (idleTimer) clearTimeout(idleTimer);
idleTimer = setTimeout(() => {
process();
idleTimer = null;
}, 60);
});
// 观察整个文档的子节点变化(轻量级配置)
observer.observe(document.documentElement || document.body, { childList: true, subtree: true });

// 可选:暴露一个手动触发的函数,方便调试 / 在控制台直接调用
window.__applyDoubleEqualsMark = process;

})();

  • Title: Hexo 支持 Markdown == 高亮扩展语法
  • Author: 零风PLFJY
  • Created at : 2025-09-24 23:27:51
  • Updated at : 2025-12-06 22:44:55
  • Link: https://blog.plfjy.top/hexo/highlight-text/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments
On this page
Hexo 支持 Markdown == 高亮扩展语法