Skip to content

Releases: Haoo-7/Obsidian-Dayline

Dayline Journal v2.10.0

Choose a tag to compare

@Haoo-7 Haoo-7 released this 08 Oct 08:49

HEIC photos taken on an iPhone now appear on every device: the desktop converts each one once into a shared thumbnail cache inside the vault, and phones and tablets read that cache directly without decoding anything.

Added

  • Cross-device HEIC thumbnails. Every desktop conversion is persisted into a configurable vault folder (default .dayline/thumbs; empty disables the cache) as one JPEG per source file plus an index.json manifest. Calendar day cells, timeline covers, On This Day photos, and HEIC note embeds on phones and tablets all read that cache. Matching needs only the source path and byte size, because a phone filesystem may re-report modification times in seconds, in local time, or rounded. The shared folder is written by the desktop only; mobile devices are read-only.
  • Background pre-warm. Once the journal index is ready, the desktop converts the HEICs the journal references (embeds, media/photos frontmatter, and the frontmatter cover) that the cache is still missing, up to 300 per session, through idle callbacks.
  • Generate everything now. A desktop-only settings action under Media metadata and privacy converts every referenced HEIC in one run, with inline progress and no per-session cap.
  • Mobile diagnostics report the shared cache state: enabled, entry count, and the reason the last read missed (index-missing, index-empty, no-entry, size-mismatch, file-missing, no-url-api), with no paths included.

Fixed

  • A phone no longer deletes the shared cache. Media events on a mobile device used to run the same "retire this entry" path as the desktop, so a phone deleted the shared thumbnail and its index entry and synced that deletion back upstream, breaking every device. Only the converting desktop may write the shared folder now.
  • An emptied cache folder rebuilds. A thumbnail that is still in memory now restores the shared copy when the file has gone, and a cache file deleted on another device invalidates the in-memory index instead of being trusted as fresh.
  • Day cells with an unresolvable cover fall back to the no-image placeholder instead of showing an empty tile that still claimed to have an image.

Verification

  • npm run typecheck, npm test (70 files / 800 tests, 39 of them new), npm run build, npm run package:release, npm run verify:release, npm run verify:release:zip and git diff --check pass. On the maintainer's machine 47 tests in the jsdom-environment suites fail for a pre-existing reason (Node/Vite externalize node:fs/node:path there); the failing set is byte-identical before and after this change.
  • Obsidian Sandbox: the built bundle deployed byte-identical and reloaded with no dev:errors. A real HEIC (947,758 bytes) converted to a 33,188-byte 900×675 JPEG, was served back as a blob URL, still matched after an 8-hour mtime shift, and the settings action rebuilt the cache from an emptied folder. data.json was rewritten by the plugin itself during the runs (weather cache only) and was restored from its byte-identical backup; Calendar/journal-metadata.json is unchanged.
  • iPhone 13 mini (real device, Syncthing test vault): confirmed — the HEIC note, its calendar day cell, and the timeline show the photo once the phone ran the read-only build. Android and the Obsidian Sync hint stay open: hidden cache folders are not synced by Obsidian Sync, so those users should point the setting at a visible folder.

Release assets

Obsidian's community installer downloads main.js, manifest.json, and styles.css individually. dayline.zip bundles those three plus THIRD_PARTY_NOTICES.md and the icons/ assets for a manual install: extract it into <Vault>/.obsidian/plugins/dayline-journal/ and enable the plugin.


iPhone 拍的 HEIC 照片现在能在所有设备上显示:桌面端把每张照片转换一次、写入 vault 内的共享缩略图缓存,手机和平板直接读取缓存,完全不需要解码。

新增

  • 跨设备 HEIC 缩略图。 桌面端每次转换都会写进一个可配置的 vault 目录(默认 .dayline/thumbs,留空关闭),每张源文件一个 JPEG,外加 index.json 清单。手机和平板上的日历格子、时间线封面、"去年今日"照片、笔记内嵌 HEIC 都读这份缓存。命中判定只看源文件路径和字节大小——手机文件系统可能把修改时间报成秒、本地时间或取整值。共享目录只由桌面端写入,移动端只读。
  • 后台预热。 日记索引就绪后,桌面端会在空闲时把日记引用到(正文内嵌、frontmatter media/photos,以及 frontmatter cover)但缓存里还缺的 HEIC 逐张转换,每会话上限 300 张。
  • 立即补齐全库缓存。 "媒体元数据与隐私"里的桌面端操作,一次跑完全部引用的 HEIC,行内显示进度,不受每会话上限限制。
  • 移动端诊断新增共享缓存状态:是否启用、条目数,以及上次读取失败的原因(index-missing、index-empty、no-entry、size-mismatch、file-missing、no-url-api),不含任何路径。

修复

  • 手机不再删除共享缓存。 以前移动端的媒体事件会走和桌面端相同的"注销条目"路径,于是手机删掉共享缩略图和索引条目,又把这次删除同步回上游,导致所有设备都坏掉。现在只有执行转换的桌面端可以写入共享目录。
  • 缓存目录被清空后能重建。 内存里仍持有的缩略图会在共享文件消失时重新补写;被其他设备删除的缓存文件会让内存索引失效,而不再被当作"仍然新鲜"。
  • 无法解析封面的日格回退为"无图片"占位,不再显示一块仍标记着"有图片"的空格子。

验证

  • npm run typecheck、npm test(70 个文件 / 800 项测试,其中 39 项为本次新增)、npm run build、npm run package:release、npm run verify:release、npm run verify:release:zip、git diff --check 全部通过。维护者本机有 47 项 jsdom 环境测试因既有原因失败(Node/Vite 在该环境下把 node:fs/node:path 外置),失败集合在本次改动前后逐字节一致。
  • Obsidian Sandbox:构建产物逐字节部署并重载,dev:errors 无错误。一张真实 HEIC(947,758 字节)转换成 33,188 字节、900×675 的 JPEG,能作为 blob URL 读回;把 mtime 人为挪 8 小时后仍能命中;设置里的按钮能从被清空的目录重建缓存。运行期间 data.json 由插件自身改写(仅天气缓存),已用逐字节备份还原;Calendar/journal-metadata.json 未变。
  • iPhone 13 mini(真机,Syncthing 测试库):已确认——手机运行只读构建后,HEIC 笔记、日历格子和时间线都能显示照片。Android 与 Obsidian Sync 提示仍为待办:Obsidian Sync 不同步隐藏目录,这类用户应把设置指向可见目录。

发布资源

Obsidian 社区安装器会分别下载 main.js、manifest.json 和 styles.css。dayline.zip 另外打包了 THIRD_PARTY_NOTICES.md 与 icons/ 资源,便于手动安装:解压到 <Vault>/.obsidian/plugins/dayline-journal/ 后启用插件即可。

Dayline Journal v2.9.4

Choose a tag to compare

@Haoo-7 Haoo-7 released this 06 Oct 03:56

Reviewing old diary entries no longer registers weather for those past days under the current address, and weather already recorded for a past day stays pinned.

Fixed

  • Browsing a past date no longer registers weather. Opening an old daily note (weather overlay) or selecting an old date in the calendar (weather card) used to fetch that day's weather from Open-Meteo using the currently configured coordinates and persist it into the weather cache — so after moving, or enabling weather later, old entries quietly acquired "weather at the current address" that was never recorded there. Settled historical dates (older than the 7-day revisable window) are now served from the cache only on the passive path; they gain weather only through an explicit act: the card/overlay refresh button, the refresh command, or the settings backfill. Recent dates (today and the revisable window) keep their previous behavior. A past date without recorded weather now shows the card's "no data" state instead of the error state.
  • A historical record can no longer be overwritten from a different place. The weather cache entry for a past day is the only remaining copy of that day, so persistence now refuses a snapshot that was fetched under different coordinates (a refresh or backfill run after moving) and keeps the pinned record. Same-place refetches — a units or timezone change, sub-kilometre drift — still update the entry.

Verification

  • npm run typecheck, npm test (69 files / 807 tests, including seven new regression tests), npm run build, npm run build:tablet, npm run package:release, npm run verify:release, npm run verify:release:zip and git diff --check all pass.
  • Obsidian Sandbox: main.js and manifest.json deployed byte-identical and reloaded with no dev:errors. The running build reports 2.9.4, its weather service carries both guards, and a live probe confirmed getSnapshot on a settled historical date resolves null with zero network requests and no cache write. data.json was rewritten once during the day — the legitimate TTL refresh of the 2026-10-06 (today) cache entry — and was restored from its byte-identical backup. Calendar/journal-metadata.json is unchanged.

Release assets

Obsidian's community installer downloads main.js, manifest.json, and styles.css individually. dayline.zip bundles those three plus THIRD_PARTY_NOTICES.md and the icons/ assets for a manual install: extract it into <Vault>/.obsidian/plugins/dayline-journal/ and enable the plugin.


回顾以前的日记时,不再按现在的地址为那些过去的日子登记天气;已经记录过的过去日期天气会被固定下来。

修复

  • 浏览过去日期不再登记天气。 以前打开旧日记(天气浮层)或在日历里选中过去的日期(天气卡片)时,插件会用当前配置的坐标向 Open-Meteo 请求那一天的天气并写入天气缓存——于是搬过家、或后来才开启天气的库,旧条目会悄悄多出一份"按现在地址登记"的天气。现在对于已定型的历史日期(早于 7 天可修订窗口),被动浏览路径只读缓存;要为过去的日子补天气,必须显式操作:卡片/浮层的刷新按钮、刷新命令,或设置里的批量补全。今天与 7 天窗口内的日期行为不变。没有天气记录的过去日期,卡片会显示"无数据"状态而不是错误状态。
  • 历史记录不再被不同地点的数据覆盖。 过去某天的天气缓存条目是那一天仅存的副本,因此持久化现在会拒绝一份用不同坐标取回的快照(搬家后的刷新或批量补全),保留已固定的记录。同一地点的重取——改温度单位或时区、亚公里级的漂移——仍会正常更新。

验证

  • npm run typecheck、npm test(69 个文件 / 807 项测试,含 7 项新增回归测试)、npm run build、npm run build:tablet、npm run package:release、npm run verify:release、npm run verify:release:zip、git diff --check 全部通过。
  • Obsidian Sandbox:main.js 与 manifest.json 逐字节部署并重载,dev:errors 无错误。运行中的构建报告 2.9.4,其天气服务带有两处修复,实测对历史日期调用 getSnapshot 返回 null、零网络请求、无缓存写入。运行期间 data.json 被改写过一次——2026-10-06(今天)缓存条目的正常 TTL 刷新——已用逐字节备份还原。Calendar/journal-metadata.json 未变。

发布资源

Obsidian 社区安装器会分别下载 main.js、manifest.json 和 styles.css。dayline.zip 另外打包了 THIRD_PARTY_NOTICES.md 与 icons/ 资源,便于手动安装:解压到 <Vault>/.obsidian/plugins/dayline-journal/ 后启用插件即可。

Dayline Journal v2.9.3

Choose a tag to compare

@Haoo-7 Haoo-7 released this 05 Oct 08:09

Three performance changes: full journal index rebuilds read entries concurrently, the timeline reuses its date formatters instead of building one per row, and calendar day backgrounds load lazily on mobile.

Performance

  • Full journal index rebuilds read entries with bounded concurrency. The rebuild walked every candidate markdown file one at a time, so vault-wide indexing paid the full serial cost of every read. It now fans out across four worker readers pulling from a shared candidate queue, keeping the same abort semantics — a refresh or mutation token change still stops every worker before anything is committed. A regression test drives overlapping reads and asserts the peak stays within the cap of four.
  • The timeline view reuses its Intl.DateTimeFormatters per locale. Every entry row built a fresh formatter for its weekday/day glyph and its "Updated" stamp, and every month header built another for the month label. Formatter construction is one of the most expensive things Intl does, and long timelines paid it for every rendered node. The three call sites now share module-level caches keyed by locale.
  • Calendar day background images load lazily. The per-day background node was created with loading="eager", so opening a month asked the browser to fetch every day's background at once. Days now request theirs as they approach the viewport (loading="lazy"; decoding="async" unchanged).

Verification

  • npm run typecheck, npm test (69 files / 800 tests), npm run build, npm run build:tablet, npm run package:release, npm run verify:release, npm run verify:release:zip and git diff --check all pass.
  • Obsidian Sandbox: main.js and manifest.json deployed byte-identical and reloaded with no dev:errors (styles.css is unchanged this release). The running build reports 2.9.3, and the timeline rendered from it stays correct through the new formatter caches — 31 entries with month headers (2026年9月 / 2026年7月 / 2025年9月), weekday/day glyphs (周二29), and "Updated" stamps all intact. The deployed bundle contains the four-reader constant and loading:"lazy" with no loading:"eager", while the 2.9.2 bundle has neither.
  • data.json was rewritten once during the run — a weather-cache refresh plus the first persistence of the pre-existing showCalendarWrittenMarker default (true, behaviorally a no-op) — and was restored from its byte-identical backup. Calendar/journal-metadata.json is unchanged.

Notes

  • Sandbox only, and partly mobile-only: the lazy-background change lives in the mobile branch (desktop renders a CSS background div, so the Mac window cannot produce an img), and the concurrency win shows at vault scales the demo vault cannot stage. Both are covered by the unit suite and deployed-bundle inspection; real-phone behavior stays a residual risk.

Release assets

Obsidian's community installer downloads main.js, manifest.json, and styles.css individually. dayline.zip bundles those three plus THIRD_PARTY_NOTICES.md and the icons/ assets for a manual install: extract it into <Vault>/.obsidian/plugins/dayline-journal/ and enable the plugin.


三处性能改动:日记索引全量重建改为并发读取,时间线复用日期格式化器而不是每行新建一个,日历格子的背景图在移动端改为懒加载。

性能

  • 日记索引全量重建改为有上限的并发读取。 以前重建逐个串行遍历所有候选 markdown 文件,全库索引要付完整的串行读取成本。现在由 4 个 worker 从共享候选队列并发读取,并保留同样的中止语义——refresh 或 mutation token 一变,所有 worker 都会在提交任何结果前停止。新增回归测试驱动并发读取,并断言峰值不超过 4 的上限。
  • 时间线视图按 locale 复用 Intl.DateTimeFormatter。 以前每条目行都为星期/日期字符和"更新于"时间各新建一个 formatter,每个月标题再建一个。formatter 的构造成本是 Intl 里最贵的操作之一,长时间线在每个渲染节点上都要付一次。三处调用点现在共享以 locale 为键的模块级缓存。
  • 日历格子背景图改为懒加载。 以前每日背景节点用 loading="eager" 创建,打开一个月就要求浏览器立刻抓取整月的背景图。现在随滚动接近视口才加载(loading="lazy";decoding="async" 不变)。

验证

  • npm run typecheck、npm test(69 个文件 / 800 项测试)、npm run build、npm run build:tablet、npm run package:release、npm run verify:release、npm run verify:release:zip、git diff --check 全部通过。
  • Obsidian Sandbox:main.js 与 manifest.json 逐字节部署并重载,dev:errors 无错误(本次 release 未改 styles.css)。运行中的构建报告 2.9.3,由它渲染的时间线经过新的 formatter 缓存后依旧正确——31 条条目,月份标题(2026年9月 / 2026年7月 / 2025年9月)、星期日期字符(周二29)、"更新于"时间全部完好。部署包里含 4-reader 常量与 loading:"lazy" 且没有 loading:"eager",而 2.9.2 的包两者相反。
  • 运行期间 data.json 被改写过一次——天气缓存刷新,外加既有的 showCalendarWrittenMarker 默认值(true,行为上无变化)首次被持久化——已用逐字节备份还原。Calendar/journal-metadata.json 未变。

备注

  • 仅有 Sandbox 证据,且部分改动只在移动端生效:懒加载位于移动端分支(桌面端渲染 CSS 背景的 div,Mac 窗口产生不出 img),并发读取的收益也要在大库里才显现,演示库无法呈现。两者由单元测试套件与部署包比对证明;真机行为仍是残留风险。

发布资源

Obsidian 社区安装器会分别下载 main.js、manifest.json 和 styles.css。dayline.zip 另外打包了 THIRD_PARTY_NOTICES.md 与 icons/ 资源,便于手动安装:解压到 <Vault>/.obsidian/plugins/dayline-journal/ 后启用插件即可。

Dayline Journal v2.9.2

Choose a tag to compare

@Haoo-7 Haoo-7 released this 05 Oct 08:09

One fix: timeline entries written on the same day now read as one group instead of looking like two unrelated days.

Fixed

  • Timeline entries written on the same day read as one group. Every card drew a separator below it and repeated the weekday/day glyph in the left column, so two notes of one day looked like two unrelated days. Adjacent cards sharing a journal date now drop the separator between them, and only the group's first card shows the weekday and day; each card keeps its own mood dot and "Updated" time.

Verification

  • npm run typecheck, npm test (69 files / 799 tests), npm run build, npm run build:tablet, npm run package:release, npm run verify:release, npm run verify:release:zip and git diff --check all pass.
  • Obsidian Sandbox: deployed byte-identical and reloaded with no dev:errors. The timeline rendered from the running build keeps the demo's same-day pair (2026-07-05-evening before 2026-07-05) as one group — dev:dom counts exactly one .journal-timeline-entry.has-same-day-next, that card's computed border-bottom-color is transparent, and the following card renders no weekday/day glyph while keeping its mood dot; neighboring different days keep both separator and date.

Notes

  • Sandbox only: the grouped cards were verified in the Mac desktop window; phone and tablet layouts share the same renderer and CSS but were not exercised on a real device, which stays a residual risk.

Release assets

Obsidian's community installer downloads main.js, manifest.json, and styles.css individually. dayline.zip bundles those three plus THIRD_PARTY_NOTICES.md and the icons/ assets for a manual install: extract it into <Vault>/.obsidian/plugins/dayline-journal/ and enable the plugin.


一处修复:同一天写下的时间线条目现在归为一组,而不是看起来像互不相干的两天。

修复

  • 同一天写下的时间线条目归为一组。 以前每张卡片下方都画分隔线,左列还重复星期和日期,同一天的两条记录看起来像互不相干的两天。现在相邻的同日期卡片之间不再有分隔线,星期和日期只出现在该组第一张卡片上;每张卡片保留自己的心情圆点和"更新于"时间。

验证

  • npm run typecheck、npm test(69 个文件 / 799 项测试)、npm run build、npm run build:tablet、npm run package:release、npm run verify:release、npm run verify:release:zip、git diff --check 全部通过。
  • Obsidian Sandbox:逐字节部署,重载后 dev:errors 无错误。运行中的构建把演示库里同一天的两条记录(2026-07-05-evening 在 2026-07-05 之前)归为一组——dev:dom 恰好数到一个 .journal-timeline-entry.has-same-day-next,该卡片的计算 border-bottom-color 为透明,后一张卡片不再渲染星期和日期但保留心情圆点;相邻的不同日期仍保留分隔线和日期。

备注

  • 仅有 Sandbox 证据:分组卡片在 Mac 桌面窗口验证;手机与平板布局共用同一渲染器和 CSS,但未在真机上验证,仍是残留风险。

发布资源

Obsidian 社区安装器会分别下载 main.js、manifest.json 和 styles.css。dayline.zip 另外打包了 THIRD_PARTY_NOTICES.md 与 icons/ 资源,便于手动安装:解压到 <Vault>/.obsidian/plugins/dayline-journal/ 后启用插件即可。

Dayline Journal 2.9.1

Choose a tag to compare

@Haoo-7 Haoo-7 released this 05 Oct 05:27

Three fixes: editor placeholder images stop claiming media info controls, Windows desktops without touch hardware stop being treated as touch devices, and the language dropdown becomes readable no matter which UI language you landed in.

Fixed

  • Editor placeholder images no longer get media info controls. Live Preview scatters CodeMirror placeholder widgets (img.cm-widgetBuffer) through the editor, and the note-media scan instrumented every <img> it found — each line's placeholder carried an aria-label, a tabindex, hover listeners, and, on touch devices, a visible info button that flashed as lines activated. The scan now skips placeholder widgets and requires a real image source, the same extension validation the embed path already had; real ![[…]] images keep hover EXIF and the touch button.
  • Windows desktops without touch hardware are no longer treated as touch devices. Chromium on Windows reports maxTouchPoints = 10 on machines with no touchscreen, and that alone flipped the plugin into its touch behavior — oversized targets and always-visible media info buttons. Touch now requires a coarse-pointer media query (primary or any pointer) or Obsidian's own mobile flag; touch-point counts only corroborate when no pointer query exists.
  • Every display language is listed under its own name. The language dropdown translated language names into the active UI language, so a user facing an unfamiliar UI — Russian showing "Упрощенный китайский" — had no readable way back. Each language now appears as its endonym (English, 简体中文, 繁體中文, 日本語, 한국어, Français, Deutsch, Español, Русский) in every UI language; only the "system" entry stays localized, because it is an instruction rather than a language name.

Verification

  • npm run typecheck, npm test (69 files / 796 tests), npm run build, npm run build:tablet, npm run package:release, npm run verify:release, npm run verify:release:zip and git diff --check all pass.
  • Obsidian Sandbox: deployed byte-identical and reloaded with no dev:errors. Before the fix, 91 of 91 img.cm-widgetBuffer placeholders in the live DOM carried the media aria-label; after, 46 of 46 are clean while a real ![[007.png]] embed keeps its instrumentation. The language dropdown rendered from the running build lists endonyms under the Chinese, Russian, and Traditional Chinese UIs alike — Система stays localized, every language entry is its own name.
  • data.json was rewritten once by a weather-cache fetch and nothing else; restored from its byte-identical backup. Calendar/journal-metadata.json is unchanged.

Notes

  • Sandbox only: it is a Mac desktop window with a fine pointer and maxTouchPoints = 0, so the Windows coarsePointer fix is proven by unit tests that simulate Chromium's reported values, not by a real Windows machine, and the touch info button flow was not exercised on a real phone. Both stay residual risks.

Release assets

Obsidian's community installer downloads main.js, manifest.json, and styles.css individually. dayline.zip bundles those three plus THIRD_PARTY_NOTICES.md and the icons/ assets for a manual install: extract it into <Vault>/.obsidian/plugins/dayline-journal/ and enable the plugin.


三处修复:编辑器占位图片不再冒领媒体信息按钮,没有触屏硬件的 Windows 桌面不再被当成触屏设备,语言下拉不管落在哪种界面语言里都读得懂。

修复

  • 编辑器占位图片不再冒领媒体信息控件。 Live Preview 会在编辑器里散布 CodeMirror 占位 widget(img.cm-widgetBuffer),而笔记媒体扫描见 <img> 就处理——每一行的占位符都带着 aria-label、tabindex、悬停监听,触屏设备上还会出现随行激活闪现的可见 info 按钮。现在扫描跳过占位 widget,并要求真实的图片 src,与 embed 路已有的扩展名校验对齐;真正的 ![[…]] 图片保留悬停 EXIF 和触屏按钮。
  • 没有触屏硬件的 Windows 桌面不再被当成触屏设备。 Windows 上的 Chromium 在无触屏的机器上也报 maxTouchPoints = 10,仅这一条就把插件切进触屏行为——放大的点击目标和常驻的媒体信息按钮。现在触屏判定要求 coarse 指针媒体查询(主指针或任意指针)命中,或 Obsidian 自己的移动端标志;触点数只在指针查询完全不可用时作为回退。
  • 每种语言都用它自己的名字列出。 语言下拉会把语言名翻译成当前界面语言,面对陌生界面的人(俄语界面显示"Упрощенный китайский")找不到回去的路。现在每种语言在所有界面语言下都以本族语名出现(English、简体中文、繁體中文、日本語、한국어、Français、Deutsch、Español、Русский);只有"系统"一项保持本地化,因为它是指令而不是语言名。

验证

  • npm run typecheck、npm test(69 个文件 / 796 项测试)、npm run build、npm run build:tablet、npm run package:release、npm run verify:release、npm run verify:release:zip、git diff --check 全部通过。
  • Obsidian Sandbox:逐字节部署,重载后 dev:errors 无错误。修复前真实 DOM 里 91 个 img.cm-widgetBuffer 占位符全部带着媒体 aria-label;修复后 46 个全部干净,而真实的 ![[007.png]] 嵌入保留完整仪表。用运行中的构建渲染语言下拉,中文、俄语、繁中三种界面下列出的都是本族语名——Система 保持本地化,语言项全部用自己的名字。
  • 运行期间 data.json 被改写过一次,内容仅为天气缓存抓取,别无改动;已用逐字节备份还原。Calendar/journal-metadata.json 未变。

备注

  • 仅有 Sandbox 证据:那是 Mac 桌面窗口,精确指针、maxTouchPoints = 0,所以 Windows 的 coarsePointer 修复由模拟 Chromium 上报值的单元测试证明,而不是真实 Windows 机器;触屏 info 按钮流程也没有在真手机上走过。这两项都还是残留风险。

发布资源

Obsidian 社区安装器会分别下载 main.js、manifest.json 和 styles.css。dayline.zip 另外打包了 THIRD_PARTY_NOTICES.md 与 icons/ 资源,便于手动安装:解压到 <Vault>/.obsidian/plugins/dayline-journal/ 后启用插件即可。

Dayline Journal v2.9.0

Choose a tag to compare

@Haoo-7 Haoo-7 released this 04 Oct 08:57

Three things: a journaled date now fills its whole calendar cell with the accent color, mood marks survive file sync and finally appear on phones, and the phone cell row lost one control.

Added

  • Written days fill with the accent color (showCalendarWrittenMarker, on by default). A journaled date without a photo fills its entire cell with the theme accent, so a month of writing reads at a glance; photo dates already fill with the image itself. The toggle sits in the calendar display group and is localized in all nine languages. Today changes from an accent fill to an accent ring for the same reason: the fill now means written, so an unwritten today must not claim otherwise.
  • The calendar mood pip on phones. The phone layout suppressed every in-cell control, which left a phone's month grid with no mood marker at all. The pip claims its own press, so it never starts the date gesture; entry count and media controls stay outside the cell. It keeps the compact tablet sizing — a roomy touch-desktop pip would swallow most of a 48px cell — and the empty state stays faintly visible, since neither a phone nor a tablet has hover to reveal it.

Fixed

  • Mood marks survive file sync. The metadata file was committed by writing a temporary file and renaming it over the original, which a sync engine can observe as the primary file going missing and propagate as a deletion to other devices. Commits now happen in place behind a .bak copy.
  • A stale synced copy heals instead of overwriting. Every real deletion leaves a tombstone, so a record that exists in the merge base, is unchanged locally and is simply absent on disk was lost to an older synced file rather than deleted: the next write re-seeds it, and a reconcile pass on load does the same, so two devices converge instead of clobbering each other. Tombstones are deliberately excluded — a recreated note must stay able to expose a fresh record even while this session still holds the old deletion.
  • An orphaned mood returns when its note does. Sync engines replace files as delete + recreate, which moved the mood to the recovery list and hid it until the user restored it by hand; it now restores itself once the file reappears at the same path. A live record at the destination always wins, and a file created before the orphaning is not a recreation.

Removed

  • The phone return-to-note arrow. Phone navigation is swipe-first — the panel and the note are one swipe apart — so the arrow, its always-visible hint, the return-leaf plumbing and the nine-language strings came out; the cell row is one control shorter.

Verification

  • npm run typecheck, npm test (69 files / 791 tests), npm run build, npm run build:tablet, npm run package:release, npm run verify:release, npm run verify:release:zip and git diff --check all pass.
  • Obsidian Sandbox: 2.9.0 deployed byte-identical (main.js 6201135f…, manifest.json aa896e07…, styles.css cc4eb753…), reloaded with no dev:errors. The loaded manifest reports 2.9.0 and showCalendarWrittenMarker is a boolean true. In the live DOM, September 2026 renders 7 .cal-written cells with the accent background and white day numbers, while today in October — unwritten — carries the inset accent ring and no fill.
  • data.json was rewritten during the run by a weather-cache fetch of 2026-10-04 and nothing else; restored from its byte-identical backup. Calendar/journal-metadata.json is unchanged.

Notes

  • Sandbox only: it is a tablet-like desktop window, so the phone mood pip, the compact sizing, and the swipe-first row without the arrow were not exercised on a real device, and the sync fixes need two devices behind a real sync engine. All four stay residual risks.
  • The fill ships on by default, so an existing install changes appearance the moment it updates: written days fill, today becomes a ring.

Release assets

Obsidian's community installer downloads main.js, manifest.json, and styles.css individually. dayline.zip bundles those three plus THIRD_PARTY_NOTICES.md and the icons/ assets for a manual install: extract it into <Vault>/.obsidian/plugins/dayline-journal/ and enable the plugin.


三件事:写了日记的日期会用主题色填满整个日历格子,心情标记扛得住文件同步并终于在手机上出现,手机端的格子行少掉一个控件。

新增

  • 已写日期用主题色填满(showCalendarWrittenMarker,默认开启)。有日记但没有照片的日期用主题强调色填满整个格子,一个月的书写量一眼可读;有照片的日期本来就用照片填满。开关在日历显示设置组里,九种语言都已翻译。今天也因此从填充改成描边:填充现在表示"已写",没写的今天不能谎称写了。
  • 手机端显示日历心情小圆点。 手机布局此前屏蔽了所有格子内控件,结果手机的月视图压根没有心情标记。小圆点自己接管按压,不会触发起日期手势;条目数和媒体控件仍然放在格子外。它沿用平板的紧凑尺寸——桌面那种大圆点在 48px 的格子里会占掉大半、还会抢掉想点日期的手势——并且因为手机和平板都没有 hover,空状态保持隐约可见。

修复

  • 心情标记不再被同步吃掉。 元数据原先是"写临时文件再 rename 覆盖"提交的,同步引擎可能把主文件短暂缺失当成删除,并传播到其他设备。现在改为原地提交,并留一份 .bak。
  • 过期的同步副本会自愈,而不是覆盖。 真正的删除都会留下 tombstone,所以"合并基准里有、本地没改、磁盘上却不见了"的记录是被旧副本冲掉,而不是被删除:下一次写入会重新补回,加载时也多了一次对账做同样的事,两台设备因此收敛而不是互相抹掉。tombstone 故意不对账——本次会话仍持有旧删除时,重建的笔记依然要能带出一条新记录。
  • 笔记回来,孤儿心情也回来。 同步引擎用"删除 + 重建"替换文件,这会把心情挪进恢复列表、藏起来等用户手动恢复;现在文件在同一位置重新出现就自动恢复。目标位置已有有效记录时以它为准,创建时间早于孤儿化时刻的文件不算重建。

移除

  • 手机端的"返回笔记"箭头。 手机导航以滑动为主——面板与笔记之间就一次滑动——按钮、常驻提示、return-leaf 相关代码和九种语言的文案一起去掉,格子行少一个控件。

验证

  • npm run typecheck、npm test(69 个文件 / 791 项测试)、npm run build、npm run build:tablet、npm run package:release、npm run verify:release、npm run verify:release:zip、git diff --check 全部通过。
  • Obsidian Sandbox:2.9.0 已逐字节部署(main.js 6201135f…、manifest.json aa896e07…、styles.css cc4eb753…),插件重载后 dev:errors 无错误。运行中的 manifest 报 2.9.0,showCalendarWrittenMarker 是布尔 true。真实 DOM 里九月 2026 渲染出 7 个 .cal-written 格子,主题色背景配白色数字;十月没写的今天只有内嵌强调色圆环、没有填充。
  • 运行期间 data.json 被改写,内容仅为新增 2026-10-04 的天气缓存,别无改动;已用逐字节备份还原。Calendar/journal-metadata.json 未变。

备注

  • 仅有 Sandbox 证据:那是接近平板形态的桌面窗口,手机心情小圆点、紧凑尺寸、去掉箭头后的滑动路径都没在真机上走过;同步相关的修复需要两台设备加真实同步引擎。这四项都还是残留风险。
  • 填充默认开启,所以老版本用户一更新,日历外观立刻变化:已写的填满,今天变成描边。

发布资源

Obsidian 社区安装器会分别下载 main.js、manifest.json 和 styles.css。dayline.zip 另外打包了 THIRD_PARTY_NOTICES.md 与 icons/ 资源,便于手动安装:解压到 <Vault>/.obsidian/plugins/dayline-journal/ 后启用插件即可。

Dayline Journal v2.8.1

Choose a tag to compare

@Haoo-7 Haoo-7 released this 02 Oct 03:57

A one-bug patch: a title that happens to read like journal-template filler was silently replaced by the empty placeholder, so the title looked unsaved.

Fixed

  • A title you type is always shown. The timeline's inline title editor writes frontmatter title, but a title that matched the generic list — freewrite, daily note, journal entry, entry, untitled — was treated as template filler and replaced by the "Title" placeholder, so typing Freewrite looked like the title had never been saved; any other wording displayed normally. That list exists to hide daily-template headings, not a deliberate choice, so only an inferred title (the note's first # Heading, or its filename) is screened against it now. A frontmatter title is what the user wrote and always renders, and On This Day's title split follows the same rule, so a memory card keeps such a title too. The list itself is unchanged, so template headings are still hidden as before.

Verification

  • npm run typecheck, npm test (69 files / 779 tests), npm run build, npm run build:tablet, npm run package:release, npm run verify:release:zip and git diff --check all pass.
  • Obsidian Sandbox: the new build was deployed and reloaded with no dev:errors. A demo note whose frontmatter is title: Freewrite rendered its card title as Freewrite instead of the placeholder, while the empty notes beside it — whose titles fall back to their filename dates — kept the placeholder.

Notes

  • Sandbox only: it is a tablet-like desktop window, so the timeline title area was not exercised on a real phone, and the fix's mobile behaviour stays a residual risk.
  • Titles are read through the journal index, so the fix applies wherever explicitTitle travels: the timeline card and the On This Day card and modal.

Release assets

Obsidian's community installer downloads main.js, manifest.json, and styles.css individually. dayline.zip bundles those three plus THIRD_PARTY_NOTICES.md and the icons/ assets for a manual install: extract it into <Vault>/.obsidian/plugins/dayline-journal/ and enable the plugin.


一个只有一处修复的补丁版:看起来像日记模板填充文字的标题会被悄悄换成空占位符,于是标题像是没保存上。

修复

  • 你输入的标题一定会显示。 时间线的行内标题编辑器写的是 frontmatter title,但命中通用词表的标题会被当成模板填充文字,替换成"标题"占位符——所以输入 Freewrite 看起来像根本没保存,而换任何别的字词都正常。这张词表(freewrite、daily note、journal entry、entry、untitled)是为了隐藏日记模板自带的标题,而不是否定用户的明确选择,因此现在只对推断出来的标题(笔记的第一个 # 标题,或文件名)做过滤。frontmatter 标题是用户写下的内容,一律照常显示;「往年今日」的标题拆分遵循同一规则,回忆卡片里的这类标题也会保留。词表本身没有改动,模板标题依旧被隐藏。

验证

  • npm run typecheck、npm test(69 个文件 / 779 项测试)、npm run build、npm run build:tablet、npm run package:release、npm run verify:release:zip、git diff --check 全部通过。
  • Obsidian Sandbox:新构建已部署并重载,dev:errors 无错误。frontmatter 为 title: Freewrite 的示例笔记,卡片标题渲染为 Freewrite 而不再是占位符;它旁边那些空笔记(标题回退到文件名日期)仍显示占位符。

备注

  • 仅 Sandbox 证据:那是接近平板形态的桌面窗口,标题区未在真机上验证,移动端表现仍属残留风险。
  • 标题统一经日记索引读取,因此修复覆盖所有携带 explicitTitle 的界面:时间线卡片,以及「往年今日」卡片与弹窗。

发布资源

Obsidian 社区安装器会分别下载 main.js、manifest.json 和 styles.css。dayline.zip 另外打包了 THIRD_PARTY_NOTICES.md 与 icons/ 资源,便于手动安装:解压到 <Vault>/.obsidian/plugins/dayline-journal/ 后启用插件即可。

Dayline Journal v2.8.0

Choose a tag to compare

@Haoo-7 Haoo-7 released this 30 Sep 16:41

The 2026-09-29 review round lands in full, and the calendar's past-year dot marker is removed. The marker was read as "this day has been written" often enough — by users and by the maintainer — that keeping it was worse than dropping it; the reasoning is recorded under Removed.

Added

  • Use current location in the weather settings reads the device location once, only when the button is tapped, fills the coordinates rounded to two decimals (about 1 km) and clears a location name that no longer matches the coordinates. It is shown on Obsidian mobile only, because desktop Electron usually has no location service; desktop users enter coordinates by hand. Denied, timed-out, unavailable, and failed reads each report in the display language. The stored coordinates travel to Open-Meteo with the weather request, which all three READMEs now state.
  • Insert-time EXIF/GPS persistence (exifPersistMetadata, off by default) writes location metadata to the journal note when an image is newly embedded or changed. The previous hover-driven path had no call site and never ran; the resolved place name now goes to a separate exif_place field instead of overwriting the shared EXIF data.
  • Keyboard and screen-reader access for the calendar grid. Day cells are focusable buttons carrying the localized date instead of the raw ISO string, and focus returns to the same date after a re-render.
  • CLDR plural forms for count labels. Languages that need more than an English two-form rule select their own category through Intl.PluralRules, with a fallback for older embedded Chromium.
  • Sixteen previously English-only settings, validation and error strings are localized: coordinate parsing and range checks, the mood metadata path errors, the journal-source/daily-folder mismatch, a mood save timeout, and the mobile back-to-note hint.

Changed

  • Recent weather reads the forecast endpoint. Days inside the recent window request past_days from the forecast host rather than the archive API, which lags by days and often had nothing for them.
  • The weather cache no longer deletes its own history. The sweep used to drop entries by fetchedAt at 90 days, which was the only copy of that weather, and it now bounds the cache by entry count instead; recent records keep the short TTL so a failed fetch is still retried.
  • Coordinate fields save on blur or after about 0.8 s instead of on every keystroke, and invalid or out-of-range input is reported inline and never saved.
  • External settings changes are honoured. onExternalSettingsChange re-reads data.json, so a value synced from another device is no longer overwritten by the stale in-memory copy on the next save.
  • Mood metadata is last-writer-wins by updatedAt, scores are validated on set(), a single unreadable record or a newer schema no longer rolls the whole file back to .bak, and a read-only store surfaces a warning instead of silently showing stale values.
  • February 29 memories appear in the February 28 view of a common year, on every On This Day surface.
  • A fresh install defaults the display language to system; a stored language is never rewritten.

Fixed

  • Mobile. Opening a journal no longer replaces the calendar in the right drawer, and no longer leaves an extra drawer leaf behind on each open; "Back to note" no longer turns the calendar leaf into an empty markdown view; a leaf the user has closed is not reused; the daily reminder waits for the journal index instead of firing early, and does not repeat; recording a mood no longer creates an empty daily note that bypasses the Daily Notes or Templater template; unload cleanup runs before the asynchronous flushes, so a flush that fails cannot skip the DOM teardown.
  • Calendar. The weather card revalidates instead of never refreshing after its first failure and refetching on every redraw; the On This Day modal no longer orphans containers after a reload or leaves a global keydown handler behind; duplicate redraws, grid rebuilds, and EXIF-cache wipes were removed; the mood control appears only where a mood or a journal entry exists, instead of drawing an empty target on every date and stealing the date tap.
  • Journal index, search and excerpts. An empty or unparsable date field falls back to the filename again, so those notes stay in the calendar and timeline; summary templates no longer treat $& and $$ in the note body as replacement patterns; search normalizes and debounces instead of re-normalizing the whole index on every keystroke; titles no longer come from a # inside a code block; tag scanning no longer reads colours, #123, or code-block content as tags; nested journal sources are validated against the daily folder; thumbnails whose filename contains parentheses render.
  • Media and EXIF. Each HEIC conversion no longer leaks a libheif WASM context; a GPS rational with a zero denominator no longer decodes as (0, 0); requestUrl timeouts are actually applied; a resolved place name no longer mutates the shared EXIF arrays.
  • Mood. CSV export neutralizes cells that a spreadsheet would evaluate as a formula; deleting a mood no longer rewrites frontmatter unconditionally; a tombstone no longer hides the frontmatter mood of a note re-created at the same path; the native date input no longer locks mid-edit.
  • Accessibility and i18n. Several hints that lived only in a title are reachable without hovering, and the strings listed under Added are no longer English-only.

Removed

  • The calendar past-year dot marker. It drew a 4px accent dot in the bottom-right corner of every date whose MM-DD has an entry in an earlier year. That is the vocabulary calendars use for "this day has an entry", and because the index only covers years before the current one the signal read backwards: a date written this year drew nothing, a date never written this year drew a dot, and today's cell was suppressed on top of it — so "a dot means written, and today is not written yet" was a self-consistent misreading. For someone who writes every day every past cell qualifies, so the marker carried no information either, and a count in its place would only have made the crowding visible. Removed with it: the onThisDayDot setting, the render block, its nine translations, the styles.css rule, and the two README rows. The merged On This Day strip, the header entry mode with its badge, and the memory modal are unchanged; a stale onThisDayDot: true in an existing data.json is inert, which a regression test covers.

Verification

  • npm run typecheck, npm test (69 files / 774 tests), npm run build, npm run build:tablet, npm run package:release, npm run verify:release:zip and git diff --check all pass.
  • Obsidian Sandbox: the new build was deployed and reloaded with no dev:errors. The calendar rendered 35 day cells for October 2026 with zero dot markers, and a September 2026 view — whose past-year index still contains 09-14, the date the previous build marked — rendered zero as well.

Notes

  • The review's M-11 finding, a non-colour cue for the calendar mood level, stays open by product decision: two encodings of the level in the marker's geometry were rejected in Sandbox acceptance, and at 6–10px the difference is imperceptible. The level remains carried by colour and the tooltip. If colour-blind legibility ever matters, the answer is a separate non-visual channel, not a marker tweak.
  • The mood picker's cross-date draft queue was deleted by the same kind of decision; changing the date discards that date's unsaved edit, and Save is the only commit point.
  • Not verified here: real phone and iPad leaf topology, native per-segment date input behaviour, device geolocation on iOS and Android, and HEIC infe/iloc versions other than the synthetic containers the tests build.
  • exif_place is written to frontmatter but nothing renders it yet; the EXIF tooltip still reads the media metadata.

Release assets

Obsidian's community installer downloads main.js, manifest.json, and styles.css individually. dayline.zip bundles those three plus THIRD_PARTY_NOTICES.md and the icons/ assets for a manual install: extract it into <Vault>/.obsidian/plugins/dayline-journal/ and enable the plugin.


2026-09-29 那一轮审查的修复全部落地,同时移除了日历上的"往年今日"小圆点。那个标记被当成"这天已写"的次数太多了(用户和作者本人都中招过),留着不如拿掉;理由记在 移除 一节。

新增

  • 天气设置新增 使用当前位置:只在你点击按钮时读取一次设备定位,填入保留两位小数(约 1 km 精度)的坐标,并在坐标变化后清掉不再匹配的地点名。该按钮只在 Obsidian 手机端显示,因为桌面端 Electron 通常没有定位服务,桌面用户手动输入坐标。被拒绝、超时、不可用和读取失败都按当前显示语言就地提示。填入的坐标会随天气请求发送到 Open-Meteo,三份 README 都已写明。
  • 插入时写入 EXIF/GPS(exifPersistMetadata,默认关闭):图片被新嵌入或发生变化时,把位置元数据写进日记。此前"悬停触发"的那条路径没有任何调用点,从未真正执行;解析出的地名现在写入独立的 exif_place 字段,不再覆盖共享的 EXIF 数据。
  • 日历格子支持键盘与读屏操作。 日期格子是可聚焦的按钮,标签使用本地化日期而不是原始 ISO 字符串;重绘后焦点回到同一天。
  • 计数标签支持 CLDR 复数形式。 需要超过英语双形式规则的语言通过 Intl.PluralRules 选择自己的复数类别,并为较旧的 Chromium 内核保留回退。
  • 补本地化十六处此前只有英文的设置、校验与错误文案:坐标解析与范围校验、心情元数据路径错误、日记来源与日记目录冲突、心情保存超时,以及移动端"返回笔记"提示。

变更

  • 近几天的天气改走预报接口。 最近窗口内的日期改用预报主机的 past_days,不再请求滞后数天、往往没有数据的归档接口。
  • 天气缓存不再删除自己的历史。 旧逻辑按 fetchedAt 在 90 天后清理条目,而那是该天气的唯一副本;现在改为按条目上限约束缓存,近期记录仍保留短 TTL,以便失败的请求之后重试。
  • 坐标输入改为失焦或停止输入约 0.8 秒后保存,不再每按一个键就保存一次;不合法或超出范围的输入就地提示且不会保存。
  • 外部设置变更会被采纳。 onExternalSettingsChange 会重新读取 data.json,从其他设备同步来的值不再被内存中的旧副本在下次保存时覆盖。
  • 心情元数据按 updatedAt 后写者胜,set() 会校验分数,单条无法解析的记录或更新的 schema 不再导致整份文件回退到 .bak,只读状态会给出警告而不是静默显示过期数据。
  • 平年的 2 月 28 日会显示 2 月 29 日的回忆,在所有"往年今日"界面一致。
  • 全新安装的默认显示语言为「跟随系统」;已存储的语言永不被改写。

修复

  • 移动端。 打开日记不再把右抽屉里的日历替换掉,也不会每打开一次就多留一个抽屉 leaf;「返回笔记」不再把日历 leaf 变成一个空的 markdown 视图;用户已关闭的 leaf 不会被复用;每日提醒会等索引就绪再发,且不会重复;记录心情不再创建绕过 Daily Notes / Templater 模板的空日记;卸载清理改到异步 flush 之前,flush 失败不会连带跳过 DOM 清理。
  • 日历。 天气卡片恢复重校验,不再首次失败后永不刷新、也不再每次重绘都重复请求;「往年今日」弹窗重载后不再残留容器,也不再留下全局 keydown 监听;移除了重复的重绘、网格重建和 EXIF 缓存清空;心情控件只在已有心情或已有日记的日期出现,不再在每个日期上画一个空目标抢走日期点击。
  • 日记索引、搜索与摘要。 日期字段为空或无法解析时重新回退到文件名,这些笔记会继续出现在日历与时间线;摘要模板不再把正文里的...
Read more

Dayline Journal v2.7.0

Choose a tag to compare

@Haoo-7 Haoo-7 released this 29 Sep 03:31

Nine display languages, vault-root journal sources, and the HEIC decoder bundled into main.js.

Added

  • Nine display languages. The display language setting now offers Simplified Chinese, Traditional Chinese, English, Japanese, Korean, French, German, Spanish, and Russian, plus "system", which resolves the host locale at call time. The settings dropdown, the migration path, and the tests read one shared list, and month and weekday names format through Intl locale tags instead of a hardcoded English/Chinese branch.
  • Localized weather conditions. 24 WMO conditions plus a "Weather code N" fallback in all nine languages. The calendar badge tooltip, the weather-card icon alt/title, and the date overlay no longer print the stored English description.
  • A brand mark in the settings header, ahead of the existing wordmark.
  • Ten remaining hardcoded English strings — the copy-mobile-diagnostics command and its notices, the calendar-leaf and mood notices, the weather timezone placeholder, the unknown-error fallback, the date-overlay title, and the mobile view group and back-button aria-labels — now resolve through t(). What deliberately stays English is recorded in docs/2026-09-29-nine-language-display.md.

Changed

  • The HEIC decoder ships inside main.js. It used to be libheif-bundle.js next to the plugin, loaded with a runtime require() of a path inside the plugin folder. Obsidian's installer only downloads main.js, manifest.json, and styles.css, so community-store installs never received it and HEIC thumbnails fell back to the raw attachment silently. The decoder is imported lazily on the first conversion, the release set no longer carries the sidecar, and THIRD_PARTY_NOTICES.md covers the bundled libheif-js (LGPL-3.0). main.js grows from 1.18 MB to about 2.9 MB.

Fixed

  • The vault root works as a journal source. Picking the root in the folder picker stored /, which path normalization collapsed to an empty string, and validation then rejected it with "enter a default daily-note folder" — the picker offered a folder the plugin refused to save. A root source now matches the files directly at the top level only, an empty folder setting still means "unset" and keeps resolving to the default, and every ${dailyFolder}/${date}.md join goes through joinVaultPath, so a root folder no longer produces a leading slash that getAbstractFileByPath does not resolve.
  • On This Day opens a memory in the journal leaf instead of splitting a new pane, and the card's title and body are separate rows rather than one run-on excerpt.
  • "How long ago" is measured from today on every On This Day surface, so opening a past-year memory no longer reads "0 years ago".
  • The timeline title keeps its text height on touch devices; the 44px tap box it had been given left 18px of dead space above the excerpt.

Verification

  • typecheck, test (61 files / 555 tests), build, build:tablet, verify:release, verify:release:zip, and diff --check pass on the merged tree.
  • The bundled HEIC decoder decoded a real sample end to end under the same esbuild settings the plugin uses: one image, 850x236, 200,600 opaque RGBA pixels. Loading the bundle instantiates no WASM, so the payload is only touched on the first conversion.

Release assets

Obsidian's community installer downloads main.js, manifest.json, and styles.css individually. dayline.zip bundles everything for a manual install, and it no longer carries libheif-bundle.js: the decoder lives inside main.js now. HEIC conversion remains desktop-only, because a decode can allocate a large buffer; the mobile route stays disabled on purpose.


九种显示语言、笔记库根目录支持,以及并入 main.js 的 HEIC 解码器。

新增

  • 九种显示语言。 显示语言设置现在提供简体中文、繁體中文、English、日本語、한국어、Français、Deutsch、Español、Русский,外加「跟随系统」,在调用时解析宿主语言。设置下拉、迁移路径与测试共用同一份语言列表;月份与星期名改由 Intl 的 locale tag 格式化,不再走硬编码的中英分支。
  • 天气状况本地化。 24 种 WMO 状况加上「Weather code N」回退,全部翻译进九种语言。日历徽章提示、天气卡图标 alt/title 与日期浮层不再显示快照里存的那段英文描述。
  • 设置页新增品牌图标,置于原有文字标识之前。
  • 另有十处此前硬编码的英文文案——移动端诊断命令及其提示、日历页与心情相关提示、天气时区占位符、未知错误回退、日期浮层标题,以及移动端视图分组与返回按钮的无障碍标签——现在都经 t() 解析。刻意保留英文的部分记录在 docs/2026-09-29-nine-language-display.md。

变更

  • HEIC 解码器并入 main.js。 它原本是插件目录里的独立文件 libheif-bundle.js,通过运行时 require() 绝对路径加载。Obsidian 安装器只下载 main.js、manifest.json 和 styles.css,所以从商店安装的用户一直拿不到它,HEIC 缩略图静默回退成原图。现在解码器在首次转换时懒加载,发布集不再包含该旁挂文件,THIRD_PARTY_NOTICES.md 覆盖了内置的 libheif-js(LGPL-3.0)。main.js 从 1.18 MB 增至约 2.9 MB。

修复

  • 笔记库根目录可用作日记来源。 在文件夹选择器里选根目录会存成 /,路径归一化把它压成空字符串,校验随即以「请填写笔记库内的默认日记目录」拒绝——选择器给出了一个插件却拒绝保存的目录。现在根目录来源只匹配顶层文件;空目录设置仍表示「未设置」并继续解析为默认目录;所有 ${dailyFolder}/${date}.md 拼接都走 joinVaultPath,根目录不再产生 getAbstractFileByPath 无法解析的前导斜杠。
  • 「去年今日」 改为在日记页内打开回忆,不再分裂出新面板;卡片标题与正文拆成两行,不再是一段连读摘要。
  • 「多久以前」在所有「去年今日」界面都以今天为基准计算,打开往年的回忆不再显示「0年前」。
  • 触屏设备上时间线标题恢复文本高度;此前给它加的 44px 点击区在摘要上方留了 18px 空白。

验证

  • 合并后的树上 typecheck、test(61 个文件 / 555 项测试)、build、build:tablet、verify:release、verify:release:zip、diff --check 全部通过。
  • 内置 HEIC 解码器在插件同款 esbuild 设置下真实解码样本通过:1 张图、850x236、200,600 个不透明 RGBA 像素。加载 bundle 不实例化任何 WASM,即只在首次转换时触碰负载。

发布资源

Obsidian 社区安装器会分别下载 main.js、manifest.json 和 styles.css。dayline.zip 打包了全部文件,便于手动安装,且已不再包含 libheif-bundle.js——解码器现在位于 main.js 内。HEIC 转换仍为桌面端专属:单次解码可能分配大缓冲,移动端路由是刻意保持关闭的。

Dayline Journal v2.6.1

Choose a tag to compare

@Haoo-7 Haoo-7 released this 26 Sep 17:37

Clears the community-plugin review findings that were safe to change and resolves the single error-severity item; user-visible behaviour is unchanged.

Security fix (review error)

  • Calendar weather badges are appended as parsed DOM instead of being written with innerHTML. This was the only error-severity finding in the review, and the only place in src/ that built markup from a string. The glyphs themselves are build-time constants from icons/badge-*.svg, but an HTML-string sink turns any future asset edit into an injection point.
  • New appendBadgeSvg(): parses the markup as XML, strips <script> and every on* attribute, then imports the node. Rendering stays zero-I/O while the sink becomes inert.
  • Verified: the DOM produced by all eight shipped glyphs is structurally identical to the previous output; malicious markup (onload, <script>, onmouseover) is stripped in every case.

Review warnings cleared

  • Every document.createElement call site now uses Obsidian's createEl/createDiv/createSpan, clearing all 41 obsidianmd/prefer-create-el findings.
  • The filename sanitizer no longer matches literal control characters in its regex; the \u0000-\u001f range is applied by code point. An exhaustive check over all 65,536 BMP code points plus three astral samples confirms the output is byte-for-byte unchanged.
  • Legacy-widened literal unions now use (string & {}) rather than | string, so weekStart, weatherUnits, and calendarMoodMarker keep their literal autocomplete instead of collapsing to string. This clears all 16 no-redundant-type-constituents findings and is a type-only change.
  • Promise rejections and thrown values are normalised to Error: requestWeatherWithRetry preserves its status property so HTTP retry eligibility is unchanged, and MediaService wraps non-Error rejection reasons.
  • Two redundant type assertions were removed, and one unnecessary console.info became the console.debug the guidelines allow.

Not addressed (important)

  • The review's @typescript-eslint/no-unsafe-* and no-explicit-any findings are not addressed here. They come from require() imports and // @ts-nocheck in nine files, which degrade imported symbols to any. They are warnings, and converting those files to ESM would change behaviour, so that work is tracked separately.

Verification

  • npm test passes: 56 test files, 488 tests (up from 55/483, adding badge-injection coverage).
  • npm run typecheck, npm run build, npm run verify:release, npm run verify:release:zip, and git diff --check pass.
  • Weather badges were exercised in the Obsidian Sandbox: 17 badges, all 17 rendering inline <svg>, 103 shapes in total, with stroke resolving through currentColor to the matching condition colour, and dev:errors reporting nothing after a reload.

修复插件审查中可安全处理的问题,并解决唯一一条 error 级问题;不改变用户可见行为。

安全修复(审查 Error)

  • 日历天气徽章改为以解析后的 DOM 追加,不再使用 innerHTML。这是插件审查中唯一一条 error 级问题,也是 src/ 中唯一一处用字符串拼接标记的地方。字形本身是来自 icons/badge-*.svg 的构建期常量,但 HTML 字符串注入点会让未来任何一次资源改动变成注入风险。
  • 新增 appendBadgeSvg():以 XML 解析标记,剥离 <script> 与所有 on* 属性后再导入节点。保持零 I/O 渲染,同时让注入点变为惰性。
  • 验证:8 个已发布字形产出的 DOM 与改动前结构完全一致;恶意标记(onload、<script>、onmouseover)全部被剥离。

审查 Warning 清理

  • 所有 document.createElement 调用点改用 Obsidian 的 createEl/createDiv/createSpan,清掉全部 41 条 obsidianmd/prefer-create-el。
  • 文件名净化不再在正则中匹配字面控制字符,\^@-\^_ 改为按码点处理。已穷举全部 65536 个 BMP 码点及 3 个星体面样本,确认输出逐字节不变。
  • 为兼容旧版持久化值而放宽的字面量联合改用 (string & {}) 而非 | string,使 weekStart、weatherUnits、calendarMoodMarker 保留字面量补全而不退化成 string。清掉全部 16 条 no-redundant-type-constituents,纯类型层面改动。
  • Promise 拒绝与抛出值统一归一为 Error:requestWeatherWithRetry 保留 status 属性,HTTP 重试判定逻辑不变;MediaService 包装非 Error 的拒绝原因。
  • 另删除两处多余类型断言,并把一处不必要的 console.info 改为指南允许的 console.debug。

未处理(重要)

  • 审查中的 @typescript-eslint/no-unsafe-* 与 no-explicit-any 未在本次处理。它们源于 9 个文件中的 require() 导入与 // @ts-nocheck,导致导入符号退化为 any。这些属于 warning;将其改为 ESM 会影响行为,属独立的后续重构。

验证

  • npm test 通过:56 个测试文件、488 项测试(原 55/483,新增徽章注入相关覆盖)。
  • npm run typecheck、npm run build、npm run verify:release、npm run verify:release:zip、git diff --check 通过。
  • 已在 Obsidian Sandbox 实测天气徽章:17 个徽章、17 个均渲染出内联 <svg>、共 103 个图形,stroke 经 currentColor 正确解析为对应天气配色;重载后 dev:errors 无任何错误。