mirror of
https://github.com/jxpeng98/obsidian-to-NotionNext
synced 2026-07-29 08:08:34 +08:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3218eb9fba | ||
|
|
48566eca20 | ||
|
|
8bd8346423 | ||
|
|
00411e9599 | ||
|
|
296125f6b4 | ||
|
|
1b385ccd0a | ||
|
|
a90e4871bb | ||
|
|
885ccba027 | ||
|
|
f282dde1b7 | ||
|
|
bc166d8db1 | ||
|
|
7612637951 | ||
|
|
e8b1617916 | ||
|
|
fd29ed820e | ||
|
|
1f58670906 | ||
|
|
fc47d36e8d | ||
|
|
cd4e610c46 | ||
|
|
b05c248c44 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -20,4 +20,7 @@ data.json
|
||||
|
||||
# Exclude macOS Finder (System Explorer) View States
|
||||
.DS_Store
|
||||
.history
|
||||
.history
|
||||
|
||||
# local data
|
||||
local-data
|
||||
|
||||
@@ -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 a bug that plugin does not work when Obsidian language is not set to Englisht, Chinese or Japanese.
|
||||
- 修复了当 Obsidian 语言设置不是英文、中文或日文时插件无法工作的问题。
|
||||
|
||||
17
README.md
17
README.md
@@ -9,27 +9,28 @@
|
||||
|
||||
[//]: # ([中文文档](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
|
||||
|
||||
### 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.**
|
||||
|
||||
### 自定义数据库用户
|
||||
### 在2.3.0版本之前的自定义数据库用户
|
||||
|
||||
**⚠️⚠️⚠️: 如果你想要更新到2.3.0版本,你需要重新创建自定义数据库。新版本有一个新的数据库结构,旧的数据库结构无法构建索引。**
|
||||
|
||||
## 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 支持一键多数据库上传
|
||||
- [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
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "share-to-notionnext",
|
||||
"name": "Share to NotionNext",
|
||||
"version": "2.3.5",
|
||||
"version": "2.4.2",
|
||||
"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.",
|
||||
"author": "EasyChris, jxpeng98",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "share-to-notionnext",
|
||||
"version": "2.3.5",
|
||||
"version": "2.4.2",
|
||||
"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",
|
||||
"scripts": {
|
||||
"dev": "node esbuild.config.mjs",
|
||||
@@ -27,7 +27,6 @@
|
||||
"@jxpeng98/martian": "^1.2.7",
|
||||
"https-proxy-agent": "^7.0.2",
|
||||
"node-fetch": "^3.3.2",
|
||||
"process": "^0.11.10",
|
||||
"remark-math": "^6.0.0",
|
||||
"yaml": "^2.3.4",
|
||||
"yaml-front-matter": "^4.1.1"
|
||||
|
||||
@@ -8,10 +8,42 @@ export const I18n: {[key: string]:any} = {
|
||||
ja,
|
||||
};
|
||||
|
||||
export const I18nConfig = (lang: string): any => {
|
||||
return I18n[lang];
|
||||
};
|
||||
class I18nManager {
|
||||
private currentLanguage: string;
|
||||
|
||||
const storedLanguage = window.localStorage.getItem("language");
|
||||
constructor() {
|
||||
this.currentLanguage = this.detectLanguage();
|
||||
}
|
||||
|
||||
export const i18nConfig = I18n[storedLanguage || window.navigator.language.split('-')[0] || "en"];
|
||||
// return the language to use
|
||||
private detectLanguage(): string {
|
||||
const storedLanguage = window.localStorage.getItem("language");
|
||||
if (storedLanguage && this.isLanguageSupported(storedLanguage)) {
|
||||
console.log(`Using stored language: ${storedLanguage}`);
|
||||
return storedLanguage;
|
||||
}
|
||||
|
||||
const browserLanguage = window.navigator.language.split("-")[0];
|
||||
if (this.isLanguageSupported(browserLanguage)) {
|
||||
console.log(`Using browser language: ${browserLanguage}`);
|
||||
return browserLanguage;
|
||||
}
|
||||
|
||||
// Default to English if no match is found
|
||||
console.log("Using default language: en");
|
||||
return "en";
|
||||
}
|
||||
|
||||
private isLanguageSupported(lang: string): boolean {
|
||||
return Object.prototype.hasOwnProperty.call(I18n, lang);
|
||||
}
|
||||
|
||||
// Get the i18n configuration for the current language
|
||||
public getConfig(): any {
|
||||
return I18n[this.currentLanguage];
|
||||
}
|
||||
}
|
||||
|
||||
export const i18nManager = new I18nManager();
|
||||
|
||||
export const i18nConfig = i18nManager.getConfig();
|
||||
|
||||
@@ -76,4 +76,8 @@ 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",
|
||||
"reach-mobile-limit": "The number of blocks exceeds the limit of 100, please use the desktop plugin",
|
||||
}
|
||||
|
||||
@@ -68,4 +68,7 @@ export const ja = {
|
||||
AddNewProperty: "新しいプロパティを追加",
|
||||
AddNewPropertyDesc: "新しいプロパティを追加してください",
|
||||
CopyErrorMessage: "自動コピーに失敗しました",
|
||||
BlockUploaded: "ブロックがアップロードされました",
|
||||
ExtraBlockUploaded: "追加ブロックがアップロードされました",
|
||||
CheckConsole: "詳細情報を確認するには、コンソールを開いてください \n opt+cmd+i/ctrl+shift+i",
|
||||
};
|
||||
|
||||
@@ -71,4 +71,7 @@ export const zh = {
|
||||
AddNewProperty: "添加新属性",
|
||||
AddNewPropertyDesc: "添加一个和Notion数据库匹配的新属性",
|
||||
CopyErrorMessage: "复制链接失败,请手动复制",
|
||||
BlockUploaded: "所有内容已成功上传",
|
||||
ExtraBlockUploaded: "额外内容已成功上传",
|
||||
CheckConsole: "opt+cmd+i/ctrl+shift+i,\n打开控制台查看更多信息",
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
|
||||
|
||||
addIcons();
|
||||
// This creates an icon in the left ribbon.
|
||||
const ribbonIconEl = this.addRibbonIcon(
|
||||
this.addRibbonIcon(
|
||||
"notion-logo",
|
||||
i18nConfig.ribbonIcon,
|
||||
async (evt: MouseEvent) => {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { i18nConfig } from "../lang/I18n";
|
||||
import { App, Notice } from "obsidian";
|
||||
import { Upload2NotionNext } from "./upload_next/Upload2NotionNext";
|
||||
import { Upload2NotionGeneral } from "./upload_general/Upload2NotionGeneral";
|
||||
import { Upload2NotionCustom } from "./upoload_custom/Upload2NotionCustom";
|
||||
import { DatabaseDetails, PluginSettings } from "../ui/settingTabs";
|
||||
import {i18nConfig} from "../lang/I18n";
|
||||
import {App, Notice} from "obsidian";
|
||||
import {Upload2NotionNext} from "./upload_next/Upload2NotionNext";
|
||||
import {Upload2NotionGeneral} from "./upload_general/Upload2NotionGeneral";
|
||||
import {Upload2NotionCustom} from "./upoload_custom/Upload2NotionCustom";
|
||||
import {DatabaseDetails, PluginSettings} from "../ui/settingTabs";
|
||||
import ObsidianSyncNotionPlugin from "../main";
|
||||
import { getNowFileMarkdownContentNext } from "./upload_next/getMarkdownNext";
|
||||
import { getNowFileMarkdownContentGeneral } from "./upload_general/getMarkdownGeneral";
|
||||
import { getNowFileMarkdownContentCustom } from "./upoload_custom/getMarkdownCustom";
|
||||
import {getNowFileMarkdownContentNext} from "./upload_next/getMarkdownNext";
|
||||
import {getNowFileMarkdownContentGeneral} from "./upload_general/getMarkdownGeneral";
|
||||
import {getNowFileMarkdownContentCustom} from "./upoload_custom/getMarkdownCustom";
|
||||
|
||||
export async function uploadCommandNext(
|
||||
plugin: ObsidianSyncNotionPlugin,
|
||||
@@ -16,7 +16,7 @@ export async function uploadCommandNext(
|
||||
app: App,
|
||||
) {
|
||||
|
||||
const { notionAPI, databaseID } = dbDetails;
|
||||
const {notionAPI, databaseID} = dbDetails;
|
||||
|
||||
// Check if the user has set up the Notion API and database ID
|
||||
if (notionAPI === "" || databaseID === "") {
|
||||
@@ -42,12 +42,12 @@ export async function uploadCommandNext(
|
||||
} = await getNowFileMarkdownContentNext(app, settings)
|
||||
|
||||
if (markDownData) {
|
||||
const { basename } = nowFile;
|
||||
const {basename} = nowFile;
|
||||
|
||||
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 { response } = res;
|
||||
const {response} = res;
|
||||
if (response.status === 200) {
|
||||
new Notice(`${i18nConfig["sync-preffix"]} ${basename} ${i18nConfig["sync-success"]}`).noticeEl.style.color = "green";
|
||||
} else {
|
||||
@@ -65,7 +65,7 @@ export async function uploadCommandGeneral(
|
||||
app: App,
|
||||
) {
|
||||
|
||||
const { notionAPI, databaseID } = dbDetails;
|
||||
const {notionAPI, databaseID} = dbDetails;
|
||||
|
||||
// Check if the user has set up the Notion API and database ID
|
||||
if (notionAPI === "" || databaseID === "") {
|
||||
@@ -74,15 +74,18 @@ export async function uploadCommandGeneral(
|
||||
return;
|
||||
}
|
||||
|
||||
const { markDownData, nowFile, cover, tags } = await getNowFileMarkdownContentGeneral(app, settings)
|
||||
const {markDownData, nowFile, cover, tags} = await getNowFileMarkdownContentGeneral(app, settings)
|
||||
|
||||
new Notice(`Start upload ${nowFile.basename}`);
|
||||
console.log(`Start upload ${nowFile.basename}`);
|
||||
|
||||
if (markDownData) {
|
||||
const { basename } = nowFile;
|
||||
const {basename} = nowFile;
|
||||
|
||||
const upload = new Upload2NotionGeneral(plugin, dbDetails);
|
||||
const res = await upload.syncMarkdownToNotionGeneral(basename, cover, tags, markDownData, nowFile, this.app);
|
||||
|
||||
const { response } = res;
|
||||
const {response} = res;
|
||||
if (response.status === 200) {
|
||||
new Notice(`${i18nConfig["sync-preffix"]} ${basename} ${i18nConfig["sync-success"]}`).noticeEl.style.color = "green";
|
||||
} else {
|
||||
@@ -100,7 +103,7 @@ export async function uploadCommandCustom(
|
||||
app: App,
|
||||
) {
|
||||
|
||||
const { notionAPI, databaseID } = settings;
|
||||
const {notionAPI, databaseID} = settings;
|
||||
|
||||
// Check if the user has set up the Notion API and database ID
|
||||
if (notionAPI === "" || databaseID === "") {
|
||||
@@ -109,15 +112,18 @@ export async function uploadCommandCustom(
|
||||
return;
|
||||
}
|
||||
|
||||
const { markDownData, nowFile, cover, customValues } = await getNowFileMarkdownContentCustom(app, dbDetails)
|
||||
const {markDownData, nowFile, cover, customValues} = await getNowFileMarkdownContentCustom(app, dbDetails)
|
||||
|
||||
new Notice(`Start upload ${nowFile.basename}`);
|
||||
console.log(`Start upload ${nowFile.basename}`);
|
||||
|
||||
if (markDownData) {
|
||||
const { basename } = nowFile;
|
||||
const {basename} = nowFile;
|
||||
|
||||
const upload = new Upload2NotionCustom(plugin, dbDetails);
|
||||
const res = await upload.syncMarkdownToNotionCustom(cover, customValues, markDownData, nowFile, this.app);
|
||||
|
||||
const { response } = res;
|
||||
const {response} = res;
|
||||
if (response.status === 200) {
|
||||
new Notice(`${i18nConfig["sync-preffix"]} ${basename} ${i18nConfig["sync-success"]}`).noticeEl.style.color = "green";
|
||||
} else {
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import { App, Notice, TFile } from "obsidian";
|
||||
import { Client } from "@notionhq/client";
|
||||
import { markdownToBlocks } from "@jxpeng98/martian";
|
||||
import {App, Notice, TFile, Platform, requestUrl} from "obsidian";
|
||||
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 { UploadBaseGeneral } from "./BaseUpload2NotionGeneral";
|
||||
import { updateYamlInfo } from "../updateYaml";
|
||||
import {DatabaseDetails, PluginSettings} from "../../ui/settingTabs";
|
||||
import {UploadBaseGeneral} from "./BaseUpload2NotionGeneral";
|
||||
import {updateYamlInfo} from "../updateYaml";
|
||||
import fetch from 'node-fetch';
|
||||
import {i18nConfig} from "../../lang/I18n";
|
||||
|
||||
interface CreatePageResponse {
|
||||
response: any;
|
||||
data: any;
|
||||
}
|
||||
|
||||
export class Upload2NotionGeneral extends UploadBaseGeneral {
|
||||
settings: PluginSettings;
|
||||
@@ -29,7 +33,7 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
|
||||
) {
|
||||
await this.deletePage(notionID);
|
||||
|
||||
const { databaseID } = this.dbDetails;
|
||||
const {databaseID} = this.dbDetails;
|
||||
|
||||
const databaseCover = await this.getDataBase(
|
||||
databaseID,
|
||||
@@ -47,7 +51,7 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
|
||||
cover: string,
|
||||
tags: string[],
|
||||
childArr: any,
|
||||
) {
|
||||
): Promise<CreatePageResponse> {
|
||||
|
||||
const {
|
||||
databaseID,
|
||||
@@ -57,6 +61,41 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
|
||||
notionAPI
|
||||
} = 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 = {
|
||||
parent: {
|
||||
database_id: databaseID,
|
||||
@@ -76,12 +115,12 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
|
||||
...(tagButton
|
||||
? {
|
||||
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) {
|
||||
@@ -103,29 +142,89 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
|
||||
}
|
||||
|
||||
console.log(bodyString)
|
||||
console.log(Platform.isDesktopApp)
|
||||
|
||||
const response = await fetch("https://api.notion.com/v1/pages", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer " + notionAPI,
|
||||
"Notion-Version": "2022-06-28",
|
||||
},
|
||||
body: JSON.stringify(bodyString),
|
||||
});
|
||||
let response: any;
|
||||
let data: any;
|
||||
|
||||
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}`);
|
||||
} else {
|
||||
console.log(`Page created: ${data.url}`);
|
||||
console.log(`Page ID: ${data.id}`);
|
||||
if (Platform.isMobileApp) {
|
||||
if(childArrLength > 100) {
|
||||
new Notice(i18nConfig["reach-mobile-limit"], 5000);
|
||||
} else {
|
||||
response = await requestUrl({
|
||||
url: `https://api.notion.com/v1/pages`,
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
// 'User-Agent': 'obsidian.md',
|
||||
Authorization:
|
||||
"Bearer " + notionAPI,
|
||||
"Notion-Version": "2022-06-28",
|
||||
},
|
||||
body: JSON.stringify(bodyString),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (Platform.isDesktopApp) {
|
||||
response = await fetch("https://api.notion.com/v1/pages", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer " + notionAPI,
|
||||
"Notion-Version": "2022-06-28",
|
||||
},
|
||||
body: JSON.stringify(bodyString),
|
||||
});
|
||||
|
||||
data = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
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
|
||||
response,
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,11 +245,11 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
|
||||
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 {abName} = this.dbDetails
|
||||
const notionIDKey = `NotionID-${abName}`;
|
||||
const notionID = frontmasster ? frontmasster[notionIDKey] : null;
|
||||
const notionID = frontMatter ? frontMatter[notionIDKey] : null;
|
||||
|
||||
|
||||
if (notionID) {
|
||||
@@ -167,10 +266,30 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
|
||||
|
||||
let {response, data} = res;
|
||||
|
||||
// console.log(response)
|
||||
if (Platform.isDesktopApp) {
|
||||
if (response && response.status === 200) {
|
||||
await updateYamlInfo(
|
||||
markdown,
|
||||
nowFile,
|
||||
data,
|
||||
app,
|
||||
this.plugin,
|
||||
this.dbDetails
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (response && response.status === 200) {
|
||||
await updateYamlInfo(markdown, nowFile, data, app, this.plugin, this.dbDetails);
|
||||
if (Platform.isMobileApp) {
|
||||
if (response && response.status === 200) {
|
||||
await updateYamlInfo(
|
||||
markdown,
|
||||
nowFile,
|
||||
response,
|
||||
app,
|
||||
this.plugin,
|
||||
this.dbDetails,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -1,334 +1,447 @@
|
||||
import { UploadBaseNext } from "./BaseUpload2NotionNext";
|
||||
import { App, Notice, TFile } from "obsidian";
|
||||
import { Client } from '@notionhq/client';
|
||||
import { markdownToBlocks, } from "@jxpeng98/martian";
|
||||
import {UploadBaseNext} from "./BaseUpload2NotionNext";
|
||||
import {App, Notice, TFile, Platform, requestUrl} from "obsidian";
|
||||
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 {DatabaseDetails, PluginSettings} from "../../ui/settingTabs";
|
||||
import {updateYamlInfo} from "../updateYaml";
|
||||
import {LIMITS, paragraph} from "@jxpeng98/martian/src/notion";
|
||||
import fetch from 'node-fetch';
|
||||
import {i18nConfig} from "../../lang/I18n";
|
||||
|
||||
interface CreatePageResponse {
|
||||
response: any;
|
||||
data: any;
|
||||
}
|
||||
|
||||
export class Upload2NotionNext extends UploadBaseNext {
|
||||
settings: PluginSettings;
|
||||
dbDetails: DatabaseDetails
|
||||
settings: PluginSettings;
|
||||
dbDetails: DatabaseDetails;
|
||||
|
||||
constructor(plugin: MyPlugin, dbDetails: DatabaseDetails) {
|
||||
super(plugin, dbDetails);
|
||||
this.dbDetails = dbDetails
|
||||
}
|
||||
constructor(plugin: MyPlugin, dbDetails: DatabaseDetails) {
|
||||
super(plugin, dbDetails);
|
||||
this.dbDetails = dbDetails;
|
||||
}
|
||||
|
||||
// 因为需要解析notion的block进行对比,非常的麻烦,
|
||||
// 暂时就直接删除,新建一个page
|
||||
async updatePage(
|
||||
notionID: string,
|
||||
title: string,
|
||||
emoji: string,
|
||||
cover: string,
|
||||
tags: string[],
|
||||
type: string,
|
||||
slug: string,
|
||||
stats: string,
|
||||
category: string,
|
||||
summary: string,
|
||||
paword: string,
|
||||
favicon: string,
|
||||
datetime: string,
|
||||
childArr: any
|
||||
) {
|
||||
await this.deletePage(notionID)
|
||||
// 因为需要解析notion的block进行对比,非常的麻烦,
|
||||
// 暂时就直接删除,新建一个page
|
||||
async updatePage(
|
||||
notionID: string,
|
||||
title: string,
|
||||
emoji: string,
|
||||
cover: string,
|
||||
tags: string[],
|
||||
type: string,
|
||||
slug: string,
|
||||
stats: string,
|
||||
category: string,
|
||||
summary: string,
|
||||
paword: string,
|
||||
favicon: string,
|
||||
datetime: string,
|
||||
childArr: any,
|
||||
) {
|
||||
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
|
||||
}
|
||||
if (cover == null) {
|
||||
cover = databaseCover;
|
||||
}
|
||||
|
||||
return await this.createPage(
|
||||
title,
|
||||
emoji,
|
||||
cover,
|
||||
tags,
|
||||
type,
|
||||
slug,
|
||||
stats,
|
||||
category,
|
||||
summary,
|
||||
paword,
|
||||
favicon,
|
||||
datetime,
|
||||
childArr)
|
||||
}
|
||||
return await this.createPage(
|
||||
title,
|
||||
emoji,
|
||||
cover,
|
||||
tags,
|
||||
type,
|
||||
slug,
|
||||
stats,
|
||||
category,
|
||||
summary,
|
||||
paword,
|
||||
favicon,
|
||||
datetime,
|
||||
childArr,
|
||||
);
|
||||
}
|
||||
|
||||
async createPage(
|
||||
title: string,
|
||||
emoji: string,
|
||||
cover: string,
|
||||
tags: string[],
|
||||
type: string,
|
||||
slug: string,
|
||||
stats: string,
|
||||
category: string,
|
||||
summary: string,
|
||||
pawrod: string,
|
||||
favicon: string,
|
||||
datetime: string,
|
||||
childArr: any
|
||||
) {
|
||||
async createPage(
|
||||
title: string,
|
||||
emoji: string,
|
||||
cover: string,
|
||||
tags: string[],
|
||||
type: string,
|
||||
slug: string,
|
||||
stats: string,
|
||||
category: string,
|
||||
summary: string,
|
||||
pawrod: string,
|
||||
favicon: string,
|
||||
datetime: string,
|
||||
childArr: any,
|
||||
): Promise<CreatePageResponse> {
|
||||
const {databaseID, notionAPI} = this.dbDetails;
|
||||
|
||||
const {
|
||||
databaseID,
|
||||
notionAPI
|
||||
} = 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
|
||||
// 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 = {
|
||||
parent: {
|
||||
database_id: databaseID,
|
||||
},
|
||||
properties: {
|
||||
title: {
|
||||
title: [
|
||||
{
|
||||
text: {
|
||||
content: title
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
type: {
|
||||
select: {
|
||||
name: type || 'Post'
|
||||
}
|
||||
},
|
||||
status: {
|
||||
select: {
|
||||
name: stats || 'Draft'
|
||||
}
|
||||
},
|
||||
category: {
|
||||
select: {
|
||||
name: category || 'Obsidian'
|
||||
}
|
||||
},
|
||||
console.log(`Page includes ${childArrLength} blocks`)
|
||||
|
||||
password: {
|
||||
rich_text: [
|
||||
{
|
||||
text: {
|
||||
content: pawrod || ''
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
icon: {
|
||||
rich_text: [
|
||||
{
|
||||
text: {
|
||||
content: favicon || ''
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
date: {
|
||||
date: {
|
||||
start: datetime || new Date().toISOString()
|
||||
}
|
||||
}
|
||||
},
|
||||
children: childArr,
|
||||
}
|
||||
|
||||
// add tags
|
||||
if (tags) {
|
||||
bodyString.properties.tags = {
|
||||
multi_select: tags.map(tag => {
|
||||
return { "name": tag }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// add title icon
|
||||
if (emoji) {
|
||||
bodyString.icon = {
|
||||
emoji: emoji
|
||||
}
|
||||
}
|
||||
|
||||
// add slug
|
||||
if (slug) {
|
||||
bodyString.properties.slug = {
|
||||
rich_text: [
|
||||
{
|
||||
text: {
|
||||
content: slug
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// check if summary is available
|
||||
if (summary) {
|
||||
bodyString.properties.summary = {
|
||||
rich_text: [
|
||||
{
|
||||
text: {
|
||||
content: summary
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (cover) {
|
||||
bodyString.cover = {
|
||||
type: "external",
|
||||
external: {
|
||||
url: cover
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bodyString.cover && this.plugin.settings.bannerUrl) {
|
||||
bodyString.cover = {
|
||||
type: "external",
|
||||
external: {
|
||||
url: this.plugin.settings.bannerUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(bodyString)
|
||||
|
||||
const response = await fetch("https://api.notion.com/v1/pages", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer " + notionAPI,
|
||||
"Notion-Version": "2022-06-28",
|
||||
},
|
||||
body: JSON.stringify(bodyString),
|
||||
});
|
||||
|
||||
const data: any = await response.json();
|
||||
|
||||
// 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);
|
||||
console.log(`Error message: \n ${data.message}`);
|
||||
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 {
|
||||
console.log(`Page created: ${data.url}`);
|
||||
console.log(`Page ID: ${data.id}`);
|
||||
firstArr = childArr;
|
||||
}
|
||||
|
||||
const pageProperties: any = {
|
||||
parent: {
|
||||
database_id: databaseID,
|
||||
},
|
||||
properties: {
|
||||
title: {
|
||||
title: [
|
||||
{
|
||||
text: {
|
||||
content: title,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
type: {
|
||||
select: {
|
||||
name: type || "Post",
|
||||
},
|
||||
},
|
||||
status: {
|
||||
select: {
|
||||
name: stats || "Draft",
|
||||
},
|
||||
},
|
||||
category: {
|
||||
select: {
|
||||
name: category || "Obsidian",
|
||||
},
|
||||
},
|
||||
|
||||
password: {
|
||||
rich_text: [
|
||||
{
|
||||
text: {
|
||||
content: pawrod || "",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
icon: {
|
||||
rich_text: [
|
||||
{
|
||||
text: {
|
||||
content: favicon || "",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
date: {
|
||||
date: {
|
||||
start: datetime || new Date().toISOString(),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// add tags
|
||||
if (tags) {
|
||||
pageProperties.properties.tags = {
|
||||
multi_select: tags.map((tag) => {
|
||||
return {name: tag};
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
// add title icon
|
||||
if (emoji) {
|
||||
pageProperties.icon = {
|
||||
emoji: emoji,
|
||||
};
|
||||
}
|
||||
|
||||
// add slug
|
||||
if (slug) {
|
||||
pageProperties.properties.slug = {
|
||||
rich_text: [
|
||||
{
|
||||
text: {
|
||||
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,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const bodyString: any = {
|
||||
...pageProperties,
|
||||
children: firstArr,
|
||||
};
|
||||
|
||||
console.log(bodyString);
|
||||
|
||||
let response: any;
|
||||
let data: any;
|
||||
|
||||
if (Platform.isMobileApp) {
|
||||
if(childArrLength > 100) {
|
||||
new Notice(i18nConfig["reach-mobile-limit"], 5000);
|
||||
} else {
|
||||
response = await requestUrl({
|
||||
url: `https://api.notion.com/v1/pages`,
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
// 'User-Agent': 'obsidian.md',
|
||||
Authorization:
|
||||
"Bearer " + notionAPI,
|
||||
"Notion-Version": "2022-06-28",
|
||||
},
|
||||
body: JSON.stringify(bodyString),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (Platform.isDesktopApp) {
|
||||
response = await fetch("https://api.notion.com/v1/pages", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer " + notionAPI,
|
||||
"Notion-Version": "2022-06-28",
|
||||
},
|
||||
body: JSON.stringify(bodyString),
|
||||
});
|
||||
|
||||
data = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
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
|
||||
response,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (response && response.status === 200) {
|
||||
await updateYamlInfo(markdown, nowFile, data, app, this.plugin, this.dbDetails);
|
||||
if (Platform.isDesktopApp) {
|
||||
if (response && response.status === 200) {
|
||||
await updateYamlInfo(
|
||||
markdown,
|
||||
nowFile,
|
||||
data,
|
||||
app,
|
||||
this.plugin,
|
||||
this.dbDetails
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (Platform.isMobileApp) {
|
||||
if (response && response.status === 200) {
|
||||
await updateYamlInfo(
|
||||
markdown,
|
||||
nowFile,
|
||||
response,
|
||||
app,
|
||||
this.plugin,
|
||||
this.dbDetails,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
import {App, Notice, TFile} from "obsidian";
|
||||
import {App, Notice, Platform, TFile, requestUrl} from "obsidian";
|
||||
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 {UploadBaseCustom} from "./BaseUpload2NotionCustom";
|
||||
import fetch from 'node-fetch';
|
||||
import {i18nConfig} from "../../lang/I18n";
|
||||
|
||||
|
||||
interface CreatePageResponse {
|
||||
response: any;
|
||||
data: any;
|
||||
}
|
||||
|
||||
export class Upload2NotionCustom extends UploadBaseCustom {
|
||||
settings: PluginSettings;
|
||||
dbDetails: DatabaseDetails;
|
||||
@@ -45,7 +50,7 @@ export class Upload2NotionCustom extends UploadBaseCustom {
|
||||
cover: string,
|
||||
customValues: Record<string, string>,
|
||||
childArr: any,
|
||||
) {
|
||||
): Promise<CreatePageResponse> {
|
||||
|
||||
const {
|
||||
databaseID,
|
||||
@@ -53,7 +58,42 @@ export class Upload2NotionCustom extends UploadBaseCustom {
|
||||
notionAPI
|
||||
} = 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) {
|
||||
bodyString.cover = {
|
||||
@@ -74,24 +114,84 @@ export class Upload2NotionCustom extends UploadBaseCustom {
|
||||
}
|
||||
|
||||
console.log(bodyString)
|
||||
console.log(Platform.isDesktopApp)
|
||||
|
||||
const response = await fetch("https://api.notion.com/v1/pages", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer " + notionAPI,
|
||||
"Notion-Version": "2022-06-28",
|
||||
},
|
||||
body: JSON.stringify(bodyString),
|
||||
});
|
||||
let response: any;
|
||||
let data: any;
|
||||
|
||||
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}`);
|
||||
} else {
|
||||
console.log(`Page created: ${data.url}`);
|
||||
console.log(`Page ID: ${data.id}`);
|
||||
if (Platform.isMobileApp) {
|
||||
if(childArrLength > 100) {
|
||||
new Notice(i18nConfig["reach-mobile-limit"], 5000);
|
||||
} else {
|
||||
response = await requestUrl({
|
||||
url: `https://api.notion.com/v1/pages`,
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
// 'User-Agent': 'obsidian.md',
|
||||
Authorization:
|
||||
"Bearer " + notionAPI,
|
||||
"Notion-Version": "2022-06-28",
|
||||
},
|
||||
body: JSON.stringify(bodyString),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (Platform.isDesktopApp) {
|
||||
response = await fetch("https://api.notion.com/v1/pages", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer " + notionAPI,
|
||||
"Notion-Version": "2022-06-28",
|
||||
},
|
||||
body: JSON.stringify(bodyString),
|
||||
});
|
||||
|
||||
data = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
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 {
|
||||
@@ -117,11 +217,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(
|
||||
@@ -138,8 +238,30 @@ export class Upload2NotionCustom extends UploadBaseCustom {
|
||||
|
||||
// console.log(response)
|
||||
|
||||
if (response && response.status === 200) {
|
||||
await updateYamlInfo(markdown, nowFile, data, app, this.plugin, this.dbDetails);
|
||||
if (Platform.isDesktopApp) {
|
||||
if (response && response.status === 200) {
|
||||
await updateYamlInfo(
|
||||
markdown,
|
||||
nowFile,
|
||||
data,
|
||||
app,
|
||||
this.plugin,
|
||||
this.dbDetails
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (Platform.isMobileApp) {
|
||||
if (response && response.status === 200) {
|
||||
await updateYamlInfo(
|
||||
markdown,
|
||||
nowFile,
|
||||
response,
|
||||
app,
|
||||
this.plugin,
|
||||
this.dbDetails,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -1245,11 +1245,6 @@ picomatch@^2.3.1:
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
|
||||
process@^0.11.10:
|
||||
version "0.11.10"
|
||||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||
integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
|
||||
|
||||
queue-microtask@^1.2.2:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
||||
|
||||
Reference in New Issue
Block a user