diff --git a/manifest.json b/manifest.json index d7317bb..0592f9e 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "obsidian-excalidraw-plugin", "name": "Excalidraw", - "version": "1.6.9", + "version": "1.6.10", "minAppVersion": "0.12.16", "description": "An Obsidian plugin to edit and view Excalidraw drawings", "author": "Zsolt Viczian", diff --git a/src/ExcalidrawView.ts b/src/ExcalidrawView.ts index 43ddfcb..095867c 100644 --- a/src/ExcalidrawView.ts +++ b/src/ExcalidrawView.ts @@ -252,16 +252,31 @@ export default class ExcalidrawView extends TextFileView { } } + //Save is triggered by multiple threads when an Excalidraw pane is terminated + //- by the view itself + //- by the activeLeafChangeEventHandler change event handler + //- by monkeypatches on detach(next) + //This semaphore helps avoid collision of saves + private preventSave:boolean = false; //this.saving is taken by Obsidian. When I set this, nothing got saved at all. async save(preventReload: boolean = true) { + if(this.preventSave) { + return; + } + this.preventSave = true; + if (!this.getScene) { + this.preventSave = false; return; } if (!this.isLoaded) { + this.preventSave = false; return; } - if(!this.app.vault.getAbstractFileByPath(this.file.path)) { + if(!this.file || !this.app.vault.getAbstractFileByPath(this.file.path)) { + this.preventSave = false; return; //file was recently deleted } + this.preventReload = preventReload; this.dirty = null; const scene = this.getScene(); @@ -309,6 +324,7 @@ export default class ExcalidrawView extends TextFileView { this.saveExcalidraw(); } } + this.preventSave = false; } // get the new file content @@ -698,6 +714,10 @@ export default class ExcalidrawView extends TextFileView { //save current drawing when user closes workspace leaf async onunload() { + const tooltip = document.body.querySelector("body>div.excalidraw-tooltip,div.excalidraw-tooltip--visible"); + if(tooltip) { + document.body.removeChild(tooltip); + } if (this.autosaveTimer) { clearInterval(this.autosaveTimer); this.autosaveTimer = null; @@ -789,7 +809,7 @@ export default class ExcalidrawView extends TextFileView { e.message === "Cannot read property 'index' of undefined" ? "\n'# Drawing' section is likely missing" : "" - }\n\nTry manually fixing the file or restoring an earlier version from sync history.\n\nYou may also look for the backup file with last working version in the same folder (same filename as your drawing, but starting with a dot. e.g. drawing.md => .drawing.md). Note the backup files do not get synchronized, so look for the backup file on other devices as well.`, + }\n\nTry manually fixing the file or restoring an earlier version from sync history.\n\nYou may also look for the backup file with last working version in the same folder (same filename as your drawing, but starting with a dot. e.g. drawing.md => .drawing.md.bak). Note the backup files do not get synchronized, so look for the backup file on other devices as well.`, 10000, ); this.setMarkdownView(); @@ -2054,9 +2074,12 @@ export default class ExcalidrawView extends TextFileView { //there were no transclusions in the raw text, quick parse was successful this.setupAutosaveTimer(); if (this.textMode === TextMode.raw) { - return [null, null, link]; + return [parseResultWrapped, parseResultOriginal, link]; } //text is displayed in raw, no need to clear the history, undo will not create problems - if (text === parseResultWrapped) { + if (text === parseResultWrapped) { + if(link) {//don't forget the case: link-prefix:"" && link-brackets:true + return [parseResultWrapped, parseResultOriginal, link]; + } return [null, null, null]; } //There were no links to parse, raw text and parsed text are equivalent this.excalidrawAPI.history.clear(); @@ -2101,15 +2124,17 @@ export default class ExcalidrawView extends TextFileView { this.file.path, ); - if (event.shiftKey && this.isFullscreen()) { + const useNewLeaf = event.shift || event[CTRL_OR_CMD]; + + if (useNewLeaf && this.isFullscreen()) { this.exitFullscreen(); } if (!file) { - (new NewFileActions(this.plugin,linkText,event.shiftKey,this)).open(); + (new NewFileActions(this.plugin,linkText,useNewLeaf,this)).open(); return; } try { - const leaf = (event.shiftKey || event[CTRL_OR_CMD]) + const leaf = useNewLeaf ? getNewOrAdjacentLeaf(this.plugin, this.leaf) : this.leaf; leaf.openFile(file, { eState: { line: lineNum - 1 } }); //if file exists open file and jump to reference diff --git a/src/Prompt.ts b/src/Prompt.ts index 21eb03b..3bd1ef2 100644 --- a/src/Prompt.ts +++ b/src/Prompt.ts @@ -418,11 +418,22 @@ export class NewFileActions extends Modal { return true; } + const createFile = async (data:string):Promise => { + if(!this.path.includes("/")) { + const re = new RegExp(`${this.view.file.name}$`,"g"); + this.path = this.view.file.path.replace(re,this.path) + } + if(!this.path.match(/\.md$/)) { + this.path = this.path+".md"; + } + const f = await this.app.vault.create(this.path,data) + return f; + } + const bMd = el.createEl("button", { text: "Create Markdown" }); bMd.onclick = async () => { if(!checks) return; - //@ts-ignore - const f = await this.app.fileManager.createNewMarkdownFileFromLinktext(this.path,this.view.file); + const f = await createFile(""); this.openFile(f); this.close(); }; @@ -430,13 +441,7 @@ export class NewFileActions extends Modal { const bEx = el.createEl("button", { text: "Create Excalidraw" }); bEx.onclick = async () => { if(!checks) return; - //@ts-ignore - const f = await this.app.fileManager.createNewMarkdownFileFromLinktext(this.path,this.view.file) - if(!f) { - new Notice(`Error creating file: ${this.path}`); - return; - } - await this.app.vault.modify(f,await this.plugin.getBlankDrawing()); + const f = await createFile(await this.plugin.getBlankDrawing()); await sleep(200); //wait for metadata cache to update, so file opens as excalidraw this.openFile(f); this.close(); diff --git a/src/SuggestorInfo.ts b/src/SuggestorInfo.ts index 09fbfd4..b0eb389 100644 --- a/src/SuggestorInfo.ts +++ b/src/SuggestorInfo.ts @@ -467,49 +467,49 @@ export const EXCALIDRAW_SCRIPTENGINE_INFO:SuggestorInfo[] = [ export const FRONTMATTER_KEYS_INFO:SuggestorInfo[] = [ { - field: FRONTMATTER_KEY, + field: "plugin", code: null, desc: "Denotes an excalidraw file. If key is not present, the file will not be recognized as an Excalidarw file. Valid values are 'parsed' and 'raw'", after: ": parsed", }, { - field: FRONTMATTER_KEY_CUSTOM_PREFIX, + field: "link-prefix", code: null, desc: "Set custom prefix to denote text element containing a valid internal link. Set to empty string if you do not want to show a prefix", after: ': "📍"', }, { - field: FRONTMATTER_KEY_CUSTOM_URL_PREFIX, + field: "url-prefix", code: null, desc: "Set custom prefix to denote text element containing a valid external link. Set to empty string if you do not want to show a prefix", after: ': "🌐"', }, { - field: FRONTMATTER_KEY_CUSTOM_LINK_BRACKETS, + field: "link-brackets", code: null, desc: "Set to true, if you want to display [[square brackets]] around the links in Text Elements", after: ": true", }, { - field: FRONTMATTER_KEY_DEFAULT_MODE, + field: "default-mode", code: null, desc: "Specifies how Excalidraw should open by default. Valid values are: view|zen", after: ": view", }, { - field: FRONTMATTER_KEY_FONT, + field: "font", code: null, desc: "This key applies to Markdown Embeds. You can control the appearance of the embedded markdown file on a file by file bases by adding the this front matter keys to your markdown document. Valid values are: Virgil|Cascadia|font_file_name.extension", after: ": Virgil", }, { - field: FRONTMATTER_KEY_FONTCOLOR, + field: "font-color", code: null, desc: "This key applies to Markdown Embeds. You can control the appearance of the embedded markdown file on a file by file bases by adding the this front matter keys to your markdown document. Valid values are: css-color-name|#HEXcolor|any-other-html-standard-format", after: ": SteelBlue", }, { - field: FRONTMATTER_KEY_MD_STYLE, + field: "css", code: null, desc: 'This key applies to Markdown Embeds. You can control the appearance of the embedded markdown file on a file by file bases by adding the this front matter keys to your markdown document. Valid values are: "css-filename|css snippet"', after: ': ""', diff --git a/src/Utils.ts b/src/Utils.ts index ef674ff..c08d6bb 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -83,9 +83,9 @@ export function splitFolderAndFilename(filepath: string): { basename: string; } { const lastIndex = filepath.lastIndexOf("/"); - const filename = lastIndex == -1 ? filepath : filepath.substr(lastIndex + 1); + const filename = lastIndex == -1 ? filepath : filepath.substring(lastIndex + 1); return { - folderpath: normalizePath(filepath.substr(0, lastIndex)), + folderpath: normalizePath(filepath.substring(0, lastIndex)), filename, basename: filename.replace(/\.[^/.]+$/, ""), }; @@ -127,7 +127,7 @@ export function getIMGPathFromExcalidrawFile( export function getBakPath(file:TFile):string { const re = new RegExp(`${file.name}$`,"g"); - return file.path.replace(re,`.${file.name}`); + return file.path.replace(re,`.${file.name}.bak`); } /** diff --git a/versions.json b/versions.json index 909ff79..7378851 100644 --- a/versions.json +++ b/versions.json @@ -1,4 +1,4 @@ { - "1.6.9": "0.12.16", + "1.6.10": "0.12.16", "1.4.2": "0.11.13" }