From 40add79b50a6e2973d94525cd16bafbcdbbe7cc0 Mon Sep 17 00:00:00 2001 From: Christian Bager Bach Houmann Date: Mon, 12 Jul 2021 16:38:09 +0200 Subject: [PATCH] Inline scripts --- README.md | 26 +++---------------------- manifest.json | 2 +- package.json | 2 +- src/constants.ts | 2 ++ src/engine/MacroChoiceEngine.ts | 3 --- src/engine/SingleInlineScriptEngine.ts | 17 ++++++++++++++++ src/formatters/completeFormatter.ts | 27 ++++++++++++++++++++++++++ versions.json | 2 +- 8 files changed, 52 insertions(+), 29 deletions(-) create mode 100644 src/engine/SingleInlineScriptEngine.ts diff --git a/README.md b/README.md index 5209247..93705d9 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,9 @@ Quickly add new pages or content to your vault. You can also do a [manual installation](docs/ManualInstallation.md). ## What's new? +### o.3.5 +- You can now execute inline JavaScript in templates or captures. + ### 0.3.4 - When creating a new file with a template, and the file already exists, you will be asked what you want to do. You can append the template to the top, bottom, overwrite the file with the template, or do nothing. @@ -26,29 +29,6 @@ You can also do a [manual installation](docs/ManualInstallation.md). - Added a new API feature which allows you to execute choices from within user scripts. These keep the current variables for the execution, so you can 'transfer' variables. - (0.3.1 HOTFIX) Fix choice finding algorithm. -### 0.2.14 - 0.2.16 -- Add 'Insert at the end of section' feature to Captures. -- Revamped the Capture & Template format suggesters. They're now more like smart-autocompleters. -- Template choices now also use the Obsidian method for creating links to files. - -### 0.2.13 -- Add error logging for when no macro is in the choice. -- Add 'Add' buttons to Macro Builder. -- Multi choices can now have commands & hotkeys. -- Attempted to address #39 - capture not creating template. -- Suggest files from both core templates folder and templater templates folder when creating a Template choice. -- Fix bug where, if there is an emoji in the folder name, the file sometimes doesn't get created -- Update the API. The suggester can now take a map function for the `displayItems`, which will be executed on the `actualItems`. There is also a utility module now, which currently allows you to set or get your clipboard. - -### 0.2.11 - 0.2.12 -- Implement Quick Commands - ironically, starting with a Wait command. With this command, you can add a delay to your macros. Useful for commands that may take a while to finish. -- Fix a bug where the command sequence did not save. -- Fix bug where 'Create file if it doesn't exist' did not work as intended when no template was given. -- Updated the documentation with new examples and changes to settings. -- Remove (missed) `console.log`. -- If formatted content is empty, don't add anything. -- Capture: Don't create file if setting is disabled. - ## Getting started The first thing you'll want to do is add a new choice. A choice can be one of four types. - [Template Choice](docs/Choices/TemplateChoice.md) - A powerful way to insert templates into your vault. diff --git a/manifest.json b/manifest.json index 50ddaaf..c7e3eb3 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "quickadd", "name": "QuickAdd", - "version": "0.3.4", + "version": "0.3.5", "minAppVersion": "0.12.5", "description": "Quickly add new pages or content to your vault.", "author": "Christian B. B. Houmann", diff --git a/package.json b/package.json index 3f6330d..6b76f74 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "quickadd", - "version": "0.3.4", + "version": "0.3.5", "description": "Quickly add new pages or content to your vault.", "main": "main.js", "scripts": { diff --git a/src/constants.ts b/src/constants.ts index eb2cef2..4b0b11b 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -20,6 +20,7 @@ export const FILE_NAME_FORMAT_SYNTAX: string[] = [ export const FILE_NUMBER_REGEX: RegExp = new RegExp(/([0-9]*)\.md$/); export const NUMBER_REGEX: RegExp = new RegExp(/^-?[0-9]*$/); +// == Format Syntax == // export const DATE_REGEX: RegExp = new RegExp(/{{DATE(\+-?[0-9]+)?}}/); export const DATE_REGEX_FORMATTED: RegExp = new RegExp(/{{DATE:([^}\n\r+]*)(\+-?[0-9]+)?}}/); export const NAME_VALUE_REGEX: RegExp = new RegExp(/{{NAME}}|{{VALUE}}/); @@ -31,6 +32,7 @@ export const JAVASCRIPT_FILE_EXTENSION_REGEX: RegExp = new RegExp(/\.js$/); export const MACRO_REGEX: RegExp = new RegExp(/{{MACRO:([^\n\r}]*)}}/); export const TEMPLATE_REGEX: RegExp = new RegExp(/{{TEMPLATE:([^\n\r}]*.md)}}/); export const LINEBREAK_REGEX: RegExp = new RegExp(/\\n/); +export const INLINE_JAVASCRIPT_REGEX: RegExp = new RegExp(/`{3,}js quickadd([\s\S]*?)`{3,}/); export const FILE_LINK_REGEX: RegExp = new RegExp(/\[\[([^\]]*)$/); diff --git a/src/engine/MacroChoiceEngine.ts b/src/engine/MacroChoiceEngine.ts index d70a0b2..6c7a128 100644 --- a/src/engine/MacroChoiceEngine.ts +++ b/src/engine/MacroChoiceEngine.ts @@ -11,11 +11,8 @@ import {QuickAddChoiceEngine} from "./QuickAddChoiceEngine"; import type {IMacro} from "../types/macros/IMacro"; import GenericSuggester from "../gui/GenericSuggester/genericSuggester"; import type {IChoiceCommand} from "../types/macros/IChoiceCommand"; -import type IChoice from "../types/choices/IChoice"; import type QuickAdd from "../main"; import type {IChoiceExecutor} from "../IChoiceExecutor"; -import {ChoiceType} from "../types/choices/choiceType"; -import type IMultiChoice from "../types/choices/IMultiChoice"; import {getUserScriptMemberAccess, waitFor} from "../utility"; import type {IWaitCommand} from "../types/macros/QuickCommands/IWaitCommand"; diff --git a/src/engine/SingleInlineScriptEngine.ts b/src/engine/SingleInlineScriptEngine.ts new file mode 100644 index 0000000..844a0d5 --- /dev/null +++ b/src/engine/SingleInlineScriptEngine.ts @@ -0,0 +1,17 @@ +import type {App} from "obsidian"; +import type QuickAdd from "../main"; +import type {IChoiceExecutor} from "../IChoiceExecutor"; +import {MacroChoiceEngine} from "./MacroChoiceEngine"; + +export class SingleInlineScriptEngine extends MacroChoiceEngine { + constructor(app: App, plugin: QuickAdd, choiceExecutor: IChoiceExecutor, variables: Map) { + super(app, plugin, null, null, choiceExecutor, variables); + } + + public async runAndGetOutput(code: string): Promise { + const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor + const userCode = new AsyncFunction(code); + + return await userCode.bind(this.params, this).call(); + } +} \ No newline at end of file diff --git a/src/formatters/completeFormatter.ts b/src/formatters/completeFormatter.ts index 4a2cc46..a84d846 100644 --- a/src/formatters/completeFormatter.ts +++ b/src/formatters/completeFormatter.ts @@ -8,6 +8,8 @@ import {SingleMacroEngine} from "../engine/SingleMacroEngine"; import {SingleTemplateEngine} from "../engine/SingleTemplateEngine"; import {MarkdownView} from "obsidian"; import type {IChoiceExecutor} from "../IChoiceExecutor"; +import {INLINE_JAVASCRIPT_REGEX} from "../constants"; +import {SingleInlineScriptEngine} from "../engine/SingleInlineScriptEngine"; export class CompleteFormatter extends Formatter { private valueHeader: string; @@ -20,6 +22,7 @@ export class CompleteFormatter extends Formatter { protected async format(input: string): Promise { let output: string = input; + output = await this.replaceInlineJavascriptInString(output); output = await this.replaceMacrosInString(output); output = await this.replaceTemplateInString(output); output = this.replaceDateInString(output); @@ -98,4 +101,28 @@ export class CompleteFormatter extends Formatter { return activeView.editor.getSelection(); } + + protected async replaceInlineJavascriptInString(input: string) { + let output: string = input; + + while (INLINE_JAVASCRIPT_REGEX.test(output)) { + const match: RegExpMatchArray = INLINE_JAVASCRIPT_REGEX.exec(output); + const code: string = match[1]?.trim(); + + if (code) { + const executor = new SingleInlineScriptEngine(this.app, this.plugin, this.choiceExecutor, this.variables); + const outVal: any = await executor.runAndGetOutput(code); + + for (let key in executor.params.variables) { + this.variables.set(key, executor.params.variables[key]); + } + + output = typeof outVal === "string" ? + output.replace(INLINE_JAVASCRIPT_REGEX, outVal) : + output.replace(INLINE_JAVASCRIPT_REGEX, ""); + } + } + + return output; + } } \ No newline at end of file diff --git a/versions.json b/versions.json index 64a52fa..5005a87 100644 --- a/versions.json +++ b/versions.json @@ -1,4 +1,4 @@ { "0.2.16": "0.12.4", - "0.3.4": "0.12.5" + "0.3.5": "0.12.5" }