Compare commits

...

15 Commits
0.2.0 ... 0.2.6

Author SHA1 Message Date
Jiaxin Peng
eee349509a Update version to 0.2.6 2023-11-12 21:02:00 +00:00
Jiaxin Peng
57c0941fed Merge pull request #6 from jxpeng98/add-button
Add switch button
2023-11-12 21:00:43 +00:00
Jiaxin Peng
8734af6dbf add switch button 2023-11-12 20:59:39 +00:00
Jiaxin Peng
041a78fb52 add button to display the command in the command palette 2023-11-11 00:29:35 +00:00
Jiaxin Peng
afec5d8364 Update version to 0.2.5 2023-11-05 20:49:28 +00:00
Jiaxin Peng
75926a38d4 Update version to 0.2.4 2023-11-05 20:46:42 +00:00
Jiaxin Peng
793dd67e0a Update version to 0.2.3 2023-11-05 20:44:51 +00:00
Jiaxin Peng
f235c80d18 update readme 2023-11-05 20:44:42 +00:00
Jiaxin Peng
f33315a4b6 fix github action bug 2023-11-05 20:43:47 +00:00
Jiaxin Peng
b62bd4ba2e Update version to 0.2.2 2023-11-05 17:58:19 +00:00
Jiaxin Peng
402d15a38b Merge pull request #5 from jxpeng98/general-database
General database
2023-11-05 17:57:21 +00:00
Jiaxin Peng
87f1ce0146 update readme and settingtabs 2023-11-05 17:50:51 +00:00
Jiaxin Peng
398b785e03 update the script and support both notionnext and general database 2023-11-05 17:32:10 +00:00
Jiaxin Peng
8617878582 restructure the code for further feature 2023-11-04 22:37:02 +00:00
Jiaxin Peng
ae9e0c14fb modify the directory structure and rename the function 2023-11-02 14:32:25 +00:00
22 changed files with 1051 additions and 600 deletions

View File

@@ -3,8 +3,30 @@
所以我在[原作者](https://github.com/EasyChris/obsidian-to-notion)的基础之上,增加了匹配[NotionNext](https://github.com/tangly1024/NotionNext)模板的功能。这样可以直接在Obsidian编辑整理好之后一键发布。
## 更新说明
### 0.2.6
- 增加一个按钮用来控制是否在名列列表中显示如下数据库。
![](https://minioapi.pjx.ac.cn/img1/2023/11/147c6a4eaa34da41a6f102558ed77106.png)
如果你关闭普通数据库的按钮你在上传命令列表中就不会出现普通数据库的选项。如果你关闭NotionNext数据库的按钮你在上传命令列表中就不会出现NotionNext数据库的选项。
![](https://minioapi.pjx.ac.cn/img1/2023/11/70b8e4fc2148688ccbd6cfc53ce339a2.png)
### 0.2.3
- 修复了一个bug现在可以正常更新了。
### 0.2.2
- 支持NotionNext 和 普通Notion 数据库的同步。
- 你可以有一个NotionNext和一个普通Notion数据库。
- 普通Notion数据库的同步方式和原作者的一样只同步`title``tags`。**如果使用普通数据库功能,你需要保证你的数据库中有`title``tags`这两个表头。必须使用小写。**
![](https://minioapi.pjx.ac.cn/img1/2023/11/712a12081d855aa60f82a7b46913ab7e.gif)
![](https://minioapi.pjx.ac.cn/img1/2023/11/9de76cecceef74c78884ddfc1c221659.gif)
### 0.2.1
- 重构代码。
### 0.2.0
- 从这个版本开始采用了类似于BRAT的交互方式。当你点击左侧同步按钮的时候首先会弹出
- 从这个版本开始,重构了交互逻辑。现在当你点击左侧的按钮,会弹出可同步的数据库选项。你可以选择你想要同步的数据库,然后点击同步按钮。**但是现在仅支持同步单个数据库如果你的数据库不是NotionNext你可以不用更新。**
### 0.1.10
- 修正了设置中的中文显示。
### 0.1.8

View File

@@ -5,15 +5,36 @@ Thanks to the [original author](https://github.com/EasyChris/obsidian-to-notion)
Thus, based on the [original author's work](https://github.com/EasyChris/obsidian-to-notion), I've added a feature to match the [NotionNext](https://github.com/tangly1024/NotionNext) template. This way, you can edit directly in Obsidian and publish with a single click after organizing.
## Update
### 0.2.6
- Add a switch button to control whether to show the upload command in the command palette.
![](https://minioapi.pjx.ac.cn/img1/2023/11/147c6a4eaa34da41a6f102558ed77106.png)
If you turn off the button for the General database, you won't see the option for the General database in the upload command list.
If you turn off the button for the NotionNext database, you won't see the option for the NotionNext database in the upload command list.
![](https://minioapi.pjx.ac.cn/img1/2023/11/70b8e4fc2148688ccbd6cfc53ce339a2.png)
### 0.2.3
- Fix the bug, now you can update normally.
### 0.2.2
- Support both NotionNext and General Notion database.
- You can have one NotionNext and one General Notion database.
- General Notion database can only have `title` and `tags` columns, and `tags` columns should be the multi-selected property. **the name of the columns is case sensitive. You should use small letter.**
![](https://minioapi.pjx.ac.cn/img1/2023/11/712a12081d855aa60f82a7b46913ab7e.gif)
![](https://minioapi.pjx.ac.cn/img1/2023/11/9de76cecceef74c78884ddfc1c221659.gif)
### 0.2.1
- Restructure the code
### 0.2.0
- From this version, the interactive logic has been rewritten. When you click the ribbon icon, it will display the sync command for all presetting NotionNext databases. You can choose the database you want to sync to. **However, only NotionNext database is supported for now.**
![](https://minioapi.pjx.ac.cn/img1/2023/11/c963e97f31a30c994e067c58443fed4f.gif)
### 0.1.10
- Fix the Chinese support in the settings.
### 0.1.8
- Rebuild the upload function, and add one button to select the different databases. **However, only NotionNext database is supported for now.**
- Rebuild the uploadCommand function, and add one button to select the different databases. **However, only NotionNext database is supported for now.**
### 0.1.7
- [x] Removed the `convert tag` option. Now, you can directly add tags in the YAML front matter. If you don't want to add tags, you can delete the tags in the YAML front matter or leave the tags blank.
@@ -189,9 +210,9 @@ Fill the configuration with the `NOTION_API_KEY` and `DATABASE_ID` you got
![](./doc/2.png)
## Upload file content to notion
Click the upload notion button
Click the uploadCommand notion button
![](./doc/4.png)
A share link will be automatically generated after successful upload
A share link will be automatically generated after successful uploadCommand
![](./doc/5.png)

View File

@@ -1,7 +1,7 @@
{
"id": "share-to-notionnext",
"name": "Share to NotionNext",
"version": "0.2.0",
"version": "0.2.6",
"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",

View File

@@ -1,6 +1,6 @@
{
"name": "share-to-notionnext",
"version": "0.2.0",
"version": "0.2.6",
"type": "module",
"description": "Shares obsidian md file to notion with notion api for NotionNext web deploy, originally created by EasyChris/obsidian-to-notion.",
"main": "main.js",

View File

@@ -1,87 +0,0 @@
import { App, Notice, requestUrl, TFile } from "obsidian";
import { Client } from '@notionhq/client';
import { markdownToBlocks, } from "@tryfabric/martian";
import * as yamlFrontMatter from "yaml-front-matter";
// import * as yaml from "yaml"
import MyPlugin from "src/main";
export class UploadBase {
plugin: MyPlugin;
notion: Client;
agent: any;
constructor(plugin: MyPlugin) {
this.plugin = plugin;
}
async deletePage(notionID: string) {
return requestUrl({
url: `https://api.notion.com/v1/blocks/${notionID}`,
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.plugin.settings.notionAPI,
'Notion-Version': '2022-06-28',
},
body: ''
});
}
async getDataBase(databaseID: string) {
const response = await requestUrl({
url: `https://api.notion.com/v1/databases/${databaseID}`,
method: 'GET',
headers: {
'Authorization': 'Bearer ' + this.plugin.settings.notionAPI,
'Notion-Version': '2022-06-28',
}
}
)
// Check if cover is present in the JSON response and then get the URL
if (response.json.cover && response.json.cover.external) {
return response.json.cover.external.url;
} else {
return null; // or some other default value, if you prefer
}
}
async updateYamlInfo(yamlContent: string, nowFile: TFile, res: any, app: App, settings: any) {
let { url, id } = res.json
// replace www to notionID
const { notionID } = settings;
if (notionID !== "") {
// replace url str "www" to notionID
url = url.replace("www.notion.so", `${notionID}.notion.site`)
}
await app.fileManager.processFrontMatter(nowFile, yamlContent => {
if (yamlContent['notionID']) {
delete yamlContent['notionID']
}
if (yamlContent['link']) {
delete yamlContent['link']
}
// add new notionID and link
yamlContent.notionID = id;
yamlContent.link = url;
});
try {
await navigator.clipboard.writeText(url)
} catch (error) {
new Notice(`复制链接失败,请手动复制${error}`)
}
// const __content = yamlContent.__content;
// delete yamlContent.__content
// const yamlhead = yaml.stringify(yamlContent)
// // if yamlhead hava last \n remove it
// const yamlhead_remove_n = yamlhead.replace(/\n$/, '')
// // if __content have start \n remove it
// const __content_remove_n = __content.replace(/^\n/, '')
// const content = '---\n' +yamlhead_remove_n +'\n---\n' + __content_remove_n;
// try {
// await nowFile.vault.modify(nowFile, content)
// } catch (error) {
// new Notice(`write file error ${error}`)
// }
}
}

View File

@@ -1,57 +0,0 @@
import {i18nConfig} from "src/I18n";
import MyPlugin from "src/main";
import {Editor, MarkdownView} from "obsidian";
import {FuzzySuggester, DatabaseList} from "./FuzzySuggester";
// create the commands list
export default class RibbonCommands {
plugin: MyPlugin;
// Total commands that will be used
Ncommand = [
{
id: "share-to-notionnext",
name: i18nConfig.ribbonIcon, // Use the translated text from i18nConfig
editorCallback: async (editor: Editor, view: MarkdownView) => {
await this.plugin.upload();
}
},
// {
// id: "share-to-notion",
// name: i18nConfig.CommandNameGeneral, // Use the translated text from i18nConfig
// editorCallback: async (editor: Editor, view: MarkdownView) => {
// await this.plugin.upload();
// }
// }
];
async ribbonDisplay() {
const NcommandList: DatabaseList[] = [];
this.Ncommand.map(command => NcommandList.push(
{
name:command.name,
match: command.editorCallback
}
)
);
const fusg = new FuzzySuggester(this.plugin);
fusg.setSuggesterData(NcommandList);
await fusg.display(async (results) => {await results.match()})
};
constructor(plugin: MyPlugin) {
this.plugin = plugin;
// Register all the commands
this.Ncommand.forEach(command => {
this.plugin.addCommand(
{
id: command.id,
name: command.name,
editorCallback: command.editorCallback,
}
);
});
}
}

View File

@@ -1,178 +0,0 @@
import {UploadBase} from "./BaseUpload2Notion";
import { App, Notice, requestUrl, TFile } from "obsidian";
import { Client } from '@notionhq/client';
import { markdownToBlocks, } from "@tryfabric/martian";
import * as yamlFrontMatter from "yaml-front-matter";
// import * as yaml from "yaml"
import MyPlugin from "src/main";
export class Upload2Notion extends UploadBase {
constructor(plugin: MyPlugin) {
super(plugin);
}
// 因为需要解析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 databasecover = await this.getDataBase(this.plugin.settings.databaseID)
if (cover == null) {
cover = databasecover
}
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) {
const bodyString: any = {
parent: {
database_id: this.plugin.settings.databaseID
},
icon: {
emoji: emoji || '📜'
},
properties: {
title: {
title: [
{
text: {
content: title
},
},
],
},
tags: {
multi_select: tags && true ? tags.map(tag => {
return { "name": tag }
}) : [],
},
type: {
select: {
name: type || 'Post'
}
},
slug: {
rich_text: [
{
text: {
content: slug || ''
}
}
]
},
status: {
select: {
name: stats || 'Draft'
}
},
category: {
select: {
name: category || 'Obsidian'
}
},
summary: {
rich_text: [
{
text: {
content: summary || ''
}
}
]
},
password: {
rich_text: [
{
text: {
content: pawrod || ''
}
}
]
},
icon: {
rich_text: [
{
text: {
content: favicon || ''
}
}
]
},
date: {
date: {
start: datetime || new Date().toISOString()
}
}
},
children: childArr,
}
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
}
}
}
try {
return await requestUrl({
url: `https://api.notion.com/v1/pages`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
// 'User-Agent': 'obsidian.md',
'Authorization': 'Bearer ' + this.plugin.settings.notionAPI,
'Notion-Version': '2022-06-28',
},
body: JSON.stringify(bodyString),
})
} catch (error) {
new Notice(`network error ${error}`)
}
}
async syncMarkdownToNotion(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, settings: any): Promise<any> {
let res: any
const yamlContent: any = yamlFrontMatter.loadFront(markdown);
const __content = yamlContent.__content
const file2Block = markdownToBlocks(__content);
const frontmasster = app.metadataCache.getFileCache(nowFile)?.frontmatter
const notionID = frontmasster ? frontmasster.notionID : null
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);
}
if (res.status === 200) {
await this.updateYamlInfo(markdown, nowFile, res, app, settings)
} else {
new Notice(`${res.text}`)
}
return res
}
}

View File

@@ -1,6 +1,6 @@
import { FuzzySuggestModal, FuzzyMatch } from 'obsidian';
import MyPlugin from "./main";
import {i18nConfig} from "./I18n";
import MyPlugin from "../main";
import {i18nConfig} from "../lang/I18n";
/**
* Simple interface for what should be displayed and stored for suggester
@@ -10,9 +10,7 @@ export interface DatabaseList {
match: any //
}
/**
* Generic suggester for quick reuse
*/
export class FuzzySuggester extends FuzzySuggestModal<DatabaseList>{
private plugin: MyPlugin;
private data: DatabaseList[];

View File

@@ -0,0 +1,110 @@
import {i18nConfig} from "src/lang/I18n";
import {Editor, MarkdownView} from "obsidian";
import {FuzzySuggester, DatabaseList} from "./FuzzySuggester";
import {uploadCommandGeneral, uploadCommandNext} from "../upload/uploadCommand";
import ObsidianSyncNotionPlugin from "src/main";
interface Command {
id: string;
name: string;
editorCallback: (editor: Editor, view: MarkdownView) => Promise<void>;
}
// create the commands list
export default class RibbonCommands {
plugin: ObsidianSyncNotionPlugin;
Ncommand: Command[] = [];
constructor(plugin: ObsidianSyncNotionPlugin) {
this.plugin = plugin;
// Check if NextButton is true, then include the corresponding command
if (this.plugin.settings.NextButton) {
this.Ncommand.push({
id: "share-to-notionnext",
name: i18nConfig.CommandName, // Use the translated text from i18nConfig
editorCallback: async (editor: Editor, view: MarkdownView) => {
await uploadCommandNext(this.plugin, this.plugin.settings, this.plugin.app);
}
});
}
// Check if GeneralButton is true, then include the corresponding command
if (this.plugin.settings.GeneralButton) {
this.Ncommand.push({
id: "share-to-notion",
name: i18nConfig.CommandNameGeneral, // Use the translated text from i18nConfig
editorCallback: async (editor: Editor, view: MarkdownView) => {
await uploadCommandGeneral(this.plugin, this.plugin.settings, this.plugin.app);
}
});
}
// Register all the commands
this.Ncommand.forEach(command => {
this.plugin.addCommand(
{
id: command.id,
name: command.name,
editorCallback: command.editorCallback,
}
);
});
}
async ribbonDisplay() {
const NcommandList: DatabaseList[] = [];
this.Ncommand.map(command => NcommandList.push(
{
name:command.name,
match: command.editorCallback
}
)
);
const fusg = new FuzzySuggester(this.plugin);
fusg.setSuggesterData(NcommandList);
await fusg.display(async (results) => {await results.match()})
};
// if the setting has been changed, try to rebuild the command list
async updateCommand() {
this.Ncommand = [];
if (this.plugin.settings.NextButton) {
this.Ncommand.push({
id: "share-to-notionnext",
name: i18nConfig.CommandName, // Use the translated text from i18nConfig
editorCallback: async (editor: Editor, view: MarkdownView) => {
await uploadCommandNext(this.plugin, this.plugin.settings, this.plugin.app);
}
});
}
if (this.plugin.settings.GeneralButton) {
this.Ncommand.push({
id: "share-to-notion",
name: i18nConfig.CommandNameGeneral, // Use the translated text from i18nConfig
editorCallback: async (editor: Editor, view: MarkdownView) => {
await uploadCommandGeneral(this.plugin, this.plugin.settings, this.plugin.app);
}
});
}
this.Ncommand.forEach(command => {
this.plugin.addCommand(
{
id: command.id,
name: command.name,
editorCallback: command.editorCallback,
}
);
});
}
}

View File

@@ -1,27 +1,31 @@
export const I18n: { [key: string]: any } = {
en: {
ribbonIcon: "Share to NotionNext",
CommandName: "share to notionnext",
CommandNameGeneral: "share to notion",
NotionNextVersion: "NotionNext Version Database",
NotionNextVersionDesc:
"Turn on this option if you are using NotionNext",
NotionNextSetting: "NotionNext Database Settings",
GeneralSetting: "General information Settings",
CommandID: "share-to-notionnext",
CommandName: "Share to NotionNext Database",
CommandIDGeneral: "share-to-notion",
CommandNameGeneral: "Share to Notion General Database",
NotionNextButton: "NotionNext command switch",
NotionNextButtonDesc: "Open this option, Sync to NotionNext command will be displayed in the command palette",
NotionNextSettingHeader: "NotionNext Database Settings",
NotionAPI: "Notion API Token",
NotionAPIDesc: "It's a secret",
NotionAPIText: "Enter your Notion API Token",
NotionID: "Database ID",
NotionIDText: "Enter your Database ID",
DatabaseID: "Database ID",
DatabaseIDText: "Enter your Database ID",
BannerUrl: "Banner url(optional)",
BannerUrlDesc:
"page banner url(optional), default is empty, if you want to show a banner, please enter the url(like:https://raw.githubusercontent.com/EasyChris/obsidian-to-notion/ae7a9ac6cf427f3ca338a409ce6967ced9506f12/doc/2.png)",
"Default is empty, if you want to show a banner, please enter the url(like: https://minioapi.pjx.ac.cn/img1/2023/11/b7b40a0724e93b7d7ab494bb3b8a2da8.png)",
BannerUrlText: "Enter your banner url",
NotionUser: "Notion ID(username, optional)",
NotionUserDesc:
"Your notion ID (optional),share link likes:https://username.notion.site/,your notion id is [username]",
NotionUserText: "Enter your notion ID (options)",
NotionGeneralSetting: "General Notion Database Settings",
NotYetFinish:
NotionUserText: "Enter your notion ID",
NotionGeneralSettingHeader: "General Notion Database Settings",
NotionGeneralButton: "Notion General command switch",
NotionGeneralButtonDesc: "Open this option, Sync to Notion General Database command will be displayed in the command palette",
NotYetFinish:
"Not finished. This function will be available in the next version",
PlaceHolder: "Enter database Name",
"notion-logo": "Share to NotionNext",
@@ -38,28 +42,36 @@ export const I18n: { [key: string]: any } = {
"The 'NNon' property is missing in the settings. Please set it up.",
"set-api-id":
"Please set up the notion API and database ID in the settings tab.",
NotionCustomSettingHeader: "Notion Custom Database Settings",
NotionCustomButton: "Notion Customised command switch",
NotionCustomButtonDesc: "Open this option, Sync to Notion Customised Database command will be displayed in the command palette",
},
zh: {
ribbonIcon: "分享到 NotionNext",
GeneralSetting: "通用信息设置",
CommandID: "share-to-notionnext",
CommandName: "分享到 NotionNext",
CommandNameGeneral: "分享到 Notion",
NotionNextVersion: "NotionNext 版本数据库",
NotionNextVersionDesc: "如果你使用的是NotionNext,请打开此选项",
NotionNextSetting: "NotionNext 数据库参数设置",
CommandIDGeneral: "share-to-notion",
CommandNameGeneral: "分享到 Notion 普通数据库",
NotionNextButton: "NotionNext 同步命令开关",
NotionNextButtonDesc: "打开此选项,NotionNext 同步将显示在命令面板中",
NotionNextSettingHeader: "NotionNext 数据库参数设置",
NotionAPI: "Notion API 令牌",
NotionAPIDesc: "显示为密码",
NotionAPIText: "输入你的 Notion API 令牌",
NotionID: "数据库 ID",
NotionIDText: "输入你的数据库 ID",
DatabaseID: "数据库 ID",
DatabaseIDText: "输入你的数据库 ID",
BannerUrl: "封面图片地址(可选)",
BannerUrlDesc:
"页面封面图片地址(可选),默认为空如果你想显示封面图片请输入图片地址例如https://raw.githubusercontent.com/EasyChris/obsidian-to-notion/ae7a9ac6cf427f3ca338a409ce6967ced9506f12/doc/2.png",
"默认为空如果你想显示封面图片请输入图片地址例如https://minioapi.pjx.ac.cn/img1/2023/11/b7b40a0724e93b7d7ab494bb3b8a2da8.png",
BannerUrlText: "输入你的封面图片地址",
NotionUser: "Notion ID用户名可选",
NotionUserDesc:
"你的 Notion ID可选分享链接类似https://username.notion.site/,你的 Notion ID 是 [username]",
NotionUserText: "输入你的 Notion ID(可选)",
NotionGeneralSetting: "普通 Notion 数据库设置",
NotionUserText: "输入你的 Notion ID",
NotionGeneralSettingHeader: "普通 Notion 数据库设置",
NotionGeneralButton: "普通数据库同步命令开关",
NotionGeneralButtonDesc: "打开此选项,同步到普通数据库命令将显示在命令面板中",
NotYetFinish: "未完成。此功能将在之后版本中提供",
PlaceHolder: "输入数据库名称",
"notion-logo": "分享到NotionNext",
@@ -72,6 +84,9 @@ export const I18n: { [key: string]: any } = {
"设置标签失败,请检查文件的frontmatter,或者在插件设置中关闭设置tags开关",
NNonMissing: "未设置'NNon'属性请在插件设置中选择NotionNext数据库。",
"set-api-id": "请在插件设置中设置notion API和database ID",
NotionCustomSettingHeader: "Notion 自定义数据库设置",
NotionCustomButton: "Notion 自定义数据库同步命令开关",
NotionCustomButtonDesc: "打开此选项,同步到自定义数据库命令将显示在命令面板中",
},
};

View File

@@ -1,32 +1,18 @@
import {App, Editor, MarkdownView, Notice, Plugin, PluginSettingTab, Setting} from "obsidian";
import {addIcons} from 'src/icon';
import {Upload2Notion} from "src/Upload2Notion";
import {Upload2NotionNext} from "src/Upload2Notion_NN";
import {i18nConfig} from "src/I18n";
import ribbonCommands from "src/NotionCommands";
import {addIcons} from 'src/ui/icon';
import {Upload2NotionGeneral} from "src/upload/upload_general/Upload2NotionGeneral";
import {Upload2NotionNext} from "src/upload/upload_next/Upload2NotionNext";
import {i18nConfig} from "src/lang/I18n";
import ribbonCommands from "src/commands/NotionCommands";
import { ObsidianSettingTab, PluginSettings, DEFAULT_SETTINGS } from "src/ui/settingTabs";
// Remember to rename these classes and interfaces!
interface PluginSettings {
NNon: boolean;
notionAPI: string;
databaseID: string;
bannerUrl: string;
notionID: string;
proxy: string;
}
const DEFAULT_SETTINGS: PluginSettings = {
NNon: undefined,
notionAPI: "",
databaseID: "",
bannerUrl: "",
notionID: "",
proxy: "",
};
export default class ObsidianSyncNotionPlugin extends Plugin {
settings: PluginSettings;
commands: ribbonCommands;
app: App;
async onload() {
await this.loadSettings();
@@ -39,23 +25,15 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
i18nConfig.ribbonIcon,
async (evt: MouseEvent) => {
// Called when the user clicks the icon.
// await this.upload();
this.commands.ribbonDisplay();
// await this.uploadCommand();
await this.commands.ribbonDisplay();
}
);
// This adds a status bar item to the bottom of the app. Does not work on mobile apps.
const statusBarItemEl = this.addStatusBarItem();
// statusBarItemEl.setText("share to notion");
this.addCommand({
id: "share-to-notionnext",
name: i18nConfig.CommandName,
editorCallback: async (editor: Editor, view: MarkdownView) => {
await this.upload()
},
});
// const statusBarItemEl = this.addStatusBarItem();
// // statusBarItemEl.setText("share to notion");
// This adds a settings tab so the user can configure various aspects of the plugin
this.addSettingTab(new ObsidianSettingTab(this.app, this));
@@ -65,102 +43,6 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
onunload() {
}
async upload() {
const {notionAPI, databaseID, NNon} = this.settings;
// Check if NNon exists
if (NNon === undefined) {
const NNonmessage = i18nConfig.NNonMissing;
new Notice(NNonmessage);
return;
}
// Check if the user has set up the Notion API and database ID
if (notionAPI === "" || databaseID === "") {
const setAPIMessage = i18nConfig["set-api-id"];
new Notice(setAPIMessage);
return;
}
const {markDownData, nowFile, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime} = await this.getNowFileMarkdownContent(this.app);
if (markDownData) {
const {basename} = nowFile;
let upload;
if (NNon) {
upload = new Upload2NotionNext(this);
} else {
upload = new Upload2Notion(this);
}
const res = await upload.syncMarkdownToNotion(basename, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, markDownData, nowFile, this.app, this.settings);
if (res.status === 200) {
new Notice(`${i18nConfig["sync-success"]}${basename}`);
} else {
new Notice(`${i18nConfig["sync-fail"]}${basename}`, 5000);
}
}
}
async getNowFileMarkdownContent(app: App) {
const nowFile = app.workspace.getActiveFile();
const {NNon} = this.settings;
let emoji = ''
let cover = ''
let tags = []
let type = ''
let slug = ''
let stats = ''
let category = ''
let summary = ''
let paword = ''
let favicon = ''
let datetime = ''
const FileCache = app.metadataCache.getFileCache(nowFile)
try {
if (NNon) {
emoji = FileCache.frontmatter.titleicon;
cover = FileCache.frontmatter.coverurl;
tags = FileCache.frontmatter.tags;
type = FileCache.frontmatter.type;
slug = FileCache.frontmatter.slug;
stats = FileCache.frontmatter.stats;
category = FileCache.frontmatter.category;
summary = FileCache.frontmatter.summary;
paword = FileCache.frontmatter.password;
favicon = FileCache.frontmatter.icon;
datetime = FileCache.frontmatter.date;
}
} catch (error) {
new Notice(i18nConfig["set-tags-fail"]);
}
if (nowFile) {
const markDownData = await nowFile.vault.read(nowFile);
return {
markDownData,
nowFile,
emoji,
cover,
tags,
type,
slug,
stats,
category,
summary,
paword,
favicon,
datetime,
};
} else {
new Notice(i18nConfig["open-file"]);
return;
}
}
async loadSettings() {
this.settings = Object.assign(
{},
@@ -172,110 +54,9 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
async saveSettings() {
await this.saveData(this.settings);
}
}
class ObsidianSettingTab extends PluginSettingTab {
plugin: ObsidianSyncNotionPlugin;
constructor(app: App, plugin: ObsidianSyncNotionPlugin) {
super(app, plugin);
this.plugin = plugin;
}
display(): void {
const {containerEl} = this;
containerEl.empty();
new Setting(containerEl)
.setName(i18nConfig.NotionNextVersion)
.setDesc(i18nConfig.NotionNextVersionDesc)
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.NNon)
.onChange(async (value) => {
this.plugin.settings.NNon = value;
await this.plugin.saveSettings();
})
);
containerEl.createEl('h2', {text: i18nConfig.NotionNextSetting})
new Setting(containerEl)
.setName(i18nConfig.NotionAPI)
.setDesc(i18nConfig.NotionAPIDesc)
.addText((text) => {
text.inputEl.type = 'password';
return text
.setPlaceholder(i18nConfig.NotionAPIText)
.setValue(this.plugin.settings.notionAPI)
.onChange(async (value) => {
this.plugin.settings.notionAPI = value;
await this.plugin.saveSettings();
})
});
const notionDatabaseID = new Setting(containerEl)
.setName(i18nConfig.NotionID)
.setDesc(i18nConfig.NotionAPIDesc)
.addText((text) => {
text.inputEl.type = 'password';
return text
.setPlaceholder(i18nConfig.NotionIDText)
.setValue(this.plugin.settings.databaseID)
.onChange(async (value) => {
this.plugin.settings.databaseID = value;
await this.plugin.saveSettings();
})
}
);
// notionDatabaseID.controlEl.querySelector('input').type='password'
new Setting(containerEl)
.setName(i18nConfig.BannerUrl)
.setDesc(i18nConfig.BannerUrlDesc)
.addText((text) =>
text
.setPlaceholder(i18nConfig.BannerUrlText)
.setValue(this.plugin.settings.bannerUrl)
.onChange(async (value) => {
this.plugin.settings.bannerUrl = value;
await this.plugin.saveSettings();
})
);
new Setting(containerEl)
.setName(i18nConfig.NotionUser)
.setDesc(i18nConfig.NotionUserDesc)
.addText((text) =>
text
.setPlaceholder(i18nConfig.NotionUserText)
.setValue(this.plugin.settings.notionID)
.onChange(async (value) => {
this.plugin.settings.notionID = value;
await this.plugin.saveSettings();
})
);
// General Database Settings
containerEl.createEl('h2', {text: i18nConfig.NotionGeneralSetting});
new Setting(containerEl)
.setName(i18nConfig.NotYetFinish)
// new Setting(containerEl)
// .setName("Convert tags(optional)")
// .setDesc("Transfer the Obsidian tags to the Notion table. It requires the column with the name 'Tags'")
// .addToggle((toggle) =>
// toggle
// .setValue(this.plugin.settings.allowTags)
// .onChange(async (value) => {
// this.plugin.settings.allowTags = value;
// await this.plugin.saveSettings();
// })
// );
}
}

0
src/ui/addButton.ts Normal file
View File

201
src/ui/settingTabs.ts Normal file
View File

@@ -0,0 +1,201 @@
import {App, PluginSettingTab, Setting} from "obsidian";
import {i18nConfig} from "../lang/I18n";
import ObsidianSyncNotionPlugin from "../main";
export interface PluginSettings {
NextButton: boolean;
notionAPINext: string;
databaseIDNext: string;
bannerUrl: string;
notionUser: string;
proxy: string;
GeneralButton: boolean;
notionAPIGeneral: string;
databaseIDGeneral: string;
CustomButton: boolean;
notionAPICustom: string;
databaseIDCustom: string;
}
export const DEFAULT_SETTINGS: PluginSettings = {
NextButton: true,
notionAPINext: "",
databaseIDNext: "",
bannerUrl: "",
notionUser: "",
proxy: "",
GeneralButton: true,
notionAPIGeneral: "",
databaseIDGeneral: "",
CustomButton: false,
notionAPICustom: "",
databaseIDCustom: "",
};
export class ObsidianSettingTab extends PluginSettingTab {
plugin: ObsidianSyncNotionPlugin;
constructor(app: App, plugin: ObsidianSyncNotionPlugin) {
super(app, plugin);
this.plugin = plugin;
}
display(): void {
const {containerEl} = this;
containerEl.empty();
containerEl.createEl('h2', {text: i18nConfig.GeneralSetting})
new Setting(containerEl)
.setName(i18nConfig.BannerUrl)
.setDesc(i18nConfig.BannerUrlDesc)
.addText((text) =>
text
.setPlaceholder(i18nConfig.BannerUrlText)
.setValue(this.plugin.settings.bannerUrl)
.onChange(async (value) => {
this.plugin.settings.bannerUrl = value;
await this.plugin.saveSettings();
})
);
new Setting(containerEl)
.setName(i18nConfig.NotionUser)
.setDesc(i18nConfig.NotionUserDesc)
.addText((text) =>
text
.setPlaceholder(i18nConfig.NotionUserText)
.setValue(this.plugin.settings.notionUser)
.onChange(async (value) => {
this.plugin.settings.notionUser = value;
await this.plugin.saveSettings();
})
);
containerEl.createEl('h2', {text: i18nConfig.NotionNextSettingHeader})
new Setting(containerEl)
.setName(i18nConfig.NotionNextButton)
.setDesc(i18nConfig.NotionNextButtonDesc)
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.NextButton)
.onChange(async (value) => {
this.plugin.settings.NextButton = value;
await this.plugin.saveSettings();
await this.plugin.commands.updateCommand();
})
);
new Setting(containerEl)
.setName(i18nConfig.NotionAPI)
.setDesc(i18nConfig.NotionAPIDesc)
.addText((text) => {
text.inputEl.type = 'password';
return text
.setPlaceholder(i18nConfig.NotionAPIText)
.setValue(this.plugin.settings.notionAPINext)
.onChange(async (value) => {
this.plugin.settings.notionAPINext = value;
await this.plugin.saveSettings();
})
});
const notionDatabaseID = new Setting(containerEl)
.setName(i18nConfig.DatabaseID)
.setDesc(i18nConfig.NotionAPIDesc)
.addText((text) => {
text.inputEl.type = 'password';
return text
.setPlaceholder(i18nConfig.DatabaseIDText)
.setValue(this.plugin.settings.databaseIDNext)
.onChange(async (value) => {
this.plugin.settings.databaseIDNext = value;
await this.plugin.saveSettings();
})
}
);
// notionDatabaseID.controlEl.querySelector('input').type='password'
// General Database Settings
containerEl.createEl('h2', {text: i18nConfig.NotionGeneralSettingHeader});
// new Setting(containerEl)
// .setName(i18nConfig.NotYetFinish)
new Setting(containerEl)
.setName(i18nConfig.NotionGeneralButton)
.setDesc(i18nConfig.NotionGeneralButtonDesc)
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.GeneralButton)
.onChange(async (value) => {
this.plugin.settings.GeneralButton = value;
await this.plugin.saveSettings();
await this.plugin.commands.updateCommand();
})
);
// new Setting(containerEl)
// .setName("Convert tags(optional)")
// .setDesc("Transfer the Obsidian tags to the Notion table. It requires the column with the name 'Tags'")
// .addToggle((toggle) =>
// toggle
// .setValue(this.plugin.settings.allowTags)
// .onChange(async (value) => {
// this.plugin.settings.allowTags = value;
// await this.plugin.saveSettings();
// })
// );
new Setting(containerEl)
.setName(i18nConfig.NotionAPI)
.setDesc(i18nConfig.NotionAPIDesc)
.addText((text) => {
text.inputEl.type = 'password';
return text
.setPlaceholder(i18nConfig.NotionAPIText)
.setValue(this.plugin.settings.notionAPIGeneral)
.onChange(async (value) => {
this.plugin.settings.notionAPIGeneral = value;
await this.plugin.saveSettings();
})
});
new Setting(containerEl)
.setName(i18nConfig.DatabaseID)
.setDesc(i18nConfig.NotionAPIDesc)
.addText((text) => {
text.inputEl.type = 'password';
return text
.setPlaceholder(i18nConfig.NotionIDText)
.setValue(this.plugin.settings.databaseIDGeneral)
.onChange(async (value) => {
this.plugin.settings.databaseIDGeneral = value;
await this.plugin.saveSettings();
})
}
);
// Custom Database Settings
// containerEl.createEl('h2', {text: i18nConfig.NotionCustomSettingHeader});
//
// new Setting(containerEl)
// .setName(i18nConfig.NotionCustomButton)
// .setDesc(i18nConfig.NotionCustomButtonDesc)
// .addToggle((toggle) =>
// toggle
// .setValue(this.plugin.settings.CustomButton)
// .onChange(async (value) => {
// this.plugin.settings.CustomButton = value;
// await this.plugin.saveSettings();
// })
// );
}
}

51
src/upload/updateYaml.ts Normal file
View File

@@ -0,0 +1,51 @@
import {App, Notice, TFile} from "obsidian";
import ObsidianSyncNotionPlugin from "../main";
import {PluginSettings} from "../ui/settingTabs";
export async function updateYamlInfo(
yamlContent: string,
nowFile: TFile,
res: any,
app: App,
plugin: ObsidianSyncNotionPlugin,
) {
let {url, id} = res.json
// replace www to notionID
const { notionUser } = plugin.settings;
if (notionUser !== "") {
// replace url str "www" to notionID
url = url.replace("www.notion.so", `${notionUser}.notion.site`)
}
await app.fileManager.processFrontMatter(nowFile, yamlContent => {
if (yamlContent['notionID']) {
delete yamlContent['notionID']
}
if (yamlContent['link']) {
delete yamlContent['link']
}
// add new notionID and link
yamlContent.notionID = id;
yamlContent.link = url;
});
try {
await navigator.clipboard.writeText(url)
} catch (error) {
new Notice(`复制链接失败,请手动复制${error}`)
}
// const __content = yamlContent.__content;
// delete yamlContent.__content
// const yamlhead = yaml.stringify(yamlContent)
// // if yamlhead hava last \n remove it
// const yamlhead_remove_n = yamlhead.replace(/\n$/, '')
// // if __content have start \n remove it
// const __content_remove_n = __content.replace(/^\n/, '')
// const content = '---\n' +yamlhead_remove_n +'\n---\n' + __content_remove_n;
// try {
// await nowFile.vault.modify(nowFile, content)
// } catch (error) {
// new Notice(`write file error ${error}`)
// }
}

View File

@@ -0,0 +1,80 @@
import {i18nConfig} from "../lang/I18n";
import {App, Notice} from "obsidian";
import {Upload2NotionNext} from "./upload_next/Upload2NotionNext";
import {Upload2NotionGeneral} from "./upload_general/Upload2NotionGeneral";
import {PluginSettings} from "../ui/settingTabs";
import ObsidianSyncNotionPlugin from "../main";
import {getNowFileMarkdownContentNext} from "./upload_next/getMarkdownNext";
import {getNowFileMarkdownContentGeneral} from "./upload_general/getMarkdownGeneral";
export async function uploadCommandNext(
plugin: ObsidianSyncNotionPlugin,
settings: PluginSettings,
app: App,
) {
const {notionAPINext, databaseIDNext} = settings;
// Check if NNon exists
// if (NNon === undefined) {
// const NNonmessage = i18nConfig.NNonMissing;
// new Notice(NNonmessage);
// return;
// }
// Check if the user has set up the Notion API and database ID
if (notionAPINext === "" || databaseIDNext === "") {
const setAPIMessage = i18nConfig["set-api-id"];
new Notice(setAPIMessage);
return;
}
const {markDownData, nowFile, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime} = await getNowFileMarkdownContentNext(app, settings)
if (markDownData) {
const {basename} = nowFile;
const upload = new Upload2NotionNext(plugin);
const res = await upload.syncMarkdownToNotionNext(basename, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, markDownData, nowFile, this.app);
if (res.status === 200) {
new Notice(`${i18nConfig["sync-success"]}${basename}`);
} else {
new Notice(`${i18nConfig["sync-fail"]}${basename}`, 5000);
}
}
}
export async function uploadCommandGeneral(
plugin: ObsidianSyncNotionPlugin,
settings: PluginSettings,
app: App,
) {
const{ notionAPIGeneral, databaseIDGeneral} = settings;
// Check if the user has set up the Notion API and database ID
if (notionAPIGeneral === "" || databaseIDGeneral === "") {
const setAPIMessage = i18nConfig["set-api-id"];
new Notice(setAPIMessage);
return;
}
const {markDownData, nowFile,cover, tags} = await getNowFileMarkdownContentGeneral(app, settings)
if (markDownData) {
const {basename} = nowFile;
const upload = new Upload2NotionGeneral(plugin);
const res = await upload.syncMarkdownToNotionGeneral(basename, cover, tags, markDownData, nowFile, this.app);
if (res.status === 200) {
new Notice(`${i18nConfig["sync-success"]}${basename}`);
} else {
new Notice(`${i18nConfig["sync-fail"]}${basename}`, 5000);
}
}
}

View File

@@ -0,0 +1,90 @@
import {App, Notice, requestUrl, TFile} from "obsidian";
import {Client} from '@notionhq/client';
import {markdownToBlocks,} from "@tryfabric/martian";
import * as yamlFrontMatter from "yaml-front-matter";
// import * as yaml from "yaml"
import MyPlugin from "src/main";
export class UploadBaseGeneral {
plugin: MyPlugin;
notion: Client;
agent: any;
constructor(plugin: MyPlugin) {
this.plugin = plugin;
}
async deletePage(notionID: string) {
return requestUrl({
url: `https://api.notion.com/v1/blocks/${notionID}`,
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.plugin.settings.notionAPINext,
'Notion-Version': '2022-06-28',
},
body: ''
});
}
async getDataBase(databaseID: string) {
const response = await requestUrl({
url: `https://api.notion.com/v1/databases/${databaseID}`,
method: 'GET',
headers: {
'Authorization': 'Bearer ' + this.plugin.settings.notionAPINext,
'Notion-Version': '2022-06-28',
}
}
)
// Check if cover is present in the JSON response and then get the URL
if (response.json.cover && response.json.cover.external) {
return response.json.cover.external.url;
} else {
return null; // or some other default value, if you prefer
}
}
// async updateYamlInfo(yamlContent: string, nowFile: TFile, res: any, app: App, settings: any) {
// let {url, id} = res.json
// // replace www to notionID
// const {notionUser} = this.plugin.settings;
//
// if (notionUser !== "") {
// // replace url str "www" to notionID
// url = url.replace("www.notion.so", `${notionUser}.notion.site`)
// }
//
// await app.fileManager.processFrontMatter(nowFile, yamlContent => {
// if (yamlContent['notionID']) {
// delete yamlContent['notionID']
// }
// if (yamlContent['link']) {
// delete yamlContent['link']
// }
// // add new notionID and link
// yamlContent.notionID = id;
// yamlContent.link = url;
// });
//
// try {
// await navigator.clipboard.writeText(url)
// } catch (error) {
// new Notice(`复制链接失败,请手动复制${error}`)
// }
// // const __content = yamlContent.__content;
// // delete yamlContent.__content
// // const yamlhead = yaml.stringify(yamlContent)
// // // if yamlhead hava last \n remove it
// // const yamlhead_remove_n = yamlhead.replace(/\n$/, '')
// // // if __content have start \n remove it
// // const __content_remove_n = __content.replace(/^\n/, '')
// // const content = '---\n' +yamlhead_remove_n +'\n---\n' + __content_remove_n;
// // try {
// // await nowFile.vault.modify(nowFile, content)
// // } catch (error) {
// // new Notice(`write file error ${error}`)
// // }
// }
}

View File

@@ -0,0 +1,144 @@
import { App, Notice, requestUrl, TFile } from "obsidian";
import { Client } from '@notionhq/client';
import { markdownToBlocks, } from "@tryfabric/martian";
import * as yamlFrontMatter from "yaml-front-matter";
// import * as yaml from "yaml"
import MyPlugin from "src/main";
import {PluginSettings} from "../../ui/settingTabs";
import {UploadBaseGeneral} from "./BaseUpload2NotionGeneral";
import {updateYamlInfo} from "../updateYaml";
export class Upload2NotionGeneral extends UploadBaseGeneral {
settings: PluginSettings;
constructor(plugin: MyPlugin) {
super(plugin);
}
// 因为需要解析notion的block进行对比非常的麻烦
// 暂时就直接删除新建一个page
async updatePage(
notionID: string,
title: string,
cover: string,
tags: string[],
childArr: any
) {
await this.deletePage(notionID)
const databasecover = await this.getDataBase(this.plugin.settings.databaseIDGeneral)
if (cover == null) {
cover = databasecover
}
return await this.createPage(
title,
cover,
tags,
childArr)
}
async createPage(
title: string,
cover: string,
tags: string[],
childArr: any
) {
const bodyString: any = {
parent: {
database_id: this.plugin.settings.databaseIDGeneral,
},
properties: {
title: {
title: [
{
text: {
content: title
},
},
],
},
tags: {
multi_select: tags && true ? tags.map(tag => {
return { "name": tag }
}) : [],
},
},
children: childArr,
}
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
}
}
}
try {
return await requestUrl({
url: `https://api.notion.com/v1/pages`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
// 'User-Agent': 'obsidian.md',
'Authorization': 'Bearer ' + this.plugin.settings.notionAPIGeneral,
'Notion-Version': '2022-06-28',
},
body: JSON.stringify(bodyString),
})
} catch (error) {
new Notice(`network error ${error}`)
}
}
async syncMarkdownToNotionGeneral(
title: string,
cover: string,
tags: string[],
markdown: string,
nowFile: TFile,
app: App,
): Promise<any> {
let res: any
const yamlContent: any = yamlFrontMatter.loadFront(markdown);
const __content = yamlContent.__content
const file2Block = markdownToBlocks(__content);
const frontmasster = app.metadataCache.getFileCache(nowFile)?.frontmatter
const notionID = frontmasster ? frontmasster.notionID : null
if (notionID) {
res = await this.updatePage(
notionID,
title,
cover,
tags,
file2Block
);
} else {
res = await this.createPage(
title,
cover,
tags,
file2Block
);
}
if (res.status === 200) {
await updateYamlInfo(markdown, nowFile, res, app, this.plugin)
} else {
new Notice(`${res.text}`)
}
return res
}
}

View File

@@ -0,0 +1,33 @@
import {App, Notice} from "obsidian";
import {i18nConfig} from "../../lang/I18n";
import {PluginSettings} from "../../ui/settingTabs";
export async function getNowFileMarkdownContentGeneral(
app: App,
settings: PluginSettings,
) {
const nowFile = app.workspace.getActiveFile();
let cover = '';
let tags = [];
const FileCache = app.metadataCache.getFileCache(nowFile);
try {
cover = FileCache.frontmatter.coverurl;
tags = FileCache.frontmatter.tags;
} catch (error) {
new Notice(i18nConfig["set-tags-fail"]);
}
if (nowFile) {
const markDownData = await nowFile.vault.read(nowFile);
return {
markDownData,
nowFile,
cover,
tags,
};
} else {
new Notice(i18nConfig["open-file"]);
return;
}
}

View File

@@ -0,0 +1,90 @@
import {App, Notice, requestUrl, TFile} from "obsidian";
import {Client} from '@notionhq/client';
import {markdownToBlocks,} from "@tryfabric/martian";
import * as yamlFrontMatter from "yaml-front-matter";
// import * as yaml from "yaml"
import MyPlugin from "src/main";
export class UploadBaseNext {
plugin: MyPlugin;
notion: Client;
agent: any;
constructor(plugin: MyPlugin) {
this.plugin = plugin;
}
async deletePage(notionID: string) {
return requestUrl({
url: `https://api.notion.com/v1/blocks/${notionID}`,
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.plugin.settings.notionAPINext,
'Notion-Version': '2022-06-28',
},
body: ''
});
}
async getDataBase(databaseID: string) {
const response = await requestUrl({
url: `https://api.notion.com/v1/databases/${databaseID}`,
method: 'GET',
headers: {
'Authorization': 'Bearer ' + this.plugin.settings.notionAPINext,
'Notion-Version': '2022-06-28',
}
}
)
// Check if cover is present in the JSON response and then get the URL
if (response.json.cover && response.json.cover.external) {
return response.json.cover.external.url;
} else {
return null; // or some other default value, if you prefer
}
}
// async updateYamlInfo(yamlContent: string, nowFile: TFile, res: any, app: App, settings: any) {
// let {url, id} = res.json
// // replace www to notionID
// const { notionUser} = this.plugin.settings;
//
// if (notionUser !== "") {
// // replace url str "www" to notionID
// url = url.replace("www.notion.so", `${notionUser}.notion.site`)
// }
//
// await app.fileManager.processFrontMatter(nowFile, yamlContent => {
// if (yamlContent['notionID']) {
// delete yamlContent['notionID']
// }
// if (yamlContent['link']) {
// delete yamlContent['link']
// }
// // add new notionID and link
// yamlContent.notionID = id;
// yamlContent.link = url;
// });
//
// try {
// await navigator.clipboard.writeText(url)
// } catch (error) {
// new Notice(`复制链接失败,请手动复制${error}`)
// }
// // const __content = yamlContent.__content;
// // delete yamlContent.__content
// // const yamlhead = yaml.stringify(yamlContent)
// // // if yamlhead hava last \n remove it
// // const yamlhead_remove_n = yamlhead.replace(/\n$/, '')
// // // if __content have start \n remove it
// // const __content_remove_n = __content.replace(/^\n/, '')
// // const content = '---\n' +yamlhead_remove_n +'\n---\n' + __content_remove_n;
// // try {
// // await nowFile.vault.modify(nowFile, content)
// // } catch (error) {
// // new Notice(`write file error ${error}`)
// // }
// }
}

View File

@@ -1,22 +1,41 @@
import {UploadBase} from "./BaseUpload2Notion";
import { UploadBaseNext } from "./BaseUpload2NotionNext";
import { App, Notice, requestUrl, TFile } from "obsidian";
import { Client } from '@notionhq/client';
import { markdownToBlocks, } from "@tryfabric/martian";
import * as yamlFrontMatter from "yaml-front-matter";
// import * as yaml from "yaml"
import MyPlugin from "src/main";
import {PluginSettings} from "../../ui/settingTabs";
import {updateYamlInfo} from "../updateYaml";
export class Upload2NotionNext extends UploadBase {
constructor(plugin: MyPlugin) {
export class Upload2NotionNext extends UploadBaseNext {
settings: PluginSettings;
constructor(plugin: MyPlugin) {
super(plugin);
}
// 因为需要解析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) {
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 databasecover = await this.getDataBase(this.plugin.settings.databaseID)
const databasecover = await this.getDataBase(this.plugin.settings.databaseIDNext)
if (cover == null) {
cover = databasecover
@@ -38,10 +57,24 @@ export class Upload2NotionNext extends UploadBase {
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
) {
const bodyString: any = {
parent: {
database_id: this.plugin.settings.databaseID
database_id: this.plugin.settings.databaseIDNext
},
icon: {
emoji: emoji || '📜'
@@ -145,7 +178,7 @@ export class Upload2NotionNext extends UploadBase {
headers: {
'Content-Type': 'application/json',
// 'User-Agent': 'obsidian.md',
'Authorization': 'Bearer ' + this.plugin.settings.notionAPI,
'Authorization': 'Bearer ' + this.plugin.settings.notionAPINext,
'Notion-Version': '2022-06-28',
},
body: JSON.stringify(bodyString),
@@ -155,7 +188,23 @@ export class Upload2NotionNext extends UploadBase {
}
}
async syncMarkdownToNotion(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, settings: any): Promise<any> {
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> {
let res: any
const yamlContent: any = yamlFrontMatter.loadFront(markdown);
const __content = yamlContent.__content
@@ -164,12 +213,41 @@ export class Upload2NotionNext extends UploadBase {
const notionID = frontmasster ? frontmasster.notionID : null
if (notionID) {
res = await this.updatePage(notionID, title, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, file2Block);
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);
res = await this.createPage(
title,
emoji,
cover,
tags,
type,
slug,
stats,
category,
summary,
paword,
favicon,
datetime,
file2Block
);
}
if (res.status === 200) {
await this.updateYamlInfo(markdown, nowFile, res, app, settings)
await updateYamlInfo(markdown, nowFile, res, app, this.plugin)
} else {
new Notice(`${res.text}`)
}

View File

@@ -0,0 +1,59 @@
import {App, Notice} from "obsidian";
import {i18nConfig} from "../../lang/I18n";
import {PluginSettings} from "../../ui/settingTabs";
export async function getNowFileMarkdownContentNext(
app: App,
settings: PluginSettings,
) {
const nowFile = app.workspace.getActiveFile();
let emoji = '';
let cover = '';
let tags = [];
let type = '';
let slug = '';
let stats = '';
let category = '';
let summary = '';
let paword = '';
let favicon = '';
let datetime = '';
const FileCache = app.metadataCache.getFileCache(nowFile);
try {
emoji = FileCache.frontmatter.titleicon;
cover = FileCache.frontmatter.coverurl;
tags = FileCache.frontmatter.tags;
type = FileCache.frontmatter.type;
slug = FileCache.frontmatter.slug;
stats = FileCache.frontmatter.stats;
category = FileCache.frontmatter.category;
summary = FileCache.frontmatter.summary;
paword = FileCache.frontmatter.password;
favicon = FileCache.frontmatter.icon;
datetime = FileCache.frontmatter.date;
} catch (error) {
new Notice(i18nConfig["set-tags-fail"]);
}
if (nowFile) {
const markDownData = await nowFile.vault.read(nowFile);
return {
markDownData,
nowFile,
emoji,
cover,
tags,
type,
slug,
stats,
category,
summary,
paword,
favicon,
datetime,
};
} else {
new Notice(i18nConfig["open-file"]);
return;
}
}