Compare commits

...

8 Commits
2.3.5 ... 2.4.1

Author SHA1 Message Date
Jiaxin Peng
bc166d8db1 Update version to 2.4.1 2024-08-28 20:31:28 +01:00
Jiaxin Peng
7612637951 Merge pull request #34 from jxpeng98/code-highlight-issue
fix code highlight issue
2024-08-28 20:30:49 +01:00
Jiaxin Peng
e8b1617916 fix item type error for iteration 2024-08-28 20:30:05 +01:00
Jiaxin Peng
fd29ed820e fix code highlight issue 2024-08-28 20:26:06 +01:00
Jiaxin Peng
1f58670906 Update version to 2.4.0 2024-08-19 11:24:23 +01:00
Jiaxin Peng
fc47d36e8d Merge pull request #32 from jxpeng98/long-notes-support
Long notes support
2024-08-18 22:39:00 +01:00
Jiaxin Peng
cd4e610c46 modify type of pageProperties 2024-08-18 18:42:59 +01:00
Jiaxin Peng
b05c248c44 feat: support long notes syncing 2024-08-18 17:16:08 +01:00
11 changed files with 555 additions and 327 deletions

View File

@@ -1,4 +1,4 @@
## Improvements ## Fix
- update the Markdown parser to ensure that no extra `\\` is added to the end of the line when having equations in the Markdown file - Fix code block not being highlighted in Notion after syncing.
- 输入公式的时候,不会在公式后面加上多余的`\\`符号 - 修复代码块同步之后,在 Notion 中未高亮的问题。

View File

@@ -9,27 +9,28 @@
[//]: # ([中文文档](README-zh.md)) [//]: # ([中文文档](README-zh.md))
**Now, support both NotionNext and General databases with customised properties.** **Now, support All Notion databases, including NotionNext and General Notion databases, and customise the database list.**
**现在支持NotionNext和普通Notion数据库自定义数据库列表。** **现在支持所有Notion数据库包括NotionNext和一般Notion数据库以及自定义数据库列表。**
## Precautions ## Precautions
### For customised database users ### For customised database users before version 2.3.0
**⚠️⚠️⚠️: The existing customised database should be recreated if you want to update to version 2.3.0. The new version has a new database structure, and the old database structure is not compatible with the new version to build the index properly.** **⚠️⚠️⚠️: The existing customised database should be recreated if you want to update to version 2.3.0. The new version has a new database structure, and the old database structure is not compatible with the new version to build the index properly.**
### 自定义数据库用户 ### 在2.3.0版本之前的自定义数据库用户
**⚠️⚠️⚠️: 如果你想要更新到2.3.0版本,你需要重新创建自定义数据库。新版本有一个新的数据库结构,旧的数据库结构无法构建索引。** **⚠️⚠️⚠️: 如果你想要更新到2.3.0版本,你需要重新创建自定义数据库。新版本有一个新的数据库结构,旧的数据库结构无法构建索引。**
## 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 (From `v2.4.0`). 从`v2.4.0`开始支持长笔记同步
- [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

@@ -1,7 +1,7 @@
{ {
"id": "share-to-notionnext", "id": "share-to-notionnext",
"name": "Share to NotionNext", "name": "Share to NotionNext",
"version": "2.3.5", "version": "2.4.1",
"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,8 +1,8 @@
{ {
"name": "share-to-notionnext", "name": "share-to-notionnext",
"version": "2.3.5", "version": "2.4.1",
"type": "module", "type": "module",
"description": "Shares obsidian md file to notion with notion api for NotionNext web deploy, 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",

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,41 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
notionAPI notionAPI
} = this.dbDetails; } = this.dbDetails;
// remove the annotations from the childArr if type is code block
childArr.forEach((block: any) => {
if (block.type === "code") {
block.code.rich_text.forEach((item: any) => {
if (item.type === "text" && item.annotations) {
delete item.annotations;
}
}
);
}
}
);
// 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 +112,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 +151,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 +218,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,22 +1,23 @@
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进行对比非常的麻烦
@@ -35,16 +36,16 @@ export class Upload2NotionNext extends UploadBaseNext {
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(
@@ -60,7 +61,8 @@ export class Upload2NotionNext extends UploadBaseNext {
paword, paword,
favicon, favicon,
datetime, datetime,
childArr) childArr,
);
} }
async createPage( async createPage(
@@ -76,16 +78,47 @@ export class Upload2NotionNext extends UploadBaseNext {
pawrod: string, pawrod: string,
favicon: string, favicon: string,
datetime: string, datetime: string,
childArr: any childArr: any,
) { ) {
const {databaseID, notionAPI} = this.dbDetails;
const { // remove the annotations from the childArr if type is code block
databaseID, childArr.forEach((block: any) => {
notionAPI if (block.type === "code") {
} = this.dbDetails block.code.rich_text.forEach((item: any) => {
if (item.type === "text" && item.annotations) {
delete item.annotations;
}
}
);
}
}
);
// check the length of the childArr
// if it is too long, split it into multiple pages
const childArrLength = childArr.length;
let extraArr: any[] = [];
let firstArr: any;
let pushCount = 0;
const bodyString: any = { 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 pageProperties: any = {
parent: { parent: {
database_id: databaseID, database_id: databaseID,
}, },
@@ -94,124 +127,125 @@ export class Upload2NotionNext extends UploadBaseNext {
title: [ title: [
{ {
text: { text: {
content: title content: title,
}, },
}, },
], ],
}, },
type: { type: {
select: { select: {
name: type || 'Post' name: type || "Post",
} },
}, },
status: { status: {
select: { select: {
name: stats || 'Draft' name: stats || "Draft",
} },
}, },
category: { category: {
select: { select: {
name: category || 'Obsidian' name: category || "Obsidian",
} },
}, },
password: { password: {
rich_text: [ rich_text: [
{ {
text: { text: {
content: pawrod || '' content: pawrod || "",
} },
} },
] ],
}, },
icon: { icon: {
rich_text: [ rich_text: [
{ {
text: { text: {
content: favicon || '' content: favicon || "",
} },
} },
] ],
}, },
date: { date: {
date: { date: {
start: datetime || new Date().toISOString() start: datetime || new Date().toISOString(),
}
}
}, },
children: childArr, },
} },
};
// add tags // add tags
if (tags) { if (tags) {
bodyString.properties.tags = { pageProperties.properties.tags = {
multi_select: tags.map(tag => { multi_select: tags.map((tag) => {
return { "name": tag } return {name: tag};
}) }),
} };
} }
// add title icon // add title icon
if (emoji) { if (emoji) {
bodyString.icon = { pageProperties.icon = {
emoji: emoji emoji: emoji,
} };
} }
// add slug // add slug
if (slug) { if (slug) {
bodyString.properties.slug = { pageProperties.properties.slug = {
rich_text: [ rich_text: [
{ {
text: { text: {
content: slug content: slug,
} },
} },
] ],
} };
} }
// check if summary is available // check if summary is available
if (summary) { if (summary) {
bodyString.properties.summary = { pageProperties.properties.summary = {
rich_text: [ rich_text: [
{ {
text: { text: {
content: summary content: summary,
},
},
],
};
} }
}
]
}
}
if (cover) { if (cover) {
bodyString.cover = { pageProperties.cover = {
type: "external", type: "external",
external: { external: {
url: cover url: cover,
} },
} };
} }
if (!bodyString.cover && this.plugin.settings.bannerUrl) { if (!pageProperties.cover && this.plugin.settings.bannerUrl) {
bodyString.cover = { pageProperties.cover = {
type: "external", type: "external",
external: { external: {
url: this.plugin.settings.bannerUrl url: this.plugin.settings.bannerUrl,
} },
} };
} }
console.log(bodyString) const bodyString: any = {
...pageProperties,
children: firstArr,
};
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,17 +255,56 @@ 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( async syncMarkdownToNotionNext(
@@ -254,38 +327,36 @@ export class Upload2NotionNext extends UploadBaseNext {
const options = { const options = {
notionLimits: { notionLimits: {
truncate: false, truncate: false,
} },
} };
let res: any let res: any;
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 = app.metadataCache.getFileCache(nowFile)?.frontmatter const frontmatter =
const { abName } = this.dbDetails app.metadataCache.getFileCache(nowFile)?.frontmatter;
const {abName} = this.dbDetails;
const notionIDKey = `NotionID-${abName}`; const notionIDKey = `NotionID-${abName}`;
const notionID = frontmasster ? frontmasster[notionIDKey] : null; const notionID = frontmatter ? frontmatter[notionIDKey] : null;
// increase the limits // increase the limits
// Motivated by https://github.com/tryfabric/martian/issues/51 // Motivated by https://github.com/tryfabric/martian/issues/51
file2Block.forEach((block, index) => { file2Block.forEach((block, index) => {
if ( if (
block.type === 'paragraph' && block.type === "paragraph" &&
block.paragraph.rich_text.length > LIMITS.RICH_TEXT_ARRAYS block.paragraph.rich_text.length > LIMITS.RICH_TEXT_ARRAYS
) { ) {
const newParagraphBlocks: any[] = [];
const newParagraphBlocks: any[] = [] const chunk: any = [];
const chunk: any = [] const richTextChunks = chunk(block.paragraph.rich_text, 100);
const richTextChunks = chunk(block.paragraph.rich_text, 100)
richTextChunks.forEach((chunk: any) => { richTextChunks.forEach((chunk: any) => {
newParagraphBlocks.push(paragraph(chunk)) newParagraphBlocks.push(paragraph(chunk));
}) });
file2Block.splice(index, 1, ...newParagraphBlocks)
file2Block.splice(index, 1, ...newParagraphBlocks);
} }
}) });
if (notionID) { if (notionID) {
res = await this.updatePage( res = await this.updatePage(
@@ -302,7 +373,7 @@ export class Upload2NotionNext extends UploadBaseNext {
paword, paword,
favicon, favicon,
datetime, datetime,
file2Block file2Block,
); );
} else { } else {
res = await this.createPage( res = await this.createPage(
@@ -318,17 +389,23 @@ export class Upload2NotionNext extends UploadBaseNext {
paword, paword,
favicon, favicon,
datetime, datetime,
file2Block 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,42 @@ export class Upload2NotionCustom extends UploadBaseCustom {
notionAPI notionAPI
} = this.dbDetails; } = this.dbDetails;
const bodyString: any = this.buildBodyString(customProperties, customValues, childArr); // remove the annotations from the childArr if type is code block
childArr.forEach((block: any) => {
if (block.type === "code") {
block.code.rich_text.forEach((item: any) => {
if (item.type === "text" && item.annotations) {
delete item.annotations;
}
}
);
}
}
);
// 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 +122,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 +188,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(