88 lines
2.2 KiB
TypeScript
88 lines
2.2 KiB
TypeScript
import { globSync } from "glob";
|
|
import MarkdownDocument from "./document.js";
|
|
|
|
/**
|
|
* Load documents from an Obsidian vault
|
|
* @param vaultPath The path to the vault to load
|
|
* @param ignorePatterns A glob pattern to ignore files for
|
|
* @returns A promise which resolves as an array of laoded Documents
|
|
*/
|
|
function loadVaultDocuments(
|
|
vaultPath: string,
|
|
ignorePatterns: string[] = [],
|
|
): MarkdownDocument[] {
|
|
const discoveredMarkdownDocuments = globSync(`${vaultPath}/**/*.md`, {
|
|
ignore: ignorePatterns,
|
|
});
|
|
|
|
const markdownDocuments: MarkdownDocument[] = [];
|
|
|
|
for (const filePath of discoveredMarkdownDocuments) {
|
|
const file = new MarkdownDocument(filePath, vaultPath);
|
|
|
|
if (markdownDocuments.some((check) => check.slug === file.slug)) {
|
|
throw new Error("Duplicate slug: " + file.slug);
|
|
}
|
|
|
|
markdownDocuments.push(file);
|
|
}
|
|
|
|
return markdownDocuments;
|
|
}
|
|
|
|
/**
|
|
* Build a VaultIndex from a list of loaded Documents
|
|
* @param vaultDocs An array of all the documents to index
|
|
* @returns A VaultIndex, which is an object that maps document slugs to information
|
|
*/
|
|
function buildVaultIndex(
|
|
vaultDocs: MarkdownDocument[],
|
|
): Record<string, MarkdownDocument> {
|
|
const index: Record<string, MarkdownDocument> = {};
|
|
|
|
for (const document of vaultDocs) {
|
|
index[document.slug] = document;
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
interface VaultOptions {
|
|
ignorePatterns?: string[];
|
|
}
|
|
|
|
export default class Vault {
|
|
documents: MarkdownDocument[] = [];
|
|
slugs: string[] = [];
|
|
index: Record<string, MarkdownDocument> = {};
|
|
readonly vaultPath: string;
|
|
|
|
readonly size: number = 0;
|
|
|
|
private ignorePatterns: string[] = [];
|
|
|
|
constructor(vaultRootPath: string, options?: VaultOptions) {
|
|
this.vaultPath = vaultRootPath;
|
|
this.ignorePatterns = options?.ignorePatterns ?? [];
|
|
|
|
const allFiles = loadVaultDocuments(this.vaultPath, this.ignorePatterns);
|
|
const allSlugs = allFiles.map((doc) => doc.slug);
|
|
|
|
this.documents = allFiles;
|
|
this.slugs = allSlugs;
|
|
this.size = allFiles.length;
|
|
this.index = buildVaultIndex(allFiles);
|
|
}
|
|
|
|
map(fn: (document: MarkdownDocument) => MarkdownDocument) {
|
|
this.documents = this.documents.map(fn);
|
|
return this;
|
|
}
|
|
|
|
write() {
|
|
this.documents.forEach((doc) => {
|
|
doc.write();
|
|
});
|
|
}
|
|
}
|