思源笔记折腾记录 -urlScheme 动作

本贴最后更新于 706 天前,其中的信息可能已经天翻地覆

一、前情提要:

思源的 URL scheme 能够通过块超链接做到唤起思源并打开指定的块,然后还能。。。。。。。。。。

额,好像然后就不能做什么了。

所以这次我们就来尝试一下扩展一下思源的 URL Scheme

二、实现原理

1、ipcRenderer

可以先在代码片段里面测试一下这段代码:

const {ipcRenderer} = require('electron')
ipcRenderer.on('siyuan-openurl',(event,msg)=>{
console.log(event,msg)
}) 
	  

随便在什么地方打开一个思源的块超链接,就可以看到在控制台的输出了:

image

啊,可以看到后面的 msg 参数就是块超链接的内容~~~。

这是为什么呢?

之前我们说过,思源的 main.js 里面是可以直接看到内容的,这里可以看一下第 771 到 799 行:

app.on('open-url', (event, url) => { // for macOS
  if (url.startsWith('siyuan://')) {
    siyuanOpenURL = url
    if (mainWindow && !mainWindow.isDestroyed()) {
      if (mainWindow.isMinimized()) {
        mainWindow.restore()
      }
      if (!mainWindow.isVisible()) {
        mainWindow.show()
      }
      mainWindow.focus()
      mainWindow.webContents.send('siyuan-openurl', url)
    }
  }
})

app.on('second-instance', (event, commandLine) => {
  if (mainWindow && !mainWindow.isDestroyed()) {
    if (mainWindow.isMinimized()) {
      mainWindow.restore()
    }
    if (!mainWindow.isVisible()) {
      mainWindow.show()
    }
    mainWindow.focus()
    mainWindow.webContents.send('siyuan-openurl',
      commandLine.find((arg) => arg.startsWith('siyuan://')))
  }
})

这两个地方就是通过进程间通信,把块超链接的内容发送给了思源的主界面。

所以我们可以通过监听这个 siyuan-openurl 信道来获取 url 的内容。

有关 ipcRenderer 之类的参考 electorn 的文档:

ipcRenderer | Electron (electronjs.org)

其实就是用来通信的嘛

2、URL 对象

这个其实就是冷饭了,之前在实现白板的时候不是用了一个解析 URL 参数的对象嘛,这次要使用的就是那个:

思源笔记折腾记录 - 做一个白板 - 保存数据和显示模式 - 链滴 (ld246.com)

之前是这样写的:

export  function 获取地址参数(){
	let 中间变量 = {}
	new URL(window.location.href).searchParams.forEach(
		(value,key)=>{中间变量[key]=value}
	)
	return 中间变量
} 

那么很容易就想到,只要把这个函数跟上面的那个结合一下,就可以了:

const {ipcRenderer} = require('electron')
ipcRenderer.on('siyuan-openurl',(event,msg)=>{
	执行URL(msg)
}) 
function 执行URL(url){
	let url 对象 =  new URL(url)
	console.log(url对象)
}	  

可以看到 url 对象上有这么些属性:

image

这样我们就可以它进行进一步的操作了。

3、注册动作

首先我们假设,一个类似:

siyuan://<路径>/<下级路径>?<参数>

的 url。

它最开始的路径名就是要执行的动作,下级路径和 url 的 searchParams 都直接传递给对应的回调函数。

这样我们就能开始注册回调了:

	const url动作注册表 = []
	const { ipcRenderer } = require('electron')
	ipcRenderer.on('siyuan-openurl', (event, msg) => {
		执行URL(msg)
	})
	function 执行URL(url) {
		let url对象 = new URL(url)
		let 路径名 = url对象.pathname.replace('//', '').split('/')[0]
		let 搜索参数 = {}
		url对象.searchParams.forEach(
			(value, key) => { 搜索参数[key] = value }
		)
		console.log(路径名, 搜索参数)
		url动作注册表.forEach(
			注册表项 => {
				console.log(注册表项.动作 === 路径名)

				if (注册表项.动作 === 路径名) {
					try {
						(async () => { 注册表项.回调函数(url对象.pathname.replace('//', ''), JSON.parse(JSON.stringify(搜索参数))) })()
					} catch (e) {
						console.warn(e)
					}
				}
			}
		)
	}
	function 注册url动作(动作, 回调函数) {
		url动作注册表.push({ 动作: 动作, 回调函数: 回调函数 })
	}
	注册url动作('blocks', (路径名, 参数) => { console.log('你点击的是',路径名, 参数) })

啊,我就随便注册一个函数试试。。。。。

现在点击一个块超链接,啊不对,现在应该叫超级块超链接,因为它的战斗力已经超过 114514 了,看一下输出就可以看到:

image

OK,收工。

把它挂载到 noobApi 上方便以后调用:

const url动作注册表 = []
if (window.require) {
    const { ipcRenderer } = require('electron')
    ipcRenderer.on('siyuan-openurl', (event, msg) => {
        执行URL(msg)
    })
    function 执行URL(url) {
        let url对象 = new URL(url)
        let 路径名 = url对象.pathname.replace('//', '').split('/')[0]
        let 搜索参数 = {}
        url对象.searchParams.forEach(
            (value, key) => { 搜索参数[key] = value }
        )
        console.log(路径名, 搜索参数)
        url动作注册表.forEach(
            注册表项 => {
                console.log(注册表项.动作 === 路径名)

                if (注册表项.动作 === 路径名) {
                    try {
                        (async () => { 注册表项.回调函数(url对象.pathname.replace('//', ''), JSON.parse(JSON.stringify(搜索参数))) })()
                    } catch (e) {
                        console.warn(e)
                    }
                }
            }
        )
    }
}
export default function 注册url动作(动作, 回调函数) {
    url动作注册表.push({ 动作: 动作, 回调函数: 回调函数 })
}

4、试一试

注册一个打开当天日记的函数试试:

noobApi.url动作.注册url动作('DailyNote', () => {
    noobApi.核心api.创建日记({
        notebook
            :
            "20210808180117-czj9bvb"
    })
})

效果就像这样

url 创建日记

这样这个 issue 就能够自己动手撸啦:

丰富 siyuan:// 协议动作,如创建文档 · Issue #6875 · siyuan-note/siyuan (github.com)

所谓折腾就是有 bug 要上,没有 bug,创造 bug 也要上嘛~~~

思考题:issue 里面提到的创建文档咋整?(其实就是换个接口而已。。。。。。)


代码片段的仓库在这里

leolee9086/snippets (github.com)

viteWdigets 的仓库在这里

leolee9086/viteWidgets (github.com)

  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    22337 引用 • 89380 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...