From 3e710231c9aa3ac4f76d40ee4598517e13e11827 Mon Sep 17 00:00:00 2001 From: Christian Bager Bach Houmann Date: Thu, 15 Jul 2021 15:44:02 +0200 Subject: [PATCH] Capture: Add option to create 'Insert After' line if it isn't found --- README.md | 3 ++ manifest.json | 2 +- package.json | 2 +- src/constants.ts | 3 ++ src/formatters/captureChoiceFormatter.ts | 17 ++++++++++ src/gui/ChoiceBuilder/captureChoiceBuilder.ts | 32 ++++++++++++++++++- src/types/choices/CaptureChoice.ts | 4 +-- src/types/choices/ICaptureChoice.ts | 2 +- versions.json | 2 +- 9 files changed, 60 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 90867f5..ac5ecd5 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? +### 0.3.6 +- Added setting to create the 'Insert After' line if it isn't found. + ### 0.3.5 - You can now execute [inline JavaScript](docs/InlineScripts.md) in templates or captures. diff --git a/manifest.json b/manifest.json index c7e3eb3..0bacd64 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "quickadd", "name": "QuickAdd", - "version": "0.3.5", + "version": "0.3.6", "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 6b76f74..0ed2b62 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "quickadd", - "version": "0.3.5", + "version": "0.3.6", "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 4b0b11b..c84796a 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -20,6 +20,9 @@ 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]*$/); +export const CREATE_IF_NOT_FOUND_TOP: string = "top"; +export const CREATE_IF_NOT_FOUND_BOTTOM: string = "bottom"; + // == 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]+)?}}/); diff --git a/src/formatters/captureChoiceFormatter.ts b/src/formatters/captureChoiceFormatter.ts index 709f606..722c293 100644 --- a/src/formatters/captureChoiceFormatter.ts +++ b/src/formatters/captureChoiceFormatter.ts @@ -5,6 +5,7 @@ import {log} from "../logger/logManager"; import type QuickAdd from "../main"; import type {IChoiceExecutor} from "../IChoiceExecutor"; import {getLinesInString, templaterParseTemplate} from "../utility"; +import {CREATE_IF_NOT_FOUND_TOP} from "../constants"; export class CaptureChoiceFormatter extends CompleteFormatter { private choice: ICaptureChoice; @@ -52,6 +53,18 @@ export class CaptureChoiceFormatter extends CompleteFormatter { const targetPosition = fileContentLines.findIndex(line => targetRegex.test(line)); if (targetPosition === -1) { + if (this.choice.insertAfter?.createIfNotFound) { + const insertAfterLineAndFormatted: string = `${await this.format(this.choice.insertAfter.after)}\n${formatted}`; + + if (this.choice.insertAfter?.createIfNotFoundLocation === CREATE_IF_NOT_FOUND_TOP) { + const frontmatterEndPosition = this.file ? await this.getFrontmatterEndPosition(this.file) : 0; + return this.insertTextAfterPositionInBody(insertAfterLineAndFormatted, this.fileContent, frontmatterEndPosition - 1); + } + else { + return this.insertTextAfterPositionInBody(insertAfterLineAndFormatted, this.fileContent, fileContentLines.length - 1); + } + } + log.logError("unable to find insert after line in file.") } @@ -104,6 +117,10 @@ export class CaptureChoiceFormatter extends CompleteFormatter { } private insertTextAfterPositionInBody(text: string, body: string, pos: number): string { + if (pos === -1) { + return `${text}\n${body}`; + } + const splitContent = body.split("\n"); const pre = splitContent.slice(0, pos + 1).join("\n"); const post = splitContent.slice(pos + 1).join("\n"); diff --git a/src/gui/ChoiceBuilder/captureChoiceBuilder.ts b/src/gui/ChoiceBuilder/captureChoiceBuilder.ts index c4df501..b6b3c4b 100644 --- a/src/gui/ChoiceBuilder/captureChoiceBuilder.ts +++ b/src/gui/ChoiceBuilder/captureChoiceBuilder.ts @@ -3,7 +3,12 @@ import type ICaptureChoice from "../../types/choices/ICaptureChoice"; import type {App} from "obsidian"; import {Setting, TextAreaComponent, TextComponent, ToggleComponent} from "obsidian"; import {FormatSyntaxSuggester} from "../formatSyntaxSuggester"; -import {FILE_NAME_FORMAT_SYNTAX, FORMAT_SYNTAX} from "../../constants"; +import { + CREATE_IF_NOT_FOUND_BOTTOM, + CREATE_IF_NOT_FOUND_TOP, + FILE_NAME_FORMAT_SYNTAX, + FORMAT_SYNTAX +} from "../../constants"; import {FormatDisplayFormatter} from "../../formatters/formatDisplayFormatter"; import type QuickAdd from "../../main"; import {FileNameDisplayFormatter} from "../../formatters/fileNameDisplayFormatter"; @@ -155,6 +160,31 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { .setValue(this.choice.insertAfter?.insertAtEnd) .onChange(value => this.choice.insertAfter.insertAtEnd = value) ); + + const createLineIfNotFound: Setting = new Setting(this.contentEl); + createLineIfNotFound.setName("Create line if not found") + .setDesc("Creates the 'insert after' line if it is not found.") + .addToggle(toggle => { + if (!this.choice.insertAfter?.createIfNotFound) + this.choice.insertAfter.createIfNotFound = false; // Set to default + + toggle + .setValue(this.choice.insertAfter?.createIfNotFound) + .onChange(value => this.choice.insertAfter.createIfNotFound = value) + .toggleEl.style.marginRight = "1em" + } + ) + .addDropdown(dropdown => { + if (!this.choice.insertAfter?.createIfNotFoundLocation) + this.choice.insertAfter.createIfNotFoundLocation = CREATE_IF_NOT_FOUND_TOP; // Set to default + + dropdown + .setValue(this.choice.insertAfter?.createIfNotFoundLocation) + .onChange(value => this.choice.insertAfter.createIfNotFoundLocation = value) + .addOption(CREATE_IF_NOT_FOUND_TOP, "Top") + .addOption(CREATE_IF_NOT_FOUND_BOTTOM, "Bottom") + } + ) } } diff --git a/src/types/choices/CaptureChoice.ts b/src/types/choices/CaptureChoice.ts index 3118f36..dfb0d06 100644 --- a/src/types/choices/CaptureChoice.ts +++ b/src/types/choices/CaptureChoice.ts @@ -8,7 +8,7 @@ export class CaptureChoice extends Choice implements ICaptureChoice { captureToActiveFile: boolean; createFileIfItDoesntExist: { enabled: boolean, createWithTemplate: boolean, template: string }; format: { enabled: boolean; format: string }; - insertAfter: { enabled: boolean; after: string, insertAtEnd: boolean }; + insertAfter: { enabled: boolean; after: string, insertAtEnd: boolean, createIfNotFound: boolean, createIfNotFoundLocation: string }; prepend: boolean; task: boolean; @@ -20,7 +20,7 @@ export class CaptureChoice extends Choice implements ICaptureChoice { this.captureToActiveFile = false; this.createFileIfItDoesntExist = {enabled: false, createWithTemplate: false, template: ""}; this.format = {enabled: false, format: ""}; - this.insertAfter = {enabled: false, after: "", insertAtEnd: false}; + this.insertAfter = {enabled: false, after: "", insertAtEnd: false, createIfNotFound: false, createIfNotFoundLocation: "top"}; this.prepend = false; this.task = false; } diff --git a/src/types/choices/ICaptureChoice.ts b/src/types/choices/ICaptureChoice.ts index ec30706..800238a 100644 --- a/src/types/choices/ICaptureChoice.ts +++ b/src/types/choices/ICaptureChoice.ts @@ -9,6 +9,6 @@ export default interface ICaptureChoice extends IChoice { prepend: boolean; appendLink: boolean; task: boolean; - insertAfter: { enabled: boolean, after: string, insertAtEnd: boolean }; + insertAfter: { enabled: boolean; after: string, insertAtEnd: boolean, createIfNotFound: boolean, createIfNotFoundLocation: string }; } diff --git a/versions.json b/versions.json index 5005a87..047390b 100644 --- a/versions.json +++ b/versions.json @@ -1,4 +1,4 @@ { "0.2.16": "0.12.4", - "0.3.5": "0.12.5" + "0.3.6": "0.12.5" }