折腾手记

运维!!运维!!

0%

使用豆包做了一个Obsidian插件

使用豆包做了一个Obsidian插件

使用豆包做了一个Obsidian插件,实现根据核心插件 文件列表 的排序方式,打开目录中前一个文件,后一个文件功能。

背景

Obsidian自带了前一个日记和后一个日记功能,但是没有在任意目录打开前一个/后一个文件功能,插件 File Tree Alternative 可以实现类似功能,但只能根据文件名排序,不够直观。

目标:实现一个根据核心插件 文件列表 排序方式,打开当前目录前一个/后一个文件的插件。

技术背景:懂一点JS,没有做过Obsidian插件,没有写过TS

最终依靠豆包,一行代码和注释也没有写,两个晚上完成了功能,运行良好。

搭建开发环境

Obsidian插件采用TS开发,豆包和Kimi给出的搭建开发环境的方法都跑不通。跟着官方文档操作一遍,能跑起来。

  1. Build a plugin - Developer Documentation,根据文档 git clone 插件样例,按照文档 npm install 需要的包
  2. npm run dev 生成 main.js,再用豆包生成的 manifest.json
  3. 在Obsidian插件目录中,新建文件夹 obsidian-previous-next-file 做为插件目录, 将 main.jsmanifest.json 符号链接到这个目录下,完成了插件安装
  4. 由于功能比较简单,源代码都在 main.ts 中,运行 npm run dev,修改源代码,可以实时反映到 main.js 中,Obsidian 中再关闭启动插件一次,就能使修改后的代码生效

manifest.json的具体内容

1
2
3
4
5
6
7
8
9
10
{
"id": "prev-next-file-plugin",
"name": "Previous & Next File Plugin",
"author": "Your Name",
"version": "0.0.3",
"minAppVersion": "0.9.0",
"description": "A plugin to open the previous or next file based on the order of Markdown files in the current file's folder (ordered by file name in descending order).",
"permissions": [],
"isDesktopOnly": false
}

和豆包交互

整个过程中,有2个点豆包不知道,人肉搜索到解决方案,再告诉豆包修改到代码中。过程中如果要小修改代码,不要自己修改,而是告诉豆包你的意图,让豆包帮你修改。

1. 如何找到核心插件文件列表的排序方式

  1. File explorer API,受到这个帖子启发,在 dev tools 里面查看
  2. app.workspace.getLeavesOfType('file-explorer')[0].view 返回一个对象,其中 .sortOrder 是排序方式,经过测试,一共6种排序方法

2. npm run build 报错,而 npm run dev 能通过

改了两个配置文件,
1. 在 `package.json` 中去掉了 `tsc -noEmit -skipLibCheck `
2. 在 `tsconfig.json` 中增加了 `noImplicitAny: false` 和 `skipLibCheck: true`

3. 和豆包的整个交互过程

一共43步,包括了所有对话,下面清单都是我对豆包讲的话,豆包的回复主要都是代码,就省略了。# 后面是补充的情况说明,不是对话的内容。

大致分为3给阶段

  1. 1-14步,生成了一个按照文件名排序,打开前一个/后一个文件的插件
  2. 15-41步,按照第三方插件 File Tree Alternatvie 排序方式,打开前一个/后一个文件
  3. 最后两步,按照核心插件 文件列表 排序方式,打开前一个/后一个文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
1. 生成一个obsidian插件,可以按照核心插件·文件列表·的文件顺序,打开前一个文件
2. main.ts:10:22 - error TS2339: Property 'openPreviousFile' does not exist on type 'PrevFilePlugin'. # 第一次生成报错,报错信息给豆包,豆包修改代码
3. 读取当前文件所在文件夹的所有markdown文件,按照文件名降序排列 # 豆包不知道怎么读取文件列表的文件顺序,退而求其次,先实现前一个/后一个文件功能
4. 再增加一个打开后一个文件的命令 # 实现了前一个文件,再增加后一个文件命令
5. 修改manifest.json相应的说明 # 说明中也增加后一个文件命令
6. 在移动app上也可以使用 # 也是修改manifest.json文件
7. main.ts:2:8 - error TS1259: Module '"path"' can only be default-imported using the 'allowSyntheticDefaultImports' flag # 报错
8. getOrderedFileList(),一直返回空数组,逻辑错误的 # 又一个报错,这个错误比较奇怪
9. 还是找不到当前目录的文件,函数一直返回空数组 # 报错
10. 有没有办法使用obsidian提供的函数返回当前文件所在文件夹的文件列表 # 报错解决不掉,询问豆包有没有其它办法
11. TypeError: Right-hand side of 'instanceof' is not an object # 继续报错
12. 还是出现上面的错误 # 继续报错
13. 找到原因了,child.extension === '.md',应该是child.extension === 'md' # 自己调试,找到原因了,错误很低级
14. 如果正序排序,代码是怎么样的 # 优化
15. 按照核心插件,文件列表的排序方式排序 # 不忘初心,还是想读取文件列表的排序方式
16. 怎样取得核心插件文件列表的排序方式 # 不忘初心
17. 怎么读取第三方插件“File Tree Alternative”的排序方式 # 豆包实在不会,尝试读取第三方插件的排序方式
18. 怎么读取第三方插件File Tree Alternative配置文件data.json的数据 # 豆包也不会,引导豆包直接读配置文件
19. File Tree Alternative的排序字段在配置data.json中的sortFilesBy和sortReverse两个字段,根据这两个字段排序 # 继续引导,这次完成的很好
20. 完善一下getPluginConfig方法
21. File Tree Alternative,实际路径为file-tree-alternative,根据实际路径修改代码,并给出完整的main.ts代码
22. file-tree-alternative还收一个排序方法file-size,根据文件大小排序,请补充代码 # 补充完整排序字典
23. file-tree-alternative的文件排序有四种方法,分别是name,created,last-update和file-size,分别对应文件名,创建时间,修改时间和文件大小,根据这四种方法修改代码 # 补充完整排序字典
24. const pluginDataPath = path.join(this.app.vault.configDir, 'plugins', 'file-tree-alternative', 'data.json');得到的配置文件路径错误 # 路径错误
25. const pluginDataPath = path.join(this.app.vault.configDir, 'plugins', 'file-tree-alternative', 'data.json');得到了obsidian安装目录,而不是vault所在的目录
26. 应该是const pluginDataPath = path.join(this.app.vault.adapter.basePath, this.app.vault.configDir, 'plugins', 'file-tree-alternative', 'data.json'); # 告诉豆包正确的方法
27. this.app.vault.configDir只返回.obsidian,
28. this.app.vault.configDir只返回.obsidian,而不是完整的路径 # 豆包不认错,和豆包讲道理
29. TypeError: aModifyTime.getTime is not a function # 报错
30. a.stat.mtime type: number # 报错
31. 考虑兼容性问题,修改代码
32. import path from 'path' 应该是import * as path from 'path' # 正确引导包
33. Cannot assign to "aCreationTime" because it is a constant # 报错
34. 去掉currentFolder instanceof this.app.vault.Folder的判断 # 报错解决不掉,相应代码意义不大,直接删掉
35. line97, Expected "}" but found ";" # 低级错误
36. 有好几处类似的错误,将, 误写成 ; 找到所有错误,并修改代码 # 低级错误,应该是步骤太多了,豆包处理不过来
37. 读取配置文件还是失败了,增加base代码 # 还是路径问题,第26步已经正确了,现在又错了
38. 修改成 const pluginDataPath = path.join(this.app.vault.adapter.basePath, this.app.vault.configDir, 'plugins', 'file-tree-alternative', 'data.json'), 测试下来能返回正确的配置文件 # 和豆包讲道理,这次豆包听进去了
39. error TS2339: Property 'basePath' does not exist on type 'DataAdapter'. # 低级错误
40. 使用npm run dev能通过,使用npm run build就报上面的错误 # 新情况,问问豆包怎么办,豆包没答出来,自己找资料,也是一个初级问题
41. error TS7006: Parameter 'child' implicitly has an 'any' type. # 低级错误,修改以后,整套代码可以正常运行,实现了读取第三方插件排序方式,打开前一个/后一个文件功能
42. 根据这个命令app.workspace.getLeavesOfType('file-explorer')[0].view.sortOrder确定排序方式 # 自己找到了怎么读取文件列表插件的排序方式
43. 返回6种排序方式,alphabetical,alphabeticalReverse,byModifiedTime,byModifiedTimeReverse,byCreatedTime,byCreatedTimeReverse,分别应对文件名,文件名倒序,编辑时间,编辑时间倒序,创建时间,创建时间倒序,按照这个逻辑修改代码 # 告诉豆包实现方法,豆包之后给出了正确代码,一次运行成功

#日期/2024-12-13