恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

obsidian-weread-plugin 模板编辑器窗口:三栏布局、Nunjucks 实时预览与主题系统集成

  • 首页
  • 资讯中心
  • /
  • obsidian-weread-plugin 模板编辑器窗口:三栏布局、Nunjucks 实时预览与主题系统集成

相关资讯

UML试题刷题攻略:用例图与顺序图核心考点与答题模板 2026/10/13 11:06:23
DR5白金高级版:Windows下PS2021的RAW处理增强方案 2026/10/13 11:06:23
工业相机选型与调试实战:Dalsa相机应用经验全解析 2026/10/13 11:01:22

最新资讯

MyBatis与MyCat分库整合实战:配置、SQL适配与故障排查
Anaconda虚拟环境管理:PyCharm项目配置与依赖避坑指南
蓝牙音频芯片选型实战指南:不看参数看场景
CAD/SHP/KML套合卫星影像:坐标校准全流程指南
编程智能体插件实战:余额监控、任务面板与番茄钟的设计之道
Nginx反向代理实战:让后台管理系统从IP:端口变成干净域名

今日推荐

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析
CAN总线错误处理机制深度解析:从位错误到Bus Off的硬件级调试

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

obsidian-weread-plugin 模板编辑器窗口:三栏布局、Nunjucks 实时预览与主题系统集成

发布时间:2026/10/13 11:06:23
obsidian-weread-plugin 模板编辑器窗口:三栏布局、Nunjucks 实时预览与主题系统集成 知识管理知识库【免费下载链接】obsidian-weread-pluginObsidian Weread Plugin is a plugin to sync Weread(微信读书) hightlights and annotations into your Obsidian Vault.项目地址https://gitcode.com/gh_mirrors/ob/obsidian-weread-plugin点击查看免费下载本文基于仓库设计文档 template-editor-window.md 展开详解 obsidian-weread-plugin微信读书划线同步到 Obsidian 的插件中模板编辑器窗口的设计与实现三栏布局模板说明 / 编辑器 / 实时预览、300ms 防抖渲染管线、Nunjucks 模板变量与过滤器体系以及它与主题管理系统Theme / activeThemeId的集成方式。读完你可以理解该编辑器从输入到预览到保存的完整调用链并掌握TemplateEditorWindow的编程式调用与 Nunjucks 模板语法。一、设计目标与功能概览obsidian-weread-plugin 将微信读书的划线、想法笔记和热门划线渲染成 Markdown 笔记写入 Vault渲染逻辑由 Nunjucks 模板驱动。模板编辑器窗口就是这个模板的可视化编辑/调试工具核心目标是让普通用户在不动手改 JSON 配置的情况下边写模板、边看渲染效果、边对照语法说明从而快速定制自己的读书笔记格式。设计文档中定义的功能特性包括三栏布局左侧模板说明文档设计规格宽 300px可在 250-500px 间拖动调整显示完整的 Nunjucks 模板语法说明包含可用变量、过滤器和示例代码支持拖动调整宽度中间模板编辑器自适应宽度语法高亮的代码编辑器支持 Nunjucks 模板语法实时语法验证右侧实时预览自适应宽度300ms 防抖的实时渲染使用示例数据预览效果错误提示显示窗口功能原生窗口体验设计文档提出使用 ElectronBrowserWindow提供完整的原生窗口功能可拖动标题栏通过标题栏拖动整个窗口最小尺寸1200×600px初始尺寸1600×900px响应式布局自动适应窗口大小深色主题专为深色模式优化的 UI从源码结构看当前仓库快照中的 TemplateEditorWindow 继承自 Obsidian 的Modal对应设计文档对比表中的 Modal 形态初始尺寸 95vw×90vh但已完整实现了上述三栏布局与全部编辑/预览交互而 ElectronBrowserWindow原生窗口模式在本项目其他模块中确有实际使用例如 WereadBrowserWindow 通过remote.BrowserWindow创建带独立 session partition 的微信读书浏览窗口wereadLoginModel.ts 和 wereadLogoutModel.ts 也采用同一模式。也就是说文档描述的 BrowserWindow 方案 与当前 Modal 实现共享同一套三栏编辑器结构区别主要在宿主窗口的承载方式。二、组件结构设计视图与实际实现设计文档给出的组件结构树如下这是设计视角的调用结构其中 Constructor/open/IPC 部分对应原生窗口方案templateEditorWindow.ts ├── Constructor │ ├── 创建 BrowserWindow │ ├── 设置窗口参数 │ └── 初始化 Renderer ├── loadContent() │ └── 加载 HTML 内容 ├── generateHTML() │ ├── 生成完整的 HTML/CSS/JS │ ├── 嵌入模板说明文档 │ └── 设置事件监听器 ├── open() │ ├── 设置 IPC 通信 │ ├── update-preview: 更新预览 │ ├── save-template: 保存模板 │ └── close-window: 关闭窗口 └── buildSampleNotebook() └── 生成示例数据对照当前仓库的实际源码 src/components/templateEditorWindow.ts核心方法结构如下方法 / 成员行号职责constructorL21-L37接收app、initialTemplate、onSave回调可选initialTrimBlocks、readOnly、themeName内部创建Renderer实例shouldCloseOnEscL40-L42返回false禁用 ESC 关闭防止误触丢失编辑内容onOpenL44-L170构建标题栏、三栏容器、两个功能开关、监听编辑器输入事件updatePreviewL172-L218用示例数据渲染当前模板并写入预览区处理空结果与异常handleCancelL220-L229有未保存修改时弹出确认对话框handleSaveL231-L241先做语法校验通过后才调用onSave(template, trimBlocks)onCloseL243-L249清空 DOM、清理防抖定时器对应文档 内存管理窗口关闭时清理监听器 的注意点buildSampleNotebookL251-L603生成一份结构完整的示例Notebook数据供预览使用构造函数签名体现了编辑器的两种工作模式constructor( app: App, initialTemplate: string, // 当前模板字符串 onSave: (template: string, trimBlocks: boolean) void, // 保存回调 initialTrimBlocks?: boolean, // 可选自动去空白初始值 readOnly false, // 只读预览主题模式 themeName?: string )只读模式下编辑器被禁用editorEl.disabled true标题显示为预览: ${themeName}且隐藏保存按钮——这正是主题管理器 预览 功能复用的路径。三、三栏布局的实现细节左侧模板说明文档说明文档是一个独立的 HTML 资产 templateInstructions.html在编辑模式下注入左栏// 仅编辑模式显示 if (!this.readOnly) { const instructionsPanel container.createDiv(weread-editor-instructions); instructionsPanel.innerHTML templateInstructions; }Webpack 配置中.html被声明为asset/source见 webpack.config.js因此import templateInstructions from ../assets/templateInstructions.html得到的是字符串可直接填充到 DOM。文档中的可用变量、过滤器清单见下文模板语法与可用变量一节。中间模板编辑器中间栏使用textarea承载模板源码面板标题区分编辑/预览模式模板编辑 (Nunjucks)或模板内容。样式定义在 style.css.weread-editor-panel、.weread-editor-textarea中整体布局容器为.weread-editor-containerL49采用 Flexbox 组织三栏标题栏样式在 L28。右侧实时预览与防抖预览区的核心交互是300ms 防抖与设计文档一致// src/components/templateEditorWindow.ts L162-L169 this.editorEl.addEventListener(input, () { if (this.debounceTimer) { activeWindow.clearTimeout(this.debounceTimer as unknown as number); } this.debounceTimer activeWindow.setTimeout(() { this.updatePreview(); }, 300); });预览面板头部还承载了三个功能开关✂️ 自动去空白trimBlocks切换后立即重渲染只读模式下展示但禁用 热门划线仅只读模式展示且禁用热门划线展示由插件全局设置控制见syncPopularHighlightsToggle Markdown 渲染开启后预览经 ObsidianMarkdownRenderer.renderMarkdown渲染为格式化视图关闭则用pre显示原始文本L199-L212updatePreview()的渲染管线为const templateStr this.editorEl.value; const sampleNotebook this.buildSampleNotebook(); const preview this.renderer.renderWithTemplate(templateStr, sampleNotebook, this.trimBlocks);错误处理分两级渲染结果为空时提示⚠️ 渲染结果为空请检查模板语法Nunjucks 抛异常时捕获并显示❌ error.messageL213-L217。这对应文档中 错误提示显示 的特性。示例数据buildSampleNotebook()预览不依赖真实的微信读书登录态而是使用内嵌的示例书籍《中国哲学简史》bookId651358构造的Notebook对象覆盖了三类渲染入口metaData书名、作者、封面 URL、ISBN、分类、出版社、简介、readInfo阅读时长、总阅读天数、完成时间戳等chapterHighlights4 个章节、8 条划线覆盖普通划线、用户划线 热门isPopularisUserHighlight、纯热门划线带popularCount共读人数、带批注reviewContent四种形态popularHighlights按章节聚合的热门划线带totalCountbookReviewchapterReviews章节笔记与bookReviews整书笔记含mdContent这份数据保证用户在编辑器里能一次性看到模板所有分支if/for/过滤器的真实渲染效果。四、渲染引擎Renderer 与 Nunjucks 过滤器预览与保存共用的渲染器是 src/renderer.ts它封装了 Nunjucks 环境export class Renderer { constructor() { const env nunjucks.configure({ autoescape: false }); addDateFilters(env); }关键点autoescape: false—— 因为模板输出的是 Markdown 笔记转义会破坏{{ }}、、等 Markdown 语法Nunjucks 标签本身不是 HTML无需自动转义。内置过滤器addDateFiltersL6-L50注册了以下过滤器与说明文档 HTML 中的清单一一对应过滤器作用默认格式formatDate秒级时间戳 → 日期YYYY-MM-DDformatDateTime秒级时间戳 → 日期时间YYYY-MM-DD HH:mm:ssformatTime秒级时间戳 → 时间HH:mm:sssplit按分隔符拆分为数组—replace字符串或正则替换支持/pattern/flags写法—trim去除首尾空白—时间过滤器基于 Obsidian 内置的window.moment实现因此模板中可以直接写{{ finishedDate | formatDate(YYYY年MM月DD日) }}这样的自定义格式。渲染入口与校验render(entry)L68-L106同步流程正式渲染笔记时调用从settingsStore取当前激活主题的模板与trimBlocks兼容 legacy 主题source legacy时回落到顶层settings.templaterenderWithTemplate(templateStr, entry, trimBlocks)L115-L142编辑器预览专用为临时模板字符串创建独立的 Nunjucks 环境trimBlocks与lstripBlocks同步开启validate(template)L58-L66用空上下文试渲染捕获异常返回布尔值——这就是保存前 实时语法验证 的落地方式trimBlocks的语义开启后自动移除模板标签{% %}前后的换行和空格让用户可以用缩进写出更易读的模板代码而不产生多余空行。五、模板语法与可用变量左侧说明文档 templateInstructions.html 是编辑器内置的 随附参考手册其内容如下此处完整继承并补充实现侧佐证功能开关✂️ 自动去空白开启后自动移除模板标签{% %}前后的换行和空格让你可以用缩进写出更易读的模板代码 Markdown 渲染开启后右侧预览会渲染为格式化的 Markdown关闭则显示原始文本Filter 过滤器时间戳字段readInfo中的readingBookDate、finishedDate等为秒级时间戳可用以下过滤器转换为可读格式timestamp | formatDate→2020-01-29格式 YYYY-MM-DD可传入自定义格式timestamp | formatDateTime→2020-01-29 08:00:00格式 YYYY-MM-DD HH:mm:ss可传入自定义格式timestamp | formatTime→08:00:00格式 HH:mm:ss可传入自定义格式示例{{ finishedDate | formatDate }} {{ finishedDate | formatDateTime }} {{ finishedDate | formatDate(YYYY年MM月DD日) }} {{ readingBookDate | formatDateTime(YYYY/MM/DD HH:mm) }}可用变量元数据变量metaData变量含义{{ title }}书名{{ author }}作者{{ cover }}封面{{ intro }}书籍简介{{ bookId }}微信图书 ID{{ publishTime }}出版时间{{ noteCount }}划线数量{{ reviewCount }}笔记数量{{ isbn }}ISBN{{ category }}分类{{ publisher }}出版社{{ readInfo }}阅读信息点击查看详情readInfo 阅读信息变量含义{{ readingTime }}阅读时长秒{{ totalReadDay }}总阅读天数{{ continueReadDays }}连续阅读天数{{ readingBookCount }}阅读书籍数{{ readingBookDate }}开始阅读时间时间戳{{ finishedDate }}完成阅读时间时间戳{{ readingProgress }}阅读进度划线变量chapterHighlights变量含义{{ chapterUid }}章节 ID{{ chapterTitle }}章节标题{{ createTime }}创建时间{{ range }}划线范围{{ markText }}划线文本笔记bookReview变量含义{{ reviewId }}reviewId{{ chapterUid }}章节 ID{{ chapterTitle }}章节标题{{ createTime }}创建时间{{ abstract }}摘录内容{{ content }}笔记内容{{ mdContent }}Markdown 笔记格式{{ type }}类型{{ range }}范围模板上下文与内置主题示例渲染时注入的上下文对象为{ metaData, chapterHighlights, bookReview, popularHighlights, syncPopularHighlightsToggle }见 renderer.ts L119-L125其中syncPopularHighlightsToggle是控制是否展示热门划线的条件变量。仓库内置三个主题模板可作为学习范本notebookTemplate.njk合并式划线与想法 inline 展示、separatedTemplate.njk分离式笔记统一在底部、wereadOfficialTemplate.njk微信官方笔记风格。以合并式模板为例展示章节标题按level映射到 Markdown 标题、划线生成微信读书 deeplink 的典型写法{% for chapter in chapterHighlights %} {% if chapter.level 1 %} ## {{ chapter.chapterTitle }} {% for highlight in chapter.highlights %} {% set rangeParts highlight.range | split(-) %} {% set deeplink weread://bestbookmark?bookId metaData.bookId chapterUid highlight.chapterUid rangeStart rangeParts[0] rangeEnd rangeParts[1] %} {% if highlight.isPopular and highlight.isUserHighlight %} {{ highlight.markText | trim }} {{ highlight.popularCount }} 人共读 ⏱ {{ highlight.createTime }} ^{{ highlight.bookmarkId }} {% endif %} {% endfor %} {% endfor %}片段取自 notebookTemplate.njk L19-L43展示了split、trim过滤器与字符串拼接的用法。六、IPC 通信设计原生窗口方案设计文档为 BrowserWindow 方案规划的进程间通信协议如下渲染进程 → 主进程update-preview发送模板字符串以更新预览save-template保存模板close-window关闭窗口主进程 → 渲染进程preview-updated返回渲染结果或错误信息从源码结构看当前仓库快照中不存在ipcMain/ipcRenderer的对应实现——因为当前TemplateEditorWindow运行在 Obsidian 主窗口页面内等价能力由进程内回调完成预览直接同步调用renderer.renderWithTemplate保存通过构造函数注入的onSave回调写回设置。文档中的 IPC 通道属于原生窗口形态的设计规划若未来TemplateEditorWindow迁移到独立BrowserWindow如登录窗口 wereadBrowserWindow.ts 的模式这套通道命名即为落地蓝图。七、使用方式与调用链1. 在设置页面中调用设计文档示例设计文档给出了设置页集成编辑器的调用范式// settingTab.ts private template(): void { const descFragment document.createRange() .createContextualFragment(templateInstructions); new Setting(this.containerEl) .setName(笔记模板) .setDesc(descFragment) .addButton((button) { return button .setButtonText(编辑模板) .setCta() .onClick(() { const editorWindow new TemplateEditorWindow( get(settingsStore).template, (newTemplate: string) { settingsStore.actions.setTemplate(newTemplate); } ); editorWindow.open(); }); }); }保存动作setTemplate在 settings.ts L414-L419 中将新模板写入 settings store 并持久化。当前仓库的实际演进从源码结构看settingTab.ts 的template()段落现在不再直接创建编辑器而是提供 主题管理 入口打开ThemeManagerModal管理内置/自定义/社区主题TemplateEditorWindow的调用点转移到了 themeManagerModal.ts// 预览只读 const editorWindow new TemplateEditorWindow( this.app, templateForPreview, () {}, theme.trimBlocks, true, // readOnly theme.name ); editorWindow.open(); // 编辑保存回主题 const editorWindow new TemplateEditorWindow( this.app, theme.template, (newTemplate: string, newTrimBlocks: boolean) { settingsStore.actions.saveTheme({ ...latestTheme, template: newTemplate, trimBlocks: newTrimBlocks }); new Notice(主题已保存); }, theme.trimBlocks, false, theme.name );这体现了保存回调签名为(template, trimBlocks)的原因一个主题同时携带模板文本与去空白开关两个属性。2. 编程调用import { TemplateEditorWindow } from ./components/templateEditorWindow; // 创建编辑器窗口 const editor new TemplateEditorWindow( currentTemplate, // 当前模板字符串 (newTemplate: string) { // 保存回调 // 处理保存的模板 console.log(新模板:, newTemplate); } ); // 打开窗口 editor.open();实际调用时按当前签名需额外传入app作为第一参数new TemplateEditorWindow(app, template, onSave, ...)并以editorWindow.open()打开——与 themeManagerModal.ts 中的用法一致。3. 保存流程的校验闸门保存并非直接落盘handleSave() 先用renderer.validate(template)做一次试渲染const isValid this.renderer.validate(template); if (!isValid) { new Notice(模板语法错误请检查后再保存); return; } this.onSave(template, this.trimBlocks); new Notice(模板已保存);配合取消时的未保存变更确认模板已修改但未保存确定要关闭吗与shouldCloseOnEsc禁用 ESC构成完整的防误操作链路。八、与之前实现的对比设计文档给出的 Modal 与 BrowserWindow 两代实现对比特性之前 (Modal)现在 (BrowserWindow)窗口类型Obsidian ModalElectron 原生窗口布局两栏编辑器预览三栏说明编辑器预览大小调整8方向拖拽调整原生窗口缩放窗口拖动自定义拖拽实现原生标题栏拖拽最大化自定义按钮原生最大化按钮最小尺寸600×400px1200×600px初始尺寸95vw×90vh1600×900px说明文档在设置页面集成在窗口左侧主题适配CSS 变量独立样式结合当前源码可以确认现在的 Modal 实现已经吸收了 现在 一栏的大部分特性——三栏布局、95vw×90vh 初始尺寸L56-L59、说明文档集成在窗口左侧、样式完全使用独立的.weread-editor-*类族style.css L14 起。两代实现共享的是编辑器核心三栏 防抖预览 语法校验差异集中在窗口宿主Modal 受限于 Obsidian 主窗口内部而 BrowserWindow 方案可获得系统级的最小化/最大化/独立缩放能力。九、主题系统集成模板编辑器不是孤立的它嵌入了 settings.ts 定义的主题体系。Theme接口models.ts L606-L617为export interface Theme { id: string; name: string; description?: string; template: string; trimBlocks: boolean; isBuiltIn: boolean; isReadOnly: boolean; source: builtin | custom | legacy; author?: string; version?: string; }BUILT_IN_THEMES提供三个内置只读主题builtin_merged合并式、builtin_separated分离式、builtin_official微信官方笔记主题全部trimBlocks: truesettings.activeThemeId记录当前激活主题getActiveTheme()用于同步流程取模板legacy 主题source legacy始终回落使用顶层settings.template编辑入口由isReadOnly控制内置/社区主题只能 预览 复制并自定义自定义主题可以进入TemplateEditorWindow编辑并saveTheme保存十、注意事项与未来改进设计文档列出的注意事项与源码印证如下仅支持桌面端BrowserWindow仅在 Electron 环境中可用扫码登录等桌面功能同样依赖此判断如 settingTab.ts 中Platform.isDesktopApp的分支内存管理确保窗口关闭时清理 IPC 监听器——当前实现在onClose()中contentEl.empty()并clearTimeout防抖定时器L243-L249调试可以使用 Electron DevTools 调试窗口内容性能使用 300ms 防抖优化实时预览性能L162-L169文档规划的未来改进方向添加快捷键支持CmdS 保存等支持多标签页编辑多个模板添加模板历史记录支持模板导入导出添加语法高亮和自动补全支持实时预览滚动同步其中 支持模板导入导出 在 themeManagerModal.ts 已部分落地主题级导出含manifest元数据。十一、相关文件索引路径说明docs/template-editor-window.md本文依据的设计文档最后更新 2025-11-22src/components/templateEditorWindow.ts编辑器窗口实现三栏布局、防抖预览、保存校验src/renderer.tsNunjucks 渲染器、过滤器注册、validate/renderWithTemplatesrc/assets/templateInstructions.html左栏模板语法说明文档src/themes/notebookTemplate.njk 等三个内置主题模板范例src/components/themeManagerModal.ts主题管理器编辑器的当前主要调用方src/settingTab.ts设置页 模板设置 段落src/settings.tsBUILT_IN_THEMES、setTemplate等设置动作style.css编辑器窗口样式.weread-editor-*注本文以当前仓库快照源码为准。设计文档描述的部分 BrowserWindow/IPC 细节属于原生窗口方案的设计规划当前TemplateEditorWindow以 Obsidian Modal 形式承载核心编辑/预览能力与文档描述一致。赞分享知识管理知识库【免费下载链接】obsidian-weread-pluginObsidian Weread Plugin is a plugin to sync Weread(微信读书) hightlights and annotations into your Obsidian Vault.项目地址https://gitcode.com/gh_mirrors/ob/obsidian-weread-plugin点击查看免费下载相关推荐如何快速集成media-kit到Flutter项目3分钟入门教程如何快速集成media kit到Flutter项目3分钟入门教程 media kit是一个功能强大的跨平台音视频播放器专为Flutter和Dart开发支持音视频跨平台3个步骤快速掌握ComfyUI UltimateSDUpscale图像放大技术3个步骤快速掌握ComfyUI UltimateSDUpscale图像放大技术 ComfyUI UltimateSDUpscale图像放大 扩展是一个强大的AI人工智能计算机视觉图像处理媒体生成Bowhead技术指标全解析18种交易信号算法实战应用Bowhead技术指标全解析18种交易信号算法实战应用 Bowhead作为一款强大的PHP交易机器人框架集成了18种主流技术指标算法帮助交易者构建自动化交创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号