block-link-plus 开发备忘 & 小记

  • block-link-plus 开发和提交过程的一些记录

  • 更新

    1
    2
    24.07.16 初始化
    24.08.23 更新

导语

个人的第一个 obsidian 插件 block-link-plus 几经波折终于完了, 此文是一些记录和备忘,非完整教程.

  • 据 log 统计,开发思路中断了 x3, 历时 4 个月 (真正写完就周末两天), 目前于官方上架流程中; 官方已合入.
    • Add plugin: Block Link Plus

Obsidian 的块引用 不支持跨行引用, 个人又非常容易写废话…就挺 ≧ ﹏ ≦ 开始各种寻找解决方案.

历程

Block Reference for multiple paragraph 多行/段 的官方论坛的讨论

  • 跨度从 Oct 2020 一直到今年 Mar 28, 说明这个需求一直存在的.
  • 但是这个 FR 也一直开着, 可能官方暂时不会有这方面动作了.

原初 0.1: 心很大

  • 干脆拓展官方语法: ˅ Unicode 02C5 极少重复.在两个 link 中间的行为一个 跨行块.
  • 空格 or 首行 + ˅link/^link + 空格 or 换行 | 都在行的结尾
1
2
3
˅link
xxx
^link
  • 这样的好处是不影响 obsidian 现有块跳转, 但是为何官方/其他开发者为何不写呢? 你猜猜? /笑/, 不管你猜不猜, 当时我反正没猜😥

一个猛子扎进了深渊, 可行性评估完全没做. 于是浪费了大量时间, 最终结论是: 现在自己业余 TS 开发做不了.

  • 更深入分析可以参考: Markdown 实现块级引用双向链接的探索
  • 拓展新语法, 修改解析器涉及到了从 MD 文件解析得到 AST 再到 HTML, 这中间那个都不是业余玩家能短期入手的.

教训 1: 天马行空的想法落地, 可行性调查先行.

  • 同类插件, 同类产品
  • 可能的成本, 业余玩家能够投入的成本是否足够.

原初 0.2: 纯添加新 heading 如何?

  • 使用 [file#˅id] ## ˅id ## ^id 整体作为 title
  • 通过分析选中文本段 [start_line,end_lien] 前后和段中的 heading 层级,添加合适的 heading 层级, 是不是就能做到多段的引用了 😊, 为自己的想法点赞!
1
2
3
4
5
## ˅id
xxx
## ^id

[[file#˅id]]

🧠热了, 乘势追击,写完了大部分功能,然后发现了如下缺陷:

  • 这种标记方式本质上,无法应用于下面这样, 没法引用 2-4 这样, 因为会被 # level = 1 的截断;
1
2
3
4
5
6
# dayly 
1
2
# define
3
4
  • 而且会破坏已有的 ![[file#title]] 的块嵌入.
    boom 💣💣

教训 2

  • 拖了太久,有了思路, 行动比🧠快…

原初 0.3

  • 冷静下梳理需求: 自己的需要仅仅是能在目标区域嵌入多行/段;
    • 多行/段 要么是一个完整的标题, 要么是一个不包含 heading 的纯文本段.
  • 思路确定了: 在 copy-block-link 基础上, 为多行文本添加合适层级的 heading.

不需要做更多工作, 不需要完备, 简单的想法,快速实践, 尽快进入: 开发 - 反馈 - 开发 - 反馈的循环.

  • 这是最符合本人节奏的开发方式, 就不是大局观的那种人, 何必违背自己的性格,患得患失, 反而浪费了很多时间.

目前就 1.5 个功能:

  • 多行文本块
  • 自定义 block id

多行文本块

这里限定, 选中文本中间不能有 heading, 不符合这个要求,直接提示报错.

为选中文本添加一个层级合适的 heading, 拷贝 [[file#˅id]]

1
2
3
4
5
6
## ˅id
abc
def
## ^id

[[file#˅id]]

第二种创建多个块引用: 批量创建多组块引用并拷贝到剪贴板.

  • 此功能来自 @Text Transporter
1
2
3
4
5
6
7
8
9
abc ^id1

def ^id2

gh ^id3

[[file#^id1]]
[[file#^id2]]
[[file#^id3]]

自定义 Block Id

Block ID = 前缀 - 随机字符

  • 自定义 block ID 的前缀 和 随机字符的长度 (3-7)

现在这个功能尚未有更多的实际用途, 或许可以通过 block ID 的前缀进行更多的聚合操作.


正在研究 dataview, 个人期望效果是:

  • 在今天日记中一个查询语句聚合所有 # 3.7 ## 3.7 ### 3.7,如同块嵌入效果一样.
  • 对应 block id 前缀可以配合日期/时间, 聚合时候能够筛选具体时间段的 block.

开发

这一节是流水账, 可能只有自己看看吧 (⓿_⓿)

Obsidian Developer Docs 官方文档自然是最开始的入口.

  • 按照 Build a plugin 搭建相关环境
  • 大致浏览 Plugins 内容

之后只需要 Ctrl-C Ctrl-V 不是, 最快的学习自然是已有的开源插件了, 这里开发过程中包括参考了大量插件代码, 包括但不限于

  • copy-block-link
  • Text Transporter
  • rendered-block-link-suggestions
  • linkify

小到如何弹出一个通知, 大到如何修改阅读模式渲染内容, 总有一款插件的某一段代码能够参考……

代码优化 / debug / 单元测试 / code review 则是 copilot 全程.

  • 题外话: gpt 在思路阶段,出现幻觉特别多, 因此浪费了大量时间, 或许创意方面, 这是目前大模型的极限, 因此还是需要实时核查信息准确性.

调试工具

  • Ctrl Shift + I obsdian 进入调试模式, f5 刷新重新加载
  • hot-reload 自动化加载
  • [[Obsidian 记录#[Obsidian42 BRAT](https <//github.com/TfTHacker/obsidian42-brat>)|Obsidian42 BRAT]] 发布 release 后, 上架前加载插件.

发布 release

  • 核心是 main.js manifest.json styles.css

插件思路

如何创建菜单, 如何弹出通知不提, 只记录一个点: 如何确认插入 heading 的层级?

首先需要获取到选中文本的 start_lineend_line:

我们还需要所有 heading 在那一行, 具体层级是多少才.需要的信息都在 fileCache: CachedMetadata

  • sections 包含了全部的可渲染段 (?) heading 表格 代码块等都在其中;
    • 每个成员都有 ‘type’ 字段, 用于确认其到底是什么类型;
  • headings? 包含了所有的 heading, 每个 heading 包含了哪一行, level 是多少, level 是从 0 开始和 # 号数量一致.
  • blocks? 则包含了所有块引用的链接.

然后后面就是各种搜索 headings? 比较各种 heading 的 level 了…不加赘述…

上架

官方的上架流程全在 obsidian-releasesSubmit your plugin

真的非常非常全, 手把手教学, 我再多写一句就是废话了.

结语

开始下半年的了结计划, 之前欠下的, 一半又停工的, 还有很多很多😒😒😒