【Obsidian样式】调整Html的detail样式为简单评论区

样式效果

通过修改 Html 语法中的 <details>评论区</details> 语法的样式来使它更像一个评论信息。

注意事项

存在问题:
一般来 <details>评论区</details> 里面不支持 ob 的语法格式,单纯以文本形式展出,也就是不支持图片、双链、Markdown 语法等,只支持 Html 语法。

如何实现渲染

如果 <details> 在一个文本段落中可以渲染包括图片甚至是嵌入文档的渲染:

源码模式:

阅读模式:

实时模式直接隐藏:


实时模式我是直接隐藏不见的,鼠标放到注释区域才会显示,如果需要显示的话请自行修改 CSS 文件。

如何快捷输入

最好给 <details> 里面的添加标签,方便后期检索

注释选中的文本 by QuickAdd

效果

PixPin_2023-12-30_00-15-31

配置

配置 QuickAdd 的 Capture:

=={{selected}}==<details>#Details<br>{{mvalue}}</details>

配置高级输入框 (可添加标签) by QuickAdd + Modal Forms

效果

PixPin_2023-12-30_00-34-02

配置

配合 QuickAdd + Modal Forms 这 2 个插件使用,Modal Forms 的只需安装即可,QuickAdd 配置 Capture:

```js quickadd
// 🔴修改Zotero路径即可
const folderPath = 'D:/Zotero/storage';
const fs = require('fs');
const modalForm = app.plugins.plugins.modalforms.api;
const files = fs.readdirSync(folderPath);
const zoteroItems = [];

let selection = window.getSelection();
selection = selection.toString();

files.forEach((file) => {
	const filePath = `${folderPath}/${file}`;
	const stat = fs.statSync(filePath);
	if (stat.isDirectory()) {
		const subFiles = fs.readdirSync(filePath);
		const pdfFiles = subFiles.filter((subFile) => subFile.endsWith('.pdf')).map((pdfFile) => pdfFile.replace('.pdf', ''));

		if (pdfFiles.length > 0) {
			const zoteroItem = {};
			zoteroItem["item"] = file;
			zoteroItem["link"] = `zotero://open-pdf/library/items/${file}`;
			zoteroItem["file"] = pdfFiles[0];
			zoteroItems.push(zoteroItem);
		}
	}
});

console.log(zoteroItems);
let zoteroItemNames = [];

zoteroItems.forEach((item) => {
	zoteroItemNames.push(item["file"]);
});

// console.log(zoteroItemNames)
const values = {
	ZoteroCites: selection,
};

const result = await modalForm.openForm({
	title: "zoteroModalForms",
	name: "zoteroModalForms",
	version: "1",
	fields: [
		{
			name: "ZoteroCites",
			label: "通过引用匹配对应的Items",
			description: "引用格式需要IEEE格式",
			input: {
				type: "textarea"
			}
		},
		{
			name: "ZoteroItems",
			label: "",
			description: "",
			input: {
				type: "multiselect",
				source: "fixed",
				multi_select_options: zoteroItemNames,
			}
		},

	]
}, {values:values});

let getZoteroItems = result.getValue('ZoteroItems').value;
let getZoteroCites = result.getValue('ZoteroCites').value;

if (getZoteroCites) {
	getZoteroItems = getZoteroItems.concat(matchZoteroItems(getZoteroCites));

}
console.log(getZoteroItems);

let zoteroItemsLinks = [];

getZoteroItems.forEach((item) => {
	// const foundItem = zoteroItems.find((zoteroItem) => zoteroItem["file"].includes(item.substring(0, 10)));
	const foundItem = zoteroItems.find((zoteroItem) => {
		const similarityThreshold = 0.3; // 相似度阈值
		const similarity = 1 - levenshteinDistance(zoteroItem["file"], item) / Math.max(zoteroItem["file"].length, item.length);
		return similarity >= similarityThreshold;
	});
	if (foundItem) {
		const zoteroLink = `[《${item}》](${foundItem["link"]})`;
		zoteroItemsLinks.push(zoteroLink);
	}
});

if (zoteroItemsLinks.length) {
	const output = zoteroItemsLinks.join("\n");
	console.log(output);
	return output;
}

function matchZoteroItems(text) {
	const regex = /《(.*?)》/gm;
	const matches = text.match(regex);
	return matches ? matches.map(match => match.slice(1, -1)) : "";
}

function levenshteinDistance(a, b) {
	// Levenshtein距离计算相似度 by ChatGPT @2024-01-04 
	const m = a.length;
	const n = b.length;
	const dp = Array.from(Array(m + 1), () => Array(n + 1).fill(0));

	for (let i = 0; i <= m; i++) {
		dp[i][0] = i;
	}

	for (let j = 0; j <= n; j++) {
		dp[0][j] = j;
	}

	for (let i = 1; i <= m; i++) {
		for (let j = 1; j <= n; j++) {
			if (a[i - 1] === b[j - 1]) {
				dp[i][j] = dp[i - 1][j - 1];
			} else {
				dp[i][j] = Math.min(
					dp[i - 1][j] + 1, // 删除操作
					dp[i][j - 1] + 1, // 插入操作
					dp[i - 1][j - 1] + 1 // 替换操作
				);
			}
		}
	}

	return dp[m][n];
}
```

CSS 代码

/* ! details 样式修改 */
/* 2023-12-13 details样式修改 */
.theme-light .markdown-preview-view details {
  background-color: rgba(252, 255, 203, 0.9);
}
.theme-dark .markdown-preview-view details {
  background-color: rgba(56, 55, 56, 0.9);
}

.markdown-source-view.mod-cm6 details {
  display: none;
}

/* 在better-search-views中正常显示 */
.markdown-preview-view:not(.better-search-views-file-match.markdown-rendered)
  details {
  position: absolute;
  font-weight: lighter;
  font-size: smaller;
  border-width: 1px;
  border-style: solid;
  border-radius: 10px;
  padding: 2px 3px 2px 3px;
  display: block;
  transform: translateY(-3rem);
  z-index: 1;
  border-inline-start: 5px solid;
  white-space: pre-wrap;
}

.markdown-preview-view:not(.better-search-views-file-match.markdown-rendered)
  details[open] {
  max-width: 500px;
  max-height: 400px;
  overflow: auto;
  z-index: 2;
}

details:not(details[open]) {
  right: 1rem;
  min-width: 20px;
}

:not(.callout-content)details[open] {
  max-width: 400px;
  z-index: 2;
}

details[open],
.popover.hover-editor details,
:not(.callout-conten) details {
  right: 1rem;
}

/* 在callout中不生效 */
.callout-content details[open] {
  transform: translateX(1rem) !important;
  position: relative !important;
  max-width: unset !important;
}

8 个赞

大佬好,我根据教程设完以后,添加批注显示是这样:
image
点击详情后,变成这样:
image
请问怎么将批注设成悬浮框的样式啊?

:+1: :ox::beer:++

CSS代码这个放入Obsidian Snippets片段中生效即可,不过我目前没用了。可能比较复杂,你可以用下有大佬制作的边注类型的Callout样式,详见:Obsidian 样式 - 用 Callout 实现的边注(注释)

这个css只能在阅读视图的模式生效,但我平时都是常开实时预览的,请问大佬有方法在阅读视图生效吗?另外我就是从边注那里找过来的,因为有一些需要平时隐藏的长文本注释需求,感觉大佬这个css和边注能很好的相互补充,各有千秋。

好像没法实时模式 就算你想点击展开也会一下变成源码

好的,感谢大佬解答。

好像达不到所演示的效果

具体的代码应该如何设置

emmm 没啥用,不建议使用了,我之后会删除文章吧

可以实现,之所以点击展开会变成源码是因为obsidian会监听光标焦点事件将任何“正在编辑”的部分转换回源码。解决方式就是通过JavaScript移除事件

为注释添加id或class:

<details class="abc">注释</details>

使用DataviewJS或其他JavaScript工具执行下面的代码:

let element = document.querySelector(".abc");
element.addEventListener("click",event => event.stopImmediatePropagation(),true);

酌情修改程序以便适应插件。