From 149a99e4ba94b47a042cc9e845ff2a44d9c4d021 Mon Sep 17 00:00:00 2001 From: mousebomb Date: Tue, 4 Nov 2025 10:34:21 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=BB=8E=E6=A0=87=E9=A2=98?= =?UTF-8?q?=E4=B8=AD=E6=8F=90=E5=8F=96=E6=97=B6=E9=97=B4=E5=A1=AB=E5=85=85?= =?UTF-8?q?=E5=88=B0=E7=94=9F=E6=88=90=E7=9A=84ics=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E4=B8=AD=20=09=09console.log=20(this.extractTimeFromTitle("10:?= =?UTF-8?q?00~12:00=E5=98=BF=E5=98=BF"))=20=09=09console.log=20(this.extra?= =?UTF-8?q?ctTimeFromTitle("10:00-12:00=20=E5=98=BF=E5=98=BF2"))=20=09=09c?= =?UTF-8?q?onsole.log=20(this.extractTimeFromTitle("=E5=98=BF=E5=98=BF3=20?= =?UTF-8?q?10:00=EF=BD=9E12:00"))=20=09=09console.log=20(this.extractTimeF?= =?UTF-8?q?romTitle("=E5=98=BF=E5=98=BF410:00~12:00"))=20=09=09console.log?= =?UTF-8?q?=20(this.extractTimeFromTitle("09:00diary-ics=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E7=9A=84=E6=96=B9=E6=A1=88"))=20=09=09consol?= =?UTF-8?q?e.log=20(this.extractTimeFromTitle("09:00=20diary-ics=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E6=97=B6=E9=97=B4=E7=9A=84=E6=96=B9=E6=A1=882"))?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- manifest.json | 2 +- src/lang.ts | 6 +++ src/main.ts | 116 ++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 115 insertions(+), 9 deletions(-) diff --git a/manifest.json b/manifest.json index 2034d70..e1b2ba8 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "diary-ics", "name": "Diary ICS", - "version": "1.0.10", + "version": "1.0.11", "minAppVersion": "0.15.0", "description": "Sync diary entries to system calendar via ICS feed.", "author": "Mousebomb", diff --git a/src/lang.ts b/src/lang.ts index 9dadffa..4875be0 100644 --- a/src/lang.ts +++ b/src/lang.ts @@ -29,6 +29,8 @@ interface LanguageStrings { h2Option: string; includeSubheadingsSetting: string; includeSubheadingsDesc: string; + extractTimeRangeSetting: string; + extractTimeRangeDesc: string; diarySettingsTitle: string; diaryFormatSetting: string; diaryFormatDesc: string; @@ -83,6 +85,8 @@ const en: LanguageStrings = { h2Option: "Level 2 heading (##)", includeSubheadingsSetting: "Include subheadings", includeSubheadingsDesc: "Include subheadings under the heading in the calendar event description", + extractTimeRangeSetting: "Auto-extract time range", + extractTimeRangeDesc: "Automatically extract HH:mm or HH:mm~HH:mm format time from title as event start and end time", diarySettingsTitle: "Diary", diaryFormatSetting: "Diary naming format", diaryFormatDesc: "The naming format of diary files, e.g., YYYY-MM-DD", @@ -137,6 +141,8 @@ const zh: LanguageStrings = { h2Option: "二级标题 (##)", includeSubheadingsSetting: "包含子级标题", includeSubheadingsDesc: "在日历事件描述中包含标题下的子级标题", + extractTimeRangeSetting: "自动提取时间段", + extractTimeRangeDesc: "自动从标题中提取HH:mm或HH:mm~HH:mm格式的时间作为事件的开始和结束时间", diarySettingsTitle: "日记设置", diaryFormatSetting: "日记命名格式", diaryFormatDesc: "日记文件的命名格式,例如YYYY-MM-DD", diff --git a/src/main.ts b/src/main.ts index 614d540..5ccae2e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -15,6 +15,8 @@ interface DiaryIcsSettings { // 日记设置 diaryFormat: string; diaryFolder: string; + // 时间提取设置 + extractTimeRange: boolean; } const DEFAULT_DAILY_NOTE_FORMAT = 'YYYY-MM-DD'; @@ -28,7 +30,8 @@ const DEFAULT_SETTINGS: DiaryIcsSettings = { frontmatterTemplate: '', frontmatterTitleTemplate: '', diaryFormat: DEFAULT_DAILY_NOTE_FORMAT, - diaryFolder: '' + diaryFolder: '', + extractTimeRange: true } export default class DiaryIcsPlugin extends Plugin { @@ -173,8 +176,6 @@ export default class DiaryIcsPlugin extends Plugin { if (this.dailyNoteFolder && !file.path.startsWith(matchFolder)) return false; // 使用moment库验证文件名是否符合日期格式 - // @ts-ignore - window.moment 在Obsidian中已经内置 - // const moment = window.moment; if (!moment) { console.error(this.locale.cannotGetMoment); return false; @@ -259,8 +260,6 @@ export default class DiaryIcsPlugin extends Plugin { new Notice(formatString(this.locale.generatingIcsFiles, files.length), 1000); for (const file of files) { // 从文件名解析日期,使用moment库根据配置的日记格式解析 - // @ts-ignore - window.moment 在Obsidian中已经内置 - // const moment = window.moment; const date = moment(file.basename, this.dailyNoteFormat, true); const year = date.year(); const month = date.month() + 1; // moment月份从0开始,需要+1 @@ -363,13 +362,50 @@ export default class DiaryIcsPlugin extends Plugin { // description += entry.content + '\n\n'; // } + // 处理时间提取 + let eventTitle = entry.title; + // 使用联合类型解决类型问题 + let eventStart: [number, number, number] | [number, number, number, number, number] = [year, month, day]; + // 修改duration类型以支持hours和minutes + let eventDuration: { days?: number; hours?: number; minutes?: number } = {days: 1}; // 默认为全天事件 + + if (this.settings.extractTimeRange) { + const timeResult = this.extractTimeFromTitle(entry.title); + eventTitle = timeResult.cleanTitle; + + if (timeResult.hasTime && timeResult.startTime) { + // 有时间信息,设置为非全天事件 + eventStart = [year, month, day, timeResult.startTime[0], timeResult.startTime[1]]; + + if (timeResult.endTime) { + // 计算持续时间 + const startMinutes = timeResult.startTime[0] * 60 + timeResult.startTime[1]; + let endMinutes = timeResult.endTime[0] * 60 + timeResult.endTime[1]; + + // 如果结束时间小于开始时间,认为是跨天了 + if (endMinutes < startMinutes) { + endMinutes += 24 * 60; + } + + const durationMinutes = endMinutes - startMinutes; + // 计算小时和分钟 + const durationHours = Math.floor(durationMinutes / 60); + const durationMins = durationMinutes % 60; + // 设置正确的duration属性 + eventDuration = {}; + if (durationHours > 0) eventDuration.hours = durationHours; + if (durationMins > 0) eventDuration.minutes = durationMins; + } + } + } + // 创建事件 events.push({ - title: entry.title, + title: eventTitle, url: `obsidian://open?vault=${encodeURIComponent(vaultName)}&file=${encodeURIComponent(file.path)}${encodeURIComponent(`#${entry.title}`)}`, description: description, - start: [year, month, day], - duration: {days: 1}, // 默认为全天事件 + start: eventStart, + duration: eventDuration, status: 'CONFIRMED', busyStatus: 'FREE' }); @@ -387,6 +423,60 @@ export default class DiaryIcsPlugin extends Plugin { }); }); } + + // 从标题中提取时间范围 + extractTimeFromTitle(title: string): { hasTime: boolean; startTime?: [number, number]; endTime?: [number, number]; cleanTitle: string } { + // 匹配格式:HH:mm~HH:mm 或 09:00~10:00 + const timeRangeRegex = /(? toggle + .setValue(this.plugin.settings.extractTimeRange) + .onChange(async (value) => { + this.plugin.settings.extractTimeRange = value; + await this.plugin.saveSettings(false); + })); + // new Setting(containerEl) // .setName('包含内容') // .setDesc('在日历事件描述中包含标题下的内容')