mirror of
https://github.com/tailormade-eu/obsidian-task-export-plugin.git
synced 2026-07-22 16:30:23 +00:00
573 lines
16 KiB
Markdown
573 lines
16 KiB
Markdown
# Requirements - Obsidian Plugin
|
|
|
|
Automatically export outstanding tasks from Obsidian vault to CSV for ManicTime time tracking.
|
|
|
|
## Overview
|
|
|
|
An Obsidian plugin that integrates task export functionality directly into Obsidian, providing both on-demand and automatic export capabilities with a native user experience.
|
|
|
|
**Related Repository**: [markdown-task-export](https://github.com/tailormade-eu/markdown-task-export) - C# Console Application (Iteration 1)
|
|
|
|
**⚠️ REFERENCE IMPLEMENTATION:**
|
|
This plugin is a **port of the working C# console application**. Use the C# codebase as a reference:
|
|
- `src/MarkdownParser.cs` - Complete parsing logic with all edge cases
|
|
- `src/CsvExporter.cs` - CSV generation with compression and header control
|
|
- `src/TaskExtractor.cs` - Customer/Project extraction and file enumeration
|
|
- `src/Models/TaskItem.cs` - Data structure for tasks
|
|
|
|
The TypeScript implementation should produce **identical CSV output** to the C# version.
|
|
|
|
## Functional Requirements
|
|
|
|
### 1. Plugin Integration
|
|
|
|
**Obsidian API Integration**
|
|
- Use Obsidian Plugin API for all file operations
|
|
- Register as a community plugin (follows Obsidian guidelines)
|
|
- Compatible with Obsidian desktop (Windows, macOS, Linux)
|
|
- Minimal performance impact on Obsidian startup/runtime
|
|
|
|
**Plugin Lifecycle**
|
|
- Load settings on plugin activation
|
|
- Initialize file watchers conditionally (based on settings)
|
|
- Clean up resources on plugin deactivation
|
|
- Save settings changes immediately
|
|
|
|
### 2. User Interface Components
|
|
|
|
**Command Palette Commands**
|
|
- "Export Outstanding Tasks" - Trigger manual export
|
|
- "Toggle Auto-Export" - Enable/disable automatic mode
|
|
- "Open Export Settings" - Jump to settings panel
|
|
|
|
**Ribbon Icon**
|
|
- Add icon to left sidebar for quick export access
|
|
- Visual feedback on click (spinning/loading state)
|
|
- Tooltip: "Export Outstanding Tasks"
|
|
|
|
**Status Bar Item**
|
|
- Display last export timestamp: "Last export: 2 minutes ago"
|
|
- Show export status: ✅ success, ⚠️ error
|
|
- Clickable to trigger manual export
|
|
- Hide when plugin is disabled
|
|
|
|
**Settings Tab**
|
|
- Custom settings panel under Settings → Plugin Options
|
|
- Input fields for all configurable options
|
|
- Real-time validation of paths
|
|
- Reset to defaults button
|
|
|
|
**Notifications**
|
|
- Success: "Exported 49 tasks to outstanding_tasks.csv"
|
|
- Error: "Export failed: [error message]"
|
|
- Optional (configurable): Show/hide notifications
|
|
- Duration: 5 seconds (auto-dismiss)
|
|
|
|
### 3. Task Detection (Same as Console App)
|
|
|
|
**Task Identification**
|
|
- Find unchecked tasks: `- [ ]`
|
|
- Ignore completed: `- [x]`, `✅ 2025-11-11`
|
|
- Support nested/indented tasks
|
|
- Multi-line task descriptions
|
|
|
|
**Parsing Logic**
|
|
- Use same extraction rules as console app (reference: `MarkdownParser.cs`)
|
|
- Extract hierarchical headers (##, ###, ####, etc.) - unlimited depth
|
|
- Associate tasks with parent headers
|
|
- Handle nested task patterns
|
|
- Preserve hierarchy when parent tasks have sub-tasks
|
|
|
|
**Key Parsing Details from C# Implementation:**
|
|
- Headers start at `##` (H2), `#` (H1) is ignored
|
|
- Empty header levels are tracked to preserve structure
|
|
- Parent tasks (tasks with sub-tasks) become additional header levels
|
|
- Indentation-based nesting detection
|
|
- Skip tasks with checkmark emojis in the text
|
|
|
|
### 4. Export Functionality
|
|
|
|
**Manual Export**
|
|
- Triggered by user command
|
|
- Scans configured Customers folder
|
|
- Generates CSV immediately
|
|
- Shows progress for large exports (> 50 files)
|
|
- Displays notification on completion
|
|
|
|
**Automatic Export**
|
|
- Triggered by file events (save/modify)
|
|
- Debounced to avoid excessive exports (configurable delay)
|
|
- Only monitors files in Customers folder
|
|
- Runs in background (non-blocking)
|
|
- Updates status bar on completion
|
|
|
|
**File Watching**
|
|
- Monitor Obsidian vault file events:
|
|
- `file-modified` event
|
|
- `file-created` event (if new .md files added)
|
|
- Filter events to only `.md` files in Customers folder
|
|
- Implement debouncing (default: 3 seconds)
|
|
- Unsubscribe when auto-export disabled
|
|
|
|
### 5. Settings Management
|
|
|
|
**Settings Schema**
|
|
```typescript
|
|
interface TaskExportSettings {
|
|
outputPath: string; // CSV output path (relative to vault)
|
|
customersFolder: string; // Root customer folder path
|
|
autoExport: boolean; // Enable auto-export
|
|
exportOnSave: boolean; // Trigger on file save
|
|
exportOnModify: boolean; // Trigger on file modify
|
|
showNotifications: boolean; // Show export notifications
|
|
compressLevels: boolean; // Remove empty hierarchy columns
|
|
includeHeader: boolean; // Include CSV header row
|
|
debounceDelay: number; // Debounce delay in seconds (1-30)
|
|
}
|
|
```
|
|
|
|
**Default Values**
|
|
- outputPath: `outstanding_tasks.csv`
|
|
- customersFolder: `Customers`
|
|
- autoExport: `false`
|
|
- exportOnSave: `true`
|
|
- exportOnModify: `false`
|
|
- showNotifications: `true`
|
|
- compressLevels: `false`
|
|
- includeHeader: `true`
|
|
- debounceDelay: `3`
|
|
|
|
**Settings Persistence**
|
|
- Saved to `.obsidian/plugins/task-export-plugin/data.json`
|
|
- Load on plugin activation
|
|
- Save immediately on change
|
|
- Validate on load (use defaults if invalid)
|
|
|
|
### 6. CSV Output (Same as Console App)
|
|
|
|
**Format**
|
|
- Header: `CustomerName,ProjectName,Level1,Level2,Level3,...,Task`
|
|
- **Dynamic columns**: Unlimited depth support (Level1, Level2, Level3, etc.)
|
|
- **Compression mode**: Optional `compressLevels` setting to remove empty columns
|
|
- When enabled: Each row only outputs non-empty levels (no padding)
|
|
- When disabled: All rows padded to maximum depth with empty columns
|
|
- **Header control**: Optional `includeHeader` setting to exclude header row
|
|
- Proper CSV escaping (commas, quotes, newlines)
|
|
- UTF-8 with BOM encoding for Excel compatibility
|
|
|
|
**CSV Escaping Rules (from C# implementation):**
|
|
- Wrap in quotes if field contains: comma, quote, newline, or carriage return
|
|
- Double any quotes inside the field: `"` becomes `""`
|
|
- Example: `Task with "quotes"` becomes `"Task with ""quotes"""`
|
|
|
|
**File Writing**
|
|
- Use Obsidian's `vault.adapter.write()` API (cross-platform compatible)
|
|
- Atomic write (write to temp, then rename) - optional for reliability
|
|
- Handle write failures gracefully
|
|
- Output path relative to vault root (mobile-friendly)
|
|
- Support absolute paths on desktop only
|
|
|
|
### 7. Error Handling
|
|
|
|
**User-Facing Errors**
|
|
- Invalid paths (show notification)
|
|
- Write permissions issues
|
|
- No tasks found (info notification)
|
|
- File reading errors (skip file, continue)
|
|
|
|
**Developer Errors**
|
|
- Log to console for debugging
|
|
- Don't crash Obsidian
|
|
- Provide detailed error messages
|
|
- Graceful degradation
|
|
|
|
**Error Recovery**
|
|
- Retry failed operations once
|
|
- Fall back to manual export if auto-export fails
|
|
- Clear error state after successful export
|
|
|
|
## Non-Functional Requirements
|
|
|
|
### Performance
|
|
|
|
**Target Metrics**
|
|
- Plugin activation: < 100ms
|
|
- Manual export (100 files): < 2 seconds
|
|
- Auto-export after file change: < 500ms
|
|
- Memory footprint: < 10MB
|
|
- No noticeable UI lag
|
|
|
|
**Optimization Strategies**
|
|
- Cache parsed file content (invalidate on change)
|
|
- Async file operations (don't block main thread)
|
|
- Debounce file change events
|
|
- Process files in batches if needed
|
|
- Only watch configured folder
|
|
|
|
### Compatibility
|
|
|
|
**Obsidian Version**
|
|
- Minimum: Obsidian 1.0.0
|
|
- Tested on latest stable release
|
|
- Full API compatibility across all platforms
|
|
|
|
**Platforms (Cross-Platform Support)**
|
|
- ✅ Windows 10/11
|
|
- ✅ macOS 11+
|
|
- ✅ Linux (major distributions)
|
|
- ✅ Android 8.0+
|
|
- ✅ iOS 13+
|
|
- ✅ Web version
|
|
- **One codebase works on all platforms**
|
|
|
|
**Platform-Specific Considerations:**
|
|
- Desktop: Full file system access (can save CSV outside vault)
|
|
- Mobile: Limited to vault directory only
|
|
- Use Obsidian's Vault API exclusively (not Node.js `fs` module)
|
|
- Detect platform with `Platform.isMobile`, `Platform.isDesktop`
|
|
|
|
**Vault Types**
|
|
- Local vaults
|
|
- Synced vaults (Dropbox, OneDrive, iCloud, etc.)
|
|
- Git-based vaults
|
|
|
|
### Usability
|
|
|
|
**User Experience**
|
|
- Intuitive settings interface
|
|
- Clear error messages
|
|
- Helpful tooltips
|
|
- Keyboard shortcuts (optional)
|
|
- Minimal clicks to export
|
|
|
|
**Documentation**
|
|
- README with installation instructions
|
|
- Settings descriptions
|
|
- Troubleshooting guide
|
|
- Example use cases
|
|
|
|
### Security
|
|
|
|
**File Access**
|
|
- Only read files user has access to
|
|
- Only write to configured output path
|
|
- Don't expose sensitive file contents
|
|
- Validate all user inputs
|
|
|
|
**Data Privacy**
|
|
- No external network requests
|
|
- No telemetry/analytics
|
|
- All processing local
|
|
- No data leaves user's machine
|
|
|
|
## Technical Requirements
|
|
|
|
### Technology Stack
|
|
|
|
**Development Environment**
|
|
- **Visual Studio Code** - Primary IDE
|
|
- **Microsoft Stack** - Preferred tooling where applicable
|
|
- **Extensions**:
|
|
- ESLint - Code quality
|
|
- Prettier - Code formatting
|
|
- TypeScript - Language support
|
|
- Obsidian Plugin Dev Tools (if available)
|
|
|
|
**Required**
|
|
- TypeScript 4.0+
|
|
- Obsidian Plugin API (latest)
|
|
- Node.js 16+ (development only, not needed by users)
|
|
- esbuild (fast bundling, replaces Rollup)
|
|
|
|
**Cross-Platform Compatibility**
|
|
- ✅ Use Obsidian's Vault API exclusively
|
|
- ✅ Use `normalizePath()` for path handling
|
|
- ✅ Use `app.vault.adapter.read()` for file reading
|
|
- ✅ Use `app.vault.adapter.write()` for file writing
|
|
- ❌ Avoid Node.js modules: `fs`, `path`, `os` (desktop-only)
|
|
- ❌ Never use absolute paths outside vault on mobile
|
|
|
|
**API Examples:**
|
|
```typescript
|
|
// ✅ Good - cross-platform
|
|
const content = await this.app.vault.adapter.read(filePath);
|
|
await this.app.vault.adapter.write(outputPath, csvContent);
|
|
const normalized = normalizePath(userPath);
|
|
|
|
// ❌ Bad - desktop only
|
|
import * as fs from 'fs';
|
|
fs.readFileSync(filePath);
|
|
```
|
|
|
|
**Optional Libraries**
|
|
- None required (use vanilla TypeScript/Obsidian API)
|
|
- Consider: Built-in CSV generation (no external dependencies)
|
|
|
|
### Project Structure
|
|
|
|
**Directory Layout:**
|
|
```
|
|
obsidian-task-export-plugin/ ← Repository root
|
|
├── .vscode/ ← VS Code settings
|
|
│ ├── settings.json
|
|
│ └── extensions.json
|
|
├── src/ ← All source code here
|
|
│ ├── main.ts # Plugin entry, command registration
|
|
│ ├── settings.ts # Settings interface and tab
|
|
│ ├── exporter.ts # Core export logic
|
|
│ ├── parser.ts # Markdown parsing
|
|
│ ├── csv-writer.ts # CSV generation
|
|
│ ├── file-watcher.ts # File monitoring and debouncing
|
|
│ └── types.ts # TypeScript interfaces
|
|
├── tests/
|
|
│ ├── exporter.test.ts
|
|
│ ├── parser.test.ts
|
|
│ └── fixtures/ # Test markdown files
|
|
├── manifest.json ← Plugin metadata (root level)
|
|
├── versions.json ← Version compatibility (root level)
|
|
├── package.json ← Dependencies (root level)
|
|
├── tsconfig.json ← TypeScript config (root level)
|
|
├── esbuild.config.mjs ← Build configuration (root level)
|
|
├── styles.css ← Optional styling (root level)
|
|
├── .eslintrc.json ← Linting config
|
|
├── .prettierrc ← Formatting config
|
|
├── README.md
|
|
└── LICENSE
|
|
```
|
|
|
|
**Project Structure Rules:**
|
|
- ✅ All source code in `src/` folder
|
|
- ✅ Configuration files at root level
|
|
- ✅ No solution file needed (TypeScript project, not .NET)
|
|
- ✅ Use VS Code workspace for development
|
|
|
|
### Build System
|
|
|
|
**Development**
|
|
```bash
|
|
npm run dev # Watch mode with source maps
|
|
```
|
|
|
|
**Production**
|
|
```bash
|
|
npm run build # Minified build for distribution
|
|
```
|
|
|
|
**Testing**
|
|
```bash
|
|
npm test # Run unit tests
|
|
npm run test:coverage # Generate coverage report
|
|
```
|
|
|
|
**Build Tool**: esbuild (fast, modern bundler)
|
|
|
|
### Plugin Manifest
|
|
|
|
```json
|
|
{
|
|
"id": "task-export-plugin",
|
|
"name": "Task Export Tool",
|
|
"version": "1.0.0",
|
|
"minAppVersion": "1.0.0",
|
|
"description": "Export outstanding tasks to CSV for time tracking",
|
|
"author": "Raoul Jacobs",
|
|
"authorUrl": "https://github.com/tailormade-eu",
|
|
"isDesktopOnly": false
|
|
}
|
|
```
|
|
|
|
## Implementation Details
|
|
|
|
### Core Classes
|
|
|
|
**TaskExportPlugin (main.ts)**
|
|
- Extends `Plugin` class
|
|
- Registers commands, ribbon icon, status bar
|
|
- Manages file watcher lifecycle
|
|
- Handles settings loading/saving
|
|
- Reference C# `Program.cs` for command-line argument patterns
|
|
|
|
**TaskExportSettings (settings.ts)**
|
|
- Extends `PluginSettingTab`
|
|
- Builds settings UI
|
|
- Validates user inputs
|
|
- Saves settings on change
|
|
|
|
**TaskExporter (exporter.ts)**
|
|
- Main export orchestration
|
|
- File enumeration via Obsidian API
|
|
- Calls parser for each file
|
|
- Aggregates results
|
|
- Writes CSV output
|
|
- Reference C# `TaskExtractor.cs` for logic
|
|
|
|
**MarkdownParser (parser.ts)**
|
|
- Parses markdown content
|
|
- Extracts headers and tasks
|
|
- Maintains hierarchical context
|
|
- Returns structured data
|
|
- **Port directly from C# `MarkdownParser.cs`** - proven logic with all edge cases
|
|
|
|
**CsvWriter (csv-writer.ts)**
|
|
- Formats data as CSV
|
|
- Handles escaping (use RFC 4180 standard)
|
|
- Writes to file via Obsidian API
|
|
- Implements compression mode
|
|
- **Port directly from C# `CsvExporter.cs`**
|
|
|
|
**FileWatcher (file-watcher.ts)**
|
|
- Subscribes to file events
|
|
- Implements debouncing
|
|
- Filters relevant files
|
|
- Triggers exports
|
|
|
|
### State Management
|
|
|
|
**Plugin State**
|
|
- Current settings
|
|
- Last export timestamp
|
|
- Export in progress flag
|
|
- Cached file content (optional)
|
|
|
|
**No Persistent State Required**
|
|
- All state derived from vault files
|
|
- Settings persisted by Obsidian
|
|
|
|
### Event Handling
|
|
|
|
**File Events**
|
|
```typescript
|
|
this.registerEvent(
|
|
this.app.workspace.on('file-modified', (file) => {
|
|
if (shouldExport(file)) {
|
|
debouncedExport();
|
|
}
|
|
})
|
|
);
|
|
```
|
|
|
|
**Command Events**
|
|
```typescript
|
|
this.addCommand({
|
|
id: 'export-tasks',
|
|
name: 'Export Outstanding Tasks',
|
|
callback: () => this.exportTasks()
|
|
});
|
|
```
|
|
|
|
## Testing Requirements
|
|
|
|
### Unit Tests
|
|
|
|
**Parser Tests**
|
|
- Task detection patterns
|
|
- Header hierarchy extraction
|
|
- Nested task handling
|
|
- Edge cases (empty files, no tasks)
|
|
|
|
**CSV Writer Tests**
|
|
- Proper escaping (commas, quotes)
|
|
- Dynamic column generation
|
|
- UTF-8 encoding
|
|
|
|
**Exporter Tests**
|
|
- Customer/Project name extraction
|
|
- File enumeration
|
|
- Error handling
|
|
|
|
### Integration Tests
|
|
|
|
**Manual Export**
|
|
- Command execution
|
|
- Progress indication
|
|
- Notification display
|
|
- File writing
|
|
|
|
**Auto Export**
|
|
- File watching activation
|
|
- Debouncing behavior
|
|
- Background processing
|
|
|
|
### Test Fixtures
|
|
|
|
Sample vault structure:
|
|
```
|
|
test-vault/
|
|
├── Customers/
|
|
│ ├── Customer A/
|
|
│ │ └── Project 1.md
|
|
│ └── Customer B/
|
|
│ └── Project 2.md
|
|
└── outstanding_tasks.csv
|
|
```
|
|
|
|
Sample markdown files with:
|
|
- Various task patterns
|
|
- Different header structures
|
|
- Special characters
|
|
- Nested tasks
|
|
|
|
## Publishing Requirements
|
|
|
|
### Obsidian Community Plugin Submission
|
|
|
|
**Required Files**
|
|
- `manifest.json` - Plugin metadata
|
|
- `main.js` - Compiled plugin code
|
|
- `styles.css` - Optional styling
|
|
- `README.md` - Documentation
|
|
- `LICENSE` - Open source license (MIT recommended)
|
|
|
|
**Review Criteria**
|
|
- Code quality and security
|
|
- No external network requests
|
|
- Proper error handling
|
|
- Clear documentation
|
|
- Follows Obsidian guidelines
|
|
|
|
**Submission Process**
|
|
1. Create GitHub repository
|
|
2. Add plugin to Obsidian community plugins list (PR)
|
|
3. Wait for review and approval
|
|
4. Plugin listed in Obsidian's plugin browser
|
|
|
|
### Release Process
|
|
|
|
**Version Tagging**
|
|
- Follow semantic versioning: `v1.0.0`
|
|
- Create GitHub release with:
|
|
- Release notes
|
|
- Attached `main.js`, `manifest.json`, `styles.css`
|
|
|
|
**Changelog**
|
|
- Maintain `CHANGELOG.md`
|
|
- Document breaking changes
|
|
- List new features and fixes
|
|
|
|
## Success Criteria
|
|
|
|
The plugin is successful if it:
|
|
|
|
1. ✅ Installs and activates without errors
|
|
2. ✅ Correctly exports all unchecked tasks from test vault
|
|
3. ✅ Auto-export works reliably with file changes
|
|
4. ✅ Settings persist across Obsidian restarts
|
|
5. ✅ No performance impact on Obsidian UI
|
|
6. ✅ Handles errors gracefully without crashing
|
|
7. ✅ Compatible with latest Obsidian version
|
|
8. ✅ CSV validates successfully in ManicTime
|
|
9. ✅ Has 80%+ code coverage in tests
|
|
10. ✅ Passes Obsidian plugin review (if submitted)
|
|
|
|
## Future Enhancements (Out of Scope for v1)
|
|
|
|
- Mobile support (iOS/Android)
|
|
- Export templates (custom CSV formats)
|
|
- Multiple output formats (JSON, XML)
|
|
- Task filtering (by date, tags, priority)
|
|
- Statistics dashboard
|
|
- Direct ManicTime API integration
|
|
- Scheduled exports (daily, weekly)
|
|
- Export history viewer
|
|
- Task completion tracking
|
|
- Custom task patterns (beyond `- [ ]`)
|