Skip to content

Commit 6ced887

Browse files
committed
fix #520
1 parent 60afd89 commit 6ced887

12 files changed

+101
-73
lines changed

packages/core/src/api/FileAPI.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import type { LinePosition } from 'packages/core/src/config/APIConfigs';
2+
import { MDLinkParser } from 'packages/core/src/parsers/MarkdownLinkParser';
3+
import { ErrorLevel, MetaBindParsingError } from 'packages/core/src/utils/errors/MetaBindErrors';
4+
import type { LineNumberContext } from 'packages/core/src/utils/LineNumberExpression';
25
import type { MB_Comps, MetaBind } from '..';
36

47
export abstract class FileAPI<Components extends MB_Comps> {
@@ -98,4 +101,52 @@ export abstract class FileAPI<Components extends MB_Comps> {
98101

99102
return false;
100103
}
104+
105+
/**
106+
* Resolves a file name, path or link to a file path.
107+
*
108+
* @param filePathLike Something that is a file path or a link.
109+
* @param relativeTo The file path to resolve the link relative to. This should be an actual full file path.
110+
*
111+
* @returns the `filePathLike` resolved to a full file path.
112+
*/
113+
public resolveFilePathLike(filePathLike: string, relativeTo?: string): string {
114+
const targetFilePath = MDLinkParser.isLink(filePathLike)
115+
? MDLinkParser.parseLink(filePathLike).target
116+
: filePathLike;
117+
const resolvedFilePath = this.mb.file.getPathByName(targetFilePath, relativeTo);
118+
if (resolvedFilePath === undefined) {
119+
throw new MetaBindParsingError({
120+
errorLevel: ErrorLevel.ERROR,
121+
cause: `Could not find a file that matches "${filePathLike}".`,
122+
effect: `Could not resolve path or link "${filePathLike}" relative to "${relativeTo}".`,
123+
});
124+
}
125+
126+
return resolvedFilePath;
127+
}
128+
129+
/**
130+
* Get the line number context based on a file content and a self note position.
131+
*
132+
* @param fileContent
133+
* @param selfNotePosition
134+
* @returns
135+
*/
136+
public createLineNumberContext(fileContent: string, selfNotePosition: LinePosition | undefined): LineNumberContext {
137+
const fileStart = 1;
138+
const fileEnd = fileContent.split('\n').length;
139+
const frontmatterPosition = this.mb.file.getFrontmatterLocation(fileContent);
140+
141+
return {
142+
fileStart: fileStart,
143+
fileEnd: fileEnd,
144+
frontmatterStart: frontmatterPosition ? frontmatterPosition.lineStart : fileStart,
145+
frontmatterEnd: frontmatterPosition ? frontmatterPosition.lineEnd : fileStart,
146+
contentStart: frontmatterPosition ? frontmatterPosition.lineEnd + 1 : fileStart,
147+
contentEnd: fileEnd,
148+
selfStart: selfNotePosition ? selfNotePosition.lineStart + 1 : undefined,
149+
selfEnd: selfNotePosition ? selfNotePosition.lineEnd + 1 : undefined,
150+
};
151+
}
101152
}

packages/core/src/config/ButtonConfig.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,32 @@ export interface ButtonContext {
207207
/**
208208
* Provides information about the button click event.
209209
*/
210-
export interface ButtonClickContext {
210+
export class ButtonClickContext {
211211
type: ButtonClickType;
212212
shiftKey: boolean;
213213
ctrlKey: boolean;
214214
altKey: boolean;
215+
216+
constructor(type: ButtonClickType, shiftKey: boolean, ctrlKey: boolean, altKey: boolean) {
217+
this.type = type;
218+
this.shiftKey = shiftKey;
219+
this.ctrlKey = ctrlKey;
220+
this.altKey = altKey;
221+
}
222+
223+
static fromMouseEvent(event: MouseEvent, type: ButtonClickType): ButtonClickContext {
224+
return new ButtonClickContext(type, event.shiftKey, event.ctrlKey, event.altKey);
225+
}
226+
227+
/**
228+
* Whether the click should cause a link to open in a new tab.
229+
* Only applicable when the click is on a link.
230+
*
231+
* @returns
232+
*/
233+
openInNewTab(): boolean {
234+
return this.type === ButtonClickType.MIDDLE || this.ctrlKey;
235+
}
215236
}
216237

217238
export enum ButtonClickType {

packages/core/src/fields/button/ButtonActionRunner.ts

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import type { MetaBind } from 'packages/core/src';
2-
import type { LinePosition } from 'packages/core/src/config/APIConfigs';
32
import type {
43
ButtonActionMap,
54
ButtonClickContext,
6-
ButtonClickType,
75
ButtonConfig,
86
ButtonContext,
97
} from 'packages/core/src/config/ButtonConfig';
@@ -23,9 +21,6 @@ import { RunTemplaterFileButtonActionConfig } from 'packages/core/src/fields/but
2321
import { SleepButtonActionConfig } from 'packages/core/src/fields/button/actions/SleepButtonActionConfig';
2422
import { TemplaterCreateNoteButtonActionConfig } from 'packages/core/src/fields/button/actions/TemplaterCreateNoteButtonActionConfig';
2523
import { UpdateMetadataButtonActionConfig } from 'packages/core/src/fields/button/actions/UpdateMetadataButtonActionConfig';
26-
import { MDLinkParser } from 'packages/core/src/parsers/MarkdownLinkParser';
27-
import { ErrorLevel, MetaBindParsingError } from 'packages/core/src/utils/errors/MetaBindErrors';
28-
import type { LineNumberContext } from 'packages/core/src/utils/LineNumberExpression';
2924

3025
type ActionContexts = {
3126
[key in ButtonActionType]: AbstractButtonActionConfig<ButtonActionMap[key]>;
@@ -56,23 +51,6 @@ export class ButtonActionRunner {
5651
};
5752
}
5853

59-
/**
60-
* Resolves a file name, path or link to a file path.
61-
*/
62-
resolveFilePath(filePath: string, relativeTo?: string): string {
63-
const targetFilePath = MDLinkParser.isLink(filePath) ? MDLinkParser.parseLink(filePath).target : filePath;
64-
const resolvedFilePath = this.mb.file.getPathByName(targetFilePath, relativeTo);
65-
if (resolvedFilePath === undefined) {
66-
throw new MetaBindParsingError({
67-
errorLevel: ErrorLevel.ERROR,
68-
cause: `Could not find a file that matches "${filePath}".`,
69-
effect: `Could not resolve path or link "${filePath}" relative to "${relativeTo}".`,
70-
});
71-
}
72-
73-
return resolvedFilePath;
74-
}
75-
7654
createDefaultButtonConfig(): ButtonConfig {
7755
return {
7856
label: 'This is a button',
@@ -154,30 +132,4 @@ export class ButtonActionRunner {
154132
getActionLabel<T extends ButtonActionType>(type: T): string {
155133
return this.actionContexts[type].getActionLabel();
156134
}
157-
158-
mouseEventToClickContext(event: MouseEvent, type: ButtonClickType): ButtonClickContext {
159-
return {
160-
type: type,
161-
shiftKey: event.shiftKey,
162-
ctrlKey: event.ctrlKey,
163-
altKey: event.altKey,
164-
};
165-
}
166-
167-
getLineNumberContext(fileContent: string, selfNotePosition: LinePosition | undefined): LineNumberContext {
168-
const fileStart = 1;
169-
const fileEnd = fileContent.split('\n').length;
170-
const frontmatterPosition = this.mb.file.getFrontmatterLocation(fileContent);
171-
172-
return {
173-
fileStart: fileStart,
174-
fileEnd: fileEnd,
175-
frontmatterStart: frontmatterPosition ? frontmatterPosition.lineStart : fileStart,
176-
frontmatterEnd: frontmatterPosition ? frontmatterPosition.lineEnd : fileStart,
177-
contentStart: frontmatterPosition ? frontmatterPosition.lineEnd + 1 : fileStart,
178-
contentEnd: fileEnd,
179-
selfStart: selfNotePosition ? selfNotePosition.lineStart + 1 : undefined,
180-
selfEnd: selfNotePosition ? selfNotePosition.lineEnd + 1 : undefined,
181-
};
182-
}
183135
}

packages/core/src/fields/button/ButtonField.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { MetaBind } from 'packages/core/src';
22
import type { NotePosition } from 'packages/core/src/config/APIConfigs';
33
import { RenderChildType } from 'packages/core/src/config/APIConfigs';
44
import type { ButtonConfig, ButtonContext } from 'packages/core/src/config/ButtonConfig';
5-
import { ButtonClickType } from 'packages/core/src/config/ButtonConfig';
5+
import { ButtonClickContext, ButtonClickType } from 'packages/core/src/config/ButtonConfig';
66
import ButtonComponent from 'packages/core/src/utils/components/ButtonComponent.svelte';
77
import { Mountable } from 'packages/core/src/utils/Mountable';
88
import { DomHelpers, isTruthy } from 'packages/core/src/utils/Utils';
@@ -77,15 +77,15 @@ export class ButtonField extends Mountable {
7777
this.config,
7878
this.filePath,
7979
this.getContext(),
80-
this.mb.buttonActionRunner.mouseEventToClickContext(event, ButtonClickType.LEFT),
80+
ButtonClickContext.fromMouseEvent(event, ButtonClickType.LEFT),
8181
);
8282
},
8383
onauxclick: async (event: MouseEvent): Promise<void> => {
8484
await this.mb.buttonActionRunner.runButtonActions(
8585
this.config,
8686
this.filePath,
8787
this.getContext(),
88-
this.mb.buttonActionRunner.mouseEventToClickContext(event, ButtonClickType.MIDDLE),
88+
ButtonClickContext.fromMouseEvent(event, ButtonClickType.LEFT),
8989
);
9090
},
9191
},

packages/core/src/fields/button/actions/CreateNoteButtonActionConfig.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export class CreateNoteButtonActionConfig extends AbstractButtonActionConfig<Cre
1919
action: CreateNoteButtonAction,
2020
_filePath: string,
2121
_context: ButtonContext,
22-
_click: ButtonClickContext,
22+
click: ButtonClickContext,
2323
): Promise<void> {
2424
if (action.openIfAlreadyExists) {
2525
const filePath = ensureFileExtension(joinPath(action.folderPath ?? '', action.fileName), 'md');
@@ -30,7 +30,13 @@ export class CreateNoteButtonActionConfig extends AbstractButtonActionConfig<Cre
3030
}
3131
}
3232

33-
await this.mb.file.create(action.folderPath ?? '', action.fileName, 'md', action.openNote ?? false);
33+
await this.mb.file.create(
34+
action.folderPath ?? '',
35+
action.fileName,
36+
'md',
37+
action.openNote ?? false,
38+
click.openInNewTab(),
39+
);
3440
}
3541

3642
create(): Required<CreateNoteButtonAction> {

packages/core/src/fields/button/actions/InsertIntoNoteButtonActionConfig.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,15 @@ export class InsertIntoNoteButtonActionConfig extends AbstractButtonActionConfig
2323
_click: ButtonClickContext,
2424
): Promise<void> {
2525
const insertString = action.templater
26-
? await this.mb.internal.evaluateTemplaterTemplate(
27-
this.mb.buttonActionRunner.resolveFilePath(action.value),
28-
filePath,
29-
)
26+
? await this.mb.internal.evaluateTemplaterTemplate(this.mb.file.resolveFilePathLike(action.value), filePath)
3027
: action.value;
3128

3229
const line = runParser(P_lineNumberExpression, action.line.toString());
3330

3431
await this.mb.file.atomicModify(filePath, content => {
3532
let splitContent = content.split('\n');
3633

37-
const lineContext = this.mb.buttonActionRunner.getLineNumberContext(content, context.position);
34+
const lineContext = this.mb.file.createLineNumberContext(content, context.position);
3835
const lineNumber = line.evaluate(lineContext);
3936

4037
if (lineNumber < 1 || lineNumber > splitContent.length) {

packages/core/src/fields/button/actions/OpenButtonActionConfig.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type {
55
ButtonContext,
66
OpenButtonAction,
77
} from 'packages/core/src/config/ButtonConfig';
8-
import { ButtonActionType, ButtonClickType } from 'packages/core/src/config/ButtonConfig';
8+
import { ButtonActionType } from 'packages/core/src/config/ButtonConfig';
99
import { AbstractButtonActionConfig } from 'packages/core/src/fields/button/AbstractButtonActionConfig';
1010
import { MDLinkParser } from 'packages/core/src/parsers/MarkdownLinkParser';
1111

@@ -21,7 +21,7 @@ export class OpenButtonActionConfig extends AbstractButtonActionConfig<OpenButto
2121
_context: ButtonContext,
2222
click: ButtonClickContext,
2323
): Promise<void> {
24-
const newTab = click.type === ButtonClickType.MIDDLE || click.ctrlKey || (action.newTab ?? false);
24+
const newTab = click.openInNewTab() || (action.newTab ?? false);
2525
const link = MDLinkParser.interpretAsLink(action.link);
2626
if (!link) {
2727
throw new Error('Invalid link');

packages/core/src/fields/button/actions/ReplaceInNoteButtonActionConfig.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class ReplaceInNoteButtonActionConfig extends AbstractButtonActionConfig<
2424
): Promise<void> {
2525
const replacement = action.templater
2626
? await this.mb.internal.evaluateTemplaterTemplate(
27-
this.mb.buttonActionRunner.resolveFilePath(action.replacement),
27+
this.mb.file.resolveFilePathLike(action.replacement),
2828
filePath,
2929
)
3030
: action.replacement;
@@ -35,7 +35,7 @@ export class ReplaceInNoteButtonActionConfig extends AbstractButtonActionConfig<
3535
await this.mb.file.atomicModify(filePath, content => {
3636
let splitContent = content.split('\n');
3737

38-
const lineContext = this.mb.buttonActionRunner.getLineNumberContext(content, context.position);
38+
const lineContext = this.mb.file.createLineNumberContext(content, context.position);
3939
const fromLineNumber = fromLine.evaluate(lineContext);
4040
const toLineNumber = toLine.evaluate(lineContext);
4141

packages/core/src/fields/button/actions/ReplaceSelfButtonActionConfig.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export class ReplaceSelfButtonActionConfig extends AbstractButtonActionConfig<Re
3636

3737
const replacement = action.templater
3838
? await this.mb.internal.evaluateTemplaterTemplate(
39-
this.mb.buttonActionRunner.resolveFilePath(action.replacement),
39+
this.mb.file.resolveFilePathLike(action.replacement),
4040
filePath,
4141
)
4242
: action.replacement;

packages/core/src/fields/button/actions/RunTemplaterFileButtonActionConfig.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export class RunTemplaterFileButtonActionConfig extends AbstractButtonActionConf
2020
_context: ButtonContext,
2121
_click: ButtonClickContext,
2222
): Promise<void> {
23-
const templateFilePath = this.mb.buttonActionRunner.resolveFilePath(action.templateFile);
23+
const templateFilePath = this.mb.file.resolveFilePathLike(action.templateFile);
2424
void (await this.mb.internal.evaluateTemplaterTemplate(templateFilePath, filePath));
2525
}
2626

0 commit comments

Comments
 (0)