From 48b7c27b465b07d2c1f409ba86124c4fbabfe4b1 Mon Sep 17 00:00:00 2001 From: Hoang Nam Date: Sun, 16 Mar 2025 16:26:27 +0700 Subject: [PATCH] Initial commit: Task Progress Bar plugin for Obsidian --- main.ts | 587 +++++++++++++++++++++++++++++++++++++++++++------- manifest.json | 12 +- package.json | 8 +- styles.css | 189 ++++++++++++++++ yarn.lock | 517 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1230 insertions(+), 83 deletions(-) create mode 100644 yarn.lock diff --git a/main.ts b/main.ts index 2d07212..77d4b9d 100644 --- a/main.ts +++ b/main.ts @@ -1,85 +1,278 @@ -import { App, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian'; +import { App, Plugin, PluginSettingTab, Setting, WorkspaceLeaf, TFile, MarkdownView, ItemView, Editor, MarkdownPostProcessorContext, debounce, Notice } from 'obsidian'; -// Remember to rename these classes and interfaces! +// Định nghĩa interface cho DataviewAPI +interface DataviewApi { + executeJs(code: string, container: HTMLElement, sourcePath?: string): Promise; + page(path: string): any; + pages(source: string): any[]; + // Không sử dụng eval vì có thể không tồn tại trong một số phiên bản Dataview +} -interface MyPluginSettings { +// Định nghĩa interface cho window object để truy cập Dataview plugin +declare global { + interface Window { + DataviewAPI?: DataviewApi; + } +} + +// Hàm helper để lấy Dataview API +function getDataviewAPI(app: App): DataviewApi | null { + // Cách 1: Thông qua window object + // @ts-ignore + if (window.DataviewAPI) { + return window.DataviewAPI; + } + + // Cách 2: Thông qua app.plugins + // @ts-ignore + const dataviewPlugin = app.plugins?.plugins?.dataview; + if (dataviewPlugin && dataviewPlugin.api) { + return dataviewPlugin.api; + } + + // Cách 3: Kiểm tra xem plugin có được enable không + // @ts-ignore + if (app.plugins.enabledPlugins.has('dataview')) { + console.log('Dataview plugin is enabled but API is not available yet'); + return null; + } + + console.log('Dataview plugin is not enabled'); + return null; +} + +interface TaskProgressBarSettings { mySetting: string; + showDebugInfo: boolean; } -const DEFAULT_SETTINGS: MyPluginSettings = { - mySetting: 'default' +const DEFAULT_SETTINGS: TaskProgressBarSettings = { + mySetting: 'default', + showDebugInfo: false } -export default class MyPlugin extends Plugin { - settings: MyPluginSettings; +export default class TaskProgressBarPlugin extends Plugin { + settings: TaskProgressBarSettings; + dvAPI: DataviewApi | null = null; + private sidebarView: TaskProgressBarView | null = null; + private lastActiveFile: TFile | null = null; + private lastFileContent: string = ''; + private dataviewCheckInterval: number | null = null; async onload() { await this.loadSettings(); - // This creates an icon in the left ribbon. - const ribbonIconEl = this.addRibbonIcon('dice', 'Sample Plugin', (evt: MouseEvent) => { - // Called when the user clicks the icon. - new Notice('This is a notice!'); - }); - // Perform additional things with the ribbon - ribbonIconEl.addClass('my-plugin-ribbon-class'); + // Register view type for the sidebar + this.registerView( + 'progress-tracker', + (leaf) => (this.sidebarView = new TaskProgressBarView(leaf, this)) + ); - // This adds a status bar item to the bottom of the app. Does not work on mobile apps. - const statusBarItemEl = this.addStatusBarItem(); - statusBarItemEl.setText('Status Bar Text'); + // Add icon to the left sidebar + this.addRibbonIcon('bar-chart-horizontal', 'Progress Tracker', () => { + this.activateView(); + }); - // This adds a simple command that can be triggered anywhere - this.addCommand({ - id: 'open-sample-modal-simple', - name: 'Open sample modal (simple)', - callback: () => { - new SampleModal(this.app).open(); - } - }); - // This adds an editor command that can perform some operation on the current editor instance - this.addCommand({ - id: 'sample-editor-command', - name: 'Sample editor command', - editorCallback: (editor: Editor, view: MarkdownView) => { - console.log(editor.getSelection()); - editor.replaceSelection('Sample Editor Command'); - } - }); - // This adds a complex command that can check whether the current state of the app allows execution of the command - this.addCommand({ - id: 'open-sample-modal-complex', - name: 'Open sample modal (complex)', - checkCallback: (checking: boolean) => { - // Conditions to check - const markdownView = this.app.workspace.getActiveViewOfType(MarkdownView); - if (markdownView) { - // If checking is true, we're simply "checking" if the command can be run. - // If checking is false, then we want to actually perform the operation. - if (!checking) { - new SampleModal(this.app).open(); + // Add settings tab + this.addSettingTab(new TaskProgressBarSettingTab(this.app, this)); + + // Kiểm tra Dataview API và thiết lập interval để kiểm tra lại nếu chưa có + this.checkDataviewAPI(); + + // Register event to update progress bar when file changes + this.registerEvent( + this.app.workspace.on('file-open', (file) => { + if (file) { + this.lastActiveFile = file; + this.updateLastFileContent(file); + if (this.sidebarView) { + this.sidebarView.updateProgressBar(file); } + } + }) + ); - // This command will only show up in Command Palette when the check function returns true - return true; + // Register event to update progress bar when editor changes + this.registerEvent( + this.app.workspace.on('editor-change', debounce(async (editor, view) => { + if (view instanceof MarkdownView && this.sidebarView) { + // Lấy nội dung hiện tại của editor + const content = editor.getValue(); + + // Kiểm tra xem nội dung có chứa task hay không + if (content.includes('- [') || content.includes('- [ ]') || content.includes('- [x]')) { + // Cập nhật ngay lập tức + if (this.lastActiveFile) { + // Cập nhật nội dung file cuối cùng trước khi kiểm tra thay đổi + this.lastActiveFile = view.file; + + // Cập nhật thanh tiến trình ngay lập tức + this.sidebarView.updateProgressBar(view.file, content); + + // Sau đó mới cập nhật nội dung file cuối cùng + this.lastFileContent = content; + } + } + } + }, 200)) // Giảm debounce xuống 200ms để phản ứng nhanh hơn + ); + + // Lắng nghe sự kiện keydown để phát hiện khi người dùng nhập task mới hoặc check/uncheck task + this.registerDomEvent(document, 'keydown', (evt: KeyboardEvent) => { + // Kiểm tra xem có đang trong editor không + const activeView = this.app.workspace.getActiveViewOfType(MarkdownView); + if (activeView && activeView.getMode() === 'source') { + // Cập nhật ngay lập tức khi nhấn các phím liên quan đến task + if (['Enter', 'Space', ']', 'x', 'X', 'Backspace', 'Delete'].includes(evt.key)) { + // Cập nhật ngay lập tức + setTimeout(() => { + const content = activeView.editor.getValue(); + if (content.includes('- [') || content.includes('- [ ]') || content.includes('- [x]')) { + this.lastActiveFile = activeView.file; + + // Cập nhật thanh tiến trình ngay lập tức + if (this.sidebarView) { + this.sidebarView.updateProgressBar(activeView.file, content); + } + + // Sau đó mới cập nhật nội dung file cuối cùng + this.lastFileContent = content; + } + }, 10); // Giảm thời gian chờ xuống 10ms } } }); - // This adds a settings tab so the user can configure various aspects of the plugin - this.addSettingTab(new SampleSettingTab(this.app, this)); - - // If the plugin hooks up any global DOM events (on parts of the app that doesn't belong to this plugin) - // Using this function will automatically remove the event listener when this plugin is disabled. + // Lắng nghe sự kiện click trong editor để phát hiện khi task được check/uncheck this.registerDomEvent(document, 'click', (evt: MouseEvent) => { - console.log('click', evt); + const target = evt.target as HTMLElement; + + // Kiểm tra xem click có phải vào checkbox của task không + if (target && target.tagName === 'INPUT' && target.classList.contains('task-list-item-checkbox')) { + // Đợi một chút để Obsidian cập nhật trạng thái task trong file + setTimeout(async () => { + const activeFile = this.app.workspace.getActiveFile(); + if (activeFile && this.sidebarView) { + // Đọc nội dung file hiện tại + const content = await this.app.vault.read(activeFile); + + // Cập nhật thanh tiến trình ngay lập tức + this.lastActiveFile = activeFile; + this.sidebarView.updateProgressBar(activeFile, content); + + // Sau đó mới cập nhật nội dung file cuối cùng + this.lastFileContent = content; + } + }, 50); // Giảm thời gian chờ xuống 50ms + } }); - // When registering intervals, this function will automatically clear the interval when the plugin is disabled. - this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000)); + // Activate view when plugin loads - đợi một chút để Obsidian khởi động hoàn toàn + setTimeout(() => { + this.activateView(); + }, 1000); + } + + // Kiểm tra Dataview API và thiết lập interval để kiểm tra lại nếu chưa có + checkDataviewAPI() { + // Kiểm tra ngay lập tức + this.dvAPI = getDataviewAPI(this.app); + + // Nếu không tìm thấy, thiết lập interval để kiểm tra lại + if (!this.dvAPI) { + this.dataviewCheckInterval = window.setInterval(() => { + this.dvAPI = getDataviewAPI(this.app); + if (this.dvAPI) { + console.log('Dataview API found'); + // Nếu tìm thấy, xóa interval + if (this.dataviewCheckInterval) { + clearInterval(this.dataviewCheckInterval); + this.dataviewCheckInterval = null; + } + + // Cập nhật sidebar nếu đang mở + if (this.sidebarView && this.lastActiveFile) { + this.sidebarView.updateProgressBar(this.lastActiveFile); + } + } + }, 2000); // Kiểm tra mỗi 2 giây + } + } + + // Kiểm tra xem trạng thái task có thay đổi không + hasTaskStatusChanged(newContent: string): boolean { + // Nếu chưa có nội dung cũ, coi như đã thay đổi + if (!this.lastFileContent) return true; + + // Đếm số lượng task hoàn thành trong nội dung cũ và mới + // Sử dụng regex chính xác hơn để phát hiện task + const oldCompletedTasks = (this.lastFileContent.match(/- \[x\]/gi) || []).length; + const newCompletedTasks = (newContent.match(/- \[x\]/gi) || []).length; + + // Đếm tổng số task trong nội dung cũ và mới + // Sử dụng regex chính xác hơn để phát hiện task chưa hoàn thành + const oldIncompleteTasks = (this.lastFileContent.match(/- \[ \]/g) || []).length; + const newIncompleteTasks = (newContent.match(/- \[ \]/g) || []).length; + + const oldTotalTasks = oldIncompleteTasks + oldCompletedTasks; + const newTotalTasks = newIncompleteTasks + newCompletedTasks; + + // Nếu số lượng task hoàn thành hoặc tổng số task thay đổi, coi như đã thay đổi + return oldCompletedTasks !== newCompletedTasks || oldTotalTasks !== newTotalTasks; + } + + // Cập nhật nội dung file cuối cùng + async updateLastFileContent(file: TFile) { + if (file) { + this.lastFileContent = await this.app.vault.read(file); + } + } + + async activateView() { + try { + const { workspace } = this.app; + + // If view already exists in leaves, show it + const leaves = workspace.getLeavesOfType('progress-tracker'); + if (leaves.length > 0) { + workspace.revealLeaf(leaves[0]); + return; + } + + // Otherwise, create a new leaf in the left sidebar + // Kiểm tra xem workspace đã sẵn sàng chưa + if (!workspace.leftSplit) { + console.log('Workspace not ready yet, retrying in 500ms'); + setTimeout(() => this.activateView(), 500); + return; + } + + // Sử dụng getLeaf thay vì createLeaf + const leaf = workspace.getLeftLeaf(false); + if (leaf) { + await leaf.setViewState({ + type: 'progress-tracker', + active: true, + }); + + // Reveal the leaf + workspace.revealLeaf(leaf); + } + } catch (error) { + console.error('Error activating view:', error); + new Notice('Error activating Task Progress Bar view. Please try again later.'); + } } onunload() { - + // Xóa interval nếu có + if (this.dataviewCheckInterval) { + clearInterval(this.dataviewCheckInterval); + this.dataviewCheckInterval = null; + } + + // Detach the view when plugin unloads + this.app.workspace.detachLeavesOfType('progress-tracker'); } async loadSettings() { @@ -91,44 +284,292 @@ export default class MyPlugin extends Plugin { } } -class SampleModal extends Modal { - constructor(app: App) { - super(app); +class TaskProgressBarView extends ItemView { + plugin: TaskProgressBarPlugin; + currentFile: TFile | null = null; + isVisible: boolean = false; + lastUpdateTime: number = 0; + + constructor(leaf: WorkspaceLeaf, plugin: TaskProgressBarPlugin) { + super(leaf); + this.plugin = plugin; } - onOpen() { - const {contentEl} = this; - contentEl.setText('Woah!'); + getViewType(): string { + return 'progress-tracker'; } - onClose() { - const {contentEl} = this; - contentEl.empty(); + getDisplayText(): string { + return 'Task Progress Bar'; + } + + getIcon(): string { + return 'bar-chart-horizontal'; + } + + async onOpen() { + this.isVisible = true; + const container = this.containerEl.children[1]; + container.empty(); + container.createEl('h4', { text: 'Task Progress' }); + + // Create progress container + const progressContainer = container.createDiv({ cls: 'task-progress-container' }); + + // Update with current file if available + const currentFile = this.app.workspace.getActiveFile(); + if (currentFile) { + this.updateProgressBar(currentFile); + } else { + // Hiển thị thông báo nếu không có file nào đang mở + progressContainer.createEl('p', { + text: 'No file is currently open. Open a markdown file to see the progress bar.' + }); + } + } + + async updateProgressBar(file: TFile | null, content?: string) { + if (!file) return; + + // Tránh cập nhật quá nhanh + const now = Date.now(); + if (now - this.lastUpdateTime < 100) return; // Giảm thời gian chờ xuống 100ms + this.lastUpdateTime = now; + + this.currentFile = file; + + const container = this.containerEl.children[1]; + const progressContainer = container.querySelector('.task-progress-container') as HTMLElement; + if (!progressContainer) return; + + // Thêm class để hiển thị animation + progressContainer.classList.add('updating'); + + // Cập nhật ngay lập tức nếu có nội dung được cung cấp + if (content) { + this.updateProgressBarContentWithString(content, progressContainer, file); + + // Xóa class sau khi cập nhật xong + setTimeout(() => { + progressContainer.classList.remove('updating'); + }, 300); + } else { + // Nếu không có nội dung, đọc từ file + setTimeout(async () => { + // Đọc nội dung file + const fileContent = await this.plugin.app.vault.read(file); + // Cập nhật với nội dung đọc được + this.updateProgressBarContentWithString(fileContent, progressContainer, file); + + // Xóa class sau khi cập nhật xong + setTimeout(() => { + progressContainer.classList.remove('updating'); + }, 300); + }, 50); + } + } + + // Phương thức mới để cập nhật với nội dung string trực tiếp + async updateProgressBarContentWithString(content: string, progressContainer: HTMLElement, file: TFile) { + progressContainer.empty(); + + // Get Dataview API + const dvAPI = this.plugin.dvAPI; + if (!dvAPI) { + // Vẫn hiển thị thanh tiến trình ngay cả khi không có Dataview API + try { + // Tạo thanh tiến trình trực tiếp từ nội dung + this.createProgressBarFromString(progressContainer, content, file); + + // Thêm thông tin về thời gian cập nhật + const updateInfo = progressContainer.createDiv({ cls: 'update-info' }); + updateInfo.createSpan({ + text: `Last updated: ${new Date().toLocaleTimeString()}`, + cls: 'update-time' + }); + + // Thêm thông báo về Dataview không khả dụng + const dataviewWarning = progressContainer.createDiv({ cls: 'dataview-warning' }); + dataviewWarning.createEl('p', { + text: 'Note: Dataview plugin is not available. Some advanced features may be limited.' + }); + + // Thêm nút để kiểm tra lại Dataview + const checkButton = dataviewWarning.createEl('button', { + text: 'Check for Dataview', + cls: 'mod-cta' + }); + checkButton.addEventListener('click', () => { + this.plugin.checkDataviewAPI(); + if (this.plugin.dvAPI) { + new Notice('Dataview API found!'); + this.updateProgressBar(file); + } else { + new Notice('Dataview API not found. Make sure Dataview plugin is installed and enabled.'); + } + }); + } catch (error) { + console.error('Error creating progress bar without Dataview:', error); + progressContainer.createEl('p', { text: 'Error creating progress bar' }); + } + + return; + } + + try { + // Tạo thanh tiến trình trực tiếp từ nội dung + this.createProgressBarFromString(progressContainer, content, file); + + // Thêm thông tin về thời gian cập nhật + const updateInfo = progressContainer.createDiv({ cls: 'update-info' }); + updateInfo.createSpan({ + text: `Last updated: ${new Date().toLocaleTimeString()}`, + cls: 'update-time' + }); + } catch (error) { + console.error('Error updating progress bar:', error); + progressContainer.createEl('p', { text: 'Error loading progress bar' }); + } + } + + // Phương thức tạo thanh tiến trình từ nội dung string + async createProgressBarFromString(container: HTMLElement, content: string, file: TFile) { + try { + // Sử dụng regex chính xác hơn để đếm task + const incompleteTasks = (content.match(/- \[ \]/g) || []).length; + const completedTasks = (content.match(/- \[x\]/gi) || []).length; // Thêm cờ 'i' để bắt cả 'x' và 'X' + const totalTasks = incompleteTasks + completedTasks; + + if (totalTasks === 0) { + container.createEl('p', { text: 'No tasks found in this file' }); + return; + } + + const percentage = Math.round((completedTasks / totalTasks) * 100); + + // Create percentage text + container.createEl('div', { + text: `${percentage}% Complete`, + cls: 'progress-percentage' + }); + + // Create progress bar + const progressBarContainer = container.createDiv({ cls: 'progress-bar' }); + const progressElement = progressBarContainer.createDiv({ cls: 'progress' }); + progressElement.style.width = `${percentage}%`; + + // Create stats + const statsContainer = container.createDiv({ cls: 'progress-stats' }); + statsContainer.createSpan({ text: `${completedTasks}/${totalTasks} tasks complete` }); + statsContainer.createSpan({ text: `${totalTasks - completedTasks} remaining` }); + + // Hiển thị danh sách các task chưa hoàn thành + if (totalTasks - completedTasks > 0) { + const taskList = container.createEl('ul', { cls: 'task-list' }); + + // Tìm tất cả các task chưa hoàn thành + const lines = content.split('\n'); + for (const line of lines) { + if (line.includes('- [ ]')) { + // Lấy nội dung task (bỏ qua "- [ ]") + const taskContent = line.substring(line.indexOf('- [ ]') + 5).trim(); + taskList.createEl('li', { text: taskContent }); + } + } + } + + // Thêm debug info nếu cần + if (this.plugin.settings.showDebugInfo) { + const debugInfo = container.createDiv({ cls: 'debug-info' }); + debugInfo.createEl('p', { text: `Debug Info:` }); + debugInfo.createEl('p', { text: `File: ${file.path}` }); + debugInfo.createEl('p', { text: `Incomplete tasks: ${incompleteTasks}` }); + debugInfo.createEl('p', { text: `Completed tasks: ${completedTasks}` }); + debugInfo.createEl('p', { text: `Total tasks: ${totalTasks}` }); + debugInfo.createEl('p', { text: `Percentage: ${percentage}%` }); + debugInfo.createEl('p', { text: `Update time: ${new Date().toISOString()}` }); + } + } catch (error) { + console.error('Error creating progress bar from string:', error); + container.createEl('p', { text: 'Error creating progress bar' }); + } + } + + async onClose() { + this.isVisible = false; } } -class SampleSettingTab extends PluginSettingTab { - plugin: MyPlugin; +class TaskProgressBarSettingTab extends PluginSettingTab { + plugin: TaskProgressBarPlugin; - constructor(app: App, plugin: MyPlugin) { + constructor(app: App, plugin: TaskProgressBarPlugin) { super(app, plugin); this.plugin = plugin; } display(): void { - const {containerEl} = this; + const { containerEl } = this; containerEl.empty(); + containerEl.createEl('h2', { text: 'Task Progress Bar Settings' }); + + // Thêm thông tin về trạng thái Dataview + const dataviewStatus = containerEl.createDiv({ cls: 'dataview-status' }); + if (this.plugin.dvAPI) { + dataviewStatus.createEl('p', { + text: '✅ Dataview API is available', + cls: 'dataview-available' + }); + } else { + dataviewStatus.createEl('p', { + text: '❌ Dataview API is not available', + cls: 'dataview-unavailable' + }); + + // Thêm nút để kiểm tra lại Dataview + const checkButton = dataviewStatus.createEl('button', { + text: 'Check for Dataview', + cls: 'mod-cta' + }); + checkButton.addEventListener('click', () => { + this.plugin.checkDataviewAPI(); + if (this.plugin.dvAPI) { + new Notice('Dataview API found!'); + this.display(); // Refresh settings tab + } else { + new Notice('Dataview API not found. Make sure Dataview plugin is installed and enabled.'); + } + }); + } + new Setting(containerEl) - .setName('Setting #1') - .setDesc('It\'s a secret') + .setName('Setting') + .setDesc('Description of the setting') .addText(text => text - .setPlaceholder('Enter your secret') + .setPlaceholder('Enter your setting') .setValue(this.plugin.settings.mySetting) .onChange(async (value) => { this.plugin.settings.mySetting = value; await this.plugin.saveSettings(); })); + + new Setting(containerEl) + .setName('Show Debug Info') + .setDesc('Show debug information in the sidebar to help troubleshoot task counting issues') + .addToggle(toggle => toggle + .setValue(this.plugin.settings.showDebugInfo) + .onChange(async (value) => { + this.plugin.settings.showDebugInfo = value; + await this.plugin.saveSettings(); + + // Cập nhật sidebar nếu đang mở - sử dụng phương thức public + const currentFile = this.app.workspace.getActiveFile(); + if (currentFile) { + // Sử dụng phương thức public để cập nhật UI + this.plugin.checkDataviewAPI(); + } + })); } } diff --git a/manifest.json b/manifest.json index dfa940e..9d9d05d 100644 --- a/manifest.json +++ b/manifest.json @@ -1,11 +1,11 @@ { - "id": "sample-plugin", - "name": "Sample Plugin", + "id": "progress-tracker", + "name": "ProgressTracker", "version": "1.0.0", "minAppVersion": "0.15.0", - "description": "Demonstrates some of the capabilities of the Obsidian API.", - "author": "Obsidian", - "authorUrl": "https://obsidian.md", - "fundingUrl": "https://obsidian.md/pricing", + "description": "Track task completion with a visual progress bar in your sidebar", + "author": "VN", + "authorUrl": "https://wpmasterynow.com", + "fundingUrl": "https://wpmasterynow.com", "isDesktopOnly": false } diff --git a/package.json b/package.json index 6a00766..a41c8e5 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,15 @@ { - "name": "obsidian-sample-plugin", + "name": "progress-tracker", "version": "1.0.0", - "description": "This is a sample plugin for Obsidian (https://obsidian.md)", + "description": "Track task completion with a visual progress bar in your sidebar", "main": "main.js", "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": "", + "keywords": ["obsidian", "dataview", "progress", "task"], + "author": "VN", "license": "MIT", "devDependencies": { "@types/node": "^16.11.6", diff --git a/styles.css b/styles.css index 71cc60f..9a0a165 100644 --- a/styles.css +++ b/styles.css @@ -6,3 +6,192 @@ available in the app when your plugin is enabled. If your plugin does not need CSS, delete this file. */ + +/* + * Task Progress Bar Styles + */ + +.task-progress-container { + padding: 10px; + margin-top: 10px; + transition: opacity 0.2s ease; +} + +.task-progress-container.updating { + opacity: 0.7; +} + +.task-progress-container .progress-bar { + width: 100%; + height: 10px; + background-color: var(--background-secondary); + border-radius: 5px; + margin: 10px 0; + overflow: hidden; +} + +.task-progress-container .progress-bar .progress { + height: 100%; + background-color: var(--interactive-accent); + border-radius: 5px; + transition: width 0.3s ease; +} + +.task-progress-container .progress-stats { + display: flex; + justify-content: space-between; + font-size: 0.8em; + color: var(--text-muted); + margin-bottom: 10px; +} + +.task-progress-container pre { + font-size: 0.8em; + padding: 8px; + background-color: var(--background-secondary); + border-radius: 4px; + overflow-x: auto; +} + +/* Ensure dataview elements display properly in the sidebar */ +.task-progress-container .dataview-result-table-wrapper { + max-width: 100%; + overflow-x: auto; +} + +.task-progress-container .dataview-result-table { + width: 100%; + font-size: 0.85em; +} + +/* Style for the progress percentage text */ +.task-progress-container .progress-percentage { + font-weight: bold; + color: var(--text-normal); + text-align: center; + margin-bottom: 5px; + font-size: 1.2em; +} + +/* Style for source info */ +.task-progress-container .source-info { + font-size: 0.75em; + color: var(--text-muted); + margin-top: 10px; + font-style: italic; +} + +/* Style for update info */ +.task-progress-container .update-info { + font-size: 0.7em; + color: var(--text-muted); + text-align: right; + margin-top: 10px; + border-top: 1px solid var(--background-modifier-border); + padding-top: 5px; +} + +.task-progress-container .update-time { + font-style: italic; +} + +/* Animation for updates */ +@keyframes highlight { + 0% { background-color: transparent; } + 30% { background-color: var(--background-modifier-success); } + 100% { background-color: transparent; } +} + +.task-progress-container.updated .progress-bar { + animation: highlight 1.5s ease; +} + +/* Styles for task list in sidebar */ +.task-progress-container ul.task-list { + padding-left: 15px; + margin: 5px 0; + max-height: 150px; + overflow-y: auto; + border-left: 2px solid var(--background-modifier-border); +} + +.task-progress-container ul.task-list li { + font-size: 0.85em; + margin-bottom: 3px; + list-style-type: none; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* Styles for Dataview status in settings */ +.dataview-status { + margin: 15px 0; + padding: 10px; + border-radius: 5px; + background-color: var(--background-secondary); +} + +.dataview-status .dataview-available { + color: var(--text-success); + font-weight: bold; +} + +.dataview-status .dataview-unavailable { + color: var(--text-error); + font-weight: bold; + margin-bottom: 10px; +} + +.dataview-status button { + margin-top: 5px; +} + +/* Styles for Dataview warning in sidebar */ +.dataview-warning { + margin-top: 15px; + padding: 8px; + border-radius: 4px; + background-color: var(--background-modifier-error-rgb); + background-color: rgba(var(--background-modifier-error-rgb), 0.1); + border-left: 3px solid var(--text-error); + font-size: 0.8em; +} + +.dataview-warning p { + margin: 0 0 8px 0; + color: var(--text-muted); +} + +.dataview-warning button { + font-size: 0.9em; + padding: 2px 8px; +} + +/* Styles for debug info */ +.debug-info { + margin-top: 15px; + padding: 8px; + border-radius: 4px; + background-color: var(--background-secondary); + border-left: 3px solid var(--text-accent); + font-size: 0.75em; + color: var(--text-muted); +} + +.debug-info p { + margin: 0 0 4px 0; + font-family: var(--font-monospace); +} + +/* Responsive design for small screens */ +@media (max-width: 600px) { + .task-progress-container .progress-stats { + flex-direction: column; + align-items: center; + } + + .task-progress-container .progress-stats span:first-child { + margin-bottom: 5px; + } +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..1621aaf --- /dev/null +++ b/yarn.lock @@ -0,0 +1,517 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@esbuild/android-arm64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.3.tgz#35d045f69c9b4cf3f8efcd1ced24a560213d3346" + integrity sha512-XvJsYo3dO3Pi4kpalkyMvfQsjxPWHYjoX4MDiB/FUM4YMfWcXa5l4VCwFWVYI1+92yxqjuqrhNg0CZg3gSouyQ== + +"@esbuild/android-arm@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.3.tgz#4986d26306a7440078d42b3bf580d186ef714286" + integrity sha512-1Mlz934GvbgdDmt26rTLmf03cAgLg5HyOgJN+ZGCeP3Q9ynYTNMn2/LQxIl7Uy+o4K6Rfi2OuLsr12JQQR8gNg== + +"@esbuild/android-x64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.3.tgz#a1928cd681e4055103384103c8bd34df7b9c7b19" + integrity sha512-nuV2CmLS07Gqh5/GrZLuqkU9Bm6H6vcCspM+zjp9TdQlxJtIe+qqEXQChmfc7nWdyr/yz3h45Utk1tUn8Cz5+A== + +"@esbuild/darwin-arm64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.3.tgz#e4af2b392e5606a4808d3a78a99d38c27af39f1d" + integrity sha512-01Hxaaat6m0Xp9AXGM8mjFtqqwDjzlMP0eQq9zll9U85ttVALGCGDuEvra5Feu/NbP5AEP1MaopPwzsTcUq1cw== + +"@esbuild/darwin-x64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.3.tgz#cbcbfb32c8d5c86953f215b48384287530c5a38e" + integrity sha512-Eo2gq0Q/er2muf8Z83X21UFoB7EU6/m3GNKvrhACJkjVThd0uA+8RfKpfNhuMCl1bKRfBzKOk6xaYKQZ4lZqvA== + +"@esbuild/freebsd-arm64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.3.tgz#90ec1755abca4c3ffe1ad10819cd9d31deddcb89" + integrity sha512-CN62ESxaquP61n1ZjQP/jZte8CE09M6kNn3baos2SeUfdVBkWN5n6vGp2iKyb/bm/x4JQzEvJgRHLGd5F5b81w== + +"@esbuild/freebsd-x64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.3.tgz#8760eedc466af253c3ed0dfa2940d0e59b8b0895" + integrity sha512-feq+K8TxIznZE+zhdVurF3WNJ/Sa35dQNYbaqM/wsCbWdzXr5lyq+AaTUSER2cUR+SXPnd/EY75EPRjf4s1SLg== + +"@esbuild/linux-arm64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.3.tgz#13916fc8873115d7d546656e19037267b12d4567" + integrity sha512-JHeZXD4auLYBnrKn6JYJ0o5nWJI9PhChA/Nt0G4MvLaMrvXuWnY93R3a7PiXeJQphpL1nYsaMcoV2QtuvRnF/g== + +"@esbuild/linux-arm@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.3.tgz#15f876d127b244635ddc09eaaa65ae97bc472a63" + integrity sha512-CLP3EgyNuPcg2cshbwkqYy5bbAgK+VhyfMU7oIYyn+x4Y67xb5C5ylxsNUjRmr8BX+MW3YhVNm6Lq6FKtRTWHQ== + +"@esbuild/linux-ia32@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.3.tgz#6691f02555d45b698195c81c9070ab4e521ef005" + integrity sha512-FyXlD2ZjZqTFh0sOQxFDiWG1uQUEOLbEh9gKN/7pFxck5Vw0qjWSDqbn6C10GAa1rXJpwsntHcmLqydY9ST9ZA== + +"@esbuild/linux-loong64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.3.tgz#f77ef657f222d8b3a8fbd530a09e40976c458d48" + integrity sha512-OrDGMvDBI2g7s04J8dh8/I7eSO+/E7nMDT2Z5IruBfUO/RiigF1OF6xoH33Dn4W/OwAWSUf1s2nXamb28ZklTA== + +"@esbuild/linux-mips64el@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.3.tgz#fa38833cfc8bfaadaa12b243257fe6d19d0f6f79" + integrity sha512-DcnUpXnVCJvmv0TzuLwKBC2nsQHle8EIiAJiJ+PipEVC16wHXaPEKP0EqN8WnBe0TPvMITOUlP2aiL5YMld+CQ== + +"@esbuild/linux-ppc64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.3.tgz#c157a602b627c90d174743e4b0dfb7630b101dbf" + integrity sha512-BDYf/l1WVhWE+FHAW3FzZPtVlk9QsrwsxGzABmN4g8bTjmhazsId3h127pliDRRu5674k1Y2RWejbpN46N9ZhQ== + +"@esbuild/linux-riscv64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.3.tgz#7bf79614bd544bd932839b1fcff6cf1f8f6bdf1a" + integrity sha512-WViAxWYMRIi+prTJTyV1wnqd2mS2cPqJlN85oscVhXdb/ZTFJdrpaqm/uDsZPGKHtbg5TuRX/ymKdOSk41YZow== + +"@esbuild/linux-s390x@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.3.tgz#6bb50c5a2613d31ce1137fe5c249ecadbecccdea" + integrity sha512-Iw8lkNHUC4oGP1O/KhumcVy77u2s6+KUjieUqzEU3XuWJqZ+AY7uVMrrCbAiwWTkpQHkr00BuXH5RpC6Sb/7Ug== + +"@esbuild/linux-x64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.3.tgz#aa140d99f0d9e0af388024823bfe4558d73fbbf9" + integrity sha512-0AGkWQMzeoeAtXQRNB3s4J1/T2XbigM2/Mn2yU1tQSmQRmHIZdkGbVq2A3aDdNslPyhb9/lH0S5GMTZ4xsjBqg== + +"@esbuild/netbsd-x64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.3.tgz#b6ae9948b03e4c95dc581c68358fb61d9d12a625" + integrity sha512-4+rR/WHOxIVh53UIQIICryjdoKdHsFZFD4zLSonJ9RRw7bhKzVyXbnRPsWSfwybYqw9sB7ots/SYyufL1mBpEg== + +"@esbuild/openbsd-x64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.3.tgz#cda007233e211fc9154324bfa460540cfc469408" + integrity sha512-cVpWnkx9IYg99EjGxa5Gc0XmqumtAwK3aoz7O4Dii2vko+qXbkHoujWA68cqXjhh6TsLaQelfDO4MVnyr+ODeA== + +"@esbuild/sunos-x64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.3.tgz#f1385b092000c662d360775f3fad80943d2169c4" + integrity sha512-RxmhKLbTCDAY2xOfrww6ieIZkZF+KBqG7S2Ako2SljKXRFi+0863PspK74QQ7JpmWwncChY25JTJSbVBYGQk2Q== + +"@esbuild/win32-arm64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.3.tgz#14e9dd9b1b55aa991f80c120fef0c4492d918801" + integrity sha512-0r36VeEJ4efwmofxVJRXDjVRP2jTmv877zc+i+Pc7MNsIr38NfsjkQj23AfF7l0WbB+RQ7VUb+LDiqC/KY/M/A== + +"@esbuild/win32-ia32@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.3.tgz#de584423513d13304a6925e01233499a37a4e075" + integrity sha512-wgO6rc7uGStH22nur4aLFcq7Wh86bE9cOFmfTr/yxN3BXvDEdCSXyKkO+U5JIt53eTOgC47v9k/C1bITWL/Teg== + +"@esbuild/win32-x64@0.17.3": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.3.tgz#2f69ea6b37031b0d1715dd2da832a8ae5eb36e74" + integrity sha512-FdVl64OIuiKjgXBjwZaJLKp0eaEckifbhn10dXWhysMJkWblg3OEEGKSIyhiD5RSgAya8WzP3DNkngtIg3Nt7g== + +"@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@5.60.8": + version "5.60.8" + resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-5.60.8.tgz#b647d04b470e8e1836dd84b2879988fc55c9de68" + integrity sha512-VjFgDF/eB+Aklcy15TtOTLQeMjTo07k7KAjql8OK5Dirr7a6sJY4T1uVBDuTVG9VEmn1uUsohOpYnVfgC6/jyw== + dependencies: + "@types/tern" "*" + +"@types/estree@*": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== + +"@types/json-schema@^7.0.9": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/node@^16.11.6": + version "16.18.126" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.126.tgz#27875faa2926c0f475b39a8bb1e546c0176f8d4b" + integrity sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw== + +"@types/tern@*": + version "0.23.9" + resolved "https://registry.yarnpkg.com/@types/tern/-/tern-0.23.9.tgz#6f6093a4a9af3e6bb8dde528e024924d196b367c" + integrity sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw== + 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.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.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.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + +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@0.17.3: + version "0.17.3" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.3.tgz#d9aa02a3bc441ed35f9569cd9505812ae3fcae61" + integrity sha512-9n3AsBRe6sIyOc6kmoXg2ypCLgf3eZSraWFRpnkto+svt8cZNuKTkb1bhQcitBcvIqjNiK7K0J3KPmwGSfkA8g== + optionalDependencies: + "@esbuild/android-arm" "0.17.3" + "@esbuild/android-arm64" "0.17.3" + "@esbuild/android-x64" "0.17.3" + "@esbuild/darwin-arm64" "0.17.3" + "@esbuild/darwin-x64" "0.17.3" + "@esbuild/freebsd-arm64" "0.17.3" + "@esbuild/freebsd-x64" "0.17.3" + "@esbuild/linux-arm" "0.17.3" + "@esbuild/linux-arm64" "0.17.3" + "@esbuild/linux-ia32" "0.17.3" + "@esbuild/linux-loong64" "0.17.3" + "@esbuild/linux-mips64el" "0.17.3" + "@esbuild/linux-ppc64" "0.17.3" + "@esbuild/linux-riscv64" "0.17.3" + "@esbuild/linux-s390x" "0.17.3" + "@esbuild/linux-x64" "0.17.3" + "@esbuild/netbsd-x64" "0.17.3" + "@esbuild/openbsd-x64" "0.17.3" + "@esbuild/sunos-x64" "0.17.3" + "@esbuild/win32-arm64" "0.17.3" + "@esbuild/win32-ia32" "0.17.3" + "@esbuild/win32-x64" "0.17.3" + +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.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +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.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + 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.8" + +fastq@^1.6.0: + version "1.19.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== + dependencies: + reusify "^1.0.4" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + 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.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +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== + +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.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + 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.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +obsidian@latest: + version "1.8.7" + resolved "https://registry.yarnpkg.com/obsidian/-/obsidian-1.8.7.tgz#601e9ea1724289effa4c9bb3b4e20d327263634f" + integrity sha512-h4bWwNFAGRXlMlMAzdEiIM2ppTGlrh7uGOJS6w4gClrsjc+ei/3YAtU2VdFUlCiPuTHpY4aBpFJJW75S1Tl/JA== + dependencies: + "@types/codemirror" "5.60.8" + 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.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + +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.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" + integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== + +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==