diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..72201e7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +# top-most EditorConfig file +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +tab_width = 2 diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..32909b2 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +npm node_modules +build \ No newline at end of file diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..00ae081 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,21 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "env": { "node": true }, + "plugins": ["@typescript-eslint"], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + "parserOptions": { + "sourceType": "module" + }, + "rules": { + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": ["error", { "args": "none" }], + "@typescript-eslint/ban-ts-comment": "off", + "no-prototype-builtins": "off", + "@typescript-eslint/no-empty-function": "off" + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e09a007 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# vscode +.vscode + +# Intellij +*.iml +.idea + +# npm +node_modules + +# Don't include the compiled main.js file in the repo. +# They should be uploaded to GitHub releases instead. +main.js + +# Exclude sourcemaps +*.map + +# obsidian +data.json + +# Exclude macOS Finder (System Explorer) View States +.DS_Store diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..b973752 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +tag-version-prefix="" \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..4ec6023 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# Cloud uploader + +This plugins is under development. Cloudinary is the only provider at the moment + +## TODO / Ideas + +- [ ] Multiple Providers + - Maybe activate several providers and have rules per provider, e.g use a specific provider per folder (maybe private notes on paid provider and public ones in free server). +- [ ] Offline first + - Save images localy and upload them. + - `Plugin#.app.vault.configDir` has the .obsidian folder + - `Plugin#.app.vault.writeBinary` for writing a binary file + - `Plugin#.app.vault.config.attachmentFolderPath` has the attachment folder path + - [More info](https://github.com/aleksey-rezvov/obsidian-local-images/blob/master/src/contentProcessor.ts) + - Parse offline images to be previewed if exists, download if not + - There should be a render-hook for all images 🤔 + - [Maybe this?](https://github.com/bicarlsen/obsidian_image_caption/blob/main/src/view_observer.ts) diff --git a/esbuild.config.mjs b/esbuild.config.mjs new file mode 100644 index 0000000..31a41f4 --- /dev/null +++ b/esbuild.config.mjs @@ -0,0 +1,44 @@ +import esbuild from "esbuild"; +import process from "process"; +import builtins from "builtin-modules"; + +const banner = `/* +THIS IS A GENERATED/BUNDLED FILE BY ESBUILD +if you want to view the source, please visit the github repository of this plugin +*/ +`; + +const prod = process.argv[2] === "production"; + +esbuild + .build({ + banner: { + js: banner, + }, + entryPoints: ["src/main.ts"], + bundle: true, + external: [ + "obsidian", + "electron", + "@codemirror/autocomplete", + "@codemirror/collab", + "@codemirror/commands", + "@codemirror/language", + "@codemirror/lint", + "@codemirror/search", + "@codemirror/state", + "@codemirror/view", + "@lezer/common", + "@lezer/highlight", + "@lezer/lr", + ...builtins, + ], + format: "cjs", + watch: !prod, + target: "es2018", + logLevel: "info", + sourcemap: prod ? false : "inline", + treeShaking: true, + outfile: "main.js", + }) + .catch(() => process.exit(1)); diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..246f778 --- /dev/null +++ b/manifest.json @@ -0,0 +1,10 @@ +{ + "id": "cloud-uploader", + "name": "Cloud Uploader", + "version": "0.0.1", + "minAppVersion": "0.15.0", + "description": "Upload drop/paste images directly to the cloud", + "author": "Algus Dark", + "authorUrl": "https://algus.ninja", + "isDesktopOnly": true +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..3c3ada8 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "obsidian-cloud-uploader", + "version": "0.0.1", + "description": "Upload drop/paste images directly to a cloud provider", + "scripts": { + "dev": "node esbuild.config.mjs", + "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production", + "version": "node version-bump.mjs && git add manifest.json versions.json" + }, + "keywords": [], + "author": "Algus Dark", + "license": "MIT", + "devDependencies": { + "@types/node": "^16.11.6", + "@typescript-eslint/eslint-plugin": "5.29.0", + "@typescript-eslint/parser": "5.29.0", + "builtin-modules": "3.3.0", + "esbuild": "0.14.47", + "obsidian": "latest", + "tslib": "2.4.0", + "typescript": "4.7.4" + } +} diff --git a/src/events.ts b/src/events.ts new file mode 100644 index 0000000..664cde1 --- /dev/null +++ b/src/events.ts @@ -0,0 +1,11 @@ +export class CustomClipboardEvent extends ClipboardEvent { + constructor(type: string, eventInitDict: ClipboardEventInit) { + super(type, eventInitDict); + } +} + +export class CustomDragEvent extends DragEvent { + constructor(type: string, eventInitDict: DragEventInit) { + super(type, eventInitDict); + } +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..11e89dd --- /dev/null +++ b/src/main.ts @@ -0,0 +1,89 @@ +import { Plugin } from "obsidian"; + +import { CustomClipboardEvent, CustomDragEvent } from "@app/events"; +import { CloudUploaderSettings, DEFAULT_SETTINGS } from "@app/settings"; +import { handleUploadEvent } from "@app/utils"; +import { CloudinaryProvider } from "@app/providers/cloudinary"; + +import type { IProvider } from "@app/providers/manager"; + +declare module "obsidian" { + interface MarkdownSubView { + clipboardManager: { + handlePaste(e: ClipboardEvent): void; + handleDrop(e: DragEvent): void; + }; + } +} + +export default class CloudUploader extends Plugin { + settings: typeof DEFAULT_SETTINGS; + provider: IProvider; + + async onload() { + await this.loadSettings(); + + this.registerEvent( + this.app.workspace.on("editor-paste", (event, editor, markdownView) => { + handleUploadEvent({ + event, + editor, + provider: this.provider, + eventAllowDefault: (dataTransfer) => { + markdownView.currentMode.clipboardManager.handlePaste( + new CustomClipboardEvent(event.type, { + clipboardData: dataTransfer, + }) + ); + }, + }); + }) + ); + + this.registerEvent( + this.app.workspace.on("editor-drop", (event, editor, markdownView) => { + handleUploadEvent({ + event, + editor, + provider: this.provider, + eventAllowDefault: (dataTransfer) => { + markdownView.currentMode.clipboardManager.handleDrop( + new CustomDragEvent(event.type, { + clientX: event.clientX, + clientY: event.clientY, + dataTransfer, + }) + ); + }, + }); + }) + ); + + this.addSettingTab(new CloudUploaderSettings(this.app, this)); + } + + private setProvider() { + switch (this.settings.provider) { + case "cloudinary": + this.provider = new CloudinaryProvider(this.settings.cloudinary); + } + } + + private async loadSettings() { + this.settings = await Object.assign( + {}, + DEFAULT_SETTINGS, + await this.loadData() + ); + + this.setProvider(); + } + + async saveSettings() { + await this.saveData(this.settings); + + this.setProvider(); + } + + onunload() {} +} diff --git a/src/providers/cloudinary.ts b/src/providers/cloudinary.ts new file mode 100644 index 0000000..fb55935 --- /dev/null +++ b/src/providers/cloudinary.ts @@ -0,0 +1,202 @@ +import { Setting } from "obsidian"; + +import CloudUploader from "@app/main"; +import { ProviderBase } from "@app/providers/manager"; + +interface ICloudinarySettings { + cloud_name: string; + upload_preset: string; + folder: string; + use_formatter: boolean; + formatter: string; +} + +export const DEFAULT_SETTINGS: ICloudinarySettings = { + cloud_name: "", + upload_preset: "", + folder: "", + use_formatter: false, + formatter: + "https://{host}/{cloud_name}/{resource_type}/{type}/v{version}/{public_id}.{format}#{width}x{height},{colors|3}", +}; + +export class CloudinarySettings { + $container: HTMLElement; + plugin: T; + settings: ICloudinarySettings; + + constructor(container: HTMLElement, plugin: T) { + this.$container = container; + this.plugin = plugin; + + this.settings = { + ...DEFAULT_SETTINGS, + ...this.plugin.settings.cloudinary, + }; + + this.display(); + } + + display() { + this.$container.empty(); + const settings = this.settings; + + new Setting(this.$container) + .setName("Cloud Name") + .setDesc("The name of your Cloudinary Cloud Account") + .addText((text) => { + text + .setPlaceholder("") + .setValue(settings.cloud_name) + .onChange(async (value) => { + settings.cloud_name = value; + await this.plugin.saveSettings(); + }); + }); + + new Setting(this.$container) + .setName("Cloudinary Upload Template") + .setDesc("Cloudinary Upload Preference string") + .addText((text) => { + text + .setPlaceholder("") + .setValue(settings.upload_preset) + .onChange(async (value) => { + try { + settings.upload_preset = value; + await this.plugin.saveSettings(); + } catch (e) { + console.log(e); + } + }); + }); + + new Setting(this.$container) + .setName("Cloudinary Upload Folder") + .setDesc( + "Folder name to use in Cloudinary. Note, this will be ignored if you have a folder set in your Cloudinary Upload Preset" + ) + .addText((text) => { + text + .setPlaceholder("") + .setValue(settings.folder) + .onChange(async (value) => { + try { + settings.folder = value; + await this.plugin.saveSettings(); + } catch (e) { + console.log(e); + } + }); + }); + + new Setting(this.$container) + .setName("Use formatter") + .setDesc( + "A formatter defines the final url of your image. By default it returns the URL without any special changes." + ) + .addToggle((toggle) => { + toggle + .setValue(settings.use_formatter) + .onChange(async (enable_formatter) => { + settings.use_formatter = enable_formatter; + await this.plugin.saveSettings(); + this.display(); + }); + }); + + const formatterSettings = new Setting(this.$container).addText((text) => { + text + .setPlaceholder("") + .setValue(settings.formatter) + .onChange(async (value) => { + try { + settings.formatter = value; + await this.plugin.saveSettings(); + } catch (e) { + console.log(e); + } + }) + .inputEl.addClass("cloud-flex-full"); + }); + + formatterSettings.settingEl.toggle(settings.use_formatter); + formatterSettings.controlEl.addClass("cloud-full-width"); + formatterSettings.infoEl.remove(); + + return this.$container; + } +} + +interface CloudinaryUploadResponse { + asset_id: string; + public_id: string; + version: number; + version_id: string; + signature: string; + width: number; + height: number; + format: string; + resource_type: string; + created_at: string; + tags: Array; + pages: number; + type: string; + etag: string; + placeholder: boolean; + url: string; + secure_url: string; + folder: string; + access_mode: string; + existing: boolean; + colors: [string, number][]; + [futureKey: string]: any; +} + +export class CloudinaryProvider extends ProviderBase { + settings: ICloudinarySettings; + + constructor(settings: ICloudinarySettings) { + super(settings); + } + + upload({ file, uuid }: { file: File; uuid: string }) { + const formData = new FormData(); + formData.append("file", file); + formData.append("upload_preset", this.settings.upload_preset); + formData.append("public_id", uuid); + formData.append("folder", this.settings.folder); + + const API_URL = `https://api.cloudinary.com/v1_1/${this.settings.cloud_name}/auto/upload`; + + return fetch(API_URL, { method: "POST", body: formData }) + .then((res) => res.json()) + .then((json: CloudinaryUploadResponse) => { + if (!this.settings.formatter || !this.settings.use_formatter) + return json.secure_url; + + const regex = /{({*[^{}]*}*)}/g; + + return this.settings.formatter.replace(regex, (_, $1) => { + if ($1.includes("colors")) { + return json.colors + .reduce<[string?]>((prev, current) => { + prev.push(current[0].substring(1)); + return prev; + }, []) + .slice(0, $1.split("|")[1]) + .join(","); + } + + switch ($1) { + case "host": + return new URL(json.secure_url).host; + case "cloud_name": + return this.settings.cloud_name; + default: + return json[$1]; + } + }); + }); + } +} diff --git a/src/providers/manager.ts b/src/providers/manager.ts new file mode 100644 index 0000000..30152e9 --- /dev/null +++ b/src/providers/manager.ts @@ -0,0 +1,35 @@ +import { + CloudinaryProvider, + DEFAULT_SETTINGS as CLOUDINARY_SETTINGS, +} from "@app/providers/cloudinary"; + +export interface IProviders { + cloudinary: { + settings: typeof CLOUDINARY_SETTINGS; + provider: CloudinaryProvider; + }; +} + +type GetProvider = + keyof IProviders extends infer K + ? K extends keyof IProviders + ? IProviders[K][T] + : never + : never; + +export type IProvider = GetProvider<"provider">; + +interface UploadParams { + file: File; + uuid: string; +} + +export abstract class ProviderBase> { + protected settings: T; + + constructor(settings: T) { + this.settings = settings; + } + + abstract upload(uploadParams: UploadParams): Promise; +} diff --git a/src/settings.ts b/src/settings.ts new file mode 100644 index 0000000..dd70649 --- /dev/null +++ b/src/settings.ts @@ -0,0 +1,65 @@ +import { App, PluginSettingTab, Setting } from "obsidian"; + +import CloudUploader from "@app/main"; +import { + CloudinarySettings, + DEFAULT_SETTINGS as CLOUDINARY_SETTINGS, +} from "@app/providers/cloudinary"; +import { capitalize } from "@app/utils"; +import { IProviders } from "@app/providers/manager"; + +export type ICloudUploaderSettings = keyof IProviders extends infer K + ? K extends keyof IProviders + ? { provider: K } & { [key in K]: IProviders[K]["settings"] } + : never + : never; + +export const DEFAULT_SETTINGS: ICloudUploaderSettings = { + provider: "cloudinary", + cloudinary: { ...CLOUDINARY_SETTINGS }, +}; + +export class CloudUploaderSettings extends PluginSettingTab { + plugin: CloudUploader; + + constructor(app: App, plugin: CloudUploader) { + super(app, plugin); + this.plugin = plugin; + } + + display() { + const $container = this.containerEl; + + $container.empty(); + $container.createEl("h1", { text: "Cloud Uploader Settings" }); + + new Setting($container) + .setName("Cloud Provider") + .setDesc("Choose a cloud provider to upload your media") + .addDropdown(($dropdown) => { + for (let [provider] of Object.entries(this.plugin.settings)) { + if (provider !== "provider") { + $dropdown.addOption(provider, capitalize(provider)); + } + } + + $dropdown.setValue(this.plugin.settings.provider); + + $dropdown.onChange( + async (value: typeof this.plugin.settings.provider) => { + this.plugin.settings.provider = value; + await this.plugin.saveSettings(); + this.display(); + } + ); + }); + + const $div = $container.createDiv(); + $div.addClass("cloud-provider-setting-item"); + + switch (this.plugin.settings.provider) { + case "cloudinary": + return new CloudinarySettings($div, this.plugin); + } + } +} diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..45389c3 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,114 @@ +import { Editor, Notice } from "obsidian"; +import { CustomClipboardEvent, CustomDragEvent } from "@app/events"; + +import type { IProvider } from "@app/providers/manager"; + +export function replaceText( + editor: Editor, + line: number, + target: string, + replacement: string +): void { + function replaceRange(line: number, ch: number) { + const from = { line, ch }; + const to = { line, ch: ch + target.length }; + + editor.replaceRange(replacement, from, to); + } + + let ch = editor.getLine(line).indexOf(target); + + // Direct replacement + if (ch !== -1) { + return replaceRange(line, ch); + } else { + // lookup replacement + // TODO: How about creating an observer for the line? + for (let i = 0; i < editor.lineCount(); i++) { + const ch = editor.getLine(i).indexOf(target); + if (ch !== -1) { + return replaceRange(i, ch); + } + } + } + + // TODO: If not found; let's add the image at the bottom of the page +} + +interface UploadEventParams { + event: ClipboardEvent | DragEvent; + editor: Editor; + provider: IProvider; + eventAllowDefault: (dataTransfer: DataTransfer) => void; +} + +export function handleUploadEvent({ + event, + editor, + provider, + eventAllowDefault, +}: UploadEventParams) { + if (event instanceof CustomClipboardEvent || event instanceof CustomDragEvent) + return; + + let data; + + if (event instanceof ClipboardEvent) { + data = event.clipboardData; + } else { + data = event.dataTransfer; + } + + if (data?.files.length) { + event.preventDefault(); + + const { files } = data; + let dataTransfer; + + for (let i = 0; i < files.length; i++) { + const file = files[i]; + + if (!file.type.startsWith("image")) { + if (!dataTransfer) { + dataTransfer = new DataTransfer(); + } + + dataTransfer.items.add(file); + continue; + } + + const uuid: string = self.crypto.randomUUID(); + const placeholder = `![uploading...](${uuid})`; + + if (editor.getLine(editor.getCursor().line).length != 0) { + editor.setCursor(editor.lineCount(), 0); + editor.replaceSelection("\n"); + } + + editor.replaceSelection(placeholder); + const line = editor.getCursor().line; + + // TODO: Limit batch uploads + console.log("sup"); + provider + .upload({ file, uuid }) + .then((url) => { + replaceText(editor, line, placeholder.trim(), `![](${url})`); + }) + .catch((error) => new Notice(error, 5000)); + } + + if (dataTransfer?.files.length) { + if (editor.getLine(editor.getCursor().line).length != 0) { + editor.setCursor(editor.lineCount(), 0); + editor.replaceSelection("\n"); + } + + eventAllowDefault(dataTransfer); + } + } +} + +export function capitalize(str: string) { + return str.charAt(0).toUpperCase() + str.slice(1); +} diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..90d2a62 --- /dev/null +++ b/styles.css @@ -0,0 +1,29 @@ +.cloud-provider-setting-item { + padding: 0.75em 0; + border-top: 1px solid var(--background-modifier-border); +} + +.cloud-provider-setting-item:empty { + padding: 0; + border: 0; +} + +.cloud-full-width { + width: 100%; +} + +.cloud-flex-full { + flex: 1; +} + +.cloud-direction-column { + flex-direction: column; +} + +.cloud-align-start { + align-items: flex-start; +} + +.cloud-stack > * + * { + margin-block-start: 1.5rem; +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..d3a8d24 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@app/*": ["src/*"] + }, + "inlineSourceMap": true, + "inlineSources": true, + "module": "ESNext", + "target": "ES6", + "allowJs": true, + "noImplicitAny": true, + "moduleResolution": "node", + "importHelpers": true, + "isolatedModules": true, + "strictNullChecks": true, + "lib": ["DOM", "ES5", "ES6", "ES7"] + }, + "include": ["**/*.ts"] +} diff --git a/version-bump.mjs b/version-bump.mjs new file mode 100644 index 0000000..d409fa0 --- /dev/null +++ b/version-bump.mjs @@ -0,0 +1,14 @@ +import { readFileSync, writeFileSync } from "fs"; + +const targetVersion = process.env.npm_package_version; + +// read minAppVersion from manifest.json and bump version to target version +let manifest = JSON.parse(readFileSync("manifest.json", "utf8")); +const { minAppVersion } = manifest; +manifest.version = targetVersion; +writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t")); + +// update versions.json with target version and minAppVersion from manifest.json +let versions = JSON.parse(readFileSync("versions.json", "utf8")); +versions[targetVersion] = minAppVersion; +writeFileSync("versions.json", JSON.stringify(versions, null, "\t")); diff --git a/versions.json b/versions.json new file mode 100644 index 0000000..ad24e42 --- /dev/null +++ b/versions.json @@ -0,0 +1,3 @@ +{ + "0.0.1": "0.15.0" +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..20514ee --- /dev/null +++ b/yarn.lock @@ -0,0 +1,519 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@types/codemirror@0.0.108": + version "0.0.108" + resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-0.0.108.tgz#e640422b666bf49251b384c390cdeb2362585bde" + integrity sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw== + dependencies: + "@types/tern" "*" + +"@types/estree@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + +"@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/node@^16.11.6": + version "16.18.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.3.tgz#d7f7ba828ad9e540270f01ce00d391c54e6e0abc" + integrity sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg== + +"@types/tern@*": + version "0.23.4" + resolved "https://registry.yarnpkg.com/@types/tern/-/tern-0.23.4.tgz#03926eb13dbeaf3ae0d390caf706b2643a0127fb" + integrity sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg== + dependencies: + "@types/estree" "*" + +"@typescript-eslint/eslint-plugin@5.29.0": + version "5.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz#c67794d2b0fd0b4a47f50266088acdc52a08aab6" + integrity sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w== + dependencies: + "@typescript-eslint/scope-manager" "5.29.0" + "@typescript-eslint/type-utils" "5.29.0" + "@typescript-eslint/utils" "5.29.0" + debug "^4.3.4" + functional-red-black-tree "^1.0.1" + ignore "^5.2.0" + regexpp "^3.2.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@5.29.0": + version "5.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.29.0.tgz#41314b195b34d44ff38220caa55f3f93cfca43cf" + integrity sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw== + dependencies: + "@typescript-eslint/scope-manager" "5.29.0" + "@typescript-eslint/types" "5.29.0" + "@typescript-eslint/typescript-estree" "5.29.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.29.0": + version "5.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz#2a6a32e3416cb133e9af8dcf54bf077a916aeed3" + integrity sha512-etbXUT0FygFi2ihcxDZjz21LtC+Eps9V2xVx09zFoN44RRHPrkMflidGMI+2dUs821zR1tDS6Oc9IXxIjOUZwA== + dependencies: + "@typescript-eslint/types" "5.29.0" + "@typescript-eslint/visitor-keys" "5.29.0" + +"@typescript-eslint/type-utils@5.29.0": + version "5.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz#241918001d164044020b37d26d5b9f4e37cc3d5d" + integrity sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg== + dependencies: + "@typescript-eslint/utils" "5.29.0" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.29.0": + version "5.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.29.0.tgz#7861d3d288c031703b2d97bc113696b4d8c19aab" + integrity sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg== + +"@typescript-eslint/typescript-estree@5.29.0": + version "5.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz#e83d19aa7fd2e74616aab2f25dfbe4de4f0b5577" + integrity sha512-mQvSUJ/JjGBdvo+1LwC+GY2XmSYjK1nAaVw2emp/E61wEVYEyibRHCqm1I1vEKbXCpUKuW4G7u9ZCaZhJbLoNQ== + dependencies: + "@typescript-eslint/types" "5.29.0" + "@typescript-eslint/visitor-keys" "5.29.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.29.0": + version "5.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.29.0.tgz#775046effd5019667bd086bcf326acbe32cd0082" + integrity sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.29.0" + "@typescript-eslint/types" "5.29.0" + "@typescript-eslint/typescript-estree" "5.29.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/visitor-keys@5.29.0": + version "5.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz#7a4749fa7ef5160c44a451bf060ac1dc6dfb77ee" + integrity sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ== + dependencies: + "@typescript-eslint/types" "5.29.0" + eslint-visitor-keys "^3.3.0" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +braces@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +builtin-modules@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" + integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== + +debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +esbuild-android-64@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.47.tgz#ef95b42c67bcf4268c869153fa3ad1466c4cea6b" + integrity sha512-R13Bd9+tqLVFndncMHssZrPWe6/0Kpv2/dt4aA69soX4PRxlzsVpCvoJeFE8sOEoeVEiBkI0myjlkDodXlHa0g== + +esbuild-android-arm64@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.47.tgz#4ebd7ce9fb250b4695faa3ee46fd3b0754ecd9e6" + integrity sha512-OkwOjj7ts4lBp/TL6hdd8HftIzOy/pdtbrNA4+0oVWgGG64HrdVzAF5gxtJufAPOsEjkyh1oIYvKAUinKKQRSQ== + +esbuild-darwin-64@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.47.tgz#e0da6c244f497192f951807f003f6a423ed23188" + integrity sha512-R6oaW0y5/u6Eccti/TS6c/2c1xYTb1izwK3gajJwi4vIfNs1s8B1dQzI1UiC9T61YovOQVuePDcfqHLT3mUZJA== + +esbuild-darwin-arm64@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.47.tgz#cd40fd49a672fca581ed202834239dfe540a9028" + integrity sha512-seCmearlQyvdvM/noz1L9+qblC5vcBrhUaOoLEDDoLInF/VQ9IkobGiLlyTPYP5dW1YD4LXhtBgOyevoIHGGnw== + +esbuild-freebsd-64@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.47.tgz#8da6a14c095b29c01fc8087a16cb7906debc2d67" + integrity sha512-ZH8K2Q8/Ux5kXXvQMDsJcxvkIwut69KVrYQhza/ptkW50DC089bCVrJZZ3sKzIoOx+YPTrmsZvqeZERjyYrlvQ== + +esbuild-freebsd-arm64@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.47.tgz#ad31f9c92817ff8f33fd253af7ab5122dc1b83f6" + integrity sha512-ZJMQAJQsIOhn3XTm7MPQfCzEu5b9STNC+s90zMWe2afy9EwnHV7Ov7ohEMv2lyWlc2pjqLW8QJnz2r0KZmeAEQ== + +esbuild-linux-32@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.47.tgz#de085e4db2e692ea30c71208ccc23fdcf5196c58" + integrity sha512-FxZOCKoEDPRYvq300lsWCTv1kcHgiiZfNrPtEhFAiqD7QZaXrad8LxyJ8fXGcWzIFzRiYZVtB3ttvITBvAFhKw== + +esbuild-linux-64@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.47.tgz#2a9321bbccb01f01b04cebfcfccbabeba3658ba1" + integrity sha512-nFNOk9vWVfvWYF9YNYksZptgQAdstnDCMtR6m42l5Wfugbzu11VpMCY9XrD4yFxvPo9zmzcoUL/88y0lfJZJJw== + +esbuild-linux-arm64@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.47.tgz#b9da7b6fc4b0ca7a13363a0c5b7bb927e4bc535a" + integrity sha512-ywfme6HVrhWcevzmsufjd4iT3PxTfCX9HOdxA7Hd+/ZM23Y9nXeb+vG6AyA6jgq/JovkcqRHcL9XwRNpWG6XRw== + +esbuild-linux-arm@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.47.tgz#56fec2a09b9561c337059d4af53625142aded853" + integrity sha512-ZGE1Bqg/gPRXrBpgpvH81tQHpiaGxa8c9Rx/XOylkIl2ypLuOcawXEAo8ls+5DFCcRGt/o3sV+PzpAFZobOsmA== + +esbuild-linux-mips64le@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.47.tgz#9db21561f8f22ed79ef2aedb7bbef082b46cf823" + integrity sha512-mg3D8YndZ1LvUiEdDYR3OsmeyAew4MA/dvaEJxvyygahWmpv1SlEEnhEZlhPokjsUMfRagzsEF/d/2XF+kTQGg== + +esbuild-linux-ppc64le@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.47.tgz#dc3a3da321222b11e96e50efafec9d2de408198b" + integrity sha512-WER+f3+szmnZiWoK6AsrTKGoJoErG2LlauSmk73LEZFQ/iWC+KhhDsOkn1xBUpzXWsxN9THmQFltLoaFEH8F8w== + +esbuild-linux-riscv64@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.47.tgz#9bd6dcd3dca6c0357084ecd06e1d2d4bf105335f" + integrity sha512-1fI6bP3A3rvI9BsaaXbMoaOjLE3lVkJtLxsgLHqlBhLlBVY7UqffWBvkrX/9zfPhhVMd9ZRFiaqXnB1T7BsL2g== + +esbuild-linux-s390x@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.47.tgz#a458af939b52f2cd32fc561410d441a51f69d41f" + integrity sha512-eZrWzy0xFAhki1CWRGnhsHVz7IlSKX6yT2tj2Eg8lhAwlRE5E96Hsb0M1mPSE1dHGpt1QVwwVivXIAacF/G6mw== + +esbuild-netbsd-64@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.47.tgz#6388e785d7e7e4420cb01348d7483ab511b16aa8" + integrity sha512-Qjdjr+KQQVH5Q2Q1r6HBYswFTToPpss3gqCiSw2Fpq/ua8+eXSQyAMG+UvULPqXceOwpnPo4smyZyHdlkcPppQ== + +esbuild-openbsd-64@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.47.tgz#309af806db561aa886c445344d1aacab850dbdc5" + integrity sha512-QpgN8ofL7B9z8g5zZqJE+eFvD1LehRlxr25PBkjyyasakm4599iroUpaj96rdqRlO2ShuyqwJdr+oNqWwTUmQw== + +esbuild-sunos-64@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.47.tgz#3f19612dcdb89ba6c65283a7ff6e16f8afbf8aaa" + integrity sha512-uOeSgLUwukLioAJOiGYm3kNl+1wJjgJA8R671GYgcPgCx7QR73zfvYqXFFcIO93/nBdIbt5hd8RItqbbf3HtAQ== + +esbuild-windows-32@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.47.tgz#a92d279c8458d5dc319abcfeb30aa49e8f2e6f7f" + integrity sha512-H0fWsLTp2WBfKLBgwYT4OTfFly4Im/8B5f3ojDv1Kx//kiubVY0IQunP2Koc/fr/0wI7hj3IiBDbSrmKlrNgLQ== + +esbuild-windows-64@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.47.tgz#2564c3fcf0c23d701edb71af8c52d3be4cec5f8a" + integrity sha512-/Pk5jIEH34T68r8PweKRi77W49KwanZ8X6lr3vDAtOlH5EumPE4pBHqkCUdELanvsT14yMXLQ/C/8XPi1pAtkQ== + +esbuild-windows-arm64@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.47.tgz#86d9db1a22d83360f726ac5fba41c2f625db6878" + integrity sha512-HFSW2lnp62fl86/qPQlqw6asIwCnEsEoNIL1h2uVMgakddf+vUuMcCbtUY1i8sst7KkgHrVKCJQB33YhhOweCQ== + +esbuild@0.14.47: + version "0.14.47" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.47.tgz#0d6415f6bd8eb9e73a58f7f9ae04c5276cda0e4d" + integrity sha512-wI4ZiIfFxpkuxB8ju4MHrGwGLyp1+awEHAHVpx6w7a+1pmYIq8T9FGEVVwFo0iFierDoMj++Xq69GXWYn2EiwA== + optionalDependencies: + esbuild-android-64 "0.14.47" + esbuild-android-arm64 "0.14.47" + esbuild-darwin-64 "0.14.47" + esbuild-darwin-arm64 "0.14.47" + esbuild-freebsd-64 "0.14.47" + esbuild-freebsd-arm64 "0.14.47" + esbuild-linux-32 "0.14.47" + esbuild-linux-64 "0.14.47" + esbuild-linux-arm "0.14.47" + esbuild-linux-arm64 "0.14.47" + esbuild-linux-mips64le "0.14.47" + esbuild-linux-ppc64le "0.14.47" + esbuild-linux-riscv64 "0.14.47" + esbuild-linux-s390x "0.14.47" + esbuild-netbsd-64 "0.14.47" + esbuild-openbsd-64 "0.14.47" + esbuild-sunos-64 "0.14.47" + esbuild-windows-32 "0.14.47" + esbuild-windows-64 "0.14.47" + esbuild-windows-arm64 "0.14.47" + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fastq@^1.6.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + dependencies: + reusify "^1.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +ignore@^5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.1.tgz#c2b1f76cb999ede1502f3a226a9310fdfe88d46c" + integrity sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +moment@2.29.4: + version "2.29.4" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" + integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +obsidian@latest: + version "0.16.3" + resolved "https://registry.yarnpkg.com/obsidian/-/obsidian-0.16.3.tgz#137b7e91f949517a1bc817b1d7ef9b8aefb219bc" + integrity sha512-hal9qk1A0GMhHSeLr2/+o3OpLmImiP+Y+sx2ewP13ds76KXsziG96n+IPFT0mSkup1zSwhEu+DeRhmbcyCCXWw== + dependencies: + "@types/codemirror" "0.0.108" + moment "2.29.4" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +regexpp@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +semver@^7.3.7: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + dependencies: + lru-cache "^6.0.0" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tslib@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +typescript@4.7.4: + version "4.7.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" + integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==