mirror of
https://github.com/jxpeng98/obsidian-to-NotionNext
synced 2026-07-29 16:35:57 +08:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b62bd4ba2e | ||
|
|
402d15a38b | ||
|
|
87f1ce0146 | ||
|
|
398b785e03 | ||
|
|
8617878582 | ||
|
|
ae9e0c14fb | ||
|
|
9be9b18efb | ||
|
|
588f57205b | ||
|
|
cfbedea91d | ||
|
|
4cd6557444 | ||
|
|
407688c303 | ||
|
|
84b998aa93 | ||
|
|
4b6f1a1f1d | ||
|
|
4a2c59d13b | ||
|
|
8f116956ce | ||
|
|
df138d9304 | ||
|
|
49b8d470fb | ||
|
|
c39323c3fa | ||
|
|
05dff7a389 | ||
|
|
24fcadbc8b |
26
.github/workflows/CI.yml
vendored
26
.github/workflows/CI.yml
vendored
@@ -1,26 +0,0 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "*"
|
||||
|
||||
env:
|
||||
PLUGIN_NAME: share-to-notionnext
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Build
|
||||
id: build
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
30
.github/workflows/release.yml
vendored
30
.github/workflows/release.yml
vendored
@@ -13,11 +13,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "14.x"
|
||||
node-version: "16.x"
|
||||
|
||||
- name: Build
|
||||
id: build
|
||||
@@ -25,10 +25,10 @@ jobs:
|
||||
npm install
|
||||
npm run build
|
||||
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 }}
|
||||
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
|
||||
id: create_release
|
||||
@@ -43,8 +43,8 @@ jobs:
|
||||
prerelease: false
|
||||
|
||||
- name: Upload zip file
|
||||
id: upload-zip
|
||||
uses: actions/upload-release-asset@v1
|
||||
id: uploadCommand-zip
|
||||
uses: actions/uploadCommand-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
with:
|
||||
@@ -54,8 +54,8 @@ jobs:
|
||||
asset_content_type: application/zip
|
||||
|
||||
- name: Upload main.js
|
||||
id: upload-main
|
||||
uses: actions/upload-release-asset@v1
|
||||
id: uploadCommand-main
|
||||
uses: actions/uploadCommand-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
with:
|
||||
@@ -65,8 +65,8 @@ jobs:
|
||||
asset_content_type: text/javascript
|
||||
|
||||
- name: Upload manifest.json
|
||||
id: upload-manifest
|
||||
uses: actions/upload-release-asset@v1
|
||||
id: uploadCommand-manifest
|
||||
uses: actions/uploadCommand-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
with:
|
||||
@@ -76,8 +76,8 @@ jobs:
|
||||
asset_content_type: application/json
|
||||
|
||||
- name: Upload markdown template
|
||||
id: upload-md
|
||||
uses: actions/upload-release-asset@v1
|
||||
id: uploadCommand-md
|
||||
uses: actions/uploadCommand-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
with:
|
||||
@@ -87,8 +87,8 @@ jobs:
|
||||
asset_content_type: text/markdown
|
||||
|
||||
# - name: Upload styles.css
|
||||
# id: upload-css
|
||||
# uses: actions/upload-release-asset@v1
|
||||
# id: uploadCommand-css
|
||||
# uses: actions/uploadCommand-release-asset@v1
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
# with:
|
||||
|
||||
31
README-zh.md
31
README-zh.md
@@ -2,6 +2,27 @@
|
||||
感谢[原作者](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编辑,整理好之后一键发布。
|
||||
## 更新说明
|
||||
### 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选项或者留白。
|
||||
|
||||
## 使用方式
|
||||
### 注意事项
|
||||
@@ -37,6 +58,10 @@
|
||||
**⚠️⚠️⚠️:表头全部小写!!!顺序无所谓!**
|
||||
|
||||
### 安装插件
|
||||
#### 社区插件市场下载
|
||||
打开`Obsidian -> 设置 -> 社区插件 -> 浏览 -> 搜索Share to NotionNext`, 然后点击安装。
|
||||
|
||||
#### 手动安装
|
||||
1. 关闭Obsidian
|
||||
2. 从Release下载插件文件,解压到你的obsidian插件目录下。
|
||||
3. 重新打开Obsidian,进入设置,启用插件。
|
||||
@@ -58,6 +83,7 @@
|
||||
# 现在阶段一定不要修改表头的名字, 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, 默认是空
|
||||
@@ -77,11 +103,10 @@ Contents Below
|
||||
|
||||
```
|
||||
模板使用如下:
|
||||

|
||||

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

|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
|
||||
37
README.md
37
README.md
@@ -4,6 +4,28 @@
|
||||
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.
|
||||
## Update
|
||||
### 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
|
||||
### Precautions
|
||||
@@ -28,7 +50,7 @@ Before installing the plugin, you must have set up the following:
|
||||
- password
|
||||
- icon
|
||||
|
||||
In version 0.0.6, I also add the following contents:
|
||||
From version 0.0.6, I also add the following contents:
|
||||
- titleicon: the unique icon for each post, it can only support emoji currently.
|
||||
- cover url: the cover image for each post, it should be end with a type of image, such as .jpg, .png, .gif, etc.
|
||||
|
||||
@@ -37,6 +59,10 @@ In version 0.0.6, I also add the following contents:
|
||||
**⚠️⚠️⚠️: All headers are in lowercase!!! The order doesn't matter!**
|
||||
|
||||
### Plugin Installation
|
||||
#### Install via Community Plugins
|
||||
Open `Obsidian settings -> Community Plugins -> Browse -> NotionNext -> Share to NotionNext`
|
||||
|
||||
#### Mannually Install
|
||||
1. Close Obsidian.
|
||||
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.
|
||||
@@ -58,6 +84,7 @@ If you don't want to use the template, you can also directly create a new file i
|
||||
# 现在阶段一定不要修改表头的名字, please do not change the name of the header in YAML front matter
|
||||
# !!!!!!!!!!!!
|
||||
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, 默认是空
|
||||
@@ -76,10 +103,10 @@ Contents Below
|
||||
|
||||
```
|
||||
Usage of the template is as follows:
|
||||

|
||||

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

|
||||

|
||||
|
||||
---
|
||||
|
||||
@@ -171,9 +198,9 @@ Fill the configuration with the `NOTION_API_KEY` and `DATABASE_ID` you got
|
||||

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

|
||||
|
||||
|
||||
|
||||
@@ -10,8 +10,7 @@ if you want to view the source, please visit the github repository of this plugi
|
||||
`;
|
||||
const prod = (process.argv[2] === 'production');
|
||||
|
||||
(async () => { // Enclose everything in an async function for using await
|
||||
const ctx = await esbuild.context({
|
||||
const ctx = await esbuild.context({
|
||||
banner: {
|
||||
js: banner,
|
||||
},
|
||||
@@ -54,6 +53,6 @@ const prod = (process.argv[2] === 'production');
|
||||
if (!prod) {
|
||||
await ctx.watch();
|
||||
} else {
|
||||
await ctx.dispose();
|
||||
await ctx.rebuild()
|
||||
ctx.dispose().then(r => console.log('Build completed'), e => console.error(e));
|
||||
}
|
||||
})().catch(() => process.exit(1)); // Use .catch here to handle any errors
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"id": "share-to-notionnext",
|
||||
"name": "Share to NotionNext",
|
||||
"version": "0.1.1",
|
||||
"version": "0.2.2",
|
||||
"minAppVersion": "0.0.1",
|
||||
"description": "Shares obsidian md file to notion with notion api for NotionNext web deploy, motivated by EasyChris/obsidian-to-notion.",
|
||||
"description": "Shares obsidian md file to notion with notion api for NotionNext web deploy, originally created by EasyChris/obsidian-to-notion.",
|
||||
"author": "EasyChris, jxpeng98",
|
||||
"authorUrl": "https://github.com/jxpeng98/obsidian-to-NotionNext",
|
||||
"authorUrl": "https://github.com/jxpeng98",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
# 现在阶段一定不要修改表头的名字, 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, 默认是空
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "share-to-notionnext",
|
||||
"version": "0.1.1",
|
||||
"version": "0.2.2",
|
||||
"type": "module",
|
||||
"description": "Shares obsidian md file to notion with notion api for NotionNext web deploy, motivated by EasyChris/obsidian-to-notion.",
|
||||
"description": "Shares obsidian md file to notion with notion api for NotionNext web deploy, originally created by EasyChris/obsidian-to-notion.",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"dev": "node esbuild.config.mjs",
|
||||
@@ -27,6 +27,7 @@
|
||||
"@tryfabric/martian": "^1.2.0",
|
||||
"https-proxy-agent": "^7.0.1",
|
||||
"process": "^0.11.10",
|
||||
"remark-math": "^6.0.0",
|
||||
"yaml": "^2.2.2",
|
||||
"yaml-front-matter": "^4.1.1"
|
||||
}
|
||||
|
||||
@@ -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]
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
import { App, Notice, requestUrl, TFile } from "obsidian";
|
||||
import { Client } from '@notionhq/client';
|
||||
import { markdownToBlocks, } from "@tryfabric/martian";
|
||||
import * as yamlFrontMatter from "yaml-front-matter";
|
||||
// import * as yaml from "yaml"
|
||||
import MyPlugin from "src/main";
|
||||
|
||||
export class Upload2Notion {
|
||||
plugin: MyPlugin;
|
||||
notion: Client;
|
||||
agent: any;
|
||||
constructor(plugin: MyPlugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
async deletePage(notionID: string) {
|
||||
return requestUrl({
|
||||
url: `https://api.notion.com/v1/blocks/${notionID}`,
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + this.plugin.settings.notionAPI,
|
||||
'Notion-Version': '2022-06-28',
|
||||
},
|
||||
body: ''
|
||||
});
|
||||
}
|
||||
|
||||
async getDataBase(databaseID: string) {
|
||||
const response = await requestUrl({
|
||||
url: `https://api.notion.com/v1/databases/${databaseID}`,
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + this.plugin.settings.notionAPI,
|
||||
'Notion-Version': '2022-06-28',
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// Check if cover is present in the JSON response and then get the URL
|
||||
if (response.json.cover && response.json.cover.external) {
|
||||
return response.json.cover.external.url;
|
||||
} else {
|
||||
return null; // or some other default value, if you prefer
|
||||
}
|
||||
}
|
||||
|
||||
// 因为需要解析notion的block进行对比,非常的麻烦,
|
||||
// 暂时就直接删除,新建一个page
|
||||
async updatePage(notionID: string, title: string, allowTags: boolean, emoji: string, cover: string, tags: string[], type: string, slug: string, stats: string, category: string, summary: string, paword: string, favicon: string, datetime: string, childArr: any) {
|
||||
await this.deletePage(notionID)
|
||||
|
||||
const databasecover = await this.getDataBase(this.plugin.settings.databaseID)
|
||||
|
||||
if (cover == null) {
|
||||
cover = databasecover
|
||||
}
|
||||
|
||||
return await this.createPage(title, allowTags, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, childArr)
|
||||
}
|
||||
|
||||
async createPage(title: string, allowTags: boolean, emoji: string, cover: string, tags: string[], type: string, slug: string, stats: string, category: string, summary: string, pawrod: string, favicon: string, datetime: string, childArr: any) {
|
||||
const bodyString: any = {
|
||||
parent: {
|
||||
database_id: this.plugin.settings.databaseID
|
||||
},
|
||||
icon: {
|
||||
emoji: emoji || '📜'
|
||||
},
|
||||
properties: {
|
||||
title: {
|
||||
title: [
|
||||
{
|
||||
text: {
|
||||
content: title
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
tags: {
|
||||
multi_select: allowTags && tags !== undefined ? tags.map(tag => {
|
||||
return { "name": tag }
|
||||
}) : [],
|
||||
},
|
||||
type: {
|
||||
select: {
|
||||
name: type || 'Post'
|
||||
}
|
||||
},
|
||||
slug: {
|
||||
rich_text: [
|
||||
{
|
||||
text: {
|
||||
content: slug || ''
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
status: {
|
||||
select: {
|
||||
name: stats || 'Draft'
|
||||
}
|
||||
},
|
||||
category: {
|
||||
select: {
|
||||
name: category || 'Obsidian'
|
||||
}
|
||||
},
|
||||
summary: {
|
||||
rich_text: [
|
||||
{
|
||||
text: {
|
||||
content: summary || ''
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
password: {
|
||||
rich_text: [
|
||||
{
|
||||
text: {
|
||||
content: pawrod || ''
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
icon: {
|
||||
rich_text: [
|
||||
{
|
||||
text: {
|
||||
content: favicon || ''
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
date: {
|
||||
date: {
|
||||
start: datetime || new Date().toISOString()
|
||||
}
|
||||
}
|
||||
},
|
||||
children: childArr,
|
||||
}
|
||||
if (cover) {
|
||||
bodyString.cover = {
|
||||
type: "external",
|
||||
external: {
|
||||
url: cover
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bodyString.cover && this.plugin.settings.bannerUrl) {
|
||||
bodyString.cover = {
|
||||
type: "external",
|
||||
external: {
|
||||
url: this.plugin.settings.bannerUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return await requestUrl({
|
||||
url: `https://api.notion.com/v1/pages`,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
// 'User-Agent': 'obsidian.md',
|
||||
'Authorization': 'Bearer ' + this.plugin.settings.notionAPI,
|
||||
'Notion-Version': '2022-06-28',
|
||||
},
|
||||
body: JSON.stringify(bodyString),
|
||||
})
|
||||
} catch (error) {
|
||||
new Notice(`network error ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
async syncMarkdownToNotion(title: string, allowTags: boolean, emoji: string, cover: string, tags: string[], type: string, slug: string, stats: string, category: string, summary: string, paword: string, favicon: string, datetime: string, markdown: string, nowFile: TFile, app: App, settings: any): Promise<any> {
|
||||
let res: any
|
||||
const yamlContent: any = yamlFrontMatter.loadFront(markdown);
|
||||
const __content = yamlContent.__content
|
||||
const file2Block = markdownToBlocks(__content);
|
||||
const frontmasster = app.metadataCache.getFileCache(nowFile)?.frontmatter
|
||||
const notionID = frontmasster ? frontmasster.notionID : null
|
||||
|
||||
if (notionID) {
|
||||
res = await this.updatePage(notionID, title, allowTags, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, file2Block);
|
||||
} else {
|
||||
res = await this.createPage(title, allowTags, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, file2Block);
|
||||
}
|
||||
if (res.status === 200) {
|
||||
await this.updateYamlInfo(markdown, nowFile, res, app, settings)
|
||||
} else {
|
||||
new Notice(`${res.text}`)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
async updateYamlInfo(yamlContent: string, nowFile: TFile, res: any, app: App, settings: any) {
|
||||
let { url, id } = res.json
|
||||
// replace www to notionID
|
||||
const { notionID } = settings;
|
||||
if (notionID !== "") {
|
||||
// replace url str "www" to notionID
|
||||
url = url.replace("www.notion.so", `${notionID}.notion.site`)
|
||||
}
|
||||
await app.fileManager.processFrontMatter(nowFile, yamlContent => {
|
||||
if (yamlContent['notionID']) {
|
||||
delete yamlContent['notionID']
|
||||
}
|
||||
if (yamlContent['link']) {
|
||||
delete yamlContent['link']
|
||||
}
|
||||
// add new notionID and link
|
||||
yamlContent.notionID = id;
|
||||
yamlContent.link = url;
|
||||
});
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(url)
|
||||
} catch (error) {
|
||||
new Notice(`复制链接失败,请手动复制${error}`)
|
||||
}
|
||||
// const __content = yamlContent.__content;
|
||||
// delete yamlContent.__content
|
||||
// const yamlhead = yaml.stringify(yamlContent)
|
||||
// // if yamlhead hava last \n remove it
|
||||
// const yamlhead_remove_n = yamlhead.replace(/\n$/, '')
|
||||
// // if __content have start \n remove it
|
||||
// const __content_remove_n = __content.replace(/^\n/, '')
|
||||
// const content = '---\n' +yamlhead_remove_n +'\n---\n' + __content_remove_n;
|
||||
// try {
|
||||
// await nowFile.vault.modify(nowFile, content)
|
||||
// } catch (error) {
|
||||
// new Notice(`write file error ${error}`)
|
||||
// }
|
||||
}
|
||||
}
|
||||
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 })
|
||||
}
|
||||
|
||||
}
|
||||
61
src/commands/NotionCommands.ts
Normal file
61
src/commands/NotionCommands.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
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";
|
||||
|
||||
// create the commands list
|
||||
export default class RibbonCommands {
|
||||
plugin: ObsidianSyncNotionPlugin;
|
||||
|
||||
// Total commands that will be used
|
||||
Ncommand = [
|
||||
{
|
||||
id: "share-to-notionnext",
|
||||
name: i18nConfig.CommandName, // Use the translated text from i18nConfig
|
||||
editorCallback: async (editor: Editor, view: MarkdownView) => {
|
||||
// await this.plugin.uploadCommand()
|
||||
await uploadCommandNext(this.plugin, this.plugin.settings, this.plugin.app)
|
||||
}
|
||||
},
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
async ribbonDisplay() {
|
||||
const NcommandList: DatabaseList[] = [];
|
||||
this.Ncommand.map(command => NcommandList.push(
|
||||
{
|
||||
name:command.name,
|
||||
match: command.editorCallback
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const fusg = new FuzzySuggester(this.plugin);
|
||||
|
||||
fusg.setSuggesterData(NcommandList);
|
||||
await fusg.display(async (results) => {await results.match()})
|
||||
};
|
||||
|
||||
constructor(plugin: ObsidianSyncNotionPlugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
// Register all the commands
|
||||
this.Ncommand.forEach(command => {
|
||||
this.plugin.addCommand(
|
||||
{
|
||||
id: command.id,
|
||||
name: command.name,
|
||||
editorCallback: command.editorCallback,
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
90
src/lang/I18n.ts
Normal file
90
src/lang/I18n.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
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",
|
||||
NotionNextVersion: "NotionNext Version Database",
|
||||
NotionNextVersionDesc:
|
||||
"Turn on this option if you are using NotionNext",
|
||||
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:
|
||||
"page banner url(optional), default is empty, if you want to show a banner, please enter the url(like: https://minioapi.pjx.ac.cn/img1/2023/11/b7b40a0724e93b7d7ab494bb3b8a2da8.png)",
|
||||
BannerUrlText: "Enter your banner url",
|
||||
NotionUser: "Notion ID(username, optional)",
|
||||
NotionUserDesc:
|
||||
"Your notion ID (optional),share link likes:https://username.notion.site/,your notion id is [username]",
|
||||
NotionUserText: "Enter your notion ID (options)",
|
||||
NotionGeneralSettingHeader: "General Notion Database Settings",
|
||||
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.",
|
||||
},
|
||||
zh: {
|
||||
ribbonIcon: "分享到 NotionNext",
|
||||
GeneralSetting: "通用信息设置",
|
||||
CommandID: "share-to-notionnext",
|
||||
CommandName: "分享到 NotionNext",
|
||||
CommandIDGeneral: "share-to-notion",
|
||||
CommandNameGeneral: "分享到 Notion 普通数据库",
|
||||
NotionNextVersion: "NotionNext 版本数据库",
|
||||
NotionNextVersionDesc: "如果你使用的是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 数据库设置",
|
||||
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",
|
||||
},
|
||||
};
|
||||
|
||||
export const I18nConfig = (lang: any): any => {
|
||||
return I18n[lang];
|
||||
};
|
||||
|
||||
export const i18nConfig = I18nConfig(
|
||||
window.localStorage.getItem("language") || "en",
|
||||
); // Export i18nConfig
|
||||
261
src/main.ts
261
src/main.ts
@@ -1,241 +1,62 @@
|
||||
import {App, Editor, MarkdownView, Notice, Plugin, PluginSettingTab, Setting} from "obsidian";
|
||||
import {addIcons} from 'src/icon';
|
||||
import {Upload2Notion} from "src/Upload2Notion";
|
||||
import {NoticeMConfig} from "src/Message";
|
||||
|
||||
import {addIcons} from 'src/ui/icon';
|
||||
import {Upload2NotionGeneral} from "src/upload/upload_general/Upload2NotionGeneral";
|
||||
import {Upload2NotionNext} from "src/upload/upload_next/Upload2NotionNext";
|
||||
import {i18nConfig} from "src/lang/I18n";
|
||||
import ribbonCommands from "src/commands/NotionCommands";
|
||||
import { ObsidianSettingTab, PluginSettings, DEFAULT_SETTINGS } from "src/ui/settingTabs";
|
||||
|
||||
// Remember to rename these classes and interfaces!
|
||||
|
||||
interface PluginSettings {
|
||||
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.
|
||||
await this.upload();
|
||||
}
|
||||
);
|
||||
settings: PluginSettings;
|
||||
commands: ribbonCommands;
|
||||
app: App;
|
||||
|
||||
// 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");
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
this.commands = new ribbonCommands(this);
|
||||
|
||||
this.addCommand({
|
||||
id: "share-to-notionnext",
|
||||
name: "share to notionnext",
|
||||
editorCallback: async (editor: Editor, view: MarkdownView) => {
|
||||
await this.upload()
|
||||
},
|
||||
});
|
||||
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();
|
||||
this.commands.ribbonDisplay();
|
||||
}
|
||||
);
|
||||
|
||||
// This adds a status bar item to the bottom of the app. Does not work on mobile apps.
|
||||
|
||||
// This adds a settings tab so the user can configure various aspects of the plugin
|
||||
this.addSettingTab(new ObsidianSettingTab(this.app, this));
|
||||
// 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 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, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime } =await this.getNowFileMarkdownContent(this.app);
|
||||
onunload() {
|
||||
}
|
||||
|
||||
if (markDownData) {
|
||||
const { basename } = nowFile;
|
||||
const upload = new Upload2Notion(this);
|
||||
const res = await upload.syncMarkdownToNotion(basename, allowTags, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, markDownData, nowFile, this.app, this.settings)
|
||||
if(res.status === 200){
|
||||
new Notice(`${langConfig["sync-success"]}${basename}`)
|
||||
}else {
|
||||
new Notice(`${langConfig["sync-fail"]}${basename}`, 5000)
|
||||
}
|
||||
}
|
||||
}
|
||||
async loadSettings() {
|
||||
this.settings = Object.assign(
|
||||
{},
|
||||
DEFAULT_SETTINGS,
|
||||
await this.loadData()
|
||||
);
|
||||
}
|
||||
|
||||
async getNowFileMarkdownContent(app: App) {
|
||||
const nowFile = app.workspace.getActiveFile();
|
||||
const { allowTags } = this.settings;
|
||||
let emoji = ''
|
||||
let cover = ''
|
||||
let tags = []
|
||||
let type = ''
|
||||
let slug = ''
|
||||
let stats = ''
|
||||
let category = ''
|
||||
let summary = ''
|
||||
let paword = ''
|
||||
let favicon = ''
|
||||
let datetime = ''
|
||||
async saveSettings() {
|
||||
await this.saveData(this.settings);
|
||||
}
|
||||
|
||||
const FileCache = app.metadataCache.getFileCache(nowFile)
|
||||
try {
|
||||
if(allowTags) {
|
||||
emoji = FileCache.frontmatter.titleicon;
|
||||
cover = FileCache.frontmatter.coverurl;
|
||||
tags = FileCache.frontmatter.tags;
|
||||
type = FileCache.frontmatter.type;
|
||||
slug = FileCache.frontmatter.slug;
|
||||
stats = FileCache.frontmatter.stats;
|
||||
category = FileCache.frontmatter.category;
|
||||
summary = FileCache.frontmatter.summary;
|
||||
paword = FileCache.frontmatter.password;
|
||||
favicon = FileCache.frontmatter.icon;
|
||||
datetime = FileCache.frontmatter.date;
|
||||
}
|
||||
} catch (error) {
|
||||
new Notice(langConfig["set-tags-fail"]);
|
||||
}
|
||||
if (nowFile) {
|
||||
const markDownData = await nowFile.vault.read(nowFile);
|
||||
return {
|
||||
markDownData,
|
||||
nowFile,
|
||||
emoji,
|
||||
cover,
|
||||
tags,
|
||||
type,
|
||||
slug,
|
||||
stats,
|
||||
category,
|
||||
summary,
|
||||
paword,
|
||||
favicon,
|
||||
datetime,
|
||||
};
|
||||
} else {
|
||||
new Notice(langConfig["open-file"]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
this.settings = Object.assign(
|
||||
{},
|
||||
DEFAULT_SETTINGS,
|
||||
await this.loadData()
|
||||
);
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
await this.saveData(this.settings);
|
||||
}
|
||||
}
|
||||
|
||||
class ObsidianSettingTab extends PluginSettingTab {
|
||||
plugin: ObsidianSyncNotionPlugin;
|
||||
|
||||
constructor(app: App, plugin: ObsidianSyncNotionPlugin) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
display(): void {
|
||||
const { containerEl } = this;
|
||||
|
||||
containerEl.empty();
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Notion API Token")
|
||||
.setDesc("It's a secret")
|
||||
.addText((text) =>{
|
||||
text.inputEl.type = 'password';
|
||||
return text
|
||||
.setPlaceholder("Enter your Notion API Token")
|
||||
.setValue(this.plugin.settings.notionAPI)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.notionAPI = value;
|
||||
await this.plugin.saveSettings();
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
const notionDatabaseID = new Setting(containerEl)
|
||||
.setName("Database ID")
|
||||
.setDesc("It's a secret")
|
||||
.addText((text) => {
|
||||
text.inputEl.type = 'password';
|
||||
return text
|
||||
.setPlaceholder("Enter your Database ID")
|
||||
.setValue(this.plugin.settings.databaseID)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.databaseID = value;
|
||||
await this.plugin.saveSettings();
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
// notionDatabaseID.controlEl.querySelector('input').type='password'
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Banner url(optional)")
|
||||
.setDesc("page banner url(optional), default is empty, if you want to show a banner, please enter the url(like:https://raw.githubusercontent.com/EasyChris/obsidian-to-notion/ae7a9ac6cf427f3ca338a409ce6967ced9506f12/doc/2.png)")
|
||||
.addText((text) =>
|
||||
text
|
||||
.setPlaceholder("Enter banner pic url: ")
|
||||
.setValue(this.plugin.settings.bannerUrl)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.bannerUrl = value;
|
||||
await this.plugin.saveSettings();
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Notion ID(optional)")
|
||||
.setDesc("Your notion ID(optional),share link likes:https://username.notion.site/,your notion id is [username]")
|
||||
.addText((text) =>
|
||||
text
|
||||
.setPlaceholder("Enter notion ID(options) ")
|
||||
.setValue(this.plugin.settings.notionID)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.notionID = value;
|
||||
await this.plugin.saveSettings();
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Convert tags(optional)")
|
||||
.setDesc("Transfer the Obsidian tags to the Notion table. It requires the column with the name 'Tags'")
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.allowTags)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.allowTags = value;
|
||||
await this.plugin.saveSettings();
|
||||
})
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
165
src/ui/settingTabs.ts
Normal file
165
src/ui/settingTabs.ts
Normal file
@@ -0,0 +1,165 @@
|
||||
import {App, PluginSettingTab, Setting} from "obsidian";
|
||||
import {i18nConfig} from "../lang/I18n";
|
||||
import ObsidianSyncNotionPlugin from "../main";
|
||||
|
||||
export interface PluginSettings {
|
||||
NNon: boolean;
|
||||
notionAPINext: string;
|
||||
databaseIDNext: string;
|
||||
bannerUrl: string;
|
||||
notionUser: string;
|
||||
proxy: string;
|
||||
notionAPIGeneral: string;
|
||||
databaseIDGeneral: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_SETTINGS: PluginSettings = {
|
||||
NNon: undefined,
|
||||
notionAPINext: "",
|
||||
databaseIDNext: "",
|
||||
bannerUrl: "",
|
||||
notionUser: "",
|
||||
proxy: "",
|
||||
notionAPIGeneral: "",
|
||||
databaseIDGeneral: "",
|
||||
};
|
||||
|
||||
|
||||
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.NotionNextVersion)
|
||||
// .setDesc(i18nConfig.NotionNextVersionDesc)
|
||||
// .addToggle((toggle) =>
|
||||
// toggle
|
||||
// .setValue(this.plugin.settings.NNon)
|
||||
// .onChange(async (value) => {
|
||||
// this.plugin.settings.NNon = value;
|
||||
// await this.plugin.saveSettings();
|
||||
// })
|
||||
// );
|
||||
|
||||
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.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("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();
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
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, this.settings);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
443
yarn.lock
443
yarn.lock
@@ -171,11 +171,25 @@
|
||||
dependencies:
|
||||
"@types/tern" "*"
|
||||
|
||||
"@types/debug@^4.0.0":
|
||||
version "4.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.9.tgz#906996938bc672aaf2fb8c0d3733ae1dda05b005"
|
||||
integrity sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==
|
||||
dependencies:
|
||||
"@types/ms" "*"
|
||||
|
||||
"@types/estree@*":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194"
|
||||
integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==
|
||||
|
||||
"@types/hast@^3.0.0":
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.1.tgz#e1705ec9258ac4885659c2d50bac06b4fcd16466"
|
||||
integrity sha512-hs/iBJx2aydugBQx5ETV3ZgeSS0oIreQrFJ4bjBl0XvM4wAmDjFEALY7p0rTSLt2eL+ibjRAAs9dTPiCLtmbqQ==
|
||||
dependencies:
|
||||
"@types/unist" "*"
|
||||
|
||||
"@types/js-yaml@*":
|
||||
version "4.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.5.tgz#738dd390a6ecc5442f35e7f03fa1431353f7e138"
|
||||
@@ -186,6 +200,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb"
|
||||
integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==
|
||||
|
||||
"@types/katex@^0.16.0":
|
||||
version "0.16.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.16.3.tgz#a341c89705145b7dd8e2a133b282a133eabe6076"
|
||||
integrity sha512-CeVMX9EhVUW8MWnei05eIRks4D5Wscw/W9Byz1s3PA+yJvcdvq9SaDjiUKvRvEgjpdTyJMjQA43ae4KTwsvOPg==
|
||||
|
||||
"@types/mdast@^3.0.0":
|
||||
version "3.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.12.tgz#beeb511b977c875a5b0cc92eab6fcac2f0895514"
|
||||
@@ -193,6 +212,18 @@
|
||||
dependencies:
|
||||
"@types/unist" "^2"
|
||||
|
||||
"@types/mdast@^4.0.0":
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.1.tgz#9c45e60a04e79f160dcefe6545d28ae536a6ed22"
|
||||
integrity sha512-IlKct1rUTJ1T81d8OHzyop15kGv9A/ff7Gz7IJgrk6jDb4Udw77pCJ+vq8oxZf4Ghpm+616+i1s/LNg/Vh7d+g==
|
||||
dependencies:
|
||||
"@types/unist" "*"
|
||||
|
||||
"@types/ms@*":
|
||||
version "0.7.32"
|
||||
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.32.tgz#f6cd08939ae3ad886fcc92ef7f0109dacddf61ab"
|
||||
integrity sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g==
|
||||
|
||||
"@types/node-fetch@^2.5.10":
|
||||
version "2.6.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660"
|
||||
@@ -218,6 +249,11 @@
|
||||
dependencies:
|
||||
"@types/estree" "*"
|
||||
|
||||
"@types/unist@*", "@types/unist@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.0.tgz#988ae8af1e5239e89f9fbb1ade4c935f4eeedf9a"
|
||||
integrity sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w==
|
||||
|
||||
"@types/unist@^2", "@types/unist@^2.0.0", "@types/unist@^2.0.2":
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.7.tgz#5b06ad6894b236a1d2bd6b2f07850ca5c59cf4d6"
|
||||
@@ -345,6 +381,11 @@ bail@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776"
|
||||
integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==
|
||||
|
||||
bail@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d"
|
||||
integrity sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==
|
||||
|
||||
braces@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||
@@ -372,6 +413,11 @@ character-entities@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b"
|
||||
integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==
|
||||
|
||||
character-entities@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22"
|
||||
integrity sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==
|
||||
|
||||
character-reference-invalid@^1.0.0:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560"
|
||||
@@ -394,6 +440,11 @@ commander@^6.2.0:
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
|
||||
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
|
||||
|
||||
commander@^8.3.0:
|
||||
version "8.3.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
|
||||
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
|
||||
|
||||
debug@4, debug@^4.0.0, debug@^4.3.4:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
@@ -401,11 +452,30 @@ debug@4, debug@^4.0.0, debug@^4.3.4:
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
decode-named-character-reference@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e"
|
||||
integrity sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==
|
||||
dependencies:
|
||||
character-entities "^2.0.0"
|
||||
|
||||
delayed-stream@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
|
||||
|
||||
dequal@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
|
||||
integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
|
||||
|
||||
devlop@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/devlop/-/devlop-1.1.0.tgz#4db7c2ca4dc6e0e834c30be70c94bbc976dc7018"
|
||||
integrity sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==
|
||||
dependencies:
|
||||
dequal "^2.0.0"
|
||||
|
||||
dir-glob@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
|
||||
@@ -582,6 +652,11 @@ is-plain-obj@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
|
||||
integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
|
||||
|
||||
is-plain-obj@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0"
|
||||
integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==
|
||||
|
||||
js-yaml@^3.14.1:
|
||||
version "3.14.1"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
|
||||
@@ -597,11 +672,23 @@ katex@^0.12.0:
|
||||
dependencies:
|
||||
commander "^2.19.0"
|
||||
|
||||
katex@^0.16.0:
|
||||
version "0.16.9"
|
||||
resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.9.tgz#bc62d8f7abfea6e181250f85a56e4ef292dcb1fa"
|
||||
integrity sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ==
|
||||
dependencies:
|
||||
commander "^8.3.0"
|
||||
|
||||
longest-streak@^2.0.0:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4"
|
||||
integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==
|
||||
|
||||
longest-streak@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.1.0.tgz#62fa67cd958742a1574af9f39866364102d90cd4"
|
||||
integrity sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==
|
||||
|
||||
lru-cache@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
|
||||
@@ -636,6 +723,24 @@ mdast-util-from-markdown@^0.8.0:
|
||||
parse-entities "^2.0.0"
|
||||
unist-util-stringify-position "^2.0.0"
|
||||
|
||||
mdast-util-from-markdown@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz#52f14815ec291ed061f2922fd14d6689c810cb88"
|
||||
integrity sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==
|
||||
dependencies:
|
||||
"@types/mdast" "^4.0.0"
|
||||
"@types/unist" "^3.0.0"
|
||||
decode-named-character-reference "^1.0.0"
|
||||
devlop "^1.0.0"
|
||||
mdast-util-to-string "^4.0.0"
|
||||
micromark "^4.0.0"
|
||||
micromark-util-decode-numeric-character-reference "^2.0.0"
|
||||
micromark-util-decode-string "^2.0.0"
|
||||
micromark-util-normalize-identifier "^2.0.0"
|
||||
micromark-util-symbol "^2.0.0"
|
||||
micromark-util-types "^2.0.0"
|
||||
unist-util-stringify-position "^4.0.0"
|
||||
|
||||
mdast-util-gfm-autolink-literal@^0.1.0:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-0.1.3.tgz#9c4ff399c5ddd2ece40bd3b13e5447d84e385fb7"
|
||||
@@ -687,6 +792,27 @@ mdast-util-math@^0.1.0:
|
||||
mdast-util-to-markdown "^0.6.0"
|
||||
repeat-string "^1.0.0"
|
||||
|
||||
mdast-util-math@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-math/-/mdast-util-math-3.0.0.tgz#8d79dd3baf8ab8ac781f62b8853768190b9a00b0"
|
||||
integrity sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==
|
||||
dependencies:
|
||||
"@types/hast" "^3.0.0"
|
||||
"@types/mdast" "^4.0.0"
|
||||
devlop "^1.0.0"
|
||||
longest-streak "^3.0.0"
|
||||
mdast-util-from-markdown "^2.0.0"
|
||||
mdast-util-to-markdown "^2.1.0"
|
||||
unist-util-remove-position "^5.0.0"
|
||||
|
||||
mdast-util-phrasing@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-phrasing/-/mdast-util-phrasing-4.0.0.tgz#468cbbb277375523de807248b8ad969feb02a5c7"
|
||||
integrity sha512-xadSsJayQIucJ9n053dfQwVu1kuXg7jCTdYsMK8rqzKZh52nLfSH/k0sAxE0u+pj/zKZX+o5wB+ML5mRayOxFA==
|
||||
dependencies:
|
||||
"@types/mdast" "^4.0.0"
|
||||
unist-util-is "^6.0.0"
|
||||
|
||||
mdast-util-to-markdown@^0.6.0, mdast-util-to-markdown@^0.6.1, mdast-util-to-markdown@~0.6.0:
|
||||
version "0.6.5"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz#b33f67ca820d69e6cc527a93d4039249b504bebe"
|
||||
@@ -699,16 +825,59 @@ mdast-util-to-markdown@^0.6.0, mdast-util-to-markdown@^0.6.1, mdast-util-to-mark
|
||||
repeat-string "^1.0.0"
|
||||
zwitch "^1.0.0"
|
||||
|
||||
mdast-util-to-markdown@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz#9813f1d6e0cdaac7c244ec8c6dabfdb2102ea2b4"
|
||||
integrity sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==
|
||||
dependencies:
|
||||
"@types/mdast" "^4.0.0"
|
||||
"@types/unist" "^3.0.0"
|
||||
longest-streak "^3.0.0"
|
||||
mdast-util-phrasing "^4.0.0"
|
||||
mdast-util-to-string "^4.0.0"
|
||||
micromark-util-decode-string "^2.0.0"
|
||||
unist-util-visit "^5.0.0"
|
||||
zwitch "^2.0.0"
|
||||
|
||||
mdast-util-to-string@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b"
|
||||
integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==
|
||||
|
||||
mdast-util-to-string@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz#7a5121475556a04e7eddeb67b264aae79d312814"
|
||||
integrity sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==
|
||||
dependencies:
|
||||
"@types/mdast" "^4.0.0"
|
||||
|
||||
merge2@^1.3.0, merge2@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
|
||||
|
||||
micromark-core-commonmark@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-2.0.0.tgz#50740201f0ee78c12a675bf3e68ffebc0bf931a3"
|
||||
integrity sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==
|
||||
dependencies:
|
||||
decode-named-character-reference "^1.0.0"
|
||||
devlop "^1.0.0"
|
||||
micromark-factory-destination "^2.0.0"
|
||||
micromark-factory-label "^2.0.0"
|
||||
micromark-factory-space "^2.0.0"
|
||||
micromark-factory-title "^2.0.0"
|
||||
micromark-factory-whitespace "^2.0.0"
|
||||
micromark-util-character "^2.0.0"
|
||||
micromark-util-chunked "^2.0.0"
|
||||
micromark-util-classify-character "^2.0.0"
|
||||
micromark-util-html-tag-name "^2.0.0"
|
||||
micromark-util-normalize-identifier "^2.0.0"
|
||||
micromark-util-resolve-all "^2.0.0"
|
||||
micromark-util-subtokenize "^2.0.0"
|
||||
micromark-util-symbol "^2.0.0"
|
||||
micromark-util-types "^2.0.0"
|
||||
|
||||
micromark-extension-gfm-autolink-literal@~0.5.0:
|
||||
version "0.5.7"
|
||||
resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-0.5.7.tgz#53866c1f0c7ef940ae7ca1f72c6faef8fed9f204"
|
||||
@@ -762,6 +931,168 @@ micromark-extension-math@^0.1.0:
|
||||
katex "^0.12.0"
|
||||
micromark "~2.11.0"
|
||||
|
||||
micromark-extension-math@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-extension-math/-/micromark-extension-math-3.0.0.tgz#c7a47d6ce990812243ad3946a30bb60e4c2a8c76"
|
||||
integrity sha512-iJ2Q28vBoEovLN5o3GO12CpqorQRYDPT+p4zW50tGwTfJB+iv/VnB6Ini+gqa24K97DwptMBBIvVX6Bjk49oyQ==
|
||||
dependencies:
|
||||
"@types/katex" "^0.16.0"
|
||||
devlop "^1.0.0"
|
||||
katex "^0.16.0"
|
||||
micromark-factory-space "^2.0.0"
|
||||
micromark-util-character "^2.0.0"
|
||||
micromark-util-symbol "^2.0.0"
|
||||
micromark-util-types "^2.0.0"
|
||||
|
||||
micromark-factory-destination@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz#857c94debd2c873cba34e0445ab26b74f6a6ec07"
|
||||
integrity sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==
|
||||
dependencies:
|
||||
micromark-util-character "^2.0.0"
|
||||
micromark-util-symbol "^2.0.0"
|
||||
micromark-util-types "^2.0.0"
|
||||
|
||||
micromark-factory-label@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz#17c5c2e66ce39ad6f4fc4cbf40d972f9096f726a"
|
||||
integrity sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==
|
||||
dependencies:
|
||||
devlop "^1.0.0"
|
||||
micromark-util-character "^2.0.0"
|
||||
micromark-util-symbol "^2.0.0"
|
||||
micromark-util-types "^2.0.0"
|
||||
|
||||
micromark-factory-space@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz#5e7afd5929c23b96566d0e1ae018ae4fcf81d030"
|
||||
integrity sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==
|
||||
dependencies:
|
||||
micromark-util-character "^2.0.0"
|
||||
micromark-util-types "^2.0.0"
|
||||
|
||||
micromark-factory-title@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz#726140fc77892af524705d689e1cf06c8a83ea95"
|
||||
integrity sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==
|
||||
dependencies:
|
||||
micromark-factory-space "^2.0.0"
|
||||
micromark-util-character "^2.0.0"
|
||||
micromark-util-symbol "^2.0.0"
|
||||
micromark-util-types "^2.0.0"
|
||||
|
||||
micromark-factory-whitespace@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz#9e92eb0f5468083381f923d9653632b3cfb5f763"
|
||||
integrity sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==
|
||||
dependencies:
|
||||
micromark-factory-space "^2.0.0"
|
||||
micromark-util-character "^2.0.0"
|
||||
micromark-util-symbol "^2.0.0"
|
||||
micromark-util-types "^2.0.0"
|
||||
|
||||
micromark-util-character@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.0.1.tgz#52b824c2e2633b6fb33399d2ec78ee2a90d6b298"
|
||||
integrity sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==
|
||||
dependencies:
|
||||
micromark-util-symbol "^2.0.0"
|
||||
micromark-util-types "^2.0.0"
|
||||
|
||||
micromark-util-chunked@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz#e51f4db85fb203a79dbfef23fd41b2f03dc2ef89"
|
||||
integrity sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==
|
||||
dependencies:
|
||||
micromark-util-symbol "^2.0.0"
|
||||
|
||||
micromark-util-classify-character@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz#8c7537c20d0750b12df31f86e976d1d951165f34"
|
||||
integrity sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==
|
||||
dependencies:
|
||||
micromark-util-character "^2.0.0"
|
||||
micromark-util-symbol "^2.0.0"
|
||||
micromark-util-types "^2.0.0"
|
||||
|
||||
micromark-util-combine-extensions@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz#75d6ab65c58b7403616db8d6b31315013bfb7ee5"
|
||||
integrity sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==
|
||||
dependencies:
|
||||
micromark-util-chunked "^2.0.0"
|
||||
micromark-util-types "^2.0.0"
|
||||
|
||||
micromark-util-decode-numeric-character-reference@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.0.tgz#a798808d02cc74113e2c939fc95363096ade7f1d"
|
||||
integrity sha512-pIgcsGxpHEtTG/rPJRz/HOLSqp5VTuIIjXlPI+6JSDlK2oljApusG6KzpS8AF0ENUMCHlC/IBb5B9xdFiVlm5Q==
|
||||
dependencies:
|
||||
micromark-util-symbol "^2.0.0"
|
||||
|
||||
micromark-util-decode-string@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz#7dfa3a63c45aecaa17824e656bcdb01f9737154a"
|
||||
integrity sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==
|
||||
dependencies:
|
||||
decode-named-character-reference "^1.0.0"
|
||||
micromark-util-character "^2.0.0"
|
||||
micromark-util-decode-numeric-character-reference "^2.0.0"
|
||||
micromark-util-symbol "^2.0.0"
|
||||
|
||||
micromark-util-encode@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz#0921ac7953dc3f1fd281e3d1932decfdb9382ab1"
|
||||
integrity sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==
|
||||
|
||||
micromark-util-html-tag-name@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz#ae34b01cbe063363847670284c6255bb12138ec4"
|
||||
integrity sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==
|
||||
|
||||
micromark-util-normalize-identifier@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz#91f9a4e65fe66cc80c53b35b0254ad67aa431d8b"
|
||||
integrity sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==
|
||||
dependencies:
|
||||
micromark-util-symbol "^2.0.0"
|
||||
|
||||
micromark-util-resolve-all@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz#189656e7e1a53d0c86a38a652b284a252389f364"
|
||||
integrity sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==
|
||||
dependencies:
|
||||
micromark-util-types "^2.0.0"
|
||||
|
||||
micromark-util-sanitize-uri@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz#ec8fbf0258e9e6d8f13d9e4770f9be64342673de"
|
||||
integrity sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==
|
||||
dependencies:
|
||||
micromark-util-character "^2.0.0"
|
||||
micromark-util-encode "^2.0.0"
|
||||
micromark-util-symbol "^2.0.0"
|
||||
|
||||
micromark-util-subtokenize@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.0.tgz#9f412442d77e0c5789ffdf42377fa8a2bcbdf581"
|
||||
integrity sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==
|
||||
dependencies:
|
||||
devlop "^1.0.0"
|
||||
micromark-util-chunked "^2.0.0"
|
||||
micromark-util-symbol "^2.0.0"
|
||||
micromark-util-types "^2.0.0"
|
||||
|
||||
micromark-util-symbol@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz#12225c8f95edf8b17254e47080ce0862d5db8044"
|
||||
integrity sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==
|
||||
|
||||
micromark-util-types@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-2.0.0.tgz#63b4b7ffeb35d3ecf50d1ca20e68fc7caa36d95e"
|
||||
integrity sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==
|
||||
|
||||
micromark@^2.11.3, micromark@~2.11.0, micromark@~2.11.3:
|
||||
version "2.11.4"
|
||||
resolved "https://registry.yarnpkg.com/micromark/-/micromark-2.11.4.tgz#d13436138eea826383e822449c9a5c50ee44665a"
|
||||
@@ -770,6 +1101,29 @@ micromark@^2.11.3, micromark@~2.11.0, micromark@~2.11.3:
|
||||
debug "^4.0.0"
|
||||
parse-entities "^2.0.0"
|
||||
|
||||
micromark@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/micromark/-/micromark-4.0.0.tgz#84746a249ebd904d9658cfabc1e8e5f32cbc6249"
|
||||
integrity sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==
|
||||
dependencies:
|
||||
"@types/debug" "^4.0.0"
|
||||
debug "^4.0.0"
|
||||
decode-named-character-reference "^1.0.0"
|
||||
devlop "^1.0.0"
|
||||
micromark-core-commonmark "^2.0.0"
|
||||
micromark-factory-space "^2.0.0"
|
||||
micromark-util-character "^2.0.0"
|
||||
micromark-util-chunked "^2.0.0"
|
||||
micromark-util-combine-extensions "^2.0.0"
|
||||
micromark-util-decode-numeric-character-reference "^2.0.0"
|
||||
micromark-util-encode "^2.0.0"
|
||||
micromark-util-normalize-identifier "^2.0.0"
|
||||
micromark-util-resolve-all "^2.0.0"
|
||||
micromark-util-sanitize-uri "^2.0.0"
|
||||
micromark-util-subtokenize "^2.0.0"
|
||||
micromark-util-symbol "^2.0.0"
|
||||
micromark-util-types "^2.0.0"
|
||||
|
||||
micromatch@^4.0.4:
|
||||
version "4.0.5"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
|
||||
@@ -868,6 +1222,16 @@ remark-math@^4.0.0:
|
||||
mdast-util-math "^0.1.0"
|
||||
micromark-extension-math "^0.1.0"
|
||||
|
||||
remark-math@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/remark-math/-/remark-math-6.0.0.tgz#0acdf74675f1c195fea6efffa78582f7ed7fc0d7"
|
||||
integrity sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==
|
||||
dependencies:
|
||||
"@types/mdast" "^4.0.0"
|
||||
mdast-util-math "^3.0.0"
|
||||
micromark-extension-math "^3.0.0"
|
||||
unified "^11.0.0"
|
||||
|
||||
remark-parse@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-9.0.0.tgz#4d20a299665880e4f4af5d90b7c7b8a935853640"
|
||||
@@ -926,6 +1290,11 @@ trough@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406"
|
||||
integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==
|
||||
|
||||
trough@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876"
|
||||
integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==
|
||||
|
||||
ts-api-utils@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.2.tgz#7c094f753b6705ee4faee25c3c684ade52d66d99"
|
||||
@@ -941,6 +1310,19 @@ typescript@5.2.2:
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78"
|
||||
integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==
|
||||
|
||||
unified@^11.0.0:
|
||||
version "11.0.3"
|
||||
resolved "https://registry.yarnpkg.com/unified/-/unified-11.0.3.tgz#e141be0fe466a2d28b2160f62712bc9cbc08fdd4"
|
||||
integrity sha512-jlCV402P+YDcFcB2VcN/n8JasOddqIiaxv118wNBoZXEhOn+lYG7BR4Bfg2BwxvlK58dwbuH2w7GX2esAjL6Mg==
|
||||
dependencies:
|
||||
"@types/unist" "^3.0.0"
|
||||
bail "^2.0.0"
|
||||
devlop "^1.0.0"
|
||||
extend "^3.0.0"
|
||||
is-plain-obj "^4.0.0"
|
||||
trough "^2.0.0"
|
||||
vfile "^6.0.0"
|
||||
|
||||
unified@^9.2.1:
|
||||
version "9.2.2"
|
||||
resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975"
|
||||
@@ -958,6 +1340,21 @@ unist-util-is@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797"
|
||||
integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==
|
||||
|
||||
unist-util-is@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-6.0.0.tgz#b775956486aff107a9ded971d996c173374be424"
|
||||
integrity sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==
|
||||
dependencies:
|
||||
"@types/unist" "^3.0.0"
|
||||
|
||||
unist-util-remove-position@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz#fea68a25658409c9460408bc6b4991b965b52163"
|
||||
integrity sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==
|
||||
dependencies:
|
||||
"@types/unist" "^3.0.0"
|
||||
unist-util-visit "^5.0.0"
|
||||
|
||||
unist-util-stringify-position@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da"
|
||||
@@ -965,6 +1362,13 @@ unist-util-stringify-position@^2.0.0:
|
||||
dependencies:
|
||||
"@types/unist" "^2.0.2"
|
||||
|
||||
unist-util-stringify-position@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz#449c6e21a880e0855bf5aabadeb3a740314abac2"
|
||||
integrity sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==
|
||||
dependencies:
|
||||
"@types/unist" "^3.0.0"
|
||||
|
||||
unist-util-visit-parents@^3.0.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6"
|
||||
@@ -973,6 +1377,23 @@ unist-util-visit-parents@^3.0.0:
|
||||
"@types/unist" "^2.0.0"
|
||||
unist-util-is "^4.0.0"
|
||||
|
||||
unist-util-visit-parents@^6.0.0:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz#4d5f85755c3b8f0dc69e21eca5d6d82d22162815"
|
||||
integrity sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==
|
||||
dependencies:
|
||||
"@types/unist" "^3.0.0"
|
||||
unist-util-is "^6.0.0"
|
||||
|
||||
unist-util-visit@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz#a7de1f31f72ffd3519ea71814cccf5fd6a9217d6"
|
||||
integrity sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==
|
||||
dependencies:
|
||||
"@types/unist" "^3.0.0"
|
||||
unist-util-is "^6.0.0"
|
||||
unist-util-visit-parents "^6.0.0"
|
||||
|
||||
vfile-message@^2.0.0:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a"
|
||||
@@ -981,6 +1402,14 @@ vfile-message@^2.0.0:
|
||||
"@types/unist" "^2.0.0"
|
||||
unist-util-stringify-position "^2.0.0"
|
||||
|
||||
vfile-message@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-4.0.2.tgz#c883c9f677c72c166362fd635f21fc165a7d1181"
|
||||
integrity sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==
|
||||
dependencies:
|
||||
"@types/unist" "^3.0.0"
|
||||
unist-util-stringify-position "^4.0.0"
|
||||
|
||||
vfile@^4.0.0:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624"
|
||||
@@ -991,6 +1420,15 @@ vfile@^4.0.0:
|
||||
unist-util-stringify-position "^2.0.0"
|
||||
vfile-message "^2.0.0"
|
||||
|
||||
vfile@^6.0.0:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/vfile/-/vfile-6.0.1.tgz#1e8327f41eac91947d4fe9d237a2dd9209762536"
|
||||
integrity sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==
|
||||
dependencies:
|
||||
"@types/unist" "^3.0.0"
|
||||
unist-util-stringify-position "^4.0.0"
|
||||
vfile-message "^4.0.0"
|
||||
|
||||
webidl-conversions@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||
@@ -1026,3 +1464,8 @@ zwitch@^1.0.0:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"
|
||||
integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==
|
||||
|
||||
zwitch@^2.0.0:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7"
|
||||
integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==
|
||||
|
||||
Reference in New Issue
Block a user