obsidian-scraps/main.ts

227 lines
5.1 KiB
TypeScript

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<void> {
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<string> {
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();
})
);
}
}