From ebcf8075011d1a76a9e643a64a276afd3c3c8123 Mon Sep 17 00:00:00 2001 From: Zsolt Viczian Date: Sun, 4 Jul 2021 12:15:42 +0200 Subject: [PATCH] 1.2.0-alpha-2 --- src/ExcalidrawData.ts | 47 +++++++++++++++++++++++++++------- src/ExcalidrawView.ts | 4 +-- src/constants.ts | 2 ++ src/lang/locale/en.ts | 14 +++++++--- src/main.ts | 59 ++++++++++++++++++++----------------------- src/openDrawing.ts | 9 +++---- src/settings.ts | 14 +++++----- 7 files changed, 89 insertions(+), 60 deletions(-) diff --git a/src/ExcalidrawData.ts b/src/ExcalidrawData.ts index b1a381d..8292b0e 100644 --- a/src/ExcalidrawData.ts +++ b/src/ExcalidrawData.ts @@ -1,5 +1,9 @@ import { App, TFile } from "obsidian"; -import { nanoid} from "./constants"; +import { + nanoid, + FRONTMATTER_KEY_CUSTOM_PREFIX, + FRONTMATTER_KEY_CUSTOM_LINK_BRACKETS, +} from "./constants"; import { measureText } from "./ExcalidrawAutomate"; import ExcalidrawPlugin from "./main"; import { ExcalidrawSettings } from "./settings"; @@ -29,7 +33,7 @@ export class ExcalidrawData { private settings:ExcalidrawSettings; private app:App; private showLinkBrackets: boolean; - private linkIndicator: string; + private linkPrefix: string; private allowParse: boolean = false; constructor(plugin: ExcalidrawPlugin) { @@ -44,13 +48,16 @@ export class ExcalidrawData { */ public async loadData(data: string,file: TFile, allowParse:boolean):Promise { //console.log("Excalidraw.Data.loadData()",{data:data,allowParse:allowParse,file:file}); - //I am storing these because if the settings change while a drawing is open parsing will run into errors during save - //The drawing will use these values until next drawing is loaded or this drawing is re-loaded - this.showLinkBrackets = this.settings.showLinkBrackets; - this.linkIndicator = this.settings.linkIndicator; this.file = file; this.textElements = new Map(); + + //I am storing these because if the settings change while a drawing is open parsing will run into errors during save + //The drawing will use these values until next drawing is loaded or this drawing is re-loaded + this.setShowLinkBrackets(); + this.setLinkPrefix(); + + //Load scene: Read the JSON string after "# Drawing" this.scene = null; @@ -259,7 +266,7 @@ export class ExcalidrawData { } outString += text.substring(position,text.length); if (linkIcon) { - outString = this.linkIndicator + outString; + outString = this.linkPrefix + outString; } return outString; @@ -281,7 +288,7 @@ export class ExcalidrawData { public syncElements(newScene:any):boolean { //console.log("Excalidraw.Data.syncElements()"); this.scene = JSON_parse(newScene); - const result = this.findNewTextElementsInScene(); + const result = this.setLinkPrefix() || this.setShowLinkBrackets() || this.findNewTextElementsInScene(); this.updateTextElementsFromSceneRawOnly(); return result; } @@ -289,7 +296,7 @@ export class ExcalidrawData { public async updateScene(newScene:any){ //console.log("Excalidraw.Data.updateScene()"); this.scene = JSON_parse(newScene); - const result = this.findNewTextElementsInScene(); + const result = this.setLinkPrefix() || this.setShowLinkBrackets() || this.findNewTextElementsInScene(); await this.updateTextElementsFromScene(); if(result) { await this.updateSceneTextElements(); @@ -302,4 +309,26 @@ export class ExcalidrawData { return this.textElements.get(id)?.raw; } + private setLinkPrefix():boolean { + const linkPrefix = this.linkPrefix; + const fileCache = this.app.metadataCache.getFileCache(this.file); + if (fileCache?.frontmatter && fileCache.frontmatter[FRONTMATTER_KEY_CUSTOM_PREFIX]!=null) { + this.linkPrefix=fileCache.frontmatter[FRONTMATTER_KEY_CUSTOM_PREFIX]; + } else { + this.linkPrefix = this.settings.linkPrefix; + } + return linkPrefix != this.linkPrefix; + } + + private setShowLinkBrackets():boolean { + const showLinkBrackets = this.showLinkBrackets; + const fileCache = this.app.metadataCache.getFileCache(this.file); + if (fileCache?.frontmatter && fileCache.frontmatter[FRONTMATTER_KEY_CUSTOM_LINK_BRACKETS]!=null) { + this.showLinkBrackets=fileCache.frontmatter[FRONTMATTER_KEY_CUSTOM_LINK_BRACKETS]!=false; + } else { + this.showLinkBrackets = this.settings.showLinkBrackets; + } + return showLinkBrackets != this.showLinkBrackets; + } + } \ No newline at end of file diff --git a/src/ExcalidrawView.ts b/src/ExcalidrawView.ts index 36ce454..f7d0c83 100644 --- a/src/ExcalidrawView.ts +++ b/src/ExcalidrawView.ts @@ -127,7 +127,7 @@ export default class ExcalidrawView extends TextFileView { // get the new file content // if drawing is in Text Element Edit Lock, then everything should be parsed and in sync - // if drawing is in Text Element Edit Unlock, then everything is raw and parse a.k.a async is not required. + // if drawing is in Text Element Edit Unlock, then everything is raw and parse and so an async function is not required here getViewData () { //console.log("ExcalidrawView.getViewData()"); if(this.getScene) { @@ -345,7 +345,7 @@ export default class ExcalidrawView extends TextFileView { .setIcon(ICON_NAME) .onClick( async (ev) => { if(!this.getScene || !this.file) return; - this.download('data:text/plain;charset=utf-8',encodeURIComponent(this.getScene()), this.file.basename+'.excalidraw'); + this.download('data:text/plain;charset=utf-8',encodeURIComponent(this.getScene().replaceAll("[","[")), this.file.basename+'.excalidraw'); }); }) .addItem((item) => { diff --git a/src/constants.ts b/src/constants.ts index 3f1512e..f6befe8 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -5,6 +5,8 @@ export function JSON_parse(x:string):any {return JSON.parse(x.replaceAll("[" import {customAlphabet} from "nanoid"; export const nanoid = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',8); export const FRONTMATTER_KEY = "excalidraw-plugin"; +export const FRONTMATTER_KEY_CUSTOM_PREFIX = "excalidraw-link-prefix"; +export const FRONTMATTER_KEY_CUSTOM_LINK_BRACKETS = "excalidraw-link-brackets"; export const VIEW_TYPE_EXCALIDRAW = "excalidraw"; export const ICON_NAME = "excalidraw-icon"; export const MAX_COLORS = 5; diff --git a/src/lang/locale/en.ts b/src/lang/locale/en.ts index 80152f9..41be424 100644 --- a/src/lang/locale/en.ts +++ b/src/lang/locale/en.ts @@ -1,3 +1,5 @@ +import { FRONTMATTER_KEY_CUSTOM_LINK_BRACKETS, FRONTMATTER_KEY_CUSTOM_PREFIX } from "src/constants"; + // English export default { // main.ts @@ -45,7 +47,7 @@ export default { TEMPLATE_NAME: "Excalidraw template file", TEMPLATE_DESC: "Full filepath to the Excalidraw template. " + "E.g.: If your template is in the default Excalidraw folder and it's name is " + - "Template, the setting would be: Excalidraw/Template", + "Template.excalidraw, the setting would be: Excalidraw/Template.excalidraw", FILENAME_HEAD: "Filenam for drawings", FILENAME_DESC: "

The auto-generated filename consists of a prefix and a date. " + "e.g.'Drawing 2021-05-24 12.58.07'.

"+ @@ -64,9 +66,13 @@ export default { "When Obsidian files change, the matching [[link]] in your drawings will also change. " + "If you don't want text accidentally changing in your drawings use [[links|with aliases]].", LINK_BRACKETS_NAME: "Show [[brackets]] around links", - LINK_BRACKETS_DESC: "In preview (locked) mode, when parsing Text Elements, place brackets around links", - LINK_INDICATOR_NAME:"Link indicator", - LINK_INDICATOR_DESC:"In preview (locked) mode, if the Text Element contains a link, precede the text with these characters.", + LINK_BRACKETS_DESC: "In preview (locked) mode, when parsing Text Elements, place brackets around links. " + + "You can override this setting for a specific drawing by adding '" + FRONTMATTER_KEY_CUSTOM_LINK_BRACKETS + + ": true/false' to the file\'s frontmatter.", + LINK_PREFIX_NAME:"Link prefix", + LINK_PREFIX_DESC:"In preview (locked) mode, if the Text Element contains a link, precede the text with these characters. " + + "You can override this setting for a specific drawing by adding \'" + FRONTMATTER_KEY_CUSTOM_PREFIX + + ': "👉 "\' to the file\'s frontmatter.', LINK_CTRL_CLICK_NAME: "CTRL + CLICK on text to open them as links", LINK_CTRL_CLICK_DESC: "You can turn this feature off if it interferes with default Excalidraw features you want to use. If " + "this is turned off, only the link button in the title bar of the drawing pane will open links.", diff --git a/src/main.ts b/src/main.ts index eac113e..123b8d8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -63,8 +63,6 @@ export default class ExcalidrawPlugin extends Plugin { private openDialog: OpenFileDialog; private activeExcalidrawView: ExcalidrawView = null; public lastActiveExcalidrawFilePath: string = null; - private workspaceEventHandlers:Map = new Map(); - private vaultEventHandlers:Map = new Map(); private hover: {linkText: string, sourcePath: string} = {linkText: null, sourcePath: null}; private observer: MutationObserver; @@ -82,7 +80,6 @@ export default class ExcalidrawPlugin extends Plugin { await this.loadSettings(); this.addSettingTab(new ExcalidrawSettingTab(this.app, this)); - await initExcalidrawAutomate(this); this.registerView( @@ -92,10 +89,10 @@ export default class ExcalidrawPlugin extends Plugin { this.addMarkdownPostProcessor(); this.registerCommands(); - this.registerEventListeners(); - //inspiration taken from kanban: https://github.com/mgmeyers/obsidian-kanban/blob/44118e25661bff9ebfe54f71ae33805dc88ffa53/src/main.ts#L267 + //inspiration taken from kanban: + //https://github.com/mgmeyers/obsidian-kanban/blob/44118e25661bff9ebfe54f71ae33805dc88ffa53/src/main.ts#L267 this.registerMonkeyPatches(); } @@ -207,7 +204,6 @@ export default class ExcalidrawPlugin extends Plugin { * @returns */ const hoverEvent = (e:any) => { - //@ts-ignore if(!(e.event.ctrlKey||e.event.metaKey)) return; if(!e.linktext) return; this.hover.linkText = e.linktext; @@ -219,10 +215,11 @@ export default class ExcalidrawPlugin extends Plugin { return; } - }; - //@ts-ignore - this.app.workspace.on('hover-link',hoverEvent); - this.workspaceEventHandlers.set('hover-link',hoverEvent); + }; + this.registerEvent( + //@ts-ignore + this.app.workspace.on('hover-link',hoverEvent) + ); //monitoring for div.popover.hover-popover.file-embed.is-loaded to be added to the DOM tree this.observer = new MutationObserver((m)=>{ @@ -283,8 +280,6 @@ export default class ExcalidrawPlugin extends Plugin { this.app.workspace.on("file-menu", fileMenuHandler) ); - this.workspaceEventHandlers.set("file-menu",fileMenuHandler); - this.addCommand({ id: "excalidraw-open", name: t("OPEN_EXISTING_NEW_PANE"), @@ -641,8 +636,9 @@ export default class ExcalidrawPlugin extends Plugin { } }); }; - self.app.vault.on("rename",renameEventHandler); - this.vaultEventHandlers.set("rename",renameEventHandler); + self.registerEvent( + self.app.vault.on("rename",renameEventHandler) + ); const modifyEventHandler = async (file:TFile) => { const leaves = self.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW); @@ -653,13 +649,15 @@ export default class ExcalidrawPlugin extends Plugin { } }); } - self.app.vault.on("modify",modifyEventHandler); - this.vaultEventHandlers.set("modify",modifyEventHandler); + self.registerEvent( + self.app.vault.on("modify",modifyEventHandler) + ) - //watch file delete and delete corresponding .svg + //watch file delete and delete corresponding .svg and .png const deleteEventHandler = async (file:TFile) => { - if (!(file instanceof TFile)) return; - if (!self.isExcalidrawFile(file)) return; + if (!(file instanceof TFile)) return; + //@ts-ignore + if (file.unsaveCachedData && !file.unsafeCachedData.search(/---\n[\s\S]*excalidraw-plugin:\s*(locked|unlocked)\n[\s\S]*---/gm)==-1) return; //close excalidraw view where this file is open const leaves = self.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW); @@ -680,8 +678,9 @@ export default class ExcalidrawPlugin extends Plugin { }); } } - self.app.vault.on("delete",deleteEventHandler); - this.vaultEventHandlers.set("delete",deleteEventHandler); + self.registerEvent( + self.app.vault.on("delete",deleteEventHandler) + ); //save open drawings when user quits the application const quitEventHandler = (tasks: Tasks) => { @@ -690,14 +689,14 @@ export default class ExcalidrawPlugin extends Plugin { (leaves[i].view as ExcalidrawView).save(); } } - self.app.workspace.on("quit",quitEventHandler); - this.workspaceEventHandlers.set("quit",quitEventHandler); + self.registerEvent( + self.app.workspace.on("quit",quitEventHandler) + ); //save Excalidraw leaf and update embeds when switching to another leaf const activeLeafChangeEventHandler = async (leaf:WorkspaceLeaf) => { const activeview:ExcalidrawView = (leaf.view instanceof ExcalidrawView) ? leaf.view as ExcalidrawView : null; if(self.activeExcalidrawView && self.activeExcalidrawView != activeview) { - //console.log("ExcalidrawPlugin.activeLeafChangeEventHandler()"); await self.activeExcalidrawView.save(); self.triggerEmbedUpdates(self.activeExcalidrawView.file?.path); } @@ -706,19 +705,15 @@ export default class ExcalidrawPlugin extends Plugin { self.lastActiveExcalidrawFilePath = self.activeExcalidrawView.file?.path; } }; - self.app.workspace.on("active-leaf-change",activeLeafChangeEventHandler); - this.workspaceEventHandlers.set("active-leaf-change",activeLeafChangeEventHandler); + self.registerEvent( + self.app.workspace.on("active-leaf-change",activeLeafChangeEventHandler) + ); }); } onunload() { destroyExcalidrawAutomate(); - for(const key of this.vaultEventHandlers.keys()) - this.app.vault.off(key,this.vaultEventHandlers.get(key)) - for(const key of this.workspaceEventHandlers.keys()) - this.app.workspace.off(key,this.workspaceEventHandlers.get(key)); this.observer.disconnect(); - const excalidrawLeaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW); excalidrawLeaves.forEach((leaf) => { this.setMarkdownView(leaf); @@ -778,7 +773,7 @@ export default class ExcalidrawPlugin extends Plugin { } private getNextDefaultFilename():string { - return this.settings.drawingFilenamePrefix + window.moment().format(this.settings.drawingFilenameDateTime)+'.md'; + return this.settings.drawingFilenamePrefix + window.moment().format(this.settings.drawingFilenameDateTime)+'.excalidraw.md'; } diff --git a/src/openDrawing.ts b/src/openDrawing.ts index 3bcb40b..6205f57 100644 --- a/src/openDrawing.ts +++ b/src/openDrawing.ts @@ -33,7 +33,7 @@ export class OpenFileDialog extends FuzzySuggestModal { this.inputEl.onkeyup = (e) => { if(e.key=="Enter" && this.action == openDialogAction.openFile) { if (this.containerEl.innerText.includes(EMPTY_MESSAGE)) { - this.plugin.createDrawing(this.plugin.settings.folder+'/'+this.inputEl.value+'.md', this.onNewPane); + this.plugin.createDrawing(this.plugin.settings.folder+'/'+this.inputEl.value+'.excalidraw.md', this.onNewPane); this.close(); } } @@ -62,11 +62,8 @@ export class OpenFileDialog extends FuzzySuggestModal { break; case(openDialogAction.insertLink): //TO-DO - //change to this.app.metadataCache.fileToLinktext(file: TFile, sourcePath: string, omitMdExtension?: boolean): string; - - //@ts-ignore - const filepath = this.app.metadataCache.getLinkpathDest(item.path,this.drawingPath)[0].path; - this.addText("[["+(filepath.endsWith(".md")?filepath.substr(0,filepath.length-3):filepath)+"]]"); //.md files don't need the extension + const filepath = this.app.metadataCache.fileToLinktext(item,this.drawingPath,true); + this.addText("[["+filepath+"]]"); break; } } diff --git a/src/settings.ts b/src/settings.ts index 1dc9089..f719d80 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -15,7 +15,7 @@ export interface ExcalidrawSettings { drawingFilenameDateTime: string, width: string, showLinkBrackets: boolean, - linkIndicator: string, + linkPrefix: string, // validLinksOnly: boolean, //valid link as in [[valid Obsidian link]] - how to treat text elements in drawings allowCtrlClick: boolean, //if disabled only the link button in the view header will open links exportWithTheme: boolean, @@ -28,11 +28,11 @@ export interface ExcalidrawSettings { export const DEFAULT_SETTINGS: ExcalidrawSettings = { folder: 'Excalidraw', - templateFilePath: 'Excalidraw/Template', + templateFilePath: 'Excalidraw/Template.excalidraw', drawingFilenamePrefix: 'Drawing ', drawingFilenameDateTime: 'YYYY-MM-DD HH.mm.ss', width: '400', - linkIndicator: ">> ", + linkPrefix: ">> ", showLinkBrackets: true, // validLinksOnly: false, allowCtrlClick: true, @@ -146,13 +146,13 @@ export class ExcalidrawSettingTab extends PluginSettingTab { })); new Setting(containerEl) - .setName(t("LINK_INDICATOR_NAME")) - .setDesc(t("LINK_INDICATOR_DESC")) + .setName(t("LINK_PREFIX_NAME")) + .setDesc(t("LINK_PREFIX_DESC")) .addText(text => text .setPlaceholder('>> ') - .setValue(this.plugin.settings.linkIndicator) + .setValue(this.plugin.settings.linkPrefix) .onChange(async (value) => { - this.plugin.settings.linkIndicator = value; + this.plugin.settings.linkPrefix = value; await this.plugin.saveSettings(); reloadDrawings(); }));