mirror of
https://github.com/jxpeng98/obsidian-to-NotionNext
synced 2026-07-30 00:48:36 +08:00
Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eee349509a | ||
|
|
57c0941fed | ||
|
|
8734af6dbf | ||
|
|
041a78fb52 | ||
|
|
afec5d8364 | ||
|
|
75926a38d4 | ||
|
|
793dd67e0a | ||
|
|
f235c80d18 | ||
|
|
f33315a4b6 | ||
|
|
b62bd4ba2e | ||
|
|
402d15a38b | ||
|
|
87f1ce0146 | ||
|
|
398b785e03 | ||
|
|
8617878582 | ||
|
|
ae9e0c14fb | ||
|
|
9be9b18efb | ||
|
|
588f57205b | ||
|
|
cfbedea91d | ||
|
|
4cd6557444 | ||
|
|
407688c303 | ||
|
|
84b998aa93 | ||
|
|
4b6f1a1f1d | ||
|
|
4a2c59d13b | ||
|
|
8f116956ce | ||
|
|
df138d9304 | ||
|
|
49b8d470fb | ||
|
|
c39323c3fa | ||
|
|
05dff7a389 | ||
|
|
24fcadbc8b | ||
|
|
fdb81f76a7 | ||
|
|
024b7f726e | ||
|
|
722ca7bb56 | ||
|
|
fb7294d607 | ||
|
|
4f06d81588 | ||
|
|
2434ddd532 | ||
|
|
55804e491a | ||
|
|
679e7ec4f1 | ||
|
|
9be679f456 | ||
|
|
a0f5d2d51b | ||
|
|
a68a3920ad | ||
|
|
76d3fc9872 | ||
|
|
e3fb50b205 | ||
|
|
5411b0bac6 |
26
.github/workflows/CI.yml
vendored
26
.github/workflows/CI.yml
vendored
@@ -1,26 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- "*"
|
|
||||||
|
|
||||||
env:
|
|
||||||
PLUGIN_NAME: obsidian-to-notion
|
|
||||||
|
|
||||||
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
|
|
||||||
33
.github/workflows/release.yml
vendored
33
.github/workflows/release.yml
vendored
@@ -6,18 +6,18 @@ on:
|
|||||||
- "*"
|
- "*"
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PLUGIN_NAME: obsidian-to-notion # 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
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: "14.x"
|
node-version: "16.x"
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
id: build
|
id: build
|
||||||
@@ -25,16 +25,16 @@ jobs:
|
|||||||
npm install
|
npm install
|
||||||
npm run build
|
npm run build
|
||||||
mkdir ${{ env.PLUGIN_NAME }}
|
mkdir ${{ env.PLUGIN_NAME }}
|
||||||
cp main.js manifest.json styles.css ${{ 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.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||||
VERSION: ${{ github.ref }}
|
VERSION: ${{ github.ref }}
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ github.ref }}
|
tag_name: ${{ github.ref }}
|
||||||
@@ -46,7 +46,7 @@ jobs:
|
|||||||
id: upload-zip
|
id: upload-zip
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_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
|
||||||
@@ -57,7 +57,7 @@ jobs:
|
|||||||
id: upload-main
|
id: upload-main
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_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
|
||||||
@@ -68,18 +68,29 @@ jobs:
|
|||||||
id: upload-manifest
|
id: upload-manifest
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_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
|
||||||
|
id: upload-md
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./obsidian_template.md
|
||||||
|
asset_name: template.md
|
||||||
|
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.GITHUB_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
|
||||||
|
|||||||
23
Message.ts
23
Message.ts
@@ -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]
|
|
||||||
}
|
|
||||||
83
README-zh.md
83
README-zh.md
@@ -1,7 +1,38 @@
|
|||||||
# Obsidian 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编辑,整理好之后一键发布。
|
||||||
|
## 更新说明
|
||||||
|
### 0.2.6
|
||||||
|
- 增加一个按钮用来控制是否在名列列表中显示如下数据库。
|
||||||
|
|
||||||
|

|
||||||
|
如果你关闭普通数据库的按钮,你在上传命令列表中就不会出现普通数据库的选项。如果你关闭NotionNext数据库的按钮,你在上传命令列表中就不会出现NotionNext数据库的选项。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 0.2.3
|
||||||
|
- 修复了一个bug,现在可以正常更新了。
|
||||||
|
### 0.2.2
|
||||||
|
- 支持NotionNext 和 普通Notion 数据库的同步。
|
||||||
|
- 你可以有一个NotionNext和一个普通Notion数据库。
|
||||||
|
- 普通Notion数据库的同步方式和原作者的一样,只同步`title`和`tags`。**如果使用普通数据库功能,你需要保证你的数据库中有`title`和`tags`这两个表头。必须使用小写。**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
### 0.2.1
|
||||||
|
- 重构代码。
|
||||||
|
### 0.2.0
|
||||||
|
- 从这个版本开始,重构了交互逻辑。现在当你点击左侧的按钮,会弹出可同步的数据库选项。你可以选择你想要同步的数据库,然后点击同步按钮。**但是,现在仅支持同步单个数据库,如果你的数据库不是NotionNext,你可以不用更新。**
|
||||||
|
|
||||||
|
|
||||||
|
### 0.1.10
|
||||||
|
- 修正了设置中的中文显示。
|
||||||
|
### 0.1.8
|
||||||
|
- 重新整理了代码,增加了一个仓库转换按钮为之后的多数据库支持作准备。**但是现在还不支持多数据库,如果你的数据库不是NotionNext,你可以不用更新。**
|
||||||
|
### 0.1.7
|
||||||
|
- [x] 删除了设置中`convert tags`的选项。 你现在可以直接添加tags,而不需要考虑是否开启tags选项。如果你不需要tags,可以直接删除tags选项或者留白。
|
||||||
|
|
||||||
## 使用方式
|
## 使用方式
|
||||||
### 注意事项
|
### 注意事项
|
||||||
@@ -11,6 +42,7 @@
|
|||||||
|
|
||||||
### 准备安装
|
### 准备安装
|
||||||
在安装插件之前,你必须配置好了以下内容:
|
在安装插件之前,你必须配置好了以下内容:
|
||||||
|
|
||||||
1. 你的NotionNext数据库。
|
1. 你的NotionNext数据库。
|
||||||
2. 根据原作者的readme.md,配置好了Notion API,并且已经和你的NotionNext仓库关联。
|
2. 根据原作者的readme.md,配置好了Notion API,并且已经和你的NotionNext仓库关联。
|
||||||
3. NotionNext Database ID
|
3. NotionNext Database ID
|
||||||
@@ -25,10 +57,21 @@
|
|||||||
- summary
|
- summary
|
||||||
- password
|
- password
|
||||||
- icon
|
- icon
|
||||||
**如果你是直接复制的NotionNext的模板,这些内容应该已经有了。我在原作者的基础之上对本插件的内容进行了更改,所以你只需要保证你的数据库有如上内容,并且所有的字母都是小写!!!**
|
|
||||||
|
在最新的0.0.6版本,我还增加了以下内容:
|
||||||
|
- titleicon: 标题的emoji图标,暂时只能支持emoji
|
||||||
|
- coverurl: 封面图片的url, url可以是任何一种图片的url, 例如jpg,png,svg等等。
|
||||||
|
|
||||||
|
**如果你是直接复制的NotionNext的模板,这些内容应该已经有了。我在原作者的基础之上对本插件的内容进行了更改,所以你只需要保证你的数据库有如上内容,并且所有的字母都是小写!!!**
|
||||||
|
|
||||||
|
|
||||||
**⚠️⚠️⚠️:表头全部小写!!!顺序无所谓!**
|
**⚠️⚠️⚠️:表头全部小写!!!顺序无所谓!**
|
||||||
|
|
||||||
### 安装插件
|
### 安装插件
|
||||||
|
#### 社区插件市场下载
|
||||||
|
打开`Obsidian -> 设置 -> 社区插件 -> 浏览 -> 搜索Share to NotionNext`, 然后点击安装。
|
||||||
|
|
||||||
|
#### 手动安装
|
||||||
1. 关闭Obsidian
|
1. 关闭Obsidian
|
||||||
2. 从Release下载插件文件,解压到你的obsidian插件目录下。
|
2. 从Release下载插件文件,解压到你的obsidian插件目录下。
|
||||||
3. 重新打开Obsidian,进入设置,启用插件。
|
3. 重新打开Obsidian,进入设置,启用插件。
|
||||||
@@ -37,34 +80,48 @@
|
|||||||
### 使用插件
|
### 使用插件
|
||||||
在仓库中我上传了一个模板,你可以直接复制到你的模板文件夹中。然后使用Obsidian的模板功能一键生成新笔记。
|
在仓库中我上传了一个模板,你可以直接复制到你的模板文件夹中。然后使用Obsidian的模板功能一键生成新笔记。
|
||||||
|
|
||||||
|
|
||||||
如果你不想使用模板,你也可以直接在Obsidian中创建一个新的文件,然后复制下边的内容。然后保存。
|
如果你不想使用模板,你也可以直接在Obsidian中创建一个新的文件,然后复制下边的内容。然后保存。
|
||||||
```markdown
|
```markdown
|
||||||
---
|
---
|
||||||
type: Post # Post or Page, the default is Post
|
# default value has been set.
|
||||||
slug: test # slug for url, the default is
|
# for any unwanted value, you can delete it or set it to empty.
|
||||||
stats: Draft # Draft, Invisible, Published
|
# for example, if you donot want to set password, you can delete password: "1234" or set it to password: ""
|
||||||
category: test
|
# 我已经在插件中设置了默认值,如果有不需要的选项,可以直接删除。
|
||||||
summary: this is a summary for test post
|
# 例如你不需要密码选项,你可以将password: "1234"删除,或者将它设置为空。
|
||||||
icon: fa-solid fa-camera # you can ignore this
|
# !!!!!!!!!!!!
|
||||||
password: "1234" # if you donot want to set password, you can delete this line
|
# 现在阶段一定不要修改表头的名字, please do not change the name of the header in YAML front matter
|
||||||
|
# !!!!!!!!!!!!
|
||||||
|
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, 默认是空
|
||||||
|
type: Post # Post or Page, default is Post, 默认是Post
|
||||||
|
slug: test # slug for url, default is empty, 默认是空
|
||||||
|
stats: Draft # Draft, Invisible, Published, default is Draft, 默认是Draft
|
||||||
|
category: test # default is 'Obsidian', 默认是'Obsidian'
|
||||||
|
summary: this is a summary for test post # default is empty, 默认是空
|
||||||
|
icon: fa-solid fa-camera # you can ignore this, default is empty, 默认是空,可直接删除
|
||||||
|
password: "1234" # if you donot want to set password, you can delete this line, default is empty, 默认是空,可直接删除
|
||||||
|
# 现在必须开启tags选项,否则会报错
|
||||||
tags:
|
tags:
|
||||||
- test # tags for post
|
- test # tags for post
|
||||||
- web # add more tags if you want
|
- web # add more tags if you want
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
Contents Below
|
Contents Below
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
模板使用如下:
|
模板使用如下:
|
||||||

|

|
||||||
|
|
||||||
**插件预览如下**
|
**插件预览如下**
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**以下为原README.md**
|
**以下为原README.md**
|
||||||
|
|
||||||
非常感谢原作者的开发,我只是在原作者的基础之上进行了修改,增加了一些功能。如果你觉得这个插件对你有帮助,可以给[原作者](https://github.com/EasyChris/obsidian-to-notion)一个star。
|
非常感谢原作者的开发,我只是在原作者的基础之上进行了修改,增加了一些功能。如果你觉得这个插件对你有帮助,可以给[原作者](https://github.com/EasyChris/obsidian-to-notion)一个star。
|
||||||
|
|
||||||
# Obsidian to Notion
|
# Obsidian to Notion
|
||||||
|
|||||||
86
README.md
86
README.md
@@ -1,8 +1,43 @@
|
|||||||
# Obsidian to NotionNext
|
# Obsidian to NotionNext
|
||||||
[中文文档](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 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.
|
||||||
|
|
||||||
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.
|
||||||
|
## Update
|
||||||
|
### 0.2.6
|
||||||
|
- Add a switch button to control whether to show the upload command in the command palette.
|
||||||
|
|
||||||
|

|
||||||
|
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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 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.**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 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
|
||||||
@@ -26,10 +61,20 @@ Before installing the plugin, you must have set up the following:
|
|||||||
- summary
|
- summary
|
||||||
- password
|
- password
|
||||||
- icon
|
- icon
|
||||||
**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!**
|
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.
|
||||||
|
|
||||||
|
**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!**
|
||||||
|
|
||||||
### 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.
|
||||||
@@ -42,28 +87,43 @@ In the repository, I have uploaded a template which you can directly copy into y
|
|||||||
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
|
||||||
---
|
---
|
||||||
type: Post # Post or Page, the default is Post
|
# default value has been set.
|
||||||
slug: test # slug for url, the default is
|
# for any unwanted value, you can delete it or set it to empty.
|
||||||
stats: Draft # Draft, Invisible, Published
|
# for example, if you donot want to set password, you can delete password: "1234" or set it to password: ""
|
||||||
category: test
|
# 我已经在插件中设置了默认值,如果有不需要的选项,可以直接删除。
|
||||||
summary: this is a summary for test post
|
# 例如你不需要密码选项,你可以将password: "1234"删除,或者将它设置为空。
|
||||||
icon: fa-solid fa-camera # you can ignore this
|
# !!!!!!!!!!!!
|
||||||
password: "1234" # if you donot want to set password, you can delete this line
|
# 现在阶段一定不要修改表头的名字, please do not change the name of the header in YAML front matter
|
||||||
|
# !!!!!!!!!!!!
|
||||||
|
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, 默认是空
|
||||||
|
type: Post # Post or Page, default is Post, 默认是Post
|
||||||
|
slug: test # slug for url, default is empty, 默认是空
|
||||||
|
stats: Draft # Draft, Invisible, Published, default is Draft, 默认是Draft
|
||||||
|
category: test # default is 'Obsidian', 默认是'Obsidian'
|
||||||
|
summary: this is a summary for test post # default is empty, 默认是空
|
||||||
|
icon: fa-solid fa-camera # you can ignore this, default is empty, 默认是空,可直接删除
|
||||||
|
password: "1234" # if you donot want to set password, you can delete this line, default is empty, 默认是空,可直接删除
|
||||||
|
# 现在必须开启tags选项,否则会报错
|
||||||
tags:
|
tags:
|
||||||
- test # tags for post
|
- test # tags for post
|
||||||
- web # add more tags if you want
|
- web # add more tags if you want
|
||||||
---
|
---
|
||||||
|
|
||||||
Contents Below
|
Contents Below
|
||||||
|
|
||||||
```
|
```
|
||||||
Usage of the template is as follows:
|
Usage of the template is as follows:
|
||||||

|

|
||||||
|
|
||||||
**Plugin preview is shown below**
|
**Plugin preview is shown below**
|
||||||

|

|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Original README.md**
|
**Original README.md**
|
||||||
|
|
||||||
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
|
||||||
@@ -150,9 +210,9 @@ Fill the configuration with the `NOTION_API_KEY` and `DATABASE_ID` you got
|
|||||||

|

|
||||||
|
|
||||||
## Upload file content to notion
|
## Upload file content to notion
|
||||||
Click the upload notion button
|
Click the uploadCommand notion button
|
||||||

|

|
||||||
A share link will be automatically generated after successful upload
|
A share link will be automatically generated after successful uploadCommand
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
|||||||
195
Upload2Notion.ts
195
Upload2Notion.ts
@@ -1,195 +0,0 @@
|
|||||||
import { Notice, requestUrl,TFile,normalizePath, App } 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 "main";
|
|
||||||
export class Upload2Notion {
|
|
||||||
app: MyPlugin;
|
|
||||||
notion: Client;
|
|
||||||
agent: any;
|
|
||||||
constructor(app: MyPlugin) {
|
|
||||||
this.app = app;
|
|
||||||
}
|
|
||||||
|
|
||||||
async deletePage(notionID:string){
|
|
||||||
const response = await requestUrl({
|
|
||||||
url: `https://api.notion.com/v1/blocks/${notionID}`,
|
|
||||||
method: 'DELETE',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': 'Bearer ' + this.app.settings.notionAPI,
|
|
||||||
'Notion-Version': '2022-02-22',
|
|
||||||
},
|
|
||||||
body: ''
|
|
||||||
})
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 因为需要解析notion的block进行对比,非常的麻烦,
|
|
||||||
// 暂时就直接删除,新建一个page
|
|
||||||
async updatePage(notionID:string, title:string, allowTags:boolean, 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 res = await this.createPage(title, allowTags, tags, type, slug, stats, category, summary, paword, favicon, datetime, childArr)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
async createPage(title:string, allowTags:boolean, 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.app.settings.databaseID
|
|
||||||
},
|
|
||||||
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(this.app.settings.bannerUrl) {
|
|
||||||
bodyString.cover = {
|
|
||||||
type: "external",
|
|
||||||
external: {
|
|
||||||
url: this.app.settings.bannerUrl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await requestUrl({
|
|
||||||
url: `https://api.notion.com/v1/pages`,
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
// 'User-Agent': 'obsidian.md',
|
|
||||||
'Authorization': 'Bearer ' + this.app.settings.notionAPI,
|
|
||||||
'Notion-Version': '2022-06-28',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(bodyString),
|
|
||||||
})
|
|
||||||
return response;
|
|
||||||
} catch (error) {
|
|
||||||
new Notice(`network error ${error}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async syncMarkdownToNotion(title:string, allowTags:boolean, 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 yamlObj:any = yamlFrontMatter.loadFront(markdown);
|
|
||||||
const __content = yamlObj.__content
|
|
||||||
const file2Block = markdownToBlocks(__content);
|
|
||||||
const frontmasster =await app.metadataCache.getFileCache(nowFile)?.frontmatter
|
|
||||||
const notionID = frontmasster ? frontmasster.notionID : null
|
|
||||||
|
|
||||||
if(notionID){
|
|
||||||
res = await this.updatePage(notionID, title, allowTags, tags, type, slug, stats, category, summary, paword, favicon, datetime, file2Block);
|
|
||||||
} else {
|
|
||||||
res = await this.createPage(title, allowTags, 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) {
|
|
||||||
const yamlObj:any = yamlFrontMatter.loadFront(yamlContent);
|
|
||||||
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`)
|
|
||||||
}
|
|
||||||
yamlObj.link = url;
|
|
||||||
try {
|
|
||||||
await navigator.clipboard.writeText(url)
|
|
||||||
} catch (error) {
|
|
||||||
new Notice(`复制链接失败,请手动复制${error}`)
|
|
||||||
}
|
|
||||||
yamlObj.notionID = id;
|
|
||||||
const __content = yamlObj.__content;
|
|
||||||
delete yamlObj.__content
|
|
||||||
const yamlhead = yaml.stringify(yamlObj)
|
|
||||||
// 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}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,14 +8,13 @@ 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');
|
||||||
|
|
||||||
esbuild.build({
|
const ctx = await esbuild.context({
|
||||||
banner: {
|
banner: {
|
||||||
js: banner,
|
js: banner,
|
||||||
},
|
},
|
||||||
entryPoints: ['main.ts'],
|
entryPoints: ['src/main.ts'],
|
||||||
bundle: true,
|
bundle: true,
|
||||||
external: [
|
external: [
|
||||||
'obsidian',
|
'obsidian',
|
||||||
@@ -41,12 +40,19 @@ esbuild.build({
|
|||||||
'@codemirror/text',
|
'@codemirror/text',
|
||||||
'@codemirror/tooltip',
|
'@codemirror/tooltip',
|
||||||
'@codemirror/view',
|
'@codemirror/view',
|
||||||
...builtins],
|
...builtins
|
||||||
|
],
|
||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
watch: !prod,
|
|
||||||
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',
|
||||||
}).catch(() => process.exit(1));
|
});
|
||||||
|
|
||||||
|
if (!prod) {
|
||||||
|
await ctx.watch();
|
||||||
|
} else {
|
||||||
|
await ctx.rebuild()
|
||||||
|
ctx.dispose().then(r => console.log('Build completed'), e => console.error(e));
|
||||||
|
}
|
||||||
|
|||||||
253
main.ts
253
main.ts
@@ -1,253 +0,0 @@
|
|||||||
import {
|
|
||||||
App,
|
|
||||||
Editor,
|
|
||||||
MarkdownView,
|
|
||||||
Modal,
|
|
||||||
Notice,
|
|
||||||
Plugin,
|
|
||||||
PluginSettingTab,
|
|
||||||
Setting,
|
|
||||||
normalizePath
|
|
||||||
} from "obsidian";
|
|
||||||
import {addIcons} from 'icon';
|
|
||||||
import { Upload2Notion } from "Upload2Notion";
|
|
||||||
import {NoticeMConfig} from "Message";
|
|
||||||
import { CLIENT_RENEG_LIMIT } from "tls";
|
|
||||||
|
|
||||||
|
|
||||||
// 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 {
|
|
||||||
settings: PluginSettings;
|
|
||||||
async onload() {
|
|
||||||
await this.loadSettings();
|
|
||||||
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.
|
|
||||||
this.upload();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// This adds a status bar item to the bottom of the app. Does not work on mobile apps.
|
|
||||||
const statusBarItemEl = this.addStatusBarItem();
|
|
||||||
// statusBarItemEl.setText("share to notion");
|
|
||||||
|
|
||||||
this.addCommand({
|
|
||||||
id: "share-to-notionnext",
|
|
||||||
name: "share to notionnext",
|
|
||||||
editorCallback: async (editor: Editor, view: MarkdownView) => {
|
|
||||||
this.upload()
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// This adds a settings tab so the user can configure various aspects of the plugin
|
|
||||||
this.addSettingTab(new SampleSettingTab(this.app, this));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
onunload() {}
|
|
||||||
|
|
||||||
async upload(){
|
|
||||||
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, tags, type, slug, stats, category, summary, paword, favicon, datetime } =await this.getNowFileMarkdownContent(this.app);
|
|
||||||
|
|
||||||
if (markDownData) {
|
|
||||||
const { basename } = nowFile;
|
|
||||||
const upload = new Upload2Notion(this);
|
|
||||||
const res = await upload.syncMarkdownToNotion(basename, allowTags, tags, type, slug, stats, category, summary, paword, favicon, datetime, markDownData, nowFile, this.app, this.settings)
|
|
||||||
if(res.status === 200){
|
|
||||||
new Notice(`${langConfig["sync-success"]}${basename}`)
|
|
||||||
}else {
|
|
||||||
new Notice(`${langConfig["sync-fail"]}${basename}`, 5000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getNowFileMarkdownContent(app: App) {
|
|
||||||
const nowFile = app.workspace.getActiveFile();
|
|
||||||
const { allowTags } = this.settings;
|
|
||||||
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) {
|
|
||||||
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,
|
|
||||||
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 SampleSettingTab extends PluginSettingTab {
|
|
||||||
plugin: ObsidianSyncNotionPlugin;
|
|
||||||
|
|
||||||
constructor(app: App, plugin: ObsidianSyncNotionPlugin) {
|
|
||||||
super(app, plugin);
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
display(): void {
|
|
||||||
const { containerEl } = this;
|
|
||||||
|
|
||||||
containerEl.empty();
|
|
||||||
|
|
||||||
containerEl.createEl("h2", {
|
|
||||||
text: "Settings for obsidian to NotionNext plugin.",
|
|
||||||
});
|
|
||||||
|
|
||||||
new Setting(containerEl)
|
|
||||||
.setName("Notion API Token")
|
|
||||||
.setDesc("It's a secret")
|
|
||||||
.addText((text) =>{
|
|
||||||
let t = text
|
|
||||||
.setPlaceholder("Enter your Notion API Token")
|
|
||||||
.setValue(this.plugin.settings.notionAPI)
|
|
||||||
.onChange(async (value) => {
|
|
||||||
this.plugin.settings.notionAPI = value;
|
|
||||||
await this.plugin.saveSettings();
|
|
||||||
})
|
|
||||||
// t.inputEl.type = 'password'
|
|
||||||
return t
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
const notionDatabaseID = new Setting(containerEl)
|
|
||||||
.setName("Database ID")
|
|
||||||
.setDesc("It's a secret")
|
|
||||||
.addText((text) => {
|
|
||||||
let t = text
|
|
||||||
.setPlaceholder("Enter your Database ID")
|
|
||||||
.setValue(this.plugin.settings.databaseID)
|
|
||||||
.onChange(async (value) => {
|
|
||||||
this.plugin.settings.databaseID = value;
|
|
||||||
await this.plugin.saveSettings();
|
|
||||||
})
|
|
||||||
// t.inputEl.type = 'password'
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"id": "obsidian-to-notionnext",
|
"id": "share-to-notionnext",
|
||||||
"name": "Obsidian shared to NotionNext",
|
"name": "Share to NotionNext",
|
||||||
"version": "0.0.1",
|
"version": "0.2.6",
|
||||||
"minAppVersion": "0.0.1",
|
"minAppVersion": "0.0.1",
|
||||||
"description": "This is a plugin for Obsidian. This plugin share obsidian md file to notion with notion api for NotionNext web deploy.",
|
"description": "Shares obsidian md file to notion with notion api for NotionNext web deploy, originally created by EasyChris/obsidian-to-notion.",
|
||||||
"author": "jxpeng98",
|
"author": "EasyChris, jxpeng98",
|
||||||
"authorUrl": "https://github.com/jxpeng98/obsidian-to-NotionNext",
|
"authorUrl": "https://github.com/jxpeng98",
|
||||||
"isDesktopOnly": false
|
"isDesktopOnly": false
|
||||||
}
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
type: Post // Post or Page
|
|
||||||
slug: test // slug for url
|
|
||||||
stats: Draft // Draft, Invisible, Published
|
|
||||||
category: test
|
|
||||||
summary: this is a summary for test post
|
|
||||||
icon: fa-solid fa-camera // you can ignore this
|
|
||||||
password: "1234" // if you donot want to set password, you can delete this line
|
|
||||||
tags:
|
|
||||||
- test // tags for post
|
|
||||||
- web // add more tags if you want
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
Contents Below
|
|
||||||
26
obsidian_template.md
Normal file
26
obsidian_template.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
# default value has been set.
|
||||||
|
# for any unwanted value, you can delete it or set it to empty.
|
||||||
|
# for example, if you donot want to set password, you can delete password: "1234" or set it to password: ""
|
||||||
|
# 我已经在插件中设置了默认值,如果有不需要的选项,可以直接删除。
|
||||||
|
# 例如你不需要密码选项,你可以将password: "1234"删除,或者将它设置为空。
|
||||||
|
# !!!!!!!!!!!!
|
||||||
|
# 现在阶段一定不要修改表头的名字, please do not change the name of the header in YAML front matter
|
||||||
|
# !!!!!!!!!!!!
|
||||||
|
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, 默认是空
|
||||||
|
type: Post # Post or Page, default is Post, 默认是Post
|
||||||
|
slug: test # slug for url, default is empty, 默认是空
|
||||||
|
stats: Draft # Draft, Invisible, Published, default is Draft, 默认是Draft
|
||||||
|
category: test # default is 'Obsidian', 默认是'Obsidian'
|
||||||
|
summary: this is a summary for test post # default is empty, 默认是空
|
||||||
|
icon: fa-solid fa-camera # you can ignore this, default is empty, 默认是空,可直接删除
|
||||||
|
password: "1234" # if you donot want to set password, you can delete this line, default is empty, 默认是空,可直接删除
|
||||||
|
# 现在必须开启tags选项,否则会报错
|
||||||
|
tags:
|
||||||
|
- test # tags for post
|
||||||
|
- web # add more tags if you want
|
||||||
|
---
|
||||||
|
|
||||||
|
Contents Below
|
||||||
22
package.json
22
package.json
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "obsidian-to-notionnext",
|
"name": "share-to-notionnext",
|
||||||
"version": "0.0.1",
|
"version": "0.2.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "This is a plugin for Obsidian. This plugin share obsidian md file to notion with notion api for NotionNext web deploy.",
|
"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",
|
||||||
@@ -13,19 +13,21 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "GNU GPLv3",
|
"license": "GNU GPLv3",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^17.0.35",
|
"@types/node": "^20.5.7",
|
||||||
"@types/yaml-front-matter": "^4.1.0",
|
"@types/yaml-front-matter": "^4.1.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.2.0",
|
"@typescript-eslint/eslint-plugin": "^6.5.0",
|
||||||
"@typescript-eslint/parser": "^5.2.0",
|
"@typescript-eslint/parser": "^6.5.0",
|
||||||
"builtin-modules": "^3.2.0",
|
"builtin-modules": "^3.2.0",
|
||||||
"esbuild": "0.13.12",
|
"esbuild": "0.19.2",
|
||||||
"obsidian": "latest",
|
"obsidian": "latest",
|
||||||
"tslib": "2.3.1",
|
"tslib": "2.6.2",
|
||||||
"typescript": "4.4.4"
|
"typescript": "5.2.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tryfabric/martian": "^1.2.0",
|
"@tryfabric/martian": "^1.2.0",
|
||||||
"https-proxy-agent": "^5.0.1",
|
"https-proxy-agent": "^7.0.1",
|
||||||
|
"process": "^0.11.10",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"yaml": "^2.2.2",
|
"yaml": "^2.2.2",
|
||||||
"yaml-front-matter": "^4.1.1"
|
"yaml-front-matter": "^4.1.1"
|
||||||
}
|
}
|
||||||
|
|||||||
51
src/commands/FuzzySuggester.ts
Normal file
51
src/commands/FuzzySuggester.ts
Normal 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 })
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
110
src/commands/NotionCommands.ts
Normal file
110
src/commands/NotionCommands.ts
Normal 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,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
99
src/lang/I18n.ts
Normal file
99
src/lang/I18n.ts
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
export const I18n: { [key: string]: any } = {
|
||||||
|
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 command switch",
|
||||||
|
NotionNextButtonDesc: "Open this option, Sync to NotionNext command will be displayed in the command palette",
|
||||||
|
NotionNextSettingHeader: "NotionNext Database Settings",
|
||||||
|
NotionAPI: "Notion API Token",
|
||||||
|
NotionAPIDesc: "It's a secret",
|
||||||
|
NotionAPIText: "Enter your Notion API Token",
|
||||||
|
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:
|
||||||
|
"Your notion ID (optional),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 command switch",
|
||||||
|
NotionGeneralButtonDesc: "Open this option, Sync to Notion General Database command will be displayed in the command palette",
|
||||||
|
NotYetFinish:
|
||||||
|
"Not finished. This function will be available in the next version",
|
||||||
|
PlaceHolder: "Enter database Name",
|
||||||
|
"notion-logo": "Share to NotionNext",
|
||||||
|
"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",
|
||||||
|
},
|
||||||
|
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: "显示为密码",
|
||||||
|
NotionAPIText: "输入你的 Notion API 令牌",
|
||||||
|
DatabaseID: "数据库 ID",
|
||||||
|
DatabaseIDText: "输入你的数据库 ID",
|
||||||
|
BannerUrl: "封面图片地址(可选)",
|
||||||
|
BannerUrlDesc:
|
||||||
|
"默认为空,如果你想显示封面图片,请输入图片地址(例如:https://minioapi.pjx.ac.cn/img1/2023/11/b7b40a0724e93b7d7ab494bb3b8a2da8.png)",
|
||||||
|
BannerUrlText: "输入你的封面图片地址",
|
||||||
|
NotionUser: "Notion ID(用户名,可选)",
|
||||||
|
NotionUserDesc:
|
||||||
|
"你的 Notion ID(可选),分享链接类似:https://username.notion.site/,你的 Notion ID 是 [username]",
|
||||||
|
NotionUserText: "输入你的 Notion ID",
|
||||||
|
NotionGeneralSettingHeader: "普通 Notion 数据库设置",
|
||||||
|
NotionGeneralButton: "普通数据库同步命令开关",
|
||||||
|
NotionGeneralButtonDesc: "打开此选项,同步到普通数据库命令将显示在命令面板中",
|
||||||
|
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: "打开此选项,同步到自定义数据库命令将显示在命令面板中",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const I18nConfig = (lang: any): any => {
|
||||||
|
return I18n[lang];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const i18nConfig = I18nConfig(
|
||||||
|
window.localStorage.getItem("language") || "en",
|
||||||
|
); // Export i18nConfig
|
||||||
62
src/main.ts
Normal file
62
src/main.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import {App, Editor, MarkdownView, Notice, Plugin, PluginSettingTab, Setting} from "obsidian";
|
||||||
|
import {addIcons} from 'src/ui/icon';
|
||||||
|
import {Upload2NotionGeneral} from "src/upload/upload_general/Upload2NotionGeneral";
|
||||||
|
import {Upload2NotionNext} from "src/upload/upload_next/Upload2NotionNext";
|
||||||
|
import {i18nConfig} from "src/lang/I18n";
|
||||||
|
import ribbonCommands from "src/commands/NotionCommands";
|
||||||
|
import { ObsidianSettingTab, PluginSettings, DEFAULT_SETTINGS } from "src/ui/settingTabs";
|
||||||
|
|
||||||
|
// Remember to rename these classes and interfaces!
|
||||||
|
|
||||||
|
|
||||||
|
export default class ObsidianSyncNotionPlugin extends Plugin {
|
||||||
|
settings: PluginSettings;
|
||||||
|
commands: ribbonCommands;
|
||||||
|
app: App;
|
||||||
|
|
||||||
|
async onload() {
|
||||||
|
await this.loadSettings();
|
||||||
|
this.commands = new ribbonCommands(this);
|
||||||
|
|
||||||
|
addIcons();
|
||||||
|
// This creates an icon in the left ribbon.
|
||||||
|
const ribbonIconEl = this.addRibbonIcon(
|
||||||
|
"notion-logo",
|
||||||
|
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.
|
||||||
|
|
||||||
|
// const statusBarItemEl = this.addStatusBarItem();
|
||||||
|
// // statusBarItemEl.setText("share to notion");
|
||||||
|
|
||||||
|
// This adds a settings tab so the user can configure various aspects of the plugin
|
||||||
|
this.addSettingTab(new ObsidianSettingTab(this.app, this));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onunload() {
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadSettings() {
|
||||||
|
this.settings = Object.assign(
|
||||||
|
{},
|
||||||
|
DEFAULT_SETTINGS,
|
||||||
|
await this.loadData()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveSettings() {
|
||||||
|
await this.saveData(this.settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -3,7 +3,7 @@ import { addIcon } from 'obsidian';
|
|||||||
const icons: Record<string, string> = {
|
const icons: Record<string, string> = {
|
||||||
'notion-logo': `
|
'notion-logo': `
|
||||||
<!-- License: Apache. Made by lawnchairlauncher: https://github.com/lawnchairlauncher/lawnicons -->
|
<!-- License: Apache. Made by lawnchairlauncher: https://github.com/lawnchairlauncher/lawnicons -->
|
||||||
<svg width="100px" height="100px" viewBox="0 0 192 192" xmlns="http://www.w3.org/2000/svg" fill="none"><path fill="#000000" fill-rule="evenodd" d="m138.462 21.522 27.784 19.588.044.033.275.201c1.713 1.256 3.349 2.455 4.452 3.83 1.411 1.76 1.884 3.644 1.884 5.877v104.706c0 3.587-.635 7.178-3.058 9.934-2.451 2.789-6.145 4.067-10.732 4.394l-.018.001-98.629 5.971-.021.001c-3.242.154-6.094.035-8.669-.907-2.688-.984-4.719-2.727-6.604-5.129l-.01-.012-19.979-25.979-.012-.017c-3.81-5.086-5.723-9.348-5.723-14.509V34.509c0-3.12.688-6.394 2.745-9.033 2.124-2.727 5.356-4.328 9.503-4.686l.058-.005 84.854-4.344c5.192-.445 8.938-.576 12.286.185 3.459.787 6.208 2.452 9.57 4.896ZM56.43 157.336h.002v3.3c0 1.904.47 2.337.613 2.452.296.235 1.203.652 3.642.518l97.449-5.371c1.928-.106 2.256-.649 2.348-.801l.005-.008c.29-.476.486-1.407.486-3.357V60.001c0-1.635-.334-2.218-.421-2.327l-.005-.007-.002-.003-.006-.002a.117.117 0 0 1-.012-.004c-.053-.019-.263-.078-.724-.037l-.057.005-101.622 5.668c-.624.056-.973.163-1.152.242-.142.062-.173.104-.181.116l-.002.002c-.066.085-.36.586-.36 2.321v91.361Zm9.085-106.705 87.074-4.506-21.028-15.375-.039-.031c-1.259-.98-2.507-1.854-4.12-2.46-1.588-.597-3.695-.993-6.669-.734l-.05.005-87.009 4.898h-.01a6.453 6.453 0 0 0-.893.116L49.934 48.56c2.037 1.646 3.109 2.146 4.337 2.367 1.538.277 3.52.167 7.722-.115l3.522-.237v.056Zm-34.231-3.586v83.893c0 .538.175 1.061.498 1.49l13.174 17.464V61.224a2.47 2.47 0 0 0-.877-1.889l-.08-.068-12.715-12.222Zm109.871 35.062c.451 2.04 0 4.082-2.041 4.315l-3.393.673v49.881c-2.947 1.586-5.66 2.492-7.927 2.492-3.622 0-4.528-1.134-7.239-4.53l-.003-.003L98.36 100.02v33.78l7.02 1.59s0 4.082-5.664 4.082l-15.615.906c-.455-.91 0-3.176 1.582-3.627l4.078-1.131V90.955l-5.66-.459c-.454-2.04.677-4.987 3.85-5.216l16.754-1.128 23.09 35.367V88.231l-5.885-.677c-.455-2.499 1.356-4.315 3.618-4.536l15.627-.91v-.001Z" clip-rule="evenodd"/></svg>
|
<svg width="110px" height="110px" viewBox="0 0 192 192" xmlns="http://www.w3.org/2000/svg" fill="none"><path fill="#817f7a" fill-rule="evenodd" d="m138.462 21.522 27.784 19.588.044.033.275.201c1.713 1.256 3.349 2.455 4.452 3.83 1.411 1.76 1.884 3.644 1.884 5.877v104.706c0 3.587-.635 7.178-3.058 9.934-2.451 2.789-6.145 4.067-10.732 4.394l-.018.001-98.629 5.971-.021.001c-3.242.154-6.094.035-8.669-.907-2.688-.984-4.719-2.727-6.604-5.129l-.01-.012-19.979-25.979-.012-.017c-3.81-5.086-5.723-9.348-5.723-14.509V34.509c0-3.12.688-6.394 2.745-9.033 2.124-2.727 5.356-4.328 9.503-4.686l.058-.005 84.854-4.344c5.192-.445 8.938-.576 12.286.185 3.459.787 6.208 2.452 9.57 4.896ZM56.43 157.336h.002v3.3c0 1.904.47 2.337.613 2.452.296.235 1.203.652 3.642.518l97.449-5.371c1.928-.106 2.256-.649 2.348-.801l.005-.008c.29-.476.486-1.407.486-3.357V60.001c0-1.635-.334-2.218-.421-2.327l-.005-.007-.002-.003-.006-.002a.117.117 0 0 1-.012-.004c-.053-.019-.263-.078-.724-.037l-.057.005-101.622 5.668c-.624.056-.973.163-1.152.242-.142.062-.173.104-.181.116l-.002.002c-.066.085-.36.586-.36 2.321v91.361Zm9.085-106.705 87.074-4.506-21.028-15.375-.039-.031c-1.259-.98-2.507-1.854-4.12-2.46-1.588-.597-3.695-.993-6.669-.734l-.05.005-87.009 4.898h-.01a6.453 6.453 0 0 0-.893.116L49.934 48.56c2.037 1.646 3.109 2.146 4.337 2.367 1.538.277 3.52.167 7.722-.115l3.522-.237v.056Zm-34.231-3.586v83.893c0 .538.175 1.061.498 1.49l13.174 17.464V61.224a2.47 2.47 0 0 0-.877-1.889l-.08-.068-12.715-12.222Zm109.871 35.062c.451 2.04 0 4.082-2.041 4.315l-3.393.673v49.881c-2.947 1.586-5.66 2.492-7.927 2.492-3.622 0-4.528-1.134-7.239-4.53l-.003-.003L98.36 100.02v33.78l7.02 1.59s0 4.082-5.664 4.082l-15.615.906c-.455-.91 0-3.176 1.582-3.627l4.078-1.131V90.955l-5.66-.459c-.454-2.04.677-4.987 3.85-5.216l16.754-1.128 23.09 35.367V88.231l-5.885-.677c-.455-2.499 1.356-4.315 3.618-4.536l15.627-.91v-.001Z" clip-rule="evenodd"/></svg>
|
||||||
`
|
`
|
||||||
};
|
};
|
||||||
|
|
||||||
201
src/ui/settingTabs.ts
Normal file
201
src/ui/settingTabs.ts
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
import {App, PluginSettingTab, Setting} from "obsidian";
|
||||||
|
import {i18nConfig} from "../lang/I18n";
|
||||||
|
import ObsidianSyncNotionPlugin from "../main";
|
||||||
|
|
||||||
|
export interface PluginSettings {
|
||||||
|
NextButton: boolean;
|
||||||
|
notionAPINext: string;
|
||||||
|
databaseIDNext: string;
|
||||||
|
bannerUrl: string;
|
||||||
|
notionUser: string;
|
||||||
|
proxy: string;
|
||||||
|
GeneralButton: boolean;
|
||||||
|
notionAPIGeneral: string;
|
||||||
|
databaseIDGeneral: string;
|
||||||
|
CustomButton: boolean;
|
||||||
|
notionAPICustom: string;
|
||||||
|
databaseIDCustom: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DEFAULT_SETTINGS: PluginSettings = {
|
||||||
|
NextButton: true,
|
||||||
|
notionAPINext: "",
|
||||||
|
databaseIDNext: "",
|
||||||
|
bannerUrl: "",
|
||||||
|
notionUser: "",
|
||||||
|
proxy: "",
|
||||||
|
GeneralButton: true,
|
||||||
|
notionAPIGeneral: "",
|
||||||
|
databaseIDGeneral: "",
|
||||||
|
CustomButton: false,
|
||||||
|
notionAPICustom: "",
|
||||||
|
databaseIDCustom: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export class ObsidianSettingTab extends PluginSettingTab {
|
||||||
|
plugin: ObsidianSyncNotionPlugin;
|
||||||
|
|
||||||
|
constructor(app: App, plugin: ObsidianSyncNotionPlugin) {
|
||||||
|
super(app, plugin);
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
display(): void {
|
||||||
|
const {containerEl} = this;
|
||||||
|
|
||||||
|
containerEl.empty();
|
||||||
|
|
||||||
|
containerEl.createEl('h2', {text: i18nConfig.GeneralSetting})
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName(i18nConfig.BannerUrl)
|
||||||
|
.setDesc(i18nConfig.BannerUrlDesc)
|
||||||
|
.addText((text) =>
|
||||||
|
text
|
||||||
|
.setPlaceholder(i18nConfig.BannerUrlText)
|
||||||
|
.setValue(this.plugin.settings.bannerUrl)
|
||||||
|
.onChange(async (value) => {
|
||||||
|
this.plugin.settings.bannerUrl = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName(i18nConfig.NotionUser)
|
||||||
|
.setDesc(i18nConfig.NotionUserDesc)
|
||||||
|
.addText((text) =>
|
||||||
|
text
|
||||||
|
.setPlaceholder(i18nConfig.NotionUserText)
|
||||||
|
.setValue(this.plugin.settings.notionUser)
|
||||||
|
.onChange(async (value) => {
|
||||||
|
this.plugin.settings.notionUser = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
containerEl.createEl('h2', {text: i18nConfig.NotionNextSettingHeader})
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName(i18nConfig.NotionNextButton)
|
||||||
|
.setDesc(i18nConfig.NotionNextButtonDesc)
|
||||||
|
.addToggle((toggle) =>
|
||||||
|
toggle
|
||||||
|
.setValue(this.plugin.settings.NextButton)
|
||||||
|
.onChange(async (value) => {
|
||||||
|
this.plugin.settings.NextButton = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
await this.plugin.commands.updateCommand();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName(i18nConfig.NotionAPI)
|
||||||
|
.setDesc(i18nConfig.NotionAPIDesc)
|
||||||
|
.addText((text) => {
|
||||||
|
text.inputEl.type = 'password';
|
||||||
|
return text
|
||||||
|
.setPlaceholder(i18nConfig.NotionAPIText)
|
||||||
|
.setValue(this.plugin.settings.notionAPINext)
|
||||||
|
.onChange(async (value) => {
|
||||||
|
this.plugin.settings.notionAPINext = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const notionDatabaseID = new Setting(containerEl)
|
||||||
|
.setName(i18nConfig.DatabaseID)
|
||||||
|
.setDesc(i18nConfig.NotionAPIDesc)
|
||||||
|
.addText((text) => {
|
||||||
|
text.inputEl.type = 'password';
|
||||||
|
return text
|
||||||
|
.setPlaceholder(i18nConfig.DatabaseIDText)
|
||||||
|
.setValue(this.plugin.settings.databaseIDNext)
|
||||||
|
.onChange(async (value) => {
|
||||||
|
this.plugin.settings.databaseIDNext = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// notionDatabaseID.controlEl.querySelector('input').type='password'
|
||||||
|
|
||||||
|
|
||||||
|
// General Database Settings
|
||||||
|
containerEl.createEl('h2', {text: i18nConfig.NotionGeneralSettingHeader});
|
||||||
|
|
||||||
|
// new Setting(containerEl)
|
||||||
|
// .setName(i18nConfig.NotYetFinish)
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName(i18nConfig.NotionGeneralButton)
|
||||||
|
.setDesc(i18nConfig.NotionGeneralButtonDesc)
|
||||||
|
.addToggle((toggle) =>
|
||||||
|
toggle
|
||||||
|
.setValue(this.plugin.settings.GeneralButton)
|
||||||
|
.onChange(async (value) => {
|
||||||
|
this.plugin.settings.GeneralButton = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
await this.plugin.commands.updateCommand();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// new Setting(containerEl)
|
||||||
|
// .setName("Convert tags(optional)")
|
||||||
|
// .setDesc("Transfer the Obsidian tags to the Notion table. It requires the column with the name 'Tags'")
|
||||||
|
// .addToggle((toggle) =>
|
||||||
|
// toggle
|
||||||
|
// .setValue(this.plugin.settings.allowTags)
|
||||||
|
// .onChange(async (value) => {
|
||||||
|
// this.plugin.settings.allowTags = value;
|
||||||
|
// await this.plugin.saveSettings();
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName(i18nConfig.NotionAPI)
|
||||||
|
.setDesc(i18nConfig.NotionAPIDesc)
|
||||||
|
.addText((text) => {
|
||||||
|
text.inputEl.type = 'password';
|
||||||
|
return text
|
||||||
|
.setPlaceholder(i18nConfig.NotionAPIText)
|
||||||
|
.setValue(this.plugin.settings.notionAPIGeneral)
|
||||||
|
.onChange(async (value) => {
|
||||||
|
this.plugin.settings.notionAPIGeneral = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName(i18nConfig.DatabaseID)
|
||||||
|
.setDesc(i18nConfig.NotionAPIDesc)
|
||||||
|
.addText((text) => {
|
||||||
|
text.inputEl.type = 'password';
|
||||||
|
return text
|
||||||
|
.setPlaceholder(i18nConfig.NotionIDText)
|
||||||
|
.setValue(this.plugin.settings.databaseIDGeneral)
|
||||||
|
.onChange(async (value) => {
|
||||||
|
this.plugin.settings.databaseIDGeneral = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Custom Database Settings
|
||||||
|
|
||||||
|
// containerEl.createEl('h2', {text: i18nConfig.NotionCustomSettingHeader});
|
||||||
|
//
|
||||||
|
// new Setting(containerEl)
|
||||||
|
// .setName(i18nConfig.NotionCustomButton)
|
||||||
|
// .setDesc(i18nConfig.NotionCustomButtonDesc)
|
||||||
|
// .addToggle((toggle) =>
|
||||||
|
// toggle
|
||||||
|
// .setValue(this.plugin.settings.CustomButton)
|
||||||
|
// .onChange(async (value) => {
|
||||||
|
// this.plugin.settings.CustomButton = value;
|
||||||
|
// await this.plugin.saveSettings();
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
}
|
||||||
51
src/upload/updateYaml.ts
Normal file
51
src/upload/updateYaml.ts
Normal 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}`)
|
||||||
|
// }
|
||||||
|
}
|
||||||
80
src/upload/uploadCommand.ts
Normal file
80
src/upload/uploadCommand.ts
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
90
src/upload/upload_general/BaseUpload2NotionGeneral.ts
Normal file
90
src/upload/upload_general/BaseUpload2NotionGeneral.ts
Normal 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}`)
|
||||||
|
// // }
|
||||||
|
// }
|
||||||
|
}
|
||||||
144
src/upload/upload_general/Upload2NotionGeneral.ts
Normal file
144
src/upload/upload_general/Upload2NotionGeneral.ts
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
import { App, Notice, requestUrl, TFile } from "obsidian";
|
||||||
|
import { Client } from '@notionhq/client';
|
||||||
|
import { markdownToBlocks, } from "@tryfabric/martian";
|
||||||
|
import * as yamlFrontMatter from "yaml-front-matter";
|
||||||
|
// import * as yaml from "yaml"
|
||||||
|
import MyPlugin from "src/main";
|
||||||
|
import {PluginSettings} from "../../ui/settingTabs";
|
||||||
|
import {UploadBaseGeneral} from "./BaseUpload2NotionGeneral";
|
||||||
|
import {updateYamlInfo} from "../updateYaml";
|
||||||
|
|
||||||
|
export class Upload2NotionGeneral extends UploadBaseGeneral {
|
||||||
|
settings: PluginSettings;
|
||||||
|
|
||||||
|
constructor(plugin: MyPlugin) {
|
||||||
|
super(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 因为需要解析notion的block进行对比,非常的麻烦,
|
||||||
|
// 暂时就直接删除,新建一个page
|
||||||
|
async updatePage(
|
||||||
|
notionID: string,
|
||||||
|
title: string,
|
||||||
|
cover: string,
|
||||||
|
tags: string[],
|
||||||
|
childArr: any
|
||||||
|
) {
|
||||||
|
await this.deletePage(notionID)
|
||||||
|
|
||||||
|
const databasecover = await this.getDataBase(this.plugin.settings.databaseIDGeneral)
|
||||||
|
|
||||||
|
if (cover == null) {
|
||||||
|
cover = databasecover
|
||||||
|
}
|
||||||
|
|
||||||
|
return await this.createPage(
|
||||||
|
title,
|
||||||
|
cover,
|
||||||
|
tags,
|
||||||
|
childArr)
|
||||||
|
}
|
||||||
|
|
||||||
|
async createPage(
|
||||||
|
title: string,
|
||||||
|
cover: string,
|
||||||
|
tags: string[],
|
||||||
|
childArr: any
|
||||||
|
) {
|
||||||
|
const bodyString: any = {
|
||||||
|
parent: {
|
||||||
|
database_id: this.plugin.settings.databaseIDGeneral,
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
title: {
|
||||||
|
title: [
|
||||||
|
{
|
||||||
|
text: {
|
||||||
|
content: title
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
tags: {
|
||||||
|
multi_select: tags && true ? tags.map(tag => {
|
||||||
|
return { "name": tag }
|
||||||
|
}) : [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: childArr,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cover) {
|
||||||
|
bodyString.cover = {
|
||||||
|
type: "external",
|
||||||
|
external: {
|
||||||
|
url: cover
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bodyString.cover && this.plugin.settings.bannerUrl) {
|
||||||
|
bodyString.cover = {
|
||||||
|
type: "external",
|
||||||
|
external: {
|
||||||
|
url: this.plugin.settings.bannerUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await requestUrl({
|
||||||
|
url: `https://api.notion.com/v1/pages`,
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
// 'User-Agent': 'obsidian.md',
|
||||||
|
'Authorization': 'Bearer ' + this.plugin.settings.notionAPIGeneral,
|
||||||
|
'Notion-Version': '2022-06-28',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(bodyString),
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
new Notice(`network error ${error}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async syncMarkdownToNotionGeneral(
|
||||||
|
title: string,
|
||||||
|
cover: string,
|
||||||
|
tags: string[],
|
||||||
|
markdown: string,
|
||||||
|
nowFile: TFile,
|
||||||
|
app: App,
|
||||||
|
): Promise<any> {
|
||||||
|
let res: any
|
||||||
|
const yamlContent: any = yamlFrontMatter.loadFront(markdown);
|
||||||
|
const __content = yamlContent.__content
|
||||||
|
const file2Block = markdownToBlocks(__content);
|
||||||
|
const frontmasster = app.metadataCache.getFileCache(nowFile)?.frontmatter
|
||||||
|
const notionID = frontmasster ? frontmasster.notionID : null
|
||||||
|
|
||||||
|
if (notionID) {
|
||||||
|
res = await this.updatePage(
|
||||||
|
notionID,
|
||||||
|
title,
|
||||||
|
cover,
|
||||||
|
tags,
|
||||||
|
file2Block
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
res = await this.createPage(
|
||||||
|
title,
|
||||||
|
cover,
|
||||||
|
tags,
|
||||||
|
file2Block
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (res.status === 200) {
|
||||||
|
await updateYamlInfo(markdown, nowFile, res, app, this.plugin)
|
||||||
|
} else {
|
||||||
|
new Notice(`${res.text}`)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/upload/upload_general/getMarkdownGeneral.ts
Normal file
33
src/upload/upload_general/getMarkdownGeneral.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
90
src/upload/upload_next/BaseUpload2NotionNext.ts
Normal file
90
src/upload/upload_next/BaseUpload2NotionNext.ts
Normal 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}`)
|
||||||
|
// // }
|
||||||
|
// }
|
||||||
|
}
|
||||||
257
src/upload/upload_next/Upload2NotionNext.ts
Normal file
257
src/upload/upload_next/Upload2NotionNext.ts
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
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> {
|
||||||
|
let res: any
|
||||||
|
const yamlContent: any = yamlFrontMatter.loadFront(markdown);
|
||||||
|
const __content = yamlContent.__content
|
||||||
|
const file2Block = markdownToBlocks(__content);
|
||||||
|
const frontmasster = app.metadataCache.getFileCache(nowFile)?.frontmatter
|
||||||
|
const notionID = frontmasster ? frontmasster.notionID : null
|
||||||
|
|
||||||
|
if (notionID) {
|
||||||
|
res = await this.updatePage(
|
||||||
|
notionID,
|
||||||
|
title,
|
||||||
|
emoji,
|
||||||
|
cover,
|
||||||
|
tags,
|
||||||
|
type,
|
||||||
|
slug,
|
||||||
|
stats,
|
||||||
|
category,
|
||||||
|
summary,
|
||||||
|
paword,
|
||||||
|
favicon,
|
||||||
|
datetime,
|
||||||
|
file2Block
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
res = await this.createPage(
|
||||||
|
title,
|
||||||
|
emoji,
|
||||||
|
cover,
|
||||||
|
tags,
|
||||||
|
type,
|
||||||
|
slug,
|
||||||
|
stats,
|
||||||
|
category,
|
||||||
|
summary,
|
||||||
|
paword,
|
||||||
|
favicon,
|
||||||
|
datetime,
|
||||||
|
file2Block
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (res.status === 200) {
|
||||||
|
await updateYamlInfo(markdown, nowFile, res, app, this.plugin)
|
||||||
|
} else {
|
||||||
|
new Notice(`${res.text}`)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
59
src/upload/upload_next/getMarkdownNext.ts
Normal file
59
src/upload/upload_next/getMarkdownNext.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,5 +18,7 @@
|
|||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"**/*.ts"
|
"**/*.ts"
|
||||||
, "Upload2Notion.ts" ]
|
,
|
||||||
|
"src/Upload2Notion.ts"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user