Compare commits

...

54 Commits
0.1.4 ... 1.1.1

Author SHA1 Message Date
Jiaxin Peng
630e3a20c2 Update version to 1.1.1 2023-11-23 11:54:50 +00:00
Jiaxin Peng
040b72b760 Update version to 1.1.0 2023-11-20 22:01:20 +00:00
Jiaxin Peng
7df4b5e9c8 Merge pull request #9 from jxpeng98/package-test
package update and add tag syncing button
2023-11-20 21:59:53 +00:00
Jiaxin Peng
3f35a56b6e rebuild the locale file and add tag button to control tag syncing function 2023-11-20 21:57:30 +00:00
Jiaxin Peng
3c7e266a35 setting tab bug fix 2023-11-20 17:07:04 +00:00
Jiaxin Peng
8201c706ea remove block limit and update packages 2023-11-16 21:09:31 +00:00
Jiaxin Peng
4433ea449d Update version to 1.0.1 2023-11-16 13:55:14 +00:00
Jiaxin Peng
96126d1334 Jump to version 1.0.0 2023-11-16 13:32:07 +00:00
Jiaxin Peng
b3702a9cc1 Update version to 1.0.0 2023-11-16 13:29:29 +00:00
Jiaxin Peng
ba9b477db7 Update version to 0.2.7 2023-11-16 13:27:48 +00:00
Jiaxin Peng
fb6951cfdf Update version to 0.3.5 2023-11-16 13:25:56 +00:00
Jiaxin Peng
6454c0417d Update version to 0.3.4 2023-11-16 13:10:53 +00:00
Jiaxin Peng
35f19a9f43 modify the action file 2023-11-16 13:10:27 +00:00
Jiaxin Peng
8e32e8f0f5 Update version to 0.3.3 2023-11-16 12:59:41 +00:00
Jiaxin Peng
880f256ae1 Update version to 0.3.2 2023-11-16 12:55:01 +00:00
Jiaxin Peng
bf9c3f2933 Update version to 0.3.1 2023-11-16 11:58:58 +00:00
Jiaxin Peng
2ac354299a update action file 2023-11-16 11:58:44 +00:00
Jiaxin Peng
8317abb667 Update version to 0.3.0 2023-11-16 11:50:36 +00:00
Jiaxin Peng
d74634aca6 Merge pull request #7 from jxpeng98/custom-title
Custom title
2023-11-16 11:48:14 +00:00
Jiaxin Peng
d400b92263 update readme 2023-11-16 11:44:45 +00:00
Jiaxin Peng
e7fa597e5a update translate 2023-11-16 11:14:19 +00:00
Jiaxin Peng
6ce689ba96 complete the basic customisation feature 2023-11-16 01:00:52 +00:00
Jiaxin Peng
b978cf7e01 complete the setting ui 2023-11-16 00:02:35 +00:00
Jiaxin Peng
4e3c88f129 reorganise the code for add new setting container 2023-11-15 12:25:30 +00:00
Jiaxin Peng
6550bca70f reorganise the setting coding 2023-11-15 09:34:22 +00:00
Jiaxin Peng
662edbb84c remove the collapse details 2023-11-15 00:16:19 +00:00
Jiaxin Peng
671936ee41 add some details for collapse 2023-11-15 00:15:52 +00:00
Jiaxin Peng
2b16ea76c6 update the setting ui 2023-11-14 23:27:38 +00:00
Jiaxin Peng
399a02187f update packages and complete the setting UI 2023-11-14 15:42:30 +00:00
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
Jiaxin Peng
9be9b18efb Update version to 0.2.0 2023-11-01 23:24:34 +00:00
Jiaxin Peng
588f57205b Modified the template and rebuilt the interactive logic 2023-11-01 23:24:18 +00:00
Jiaxin Peng
cfbedea91d Update version to 0.1.10 2023-11-01 10:32:35 +00:00
Jiaxin Peng
4cd6557444 chinese support in settings 2023-11-01 10:32:22 +00:00
Jiaxin Peng
407688c303 Update version to 0.1.9 2023-11-01 09:53:29 +00:00
Jiaxin Peng
84b998aa93 initialise the NNon value and add i18n 2023-11-01 09:53:14 +00:00
Jiaxin Peng
4b6f1a1f1d Update version to 0.1.8 2023-10-31 23:56:50 +00:00
Jiaxin Peng
4a2c59d13b Update version to 0.1.7 2023-10-11 23:05:46 +01:00
Jiaxin Peng
8f116956ce Update version to 0.1.6 2023-09-28 12:00:40 +01:00
Jiaxin Peng
df138d9304 Update version to 0.1.5 2023-08-29 15:18:41 +01:00
34 changed files with 3192 additions and 942 deletions

View File

@@ -1,26 +0,0 @@
name: CI
on:
push:
branches:
- "*"
env:
PLUGIN_NAME: share-to-notionnext
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 16
- name: Build
id: build
run: |
npm install
npm run build

View File

@@ -1,98 +1,99 @@
name: Release Obsidian plugin name: Release
on: on:
push: push:
tags: tags:
- "*" - "*"
env: env:
PLUGIN_NAME: share-to-notionnext # Change this to match the id of your plugin. PLUGIN_NAME: share-to-notionnext # Change this to match the id of your plugin.
jobs: jobs:
build: build:
runs-on: ubuntu-latest name: release
runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: "16.x" node-version: "18"
- name: Build - name: Build
id: build id: build
run: | run: |
npm install npm install
npm run build npm run build
mkdir ${{ env.PLUGIN_NAME }} mkdir ${{ env.PLUGIN_NAME }}
cp main.js manifest.json ${{ env.PLUGIN_NAME }} cp main.js manifest.json ${{ env.PLUGIN_NAME }}
zip -r ${{ env.PLUGIN_NAME }}.zip ${{ env.PLUGIN_NAME }} zip -r ${{ env.PLUGIN_NAME }}.zip ${{ env.PLUGIN_NAME }}
ls ls
echo "::set-output name=tag_name::$(git tag --sort version:refname | tail -n 1)" echo "tag_name=$(git tag --sort version:refname | tail -n 1)" >> $GITHUB_OUTPUT
- name: Create Release - name: Create Release
id: create_release id: create_release
uses: actions/create-release@v1 uses: actions/create-release@v1
env: env:
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
VERSION: ${{ github.ref }} VERSION: ${{ github.ref }}
with: with:
tag_name: ${{ github.ref }} tag_name: ${{ github.ref }}
release_name: ${{ github.ref }} release_name: ${{ github.ref }}
draft: false draft: false
prerelease: false prerelease: false
- name: Upload zip file - name: Upload zip file
id: upload-zip id: upload-zip
uses: actions/upload-release-asset@v1 uses: actions/upload-release-asset@v1
env: env:
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
with: with:
upload_url: ${{ steps.create_release.outputs.upload_url }} upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./${{ env.PLUGIN_NAME }}.zip asset_path: ./${{ env.PLUGIN_NAME }}.zip
asset_name: ${{ env.PLUGIN_NAME }}-${{ steps.build.outputs.tag_name }}.zip asset_name: ${{ env.PLUGIN_NAME }}-${{ steps.build.outputs.tag_name }}.zip
asset_content_type: application/zip asset_content_type: application/zip
- name: Upload main.js - name: Upload main.js
id: upload-main id: upload-main
uses: actions/upload-release-asset@v1 uses: actions/upload-release-asset@v1
env: env:
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
with: with:
upload_url: ${{ steps.create_release.outputs.upload_url }} upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./main.js asset_path: ./main.js
asset_name: main.js asset_name: main.js
asset_content_type: text/javascript asset_content_type: text/javascript
- name: Upload manifest.json - name: Upload manifest.json
id: upload-manifest id: upload-manifest
uses: actions/upload-release-asset@v1 uses: actions/upload-release-asset@v1
env: env:
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
with: with:
upload_url: ${{ steps.create_release.outputs.upload_url }} upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./manifest.json asset_path: ./manifest.json
asset_name: manifest.json asset_name: manifest.json
asset_content_type: application/json asset_content_type: application/json
- name: Upload markdown template - name: Upload markdown template
id: upload-md id: upload-md
uses: actions/upload-release-asset@v1 uses: actions/upload-release-asset@v1
env: env:
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
with: with:
upload_url: ${{ steps.create_release.outputs.upload_url }} upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./obsidian_template.md asset_path: ./obsidian_template.md
asset_name: template.md asset_name: template.md
asset_content_type: text/markdown asset_content_type: text/markdown
# - name: Upload styles.css # - name: Upload styles.css
# id: upload-css # id: upload-css
# uses: actions/upload-release-asset@v1 # uses: actions/upload-release-asset@v1
# env: # env:
# GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} # GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
# with: # with:
# upload_url: ${{ steps.create_release.outputs.upload_url }} # upload_url: ${{ steps.create_release.outputs.upload_url }}
# asset_path: ./styles.css # asset_path: ./styles.css
# asset_name: styles.css # asset_name: styles.css
# asset_content_type: text/css # asset_content_type: text/css

33
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Test and Build
on:
push:
branches:
- "*"
- "!master"
env:
PLUGIN_NAME: share-to-notionnext # Change this to match the id of your plugin.
jobs:
build:
name: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: "18"
- name: Build
id: build
run: |
npm install
npm run build
mkdir ${{ env.PLUGIN_NAME }}
cp main.js manifest.json ${{ env.PLUGIN_NAME }}
zip -r ${{ env.PLUGIN_NAME }}.zip ${{ env.PLUGIN_NAME }}
ls
echo "tag_name=$(git tag --sort version:refname | tail -n 1)" >> $GITHUB_OUTPUT

View File

@@ -1,15 +1,98 @@
# Obsidian share to NotionNext # Obsidian share to NotionNext
感谢[原作者](https://github.com/EasyChris/obsidian-to-notion)开发出了这么好用的插件能够将obsidian同步到notion。 但是原仓库只能同步Name和Tags信息如果像我一样通过[NotionNext](https://github.com/tangly1024/NotionNext)来搭建自己的网页,就有一些局限性。每次导入之后都需要进行大量的修改。 感谢[原作者](https://github.com/EasyChris/obsidian-to-notion)开发出了这么好用的插件能够将obsidian同步到notion。 但是原仓库只能同步Name和Tags信息如果像我一样通过[NotionNext](https://github.com/tangly1024/NotionNext)来搭建自己的网页,就有一些局限性。每次导入之后都需要进行大量的修改。
所以我在[原作者](https://github.com/EasyChris/obsidian-to-notion)的基础之上,增加了匹配[NotionNext](https://github.com/tangly1024/NotionNext)模板的功能。这样可以直接在Obsidian编辑整理好之后一键发布。 所以我在[原作者](https://github.com/EasyChris/obsidian-to-notion)的基础之上,增加了匹配[NotionNext](https://github.com/tangly1024/NotionNext)模板的功能。这样可以直接在Obsidian编辑整理好之后一键发布。
## 更新说明
### 1.1.1
- 修复了在日语系统下,无法显示设置按钮的错误。
- 增加日语翻译。
### 1.1.0
- 修复设置中自定义标题的显示问题。
- 增加了标签同步的控制按钮。以减少空标签集造成的上传失败。
如果你不想使用同步标签功能你可以在设置中关闭。不论你在md文件表头添加了tags与否都不会将标签同步到Notion数据库中。
如果你需要同步标签到Notion数据库中**你需要通过如下格式添加表填到md表头中。**
```yaml
tags: #空标签选项1
tags: [test,test1,test2] # 用中括号将所有的标签括起来选项2
tags:
- test
- test1
- test2 # 每个标签单独一行选项3
```
### 1.0.1
- 修复了自定义标题在设置菜单中显示错误的问题。
### 1.0.0 (大更新)
- 这个版本开始,你可以**任意修改第一列表头的名字 (标题列,默认:'title')**。 **注意你必须保证你的Notion数据库中有'tags这一列的存在并且在markdown文件中把`tags:`添加到你的YAML表头中。否则会返回`400 错误`。但是你可以`tags:`设置为空。**
![](https://minioapi.pjx.ac.cn/img1/2023/11/4a298b9be3990e9d2201bf2f50ca5a0a.png)
例如这样:
![](https://minioapi.pjx.ac.cn/img1/2023/11/4cd8d79cd9dd9dde299e39c666cb3473.gif)
- 增加了一个控制按钮来控制是否开启当前数据库同步命令的功能。如果你关闭了这个按钮,你在上传命令列表中就不会出现当前数据库的选项。
![](https://minioapi.pjx.ac.cn/img1/2023/11/becb60fc44783842da4b3cf4c322f363.gif)
### 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
- 从这个版本开始,重构了交互逻辑。现在当你点击左侧的按钮,会弹出可同步的数据库选项。你可以选择你想要同步的数据库,然后点击同步按钮。**但是现在仅支持同步单个数据库如果你的数据库不是NotionNext你可以不用更新。**
### 0.1.10
- 修正了设置中的中文显示。
### 0.1.8
- 重新整理了代码,增加了一个仓库转换按钮为之后的多数据库支持作准备。**但是现在还不支持多数据库如果你的数据库不是NotionNext你可以不用更新。**
### 0.1.7
- [x] 删除了设置中`convert tags`的选项。 你现在可以直接添加tags而不需要考虑是否开启tags选项。如果你不需要tags可以直接删除tags选项或者留白。
## 使用方式 ## 使用方式
### 注意事项 ### 注意事项
本插件现在暂时只能用于匹配[NotionNext](https://github.com/tangly1024/NotionNext)。如果你不是使用这个模板,你只会无限返回`error 400`. 本插件现在暂时只能用于匹配[NotionNext](https://github.com/tangly1024/NotionNext)。如果你不是使用这个模板,你只会无限返回`error 400`.
所以没有NotionNext需求的请使用原作者的[Obsidian-to-notion](https://github.com/EasyChris/obsidian-to-notion) 所以没有NotionNext需求的请使用原作者的[Obsidian-to-notion](https://github.com/EasyChris/obsidian-to-notion)
### 准备安装 ### 准备安装
在安装插件之前,你必须配置好了以下内容: 在安装插件之前,你必须配置好了以下内容:
1. 你的NotionNext数据库。 1. 你的NotionNext数据库。
@@ -28,25 +111,33 @@
- icon - icon
在最新的0.0.6版本,我还增加了以下内容: 在最新的0.0.6版本,我还增加了以下内容:
- titleicon 标题的emoji图标,暂时只能支持emoji - titleicon 标题的emoji图标,暂时只能支持emoji
- coverurl 封面图片的url url可以是任何一种图片的url 例如jpgpngsvg等等。 - coverurl 封面图片的url url可以是任何一种图片的url 例如jpgpngsvg等等。
**如果你是直接复制的NotionNext的模板这些内容应该已经有了。我在原作者的基础之上对本插件的内容进行了更改所以你只需要保证你的数据库有如上内容并且所有的字母都是小写** **如果你是直接复制的NotionNext的模板这些内容应该已经有了。我在原作者的基础之上对本插件的内容进行了更改所以你只需要保证你的数据库有如上内容并且所有的字母都是小写**
**⚠️⚠️⚠️:表头全部小写!!!顺序无所谓!** **⚠️⚠️⚠️:表头全部小写!!!顺序无所谓!**
### 安装插件 ### 安装插件
#### 社区插件市场下载
打开`Obsidian -> 设置 -> 社区插件 -> 浏览 -> 搜索Share to NotionNext`, 然后点击安装。
#### 手动安装
1. 关闭Obsidian 1. 关闭Obsidian
2. 从Release下载插件文件解压到你的obsidian插件目录下。 2. 从Release下载插件文件解压到你的obsidian插件目录下。
3. 重新打开Obsidian进入设置启用插件。 3. 重新打开Obsidian进入设置启用插件。
4. 在设置中找到Obsidian to NotionNext填入你的NotionNext Database ID 和 API token。 4. 在设置中找到Obsidian to NotionNext填入你的NotionNext Database ID 和 API token。
### 使用插件 ### 使用插件
在仓库中我上传了一个模板你可以直接复制到你的模板文件夹中。然后使用Obsidian的模板功能一键生成新笔记。 在仓库中我上传了一个模板你可以直接复制到你的模板文件夹中。然后使用Obsidian的模板功能一键生成新笔记。
如果你不想使用模板你也可以直接在Obsidian中创建一个新的文件然后复制下边的内容。然后保存。 如果你不想使用模板你也可以直接在Obsidian中创建一个新的文件然后复制下边的内容。然后保存。
```markdown ```markdown
--- ---
# default value has been set. # default value has been set.
@@ -58,6 +149,7 @@
# 现在阶段一定不要修改表头的名字, please do not change the name of the header in YAML front matter # 现在阶段一定不要修改表头的名字, please do not change the name of the header in YAML front matter
# !!!!!!!!!!!! # !!!!!!!!!!!!
titleicon: 📎 # emoji icon, default is 📜, 默认是📜 titleicon: 📎 # emoji icon, default is 📜, 默认是📜
date: 2023-07-23 # default is today 默认是今天。 Format is YYYY-MM-DD 格式是YYYY-MM-DD
coverurl: https://img.jxpeng.dev/2023/08/843e27a210847f05a0f7cfb121fec100.jpg # default is empty 默认是空 coverurl: https://img.jxpeng.dev/2023/08/843e27a210847f05a0f7cfb121fec100.jpg # default is empty 默认是空
type: Post # Post or Page, default is Post 默认是Post type: Post # Post or Page, default is Post 默认是Post
slug: test # slug for url, default is empty 默认是空 slug: test # slug for url, default is empty 默认是空
@@ -76,12 +168,12 @@ Contents Below
``` ```
模板使用如下: 模板使用如下:
![](https://img.jxpeng.dev/2023/08/5ba5e7aeb86650c060c620786371717c.mp4) ![](https://minioapi.pjx.ac.cn/img1/2023/09/354b950e5777b48832c2475e4a31f2cc.gif)
**插件预览如下** **插件预览如下**
![](https://img.jxpeng.dev/2023/08/7edefe36899b7431a65db891f429a137.mp4) ![](https://minioapi.pjx.ac.cn/img1/2023/09/d6199619b68fab218fca8ae0cebece78.gif)
--- ---
@@ -90,6 +182,7 @@ Contents Below
非常感谢原作者的开发,我只是在原作者的基础之上进行了修改,增加了一些功能。如果你觉得这个插件对你有帮助,可以给[原作者](https://github.com/EasyChris/obsidian-to-notion)一个star。 非常感谢原作者的开发,我只是在原作者的基础之上进行了修改,增加了一些功能。如果你觉得这个插件对你有帮助,可以给[原作者](https://github.com/EasyChris/obsidian-to-notion)一个star。
# Obsidian to Notion # Obsidian to Notion
[![](https://github.com/Easychris/obsidian-to-notion/actions/workflows/CI.yml/badge.svg)](https://github.com/Easychris/obsidian-to-notion/actions/workflows/CI.yml) [![](https://github.com/Easychris/obsidian-to-notion/actions/workflows/CI.yml/badge.svg)](https://github.com/Easychris/obsidian-to-notion/actions/workflows/CI.yml)
[![Release Obsidian plugin](https://github.com/Easychris/obsidian-to-notion/actions/workflows/release.yml/badge.svg)](https://github.com/Easychris/obsidian-to-notion/actions/workflows/release.yml) [![Release Obsidian plugin](https://github.com/Easychris/obsidian-to-notion/actions/workflows/release.yml/badge.svg)](https://github.com/Easychris/obsidian-to-notion/actions/workflows/release.yml)
[![GitHub license](https://camo.githubusercontent.com/400c4e52df43f6a0ab8a89b74b1a78d1a64da56a7848b9110c9d2991bb7c3105/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d47504c76332d626c75652e737667)](https://raw.githubusercontent.com/EasyChris/obsidian-to-notion/master/LICENSE) [![GitHub license](https://camo.githubusercontent.com/400c4e52df43f6a0ab8a89b74b1a78d1a64da56a7848b9110c9d2991bb7c3105/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d47504c76332d626c75652e737667)](https://raw.githubusercontent.com/EasyChris/obsidian-to-notion/master/LICENSE)
@@ -105,31 +198,40 @@ Obsidian share to Notion [English](README.md)
![](./doc/1.gif) ![](./doc/1.gif)
# 使用方式 # 使用方式
## 安装插件 ## 安装插件
### 市场下载 ### 市场下载
插件市场搜索 noiton 即可下载 插件市场搜索 noiton 即可下载
![](https://afox-1256168983.cos.ap-shanghai.myqcloud.com/20220628214145.png) ![](https://afox-1256168983.cos.ap-shanghai.myqcloud.com/20220628214145.png)
### BRAT ### BRAT
插件中中心搜索 BRAT 插件中中心搜索 BRAT
添加 `EasyChris/obsidian-to-notion` 到 BRAT 插件安装列表中 添加 `EasyChris/obsidian-to-notion` 到 BRAT 插件安装列表中
返回插件中心启用即可 返回插件中心启用即可
### 手动安装 ### 手动安装
``` ```
cd YOUR_OBSIDIAN_FOLDER/.obsidian/plugins/ cd YOUR_OBSIDIAN_FOLDER/.obsidian/plugins/
git clone https://github.com/EasyChris/obsidian-to-notion.git git clone https://github.com/EasyChris/obsidian-to-notion.git
``` ```
## 申请 Notion API ## 申请 Notion API
官方参考文档:[https://developers.notion.com/docs](https://developers.notion.com/docs) 官方参考文档:[https://developers.notion.com/docs](https://developers.notion.com/docs)
### 第 1 步创建integration。
### 第 1 步创建integration
转到 [https://www.notion.com/my-integrations](https://www.notion.com/my-integrations) 转到 [https://www.notion.com/my-integrations](https://www.notion.com/my-integrations)
创建完成之后,复制`secrets toekn` 创建完成之后,复制`secrets toekn`
![](https://files.readme.io/2ec137d-093ad49-create-integration.gif) ![](https://files.readme.io/2ec137d-093ad49-create-integration.gif)
### 第2步与你的集成共享一个数据库 ### 第2步与你的集成共享一个数据库
新建一个的page权限为公开 新建一个的page权限为公开
在page中新建一个数据库 -> 需要`full page database` 在page中新建一个数据库 -> 需要`full page database`
![](./doc/3.gif) ![](./doc/3.gif)
@@ -144,9 +246,6 @@ git clone https://github.com/EasyChris/obsidian-to-notion.git
![](https://afox-1256168983.cos.ap-shanghai.myqcloud.com/20220618102029.png) ![](https://afox-1256168983.cos.ap-shanghai.myqcloud.com/20220618102029.png)
### 第三步复制database ID ### 第三步复制database ID
``` ```
@@ -155,27 +254,28 @@ https://www.notion.so/myworkspace/a8aec43384f447ed84390e8e42c2e089?v=...
``` ```
## 打开插件配置 ## 打开插件配置
将得到的 `NOTION_API_KEY``DATABASE_ID`填入配置当中 将得到的 `NOTION_API_KEY``DATABASE_ID`填入配置当中
![](./doc/2.png) ![](./doc/2.png)
## 上传文件内容到notion ## 上传文件内容到notion
点击上传notion的按钮 点击上传notion的按钮
![](./doc/4.png) ![](./doc/4.png)
上传成功之后会自动生成一个分享链接 上传成功之后会自动生成一个分享链接
![](./doc/5.png) ![](./doc/5.png)
## 页面 Banner 链接[可选] ## 页面 Banner 链接[可选]
默认可以不填写 默认可以不填写
横幅URL必须是图像URL例如https//i.imgur.com/xxx.jpg 横幅URL必须是图像URL例如https//i.imgur.com/xxx.jpg
## Notion ID [可选] ## Notion ID [可选]
Notion ID是你想分享文件的页面ID。 Notion ID是你想分享文件的页面ID。
如果你不写它notion将分享到默认的链接https://www.notion.so/myworkspace/a8aec43384f447ed84390访问这个页面将重定向到你的网站页面 如果你不写它notion将分享到默认的链接<https://www.notion.so/myworkspace/a8aec43384f447ed84390访问这个页面将重定向到你的网站页面>
如果你写了Notion ID它将分享到页面链接如https://your_user_name.notion.site/myworkspace/a8aec43384f447ed84390不需要重定向网址 如果你写了Notion ID它将分享到页面链接如<https://your_user_name.notion.site/myworkspace/a8aec43384f447ed84390不需要重定向网址>
## 同步图片 ## 同步图片
@@ -186,6 +286,7 @@ Notion ID是你想分享文件的页面ID。
[顿顿饭](https://dun.mianbaoduo.com/@easy) [顿顿饭](https://dun.mianbaoduo.com/@easy)
# 感谢 # 感谢
[开发流程 | Obsidian 插件开发文档](https://luhaifeng666.github.io/obsidian-plugin-docs-zh/zh/getting-started/development-workflow.html) [开发流程 | Obsidian 插件开发文档](https://luhaifeng666.github.io/obsidian-plugin-docs-zh/zh/getting-started/development-workflow.html)
[GitHub - devbean/obsidian-wordpress: An obsidian plugin for publishing docs to WordPress.](https://github.com/devbean/obsidian-wordpress) [GitHub - devbean/obsidian-wordpress: An obsidian plugin for publishing docs to WordPress.](https://github.com/devbean/obsidian-wordpress)

632
README.html Normal file
View File

@@ -0,0 +1,632 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
<meta charset="utf-8">
<meta name="generator" content="quarto-1.3.450">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>readme</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
ul.task-list li input[type="checkbox"] {
width: 0.8em;
margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */
vertical-align: middle;
}
/* CSS for syntax highlighting */
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
}
pre.numberSource { margin-left: 3em; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
</style>
<script src="README_files/libs/clipboard/clipboard.min.js"></script>
<script src="README_files/libs/quarto-html/quarto.js"></script>
<script src="README_files/libs/quarto-html/popper.min.js"></script>
<script src="README_files/libs/quarto-html/tippy.umd.min.js"></script>
<script src="README_files/libs/quarto-html/anchor.min.js"></script>
<link href="README_files/libs/quarto-html/tippy.css" rel="stylesheet">
<link href="README_files/libs/quarto-html/quarto-syntax-highlighting.css" rel="stylesheet" id="quarto-text-highlighting-styles">
<script src="README_files/libs/bootstrap/bootstrap.min.js"></script>
<link href="README_files/libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
<link href="README_files/libs/bootstrap/bootstrap.min.css" rel="stylesheet" id="quarto-bootstrap" data-mode="light">
</head>
<body class="fullcontent">
<div id="quarto-content" class="page-columns page-rows-contents page-layout-article">
<main class="content" id="quarto-document-content">
<section id="obsidian-to-notionnext" class="level1">
<h1>Obsidian to NotionNext</h1>
<p><a href="https://github.com/jxpeng98/obsidian-to-NotionNext/actions/workflows/test.yml"><img src="https://github.com/jxpeng98/obsidian-to-NotionNext/actions/workflows/test.yml/badge.svg" class="img-fluid" alt="test.yml"></a> <a href="https://github.com/jxpeng98/obsidian-to-NotionNext/actions/workflows/release.yml"><img src="https://github.com/jxpeng98/obsidian-to-NotionNext/actions/workflows/release.yml/badge.svg" class="img-fluid" alt="Release Obsidian plugin"></a> <a href="https://GitHub.com/jxpeng98/obsidian-to-NotionNext/releases/"><img src="https://img.shields.io/github/downloads/jxpeng98/obsidian-to-NotionNext/total.svg" class="img-fluid" alt="Github all releases"></a> <a href="https://github.com/jxpeng98/obsidian-to-NotionNext/releases"><img src="https://badgen.net/github/release/jxpeng98/obsidian-to-NotionNext.png" class="img-fluid" alt="GitLab latest release"></a></p>
<p><a href="README-zh.md">中文文档</a></p>
<p>Thanks to the <a href="https://github.com/EasyChris/obsidian-to-notion">original author</a> for developing such a useful plugin that can synchronize Obsidian to Notion. However, the original repository can only sync Name and Tags information. For those like me who use <a href="https://github.com/tangly1024/NotionNext">NotionNext</a> to set up their website, this presents some limitations. Every time I import, I need to make a lot of modifications.</p>
<p>Thus, based on the <a href="https://github.com/EasyChris/obsidian-to-notion">original authors work</a>, Ive added a feature to match the <a href="https://github.com/tangly1024/NotionNext">NotionNext</a> template. This way, you can edit directly in Obsidian and publish with a single click after organizing.</p>
<p><strong>Now, support both NotionNext and General databases.</strong></p>
<section id="update" class="level2">
<h2 class="anchored" data-anchor-id="update">Update</h2>
<section id="section" class="level3">
<h3 class="anchored" data-anchor-id="section">1.0.1</h3>
<ul>
<li>Fix the custom name element display bug in the settings.</li>
</ul>
</section>
<section id="big-update" class="level3">
<h3 class="anchored" data-anchor-id="big-update">1.0.0 (Big Update)</h3>
<ul>
<li>From this version, you can <strong>modify the first column name (title column, default: title)</strong> as you want. (<strong>Note: You need to have the tags column in your Notion General database, and add <code>tags:</code> in your markdown frontmatter. If not, you will receive <code>network error 400</code>. But you can leave the <code>tags:</code> blank.</strong>)</li>
</ul>
<p><img src="https://minioapi.pjx.ac.cn/img1/2023/11/4a298b9be3990e9d2201bf2f50ca5a0a.png" class="img-fluid"> Like this: <img src="https://minioapi.pjx.ac.cn/img1/2023/11/4cd8d79cd9dd9dde299e39c666cb3473.gif" class="img-fluid"></p>
<ul>
<li>Add a switch button to control whether display the setting tabs in the plugin settings for both NotionNext and Notion General databases.</li>
</ul>
<p><img src="https://minioapi.pjx.ac.cn/img1/2023/11/becb60fc44783842da4b3cf4c322f363.gif" class="img-fluid"></p>
</section>
<section id="section-1" class="level3">
<h3 class="anchored" data-anchor-id="section-1">0.2.6</h3>
<ul>
<li>Add a switch button to control whether to show the upload command in the command palette.</li>
</ul>
<p><img src="https://minioapi.pjx.ac.cn/img1/2023/11/147c6a4eaa34da41a6f102558ed77106.png" class="img-fluid"> If you turn off the button for the General database, you wont see the option for the General database in the upload command list.</p>
<p>If you turn off the button for the NotionNext database, you wont see the option for the NotionNext database in the upload command list.</p>
<p><img src="https://minioapi.pjx.ac.cn/img1/2023/11/70b8e4fc2148688ccbd6cfc53ce339a2.png" class="img-fluid"></p>
</section>
<section id="section-2" class="level3">
<h3 class="anchored" data-anchor-id="section-2">0.2.3</h3>
<ul>
<li>Fix the bug, now you can update normally.</li>
</ul>
</section>
<section id="section-3" class="level3">
<h3 class="anchored" data-anchor-id="section-3">0.2.2</h3>
<ul>
<li>Support both NotionNext and General Notion database.</li>
<li>You can have one NotionNext and one General Notion database.</li>
<li>General Notion database can only have <code>title</code> and <code>tags</code> columns, and <code>tags</code> columns should be the multi-selected property. <strong>the name of the columns is case sensitive. You should use small letter.</strong></li>
</ul>
<p><img src="https://minioapi.pjx.ac.cn/img1/2023/11/712a12081d855aa60f82a7b46913ab7e.gif" class="img-fluid"></p>
<p><img src="https://minioapi.pjx.ac.cn/img1/2023/11/9de76cecceef74c78884ddfc1c221659.gif" class="img-fluid"></p>
</section>
<section id="section-4" class="level3">
<h3 class="anchored" data-anchor-id="section-4">0.2.1</h3>
<ul>
<li>Restructure the code</li>
</ul>
</section>
<section id="section-5" class="level3">
<h3 class="anchored" data-anchor-id="section-5">0.2.0</h3>
<ul>
<li>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. <strong>However, only NotionNext database is supported for now.</strong></li>
</ul>
</section>
<section id="section-6" class="level3">
<h3 class="anchored" data-anchor-id="section-6">0.1.10</h3>
<ul>
<li>Fix the Chinese support in the settings.</li>
</ul>
</section>
<section id="section-7" class="level3">
<h3 class="anchored" data-anchor-id="section-7">0.1.8</h3>
<ul>
<li>Rebuild the uploadCommand function, and add one button to select the different databases. <strong>However, only NotionNext database is supported for now.</strong></li>
</ul>
</section>
<section id="section-8" class="level3">
<h3 class="anchored" data-anchor-id="section-8">0.1.7</h3>
<ul class="task-list">
<li><input type="checkbox" checked="">Removed the <code>convert tag</code> option. Now, you can directly add tags in the YAML front matter. If you dont want to add tags, you can delete the tags in the YAML front matter or leave the tags blank.</li>
</ul>
</section>
</section>
<section id="how-to-use" class="level2">
<h2 class="anchored" data-anchor-id="how-to-use">How to Use</h2>
<section id="precautions" class="level3">
<h3 class="anchored" data-anchor-id="precautions">Precautions</h3>
<p>For now, this plugin is exclusively for <a href="https://github.com/tangly1024/NotionNext">NotionNext</a>. If youre not using this template, youll keep receiving <code>error 400</code>.</p>
<p>For those without a NotionNext requirement, please use the original <a href="https://github.com/EasyChris/obsidian-to-notion">Obsidian-to-notion</a>.</p>
</section>
<section id="pre-installation-steps" class="level3">
<h3 class="anchored" data-anchor-id="pre-installation-steps">Pre-Installation Steps</h3>
<p>Before installing the plugin, you must have set up the following:</p>
<ol type="1">
<li>Your NotionNext database.</li>
<li>According to the original authors readme.md, set up the Notion API, and it should already be associated with your NotionNext repository.</li>
<li>NotionNext Database ID</li>
<li>Your NotionNext database should have the following contents:
<ul>
<li>type</li>
<li>title</li>
<li>slug</li>
<li>category</li>
<li>tags</li>
<li>date</li>
<li>status</li>
<li>summary</li>
<li>password</li>
<li>icon</li>
</ul></li>
</ol>
<p>From version 0.0.6, I also add the following contents: - titleicon: the unique icon for each post, it can only support emoji currently. - cover url: the cover image for each post, it should be end with a type of image, such as .jpg, .png, .gif, etc.</p>
<p><strong>If youve directly copied the NotionNext template, these contents should already exist. Ive made changes to this plugin based on the original authors work. All you need to ensure is that your database has the above content, and every letter is in lowercase!!!</strong></p>
<p><strong>⚠️⚠️⚠️: All headers are in lowercase!!! The order doesnt matter!</strong></p>
</section>
<section id="plugin-installation" class="level3">
<h3 class="anchored" data-anchor-id="plugin-installation">Plugin Installation</h3>
<section id="install-via-community-plugins" class="level4">
<h4 class="anchored" data-anchor-id="install-via-community-plugins">Install via Community Plugins</h4>
<p>Open <code>Obsidian settings -&gt; Community Plugins -&gt; Browse -&gt; NotionNext -&gt; Share to NotionNext</code></p>
</section>
<section id="mannually-install" class="level4">
<h4 class="anchored" data-anchor-id="mannually-install">Mannually Install</h4>
<ol type="1">
<li>Close Obsidian.</li>
<li>Download the plugin file from Release and unzip it into your Obsidian plugin directory.</li>
<li>Re-open Obsidian, go to settings, and enable the plugin.</li>
<li>In the settings, find Obsidian to NotionNext, and enter your NotionNext Database ID and API token.</li>
</ol>
</section>
</section>
<section id="how-to-use-1" class="level3">
<h3 class="anchored" data-anchor-id="how-to-use-1">How to Use</h3>
</section>
<section id="using-the-plugin" class="level3">
<h3 class="anchored" data-anchor-id="using-the-plugin">Using the Plugin</h3>
<p>In the repository, I have uploaded a template which you can directly copy into your template folder. After that, use Obsidians template feature to create a new note with one click.</p>
<p>If you dont want to use the template, you can also directly create a new file in Obsidian and then copy the content below. Then save it.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">---</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="co"># default value has been set.</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="co"># for any unwanted value, you can delete it or set it to empty.</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="co"># for example, if you donot want to set password, you can delete password: "1234" or set it to password: ""</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="co"># 我已经在插件中设置了默认值,如果有不需要的选项,可以直接删除。</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="co"># 例如你不需要密码选项你可以将password: "1234"删除,或者将它设置为空。</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="co"># !!!!!!!!!!!!</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="co"># 现在阶段一定不要修改表头的名字, please do not change the name of the header in YAML front matter</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="co"># !!!!!!!!!!!!</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="an">titleicon:</span><span class="co"> 📎 # emoji icon, default is 📜, 默认是📜</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="an">date:</span><span class="co"> 2023-07-23 # default is today 默认是今天。 Format is YYYY-MM-DD 格式是YYYY-MM-DD</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="an">coverurl:</span><span class="co"> https://img.jxpeng.dev/2023/08/843e27a210847f05a0f7cfb121fec100.jpg # default is empty 默认是空</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="an">type:</span><span class="co"> Post # Post or Page, default is Post 默认是Post</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="an">slug:</span><span class="co"> test # slug for url, default is empty 默认是空</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="an">stats:</span><span class="co"> Draft # Draft, Invisible, Published, default is Draft 默认是Draft</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="an">category:</span><span class="co"> test # default is 'Obsidian' 默认是'Obsidian'</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="an">summary:</span><span class="co"> this is a summary for test post # default is empty 默认是空</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a><span class="an">icon:</span><span class="co"> fa-solid fa-camera # you can ignore this, default is empty 默认是空,可直接删除</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="an">password:</span><span class="co"> "1234" # if you donot want to set password, you can delete this line, default is empty 默认是空,可直接删除</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="co"># 现在必须开启tags选项否则会报错</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a><span class="an">tags:</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a><span class="co"> - test # tags for post</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a><span class="co"> - web # add more tags if you want</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a><span class="co">---</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>Contents Below</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<p>Usage of the template is as follows: <img src="https://minioapi.pjx.ac.cn/img1/2023/09/354b950e5777b48832c2475e4a31f2cc.gif" class="img-fluid"></p>
<p><strong>Plugin preview is shown below</strong> <img src="https://minioapi.pjx.ac.cn/img1/2023/09/d6199619b68fab218fca8ae0cebece78.gif" class="img-fluid"></p>
<hr>
<p><strong>Original README.md</strong></p>
<p>Many Thanks for the original authors work. Ive only made some changes to the original authors work. If you find this plugin useful, please give the <a href="https://github.com/EasyChris/obsidian-to-notion">original author</a> a star.</p>
</section>
</section>
</section>
<section id="obsidian-to-notion" class="level1">
<h1>Obsidian to Notion</h1>
<p><a href="https://github.com/Easychris/obsidian-to-notion/actions/workflows/CI.yml"><img src="https://github.com/Easychris/obsidian-to-notion/actions/workflows/CI.yml/badge.svg" class="img-fluid"></a> <a href="https://github.com/Easychris/obsidian-to-notion/actions/workflows/release.yml"><img src="https://github.com/Easychris/obsidian-to-notion/actions/workflows/release.yml/badge.svg" class="img-fluid" alt="Release Obsidian plugin"></a> <a href="https://raw.githubusercontent.com/EasyChris/obsidian-to-notion/master/LICENSE"><img src="https://img.shields.io/github/license/EasyChris/obsidian-to-notion.png" class="img-fluid" alt="GitHub license"></a> <a href="https://GitHub.com/Easychris/obsidian-to-notion/releases/"><img src="https://img.shields.io/github/downloads/Easychris/obsidian-to-notion/total.svg" class="img-fluid" alt="Github all releases"></a> <a href="https://github.com/Easychris/obsidian-to-notion/releases"><img src="https://badgen.net/github/release/Easychris/obsidian-to-notion/.png" class="img-fluid" alt="GitLab latest release"></a></p>
<p>Share of obsidian to Notion <a href="README-zh.md">中文文档</a></p>
<p>Sharing files from Obsidian to Notion with a single click, and Obsidian will automatically add the Notion share link</p>
<p>You are welcome to offer it a star if it can benefit you.</p>
<p><img src="./doc/1.gif" class="img-fluid"></p>
</section>
<section id="todo" class="level1">
<h1>TODO</h1>
<section id="todo-board" class="level3">
<h3 class="anchored" data-anchor-id="todo-board"><a href="https://github.com/users/EasyChris/projects/3/views/1">TODO Board</a></h3>
<ul class="task-list">
<li><input type="checkbox" checked="">support for custom page banner</li>
<li><input type="checkbox" checked="">update the exsit page</li>
<li><input type="checkbox" checked="">support for mult language</li>
<li><input type="checkbox" checked="">support for auto copy the share link to clipboard</li>
<li><input type="checkbox" checked="">support for mobile</li>
<li><input type="checkbox" checked="">support tags thank for <a href="https://github.com/jannikbuscha"><span class="citation" data-cites="jannikbuscha">@jannikbuscha</span></a></li>
<li><input type="checkbox">transfer the bi-link format like [[]] into the format that Notion supports.</li>
</ul>
</section>
</section>
<section id="how-to-use-2" class="level1">
<h1>How to use</h1>
<section id="install-the-plugin" class="level2">
<h2 class="anchored" data-anchor-id="install-the-plugin">Install the plugin</h2>
<section id="marketplace-download" class="level3">
<h3 class="anchored" data-anchor-id="marketplace-download">Marketplace download</h3>
<p>Open obsidian setting -&gt; Add plugin -&gt; Search -&gt; notion</p>
<p><img src="https://afox-1256168983.cos.ap-shanghai.myqcloud.com/20220628214145.png" class="img-fluid"></p>
</section>
<section id="brat" class="level3">
<h3 class="anchored" data-anchor-id="brat">BRAT</h3>
<p>Enter <code>BRAT</code> into the plugin market center to find it. Add <code>EasyChris/obsidian-to-notion</code> to the list of BRAT plugins that have been installed. Return to the plugin center and turn it on.</p>
</section>
<section id="manual-installation" class="level3">
<h3 class="anchored" data-anchor-id="manual-installation">Manual installation</h3>
<pre><code>cd YOUR_OBSIDIAN_FOLDER/.obsidian/plugins/
git clone https://github.com/EasyChris/obsidian-to-notion.git</code></pre>
</section>
</section>
<section id="apply-notion-api" class="level2">
<h2 class="anchored" data-anchor-id="apply-notion-api">Apply Notion API</h2>
<p>Official reference documentation: <a href="https://developers.notion.com/docs">https://developers.notion.com/docs</a></p>
<section id="step-1-create-integration" class="level3">
<h3 class="anchored" data-anchor-id="step-1-create-integration">Step 1: Create integration</h3>
<p>Go to <a href="https://www.notion.com/my-integrations">https://www.notion.com/my-integrations</a> Once created, copy <code>secrets toekn</code> <img src="https://files.readme.io/2ec137d-093ad49-create-integration.gif" class="img-fluid"></p>
<section id="note" class="level4">
<h4 class="anchored" data-anchor-id="note">Note</h4>
<p>database first custom name must be “Name”, otherwise sync to notion will be failed</p>
<p><img src="https://afox-1256168983.cos.ap-shanghai.myqcloud.com/20220618102029.png" class="img-fluid"></p>
</section>
</section>
<section id="step-2-share-a-database-with-your-integration" class="level3">
<h3 class="anchored" data-anchor-id="step-2-share-a-database-with-your-integration">Step 2: Share a database with your integration</h3>
<p>Create a new page (with public permissions) Create a new database in the page -&gt; you need <code>full page database</code> <img src="./doc/3.gif" class="img-fluid"></p>
<p>Add <code>integration</code> to your new database</p>
<p><img src="./doc/6.gif" class="img-fluid"></p>
</section>
<section id="step-3-copy-the-database-id" class="level3">
<h3 class="anchored" data-anchor-id="step-3-copy-the-database-id">Step 3: Copy the database ID</h3>
<pre><code>https://www.notion.so/myworkspace/a8aec43384f447ed84390e8e42c2e089?v=...
| --------- Database ID --------|
</code></pre>
</section>
</section>
<section id="open-the-plugin-configuration" class="level2">
<h2 class="anchored" data-anchor-id="open-the-plugin-configuration">Open the plugin configuration</h2>
<p>Fill the configuration with the <code>NOTION_API_KEY</code> and <code>DATABASE_ID</code> you got <img src="./doc/2.png" class="img-fluid"></p>
</section>
<section id="upload-file-content-to-notion" class="level2">
<h2 class="anchored" data-anchor-id="upload-file-content-to-notion">Upload file content to notion</h2>
<p>Click the uploadCommand notion button <img src="./doc/4.png" class="img-fluid"> A share link will be automatically generated after successful uploadCommand <img src="./doc/5.png" class="img-fluid"></p>
</section>
<section id="banner-url-option" class="level2">
<h2 class="anchored" data-anchor-id="banner-url-option">Banner URL [option]</h2>
<p>Banner url must be a image url like: <a href="https://i.imgur.com/xxx.jpg" class="uri">https://i.imgur.com/xxx.jpg</a> If you dont want to use banner, leave it blank</p>
</section>
<section id="convert-tags-option" class="level2">
<h2 class="anchored" data-anchor-id="convert-tags-option">Convert Tags [option]</h2>
<p>Transfer the Obsidian tags to the Notion table. It requires the column with the name Tags. <img src="./doc/7.png" class="img-fluid"></p>
<p>Add tags to your notion page</p>
<p><img src="./doc/10.png" class="img-fluid"></p>
<ul>
<li>open plugin convert tags</li>
</ul>
<p><img src="./doc/8.png" class="img-fluid"></p>
<ul>
<li>add tags in the head</li>
</ul>
<div class="sourceCode" id="cb4"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="co">---</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="an">tags:</span><span class="co"> [tag1,tag2]</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="co">---</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>this is test tags</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="sourceCode" id="cb5"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="co">---</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="an">tags:</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="co"> - tag4</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="co">---</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>this is test tags</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<p><img src="./doc/9.png" class="img-fluid"></p>
<p>Thanks for <a href="https://github.com/jannikbuscha"><span class="citation" data-cites="jannikbuscha">@jannikbuscha</span></a> contribution</p>
</section>
<section id="notion-id-option" class="level2">
<h2 class="anchored" data-anchor-id="notion-id-option">Notion ID [option]</h2>
<p>Notion ID is the your notion site ID that you want to share the file to. if you dont write it, notion will share to the default link like: <a href="https://www.notion.so/myworkspace/a8aec43384f447ed84390" class="uri">https://www.notion.so/myworkspace/a8aec43384f447ed84390</a> that visit this page need to redirect to your site url if you write the Notion ID, it will share to the page link like: <a href="https://your_user_name.notion.site/myworkspace/a8aec43384f447ed84390" class="uri">https://your_user_name.notion.site/myworkspace/a8aec43384f447ed84390</a>. The visiter dont need to redirect url.</p>
</section>
<section id="sync-image-to-notion" class="level2">
<h2 class="anchored" data-anchor-id="sync-image-to-notion">Sync image to Notion</h2>
<p>To sync images to your oss or cos bucket, use the <a href="https://github.com/renmu123/obsidian-image-auto-upload-plugin">Obsidian Image Auto Upload Plugin</a>.</p>
</section>
</section>
<section id="development" class="level1">
<h1>Development</h1>
<pre><code>git clone https://github.com/EasyChris/obsidian-to-notion.git
yarn install
yarn dev</code></pre>
<section id="release" class="level2">
<h2 class="anchored" data-anchor-id="release">Release</h2>
<pre><code>node update-version.js
./release.sh</code></pre>
<p>```</p>
</section>
</section>
<section id="thanks" class="level1">
<h1>Thanks</h1>
<p><a href="https://luhaifeng666.github.io/obsidian-plugin-docs-zh/zh/getting-started/development-workflow.html">Development Process | Obsidian Plugin Development Documentation</a></p>
<p><a href="https://github.com/devbean/obsidian-wordpress">GitHub - devbean/obsidian-wordpress: An obsidian plugin for publishing docs to WordPress.</a></p>
<p><a href="https://github.com/obsidianmd/obsidian-api">GitHub - obsidianmd/obsidian-api</a></p>
<p><a href="https://github.dev/zhaohongxuan/obsidian-weread-plugin">GitHub - Easychris/obsidian-to-notion: Obsidian Weread Plugin is an plugin to sync Weread(微信读书) hightlights and annotations into your Obsidian Vault.</a></p>
<p><a href="https://github.com/Quorafind/Obsidian-Memos">GitHub - Quorafind/Obsidian-Memos: A quick capture plugin for Obsidian, all data from your notes.</a></p>
<p><a href="https://github.com/jannikbuscha">https://github.com/jannikbuscha/obsidian-to-notion</a></p>
</section>
<section id="license" class="level1">
<h1>License</h1>
<p>GNU GPLv3</p>
</section>
</main>
<!-- /main column -->
<script id="quarto-html-after-body" type="application/javascript">
window.document.addEventListener("DOMContentLoaded", function (event) {
const toggleBodyColorMode = (bsSheetEl) => {
const mode = bsSheetEl.getAttribute("data-mode");
const bodyEl = window.document.querySelector("body");
if (mode === "dark") {
bodyEl.classList.add("quarto-dark");
bodyEl.classList.remove("quarto-light");
} else {
bodyEl.classList.add("quarto-light");
bodyEl.classList.remove("quarto-dark");
}
}
const toggleBodyColorPrimary = () => {
const bsSheetEl = window.document.querySelector("link#quarto-bootstrap");
if (bsSheetEl) {
toggleBodyColorMode(bsSheetEl);
}
}
toggleBodyColorPrimary();
const icon = "";
const anchorJS = new window.AnchorJS();
anchorJS.options = {
placement: 'right',
icon: icon
};
anchorJS.add('.anchored');
const isCodeAnnotation = (el) => {
for (const clz of el.classList) {
if (clz.startsWith('code-annotation-')) {
return true;
}
}
return false;
}
const clipboard = new window.ClipboardJS('.code-copy-button', {
text: function(trigger) {
const codeEl = trigger.previousElementSibling.cloneNode(true);
for (const childEl of codeEl.children) {
if (isCodeAnnotation(childEl)) {
childEl.remove();
}
}
return codeEl.innerText;
}
});
clipboard.on('success', function(e) {
// button target
const button = e.trigger;
// don't keep focus
button.blur();
// flash "checked"
button.classList.add('code-copy-button-checked');
var currentTitle = button.getAttribute("title");
button.setAttribute("title", "Copied!");
let tooltip;
if (window.bootstrap) {
button.setAttribute("data-bs-toggle", "tooltip");
button.setAttribute("data-bs-placement", "left");
button.setAttribute("data-bs-title", "Copied!");
tooltip = new bootstrap.Tooltip(button,
{ trigger: "manual",
customClass: "code-copy-button-tooltip",
offset: [0, -8]});
tooltip.show();
}
setTimeout(function() {
if (tooltip) {
tooltip.hide();
button.removeAttribute("data-bs-title");
button.removeAttribute("data-bs-toggle");
button.removeAttribute("data-bs-placement");
}
button.setAttribute("title", currentTitle);
button.classList.remove('code-copy-button-checked');
}, 1000);
// clear code selection
e.clearSelection();
});
function tippyHover(el, contentFn) {
const config = {
allowHTML: true,
content: contentFn,
maxWidth: 500,
delay: 100,
arrow: false,
appendTo: function(el) {
return el.parentElement;
},
interactive: true,
interactiveBorder: 10,
theme: 'quarto',
placement: 'bottom-start'
};
window.tippy(el, config);
}
const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
for (var i=0; i<noterefs.length; i++) {
const ref = noterefs[i];
tippyHover(ref, function() {
// use id or data attribute instead here
let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
try { href = new URL(href).hash; } catch {}
const id = href.replace(/^#\/?/, "");
const note = window.document.getElementById(id);
return note.innerHTML;
});
}
let selectedAnnoteEl;
const selectorForAnnotation = ( cell, annotation) => {
let cellAttr = 'data-code-cell="' + cell + '"';
let lineAttr = 'data-code-annotation="' + annotation + '"';
const selector = 'span[' + cellAttr + '][' + lineAttr + ']';
return selector;
}
const selectCodeLines = (annoteEl) => {
const doc = window.document;
const targetCell = annoteEl.getAttribute("data-target-cell");
const targetAnnotation = annoteEl.getAttribute("data-target-annotation");
const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation));
const lines = annoteSpan.getAttribute("data-code-lines").split(",");
const lineIds = lines.map((line) => {
return targetCell + "-" + line;
})
let top = null;
let height = null;
let parent = null;
if (lineIds.length > 0) {
//compute the position of the single el (top and bottom and make a div)
const el = window.document.getElementById(lineIds[0]);
top = el.offsetTop;
height = el.offsetHeight;
parent = el.parentElement.parentElement;
if (lineIds.length > 1) {
const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]);
const bottom = lastEl.offsetTop + lastEl.offsetHeight;
height = bottom - top;
}
if (top !== null && height !== null && parent !== null) {
// cook up a div (if necessary) and position it
let div = window.document.getElementById("code-annotation-line-highlight");
if (div === null) {
div = window.document.createElement("div");
div.setAttribute("id", "code-annotation-line-highlight");
div.style.position = 'absolute';
parent.appendChild(div);
}
div.style.top = top - 2 + "px";
div.style.height = height + 4 + "px";
let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter");
if (gutterDiv === null) {
gutterDiv = window.document.createElement("div");
gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter");
gutterDiv.style.position = 'absolute';
const codeCell = window.document.getElementById(targetCell);
const gutter = codeCell.querySelector('.code-annotation-gutter');
gutter.appendChild(gutterDiv);
}
gutterDiv.style.top = top - 2 + "px";
gutterDiv.style.height = height + 4 + "px";
}
selectedAnnoteEl = annoteEl;
}
};
const unselectCodeLines = () => {
const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"];
elementsIds.forEach((elId) => {
const div = window.document.getElementById(elId);
if (div) {
div.remove();
}
});
selectedAnnoteEl = undefined;
};
// Attach click handler to the DT
const annoteDls = window.document.querySelectorAll('dt[data-target-cell]');
for (const annoteDlNode of annoteDls) {
annoteDlNode.addEventListener('click', (event) => {
const clickedEl = event.target;
if (clickedEl !== selectedAnnoteEl) {
unselectCodeLines();
const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active');
if (activeEl) {
activeEl.classList.remove('code-annotation-active');
}
selectCodeLines(clickedEl);
clickedEl.classList.add('code-annotation-active');
} else {
// Unselect the line
unselectCodeLines();
clickedEl.classList.remove('code-annotation-active');
}
});
}
const findCites = (el) => {
const parentEl = el.parentElement;
if (parentEl) {
const cites = parentEl.dataset.cites;
if (cites) {
return {
el,
cites: cites.split(' ')
};
} else {
return findCites(el.parentElement)
}
} else {
return undefined;
}
};
var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
for (var i=0; i<bibliorefs.length; i++) {
const ref = bibliorefs[i];
const citeInfo = findCites(ref);
if (citeInfo) {
tippyHover(citeInfo.el, function() {
var popup = window.document.createElement('div');
citeInfo.cites.forEach(function(cite) {
var citeDiv = window.document.createElement('div');
citeDiv.classList.add('hanging-indent');
citeDiv.classList.add('csl-entry');
var biblioDiv = window.document.getElementById('ref-' + cite);
if (biblioDiv) {
citeDiv.innerHTML = biblioDiv.innerHTML;
}
popup.appendChild(citeDiv);
});
return popup.innerHTML;
});
}
}
});
</script>
</div> <!-- /content -->
</body></html>

171
README.md
View File

@@ -1,18 +1,113 @@
# Obsidian to NotionNext # Obsidian to NotionNext
[![Test](https://github.com/jxpeng98/obsidian-to-NotionNext/actions/workflows/test.yml/badge.svg)](https://github.com/jxpeng98/obsidian-to-NotionNext/actions/workflows/test.yml)
[![Release](https://github.com/jxpeng98/obsidian-to-NotionNext/actions/workflows/release.yml/badge.svg)](https://github.com/jxpeng98/obsidian-to-NotionNext/actions/workflows/release.yml)
[![Github all releases](https://img.shields.io/github/downloads/jxpeng98/obsidian-to-NotionNext/total.svg)](https://GitHub.com/jxpeng98/obsidian-to-NotionNext/releases/)
[![GitLab latest release](https://badgen.net/github/release/jxpeng98/obsidian-to-NotionNext)](https://github.com/jxpeng98/obsidian-to-NotionNext/releases)
[中文文档](README-zh.md) [中文文档](README-zh.md)
Thanks to the [original author](https://github.com/EasyChris/obsidian-to-notion) for developing such a useful plugin that can synchronize Obsidian to Notion. However, the original repository can only sync Name and Tags information. For those like me who use [NotionNext](https://github.com/tangly1024/NotionNext) to set up their website, this presents some limitations. Every time I import, I need to make a lot of modifications. Thanks to the [original author](https://github.com/EasyChris/obsidian-to-notion) for developing such a useful plugin that can synchronize Obsidian to Notion. However, the original repository can only sync Name and Tag information. For those like me who use [NotionNext](https://github.com/tangly1024/NotionNext) to set up their website, this presents some limitations. Every time I import, I need to make a lot of modifications.
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. 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.
**Now, support both NotionNext and General databases.**
## Update
### 1.1.1
- Fix the setting display bug in Japanese.
- Add Japanese translation.
### 1.1.0
- Fix the custom name setting tab display bug.
- Add a toggle to control whether to sync `tags` since the empty tags may cause the syncing error.
If you switch off the `tags` function in the plugin settings, it will ignore the `tags` in your frontmatter.
If you prefer to sync tags to Notion database, you can switch on the `tags` function in the plugin settings. **You can only use the following format for tags:**
```yaml
tags: #empty tags, option 1
tags: [test,test1,test2] # use the square brackets, option 2
tags:
- test
- test1
- test2 # use the dash option 3
```
### 1.0.1
- Fix the custom name element display bug in the settings.
### 1.0.0 (Big Update)
- From this version, you can **modify the first column name (title column, default: 'title')** as you want. (**Note: You need to have the 'tags' column in your Notion General database, and add `tags:` in your markdown frontmatter. If not, you will receive `network error 400`. But you can leave the `tags:` blank.**)
![](https://minioapi.pjx.ac.cn/img1/2023/11/4a298b9be3990e9d2201bf2f50ca5a0a.png)
Like this:
![](https://minioapi.pjx.ac.cn/img1/2023/11/4cd8d79cd9dd9dde299e39c666cb3473.gif)
- Add a switch button to control whether display the setting tabs in the plugin settings for both NotionNext and Notion General databases.
![](https://minioapi.pjx.ac.cn/img1/2023/11/becb60fc44783842da4b3cf4c322f363.gif)
### 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.**
### 0.1.10
- Fix the Chinese support in the settings.
### 0.1.8
- 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.
## How to Use ## How to Use
### Precautions ### Precautions
For now, this plugin is exclusively for [NotionNext](https://github.com/tangly1024/NotionNext). If you're not using this template, you'll keep receiving `error 400`. For now, this plugin is exclusively for [NotionNext](https://github.com/tangly1024/NotionNext). If you're not using this template, you'll keep receiving `error 400`.
For those without a NotionNext requirement, please use the original [Obsidian-to-notion](https://github.com/EasyChris/obsidian-to-notion). For those without a NotionNext requirement, please use the original [Obsidian-to-notion](https://github.com/EasyChris/obsidian-to-notion).
### Pre-Installation Steps ### Pre-Installation Steps
Before installing the plugin, you must have set up the following: Before installing the plugin, you must have set up the following:
1. Your NotionNext database. 1. Your NotionNext database.
2. According to the original author's readme.md, set up the Notion API, and it should already be associated with your NotionNext repository. 2. According to the original author's readme.md, set up the Notion API, and it should already be associated with your NotionNext repository.
3. NotionNext Database ID 3. NotionNext Database ID
@@ -28,25 +123,35 @@ Before installing the plugin, you must have set up the following:
- password - password
- icon - icon
In version 0.0.6, I also add the following contents: From version 0.0.6, I also add the following contents:
- titleicon: the unique icon for each post, it can only support emoji currently. - titleicon: the unique icon for each post, it can only support emoji currently.
- cover url: the cover image for each post, it should be end with a type of image, such as .jpg, .png, .gif, etc. - cover url: the cover image for each post, it should be end with a type of image, such as .jpg, .png, .gif, etc.
**If you've directly copied the NotionNext template, these contents should already exist. I've made changes to this plugin based on the original author's work. All you need to ensure is that your database has the above content, and every letter is in lowercase!!!** **If you've directly copied the NotionNext template, these contents should already exist. I've made changes to this plugin based on the original author's work. All you need to ensure is that your database has the above content, and every letter is in lowercase!!!**
**⚠️⚠️⚠️: All headers are in lowercase!!! The order doesn't matter!** **⚠️⚠️⚠️: All headers are in lowercase!!! The order doesn't matter!**
### Plugin Installation ### Plugin Installation
#### Install via Community Plugins
Open `Obsidian settings -> Community Plugins -> Browse -> NotionNext -> Share to NotionNext`
#### Mannually Install
1. Close Obsidian. 1. Close Obsidian.
2. Download the plugin file from Release and unzip it into your Obsidian plugin directory. 2. Download the plugin file from Release and unzip it into your Obsidian plugin directory.
3. Re-open Obsidian, go to settings, and enable the plugin. 3. Re-open Obsidian, go to settings, and enable the plugin.
4. In the settings, find Obsidian to NotionNext, and enter your NotionNext Database ID and API token. 4. In the settings, find Obsidian to NotionNext, and enter your NotionNext Database ID and API token.
### How to Use ### How to Use
### Using the Plugin ### Using the Plugin
In the repository, I have uploaded a template which you can directly copy into your template folder. After that, use Obsidian's template feature to create a new note with one click. In the repository, I have uploaded a template which you can directly copy into your template folder. After that, use Obsidian's template feature to create a new note with one click.
If you don't want to use the template, you can also directly create a new file in Obsidian and then copy the content below. Then save it. If you don't want to use the template, you can also directly create a new file in Obsidian and then copy the content below. Then save it.
```markdown ```markdown
--- ---
# default value has been set. # default value has been set.
@@ -58,6 +163,7 @@ If you don't want to use the template, you can also directly create a new file i
# 现在阶段一定不要修改表头的名字, please do not change the name of the header in YAML front matter # 现在阶段一定不要修改表头的名字, please do not change the name of the header in YAML front matter
# !!!!!!!!!!!! # !!!!!!!!!!!!
titleicon: 📎 # emoji icon, default is 📜, 默认是📜 titleicon: 📎 # emoji icon, default is 📜, 默认是📜
date: 2023-07-23 # default is today 默认是今天。 Format is YYYY-MM-DD 格式是YYYY-MM-DD
coverurl: https://img.jxpeng.dev/2023/08/843e27a210847f05a0f7cfb121fec100.jpg # default is empty 默认是空 coverurl: https://img.jxpeng.dev/2023/08/843e27a210847f05a0f7cfb121fec100.jpg # default is empty 默认是空
type: Post # Post or Page, default is Post 默认是Post type: Post # Post or Page, default is Post 默认是Post
slug: test # slug for url, default is empty 默认是空 slug: test # slug for url, default is empty 默认是空
@@ -75,11 +181,12 @@ tags:
Contents Below Contents Below
``` ```
Usage of the template is as follows: Usage of the template is as follows:
![](https://img.jxpeng.dev/2023/08/189384bf03c562030f4828343e1b7a6c.gif) ![](https://minioapi.pjx.ac.cn/img1/2023/09/354b950e5777b48832c2475e4a31f2cc.gif)
**Plugin preview is shown below** **Plugin preview is shown below**
![](https://img.jxpeng.dev/2023/08/6063dd06eea4ee6939b5058dd129a698.gif) ![](https://minioapi.pjx.ac.cn/img1/2023/09/d6199619b68fab218fca8ae0cebece78.gif)
--- ---
@@ -88,13 +195,13 @@ Usage of the template is as follows:
Many Thanks for the original author's work. I've only made some changes to the original author's work. If you find this plugin useful, please give the [original author](https://github.com/EasyChris/obsidian-to-notion) a star. Many Thanks for the original author's work. I've only made some changes to the original author's work. If you find this plugin useful, please give the [original author](https://github.com/EasyChris/obsidian-to-notion) a star.
# Obsidian to Notion # Obsidian to Notion
[![](https://github.com/Easychris/obsidian-to-notion/actions/workflows/CI.yml/badge.svg)](https://github.com/Easychris/obsidian-to-notion/actions/workflows/CI.yml) [![](https://github.com/Easychris/obsidian-to-notion/actions/workflows/CI.yml/badge.svg)](https://github.com/Easychris/obsidian-to-notion/actions/workflows/CI.yml)
[![Release Obsidian plugin](https://github.com/Easychris/obsidian-to-notion/actions/workflows/release.yml/badge.svg)](https://github.com/Easychris/obsidian-to-notion/actions/workflows/release.yml) [![Release Obsidian plugin](https://github.com/Easychris/obsidian-to-notion/actions/workflows/release.yml/badge.svg)](https://github.com/Easychris/obsidian-to-notion/actions/workflows/release.yml)
[![GitHub license](https://img.shields.io/github/license/EasyChris/obsidian-to-notion)](https://raw.githubusercontent.com/EasyChris/obsidian-to-notion/master/LICENSE) [![GitHub license](https://img.shields.io/github/license/EasyChris/obsidian-to-notion)](https://raw.githubusercontent.com/EasyChris/obsidian-to-notion/master/LICENSE)
[![Github all releases](https://img.shields.io/github/downloads/Easychris/obsidian-to-notion/total.svg)](https://GitHub.com/Easychris/obsidian-to-notion/releases/) [![Github all releases](https://img.shields.io/github/downloads/Easychris/obsidian-to-notion/total.svg)](https://GitHub.com/Easychris/obsidian-to-notion/releases/)
[![GitLab latest release](https://badgen.net/github/release/Easychris/obsidian-to-notion/)](https://github.com/Easychris/obsidian-to-notion/releases) [![GitLab latest release](https://badgen.net/github/release/Easychris/obsidian-to-notion/)](https://github.com/Easychris/obsidian-to-notion/releases)
Share of obsidian to Notion [中文文档](README-zh.md) Share of obsidian to Notion [中文文档](README-zh.md)
Sharing files from Obsidian to Notion with a single click, and Obsidian will automatically add the Notion share link Sharing files from Obsidian to Notion with a single click, and Obsidian will automatically add the Notion share link
@@ -104,7 +211,9 @@ You are welcome to offer it a star if it can benefit you.
![](./doc/1.gif) ![](./doc/1.gif)
# TODO # TODO
### [TODO Board](https://github.com/users/EasyChris/projects/3/views/1) ### [TODO Board](https://github.com/users/EasyChris/projects/3/views/1)
- [x] support for custom page banner - [x] support for custom page banner
- [x] update the exsit page - [x] update the exsit page
- [x] support for mult language - [x] support for mult language
@@ -113,41 +222,47 @@ You are welcome to offer it a star if it can benefit you.
- [x] support tags thank for [@jannikbuscha](https://github.com/jannikbuscha) - [x] support tags thank for [@jannikbuscha](https://github.com/jannikbuscha)
- [ ] transfer the bi-link format like [[]] into the format that Notion supports. - [ ] transfer the bi-link format like [[]] into the format that Notion supports.
# How to use # How to use
## Install the plugin ## Install the plugin
### Marketplace download ### Marketplace download
Open obsidian setting -> Add plugin -> Search -> notion Open obsidian setting -> Add plugin -> Search -> notion
![](https://afox-1256168983.cos.ap-shanghai.myqcloud.com/20220628214145.png) ![](https://afox-1256168983.cos.ap-shanghai.myqcloud.com/20220628214145.png)
### BRAT ### BRAT
Enter `BRAT` into the plugin market center to find it. Enter `BRAT` into the plugin market center to find it.
Add `EasyChris/obsidian-to-notion` to the list of BRAT plugins that have been installed. Add `EasyChris/obsidian-to-notion` to the list of BRAT plugins that have been installed.
Return to the plugin center and turn it on. Return to the plugin center and turn it on.
### Manual installation ### Manual installation
``` ```
cd YOUR_OBSIDIAN_FOLDER/.obsidian/plugins/ cd YOUR_OBSIDIAN_FOLDER/.obsidian/plugins/
git clone https://github.com/EasyChris/obsidian-to-notion.git git clone https://github.com/EasyChris/obsidian-to-notion.git
``` ```
## Apply Notion API ## Apply Notion API
Official reference documentation: [https://developers.notion.com/docs](https://developers.notion.com/docs) Official reference documentation: [https://developers.notion.com/docs](https://developers.notion.com/docs)
### Step 1: Create integration.
### Step 1: Create integration
Go to [https://www.notion.com/my-integrations](https://www.notion.com/my-integrations) Go to [https://www.notion.com/my-integrations](https://www.notion.com/my-integrations)
Once created, copy `secrets toekn` Once created, copy `secrets toekn`
![](https://files.readme.io/2ec137d-093ad49-create-integration.gif) ![](https://files.readme.io/2ec137d-093ad49-create-integration.gif)
#### Note: #### Note
database first custom name must be "Name", otherwise sync to notion will be failed database first custom name must be "Name", otherwise sync to notion will be failed
![](https://afox-1256168983.cos.ap-shanghai.myqcloud.com/20220618102029.png) ![](https://afox-1256168983.cos.ap-shanghai.myqcloud.com/20220618102029.png)
### Step 2: Share a database with your integration ### Step 2: Share a database with your integration
Create a new page (with public permissions) Create a new page (with public permissions)
Create a new database in the page -> you need `full page database` Create a new database in the page -> you need `full page database`
![](./doc/3.gif) ![](./doc/3.gif)
@@ -164,25 +279,25 @@ https://www.notion.so/myworkspace/a8aec43384f447ed84390e8e42c2e089?v=...
``` ```
## Open the plugin configuration ## Open the plugin configuration
Fill the configuration with the `NOTION_API_KEY` and `DATABASE_ID` you got Fill the configuration with the `NOTION_API_KEY` and `DATABASE_ID` you got
![](./doc/2.png) ![](./doc/2.png)
## Upload file content to notion ## Upload file content to notion
Click the upload notion button
Click the uploadCommand notion button
![](./doc/4.png) ![](./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) ![](./doc/5.png)
## Banner URL [option] ## Banner URL [option]
Banner url must be a image url like: https://i.imgur.com/xxx.jpg
Banner url must be a image url like: <https://i.imgur.com/xxx.jpg>
If you don't want to use banner, leave it blank If you don't want to use banner, leave it blank
## Convert Tags [option] ## Convert Tags [option]
Transfer the Obsidian tags to the Notion table. Transfer the Obsidian tags to the Notion table.
It requires the column with the name 'Tags'. It requires the column with the name 'Tags'.
![](./doc/7.png) ![](./doc/7.png)
@@ -191,11 +306,11 @@ Add tags to your notion page
![](./doc/10.png) ![](./doc/10.png)
* open plugin convert tags - open plugin convert tags
![](./doc/8.png) ![](./doc/8.png)
* add tags in the head - add tags in the head
```markdown ```markdown
--- ---
@@ -206,7 +321,6 @@ this is test tags
``` ```
```markdown ```markdown
--- ---
tags: tags:
@@ -221,24 +335,20 @@ this is test tags
Thanks for [@jannikbuscha](https://github.com/jannikbuscha) contribution Thanks for [@jannikbuscha](https://github.com/jannikbuscha) contribution
## Notion ID [option] ## Notion ID [option]
Notion ID is the your notion site ID that you want to share the file to. Notion ID is the your notion site ID that you want to share the file to.
if you don't write it, notion will share to the default link like: if you don't write it, notion will share to the default link like:
https://www.notion.so/myworkspace/a8aec43384f447ed84390 <https://www.notion.so/myworkspace/a8aec43384f447ed84390>
that visit this page need to redirect to your site url that visit this page need to redirect to your site url
if you write the Notion ID, it will share to the page link like: if you write the Notion ID, it will share to the page link like:
https://your_user_name.notion.site/myworkspace/a8aec43384f447ed84390. <https://your_user_name.notion.site/myworkspace/a8aec43384f447ed84390>.
The visiter don't need to redirect url. The visiter don't need to redirect url.
## Sync image to Notion ## Sync image to Notion
To sync images to your oss or cos bucket, use the [Obsidian Image Auto Upload Plugin](https://github.com/renmu123/obsidian-image-auto-upload-plugin). To sync images to your oss or cos bucket, use the [Obsidian Image Auto Upload Plugin](https://github.com/renmu123/obsidian-image-auto-upload-plugin).
# Development # Development
``` ```
@@ -253,6 +363,7 @@ yarn dev
node update-version.js node update-version.js
./release.sh ./release.sh
``` ```
``` ```

View File

@@ -1,58 +1,60 @@
import esbuild from "esbuild"; import esbuild from "esbuild";
import process from "process"; import process from "process";
import builtins from 'builtin-modules' import builtins from "builtin-modules";
const banner = const banner = `/*
`/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin if you want to view the source, please visit the github repository of this plugin
*/ */
`; `;
const prod = (process.argv[2] === 'production'); const prod = process.argv[2] === "production";
const ctx = await esbuild.context({ const ctx = await esbuild.context({
banner: { banner: {
js: banner, js: banner,
}, },
entryPoints: ['src/main.ts'], entryPoints: ["src/main.ts"],
bundle: true, bundle: true,
external: [ external: [
'obsidian', "obsidian",
'electron', "electron",
'@codemirror/autocomplete', "@codemirror/autocomplete",
'@codemirror/closebrackets', "@codemirror/closebrackets",
'@codemirror/collab', "@codemirror/collab",
'@codemirror/commands', "@codemirror/commands",
'@codemirror/comment', "@codemirror/comment",
'@codemirror/fold', "@codemirror/fold",
'@codemirror/gutter', "@codemirror/gutter",
'@codemirror/highlight', "@codemirror/highlight",
'@codemirror/history', "@codemirror/history",
'@codemirror/language', "@codemirror/language",
'@codemirror/lint', "@codemirror/lint",
'@codemirror/matchbrackets', "@codemirror/matchbrackets",
'@codemirror/panel', "@codemirror/panel",
'@codemirror/rangeset', "@codemirror/rangeset",
'@codemirror/rectangular-selection', "@codemirror/rectangular-selection",
'@codemirror/search', "@codemirror/search",
'@codemirror/state', "@codemirror/state",
'@codemirror/stream-parser', "@codemirror/stream-parser",
'@codemirror/text', "@codemirror/text",
'@codemirror/tooltip', "@codemirror/tooltip",
'@codemirror/view', "@codemirror/view",
...builtins ...builtins,
], ],
format: 'cjs', format: "cjs",
target: 'es2016', target: "es2016",
logLevel: "info", logLevel: "info",
sourcemap: prod ? false : 'inline', sourcemap: prod ? false : "inline",
treeShaking: true, treeShaking: true,
outfile: 'main.js', outfile: "main.js",
}); });
if (!prod) { if (!prod) {
await ctx.watch(); await ctx.watch();
} else { } else {
await ctx.rebuild() await ctx.rebuild();
ctx.dispose().then(r => console.log('Build completed'), e => console.error(e)); ctx.dispose().then(
} (r) => console.log("Build completed"),
(e) => console.error(e),
);
}

View File

@@ -1,10 +1,10 @@
{ {
"id": "share-to-notionnext", "id": "share-to-notionnext",
"name": "Share to NotionNext", "name": "Share to NotionNext",
"version": "0.1.4", "version": "1.1.1",
"minAppVersion": "0.0.1", "minAppVersion": "0.0.1",
"description": "Shares obsidian md file to notion with notion api for NotionNext web deploy, motivated 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",
"authorUrl": "https://github.com/jxpeng98/obsidian-to-NotionNext", "authorUrl": "https://github.com/jxpeng98",
"isDesktopOnly": false "isDesktopOnly": false
} }

View File

@@ -8,6 +8,7 @@
# 现在阶段一定不要修改表头的名字, please do not change the name of the header in YAML front matter # 现在阶段一定不要修改表头的名字, please do not change the name of the header in YAML front matter
# !!!!!!!!!!!! # !!!!!!!!!!!!
titleicon: 📎 # default is 📜, 默认是📜 titleicon: 📎 # default is 📜, 默认是📜
date: 2023-07-23 # default is today 默认是今天。 Format is YYYY-MM-DD 格式是YYYY-MM-DD
coverurl: https://img.jxpeng.dev/2023/08/843e27a210847f05a0f7cfb121fec100.jpg # default is empty 默认是空 coverurl: https://img.jxpeng.dev/2023/08/843e27a210847f05a0f7cfb121fec100.jpg # default is empty 默认是空
type: Post # Post or Page, default is Post 默认是Post type: Post # Post or Page, default is Post 默认是Post
slug: test # slug for url, default is empty 默认是空 slug: test # slug for url, default is empty 默认是空

View File

@@ -1,8 +1,8 @@
{ {
"name": "share-to-notionnext", "name": "share-to-notionnext",
"version": "0.1.4", "version": "1.1.1",
"type": "module", "type": "module",
"description": "Shares obsidian md file to notion with notion api for NotionNext web deploy, motivated 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.",
"main": "main.js", "main": "main.js",
"scripts": { "scripts": {
"dev": "node esbuild.config.mjs", "dev": "node esbuild.config.mjs",
@@ -14,20 +14,21 @@
"license": "GNU GPLv3", "license": "GNU GPLv3",
"devDependencies": { "devDependencies": {
"@types/node": "^20.5.7", "@types/node": "^20.5.7",
"@types/yaml-front-matter": "^4.1.0", "@types/yaml-front-matter": "^4.1.3",
"@typescript-eslint/eslint-plugin": "^6.5.0", "@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.5.0", "@typescript-eslint/parser": "^6.11.0",
"builtin-modules": "^3.2.0", "builtin-modules": "^3.2.0",
"esbuild": "0.19.2", "esbuild": "0.19.5",
"obsidian": "latest", "obsidian": "latest",
"tslib": "2.6.2", "tslib": "2.6.2",
"typescript": "5.2.2" "typescript": "5.2.2"
}, },
"dependencies": { "dependencies": {
"@tryfabric/martian": "^1.2.0", "@tryfabric/martian": "^1.2.4",
"https-proxy-agent": "^7.0.1", "https-proxy-agent": "^7.0.2",
"process": "^0.11.10", "process": "^0.11.10",
"yaml": "^2.2.2", "remark-math": "^6.0.0",
"yaml": "^2.3.4",
"yaml-front-matter": "^4.1.1" "yaml-front-matter": "^4.1.1"
} }
} }

View File

@@ -1,23 +0,0 @@
export const NoticeMsg: {[key: string]:any} = {
"en": {
"notion-logo": "Share to NotionNext",
"sync-success": "Sync to NotionNext success: \n",
"sync-fail": "Sync to NotionNext fail: \n",
"open-notion": "Please open the file that needs to be synchronized",
"config-secrets-notion-api": "Please set up the notion API in the settings tab.",
"config-secrets-database-id": "Please set up the database id in the settings tab.",
"set-tags-fail": "Set tags fail,please check the frontmatter of the file or close the tag switch in the settings tab.",
},
"zh": {
"notion-logo": "分享到NotionNext",
"sync-success": "同步到NotionNext成功:\n",
"sync-fail": "同步到NotionNext失败: \n",
"open-file": "请打开需要同步的文件",
"set-tags-fail": "设置标签失败,请检查文件的frontmatter,或者在插件设置中关闭设置tags开关",
},
}
export const NoticeMConfig = (lang:any) :any => {
return NoticeMsg[lang]
}

View File

@@ -1,239 +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 Upload2Notion {
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
}
}
// 因为需要解析notion的block进行对比非常的麻烦
// 暂时就直接删除新建一个page
async updatePage(notionID: string, title: string, allowTags: boolean, 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, allowTags, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, childArr)
}
async createPage(title: string, allowTags: boolean, 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: allowTags && tags !== undefined ? 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, allowTags: boolean, 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, allowTags, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, file2Block);
} else {
res = await this.createPage(title, allowTags, 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
}
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

@@ -0,0 +1,51 @@
import { FuzzySuggestModal, FuzzyMatch } from 'obsidian';
import MyPlugin from "../main";
import { i18nConfig } from "../lang/I18n";
/**
* Simple interface for what should be displayed and stored for suggester
*/
export interface DatabaseList {
name: string, // specific database name
match: any //
}
export class FuzzySuggester extends FuzzySuggestModal<DatabaseList>{
private plugin: MyPlugin;
private data: DatabaseList[];
private callback: any;
constructor(plugin: MyPlugin) {
super(plugin.app);
this.plugin = plugin;
this.setPlaceholder(i18nConfig.PlaceHolder);
}
setSuggesterData(suggesterData: Array<DatabaseList>): void { this.data = suggesterData }
async display(callBack: (item: DatabaseList, evt: MouseEvent | KeyboardEvent) => void): Promise<any> {
this.callback = callBack;
this.open();
}
// Store the data
getItems(): DatabaseList[] {
return this.data
}
getItemText(item: DatabaseList): string {
return item.name
}
onChooseItem(item: DatabaseList, evt: MouseEvent | KeyboardEvent): void { }
onChooseSuggestion(item: FuzzyMatch<DatabaseList>, evt: MouseEvent | KeyboardEvent): void {
this.callback(item.item, evt)
}
renderSuggestion(item: FuzzyMatch<DatabaseList>, el: HTMLElement): void {
el.createEl('div', { text: item.item.name })
}
}

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,
}
);
});
}
}

17
src/lang/I18n.ts Normal file
View File

@@ -0,0 +1,17 @@
import {en} from "./locale/en";
import {zh} from "./locale/zh";
import {ja} from "./locale/ja";
export const I18n: {[key: string]:any} = {
en,
zh,
ja,
};
export const I18nConfig = (lang: string): any => {
return I18n[lang];
};
const storedLanguage = window.localStorage.getItem("language");
export const i18nConfig = I18n[storedLanguage || window.navigator.language.split('-')[0] || "en"];

54
src/lang/locale/en.ts Normal file
View File

@@ -0,0 +1,54 @@
export const en = {
ribbonIcon: "Share to NotionNext",
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 Sync",
NotionNextButtonDesc: "Open this option, Sync to NotionNext command will be displayed in the command palette (default: ON)",
NotionNextSettingHeader: "NotionNext Database Settings",
NotionAPI: "Notion API Token",
NotionAPIDesc: "Generate from https://www.notion.so/my-integrations",
NotionAPIText: "Enter your Notion API Token",
DatabaseID: "Database ID",
DatabaseIDText: "Enter your Database ID",
BannerUrl: "Banner url (optional)",
BannerUrlDesc:
"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:
"Collect from share link likes:https://username.notion.site. Your notion id is [username]",
NotionUserText: "Enter your notion ID",
NotionGeneralSettingHeader: "General Notion Database Settings",
NotionGeneralButton: "Notion General Sync",
NotionGeneralButtonDesc: "Open this option, Sync to Notion General Database command will be displayed in the command palette (default: ON)",
NotionTagButton: "Notion Tags Sync",
NotionTagButtonDesc: "Sync Tags to Notion General Database (default: ON)",
NotionCustomTitle: "Customise title property",
NotionCustomTitleDesc: "Modify the column name of the Notion database (default: OFF)",
NotionCustomTitleName: "Preferred title name",
NotionCustomTitleNameDesc: "Enter the preferred title name for the first column of the Notion database (default: title)",
NotionCustomTitleText: "Enter the name",
NotYetFinish:
"Not finished. This function will be available in the next version",
PlaceHolder: "Enter database Name",
"notion-logo": "Share to NotionNext",
"sync-success": "Sync to NotionNext success: \n",
"sync-fail": "Sync to NotionNext fail: \n",
"open-notion": "Please open the file that needs to be synchronized",
"config-secrets-notion-api":
"Please set up the notion API in the settings tab.",
"config-secrets-database-id":
"Please set up the database id in the settings tab.",
"set-tags-fail":
"Set tags fail,please check the frontmatter of the file or close the tag switch in the settings tab.",
NNonMissing:
"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",
}

46
src/lang/locale/ja.ts Normal file
View File

@@ -0,0 +1,46 @@
export const ja = {
ribbonIcon: "NotionNextで共有",
GeneralSetting: "一般設定",
CommandID: "share-to-notionnext",
CommandName: "NotionNextデータベースに共有",
CommandIDGeneral: "share-to-notion",
CommandNameGeneral: "一般的なNotionデータベースに共有",
NotionNextButton: "NotionNext同期",
NotionNextButtonDesc: "このオプションを開くと、NotionNext同期コマンドがコマンドパレットに表示されますデフォルトON",
NotionNextSettingHeader: "NotionNextデータベース設定",
NotionAPI: "Notion API トークン",
NotionAPIDesc: "https://www.notion.so/my-integrations から生成してください",
NotionAPIText: "Notion API トークンを入力",
DatabaseID: "データベースID",
DatabaseIDText: "データベースIDを入力",
BannerUrl: "バナーのURL任意",
BannerUrlDesc: "デフォルトは空白です。バナーを表示したい場合は、URLを入力してくださいhttps://minioapi.pjx.ac.cn/img1/2023/11/b7b40a0724e93b7d7ab494bb3b8a2da8.png",
BannerUrlText: "バナーのURLを入力",
NotionUser: "Notion IDユーザー名、任意",
NotionUserDesc: "共有リンクから取得https://username.notion.site。Notion IDは[username]です",
NotionUserText: "Notion IDを入力",
NotionGeneralSettingHeader: "一般的なNotionデータベース設定",
NotionGeneralButton: "一般的なNotion同期",
NotionGeneralButtonDesc: "このオプションを開くと、一般的なNotionデータベース同期コマンドがコマンドパレットに表示されますデフォルトON",
NotionTagButton: "Notionタグ同期",
NotionTagButtonDesc: "タグを一般的なNotionデータベースに同期デフォルトON",
NotionCustomTitle: "タイトルのカスタマイズ",
NotionCustomTitleDesc: "Notionデータベースの列名を変更デフォルトOFF",
NotionCustomTitleName: "希望のタイトル名",
NotionCustomTitleNameDesc: "Notionデータベースの最初の列のための希望のタイトル名を入力デフォルトtitle",
NotionCustomTitleText: "名前を入力",
NotYetFinish: "未完了。この機能は次のバージョンで利用可能になります",
PlaceHolder: "データベース名を入力",
"notion-logo": "NotionNextで共有",
"sync-success": "NotionNextへの同期に成功\n",
"sync-fail": "NotionNextへの同期に失敗\n",
"open-notion": "同期が必要なファイルを開いてください",
"config-secrets-notion-api": "設定タブでNotion APIを設定してください",
"config-secrets-database-id": "設定タブでデータベースIDを設定してください",
"set-tags-fail": "タグの設定に失敗。ファイルのfrontmatterを確認するか、設定タブでタグのスイッチをオフにしてください",
NNonMissing: "設定に 'NNon' プロパティがありません。設定してください",
"set-api-id": "設定タブでNotion APIおよびデータベースIDを設定してください",
NotionCustomSettingHeader: "Notionカスタムデータベース設定",
NotionCustomButton: "Notionカスタマイズコマンドの切り替え",
NotionCustomButtonDesc: "このオプションを開くと、Notionカスタムデータベース同期コマンドがコマンドパレットに表示されます",
};

49
src/lang/locale/zh.ts Normal file
View File

@@ -0,0 +1,49 @@
export const zh = {
ribbonIcon: "分享到 NotionNext",
GeneralSetting: "通用设置",
CommandID: "share-to-notionnext",
CommandName: "分享到 NotionNext",
CommandIDGeneral: "share-to-notion",
CommandNameGeneral: "分享到 Notion 普通数据库",
NotionNextButton: "NotionNext 同步",
NotionNextButtonDesc: "打开此选项NotionNext 同步将显示在命令面板中(默认:开)",
NotionNextSettingHeader: "NotionNext 数据库参数设置",
NotionAPI: "Notion API 令牌",
NotionAPIDesc: "从 https://www.notion.so/my-integrations 生成",
NotionAPIText: "输入你的 Notion API 令牌",
DatabaseID: "数据库 ID",
DatabaseIDText: "输入你的数据库 ID",
BannerUrl: "封面图片地址(可选)",
BannerUrlDesc:
"默认为空如果你想显示封面图片请输入图片地址例如https://minioapi.pjx.ac.cn/img1/2023/11/b7b40a0724e93b7d7ab494bb3b8a2da8.png",
BannerUrlText: "输入你的封面图片地址",
NotionUser: "Notion ID用户名可选",
NotionUserDesc:
"数据库分享链接类似https://username.notion.site/。你的 Notion ID 是 [username]",
NotionUserText: "输入你的 Notion ID",
NotionGeneralSettingHeader: "普通 Notion 数据库设置",
NotionGeneralButton: "普通数据库同步",
NotionGeneralButtonDesc: "打开此选项,同步到普通数据库命令将显示在命令面板中(默认:开)",
NotionTagButton: "标签同步开关",
NotionTagButtonDesc: "将标签同步到普通数据库(默认:开)",
NotionCustomTitle: "修改 Notion 数据库表头开关",
NotionCustomTitleDesc: "自定义Notion 数据库第一列表头名(默认:关)",
NotionCustomTitleName: "想要修改的表头名",
NotionCustomTitleNameDesc: "输入你想要修改的notion数据库的表头名默认title",
NotionCustomTitleText: "输入表头名",
NotYetFinish: "未完成。此功能将在之后版本中提供",
PlaceHolder: "输入数据库名称",
"notion-logo": "分享到NotionNext",
"sync-success": "同步到NotionNext成功:\n",
"sync-fail": "同步到NotionNext失败: \n",
"open-file": "请打开需要同步的文件",
"config-secrets-notion-api": "请在插件设置中添加notion API",
"config-secrets-database-id": "请在插件设置中添加database id",
"set-tags-fail":
"设置标签失败,请检查文件的frontmatter,或者在插件设置中关闭设置tags开关",
NNonMissing: "未设置'NNon'属性请在插件设置中选择NotionNext数据库。",
"set-api-id": "请在插件设置中设置notion API和database ID",
NotionCustomSettingHeader: "Notion 自定义数据库设置",
NotionCustomButton: "Notion 自定义数据库同步命令开关",
NotionCustomButtonDesc: "打开此选项,同步到自定义数据库命令将显示在命令面板中",
}

View File

@@ -1,241 +1,62 @@
import {App, Editor, MarkdownView, Notice, Plugin, PluginSettingTab, Setting} from "obsidian"; import { App, Editor, MarkdownView, Notice, Plugin, PluginSettingTab, Setting } from "obsidian";
import {addIcons} from 'src/icon'; import { addIcons } from 'src/ui/icon';
import {Upload2Notion} from "src/Upload2Notion"; import { Upload2NotionGeneral } from "src/upload/upload_general/Upload2NotionGeneral";
import {NoticeMConfig} from "src/Message"; 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! // Remember to rename these classes and interfaces!
interface PluginSettings {
notionAPI: string;
databaseID: string;
bannerUrl: string;
notionID: string;
proxy: string;
allowTags: boolean;
}
const langConfig = NoticeMConfig( window.localStorage.getItem('language') || 'en')
const DEFAULT_SETTINGS: PluginSettings = {
notionAPI: "",
databaseID: "",
bannerUrl: "",
notionID: "",
proxy: "",
allowTags: false
};
export default class ObsidianSyncNotionPlugin extends Plugin { export default class ObsidianSyncNotionPlugin extends Plugin {
settings: PluginSettings; settings: PluginSettings;
async onload() { commands: ribbonCommands;
await this.loadSettings(); app: App;
addIcons();
// This creates an icon in the left ribbon.
const ribbonIconEl = this.addRibbonIcon(
"notion-logo",
"Share to NotionNext",
async (evt: MouseEvent) => {
// Called when the user clicks the icon.
await this.upload();
}
);
// This adds a status bar item to the bottom of the app. Does not work on mobile apps. async onload() {
const statusBarItemEl = this.addStatusBarItem(); await this.loadSettings();
// statusBarItemEl.setText("share to notion"); this.commands = new ribbonCommands(this);
this.addCommand({ addIcons();
id: "share-to-notionnext", // This creates an icon in the left ribbon.
name: "share to notionnext", const ribbonIconEl = this.addRibbonIcon(
editorCallback: async (editor: Editor, view: MarkdownView) => { "notion-logo",
await this.upload() i18nConfig.ribbonIcon,
}, async (evt: MouseEvent) => {
}); // Called when the user clicks the icon.
// 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.
// This adds a settings tab so the user can configure various aspects of the plugin // const statusBarItemEl = this.addStatusBarItem();
this.addSettingTab(new ObsidianSettingTab(this.app, this)); // // 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));
onunload() {} }
async upload(){ onunload() {
const { notionAPI, databaseID, allowTags } = this.settings; }
if (notionAPI === "" || databaseID === "") {
new Notice(
"Please set up the notion API and database ID in the settings tab."
);
return;
}
const { markDownData, nowFile, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime } =await this.getNowFileMarkdownContent(this.app);
if (markDownData) { async loadSettings() {
const { basename } = nowFile; this.settings = Object.assign(
const upload = new Upload2Notion(this); {},
const res = await upload.syncMarkdownToNotion(basename, allowTags, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, markDownData, nowFile, this.app, this.settings) DEFAULT_SETTINGS,
if(res.status === 200){ await this.loadData()
new Notice(`${langConfig["sync-success"]}${basename}`) );
}else { }
new Notice(`${langConfig["sync-fail"]}${basename}`, 5000)
}
}
}
async getNowFileMarkdownContent(app: App) { async saveSettings() {
const nowFile = app.workspace.getActiveFile(); await this.saveData(this.settings);
const { allowTags } = 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(allowTags) {
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(langConfig["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(langConfig["open-file"]);
return;
}
}
async loadSettings() {
this.settings = Object.assign(
{},
DEFAULT_SETTINGS,
await this.loadData()
);
}
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("Notion API Token")
.setDesc("It's a secret")
.addText((text) =>{
text.inputEl.type = 'password';
return text
.setPlaceholder("Enter your Notion API Token")
.setValue(this.plugin.settings.notionAPI)
.onChange(async (value) => {
this.plugin.settings.notionAPI = value;
await this.plugin.saveSettings();
})
});
const notionDatabaseID = new Setting(containerEl)
.setName("Database ID")
.setDesc("It's a secret")
.addText((text) => {
text.inputEl.type = 'password';
return text
.setPlaceholder("Enter your Database ID")
.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("Banner url(optional)")
.setDesc("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)")
.addText((text) =>
text
.setPlaceholder("Enter banner pic url: ")
.setValue(this.plugin.settings.bannerUrl)
.onChange(async (value) => {
this.plugin.settings.bannerUrl = value;
await this.plugin.saveSettings();
})
);
new Setting(containerEl)
.setName("Notion ID(optional)")
.setDesc("Your notion ID(optional),share link likes:https://username.notion.site/,your notion id is [username]")
.addText((text) =>
text
.setPlaceholder("Enter notion ID(options) ")
.setValue(this.plugin.settings.notionID)
.onChange(async (value) => {
this.plugin.settings.notionID = value;
await this.plugin.saveSettings();
})
);
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

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

@@ -0,0 +1,247 @@
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;
tagButton: boolean;
CustomTitleButton: boolean;
CustomTitleName: string;
notionAPIGeneral: string;
databaseIDGeneral: string;
CustomButton: boolean;
notionAPICustom: string;
databaseIDCustom: string;
[key: string]: any;
}
export const DEFAULT_SETTINGS: PluginSettings = {
NextButton: true,
notionAPINext: "",
databaseIDNext: "",
bannerUrl: "",
notionUser: "",
proxy: "",
GeneralButton: true,
tagButton: true,
CustomTitleButton: false,
CustomTitleName: "",
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();
// General Settings
containerEl.createEl('h2', { text: i18nConfig.GeneralSetting });
this.createSettingEl(containerEl, i18nConfig.BannerUrl, i18nConfig.BannerUrlDesc, 'text', i18nConfig.BannerUrlText, this.plugin.settings.bannerUrl, 'bannerUrl')
this.createSettingEl(containerEl, i18nConfig.NotionUser, i18nConfig.NotionUserDesc, 'text', i18nConfig.NotionUserText, this.plugin.settings.notionUser, 'notionUser')
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;
this.updateSettingEl(notionAPINextEl, value)
this.updateSettingEl(databaseIDNextEl, value)
await this.plugin.saveSettings();
await this.plugin.commands.updateCommand();
})
);
const notionAPINextEl = this.createStyleDiv('api-next', this.plugin.settings.NextButton)
this.createSettingEl(notionAPINextEl, i18nConfig.NotionAPI, i18nConfig.NotionAPIDesc, 'password', i18nConfig.NotionAPIText, this.plugin.settings.notionAPINext, 'notionAPINext')
const databaseIDNextEl = this.createStyleDiv('databaseID-next', this.plugin.settings.NextButton)
this.createSettingEl(databaseIDNextEl, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.plugin.settings.databaseIDNext, 'databaseIDNext')
// 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;
this.updateSettingEl(tagButtonEl, value)
this.updateSettingEl(CustomTitleEl, value)
// name should follow the result of the title button
if (value) {
this.updateSettingEl(CustomNameEl, this.plugin.settings.CustomTitleButton)
} else {
this.updateSettingEl(CustomNameEl, value)
}
this.updateSettingEl(notionAPIGeneralEl, value)
this.updateSettingEl(databaseIDGeneralEl, value)
await this.plugin.saveSettings();
await this.plugin.commands.updateCommand();
})
);
// add the tagButton to control whether to add tags to the general database
const tagButtonEl = this.createStyleDiv('tag-button', (this.plugin.settings.GeneralButton && this.plugin.settings.CustomTitleButton));
this.createSettingEl(tagButtonEl, i18nConfig.NotionTagButton, i18nConfig.NotionTagButtonDesc, 'toggle', i18nConfig.NotionCustomTitleText, this.plugin.settings.tagButton, 'tagButton')
// Custom Title Button
const CustomTitleEl = this.createStyleDiv('custom-title', this.plugin.settings.GeneralButton);
new Setting(CustomTitleEl)
.setName(i18nConfig.NotionCustomTitle)
.setDesc(i18nConfig.NotionCustomTitleDesc)
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.CustomTitleButton)
.onChange(async (value) => {
this.plugin.settings.CustomTitleButton = value;
this.updateSettingEl(CustomNameEl, value)
await this.plugin.saveSettings();
await this.plugin.commands.updateCommand();
})
);
// Custom Title Name
const CustomNameEl = this.createStyleDiv('custom-name', (this.plugin.settings.CustomTitleButton && this.plugin.settings.GeneralButton));
this.createSettingEl(CustomNameEl, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.plugin.settings.CustomTitleName, 'CustomTitleName')
// 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();
// })
// );
const notionAPIGeneralEl = this.createStyleDiv('api-general', this.plugin.settings.GeneralButton);
this.createSettingEl(notionAPIGeneralEl, i18nConfig.NotionAPI, i18nConfig.NotionAPIDesc, 'password', i18nConfig.NotionAPIText, this.plugin.settings.notionAPIGeneral, 'notionAPIGeneral')
const databaseIDGeneralEl = this.createStyleDiv('databaseID-general', this.plugin.settings.GeneralButton);
this.createSettingEl(databaseIDGeneralEl, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.plugin.settings.databaseIDGeneral, 'databaseIDGeneral')
// 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();
// })
// );
}
// create a function to create a div with a style for pop over elements
private createStyleDiv(className: string, commandValue: boolean = false) {
return this.containerEl.createDiv(className, (div) => {
this.updateSettingEl(div, commandValue);
});
}
// update the setting display style in the setting tab
private updateSettingEl(element: HTMLElement, commandValue: boolean) {
element.style.borderTop = commandValue ? "1px solid var(--background-modifier-border)" : "none";
element.style.paddingTop = commandValue ? "0.75em" : "0";
element.style.display = commandValue ? "block" : "none";
element.style.alignItems = "center";
}
// function to add one setting element in the setting tab.
private createSettingEl(containerEl: HTMLElement, name: string, desc: string, type: string, placeholder: string, holderValue: any, settingsKey: string) {
if (type === 'password') {
return new Setting(containerEl)
.setName(name)
.setDesc(desc)
.addText((text) => {
text.inputEl.type = type;
return text
.setPlaceholder(placeholder)
.setValue(holderValue)
.onChange(async (value) => {
this.plugin.settings[settingsKey] = value; // Update the plugin settings directly
await this.plugin.saveSettings();
})
});
} else if (type === 'toggle') {
return new Setting(containerEl)
.setName(name)
.setDesc(desc)
.addToggle((toggle) =>
toggle
.setValue(holderValue)
.onChange(async (value) => {
this.plugin.settings[settingsKey] = value; // Update the plugin settings directly
await this.plugin.saveSettings();
await this.plugin.commands.updateCommand();
})
);
} else if (type === 'text') {
return new Setting(containerEl)
.setName(name)
.setDesc(desc)
.addText((text) =>
text
.setPlaceholder(placeholder)
.setValue(holderValue)
.onChange(async (value) => {
this.plugin.settings[settingsKey] = value; // Update the plugin settings directly
await this.plugin.saveSettings();
await this.plugin.commands.updateCommand();
})
);
}
}
}

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,148 @@
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: {
[this.plugin.settings.CustomTitleButton
? this.plugin.settings.CustomTitleName
: "title"]: {
title: [
{
text: {
content: title,
},
},
],
},
...(this.plugin.settings.tagsButton
? {
tags: {
multi_select: tags && true ? tags.map((tag) => ({ 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> {
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 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

@@ -0,0 +1,262 @@
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 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
) {
await this.deletePage(notionID)
const databasecover = await this.getDataBase(this.plugin.settings.databaseIDNext)
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.databaseIDNext
},
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.notionAPINext,
'Notion-Version': '2022-06-28',
},
body: JSON.stringify(bodyString),
})
} catch (error) {
new Notice(`network error ${error}`)
}
}
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 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 updateYamlInfo(markdown, nowFile, res, app, this.plugin)
} else {
new Notice(`${res.text}`)
}
return res
}
}

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;
}
}

View File

@@ -17,8 +17,8 @@
] ]
}, },
"include": [ "include": [
"**/*.ts" "**/*.ts",
, "src/Upload2Notion.ts",
"src/Upload2Notion.ts" "src/*.ts"
] ]
} }

View File

@@ -1,11 +1,10 @@
// update package.json version // update package.json version
import fs from 'fs'; import fs from "fs";
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8')); const packageJson = JSON.parse(fs.readFileSync("./package.json", "utf8"));
console.log(packageJson.version); console.log(packageJson.version);
// get node args // get node args
const args = process.argv.slice(2); const args = process.argv.slice(2);
@@ -13,14 +12,13 @@ packageJson.version = args[0];
console.log(packageJson.version); console.log(packageJson.version);
// write package.json // write package.json
fs.writeFileSync('./package.json', JSON.stringify(packageJson, null, 2)); fs.writeFileSync("./package.json", JSON.stringify(packageJson, null, 2));
// read manifest.json // read manifest.json
const manifestJson = JSON.parse(fs.readFileSync('./manifest.json', 'utf8')); const manifestJson = JSON.parse(fs.readFileSync("./manifest.json", "utf8"));
manifestJson.version = args[0]; manifestJson.version = args[0];
// write manifest.json // write manifest.json
fs.writeFileSync('./manifest.json', JSON.stringify(manifestJson, null, 2)); fs.writeFileSync("./manifest.json", JSON.stringify(manifestJson, null, 2));

900
yarn.lock

File diff suppressed because it is too large Load Diff