Compare commits

...

40 Commits
0.1.9 ... 1.0.0

Author SHA1 Message Date
Jiaxin Peng
b3702a9cc1 Update version to 1.0.0 2023-11-16 13:29:29 +00:00
Jiaxin Peng
ba9b477db7 Update version to 0.2.7 2023-11-16 13:27:48 +00:00
Jiaxin Peng
fb6951cfdf Update version to 0.3.5 2023-11-16 13:25:56 +00:00
Jiaxin Peng
6454c0417d Update version to 0.3.4 2023-11-16 13:10:53 +00:00
Jiaxin Peng
35f19a9f43 modify the action file 2023-11-16 13:10:27 +00:00
Jiaxin Peng
8e32e8f0f5 Update version to 0.3.3 2023-11-16 12:59:41 +00:00
Jiaxin Peng
880f256ae1 Update version to 0.3.2 2023-11-16 12:55:01 +00:00
Jiaxin Peng
bf9c3f2933 Update version to 0.3.1 2023-11-16 11:58:58 +00:00
Jiaxin Peng
2ac354299a update action file 2023-11-16 11:58:44 +00:00
Jiaxin Peng
8317abb667 Update version to 0.3.0 2023-11-16 11:50:36 +00:00
Jiaxin Peng
d74634aca6 Merge pull request #7 from jxpeng98/custom-title
Custom title
2023-11-16 11:48:14 +00:00
Jiaxin Peng
d400b92263 update readme 2023-11-16 11:44:45 +00:00
Jiaxin Peng
e7fa597e5a update translate 2023-11-16 11:14:19 +00:00
Jiaxin Peng
6ce689ba96 complete the basic customisation feature 2023-11-16 01:00:52 +00:00
Jiaxin Peng
b978cf7e01 complete the setting ui 2023-11-16 00:02:35 +00:00
Jiaxin Peng
4e3c88f129 reorganise the code for add new setting container 2023-11-15 12:25:30 +00:00
Jiaxin Peng
6550bca70f reorganise the setting coding 2023-11-15 09:34:22 +00:00
Jiaxin Peng
662edbb84c remove the collapse details 2023-11-15 00:16:19 +00:00
Jiaxin Peng
671936ee41 add some details for collapse 2023-11-15 00:15:52 +00:00
Jiaxin Peng
2b16ea76c6 update the setting ui 2023-11-14 23:27:38 +00:00
Jiaxin Peng
399a02187f update packages and complete the setting UI 2023-11-14 15:42:30 +00:00
Jiaxin Peng
eee349509a Update version to 0.2.6 2023-11-12 21:02:00 +00:00
Jiaxin Peng
57c0941fed Merge pull request #6 from jxpeng98/add-button
Add switch button
2023-11-12 21:00:43 +00:00
Jiaxin Peng
8734af6dbf add switch button 2023-11-12 20:59:39 +00:00
Jiaxin Peng
041a78fb52 add button to display the command in the command palette 2023-11-11 00:29:35 +00:00
Jiaxin Peng
afec5d8364 Update version to 0.2.5 2023-11-05 20:49:28 +00:00
Jiaxin Peng
75926a38d4 Update version to 0.2.4 2023-11-05 20:46:42 +00:00
Jiaxin Peng
793dd67e0a Update version to 0.2.3 2023-11-05 20:44:51 +00:00
Jiaxin Peng
f235c80d18 update readme 2023-11-05 20:44:42 +00:00
Jiaxin Peng
f33315a4b6 fix github action bug 2023-11-05 20:43:47 +00:00
Jiaxin Peng
b62bd4ba2e Update version to 0.2.2 2023-11-05 17:58:19 +00:00
Jiaxin Peng
402d15a38b Merge pull request #5 from jxpeng98/general-database
General database
2023-11-05 17:57:21 +00:00
Jiaxin Peng
87f1ce0146 update readme and settingtabs 2023-11-05 17:50:51 +00:00
Jiaxin Peng
398b785e03 update the script and support both notionnext and general database 2023-11-05 17:32:10 +00:00
Jiaxin Peng
8617878582 restructure the code for further feature 2023-11-04 22:37:02 +00:00
Jiaxin Peng
ae9e0c14fb modify the directory structure and rename the function 2023-11-02 14:32:25 +00:00
Jiaxin Peng
9be9b18efb Update version to 0.2.0 2023-11-01 23:24:34 +00:00
Jiaxin Peng
588f57205b Modified the template and rebuilt the interactive logic 2023-11-01 23:24:18 +00:00
Jiaxin Peng
cfbedea91d Update version to 0.1.10 2023-11-01 10:32:35 +00:00
Jiaxin Peng
4cd6557444 chinese support in settings 2023-11-01 10:32:22 +00:00
26 changed files with 1390 additions and 715 deletions

View File

@@ -1,4 +1,4 @@
name: Release Obsidian plugin
name: Release Obsidian-to-NotionNext plugin
on:
push:

View File

@@ -3,6 +3,42 @@
所以我在[原作者](https://github.com/EasyChris/obsidian-to-notion)的基础之上,增加了匹配[NotionNext](https://github.com/tangly1024/NotionNext)模板的功能。这样可以直接在Obsidian编辑整理好之后一键发布。
## 更新说明
### 0.3.0 (大更新)
- 这个版本开始,你可以**任意修改第一列表头的名字 (标题列,默认:'title')**。 **注意你必须保证你的Notion数据库中有'tags这一列的存在并且在markdown文件中把`tags:`添加到你的YAML表头中。否则会返回`400 错误`。但是你可以`tags:`设置为空。**
![](https://minioapi.pjx.ac.cn/img1/2023/11/4a298b9be3990e9d2201bf2f50ca5a0a.png)
例如这样:
![](https://minioapi.pjx.ac.cn/img1/2023/11/4cd8d79cd9dd9dde299e39c666cb3473.gif)
- 增加了一个控制按钮来控制是否开启当前数据库同步命令的功能。如果你关闭了这个按钮,你在上传命令列表中就不会出现当前数据库的选项。
![](https://minioapi.pjx.ac.cn/img1/2023/11/becb60fc44783842da4b3cf4c322f363.gif)
### 0.2.6
- 增加一个按钮用来控制是否在名列列表中显示如下数据库。
![](https://minioapi.pjx.ac.cn/img1/2023/11/147c6a4eaa34da41a6f102558ed77106.png)
如果你关闭普通数据库的按钮你在上传命令列表中就不会出现普通数据库的选项。如果你关闭NotionNext数据库的按钮你在上传命令列表中就不会出现NotionNext数据库的选项。
![](https://minioapi.pjx.ac.cn/img1/2023/11/70b8e4fc2148688ccbd6cfc53ce339a2.png)
### 0.2.3
- 修复了一个bug现在可以正常更新了。
### 0.2.2
- 支持NotionNext 和 普通Notion 数据库的同步。
- 你可以有一个NotionNext和一个普通Notion数据库。
- 普通Notion数据库的同步方式和原作者的一样只同步`title``tags`。**如果使用普通数据库功能,你需要保证你的数据库中有`title``tags`这两个表头。必须使用小写。**
![](https://minioapi.pjx.ac.cn/img1/2023/11/712a12081d855aa60f82a7b46913ab7e.gif)
![](https://minioapi.pjx.ac.cn/img1/2023/11/9de76cecceef74c78884ddfc1c221659.gif)
### 0.2.1
- 重构代码。
### 0.2.0
- 从这个版本开始,重构了交互逻辑。现在当你点击左侧的按钮,会弹出可同步的数据库选项。你可以选择你想要同步的数据库,然后点击同步按钮。**但是现在仅支持同步单个数据库如果你的数据库不是NotionNext你可以不用更新。**
### 0.1.10
- 修正了设置中的中文显示。
### 0.1.8
- 重新整理了代码,增加了一个仓库转换按钮为之后的多数据库支持作准备。**但是现在还不支持多数据库如果你的数据库不是NotionNext你可以不用更新。**
### 0.1.7
@@ -67,6 +103,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 默认是空

View File

@@ -4,9 +4,52 @@
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.
**Now, support both NotionNext and General databases.**
## Update
### 0.3.0 (Big Update)
- From this version, you can **modify the first column name (title column, default: 'title')** as you want. (**Note: You need to have the 'tags' column in your Notion General database, and add `tags:` in your markdown frontmatter. If not, you will receive `network error 400`. But you can leave the `tags:` blank.**)
![](https://minioapi.pjx.ac.cn/img1/2023/11/4a298b9be3990e9d2201bf2f50ca5a0a.png)
Like this:
![](https://minioapi.pjx.ac.cn/img1/2023/11/4cd8d79cd9dd9dde299e39c666cb3473.gif)
- Add a switch button to control whether display the setting tabs in the plugin settings for both NotionNext and Notion General databases.
![](https://minioapi.pjx.ac.cn/img1/2023/11/becb60fc44783842da4b3cf4c322f363.gif)
### 0.2.6
- Add a switch button to control whether to show the upload command in the command palette.
![](https://minioapi.pjx.ac.cn/img1/2023/11/147c6a4eaa34da41a6f102558ed77106.png)
If you turn off the button for the General database, you won't see the option for the General database in the upload command list.
If you turn off the button for the NotionNext database, you won't see the option for the NotionNext database in the upload command list.
![](https://minioapi.pjx.ac.cn/img1/2023/11/70b8e4fc2148688ccbd6cfc53ce339a2.png)
### 0.2.3
- Fix the bug, now you can update normally.
### 0.2.2
- Support both NotionNext and General Notion database.
- You can have one NotionNext and one General Notion database.
- General Notion database can only have `title` and `tags` columns, and `tags` columns should be the multi-selected property. **the name of the columns is case sensitive. You should use small letter.**
![](https://minioapi.pjx.ac.cn/img1/2023/11/712a12081d855aa60f82a7b46913ab7e.gif)
![](https://minioapi.pjx.ac.cn/img1/2023/11/9de76cecceef74c78884ddfc1c221659.gif)
### 0.2.1
- Restructure the code
### 0.2.0
- From this version, the interactive logic has been rewritten. When you click the ribbon icon, it will display the sync command for all presetting NotionNext databases. You can choose the database you want to sync to. **However, only NotionNext database is supported for now.**
### 0.1.10
- Fix the Chinese support in the settings.
### 0.1.8
- Rebuild the upload function, and add one button to select the different databases. **However, only NotionNext database is supported for now.**
- Rebuild the uploadCommand function, and add one button to select the different databases. **However, only NotionNext database is supported for now.**
### 0.1.7
- [x] Removed the `convert tag` option. Now, you can directly add tags in the YAML front matter. If you don't want to add tags, you can delete the tags in the YAML front matter or leave the tags blank.
@@ -68,6 +111,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 默认是空
@@ -181,9 +225,9 @@ Fill the configuration with the `NOTION_API_KEY` and `DATABASE_ID` you got
![](./doc/2.png)
## Upload file content to notion
Click the upload notion button
Click the uploadCommand notion button
![](./doc/4.png)
A share link will be automatically generated after successful upload
A share link will be automatically generated after successful uploadCommand
![](./doc/5.png)

View File

@@ -1,7 +1,7 @@
{
"id": "share-to-notionnext",
"name": "Share to NotionNext",
"version": "0.1.9",
"version": "1.0.0",
"minAppVersion": "0.0.1",
"description": "Shares obsidian md file to notion with notion api for NotionNext web deploy, originally created by EasyChris/obsidian-to-notion.",
"author": "EasyChris, jxpeng98",

View File

@@ -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 默认是空

View File

@@ -1,6 +1,6 @@
{
"name": "share-to-notionnext",
"version": "0.1.9",
"version": "1.0.0",
"type": "module",
"description": "Shares obsidian md file to notion with notion api for NotionNext web deploy, originally created by EasyChris/obsidian-to-notion.",
"main": "main.js",
@@ -14,9 +14,9 @@
"license": "GNU GPLv3",
"devDependencies": {
"@types/node": "^20.5.7",
"@types/yaml-front-matter": "^4.1.0",
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
"@types/yaml-front-matter": "^4.1.3",
"@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.11.0",
"builtin-modules": "^3.2.0",
"esbuild": "0.19.2",
"obsidian": "latest",
@@ -24,11 +24,11 @@
"typescript": "5.2.2"
},
"dependencies": {
"@tryfabric/martian": "^1.2.0",
"https-proxy-agent": "^7.0.1",
"@tryfabric/martian": "^1.2.4",
"https-proxy-agent": "^7.0.2",
"process": "^0.11.10",
"remark-math": "^6.0.0",
"yaml": "^2.2.2",
"yaml": "^2.3.4",
"yaml-front-matter": "^4.1.1"
}
}

View File

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

View File

@@ -1,29 +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.",
"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": {
"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 NoticeMConfig = (lang: any): any => {
return NoticeMsg[lang]
}

View File

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

View File

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

View File

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

View File

@@ -1,28 +0,0 @@
export const i18n: { [key: string]: any } = {
"en": {
NotionNextVersion: "NotionNext Version Database",
NotionNextVersionDesc: "Turn on this option if you are using NotionNext",
NotionNextSetting: "NotionNext Database Settings",
NotionAPI: "Notion API Token",
NotionAPIDesc: "It's a secret",
NotionID: "Database ID",
BannerUrl: "Banner url(optional)",
BannerUrlDesc: "page banner url(optional), default is empty, if you want to show a banner, please enter the url(like:https://raw.githubusercontent.com/EasyChris/obsidian-to-notion/ae7a9ac6cf427f3ca338a409ce6967ced9506f12/doc/2.png)",
NotionUser: "Notion ID(username, optional)",
NotionGeneralSetting: "General Notion Database Settings",
NotYetFinish: "Not finished. This function will be available in the next version",
},
"zh": {
NotionNextVersion: "NotionNext 版本数据库",
NotionNextVersionDesc: "如果你使用的是NotionNext请打开此选项",
NotionNextSetting: "NotionNext 数据库参数设置",
NotionAPI: "Notion API 令牌",
NotionAPIDesc: "显示为密码",
NotionID: "数据库 ID",
BannerUrl: "封面图片地址(可选)",
BannerUrlDesc: "页面封面图片地址可选默认为空如果你想显示封面图片请输入图片地址例如https://raw.githubusercontent.com/EasyChris/obsidian-to-notion/ae7a9ac6cf427f3ca338a409ce6967ced9506f12/doc/2.png",
NotionUser: "Notion ID用户名可选",
NotionGeneralSetting: "普通 Notion 数据库设置",
NotYetFinish: "未完成。此功能将在之后版本中提供",
},
}

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

@@ -0,0 +1,109 @@
export const I18n: { [key: string]: any } = {
en: {
ribbonIcon: "Share to NotionNext",
GeneralSetting: "General information Settings",
CommandID: "share-to-notionnext",
CommandName: "Share to NotionNext Database",
CommandIDGeneral: "share-to-notion",
CommandNameGeneral: "Share to Notion General Database",
NotionNextButton: "NotionNext Sync",
NotionNextButtonDesc: "Open this option, Sync to NotionNext command will be displayed in the command palette (default: ON)",
NotionNextSettingHeader: "NotionNext Database Settings",
NotionAPI: "Notion API Token",
NotionAPIDesc: "Generate from https://www.notion.so/my-integrations",
NotionAPIText: "Enter your Notion API Token",
DatabaseID: "Database ID",
DatabaseIDText: "Enter your Database ID",
BannerUrl: "Banner url (optional)",
BannerUrlDesc:
"Default is empty, if you want to show a banner, please enter the url (like: https://minioapi.pjx.ac.cn/img1/2023/11/b7b40a0724e93b7d7ab494bb3b8a2da8.png)",
BannerUrlText: "Enter your banner url",
NotionUser: "Notion ID (username, optional)",
NotionUserDesc:
"Collect from share link likes:https://username.notion.site. Your notion id is [username]",
NotionUserText: "Enter your notion ID",
NotionGeneralSettingHeader: "General Notion Database Settings",
NotionGeneralButton: "Notion General Sync",
NotionGeneralButtonDesc: "Open this option, Sync to Notion General Database command will be displayed in the command palette (default: ON)",
NotionCustomTitle: "Customise title property",
NotionCustomTitleDesc: "Modify the column name of the Notion database (default: OFF)",
NotionCustomTitleName: "Preferred title name",
NotionCustomTitleNameDesc: "Enter the preferred title name for the first column of the Notion database (default: title)",
NotionCustomTitleText: "Enter the name",
NotYetFinish:
"Not finished. This function will be available in the next version",
PlaceHolder: "Enter database Name",
"notion-logo": "Share to NotionNext",
"sync-success": "Sync to NotionNext success: \n",
"sync-fail": "Sync to NotionNext fail: \n",
"open-notion": "Please open the file that needs to be synchronized",
"config-secrets-notion-api":
"Please set up the notion API in the settings tab.",
"config-secrets-database-id":
"Please set up the database id in the settings tab.",
"set-tags-fail":
"Set tags fail,please check the frontmatter of the file or close the tag switch in the settings tab.",
NNonMissing:
"The 'NNon' property is missing in the settings. Please set it up.",
"set-api-id":
"Please set up the notion API and database ID in the settings tab.",
NotionCustomSettingHeader: "Notion Custom Database Settings",
NotionCustomButton: "Notion Customised command switch",
NotionCustomButtonDesc: "Open this option, Sync to Notion Customised Database command will be displayed in the command palette",
},
zh: {
ribbonIcon: "分享到 NotionNext",
GeneralSetting: "通用设置",
CommandID: "share-to-notionnext",
CommandName: "分享到 NotionNext",
CommandIDGeneral: "share-to-notion",
CommandNameGeneral: "分享到 Notion 普通数据库",
NotionNextButton: "NotionNext 同步",
NotionNextButtonDesc: "打开此选项NotionNext 同步将显示在命令面板中(默认:开)",
NotionNextSettingHeader: "NotionNext 数据库参数设置",
NotionAPI: "Notion API 令牌",
NotionAPIDesc: "从 https://www.notion.so/my-integrations 生成",
NotionAPIText: "输入你的 Notion API 令牌",
DatabaseID: "数据库 ID",
DatabaseIDText: "输入你的数据库 ID",
BannerUrl: "封面图片地址(可选)",
BannerUrlDesc:
"默认为空如果你想显示封面图片请输入图片地址例如https://minioapi.pjx.ac.cn/img1/2023/11/b7b40a0724e93b7d7ab494bb3b8a2da8.png",
BannerUrlText: "输入你的封面图片地址",
NotionUser: "Notion ID用户名可选",
NotionUserDesc:
"数据库分享链接类似https://username.notion.site/。你的 Notion ID 是 [username]",
NotionUserText: "输入你的 Notion ID",
NotionGeneralSettingHeader: "普通 Notion 数据库设置",
NotionGeneralButton: "普通数据库同步",
NotionGeneralButtonDesc: "打开此选项,同步到普通数据库命令将显示在命令面板中(默认:开)",
NotionCustomTitle: "修改 Notion 数据库表头开关",
NotionCustomTitleDesc: "自定义Notion 数据库第一列表头名(默认:关)",
NotionCustomTitleName: "想要修改的表头名",
NotionCustomTitleNameDesc: "输入你想要修改的notion数据库的表头名默认title",
NotionCustomTitleText: "输入表头名",
NotYetFinish: "未完成。此功能将在之后版本中提供",
PlaceHolder: "输入数据库名称",
"notion-logo": "分享到NotionNext",
"sync-success": "同步到NotionNext成功:\n",
"sync-fail": "同步到NotionNext失败: \n",
"open-file": "请打开需要同步的文件",
"config-secrets-notion-api": "请在插件设置中添加notion API",
"config-secrets-database-id": "请在插件设置中添加database id",
"set-tags-fail":
"设置标签失败,请检查文件的frontmatter,或者在插件设置中关闭设置tags开关",
NNonMissing: "未设置'NNon'属性请在插件设置中选择NotionNext数据库。",
"set-api-id": "请在插件设置中设置notion API和database ID",
NotionCustomSettingHeader: "Notion 自定义数据库设置",
NotionCustomButton: "Notion 自定义数据库同步命令开关",
NotionCustomButtonDesc: "打开此选项,同步到自定义数据库命令将显示在命令面板中",
},
};
export const I18nConfig = (lang: any): any => {
return I18n[lang];
};
export const i18nConfig = I18nConfig(
window.localStorage.getItem("language") || "en",
); // Export i18nConfig

View File

@@ -1,60 +1,39 @@
import {App, Editor, MarkdownView, Notice, Plugin, PluginSettingTab, Setting} from "obsidian";
import {addIcons} from 'src/icon';
import {Upload2Notion} from "src/Upload2Notion";
import {Upload2NotionNext} from "src/Upload2Notion_NN";
import {NoticeMConfig} from "src/Message";
import { App, Editor, MarkdownView, Notice, Plugin, PluginSettingTab, Setting } from "obsidian";
import { addIcons } from 'src/ui/icon';
import { Upload2NotionGeneral } from "src/upload/upload_general/Upload2NotionGeneral";
import { Upload2NotionNext } from "src/upload/upload_next/Upload2NotionNext";
import { i18nConfig } from "src/lang/I18n";
import ribbonCommands from "src/commands/NotionCommands";
import { ObsidianSettingTab, PluginSettings, DEFAULT_SETTINGS } from "src/ui/settingTabs";
// Remember to rename these classes and interfaces!
interface PluginSettings {
NNon: boolean;
notionAPI: string;
databaseID: string;
bannerUrl: string;
notionID: string;
proxy: string;
}
const langConfig = NoticeMConfig(window.localStorage.getItem('language') || 'en')
const DEFAULT_SETTINGS: PluginSettings = {
NNon: undefined,
notionAPI: "",
databaseID: "",
bannerUrl: "",
notionID: "",
proxy: "",
};
export default class ObsidianSyncNotionPlugin extends Plugin {
settings: PluginSettings;
commands: ribbonCommands;
app: App;
async onload() {
await this.loadSettings();
this.commands = new ribbonCommands(this);
addIcons();
// This creates an icon in the left ribbon.
const ribbonIconEl = this.addRibbonIcon(
"notion-logo",
"Share to NotionNext",
i18nConfig.ribbonIcon,
async (evt: MouseEvent) => {
// Called when the user clicks the icon.
await this.upload();
// await this.uploadCommand();
await this.commands.ribbonDisplay();
}
);
// This adds a status bar item to the bottom of the app. Does not work on mobile apps.
const statusBarItemEl = this.addStatusBarItem();
// statusBarItemEl.setText("share to notion");
this.addCommand({
id: "share-to-notionnext",
name: "share to notionnext",
editorCallback: async (editor: Editor, view: MarkdownView) => {
await this.upload()
},
});
// const statusBarItemEl = this.addStatusBarItem();
// // statusBarItemEl.setText("share to notion");
// This adds a settings tab so the user can configure various aspects of the plugin
this.addSettingTab(new ObsidianSettingTab(this.app, this));
@@ -64,102 +43,6 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
onunload() {
}
async upload() {
const { notionAPI, databaseID, NNon} = this.settings;
// Check if NNon exists
if (NNon === undefined) {
const NNonmessage = NoticeMConfig(window.localStorage.getItem('language') || 'en')["NNonMissing"];
new Notice(NNonmessage);
return;
}
// Check if the user has set up the Notion API and database ID
if (notionAPI === "" || databaseID === "") {
const setAPIMessage = NoticeMConfig(window.localStorage.getItem('language') || 'en')["set-api-id"];
new Notice(setAPIMessage);
return;
}
const {markDownData, nowFile, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime} = await this.getNowFileMarkdownContent(this.app);
if (markDownData) {
const { basename } = nowFile;
let upload;
if (NNon) {
upload = new Upload2NotionNext(this);
} else {
upload = new Upload2Notion(this);
}
const res = await upload.syncMarkdownToNotion(basename, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, markDownData, nowFile, this.app, this.settings);
if (res.status === 200) {
new Notice(`${langConfig["sync-success"]}${basename}`);
} else {
new Notice(`${langConfig["sync-fail"]}${basename}`, 5000);
}
}
}
async getNowFileMarkdownContent(app: App) {
const nowFile = app.workspace.getActiveFile();
const {NNon} = this.settings;
let emoji = ''
let cover = ''
let tags = []
let type = ''
let slug = ''
let stats = ''
let category = ''
let summary = ''
let paword = ''
let favicon = ''
let datetime = ''
const FileCache = app.metadataCache.getFileCache(nowFile)
try {
if (NNon) {
emoji = FileCache.frontmatter.titleicon;
cover = FileCache.frontmatter.coverurl;
tags = FileCache.frontmatter.tags;
type = FileCache.frontmatter.type;
slug = FileCache.frontmatter.slug;
stats = FileCache.frontmatter.stats;
category = FileCache.frontmatter.category;
summary = FileCache.frontmatter.summary;
paword = FileCache.frontmatter.password;
favicon = FileCache.frontmatter.icon;
datetime = FileCache.frontmatter.date;
}
} catch (error) {
new Notice(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(
{},
@@ -171,110 +54,9 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
async saveSettings() {
await this.saveData(this.settings);
}
}
class ObsidianSettingTab extends PluginSettingTab {
plugin: ObsidianSyncNotionPlugin;
constructor(app: App, plugin: ObsidianSyncNotionPlugin) {
super(app, plugin);
this.plugin = plugin;
}
display(): void {
const {containerEl} = this;
containerEl.empty();
new Setting(containerEl)
.setName("NotionNext version ")
.setDesc("Turn on this option if you are using NotionNext")
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.NNon)
.onChange(async (value) => {
this.plugin.settings.NNon = value;
await this.plugin.saveSettings();
})
);
containerEl.createEl('h2', {text: 'NotionNext Database Settings'})
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(username, 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();
})
);
// General Database Settings
containerEl.createEl('h2', {text: 'General Notion Database Settings'});
new Setting(containerEl)
.setName("Not finished. This function will be available in the next version")
// new Setting(containerEl)
// .setName("Convert tags(optional)")
// .setDesc("Transfer the Obsidian tags to the Notion table. It requires the column with the name 'Tags'")
// .addToggle((toggle) =>
// toggle
// .setValue(this.plugin.settings.allowTags)
// .onChange(async (value) => {
// this.plugin.settings.allowTags = value;
// await this.plugin.saveSettings();
// })
// );
}
}

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

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

@@ -0,0 +1,231 @@
import { App, PluginSettingTab, Setting } from "obsidian";
import { i18nConfig } from "../lang/I18n";
import ObsidianSyncNotionPlugin from "../main";
export interface PluginSettings {
NextButton: boolean;
notionAPINext: string;
databaseIDNext: string;
bannerUrl: string;
notionUser: string;
proxy: string;
GeneralButton: boolean;
CustomTitleButton: boolean;
CustomTitleName: string;
notionAPIGeneral: string;
databaseIDGeneral: string;
CustomButton: boolean;
notionAPICustom: string;
databaseIDCustom: string;
[key: string]: any;
}
export const DEFAULT_SETTINGS: PluginSettings = {
NextButton: true,
notionAPINext: "",
databaseIDNext: "",
bannerUrl: "",
notionUser: "",
proxy: "",
GeneralButton: true,
CustomTitleButton: false,
CustomTitleName: "",
notionAPIGeneral: "",
databaseIDGeneral: "",
CustomButton: false,
notionAPICustom: "",
databaseIDCustom: "",
};
export class ObsidianSettingTab extends PluginSettingTab {
plugin: ObsidianSyncNotionPlugin;
constructor(app: App, plugin: ObsidianSyncNotionPlugin) {
super(app, plugin);
this.plugin = plugin;
}
display(): void {
const { containerEl } = this;
containerEl.empty();
// General Settings
containerEl.createEl('h2', { text: i18nConfig.GeneralSetting });
this.createSettingEl(containerEl, i18nConfig.BannerUrl, i18nConfig.BannerUrlDesc, 'text', i18nConfig.BannerUrlText, this.plugin.settings.bannerUrl, 'bannerUrl')
this.createSettingEl(containerEl, i18nConfig.NotionUser, i18nConfig.NotionUserDesc, 'text', i18nConfig.NotionUserText, this.plugin.settings.notionUser, 'notionUser')
containerEl.createEl('h2', { text: i18nConfig.NotionNextSettingHeader })
new Setting(containerEl)
.setName(i18nConfig.NotionNextButton)
.setDesc(i18nConfig.NotionNextButtonDesc)
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.NextButton)
.onChange(async (value) => {
this.plugin.settings.NextButton = value;
this.updateSettingEl(notionAPINextEl, value)
this.updateSettingEl(databaseIDNextEl, value)
await this.plugin.saveSettings();
await this.plugin.commands.updateCommand();
})
);
const notionAPINextEl = this.createStyleDiv('api-next', this.plugin.settings.NextButton)
this.createSettingEl(notionAPINextEl, i18nConfig.NotionAPI, i18nConfig.NotionAPIDesc, 'password', i18nConfig.NotionAPIText, this.plugin.settings.notionAPINext, 'notionAPINext')
const databaseIDNextEl = this.createStyleDiv('databaseID-next', this.plugin.settings.NextButton)
this.createSettingEl(databaseIDNextEl, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.plugin.settings.databaseIDNext, 'databaseIDNext')
// General Database Settings
containerEl.createEl('h2', { text: i18nConfig.NotionGeneralSettingHeader });
// new Setting(containerEl)
// .setName(i18nConfig.NotYetFinish)
new Setting(containerEl)
.setName(i18nConfig.NotionGeneralButton)
.setDesc(i18nConfig.NotionGeneralButtonDesc)
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.GeneralButton)
.onChange(async (value) => {
this.plugin.settings.GeneralButton = value;
this.updateSettingEl(CustomTitleEl, value)
this.updateSettingEl(notionAPIGeneralEl, value)
this.updateSettingEl(databaseIDGeneralEl, value)
await this.plugin.saveSettings();
await this.plugin.commands.updateCommand();
})
);
const CustomTitleEl = this.createStyleDiv('custom-title', this.plugin.settings.GeneralButton);
new Setting(CustomTitleEl)
.setName(i18nConfig.NotionCustomTitle)
.setDesc(i18nConfig.NotionCustomTitleDesc)
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.CustomTitleButton)
.onChange(async (value) => {
this.plugin.settings.CustomTitleButton = value;
this.updateSettingEl(CustomNameEl, value)
await this.plugin.saveSettings();
await this.plugin.commands.updateCommand();
})
);
const CustomNameEl = this.createStyleDiv('custom-name', this.plugin.settings.CustomTitleButton);
this.createSettingEl(CustomNameEl, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.plugin.settings.CustomTitleName, 'CustomTitleName')
// new Setting(containerEl)
// .setName("Convert tags(optional)")
// .setDesc("Transfer the Obsidian tags to the Notion table. It requires the column with the name 'Tags'")
// .addToggle((toggle) =>
// toggle
// .setValue(this.plugin.settings.allowTags)
// .onChange(async (value) => {
// this.plugin.settings.allowTags = value;
// await this.plugin.saveSettings();
// })
// );
const notionAPIGeneralEl = this.createStyleDiv('api-general', this.plugin.settings.GeneralButton);
this.createSettingEl(notionAPIGeneralEl, i18nConfig.NotionAPI, i18nConfig.NotionAPIDesc, 'password', i18nConfig.NotionAPIText, this.plugin.settings.notionAPIGeneral, 'notionAPIGeneral')
const databaseIDGeneralEl = this.createStyleDiv('databaseID-general', this.plugin.settings.GeneralButton);
this.createSettingEl(databaseIDGeneralEl, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.plugin.settings.databaseIDGeneral, 'databaseIDGeneral')
// Custom Database Settings
// containerEl.createEl('h2', {text: i18nConfig.NotionCustomSettingHeader});
//
// new Setting(containerEl)
// .setName(i18nConfig.NotionCustomButton)
// .setDesc(i18nConfig.NotionCustomButtonDesc)
// .addToggle((toggle) =>
// toggle
// .setValue(this.plugin.settings.CustomButton)
// .onChange(async (value) => {
// this.plugin.settings.CustomButton = value;
// await this.plugin.saveSettings();
// })
// );
}
// create a function to create a div with a style for pop over elements
private createStyleDiv(className: string, commandValue: boolean = false) {
return this.containerEl.createDiv(className, (div) => {
this.updateSettingEl(div, commandValue);
});
}
// update the setting display style in the setting tab
private updateSettingEl(element: HTMLElement, commandValue: boolean) {
element.style.borderTop = commandValue ? "1px solid var(--background-modifier-border)" : "none";
element.style.paddingTop = commandValue ? "0.75em" : "0";
element.style.display = commandValue ? "block" : "none";
element.style.alignItems = "center";
}
// function to add one setting element in the setting tab.
private createSettingEl(containerEl: HTMLElement, name: string, desc: string, type: string, placeholder: string, holderValue: any, settingsKey: string) {
if (type === 'password') {
return new Setting(containerEl)
.setName(name)
.setDesc(desc)
.addText((text) => {
text.inputEl.type = type;
return text
.setPlaceholder(placeholder)
.setValue(holderValue)
.onChange(async (value) => {
this.plugin.settings[settingsKey] = value; // Update the plugin settings directly
await this.plugin.saveSettings();
})
});
} else if (type === 'toggle') {
return new Setting(containerEl)
.setName(name)
.setDesc(desc)
.addToggle((toggle) =>
toggle
.setValue(holderValue)
.onChange(async (value) => {
this.plugin.settings[settingsKey] = value; // Update the plugin settings directly
await this.plugin.saveSettings();
await this.plugin.commands.updateCommand();
})
);
} else if (type === 'text') {
return new Setting(containerEl)
.setName(name)
.setDesc(desc)
.addText((text) =>
text
.setPlaceholder(placeholder)
.setValue(holderValue)
.onChange(async (value) => {
this.plugin.settings[settingsKey] = value; // Update the plugin settings directly
await this.plugin.saveSettings();
await this.plugin.commands.updateCommand();
})
);
}
}
}

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

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

View File

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

View File

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

View File

@@ -0,0 +1,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: {
[this.plugin.settings.CustomTitleButton ? this.plugin.settings.CustomTitleName : 'title']: {
title: [
{
text: {
content: title
},
},
],
},
tags: {
multi_select: tags && true ? tags.map(tag => {
return { "name": tag }
}) : [],
},
},
children: childArr,
}
if (cover) {
bodyString.cover = {
type: "external",
external: {
url: cover
}
}
}
if (!bodyString.cover && this.plugin.settings.bannerUrl) {
bodyString.cover = {
type: "external",
external: {
url: this.plugin.settings.bannerUrl
}
}
}
try {
return await requestUrl({
url: `https://api.notion.com/v1/pages`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
// 'User-Agent': 'obsidian.md',
'Authorization': 'Bearer ' + this.plugin.settings.notionAPIGeneral,
'Notion-Version': '2022-06-28',
},
body: JSON.stringify(bodyString),
})
} catch (error) {
new Notice(`network error ${error}`)
}
}
async syncMarkdownToNotionGeneral(
title: string,
cover: string,
tags: string[],
markdown: string,
nowFile: TFile,
app: App,
): Promise<any> {
let res: any
const yamlContent: any = yamlFrontMatter.loadFront(markdown);
const __content = yamlContent.__content
const file2Block = markdownToBlocks(__content);
const frontmasster = app.metadataCache.getFileCache(nowFile)?.frontmatter
const notionID = frontmasster ? frontmasster.notionID : null
if (notionID) {
res = await this.updatePage(
notionID,
title,
cover,
tags,
file2Block
);
} else {
res = await this.createPage(
title,
cover,
tags,
file2Block
);
}
if (res.status === 200) {
await updateYamlInfo(markdown, nowFile, res, app, this.plugin)
} else {
new Notice(`${res.text}`)
}
return res
}
}

View File

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

View File

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

View File

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

View File

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

275
yarn.lock
View File

@@ -120,9 +120,9 @@
eslint-visitor-keys "^3.3.0"
"@eslint-community/regexpp@^4.5.1":
version "4.8.0"
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.8.0.tgz#11195513186f68d42fbf449f9a7136b2c0c92005"
integrity sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==
version "4.10.0"
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63"
integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
@@ -153,7 +153,7 @@
"@types/node-fetch" "^2.5.10"
node-fetch "^2.6.1"
"@tryfabric/martian@^1.2.0":
"@tryfabric/martian@^1.2.4":
version "1.2.4"
resolved "https://registry.yarnpkg.com/@tryfabric/martian/-/martian-1.2.4.tgz#3fdfe7129f1c28bccddc34854cf353b0f37c0c02"
integrity sha512-g7SP7beaxrjxLnW//vskra07a1jsJowqp07KMouxh4gCwaF+ItHbRZN8O+1dhJivBi3VdasT71BPyk+8wzEreQ==
@@ -172,111 +172,113 @@
"@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==
version "4.1.12"
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917"
integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==
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==
version "1.0.5"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
"@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==
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.3.tgz#7f75e6b43bc3f90316046a287d9ad3888309f7e1"
integrity sha512-2fYGlaDy/qyLlhidX42wAH0KBi2TCjKMH8CHmBXgRlJ3Y+OXTiqsPQ6IWarZKwF1JoUcAJdPogv1d4b0COTpmQ==
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"
integrity sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==
version "4.0.9"
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.9.tgz#cd82382c4f902fed9691a2ed79ec68c5898af4c2"
integrity sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==
"@types/json-schema@^7.0.12":
version "7.0.12"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb"
integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==
version "7.0.15"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
"@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==
version "0.16.6"
resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.16.6.tgz#6dd82f78a1a1d2eceeff6bb97ba98d7c062454cb"
integrity sha512-rZYO1HInM99rAFYNwGqbYPxHZHxu2IwZYKj4bJ4oh6edVrm1UId8mmbHIZLBtG253qU6y3piag0XYe/joNnwzQ==
"@types/mdast@^3.0.0":
version "3.0.12"
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.12.tgz#beeb511b977c875a5b0cc92eab6fcac2f0895514"
integrity sha512-DT+iNIRNX884cx0/Q1ja7NyUPpZuv0KPyL5rGNxm1WC1OtHstl7n4Jb7nk+xacNShQMbczJjt8uFzznpp6kYBg==
version "3.0.15"
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5"
integrity sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==
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==
version "4.0.3"
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.3.tgz#1e011ff013566e919a4232d1701ad30d70cab333"
integrity sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==
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==
version "0.7.34"
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433"
integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==
"@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"
integrity sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==
version "2.6.9"
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.9.tgz#15f529d247f1ede1824f7e7acdaa192d5f28071e"
integrity sha512-bQVlnMLFJ2d35DkPNjEPmd9ueO/rh5EiaZt2bhqiSarPjZIuIV6bPQVqcrEyvNo+AfTrRGVazle1tl597w3gfA==
dependencies:
"@types/node" "*"
form-data "^3.0.0"
form-data "^4.0.0"
"@types/node@*", "@types/node@^20.5.7":
version "20.5.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.7.tgz#4b8ecac87fbefbc92f431d09c30e176fc0a7c377"
integrity sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==
version "20.9.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.9.0.tgz#bfcdc230583aeb891cf51e73cfdaacdd8deae298"
integrity sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==
dependencies:
undici-types "~5.26.4"
"@types/semver@^7.5.0":
version "7.5.1"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.1.tgz#0480eeb7221eb9bc398ad7432c9d7e14b1a5a367"
integrity sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==
version "7.5.5"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.5.tgz#deed5ab7019756c9c90ea86139106b0346223f35"
integrity sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==
"@types/tern@*":
version "0.23.4"
resolved "https://registry.yarnpkg.com/@types/tern/-/tern-0.23.4.tgz#03926eb13dbeaf3ae0d390caf706b2643a0127fb"
integrity sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==
version "0.23.7"
resolved "https://registry.yarnpkg.com/@types/tern/-/tern-0.23.7.tgz#f3c27fb7d6db5e86d7f069e7d5124bfa677a5b2d"
integrity sha512-0YS9XCZ0LAhlP11HV9SqncUYyz9Ggsgc7Om/AmchKvoeFyj0qPaJmX6rJ93mJVExizWDzUMb49gAtVpI1uHd8Q==
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==
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.2.tgz#6dd61e43ef60b34086287f83683a5c1b2dc53d20"
integrity sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==
"@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"
integrity sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==
version "2.0.10"
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc"
integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==
"@types/yaml-front-matter@^4.1.0":
version "4.1.0"
resolved "https://registry.yarnpkg.com/@types/yaml-front-matter/-/yaml-front-matter-4.1.0.tgz#324404e069353972286bf60117f8b404b7cb0220"
integrity sha512-d4YGe2onl1T4VA6QhT4agdxaStOBe/ig9RAFAT1OltytvO2z9Ro69DiwHD2FUwewcjeD9PWEfUeZhw7E9hApcQ==
"@types/yaml-front-matter@^4.1.3":
version "4.1.3"
resolved "https://registry.yarnpkg.com/@types/yaml-front-matter/-/yaml-front-matter-4.1.3.tgz#76478882b5ee3e892dd2ee2af86a6dd8c089ce4d"
integrity sha512-XDsnZdIZ8QGRFzfRTCSxjbm0NGQQfFPxk2zqy0DB4SH2TXJVptzdY+IgDNM1K2ZIjFvFaHo2l5wJd71JzMeI9A==
dependencies:
"@types/js-yaml" "*"
"@types/node" "*"
"@typescript-eslint/eslint-plugin@^6.5.0":
version "6.5.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.5.0.tgz#5cee33edf0d45d5ec773e3b3111206b098ac8599"
integrity sha512-2pktILyjvMaScU6iK3925uvGU87E+N9rh372uGZgiMYwafaw9SXq86U04XPq3UH6tzRvNgBsub6x2DacHc33lw==
"@typescript-eslint/eslint-plugin@^6.11.0":
version "6.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.11.0.tgz#52aae65174ff526576351f9ccd41cea01001463f"
integrity sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==
dependencies:
"@eslint-community/regexpp" "^4.5.1"
"@typescript-eslint/scope-manager" "6.5.0"
"@typescript-eslint/type-utils" "6.5.0"
"@typescript-eslint/utils" "6.5.0"
"@typescript-eslint/visitor-keys" "6.5.0"
"@typescript-eslint/scope-manager" "6.11.0"
"@typescript-eslint/type-utils" "6.11.0"
"@typescript-eslint/utils" "6.11.0"
"@typescript-eslint/visitor-keys" "6.11.0"
debug "^4.3.4"
graphemer "^1.4.0"
ignore "^5.2.4"
@@ -284,72 +286,72 @@
semver "^7.5.4"
ts-api-utils "^1.0.1"
"@typescript-eslint/parser@^6.5.0":
version "6.5.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.5.0.tgz#3d6ed231c5e307c5f5f4a0d86893ec01e92b8c77"
integrity sha512-LMAVtR5GN8nY0G0BadkG0XIe4AcNMeyEy3DyhKGAh9k4pLSMBO7rF29JvDBpZGCmp5Pgz5RLHP6eCpSYZJQDuQ==
"@typescript-eslint/parser@^6.11.0":
version "6.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.11.0.tgz#9640d9595d905f3be4f278bf515130e6129b202e"
integrity sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==
dependencies:
"@typescript-eslint/scope-manager" "6.5.0"
"@typescript-eslint/types" "6.5.0"
"@typescript-eslint/typescript-estree" "6.5.0"
"@typescript-eslint/visitor-keys" "6.5.0"
"@typescript-eslint/scope-manager" "6.11.0"
"@typescript-eslint/types" "6.11.0"
"@typescript-eslint/typescript-estree" "6.11.0"
"@typescript-eslint/visitor-keys" "6.11.0"
debug "^4.3.4"
"@typescript-eslint/scope-manager@6.5.0":
version "6.5.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.5.0.tgz#f2cb20895aaad41b3ad27cc3a338ce8598f261c5"
integrity sha512-A8hZ7OlxURricpycp5kdPTH3XnjG85UpJS6Fn4VzeoH4T388gQJ/PGP4ole5NfKt4WDVhmLaQ/dBLNDC4Xl/Kw==
"@typescript-eslint/scope-manager@6.11.0":
version "6.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz#621f603537c89f4d105733d949aa4d55eee5cea8"
integrity sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==
dependencies:
"@typescript-eslint/types" "6.5.0"
"@typescript-eslint/visitor-keys" "6.5.0"
"@typescript-eslint/types" "6.11.0"
"@typescript-eslint/visitor-keys" "6.11.0"
"@typescript-eslint/type-utils@6.5.0":
version "6.5.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.5.0.tgz#6d246c93739282bc0d2e623f28d0dec6cfcc38d7"
integrity sha512-f7OcZOkRivtujIBQ4yrJNIuwyCQO1OjocVqntl9dgSIZAdKqicj3xFDqDOzHDlGCZX990LqhLQXWRnQvsapq8A==
"@typescript-eslint/type-utils@6.11.0":
version "6.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.11.0.tgz#d0b8b1ab6c26b974dbf91de1ebc5b11fea24e0d1"
integrity sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==
dependencies:
"@typescript-eslint/typescript-estree" "6.5.0"
"@typescript-eslint/utils" "6.5.0"
"@typescript-eslint/typescript-estree" "6.11.0"
"@typescript-eslint/utils" "6.11.0"
debug "^4.3.4"
ts-api-utils "^1.0.1"
"@typescript-eslint/types@6.5.0":
version "6.5.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.5.0.tgz#f4e55cfd99ac5346ea772770bf212a3e689a8f04"
integrity sha512-eqLLOEF5/lU8jW3Bw+8auf4lZSbbljHR2saKnYqON12G/WsJrGeeDHWuQePoEf9ro22+JkbPfWQwKEC5WwLQ3w==
"@typescript-eslint/types@6.11.0":
version "6.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.11.0.tgz#8ad3aa000cbf4bdc4dcceed96e9b577f15e0bf53"
integrity sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==
"@typescript-eslint/typescript-estree@6.5.0":
version "6.5.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.5.0.tgz#1cef6bc822585e9ef89d88834bc902d911d747ed"
integrity sha512-q0rGwSe9e5Kk/XzliB9h2LBc9tmXX25G0833r7kffbl5437FPWb2tbpIV9wAATebC/018pGa9fwPDuvGN+LxWQ==
"@typescript-eslint/typescript-estree@6.11.0":
version "6.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz#7b52c12a623bf7f8ec7f8a79901b9f98eb5c7990"
integrity sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==
dependencies:
"@typescript-eslint/types" "6.5.0"
"@typescript-eslint/visitor-keys" "6.5.0"
"@typescript-eslint/types" "6.11.0"
"@typescript-eslint/visitor-keys" "6.11.0"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.5.4"
ts-api-utils "^1.0.1"
"@typescript-eslint/utils@6.5.0":
version "6.5.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.5.0.tgz#6668bee4f7f24978b11df8a2ea42d56eebc4662c"
integrity sha512-9nqtjkNykFzeVtt9Pj6lyR9WEdd8npPhhIPM992FWVkZuS6tmxHfGVnlUcjpUP2hv8r4w35nT33mlxd+Be1ACQ==
"@typescript-eslint/utils@6.11.0":
version "6.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.11.0.tgz#11374f59ef4cea50857b1303477c08aafa2ca604"
integrity sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==
dependencies:
"@eslint-community/eslint-utils" "^4.4.0"
"@types/json-schema" "^7.0.12"
"@types/semver" "^7.5.0"
"@typescript-eslint/scope-manager" "6.5.0"
"@typescript-eslint/types" "6.5.0"
"@typescript-eslint/typescript-estree" "6.5.0"
"@typescript-eslint/scope-manager" "6.11.0"
"@typescript-eslint/types" "6.11.0"
"@typescript-eslint/typescript-estree" "6.11.0"
semver "^7.5.4"
"@typescript-eslint/visitor-keys@6.5.0":
version "6.5.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.5.0.tgz#1a6f474a0170a447b76f0699ce6700110fd11436"
integrity sha512-yCB/2wkbv3hPsh02ZS8dFQnij9VVQXJMN/gbQsaaY+zxALkZnxa/wagvLEFsAWMPv7d7lxQmNsIzGU1w/T/WyA==
"@typescript-eslint/visitor-keys@6.11.0":
version "6.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz#d991538788923f92ec40d44389e7075b359f3458"
integrity sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==
dependencies:
"@typescript-eslint/types" "6.5.0"
"@typescript-eslint/types" "6.11.0"
eslint-visitor-keys "^3.4.1"
agent-base@^7.0.2:
@@ -532,9 +534,9 @@ extend@^3.0.0:
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
fast-glob@^3.2.9:
version "3.3.1"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4"
integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==
version "3.3.2"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
dependencies:
"@nodelib/fs.stat" "^2.0.2"
"@nodelib/fs.walk" "^1.2.3"
@@ -556,10 +558,10 @@ fill-range@^7.0.1:
dependencies:
to-regex-range "^5.0.1"
form-data@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==
form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
@@ -589,18 +591,18 @@ graphemer@^1.4.0:
resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
https-proxy-agent@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.1.tgz#0277e28f13a07d45c663633841e20a40aaafe0ab"
integrity sha512-Eun8zV0kcYS1g19r78osiQLEFIRspRUDd9tIfBCTBPBeMieF/EsJNL8VI3xOIdYRDEkjQnqOYPsZ2DsWsVsFwQ==
https-proxy-agent@^7.0.2:
version "7.0.2"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b"
integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==
dependencies:
agent-base "^7.0.2"
debug "4"
ignore@^5.2.0, ignore@^5.2.4:
version "5.2.4"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
version "5.3.0"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78"
integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==
is-alphabetical@^1.0.0:
version "1.0.4"
@@ -1024,9 +1026,9 @@ micromark-util-combine-extensions@^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==
version "2.0.1"
resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz#2698bbb38f2a9ba6310e359f99fcb2b35a0d2bd5"
integrity sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==
dependencies:
micromark-util-symbol "^2.0.0"
@@ -1167,9 +1169,9 @@ node-fetch@^2.6.1:
whatwg-url "^5.0.0"
obsidian@latest:
version "1.4.4"
resolved "https://registry.yarnpkg.com/obsidian/-/obsidian-1.4.4.tgz#b987be40f6e33843b773e4248931139c3d55e1db"
integrity sha512-q2V5GNT/M40uYOENdVw5kovPSoaO6vppiiyBCkIqWgKp4oN654jA/GQ0OaNBA7p5NdfS245QCeRgCFQ42wOZiw==
version "1.4.11"
resolved "https://registry.yarnpkg.com/obsidian/-/obsidian-1.4.11.tgz#5cba594c83a74ebad58b630c610265018abdadaa"
integrity sha512-BCVYTvaXxElJMl6MMbDdY/CGK+aq18SdtDY/7vH8v6BxCBQ6KF4kKxL0vG9UZ0o5qh139KpUoJHNm+6O5dllKA==
dependencies:
"@types/codemirror" "5.60.8"
moment "2.29.4"
@@ -1296,9 +1298,9 @@ trough@^2.0.0:
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"
integrity sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==
version "1.0.3"
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331"
integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==
tslib@2.6.2:
version "2.6.2"
@@ -1310,10 +1312,15 @@ typescript@5.2.2:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78"
integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==
undici-types@~5.26.4:
version "5.26.5"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
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==
version "11.0.4"
resolved "https://registry.yarnpkg.com/unified/-/unified-11.0.4.tgz#f4be0ac0fe4c88cb873687c07c64c49ed5969015"
integrity sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==
dependencies:
"@types/unist" "^3.0.0"
bail "^2.0.0"
@@ -1455,10 +1462,10 @@ yaml-front-matter@^4.1.1:
commander "^6.2.0"
js-yaml "^3.14.1"
yaml@^2.2.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.2.tgz#f522db4313c671a0ca963a75670f1c12ea909144"
integrity sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==
yaml@^2.3.4:
version "2.3.4"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2"
integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==
zwitch@^1.0.0:
version "1.0.5"