-
Notifications
You must be signed in to change notification settings - Fork 184
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
739 additions
and
0 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
--- | ||
uid: 20240629182937 | ||
title: 快速复制标题链接和内联代码 | ||
tags: [Obsidian] | ||
description: | ||
author: Moy | ||
type: tutorial | ||
draft: false | ||
editable: false | ||
modified: 20240630162130 | ||
aliases: [] | ||
create_date: 2024-06-29T18:29 | ||
modified_date: 2024-06-30T15:57 | ||
publish: true | ||
--- | ||
|
||
# 快速复制标题链接和内联代码 | ||
|
||
在使用 OB 的时候,有时候会想复制指向某个标题的引用链接。 | ||
|
||
想要的结果是:`[[笔记名称#标题|标题]]` | ||
|
||
这样的链接可以**直接跳转到这个标题所在的位置**,并且**只显示标题文本**,避免链接过长。 | ||
|
||
是否显示笔记名称的长度区别: | ||
|
||
![](https://cdn.pkmer.cn/images/202407012053309.png!pkmer) | ||
|
||
我一直的做法是先双击 `[[` 后选择一个笔记,选完之后再输入 `#` 选择页面里的一个标题,最后修改显示文本。 | ||
|
||
这样太麻烦了(尤其是有时候想要复制的页面就直接开着!),所以我写了一个 TP 脚本来**快速复制指向标题的链接**。 | ||
|
||
> [!info] Copy Block Link 插件 | ||
> 这个插件也可以实现相同的功能,甚至支持复制指向块的链接。 | ||
> 但因为缺少自定义功能,默认的链接文本太长(如上图的第二行),所以还是选择自己写脚本了。 | ||
## TP 脚本 | ||
|
||
```markdown | ||
<%* | ||
// 2024.06.05 增加了对行内代码 inline code 的兼容 | ||
|
||
function getInlineCode(str, cursor){ | ||
let start = str.lastIndexOf('`', cursor - 1); | ||
let end = str.indexOf('`', cursor); | ||
|
||
if (start === -1 || end === -1) { | ||
return null; | ||
} | ||
|
||
return str.substring(start + 1, end); | ||
} | ||
|
||
async function linkHeading() { | ||
const curView = app.workspace.activeLeaf.view; | ||
const curFile = curView.file; | ||
const curEditor = curView.editor; | ||
const curLine = curEditor.getLine(curEditor.getCursor().line); | ||
|
||
if (!curLine.startsWith('#') || !curLine.includes('# ')) { | ||
if (!curLine.includes("`")) { | ||
new Notice("当前光标处没有标题"); | ||
return; | ||
} else { | ||
const curCh = curEditor.getCursor().ch; | ||
let inlineCode = getInlineCode(curLine, curCh) | ||
if (inlineCode) { | ||
navigator.clipboard.writeText(inlineCode) | ||
new Notice("Inline Code Copied!"); | ||
return; | ||
} | ||
} | ||
} | ||
|
||
let selectedHeading = curLine.replace(/#+ /, "#") | ||
const filename = curFile.name; | ||
let linkAlias = selectedHeading.replace(/# ?/, "") | ||
|
||
let headingReferenceLink = `[[${filename}${selectedHeading}|${linkAlias}]]` | ||
|
||
navigator.clipboard.writeText(headingReferenceLink) | ||
new Notice("Heading Copied!"); | ||
} | ||
|
||
await linkHeading(); | ||
%> | ||
``` | ||
|
||
## 使用方法 | ||
|
||
在光标位于标题的时候,执行这个 TP 脚本即可复制链接。 | ||
|
||
为了更省事儿,我用 **Commander** 插件将这个命令加进了右键菜单: | ||
|
||
![](https://cdn.pkmer.cn/images/202407012053310.png!pkmer) | ||
|
||
这样可以直接右键点击标题并复制: | ||
|
||
![](https://cdn.pkmer.cn/images/202407012053311.gif!pkmer) | ||
|
||
## 拓展用法:复制内联代码 ✨ | ||
|
||
在 OB 内我们有时候会写像是 `print("Hello world")` 这样的内联代码。 | ||
|
||
但想要复制的时候,还得小心翼翼选中两个 \` 符号中间的文本内容,很麻烦。 | ||
|
||
所以,干脆给这个脚本额外加了一个功能—— | ||
|
||
如果对内联代码执行,就会**只复制代码本身内容**。 | ||
|
||
这样在需要复制 Inline code 的时候就很方便。 |
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,273 @@ | ||
--- | ||
uid: 20240629212603 | ||
title: 分享一种好看的月历做法 | ||
tags: [Obsidian] | ||
description: 如何在 Obsidian 里做一个好看又实用的月份显示(适用于年度笔记)。 | ||
author: Moy | ||
type: practice | ||
draft: false | ||
editable: false | ||
modified: 20240701210544 | ||
|
||
--- | ||
|
||
# 分享一种好看的月历做法 | ||
|
||
起因是最近在做 Obsidian 里的**年度笔记**。 | ||
|
||
想要在笔记里展示各个月份,方便点进每个月的**月度笔记**。 | ||
|
||
一开始直接写的链接,像是这样: | ||
|
||
```markdown | ||
上半年:[[2024年1月|1月]] [[2024年2月|2月]] [[2024年3月|3月]] [[2024年4月|4月]] [[2024年5月|5月]] [[2024年6月|6月]] | ||
下半年:[[2024年7月|7月]] [[2024年8月|8月]] [[2024年9月|9月]] [[2024年10月|10月]] [[2024年11月|11月]] [[2024年21月|12月]] | ||
``` | ||
|
||
有两个问题: | ||
|
||
1. 写起来麻烦,要自己一个个写 | ||
2. 丑 | ||
|
||
所以稍微折腾了一下,用 Dataview 做了个更好看的月历,效果如图: | ||
|
||
![](https://cdn.pkmer.cn/images/202407012053614.png!pkmer) | ||
|
||
这是按钮(其实是链接)实际交互起来的演示: | ||
|
||
![](https://cdn.pkmer.cn/images/202407012053615.gif!pkmer) | ||
|
||
每个月份笔记本质上都是个链接,所以可以直接显示悬浮预览/浮动编辑窗,或是右键用不同方式打开: | ||
|
||
![](https://cdn.pkmer.cn/images/202407012053616.png!pkmer) | ||
|
||
> [!info] 依赖插件 Dataview | ||
> 这个东西用了 Dataview 插件,并且需要开启 Dataview 插件里的 JS 代码功能(Enable Javascript Queries) | ||
> ~~不会有人用 OB 不装 DV 吧~~ | ||
## 制作方法 | ||
|
||
其实非常简单,大概是两个步骤: | ||
|
||
1. 粘贴下面的 Dataview js 代码片段,并根据自己的笔记情况修改几个参数 | ||
2. 添加 css 样式 | ||
|
||
### Dataview js 代码 | ||
|
||
````js | ||
```dataviewjs | ||
// 0. 从当前文件获取年份,或者直接填写变量 | ||
let year = dv.current().year || 2024 | ||
// 1. 这里是你的月份笔记的基础路径 | ||
const baseFolder = `PeriodicNote/Monthly/${year}年` | ||
// 当前月份的前缀和后缀 | ||
let prefix = "" | ||
let suffix = "" | ||
let content = "" | ||
for (let i=0; i < 12; i++) { | ||
let monthNum = i+1 | ||
let monthName = `${monthNum}月` | ||
let cssClasses = "internal-link monthly-btn ready" | ||
if (monthNum == dv.func.dateformat(dv.date('now'), "M")) { | ||
monthName = `${prefix}${monthName}${suffix}` | ||
cssClasses += " current-month" | ||
} | ||
// 2. 这里是你的月份笔记的路径 | ||
const monthlyNote = `${baseFolder}/${year}年${monthNum}月/${year}年${monthNum}月` | ||
let isExist = app.vault.getAbstractFileByPath(monthlyNote+".md") | ||
if (!isExist) { | ||
cssClasses += " not-exist" | ||
} | ||
content += `<a class="${cssClasses}" href="${monthlyNote}">${monthName}</a>` | ||
if (i % 3 === 2) { | ||
// content += " <br>" | ||
dv.el("div", `<div class="breadcrumbs-wrapper"> ${content} </div>`); | ||
content = "" | ||
} | ||
} | ||
``` | ||
```` | ||
|
||
粘贴这一段之后,你应该就能看到基本的视图了。 | ||
|
||
![](https://cdn.pkmer.cn/images/202407012053617.png!pkmer) | ||
|
||
丑丑的,缩成一团。 | ||
|
||
但是别担心,之后我们会用 css 来美化它。 | ||
|
||
首先要解决的问题是:这些链接都还是无效的。 | ||
|
||
你需要修改几个地方让它们能指向实际的月度笔记路径。 | ||
|
||
#### 年份 | ||
|
||
> `// 0. 从当前文件获取年份,或者直接填写变量` | ||
你有两种办法指定年份,其一是在当前笔记添加一个 `year` 属性,并填写当前的年份。 | ||
|
||
![](https://cdn.pkmer.cn/images/202407012053618.png!pkmer) | ||
|
||
其二是直接写在代码里,修改 `||` 后面的数字即可: | ||
|
||
```js | ||
// 0. 从当前文件获取年份,或者直接填写变量 | ||
let year = dv.current().year || 2066 | ||
``` | ||
|
||
两种办法的区别是:前者可以直接复制这个代码片段到任何笔记里,自动读取笔记的年份属性(比如每年的年度笔记都可以用这份代码);而后者则需要自己手动修改代码里的年份变量。 | ||
|
||
#### 文件夹 | ||
|
||
> `// 1. 这里是你的月份笔记的基础路径` | ||
在这个位置把 `baseFolder` 修改成你的月份笔记的基础路径,其中 `${year}` 代表你在属性里填写的年份。 | ||
|
||
比如文件夹如果是 `月度笔记/2024年/` 就写成: | ||
|
||
```js | ||
// 1. 这里是你的月份笔记的基础路径 | ||
const baseFolder = `月度笔记/${year}年` | ||
``` | ||
|
||
### 文件名 | ||
|
||
> `// 2. 这里是你的月份笔记的路径` | ||
这个位置则是修改你实际的月度笔记完整路径,其中 `${year}` 和 `${monthNum}` 会被替换成实际的年份和月份,然后 `${baseFolder}` 就是上面填写的那个基础路径。 | ||
|
||
比如完整路径如果是 `月度笔记/2024年/1月.md`,这里就写成: | ||
|
||
```js | ||
// 2. 这里是你的月份笔记的路径 | ||
const monthlyNote = `${baseFolder}/${monthNum}月` | ||
|
||
``` | ||
|
||
这样改完之后,每个笔记应该都能正确工作了。 | ||
|
||
你可以点击按钮打开某个笔记,或者鼠标停在上面来查看悬浮预览。 | ||
|
||
### 题外话:关于用到的函数 | ||
|
||
写到的时候用到了几个函数,这里也简单介绍一下。 | ||
|
||
`dv.func.dateformat()` 可以获得指定格式的日期(但是用 `momentJS` 或者 `datetime` 也 OK);配合 `dv.date('now')` 可以获得当前的时间。 | ||
|
||
所以结合起来,`dv.func.dateformat(dv.date('now', "M")` 就可以获得当前的月份,并进行对比。 | ||
|
||
dvjs 函数介绍:[Functions - Dataview](https://blacksmithgu.github.io/obsidian-dataview/reference/functions/#datetext-format) | ||
> 顺便,如果想在 DV 外部调用 dataview 函数(比如做测试),可以用 `app.plugins.plugins["dataview"].api.func` 获取函数。 | ||
> 对于 Templater 插件也可以类似地用 `app.plugins.plugins["templater-obsidian"].templater.current_functions_object` 获取到 TP 的各种函数。 | ||
另外还用到了 OB 原生的函数 `app.vault.getAbstractFileByFile()` 用来判断文件是否存在,并根据结果来分配 css 变量。 | ||
|
||
### CSS 样式 | ||
|
||
接下来是美化时间! | ||
|
||
粘贴以下 CSS 片段到你的 css snippets 内: | ||
|
||
```css | ||
/* 月历按钮美化.css */ | ||
|
||
/* 整体布局 */ | ||
.breadcrumbs-wrapper { | ||
display: flex; | ||
justify-content: space-around; | ||
margin-bottom: 25px; | ||
height: 48px; | ||
} | ||
|
||
/* 每月按钮做的样式 */ | ||
.ready.monthly-btn { | ||
display: inline-block; | ||
padding: 0.18rem 1.8rem; | ||
/*font-size: 16px;*/ | ||
font-weight: 500; | ||
color: var(--text-normal); | ||
border: 3px solid var(--color-accent); | ||
cursor: pointer; | ||
position: relative; | ||
background-color: transparent; | ||
text-decoration: none; | ||
overflow: hidden; | ||
z-index: 1; | ||
font-family: inherit; | ||
|
||
/*固定按钮大小并居中文本*/ | ||
width: 6em; | ||
text-align: center; | ||
|
||
transition: color .3s; | ||
} | ||
|
||
/* 当前月份的按钮的特殊样式 */ | ||
.ready.monthly-btn.current-month { | ||
color: var(--text-accent-hover) !important; | ||
} | ||
|
||
/* 尚未创建按钮的特殊样式 */ | ||
.ready.monthly-btn.not-exist { | ||
color: var(--text-muted) !important; | ||
} | ||
|
||
/* 浮动的效果 */ | ||
.ready.monthly-btn::before { | ||
content: ""; | ||
position: absolute; | ||
left: 0; | ||
top: 0; | ||
width: 100%; | ||
height: 100%; | ||
background-color: var(--color-accent); | ||
transform: translateX(-100%); | ||
z-index: -1; | ||
|
||
transition: all .3s; | ||
} | ||
|
||
.ready.monthly-btn:hover { | ||
color: var(--background-primary) !important; | ||
} | ||
|
||
.ready.monthly-btn:hover::before { | ||
transform: translateX(0); | ||
} | ||
|
||
|
||
``` | ||
|
||
> [!info] CSS 片段 | ||
> 如果你不知道啥是 css 片段,参考文档:[PKMer_Obsidian 的 CSS 代码片段]( https://pkmer.cn/show/20230329145845 ) | ||
如果你不喜欢这个样式,也可以去类似 [零代码 - 精美CSS样式库](https://www.lingdaima.com/css/#/) 这样的网站找到自己喜欢的样式,然后替换上面的 CSS 片段。 | ||
|
||
例如找到一个想要的按钮,复制它的 css 片段: | ||
|
||
![](https://cdn.pkmer.cn/images/202407012053619.png!pkmer) | ||
|
||
然后将片段里的 `button` 都替换成 `.ready.monthly-btn` 就可以了! | ||
|
||
## 特别说明 | ||
|
||
这段代码的最初灵感——以及排列的样式——都来自木一 Benature 的示例库! | ||
|
||
![](https://cdn.pkmer.cn/images/202407012053620.png!pkmer) | ||
|
||
(日记里的前后按钮) | ||
|
||
木一大佬的示例库让我学到了炒鸡多,感兴趣的话也可以前去查看: | ||
|
||
[Benature/obsidian-sample-vault](https://github.com/Benature/obsidian-sample-vault) |
Oops, something went wrong.