diff --git "a/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Excalidraw/ExcalidrawAutomate/\350\207\252\345\256\232\344\271\211Excalidraw\350\204\232\346\234\254-\345\217\214\345\207\273\346\267\273\345\212\240\345\234\206\345\234\210\347\274\226\345\217\267.md" "b/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Excalidraw/ExcalidrawAutomate/\350\207\252\345\256\232\344\271\211Excalidraw\350\204\232\346\234\254-\345\217\214\345\207\273\346\267\273\345\212\240\345\234\206\345\234\210\347\274\226\345\217\267.md" index da4d2eae8..d1277419f 100644 --- "a/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Excalidraw/ExcalidrawAutomate/\350\207\252\345\256\232\344\271\211Excalidraw\350\204\232\346\234\254-\345\217\214\345\207\273\346\267\273\345\212\240\345\234\206\345\234\210\347\274\226\345\217\267.md" +++ "b/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Excalidraw/ExcalidrawAutomate/\350\207\252\345\256\232\344\271\211Excalidraw\350\204\232\346\234\254-\345\217\214\345\207\273\346\267\273\345\212\240\345\234\206\345\234\210\347\274\226\345\217\267.md" @@ -1,9 +1,7 @@ --- uid: 20240221010235 title: 自定义 Excalidraw 脚本 - 双击添加圆圈编号 -tags: - - Excalidraw脚本 - - 图片注释 +tags: [Excalidraw脚本, 图片注释] description: 给Excalidraw添加圆圈编号功能 author: 熊猫别熬夜,一鸣惊人 type: other @@ -18,7 +16,7 @@ modified: 20240221010515 参考了 [一鸣惊人的脚本](https://www.bilibili.com/video/BV1XZ421m74S/?share_source=copy_web&vd_source=71b5851b6744265a191d3ec972be4787) 和 大叔的 `Scribble Helper` 脚本,用于添加有序的圆圈编号。 -![2024-01-13_自定义Excalidraw脚本-编号模式-添加圆圈编号_IMG-1](https://cdn.pkmer.cn/images/202402210103272.gif!pkmer) +![自定义 Excalidraw 脚本 - 双击添加圆圈编号](https://cdn.pkmer.cn/images/202402231932575.png!pkmer) > ✅已启动编号模式,双击添加 num > ⏩双击 num 可以重新编辑编号 diff --git "a/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Excalidraw/Excalidraw\345\246\202\344\275\225\345\256\211\350\243\205\350\204\232\346\234\254_\350\204\232\346\234\254\350\256\276\347\275\256\344\273\213\347\273\215.md" "b/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Excalidraw/Excalidraw\345\246\202\344\275\225\345\256\211\350\243\205\350\204\232\346\234\254_\350\204\232\346\234\254\350\256\276\347\275\256\344\273\213\347\273\215.md" index c09023446..a9643d5d4 100644 --- "a/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Excalidraw/Excalidraw\345\246\202\344\275\225\345\256\211\350\243\205\350\204\232\346\234\254_\350\204\232\346\234\254\350\256\276\347\275\256\344\273\213\347\273\215.md" +++ "b/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Excalidraw/Excalidraw\345\246\202\344\275\225\345\256\211\350\243\205\350\204\232\346\234\254_\350\204\232\346\234\254\350\256\276\347\275\256\344\273\213\347\273\215.md" @@ -81,7 +81,7 @@ Excalidraw 插件有专门的脚本市场: #### Tip:固定按钮到侧边栏 -可以通过**“鼠标右键/鼠标左键长按”** "Obsidian 工具面板 " 的按钮,将按钮固定到 Excalidraw 侧边栏,==再次在**侧边栏**或者**工具面板**中针对按钮**“鼠标右键/鼠标左键”** 长按即可取消固定。== +可以通过**“鼠标右键/鼠标左键长按”** "Obsidian 工具面板 " 的按钮,将按钮固定到 Excalidraw 侧边栏,再次在**侧边栏**或者**工具面板**中针对按钮**“鼠标右键/鼠标左键”** 长按即可取消固定。 ![Excalidraw 如何安装脚本 + 脚本设置介绍](https://cdn.pkmer.cn/images/202312291948914.png!pkmer) @@ -101,7 +101,7 @@ Excalidraw 插件有专门的脚本市场: ### 设置脚本配置 -有些脚本有自带的配置选项,==❗需要单击第一次运行后,Excalidraw 才会加载到 Excalidraw 的插件设置里的**已安装脚本的设置**选项中==,这里面可以看到不同脚本的设置选项: +有些脚本有自带的配置选项,❗需要单击第一次运行后,Excalidraw 才会加载到 Excalidraw 的插件设置里的**已安装脚本的设置**选项中,这里面可以看到不同脚本的设置选项: ![Excalidraw 如何安装脚本 + 脚本设置介绍](https://cdn.pkmer.cn/images/202312291948917.png!pkmer) diff --git "a/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Excalidraw/\350\207\252\345\256\232\344\271\211Excalidraw\350\204\232\346\234\254-\344\270\212\344\274\240\347\224\273\346\235\277\344\270\255\347\232\204\345\233\276\347\211\207\345\210\260\345\233\276\345\272\212.md" "b/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Excalidraw/\350\207\252\345\256\232\344\271\211Excalidraw\350\204\232\346\234\254-\344\270\212\344\274\240\347\224\273\346\235\277\344\270\255\347\232\204\345\233\276\347\211\207\345\210\260\345\233\276\345\272\212.md" index 220303e97..63981a8d5 100644 --- "a/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Excalidraw/\350\207\252\345\256\232\344\271\211Excalidraw\350\204\232\346\234\254-\344\270\212\344\274\240\347\224\273\346\235\277\344\270\255\347\232\204\345\233\276\347\211\207\345\210\260\345\233\276\345\272\212.md" +++ "b/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Excalidraw/\350\207\252\345\256\232\344\271\211Excalidraw\350\204\232\346\234\254-\344\270\212\344\274\240\347\224\273\346\235\277\344\270\255\347\232\204\345\233\276\347\211\207\345\210\260\345\233\276\345\272\212.md" @@ -5,7 +5,7 @@ tags: - 图床 - Excalidraw脚本 description: Excalidraw 画板中引用的图片直接上传到 PicGo 的 Server 转为在线图片 -author: +author: 熊猫别熬夜 type: other draft: false editable: false diff --git "a/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Quickadd/QuickAdd\350\204\232\346\234\254-\345\210\251\347\224\250Canvas\345\271\263\351\223\272\347\254\224\350\256\260.md" "b/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Quickadd/QuickAdd\350\204\232\346\234\254-\345\210\251\347\224\250Canvas\345\271\263\351\223\272\347\254\224\350\256\260.md" new file mode 100644 index 000000000..e4f412cdf --- /dev/null +++ "b/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Quickadd/QuickAdd\350\204\232\346\234\254-\345\210\251\347\224\250Canvas\345\271\263\351\223\272\347\254\224\350\256\260.md" @@ -0,0 +1,408 @@ +--- +uid: 20240222233410 +title: QuickAdd 脚本 - 利用 Canvas 平铺笔记 +tags: [Canvas, quickadd脚本] +description: 利用 Canvas 平铺笔记 +author: 熊猫别熬夜 +type: other +draft: false +editable: false +modified: 20240222233822 +--- + +# QuickAdd 脚本 - 利用 Canvas 平铺笔记 + +在 Obsidian 中文论坛看到这篇 [在Excalidraw中列出某笔记所有二级Heading - 经验分享 - Obsidian 中文论坛](https://forum-zh.obsidian.md/t/topic/30401) ,我就想用 Canvas 来平铺一下,这样笔记可以全局预览和编辑。 + +## Canvas 的标题引用格式 + +Canvas 是可以只显示文档的块和标题的,具体格式如下,标题是在 `subpath` 中且前面有个 `#` 号。 + +```json +{ + "nodes":[ + {"id":"d9f2b88a08cb0f1c","type":"file","file":"QuickDraft-20240221200235533.md","subpath":"#PkmerFAQ","x":-447,"y":-333,"width":960,"height":760}, + {"id":"6b050e9a6fa81b69","type":"file","file":"QuickDraft-20240221200235533.md","subpath":"#PkmerDocs","x":560,"y":-333,"width":960,"height":760}, + {"id":"454248a7b980b488","type":"file","file":"QuickDraft-20240221200235533.md","subpath":"#Fix","x":1580,"y":-333,"width":960,"height":760}, + {"id":"207cfe3dd7b01f03","type":"file","file":"QuickDraft-20240221200235533.md","subpath":"#Fix","x":-447,"y":500,"width":960,"height":760} + ], + "edges":[] +} +``` + +## 实现过程和效果 + +![2024-02-21_QuickAdd脚本-利用Canvas平铺笔记_IMG-1](https://cdn.pkmer.cn/images/202402230946313.gif!pkmer) + +- 获取当前笔记路径 + - 提取所有标题 (可选范围,即标题参数),暂定二级标题 +- 设定间距、宽度、高度参数 +- 循环排列即生成 JSON 数据 +- 生成 canvas 即可 + +我是固定一个 Canvas 用来编辑,我这边直接随便设置的一个 `未命名.canvas`,可以 2 种模式可以相互转换,转换的参数通过代码参数来调节。 + +### 可调整的参数 + +```js +// 大纲等级 +const level = 2; +// 卡片参数 +const width = 960; +const height = 760; +// 卡片间隔 +const space = 50; +// 每行卡片的数量限制 +const limit = 4; +// 基于库的相对路径的Canvas +const canvasPath = "未命名.canvas"; +``` + +## Quickadd 配置 Macro 代码 + +将下述脚本放在 Quickadd 的配置文件夹下,保存为 `convertMdToCanvas.js` 文件,在 Quickadd 插件设置添加 Macro 动作: + +![2024-02-21_QuickAdd脚本-利用Canvas平铺笔记_IMG-2](https://cdn.pkmer.cn/images/202402230946314.png!pkmer) + +在 Scripts 中选择对应的 `convertMdToCanvas` 脚本,点击添加即可: + +![2024-02-21_QuickAdd脚本-利用Canvas平铺笔记_IMG-3](https://cdn.pkmer.cn/images/202402230946315.png!pkmer) + +### 脚本 + +```js +const path = require('path'); +const fs = require('fs'); +// 获取笔记的基本路径 +const file = app.workspace.getActiveFile(); +const fileFullPath = app.vault.adapter.getFullPath(file.path); + +// 可调节的参数 +// 大纲等级 +const level = 2; +// 卡片参数 +const width = 960; +const height = 760; +// 卡片间隔 +const space = 50; +// 每行卡片的数量限制 +const limit = 3; +// 基于库的相对路径的Canvas +const canvasPath = "未命名.canvas"; + +module.exports = async () => { + const canvasData = { + nodes: [], + edges: [] + }; + if (file.extension === 'md') { + console.log("开始获取二级标题"); + const heads = getHeadings(fileFullPath, level); + console.log(heads); + + let x = 0; + let y = 0; + let n = 1; + let nodes = []; + const length = heads.length; + + for (let i = 1; i <= length; i++) { + const node = { + id: "", + type: "file", + file: file.path, + subpath: "", + x: 0, + y: 0, + width: width, + height: height, + }; + + node.subpath = heads[i - 1]; + node.id = i; + node.x = x; + node.y = y; + console.log([heads[i - 1], x, y]); + + x += width + space; + if (i >= limit * n) { + y += height + space; + x = 0; + n = n + 1; + } + console.log([heads[i - 1], node.x, y]); + + nodes.push(node); + } + canvasData.nodes = nodes; + console.log(canvasData); + const canvasFile = app.vault.getAbstractFileByPath(canvasPath); + const canvasJson = JSON.stringify(canvasData, null, 2); + if (canvasFile) { + app.vault.modify(canvasFile, canvasJson); + } else { + canvasFile = app.vault.create(canvasPath, canvasJson); + } + app.workspace.activeLeaf.openFile(canvasFile); + + } else if (file.extension === 'canvas') { + fs.readFile(fileFullPath, 'utf8', (err, data) => { + if (err) throw err; + const canvasData = JSON.parse(data); + // 获取nodes中的object.file + canvasData.nodes; + const mdFilePath = canvasData.nodes[0].file; + app.workspace.activeLeaf.openFile(app.vault.getAbstractFileByPath(mdFilePath)); + }); + + } + +}; + + +function getHeadings(fileFullPath, level) { + // 读取文件内容 + const fileContent = fs.readFileSync(fileFullPath, 'utf-8'); + + // 使用正则表达式提取指定级别的标题 + const regex = new RegExp(`^#{2,${level}}\\s(.+)`, 'gm'); + const matches = []; + let match; + + while ((match = regex.exec(fileContent)) !== null) { + matches.push("#" + match[1]); + } + return matches; +} +``` + +## 配合 Modal Form 插件来调节参数 + +![2024-02-21_QuickAdd脚本-利用Canvas平铺笔记_IMG-4](https://cdn.pkmer.cn/images/202402230946316.png!pkmer) + +> 配合 ModalForm 插件写了个表单,可以设置参数,不过体验下来,还不如提前把参数设置好一键切换来的方便,还不需要额外安装插件。 + +### 脚本 + +配置同上述一样,不过需要安装 Modal Form 插件 + +```js + +// 基于库的相对路径的Canvas +const canvasPath = "未命名.canvas"; + +const path = require('path'); +const fs = require('fs'); +const modalForm = app.plugins.plugins.modalforms.api; +// 获取笔记的基本路径 +const file = app.workspace.getActiveFile(); +const fileFullPath = app.vault.adapter.getFullPath(file.path); + + +module.exports = async () => { + + const editorForm1 = { + "title": "ConvertMdToCanvas", + "name": "ConvertMdToCanvas", + "fields": [ + { + "name": "level", + "label": "level", + "description": "提取至第几级标题,忽略一级标题", + "input": { + "type": "slider", + "min": 2, + "max": 6 + } + }, + { + "name": "width", + "label": "Width", + "description": "卡片宽度", + "isRequired": true, + "input": { + "type": "number" + } + }, + { + "name": "height", + "label": "height", + "description": "卡片高度", + "isRequired": true, + "input": { + "type": "number" + } + }, + { + "name": "space", + "label": "space", + "description": "卡片间距", + "isRequired": true, + "input": { + "type": "number" + } + }, + { + "name": "limit", + "label": "limit", + "description": "每行卡片的数量限制", + "input": { + "type": "slider", + "min": 1, + "max": 10 + } + }, + ] + }; + const canvasData = { + nodes: [], + edges: [] + }; + if (file.extension === 'md') { + // 设定默认值 + let result = await modalForm.openForm( + editorForm1, + { + values: { + level: 2, + width: 960, + height: 760, + limit: 4, + space: 50, + } + } + ); + + + // 大纲等级 + const level = result.getValue('level').value; + // 卡片参数 + const width = result.getValue('width').value; + const height = result.getValue('height').value; + // 卡片间隔 + const space = result.getValue('space').value; + // 每行卡片的数量限制 + const limit = result.getValue('limit').value; + + console.log("开始获取二级标题"); + const heads = getHeadings(fileFullPath, level); + console.log(heads); + + let x = 0; + let y = 0; + let n = 1; + let nodes = []; + const length = heads.length; + + for (let i = 1; i <= length; i++) { + const node = { + id: "", + type: "file", + file: file.path, + subpath: "", + x: 0, + y: 0, + width: width, + height: height, + }; + + node.subpath = heads[i - 1]; + node.id = i; + node.x = x; + node.y = y; + console.log([heads[i - 1], x, y]); + + x += width + space; + if (i >= limit * n) { + y += height + space; + x = 0; + n = n + 1; + } + console.log([heads[i - 1], node.x, y]); + + nodes.push(node); + } + canvasData.nodes = nodes; + console.log(canvasData); + const canvasFile = app.vault.getAbstractFileByPath(canvasPath); + const canvasJson = JSON.stringify(canvasData, null, 2); + if (canvasFile) { + app.vault.modify(canvasFile, canvasJson); + } else { + canvasFile = app.vault.create(canvasPath, canvasJson); + } + app.workspace.activeLeaf.openFile(canvasFile); + + } else if (file.extension === 'canvas') { + fs.readFile(fileFullPath, 'utf8', (err, data) => { + if (err) throw err; + const canvasData = JSON.parse(data); + // 获取nodes中的object.file + canvasData.nodes; + const mdFilePath = canvasData.nodes[0].file; + app.workspace.activeLeaf.openFile(app.vault.getAbstractFileByPath(mdFilePath)); + }); + + } + + +}; + +function getHeadings(fileFullPath, level) { + // 读取文件内容 + const fileContent = fs.readFileSync(fileFullPath, 'utf-8'); + + // 使用正则表达式提取指定级别的标题 + const regex = new RegExp(`^#{2,${level}}\\s(.+)`, 'gm'); + const matches = []; + let match; + + while ((match = regex.exec(fileContent)) !== null) { + matches.push("#" + match[1]); + } + return matches; +} +``` + +## Quickadd 配置 Capture + +![2024-02-21_QuickAdd脚本-利用Canvas平铺笔记_IMG-5](https://cdn.pkmer.cn/images/202402230946317.png!pkmer) + +### 脚本 + +该代码由 Obsidian 中文论坛的 PlayerMiller 提供,来源于: + +````md +```js quickadd +const fs = require('fs'), getFBP = path => app.vault.getAbstractFileByPath(path), getHeadings = (vFPath, lv) => { + let fileContent = fs.readFileSync(vFPath, 'utf-8'), regex = new RegExp(`^#{2,${lv}} (.+)`, 'gm') + , mats = [], mat; while ((mat = regex.exec(fileContent)) !== null) mats.push(`#${mat[1]}`); return mats; +} + , file = app.workspace.getActiveFile(), vFPath = app.vault.adapter.getFullPath(file.path), cvsData = { nodes: [], edges: [] } + , lv = 2, width = 960, height = 760, space = 50, limit = 4, cvsPath = '未命名.canvas'; // 参数行 +switch (file.extension) { + case 'md': let heads = getHeadings(vFPath, lv), x = 0, y = 0, n = 1, nodes = []; + for (let i = 1; i <= heads.length; i++) { + let node = { id: '', type: 'file', file: file.path, subpath: '', x: 0, y: 0, width: width, height: height }; + node.subpath = heads[i - 1]; node.id = i; node.x = x; node.y = y; x += width + space; + if (i >= limit * n) { y += height + space; x = 0; n += 1; }; nodes.push(node); + }; cvsData.nodes = nodes; let cvsFile = getFBP(cvsPath), cvsJson = JSON.stringify(cvsData, null, 2); + if (cvsFile) { app.vault.modify(cvsFile, cvsJson); } else cvsFile = await app.vault.create(cvsPath, cvsJson); + app.workspace.activeLeaf.openFile(cvsFile); break; + case 'canvas': fs.readFile(vFPath, 'utf8', (err, data) => { + if (err) throw err; let mdFilePath = JSON.parse(data).nodes[0].file; + app.workspace.activeLeaf.openFile(getFBP(mdFilePath)); + }); break; +} +``` +```` + +## 拓展想法 + +如果确定每个标题的格式 (如:草稿、提示、总结),是否可以按照康奈尔笔记布局一样生成对应的 Canvas 来编辑: + +![2024-02-21_QuickAdd脚本-利用Canvas平铺笔记_IMG-6](https://cdn.pkmer.cn/images/202402230946318.png!pkmer) + +## References + +- [在Excalidraw中列出某笔记所有二级Heading - 经验分享 - Obsidian 中文论坛](https://forum-zh.obsidian.md/t/topic/30401) \ No newline at end of file diff --git "a/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Quickadd/quickadd.md" "b/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Quickadd/quickadd.md" index c83bd6c78..6a0c18bd4 100644 --- "a/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Quickadd/quickadd.md" +++ "b/10-Obsidian/Obsidian\347\244\276\345\214\272\346\217\222\344\273\266/Quickadd/quickadd.md" @@ -27,6 +27,7 @@ modified: 20240111113104 - [[Quickadd脚本-一键在系统应用中打开图片编辑]] - [[QuickAdd脚本-插入Zotero的条目PDF链接]] - [[QuickAdd脚本-修复Canvas中的失效文档的链接]] +- [[QuickAdd脚本-利用Canvas平铺笔记]] - [[copy-selection-in-canvas]] - [[QuickAdd脚本-随机漫游笔记]]