utools实现全局追加文本到obsidian文件

请问有大佬会utools的插件开发吗?

我最近在写一个utools插件,可以读取剪贴板然后将内容追加到obsidian的某个文件中,这样就可以实现全局快捷输入内容到obsidian了。

然而我不是很会js,目前插件的preload.js文件写成下面的样子,很粗略地实现要求,但还有很多地方能改进:

window.exports = {
    "Timestamp": { // 注意:键对应的是 plugin.json 中的 features.code
        mode: "list",  // 列表模式
        args: {
            // 进入插件应用时调用(可选)
            enter: (action, callbackSetList) => {
                // 如果进入插件应用就要显示列表数据
                utools.showNotification("进入插件")
                callbackSetList([
                    {
                        title: "1",
                        description: '略',
                        icon: 'logo.png' // 图标(可选)
                    },
                    { 
                        title: "2",
                        description: '略',
                        icon: 'logo.png' // 图标(可选)
                    },
                    {
                        title: '3',
                        description: '略',
                        icon: 'logo.png' // 图标(可选)
                    }
                ])
            },
            // 用户选择列表中某个条目时被调用
            select: (action, itemData, callbackSetList) => {

                // 函数用于将 payload 追加到文件
                const appendPayloadToFile = (payload) => {
                    const fs = require('fs');
                    const data = `\n${payload.payload}`;
                    fs.appendFile('D:\\Project\\JS\\example.txt', data, 'utf8', (err) => {
                        if (err) {
                            console.error('文件追加失败:', err);
                            utools.showNotification('文件追加失败');
                            return;
                        }
                        utools.showNotification('文件异步追加成功');
                    });
                };
                // 函数用于处理 payload
                const processPayload = (payload) => {
                    let processedPayload;
                    switch (payload.type) {
                        case 'img':
                            processedPayload = payload;
                            break;
                        case 'text':
                            processedPayload = payload;
                            break;
                        default:
                            processedPayload = null;
                    }
                    return processedPayload;
                };

                // 主函数,处理用户进入插件应用
                const ggg = (payload) => {
                    console.log('用户进入插件应用', payload.code, payload.type, payload);
                    utools.showNotification(payload);
                    appendPayloadToFile(payload);
                    return processPayload(payload);
                };

                // 注册插件进入事件
                utools.onPluginEnter(ggg);
            },
        }
    }
}

有待改进

  • 目前只实现了文本的追加,图片的追加思路是写入图片obsidian内链到文件同时移动图片文件到obsidian附件夹
  • 更好的编辑框?

其他

2 个赞

quicker的工作仪表盘,可以实现写入不同MD文件,手动加入你选择的md文件

00 intro

作为一个小玩具,我在几个月前完善了这个插件,在此增加补充说明兼抛砖引玉。

它的定位是实现比一般的剪藏插件更加轻量的剪藏操作

  • 几个快捷键操作可以直接写入特定的 inbox md文件,不需要离开浏览页面;
  • 尤其适用完全键盘流浏览网页碎片化资讯场景:浏览器文本光标浏览复制文本 + 本插件快速追加到md文件

01 配置

由于没有上架utool插件市场,下面需要手动完成配置 + 插件打包安装。

  1. 项目文件结构:

在文件夹 Obsidian SnapPaste 1.0.0 中:

Obsidian SnapPaste 1.0.0
├─ logo.png
├─ plugin.json
└─ preload.js

其中 logo.png 随便选一张图片即可,推荐 obsidian logo

  1. plugin.json

填入内容:

{
    "pluginname": "Obsidian SnapPaste",
    "description": "将文本或者图片快速追加到Obsidian的Inbox文件",
    "preload": "preload.js",
    "logo": "logo.png",
    "version": "1.0.0",
    "features": [
        {
            "code": "ob追加",
            "cmds": [
                "over",
                {
                    "type": "over",
                    "label": "文本追加"
                },
                "img",
                {
                    "type": "img",
                    "label": "图片追加"
                }
            ]
        }
    ],
    "pluginSetting": {
        "single": true
    }
}

  1. preload.js

填入内容:

window.exports = {

    // 插件运行需要初始化
    "ob追加": { // 注意:键对应的是 plugin.json 中的 features.code
        mode: "none",  // 无ui模式
        args: {
            enter: (action) => {
                // 函数用于将 payload 追加到文件
                const appendPayloadToFile = (payload) => {
                    const fs = require('fs');
                    const path = require('path');
                    const dirname         = 'D:\\Obsidian库名\\Obsidian附件文件夹'
                    const obinboxfilepath = 'D:\\Obsidian库名\\Inbox.md';
                    if (payload.type == "over"){
                        const data = `\n${payload.payload}`;
                        fs.appendFile(obinboxfilepath, data, 'utf8', (err) => {
                            if (err) {
                                console.error('文件追加失败:',  err);
                                utools.showNotification('😭');
                                return;
                            }
                            utools.showNotification(`🥰:${data}`);
                        });
                    } else if (payload.type == "img") {

                        // 函数用于将 截图payload 追加到文件
                        const base64Data     = payload.payload                                       //获取截图的base64编码
                        const base64Image    = base64Data.split(',')[1];                             //移除数据类型前缀,只保留Base64编码部分
                        const fileType       = base64Data.split(';')[0].split(':')[1].split('/')[1]; //提取文件类型

                        // 获取当前日期并格式化为 YYYY-MM-DD
                        const now            = new Date();
                        const year           = now.getFullYear().toString().slice(-2);           //获取年份的后两位
                        const month          = (now.getMonth() + 1).toString().padStart(2, '0'); //获取月份并补零
                        const day            = now.getDate().toString().padStart(2, '0');        //获取日期并补零
                        const timestamp      = `${year}-${month}-${day}`;

                        // 生成 4 位随机数
                        const random_num     = Math.random().toString(16).slice(2, 6);                //生成 4 位随机数
                        const filename       = `Ob Snappaste ${random_num} ${timestamp}.${fileType}`; //生成随机文件名
                        const obInternalLink = `\n![[${filename}]]`;                                  //根据文件名生成截图文件的ob内链
                        const buffer         = Buffer.from(base64Image, 'base64');                    //将Base64编码解码为Buffer
                        const outputPath     = path.join(dirname, filename);                          //设置文件保存路径和文件名

                        // 将Buffer数据写入图片文件,截图文件进入到ob库
                        fs.writeFile(outputPath, buffer, (err) => {
                            if (err) {
                                utools.showNotification('😭图片生成失败');
                                return;
                            }
                            utools.showNotification(`🥰图片生成成功 ${outputPath}`);
                        });

                        // 将ob内链文本写入obinbox文件
                        fs.appendFile(obinboxfilepath, obInternalLink, 'utf8', (err) => {
                            if (err) {
                                utools.showNotification('😭内链生成失败');
                                return;
                            }
                            utools.showNotification(`🥰内链 ${obInternalLink}`);
                        });
                    } else {
                        utools.showNotification("❌非可处理文件❌");
                    }
                };
                // 主函数,处理用户进入插件应用
                const mainfunction = (payload) => {
                    appendPayloadToFile(payload);
                    utools.hideMainWindow(true);
                    utools.outPlugin();
                };
                // 注册插件进入事件
                utools.onPluginEnter(mainfunction);
                utools.showNotification("插件初始化, 须重试1次");
            },
        }
    }
}

其中需要修改几处参数:

  • dirname:你的库附件文件夹路径,绝对路径;
  • obinboxfilepath:你的库的某一个md文件,绝对路径,插件将会把剪藏文本或图片写入到这个md文件;

代码的其他部分(如提示信息,附件文件命名)可以通过询问ai自行修改


02 插件打包和安装

在完成01的文件配置后,需要在utool插件市场中安装utool官方的开发者工具,之后:

utool中打开 utool官方开发者工具——新建项目,随便填一些信息——选择上面 01 完成的文件夹 Obsidian SnapPaste 1.0.0 作为项目文件——打包,将生成 Obsidian SnapPaste 1.0.0.upxs文件——复制这个upxs文件,在utool中安装

03 使用

使用之前,在utool中如此设置插件

在(开机后)第一次使用这个插件,会提示需要初始化,只需要再试一次后续即可正常使用。

在使用时,复制文本/图片 ——Alt+Space打开utool——选择追加

04 不足和改进

  • 文本图片混排只能追加其中的文本,图片无法获取(这是utool本身的数据处理类型决定的)
  • 只能追加到一个指定的 obsidian inbox.md,不能选取追加到某一个md文件(后续可以完善,增加在utool中搜索obsidian库中的md文件并追加)
  • 假如obsidian附件文件夹或者obsidian inbox.md路径变化,需要重新配置插件文件(完全是我的水平问题,应该可以在utool中增加插件设置页,支持修改附件文件夹路径和inbox.md文件路径,当然我觉得这两个路径不会总是变化的~所以没有也能用 :smiling_face_with_tear: