Compare commits

...

17 Commits
2.3.5 ... 2.4.2

Author SHA1 Message Date
Jiaxin Peng
3218eb9fba Update version to 2.4.2 2024-09-19 13:50:51 +01:00
Jiaxin Peng
48566eca20 Merge pull request #37 from jxpeng98/pluggin-does-not-appear-on-mac
fix: obsidian language not set in English, Chinese and Japanese
2024-09-19 13:49:08 +01:00
Jiaxin Peng
8bd8346423 fix: obsidian language not set in English, Chinese and Japanese 2024-09-19 13:47:57 +01:00
Jiaxin Peng
00411e9599 Merge pull request #35 from jxpeng98/mobile-fail-to-start
feat: separate mobile sync from desktop version
2024-09-03 12:19:23 +01:00
Jiaxin Peng
296125f6b4 chore: remove process from dependencies 2024-09-03 12:15:36 +01:00
Jiaxin Peng
1b385ccd0a solve: the fail to load of mobile caused by the node version 2024-09-01 23:26:22 +01:00
Jiaxin Peng
a90e4871bb Backup mobile requesturl after version 2.4.1 2024-09-01 22:57:03 +01:00
Jiaxin Peng
885ccba027 fix: test the desktop function for next and general 2024-08-31 23:43:19 +01:00
Jiaxin Peng
f282dde1b7 fix: test the desktop function of custom database
with platform function
2024-08-31 00:00:09 +01:00
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
15 changed files with 812 additions and 412 deletions

3
.gitignore vendored
View File

@@ -21,3 +21,6 @@ data.json
# Exclude macOS Finder (System Explorer) View States # Exclude macOS Finder (System Explorer) View States
.DS_Store .DS_Store
.history .history
# local data
local-data

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 a bug that plugin does not work when Obsidian language is not set to Englisht, Chinese or Japanese.
- 输入公式的时候,不会在公式后面加上多余的`\\`符号 - 修复了当 Obsidian 语言设置不是英文、中文或日文时插件无法工作的问题。

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.2",
"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.2",
"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",
@@ -27,7 +27,6 @@
"@jxpeng98/martian": "^1.2.7", "@jxpeng98/martian": "^1.2.7",
"https-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.2",
"node-fetch": "^3.3.2", "node-fetch": "^3.3.2",
"process": "^0.11.10",
"remark-math": "^6.0.0", "remark-math": "^6.0.0",
"yaml": "^2.3.4", "yaml": "^2.3.4",
"yaml-front-matter": "^4.1.1" "yaml-front-matter": "^4.1.1"

View File

@@ -8,10 +8,42 @@ export const I18n: {[key: string]:any} = {
ja, ja,
}; };
export const I18nConfig = (lang: string): any => { class I18nManager {
return I18n[lang]; private currentLanguage: string;
};
constructor() {
this.currentLanguage = this.detectLanguage();
}
// return the language to use
private detectLanguage(): string {
const storedLanguage = window.localStorage.getItem("language"); const storedLanguage = window.localStorage.getItem("language");
if (storedLanguage && this.isLanguageSupported(storedLanguage)) {
console.log(`Using stored language: ${storedLanguage}`);
return storedLanguage;
}
export const i18nConfig = I18n[storedLanguage || window.navigator.language.split('-')[0] || "en"]; 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();

View File

@@ -76,4 +76,8 @@ 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",
"reach-mobile-limit": "The number of blocks exceeds the limit of 100, please use the desktop plugin",
} }

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

@@ -20,7 +20,7 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
addIcons(); addIcons();
// This creates an icon in the left ribbon. // This creates an icon in the left ribbon.
const ribbonIconEl = this.addRibbonIcon( this.addRibbonIcon(
"notion-logo", "notion-logo",
i18nConfig.ribbonIcon, i18nConfig.ribbonIcon,
async (evt: MouseEvent) => { async (evt: MouseEvent) => {

View File

@@ -76,6 +76,9 @@ export async function uploadCommandGeneral(
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) { if (markDownData) {
const {basename} = nowFile; const {basename} = nowFile;
@@ -111,6 +114,9 @@ export async function uploadCommandCustom(
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) { if (markDownData) {
const {basename} = nowFile; const {basename} = nowFile;

View File

@@ -1,13 +1,17 @@
import { App, Notice, TFile } from "obsidian"; import {App, Notice, TFile, Platform, requestUrl} from "obsidian";
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 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";
interface CreatePageResponse {
response: any;
data: any;
}
export class Upload2NotionGeneral extends UploadBaseGeneral { export class Upload2NotionGeneral extends UploadBaseGeneral {
settings: PluginSettings; settings: PluginSettings;
@@ -47,7 +51,7 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
cover: string, cover: string,
tags: string[], tags: string[],
childArr: any, childArr: any,
) { ): Promise<CreatePageResponse> {
const { const {
databaseID, databaseID,
@@ -57,6 +61,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,
@@ -81,7 +120,7 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
} }
: {}), : {}),
}, },
children: childArr, children: firstArr,
}; };
if (cover) { if (cover) {
@@ -103,8 +142,32 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
} }
console.log(bodyString) console.log(bodyString)
console.log(Platform.isDesktopApp)
const response = await fetch("https://api.notion.com/v1/pages", { 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", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
@@ -114,18 +177,54 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
body: JSON.stringify(bodyString), body: JSON.stringify(bodyString),
}); });
const data: any = await response.json(); data = 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,
data // for id and url data
} }
} }
@@ -146,11 +245,11 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
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) {
@@ -167,10 +266,30 @@ export class Upload2NotionGeneral extends UploadBaseGeneral {
let {response, data} = res; let {response, data} = res;
// console.log(response) if (Platform.isDesktopApp) {
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
);
}
}
if (Platform.isMobileApp) {
if (response && response.status === 200) {
await updateYamlInfo(
markdown,
nowFile,
response,
app,
this.plugin,
this.dbDetails,
);
}
} }
return res; return res;

View File

@@ -1,22 +1,26 @@
import {UploadBaseNext} from "./BaseUpload2NotionNext"; import {UploadBaseNext} from "./BaseUpload2NotionNext";
import { App, Notice, TFile } from "obsidian"; import {App, Notice, TFile, Platform, requestUrl} from "obsidian";
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 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";
interface CreatePageResponse {
response: any;
data: any;
}
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 +39,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 +64,8 @@ export class Upload2NotionNext extends UploadBaseNext {
paword, paword,
favicon, favicon,
datetime, datetime,
childArr) childArr,
);
} }
async createPage( async createPage(
@@ -76,16 +81,47 @@ export class Upload2NotionNext extends UploadBaseNext {
pawrod: string, pawrod: string,
favicon: string, favicon: string,
datetime: string, datetime: string,
childArr: any childArr: any,
) { ): Promise<CreatePageResponse> {
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,120 +130,144 @@ 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,
},
};
} }
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),
});
} }
} }
console.log(bodyString) if (Platform.isDesktopApp) {
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",
@@ -217,22 +277,56 @@ export class Upload2NotionNext extends UploadBaseNext {
body: JSON.stringify(bodyString), body: JSON.stringify(bodyString),
}); });
const data: any = await response.json(); data = await response.json();
// 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}`);
} }
return { // upload the rest of the blocks
response, // for status code if (pushCount > 0) {
data // for id and url 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,
data
};
}
async syncMarkdownToNotionNext( async syncMarkdownToNotionNext(
title: string, title: string,
@@ -254,38 +348,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 +394,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 +410,38 @@ export class Upload2NotionNext extends UploadBaseNext {
paword, paword,
favicon, favicon,
datetime, datetime,
file2Block file2Block,
); );
} }
let {response, data} = res; let {response, data} = res;
if (Platform.isDesktopApp) {
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
);
}
}
if (Platform.isMobileApp) {
if (response && response.status === 200) {
await updateYamlInfo(
markdown,
nowFile,
response,
app,
this.plugin,
this.dbDetails,
);
}
} }
return res; return res;
} }
} }

View File

@@ -1,14 +1,19 @@
import {App, Notice, TFile} from "obsidian"; import {App, Notice, Platform, TFile, requestUrl} from "obsidian";
import {markdownToBlocks} from "@jxpeng98/martian"; import {markdownToBlocks} from "@jxpeng98/martian";
import * as yamlFrontMatter from "yaml-front-matter"; import * as yamlFrontMatter from "yaml-front-matter";
// import * 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 {UploadBaseCustom} from "./BaseUpload2NotionCustom"; import {UploadBaseCustom} from "./BaseUpload2NotionCustom";
import fetch from 'node-fetch'; import fetch from 'node-fetch';
import {i18nConfig} from "../../lang/I18n";
interface CreatePageResponse {
response: any;
data: any;
}
export class Upload2NotionCustom extends UploadBaseCustom { export class Upload2NotionCustom extends UploadBaseCustom {
settings: PluginSettings; settings: PluginSettings;
dbDetails: DatabaseDetails; dbDetails: DatabaseDetails;
@@ -45,7 +50,7 @@ export class Upload2NotionCustom extends UploadBaseCustom {
cover: string, cover: string,
customValues: Record<string, string>, customValues: Record<string, string>,
childArr: any, childArr: any,
) { ): Promise<CreatePageResponse> {
const { const {
databaseID, databaseID,
@@ -53,7 +58,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 = {
@@ -74,8 +114,32 @@ export class Upload2NotionCustom extends UploadBaseCustom {
} }
console.log(bodyString) console.log(bodyString)
console.log(Platform.isDesktopApp)
const response = await fetch("https://api.notion.com/v1/pages", { 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", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
@@ -85,15 +149,51 @@ export class Upload2NotionCustom extends UploadBaseCustom {
body: JSON.stringify(bodyString), body: JSON.stringify(bodyString),
}); });
const data: any = await response.json(); data = 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 +217,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(
@@ -138,8 +238,30 @@ export class Upload2NotionCustom extends UploadBaseCustom {
// console.log(response) // console.log(response)
if (Platform.isDesktopApp) {
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
);
}
}
if (Platform.isMobileApp) {
if (response && response.status === 200) {
await updateYamlInfo(
markdown,
nowFile,
response,
app,
this.plugin,
this.dbDetails,
);
}
} }
return res; return res;

View File

@@ -1245,11 +1245,6 @@ picomatch@^2.3.1:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 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: queue-microtask@^1.2.2:
version "1.2.3" version "1.2.3"
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"