6.8 KiB
Add Configurable CSV Delimiter Feature to Obsidian Plugin
Context
The C# console application (markdown-task-export) has been updated with a configurable CSV delimiter feature. This allows users to choose between comma (,) and semicolon (;) delimiters.
Reference Implementation: markdown-task-export
Changes in C# Version (Iteration 1)
1. ExportOptions.cs
Added Delimiter property:
public char Delimiter { get; set; } = ',';
2. CsvExporter.cs
- Added constructor parameter to accept delimiter
- Updated all hardcoded commas to use
_delimiterfield - Updated
EscapeField()method to check for the configured delimiter
public CsvExporter(char delimiter = ',')
{
_delimiter = delimiter;
}
private string EscapeField(string field)
{
bool needsQuotes = field.Contains(_delimiter) || field.Contains('"') || ...
// Rest of escaping logic
}
3. Program.cs
Added command-line argument:
-d, --delimiter <value> CSV delimiter: 'comma' or 'semicolon' (default: comma)
Accepts: comma, ,, semicolon, or ;
4. Usage Examples
# Use semicolon delimiter (useful for Excel in Europe)
dotnet run -- -i "./Customers" --delimiter semicolon
# Short form
dotnet run -- -i "./Customers" -d ";"
# Default comma
dotnet run -- -i "./Customers"
Required Changes for Obsidian Plugin (Iteration 2)
1. Update TaskExportSettings Interface
Add delimiter setting:
interface TaskExportSettings {
outputPath: string;
customersFolder: string;
autoExport: boolean;
exportOnSave: boolean;
exportOnModify: boolean;
showNotifications: boolean;
compressLevels: boolean;
includeHeader: boolean;
debounceDelay: number;
delimiter: ',' | ';'; // NEW: CSV delimiter
}
Default value should be ',' (comma).
2. Update Settings UI
Add a dropdown/toggle in the settings panel:
new Setting(containerEl)
.setName('CSV Delimiter')
.setDesc('Choose delimiter for CSV output. Comma is standard, semicolon is common in Europe.')
.addDropdown(dropdown => dropdown
.addOption(',', 'Comma (,)')
.addOption(';', 'Semicolon (;)')
.setValue(this.plugin.settings.delimiter)
.onChange(async (value) => {
this.plugin.settings.delimiter = value as ',' | ';';
await this.plugin.saveSettings();
}));
3. Update CSV Writer/Exporter
Update the CSV generation logic to use the configured delimiter:
class CsvWriter {
private delimiter: string;
constructor(delimiter: ',' | ';' = ',') {
this.delimiter = delimiter;
}
private escapeField(field: string): string {
if (!field) return '';
// Check if escaping is needed
const needsQuotes = field.includes(this.delimiter) ||
field.includes('"') ||
field.includes('\n') ||
field.includes('\r');
if (needsQuotes) {
// Double any existing quotes
field = field.replace(/"/g, '""');
// Wrap in quotes
return `"${field}"`;
}
return field;
}
generateCsv(tasks: TaskItem[], includeHeader: boolean): string {
const lines: string[] = [];
// Build header
if (includeHeader) {
const headerParts = ['CustomerName', 'ProjectName', ...levelHeaders, 'Task'];
lines.push(headerParts.join(this.delimiter));
}
// Build data rows
for (const task of tasks) {
const parts = [
this.escapeField(task.customerName),
this.escapeField(task.projectName),
...task.levels.map(l => this.escapeField(l)),
this.escapeField(task.task)
];
lines.push(parts.join(this.delimiter));
}
return lines.join('\n');
}
}
4. Update Export Logic
Pass the delimiter setting to the CSV writer:
async exportTasks() {
const tasks = await this.extractTasks();
const writer = new CsvWriter(this.settings.delimiter);
const csv = writer.generateCsv(
tasks,
this.settings.includeHeader
);
await this.app.vault.adapter.write(
this.settings.outputPath,
csv
);
}
5. Update Status Bar/Notifications
Optionally show which delimiter was used:
new Notice(`Exported ${taskCount} tasks (${delimiterName})`);
Where delimiterName is:
','→"comma-separated"';'→"semicolon-separated"
Why This Feature?
Regional Differences:
- USA, UK: Comma is standard CSV delimiter
- Europe (Germany, France, etc.): Semicolon is standard because comma is used as decimal separator (1,234.56 → 1.234,56)
- Excel Behavior: Excel auto-detects delimiter based on system locale
Use Cases:
- European users need semicolon for Excel to open CSV correctly
- Data contains many commas (descriptions, addresses) → semicolon avoids escaping
- Compatibility with time tracking systems expecting specific delimiter
Testing Requirements
Test both delimiters:
// Test cases
const testData = [
{ task: 'Simple task', expected: 'Simple task' },
{ task: 'Task, with comma', expected: '"Task, with comma"' }, // comma mode
{ task: 'Task; with semicolon', expected: '"Task; with semicolon"' }, // semicolon mode
{ task: 'Task with "quotes"', expected: '"Task with ""quotes"""' }, // both modes
];
Verify:
- ✅ Comma delimiter (default) works
- ✅ Semicolon delimiter works
- ✅ Field escaping respects the chosen delimiter
- ✅ Setting persists across Obsidian restarts
- ✅ Excel opens files correctly with both delimiters
Implementation Priority
Priority Level: Medium
- Not blocking for MVP
- Adds significant value for European users
- Simple to implement (mirrors C# version)
- Should be included in v1.0.0 release
Documentation Updates
Update README.md to mention delimiter option in settings:
### Settings
| Setting | Description | Default |
|---------|-------------|---------|
| **CSV Delimiter** | Choose comma or semicolon delimiter | Comma |
Add usage note:
**Note for European Users**: If Excel doesn't open the CSV correctly, try changing the delimiter to semicolon in settings.
Summary
Port the delimiter feature from C# version to Obsidian plugin by:
- Add
delimiter: ',' | ';'to settings (default:',') - Add dropdown in settings UI
- Update CSV writer to use configurable delimiter
- Update field escaping to check for the configured delimiter
- Test with both delimiters
- Document in README
This maintains feature parity between Iteration 1 (C# console app) and Iteration 2 (Obsidian plugin).