Merge pull request #64 from jxpeng98/callout-support

feat: callout support
This commit is contained in:
Jiaxin Peng
2025-10-27 23:20:27 +00:00
committed by GitHub
7 changed files with 665 additions and 682 deletions

View File

@@ -1,6 +1,6 @@
## Feature ## Feature
- Unify and combine the upload logic for three types of database.
- Better debugging information for upload failures. - Better debugging information for upload failures.
- 统一和合并三种数据库的上传逻辑。 - Support synchronising Obsidian callouts as Notion callout blocks.
- 优化控制台输出的调试信息。 - 优化控制台输出的调试信息。
- 支持将 Obsidian Callout 同步为 Notion Callout 区块。

View File

@@ -30,8 +30,20 @@
- [x] Support custom properties for Notion General database. 支持自定义属性 - [x] Support custom properties for Notion General database. 支持自定义属性
- [x] Support preview for database details in plugin settings. 支持预览数据库详情 - [x] Support preview for database details in plugin settings. 支持预览数据库详情
- [x] Support edit for database details in plugin settings. 支持编辑数据库详情 - [x] Support edit for database details in plugin settings. 支持编辑数据库详情
- [x] Convert Obsidian callouts into Notion callout blocks so your `[!info]` style notes stay consistent after syncing.
- [ ] Support group upload with one click 支持一键多数据库上传 - [ ] Support group upload with one click 支持一键多数据库上传
## Callout support
Obsidian callouts written with the standard syntax (for example `> [!warning]` or `> [!quote]`) are automatically rendered as Notion callout blocks during upload. The plugin keeps the chosen callout type, title, and body content so your callout styling survives the trip from Obsidian to Notion without extra configuration.
```markdown
> [!info] Tips
> Remember to update your front matter before syncing.
```
After syncing, the note will contain an equivalent Notion callout block with the same icon and text.
## How to use ## How to use
If you want to use this plugin, you need to follow the following steps to set up the plugin. The steps can be divided into two parts: setting up the Notion API and setting up the plugin in Obsidian. If you want to use this plugin, you need to follow the following steps to set up the plugin. The steps can be divided into two parts: setting up the Notion API and setting up the plugin in Obsidian.

View File

@@ -10,7 +10,7 @@
"version": "node version-bump.mjs && git add manifest.json versions.json" "version": "node version-bump.mjs && git add manifest.json versions.json"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "Jiaxin PENG",
"license": "GNU GPLv3", "license": "GNU GPLv3",
"devDependencies": { "devDependencies": {
"@types/node": "^20.5.7", "@types/node": "^20.5.7",
@@ -24,7 +24,7 @@
"typescript": "5.2.2" "typescript": "5.2.2"
}, },
"dependencies": { "dependencies": {
"@jxpeng98/martian": "^1.2.7", "@jxpeng98/martian": "^1.3.1",
"https-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.2",
"remark-math": "^6.0.0", "remark-math": "^6.0.0",
"yaml": "^2.3.4", "yaml": "^2.3.4",

View File

@@ -1,7 +1,7 @@
import { App, TFile } from "obsidian"; import { App, TFile } from "obsidian";
import { markdownToBlocks } from "@jxpeng98/martian"; import { markdownToBlocks } from "@jxpeng98/martian";
import * as yamlFrontMatter from "yaml-front-matter"; import * as yamlFrontMatter from "yaml-front-matter";
import { LIMITS, paragraph } from "@jxpeng98/martian/src/notion"; import { LIMITS, paragraph } from "@jxpeng98/martian";
import MyPlugin from "src/main"; import MyPlugin from "src/main";
import { DatabaseDetails } from "../ui/settingTabs"; import { DatabaseDetails } from "../ui/settingTabs";
import { updateYamlInfo } from "./updateYaml"; import { updateYamlInfo } from "./updateYaml";
@@ -89,11 +89,7 @@ export class Upload2Notion extends UploadBase {
} }
async sync(request: SyncRequest): Promise<NotionPageResponse> { async sync(request: SyncRequest): Promise<NotionPageResponse> {
console.log(`[Upload2Notion] Start sync`, { const startedAt = Date.now();
dataset: request.dataset,
file: request.nowFile.path,
database: this.dbDetails.databaseID,
});
let response: NotionPageResponse; let response: NotionPageResponse;
@@ -111,13 +107,7 @@ export class Upload2Notion extends UploadBase {
throw new Error(`Unsupported dataset type: ${(request as any).dataset}`); throw new Error(`Unsupported dataset type: ${(request as any).dataset}`);
} }
console.log(`[Upload2Notion] Notion response status`, response.response?.status);
if (response.response && response.response.status === 200) { if (response.response && response.response.status === 200) {
console.log(`[Upload2Notion] Sync success`, {
notionPageId: response.data?.id,
notionPageUrl: response.data?.url,
});
await updateYamlInfo( await updateYamlInfo(
request.markdown, request.markdown,
request.nowFile, request.nowFile,
@@ -142,6 +132,11 @@ export class Upload2Notion extends UploadBase {
notionLimits: {truncate: false}, notionLimits: {truncate: false},
}); });
const notionId = this.getNotionId(request.app, request.nowFile); const notionId = this.getNotionId(request.app, request.nowFile);
this.debugLog("Upload2Notion", "General dataset payload prepared", {
blockCount: blocks.length,
notionId: notionId ?? null,
tagCount: request.tags?.length ?? 0,
});
return this.upsertGeneral({ return this.upsertGeneral({
title: request.title, title: request.title,
@@ -163,6 +158,12 @@ export class Upload2Notion extends UploadBase {
}); });
this.splitRichTextParagraphs(blocks); this.splitRichTextParagraphs(blocks);
const notionId = this.getNotionId(request.app, request.nowFile); const notionId = this.getNotionId(request.app, request.nowFile);
this.debugLog("Upload2Notion", "Next dataset payload prepared", {
blockCount: blocks.length,
notionId: notionId ?? null,
hasEmoji: !!request.emoji,
tags: request.tags || [],
});
return this.upsertNext({ return this.upsertNext({
title: request.title, title: request.title,
@@ -191,6 +192,11 @@ export class Upload2Notion extends UploadBase {
notionLimits: {truncate: false}, notionLimits: {truncate: false},
}); });
const notionId = this.getNotionId(request.app, request.nowFile); const notionId = this.getNotionId(request.app, request.nowFile);
this.debugLog("Upload2Notion", "Custom dataset payload prepared", {
blockCount: blocks.length,
notionId: notionId ?? null,
customValueKeys: Object.keys(request.customValues || {}),
});
return this.upsertCustom({ return this.upsertCustom({
cover: request.cover, cover: request.cover,
@@ -203,12 +209,21 @@ export class Upload2Notion extends UploadBase {
private buildBlocks(markdown: string, options: Record<string, unknown>): any[] { private buildBlocks(markdown: string, options: Record<string, unknown>): any[] {
const yamlContent: any = yamlFrontMatter.loadFront(markdown); const yamlContent: any = yamlFrontMatter.loadFront(markdown);
const content = yamlContent.__content; const content = yamlContent.__content;
return markdownToBlocks(content, options); const blocks = markdownToBlocks(content, options);
this.debugLog("Upload2Notion", "Converted markdown to blocks", {
blockCount: blocks.length,
firstBlockTypes: blocks.slice(0, 5).map((block: any) => block?.type),
options,
});
return blocks;
} }
private getNotionId(app: App, nowFile: TFile): string | undefined { private getNotionId(app: App, nowFile: TFile): string | undefined {
const frontMatter = app.metadataCache.getFileCache(nowFile)?.frontmatter; const frontMatter = app.metadataCache.getFileCache(nowFile)?.frontmatter;
if (!frontMatter) { if (!frontMatter) {
this.debugLog("Upload2Notion", "No frontmatter found when resolving Notion ID", {
filePath: nowFile.path,
});
return undefined; return undefined;
} }
const {abName} = this.dbDetails; const {abName} = this.dbDetails;
@@ -247,8 +262,20 @@ export class Upload2Notion extends UploadBase {
const cover = params.notionId const cover = params.notionId
? await this.resolveCoverForUpdate(params.cover) ? await this.resolveCoverForUpdate(params.cover)
: params.cover; : params.cover;
this.debugLog("Upload2Notion", "Upserting general page", {
title: params.title,
blockCount: params.childArr.length,
firstChunkSize: firstChunk.length,
extraChunkCount: extraChunks.length,
cover: cover ?? null,
notionIdExisting: params.notionId ?? null,
tagList: params.tags,
});
if (params.notionId) { if (params.notionId) {
console.log(`[Upload2Notion] Deleting existing Notion page`, {
notionId: params.notionId,
});
await this.deletePage(params.notionId); await this.deletePage(params.notionId);
} }
@@ -267,6 +294,17 @@ export class Upload2Notion extends UploadBase {
const cover = params.notionId const cover = params.notionId
? await this.resolveCoverForUpdate(params.cover) ? await this.resolveCoverForUpdate(params.cover)
: params.cover; : params.cover;
this.debugLog("Upload2Notion", "Upserting NotionNext page", {
title: params.title,
type: params.type,
slug: params.slug,
blockCount: params.childArr.length,
firstChunkSize: firstChunk.length,
extraChunkCount: extraChunks.length,
cover: cover ?? null,
hasEmoji: !!params.emoji,
notionIdExisting: params.notionId ?? null,
});
if (params.notionId) { if (params.notionId) {
await this.deletePage(params.notionId); await this.deletePage(params.notionId);
@@ -296,6 +334,14 @@ export class Upload2Notion extends UploadBase {
const cover = params.notionId const cover = params.notionId
? await this.resolveCoverForUpdate(params.cover) ? await this.resolveCoverForUpdate(params.cover)
: params.cover; : params.cover;
this.debugLog("Upload2Notion", "Upserting custom page", {
blockCount: params.childArr.length,
firstChunkSize: firstChunk.length,
extraChunkCount: extraChunks.length,
cover: cover ?? null,
notionIdExisting: params.notionId ?? null,
customValueKeys: Object.keys(params.customValues || {}),
});
if (params.notionId) { if (params.notionId) {
await this.deletePage(params.notionId); await this.deletePage(params.notionId);

View File

@@ -33,16 +33,21 @@ export abstract class UploadBase {
"Notion-Version": "2022-06-28", "Notion-Version": "2022-06-28",
}, },
body: "", body: "",
}); throw: false,
}).catch((error) =>
this.handleRequestError(error, `Deleting Notion page ${notionID}`),
);
} }
protected prepareBlocks(childArr: any[]): PreparedBlocks { protected prepareBlocks(childArr: any[]): PreparedBlocks {
this.stripCodeAnnotations(childArr); this.stripCodeAnnotations(childArr);
const childArrLength = childArr.length; const childArrLength = childArr.length;
console.log(`Page includes ${childArrLength} blocks`);
if (childArrLength <= 100) { if (childArrLength <= 100) {
this.debugLog("UploadBase", "Blocks fit into a single request", {
totalBlocks: childArrLength,
});
return { return {
firstChunk: childArr, firstChunk: childArr,
extraChunks: [], extraChunks: [],
@@ -54,6 +59,13 @@ export abstract class UploadBase {
extraChunks.push(childArr.slice(i, i + 100)); extraChunks.push(childArr.slice(i, i + 100));
} }
this.debugLog("UploadBase", "Blocks split into multiple chunks", {
totalBlocks: childArrLength,
firstChunkSize: 100,
extraChunkCount: extraChunks.length,
lastChunkSize: extraChunks[extraChunks.length - 1].length,
});
return { return {
firstChunk: childArr.slice(0, 100), firstChunk: childArr.slice(0, 100),
extraChunks, extraChunks,
@@ -76,10 +88,18 @@ export abstract class UploadBase {
}, },
}; };
} }
this.debugLog("UploadBase", "Cover applied to payload", {
chosenCover: body.cover?.external?.url ?? null,
defaultBannerUsed: !cover && !!this.plugin.settings.bannerUrl,
});
} }
protected async resolveCoverForUpdate(cover?: string): Promise<string | undefined> { protected async resolveCoverForUpdate(cover?: string): Promise<string | undefined> {
if (cover) { if (cover) {
this.debugLog("UploadBase", "Existing cover retained for update", {
cover,
});
return cover; return cover;
} }
const databaseCover = await this.fetchDatabaseCover(); const databaseCover = await this.fetchDatabaseCover();
@@ -88,6 +108,7 @@ export abstract class UploadBase {
protected async submitPage(body: any, extraChunks: any[][]): Promise<NotionPageResponse> { protected async submitPage(body: any, extraChunks: any[][]): Promise<NotionPageResponse> {
const {notionAPI} = this.dbDetails; const {notionAPI} = this.dbDetails;
const startedAt = Date.now();
const response = await requestUrl({ const response = await requestUrl({
url: `https://api.notion.com/v1/pages`, url: `https://api.notion.com/v1/pages`,
@@ -99,16 +120,22 @@ export abstract class UploadBase {
}, },
body: JSON.stringify(body), body: JSON.stringify(body),
throw: false, throw: false,
}); }).catch((error) =>
this.handleRequestError(error, "Creating Notion page"),
);
const data = await response.json; const data = await response.json;
this.debugLog("UploadBase", "Page creation response received", {
status: response.status,
durationMs: Date.now() - startedAt,
notionUrl: data?.url ?? null,
pageId: data?.id ?? null,
});
if (response.status !== 200) { if (response.status !== 200) {
new Notice(`Error ${data.status}: ${data.code} \n ${i18nConfig["CheckConsole"]}`, 5000); new Notice(`Error ${data.status}: ${data.code} \n ${i18nConfig["CheckConsole"]}`, 5000);
console.log(`Error message: \n ${data.message}`); console.log(`Error message: \n ${data.message}`);
} else { } else {
console.log(`Page created: ${data.url}`);
console.log(`Page ID: ${data.id}`);
if (extraChunks.length > 0) { if (extraChunks.length > 0) {
await this.appendExtraBlocks(data.id, extraChunks); await this.appendExtraBlocks(data.id, extraChunks);
} }
@@ -138,8 +165,6 @@ export abstract class UploadBase {
children: chunk, children: chunk,
}; };
console.log(extraBlocks);
const extraResponse = await requestUrl({ const extraResponse = await requestUrl({
url: `https://api.notion.com/v1/blocks/${pageId}/children`, url: `https://api.notion.com/v1/blocks/${pageId}/children`,
method: "PATCH", method: "PATCH",
@@ -149,7 +174,10 @@ export abstract class UploadBase {
"Notion-Version": "2022-06-28", "Notion-Version": "2022-06-28",
}, },
body: JSON.stringify(extraBlocks), body: JSON.stringify(extraBlocks),
}); throw: false,
}).catch((error) =>
this.handleRequestError(error, `Appending blocks to page ${pageId}`),
);
const extraData: any = await extraResponse.json; const extraData: any = await extraResponse.json;
@@ -175,7 +203,10 @@ export abstract class UploadBase {
Authorization: "Bearer " + notionAPI, Authorization: "Bearer " + notionAPI,
"Notion-Version": "2022-06-28", "Notion-Version": "2022-06-28",
}, },
}); throw: false,
}).catch((error) =>
this.handleRequestError(error, `Fetching database ${databaseID}`),
);
if (response.json.cover && response.json.cover.external) { if (response.json.cover && response.json.cover.external) {
return response.json.cover.external.url; return response.json.cover.external.url;
@@ -183,4 +214,35 @@ export abstract class UploadBase {
return null; return null;
} }
protected debugLog(context: string, message: string, payload?: Record<string, unknown>): void {
if (payload) {
console.log(`[${context}] ${message}`, payload);
} else {
console.log(`[${context}] ${message}`);
}
}
protected maskValue(value?: string, visibleChars = 4): string | undefined {
if (!value) {
return value;
}
if (value.length <= visibleChars * 2) {
return `${value.slice(0, visibleChars)}***`;
}
return `${value.slice(0, visibleChars)}***${value.slice(-visibleChars)}`;
}
private handleRequestError(error: unknown, context: string): never {
const message = error instanceof Error && error.message
? error.message
: String(error);
console.error(`[UploadBase] ${context} failed`, {
message,
error,
});
throw new Error(
`${context} failed: ${message}. Please check your network connection or proxy settings.`,
);
}
} }

View File

@@ -1,12 +1,39 @@
import {i18nConfig} from "../lang/I18n"; import {i18nConfig} from "../lang/I18n";
import {App, Notice} from "obsidian"; import {App, Notice} from "obsidian";
import {Upload2Notion} from "./Upload2Notion"; import {Upload2Notion} from "./Upload2Notion";
import type {NotionPageResponse} from "./common/UploadBase";
import {DatabaseDetails, PluginSettings} from "../ui/settingTabs"; import {DatabaseDetails, PluginSettings} from "../ui/settingTabs";
import ObsidianSyncNotionPlugin from "../main"; import ObsidianSyncNotionPlugin from "../main";
import {getNowFileMarkdownContentNext} from "./common/getMarkdownNext"; import {getNowFileMarkdownContentNext} from "./common/getMarkdownNext";
import {getNowFileMarkdownContentGeneral} from "./common/getMarkdownGeneral"; import {getNowFileMarkdownContentGeneral} from "./common/getMarkdownGeneral";
import {getNowFileMarkdownContentCustom} from "./common/getMarkdownCustom"; import {getNowFileMarkdownContentCustom} from "./common/getMarkdownCustom";
const SYNC_ERROR_NOTICE_DURATION = 8000;
function extractErrorMessage(error: unknown): string {
if (error instanceof Error && error.message) {
return error.message;
}
return String(error);
}
function notifySyncError(prefix: string, basename: string, error: unknown): void {
const errorMessage = extractErrorMessage(error);
console.error(`${prefix} Sync failed`, error);
new Notice(
`${i18nConfig["sync-fail"]} ${basename}. ${errorMessage}\n${i18nConfig["CheckConsole"]}`,
SYNC_ERROR_NOTICE_DURATION,
);
}
function logCommandDebug(context: string, message: string, payload?: Record<string, unknown>): void {
if (payload) {
console.log(`[${context}] ${message}`, payload);
} else {
console.log(`[${context}] ${message}`);
}
}
export async function uploadCommandNext( export async function uploadCommandNext(
plugin: ObsidianSyncNotionPlugin, plugin: ObsidianSyncNotionPlugin,
settings: PluginSettings, settings: PluginSettings,
@@ -38,38 +65,76 @@ export async function uploadCommandNext(
paword, paword,
favicon, favicon,
datetime datetime
} = await getNowFileMarkdownContentNext(app, settings) } = await getNowFileMarkdownContentNext(app, settings);
logCommandDebug("uploadCommandNext", "Metadata extracted from markdown", {
hasMarkdown: !!markDownData,
markdownLength: markDownData?.length ?? 0,
tagCount: tags?.length ?? 0,
coverIncluded: !!cover,
hasEmoji: !!emoji,
type,
slug,
hasPassword: !!paword,
datetime,
});
if (markDownData) { if (markDownData) {
const {basename} = nowFile; const {basename} = nowFile;
logCommandDebug("uploadCommandNext", "Preparing to upload", {
filename: basename,
filePath: nowFile.path,
});
const upload = new Upload2Notion(plugin, dbDetails); const upload = new Upload2Notion(plugin, dbDetails);
const res = await upload.sync({ let res: NotionPageResponse;
dataset: "next", try {
title: basename, res = await upload.sync({
emoji: emoji || "", dataset: "next",
cover: cover || "", title: basename,
tags: tags || [], emoji: emoji || "",
type: type || "", cover: cover || "",
slug: slug || "", tags: tags || [],
stats: stats || "", type: type || "",
category: category || "", slug: slug || "",
summary: summary || "", stats: stats || "",
password: paword || "", category: category || "",
favicon: favicon || "", summary: summary || "",
datetime: datetime || "", password: paword || "",
markdown: markDownData, favicon: favicon || "",
nowFile, datetime: datetime || "",
app, markdown: markDownData,
}); nowFile,
app,
});
} catch (error: unknown) {
notifySyncError("[uploadCommandNext]", basename, error);
logCommandDebug("uploadCommandNext", "Sync threw error", {
filename: basename,
error: extractErrorMessage(error),
});
return;
}
const {response} = res; const {response} = res;
if (response.status === 200) { if (response.status === 200) {
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";
console.log(`${i18nConfig["sync-preffix"]} ${basename} ${i18nConfig["sync-success"]}`);
logCommandDebug("uploadCommandNext", "Sync succeeded", {
filename: basename,
status: response.status,
pageId: res.data?.id ?? null,
pageUrl: res.data?.url ?? null,
});
} else { } else {
new Notice(`${i18nConfig["sync-fail"]} ${basename}`, 5000); new Notice(`${i18nConfig["sync-fail"]} ${basename}`, 5000);
console.log(`${i18nConfig["sync-fail"]} ${basename}`); console.log(`${i18nConfig["sync-fail"]} ${basename}`);
logCommandDebug("uploadCommandNext", "Sync failed with status", {
filename: basename,
status: response.status,
errorCode: res.data?.code ?? null,
errorStatus: res.data?.status ?? null,
});
} }
} }
@@ -100,25 +165,53 @@ export async function uploadCommandGeneral(
if (markDownData) { if (markDownData) {
const {basename} = nowFile; const {basename} = nowFile;
logCommandDebug("uploadCommandGeneral", "Preparing to upload", {
filename: basename,
markdownLength: markDownData.length,
tagCount: tags?.length ?? 0,
hasCover: !!cover,
});
const upload = new Upload2Notion(plugin, dbDetails); const upload = new Upload2Notion(plugin, dbDetails);
const res = await upload.sync({ let res: NotionPageResponse;
dataset: "general", try {
title: basename, res = await upload.sync({
cover: cover || "", dataset: "general",
tags: tags || [], title: basename,
markdown: markDownData, cover: cover || "",
nowFile, tags: tags || [],
app, markdown: markDownData,
}); nowFile,
app,
});
} catch (error: unknown) {
notifySyncError("[uploadCommandGeneral]", basename, error);
logCommandDebug("uploadCommandGeneral", "Sync threw error", {
filename: basename,
error: extractErrorMessage(error),
});
return;
}
const {response} = res; const {response} = res;
if (response.status === 200) { if (response.status === 200) {
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";
console.log(`${i18nConfig["sync-preffix"]} ${basename} ${i18nConfig["sync-success"]}`);
logCommandDebug("uploadCommandGeneral", "Sync succeeded", {
filename: basename,
status: response.status,
pageId: res.data?.id ?? null,
pageUrl: res.data?.url ?? null,
});
} else { } else {
new Notice(`${i18nConfig["sync-fail"]} ${basename}`, 5000); new Notice(`${i18nConfig["sync-fail"]} ${basename}`, 5000);
console.log(`${i18nConfig["sync-fail"]} ${basename}`); console.log(`${i18nConfig["sync-fail"]} ${basename}`);
logCommandDebug("uploadCommandGeneral", "Sync failed with status", {
filename: basename,
status: response.status,
errorCode: res.data?.code ?? null,
errorStatus: res.data?.status ?? null,
});
} }
} }
@@ -149,25 +242,53 @@ export async function uploadCommandCustom(
if (markDownData) { if (markDownData) {
const {basename} = nowFile; const {basename} = nowFile;
logCommandDebug("uploadCommandCustom", "Preparing to upload", {
filename: basename,
markdownLength: markDownData.length,
hasCover: !!cover,
customValueKeys: Object.keys(customValues || {}),
});
const upload = new Upload2Notion(plugin, dbDetails); const upload = new Upload2Notion(plugin, dbDetails);
const res = await upload.sync({ let res: NotionPageResponse;
dataset: "custom", try {
cover: cover || "", res = await upload.sync({
customValues, dataset: "custom",
markdown: markDownData, cover: cover || "",
nowFile, customValues,
app, markdown: markDownData,
}); nowFile,
app,
});
} catch (error: unknown) {
notifySyncError("[uploadCommandCustom]", basename, error);
logCommandDebug("uploadCommandCustom", "Sync threw error", {
filename: basename,
error: extractErrorMessage(error),
});
return;
}
const {response} = res; const {response} = res;
if (response.status === 200) { if (response.status === 200) {
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";
console.log(`${i18nConfig["sync-preffix"]} ${basename} ${i18nConfig["sync-success"]}`);
logCommandDebug("uploadCommandCustom", "Sync succeeded", {
filename: basename,
status: response.status,
pageId: res.data?.id ?? null,
pageUrl: res.data?.url ?? null,
});
} else { } else {
new Notice(`${i18nConfig["sync-fail"]} ${basename}`, 5000); new Notice(`${i18nConfig["sync-fail"]} ${basename}`, 5000);
console.log(`${i18nConfig["sync-fail"]} ${basename}`); console.log(`${i18nConfig["sync-fail"]} ${basename}`);
logCommandDebug("uploadCommandCustom", "Sync failed with status", {
filename: basename,
status: response.status,
errorCode: res.data?.code ?? null,
errorStatus: res.data?.status ?? null,
});
} }
} }

972
yarn.lock

File diff suppressed because it is too large Load Diff