求助思源导出 markdown 快捷键

求大佬 帮忙写一个 JS 代码,功能为为思源的导出 markdown 格式 添加快捷键。或者告知写代码方法也行,我是小白。

image.png

或者能把这下方这个 "Markdown 批量转换" 插件设置一个快捷键,能呼出转换面板 就更好啦~

image.png

  • 思源笔记

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

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

    25296 引用 • 104434 回帖
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    9662 引用 • 43960 回帖 • 90 关注

相关帖子

被采纳的回答
  • wilsons 1 赞同

    确实用 zip 解压的方式较复杂,不过还有更简单方法,比如,直接读取文档 Markdown 源码,然后把内容直接写入到文件,这样只需要两步即可。

    代码如下

    // alt+d 导出markdown文档(docId为空导出当前文档) // see https://ld246.com/article/1743689632996 { // 导出文档的id(docId为空导出当前文档) const docId = ''; // 写入markdown文件路径 // 需填写绝对路径 // windows路径需要用\转义,比如 c:\\ const toPath = '/your/path/Downloads/'; // alt+d事件 document.addEventListener('keydown', async function(event) { // 检查是否按下了 Alt 键和 D 键,并确保没有按下其他修饰键 if ( event.altKey && // Alt 键被按下 event.code === 'KeyD' && // D 键被按下 !event.shiftKey && // Shift 键未被按下 !event.ctrlKey && // Ctrl 键未被按下 !event.metaKey // Cmd 键(Meta 键)未被按下 ) { event.preventDefault(); // 阻止默认行为(可选) if(!isElectron()) { showMessage('仅在Electron客户端有效', true); return; } // 获取Markdown文本 const doc = await fetchSyncPost("/api/lute/copyStdMarkdown", {id: docId || getCurrentDocId()}); if(!doc || doc.code !== 0) { showMessage(doc.msg || '获取文档失败', true); return; } const markdown = doc.data || ''; // 写入文本到文件 const fs = require('fs'); if (!fs.existsSync(toPath)) { showMessage('保存路径不存在', true); return; } let title = '未命名文档'; if(docId) { const docInfo = fetchSyncPost('/api/block/getDocInfo',{id:docId}); if(docInfo && docInfo.data && docInfo.data.name){ title = docInfo.data.name; } } else { title = getCurrentDocTitle() || title; } const path = require('path'); fs.appendFileSync(path.join(toPath, title + '.md'), markdown, 'utf8'); showMessage('已导出成功', false, 3000); } }, true); // 获取当前文档id function getCurrentDocId() { return (document.querySelector('[data-type="wnd"].layout__wnd--active .protyle:not(.fn__none)')||document.querySelector('[data-type="wnd"] .protyle:not(.fn__none)'))?.querySelector('.protyle-title')?.dataset?.nodeId; } function getCurrentDocTitle() { return (document.querySelector('[data-type="wnd"].layout__wnd--active .protyle:not(.fn__none)')||document.querySelector('[data-type="wnd"] .protyle:not(.fn__none)'))?.querySelector('.protyle-title__input')?.textContent; } // api请求 async function fetchSyncPost(url, data, method = 'POST') { return await (await fetch(url, {method: method, body: JSON.stringify(data||{})})).json(); } function isElectron() { return navigator.userAgent.includes('Electron'); } // 发送消息 function showMessage(message, isError = false, delay = 7000) { return fetch('/api/notification/' + (isError ? 'pushErrMsg' : 'pushMsg'), { "method": "POST", "body": JSON.stringify({"msg": message, "timeout": delay}) }); } }

欢迎来到这里!

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

注册 关于
请输入回帖内容 ...
  • wilsons 1 赞同

    确实用 zip 解压的方式较复杂,不过还有更简单方法,比如,直接读取文档 Markdown 源码,然后把内容直接写入到文件,这样只需要两步即可。

    代码如下

    // alt+d 导出markdown文档(docId为空导出当前文档) // see https://ld246.com/article/1743689632996 { // 导出文档的id(docId为空导出当前文档) const docId = ''; // 写入markdown文件路径 // 需填写绝对路径 // windows路径需要用\转义,比如 c:\\ const toPath = '/your/path/Downloads/'; // alt+d事件 document.addEventListener('keydown', async function(event) { // 检查是否按下了 Alt 键和 D 键,并确保没有按下其他修饰键 if ( event.altKey && // Alt 键被按下 event.code === 'KeyD' && // D 键被按下 !event.shiftKey && // Shift 键未被按下 !event.ctrlKey && // Ctrl 键未被按下 !event.metaKey // Cmd 键(Meta 键)未被按下 ) { event.preventDefault(); // 阻止默认行为(可选) if(!isElectron()) { showMessage('仅在Electron客户端有效', true); return; } // 获取Markdown文本 const doc = await fetchSyncPost("/api/lute/copyStdMarkdown", {id: docId || getCurrentDocId()}); if(!doc || doc.code !== 0) { showMessage(doc.msg || '获取文档失败', true); return; } const markdown = doc.data || ''; // 写入文本到文件 const fs = require('fs'); if (!fs.existsSync(toPath)) { showMessage('保存路径不存在', true); return; } let title = '未命名文档'; if(docId) { const docInfo = fetchSyncPost('/api/block/getDocInfo',{id:docId}); if(docInfo && docInfo.data && docInfo.data.name){ title = docInfo.data.name; } } else { title = getCurrentDocTitle() || title; } const path = require('path'); fs.appendFileSync(path.join(toPath, title + '.md'), markdown, 'utf8'); showMessage('已导出成功', false, 3000); } }, true); // 获取当前文档id function getCurrentDocId() { return (document.querySelector('[data-type="wnd"].layout__wnd--active .protyle:not(.fn__none)')||document.querySelector('[data-type="wnd"] .protyle:not(.fn__none)'))?.querySelector('.protyle-title')?.dataset?.nodeId; } function getCurrentDocTitle() { return (document.querySelector('[data-type="wnd"].layout__wnd--active .protyle:not(.fn__none)')||document.querySelector('[data-type="wnd"] .protyle:not(.fn__none)'))?.querySelector('.protyle-title__input')?.textContent; } // api请求 async function fetchSyncPost(url, data, method = 'POST') { return await (await fetch(url, {method: method, body: JSON.stringify(data||{})})).json(); } function isElectron() { return navigator.userAgent.includes('Electron'); } // 发送消息 function showMessage(message, isError = false, delay = 7000) { return fetch('/api/notification/' + (isError ? 'pushErrMsg' : 'pushMsg'), { "method": "POST", "body": JSON.stringify({"msg": message, "timeout": delay}) }); } }
    1 回复
  • 其他回帖
  • carethink via macOS
    作者

    感谢感谢~,我按照您的代码一次成功。导出的文件是 zip 文件夹,然后我在这个基础上用 ai 修改了一下,按 alt+d 之后,直接导出 markdown 文件,不经过浏览器下载。

    但是遇到一个问题,每个文件导出时都会弹出一个“存储为”的窗口,让我选择 文件保存路径并填写文件名,文件名的位置 默认显示"未命名文档.md",每次都要修改,这就很麻烦。如果能够把这一步绕过去,直接存储,并以思源内的原始文件名进行保存,就太好了。如果绕不过去的话,能不能在每次都弹出这个窗口时,让文件名默认显示为 我导出文档的文件名呢, 这样我每次导出只需要按一个回车。具体代码如下:

    代码.txt.zip

    1 回复
  • 试试这个 alt+d 导出 markdown 文档(docId 为空导出当前文档)

    // alt+d 导出markdown文档(docId为空导出当前文档) // see https://ld246.com/article/1743689632996 { // 导出文档的id(docId为空导出当前文档) const docId = ''; // alt+d事件 document.addEventListener('keydown', async function(event) { // 检查是否按下了 Alt 键和 D 键,并确保没有按下其他修饰键 if ( event.altKey && // Alt 键被按下 event.code === 'KeyD' && // D 键被按下 !event.shiftKey && // Shift 键未被按下 !event.ctrlKey && // Ctrl 键未被按下 !event.metaKey // Cmd 键(Meta 键)未被按下 ) { event.preventDefault(); // 阻止默认行为(可选) const result = await fetchSyncPost('/api/export/exportMd', {id:docId||getCurrentDocId()}); window.open(result.data.zip); } }, true); // 获取当前文档id function getCurrentDocId() { return (document.querySelector('[data-type="wnd"].layout__wnd--active .protyle:not(.fn__none)')||document.querySelector('[data-type="wnd"] .protyle:not(.fn__none)'))?.querySelector('.protyle-title')?.dataset?.nodeId; } // api请求 async function fetchSyncPost(url, data, method = 'POST') { return await (await fetch(url, {method: method, body: JSON.stringify(data||{})})).json(); } }
    1 回复
    1 操作
    wilsons 在 2025-04-04 10:28:54 更新了该回帖
  • 确实,编程有时对提高效率确实重要。

    对于思源来说会 js 和 css 就够了 。

    现在网上基本都有入门视频啥的,一般能耐心看完一套基本就入门了,深入就得靠多实践了。

    我也没系统学过 js,基本用到什么学什么,不过要深入,系统学习还是很重要的。

    1 回复
  • 查看全部回帖

推荐标签 标签

  • 友情链接

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

    24 引用 • 373 回帖
  • Ubuntu

    Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的 Linux 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。Ubuntu 的目标在于为一般用户提供一个最新的、同时又相当稳定的主要由自由软件构建而成的操作系统。

    127 引用 • 169 回帖
  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    173 引用 • 414 回帖 • 367 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 564 关注
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 435 关注
  • RIP

    愿逝者安息!

    8 引用 • 92 回帖 • 399 关注
  • 安全

    安全永远都不是一个小问题。

    203 引用 • 818 回帖
  • Webswing

    Webswing 是一个能将任何 Swing 应用通过纯 HTML5 运行在浏览器中的 Web 服务器,详细介绍请看 将 Java Swing 应用变成 Web 应用

    1 引用 • 15 回帖 • 640 关注
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    495 引用 • 930 回帖
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    267 引用 • 666 回帖
  • 七牛云

    七牛云是国内领先的企业级公有云服务商,致力于打造以数据为核心的场景化 PaaS 服务。围绕富媒体场景,七牛先后推出了对象存储,融合 CDN 加速,数据通用处理,内容反垃圾服务,以及直播云服务等。

    28 引用 • 226 回帖 • 132 关注
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖
  • 宕机

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

    13 引用 • 82 回帖 • 76 关注
  • GAE

    Google App Engine(GAE)是 Google 管理的数据中心中用于 WEB 应用程序的开发和托管的平台。2008 年 4 月 发布第一个测试版本。目前支持 Python、Java 和 Go 开发部署。全球已有数十万的开发者在其上开发了众多的应用。

    14 引用 • 42 回帖 • 811 关注
  • danl
    164 关注
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    56 引用 • 85 回帖
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 495 关注
  • 叶归
    6 引用 • 17 回帖 • 12 关注
  • SEO

    发布对别人有帮助的原创内容是最好的 SEO 方式。

    35 引用 • 200 回帖 • 31 关注
  • ReactiveX

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的 API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。

    1 引用 • 2 回帖 • 181 关注
  • Firefox

    Mozilla Firefox 中文俗称“火狐”(正式缩写为 Fx 或 fx,非正式缩写为 FF),是一个开源的网页浏览器,使用 Gecko 排版引擎,支持多种操作系统,如 Windows、OSX 及 Linux 等。

    7 引用 • 30 回帖 • 385 关注
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    245 引用 • 1338 回帖
  • 代码片段

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

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

    154 引用 • 1008 回帖
  • 互联网

    互联网(Internet),又称网际网络,或音译因特网、英特网。互联网始于 1969 年美国的阿帕网,是网络与网络之间所串连成的庞大网络,这些网络以一组通用的协议相连,形成逻辑上的单一巨大国际网络。

    99 引用 • 367 回帖
  • CAP

    CAP 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。

    12 引用 • 5 回帖 • 631 关注
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖
  • RYMCU

    RYMCU 致力于打造一个即严谨又活泼、专业又不失有趣,为数百万人服务的开源嵌入式知识学习交流平台。

    4 引用 • 6 回帖 • 56 关注