-
-
Notifications
You must be signed in to change notification settings - Fork 83
Expand file tree
/
Copy pathFileAPI.ts
More file actions
153 lines (132 loc) · 4.6 KB
/
FileAPI.ts
File metadata and controls
153 lines (132 loc) · 4.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import type { LinePosition } from 'packages/core/src/config/APIConfigs';
import { MDLinkParser } from 'packages/core/src/parsers/MarkdownLinkParser';
import { ErrorLevel, MetaBindParsingError } from 'packages/core/src/utils/errors/MetaBindErrors';
import type { LineNumberContext } from 'packages/core/src/utils/LineNumberExpression';
import type { MB_Comps, MetaBind } from '..';
import type { ButtonPaneType } from '../config/ButtonConfig';
export abstract class FileAPI<Components extends MB_Comps> {
readonly mb: MetaBind<Components>;
constructor(mb: MetaBind<Components>) {
this.mb = mb;
}
public abstract read(filePath: string): Promise<string>;
public abstract write(filePath: string, content: string): Promise<void>;
// currently not used
// public abstract deleteFile(filePath: string): Promise<void>;
public abstract exists(filePath: string): Promise<boolean>;
public abstract atomicModify(filePath: string, modify: (content: string) => string): Promise<void>;
/**
* Create a file in the given folder with the given name and extension.
* If the name is already taken, a number will be appended to the name.
*
* @param folderPath the path to the folder
* @param fileName the name of the file
* @param extension the extension of the file
* @param open whether to open the file
* @param newTab whether to open the file in a new tab or the current one
*
* @returns the path to the created file
*/
public abstract create(
folderPath: string,
fileName: string,
extension: string,
open?: boolean,
newTab?: boolean,
): Promise<string>;
/**
* List all files by their path.
*/
public abstract getAllFiles(): string[];
/**
* List all folders by their path.
*/
public abstract getAllFolders(): string[];
/**
* Open a specific file.
*
* @param filePath
* @param callingFilePath
* @param PaneType
*/
public abstract open(filePath: string, callingFilePath: string, PaneType: ButtonPaneType | boolean): Promise<void>;
/**
* Resolves a file name to a file path.
*
* @param name
* @param relativeTo
*/
public abstract getPathByName(name: string, relativeTo?: string): string | undefined;
public getFrontmatterLocation(fileContent: string): LinePosition | undefined {
const splitContent = fileContent.split('\n');
if (splitContent.at(0) !== '---') {
return undefined;
}
for (let i = 1; i < splitContent.length; i++) {
if (splitContent.at(i) === '---') {
return {
lineStart: 1,
lineEnd: i + 1,
};
}
}
return undefined;
}
/**
* Checks if a file path has been excluded in the settings.
*
* @param filePath
*/
public isExcludedFromRendering(filePath: string): boolean {
for (const excludedFolder of this.mb.getSettings().excludedFolders) {
if (filePath.startsWith(excludedFolder)) {
return true;
}
}
return false;
}
/**
* Resolves a file name, path or link to a file path.
*
* @param filePathLike Something that is a file path or a link.
* @param relativeTo The file path to resolve the link relative to. This should be an actual full file path.
*
* @returns the `filePathLike` resolved to a full file path.
*/
public resolveFilePathLike(filePathLike: string, relativeTo?: string): string {
const targetFilePath = MDLinkParser.isLink(filePathLike)
? MDLinkParser.parseLink(filePathLike).target
: filePathLike;
const resolvedFilePath = this.mb.file.getPathByName(targetFilePath, relativeTo);
if (resolvedFilePath === undefined) {
throw new MetaBindParsingError({
errorLevel: ErrorLevel.ERROR,
cause: `Could not find a file that matches "${filePathLike}".`,
effect: `Could not resolve path or link "${filePathLike}" relative to "${relativeTo}".`,
});
}
return resolvedFilePath;
}
/**
* Get the line number context based on a file content and a self note position.
*
* @param fileContent
* @param selfNotePosition
* @returns
*/
public createLineNumberContext(fileContent: string, selfNotePosition: LinePosition | undefined): LineNumberContext {
const fileStart = 1;
const fileEnd = fileContent.split('\n').length;
const frontmatterPosition = this.mb.file.getFrontmatterLocation(fileContent);
return {
fileStart: fileStart,
fileEnd: fileEnd,
frontmatterStart: frontmatterPosition ? frontmatterPosition.lineStart : fileStart,
frontmatterEnd: frontmatterPosition ? frontmatterPosition.lineEnd : fileStart,
contentStart: frontmatterPosition ? frontmatterPosition.lineEnd + 1 : fileStart,
contentEnd: fileEnd,
selfStart: selfNotePosition ? selfNotePosition.lineStart + 1 : undefined,
selfEnd: selfNotePosition ? selfNotePosition.lineEnd + 1 : undefined,
};
}
}