-
-
Notifications
You must be signed in to change notification settings - Fork 11.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3099 from qixing-jk/feat-spoiler-text-plugin
Feat spoiler text plugin 支持spoiler text
- Loading branch information
Showing
4 changed files
with
126 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* Spoiler text styles */ | ||
.spoiler-text { | ||
color: transparent; /* 文字透明 */ | ||
background-color: #808080; /* 背景为黑色 */ | ||
border-color: #808080; | ||
text-decoration-color: #808080; | ||
text-emphasis-color: #808080; | ||
border-radius: 8px; | ||
filter: blur(1px); /* 初始模糊 */ | ||
--hide-transition: 0.3s ease-out; | ||
transition: opacity var(--hide-transition), | ||
filter var(--hide-transition); | ||
} | ||
|
||
.spoiler-text:hover { | ||
color: inherit; /* 鼠标悬停时恢复文字颜色 */ | ||
background-color: inherit; /* 鼠标悬停时恢复背景颜色 */ | ||
border-color: inherit; | ||
text-decoration-color: inherit; | ||
text-emphasis-color: inherit; | ||
opacity: 1; /* 鼠标悬停时恢复不透明度 */ | ||
filter: blur(0); /* 鼠标悬停时解除模糊 */ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/** | ||
* 将Node文本中的指定标签内容转换为带有指定类名的span | ||
* @param regex | ||
* @param node | ||
* @param className | ||
*/ | ||
function convertTextToSpoilerSpan(regex, node, className) { | ||
const wholeText = node.wholeText | ||
let outerSpan = document.createElement('span') | ||
const fragments = [] | ||
let lastIndex = 0 | ||
let match | ||
while ((match = regex.exec(wholeText)) !== null) { | ||
console.log('符合要求的文字' + wholeText) | ||
// 添加前面未匹配的部分 | ||
if (match.index > lastIndex) { | ||
outerSpan.appendChild( | ||
document.createTextNode(wholeText.slice(lastIndex, match.index)) | ||
) | ||
} | ||
|
||
// 创建 span 包裹的内容 | ||
const span = document.createElement('span') | ||
span.textContent = match[1] // 提取匹配的内容 | ||
if (className) { | ||
span.className = className | ||
} | ||
outerSpan.appendChild(span) | ||
// 设置lastIndex | ||
lastIndex = regex.lastIndex | ||
} | ||
if (outerSpan.childNodes.length) { | ||
// 添加剩余未匹配的部分 | ||
if (lastIndex < wholeText.length) { | ||
outerSpan.appendChild(document.createTextNode(wholeText.slice(lastIndex))) | ||
} | ||
node.replaceWith(outerSpan) | ||
} | ||
} | ||
|
||
/** | ||
* 收集并处理指定节点下的所有文本节点 | ||
* @param root | ||
* @param className | ||
* @param spoilerTag | ||
*/ | ||
function processTextNodes(root, className, spoilerTag) { | ||
const regex = new RegExp(`${spoilerTag}(.*?)${spoilerTag}`, 'g') | ||
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, { | ||
acceptNode: function (node) { | ||
return regex.test(node.wholeText) | ||
? NodeFilter.FILTER_ACCEPT | ||
: NodeFilter.FILTER_REJECT | ||
} | ||
}) | ||
const waitProcessNodes = [] | ||
while (walker.nextNode()) { | ||
const node = walker.currentNode | ||
waitProcessNodes.push(node) | ||
} | ||
for (const waitProcessNode of waitProcessNodes) { | ||
convertTextToSpoilerSpan(regex, waitProcessNode, className) | ||
} | ||
} | ||
|
||
/** | ||
* 定位到目标处理位置,开始进行文本到spoiler的转换 | ||
* @param spoilerTag | ||
*/ | ||
function textToSpoiler(spoilerTag) { | ||
const intervalID = setInterval(() => { | ||
const articleElement = document.querySelector( | ||
'#article-wrapper #notion-article main' | ||
) | ||
if (articleElement) { | ||
setTimeout(() => { | ||
processTextNodes(articleElement, 'spoiler-text', spoilerTag) | ||
clearInterval(intervalID) | ||
}, 300) | ||
} | ||
}, 1000) | ||
} | ||
|
||
window.textToSpoiler = textToSpoiler |