8 层功力的 remnote 制卡 并多多一键制卡更新,支持列表项制卡,增加一键移除

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

需要了解是什么参见并夕夕版 文档树制卡 v0.5 支持直接获取路径和分屏,演示见下:

一键添加和移除.gif

列表项制卡的符号参考了 remnote,也就是》》和 >>。要是有什么容易打出来也不大可能有其他用途、而且好看的符号也可以提,当然更欢迎自行添加。

另外,由于接口的限制,暂时没办法移除使用快捷键添加的卡片——因为获取不到 ALL 卡包。

喜欢的话留个言,也让我知道除我以外还有人用。

// 一键移除卡片 v0.1 // 请求函数 // 使用匿名函数,防止污染空间 (() => { function request(url, data = null, method = "POST") { return new Promise((resolve, reject) => { if (method.toUpperCase() == "POST") { fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data), }) .then( (data) => resolve(data.json()), (error) => { reject(error); } ) .catch((err) => { console.error("请求失败:", err); }); } }); } // 弹出提示信息 async function showMessage(msg) { await request("/api/notification/pushMsg", { msg, timeout: 3000 }); } function getCurrentPage() { //获取当前屏幕 const currentScreen = document.querySelector(".layout__wnd--active"); //获取当前页面 const currentPage = currentScreen.querySelector( ".fn__flex-1.protyle:not(.fn__none)" ); return currentPage; } //传入 node节点列表 arr和数据抽取函数 fliter。 // fliter 传入一个节点,返回一个字典 // 字典格式: // {status,data} // status 为 ok,则代表为抽取成功,将data压入返回列表anwer,并最后返回。 function iterArr(arr, fliter) { if (!arr && arr.length <= 0) { return []; } length = arr.length; anwer = []; for (let node of arr) { data = fliter(node); if (data["status"] === "ok" && data["data"]) { anwer.push(data["data"]); } } return anwer; } function fliterBlockCard(node) { return { status: "ok", data: node.getAttribute("data-node-id") } } async function removeCards() { //获取全部deck let res = await request("/api/riff/getRiffDecks", {}); //获取deck.id let customDeckIdArr = []; Array.from(res.data).forEach((item) => { customDeckIdArr.push(item.id); }) if (customDeckIdArr.length === 0) { showMessage(`未能获取到卡包`); return; } // 获取需要被制成卡片的块的ID const currentPage = getCurrentPage() //已制卡块 const cardedBlockList = currentPage.querySelectorAll(".protyle-wysiwyg [data-node-id][custom-riff-decks]") let arr = []; var cardedBlockIdList = iterArr(cardedBlockList, fliterBlockCard) arr = arr.concat(cardedBlockIdList) if (arr.length === 0) { showMessage(`未能获取到页面的卡片`); return; } // 去重 arr = [... new Set(arr)]; for (deckIndex in customDeckIdArr) { // 把标记所在块全部制成卡片 let body = { deckID: customDeckIdArr[deckIndex], blockIDs: arr, }; let res = await request("/api/riff/removeRiffCards", body); if (res.code === 0) { showMessage(`${res.data.name}卡包的总卡片数:${res.data.size}`); } } } const barMode = document.getElementById("barMode"); barMode.insertAdjacentHTML( "beforebegin", '<div id="removeCards" class="toolbar__item b3-tooltips b3-tooltips__se" aria-label="移除卡片" ></div>' ); const removeCardsBtn = document.getElementById("removeCards"); removeCardsBtn.style.width = "auto"; const removeCardsBtnIcon = `<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48"><path d="M600 826v-60h145v60H600Zm0-368v-60h280v60H600Zm0 184v-60h235v60H600ZM125 381H80v-60h170v-45h135v45h170v60h-45v415q0 24-18 42t-42 18H185q-24 0-42-18t-18-42V381Zm60 0v415h265V381H185Zm0 0v415-415Z"/></svg>`; removeCardsBtn.innerHTML = removeCardsBtnIcon; removeCardsBtn.addEventListener( "click", (e) => { removeCards(); e.stopPropagation(); e.preventDefault(); }, true ); })();
// 一键制卡 v0.6 // 请求函数 // 使用匿名函数,防止污染空间 (() => { function request(url, data = null, method = "POST") { return new Promise((resolve, reject) => { if (method.toUpperCase() == "POST") { fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data), }) .then( (data) => resolve(data.json()), (error) => { reject(error); } ) .catch((err) => { console.error("请求失败:", err); }); } }); } // 弹出提示信息 async function showMessage(msg) { await request("/api/notification/pushMsg", { msg, timeout: 3000 }); } // 获取当前文档id function getFileID() { //获取当前页面 const currentPage = getCurrentPage(); //获取当前页面id const currentPageID = currentPage.querySelector( "span.protyle-breadcrumb__item--active" ).getAttribute("data-node-id"); return currentPageID; } function getCurrentPage() { //获取当前屏幕 const currentScreen = document.querySelector(".layout__wnd--active"); //获取当前页面 const currentPage = currentScreen.querySelector( ".fn__flex-1.protyle:not(.fn__none)" ); return currentPage; } //传入 node节点列表 arr和数据抽取函数 fliter。 // fliter 传入一个节点,返回一个字典 // 字典格式: // {status,data} // status 为 ok,则代表为抽取成功,将data压入返回列表anwer,并最后返回。 function iterArr(arr, fliter) { if (!arr && arr.length <= 0) { return []; } length = arr.length; anwer = []; for (let node of arr) { data = fliter(node); if (data["status"] === "ok" && data["data"]) { anwer.push(data["data"]); } } return anwer; } // 传入列表下的段落,返回被标记段落的父节点:列表项的id function fliterListCard(node) { var re = /(>>|(》》))\s?\u200b?$/; if (re.test(node.innerText)) { return { status: "ok", data: node.parentElement.getAttribute("data-node-id") } } return { status: "no", data: null }; } function fliterMarkCard(node) { return { status: "ok", data: node.parentElement.parentElement.getAttribute("data-node-id") } } function fliterSuperBlockCard(node) { return { status: "ok", data: node.getAttribute("data-node-id") } } // 获取当前文档路径 async function getHpath() { currentPageID = getFileID() body = { "id": currentPageID } let res = await request("/api/filetree/getHPathByID", body); //检测返回值 if (res.code === 0) { let currentPagePath = res.data; return currentPagePath; } return null; } // 添加多个卡片 async function addCards() { //获取全部deck let res = await request("/api/riff/getRiffDecks", {}); //获取当前打开文档的路径 focusItemPath = await getHpath() if (focusItemPath === null) { showMessage(`未能当前文档读取路径`); return; } //获取deck.id, 其deck.name 包含在 focusItemPath 中 let customDeckIdArr = []; Array.from(res.data).forEach((item) => { let name = item.name; if (focusItemPath.search(name) != -1) { customDeckIdArr.push(item.id); } }) if (customDeckIdArr.length === 0) { showMessage(`未能获取到:${focusItemPath} 的卡包`); return; } // 获取需要被制成卡片的块的ID const currentPage = getCurrentPage() //标记块 const markList = currentPage.querySelectorAll("span[data-type='mark']") //超级块 const superBlockList = currentPage.querySelectorAll("div[class='sb']") //列表块 const listList = currentPage.querySelectorAll("div[class='li']:has(div[class='li']) > div[class = 'p']") let arr = []; var markCardList = iterArr(markList, fliterMarkCard) var superBlockCardList = iterArr(superBlockList, fliterSuperBlockCard) var listCardList = iterArr(listList, fliterListCard) arr = arr.concat(markCardList, superBlockCardList, listCardList) if (arr.length === 0) { showMessage(`未能获取到:${focusItemPath} 页面的卡片`); return; } // 去重 arr = [... new Set(arr)]; for (deckIndex in customDeckIdArr) { // 把标记所在块全部制成卡片 let body = { deckID: customDeckIdArr[deckIndex], blockIDs: arr, }; let res = await request("/api/riff/addRiffCards", body); if (res.code === 0) { showMessage(`${res.data.name}卡包的总卡片数:${res.data.size}`); } } } // 添加一个按钮 const barMode = document.getElementById("barMode"); barMode.insertAdjacentHTML( "beforebegin", '<div id="addCards" class="toolbar__item b3-tooltips b3-tooltips__se" aria-label="制作卡片" ></div>' ); const addCardsBtn = document.getElementById("addCards"); addCardsBtn.style.width = "auto"; const addCardsBtnIcon = `<svg t="1674130669751" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4526" width="200" height="200"><path d="M928 160H96a32 32 0 0 0-32 32v672a32 32 0 0 0 32 32h832a32 32 0 0 0 32-32V192a32 32 0 0 0-32-32z m-32 672H128V224h768v608z" p-id="4527" fill="#9aa0a6"></path><path d="M230.592 448.096H544a32 32 0 1 0 0-64H230.592a32 32 0 0 0 0 64zM230.592 640.096H544a32 32 0 1 0 0-64H230.592a32 32 0 1 0 0 64zM768 704a32 32 0 0 0 32-32V350.016a32 32 0 1 0-64 0V672a32 32 0 0 0 32 32z" p-id="4528" fill="#9aa0a6"></path></svg>`; addCardsBtn.innerHTML = addCardsBtnIcon; addCardsBtn.addEventListener( "click", (e) => { addCards(); e.stopPropagation(); e.preventDefault(); }, true ); })();
  • 思源笔记

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

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

    25501 引用 • 105453 回帖

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    32 引用 • 108 回帖 • 1 关注
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 53 关注
  • BookxNote

    BookxNote 是一款全新的电子书学习工具,助力您的学习与思考,让您的大脑更高效的记忆。

    笔记整理交给我,一心只读圣贤书。

    1 引用 • 1 回帖
  • wolai

    我来 wolai:不仅仅是未来的云端笔记!

    2 引用 • 14 回帖 • 5 关注
  • 印象笔记
    3 引用 • 16 回帖 • 1 关注
  • 宕机

    宕机,多指一些网站、游戏、网络应用等服务器一种区别于正常运行的状态,也叫“Down 机”、“当机”或“死机”。宕机状态不仅仅是指服务器“挂掉了”、“死机了”状态,也包括服务器假死、停用、关闭等一些原因而导致出现的不能够正常运行的状态。

    13 引用 • 82 回帖 • 78 关注
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    499 引用 • 1395 回帖 • 246 关注
  • 30Seconds

    📙 前端知识精选集,包含 HTML、CSS、JavaScript、React、Node、安全等方面,每天仅需 30 秒。

    • 精选常见面试题,帮助您准备下一次面试
    • 精选常见交互,帮助您拥有简洁酷炫的站点
    • 精选有用的 React 片段,帮助你获取最佳实践
    • 精选常见代码集,帮助您提高打码效率
    • 整理前端界的最新资讯,邀您一同探索新世界
    488 引用 • 384 回帖 • 10 关注
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    29 引用 • 202 回帖 • 28 关注
  • WordPress

    WordPress 是一个使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设自己的博客。也可以把 WordPress 当作一个内容管理系统(CMS)来使用。WordPress 是一个免费的开源项目,在 GNU 通用公共许可证(GPLv2)下授权发布。

    67 引用 • 114 回帖 • 193 关注
  • 酷鸟浏览器

    安全 · 稳定 · 快速
    为跨境从业人员提供专业的跨境浏览器

    3 引用 • 59 回帖 • 48 关注
  • Flutter

    Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。 Flutter 可以与现有的代码一起工作,它正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。

    39 引用 • 92 回帖 • 4 关注
  • 持续集成

    持续集成(Continuous Integration)是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。

    15 引用 • 7 回帖 • 1 关注
  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    22 引用 • 22 回帖 • 2 关注
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖 • 1 关注
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    170 引用 • 1150 回帖 • 2 关注
  • ZooKeeper

    ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 HBase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

    59 引用 • 29 回帖
  • Sublime

    Sublime Text 是一款可以用来写代码、写文章的文本编辑器。支持代码高亮、自动完成,还支持通过插件进行扩展。

    10 引用 • 5 回帖 • 2 关注
  • 又拍云

    又拍云是国内领先的 CDN 服务提供商,国家工信部认证通过的“可信云”,乌云众测平台认证的“安全云”,为移动时代的创业者提供新一代的 CDN 加速服务。

    20 引用 • 37 回帖 • 576 关注
  • Kafka

    Kafka 是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是现代系统中许多功能的基础。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。

    36 引用 • 35 回帖 • 2 关注
  • Thymeleaf

    Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。类似 Velocity、 FreeMarker 等,它也可以轻易的与 Spring 等 Web 框架进行集成作为 Web 应用的模板引擎。与其它模板引擎相比,Thymeleaf 最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个 Web 应用。

    11 引用 • 19 回帖 • 391 关注
  • GitLab

    GitLab 是利用 Ruby 一个开源的版本管理系统,实现一个自托管的 Git 项目仓库,可通过 Web 界面操作公开或私有项目。

    46 引用 • 72 回帖 • 1 关注
  • OneDrive
    2 引用
  • Log4j

    Log4j 是 Apache 开源的一款使用广泛的 Java 日志组件。

    20 引用 • 18 回帖 • 29 关注
  • 爬虫

    网络爬虫(Spider、Crawler),是一种按照一定的规则,自动地抓取万维网信息的程序。

    106 引用 • 275 回帖
  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖