Compare commits

...

20 Commits

Author SHA1 Message Date
Jiaxin Peng
a2200b68af chore: bump version to 2.8.4 2026-03-04 10:37:07 +00:00
Jiaxin Peng
95b22619b4 chore: update changelog format and remove version prefix for consistency 2026-03-04 10:37:02 +00:00
Jiaxin Peng
b08c46c233 fix: update release tag patterns and add version bump message in .npmrc 2026-03-04 10:32:32 +00:00
Jiaxin Peng
8dfb82b4ce 2.8.3 2026-03-04 10:29:10 +00:00
Jiaxin Peng
8502650033 fix: remove tag-version-prefix from .npmrc to correct version formatting in package.json 2026-03-04 10:29:06 +00:00
Jiaxin Peng
30e34e3f8c chore: update Node.js version to 22 in workflows and package.json 2026-03-04 10:10:41 +00:00
Jiaxin Peng
ec3d3e85a2 chore: update changelog 2026-03-04 10:00:12 +00:00
Jiaxin Peng
fe04e8df7f 2.8.2 2026-03-04 09:58:39 +00:00
Jiaxin Peng
d36deb7b30 fix: Set tag-version-prefix to "v" for proper versioning 2026-03-04 09:58:28 +00:00
Jiaxin Peng
e8295746e1 feat: Add release notes generation and update release process to use them 2026-03-04 09:52:07 +00:00
Jiaxin Peng
83df1111c4 2.8.1 2026-03-04 09:37:18 +00:00
Jiaxin Peng
6e8be42e3c chore: update changelog 2026-03-04 09:37:13 +00:00
Jiaxin Peng
6b02cb219e feat: Enhance version bumping process to update CHANGELOG.md with new version header 2026-03-04 09:30:32 +00:00
Jiaxin Peng
cd7eb78378 feat: Add isAutoSync option to sync requests and update success notice logic 2026-03-04 09:14:38 +00:00
Jiaxin Peng
3e00f127e9 feat: Add auto sync success notice setting and update upload commands to utilize it 2026-03-04 09:05:41 +00:00
Jiaxin Peng
4fb3b99996 feat: Add auto sync success notification messages in English, Japanese, and Chinese locales 2026-03-04 09:04:57 +00:00
Jiaxin Peng
269d354734 chore: Update roadmap to reflect completion of automatic syncing and file attachments features 2026-01-29 20:25:03 +00:00
Jiaxin Peng
a37bda1575 chore: Update changelog and documentation for v2.8.0 release with new features, changes, and fixes 2026-01-29 20:20:23 +00:00
Jiaxin Peng
19d66917d2 chore: Update changelog for v2.8.0-beta.4 release with new features and fixes 2026-01-29 20:15:11 +00:00
Jiaxin Peng
a9acfbe956 Merge pull request #72 from jxpeng98/dev
Add autosync feature
2026-01-29 20:12:04 +00:00
22 changed files with 343 additions and 42 deletions

View File

@@ -23,7 +23,7 @@ jobs:
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: "18" node-version: "22"
- name: Build - name: Build
id: build id: build

View File

@@ -5,14 +5,14 @@ on:
branches: branches:
- main - main
tags: tags:
# Only trigger for release tags (e.g., v1.0.0, v2.3.4) # Only trigger for release tags (e.g., 1.0.0, 2.3.4)
# Excludes prerelease tags (e.g., v2.8.0-beta.3, v1.0.0-rc.1) # Excludes prerelease tags (e.g., 2.8.0-beta.3, 1.0.0-rc.1)
- "v[0-9]+.[0-9]+.[0-9]" - "[0-9]+.[0-9]+.[0-9]"
- "v[0-9]+.[0-9]+.[0-9][0-9]" - "[0-9]+.[0-9]+.[0-9][0-9]"
- "v[0-9]+.[0-9]+.[0-9][0-9][0-9]" - "[0-9]+.[0-9]+.[0-9][0-9][0-9]"
- "v[0-9]+.[0-9][0-9].[0-9]" - "[0-9]+.[0-9][0-9].[0-9]"
- "v[0-9]+.[0-9][0-9].[0-9][0-9]" - "[0-9]+.[0-9][0-9].[0-9][0-9]"
- "v[0-9]+.[0-9][0-9].[0-9][0-9][0-9]" - "[0-9]+.[0-9][0-9].[0-9][0-9][0-9]"
env: env:
PLUGIN_NAME: share-to-notionnext # Change this to match the id of your plugin. PLUGIN_NAME: share-to-notionnext # Change this to match the id of your plugin.
@@ -27,7 +27,7 @@ jobs:
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: "18" node-version: "22"
# - name: Generate changelog # - name: Generate changelog
# id: changelog # id: changelog
@@ -48,21 +48,67 @@ jobs:
ls ls
echo "tag_name=$(git tag --sort version:refname | tail -n 1)" >> $GITHUB_OUTPUT echo "tag_name=$(git tag --sort version:refname | tail -n 1)" >> $GITHUB_OUTPUT
- name: Generate release notes
if: startsWith(github.ref, 'refs/tags/')
run: |
node - <<'NODE'
const fs = require('fs');
const tag = process.env.GITHUB_REF_NAME;
if (!tag) {
throw new Error('GITHUB_REF_NAME is not set');
}
const changelog = fs.readFileSync('CHANGELOG.md', 'utf8');
const lines = changelog.split(/\r?\n/);
const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const headerRe = new RegExp(`^##\\s+${escapeRegex(tag)}\\b`);
const start = lines.findIndex((line) => headerRe.test(line));
if (start === -1) {
throw new Error(`Could not find changelog section for tag "${tag}"`);
}
let end = lines.length;
for (let i = start + 1; i < lines.length; i++) {
if (/^##\s+/.test(lines[i])) {
end = i;
break;
}
}
let section = lines.slice(start, end);
while (section.length > 0 && section[section.length - 1].trim() === '') {
section.pop();
}
if (section.length > 0 && section[section.length - 1].trim() === '---') {
section.pop();
while (section.length > 0 && section[section.length - 1].trim() === '') {
section.pop();
}
}
fs.writeFileSync('release-notes.md', `${section.join('\n')}\n`);
NODE
- name: Create Release - name: Create Release
id: create_release id: create_release
if: startsWith(github.ref, 'refs/tags/')
uses: actions/create-release@v1 uses: actions/create-release@v1
env: env:
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
VERSION: ${{ github.ref }} VERSION: ${{ github.ref }}
with: with:
tag_name: ${{ github.ref }} tag_name: ${{ github.ref_name }}
release_name: ${{ github.ref }} release_name: ${{ github.ref_name }}
body_path: ${{ env.CHANGELOG_FILENAME }} body_path: release-notes.md
draft: false draft: false
prerelease: false prerelease: false
- name: Upload zip file - name: Upload zip file
id: upload-zip id: upload-zip
if: startsWith(github.ref, 'refs/tags/')
uses: actions/upload-release-asset@v1 uses: actions/upload-release-asset@v1
env: env:
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
@@ -74,6 +120,7 @@ jobs:
- name: Upload main.js - name: Upload main.js
id: upload-main id: upload-main
if: startsWith(github.ref, 'refs/tags/')
uses: actions/upload-release-asset@v1 uses: actions/upload-release-asset@v1
env: env:
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
@@ -85,6 +132,7 @@ jobs:
- name: Upload manifest.json - name: Upload manifest.json
id: upload-manifest id: upload-manifest
if: startsWith(github.ref, 'refs/tags/')
uses: actions/upload-release-asset@v1 uses: actions/upload-release-asset@v1
env: env:
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
@@ -96,6 +144,7 @@ jobs:
- name: Upload markdown template - name: Upload markdown template
id: upload-md id: upload-md
if: startsWith(github.ref, 'refs/tags/')
uses: actions/upload-release-asset@v1 uses: actions/upload-release-asset@v1
env: env:
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}

View File

@@ -18,7 +18,7 @@ jobs:
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: "18" node-version: "22"
- name: Build - name: Build
id: build id: build

3
.gitignore vendored
View File

@@ -28,3 +28,6 @@ local-data
# vitepress # vitepress
docs/.vitepress/dist docs/.vitepress/dist
docs/.vitepress/cache docs/.vitepress/cache
# claude code
.claude

1
.npmrc
View File

@@ -1 +1,2 @@
tag-version-prefix="" tag-version-prefix=""
message="chore: bump version to %s"

View File

@@ -1,5 +1,85 @@
# Changelog # Changelog
## Unreleased
### Added
### Changed
### Fixed
## 2.8.4 (2026-03-04)
### Fixed
- Fixed version bump with `tag-version-prefix="v"` in `.npmrc` causing incorrect version format in `package.json` (e.g. `v2.8.1` instead of `2.8.1`)
## 2.8.1 (2026-03-04)
### Added
- **Auto-sync success notice setting**: Toggle whether to show success notifications for auto-sync (defaults to off)
### Changed
- Auto-sync is quieter by default: success and "start upload" notices are suppressed unless explicitly enabled
### Fixed
- Auto-sync no longer shows "All blocks has been uploaded" (`BlockUploaded`) notice when success notices are disabled
## 2.8.0 (2026-01-29)
### Added
- **Auto Sync**: Automatically sync notes on content or frontmatter changes, with configurable delay and multi-database support
- **Attachment Upload**: Upload local images and PDFs to Notion via the File Upload API and insert them as `image`/`file` blocks
- **Auto-copy Notion Link**: Option to copy the Notion page link to clipboard after syncing
- **Auto-sync frontmatter key**: Customize the frontmatter key for auto-sync database lists (default: `autosync-database`)
- Comprehensive i18n support for UI and notifications
- Prerelease workflow for beta testing via GitHub Actions and BRAT
### Changed
- Improved auto-sync behavior and notices for files without `autosync-database` or missing NotionID
- Limited attachment link parsing to **Wikilinks** and **standard Markdown links** (Obsidian/App URL formats are now TODO/disabled)
- Standardized Notion API request header `Notion-Version` to `2025-09-03`
- Reduced per-file upload limit to **5MB** to maximize compatibility across Notion plans
- Enhanced settings tab and documentation for auto-sync usage
### Fixed
- Fixed mobile compatibility issues by using `window.setTimeout` instead of `NodeJS.Timeout`
- Prevented sync loops and improved change detection for frontmatter/body updates
- File placeholder tokens no longer break due to Markdown underscore parsing
- Better block ordering when attachments are on standalone lines in Markdown
- Preserve image captions when converting `external` images to `file_upload`
- Avoid duplicate filename display on uploaded `file` blocks
- Fixed `undefined` appearing in sync success notification by adding missing `sync-preffix` i18n key
---
## v2.8.0-beta.4 (2026-01-04)
### Added
- **Attachment Upload**: Upload local images and PDFs to Notion via the File Upload API and insert them as `image`/`file` blocks
- **Auto-sync safeguard**: Auto-sync is skipped for notes containing internal attachments (manual sync required)
### Changed
- Limited attachment link parsing to **Wikilinks** and **standard Markdown links** (Obsidian/App URL formats are now TODO/disabled)
- Standardized Notion API request header `Notion-Version` to `2025-09-03`
- Reduced per-file upload limit to **5MB** to maximize compatibility across Notion plans
### Fixed
- File placeholder tokens no longer break due to Markdown underscore parsing
- Better block ordering when attachments are on standalone lines in Markdown
- Preserve image captions when converting `external` images to `file_upload`
- Avoid duplicate filename display on uploaded `file` blocks
---
## v2.8.0-beta.3 (2025-12-10) ## v2.8.0-beta.3 (2025-12-10)
### Added ### Added

View File

@@ -7,6 +7,35 @@ description: Release notes and updates for Obsidian to NotionNext
Welcome to the Changelog for Obsidian to NotionNext! Here you'll find a detailed list of all the updates, improvements, and bug fixes made to the plugin over time from the version `2.7.0` onwards. Welcome to the Changelog for Obsidian to NotionNext! Here you'll find a detailed list of all the updates, improvements, and bug fixes made to the plugin over time from the version `2.7.0` onwards.
## v2.8.0 (2026-01-29)
### Added
- **Auto Sync**: Automatically sync notes on content or frontmatter changes, with configurable delay and multi-database support
- **Attachment Upload**: Upload local images and PDFs to Notion via the File Upload API and insert them as `image`/`file` blocks
- **Auto-copy Notion Link**: Option to copy the Notion page link to clipboard after syncing
- **Auto-sync frontmatter key**: Customize the frontmatter key for auto-sync database lists (default: `autosync-database`)
- Comprehensive i18n support for UI and notifications
- Prerelease workflow for beta testing via GitHub Actions and BRAT
### Changed
- Improved auto-sync behavior and notices for files without `autosync-database` or missing NotionID
- Limited attachment link parsing to **Wikilinks** and **standard Markdown links** (Obsidian/App URL formats are now TODO/disabled)
- Standardized Notion API request header `Notion-Version` to `2025-09-03`
- Reduced per-file upload limit to **5MB** to maximize compatibility across Notion plans
- Enhanced settings tab and documentation for auto-sync usage
### Fixed
- Fixed mobile compatibility issues by using `window.setTimeout` instead of `NodeJS.Timeout`
- Prevented sync loops and improved change detection for frontmatter/body updates
- File placeholder tokens no longer break due to Markdown underscore parsing
- Better block ordering when attachments are on standalone lines in Markdown
- Preserve image captions when converting `external` images to `file_upload`
- Avoid duplicate filename display on uploaded `file` blocks
- Fixed `undefined` appearing in sync success notification by adding missing `sync-preffix` i18n key
## v2.8.0-beta.2 (2025-11-05) ## v2.8.0-beta.2 (2025-11-05)
### Featured ### Featured

View File

@@ -5,6 +5,6 @@ description: Planned features and improvements for Obsidian to NotionNext
# Roadmap # Roadmap
- [ ] Automatic Syncing: Implement automatic syncing of notes at regular intervals or upon changes. - [x] Automatic Syncing: Implement automatic syncing of notes at regular intervals or upon changes.
- [ ] File Attachments: Support for syncing file attachments from Obsidian to Notion. - [x] File Attachments: Support for syncing file attachments from Obsidian to Notion.
- [ ] Relation Property: Enable mapping of Obsidian links to Notion relation properties. - [ ] Relation Property: Enable mapping of Obsidian links to Notion relation properties.

View File

@@ -4,3 +4,32 @@ description: Obsidian to NotionNext 的版本更新与变更记录
--- ---
欢迎来到 Obsidian to NotionNext 的更新日志!这里会记录自 `2.7.0` 版本起的所有更新、改进以及问题修复,方便你快速了解插件的演进情况。 欢迎来到 Obsidian to NotionNext 的更新日志!这里会记录自 `2.7.0` 版本起的所有更新、改进以及问题修复,方便你快速了解插件的演进情况。
## v2.8.0 (2026-01-29)
### 新增
- **自动同步**:当内容或 frontmatter 变化时自动同步,支持可配置延迟与多数据库
- **附件上传**:通过 File Upload API 上传本地图片与 PDF并插入为 `image`/`file`
- **自动复制 Notion 链接**:同步后自动复制页面链接到剪贴板
- **自动同步 frontmatter key**:可自定义自动同步数据库列表的 frontmatter key默认 `autosync-database`
- 完整的 UI 与通知 i18n 支持
- 通过 GitHub Actions + BRAT 的预发布测试流程
### 变更
- 优化自动同步行为与提示:无 `autosync-database` 或缺少 NotionID 的文件处理更智能
- 限制附件链接解析为 **Wikilinks****标准 Markdown 链接**Obsidian/App URL 暂停/待办)
- 统一 Notion API 请求头 `Notion-Version``2025-09-03`
- 单文件上传限制降为 **5MB**,提升兼容性
- 强化设置面板与自动同步相关文档
### 修复
- 移动端兼容性修复:使用 `window.setTimeout` 替代 `NodeJS.Timeout`
- 防止同步循环,改进 frontmatter/正文变更检测
- 修复 Markdown 下划线导致的占位符解析问题
- 修复附件独占行时的块顺序
- 保留 `external` 图片转为 `file_upload` 时的图片标题
- 避免上传 `file` 块时重复显示文件名
- 修复同步成功通知出现 `undefined`(补充 `sync-preffix` i18n key

View File

@@ -3,6 +3,6 @@ title: 路线图
description: Obsidian to NotionNext 的规划功能与未来改进 description: Obsidian to NotionNext 的规划功能与未来改进
--- ---
- [ ] 自动同步:支持按时间间隔或内容变更自动同步笔记。 - [x] 自动同步:支持按时间间隔或内容变更自动同步笔记。
- [ ] 附件支持:允许将 Obsidian 笔记中的附件一同上传到 Notion。 - [x] 附件支持:允许将 Obsidian 笔记中的附件一同上传到 Notion。
- [ ] 关联属性:实现将 Obsidian 链接映射到 Notion 的 relation 属性。 - [ ] 关联属性:实现将 Obsidian 链接映射到 Notion 的 relation 属性。

View File

@@ -1,7 +1,7 @@
{ {
"id": "share-to-notionnext", "id": "share-to-notionnext",
"name": "Share to NotionNext", "name": "Share to NotionNext",
"version": "2.7.0", "version": "2.8.4",
"minAppVersion": "0.0.1", "minAppVersion": "0.0.1",
"description": "Shares obsidian md file to notion with notion api for NotionNext web deploy, originally created by EasyChris/obsidian-to-notion.", "description": "Shares obsidian md file to notion with notion api for NotionNext web deploy, originally created by EasyChris/obsidian-to-notion.",
"author": "EasyChris, jxpeng98", "author": "EasyChris, jxpeng98",

View File

@@ -1,19 +1,19 @@
{ {
"name": "share-to-notionnext", "name": "share-to-notionnext",
"version": "2.7.0", "version": "2.8.4",
"type": "module", "type": "module",
"description": "Share files to any Notion database using the Notion API, originally created by EasyChris/obsidian-to-notion.", "description": "Share files to any Notion database using the Notion API, originally created by EasyChris/obsidian-to-notion.",
"main": "main.js", "main": "main.js",
"scripts": { "scripts": {
"dev": "node esbuild.config.mjs", "dev": "node esbuild.config.mjs",
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production", "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
"version": "node version-bump.mjs && git add manifest.json versions.json" "version": "node version-bump.mjs && git add manifest.json versions.json CHANGELOG.md"
}, },
"keywords": [], "keywords": [],
"author": "Jiaxin PENG", "author": "Jiaxin PENG",
"license": "GNU GPLv3", "license": "GNU GPLv3",
"devDependencies": { "devDependencies": {
"@types/node": "^20.5.7", "@types/node": "^22.11.3",
"@types/yaml-front-matter": "^4.1.3", "@types/yaml-front-matter": "^4.1.3",
"@typescript-eslint/eslint-plugin": "^6.16.0", "@typescript-eslint/eslint-plugin": "^6.16.0",
"@typescript-eslint/parser": "^6.16.0", "@typescript-eslint/parser": "^6.16.0",

View File

@@ -44,6 +44,8 @@ export const en = {
AutoSyncDelay: "Auto Sync Delay (seconds)", AutoSyncDelay: "Auto Sync Delay (seconds)",
AutoSyncDelayDesc: "Delay in seconds to wait before syncing after a change. Prevents excessive syncs (default: 5s, min: 2s).", AutoSyncDelayDesc: "Delay in seconds to wait before syncing after a change. Prevents excessive syncs (default: 5s, min: 2s).",
AutoSyncDelayText: "Enter delay in seconds", AutoSyncDelayText: "Enter delay in seconds",
AutoSyncSuccessNotice: "Auto Sync Success Notice",
AutoSyncSuccessNoticeDesc: "Show a notification when auto-sync succeeds (default: off; failures are still notified).",
NotionGeneralSettingHeader: "General Notion Database Settings", NotionGeneralSettingHeader: "General Notion Database Settings",
NotionGeneralButton: "General Database Sync", NotionGeneralButton: "General Database Sync",
NotionGeneralButtonDesc: "Enables the 'Sync to General Database' command in the command palette (default: on).", NotionGeneralButtonDesc: "Enables the 'Sync to General Database' command in the command palette (default: on).",

View File

@@ -42,6 +42,8 @@ export const ja = {
AutoSyncDelay: "自動同期の遅延(秒)", AutoSyncDelay: "自動同期の遅延(秒)",
AutoSyncDelayDesc: "変更が検知されてから同期を開始するまでの遅延時間。同期の頻発を防ぎますデフォルト5秒、最小2秒。", AutoSyncDelayDesc: "変更が検知されてから同期を開始するまでの遅延時間。同期の頻発を防ぎますデフォルト5秒、最小2秒。",
AutoSyncDelayText: "遅延秒数を入力", AutoSyncDelayText: "遅延秒数を入力",
AutoSyncSuccessNotice: "自動同期成功通知",
AutoSyncSuccessNoticeDesc: "自動同期が成功したときに通知を表示します(デフォルト:オフ。失敗時は通知されます)。",
NotionGeneralSettingHeader: "一般Notionデータベース設定", NotionGeneralSettingHeader: "一般Notionデータベース設定",
NotionGeneralButton: "一般データベース同期", NotionGeneralButton: "一般データベース同期",
NotionGeneralButtonDesc: "有効にすると、コマンドパレットに「一般データベースへ同期」が表示されます(デフォルト:オン)。", NotionGeneralButtonDesc: "有効にすると、コマンドパレットに「一般データベースへ同期」が表示されます(デフォルト:オン)。",

View File

@@ -44,6 +44,8 @@ export const zh = {
AutoSyncDelay: "自动同步延迟(秒)", AutoSyncDelay: "自动同步延迟(秒)",
AutoSyncDelayDesc: "文档修改后,等待指定秒数再触发自动同步,以避免频繁操作(默认 5 秒,最少 2 秒)", AutoSyncDelayDesc: "文档修改后,等待指定秒数再触发自动同步,以避免频繁操作(默认 5 秒,最少 2 秒)",
AutoSyncDelayText: "输入延迟秒数", AutoSyncDelayText: "输入延迟秒数",
AutoSyncSuccessNotice: "自动同步成功通知",
AutoSyncSuccessNoticeDesc: "是否在自动同步成功后弹出通知(默认关闭,仅在失败时通知)",
NotionGeneralSettingHeader: "通用 Notion 数据库设置", NotionGeneralSettingHeader: "通用 Notion 数据库设置",
NotionGeneralButton: "通用数据库同步", NotionGeneralButton: "通用数据库同步",
NotionGeneralButtonDesc: "启用后,命令面板中将显示“同步到通用数据库”命令(默认开启)", NotionGeneralButtonDesc: "启用后,命令面板中将显示“同步到通用数据库”命令(默认开启)",

View File

@@ -92,6 +92,9 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
if (typeof this.settings.autoSyncDelay !== 'number' || this.settings.autoSyncDelay < 2) { if (typeof this.settings.autoSyncDelay !== 'number' || this.settings.autoSyncDelay < 2) {
this.settings.autoSyncDelay = DEFAULT_SETTINGS.autoSyncDelay; this.settings.autoSyncDelay = DEFAULT_SETTINGS.autoSyncDelay;
} }
if (typeof this.settings.autoSyncSuccessNotice !== 'boolean') {
this.settings.autoSyncSuccessNotice = DEFAULT_SETTINGS.autoSyncSuccessNotice;
}
if (typeof this.settings.NotionLinkDisplay !== 'boolean') { if (typeof this.settings.NotionLinkDisplay !== 'boolean') {
this.settings.NotionLinkDisplay = DEFAULT_SETTINGS.NotionLinkDisplay; this.settings.NotionLinkDisplay = DEFAULT_SETTINGS.NotionLinkDisplay;
} }
@@ -112,6 +115,7 @@ 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.autoSyncSuccessNotice === undefined ||
loadedData.NotionLinkDisplay === undefined || loadedData.NotionLinkDisplay === undefined ||
loadedData.autoCopyNotionLink === undefined || loadedData.autoCopyNotionLink === undefined ||
loadedData.autoSyncFrontmatterKey === undefined; loadedData.autoSyncFrontmatterKey === undefined;
@@ -123,6 +127,7 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
} else { } else {
if (loadedData.autoSync === undefined) migratedFields.push('autoSync'); if (loadedData.autoSync === undefined) migratedFields.push('autoSync');
if (loadedData.autoSyncDelay === undefined) migratedFields.push('autoSyncDelay'); if (loadedData.autoSyncDelay === undefined) migratedFields.push('autoSyncDelay');
if (loadedData.autoSyncSuccessNotice === undefined) migratedFields.push('autoSyncSuccessNotice');
if (loadedData.NotionLinkDisplay === undefined) migratedFields.push('NotionLinkDisplay'); if (loadedData.NotionLinkDisplay === undefined) migratedFields.push('NotionLinkDisplay');
if (loadedData.autoCopyNotionLink === undefined) migratedFields.push('autoCopyNotionLink'); if (loadedData.autoCopyNotionLink === undefined) migratedFields.push('autoCopyNotionLink');
@@ -146,6 +151,7 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
console.log('[Settings] Settings saved successfully', { console.log('[Settings] Settings saved successfully', {
autoSync: this.settings.autoSync, autoSync: this.settings.autoSync,
autoSyncDelay: this.settings.autoSyncDelay, autoSyncDelay: this.settings.autoSyncDelay,
autoSyncSuccessNotice: this.settings.autoSyncSuccessNotice,
NotionLinkDisplay: this.settings.NotionLinkDisplay, NotionLinkDisplay: this.settings.NotionLinkDisplay,
autoSyncFrontmatterKey: this.settings.autoSyncFrontmatterKey, autoSyncFrontmatterKey: this.settings.autoSyncFrontmatterKey,
databaseCount: Object.keys(this.settings.databaseDetails || {}).length databaseCount: Object.keys(this.settings.databaseDetails || {}).length
@@ -162,6 +168,10 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
console.warn('[Settings] Invalid autoSyncDelay value, resetting to default'); console.warn('[Settings] Invalid autoSyncDelay value, resetting to default');
this.settings.autoSyncDelay = DEFAULT_SETTINGS.autoSyncDelay; this.settings.autoSyncDelay = DEFAULT_SETTINGS.autoSyncDelay;
} }
if (typeof this.settings.autoSyncSuccessNotice !== 'boolean') {
console.warn('[Settings] Invalid autoSyncSuccessNotice value, resetting to default');
this.settings.autoSyncSuccessNotice = DEFAULT_SETTINGS.autoSyncSuccessNotice;
}
if (typeof this.settings.NotionLinkDisplay !== 'boolean') { if (typeof this.settings.NotionLinkDisplay !== 'boolean') {
console.warn('[Settings] Invalid NotionLinkDisplay value, resetting to default'); console.warn('[Settings] Invalid NotionLinkDisplay value, resetting to default');
this.settings.NotionLinkDisplay = DEFAULT_SETTINGS.NotionLinkDisplay; this.settings.NotionLinkDisplay = DEFAULT_SETTINGS.NotionLinkDisplay;
@@ -415,11 +425,11 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
try { try {
// Trigger appropriate upload command based on database format // Trigger appropriate upload command based on database format
if (dbDetails.format === 'next') { if (dbDetails.format === 'next') {
await uploadCommandNext(this, this.settings, dbDetails, this.app); await uploadCommandNext(this, this.settings, dbDetails, this.app, { isAutoSync: true });
} else if (dbDetails.format === 'general') { } else if (dbDetails.format === 'general') {
await uploadCommandGeneral(this, this.settings, dbDetails, this.app); await uploadCommandGeneral(this, this.settings, dbDetails, this.app, { isAutoSync: true });
} else if (dbDetails.format === 'custom') { } else if (dbDetails.format === 'custom') {
await uploadCommandCustom(this, this.settings, dbDetails, this.app); await uploadCommandCustom(this, this.settings, dbDetails, this.app, { isAutoSync: true });
} }
} catch (error) { } catch (error) {
console.error(`[AutoSync] Error syncing to ${dbDetails.fullName}:`, error); console.error(`[AutoSync] Error syncing to ${dbDetails.fullName}:`, error);

View File

@@ -17,6 +17,7 @@ export interface PluginSettings {
autoCopyNotionLink: boolean; autoCopyNotionLink: boolean;
autoSync: boolean; autoSync: boolean;
autoSyncDelay: number; autoSyncDelay: number;
autoSyncSuccessNotice: boolean;
autoSyncFrontmatterKey: string; autoSyncFrontmatterKey: string;
proxy: string; proxy: string;
GeneralButton: boolean; GeneralButton: boolean;
@@ -57,6 +58,7 @@ export const DEFAULT_SETTINGS: PluginSettings = {
autoCopyNotionLink: true, autoCopyNotionLink: true,
autoSync: false, autoSync: false,
autoSyncDelay: 5, autoSyncDelay: 5,
autoSyncSuccessNotice: false,
autoSyncFrontmatterKey: DEFAULT_AUTO_SYNC_DATABASE_KEY, autoSyncFrontmatterKey: DEFAULT_AUTO_SYNC_DATABASE_KEY,
proxy: "", proxy: "",
GeneralButton: true, GeneralButton: true,
@@ -100,6 +102,15 @@ export class ObsidianSettingTab extends PluginSettingTab {
this.createSettingEl(containerEl, i18nConfig.AutoCopyNotionLink, i18nConfig.AutoCopyNotionLinkDesc, 'toggle', i18nConfig.AutoCopyNotionLink, this.plugin.settings.autoCopyNotionLink, 'autoCopyNotionLink') this.createSettingEl(containerEl, i18nConfig.AutoCopyNotionLink, i18nConfig.AutoCopyNotionLinkDesc, 'toggle', i18nConfig.AutoCopyNotionLink, this.plugin.settings.autoCopyNotionLink, 'autoCopyNotionLink')
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')
this.createSettingEl(
containerEl,
i18nConfig.AutoSyncSuccessNotice,
i18nConfig.AutoSyncSuccessNoticeDesc,
'toggle',
i18nConfig.AutoSyncSuccessNotice,
this.plugin.settings.autoSyncSuccessNotice,
'autoSyncSuccessNotice'
)
new Setting(containerEl) new Setting(containerEl)
.setName(i18nConfig.AutoSyncFrontmatterKey) .setName(i18nConfig.AutoSyncFrontmatterKey)
@@ -369,4 +380,3 @@ export class ObsidianSettingTab extends PluginSettingTab {
} }
} }
} }

View File

@@ -15,6 +15,7 @@ interface BaseSyncRequest {
markdown: string; markdown: string;
nowFile: TFile; nowFile: TFile;
app: App; app: App;
isAutoSync?: boolean;
} }
interface GeneralSyncRequest extends BaseSyncRequest { interface GeneralSyncRequest extends BaseSyncRequest {
@@ -91,6 +92,7 @@ export class Upload2Notion extends UploadBase {
async sync(request: SyncRequest): Promise<NotionPageResponse> { async sync(request: SyncRequest): Promise<NotionPageResponse> {
const startedAt = Date.now(); const startedAt = Date.now();
this.isAutoSync = !!request.isAutoSync;
let response: NotionPageResponse; let response: NotionPageResponse;

View File

@@ -18,12 +18,20 @@ interface PreparedBlocks {
export abstract class UploadBase { export abstract class UploadBase {
protected plugin: MyPlugin; protected plugin: MyPlugin;
protected dbDetails: DatabaseDetails; protected dbDetails: DatabaseDetails;
protected isAutoSync = false;
protected constructor(plugin: MyPlugin, dbDetails: DatabaseDetails) { protected constructor(plugin: MyPlugin, dbDetails: DatabaseDetails) {
this.plugin = plugin; this.plugin = plugin;
this.dbDetails = dbDetails; this.dbDetails = dbDetails;
} }
private shouldShowSuccessNotices(): boolean {
if (!this.isAutoSync) {
return true;
}
return !!this.plugin.settings.autoSyncSuccessNotice;
}
async deletePage(notionID: string) { async deletePage(notionID: string) {
const {notionAPI} = this.dbDetails; const {notionAPI} = this.dbDetails;
return requestUrl({ return requestUrl({
@@ -190,11 +198,13 @@ export abstract class UploadBase {
console.log(`${i18nConfig["ExtraBlockUploaded"]} to page: ${pageId}`); console.log(`${i18nConfig["ExtraBlockUploaded"]} to page: ${pageId}`);
if (i === extraChunks.length - 1) { if (i === extraChunks.length - 1) {
console.log(`${i18nConfig["BlockUploaded"]} to page: ${pageId}`); console.log(`${i18nConfig["BlockUploaded"]} to page: ${pageId}`);
if (this.shouldShowSuccessNotices()) {
new Notice(`${i18nConfig["BlockUploaded"]} page: ${pageId}`, 5000); new Notice(`${i18nConfig["BlockUploaded"]} page: ${pageId}`, 5000);
} }
} }
} }
} }
}
private async fetchDatabaseCover(): Promise<string | null> { private async fetchDatabaseCover(): Promise<string | null> {
const {notionAPI, databaseID} = this.dbDetails; const {notionAPI, databaseID} = this.dbDetails;

View File

@@ -10,6 +10,10 @@ import {getNowFileMarkdownContentCustom} from "./common/getMarkdownCustom";
const SYNC_ERROR_NOTICE_DURATION = 8000; const SYNC_ERROR_NOTICE_DURATION = 8000;
interface UploadCommandOptions {
isAutoSync?: boolean;
}
function extractErrorMessage(error: unknown): string { function extractErrorMessage(error: unknown): string {
if (error instanceof Error && error.message) { if (error instanceof Error && error.message) {
return error.message; return error.message;
@@ -17,6 +21,16 @@ function extractErrorMessage(error: unknown): string {
return String(error); return String(error);
} }
function shouldShowAutoSyncSuccessNotice(
plugin: ObsidianSyncNotionPlugin,
options?: UploadCommandOptions,
): boolean {
if (!options?.isAutoSync) {
return true;
}
return !!plugin.settings.autoSyncSuccessNotice;
}
function notifySyncError(prefix: string, basename: string, error: unknown): void { function notifySyncError(prefix: string, basename: string, error: unknown): void {
const errorMessage = extractErrorMessage(error); const errorMessage = extractErrorMessage(error);
console.error(`${prefix} Sync failed`, error); console.error(`${prefix} Sync failed`, error);
@@ -39,6 +53,7 @@ export async function uploadCommandNext(
settings: PluginSettings, settings: PluginSettings,
dbDetails: DatabaseDetails, dbDetails: DatabaseDetails,
app: App, app: App,
options?: UploadCommandOptions,
) { ) {
const {notionAPI, databaseID} = dbDetails; const {notionAPI, databaseID} = dbDetails;
@@ -91,6 +106,7 @@ export async function uploadCommandNext(
try { try {
res = await upload.sync({ res = await upload.sync({
dataset: "next", dataset: "next",
isAutoSync: options?.isAutoSync,
title: basename, title: basename,
emoji: emoji || "", emoji: emoji || "",
cover: cover || "", cover: cover || "",
@@ -118,7 +134,9 @@ export async function uploadCommandNext(
const {response} = res; const {response} = res;
if (response.status === 200) { if (response.status === 200) {
if (shouldShowAutoSyncSuccessNotice(plugin, options)) {
new Notice(`${i18nConfig["sync-preffix"]} ${basename} ${i18nConfig["sync-success"]}`).noticeEl.style.color = "green"; new Notice(`${i18nConfig["sync-preffix"]} ${basename} ${i18nConfig["sync-success"]}`).noticeEl.style.color = "green";
}
logCommandDebug("uploadCommandNext", "Sync succeeded", { logCommandDebug("uploadCommandNext", "Sync succeeded", {
filename: basename, filename: basename,
@@ -146,6 +164,7 @@ export async function uploadCommandGeneral(
settings: PluginSettings, settings: PluginSettings,
dbDetails: DatabaseDetails, dbDetails: DatabaseDetails,
app: App, app: App,
options?: UploadCommandOptions,
) { ) {
const {notionAPI, databaseID} = dbDetails; const {notionAPI, databaseID} = dbDetails;
@@ -160,7 +179,9 @@ export async function uploadCommandGeneral(
const {markDownData, nowFile, cover, tags} = await getNowFileMarkdownContentGeneral(app, settings) const {markDownData, nowFile, cover, tags} = await getNowFileMarkdownContentGeneral(app, settings)
if (!options?.isAutoSync) {
new Notice(i18nConfig.StartUpload.replace('{filename}', nowFile.basename)); new Notice(i18nConfig.StartUpload.replace('{filename}', nowFile.basename));
}
console.log(`Start upload ${nowFile.basename}`); console.log(`Start upload ${nowFile.basename}`);
if (markDownData) { if (markDownData) {
@@ -177,6 +198,7 @@ export async function uploadCommandGeneral(
try { try {
res = await upload.sync({ res = await upload.sync({
dataset: "general", dataset: "general",
isAutoSync: options?.isAutoSync,
title: basename, title: basename,
cover: cover || "", cover: cover || "",
tags: tags || [], tags: tags || [],
@@ -195,7 +217,9 @@ export async function uploadCommandGeneral(
const {response} = res; const {response} = res;
if (response.status === 200) { if (response.status === 200) {
if (shouldShowAutoSyncSuccessNotice(plugin, options)) {
new Notice(`${i18nConfig["sync-preffix"]} ${basename} ${i18nConfig["sync-success"]}`).noticeEl.style.color = "green"; new Notice(`${i18nConfig["sync-preffix"]} ${basename} ${i18nConfig["sync-success"]}`).noticeEl.style.color = "green";
}
logCommandDebug("uploadCommandGeneral", "Sync succeeded", { logCommandDebug("uploadCommandGeneral", "Sync succeeded", {
filename: basename, filename: basename,
@@ -223,6 +247,7 @@ export async function uploadCommandCustom(
settings: PluginSettings, settings: PluginSettings,
dbDetails: DatabaseDetails, dbDetails: DatabaseDetails,
app: App, app: App,
options?: UploadCommandOptions,
) { ) {
const {notionAPI, databaseID} = dbDetails; const {notionAPI, databaseID} = dbDetails;
@@ -237,7 +262,9 @@ export async function uploadCommandCustom(
const {markDownData, nowFile, cover, customValues} = await getNowFileMarkdownContentCustom(app, dbDetails) const {markDownData, nowFile, cover, customValues} = await getNowFileMarkdownContentCustom(app, dbDetails)
if (!options?.isAutoSync) {
new Notice(i18nConfig.StartUpload.replace('{filename}', nowFile.basename)); new Notice(i18nConfig.StartUpload.replace('{filename}', nowFile.basename));
}
console.log(`Start upload ${nowFile.basename}`); console.log(`Start upload ${nowFile.basename}`);
if (markDownData) { if (markDownData) {
@@ -254,6 +281,7 @@ export async function uploadCommandCustom(
try { try {
res = await upload.sync({ res = await upload.sync({
dataset: "custom", dataset: "custom",
isAutoSync: options?.isAutoSync,
cover: cover || "", cover: cover || "",
customValues, customValues,
markdown: markDownData, markdown: markDownData,
@@ -272,7 +300,9 @@ export async function uploadCommandCustom(
const {response} = res; const {response} = res;
if (response.status === 200) { if (response.status === 200) {
if (shouldShowAutoSyncSuccessNotice(plugin, options)) {
new Notice(`${i18nConfig["sync-preffix"]} ${basename} ${i18nConfig["sync-success"]}`).noticeEl.style.color = "green"; new Notice(`${i18nConfig["sync-preffix"]} ${basename} ${i18nConfig["sync-success"]}`).noticeEl.style.color = "green";
}
logCommandDebug("uploadCommandCustom", "Sync succeeded", { logCommandDebug("uploadCommandCustom", "Sync succeeded", {
filename: basename, filename: basename,

View File

@@ -12,3 +12,40 @@ writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t"));
let versions = JSON.parse(readFileSync("versions.json", "utf8")); let versions = JSON.parse(readFileSync("versions.json", "utf8"));
versions[targetVersion] = minAppVersion; versions[targetVersion] = minAppVersion;
writeFileSync("versions.json", JSON.stringify(versions, null, "\t")); writeFileSync("versions.json", JSON.stringify(versions, null, "\t"));
// tag the changelog by converting "Unreleased" to the new version section
function bumpChangelog(version) {
const changelogPath = "CHANGELOG.md";
const content = readFileSync(changelogPath, "utf8");
const unreleasedHeader = "## Unreleased";
if (!content.includes(unreleasedHeader)) {
console.warn(`[version-bump] ${unreleasedHeader} not found in ${changelogPath}, skipping changelog tagging`);
return;
}
const today = new Date().toISOString().slice(0, 10);
const releaseHeader = `## ${version} (${today})`;
const updated = content.replace(unreleasedHeader, releaseHeader);
const marker = "# Changelog\n\n";
if (!updated.startsWith(marker)) {
writeFileSync(changelogPath, updated);
return;
}
const newUnreleased = [
"## Unreleased",
"",
"### Added",
"",
"### Changed",
"",
"### Fixed",
"",
].join("\n");
writeFileSync(changelogPath, marker + newUnreleased + updated.slice(marker.length));
}
bumpChangelog(targetVersion);

View File

@@ -1,4 +1,9 @@
{ {
"1.0.0": "0.9.7", "1.0.0": "0.9.7",
"1.0.1": "0.12.0" "1.0.1": "0.12.0",
"2.8.0": "0.0.1",
"2.8.1": "0.0.1",
"2.8.2": "0.0.1",
"2.8.3": "0.0.1",
"2.8.4": "0.0.1"
} }