feat: support long notes syncing

This commit is contained in:
Jiaxin Peng
2024-08-18 17:16:08 +01:00
parent 800e218dee
commit b05c248c44
9 changed files with 514 additions and 321 deletions

View File

@@ -1,4 +1,8 @@
## Improvements ## Features
- Support WebP format images. 支持 WebP 格式图片。
- Support sync with long notes. 支持长文章同步。
Long articles or notes have been split into multiple parts, and the parts are synchronized in order.
长文章同步是通过将长文章或笔记拆分为多个部分,按顺序同步这些部分。
- update the Markdown parser to ensure that no extra `\\` is added to the end of the line when having equations in the Markdown file
- 输入公式的时候,不会在公式后面加上多余的`\\`符号

View File

@@ -25,11 +25,12 @@
## TODO List ## TODO List
- [x] ~~Modify the Edit function for the custom properties. 改进自定义属性的编辑功能~~ - [x] Modify the Edit function for the custom properties. 改进自定义属性的编辑功能
- [x] Support sync with long notes. 支持长文章同步
- [x] Support custom properties for Notion General database. 支持自定义属性
- [x] Support preview for database details in plugin settings. 支持预览数据库详情
- [x] Support edit for database details in plugin settings. 支持编辑数据库详情
- [ ] Support group upload with one click 支持一键多数据库上传 - [ ] Support group upload with one click 支持一键多数据库上传
- [x] ~~Support custom properties for Notion General database. 支持自定义属性~~
- [x] ~~Support preview for database details in plugin settings. 支持预览数据库详情~~
- [x] ~~Support edit for database details in plugin settings. 支持编辑数据库详情~~
## How to use ## How to use

View File

@@ -76,4 +76,7 @@ export const en = {
AddNewProperty: "Add New Property", AddNewProperty: "Add New Property",
AddNewPropertyDesc: "Add new property match with your notion database", AddNewPropertyDesc: "Add new property match with your notion database",
CopyErrorMessage: "Auto copy failed, please copy it manually", CopyErrorMessage: "Auto copy failed, please copy it manually",
BlockUploaded: "All blocks uploaded",
ExtraBlockUploaded: "Extra blocks uploaded",
CheckConsole: "Check the console for more information \n opt+cmd+i/ctrl+shift+i",
} }

View File

@@ -68,4 +68,7 @@ export const ja = {
AddNewProperty: "新しいプロパティを追加", AddNewProperty: "新しいプロパティを追加",
AddNewPropertyDesc: "新しいプロパティを追加してください", AddNewPropertyDesc: "新しいプロパティを追加してください",
CopyErrorMessage: "自動コピーに失敗しました", CopyErrorMessage: "自動コピーに失敗しました",
BlockUploaded: "ブロックがアップロードされました",
ExtraBlockUploaded: "追加ブロックがアップロードされました",
CheckConsole: "詳細情報を確認するには、コンソールを開いてください \n opt+cmd+i/ctrl+shift+i",
}; };

View File

@@ -71,4 +71,7 @@ export const zh = {
AddNewProperty: "添加新属性", AddNewProperty: "添加新属性",
AddNewPropertyDesc: "添加一个和Notion数据库匹配的新属性", AddNewPropertyDesc: "添加一个和Notion数据库匹配的新属性",
CopyErrorMessage: "复制链接失败,请手动复制", CopyErrorMessage: "复制链接失败,请手动复制",
BlockUploaded: "所有内容已成功上传",
ExtraBlockUploaded: "额外内容已成功上传",
CheckConsole: "opt+cmd+i/ctrl+shift+i\n打开控制台查看更多信息",
} }

View File

@@ -1,13 +1,13 @@
import { i18nConfig } from "../lang/I18n"; import {i18nConfig} from "../lang/I18n";
import { App, Notice } from "obsidian"; import {App, Notice} from "obsidian";
import { Upload2NotionNext } from "./upload_next/Upload2NotionNext"; import {Upload2NotionNext} from "./upload_next/Upload2NotionNext";
import { Upload2NotionGeneral } from "./upload_general/Upload2NotionGeneral"; import {Upload2NotionGeneral} from "./upload_general/Upload2NotionGeneral";
import { Upload2NotionCustom } from "./upoload_custom/Upload2NotionCustom"; import {Upload2NotionCustom} from "./upoload_custom/Upload2NotionCustom";
import { DatabaseDetails, PluginSettings } from "../ui/settingTabs"; import {DatabaseDetails, PluginSettings} from "../ui/settingTabs";
import ObsidianSyncNotionPlugin from "../main"; import ObsidianSyncNotionPlugin from "../main";
import { getNowFileMarkdownContentNext } from "./upload_next/getMarkdownNext"; import {getNowFileMarkdownContentNext} from "./upload_next/getMarkdownNext";
import { getNowFileMarkdownContentGeneral } from "./upload_general/getMarkdownGeneral"; import {getNowFileMarkdownContentGeneral} from "./upload_general/getMarkdownGeneral";
import { getNowFileMarkdownContentCustom } from "./upoload_custom/getMarkdownCustom"; import {getNowFileMarkdownContentCustom} from "./upoload_custom/getMarkdownCustom";
export async function uploadCommandNext( export async function uploadCommandNext(
plugin: ObsidianSyncNotionPlugin, plugin: ObsidianSyncNotionPlugin,
@@ -16,7 +16,7 @@ export async function uploadCommandNext(
app: App, app: App,
) { ) {
const { notionAPI, databaseID } = dbDetails; const {notionAPI, databaseID} = dbDetails;
// Check if the user has set up the Notion API and database ID // Check if the user has set up the Notion API and database ID
if (notionAPI === "" || databaseID === "") { if (notionAPI === "" || databaseID === "") {
@@ -42,12 +42,12 @@ export async function uploadCommandNext(
} = await getNowFileMarkdownContentNext(app, settings) } = await getNowFileMarkdownContentNext(app, settings)
if (markDownData) { if (markDownData) {
const { basename } = nowFile; const {basename} = nowFile;
const upload = new Upload2NotionNext(plugin, dbDetails); const upload = new Upload2NotionNext(plugin, dbDetails);
const res = await upload.syncMarkdownToNotionNext(basename, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, markDownData, nowFile, this.app); const res = await upload.syncMarkdownToNotionNext(basename, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, markDownData, nowFile, this.app);
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";
} else { } else {
@@ -65,7 +65,7 @@ export async function uploadCommandGeneral(
app: App, app: App,
) { ) {
const { notionAPI, databaseID } = dbDetails; const {notionAPI, databaseID} = dbDetails;
// Check if the user has set up the Notion API and database ID // Check if the user has set up the Notion API and database ID
if (notionAPI === "" || databaseID === "") { if (notionAPI === "" || databaseID === "") {
@@ -74,15 +74,15 @@ export async function uploadCommandGeneral(
return; return;
} }
const { markDownData, nowFile, cover, tags } = await getNowFileMarkdownContentGeneral(app, settings) const {markDownData, nowFile, cover, tags} = await getNowFileMarkdownContentGeneral(app, settings)
if (markDownData) { if (markDownData) {
const { basename } = nowFile; const {basename} = nowFile;
const upload = new Upload2NotionGeneral(plugin, dbDetails); const upload = new Upload2NotionGeneral(plugin, dbDetails);
const res = await upload.syncMarkdownToNotionGeneral(basename, cover, tags, markDownData, nowFile, this.app); const res = await upload.syncMarkdownToNotionGeneral(basename, cover, tags, markDownData, nowFile, this.app);
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";
} else { } else {
@@ -100,7 +100,7 @@ export async function uploadCommandCustom(
app: App, app: App,
) { ) {
const { notionAPI, databaseID } = settings; const {notionAPI, databaseID} = settings;
// Check if the user has set up the Notion API and database ID // Check if the user has set up the Notion API and database ID
if (notionAPI === "" || databaseID === "") { if (notionAPI === "" || databaseID === "") {
@@ -109,15 +109,15 @@ export async function uploadCommandCustom(
return; return;
} }
const { markDownData, nowFile, cover, customValues } = await getNowFileMarkdownContentCustom(app, dbDetails) const {markDownData, nowFile, cover, customValues} = await getNowFileMarkdownContentCustom(app, dbDetails)
if (markDownData) { if (markDownData) {
const { basename } = nowFile; const {basename} = nowFile;
const upload = new Upload2NotionCustom(plugin, dbDetails); const upload = new Upload2NotionCustom(plugin, dbDetails);
const res = await upload.syncMarkdownToNotionCustom(cover, customValues, markDownData, nowFile, this.app); const res = await upload.syncMarkdownToNotionCustom(cover, customValues, markDownData, nowFile, this.app);
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";
} else { } else {

View File

@@ -1,13 +1,14 @@
import { App, Notice, TFile } from "obsidian"; import {App, Notice, TFile} from "obsidian";
import { Client } from "@notionhq/client"; import {Client} from "@notionhq/client";
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 * as yaml from "yaml" // import * as yaml from "yaml"
import MyPlugin from "src/main"; import MyPlugin from "src/main";
import { DatabaseDetails, PluginSettings } from "../../ui/settingTabs"; import {DatabaseDetails, PluginSettings} from "../../ui/settingTabs";
import { UploadBaseGeneral } from "./BaseUpload2NotionGeneral"; import {UploadBaseGeneral} from "./BaseUpload2NotionGeneral";
import { updateYamlInfo } from "../updateYaml"; import {updateYamlInfo} from "../updateYaml";
import fetch from 'node-fetch'; import fetch from 'node-fetch';
import {i18nConfig} from "../../lang/I18n";
export class Upload2NotionGeneral extends UploadBaseGeneral { export class Upload2NotionGeneral extends UploadBaseGeneral {
settings: PluginSettings; settings: PluginSettings;
@@ -29,7 +30,7 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
) { ) {
await this.deletePage(notionID); await this.deletePage(notionID);
const { databaseID } = this.dbDetails; const {databaseID} = this.dbDetails;
const databaseCover = await this.getDataBase( const databaseCover = await this.getDataBase(
databaseID, databaseID,
@@ -57,6 +58,28 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
notionAPI notionAPI
} = this.dbDetails; } = this.dbDetails;
// check the length of the childArr and split it into chunks of 100
const childArrLength = childArr.length;
let extraArr: any[] = [];
let firstArr: any;
let pushCount = 0;
console.log(`Page includes ${childArrLength} blocks`)
if (childArrLength > 100) {
for (let i = 0; i < childArr.length; i += 100) {
if (i == 0) {
firstArr = childArr.slice(0, 100);
} else {
const chunk = childArr.slice(i, i + 100);
extraArr.push(chunk);
pushCount++;
}
}
} else {
firstArr = childArr;
}
const bodyString: any = { const bodyString: any = {
parent: { parent: {
database_id: databaseID, database_id: databaseID,
@@ -76,12 +99,12 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
...(tagButton ...(tagButton
? { ? {
tags: { tags: {
multi_select: tags && true ? tags.map((tag) => ({ name: tag })) : [], multi_select: tags && true ? tags.map((tag) => ({name: tag})) : [],
}, },
} }
: {}), : {}),
}, },
children: childArr, children: firstArr,
}; };
if (cover) { if (cover) {
@@ -115,14 +138,48 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
}); });
const data: any = await response.json(); const data: any = await response.json();
if (!response.ok) { if (!response.ok) {
new Notice(`Error ${data.status}: ${data.code} \n Check the console for more information \n opt+cmd+i/ctrl+shift+i`, 5000); new Notice(`Error ${data.status}: ${data.code} \n ${i18nConfig["CheckConsole"]}`, 5000);
console.log(`Error message: \n ${data.message}`);
} else { } else {
console.log(`Page created: ${data.url}`); console.log(`Page created: ${data.url}`);
console.log(`Page ID: ${data.id}`); console.log(`Page ID: ${data.id}`);
} }
// upload the rest of the blocks
if (pushCount > 0) {
for (let i = 0; i < pushCount; i++) {
const extraBlocks = {
children: extraArr[i],
};
console.log(extraBlocks)
const extraResponse = await fetch(`https://api.notion.com/v1/blocks/${data.id}/children`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + notionAPI,
"Notion-Version": "2022-06-28",
},
body: JSON.stringify(extraBlocks),
});
const extraData: any = await extraResponse.json();
if (!extraResponse.ok) {
new Notice(`Error ${extraData.status}: ${extraData.code} \n ${i18nConfig["CheckConsole"]}`, 5000);
console.log(`Error message: \n ${extraData.message}`);
} else {
console.log(`${i18nConfig["ExtraBlockUploaded"]} to page: ${data.id}`);
if (i === pushCount - 1) {
console.log(`${i18nConfig["BlockUploaded"]} to page: ${data.id}`);
new Notice(`${i18nConfig["BlockUploaded"]} page: ${data.id}`, 5000);
}
}
}
}
return { return {
response, // for status code response, // for status code
data // for id and url data // for id and url
@@ -148,7 +205,7 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
const file2Block = markdownToBlocks(__content, options); const file2Block = markdownToBlocks(__content, options);
const frontmasster = const frontmasster =
app.metadataCache.getFileCache(nowFile)?.frontmatter; app.metadataCache.getFileCache(nowFile)?.frontmatter;
const { abName } = this.dbDetails const {abName} = this.dbDetails
const notionIDKey = `NotionID-${abName}`; const notionIDKey = `NotionID-${abName}`;
const notionID = frontmasster ? frontmasster[notionIDKey] : null; const notionID = frontmasster ? frontmasster[notionIDKey] : null;

View File

@@ -1,217 +1,238 @@
import { UploadBaseNext } from "./BaseUpload2NotionNext"; import {UploadBaseNext} from "./BaseUpload2NotionNext";
import { App, Notice, TFile } from "obsidian"; import {App, Notice, TFile} from "obsidian";
import { Client } from '@notionhq/client'; import {Client} from "@notionhq/client";
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 * as yaml from "yaml" // import * as yaml from "yaml"
import MyPlugin from "src/main"; import MyPlugin from "src/main";
import { DatabaseDetails, PluginSettings } from "../../ui/settingTabs"; import {DatabaseDetails, PluginSettings} from "../../ui/settingTabs";
import { updateYamlInfo } from "../updateYaml"; import {updateYamlInfo} from "../updateYaml";
import { LIMITS, paragraph } from "@jxpeng98/martian/src/notion"; import {LIMITS, paragraph} from "@jxpeng98/martian/src/notion";
import fetch from 'node-fetch'; import fetch from "node-fetch";
import {i18nConfig} from "../../lang/I18n";
export class Upload2NotionNext extends UploadBaseNext { export class Upload2NotionNext extends UploadBaseNext {
settings: PluginSettings; settings: PluginSettings;
dbDetails: DatabaseDetails dbDetails: DatabaseDetails;
constructor(plugin: MyPlugin, dbDetails: DatabaseDetails) { constructor(plugin: MyPlugin, dbDetails: DatabaseDetails) {
super(plugin, dbDetails); super(plugin, dbDetails);
this.dbDetails = dbDetails this.dbDetails = dbDetails;
} }
// 因为需要解析notion的block进行对比非常的麻烦 // 因为需要解析notion的block进行对比非常的麻烦
// 暂时就直接删除新建一个page // 暂时就直接删除新建一个page
async updatePage( async updatePage(
notionID: string, notionID: string,
title: string, title: string,
emoji: string, emoji: string,
cover: string, cover: string,
tags: string[], tags: string[],
type: string, type: string,
slug: string, slug: string,
stats: string, stats: string,
category: string, category: string,
summary: string, summary: string,
paword: string, paword: string,
favicon: string, favicon: string,
datetime: string, datetime: string,
childArr: any childArr: any,
) { ) {
await this.deletePage(notionID) await this.deletePage(notionID);
const { databaseID } = this.dbDetails const {databaseID} = this.dbDetails;
const databaseCover = await this.getDataBase(databaseID) const databaseCover = await this.getDataBase(databaseID);
if (cover == null) { if (cover == null) {
cover = databaseCover cover = databaseCover;
} }
return await this.createPage( return await this.createPage(
title, title,
emoji, emoji,
cover, cover,
tags, tags,
type, type,
slug, slug,
stats, stats,
category, category,
summary, summary,
paword, paword,
favicon, favicon,
datetime, datetime,
childArr) childArr,
} );
}
async createPage( async createPage(
title: string, title: string,
emoji: string, emoji: string,
cover: string, cover: string,
tags: string[], tags: string[],
type: string, type: string,
slug: string, slug: string,
stats: string, stats: string,
category: string, category: string,
summary: string, summary: string,
pawrod: string, pawrod: string,
favicon: string, favicon: string,
datetime: string, datetime: string,
childArr: any childArr: any,
) { ) {
const {databaseID, notionAPI} = this.dbDetails;
const { // check the length of the childArr
databaseID, // if it is too long, split it into multiple pages
notionAPI const childArrLength = childArr.length;
} = this.dbDetails let extraArr: any[] = [];
let firstArr: any;
let pushCount = 0;
console.log(`Page includes ${childArrLength} blocks`)
const bodyString: any = { if (childArrLength > 100) {
parent: { for (let i = 0; i < childArr.length; i += 100) {
database_id: databaseID, if (i == 0) {
}, firstArr = childArr.slice(0, 100);
properties: { } else {
title: { const chunk = childArr.slice(i, i + 100);
title: [ extraArr.push(chunk);
{ pushCount++;
text: { }
content: title }
}, } else {
}, firstArr = childArr;
], }
},
type: {
select: {
name: type || 'Post'
}
},
status: {
select: {
name: stats || 'Draft'
}
},
category: {
select: {
name: category || 'Obsidian'
}
},
password: { const pageProperties = {
rich_text: [ parent: {
{ database_id: databaseID,
text: { },
content: pawrod || '' properties: {
} title: {
} title: [
] {
}, text: {
icon: { content: title,
rich_text: [ },
{ },
text: { ],
content: favicon || '' },
} type: {
} select: {
] name: type || "Post",
}, },
date: { },
date: { status: {
start: datetime || new Date().toISOString() select: {
} name: stats || "Draft",
} },
}, },
children: childArr, category: {
} select: {
name: category || "Obsidian",
},
},
// add tags password: {
if (tags) { rich_text: [
bodyString.properties.tags = { {
multi_select: tags.map(tag => { text: {
return { "name": tag } content: pawrod || "",
}) },
} },
} ],
},
icon: {
rich_text: [
{
text: {
content: favicon || "",
},
},
],
},
date: {
date: {
start: datetime || new Date().toISOString(),
},
},
},
};
// add title icon // add tags
if (emoji) { if (tags) {
bodyString.icon = { pageProperties.properties.tags = {
emoji: emoji multi_select: tags.map((tag) => {
} return {name: tag};
} }),
};
}
// add slug // add title icon
if (slug) { if (emoji) {
bodyString.properties.slug = { pageProperties.icon = {
rich_text: [ emoji: emoji,
{ };
text: { }
content: slug
}
}
]
}
}
// check if summary is available // add slug
if (summary) { if (slug) {
bodyString.properties.summary = { pageProperties.properties.slug = {
rich_text: [ rich_text: [
{ {
text: { text: {
content: summary content: slug,
} },
} },
] ],
} };
} }
// check if summary is available
if (summary) {
pageProperties.properties.summary = {
rich_text: [
{
text: {
content: summary,
},
},
],
};
}
if (cover) {
pageProperties.cover = {
type: "external",
external: {
url: cover,
},
};
}
if (!pageProperties.cover && this.plugin.settings.bannerUrl) {
pageProperties.cover = {
type: "external",
external: {
url: this.plugin.settings.bannerUrl,
},
};
}
if (cover) { const bodyString: any = {
bodyString.cover = { ...pageProperties,
type: "external", children: firstArr,
external: { };
url: cover
}
}
}
if (!bodyString.cover && this.plugin.settings.bannerUrl) { console.log(bodyString);
bodyString.cover = {
type: "external",
external: {
url: this.plugin.settings.bannerUrl
}
}
}
console.log(bodyString)
const response = await fetch("https://api.notion.com/v1/pages", { const response = await fetch("https://api.notion.com/v1/pages", {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
"Authorization": "Bearer " + notionAPI, Authorization: "Bearer " + notionAPI,
"Notion-Version": "2022-06-28", "Notion-Version": "2022-06-28",
}, },
body: JSON.stringify(bodyString), body: JSON.stringify(bodyString),
@@ -221,114 +242,157 @@ export class Upload2NotionNext extends UploadBaseNext {
// can use response.ok or response.status === 200 // can use response.ok or response.status === 200
if (!response.ok) { if (!response.ok) {
new Notice(`Error ${data.status}: ${data.code} \n Check the console for more information \n opt+cmd+i/ctrl+shift+i`, 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 created: ${data.url}`);
console.log(`Page ID: ${data.id}`); console.log(`Page ID: ${data.id}`);
} }
// if the childArr is over 100, patch the rest of the blocks append to the page
if (pushCount > 0) {
for (let i = 0; i < pushCount; i++) {
const extraBlocks = {
children: extraArr[i]
}
console.log(extraBlocks)
const extraResponse = await fetch(
`https://api.notion.com/v1/blocks/${data.id}/children`,
{
method: "PATCH",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + notionAPI,
"Notion-Version": "2022-06-28",
},
body: JSON.stringify(extraBlocks),
});
const extraData: any = await extraResponse.json();
if (!extraResponse.ok) {
new Notice(
`Extra Block: Error ${extraData.status}: ${extraData.code} \n ${i18nConfig["CheckConsole"]}`,
5000,
);
console.log(`Error message: \n ${extraData.message}`);
} else {
console.log(`${i18nConfig["ExtraBlockUploaded"]} to page: ${data.id}`);
if (i === pushCount - 1) {
console.log(`${i18nConfig["BlockUploaded"]} to page: ${data.id}`);
new Notice(`${i18nConfig["BlockUploaded"]} page: ${data.id}`, 5000);
}
}
}
}
return { return {
response, // for status code response, // for status code
data // for id and url data, // for id and url
};
}
async syncMarkdownToNotionNext(
title: string,
emoji: string,
cover: string,
tags: string[],
type: string,
slug: string,
stats: string,
category: string,
summary: string,
paword: string,
favicon: string,
datetime: string,
markdown: string,
nowFile: TFile,
app: App,
): Promise<any> {
const options = {
notionLimits: {
truncate: false,
},
};
let res: any;
const yamlContent: any = yamlFrontMatter.loadFront(markdown);
const __content = yamlContent.__content;
const file2Block = markdownToBlocks(__content, options);
const frontmatter =
app.metadataCache.getFileCache(nowFile)?.frontmatter;
const {abName} = this.dbDetails;
const notionIDKey = `NotionID-${abName}`;
const notionID = frontmatter ? frontmatter[notionIDKey] : null;
// increase the limits
// Motivated by https://github.com/tryfabric/martian/issues/51
file2Block.forEach((block, index) => {
if (
block.type === "paragraph" &&
block.paragraph.rich_text.length > LIMITS.RICH_TEXT_ARRAYS
) {
const newParagraphBlocks: any[] = [];
const chunk: any = [];
const richTextChunks = chunk(block.paragraph.rich_text, 100);
richTextChunks.forEach((chunk: any) => {
newParagraphBlocks.push(paragraph(chunk));
});
file2Block.splice(index, 1, ...newParagraphBlocks);
}
});
if (notionID) {
res = await this.updatePage(
notionID,
title,
emoji,
cover,
tags,
type,
slug,
stats,
category,
summary,
paword,
favicon,
datetime,
file2Block,
);
} else {
res = await this.createPage(
title,
emoji,
cover,
tags,
type,
slug,
stats,
category,
summary,
paword,
favicon,
datetime,
file2Block,
);
} }
}
async syncMarkdownToNotionNext(
title: string,
emoji: string,
cover: string,
tags: string[],
type: string,
slug: string,
stats: string,
category: string,
summary: string,
paword: string,
favicon: string,
datetime: string,
markdown: string,
nowFile: TFile,
app: App,
): Promise<any> {
const options = {
notionLimits: {
truncate: false,
}
}
let res: any
const yamlContent: any = yamlFrontMatter.loadFront(markdown);
const __content = yamlContent.__content
const file2Block = markdownToBlocks(__content, options);
const frontmasster = app.metadataCache.getFileCache(nowFile)?.frontmatter
const { abName } = this.dbDetails
const notionIDKey = `NotionID-${abName}`;
const notionID = frontmasster ? frontmasster[notionIDKey] : null;
// increase the limits
// Motivated by https://github.com/tryfabric/martian/issues/51
file2Block.forEach((block, index) => {
if (
block.type === 'paragraph' &&
block.paragraph.rich_text.length > LIMITS.RICH_TEXT_ARRAYS
) {
const newParagraphBlocks: any[] = []
const chunk: any = []
const richTextChunks = chunk(block.paragraph.rich_text, 100)
richTextChunks.forEach((chunk: any) => {
newParagraphBlocks.push(paragraph(chunk))
})
file2Block.splice(index, 1, ...newParagraphBlocks)
}
})
if (notionID) {
res = await this.updatePage(
notionID,
title,
emoji,
cover,
tags,
type,
slug,
stats,
category,
summary,
paword,
favicon,
datetime,
file2Block
);
} else {
res = await this.createPage(
title,
emoji,
cover,
tags,
type,
slug,
stats,
category,
summary,
paword,
favicon,
datetime,
file2Block
);
}
let {response, data} = res; let {response, data} = res;
if (response && response.status === 200) { if (response && response.status === 200) {
await updateYamlInfo(markdown, nowFile, data, app, this.plugin, this.dbDetails); await updateYamlInfo(
markdown,
nowFile,
data,
app,
this.plugin,
this.dbDetails,
);
} }
return res; return res;
} }
} }

View File

@@ -7,6 +7,7 @@ import {DatabaseDetails, PluginSettings} from "../../ui/settingTabs";
import {updateYamlInfo} from "../updateYaml"; import {updateYamlInfo} from "../updateYaml";
import {UploadBaseCustom} from "./BaseUpload2NotionCustom"; import {UploadBaseCustom} from "./BaseUpload2NotionCustom";
import fetch from 'node-fetch'; import fetch from 'node-fetch';
import {i18nConfig} from "../../lang/I18n";
export class Upload2NotionCustom extends UploadBaseCustom { export class Upload2NotionCustom extends UploadBaseCustom {
@@ -53,7 +54,29 @@ export class Upload2NotionCustom extends UploadBaseCustom {
notionAPI notionAPI
} = this.dbDetails; } = this.dbDetails;
const bodyString: any = this.buildBodyString(customProperties, customValues, childArr); // check the length of the childArr and split it into chunks of 100
const childArrLength = childArr.length;
let extraArr: any[] = [];
let firstArr: any;
let pushCount = 0;
console.log(`Page includes ${childArrLength} blocks`)
if (childArrLength > 100) {
for (let i = 0; i < childArr.length; i += 100) {
if (i == 0) {
firstArr = childArr.slice(0, 100);
} else {
const chunk = childArr.slice(i, i + 100);
extraArr.push(chunk);
pushCount++;
}
}
} else {
firstArr = childArr;
}
const bodyString: any = this.buildBodyString(customProperties, customValues, firstArr);
if (cover) { if (cover) {
bodyString.cover = { bodyString.cover = {
@@ -86,14 +109,49 @@ export class Upload2NotionCustom extends UploadBaseCustom {
}); });
const data: any = await response.json(); const data: any = await response.json();
if (!response.ok) { if (!response.ok) {
new Notice(`Error ${data.status}: ${data.code} \n Check the console for more information \n opt+cmd+i/ctrl+shift+i`, 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 created: ${data.url}`);
console.log(`Page ID: ${data.id}`); console.log(`Page ID: ${data.id}`);
} }
// upload the rest of the blocks
if (pushCount > 0) {
for (let i = 0; i < pushCount; i++) {
const extraBlocks = {
children: extraArr[i],
};
console.log(extraBlocks)
const extraResponse = await fetch(`https://api.notion.com/v1/blocks/${data.id}/children`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + notionAPI,
"Notion-Version": "2022-06-28",
},
body: JSON.stringify(extraBlocks),
});
const extraData: any = await extraResponse.json();
if (!extraResponse.ok) {
new Notice(`Error ${extraData.status}: ${extraData.code} \n ${i18nConfig["CheckConsole"]}`, 5000);
console.log(`Error message: \n ${extraData.message}`);
} else {
console.log(`${i18nConfig["ExtraBlockUploaded"]} to page: ${data.id}`);
if (i === pushCount - 1) {
console.log(`${i18nConfig["BlockUploaded"]} to page: ${data.id}`);
new Notice(`${i18nConfig["BlockUploaded"]} page: ${data.id}`, 5000);
}
}
}
}
return { return {
response, // for status code response, // for status code
data // for id and url data // for id and url
@@ -117,11 +175,11 @@ export class Upload2NotionCustom extends UploadBaseCustom {
const yamlContent: any = yamlFrontMatter.loadFront(markdown); const yamlContent: any = yamlFrontMatter.loadFront(markdown);
const __content = yamlContent.__content; const __content = yamlContent.__content;
const file2Block = markdownToBlocks(__content, options); const file2Block = markdownToBlocks(__content, options);
const frontmasster = const frontMatter =
app.metadataCache.getFileCache(nowFile)?.frontmatter; app.metadataCache.getFileCache(nowFile)?.frontmatter;
const {abName} = this.dbDetails const {abName} = this.dbDetails
const notionIDKey = `NotionID-${abName}`; const notionIDKey = `NotionID-${abName}`;
const notionID = frontmasster ? frontmasster[notionIDKey] : null; const notionID = frontMatter ? frontMatter[notionIDKey] : null;
if (notionID) { if (notionID) {
res = await this.updatePage( res = await this.updatePage(