onlyworlds_obsidian-plugin/Commands/CreateTemplatesCommand.ts
Titus 87e003e2e7 2.0.0: SDK, auto-sync, native settings, modernized build
Major rebuild. Plugin now uses @onlyworlds/sdk for API calls via Obsidian's
requestUrl, native PluginSettingTab for configuration, and a debounced auto-sync
engine that pushes element edits to onlyworlds.com after idle.

Changes
- Drop handrolled API code; route all writes through @onlyworlds/sdk subclass
- Native settings tab: API key, PIN, default world, sync mode, debounce
- PIN handling: persist in settings or cache per session; no per-save prompts
- Auto-sync toggle with configurable debounce (default 3s)
- Status bar + ribbon icon reflect sync state (idle/dirty/syncing/synced/error)
- Ribbon click opens menu (Sync / Settings / About) instead of firing sync
- Settings API key wins over per-world World.md (legacy fallback preserved)
- Add Map, Pin, Marker to element category enum (now 22)
- ESLint config (eslint-plugin-obsidianmd) scoped to new code
- Modernize build: TS 5.8, esbuild 0.25, stricter tsconfig
- Drop dead code: GraphViewExtensions, dead command imports, handleApiError

Compatibility
- Existing v1 vaults work unchanged. Span-tag format preserved.
- OnlyWorlds/Settings.md still readable; new settings tab takes precedence.
- isDesktopOnly: true. Mobile pending verification.
2026-05-11 12:51:28 +02:00

74 lines
3 KiB
TypeScript

import { App, Notice, normalizePath } from 'obsidian';
import { v7 as uuidv7 } from 'uuid';
import { Category } from '../enums';
export class CreateTemplatesCommand {
app: App;
manifest: any;
constructor(app: App, manifest: any) {
this.app = app;
this.manifest = manifest;
}
async execute(): Promise<void> {
const templateFolder = normalizePath('OnlyWorlds/PluginFiles/Templates');
const categories = Object.keys(Category).filter(key => isNaN(Number(key)));
// Ensure the template folder exists
await this.createFolderIfNeeded(templateFolder);
// Base URL for fetching the templates from GitHub
const githubBaseUrl = 'https://raw.githubusercontent.com/OnlyWorlds/OnlyWorlds/main/languages/obsidian_templates/';
// Categories with no legacy template files upstream (added to schema later).
const noLegacyTemplate = new Set(['Map', 'Pin', 'Marker']);
for (const category of categories) {
if (noLegacyTemplate.has(category)) {
continue;
}
const fileName = `${category}.md`;
const targetPath = normalizePath(`${templateFolder}/${fileName}`);
const templateUrl = `${githubBaseUrl}${fileName}`;
// Check if the template file already exists in the user's vault
if (!this.app.vault.getAbstractFileByPath(targetPath)) {
try {
// Fetch the template from GitHub
const response = await fetch(templateUrl);
if (!response.ok) {
throw new Error(`Failed to fetch template: ${templateUrl}`);
}
let content = await response.text();
// Replace {{id}} placeholder with a UUID, if needed
const uuid = uuidv7();
content = content.replace('{{id}}', uuid);
// Write the content to the user's vault
await this.app.vault.create(targetPath, content);
console.log(`Template ${fileName} created successfully.`);
} catch (error) {
console.error(`Error fetching template for ${category}:`, error);
new Notice(`Error fetching template for ${category}.`);
}
} else {
console.log(`Template ${fileName} already exists, skipping.`);
}
}
}
async createFolderIfNeeded(folderPath: string) {
try {
const existingFolder = this.app.vault.getAbstractFileByPath(folderPath);
if (!existingFolder) {
await this.app.vault.createFolder(folderPath);
new Notice('Fetching Plugin Files..');
}
} catch (error) {
console.error(`Error creating folder: ${folderPath}`, error);
new Notice('Error: Could not create folder.');
}
}
}