Merge pull request #32 from jxpeng98/long-notes-support

Long notes support
This commit is contained in:
Jiaxin Peng
2024-08-18 22:39:00 +01:00
committed by GitHub
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
- [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 支持一键多数据库上传
- [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

View File

@@ -76,4 +76,7 @@ export const en = {
AddNewProperty: "Add New Property",
AddNewPropertyDesc: "Add new property match with your notion database",
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: "新しいプロパティを追加",
AddNewPropertyDesc: "新しいプロパティを追加してください",
CopyErrorMessage: "自動コピーに失敗しました",
BlockUploaded: "ブロックがアップロードされました",
ExtraBlockUploaded: "追加ブロックがアップロードされました",
CheckConsole: "詳細情報を確認するには、コンソールを開いてください \n opt+cmd+i/ctrl+shift+i",
};

View File

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

View File

@@ -8,6 +8,7 @@ import { DatabaseDetails, PluginSettings } from "../../ui/settingTabs";
import {UploadBaseGeneral} from "./BaseUpload2NotionGeneral";
import {updateYamlInfo} from "../updateYaml";
import fetch from 'node-fetch';
import {i18nConfig} from "../../lang/I18n";
export class Upload2NotionGeneral extends UploadBaseGeneral {
settings: PluginSettings;
@@ -57,6 +58,28 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
notionAPI
} = 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 = {
parent: {
database_id: databaseID,
@@ -81,7 +104,7 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
}
: {}),
},
children: childArr,
children: firstArr,
};
if (cover) {
@@ -115,14 +138,48 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
});
const data: any = await response.json();
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);
console.log(`Error message: \n ${data.message}`);
new Notice(`Error ${data.status}: ${data.code} \n ${i18nConfig["CheckConsole"]}`, 5000);
} else {
console.log(`Page created: ${data.url}`);
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 {
response, // for status code
data // for id and url

View File

@@ -1,22 +1,23 @@
import {UploadBaseNext} from "./BaseUpload2NotionNext";
import {App, Notice, TFile} from "obsidian";
import { Client } from '@notionhq/client';
import { markdownToBlocks, } from "@jxpeng98/martian";
import {Client} from "@notionhq/client";
import {markdownToBlocks} from "@jxpeng98/martian";
import * as yamlFrontMatter from "yaml-front-matter";
// import * as yaml from "yaml"
import MyPlugin from "src/main";
import {DatabaseDetails, PluginSettings} from "../../ui/settingTabs";
import {updateYamlInfo} from "../updateYaml";
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 {
settings: PluginSettings;
dbDetails: DatabaseDetails
dbDetails: DatabaseDetails;
constructor(plugin: MyPlugin, dbDetails: DatabaseDetails) {
super(plugin, dbDetails);
this.dbDetails = dbDetails
this.dbDetails = dbDetails;
}
// 因为需要解析notion的block进行对比非常的麻烦
@@ -35,16 +36,16 @@ export class Upload2NotionNext extends UploadBaseNext {
paword: string,
favicon: 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) {
cover = databaseCover
cover = databaseCover;
}
return await this.createPage(
@@ -60,7 +61,8 @@ export class Upload2NotionNext extends UploadBaseNext {
paword,
favicon,
datetime,
childArr)
childArr,
);
}
async createPage(
@@ -76,16 +78,34 @@ export class Upload2NotionNext extends UploadBaseNext {
pawrod: string,
favicon: string,
datetime: string,
childArr: any
childArr: any,
) {
const {databaseID, notionAPI} = this.dbDetails;
const {
databaseID,
notionAPI
} = this.dbDetails
// 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;
console.log(`Page includes ${childArrLength} blocks`)
const bodyString: any = {
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: {
database_id: databaseID,
},
@@ -94,124 +114,125 @@ export class Upload2NotionNext extends UploadBaseNext {
title: [
{
text: {
content: title
content: title,
},
},
],
},
type: {
select: {
name: type || 'Post'
}
name: type || "Post",
},
},
status: {
select: {
name: stats || 'Draft'
}
name: stats || "Draft",
},
},
category: {
select: {
name: category || 'Obsidian'
}
name: category || "Obsidian",
},
},
password: {
rich_text: [
{
text: {
content: pawrod || ''
}
}
]
content: pawrod || "",
},
},
],
},
icon: {
rich_text: [
{
text: {
content: favicon || ''
}
}
]
content: favicon || "",
},
},
],
},
date: {
date: {
start: datetime || new Date().toISOString()
}
}
start: datetime || new Date().toISOString(),
},
children: childArr,
}
},
},
};
// add tags
if (tags) {
bodyString.properties.tags = {
multi_select: tags.map(tag => {
return { "name": tag }
})
}
pageProperties.properties.tags = {
multi_select: tags.map((tag) => {
return {name: tag};
}),
};
}
// add title icon
if (emoji) {
bodyString.icon = {
emoji: emoji
}
pageProperties.icon = {
emoji: emoji,
};
}
// add slug
if (slug) {
bodyString.properties.slug = {
pageProperties.properties.slug = {
rich_text: [
{
text: {
content: slug
}
}
]
}
content: slug,
},
},
],
};
}
// check if summary is available
if (summary) {
bodyString.properties.summary = {
pageProperties.properties.summary = {
rich_text: [
{
text: {
content: summary
content: summary,
},
},
],
};
}
}
]
}
}
if (cover) {
bodyString.cover = {
pageProperties.cover = {
type: "external",
external: {
url: cover
}
}
url: cover,
},
};
}
if (!bodyString.cover && this.plugin.settings.bannerUrl) {
bodyString.cover = {
if (!pageProperties.cover && this.plugin.settings.bannerUrl) {
pageProperties.cover = {
type: "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", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + notionAPI,
Authorization: "Bearer " + notionAPI,
"Notion-Version": "2022-06-28",
},
body: JSON.stringify(bodyString),
@@ -221,17 +242,56 @@ export class Upload2NotionNext extends UploadBaseNext {
// can use response.ok or response.status === 200
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 {
console.log(`Page created: ${data.url}`);
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 {
response, // for status code
data // for id and url
}
data, // for id and url
};
}
async syncMarkdownToNotionNext(
@@ -254,38 +314,36 @@ export class Upload2NotionNext extends UploadBaseNext {
const options = {
notionLimits: {
truncate: false,
}
}
let res: any
},
};
let res: any;
const yamlContent: any = yamlFrontMatter.loadFront(markdown);
const __content = yamlContent.__content
const __content = yamlContent.__content;
const file2Block = markdownToBlocks(__content, options);
const frontmasster = app.metadataCache.getFileCache(nowFile)?.frontmatter
const { abName } = this.dbDetails
const frontmatter =
app.metadataCache.getFileCache(nowFile)?.frontmatter;
const {abName} = this.dbDetails;
const notionIDKey = `NotionID-${abName}`;
const notionID = frontmasster ? frontmasster[notionIDKey] : null;
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.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)
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)
newParagraphBlocks.push(paragraph(chunk));
});
file2Block.splice(index, 1, ...newParagraphBlocks);
}
})
});
if (notionID) {
res = await this.updatePage(
@@ -302,7 +360,7 @@ export class Upload2NotionNext extends UploadBaseNext {
paword,
favicon,
datetime,
file2Block
file2Block,
);
} else {
res = await this.createPage(
@@ -318,17 +376,23 @@ export class Upload2NotionNext extends UploadBaseNext {
paword,
favicon,
datetime,
file2Block
file2Block,
);
}
let {response, data} = res;
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;
}
}

View File

@@ -7,6 +7,7 @@ import {DatabaseDetails, PluginSettings} from "../../ui/settingTabs";
import {updateYamlInfo} from "../updateYaml";
import {UploadBaseCustom} from "./BaseUpload2NotionCustom";
import fetch from 'node-fetch';
import {i18nConfig} from "../../lang/I18n";
export class Upload2NotionCustom extends UploadBaseCustom {
@@ -53,7 +54,29 @@ export class Upload2NotionCustom extends UploadBaseCustom {
notionAPI
} = 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) {
bodyString.cover = {
@@ -86,14 +109,49 @@ export class Upload2NotionCustom extends UploadBaseCustom {
});
const data: any = await response.json();
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 {
console.log(`Page created: ${data.url}`);
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 {
response, // for status code
data // for id and url
@@ -117,11 +175,11 @@ export class Upload2NotionCustom extends UploadBaseCustom {
const yamlContent: any = yamlFrontMatter.loadFront(markdown);
const __content = yamlContent.__content;
const file2Block = markdownToBlocks(__content, options);
const frontmasster =
const frontMatter =
app.metadataCache.getFileCache(nowFile)?.frontmatter;
const {abName} = this.dbDetails
const notionIDKey = `NotionID-${abName}`;
const notionID = frontmasster ? frontmasster[notionIDKey] : null;
const notionID = frontMatter ? frontMatter[notionIDKey] : null;
if (notionID) {
res = await this.updatePage(