Skip to content

Commit 77dda11

Browse files
authored
Assorted fixes (#52)
1 parent 69b3ae0 commit 77dda11

15 files changed

+180
-121
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ Quickly add new pages or content to your vault.
99
You can also do a [manual installation](docs/ManualInstallation.md).
1010

1111
## What's new?
12+
### 3.6.10
13+
- Added a warning when deleting a Multi choice that you will delete all choices within.
14+
- Fix #51 - Templater syntax is now processed when appending to the current file.
15+
- Fix "Template (not found)" for templates that exist.
16+
- Fix #46 - Error if adding a template that doesn't exist.
17+
- Template: Create file in same folder as current file.
18+
- Fix bug with insertion and creation of 'Insert After' line (if it does not exist).
19+
1220
### 0.3.6 - 0.3.9
1321
- Added setting to create the 'Insert After' line if it isn't found.
1422
- (HOTFIX) Escape regular expression special characters in Insert After when searching for it.

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "quickadd",
33
"name": "QuickAdd",
4-
"version": "0.3.9",
4+
"version": "0.3.10",
55
"minAppVersion": "0.12.5",
66
"description": "Quickly add new pages or content to your vault.",
77
"author": "Christian B. B. Houmann",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "quickadd",
3-
"version": "0.3.9",
3+
"version": "0.3.10",
44
"description": "Quickly add new pages or content to your vault.",
55
"main": "main.js",
66
"scripts": {

src/engine/CaptureChoiceEngine.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type ICaptureChoice from "../types/choices/ICaptureChoice";
22
import type {App, TFile} from "obsidian";
33
import {log} from "../logger/logManager";
44
import {CaptureChoiceFormatter} from "../formatters/captureChoiceFormatter";
5-
import {appendToCurrentLine, replaceTemplaterTemplatesInCreatedFile} from "../utility";
5+
import {appendToCurrentLine, replaceTemplaterTemplatesInCreatedFile, templaterParseTemplate} from "../utility";
66
import {VALUE_SYNTAX} from "../constants";
77
import type QuickAdd from "../main";
88
import {QuickAddChoiceEngine} from "./QuickAddChoiceEngine";
@@ -96,20 +96,21 @@ export class CaptureChoiceEngine extends QuickAddChoiceEngine {
9696
}
9797

9898
private async captureToActiveFile() {
99+
const activeFile: TFile = this.app.workspace.getActiveFile();
100+
if (!activeFile) {
101+
log.logError("Cannot capture to active file - no active file.")
102+
}
103+
99104
let content: string = await this.getCaptureContent();
100105

101106
if (this.choice.format.enabled) {
102107
content = await this.formatter.formatContent(content, this.choice);
108+
content = await templaterParseTemplate(this.app, content, activeFile);
103109
}
104110

105111
if (!content) return;
106112

107113
if (this.choice.prepend) {
108-
const activeFile: TFile = this.app.workspace.getActiveFile();
109-
if (!activeFile) {
110-
log.logError("Cannot capture to active file - no active file.")
111-
}
112-
113114
const fileContent: string = await this.app.vault.cachedRead(activeFile);
114115
const newFileContent: string = `${fileContent}${content}`
115116

src/engine/SingleTemplateEngine.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {TemplateEngine} from "./TemplateEngine";
22
import type {App} from "obsidian";
33
import type QuickAdd from "../main";
44
import type {IChoiceExecutor} from "../IChoiceExecutor";
5+
import {log} from "../logger/logManager";
56

67
export class SingleTemplateEngine extends TemplateEngine {
78
constructor(app: App, plugin: QuickAdd, private templatePath: string, choiceExecutor: IChoiceExecutor) {
@@ -10,7 +11,7 @@ export class SingleTemplateEngine extends TemplateEngine {
1011
public async run(): Promise<string> {
1112
let templateContent: string = await this.getTemplateContent(this.templatePath);
1213
if (!templateContent) {
13-
throw new Error(`Template ${this.templatePath} not found.`);
14+
log.logError(`Template ${this.templatePath} not found.`);
1415
}
1516

1617
templateContent = await this.formatter.formatFileContent(templateContent);

src/engine/TemplateChoiceEngine.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type ITemplateChoice from "../types/choices/ITemplateChoice";
22
import type {App} from "obsidian";
33
import {TFile} from "obsidian";
4-
import {appendToCurrentLine, getAllFolders} from "../utility";
4+
import {appendToCurrentLine, getAllFolderPathsInVault} from "../utility";
55
import {
66
fileExistsAppendToBottom,
77
fileExistsAppendToTop,
@@ -28,13 +28,7 @@ export class TemplateChoiceEngine extends TemplateEngine {
2828
let folderPath: string = "";
2929

3030
if (this.choice.folder.enabled) {
31-
let folders: string[] = this.choice.folder.folders;
32-
33-
if (this.choice.folder?.chooseWhenCreatingNote) {
34-
folders = await getAllFolders(this.app);
35-
}
36-
37-
folderPath = await this.getOrCreateFolder(folders);
31+
folderPath = await this.getFolderPath();
3832
}
3933

4034
let filePath;
@@ -96,4 +90,24 @@ export class TemplateChoiceEngine extends TemplateEngine {
9690
}
9791
}
9892
}
93+
94+
private async getFolderPath() {
95+
let folders: string[] = [...this.choice.folder.folders];
96+
97+
if (this.choice.folder?.chooseWhenCreatingNote) {
98+
const allFoldersInVault: string[] = getAllFolderPathsInVault(this.app);
99+
return await this.getOrCreateFolder(allFoldersInVault);
100+
}
101+
102+
if (this.choice.folder?.createInSameFolderAsActiveFile) {
103+
const activeFile: TFile = this.app.workspace.getActiveFile();
104+
105+
if (!activeFile)
106+
log.logError("No active file. Cannot create new file.");
107+
108+
return this.getOrCreateFolder([activeFile.parent.path]);
109+
}
110+
111+
return await this.getOrCreateFolder(folders);
112+
}
99113
}

src/formatters/captureChoiceFormatter.ts

Lines changed: 56 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {log} from "../logger/logManager";
55
import type QuickAdd from "../main";
66
import type {IChoiceExecutor} from "../IChoiceExecutor";
77
import {escapeRegExp, getLinesInString, templaterParseTemplate} from "../utility";
8-
import {CREATE_IF_NOT_FOUND_TOP} from "../constants";
8+
import {CREATE_IF_NOT_FOUND_BOTTOM, CREATE_IF_NOT_FOUND_TOP} from "../constants";
99

1010
export class CaptureChoiceFormatter extends CompleteFormatter {
1111
private choice: ICaptureChoice;
@@ -47,74 +47,86 @@ export class CaptureChoiceFormatter extends CompleteFormatter {
4747
return `${this.fileContent}\n${formatted}`
4848

4949
if (this.choice.insertAfter.enabled) {
50-
const target: string = await this.format(this.choice.insertAfter.after);
51-
const targetRegex = new RegExp(`\s*${escapeRegExp(target)}\s*`)
52-
let fileContentLines: string[] = getLinesInString(this.fileContent);
53-
54-
const targetPosition = fileContentLines.findIndex(line => targetRegex.test(line));
55-
if (targetPosition === -1) {
56-
if (this.choice.insertAfter?.createIfNotFound) {
57-
const insertAfterLine: string = this.replaceLinebreakInString(await this.format(this.choice.insertAfter.after));
58-
const insertAfterLineAndFormatted: string = `${insertAfterLine}\n${formatted}`;
59-
60-
if (this.choice.insertAfter?.createIfNotFoundLocation === CREATE_IF_NOT_FOUND_TOP) {
61-
const frontmatterEndPosition = this.file ? await this.getFrontmatterEndPosition(this.file) : 0;
62-
return this.insertTextAfterPositionInBody(insertAfterLineAndFormatted, this.fileContent, frontmatterEndPosition);
63-
}
64-
else {
65-
return this.insertTextAfterPositionInBody(insertAfterLineAndFormatted, this.fileContent, fileContentLines.length - 1);
66-
}
67-
}
50+
return await this.insertAfterHandler(formatted);
51+
}
6852

69-
log.logError("unable to find insert after line in file.")
53+
const frontmatterEndPosition = this.file ? await this.getFrontmatterEndPosition(this.file) : null;
54+
if (!frontmatterEndPosition)
55+
return `${formatted}${this.fileContent}`;
56+
57+
return this.insertTextAfterPositionInBody(formatted, this.fileContent, frontmatterEndPosition);
58+
}
59+
60+
private async insertAfterHandler(formatted: string) {
61+
const targetString: string = await this.format(this.choice.insertAfter.after);
62+
const targetRegex = new RegExp(`\s*${escapeRegExp(targetString.replace('\\n', ''))}\s*`);
63+
let fileContentLines: string[] = getLinesInString(this.fileContent);
64+
65+
const targetPosition = fileContentLines.findIndex(line => targetRegex.test(line));
66+
const targetNotFound = targetPosition === -1;
67+
if (targetNotFound) {
68+
if (this.choice.insertAfter?.createIfNotFound) {
69+
return await this.createInsertAfterIfNotFound(formatted);
7070
}
7171

72-
if (this.choice.insertAfter?.insertAtEnd) {
73-
const nextHeaderPositionAfterTargetPosition = fileContentLines.slice(targetPosition + 1).findIndex(line => (/^#+ |---/).test(line))
74-
const foundNextHeader = nextHeaderPositionAfterTargetPosition !== -1;
72+
log.logError("unable to find insert after line in file.")
73+
}
74+
75+
if (this.choice.insertAfter?.insertAtEnd) {
76+
const nextHeaderPositionAfterTargetPosition = fileContentLines
77+
.slice(targetPosition + 1)
78+
.findIndex(line => (/^#+ |---/).test(line))
79+
const foundNextHeader = nextHeaderPositionAfterTargetPosition !== -1;
7580

76-
if (foundNextHeader) {
77-
let endOfSectionIndex: number;
81+
if (foundNextHeader) {
82+
let endOfSectionIndex: number;
7883

79-
for (let i = nextHeaderPositionAfterTargetPosition + targetPosition; i > targetPosition; i--) {
80-
const lineIsNewline: boolean = (/^[\s\n ]*$/).test(fileContentLines[i]);
84+
for (let i = nextHeaderPositionAfterTargetPosition + targetPosition; i > targetPosition; i--) {
85+
const lineIsNewline: boolean = (/^[\s\n ]*$/).test(fileContentLines[i]);
8186

82-
if (!lineIsNewline) {
83-
endOfSectionIndex = i;
84-
break;
85-
}
87+
if (!lineIsNewline) {
88+
endOfSectionIndex = i;
89+
break;
8690
}
91+
}
8792

88-
if (!endOfSectionIndex) endOfSectionIndex = targetPosition;
93+
if (!endOfSectionIndex) endOfSectionIndex = targetPosition;
8994

90-
return this.insertTextAfterPositionInBody(formatted, this.fileContent, endOfSectionIndex);
91-
} else {
92-
return this.insertTextAfterPositionInBody(formatted, this.fileContent, fileContentLines.length - 1);
93-
}
95+
return this.insertTextAfterPositionInBody(formatted, this.fileContent, endOfSectionIndex);
96+
} else {
97+
return this.insertTextAfterPositionInBody(formatted, this.fileContent, fileContentLines.length - 1);
9498
}
95-
96-
return this.insertTextAfterPositionInBody(formatted, this.fileContent, targetPosition);
9799
}
98100

99-
const frontmatterEndPosition = this.file ? await this.getFrontmatterEndPosition(this.file) : null;
100-
if (!frontmatterEndPosition)
101-
return `${formatted}${this.fileContent}`;
101+
return this.insertTextAfterPositionInBody(formatted, this.fileContent, targetPosition);
102+
}
102103

103-
return this.insertTextAfterPositionInBody(formatted, this.fileContent, frontmatterEndPosition);
104+
private async createInsertAfterIfNotFound(formatted: string) {
105+
const insertAfterLine: string = this.replaceLinebreakInString(await this.format(this.choice.insertAfter.after));
106+
const insertAfterLineAndFormatted: string = `${insertAfterLine}\n${formatted}`;
107+
108+
if (this.choice.insertAfter?.createIfNotFoundLocation === CREATE_IF_NOT_FOUND_TOP) {
109+
const frontmatterEndPosition = this.file ? await this.getFrontmatterEndPosition(this.file) : -1;
110+
return this.insertTextAfterPositionInBody(insertAfterLineAndFormatted, this.fileContent, frontmatterEndPosition);
111+
}
112+
113+
if (this.choice.insertAfter?.createIfNotFoundLocation === CREATE_IF_NOT_FOUND_BOTTOM) {
114+
return `${this.fileContent}\n${insertAfterLineAndFormatted}`;
115+
}
104116
}
105117

106118
private async getFrontmatterEndPosition(file: TFile) {
107119
const fileCache = await this.app.metadataCache.getFileCache(file);
108120

109121
if (!fileCache || !fileCache.frontmatter) {
110122
log.logMessage("could not get frontmatter. Maybe there isn't any.")
111-
return 0;
123+
return -1;
112124
}
113125

114126
if (fileCache.frontmatter.position)
115127
return fileCache.frontmatter.position.end.line;
116128

117-
return 0;
129+
return -1;
118130
}
119131

120132
private insertTextAfterPositionInBody(text: string, body: string, pos: number): string {

src/formatters/completeFormatter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export class CompleteFormatter extends Formatter {
1616

1717
constructor(protected app: App, private plugin: QuickAdd, protected choiceExecutor: IChoiceExecutor) {
1818
super();
19-
this.variables = choiceExecutor.variables;
19+
this.variables = choiceExecutor?.variables;
2020
}
2121

2222
protected async format(input: string): Promise<string> {

src/gui/ChoiceBuilder/captureChoiceBuilder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,10 @@ export class CaptureChoiceBuilder extends ChoiceBuilder {
179179
this.choice.insertAfter.createIfNotFoundLocation = CREATE_IF_NOT_FOUND_TOP; // Set to default
180180

181181
dropdown
182-
.setValue(this.choice.insertAfter?.createIfNotFoundLocation)
183-
.onChange(value => this.choice.insertAfter.createIfNotFoundLocation = value)
184182
.addOption(CREATE_IF_NOT_FOUND_TOP, "Top")
185183
.addOption(CREATE_IF_NOT_FOUND_BOTTOM, "Bottom")
184+
.setValue(this.choice.insertAfter?.createIfNotFoundLocation)
185+
.onChange(value => this.choice.insertAfter.createIfNotFoundLocation = value)
186186
}
187187
)
188188
}

0 commit comments

Comments
 (0)