-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Query embed block supports executing JavaScript #9648
Comments
关于出入参数,也许可以参考一下 {
embedBlockID: string,
stmt: string,
headingMode: 1 | 0,
excludeIDs: [item.getAttribute("data-node-id"), protyle.block.rootID],
breadcrumb: boolean
} 可以仿照这个接口,直接输入给定的 block id {
embedBlockID: string,
includeIDs: string[],
headingMode: 1 | 0,
breadcrumb: boolean
} 至于输入和 searchEmbedBlock 保持一致,都是吧。 {
blocks: blocks
} 那个 |
能否来一段脚本示例,比如完成某个功能的,这样我们好具体再讨论看看。 |
以下面这个例子为例,这个是我使用 下面这个案例的目标是,将查询的结果,按照笔记本自定义排序的大小来排列。程序最后返回一个 //js
const notebooks = window.siyuan.notebooks.reduce(
(target, key, index) => { target[key['id']] = key; return target;},
{}
);
/**
* 查询的结果按照文档树上笔记本自定义排列的顺序排列
*/
const query = async () => {
//为了方便测试,加了 order by random()
let blocks = await api.sql(`
select * from blocks where created like '20231116%' order by random() limit 16`);
blocks.sort((b1, b2) => notebooks[b1.box].sort - notebooks[b2.box].sort);
console.log(blocks.map((b) => {return {box: notebooks[b.box].name, content: b.content};}));
return blocks;
}
//返回一个 block 列表,嵌入块就根据这个 block 的内容和顺序来展示
return query(); 前端获取到返回的 实际操作的时候,还可以做一些简化,比如可以允许用户只编写 |
感谢,我还需要确认下,需要内核新开接口主要原因是 /api/query/sql 接口返回不了嵌入块接口需要的格式对吧,后半段要使用已有嵌入块渲染的代码? |
对,或者更确切的说是由于 SQL 语法本身的一些缺陷,有些复杂一点的查询难以或者无法实现;希望可以通过引入 js 的程序逻辑来增强查询的能力。 |
嗯,逻辑增强我知道,上面主要问的是实现上的参数格式。这样吧,我们再考虑看看,也许下个特性版 v2.11.0 就安排上。 |
实现方案:
前端 @Vanessa219 |
目前前端支持 return Promise 或者 array
|
能否进一步解偶,直接由js运行getEmbeBlock? |
目前是通过执行 js 获取 id 数组,进一步解耦要如何做? |
还需要一个api来更新块的content,目前sql api只能查询,无法执行update操作。 |
@zxhd863943427 你说的是内核还是前端? |
前端,需要一个新的api更新块的content,便于索引内容。 话说其实挂件块也是需要这个api的。 |
是 |
并不是,是 sqlite 的 blocks 表里的 content 字段,这个是用来搜索的字段,自定义渲染内容最好能自己更新这个字段,才能被搜索到。如果直接写在备注、别名等位置,虽然可以达成搜索的效果,但是会污染原有的 sy 文件。 |
@zxhd863943427 你说的是 js 嵌入块需要更新 content 字段对吧?这里目前是不支持自动索引的,因为 go 里面没法执行 js: 所以是需要加个接口来主动更新 content 字段? |
对的,需要一个接口,至少要能实现这种操作: fetchSyncPost('/api/query/updateContent',{"id": id, "content": content}) |
但是,searchEmbedBlock/getEmbedBlock 自动索引的内容和自定义渲染的内容可能是不一样的。 |
那等晚点我们还是提供一个更新 content 的内核接口吧。 |
另外,api/search/getEmbedBlock的返回感觉缺了好多值:
什么部分是会正确返回,什么只是留一个空字符串,这个能说明吗 |
好像提供更新 content 的接口会有问题,因为这个 content 是和 block 绑定的,如果提供更新 content 的接口的话 block 变动后就不一致了。 |
嵌入块返回的结果很多字段没有填充,前端目前没有用上的就不填充了。 |
额,不乱用应该没问题,毕竟自定义渲染肯定是每次更新都会重新调用一次。 |
改了原块就会被自动覆盖,失去效果了。数据库上最好是只读单向的,仅从 block -> content 方向索引,否则后面可能会引起其他问题。 |
等等,和block绑定,是哪个block? |
编辑器里面的 block |
为什么getEmbedBlock没有违反这个规则呢? |
searchEmbedBlock/getEmbedBlock 仅更新嵌入块的 content,不能更新其他块。 |
那能否同样提供一个能自定义内容、仅更新嵌入块的 content的api? |
能是能,就是感觉破坏单向的设计怕后面出事 😂 |
后面试试这个接口 #9736 |
@Vanessa219 @88250 该功能的具体使用方法是否未写入用户手册中❓ |
没有写,哪位有时间的话帮忙补充一下吧,谢谢。 |
允许嵌入块内执行 Js 以增强复杂查询能力的提案
In what scenarios do you need this feature?
需求:希望能允许在嵌入块内执行 JS,以弥补原始的 SQL 本身逻辑不足的缘故
理由:SQL 虽然强大,但是由于缺失基本的顺序执行。条件片段等逻辑,在处理复杂逻辑查询方面会异常受限
思路:
Describe the optimal solution
具体的实施方案分为两个部分:
1. 通过(在嵌入块开头加入 shebang || 设置自定义属性)来声明本嵌入块是否要执行 js
方案总结
方案一:当嵌入块内容以以下声明为开头的时候,将这个嵌入块视为一个可执行 js 的嵌入
//!js
方案二:设置自定义属性,特定属性的嵌入块会被认为应该作为 js 来执行
具体说明
嵌入块的相关代码在https://github.com/siyuan-note/siyuan/blob/master/app/src/protyle/render/blockRender.ts,其中第 32 行会读取嵌入块的内容并当作一个 sql 查询内容,然后交给
/api/search/searchEmbedBlock
API 执行所以只需要在 32 行后面加上判断即可获知改嵌入块是否需要用 js 来执行
2. 如何将 js 转化为嵌入块查询:两个独立的方案
基本原理
规定: JS嵌入块最后一句,应当返回一个
Block[]
在前端部分,将 JS 嵌入块代码放入
Function
对象中,并提供一个sql
api 用于查询 sqlsql
api 可以直接比照前端的 apifetch
等可能引起安全问题的 API根据 JS 嵌入块代码返回的 Block 列表来构造嵌入块,具体而言有两种方案
selelct * from id in (...)
语句,坏处是不够直接且可能让前端代码逻辑变复杂,好处是后端完全无感2.1 后端方案:后端提供一个新的 API,直接给定 block list 返回嵌入块查询
由弘哥首先提议
我后面也研究了一下后端嵌入块查询的调用过程,觉得应该可以实现。只需要去掉
search.go
的调用,直接用前端给的 block list 就行。2.2 前端方案:将 js 执行过程拼接为新的 SQL 语句
基本思路是:
执行 js 代码,获取 block list
将 block list 拼成
select * from blocks where id in ("id1", "id2", ...)
,比如这样:将新的构造的 SQL 语句发往后端
将返回结果按照发送时候的顺序重新排列一下
select * from blocks where id in ("id1", "id2", ...)
语句可以查询到正确的结果,但是嵌入块内部DOM的排列顺序却是乱的,所以为了保证顺序正确,需要前端在 searchEmbedBlock 的返回结果中将response.data.blocks
重新排序一下。补充:为什么不想做成插件
The text was updated successfully, but these errors were encountered: