diff --git a/README.md b/README.md index d54990c..8661eaa 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,11 @@ Run commands and open links by clicking on ✨ Buttons ✨ --- -**last updated:** February 1st, 2024 +**last updated:** February 9th, 2024 +0.5.1 - fixed all those templater issues + +0.5.0 Holy shit, look at all these awesome people that helped improve Buttons! - Enhancement: Moved to more reliable templater processor ([shabegom]) @@ -333,15 +336,33 @@ Note: swap count is reset if you close the note. ## Releases -### 0.5.0 - +### 0.5.1 +- Bugfix: Templater commands that move, rename, etc should be working again +- The default templates plugin should be working again +- sets a default name for a button so problems don't happen. +### 0.5.0 +- Enhancement: Moved to more reliable templater processor ([shabegom]) - Bugfix: buttons now render in Live Preview mode when Obsidian starts ([Lx]) - Bugfix: improve reliability of `templater` option ([Lx]) -- improve speed of `remove` option ([Lx]) +- Enhancement: improve speed of `remove` option ([Lx]) +- Feature: Add default folder and prompt for name settings ([unxok]) +- Features: Button type copy for "copy text to clipboard", and custom color for button background and tex ([rafa-carmo]) +- Feature: adds hidden attribute to buttons ([Liimurr]) +- Enhancement: Create folder for new note if it doesn't exist ([SabriDW]) +- Bugfix: fix template search with folders having "/" prefixed ([Balake]) +- Feature: Open new tab when creating new file ([0snug0]) +- Update Readme: new note from template ([antulik]) [Lx]: https://github.com/Lx +[unxok]: https://github.com/unxok +[rafa-carmo]: https://github.com/rafa-carmo +[Liimurr]: https://github.com/Liimurr +[SabriDW]: https://github.com/SabriDW +[Balake]: https://github.com/Balake +[0snug0]: https://github.com/0snug0 +[antulik]: https://github.com/antulik ### 0.4.4 diff --git a/manifest.json b/manifest.json index fdbaf6e..25fd03b 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "id": "buttons", "name": "Buttons", "description": "Create Buttons in your Obsidian notes to run commands, open links, and insert templates", - "version": "0.5.0", + "version": "0.5.1", "author": "shabegom", "authorUrl": "https://shbgm.ca", "isDesktopOnly": false, diff --git a/src/button.ts b/src/button.ts index 07c5b30..9d683bf 100644 --- a/src/button.ts +++ b/src/button.ts @@ -4,13 +4,11 @@ import { calculate, command, copy, - copyText, link, remove, replace, swap, template, - templater, text, } from "./buttonTypes"; import { getButtonPosition, getInlineButtonPosition } from "./parser"; @@ -93,10 +91,6 @@ const clickHandler = async ( if (args.type === "link") { link(args); } - // handle copy text buttons - if (args.type === "copy") { - copyText(args); - } // handle template buttons if (args.type && args.type.includes("template")) { content = await app.vault.read(activeView.file); diff --git a/src/buttonTypes.ts b/src/buttonTypes.ts index 0b4a91e..9e4c930 100644 --- a/src/buttonTypes.ts +++ b/src/buttonTypes.ts @@ -21,7 +21,7 @@ import { setButtonSwapById, getButtonById, } from "./buttonStore"; -import { processTemplate } from "./templater" +import {processTemplate} from "./templater" export const calculate = async ( app: App, @@ -76,17 +76,17 @@ export const text = async ( ): Promise => { // prepend template above the button if (args.type.includes("prepend")) { - await prependContent(app, args.action, position.lineStart); + await prependContent(app, args.action, position.lineStart, false); } // append template below the button if (args.type.includes("append")) { - await appendContent(app, args.action, position.lineEnd); + await appendContent(app, args.action, position.lineEnd, false); } if (args.type.includes("note")) { - createNote(app, args.action, args.type, args.folder, args.prompt); + createNote(app, args.type, args.folder, args.prompt, args.action, false); } if (args.type.includes("line")) { - await addContentAtLine(app, args.action, args.type); + await addContentAtLine(app, args.action, args.type, false); } }; @@ -97,44 +97,57 @@ export const template = async ( ): Promise => { const templatesEnabled = app.internalPlugins.plugins.templates.enabled; const templaterPluginEnabled = app.plugins.plugins["templater-obsidian"]; + let isTemplater = false + const templateFile = args.action.toLowerCase(); + const allFiles = app.vault.getFiles(); + let file = null - // only run if templates plugin is enabled if (templatesEnabled || templaterPluginEnabled) { - const folders: string[] = [ + if (templatesEnabled) { + const folder: string = templatesEnabled && - app.internalPlugins.plugins.templates.instance.options.folder?.toLowerCase(), + app.internalPlugins.plugins.templates.instance.options.folder?.toLowerCase() + const isFound = allFiles.filter((file) => { + let found = false; + if (file.path.toLowerCase() === `${folder}/${templateFile}.md`) { + found = true; + } + return found + }) + file = isFound[0] + } + + if (!file && templaterPluginEnabled) { + const folder: string = templaterPluginEnabled && app.plugins?.plugins[ "templater-obsidian" - ]?.settings.templates_folder?.toLowerCase(), - ].filter((folder) => folder); - const templateFile = args.action.toLowerCase(); - const allFiles = app.vault.getFiles(); - const file: TFile = allFiles.filter((file) => { + ]?.settings.templates_folder?.toLowerCase() + const isFound = allFiles.filter((file) => { let found = false; - folders[0] && - folders.forEach((folder) => { if (file.path.toLowerCase() === `${folder}/${templateFile}.md`) { found = true; + isTemplater = true; } - }); return found; - })[0]; + }) + file = isFound[0] + } + if (file) { - const content = await processTemplate(file) // prepend template above the button if (args.type.includes("prepend")) { - await prependContent(app, content, position.lineStart); + await prependContent(app, file, position.lineStart, isTemplater); } // append template below the button if (args.type.includes("append")) { - await appendContent(app, content, position.lineEnd); + await appendContent(app, file, position.lineEnd, isTemplater); } if (args.type.includes("note")) { - createNote(app, content, args.type, args.folder, args.prompt, file, args.templater); + createNote(app, args.type, args.folder, args.prompt, file, isTemplater); } if (args.type.includes("line")) { - await addContentAtLine(app, content, args.type); + await addContentAtLine(app, file, args.type, isTemplater); } } else { new Notice( @@ -303,7 +316,3 @@ export const templater = async ( } }; -export const copyText = ({ action }: Arguments): void => { - navigator.clipboard.writeText(action); - new Notice('Text Copied!'); -} diff --git a/src/handlers.ts b/src/handlers.ts index 053896a..2112fbb 100644 --- a/src/handlers.ts +++ b/src/handlers.ts @@ -3,7 +3,7 @@ import { ExtendedBlockCache } from "./types"; import { getStore } from "./buttonStore"; import { createContentArray, handleValueArray } from "./utils"; import { nameModal } from "./nameModal"; -import { Z_FULL_FLUSH } from "node:zlib"; +import templater from "./templater"; export const removeButton = async ( app: App, @@ -80,15 +80,29 @@ export const removeSection = async ( export const prependContent = async ( app: App, - insert: string, + insert: string | TFile, lineStart: number, + isTemplater: boolean, ): Promise => { const activeView = app.workspace.getActiveViewOfType(MarkdownView); if (activeView) { const file = activeView.file; let content = await app.vault.read(file); const contentArray = content.split("\n"); - contentArray.splice(lineStart, 0, insert); + if (typeof insert === "string") { + contentArray.splice(lineStart, 0, `${insert}`); + } else { + if (isTemplater) { + const runTemplater = await templater(insert, file); + const content = await app.vault.read(insert); + const processed = await runTemplater(content); + contentArray.splice(lineStart, 0, `${processed}`); + } else { + activeView.editor.setCursor(lineStart) + await (app as any).internalPlugins?.plugins["templates"].instance + .insertTemplate(insert); + } + } content = contentArray.join("\n"); await app.vault.modify(file, content); } else { @@ -98,8 +112,9 @@ export const prependContent = async ( export const appendContent = async ( app: App, - insert: string, + insert: any, lineEnd: number, + isTemplater: boolean, ): Promise => { const activeView = app.workspace.getActiveViewOfType(MarkdownView); if (activeView) { @@ -112,11 +127,23 @@ export const appendContent = async ( contentArray[lineEnd + 1].includes("^button") ) { insertionPoint = lineEnd + 2; - insert = `\n${insert}`; } else { insertionPoint = lineEnd + 1; } - contentArray.splice(insertionPoint, 0, `${insert}`); + if (typeof insert === "string") { + contentArray.splice(insertionPoint, 0, `\n${insert}`); + } else { + if (isTemplater) { + const runTemplater = await templater(insert, file); + const content = await app.vault.read(insert); + const processed = await runTemplater(content); + contentArray.splice(insertionPoint, 0, `${processed}`); + } else { + activeView.editor.setCursor(insertionPoint) + await (app as any).internalPlugins?.plugins["templates"].instance + .insertTemplate(insert); + } + } content = contentArray.join("\n"); await app.vault.modify(file, content); } else { @@ -126,8 +153,9 @@ export const appendContent = async ( export const addContentAtLine = async ( app: App, - insert: string, + insert: string | TFile, type: string, + isTemplater: boolean, ): Promise => { const lineNumber = type.match(/(\d+)/g); if (lineNumber[0]) { @@ -137,7 +165,20 @@ export const addContentAtLine = async ( const file = activeView.file; let content = await app.vault.read(file); const contentArray = content.split("\n"); - contentArray.splice(insertionPoint, 0, `${insert}`); + if (typeof insert === "string") { + contentArray.splice(insertionPoint, 0, `${insert}`); + } else { + if (isTemplater) { + const runTemplater = await templater(insert, file); + const content = await app.vault.read(insert); + const processed = await runTemplater(content); + contentArray.splice(insertionPoint, 0, `${processed}`); + } else { + activeView.editor.setCursor(insertionPoint) + await (app as any).internalPlugins?.plugins["templates"].instance + .insertTemplate(insert); + } + } content = contentArray.join("\n"); await app.vault.modify(file, content); } @@ -148,12 +189,11 @@ export const addContentAtLine = async ( export const createNote = async ( app: App, - content: string, type: string, folder: string, prompt: string, - filePath?: TFile, - templater?: string, + filePath: TFile | string, + isTemplater?: boolean, ): Promise => { const path = type.match(/\(([\s\S]*?),?\s?(split|tab)?\)/); @@ -168,7 +208,7 @@ export const createNote = async ( const directoryPath = fullPath.substring(0, fullPath.lastIndexOf("/")); // Check if the directory exists, if not, create it if (directoryPath && !app.vault.getAbstractFileByPath(directoryPath)) { - console.log("trying to create folder at: ", directoryPath) + console.log("trying to create folder at: ", directoryPath); await app.vault.createFolder(directoryPath); } @@ -181,9 +221,24 @@ export const createNote = async ( ? `${directoryPath}/${promptedName}.md` : fullPath; } + let file: TFile; + + if (typeof filePath === "string") { + file = await app.vault.create(fullPath, filePath); + } - await app.vault.create(fullPath, content); - const file = app.vault.getAbstractFileByPath(fullPath) as TFile; + + const templateContent = await app.vault.read(filePath as TFile); + if (isTemplater) { + file = await app.vault.create(fullPath, templateContent); + const runTemplater = await templater(filePath, file); + const content = await app.vault.read(filePath); + const processed = await runTemplater(content); + await app.vault.modify(file, processed); + } + if (!isTemplater && typeof filePath !== "string") { + file = await app.vault.create(fullPath, ""); + } if (path[2] === "split") { await app.workspace.splitActiveLeaf().openFile(file); @@ -192,16 +247,10 @@ export const createNote = async ( } else { await app.workspace.getLeaf().openFile(file); } - // I don't know what this was supposed to do... - // if (filePath) { - // if (templater) { - // (app as any).plugins.plugins["templater-obsidian"].templater - // .append_template_to_active_file(filePath); - // } else { - // (app as any).internalPlugins?.plugins["templates"].instance - // .insertTemplate(filePath); - // } - // } + if (!isTemplater && typeof filePath !== "string") { + await (app as any).internalPlugins?.plugins["templates"].instance + .insertTemplate(filePath); + } } catch (e) { console.error("Error in Buttons: ", e); new Notice("There was an error! Maybe the file already exists?", 2000); diff --git a/src/suggest.ts b/src/suggest.ts index 9b6b44e..dd2c24d 100644 --- a/src/suggest.ts +++ b/src/suggest.ts @@ -233,7 +233,7 @@ export class TemplateSuggest extends TextInputSuggest { folders.push(folder.toLowerCase()); } if (this.templaterPlugin) { - const folder = this.templaterPlugin.settings.template_folder; + const folder = this.templaterPlugin.settings.templates_folder; if (folder) { folders.push(folder.toLowerCase()); } diff --git a/src/templater.ts b/src/templater.ts index 99e707e..1afd607 100644 --- a/src/templater.ts +++ b/src/templater.ts @@ -5,14 +5,17 @@ type RunTemplater = (command: string) => Promise; interface Item { name: string; static_functions: Array<[string, () => unknown]>; + dynamic_functions: Array<[string, () => unknown]>; } -async function templater(file?: TFile): Promise { - const activeFile = file ? file : app.workspace.getActiveFile(); +async function templater( + template: TFile, + target: TFile, +): Promise { const config = { - template_file: activeFile, - active_file: activeFile, - target_file: activeFile, + template_file: template, + active_file: app.workspace.getActiveFile(), + target_file: target, run_mode: "DynamicProcessor", }; const plugins = app.plugins.plugins; @@ -24,25 +27,18 @@ async function templater(file?: TFile): Promise { // eslint-disable-next-line // @ts-ignore const { templater } = plugins["templater-obsidian"]; - const internalModuleArray = - templater.functions_generator.internal_functions.modules_array; - const functions = internalModuleArray.reduce( - (acc: Record, item: Item) => { - acc[item.name] = Object.fromEntries(item.static_functions); - return acc; - }, - {} - ); + const functions = await templater.functions_generator.internal_functions.generate_object(config) + functions.user = {}; - const userScriptFunctions = - await templater.functions_generator.user_functions.user_script_functions.generate_user_script_functions(); + const userScriptFunctions = await templater.functions_generator.user_functions + .user_script_functions.generate_user_script_functions(config); userScriptFunctions.forEach((value: () => unknown, key: string) => { functions.user[key] = value; }); - if (activeFile) { - const userSystemFunctions = - await templater.functions_generator.user_functions.user_system_functions.generate_system_functions( - config + if (template) { + const userSystemFunctions = await templater.functions_generator + .user_functions.user_system_functions.generate_system_functions( + config, ); userSystemFunctions.forEach((value: () => unknown, key: string) => { functions.user[key] = value; @@ -56,7 +52,7 @@ async function templater(file?: TFile): Promise { export async function processTemplate(file: TFile) { try { const content = await app.vault.read(file); - const runTemplater = await templater(file); + const runTemplater = await templater(file, file); if (runTemplater) { const processed = await runTemplater(content); return processed; diff --git a/src/types.ts b/src/types.ts index 6bd952e..46eda67 100644 --- a/src/types.ts +++ b/src/types.ts @@ -60,3 +60,5 @@ export interface Position { lineStart: number; lineEnd: number; } + +