思源笔记折腾记录 - 做一个白板 - 更多的视图

本贴最后更新于 844 天前,其中的信息可能已经事过景迁

一、前情提要:

之前实现了一个简单的白板工具,并且让它能够实现显示子文档了。

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

就像这样:

image

不过只有子文档视图显然不给力啊。

所以我们来给它增加一些视图。

二、实现过程:

1、实现 sql 适配器

之前我们的子文档视图适配器是这样获取数据的:

获取卡片列表: async () => { return await 核心api.sql( { stmt: `select * from blocks where path like '%${id}%' and type='d'` } ) },

很容易想到,那把不同的 sql 喂给这个适配器就能够实现不同的视图了嘛。

所以先来实现一个通用的 sql 适配器算了。

这次我们使用类 class 来试一下:

import { 核心api,获取地址参数 } from ".." let 白板id = 获取地址参数().id let mode = 获取地址参数().mode if (!白板id) { 白板id = '20200812220555-lj3enxa' } if (!mode) { mode = "子文档视图" } export class 基础块适配器{ 获取卡片内容数据=async (卡片id) => { return await 核心api.exportPreview( { id: 卡片id } ) } 获取卡片几何数据= async (卡片id) => { let 原始数据 = await 核心api.sql( { stmt: `select * from attributes where name = 'custom-whiteBoardData-${白板id}' and block_id='${卡片id}'` } ) if (原始数据 && 原始数据[0]) { let json数据 = JSON.parse(原始数据[0].value) return json数据.find( item => { return item.mode === mode } ) } } 保存卡片几何数据= async (卡片id, 显示数据) => { let 原始数据 = await 核心api.sql( { stmt: `select * from attributes where name = 'custom-whiteBoardData-${白板id}' and block_id='${卡片id}'` } ) if (原始数据 && 原始数据[0]) { let json数据 = JSON.parse(原始数据[0].value) json数据.find( item => { return item.mode === mode } ).data = 显示数据 let obj = {} obj.id =卡片id obj.attrs ={} obj.attrs[`custom-whiteBoardData-${白板id}`]=JSON.stringify(json数据) await 核心api.setBlockAttrs(obj) } else { let obj = {} obj.id =卡片id obj.attrs ={} obj.attrs[`custom-whiteBoardData-${白板id}`]=JSON.stringify([{ mode: mode, data: 显示数据 }]) await 核心api.setBlockAttrs(obj) } } }

这是一个最基本的思源块适配器,实现了保存几何信息到块属性的功能。

然后我们继承并扩展一下它:

import { 核心api,获取地址参数 } from ".." import {基础块适配器} from './baseBlock' let 白板id = 获取地址参数().id let mode = 获取地址参数().mode if (!白板id) { 白板id = '20200812220555-lj3enxa' } if (!mode) { mode = "子文档视图" } export class 基础sql适配器 extends 基础块适配器{ constructor(sql){ super() this.sql =sql } 获取卡片列表=async () => { return await 核心api.sql( { stmt: this.sql } ) } }

extends 后面的是基类,前面的基础 sql 适配器继承了这个类的各种方法,所以只需要再改一下获取卡片列表的方法就行了。

然后基于这个基础 sql 类,就可以更简单地实现之前的子文档适配器了:

import { 基础sql适配器 } from "./baseSQL" import { 获取地址参数 } from ".." let id = 获取地址参数().id||'20200812220555-lj3enxa' let 子文档视图适配器 = new 基础sql适配器( `select * from blocks where type = 'd' and path like '%${id}%'` ) export default 子文档视图适配器

好啦,这回子文档视图适配器就简单多了。

2、搜索适配器

然后来实现更多种类的适配器,比如说:

import { 基础块适配器 } from "./baseBlock"; import {核心api,获取地址参数} from '..' import 'http://127.0.0.1:6806/stage/protyle/js/lute/lute.min.js' let lute =Lute.New() lute.SetTextMark(true) lute.SetProtyleWYSIWYG(true) lute.SetBlockRef(true) lute.SetFileAnnotationRef(true) lute.SetKramdownIAL(true) lute.SetTag(true) lute.SetSuperBlock(true) lute.SetImgPathAllowSpace(true) lute.SetGitConflict(true) lute.SetMark(true) lute.SetSup(true) lute.SetSub(true) lute.SetInlineMathAllowDigitAfterOpenMarker(true) lute.SetFootnotes(false) lute.SetToC(false) lute.SetIndentCodeBlock(false) lute.SetParagraphBeginningSpace(true) lute.SetAutoSpace(false) lute.SetHeadingID(false) lute.SetSetext(false) lute.SetYamlFrontMatter(false) lute.SetLinkRef(false) lute.SetCodeSyntaxHighlight(false) lute.SetSanitize(true) export class 搜索适配器 extends 基础块适配器{ constructor(关键词){ super() if(!关键词,关键词=获取地址参数().search) this.关键词 = 关键词 } 获取卡片列表=async()=>{ return (await 核心api.fullTextSearchBlock( {query:this.关键词} )).blocks } 获取卡片内容数据=async(卡片id)=>{ let data = await 核心api.getDoc( { id:卡片id, mode:0, size:102400 } ) //使用lute来生成html return {html:lute.Md2HTML(lute.BlockDOM2StdMd(data.content))} } }

这就是一个搜索适配器,作用是把思源的关键词搜索结果显示成一个白板视图:

image

这样就显示了搜索思源笔记的结果。

因为几何信息是存储在块上的,所以就算搜索结果有变化,已经在白板上放好位置的块也不会乱跑啦。

不过这里有个小问题,在不同的关键词搜索结果里,同一个块会停留在同一个位置,所以我们来重载一下它的读写数据方法:

获取卡片几何数据= async (卡片id) => { let 原始数据 = await 核心api.sql( { stmt: `select * from attributes where name = 'custom-whiteBoardData-${白板id}' and block_id='${卡片id}'` } ) if (原始数据 && 原始数据[0]) { let json数据 = JSON.parse(原始数据[0].value) let 关键词匹配结果= json数据.find( item => { return item.mode === '搜索视图'&&item.search===this.关键词 } ) if(关键词匹配结果){ return 关键词匹配结果 } else { return json数据.find( item =>{return item.mode==='搜索视图'} ) } } } 保存卡片几何数据=async (卡片id,显示数据)=>{ let 原始数据 = await 核心api.sql( { stmt: `select * from attributes where name = 'custom-whiteBoardData-${白板id}' and block_id='${卡片id}'` } ) let json数据 if (原始数据 && 原始数据[0]) { json数据 = JSON.parse(原始数据[0].value) let 旧数据= json数据.find( item => { return item.mode === '搜索视图'&&item.search===this.关键词 } ) if(旧数据){ 旧数据.data = 显示数据 } else json数据.push({ mode:'搜索视图', search:this.关键词, data:显示数据 }) } else json数据=[{mode:'搜索视图',search:this.关键词,data:显示数据}] let obj = {} obj.id =卡片id obj.attrs ={} obj.attrs[`custom-whiteBoardData-${白板id}`]=JSON.stringify(json数据) await 核心api.setBlockAttrs(obj) }

好了,这样就把每个关键词的搜索结果分开了。

image

image

可以看到这回每个搜素关键词白板里各个块的位置就不再一样了。

3、超链接适配器:

来,我们来搞一个新的,显示一个文档里面所有的超链接,基于 sql 适配器改一下获取数据的结果就可以了。

首先是获取搜索结果,:

import { 基础sql适配器 } from "./baseSQL" import { 获取地址参数 } from ".." let id = 获取地址参数().id||'20200812220555-lj3enxa' let sql = `select * from spans where root_id ='${id}' and type like '%textmark%a%'` export class 超链接适配器 extends 基础sql适配器{ constructor(){ super(sql) } 获取卡片内容数据=async (卡片id) => { let 卡片数据 = this.卡片列表.find( item=>{return item.id === 卡片id} ) let 链接 = 卡片数据.markdown.replace(`[${卡片数据.content}]`,'') console.log(链接) 链接 = 链接.substring(1,链接.length-1) return {html:`<iframe src='${链接}' style="width:100%;height:calc(100% - 10px);"></iframe>`} } }

啊,也就是把文档里面所有的超链接显示成 iframe 展示到白板上,这样好像比较适合做啥网址收集什么的?

image

上面那个浏览器页签一样的也是在思源里打开的,它的实现参考这里:

思源笔记折腾记录 - 思源内部打开网页 - 链滴 (ld246.com)

不过其实这个适配器还没有完成,因为它的修改还没有保存的方式,不过可以自己思考一下,它能够往哪里存,想出来的可以在评论里说一下,不止有一种方法的。

好了,其实还有一个地方没有说,适配器需要显式的引入和声明:

whiteBoard\src\data\adapter.js

import { 获取地址参数, 核心api } from "./index.js"; import 子文档视图适配器 from './adapters/childDoc.js' import { 搜索适配器 } from "./adapters/search.js"; import { 超链接适配器 } from "./adapters/hyperLinks.js"; let { id,mode,search } = 获取地址参数() if (!mode) { mode = "子文档视图" } if(!id){ id = '20200812220555-lj3enxa' } let 适配器列表 = { 子文档视图:子文档视图适配器, 搜索视图:new 搜索适配器(search), 超链接列表视图:new 超链接适配器() } let 当前数据适配器 = 适配器列表[mode] export default 当前数据适配器

就像上面那样。

还可以实现更多的适配器来显示更多的白板布局,就是提供一下数据获取和保存的方法而已,不过就不多说这个了。


代码片段的仓库在这里

leolee9086/snippets (github.com)

viteWdigets 的仓库在这里

leolee9086/viteWidgets (github.com)

  • 思源笔记

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

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

    24810 引用 • 102062 回帖

相关帖子

欢迎来到这里!

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

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