遇到的问题
上一条提出这个问题的貌似还是23年3月。
简单来说,就是,在obsidian中添加html格式的跳转锚点是无效的(但是之前用过的所有md编辑器都支持这一点)。虽然自然是可以用大标题跳转但是还是让我非常不快,而且总不能在跳转的地方全都加一个大标题吧。写非常大段的说明文档时这一点非常伤。
上一次提出这个问题的帖子也是用跳转标题解决的,想问一下时隔一年多有没有更好的解决方案……官方看上去是已经不理这个问题了。
上一条提出这个问题的貌似还是23年3月。
简单来说,就是,在obsidian中添加html格式的跳转锚点是无效的(但是之前用过的所有md编辑器都支持这一点)。虽然自然是可以用大标题跳转但是还是让我非常不快,而且总不能在跳转的地方全都加一个大标题吧。写非常大段的说明文档时这一点非常伤。
上一次提出这个问题的帖子也是用跳转标题解决的,想问一下时隔一年多有没有更好的解决方案……官方看上去是已经不理这个问题了。
类似的似乎是用块链接,然后跳转到对应的块
是像之前加上^tag 这样的方式吗,我去试试看。但是说实在话跳转本身需要加个块本身也让人多少感觉有点不适应(手头有很多文档都要改成那样了挺烦的)
自己顶一顶,下午写文档的时候仍然觉得很痛苦,真的没有其他解决方法了嘛
你对跳转有什么很高的需求么,为什么说明性文档不能使用标题的形式;而且一共有6种标题,大标题确实可能影响排版但是可以用小一点的?
主要还是,原本他就只是在文章中出现的一个小字眼,比方说一个名字,文章中出现了,总不能把这名字写成一个标题吧?但是我又希望能在文章开头点击这个名字他就能跳转到这个地方。
其他的还有挺多需求,然后为了追求最大md兼容性我是最希望使用html跳转的,但是结果没想到居然用不了。看有些人说是用自带的引用,但是我是真不喜欢我的笔记和软件强绑定……那不就和思源是一个套路了么?
好的,我之后去用一下。主要是我写的文档一般不只是给自己看,所以确实想希望别人用自己的软件打开也能跳转,这样
如果需求比较大的话,还是以需求为主,你觉得其他md编辑器可以实现需求就用其他的,Obsidian毕竟也不是全能
比较接近的是outliner.md用注释来包裹文本, 要是想用html标签来包裹, 可能得照着outliner.md源码自己写一个插件出来了, 而且还得额外处理ob对链接的行为.
现在我对这问题有了些新理解
下文中:
“blockref” 指 Obsidian 里对普通段落的链接语法 ^xxx-id
“html 锚点” 指在 md 里写 html 语法 <a name="xxx" />
或者 <div id="yyy"></div>
个人觉得, 其实 blockref 就是 html 锚点的替代品, 这俩方案还有几个相似点:
blockref 在大部分情况下是够用的, 唯一的问题是跟别的工具协作时:
所以只要用最小代价把这差异消除就行了,
目前想到了这几个方案, 楼主按照自己的实际需求取舍
A 在导出时做兼容
Ob 里只用 blockref, 把兼容工作推迟到 “导出时”
大多数导出工具, 都有允许用户自己定制一些细节; 即使没让定制, 也可以在字符串层次做预处理和后处理
简单说就是在导出之前, 检测到段落最后有个 ^xxx
就给替换成 <a name="xxx" />
注: Obsidian md 转 CommonMark md, 也可以看作导出
B 两种锚点语法同时写
编辑笔记时, 同一段落里 blockref 和 html anchor 全给写上, 如
# 原先写法是
段落正文. 段落正文. 段落正文. 段落正文 ^xxx
# 全都自动替换成
<a name="xxx" /> <div id="xxx"></div> 段落正文. 段落正文. 段落正文. 段落正文 ^xxx
各家软件乐意认哪个都随便, 反正都指向同一个地方
少量的手动写就完了, 大量的考虑自动化实时替换
C 修改链接点击操作
思路是点击链接时, 先找是否存在 html 风格锚点, 找到就跳转过去, 找不到就走默认的点击行为
原理借鉴这篇帖子 在新窗口打开内链的快捷键是什么? - 疑问解答
### 链接源头
1
[[#^testanchor1]] 双链语法
2
[[#^testanchor2|别名]] 双链语法, 带别名
3
[标准 md 语法 指向页内锚点](#testanchor3)
TODO 跨笔记
### 锚点 (链接目标)
**1 链接是 最简Ob双链写法**
普通段落, Ob 风格块链接目标 ^testanchor1
自闭合 name anchor 做为锚点 <a name="testanchor1" /> 其内容形如 `<a name="xxx" />`
**2 链接里 Ob双链别名写法**
普通段落, Ob 风格块链接目标 ^testanchor2
自闭合 name anchor 做为锚点 <a name="testanchor2" /> 其内容形如 `<a name="xxx" />`
**3 链接是 标准 md 写法**
普通段落, Ob 风格块链接目标 ^testanchor3
自闭合 name anchor 做为锚点 <a name="testanchor3" /> 其内容形如 `<a name="xxx" />`
TODO 跨笔记
上面文档贴 Ob 里, 点击这些链接后 1 2 会成功, 3 会无效
然后 Ctrl+Shift+i
打开控制台, 粘贴如下脚本
async function locate_anchor_name(token, note_path) {
const anchor = `<a name="${token.startsWith('^') ? token.slice(1, ) : token}" />`;
console.log(`locating name ${anchor}`);
// debugger;
const current_content = await app.vault.read(note_path);
console.log(`current_note ${note_path}; current_content ${current_content.slice(0, 50)}`);
const paragraphs = current_content.split('\n');
for (let line = 0; line < paragraphs.length; line += 1) {
const pos = paragraphs[line].indexOf(anchor);
if (pos >= 0) {
return {
from: {line: line, ch: pos},
to: {line: line, ch: pos + anchor.length}
};
}
}
return null;
}
const originTriggerClickableToken = app.workspace.activeLeaf.view.editMode.triggerClickableToken.bind(app.workspace.activeLeaf.view.editMode);
app.workspace.activeLeaf.view.editMode.triggerClickableToken= async (e, t) => {
console.log('current e=', e);
console.log('current t=', t);
if (e && e.type==='internal-link' && e.text.startsWith('#')) {
const current_note = app.workspace.getActiveFile();
const token = e.text.slice(1, );
const selection = await locate_anchor_name(token, current_note);
if (selection) {
console.log('loc', selection);
const editor = app.workspace.getActiveFileView().editor;
// console.log(editor);
editor.setCursor({ line: selection.from.line, ch: 0});
editor.transaction({
selection: selection,
});
editor.scrollIntoView(selection, true);
} else {
// 调用原有函数
originTriggerClickableToken(e, t);
}
}
}
此后再次点击测试链接, 则 1 2 3 都会成功, 且有歧义时会优先寻找 html 锚点
注: 仅支持实时阅览模式, 仅支持同笔记里导航,
脚本我写的不好, 只是提供一种思路, 这想要写完善了, 得考虑许多细节
但是这思路可以顺带解决小标题的 slugify 以及 urlencoding 之类问题