Skip to content

Commit

Permalink
Assorted fixes (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
chhoumann authored Jul 17, 2021
1 parent 69b3ae0 commit 77dda11
Show file tree
Hide file tree
Showing 15 changed files with 180 additions and 121 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ Quickly add new pages or content to your vault.
You can also do a [manual installation](docs/ManualInstallation.md).

## What's new?
### 3.6.10
- Added a warning when deleting a Multi choice that you will delete all choices within.
- Fix #51 - Templater syntax is now processed when appending to the current file.
- Fix "Template (not found)" for templates that exist.
- Fix #46 - Error if adding a template that doesn't exist.
- Template: Create file in same folder as current file.
- Fix bug with insertion and creation of 'Insert After' line (if it does not exist).

### 0.3.6 - 0.3.9
- Added setting to create the 'Insert After' line if it isn't found.
- (HOTFIX) Escape regular expression special characters in Insert After when searching for it.
Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "quickadd",
"name": "QuickAdd",
"version": "0.3.9",
"version": "0.3.10",
"minAppVersion": "0.12.5",
"description": "Quickly add new pages or content to your vault.",
"author": "Christian B. B. Houmann",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "quickadd",
"version": "0.3.9",
"version": "0.3.10",
"description": "Quickly add new pages or content to your vault.",
"main": "main.js",
"scripts": {
Expand Down
13 changes: 7 additions & 6 deletions src/engine/CaptureChoiceEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type ICaptureChoice from "../types/choices/ICaptureChoice";
import type {App, TFile} from "obsidian";
import {log} from "../logger/logManager";
import {CaptureChoiceFormatter} from "../formatters/captureChoiceFormatter";
import {appendToCurrentLine, replaceTemplaterTemplatesInCreatedFile} from "../utility";
import {appendToCurrentLine, replaceTemplaterTemplatesInCreatedFile, templaterParseTemplate} from "../utility";
import {VALUE_SYNTAX} from "../constants";
import type QuickAdd from "../main";
import {QuickAddChoiceEngine} from "./QuickAddChoiceEngine";
Expand Down Expand Up @@ -96,20 +96,21 @@ export class CaptureChoiceEngine extends QuickAddChoiceEngine {
}

private async captureToActiveFile() {
const activeFile: TFile = this.app.workspace.getActiveFile();
if (!activeFile) {
log.logError("Cannot capture to active file - no active file.")
}

let content: string = await this.getCaptureContent();

if (this.choice.format.enabled) {
content = await this.formatter.formatContent(content, this.choice);
content = await templaterParseTemplate(this.app, content, activeFile);
}

if (!content) return;

if (this.choice.prepend) {
const activeFile: TFile = this.app.workspace.getActiveFile();
if (!activeFile) {
log.logError("Cannot capture to active file - no active file.")
}

const fileContent: string = await this.app.vault.cachedRead(activeFile);
const newFileContent: string = `${fileContent}${content}`

Expand Down
3 changes: 2 additions & 1 deletion src/engine/SingleTemplateEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {TemplateEngine} from "./TemplateEngine";
import type {App} from "obsidian";
import type QuickAdd from "../main";
import type {IChoiceExecutor} from "../IChoiceExecutor";
import {log} from "../logger/logManager";

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

templateContent = await this.formatter.formatFileContent(templateContent);
Expand Down
30 changes: 22 additions & 8 deletions src/engine/TemplateChoiceEngine.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type ITemplateChoice from "../types/choices/ITemplateChoice";
import type {App} from "obsidian";
import {TFile} from "obsidian";
import {appendToCurrentLine, getAllFolders} from "../utility";
import {appendToCurrentLine, getAllFolderPathsInVault} from "../utility";
import {
fileExistsAppendToBottom,
fileExistsAppendToTop,
Expand All @@ -28,13 +28,7 @@ export class TemplateChoiceEngine extends TemplateEngine {
let folderPath: string = "";

if (this.choice.folder.enabled) {
let folders: string[] = this.choice.folder.folders;

if (this.choice.folder?.chooseWhenCreatingNote) {
folders = await getAllFolders(this.app);
}

folderPath = await this.getOrCreateFolder(folders);
folderPath = await this.getFolderPath();
}

let filePath;
Expand Down Expand Up @@ -96,4 +90,24 @@ export class TemplateChoiceEngine extends TemplateEngine {
}
}
}

private async getFolderPath() {
let folders: string[] = [...this.choice.folder.folders];

if (this.choice.folder?.chooseWhenCreatingNote) {
const allFoldersInVault: string[] = getAllFolderPathsInVault(this.app);
return await this.getOrCreateFolder(allFoldersInVault);
}

if (this.choice.folder?.createInSameFolderAsActiveFile) {
const activeFile: TFile = this.app.workspace.getActiveFile();

if (!activeFile)
log.logError("No active file. Cannot create new file.");

return this.getOrCreateFolder([activeFile.parent.path]);
}

return await this.getOrCreateFolder(folders);
}
}
100 changes: 56 additions & 44 deletions src/formatters/captureChoiceFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {log} from "../logger/logManager";
import type QuickAdd from "../main";
import type {IChoiceExecutor} from "../IChoiceExecutor";
import {escapeRegExp, getLinesInString, templaterParseTemplate} from "../utility";
import {CREATE_IF_NOT_FOUND_TOP} from "../constants";
import {CREATE_IF_NOT_FOUND_BOTTOM, CREATE_IF_NOT_FOUND_TOP} from "../constants";

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

if (this.choice.insertAfter.enabled) {
const target: string = await this.format(this.choice.insertAfter.after);
const targetRegex = new RegExp(`\s*${escapeRegExp(target)}\s*`)
let fileContentLines: string[] = getLinesInString(this.fileContent);

const targetPosition = fileContentLines.findIndex(line => targetRegex.test(line));
if (targetPosition === -1) {
if (this.choice.insertAfter?.createIfNotFound) {
const insertAfterLine: string = this.replaceLinebreakInString(await this.format(this.choice.insertAfter.after));
const insertAfterLineAndFormatted: string = `${insertAfterLine}\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);
}
else {
return this.insertTextAfterPositionInBody(insertAfterLineAndFormatted, this.fileContent, fileContentLines.length - 1);
}
}
return await this.insertAfterHandler(formatted);
}

log.logError("unable to find insert after line in file.")
const frontmatterEndPosition = this.file ? await this.getFrontmatterEndPosition(this.file) : null;
if (!frontmatterEndPosition)
return `${formatted}${this.fileContent}`;

return this.insertTextAfterPositionInBody(formatted, this.fileContent, frontmatterEndPosition);
}

private async insertAfterHandler(formatted: string) {
const targetString: string = await this.format(this.choice.insertAfter.after);
const targetRegex = new RegExp(`\s*${escapeRegExp(targetString.replace('\\n', ''))}\s*`);
let fileContentLines: string[] = getLinesInString(this.fileContent);

const targetPosition = fileContentLines.findIndex(line => targetRegex.test(line));
const targetNotFound = targetPosition === -1;
if (targetNotFound) {
if (this.choice.insertAfter?.createIfNotFound) {
return await this.createInsertAfterIfNotFound(formatted);
}

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

if (this.choice.insertAfter?.insertAtEnd) {
const nextHeaderPositionAfterTargetPosition = fileContentLines
.slice(targetPosition + 1)
.findIndex(line => (/^#+ |---/).test(line))
const foundNextHeader = nextHeaderPositionAfterTargetPosition !== -1;

if (foundNextHeader) {
let endOfSectionIndex: number;
if (foundNextHeader) {
let endOfSectionIndex: number;

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

if (!lineIsNewline) {
endOfSectionIndex = i;
break;
}
if (!lineIsNewline) {
endOfSectionIndex = i;
break;
}
}

if (!endOfSectionIndex) endOfSectionIndex = targetPosition;
if (!endOfSectionIndex) endOfSectionIndex = targetPosition;

return this.insertTextAfterPositionInBody(formatted, this.fileContent, endOfSectionIndex);
} else {
return this.insertTextAfterPositionInBody(formatted, this.fileContent, fileContentLines.length - 1);
}
return this.insertTextAfterPositionInBody(formatted, this.fileContent, endOfSectionIndex);
} else {
return this.insertTextAfterPositionInBody(formatted, this.fileContent, fileContentLines.length - 1);
}

return this.insertTextAfterPositionInBody(formatted, this.fileContent, targetPosition);
}

const frontmatterEndPosition = this.file ? await this.getFrontmatterEndPosition(this.file) : null;
if (!frontmatterEndPosition)
return `${formatted}${this.fileContent}`;
return this.insertTextAfterPositionInBody(formatted, this.fileContent, targetPosition);
}

return this.insertTextAfterPositionInBody(formatted, this.fileContent, frontmatterEndPosition);
private async createInsertAfterIfNotFound(formatted: string) {
const insertAfterLine: string = this.replaceLinebreakInString(await this.format(this.choice.insertAfter.after));
const insertAfterLineAndFormatted: string = `${insertAfterLine}\n${formatted}`;

if (this.choice.insertAfter?.createIfNotFoundLocation === CREATE_IF_NOT_FOUND_TOP) {
const frontmatterEndPosition = this.file ? await this.getFrontmatterEndPosition(this.file) : -1;
return this.insertTextAfterPositionInBody(insertAfterLineAndFormatted, this.fileContent, frontmatterEndPosition);
}

if (this.choice.insertAfter?.createIfNotFoundLocation === CREATE_IF_NOT_FOUND_BOTTOM) {
return `${this.fileContent}\n${insertAfterLineAndFormatted}`;
}
}

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

if (!fileCache || !fileCache.frontmatter) {
log.logMessage("could not get frontmatter. Maybe there isn't any.")
return 0;
return -1;
}

if (fileCache.frontmatter.position)
return fileCache.frontmatter.position.end.line;

return 0;
return -1;
}

private insertTextAfterPositionInBody(text: string, body: string, pos: number): string {
Expand Down
2 changes: 1 addition & 1 deletion src/formatters/completeFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class CompleteFormatter extends Formatter {

constructor(protected app: App, private plugin: QuickAdd, protected choiceExecutor: IChoiceExecutor) {
super();
this.variables = choiceExecutor.variables;
this.variables = choiceExecutor?.variables;
}

protected async format(input: string): Promise<string> {
Expand Down
4 changes: 2 additions & 2 deletions src/gui/ChoiceBuilder/captureChoiceBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,10 @@ export class CaptureChoiceBuilder extends ChoiceBuilder {
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")
.setValue(this.choice.insertAfter?.createIfNotFoundLocation)
.onChange(value => this.choice.insertAfter.createIfNotFoundLocation = value)
}
)
}
Expand Down
Loading

0 comments on commit 77dda11

Please sign in to comment.