插件地址:Achuan-2/siyuan-plugin-highlight-cloze
🤔 背景
在学习过程中,我们经常会遇到一些需要填空的题目、需要记忆的知识点,为了方便记忆,我们可以使用高亮挖空的方式来标记这些知识点和题目,确认是否自己真的记住了这些内容。
其实 Tsundoku 主题很早是支持高亮挖空的,但是后面由于思源笔记有了插件,就被我砍掉了,一直期待有大佬写一个高亮挖空插件,但是好像一直没看到。
最近要准备博士研究生的英语课程考试,需要背 stock phase,闪卡适合有规律的复习,如果我想随时复习(突击复习)就不是那么方便,于是就迅速写了这样一个高亮挖空插件来帮助我复习。
✨ 功能
-
✨ 点击顶部的插件按钮,即可隐藏/显示高亮文字。
-
✨ 高亮挖空模式下,鼠标悬浮挖空文字可显示高亮文字。
-
✨ 高亮挖空模式下,导出 pdf 能保持高亮挖空样式,这样就能打印挖空的文档来制作题目用于复习和测试。
-
✨ 支持设置快捷键,默认为空
🎨 自定义 css
插件支持自定义高亮挖空的样式
举例:如果你想要高亮挖空的样式是黑色下划线,可以把设置里的 css 改为下面的内容
/* 高亮挖空的样式 */
.b3-typography mark,
.b3-typography span[data-type~=mark],
.protyle-wysiwyg mark,
.protyle-wysiwyg span[data-type~='mark'] {
color: transparent !important;
transition: color 0.5s ease-in-out;
background: none !important;
border-bottom: 2px solid var(--b3-theme-on-background) !important;
}
/* 悬浮高亮挖空显示文字的样式 */
.b3-typography mark:hover,
.b3-typography span[data-type~=mark]:hover,
.protyle-wysiwyg mark:hover,
.protyle-wysiwyg span[data-type~='mark']:hover {
color: var(--b3-protyle-inline-mark-color) !important;
transition: color 0.5s ease-in-out;
}
如果你只是希望导出 pdf 的挖空样式是黑色下划线,在思源里还是原来的高亮样式,可以单独对 #preview .protyle-wysiwyg span[data-type~='mark']
设置样式
/* 高亮挖空的样式 */
.b3-typography mark,
.b3-typography span[data-type~=mark],
.protyle-wysiwyg mark,
.protyle-wysiwyg span[data-type~='mark'] {
color: transparent !important;
transition: color 0.5s ease-in-out;
}
/* 悬浮高亮挖空显示文字的样式 */
.b3-typography mark:hover,
.b3-typography span[data-type~=mark]:hover,
.protyle-wysiwyg mark:hover,
.protyle-wysiwyg span[data-type~='mark']:hover {
color: var(--b3-protyle-inline-mark-color) !important;
transition: color 0.5s ease-in-out;
}
/* 导出pdf时高亮挖空的样式 */
#preview .protyle-wysiwyg span[data-type~='mark'] {
color: transparent !important;
border-bottom: 2px solid var(--b3-theme-on-background);
}
❤ 用爱发电
穷苦研究生在读ing,如果喜欢我的插件,欢迎给 GitHub 仓库点 star 和捐赠,这会激励我继续完善此插件和开发新插件。
🔗 参考
-
- 是点击显示高亮文本,更复杂,不过我觉得悬浮是不是更好用些
📒 开发笔记
添加 icon
// 添加icon
this.addIcons(`<symbol id="iconMarkHide" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160">
<path d="M134,100v34H26v-34h-12v46h132v-46h-12Z" style="fill: #212121;"/>
<path d="M62,89h36l8,21h14L87,30h-14l-33,80h14s8-21,8-21ZM80,43l14,36h-28l14-36Z" style="fill: #212121;"/>
</symbol>`);
添加顶部按钮
学习
- 发现 this.addTopBar 可以返回一个
topBarElement
,然后click
函数里是可以直接对topBarElement
进行样式修改的! - 为了点击按钮,就隐藏高亮文字,直接给 body 添加一个属性
custom-highlight-hidden
,css 只对有custom-highlight-hidden
的 body 进行作用,这样就不用 js 来querySelectorAll
了!
// 添加顶部栏按钮
const topBarElement = this.addTopBar({
icon: "iconMarkHide",
title: this.i18n.hide,
position: "right",
callback: () => {
if (topBarElement.style.backgroundColor === 'transparent' || !topBarElement.style.backgroundColor) {
topBarElement.style.backgroundColor = "var(--b3-toolbar-hover)";
document.body.classList.add('custom-highlight-hidden');
topBarElement.setAttribute('aria-label', this.i18n.show);
} else {
topBarElement.style.backgroundColor = 'transparent';
document.body.classList.remove('custom-highlight-hidden');
topBarElement.setAttribute('aria-label', this.i18n.hide);
}
}
});
如何让导出 pdf 也能用高亮挖空样式
弃用外部 css 方案,直接在 head 添加 style,id 设置为'snippetCSS-Markhide',这样启用高亮挖空模式,导出 pdf 也能用(发现必须要 snippetCSS 开头才行,来模拟代码片段样式)
this.styleElement = document.createElement('style');
this.styleElement.id = 'snippetCSS-Markhide';
document.head.appendChild(this.styleElement);
...
// Modify top bar callback
const topBarElement = this.addTopBar({
icon: "iconMarkHide",
title: this.i18n.hide,
position: "right",
callback: async () => {
if (!this.isActive) {
topBarElement.style.backgroundColor = "var(--b3-toolbar-hover)";
this.isActive = true;
this.styleElement.textContent = this.HIDE_STYLES;
topBarElement.setAttribute('aria-label', this.i18n.show);
} else {
topBarElement.style.backgroundColor = 'transparent';
this.isActive = false;
this.styleElement.textContent = '';
topBarElement.setAttribute('aria-label', this.i18n.hide);
}
}
});
}
css 样式
private readonly HIDE_STYLES = `/* 高亮挖空的样式 */
.b3-typography mark,
.b3-typography span[data-type~=mark],
.protyle-wysiwyg mark,
.protyle-wysiwyg span[data-type~='mark'] {
color: transparent !important;
transition: color 0.5s ease-in-out;
}
/* 悬浮高亮挖空显示文字的样式 */
.b3-typography mark:hover,
.b3-typography span[data-type~=mark]:hover,
.protyle-wysiwyg mark:hover,
.protyle-wysiwyg span[data-type~='mark']:hover {
color: var(--b3-protyle-inline-mark-color) !important;
transition: color 0.5s ease-in-out;
}
`;
如何添加自定义 css 的设置,并在设置保存时就刷新 css
方案:
- 添加设置:用 SettingUtils 添加 textarea,考虑到 css 很多行,修改默认的 rows=20,这样能完全显示 css 内容
- 设置保存时就刷新 css:添加 callback,保存时,调用
this.updateCSS
updateCSS(css: string) {
if (this.isActive) {
this.styleElement.textContent = css;
}
}
···
async onload() {
this.settingUtils = new SettingUtils({
plugin: this,
name: STORAGE_NAME,
});
this.settingUtils.addItem({
key: "css",
value: this.HIDE_STYLES,
type: "textarea",
title: this.i18n.settings.css.title,
description: this.i18n.settings.css.description,
action: {
callback: () => {
const newCSS = this.settingUtils.take('css');
if (newCSS) {
this.updateCSS(newCSS);
}
}
}
});
}
设置添加一个重置按钮,可以重置修改的 css
创建默认设置变量
export default class MarkHide extends Plugin {
private readonly HIDE_STYLES = `/* 高亮挖空的样式 */
.b3-typography mark,
.b3-typography span[data-type~=mark],
.protyle-wysiwyg mark,
.protyle-wysiwyg span[data-type~='mark'] {
color: transparent !important;
transition: color 0.5s ease-in-out;
}
/* 悬浮高亮挖空显示文字的样式 */
.b3-typography mark:hover,
.b3-typography span[data-type~=mark]:hover,
.protyle-wysiwyg mark:hover,
.protyle-wysiwyg span[data-type~='mark']:hover {
color: var(--b3-protyle-inline-mark-color) !important;
transition: color 0.5s ease-in-out;
}
`;
private getDefaultSettings() {
return {
css: this.HIDE_STYLES,
};
}
}
添加一个重置按钮
async onload() {
// Reset Settings Button
this.settingUtils.addItem({
key: "resetConfig",
value: "",
type: "button",
title: this.i18n.settings.reset?.title || "Reset Settings",
description: this.i18n.settings.reset?.description || "Reset all settings to default values",
button: {
label: this.i18n.settings.reset?.label || "Reset",
callback: async () => {
const defaultSettings = this.getDefaultSettings();
// Update each setting item's value and UI element 只是UI改了,json的值没有改,所以不点击保存可以反悔
for (const [key, value] of Object.entries(defaultSettings)) {
await this.settingUtils.set(key, '');
// 等0.2秒,有一个刷新效果
await new Promise((resolve) => setTimeout(resolve, 200));
await this.settingUtils.set(key, value);
}
}
}
});
}
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于