├── .gitignore ├── src ├── styles.css ├── packages │ └── obsidian-components │ │ ├── Button.tsx │ │ ├── Logo.tsx │ │ └── Toggle.tsx ├── types.d.ts ├── NotionSyncSettingsTab.tsx ├── components │ └── App.tsx ├── main.ts ├── functions │ └── parser.ts └── api.tsx ├── CHANGELOG.md ├── notion-sync.code-workspace ├── postcss.config.js ├── manifest.json ├── dist ├── manifest.json └── styles.css ├── tsconfig.json ├── package.json ├── LICENSE ├── esbuild.config.mjs ├── tailwind.config.js ├── README.md └── pnpm-lock.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | */.DS_Store 4 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | @tailwind utilities; 2 | @tailwind components; 3 | @tailwind base; 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Planned 2 | - [ ] sync text 3 | - [ ] two-way sync 4 | 5 | # 1.5.0 (Upcoming) -------------------------------------------------------------------------------- /notion-sync.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": {} 8 | } -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "notion-sync", 3 | "name": "Notion Sync", 4 | "version": "1.0.0", 5 | "minAppVersion": "0.15.0", 6 | "description": "Two-way sync file properties between Notion databases and Obsidian folders.", 7 | "author": "Joshua Tazman Reinier", 8 | "authorUrl": "https://joshuareinier.com", 9 | "fundingUrl": "https://bmc.link/joshuatreinier", 10 | "isDesktopOnly": false 11 | } 12 | -------------------------------------------------------------------------------- /dist/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "notion-sync", 3 | "name": "Notion Sync", 4 | "version": "1.0.0", 5 | "minAppVersion": "0.15.0", 6 | "description": "Two-way sync file properties between Notion databases and Obsidian folders.", 7 | "author": "Joshua Tazman Reinier", 8 | "authorUrl": "https://joshuareinier.com", 9 | "fundingUrl": "https://bmc.link/joshuatreinier", 10 | "isDesktopOnly": false 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "inlineSourceMap": true, 5 | "inlineSources": true, 6 | "module": "ESNext", 7 | "target": "ES6", 8 | "allowJs": true, 9 | "noImplicitAny": false, 10 | "moduleResolution": "node", 11 | "importHelpers": true, 12 | "isolatedModules": true, 13 | "strictNullChecks": true, 14 | "lib": ["DOM", "ES5", "ES6", "ES7"], 15 | "jsx": "react-jsx", 16 | "allowSyntheticDefaultImports": true, 17 | "resolveJsonModule": true, 18 | "jsxImportSource": "react" 19 | }, 20 | "include": ["src"] 21 | } 22 | -------------------------------------------------------------------------------- /src/packages/obsidian-components/Button.tsx: -------------------------------------------------------------------------------- 1 | import { forwardRef } from 'react' 2 | import Logo from './Logo' 3 | import React from 'react' 4 | 5 | const Button = forwardRef< 6 | HTMLDivElement, 7 | { 8 | className?: string 9 | src?: string 10 | } & React.ButtonHTMLAttributes 11 | >(({ className, src, children, ...rest }, ref) => { 12 | return ( 13 |
17 | {src ? : children ?? null} 18 |
19 | ) 20 | }) 21 | 22 | export default Button 23 | -------------------------------------------------------------------------------- /src/packages/obsidian-components/Logo.tsx: -------------------------------------------------------------------------------- 1 | import { setIcon } from 'obsidian' 2 | import { useLayoutEffect, useRef } from 'react' 3 | import invariant from 'tiny-invariant' 4 | 5 | export default function Logo({ src, className = '', title = '' }) { 6 | const frame = useRef(null) 7 | useLayoutEffect(() => { 8 | invariant(frame.current) 9 | setIcon(frame.current, src) 10 | }, [src]) 11 | 12 | return ( 13 |
18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/types.d.ts: -------------------------------------------------------------------------------- 1 | import { PageObjectResponse } from '@notionhq/client/build/src/api-endpoints' 2 | import Api from './api' 3 | import { TFile } from 'obsidian' 4 | 5 | declare global { 6 | type NotionSyncSettings = { 7 | databases: Record 8 | apiKey: string 9 | lastSync: number 10 | lastConflicts: string[] 11 | } 12 | 13 | type NotionFile = { 14 | path: string 15 | } 16 | 17 | type NotionProperty = PageObjectResponse['properties'][string] 18 | } 19 | 20 | declare module 'obsidian' { 21 | interface Vault { 22 | getAbstractFileByPathInsensitive: (path: string) => TFile | null 23 | } 24 | 25 | interface App { 26 | isMobile: boolean 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "obsidian-notion-sync", 3 | "version": "1.0.0", 4 | "description": "Notion Sync", 5 | "main": "main.js", 6 | "keywords": [], 7 | "author": "Joshua Reinier", 8 | "license": "MIT", 9 | "scripts": { 10 | "dev": "node esbuild.config.mjs", 11 | "build": "tsc -p \".\" -noEmit -skipLibCheck && npm run copy-manifest && MODE=production node esbuild.config.mjs", 12 | "copy-manifest": "cp manifest.json ./dist", 13 | "check": "tsc -noEmit -skipLibCheck" 14 | }, 15 | "dependencies": { 16 | "@notionhq/client": "^2.2.15", 17 | "@types/lodash": "^4.17.9", 18 | "axios": "^1.7.7", 19 | "esbuild": "^0.24.0", 20 | "esbuild-copy-static-files": "^0.1.0", 21 | "esbuild-postcss": "^0.0.4", 22 | "lodash": "^4.17.21", 23 | "luxon": "^3.5.0", 24 | "obsidian": "^1.7.2", 25 | "obsidian-dataview": "^0.5.67", 26 | "react": "^18.3.1", 27 | "react-dom": "^18.3.1", 28 | "tailwindcss": "^3.4.12", 29 | "tiny-invariant": "^1.3.3" 30 | }, 31 | "devDependencies": { 32 | "autoprefixer": "^10.4.20", 33 | "tslib": "^2.7.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/packages/obsidian-components/Toggle.tsx: -------------------------------------------------------------------------------- 1 | import { Setting, ToggleComponent } from 'obsidian' 2 | import { useEffect, useRef } from 'react' 3 | import invariant from 'tiny-invariant' 4 | 5 | export default function Toggle({ 6 | callback, 7 | title, 8 | value, 9 | }: { 10 | callback: (state: boolean) => void 11 | title: string 12 | value: boolean 13 | }) { 14 | const frame = useRef(null) 15 | const thisToggle = useRef(null) 16 | const thisSetting = useRef(null) 17 | 18 | useEffect(() => { 19 | invariant(frame.current) 20 | if (!thisSetting.current) { 21 | thisSetting.current = new Setting(frame.current).setName(title) 22 | } 23 | thisSetting.current.addToggle((toggle) => { 24 | thisToggle.current = toggle 25 | toggle.setValue(value) 26 | toggle.onChange((state) => callback(state)) 27 | }) 28 | return () => { 29 | thisSetting.current?.clear() 30 | } 31 | }, []) 32 | 33 | useEffect(() => { 34 | thisToggle.current?.setValue(value) 35 | }, [value]) 36 | 37 | return
38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Joshua Tazman Reinier 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/NotionSyncSettingsTab.tsx: -------------------------------------------------------------------------------- 1 | import { Notice, PluginSettingTab, Setting, App as ObsidianApp } from 'obsidian' 2 | import NotionSync from './main' 3 | import { Root, createRoot } from 'react-dom/client' 4 | import App from './components/App' 5 | 6 | export default class NotionSyncSettingsTab extends PluginSettingTab { 7 | plugin: NotionSync 8 | root: Root 9 | 10 | constructor(app: ObsidianApp, plugin: NotionSync) { 11 | super(app, plugin) 12 | this.plugin = plugin 13 | } 14 | 15 | async display() { 16 | let { containerEl } = this 17 | containerEl.empty() 18 | 19 | new Setting(containerEl) 20 | .setName('Notion Integration Secret') 21 | .setDesc( 22 | 'The integration secret to your Notion database (visit notion.so/my-integrations to generate a new key).' 23 | ) 24 | .addText(text => { 25 | text.setValue(this.plugin.settings.apiKey) 26 | text.onChange(value => { 27 | this.plugin.setSetting({ apiKey: value }) 28 | this.renderRoot() 29 | }) 30 | }) 31 | 32 | new Setting(containerEl) 33 | .setName('Synced Databases') 34 | .setDesc('Add/remove databases to sync to Obsidian.') 35 | 36 | const names = containerEl.appendChild(createDiv()) 37 | 38 | this.root = createRoot(names) 39 | await this.renderRoot() 40 | } 41 | 42 | async renderRoot() { 43 | this.root.render() 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /esbuild.config.mjs: -------------------------------------------------------------------------------- 1 | import esbuild from 'esbuild' 2 | import process from 'process' 3 | import esbuildCopyStaticFiles from 'esbuild-copy-static-files' 4 | import postcss from 'esbuild-postcss' 5 | 6 | const banner = `/* 7 | THIS IS A GENERATED/BUNDLED FILE BY ESBUILD 8 | if you want to view the source, please visit the github repository of this plugin 9 | */ 10 | ` 11 | 12 | const DIR = 'notion-sync' 13 | if (!DIR) throw new Error('plugin id missing') 14 | const VAULT = 'Joshua' 15 | 16 | const MODE = process.env.MODE 17 | 18 | let entryPoints = [`src/main.ts`] 19 | entryPoints.push(`src/styles.css`) 20 | 21 | const plugins = [ 22 | postcss(), 23 | esbuildCopyStaticFiles({ 24 | src: `./dist`, 25 | dest: `/Users/jreinier/${VAULT}/.obsidian/plugins/${DIR}`, 26 | dereference: true, 27 | errorOnExist: false, 28 | preserveTimestamps: true 29 | }) 30 | ] 31 | 32 | const context = await esbuild.context({ 33 | banner: { 34 | js: banner 35 | }, 36 | entryPoints, 37 | bundle: true, 38 | external: [ 39 | 'obsidian', 40 | 'electron', 41 | '@codemirror/autocomplete', 42 | '@codemirror/collab', 43 | '@codemirror/commands', 44 | '@codemirror/language', 45 | '@codemirror/lint', 46 | '@codemirror/search', 47 | '@codemirror/state', 48 | '@codemirror/view', 49 | '@lezer/common', 50 | '@lezer/highlight', 51 | '@lezer/lr' 52 | ], 53 | format: 'cjs', 54 | target: 'es2018', 55 | logLevel: 'info', 56 | sourcemap: MODE === 'production' ? false : 'inline', 57 | treeShaking: true, 58 | outdir: `dist`, 59 | 60 | loader: { 61 | '.mp3': 'dataurl', 62 | '.svg': 'text', 63 | '.png': 'dataurl' 64 | }, 65 | plugins 66 | }) 67 | 68 | if (MODE === 'production') { 69 | await context.rebuild() 70 | process.exit(0) 71 | } else { 72 | await context.watch() 73 | } 74 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | const plugin = require('tailwindcss/plugin') 2 | const pluginDir = process.env.DIR || '.' 3 | 4 | /** @type {import('tailwindcss').Config} */ 5 | module.exports = { 6 | content: [`src/${pluginDir}/**/*.{tsx,css,ts}`], 7 | plugins: [ 8 | plugin(function ({ addVariant }) { 9 | addVariant('child', '& > *') 10 | addVariant('ancestor', '& *') 11 | }), 12 | ], 13 | corePlugins: { 14 | preflight: false, 15 | }, 16 | important: pluginDir.includes('time-ruler') 17 | ? '#time-ruler' 18 | : pluginDir.includes('link-tree') 19 | ? '#link-tree' 20 | : undefined, 21 | theme: { 22 | extend: { 23 | minHeight: { 24 | line: 'var(--font-text-size)', 25 | }, 26 | lineHeight: { 27 | line: 'var(--line-height-normal)', 28 | }, 29 | height: { 30 | line: 'calc(var(--line-height-normal) * 1em)', 31 | }, 32 | fontSize: { 33 | base: 'var(--font-text-size)', 34 | }, 35 | fontFamily: { 36 | menu: 'var(--font-interface)', 37 | serif: 'var(--font-text)', 38 | sans: 'var(--font-text)', 39 | }, 40 | borderRadius: { 41 | icon: 'var(--clickable-icon-radius)', 42 | checkbox: 'var(--checkbox-radius)', 43 | }, 44 | colors: { 45 | primary: 'var(--background-primary)', 46 | 'primary-alt': 'var(--background-primary-alt)', 47 | secondary: 'var(--background-secondary)', 48 | 'secondary-alt': 'var(--background-secondary-alt)', 49 | error: 'var(--background-modifier-error)', 50 | border: 'var(--background-modifier-border)', 51 | hover: 'var(--background-modifier-hover)', 52 | selection: 'var(--text-selection)', 53 | normal: 'var(--text-normal)', 54 | muted: 'var(--text-muted)', 55 | faint: 'var(--text-faint)', 56 | accent: 'var(--text-accent)', 57 | }, 58 | screens: { 59 | mobile: { raw: '(hover: none)' }, 60 | mouse: { raw: '(hover: hover)' }, 61 | }, 62 | }, 63 | }, 64 | } 65 | -------------------------------------------------------------------------------- /src/components/App.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react' 2 | import Api from '../api' 3 | import { parseTitle } from '../functions/parser' 4 | import { Setting, ToggleComponent } from 'obsidian' 5 | import _ from 'lodash' 6 | 7 | export default function App({ obsidianApi }: { obsidianApi: Api }) { 8 | const apiKey = obsidianApi.settings.apiKey 9 | const [databases, setDatabases] = useState( 10 | obsidianApi.databases 11 | ) 12 | 13 | useEffect(() => { 14 | obsidianApi.load().then(() => { 15 | setDatabases(obsidianApi.databases) 16 | }) 17 | }, []) 18 | 19 | if (!apiKey) 20 | return ( 21 |
22 |

Please set an API key before adding files.

23 |

Steps:

24 |
    25 |
  1. 26 | Go to{' '} 27 | 28 | the Notion integrations website 29 | {' '} 30 | and click "Create New Integration." 31 |
  2. 32 |
  3. Name it "Notion Sync." The logo is not necessary.
  4. 33 |
  5. 34 | Copy the "Internal Integration Secret" and paste it into the "Api 35 | Key" setting above. 36 |
  6. 37 |
38 |
39 | ) 40 | 41 | return ( 42 |
43 | {_.sortBy(Object.values(databases), database => parseTitle(database)).map( 44 | database => { 45 | const title = parseTitle(database) 46 | 47 | return ( 48 |
49 |
{title}
50 | 59 | obsidianApi.updateFile(database.id, { 60 | path: ev.target.value 61 | }) 62 | }> 63 |
64 | ) 65 | } 66 | )} 67 |
68 | ) 69 | } 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Notion Sync 2 | Notion Sync allows you to easily two-way sync an Obsidian folder with a Notion database, keeping file properties in sync. 3 | 4 | Notion is a great database platform, and nothing in Obsidian can fully replace its ease of use. Notion Sync exists to seamlessly link Obsidian with Notion, enabling Notion's searching, filtering, and interface to be used with Obsidian file properties. 5 | 6 | **NOTE:** This plugin is only for syncing **properties** between Obsidian and Notion. File content will not be changed. 7 | 8 | # Requirements 9 | This plugin requires the [Dataview](obsidian://show-plugin?id=dataview) plugin to function. Thanks Dataview! 10 | 11 | # Link a database 12 | 1. Create an access token for Notion Sync by visiting [My Integrations](https://www.notion.so/my-integrations) and selecting "New Integration." You can name it anything — we suggest "Notion Sync." An integration secret will be generated, which gives permission for Notion Sync to access databases you add. 13 | 2. In the next page under "Internal Integration Secret," click "Show," then "Copy." 14 | 3. Paste the integration secret into the Notion Sync "Notion Integration Secret" setting. 15 | 4. Back in Notion, click on a database's options (the three dots icon in the top-right) and go to "Add connections" under the "Connections" section. Search for "Notion Sync" (or whatever you named the integration) and to connect it to the database. 16 | 5. In Obsidian, reopen the Settings window and the database's name will appear in Notion Sync settings. Select a path to an empty folder you would like to sync to. Once selected, Notion Sync will create a folder there if it doesn't exist already. 17 | 6. In the Obsidian Command Palette, use "Notion Sync: Download all files" to download the database to Obsidian. 18 | 19 | # Sync a database 20 | - Use "Notion Sync: Sync" to sync any changes since the last time the command was called. The most recent version (Obsidian or Notion) will be synced. If any files have been modified in **both** Obsidian and Notion since the last sync, you will have the option to choose to upload or download them. 21 | - Use "Notion Sync: Download/Upload all files" to perform a clean upload/download of every file in the databases you've added. 22 | - Use "Notion Sync: Download/Upload this file" to sync a single file. 23 | 24 | # Internet Requests 25 | The sync uses the following API routes in Notion: 26 | - `GET`, `POST`, and `PATCH` to [https://api.notion.com/v1/pages](https://developers.notion.com/reference/post-page) to get, set, and create pages. 27 | - `POST` to [https://api.notion.com/v1/databases/{database_id}/query](https://developers.notion.com/reference/post-database-query) to search available pages. 28 | - `GET` to [https://api.notion.com/v1/users/{user_id}](https://developers.notion.com/reference/get-user) to get names of users, when the "User" property exists in pages. 29 | 30 | # Acknowledgements 31 | This plugin uses the excellent Notion API to sync files, as well as the Dataview plugin to query relevant metadata. -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { Notice, Plugin } from 'obsidian' 2 | import NotionSyncSettingsTab from './NotionSyncSettingsTab' 3 | import Api from './api' 4 | import { DateTime } from 'luxon' 5 | import invariant from 'tiny-invariant' 6 | 7 | const DEFAULT_SETTINGS: NotionSyncSettings = { 8 | databases: {}, 9 | apiKey: '', 10 | lastSync: 0, 11 | lastConflicts: [] 12 | } 13 | 14 | export default class NotionSync extends Plugin { 15 | settings: NotionSyncSettings 16 | api: Api 17 | 18 | async onload() { 19 | await this.loadSettings() 20 | // called from obsidianApi etc. 21 | this.setSetting = this.setSetting.bind(this) 22 | 23 | this.addSettingTab(new NotionSyncSettingsTab(this.app, this)) 24 | this.api = new Api(this.app, this.settings, this.setSetting) 25 | 26 | this.addCommand({ 27 | name: 'Sync', 28 | callback: () => this.api.sync(), 29 | id: 'sync' 30 | }) 31 | 32 | this.addCommand({ 33 | name: 'Download all files', 34 | id: 'force-download', 35 | callback: async () => { 36 | this.setSetting({ lastSync: 0 }) 37 | await this.api.sync('download') 38 | } 39 | }) 40 | 41 | this.addCommand({ 42 | name: 'Download this file', 43 | id: 'force-download-file', 44 | editorCallback: async (_editor, ctx) => { 45 | if (!ctx.file) return 46 | await this.app.fileManager.processFrontMatter( 47 | ctx.file, 48 | async frontmatter => { 49 | invariant(ctx.file) 50 | const id = frontmatter['Notion ID'] 51 | if (!id) { 52 | new Notice('No Notion ID property.') 53 | return 54 | } 55 | const page = await this.api.getPage(id, true) 56 | await this.api.downloadPage(page, ctx.file, ctx.file.path, true) 57 | new Notice('Notion sync: downloaded.') 58 | } 59 | ) 60 | } 61 | }) 62 | 63 | this.addCommand({ 64 | name: 'Upload this file', 65 | id: 'force-upload-file', 66 | editorCallback: async (_editor, ctx) => { 67 | if (!ctx.file) return 68 | await this.app.fileManager.processFrontMatter( 69 | ctx.file, 70 | async frontmatter => { 71 | invariant(ctx.file) 72 | const id = frontmatter['Notion ID'] 73 | console.log(this.settings) 74 | const database = Object.entries(this.settings.databases).find(x => 75 | ctx.file!.path.includes(x[1].path) 76 | )! 77 | await this.api.uploadFile(ctx.file, id, database[0], true) 78 | new Notice('Notion sync: uploaded.') 79 | } 80 | ) 81 | } 82 | }) 83 | 84 | this.addCommand({ 85 | name: 'Upload all files', 86 | id: 'force-upload', 87 | callback: async () => { 88 | this.setSetting({ lastSync: 0 }) 89 | await this.api.sync('upload') 90 | } 91 | }) 92 | } 93 | 94 | async loadSettings() { 95 | this.settings = Object.assign(DEFAULT_SETTINGS, await this.loadData()) 96 | } 97 | 98 | async setSetting(settings: Partial) { 99 | for (let key of Object.keys(settings)) { 100 | this.settings[key] = settings[key] 101 | } 102 | await this.saveData(this.settings) 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/functions/parser.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CheckboxPropertyItemObjectResponse, 3 | DatabaseObjectResponse, 4 | DatePropertyItemObjectResponse, 5 | EmailPropertyItemObjectResponse, 6 | MultiSelectPropertyItemObjectResponse, 7 | NumberPropertyItemObjectResponse, 8 | PageObjectResponse, 9 | PhoneNumberPropertyItemObjectResponse, 10 | PropertyItemObjectResponse, 11 | RichTextItemResponse, 12 | RollupPropertyItemObjectResponse, 13 | SelectPropertyItemObjectResponse, 14 | StatusPropertyItemObjectResponse, 15 | TextRichTextItemResponse, 16 | UniqueIdPropertyItemObjectResponse, 17 | UrlPropertyItemObjectResponse 18 | } from '@notionhq/client/build/src/api-endpoints' 19 | import { DateTime } from 'luxon' 20 | import Api from '../api' 21 | import { isFullDatabase } from '@notionhq/client' 22 | import invariant from 'tiny-invariant' 23 | 24 | export function getFileName(path: string) { 25 | return path.includes('/') ? path.slice(path.lastIndexOf('/') + 1) : path 26 | } 27 | export function parseTitle(database: DatabaseObjectResponse) { 28 | return parseText(database.title) 29 | } 30 | 31 | export function yamlToNotion( 32 | type: PageObjectResponse['properties'][string]['type'], 33 | property: boolean | number | string | string[] 34 | ) { 35 | switch (type) { 36 | case 'checkbox': 37 | return ( 38 | property === true ? true : false 39 | ) as CheckboxPropertyItemObjectResponse['checkbox'] 40 | case 'date': 41 | return ( 42 | property 43 | ? { 44 | start: property 45 | } 46 | : null 47 | ) as DatePropertyItemObjectResponse['date'] 48 | case 'email': 49 | return String(property) as EmailPropertyItemObjectResponse['email'] 50 | case 'multi_select': 51 | return ( 52 | property instanceof Array 53 | ? property.map(option => ({ 54 | name: option 55 | })) 56 | : property 57 | ? [ 58 | { 59 | name: String(property) 60 | } 61 | ] 62 | : [] 63 | ) as MultiSelectPropertyItemObjectResponse['multi_select'] 64 | case 'number': 65 | return Number(property) as NumberPropertyItemObjectResponse['number'] 66 | case 'phone_number': 67 | return String( 68 | property 69 | ) as PhoneNumberPropertyItemObjectResponse['phone_number'] 70 | case 'select': 71 | return ( 72 | property 73 | ? { 74 | name: property 75 | } 76 | : null 77 | ) as SelectPropertyItemObjectResponse['select'] 78 | case 'status': 79 | return ( 80 | !property 81 | ? null 82 | : { 83 | name: property 84 | } 85 | ) as StatusPropertyItemObjectResponse['status'] 86 | case 'title': 87 | case 'rich_text': 88 | return [ 89 | { 90 | type: 'text', 91 | text: { content: !property ? '' : String(property) } 92 | } 93 | ] as TextRichTextItemResponse[] 94 | case 'unique_id': 95 | return { 96 | prefix: '', 97 | number: 98 | typeof property === 'string' 99 | ? parseInt(property) 100 | : typeof property === 'number' 101 | ? property 102 | : undefined 103 | } as UniqueIdPropertyItemObjectResponse['unique_id'] 104 | case 'url': 105 | return String(property) as UrlPropertyItemObjectResponse['url'] 106 | case 'relation': 107 | case 'verification': 108 | case 'people': 109 | case 'rollup': 110 | case 'last_edited_time': 111 | case 'files': 112 | case 'formula': 113 | case 'last_edited_by': 114 | case 'created_by': 115 | case 'created_time': 116 | return undefined 117 | } 118 | } 119 | 120 | export function yamlToMarkdown( 121 | property: boolean | number | string | string[] | object 122 | ): string { 123 | switch (typeof property) { 124 | case 'boolean': 125 | return property ? 'X' : ' ' 126 | case 'number': 127 | return String(property) 128 | case 'object': 129 | if (property instanceof Array) { 130 | return property.join(', ') 131 | } else { 132 | let propertyString: string[] = [] 133 | for (let [key, value] of Object.entries(property)) { 134 | propertyString.push(`${key}: ${yamlToMarkdown(value)}`) 135 | } 136 | return propertyString.join(', ') 137 | } 138 | case 'string': 139 | return property 140 | } 141 | } 142 | 143 | export function parsePageTitle(page: PageObjectResponse) { 144 | const search = Object.entries(page.properties).find( 145 | ([key, property]) => property.type === 'title' 146 | ) 147 | invariant(search) 148 | const [titleKey, title] = search 149 | invariant(title.type === 'title') 150 | return [titleKey, parseText(title.title).replace(/\//g, '-')] 151 | } 152 | 153 | export function parseText(object: RichTextItemResponse[]) { 154 | return object.map(span => span.plain_text).join('') 155 | } 156 | -------------------------------------------------------------------------------- /dist/styles.css: -------------------------------------------------------------------------------- 1 | /* src/styles.css */ 2 | .mb-1 { 3 | margin-bottom: 0.25rem; 4 | } 5 | .flex { 6 | display: flex; 7 | } 8 | .h-full { 9 | height: 100%; 10 | } 11 | .w-1\/2 { 12 | width: 50%; 13 | } 14 | .w-full { 15 | width: 100%; 16 | } 17 | .flex-none { 18 | flex: none; 19 | } 20 | .grow { 21 | flex-grow: 1; 22 | } 23 | .select-none { 24 | -webkit-user-select: none; 25 | -moz-user-select: none; 26 | user-select: none; 27 | } 28 | .flex-col { 29 | flex-direction: column; 30 | } 31 | .items-center { 32 | align-items: center; 33 | } 34 | .justify-center { 35 | justify-content: center; 36 | } 37 | .space-x-2 > :not([hidden]) ~ :not([hidden]) { 38 | --tw-space-x-reverse: 0; 39 | margin-right: calc(0.5rem * var(--tw-space-x-reverse)); 40 | margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse))); 41 | } 42 | .whitespace-nowrap { 43 | white-space: nowrap; 44 | } 45 | .p-1 { 46 | padding: 0.25rem; 47 | } 48 | .font-menu { 49 | font-family: var(--font-interface); 50 | } 51 | .text-sm { 52 | font-size: 0.875rem; 53 | line-height: 1.25rem; 54 | } 55 | .filter { 56 | filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); 57 | } 58 | *, 59 | ::before, 60 | ::after { 61 | --tw-border-spacing-x: 0; 62 | --tw-border-spacing-y: 0; 63 | --tw-translate-x: 0; 64 | --tw-translate-y: 0; 65 | --tw-rotate: 0; 66 | --tw-skew-x: 0; 67 | --tw-skew-y: 0; 68 | --tw-scale-x: 1; 69 | --tw-scale-y: 1; 70 | --tw-pan-x: ; 71 | --tw-pan-y: ; 72 | --tw-pinch-zoom: ; 73 | --tw-scroll-snap-strictness: proximity; 74 | --tw-gradient-from-position: ; 75 | --tw-gradient-via-position: ; 76 | --tw-gradient-to-position: ; 77 | --tw-ordinal: ; 78 | --tw-slashed-zero: ; 79 | --tw-numeric-figure: ; 80 | --tw-numeric-spacing: ; 81 | --tw-numeric-fraction: ; 82 | --tw-ring-inset: ; 83 | --tw-ring-offset-width: 0px; 84 | --tw-ring-offset-color: #fff; 85 | --tw-ring-color: rgb(59 130 246 / 0.5); 86 | --tw-ring-offset-shadow: 0 0 #0000; 87 | --tw-ring-shadow: 0 0 #0000; 88 | --tw-shadow: 0 0 #0000; 89 | --tw-shadow-colored: 0 0 #0000; 90 | --tw-blur: ; 91 | --tw-brightness: ; 92 | --tw-contrast: ; 93 | --tw-grayscale: ; 94 | --tw-hue-rotate: ; 95 | --tw-invert: ; 96 | --tw-saturate: ; 97 | --tw-sepia: ; 98 | --tw-drop-shadow: ; 99 | --tw-backdrop-blur: ; 100 | --tw-backdrop-brightness: ; 101 | --tw-backdrop-contrast: ; 102 | --tw-backdrop-grayscale: ; 103 | --tw-backdrop-hue-rotate: ; 104 | --tw-backdrop-invert: ; 105 | --tw-backdrop-opacity: ; 106 | --tw-backdrop-saturate: ; 107 | --tw-backdrop-sepia: ; 108 | --tw-contain-size: ; 109 | --tw-contain-layout: ; 110 | --tw-contain-paint: ; 111 | --tw-contain-style: ; 112 | } 113 | ::backdrop { 114 | --tw-border-spacing-x: 0; 115 | --tw-border-spacing-y: 0; 116 | --tw-translate-x: 0; 117 | --tw-translate-y: 0; 118 | --tw-rotate: 0; 119 | --tw-skew-x: 0; 120 | --tw-skew-y: 0; 121 | --tw-scale-x: 1; 122 | --tw-scale-y: 1; 123 | --tw-pan-x: ; 124 | --tw-pan-y: ; 125 | --tw-pinch-zoom: ; 126 | --tw-scroll-snap-strictness: proximity; 127 | --tw-gradient-from-position: ; 128 | --tw-gradient-via-position: ; 129 | --tw-gradient-to-position: ; 130 | --tw-ordinal: ; 131 | --tw-slashed-zero: ; 132 | --tw-numeric-figure: ; 133 | --tw-numeric-spacing: ; 134 | --tw-numeric-fraction: ; 135 | --tw-ring-inset: ; 136 | --tw-ring-offset-width: 0px; 137 | --tw-ring-offset-color: #fff; 138 | --tw-ring-color: rgb(59 130 246 / 0.5); 139 | --tw-ring-offset-shadow: 0 0 #0000; 140 | --tw-ring-shadow: 0 0 #0000; 141 | --tw-shadow: 0 0 #0000; 142 | --tw-shadow-colored: 0 0 #0000; 143 | --tw-blur: ; 144 | --tw-brightness: ; 145 | --tw-contrast: ; 146 | --tw-grayscale: ; 147 | --tw-hue-rotate: ; 148 | --tw-invert: ; 149 | --tw-saturate: ; 150 | --tw-sepia: ; 151 | --tw-drop-shadow: ; 152 | --tw-backdrop-blur: ; 153 | --tw-backdrop-brightness: ; 154 | --tw-backdrop-contrast: ; 155 | --tw-backdrop-grayscale: ; 156 | --tw-backdrop-hue-rotate: ; 157 | --tw-backdrop-invert: ; 158 | --tw-backdrop-opacity: ; 159 | --tw-backdrop-saturate: ; 160 | --tw-backdrop-sepia: ; 161 | --tw-contain-size: ; 162 | --tw-contain-layout: ; 163 | --tw-contain-paint: ; 164 | --tw-contain-style: ; 165 | } 166 | .child\:pb-0 > * { 167 | padding-bottom: 0px; 168 | } 169 | /*# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3N0eWxlcy5jc3MiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi5tYi0xIHtcbiAgICBtYXJnaW4tYm90dG9tOiAwLjI1cmVtXG59XG4uZmxleCB7XG4gICAgZGlzcGxheTogZmxleFxufVxuLmgtZnVsbCB7XG4gICAgaGVpZ2h0OiAxMDAlXG59XG4udy0xXFwvMiB7XG4gICAgd2lkdGg6IDUwJVxufVxuLnctZnVsbCB7XG4gICAgd2lkdGg6IDEwMCVcbn1cbi5mbGV4LW5vbmUge1xuICAgIGZsZXg6IG5vbmVcbn1cbi5ncm93IHtcbiAgICBmbGV4LWdyb3c6IDFcbn1cbi5zZWxlY3Qtbm9uZSB7XG4gICAgLXdlYmtpdC11c2VyLXNlbGVjdDogbm9uZTtcbiAgICAgICAtbW96LXVzZXItc2VsZWN0OiBub25lO1xuICAgICAgICAgICAgdXNlci1zZWxlY3Q6IG5vbmVcbn1cbi5mbGV4LWNvbCB7XG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtblxufVxuLml0ZW1zLWNlbnRlciB7XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlclxufVxuLmp1c3RpZnktY2VudGVyIHtcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlclxufVxuLnNwYWNlLXgtMiA+IDpub3QoW2hpZGRlbl0pIH4gOm5vdChbaGlkZGVuXSkge1xuICAgIC0tdHctc3BhY2UteC1yZXZlcnNlOiAwO1xuICAgIG1hcmdpbi1yaWdodDogY2FsYygwLjVyZW0gKiB2YXIoLS10dy1zcGFjZS14LXJldmVyc2UpKTtcbiAgICBtYXJnaW4tbGVmdDogY2FsYygwLjVyZW0gKiBjYWxjKDEgLSB2YXIoLS10dy1zcGFjZS14LXJldmVyc2UpKSlcbn1cbi53aGl0ZXNwYWNlLW5vd3JhcCB7XG4gICAgd2hpdGUtc3BhY2U6IG5vd3JhcFxufVxuLnAtMSB7XG4gICAgcGFkZGluZzogMC4yNXJlbVxufVxuLmZvbnQtbWVudSB7XG4gICAgZm9udC1mYW1pbHk6IHZhcigtLWZvbnQtaW50ZXJmYWNlKVxufVxuLnRleHQtc20ge1xuICAgIGZvbnQtc2l6ZTogMC44NzVyZW07XG4gICAgbGluZS1oZWlnaHQ6IDEuMjVyZW1cbn1cbi5maWx0ZXIge1xuICAgIGZpbHRlcjogdmFyKC0tdHctYmx1cikgdmFyKC0tdHctYnJpZ2h0bmVzcykgdmFyKC0tdHctY29udHJhc3QpIHZhcigtLXR3LWdyYXlzY2FsZSkgdmFyKC0tdHctaHVlLXJvdGF0ZSkgdmFyKC0tdHctaW52ZXJ0KSB2YXIoLS10dy1zYXR1cmF0ZSkgdmFyKC0tdHctc2VwaWEpIHZhcigtLXR3LWRyb3Atc2hhZG93KVxufVxuKiwgOjpiZWZvcmUsIDo6YWZ0ZXIge1xuICAgIC0tdHctYm9yZGVyLXNwYWNpbmcteDogMDtcbiAgICAtLXR3LWJvcmRlci1zcGFjaW5nLXk6IDA7XG4gICAgLS10dy10cmFuc2xhdGUteDogMDtcbiAgICAtLXR3LXRyYW5zbGF0ZS15OiAwO1xuICAgIC0tdHctcm90YXRlOiAwO1xuICAgIC0tdHctc2tldy14OiAwO1xuICAgIC0tdHctc2tldy15OiAwO1xuICAgIC0tdHctc2NhbGUteDogMTtcbiAgICAtLXR3LXNjYWxlLXk6IDE7XG4gICAgLS10dy1wYW4teDogIDtcbiAgICAtLXR3LXBhbi15OiAgO1xuICAgIC0tdHctcGluY2gtem9vbTogIDtcbiAgICAtLXR3LXNjcm9sbC1zbmFwLXN0cmljdG5lc3M6IHByb3hpbWl0eTtcbiAgICAtLXR3LWdyYWRpZW50LWZyb20tcG9zaXRpb246ICA7XG4gICAgLS10dy1ncmFkaWVudC12aWEtcG9zaXRpb246ICA7XG4gICAgLS10dy1ncmFkaWVudC10by1wb3NpdGlvbjogIDtcbiAgICAtLXR3LW9yZGluYWw6ICA7XG4gICAgLS10dy1zbGFzaGVkLXplcm86ICA7XG4gICAgLS10dy1udW1lcmljLWZpZ3VyZTogIDtcbiAgICAtLXR3LW51bWVyaWMtc3BhY2luZzogIDtcbiAgICAtLXR3LW51bWVyaWMtZnJhY3Rpb246ICA7XG4gICAgLS10dy1yaW5nLWluc2V0OiAgO1xuICAgIC0tdHctcmluZy1vZmZzZXQtd2lkdGg6IDBweDtcbiAgICAtLXR3LXJpbmctb2Zmc2V0LWNvbG9yOiAjZmZmO1xuICAgIC0tdHctcmluZy1jb2xvcjogcmdiKDU5IDEzMCAyNDYgLyAwLjUpO1xuICAgIC0tdHctcmluZy1vZmZzZXQtc2hhZG93OiAwIDAgIzAwMDA7XG4gICAgLS10dy1yaW5nLXNoYWRvdzogMCAwICMwMDAwO1xuICAgIC0tdHctc2hhZG93OiAwIDAgIzAwMDA7XG4gICAgLS10dy1zaGFkb3ctY29sb3JlZDogMCAwICMwMDAwO1xuICAgIC0tdHctYmx1cjogIDtcbiAgICAtLXR3LWJyaWdodG5lc3M6ICA7XG4gICAgLS10dy1jb250cmFzdDogIDtcbiAgICAtLXR3LWdyYXlzY2FsZTogIDtcbiAgICAtLXR3LWh1ZS1yb3RhdGU6ICA7XG4gICAgLS10dy1pbnZlcnQ6ICA7XG4gICAgLS10dy1zYXR1cmF0ZTogIDtcbiAgICAtLXR3LXNlcGlhOiAgO1xuICAgIC0tdHctZHJvcC1zaGFkb3c6ICA7XG4gICAgLS10dy1iYWNrZHJvcC1ibHVyOiAgO1xuICAgIC0tdHctYmFja2Ryb3AtYnJpZ2h0bmVzczogIDtcbiAgICAtLXR3LWJhY2tkcm9wLWNvbnRyYXN0OiAgO1xuICAgIC0tdHctYmFja2Ryb3AtZ3JheXNjYWxlOiAgO1xuICAgIC0tdHctYmFja2Ryb3AtaHVlLXJvdGF0ZTogIDtcbiAgICAtLXR3LWJhY2tkcm9wLWludmVydDogIDtcbiAgICAtLXR3LWJhY2tkcm9wLW9wYWNpdHk6ICA7XG4gICAgLS10dy1iYWNrZHJvcC1zYXR1cmF0ZTogIDtcbiAgICAtLXR3LWJhY2tkcm9wLXNlcGlhOiAgO1xuICAgIC0tdHctY29udGFpbi1zaXplOiAgO1xuICAgIC0tdHctY29udGFpbi1sYXlvdXQ6ICA7XG4gICAgLS10dy1jb250YWluLXBhaW50OiAgO1xuICAgIC0tdHctY29udGFpbi1zdHlsZTogIFxufVxuOjpiYWNrZHJvcCB7XG4gICAgLS10dy1ib3JkZXItc3BhY2luZy14OiAwO1xuICAgIC0tdHctYm9yZGVyLXNwYWNpbmcteTogMDtcbiAgICAtLXR3LXRyYW5zbGF0ZS14OiAwO1xuICAgIC0tdHctdHJhbnNsYXRlLXk6IDA7XG4gICAgLS10dy1yb3RhdGU6IDA7XG4gICAgLS10dy1za2V3LXg6IDA7XG4gICAgLS10dy1za2V3LXk6IDA7XG4gICAgLS10dy1zY2FsZS14OiAxO1xuICAgIC0tdHctc2NhbGUteTogMTtcbiAgICAtLXR3LXBhbi14OiAgO1xuICAgIC0tdHctcGFuLXk6ICA7XG4gICAgLS10dy1waW5jaC16b29tOiAgO1xuICAgIC0tdHctc2Nyb2xsLXNuYXAtc3RyaWN0bmVzczogcHJveGltaXR5O1xuICAgIC0tdHctZ3JhZGllbnQtZnJvbS1wb3NpdGlvbjogIDtcbiAgICAtLXR3LWdyYWRpZW50LXZpYS1wb3NpdGlvbjogIDtcbiAgICAtLXR3LWdyYWRpZW50LXRvLXBvc2l0aW9uOiAgO1xuICAgIC0tdHctb3JkaW5hbDogIDtcbiAgICAtLXR3LXNsYXNoZWQtemVybzogIDtcbiAgICAtLXR3LW51bWVyaWMtZmlndXJlOiAgO1xuICAgIC0tdHctbnVtZXJpYy1zcGFjaW5nOiAgO1xuICAgIC0tdHctbnVtZXJpYy1mcmFjdGlvbjogIDtcbiAgICAtLXR3LXJpbmctaW5zZXQ6ICA7XG4gICAgLS10dy1yaW5nLW9mZnNldC13aWR0aDogMHB4O1xuICAgIC0tdHctcmluZy1vZmZzZXQtY29sb3I6ICNmZmY7XG4gICAgLS10dy1yaW5nLWNvbG9yOiByZ2IoNTkgMTMwIDI0NiAvIDAuNSk7XG4gICAgLS10dy1yaW5nLW9mZnNldC1zaGFkb3c6IDAgMCAjMDAwMDtcbiAgICAtLXR3LXJpbmctc2hhZG93OiAwIDAgIzAwMDA7XG4gICAgLS10dy1zaGFkb3c6IDAgMCAjMDAwMDtcbiAgICAtLXR3LXNoYWRvdy1jb2xvcmVkOiAwIDAgIzAwMDA7XG4gICAgLS10dy1ibHVyOiAgO1xuICAgIC0tdHctYnJpZ2h0bmVzczogIDtcbiAgICAtLXR3LWNvbnRyYXN0OiAgO1xuICAgIC0tdHctZ3JheXNjYWxlOiAgO1xuICAgIC0tdHctaHVlLXJvdGF0ZTogIDtcbiAgICAtLXR3LWludmVydDogIDtcbiAgICAtLXR3LXNhdHVyYXRlOiAgO1xuICAgIC0tdHctc2VwaWE6ICA7XG4gICAgLS10dy1kcm9wLXNoYWRvdzogIDtcbiAgICAtLXR3LWJhY2tkcm9wLWJsdXI6ICA7XG4gICAgLS10dy1iYWNrZHJvcC1icmlnaHRuZXNzOiAgO1xuICAgIC0tdHctYmFja2Ryb3AtY29udHJhc3Q6ICA7XG4gICAgLS10dy1iYWNrZHJvcC1ncmF5c2NhbGU6ICA7XG4gICAgLS10dy1iYWNrZHJvcC1odWUtcm90YXRlOiAgO1xuICAgIC0tdHctYmFja2Ryb3AtaW52ZXJ0OiAgO1xuICAgIC0tdHctYmFja2Ryb3Atb3BhY2l0eTogIDtcbiAgICAtLXR3LWJhY2tkcm9wLXNhdHVyYXRlOiAgO1xuICAgIC0tdHctYmFja2Ryb3Atc2VwaWE6ICA7XG4gICAgLS10dy1jb250YWluLXNpemU6ICA7XG4gICAgLS10dy1jb250YWluLWxheW91dDogIDtcbiAgICAtLXR3LWNvbnRhaW4tcGFpbnQ6ICA7XG4gICAgLS10dy1jb250YWluLXN0eWxlOiAgXG59XG4uY2hpbGRcXDpwYi0wID4gKiB7XG4gICAgcGFkZGluZy1ib3R0b206IDBweFxufVxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUFBLENBQUM7QUFDRyxpQkFBZTtBQUNuQjtBQUNBLENBQUM7QUFDRyxXQUFTO0FBQ2I7QUFDQSxDQUFDO0FBQ0csVUFBUTtBQUNaO0FBQ0EsQ0FBQztBQUNHLFNBQU87QUFDWDtBQUNBLENBQUM7QUFDRyxTQUFPO0FBQ1g7QUFDQSxDQUFDO0FBQ0csUUFBTTtBQUNWO0FBQ0EsQ0FBQztBQUNHLGFBQVc7QUFDZjtBQUNBLENBQUM7QUFDRyx1QkFBcUI7QUFDbEIsb0JBQWtCO0FBQ2IsZUFBYTtBQUN6QjtBQUNBLENBQUM7QUFDRyxrQkFBZ0I7QUFDcEI7QUFDQSxDQUFDO0FBQ0csZUFBYTtBQUNqQjtBQUNBLENBQUM7QUFDRyxtQkFBaUI7QUFDckI7QUFDQSxDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQztBQUNoQyx3QkFBc0I7QUFDdEIsZ0JBQWMsS0FBSyxPQUFPLEVBQUUsSUFBSTtBQUNoQyxlQUFhLEtBQUssT0FBTyxFQUFFLEtBQUssRUFBRSxFQUFFLElBQUk7QUFDNUM7QUFDQSxDQUFDO0FBQ0csZUFBYTtBQUNqQjtBQUNBLENBQUM7QUFDRyxXQUFTO0FBQ2I7QUFDQSxDQUFDO0FBQ0csZUFBYSxJQUFJO0FBQ3JCO0FBQ0EsQ0FBQztBQUNHLGFBQVc7QUFDWCxlQUFhO0FBQ2pCO0FBQ0EsQ0FBQztBQUNHLFVBQVEsSUFBSSxXQUFXLElBQUksaUJBQWlCLElBQUksZUFBZSxJQUFJLGdCQUFnQixJQUFJLGlCQUFpQixJQUFJLGFBQWEsSUFBSSxlQUFlLElBQUksWUFBWSxJQUFJO0FBQ3BLO0FBQ0E7QUFBRztBQUFVO0FBQ1QseUJBQXVCO0FBQ3ZCLHlCQUF1QjtBQUN2QixvQkFBa0I7QUFDbEIsb0JBQWtCO0FBQ2xCLGVBQWE7QUFDYixlQUFhO0FBQ2IsZUFBYTtBQUNiLGdCQUFjO0FBQ2QsZ0JBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQSwrQkFBNkI7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQXdCO0FBQ3hCLDBCQUF3QjtBQUN4QixtQkFBaUIsSUFBSSxHQUFHLElBQUksSUFBSSxFQUFFO0FBQ2xDLDJCQUF5QixFQUFFLEVBQUU7QUFDN0Isb0JBQWtCLEVBQUUsRUFBRTtBQUN0QixlQUFhLEVBQUUsRUFBRTtBQUNqQix1QkFBcUIsRUFBRSxFQUFFO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0o7QUFDQTtBQUNJLHlCQUF1QjtBQUN2Qix5QkFBdUI7QUFDdkIsb0JBQWtCO0FBQ2xCLG9CQUFrQjtBQUNsQixlQUFhO0FBQ2IsZUFBYTtBQUNiLGVBQWE7QUFDYixnQkFBYztBQUNkLGdCQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0EsK0JBQTZCO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUF3QjtBQUN4QiwwQkFBd0I7QUFDeEIsbUJBQWlCLElBQUksR0FBRyxJQUFJLElBQUksRUFBRTtBQUNsQywyQkFBeUIsRUFBRSxFQUFFO0FBQzdCLG9CQUFrQixFQUFFLEVBQUU7QUFDdEIsZUFBYSxFQUFFLEVBQUU7QUFDakIsdUJBQXFCLEVBQUUsRUFBRTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNKO0FBQ0EsQ0FBQyxZQUFZLEVBQUU7QUFDWCxrQkFBZ0I7QUFDcEI7IiwKICAibmFtZXMiOiBbXQp9Cg== */ 170 | -------------------------------------------------------------------------------- /src/api.tsx: -------------------------------------------------------------------------------- 1 | import { Client } from '@notionhq/client' 2 | import { 3 | DatabaseObjectResponse, 4 | PageObjectResponse, 5 | PropertyItemObjectResponse, 6 | UserObjectResponse 7 | } from '@notionhq/client/build/src/api-endpoints' 8 | import { 9 | App, 10 | Component, 11 | Modal, 12 | Notice, 13 | App as ObsidianApp, 14 | RequestUrlParam, 15 | TAbstractFile, 16 | TFile, 17 | TFolder, 18 | normalizePath, 19 | parseLinktext, 20 | request, 21 | requestUrl 22 | } from 'obsidian' 23 | 24 | import invariant from 'tiny-invariant' 25 | import { 26 | getFileName, 27 | parsePageTitle, 28 | parseText, 29 | yamlToMarkdown, 30 | yamlToNotion 31 | } from './functions/parser' 32 | import NotionSync from './main' 33 | import { DateTime } from 'luxon' 34 | import _, { clone } from 'lodash' 35 | import { DataArray, Literal, PageMetadata, getAPI } from 'obsidian-dataview' 36 | import { createRoot } from 'react-dom/client' 37 | import { useState } from 'react' 38 | import { log } from 'console' 39 | 40 | export type Progress = { 41 | conflicting: { page: PageObjectResponse; tFile: TFile }[] 42 | skipped: string[] 43 | uploaded: string[] 44 | downloaded: string[] 45 | failed: string[] 46 | } 47 | export default class Api extends Component { 48 | settings: NotionSyncSettings 49 | app: ObsidianApp 50 | setSetting: NotionSync['setSetting'] 51 | databases: Record 52 | people: Record 53 | pages: Record 54 | progress: Progress 55 | 56 | async load() { 57 | this.databases = await this.loadDatabases() 58 | } 59 | 60 | async sync(force?: 'download' | 'upload') { 61 | new Notice('Notion Sync: syncing...') 62 | 63 | this.progress = { 64 | failed: [], 65 | conflicting: [], 66 | uploaded: [], 67 | downloaded: [], 68 | skipped: [] 69 | } 70 | 71 | const loadedDatabases = Object.values(this.databases).filter( 72 | db => this.settings.databases[db.id]?.path 73 | ) 74 | const promises: Promise[] = [] 75 | for (let database of loadedDatabases) { 76 | promises.push(this.syncDatabase(database.id, force)) 77 | } 78 | 79 | await Promise.all(promises) 80 | 81 | this.setSetting({ lastSync: Date.now() }) 82 | 83 | new Notice( 84 | `Sync successful.\nDownloaded: ${this.progress.downloaded.length}\nUploaded: ${this.progress.uploaded.length}\nSkipped: ${this.progress.skipped.length}\nCheck console for details.` 85 | ) 86 | if (this.progress.conflicting.length > 0) { 87 | const modal = new Modal(this.app) 88 | const content = createRoot(modal.contentEl) 89 | 90 | const SyncStatus = (conflicting: Progress['conflicting']) => { 91 | const uploadFile = async (conflict, i) => { 92 | await this.uploadFile( 93 | conflict.tFile, 94 | conflict.page.id, 95 | conflict.page.parent['dtabase_id'] 96 | ) 97 | const newConflicting = conflicting 98 | .slice(0, i) 99 | .concat(conflicting.slice(i + 1)) 100 | if (newConflicting.length === 0) { 101 | modal.close() 102 | new Notice('All conflicts resolved.') 103 | } else content.render(SyncStatus(newConflicting)) 104 | } 105 | 106 | return ( 107 | <> 108 |
Conflicts:
109 |
110 | 120 | 121 |
122 |
123 | {conflicting.map((conflict, i) => ( 124 |
125 |

{conflict.tFile.basename}

126 |
127 | 130 | 149 |
150 | ))} 151 |
152 |
153 | These files have been modified in both Notion and Obsidian; please 154 | fix by using "upload" or "download" after reviewing the 155 | differences. 156 |
157 | 158 | ) 159 | } 160 | 161 | content.render(SyncStatus([...this.progress.conflicting])) 162 | modal.onClose = () => { 163 | content.unmount() 164 | } 165 | modal.open() 166 | } 167 | } 168 | 169 | async createFile(givenPath: string) { 170 | const path = normalizePath(givenPath + '.md').replace(/:/g, ' -') 171 | let writeFile = this.app.vault.getAbstractFileByPathInsensitive(path) 172 | 173 | if (!(writeFile instanceof TFile)) { 174 | const folders = path.split('/').slice(0, -1) 175 | let currentFolder = '' 176 | for (let i = 0; i < folders.length; i++) { 177 | currentFolder += '/' + folders[i] 178 | const folderVault = this.app.vault.getAbstractFileByPathInsensitive( 179 | normalizePath(currentFolder) 180 | ) 181 | if (!(folderVault instanceof TFolder)) { 182 | try { 183 | await this.app.vault.createFolder(currentFolder) 184 | } catch (err) { 185 | console.warn('error:', err.message) 186 | } 187 | } 188 | } 189 | writeFile = await this.app.vault.create(path, '') 190 | } 191 | 192 | return writeFile 193 | } 194 | 195 | async getPerson(personId: string) { 196 | if (this.people[personId]) return this.people[personId] 197 | const person = await this.request({ 198 | url: `https://api.notion.com/v1/users/${personId}` 199 | }) 200 | this.people[personId] = person 201 | return person 202 | } 203 | 204 | async getPage(pageId: string, skipCache = false) { 205 | if (this.pages[pageId] && !skipCache) return this.pages[pageId] 206 | const page = (await this.request({ 207 | url: `https://api.notion.com/v1/pages/${pageId}` 208 | })) as PageObjectResponse 209 | this.pages[pageId] = page 210 | return page 211 | } 212 | 213 | async uploadFile( 214 | tFile: TFile, 215 | page_id: string | undefined, 216 | databaseId: string, 217 | skipProgress = false 218 | ) { 219 | let page: PageObjectResponse 220 | try { 221 | invariant(page_id) 222 | page = await this.getPage(page_id as string) 223 | if (page.in_trash) throw 'in trash' 224 | } catch { 225 | const newPage = await this.request({ 226 | url: `https://api.notion.com/v1/pages`, 227 | body: { 228 | parent: { database_id: databaseId }, 229 | properties: { 230 | Name: { 231 | title: [{ text: { content: tFile.basename } }] 232 | } 233 | } 234 | }, 235 | method: 'POST' 236 | }) 237 | if (!newPage) { 238 | throw new Error('no new page created') 239 | } 240 | page_id = newPage.id 241 | await this.app.fileManager.processFrontMatter( 242 | tFile, 243 | frontmatter => (frontmatter['Notion ID'] = page_id) 244 | ) 245 | page = await this.getPage(page_id) 246 | } 247 | 248 | const [nameKey, name] = parsePageTitle(page) 249 | await this.app.fileManager.processFrontMatter(tFile, frontmatter => { 250 | const notionProperties: Record = {} 251 | for (let key of Object.keys(frontmatter).filter( 252 | key => page.properties[key] !== undefined 253 | )) { 254 | const parsedProperty = yamlToNotion( 255 | page.properties[key].type, 256 | frontmatter[key] 257 | ) 258 | 259 | if ( 260 | parsedProperty !== undefined && 261 | !_.isEqual( 262 | parsedProperty, 263 | page.properties[key][page.properties[key].type] 264 | ) 265 | ) { 266 | notionProperties[key] = { 267 | [page.properties[key].type]: parsedProperty 268 | } 269 | } 270 | } 271 | 272 | if (name !== tFile.basename) { 273 | notionProperties[nameKey] = { 274 | title: [{ text: { content: tFile.basename } }] 275 | } 276 | } 277 | 278 | if ((_.keys(notionProperties).length = 0)) { 279 | this.progress.skipped.push(tFile.path) 280 | return 281 | } 282 | 283 | this.request({ 284 | url: `https://api.notion.com/v1/pages/${page.id}`, 285 | method: 'PATCH', 286 | body: { 287 | properties: notionProperties 288 | } 289 | }).catch(err => { 290 | console.log('failure:', err) 291 | }) 292 | }) 293 | if (!skipProgress) this.progress.uploaded.push(name) 294 | } 295 | 296 | async downloadPage( 297 | page: PageObjectResponse, 298 | tFile: TAbstractFile | null, 299 | path: string, 300 | skipProgress = false 301 | ) { 302 | const [nameKey, name] = parsePageTitle(page) 303 | if (!(tFile instanceof TFile)) { 304 | tFile = await this.createFile(path + '/' + name) 305 | } 306 | invariant(tFile instanceof TFile) 307 | 308 | if (tFile.basename !== name) { 309 | await this.app.vault.rename( 310 | tFile, 311 | tFile.parent?.path + '/' + name + '.md' 312 | ) 313 | } 314 | 315 | const convertedProperties = Object.entries(await this.notionToYaml(page)) 316 | 317 | await this.app.fileManager.processFrontMatter(tFile, frontmatter => { 318 | for (let [key, value] of convertedProperties) { 319 | if (value === name) continue 320 | frontmatter[key] = value 321 | } 322 | frontmatter['Notion ID'] = page.id 323 | }) 324 | 325 | if (!skipProgress) this.progress.downloaded.push(name) 326 | console.info('downloaded', name) 327 | } 328 | 329 | async notionToYaml(page: PageObjectResponse) { 330 | const yamlProperties: Record = {} 331 | for (let [propertyKey, property] of Object.entries(page.properties)) { 332 | yamlProperties[propertyKey] = await this.parseProperty(property) 333 | } 334 | return yamlProperties 335 | } 336 | 337 | async parseProperty(property: PageObjectResponse['properties'][string]) { 338 | const fromISO = (string: string) => string.slice(0, 16) 339 | 340 | const parseDate = ( 341 | date: (PropertyItemObjectResponse & { type: 'date' })['date'] 342 | ) => 343 | !date 344 | ? '' 345 | : date.end 346 | ? { 347 | start: fromISO(date.start), 348 | end: fromISO(date.end) 349 | } 350 | : fromISO(date.start) 351 | 352 | switch (property.type) { 353 | case 'checkbox': 354 | return property.checkbox ? true : false 355 | case 'created_by': 356 | case 'last_edited_by': 357 | return (await this.getPerson(property[property.type].id)).name 358 | case 'date': 359 | return parseDate(property.date) 360 | case 'email': 361 | return property.email ?? '' 362 | case 'files': 363 | return property.files.map(file => file.name) 364 | case 'formula': 365 | switch (property.formula.type) { 366 | case 'boolean': 367 | return property.formula ? 'true' : 'false' 368 | case 'date': 369 | return parseDate(property.formula.date) 370 | case 'number': 371 | return String(property.formula.number) 372 | case 'string': 373 | return property.formula.string ?? '' 374 | } 375 | case 'last_edited_time': 376 | case 'created_time': 377 | return fromISO(property[property.type]) 378 | case 'multi_select': 379 | return property.multi_select.map(item => item.name) 380 | case 'number': 381 | return String(property.number) 382 | case 'people': 383 | return ( 384 | await Promise.all( 385 | property.people.map(person => this.getPerson(person.id)) 386 | ) 387 | ).map(user => user.name ?? '') 388 | 389 | case 'phone_number': 390 | case 'url': 391 | return property[property.type] ?? '' 392 | case 'relation': 393 | return ( 394 | await Promise.all( 395 | property.relation.map(value => this.getPage(value.id)) 396 | ) 397 | ).map(page => '[[' + parsePageTitle(page) + ']]') 398 | case 'rich_text': 399 | case 'title': 400 | return parseText(property[property.type]) 401 | case 'rollup': 402 | switch (property.rollup.type) { 403 | case 'array': 404 | return await Promise.all( 405 | property.rollup.array.map(property => 406 | this.parseProperty({ ...property, id: '' }) 407 | ) 408 | ) 409 | case 'date': 410 | return parseDate(property.rollup.date) 411 | case 'number': 412 | return property.rollup.number 413 | } 414 | case 'select': 415 | const name = property[property.type]?.name 416 | return name ?? '' 417 | case 'status': 418 | return property[property.type]?.name ?? '' 419 | case 'unique_id': 420 | return ( 421 | property.unique_id.prefix ?? '' + String(property.unique_id.number) 422 | ) 423 | case 'verification': 424 | return property.verification?.date 425 | ? parseDate(property.verification.date) ?? '' 426 | : '' 427 | } 428 | } 429 | 430 | async syncDatabase(databaseId: string, force?: 'download' | 'upload') { 431 | const database = this.settings.databases[databaseId] 432 | if (!database.path) return 433 | 434 | const lastSync = DateTime.fromMillis(this.settings.lastSync) 435 | const lastSyncISO = lastSync.toISO() 436 | 437 | let pages: PageObjectResponse[] = [] 438 | 439 | let newPages: { results: PageObjectResponse[] } 440 | let start_cursor = undefined 441 | do { 442 | newPages = await this.request({ 443 | url: `https://api.notion.com/v1/databases/${databaseId}/query`, 444 | method: 'POST', 445 | body: { 446 | start_cursor, 447 | filter: 448 | force === 'download' 449 | ? undefined 450 | : { 451 | timestamp: 'last_edited_time', 452 | last_edited_time: { 453 | after: lastSyncISO 454 | } 455 | } 456 | } 457 | }) 458 | start_cursor = newPages['next_cursor'] 459 | pages.push(...newPages.results) 460 | } while (newPages['has_more']) 461 | 462 | let dv = getAPI() 463 | if (!dv) { 464 | new Notice('Please install Dataview to use Notion Sync.') 465 | throw new Error('Dataview must be installed') 466 | } 467 | 468 | const files = dv.pages(`"${database.path}"`) as DataArray< 469 | Record & { file: PageMetadata } 470 | > 471 | 472 | const uploading = 473 | force === 'download' 474 | ? [] 475 | : force === 'upload' 476 | ? files 477 | : files.filter(file => file.file.mtime > lastSync) 478 | const databasePath = 479 | normalizePath(this.settings.databases[databaseId].path) + '/' 480 | 481 | for (let page of pages) { 482 | const pageTitle = parsePageTitle(page) 483 | const file = files.find(file => file['Notion ID'] === page.id) 484 | const tFile = this.app.vault.getAbstractFileByPathInsensitive( 485 | file ? file.file.path : databasePath + pageTitle + '.md' 486 | ) 487 | if ( 488 | force !== 'download' && 489 | tFile && 490 | tFile.stat.mtime > this.settings.lastSync 491 | ) { 492 | this.progress.conflicting.push({ 493 | page, 494 | tFile 495 | }) 496 | } else { 497 | await this.downloadPage(page, tFile, database.path) 498 | } 499 | } 500 | 501 | for (let file of uploading) { 502 | const tFile = this.app.vault.getAbstractFileByPathInsensitive( 503 | file.file.path 504 | ) 505 | invariant(tFile) 506 | 507 | await this.uploadFile( 508 | tFile, 509 | file['Notion ID'] as string | undefined, 510 | databaseId 511 | ) 512 | } 513 | } 514 | 515 | constructor( 516 | app: ObsidianApp, 517 | settings: Api['settings'], 518 | setSetting: Api['setSetting'] 519 | ) { 520 | super() 521 | this.app = app 522 | this.settings = settings 523 | this.setSetting = setSetting 524 | this.people = {} 525 | this.pages = {} 526 | this.load = this.load.bind(this) 527 | this.load().then(() => console.log('loaded Notion databases')) 528 | } 529 | 530 | async request any>( 531 | config: Omit & { 532 | body?: Partial[0]> 533 | } 534 | ): Promise>> { 535 | let result 536 | try { 537 | result = await requestUrl({ 538 | ...config, 539 | headers: { 540 | Authorization: `Bearer ${this.settings.apiKey}`, 541 | 'Notion-Version': '2022-06-28', 542 | 'Content-Type': 'application/json', 543 | Accept: 'application/json' 544 | }, 545 | body: config.body ? JSON.stringify(config.body) : undefined 546 | }) 547 | } catch (e) { 548 | if (e.message.includes('net::ERR_NETWORK_CHANGED')) { 549 | console.log('net changed, retrying') 550 | 551 | return await this.request(config) 552 | } else if (e.message.includes('status 429')) { 553 | console.log('too many requests, waiting to retry', e) 554 | 555 | // return await new Promise(res => { 556 | // setTimeout( 557 | // async () => this.request(config).then(result => res(result)), 558 | // 1000 559 | // ) 560 | // }) 561 | } 562 | console.log('ERROR', e, config.body) 563 | } 564 | 565 | if (!result) { 566 | throw 'no result' 567 | } 568 | 569 | return result.json 570 | } 571 | 572 | private async loadDatabases() { 573 | const search = await this.request({ 574 | url: 'https://api.notion.com/v1/search', 575 | method: 'POST', 576 | body: { 577 | filter: { property: 'object', value: 'database' } 578 | } 579 | }) 580 | 581 | const databases = Object.fromEntries( 582 | search.results.map((database: DatabaseObjectResponse) => [ 583 | database.id, 584 | database 585 | ]) 586 | ) 587 | return databases 588 | } 589 | 590 | updateFile(id: string, file: NotionFile) { 591 | const defaultFile: NotionFile = { 592 | path: '' 593 | } 594 | 595 | const oldFile: NotionFile = { 596 | ...defaultFile, 597 | ...this.settings.databases[id] 598 | } 599 | 600 | this.setSetting({ 601 | databases: { 602 | ...this.settings.databases, 603 | [id]: { ...this.settings.databases[id], ...file } 604 | } 605 | }) 606 | 607 | if (oldFile.path !== file.path) { 608 | const oldFileObject = this.app.vault.getAbstractFileByPath( 609 | normalizePath(oldFile.path + '/' + getFileName(oldFile.path) + '.md') 610 | ) 611 | 612 | if (oldFileObject && !file.path) { 613 | this.app.vault.delete(oldFileObject) 614 | } else if (!oldFileObject && file.path) { 615 | this.createFile(file.path + '/' + getFileName(file.path)) 616 | } else if (oldFileObject && file.path) { 617 | const parent = this.app.vault.getAbstractFileByPath( 618 | normalizePath(oldFile.path) 619 | ) 620 | if (!parent) return 621 | this.app.fileManager.renameFile( 622 | oldFileObject, 623 | normalizePath(file.path + '/' + getFileName(file.path) + '.md') 624 | ) 625 | this.app.vault.rename(parent, file.path) 626 | } 627 | } 628 | } 629 | } 630 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | dependencies: 8 | '@notionhq/client': 9 | specifier: ^2.2.15 10 | version: 2.2.15 11 | '@types/lodash': 12 | specifier: ^4.17.9 13 | version: 4.17.9 14 | axios: 15 | specifier: ^1.7.7 16 | version: 1.7.7 17 | esbuild: 18 | specifier: ^0.24.0 19 | version: 0.24.0 20 | esbuild-copy-static-files: 21 | specifier: ^0.1.0 22 | version: 0.1.0 23 | esbuild-postcss: 24 | specifier: ^0.0.4 25 | version: 0.0.4(esbuild@0.24.0)(postcss@8.4.47) 26 | lodash: 27 | specifier: ^4.17.21 28 | version: 4.17.21 29 | luxon: 30 | specifier: ^3.5.0 31 | version: 3.5.0 32 | obsidian: 33 | specifier: ^1.7.2 34 | version: 1.7.2(@codemirror/state@6.4.1)(@codemirror/view@6.33.0) 35 | obsidian-dataview: 36 | specifier: ^0.5.67 37 | version: 0.5.67 38 | react: 39 | specifier: ^18.3.1 40 | version: 18.3.1 41 | react-dom: 42 | specifier: ^18.3.1 43 | version: 18.3.1(react@18.3.1) 44 | tailwindcss: 45 | specifier: ^3.4.12 46 | version: 3.4.12 47 | tiny-invariant: 48 | specifier: ^1.3.3 49 | version: 1.3.3 50 | 51 | devDependencies: 52 | autoprefixer: 53 | specifier: ^10.4.20 54 | version: 10.4.20(postcss@8.4.47) 55 | tslib: 56 | specifier: ^2.7.0 57 | version: 2.7.0 58 | 59 | packages: 60 | 61 | /@alloc/quick-lru@5.2.0: 62 | resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} 63 | engines: {node: '>=10'} 64 | dev: false 65 | 66 | /@codemirror/state@6.4.1: 67 | resolution: {integrity: sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==} 68 | dev: false 69 | 70 | /@codemirror/view@6.33.0: 71 | resolution: {integrity: sha512-AroaR3BvnjRW8fiZBalAaK+ZzB5usGgI014YKElYZvQdNH5ZIidHlO+cyf/2rWzyBFRkvG6VhiXeAEbC53P2YQ==} 72 | dependencies: 73 | '@codemirror/state': 6.4.1 74 | style-mod: 4.1.2 75 | w3c-keyname: 2.2.8 76 | dev: false 77 | 78 | /@esbuild/aix-ppc64@0.24.0: 79 | resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} 80 | engines: {node: '>=18'} 81 | cpu: [ppc64] 82 | os: [aix] 83 | requiresBuild: true 84 | dev: false 85 | optional: true 86 | 87 | /@esbuild/android-arm64@0.24.0: 88 | resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} 89 | engines: {node: '>=18'} 90 | cpu: [arm64] 91 | os: [android] 92 | requiresBuild: true 93 | dev: false 94 | optional: true 95 | 96 | /@esbuild/android-arm@0.24.0: 97 | resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} 98 | engines: {node: '>=18'} 99 | cpu: [arm] 100 | os: [android] 101 | requiresBuild: true 102 | dev: false 103 | optional: true 104 | 105 | /@esbuild/android-x64@0.24.0: 106 | resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} 107 | engines: {node: '>=18'} 108 | cpu: [x64] 109 | os: [android] 110 | requiresBuild: true 111 | dev: false 112 | optional: true 113 | 114 | /@esbuild/darwin-arm64@0.24.0: 115 | resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} 116 | engines: {node: '>=18'} 117 | cpu: [arm64] 118 | os: [darwin] 119 | requiresBuild: true 120 | dev: false 121 | optional: true 122 | 123 | /@esbuild/darwin-x64@0.24.0: 124 | resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} 125 | engines: {node: '>=18'} 126 | cpu: [x64] 127 | os: [darwin] 128 | requiresBuild: true 129 | dev: false 130 | optional: true 131 | 132 | /@esbuild/freebsd-arm64@0.24.0: 133 | resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} 134 | engines: {node: '>=18'} 135 | cpu: [arm64] 136 | os: [freebsd] 137 | requiresBuild: true 138 | dev: false 139 | optional: true 140 | 141 | /@esbuild/freebsd-x64@0.24.0: 142 | resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} 143 | engines: {node: '>=18'} 144 | cpu: [x64] 145 | os: [freebsd] 146 | requiresBuild: true 147 | dev: false 148 | optional: true 149 | 150 | /@esbuild/linux-arm64@0.24.0: 151 | resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} 152 | engines: {node: '>=18'} 153 | cpu: [arm64] 154 | os: [linux] 155 | requiresBuild: true 156 | dev: false 157 | optional: true 158 | 159 | /@esbuild/linux-arm@0.24.0: 160 | resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} 161 | engines: {node: '>=18'} 162 | cpu: [arm] 163 | os: [linux] 164 | requiresBuild: true 165 | dev: false 166 | optional: true 167 | 168 | /@esbuild/linux-ia32@0.24.0: 169 | resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} 170 | engines: {node: '>=18'} 171 | cpu: [ia32] 172 | os: [linux] 173 | requiresBuild: true 174 | dev: false 175 | optional: true 176 | 177 | /@esbuild/linux-loong64@0.24.0: 178 | resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} 179 | engines: {node: '>=18'} 180 | cpu: [loong64] 181 | os: [linux] 182 | requiresBuild: true 183 | dev: false 184 | optional: true 185 | 186 | /@esbuild/linux-mips64el@0.24.0: 187 | resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} 188 | engines: {node: '>=18'} 189 | cpu: [mips64el] 190 | os: [linux] 191 | requiresBuild: true 192 | dev: false 193 | optional: true 194 | 195 | /@esbuild/linux-ppc64@0.24.0: 196 | resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} 197 | engines: {node: '>=18'} 198 | cpu: [ppc64] 199 | os: [linux] 200 | requiresBuild: true 201 | dev: false 202 | optional: true 203 | 204 | /@esbuild/linux-riscv64@0.24.0: 205 | resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} 206 | engines: {node: '>=18'} 207 | cpu: [riscv64] 208 | os: [linux] 209 | requiresBuild: true 210 | dev: false 211 | optional: true 212 | 213 | /@esbuild/linux-s390x@0.24.0: 214 | resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} 215 | engines: {node: '>=18'} 216 | cpu: [s390x] 217 | os: [linux] 218 | requiresBuild: true 219 | dev: false 220 | optional: true 221 | 222 | /@esbuild/linux-x64@0.24.0: 223 | resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} 224 | engines: {node: '>=18'} 225 | cpu: [x64] 226 | os: [linux] 227 | requiresBuild: true 228 | dev: false 229 | optional: true 230 | 231 | /@esbuild/netbsd-x64@0.24.0: 232 | resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} 233 | engines: {node: '>=18'} 234 | cpu: [x64] 235 | os: [netbsd] 236 | requiresBuild: true 237 | dev: false 238 | optional: true 239 | 240 | /@esbuild/openbsd-arm64@0.24.0: 241 | resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} 242 | engines: {node: '>=18'} 243 | cpu: [arm64] 244 | os: [openbsd] 245 | requiresBuild: true 246 | dev: false 247 | optional: true 248 | 249 | /@esbuild/openbsd-x64@0.24.0: 250 | resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} 251 | engines: {node: '>=18'} 252 | cpu: [x64] 253 | os: [openbsd] 254 | requiresBuild: true 255 | dev: false 256 | optional: true 257 | 258 | /@esbuild/sunos-x64@0.24.0: 259 | resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} 260 | engines: {node: '>=18'} 261 | cpu: [x64] 262 | os: [sunos] 263 | requiresBuild: true 264 | dev: false 265 | optional: true 266 | 267 | /@esbuild/win32-arm64@0.24.0: 268 | resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} 269 | engines: {node: '>=18'} 270 | cpu: [arm64] 271 | os: [win32] 272 | requiresBuild: true 273 | dev: false 274 | optional: true 275 | 276 | /@esbuild/win32-ia32@0.24.0: 277 | resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} 278 | engines: {node: '>=18'} 279 | cpu: [ia32] 280 | os: [win32] 281 | requiresBuild: true 282 | dev: false 283 | optional: true 284 | 285 | /@esbuild/win32-x64@0.24.0: 286 | resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} 287 | engines: {node: '>=18'} 288 | cpu: [x64] 289 | os: [win32] 290 | requiresBuild: true 291 | dev: false 292 | optional: true 293 | 294 | /@isaacs/cliui@8.0.2: 295 | resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} 296 | engines: {node: '>=12'} 297 | dependencies: 298 | string-width: 5.1.2 299 | string-width-cjs: /string-width@4.2.3 300 | strip-ansi: 7.1.0 301 | strip-ansi-cjs: /strip-ansi@6.0.1 302 | wrap-ansi: 8.1.0 303 | wrap-ansi-cjs: /wrap-ansi@7.0.0 304 | dev: false 305 | 306 | /@jridgewell/gen-mapping@0.3.5: 307 | resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} 308 | engines: {node: '>=6.0.0'} 309 | dependencies: 310 | '@jridgewell/set-array': 1.2.1 311 | '@jridgewell/sourcemap-codec': 1.5.0 312 | '@jridgewell/trace-mapping': 0.3.25 313 | dev: false 314 | 315 | /@jridgewell/resolve-uri@3.1.2: 316 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 317 | engines: {node: '>=6.0.0'} 318 | dev: false 319 | 320 | /@jridgewell/set-array@1.2.1: 321 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} 322 | engines: {node: '>=6.0.0'} 323 | dev: false 324 | 325 | /@jridgewell/sourcemap-codec@1.5.0: 326 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 327 | dev: false 328 | 329 | /@jridgewell/trace-mapping@0.3.25: 330 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 331 | dependencies: 332 | '@jridgewell/resolve-uri': 3.1.2 333 | '@jridgewell/sourcemap-codec': 1.5.0 334 | dev: false 335 | 336 | /@lezer/common@1.2.1: 337 | resolution: {integrity: sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==} 338 | dev: false 339 | 340 | /@lezer/highlight@1.2.1: 341 | resolution: {integrity: sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==} 342 | dependencies: 343 | '@lezer/common': 1.2.1 344 | dev: false 345 | 346 | /@lezer/lr@1.4.2: 347 | resolution: {integrity: sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==} 348 | dependencies: 349 | '@lezer/common': 1.2.1 350 | dev: false 351 | 352 | /@nodelib/fs.scandir@2.1.5: 353 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 354 | engines: {node: '>= 8'} 355 | dependencies: 356 | '@nodelib/fs.stat': 2.0.5 357 | run-parallel: 1.2.0 358 | dev: false 359 | 360 | /@nodelib/fs.stat@2.0.5: 361 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 362 | engines: {node: '>= 8'} 363 | dev: false 364 | 365 | /@nodelib/fs.walk@1.2.8: 366 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 367 | engines: {node: '>= 8'} 368 | dependencies: 369 | '@nodelib/fs.scandir': 2.1.5 370 | fastq: 1.17.1 371 | dev: false 372 | 373 | /@notionhq/client@2.2.15: 374 | resolution: {integrity: sha512-XhdSY/4B1D34tSco/GION+23GMjaS9S2zszcqYkMHo8RcWInymF6L1x+Gk7EmHdrSxNFva2WM8orhC4BwQCwgw==} 375 | engines: {node: '>=12'} 376 | dependencies: 377 | '@types/node-fetch': 2.6.11 378 | node-fetch: 2.7.0 379 | transitivePeerDependencies: 380 | - encoding 381 | dev: false 382 | 383 | /@pkgjs/parseargs@0.11.0: 384 | resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 385 | engines: {node: '>=14'} 386 | requiresBuild: true 387 | dev: false 388 | optional: true 389 | 390 | /@types/codemirror@5.60.8: 391 | resolution: {integrity: sha512-VjFgDF/eB+Aklcy15TtOTLQeMjTo07k7KAjql8OK5Dirr7a6sJY4T1uVBDuTVG9VEmn1uUsohOpYnVfgC6/jyw==} 392 | dependencies: 393 | '@types/tern': 0.23.9 394 | dev: false 395 | 396 | /@types/estree@1.0.6: 397 | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} 398 | dev: false 399 | 400 | /@types/lodash@4.17.9: 401 | resolution: {integrity: sha512-w9iWudx1XWOHW5lQRS9iKpK/XuRhnN+0T7HvdCCd802FYkT1AMTnxndJHGrNJwRoRHkslGr4S29tjm1cT7x/7w==} 402 | dev: false 403 | 404 | /@types/node-fetch@2.6.11: 405 | resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==} 406 | dependencies: 407 | '@types/node': 22.5.5 408 | form-data: 4.0.0 409 | dev: false 410 | 411 | /@types/node@22.5.5: 412 | resolution: {integrity: sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==} 413 | dependencies: 414 | undici-types: 6.19.8 415 | dev: false 416 | 417 | /@types/tern@0.23.9: 418 | resolution: {integrity: sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==} 419 | dependencies: 420 | '@types/estree': 1.0.6 421 | dev: false 422 | 423 | /ansi-regex@5.0.1: 424 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 425 | engines: {node: '>=8'} 426 | dev: false 427 | 428 | /ansi-regex@6.1.0: 429 | resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} 430 | engines: {node: '>=12'} 431 | dev: false 432 | 433 | /ansi-styles@4.3.0: 434 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 435 | engines: {node: '>=8'} 436 | dependencies: 437 | color-convert: 2.0.1 438 | dev: false 439 | 440 | /ansi-styles@6.2.1: 441 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} 442 | engines: {node: '>=12'} 443 | dev: false 444 | 445 | /any-promise@1.3.0: 446 | resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} 447 | dev: false 448 | 449 | /anymatch@3.1.3: 450 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 451 | engines: {node: '>= 8'} 452 | dependencies: 453 | normalize-path: 3.0.0 454 | picomatch: 2.3.1 455 | dev: false 456 | 457 | /arg@5.0.2: 458 | resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} 459 | dev: false 460 | 461 | /asynckit@0.4.0: 462 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} 463 | dev: false 464 | 465 | /autoprefixer@10.4.20(postcss@8.4.47): 466 | resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} 467 | engines: {node: ^10 || ^12 || >=14} 468 | hasBin: true 469 | peerDependencies: 470 | postcss: ^8.1.0 471 | dependencies: 472 | browserslist: 4.23.3 473 | caniuse-lite: 1.0.30001662 474 | fraction.js: 4.3.7 475 | normalize-range: 0.1.2 476 | picocolors: 1.1.0 477 | postcss: 8.4.47 478 | postcss-value-parser: 4.2.0 479 | dev: true 480 | 481 | /axios@1.7.7: 482 | resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} 483 | dependencies: 484 | follow-redirects: 1.15.9 485 | form-data: 4.0.0 486 | proxy-from-env: 1.1.0 487 | transitivePeerDependencies: 488 | - debug 489 | dev: false 490 | 491 | /balanced-match@1.0.2: 492 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 493 | dev: false 494 | 495 | /binary-extensions@2.3.0: 496 | resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} 497 | engines: {node: '>=8'} 498 | dev: false 499 | 500 | /brace-expansion@2.0.1: 501 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 502 | dependencies: 503 | balanced-match: 1.0.2 504 | dev: false 505 | 506 | /braces@3.0.3: 507 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 508 | engines: {node: '>=8'} 509 | dependencies: 510 | fill-range: 7.1.1 511 | dev: false 512 | 513 | /browserslist@4.23.3: 514 | resolution: {integrity: sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==} 515 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 516 | hasBin: true 517 | dependencies: 518 | caniuse-lite: 1.0.30001662 519 | electron-to-chromium: 1.5.27 520 | node-releases: 2.0.18 521 | update-browserslist-db: 1.1.0(browserslist@4.23.3) 522 | dev: true 523 | 524 | /camelcase-css@2.0.1: 525 | resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} 526 | engines: {node: '>= 6'} 527 | dev: false 528 | 529 | /caniuse-lite@1.0.30001662: 530 | resolution: {integrity: sha512-sgMUVwLmGseH8ZIrm1d51UbrhqMCH3jvS7gF/M6byuHOnKyLOBL7W8yz5V02OHwgLGA36o/AFhWzzh4uc5aqTA==} 531 | dev: true 532 | 533 | /chokidar@3.6.0: 534 | resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} 535 | engines: {node: '>= 8.10.0'} 536 | dependencies: 537 | anymatch: 3.1.3 538 | braces: 3.0.3 539 | glob-parent: 5.1.2 540 | is-binary-path: 2.1.0 541 | is-glob: 4.0.3 542 | normalize-path: 3.0.0 543 | readdirp: 3.6.0 544 | optionalDependencies: 545 | fsevents: 2.3.3 546 | dev: false 547 | 548 | /color-convert@2.0.1: 549 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 550 | engines: {node: '>=7.0.0'} 551 | dependencies: 552 | color-name: 1.1.4 553 | dev: false 554 | 555 | /color-name@1.1.4: 556 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 557 | dev: false 558 | 559 | /combined-stream@1.0.8: 560 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} 561 | engines: {node: '>= 0.8'} 562 | dependencies: 563 | delayed-stream: 1.0.0 564 | dev: false 565 | 566 | /commander@4.1.1: 567 | resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} 568 | engines: {node: '>= 6'} 569 | dev: false 570 | 571 | /cross-spawn@7.0.3: 572 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 573 | engines: {node: '>= 8'} 574 | dependencies: 575 | path-key: 3.1.1 576 | shebang-command: 2.0.0 577 | which: 2.0.2 578 | dev: false 579 | 580 | /cssesc@3.0.0: 581 | resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} 582 | engines: {node: '>=4'} 583 | hasBin: true 584 | dev: false 585 | 586 | /delayed-stream@1.0.0: 587 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} 588 | engines: {node: '>=0.4.0'} 589 | dev: false 590 | 591 | /didyoumean@1.2.2: 592 | resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} 593 | dev: false 594 | 595 | /dlv@1.1.3: 596 | resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} 597 | dev: false 598 | 599 | /eastasianwidth@0.2.0: 600 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 601 | dev: false 602 | 603 | /electron-to-chromium@1.5.27: 604 | resolution: {integrity: sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw==} 605 | dev: true 606 | 607 | /emoji-regex@10.4.0: 608 | resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} 609 | dev: false 610 | 611 | /emoji-regex@8.0.0: 612 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 613 | dev: false 614 | 615 | /emoji-regex@9.2.2: 616 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} 617 | dev: false 618 | 619 | /esbuild-copy-static-files@0.1.0: 620 | resolution: {integrity: sha512-KlpmYqANA1t2nZavEdItfcOjJC6wbHA21v35HJWN32DddGTWKNNGDKljUzbCPojmpD+wAw8/DXr5abJ4jFCE0w==} 621 | dev: false 622 | 623 | /esbuild-postcss@0.0.4(esbuild@0.24.0)(postcss@8.4.47): 624 | resolution: {integrity: sha512-CKYibp+aCswskE+gBPnGZ0b9YyuY0n9w2dxyMaoLYEvGTwmjkRj5SV8l1zGJpw8KylqmcMTK0Gr349RnOLd+8A==} 625 | peerDependencies: 626 | esbuild: '*' 627 | postcss: ^8.0.0 628 | dependencies: 629 | esbuild: 0.24.0 630 | postcss: 8.4.47 631 | postcss-load-config: 3.1.4(postcss@8.4.47) 632 | transitivePeerDependencies: 633 | - ts-node 634 | dev: false 635 | 636 | /esbuild@0.24.0: 637 | resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} 638 | engines: {node: '>=18'} 639 | hasBin: true 640 | requiresBuild: true 641 | optionalDependencies: 642 | '@esbuild/aix-ppc64': 0.24.0 643 | '@esbuild/android-arm': 0.24.0 644 | '@esbuild/android-arm64': 0.24.0 645 | '@esbuild/android-x64': 0.24.0 646 | '@esbuild/darwin-arm64': 0.24.0 647 | '@esbuild/darwin-x64': 0.24.0 648 | '@esbuild/freebsd-arm64': 0.24.0 649 | '@esbuild/freebsd-x64': 0.24.0 650 | '@esbuild/linux-arm': 0.24.0 651 | '@esbuild/linux-arm64': 0.24.0 652 | '@esbuild/linux-ia32': 0.24.0 653 | '@esbuild/linux-loong64': 0.24.0 654 | '@esbuild/linux-mips64el': 0.24.0 655 | '@esbuild/linux-ppc64': 0.24.0 656 | '@esbuild/linux-riscv64': 0.24.0 657 | '@esbuild/linux-s390x': 0.24.0 658 | '@esbuild/linux-x64': 0.24.0 659 | '@esbuild/netbsd-x64': 0.24.0 660 | '@esbuild/openbsd-arm64': 0.24.0 661 | '@esbuild/openbsd-x64': 0.24.0 662 | '@esbuild/sunos-x64': 0.24.0 663 | '@esbuild/win32-arm64': 0.24.0 664 | '@esbuild/win32-ia32': 0.24.0 665 | '@esbuild/win32-x64': 0.24.0 666 | dev: false 667 | 668 | /escalade@3.2.0: 669 | resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} 670 | engines: {node: '>=6'} 671 | dev: true 672 | 673 | /fast-glob@3.3.2: 674 | resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} 675 | engines: {node: '>=8.6.0'} 676 | dependencies: 677 | '@nodelib/fs.stat': 2.0.5 678 | '@nodelib/fs.walk': 1.2.8 679 | glob-parent: 5.1.2 680 | merge2: 1.4.1 681 | micromatch: 4.0.8 682 | dev: false 683 | 684 | /fastq@1.17.1: 685 | resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} 686 | dependencies: 687 | reusify: 1.0.4 688 | dev: false 689 | 690 | /fill-range@7.1.1: 691 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 692 | engines: {node: '>=8'} 693 | dependencies: 694 | to-regex-range: 5.0.1 695 | dev: false 696 | 697 | /follow-redirects@1.15.9: 698 | resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} 699 | engines: {node: '>=4.0'} 700 | peerDependencies: 701 | debug: '*' 702 | peerDependenciesMeta: 703 | debug: 704 | optional: true 705 | dev: false 706 | 707 | /foreground-child@3.3.0: 708 | resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} 709 | engines: {node: '>=14'} 710 | dependencies: 711 | cross-spawn: 7.0.3 712 | signal-exit: 4.1.0 713 | dev: false 714 | 715 | /form-data@4.0.0: 716 | resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} 717 | engines: {node: '>= 6'} 718 | dependencies: 719 | asynckit: 0.4.0 720 | combined-stream: 1.0.8 721 | mime-types: 2.1.35 722 | dev: false 723 | 724 | /fraction.js@4.3.7: 725 | resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} 726 | dev: true 727 | 728 | /fsevents@2.3.3: 729 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 730 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 731 | os: [darwin] 732 | requiresBuild: true 733 | dev: false 734 | optional: true 735 | 736 | /function-bind@1.1.2: 737 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 738 | dev: false 739 | 740 | /glob-parent@5.1.2: 741 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 742 | engines: {node: '>= 6'} 743 | dependencies: 744 | is-glob: 4.0.3 745 | dev: false 746 | 747 | /glob-parent@6.0.2: 748 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 749 | engines: {node: '>=10.13.0'} 750 | dependencies: 751 | is-glob: 4.0.3 752 | dev: false 753 | 754 | /glob@10.4.5: 755 | resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} 756 | hasBin: true 757 | dependencies: 758 | foreground-child: 3.3.0 759 | jackspeak: 3.4.3 760 | minimatch: 9.0.5 761 | minipass: 7.1.2 762 | package-json-from-dist: 1.0.0 763 | path-scurry: 1.11.1 764 | dev: false 765 | 766 | /hasown@2.0.2: 767 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 768 | engines: {node: '>= 0.4'} 769 | dependencies: 770 | function-bind: 1.1.2 771 | dev: false 772 | 773 | /immediate@3.0.6: 774 | resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} 775 | dev: false 776 | 777 | /is-binary-path@2.1.0: 778 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 779 | engines: {node: '>=8'} 780 | dependencies: 781 | binary-extensions: 2.3.0 782 | dev: false 783 | 784 | /is-core-module@2.15.1: 785 | resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} 786 | engines: {node: '>= 0.4'} 787 | dependencies: 788 | hasown: 2.0.2 789 | dev: false 790 | 791 | /is-extglob@2.1.1: 792 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 793 | engines: {node: '>=0.10.0'} 794 | dev: false 795 | 796 | /is-fullwidth-code-point@3.0.0: 797 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 798 | engines: {node: '>=8'} 799 | dev: false 800 | 801 | /is-glob@4.0.3: 802 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 803 | engines: {node: '>=0.10.0'} 804 | dependencies: 805 | is-extglob: 2.1.1 806 | dev: false 807 | 808 | /is-number@7.0.0: 809 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 810 | engines: {node: '>=0.12.0'} 811 | dev: false 812 | 813 | /isexe@2.0.0: 814 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 815 | dev: false 816 | 817 | /jackspeak@3.4.3: 818 | resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} 819 | dependencies: 820 | '@isaacs/cliui': 8.0.2 821 | optionalDependencies: 822 | '@pkgjs/parseargs': 0.11.0 823 | dev: false 824 | 825 | /jiti@1.21.6: 826 | resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} 827 | hasBin: true 828 | dev: false 829 | 830 | /js-tokens@4.0.0: 831 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 832 | dev: false 833 | 834 | /lie@3.1.1: 835 | resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} 836 | dependencies: 837 | immediate: 3.0.6 838 | dev: false 839 | 840 | /lilconfig@2.1.0: 841 | resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} 842 | engines: {node: '>=10'} 843 | dev: false 844 | 845 | /lilconfig@3.1.2: 846 | resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} 847 | engines: {node: '>=14'} 848 | dev: false 849 | 850 | /lines-and-columns@1.2.4: 851 | resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} 852 | dev: false 853 | 854 | /localforage@1.10.0: 855 | resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==} 856 | dependencies: 857 | lie: 3.1.1 858 | dev: false 859 | 860 | /lodash@4.17.21: 861 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} 862 | dev: false 863 | 864 | /loose-envify@1.4.0: 865 | resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} 866 | hasBin: true 867 | dependencies: 868 | js-tokens: 4.0.0 869 | dev: false 870 | 871 | /lru-cache@10.4.3: 872 | resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} 873 | dev: false 874 | 875 | /luxon@3.5.0: 876 | resolution: {integrity: sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==} 877 | engines: {node: '>=12'} 878 | dev: false 879 | 880 | /merge2@1.4.1: 881 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 882 | engines: {node: '>= 8'} 883 | dev: false 884 | 885 | /micromatch@4.0.8: 886 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 887 | engines: {node: '>=8.6'} 888 | dependencies: 889 | braces: 3.0.3 890 | picomatch: 2.3.1 891 | dev: false 892 | 893 | /mime-db@1.52.0: 894 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} 895 | engines: {node: '>= 0.6'} 896 | dev: false 897 | 898 | /mime-types@2.1.35: 899 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} 900 | engines: {node: '>= 0.6'} 901 | dependencies: 902 | mime-db: 1.52.0 903 | dev: false 904 | 905 | /minimatch@9.0.5: 906 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 907 | engines: {node: '>=16 || 14 >=14.17'} 908 | dependencies: 909 | brace-expansion: 2.0.1 910 | dev: false 911 | 912 | /minipass@7.1.2: 913 | resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} 914 | engines: {node: '>=16 || 14 >=14.17'} 915 | dev: false 916 | 917 | /moment@2.29.4: 918 | resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==} 919 | dev: false 920 | 921 | /mz@2.7.0: 922 | resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} 923 | dependencies: 924 | any-promise: 1.3.0 925 | object-assign: 4.1.1 926 | thenify-all: 1.6.0 927 | dev: false 928 | 929 | /nanoid@3.3.7: 930 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} 931 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 932 | hasBin: true 933 | 934 | /node-fetch@2.7.0: 935 | resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} 936 | engines: {node: 4.x || >=6.0.0} 937 | peerDependencies: 938 | encoding: ^0.1.0 939 | peerDependenciesMeta: 940 | encoding: 941 | optional: true 942 | dependencies: 943 | whatwg-url: 5.0.0 944 | dev: false 945 | 946 | /node-releases@2.0.18: 947 | resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} 948 | dev: true 949 | 950 | /normalize-path@3.0.0: 951 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 952 | engines: {node: '>=0.10.0'} 953 | dev: false 954 | 955 | /normalize-range@0.1.2: 956 | resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} 957 | engines: {node: '>=0.10.0'} 958 | dev: true 959 | 960 | /object-assign@4.1.1: 961 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 962 | engines: {node: '>=0.10.0'} 963 | dev: false 964 | 965 | /object-hash@3.0.0: 966 | resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} 967 | engines: {node: '>= 6'} 968 | dev: false 969 | 970 | /obsidian-calendar-ui@0.3.12(@codemirror/state@6.4.1)(@codemirror/view@6.33.0): 971 | resolution: {integrity: sha512-hdoRqCPnukfRgCARgArXaqMQZ+Iai0eY7f0ZsFHHfywpv4gKg3Tx5p47UsLvRO5DD+4knlbrL7Gel57MkfcLTw==} 972 | dependencies: 973 | obsidian-daily-notes-interface: 0.8.4(@codemirror/state@6.4.1)(@codemirror/view@6.33.0) 974 | svelte: 3.35.0 975 | tslib: 2.1.0 976 | transitivePeerDependencies: 977 | - '@codemirror/state' 978 | - '@codemirror/view' 979 | dev: false 980 | 981 | /obsidian-daily-notes-interface@0.8.4(@codemirror/state@6.4.1)(@codemirror/view@6.33.0): 982 | resolution: {integrity: sha512-REKQtAuIOKDbvNH/th1C1gWmJWCP5tRn9T/mfZGZt4Zncgko7McXK0aSKFtEInipvgbZJ2nScivvyLdiWluSMw==} 983 | hasBin: true 984 | dependencies: 985 | obsidian: github.com/obsidianmd/obsidian-api/23947b58d372ea02225324308e31d36b4aa95869(@codemirror/state@6.4.1)(@codemirror/view@6.33.0) 986 | tslib: 2.1.0 987 | transitivePeerDependencies: 988 | - '@codemirror/state' 989 | - '@codemirror/view' 990 | dev: false 991 | 992 | /obsidian-dataview@0.5.67: 993 | resolution: {integrity: sha512-nLQrjvZ6Ny5s6mCfi+rv0TsdYkKTV4YfDqyLNixxNkyLCqgE9AXKJlJNnkv3Ic1brGOw2m/0SgtdWykKzobwMQ==} 994 | dependencies: 995 | '@codemirror/language': github.com/lishid/cm-language/2644bfc27afda707a7e1f3aedaf3ca7120f63cd9 996 | '@codemirror/state': 6.4.1 997 | '@codemirror/view': 6.33.0 998 | emoji-regex: 10.4.0 999 | localforage: 1.10.0 1000 | luxon: 3.5.0 1001 | obsidian-calendar-ui: 0.3.12(@codemirror/state@6.4.1)(@codemirror/view@6.33.0) 1002 | papaparse: 5.4.1 1003 | parsimmon: 1.18.1 1004 | preact: 10.24.0 1005 | dev: false 1006 | 1007 | /obsidian@1.7.2(@codemirror/state@6.4.1)(@codemirror/view@6.33.0): 1008 | resolution: {integrity: sha512-k9hN9brdknJC+afKr5FQzDRuEFGDKbDjfCazJwpgibwCAoZNYHYV8p/s3mM8I6AsnKrPKNXf8xGuMZ4enWelZQ==} 1009 | peerDependencies: 1010 | '@codemirror/state': ^6.0.0 1011 | '@codemirror/view': ^6.0.0 1012 | dependencies: 1013 | '@codemirror/state': 6.4.1 1014 | '@codemirror/view': 6.33.0 1015 | '@types/codemirror': 5.60.8 1016 | moment: 2.29.4 1017 | dev: false 1018 | 1019 | /package-json-from-dist@1.0.0: 1020 | resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} 1021 | dev: false 1022 | 1023 | /papaparse@5.4.1: 1024 | resolution: {integrity: sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==} 1025 | dev: false 1026 | 1027 | /parsimmon@1.18.1: 1028 | resolution: {integrity: sha512-u7p959wLfGAhJpSDJVYXoyMCXWYwHia78HhRBWqk7AIbxdmlrfdp5wX0l3xv/iTSH5HvhN9K7o26hwwpgS5Nmw==} 1029 | dev: false 1030 | 1031 | /path-key@3.1.1: 1032 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1033 | engines: {node: '>=8'} 1034 | dev: false 1035 | 1036 | /path-parse@1.0.7: 1037 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1038 | dev: false 1039 | 1040 | /path-scurry@1.11.1: 1041 | resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} 1042 | engines: {node: '>=16 || 14 >=14.18'} 1043 | dependencies: 1044 | lru-cache: 10.4.3 1045 | minipass: 7.1.2 1046 | dev: false 1047 | 1048 | /picocolors@1.1.0: 1049 | resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} 1050 | 1051 | /picomatch@2.3.1: 1052 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1053 | engines: {node: '>=8.6'} 1054 | dev: false 1055 | 1056 | /pify@2.3.0: 1057 | resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} 1058 | engines: {node: '>=0.10.0'} 1059 | dev: false 1060 | 1061 | /pirates@4.0.6: 1062 | resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} 1063 | engines: {node: '>= 6'} 1064 | dev: false 1065 | 1066 | /postcss-import@15.1.0(postcss@8.4.47): 1067 | resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} 1068 | engines: {node: '>=14.0.0'} 1069 | peerDependencies: 1070 | postcss: ^8.0.0 1071 | dependencies: 1072 | postcss: 8.4.47 1073 | postcss-value-parser: 4.2.0 1074 | read-cache: 1.0.0 1075 | resolve: 1.22.8 1076 | dev: false 1077 | 1078 | /postcss-js@4.0.1(postcss@8.4.47): 1079 | resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} 1080 | engines: {node: ^12 || ^14 || >= 16} 1081 | peerDependencies: 1082 | postcss: ^8.4.21 1083 | dependencies: 1084 | camelcase-css: 2.0.1 1085 | postcss: 8.4.47 1086 | dev: false 1087 | 1088 | /postcss-load-config@3.1.4(postcss@8.4.47): 1089 | resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} 1090 | engines: {node: '>= 10'} 1091 | peerDependencies: 1092 | postcss: '>=8.0.9' 1093 | ts-node: '>=9.0.0' 1094 | peerDependenciesMeta: 1095 | postcss: 1096 | optional: true 1097 | ts-node: 1098 | optional: true 1099 | dependencies: 1100 | lilconfig: 2.1.0 1101 | postcss: 8.4.47 1102 | yaml: 1.10.2 1103 | dev: false 1104 | 1105 | /postcss-load-config@4.0.2(postcss@8.4.47): 1106 | resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} 1107 | engines: {node: '>= 14'} 1108 | peerDependencies: 1109 | postcss: '>=8.0.9' 1110 | ts-node: '>=9.0.0' 1111 | peerDependenciesMeta: 1112 | postcss: 1113 | optional: true 1114 | ts-node: 1115 | optional: true 1116 | dependencies: 1117 | lilconfig: 3.1.2 1118 | postcss: 8.4.47 1119 | yaml: 2.5.1 1120 | dev: false 1121 | 1122 | /postcss-nested@6.2.0(postcss@8.4.47): 1123 | resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} 1124 | engines: {node: '>=12.0'} 1125 | peerDependencies: 1126 | postcss: ^8.2.14 1127 | dependencies: 1128 | postcss: 8.4.47 1129 | postcss-selector-parser: 6.1.2 1130 | dev: false 1131 | 1132 | /postcss-selector-parser@6.1.2: 1133 | resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} 1134 | engines: {node: '>=4'} 1135 | dependencies: 1136 | cssesc: 3.0.0 1137 | util-deprecate: 1.0.2 1138 | dev: false 1139 | 1140 | /postcss-value-parser@4.2.0: 1141 | resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} 1142 | 1143 | /postcss@8.4.47: 1144 | resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} 1145 | engines: {node: ^10 || ^12 || >=14} 1146 | dependencies: 1147 | nanoid: 3.3.7 1148 | picocolors: 1.1.0 1149 | source-map-js: 1.2.1 1150 | 1151 | /preact@10.24.0: 1152 | resolution: {integrity: sha512-aK8Cf+jkfyuZ0ZZRG9FbYqwmEiGQ4y/PUO4SuTWoyWL244nZZh7bd5h2APd4rSNDYTBNghg1L+5iJN3Skxtbsw==} 1153 | dev: false 1154 | 1155 | /proxy-from-env@1.1.0: 1156 | resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} 1157 | dev: false 1158 | 1159 | /queue-microtask@1.2.3: 1160 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1161 | dev: false 1162 | 1163 | /react-dom@18.3.1(react@18.3.1): 1164 | resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} 1165 | peerDependencies: 1166 | react: ^18.3.1 1167 | dependencies: 1168 | loose-envify: 1.4.0 1169 | react: 18.3.1 1170 | scheduler: 0.23.2 1171 | dev: false 1172 | 1173 | /react@18.3.1: 1174 | resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} 1175 | engines: {node: '>=0.10.0'} 1176 | dependencies: 1177 | loose-envify: 1.4.0 1178 | dev: false 1179 | 1180 | /read-cache@1.0.0: 1181 | resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} 1182 | dependencies: 1183 | pify: 2.3.0 1184 | dev: false 1185 | 1186 | /readdirp@3.6.0: 1187 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 1188 | engines: {node: '>=8.10.0'} 1189 | dependencies: 1190 | picomatch: 2.3.1 1191 | dev: false 1192 | 1193 | /resolve@1.22.8: 1194 | resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} 1195 | hasBin: true 1196 | dependencies: 1197 | is-core-module: 2.15.1 1198 | path-parse: 1.0.7 1199 | supports-preserve-symlinks-flag: 1.0.0 1200 | dev: false 1201 | 1202 | /reusify@1.0.4: 1203 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 1204 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1205 | dev: false 1206 | 1207 | /run-parallel@1.2.0: 1208 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1209 | dependencies: 1210 | queue-microtask: 1.2.3 1211 | dev: false 1212 | 1213 | /scheduler@0.23.2: 1214 | resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} 1215 | dependencies: 1216 | loose-envify: 1.4.0 1217 | dev: false 1218 | 1219 | /shebang-command@2.0.0: 1220 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1221 | engines: {node: '>=8'} 1222 | dependencies: 1223 | shebang-regex: 3.0.0 1224 | dev: false 1225 | 1226 | /shebang-regex@3.0.0: 1227 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1228 | engines: {node: '>=8'} 1229 | dev: false 1230 | 1231 | /signal-exit@4.1.0: 1232 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 1233 | engines: {node: '>=14'} 1234 | dev: false 1235 | 1236 | /source-map-js@1.2.1: 1237 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 1238 | engines: {node: '>=0.10.0'} 1239 | 1240 | /string-width@4.2.3: 1241 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 1242 | engines: {node: '>=8'} 1243 | dependencies: 1244 | emoji-regex: 8.0.0 1245 | is-fullwidth-code-point: 3.0.0 1246 | strip-ansi: 6.0.1 1247 | dev: false 1248 | 1249 | /string-width@5.1.2: 1250 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} 1251 | engines: {node: '>=12'} 1252 | dependencies: 1253 | eastasianwidth: 0.2.0 1254 | emoji-regex: 9.2.2 1255 | strip-ansi: 7.1.0 1256 | dev: false 1257 | 1258 | /strip-ansi@6.0.1: 1259 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1260 | engines: {node: '>=8'} 1261 | dependencies: 1262 | ansi-regex: 5.0.1 1263 | dev: false 1264 | 1265 | /strip-ansi@7.1.0: 1266 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} 1267 | engines: {node: '>=12'} 1268 | dependencies: 1269 | ansi-regex: 6.1.0 1270 | dev: false 1271 | 1272 | /style-mod@4.1.2: 1273 | resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==} 1274 | dev: false 1275 | 1276 | /sucrase@3.35.0: 1277 | resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} 1278 | engines: {node: '>=16 || 14 >=14.17'} 1279 | hasBin: true 1280 | dependencies: 1281 | '@jridgewell/gen-mapping': 0.3.5 1282 | commander: 4.1.1 1283 | glob: 10.4.5 1284 | lines-and-columns: 1.2.4 1285 | mz: 2.7.0 1286 | pirates: 4.0.6 1287 | ts-interface-checker: 0.1.13 1288 | dev: false 1289 | 1290 | /supports-preserve-symlinks-flag@1.0.0: 1291 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1292 | engines: {node: '>= 0.4'} 1293 | dev: false 1294 | 1295 | /svelte@3.35.0: 1296 | resolution: {integrity: sha512-gknlZkR2sXheu/X+B7dDImwANVvK1R0QGQLd8CNIfxxGPeXBmePnxfzb6fWwTQRsYQG7lYkZXvpXJvxvpsoB7g==} 1297 | engines: {node: '>= 8'} 1298 | dev: false 1299 | 1300 | /tailwindcss@3.4.12: 1301 | resolution: {integrity: sha512-Htf/gHj2+soPb9UayUNci/Ja3d8pTmu9ONTfh4QY8r3MATTZOzmv6UYWF7ZwikEIC8okpfqmGqrmDehua8mF8w==} 1302 | engines: {node: '>=14.0.0'} 1303 | hasBin: true 1304 | dependencies: 1305 | '@alloc/quick-lru': 5.2.0 1306 | arg: 5.0.2 1307 | chokidar: 3.6.0 1308 | didyoumean: 1.2.2 1309 | dlv: 1.1.3 1310 | fast-glob: 3.3.2 1311 | glob-parent: 6.0.2 1312 | is-glob: 4.0.3 1313 | jiti: 1.21.6 1314 | lilconfig: 2.1.0 1315 | micromatch: 4.0.8 1316 | normalize-path: 3.0.0 1317 | object-hash: 3.0.0 1318 | picocolors: 1.1.0 1319 | postcss: 8.4.47 1320 | postcss-import: 15.1.0(postcss@8.4.47) 1321 | postcss-js: 4.0.1(postcss@8.4.47) 1322 | postcss-load-config: 4.0.2(postcss@8.4.47) 1323 | postcss-nested: 6.2.0(postcss@8.4.47) 1324 | postcss-selector-parser: 6.1.2 1325 | resolve: 1.22.8 1326 | sucrase: 3.35.0 1327 | transitivePeerDependencies: 1328 | - ts-node 1329 | dev: false 1330 | 1331 | /thenify-all@1.6.0: 1332 | resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} 1333 | engines: {node: '>=0.8'} 1334 | dependencies: 1335 | thenify: 3.3.1 1336 | dev: false 1337 | 1338 | /thenify@3.3.1: 1339 | resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} 1340 | dependencies: 1341 | any-promise: 1.3.0 1342 | dev: false 1343 | 1344 | /tiny-invariant@1.3.3: 1345 | resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} 1346 | dev: false 1347 | 1348 | /to-regex-range@5.0.1: 1349 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1350 | engines: {node: '>=8.0'} 1351 | dependencies: 1352 | is-number: 7.0.0 1353 | dev: false 1354 | 1355 | /tr46@0.0.3: 1356 | resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} 1357 | dev: false 1358 | 1359 | /ts-interface-checker@0.1.13: 1360 | resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} 1361 | dev: false 1362 | 1363 | /tslib@2.1.0: 1364 | resolution: {integrity: sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==} 1365 | dev: false 1366 | 1367 | /tslib@2.7.0: 1368 | resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} 1369 | dev: true 1370 | 1371 | /undici-types@6.19.8: 1372 | resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} 1373 | dev: false 1374 | 1375 | /update-browserslist-db@1.1.0(browserslist@4.23.3): 1376 | resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} 1377 | hasBin: true 1378 | peerDependencies: 1379 | browserslist: '>= 4.21.0' 1380 | dependencies: 1381 | browserslist: 4.23.3 1382 | escalade: 3.2.0 1383 | picocolors: 1.1.0 1384 | dev: true 1385 | 1386 | /util-deprecate@1.0.2: 1387 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 1388 | dev: false 1389 | 1390 | /w3c-keyname@2.2.8: 1391 | resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} 1392 | dev: false 1393 | 1394 | /webidl-conversions@3.0.1: 1395 | resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} 1396 | dev: false 1397 | 1398 | /whatwg-url@5.0.0: 1399 | resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} 1400 | dependencies: 1401 | tr46: 0.0.3 1402 | webidl-conversions: 3.0.1 1403 | dev: false 1404 | 1405 | /which@2.0.2: 1406 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1407 | engines: {node: '>= 8'} 1408 | hasBin: true 1409 | dependencies: 1410 | isexe: 2.0.0 1411 | dev: false 1412 | 1413 | /wrap-ansi@7.0.0: 1414 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 1415 | engines: {node: '>=10'} 1416 | dependencies: 1417 | ansi-styles: 4.3.0 1418 | string-width: 4.2.3 1419 | strip-ansi: 6.0.1 1420 | dev: false 1421 | 1422 | /wrap-ansi@8.1.0: 1423 | resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} 1424 | engines: {node: '>=12'} 1425 | dependencies: 1426 | ansi-styles: 6.2.1 1427 | string-width: 5.1.2 1428 | strip-ansi: 7.1.0 1429 | dev: false 1430 | 1431 | /yaml@1.10.2: 1432 | resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} 1433 | engines: {node: '>= 6'} 1434 | dev: false 1435 | 1436 | /yaml@2.5.1: 1437 | resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==} 1438 | engines: {node: '>= 14'} 1439 | hasBin: true 1440 | dev: false 1441 | 1442 | github.com/lishid/cm-language/2644bfc27afda707a7e1f3aedaf3ca7120f63cd9: 1443 | resolution: {tarball: https://codeload.github.com/lishid/cm-language/tar.gz/2644bfc27afda707a7e1f3aedaf3ca7120f63cd9} 1444 | name: '@codemirror/language' 1445 | version: 6.10.1 1446 | prepare: true 1447 | requiresBuild: true 1448 | dependencies: 1449 | '@codemirror/state': 6.4.1 1450 | '@codemirror/view': 6.33.0 1451 | '@lezer/common': 1.2.1 1452 | '@lezer/highlight': 1.2.1 1453 | '@lezer/lr': 1.4.2 1454 | style-mod: 4.1.2 1455 | dev: false 1456 | 1457 | github.com/obsidianmd/obsidian-api/23947b58d372ea02225324308e31d36b4aa95869(@codemirror/state@6.4.1)(@codemirror/view@6.33.0): 1458 | resolution: {tarball: https://codeload.github.com/obsidianmd/obsidian-api/tar.gz/23947b58d372ea02225324308e31d36b4aa95869} 1459 | id: github.com/obsidianmd/obsidian-api/23947b58d372ea02225324308e31d36b4aa95869 1460 | name: obsidian 1461 | version: 1.7.2 1462 | peerDependencies: 1463 | '@codemirror/state': ^6.0.0 1464 | '@codemirror/view': ^6.0.0 1465 | dependencies: 1466 | '@codemirror/state': 6.4.1 1467 | '@codemirror/view': 6.33.0 1468 | '@types/codemirror': 5.60.8 1469 | moment: 2.29.4 1470 | dev: false 1471 | --------------------------------------------------------------------------------