import { App, Plugin, PluginSettingTab, Setting, moment, Vault, Notice, } from "obsidian"; import { nouns } from "./nouns.js"; import { adjectives } from "./adjectives.js"; import { capitalize, sample } from "lodash-es"; interface ScrapsPluginSettings { scrapsRootDir: string; scrapsPathFormat: string; scrapsFileName: string; } const DEFAULT_SETTINGS: ScrapsPluginSettings = { scrapsRootDir: "_Scraps", scrapsPathFormat: "MM MMM/R", scrapsFileName: "ddd MMM DD hhmmssa", }; function getFormattedDate(format: string): string { const momentFormatted = moment().format(format); const currentWeek = Math.ceil(moment().date() / 7); return momentFormatted.replace("R", `Week ${currentWeek}`); } async function mkdirp(vault: Vault, folderPath: string): Promise { const pathParts = folderPath.split("/"); // Start building the path incrementally let currentPath = ""; for (const part of pathParts) { currentPath = currentPath ? `${currentPath}/${part}` : part; try { // Check if folder exists if (!vault.getAbstractFileByPath(currentPath)) { // Create the folder if it doesn't exist await vault.createFolder(currentPath); } } catch (error) { console.error(`Error creating folder ${currentPath}:`, error); throw error; } } } export default class ScrapsPlugin extends Plugin { settings: ScrapsPluginSettings; async ensureScrapDir(): Promise { const pathname = `${this.getScrapDir()}`; await mkdirp(this.app.vault, pathname); return pathname; } getScrapDir(): string { return `${this.settings.scrapsRootDir}/${getFormattedDate( this.settings.scrapsPathFormat )}`; } getScrapFileName(): string { const adj = capitalize(sample(adjectives)); const noun = capitalize(sample(nouns)); return `Scrap ${adj} ${noun}.md`; } getScrapFilePath(): string { return `${this.getScrapDir()}/${this.getScrapFileName()}`; } async createScrap() { await this.ensureScrapDir(); const newScrap = await this.app.vault.create( this.getScrapFilePath(), "" ); await this.app.workspace.getLeaf(false).openFile(newScrap); } async convertToScrap() { const currentFile = this.app.workspace.getActiveFile(); if (currentFile === null) { new Notice("No file is currently open"); return; } await this.ensureScrapDir(); await this.app.fileManager.renameFile( currentFile, this.getScrapFilePath() ); } async onload() { await this.loadSettings(); this.addSettingTab(new ScrapsSettingTab(this.app, this)); this.addCommand({ id: "scraps-new", name: "Scraps: Create new Scrap", icon: "badge-plus", callback: async () => { this.createScrap(); }, }); this.addRibbonIcon("badge-plus", "Create new Scrap", async () => { this.createScrap(); }); this.addCommand({ id: "scraps-convert", name: "Scraps: Convert current file to Scrap", icon: "file-plus", editorCallback: async () => this.convertToScrap(), }); this.addRibbonIcon("file-plus", "Convert file to Scrap", async () => { this.convertToScrap(); }); this.addCommand({ id: "scraps-copy", name: "Scraps: Copy current file to Scraps", icon: "copy-plus", editorCallback: async () => { const currentFile = this.app.workspace.getActiveFile(); if (currentFile === null) { new Notice("No file is currently open"); return; } await this.ensureScrapDir(); const newScrap = await this.app.vault.copy( currentFile, this.getScrapFilePath() ); await this.app.workspace.getLeaf(false).openFile(newScrap); }, }); } onunload() {} async loadSettings() { this.settings = Object.assign( {}, DEFAULT_SETTINGS, await this.loadData() ); } async saveSettings() { await this.saveData(this.settings); } } class ScrapsSettingTab extends PluginSettingTab { plugin: ScrapsPlugin; constructor(app: App, plugin: ScrapsPlugin) { super(app, plugin); this.plugin = plugin; } display(): void { const { containerEl } = this; containerEl.empty(); new Setting(containerEl) .setName("Scraps Root Directory") .setDesc("The directory where all your scraps will be stored") .addText((text) => text .setPlaceholder("Enter directory") .setValue(this.plugin.settings.scrapsRootDir) .onChange(async (value) => { this.plugin.settings.scrapsRootDir = value; await this.plugin.saveSettings(); }) ); new Setting(containerEl) .setName("Scraps Path Format") .setDesc("The format of the path to the scrap") .addText((text) => text .setPlaceholder("Enter format") .setValue(this.plugin.settings.scrapsPathFormat) .onChange(async (value) => { this.plugin.settings.scrapsPathFormat = value; await this.plugin.saveSettings(); }) ); new Setting(containerEl) .setName("Scraps File Name Format") .setDesc("The format of the filename") .addText((text) => text .setPlaceholder("Enter format") .setValue(this.plugin.settings.scrapsFileName) .onChange(async (value) => { this.plugin.settings.scrapsFileName = value; await this.plugin.saveSettings(); }) ); } }