import { EOL } from "os"; import * as path from "path"; import * as fs from "fs"; import { Card } from "./Card"; export class MarkdownFile { private readonly metaStart = `[//]: # (Autogenerated Anki Metadata -- delete to disable sync)`; private readonly metaEnd = `[//]: # (End Autogenerated Anki Metadata)`; public uri: string; public cachedContent: string; public noteIds: number[] = []; public autoSend: boolean = false; constructor(uri: string) { this.uri = uri; this.cachedContent = ""; } /** * 加载文件内容 * @param content 文件内容 */ private loadContent(content: string) { this.noteIds = this.readNoteIds(content); this.autoSend = this.readAutoSendMeta(content); this.cachedContent = this.removeMeta(content.toString()); } async load() { try { const content = (await fs.readFileSync(this.uri)).toString(); this.loadContent(content); } catch (e) { throw e; } } public dirPath() { return path.dirname(this.uri); } private removeMeta(content: string) { const before = content.split(this.metaStart)[0]; const endSplit = content.split(this.metaEnd); const after = endSplit.length > 1 ? endSplit[1] : ""; // console.log(before); const removed = (before + after).trimEnd(); return removed; } // TODO: make line breaks consistent with what's used in the file public async updateMeta(cards: Card[], autoSend: boolean) { this.autoSend = autoSend; const ids = cards.map((c) => c.noteId ?? 0); const metaBody = `[auto-send]: # (${this.autoSend ? "yes" : "no"})${EOL}[note-ids]: # (${ids.join(", ")})`; const meta = `${EOL}${EOL}${EOL}${this.metaStart}${EOL}${metaBody}${EOL}${this.metaEnd}${EOL}`; const content = this.cachedContent + meta; fs.writeFileSync(this.uri, content); } private readNoteIds(content: string): number[] { const re = RegExp(/\[note-ids\]: # \((.+)\)/); const matches = content.match(re); if (matches) { return matches[1].split(", ").map(Number); // what is this wizardry } return []; } private readAutoSendMeta(content: string): boolean { const re = RegExp(/\[auto-send\]: # \((.+)\)/); const matches = content.match(re); if (matches) { return matches[1] === "yes"; // what is this wizardry } return false; } public static fromActiveTextEditor(uri: string): MarkdownFile { let file = new MarkdownFile(uri); file.loadContent(fs.readFileSync(uri).toString() ?? ""); return file; } }