feat: add auto sync frontmatter key configuration and update related messages

This commit is contained in:
Jiaxin Peng
2025-11-06 16:43:24 +00:00
parent ae4488546c
commit bb4b75c82e
7 changed files with 80 additions and 24 deletions

View File

@@ -37,6 +37,8 @@ export const en = {
NotionLinkDisplayDesc: "Default is ON, if you want to hide the link in the front matter, please turn it off", NotionLinkDisplayDesc: "Default is ON, if you want to hide the link in the front matter, please turn it off",
AutoSync: "Auto Sync", AutoSync: "Auto Sync",
AutoSyncDesc: "Automatically sync to Notion when frontmatter or content is modified (requires existing NotionID)", AutoSyncDesc: "Automatically sync to Notion when frontmatter or content is modified (requires existing NotionID)",
AutoSyncFrontmatterKey: "Auto Sync Frontmatter Key",
AutoSyncFrontmatterKeyDesc: "Set the frontmatter property name that lists which databases should auto sync (defaults to autosync-database).",
AutoSyncDelay: "Auto Sync Delay (seconds)", AutoSyncDelay: "Auto Sync Delay (seconds)",
AutoSyncDelayDesc: "How many seconds to wait after document modification before triggering auto sync (default: 5 seconds, minimum: 2 seconds)", AutoSyncDelayDesc: "How many seconds to wait after document modification before triggering auto sync (default: 5 seconds, minimum: 2 seconds)",
AutoSyncDelayText: "Enter delay in seconds", AutoSyncDelayText: "Enter delay in seconds",
@@ -86,7 +88,7 @@ export const en = {
CheckConsole: "Check the console for more information \n opt+cmd+i/ctrl+shift+i", CheckConsole: "Check the console for more information \n opt+cmd+i/ctrl+shift+i",
SettingsMigrated: "✨ Plugin settings updated! Auto sync feature added, check plugin settings", SettingsMigrated: "✨ Plugin settings updated! Auto sync feature added, check plugin settings",
AutoSyncNoNotionID: "⚠️ Auto sync skipped: This document has not been synced to Notion, please upload manually first", AutoSyncNoNotionID: "⚠️ Auto sync skipped: This document has not been synced to Notion, please upload manually first",
AutoSyncMissingDatabaseList: "⚠️ Auto sync skipped: Add an \"aytosync-database\" list in the frontmatter to choose databases", AutoSyncMissingDatabaseList: "⚠️ Auto sync skipped: Add a \"{key}\" entry in the frontmatter to choose databases",
AutoSyncMultipleSync: "🔄 Auto sync: Syncing to {count} database(s)...", AutoSyncMultipleSync: "🔄 Auto sync: Syncing to {count} database(s)...",
AutoSyncFailed: "Auto sync to {database} failed: {error}", AutoSyncFailed: "Auto sync to {database} failed: {error}",
AutoSyncError: "Auto sync failed for {filename}: {error}", AutoSyncError: "Auto sync failed for {filename}: {error}",

View File

@@ -31,13 +31,15 @@ export const ja = {
NotionUser: "Notion IDユーザー名、任意", NotionUser: "Notion IDユーザー名、任意",
NotionUserDesc: "共有リンクから取得https://username.notion.site。Notion IDは[username]です", NotionUserDesc: "共有リンクから取得https://username.notion.site。Notion IDは[username]です",
NotionUserText: "Notion IDを入力", NotionUserText: "Notion IDを入力",
NotionLinkDisplay: "Notionリンク表示", NotionLinkDisplay: "Notionリンク表示",
NotionLinkDisplayDesc: "デフォルトはONです。front matterにリンクを非表示にしたい場合は、オフにしてください", NotionLinkDisplayDesc: "デフォルトはONです。front matterにリンクを非表示にしたい場合は、オフにしてください",
AutoSync: "自動同期", AutoSync: "自動同期",
AutoSyncDesc: "frontmatter またはコンテンツが変更されたときに自動的に Notion に同期しますNotionID が必要)", AutoSyncDesc: "frontmatter またはコンテンツが変更されたときに自動的に Notion に同期しますNotionID が必要)",
AutoSyncDelay: "自動同期遅延時間(秒)", AutoSyncFrontmatterKey: "自動同期 frontmatter キー",
AutoSyncDelayDesc: "ドキュメントの変更後、自動同期をトリガーするまでの待機時間デフォルト5秒、最小2秒", AutoSyncFrontmatterKeyDesc: "自動同期するデータベースを列挙する frontmatter のプロパティ名を設定します(デフォルトは autosync-database",
AutoSyncDelayText: "遅延秒数を入力", AutoSyncDelay: "自動同期遅延時間(秒)",
AutoSyncDelayDesc: "ドキュメントの変更後、自動同期をトリガーするまでの待機時間デフォルト5秒、最小2秒",
AutoSyncDelayText: "遅延秒数を入力",
NotionGeneralSettingHeader: "一般的なNotionデータベース設定", NotionGeneralSettingHeader: "一般的なNotionデータベース設定",
NotionGeneralButton: "一般的なNotion同期", NotionGeneralButton: "一般的なNotion同期",
NotionGeneralButtonDesc: "このオプションを開くと、一般的なNotionデータベース同期コマンドがコマンドパレットに表示されますデフォルトON", NotionGeneralButtonDesc: "このオプションを開くと、一般的なNotionデータベース同期コマンドがコマンドパレットに表示されますデフォルトON",
@@ -75,11 +77,11 @@ export const ja = {
CopyErrorMessage: "自動コピーに失敗しました", CopyErrorMessage: "自動コピーに失敗しました",
BlockUploaded: "ブロックがアップロードされました", BlockUploaded: "ブロックがアップロードされました",
ExtraBlockUploaded: "追加ブロックがアップロードされました", ExtraBlockUploaded: "追加ブロックがアップロードされました",
CheckConsole: "詳細情報を確認するには、コンソールを開いてください \n opt+cmd+i/ctrl+shift+i", CheckConsole: "詳細情報を確認するには、コンソールを開いてください \n opt+cmd+i/ctrl+shift+i",
SettingsMigrated: "✨ プラグイン設定が更新されました!自動同期機能が追加されました。設定を確認してください", SettingsMigrated: "✨ プラグイン設定が更新されました!自動同期機能が追加されました。設定を確認してください",
AutoSyncNoNotionID: "⚠️ 自動同期をスキップ:このドキュメントは Notion に同期されていません。まず手動でアップロードしてください", AutoSyncNoNotionID: "⚠️ 自動同期をスキップ:このドキュメントは Notion に同期されていません。まず手動でアップロードしてください",
AutoSyncMissingDatabaseList: "⚠️ 自動同期をスキップfrontmatter に aytosync-database リストを設定してください", AutoSyncMissingDatabaseList: "⚠️ 自動同期をスキップfrontmatter に \"{key}\" 項目を追加してください",
AutoSyncMultipleSync: "🔄 自動同期:{count} 個のデータベースに同期中...", AutoSyncMultipleSync: "🔄 自動同期:{count} 個のデータベースに同期中...",
AutoSyncFailed: "{database} への自動同期に失敗しました:{error}", AutoSyncFailed: "{database} への自動同期に失敗しました:{error}",
AutoSyncError: "{filename} の自動同期に失敗しました:{error}", AutoSyncError: "{filename} の自動同期に失敗しました:{error}",
"reach-mobile-limit": "ブロック数が100の制限を超えています。デスクトップ版プラグインを使用してください", "reach-mobile-limit": "ブロック数が100の制限を超えています。デスクトップ版プラグインを使用してください",

View File

@@ -37,6 +37,8 @@ export const zh = {
NotionLinkDisplayDesc: "默认开启如果你不想在front matter中显示链接请关闭", NotionLinkDisplayDesc: "默认开启如果你不想在front matter中显示链接请关闭",
AutoSync: "自动同步", AutoSync: "自动同步",
AutoSyncDesc: "当检测到文档的 frontmatter 或内容发生修改时,自动同步到 Notion需要文档已有 NotionID", AutoSyncDesc: "当检测到文档的 frontmatter 或内容发生修改时,自动同步到 Notion需要文档已有 NotionID",
AutoSyncFrontmatterKey: "自动同步 Frontmatter 键名",
AutoSyncFrontmatterKeyDesc: "设置用于列出自动同步数据库的 frontmatter 属性名称(默认 autosync-database。",
AutoSyncDelay: "自动同步延迟时间(秒)", AutoSyncDelay: "自动同步延迟时间(秒)",
AutoSyncDelayDesc: "文档修改后等待多少秒才触发自动同步避免频繁同步默认5秒最小2秒", AutoSyncDelayDesc: "文档修改后等待多少秒才触发自动同步避免频繁同步默认5秒最小2秒",
AutoSyncDelayText: "输入延迟秒数", AutoSyncDelayText: "输入延迟秒数",
@@ -81,7 +83,7 @@ export const zh = {
CheckConsole: "opt+cmd+i/ctrl+shift+i\n打开控制台查看更多信息", CheckConsole: "opt+cmd+i/ctrl+shift+i\n打开控制台查看更多信息",
SettingsMigrated: "✨ 插件设置已更新!新增自动同步功能,请在设置中查看", SettingsMigrated: "✨ 插件设置已更新!新增自动同步功能,请在设置中查看",
AutoSyncNoNotionID: "⚠️ 自动同步跳过:此文档未同步到 Notion请先手动上传", AutoSyncNoNotionID: "⚠️ 自动同步跳过:此文档未同步到 Notion请先手动上传",
AutoSyncMissingDatabaseList: "⚠️ 自动同步跳过:请在 frontmatter 中设置 aytosync-database 列表", AutoSyncMissingDatabaseList: "⚠️ 自动同步跳过:请在 frontmatter 中添加 \"{key}\" 项来指定数据库",
AutoSyncMultipleSync: "🔄 自动同步:正在同步到 {count} 个数据库...", AutoSyncMultipleSync: "🔄 自动同步:正在同步到 {count} 个数据库...",
AutoSyncFailed: "自动同步到 {database} 失败:{error}", AutoSyncFailed: "自动同步到 {database} 失败:{error}",
AutoSyncError: "自动同步 {filename} 失败:{error}", AutoSyncError: "自动同步 {filename} 失败:{error}",

View File

@@ -4,7 +4,7 @@ import { i18nConfig } from "src/lang/I18n";
import ribbonCommands from "src/commands/NotionCommands"; import ribbonCommands from "src/commands/NotionCommands";
import { ObsidianSettingTab, PluginSettings, DEFAULT_SETTINGS, DatabaseDetails } from "src/ui/settingTabs"; import { ObsidianSettingTab, PluginSettings, DEFAULT_SETTINGS, DatabaseDetails } from "src/ui/settingTabs";
import { uploadCommandNext, uploadCommandGeneral, uploadCommandCustom } from "src/upload/uploadCommand"; import { uploadCommandNext, uploadCommandGeneral, uploadCommandCustom } from "src/upload/uploadCommand";
import { AUTO_SYNC_DATABASE_KEY, parseAutoSyncDatabaseList } from "src/utils/frontmatter"; import { DEFAULT_AUTO_SYNC_DATABASE_KEY, parseAutoSyncDatabaseList, resolveAutoSyncKey } from "src/utils/frontmatter";
// Remember to rename these classes and interfaces! // Remember to rename these classes and interfaces!
@@ -92,6 +92,10 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
if (typeof this.settings.NotionLinkDisplay !== 'boolean') { if (typeof this.settings.NotionLinkDisplay !== 'boolean') {
this.settings.NotionLinkDisplay = DEFAULT_SETTINGS.NotionLinkDisplay; this.settings.NotionLinkDisplay = DEFAULT_SETTINGS.NotionLinkDisplay;
} }
if (typeof this.settings.autoSyncFrontmatterKey !== 'string') {
this.settings.autoSyncFrontmatterKey = DEFAULT_AUTO_SYNC_DATABASE_KEY;
}
this.settings.autoSyncFrontmatterKey = resolveAutoSyncKey(this.settings.autoSyncFrontmatterKey);
// Ensure databaseDetails exists // Ensure databaseDetails exists
if (!this.settings.databaseDetails || typeof this.settings.databaseDetails !== 'object') { if (!this.settings.databaseDetails || typeof this.settings.databaseDetails !== 'object') {
@@ -102,7 +106,8 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
const needsSave = !loadedData || const needsSave = !loadedData ||
loadedData.autoSync === undefined || loadedData.autoSync === undefined ||
loadedData.autoSyncDelay === undefined || loadedData.autoSyncDelay === undefined ||
loadedData.NotionLinkDisplay === undefined; loadedData.NotionLinkDisplay === undefined ||
loadedData.autoSyncFrontmatterKey === undefined;
if (needsSave) { if (needsSave) {
const migratedFields = []; const migratedFields = [];
@@ -134,6 +139,7 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
autoSync: this.settings.autoSync, autoSync: this.settings.autoSync,
autoSyncDelay: this.settings.autoSyncDelay, autoSyncDelay: this.settings.autoSyncDelay,
NotionLinkDisplay: this.settings.NotionLinkDisplay, NotionLinkDisplay: this.settings.NotionLinkDisplay,
autoSyncFrontmatterKey: this.settings.autoSyncFrontmatterKey,
databaseCount: Object.keys(this.settings.databaseDetails || {}).length databaseCount: Object.keys(this.settings.databaseDetails || {}).length
}); });
} }
@@ -156,6 +162,20 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
console.warn('[Settings] Invalid databaseDetails, resetting to empty object'); console.warn('[Settings] Invalid databaseDetails, resetting to empty object');
this.settings.databaseDetails = {}; this.settings.databaseDetails = {};
} }
if (typeof this.settings.autoSyncFrontmatterKey !== 'string' || this.settings.autoSyncFrontmatterKey.trim().length === 0) {
console.warn('[Settings] Invalid autoSyncFrontmatterKey, resetting to default');
this.settings.autoSyncFrontmatterKey = DEFAULT_AUTO_SYNC_DATABASE_KEY;
} else {
this.settings.autoSyncFrontmatterKey = resolveAutoSyncKey(this.settings.autoSyncFrontmatterKey);
}
}
resetAutoSyncNoticeCache() {
this.missingAutoSyncNoticeShown.clear();
}
getAutoSyncFrontmatterKey(): string {
return resolveAutoSyncKey(this.settings.autoSyncFrontmatterKey);
} }
async addDatabaseDetails(dbDetails: DatabaseDetails) { async addDatabaseDetails(dbDetails: DatabaseDetails) {
@@ -330,14 +350,16 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
} }
} }
const autoSyncTargets = parseAutoSyncDatabaseList(frontMatter[AUTO_SYNC_DATABASE_KEY]); const autoSyncKey = this.getAutoSyncFrontmatterKey();
const autoSyncTargets = parseAutoSyncDatabaseList(frontMatter[autoSyncKey]);
if (autoSyncTargets.length === 0) { if (autoSyncTargets.length === 0) {
if (!this.missingAutoSyncNoticeShown.has(file.path)) { if (!this.missingAutoSyncNoticeShown.has(file.path)) {
new Notice(i18nConfig.AutoSyncMissingDatabaseList, 10000); const message = i18nConfig.AutoSyncMissingDatabaseList.replace('{key}', autoSyncKey);
new Notice(message, 10000);
this.missingAutoSyncNoticeShown.add(file.path); this.missingAutoSyncNoticeShown.add(file.path);
} }
console.log(`[AutoSync] No auto sync database list found in ${file.path}`); console.log(`[AutoSync] No auto sync database list found in ${file.path} using key "${autoSyncKey}"`);
return; return;
} }

View File

@@ -5,6 +5,7 @@ import { SettingModal } from "./settingModal";
import { PreviewModal } from "./PreviewModal"; import { PreviewModal } from "./PreviewModal";
import { EditModal } from "./EditModal"; import { EditModal } from "./EditModal";
import { DeleteModal } from "./DeleteModal"; import { DeleteModal } from "./DeleteModal";
import { DEFAULT_AUTO_SYNC_DATABASE_KEY } from "src/utils/frontmatter";
export interface PluginSettings { export interface PluginSettings {
NextButton: boolean; NextButton: boolean;
@@ -15,6 +16,7 @@ export interface PluginSettings {
NotionLinkDisplay: boolean; NotionLinkDisplay: boolean;
autoSync: boolean; autoSync: boolean;
autoSyncDelay: number; autoSyncDelay: number;
autoSyncFrontmatterKey: string;
proxy: string; proxy: string;
GeneralButton: boolean; GeneralButton: boolean;
tagButton: boolean; tagButton: boolean;
@@ -53,6 +55,7 @@ export const DEFAULT_SETTINGS: PluginSettings = {
NotionLinkDisplay: true, NotionLinkDisplay: true,
autoSync: false, autoSync: false,
autoSyncDelay: 5, autoSyncDelay: 5,
autoSyncFrontmatterKey: DEFAULT_AUTO_SYNC_DATABASE_KEY,
proxy: "", proxy: "",
GeneralButton: true, GeneralButton: true,
tagButton: true, tagButton: true,
@@ -94,6 +97,20 @@ export class ObsidianSettingTab extends PluginSettingTab {
this.createSettingEl(containerEl, i18nConfig.AutoSync, i18nConfig.AutoSyncDesc, 'toggle', i18nConfig.AutoSync, this.plugin.settings.autoSync, 'autoSync') this.createSettingEl(containerEl, i18nConfig.AutoSync, i18nConfig.AutoSyncDesc, 'toggle', i18nConfig.AutoSync, this.plugin.settings.autoSync, 'autoSync')
new Setting(containerEl)
.setName(i18nConfig.AutoSyncFrontmatterKey)
.setDesc(i18nConfig.AutoSyncFrontmatterKeyDesc)
.addText((text) =>
text
.setPlaceholder(DEFAULT_AUTO_SYNC_DATABASE_KEY)
.setValue(this.plugin.settings.autoSyncFrontmatterKey ?? "")
.onChange(async (value) => {
this.plugin.settings.autoSyncFrontmatterKey = value;
await this.plugin.saveSettings();
this.plugin.resetAutoSyncNoticeCache();
})
);
// Auto Sync Delay setting - only visible when autoSync is enabled // Auto Sync Delay setting - only visible when autoSync is enabled
this.autoSyncDelayContainer = containerEl.createDiv(); this.autoSyncDelayContainer = containerEl.createDiv();
const delaySetting = new Setting(this.autoSyncDelayContainer) const delaySetting = new Setting(this.autoSyncDelayContainer)
@@ -350,4 +367,3 @@ export class ObsidianSettingTab extends PluginSettingTab {
} }
} }

View File

@@ -2,7 +2,7 @@ import { App, Notice, TFile } from "obsidian";
import ObsidianSyncNotionPlugin from "../main"; import ObsidianSyncNotionPlugin from "../main";
import { DatabaseDetails } from "../ui/settingTabs"; import { DatabaseDetails } from "../ui/settingTabs";
import { i18nConfig } from "src/lang/I18n"; import { i18nConfig } from "src/lang/I18n";
import { AUTO_SYNC_DATABASE_KEY, ensureAutoSyncDatabaseEntry } from "src/utils/frontmatter"; import { ensureAutoSyncDatabaseEntry } from "src/utils/frontmatter";
export async function updateYamlInfo( export async function updateYamlInfo(
yamlContent: string, yamlContent: string,
@@ -18,6 +18,7 @@ export async function updateYamlInfo(
const { abName } = dbDetails const { abName } = dbDetails
const notionIDKey = `NotionID-${abName}`; const notionIDKey = `NotionID-${abName}`;
const linkKey = `link-${abName}`; const linkKey = `link-${abName}`;
const autoSyncKey = plugin.getAutoSyncFrontmatterKey();
if (notionUser !== "") { if (notionUser !== "") {
// replace url str "www" to notionID // replace url str "www" to notionID
@@ -36,8 +37,8 @@ export async function updateYamlInfo(
(NotionLinkDisplay) ? yamlContent[linkKey] = url : null; (NotionLinkDisplay) ? yamlContent[linkKey] = url : null;
// ensure auto sync database list contains current short name // ensure auto sync database list contains current short name
yamlContent[AUTO_SYNC_DATABASE_KEY] = ensureAutoSyncDatabaseEntry( yamlContent[autoSyncKey] = ensureAutoSyncDatabaseEntry(
yamlContent[AUTO_SYNC_DATABASE_KEY], yamlContent[autoSyncKey],
abName abName
); );
}); });

View File

@@ -1,4 +1,15 @@
export const AUTO_SYNC_DATABASE_KEY = "aytosync-database"; export const DEFAULT_AUTO_SYNC_DATABASE_KEY = "autosync-database";
export function resolveAutoSyncKey(rawKey: unknown): string {
if (typeof rawKey === "string") {
const trimmed = rawKey.trim();
if (trimmed.length > 0) {
return trimmed;
}
}
return DEFAULT_AUTO_SYNC_DATABASE_KEY;
}
function toCandidateList(value: unknown): string[] { function toCandidateList(value: unknown): string[] {
if (Array.isArray(value)) { if (Array.isArray(value)) {