diff --git a/src/ExcalidrawData.ts b/src/ExcalidrawData.ts index 51359a5..b59bf49 100644 --- a/src/ExcalidrawData.ts +++ b/src/ExcalidrawData.ts @@ -1039,10 +1039,12 @@ export class ExcalidrawData { const processedIds = new Set(); fileIds.forEach(fileId=>{ if(processedIds.has(fileId)) { - const file = this.files.get(fileId as FileId); - const equation = this.equations.get(fileId as FileId); + const file = this.getFile(fileId); + //const file = this.files.get(fileId as FileId); + const equation = this.getEquation(fileId); + //const equation = this.equations.get(fileId as FileId); //images should have a single reference, but equations and markdown embeds should have as many as instances of the file in the scene - if(file && file.file.extension !== "md") { + if(file && (file.file.extension !== "md" || !this.plugin.isExcalidrawFile(file.file))) { return; } const newId = fileid(); @@ -1051,10 +1053,12 @@ export class ExcalidrawData { dirty = true; processedIds.add(newId); if(file) { - this.files.set(newId as FileId,new EmbeddedFile(this.plugin,this.file.path,file.linkParts.original)) + this.setFile(newId as FileId,new EmbeddedFile(this.plugin,this.file.path,file.linkParts.original)); + //this.files.set(newId as FileId,new EmbeddedFile(this.plugin,this.file.path,file.linkParts.original)) } if(equation) { - this.equations.set(newId as FileId, equation); + this.setEquation(newId as FileId, {latex:equation.latex, isLoaded:false}); + //this.equations.set(newId as FileId, equation); } } processedIds.add(fileId); @@ -1350,8 +1354,13 @@ export class ExcalidrawData { if (!data.file) { return; } + + const parts = data.linkParts.original.split("#"); this.plugin.filesMaster.set(fileId, { - path: data.file.path, + path:data.file.path, + blockrefData: parts.length === 1 + ? null + : parts[1], hasSVGwithBitmap: data.isSVGwithBitmap, }); } @@ -1361,7 +1370,19 @@ export class ExcalidrawData { } public getFile(fileId: FileId): EmbeddedFile { - return this.files.get(fileId); + let embeddedFile = this.files.get(fileId); + if(embeddedFile) return embeddedFile; + const masterFile = this.plugin.filesMaster.get(fileId); + if(!masterFile) return embeddedFile; + embeddedFile = new EmbeddedFile( + this.plugin, + this.file.path, + masterFile.blockrefData + ? masterFile.path + "#" + masterFile.blockrefData + : masterFile.path + ); + this.files.set(fileId,embeddedFile); + return embeddedFile; } public getFileEntries() { @@ -1380,15 +1401,17 @@ export class ExcalidrawData { return true; } if (this.plugin.filesMaster.has(fileId)) { - const fileMaster = this.plugin.filesMaster.get(fileId); - if (!this.app.vault.getAbstractFileByPath(fileMaster.path)) { + const masterFile = this.plugin.filesMaster.get(fileId); + if (!this.app.vault.getAbstractFileByPath(masterFile.path)) { this.plugin.filesMaster.delete(fileId); return true; } // the file no longer exists const embeddedFile = new EmbeddedFile( this.plugin, this.file.path, - fileMaster.path, + masterFile.blockrefData + ? masterFile.path + "#" + masterFile.blockrefData + : masterFile.path ); this.files.set(fileId, embeddedFile); return true; @@ -1405,7 +1428,12 @@ export class ExcalidrawData { } public getEquation(fileId: FileId): { latex: string; isLoaded: boolean } { - return this.equations.get(fileId); + let result = this.equations.get(fileId); + if(result) return result; + const latex = this.plugin.equationsMaster.get(fileId); + if(!latex) return result; + this.equations.set(fileId, {latex, isLoaded: false}); + return {latex, isLoaded: false}; } public getEquationEntries() { @@ -1514,6 +1542,7 @@ export const getTransclusion = async ( const c = headings[i].node.children[0]; const dataHeading = headings[i].node.data?.hProperties?.dataHeading; const cc = c?.children; + //const refNoSpace = linkParts.ref.replaceAll(" ",""); if ( !startPos && (c?.value?.replaceAll(REG_BLOCK_REF_CLEAN, "") === linkParts.ref || diff --git a/src/ExcalidrawView.ts b/src/ExcalidrawView.ts index ea20100..4e9812a 100644 --- a/src/ExcalidrawView.ts +++ b/src/ExcalidrawView.ts @@ -56,8 +56,7 @@ import { } from "./utils/FileUtils"; import { checkExcalidrawVersion, - decompress, - //debug, + debug, embedFontsInSVG, errorlog, getExportTheme, @@ -88,6 +87,7 @@ import { ToolsPanel } from "./menu/ToolsPanel"; import { ScriptEngine } from "./Scripts"; import { getTextElementAtPointer, getImageElementAtPointer, getElementWithLinkAtPointer } from "./utils/GetElementAtPointer"; + export enum TextMode { parsed, raw, @@ -441,10 +441,11 @@ export default class ExcalidrawView extends TextFileView { } try { - const allowSave = + const allowSave = Boolean ( (this.semaphores.dirty !== null && this.semaphores.dirty) || this.semaphores.autosaving || - forcesave; //dirty == false when view.file == null; + forcesave + ); //dirty == false when view.file == null; const scene = this.getScene(); if (this.compatibilityMode) { @@ -788,7 +789,7 @@ export default class ExcalidrawView extends TextFileView { addFiles, this.plugin, ); - this.setDirty(); + this.setDirty(1); }); return; } @@ -814,7 +815,7 @@ export default class ExcalidrawView extends TextFileView { ef.resetImage(this.file.path, link); await this.save(false); await this.loadSceneFiles(); - this.setDirty(); + this.setDirty(2); }); return; } @@ -887,6 +888,14 @@ export default class ExcalidrawView extends TextFileView { diskIcon: HTMLElement; + excalidrawGetSceneVersion: (elements: ExcalidrawElement[]) => number; + getSceneVersion (elements: ExcalidrawElement[]):number { + if(!this.excalidrawGetSceneVersion) { + this.excalidrawGetSceneVersion = this.plugin.getPackage(this.ownerWindow).excalidrawLib.getSceneVersion; + } + return this.excalidrawGetSceneVersion(elements.filter(el=>!el.isDeleted)); + } + onload() { const apiMissing = Boolean(typeof this.containerEl.onWindowMigrated === "undefined") //@ts-ignore @@ -1530,12 +1539,11 @@ export default class ExcalidrawView extends TextFileView { } } }) - const getSceneVersion = this.plugin.getPackage(this.ownerWindow).excalidrawLib.getSceneVersion; - this.previousSceneVersion = getSceneVersion(sceneElements); + this.previousSceneVersion = this.getSceneVersion(sceneElements); //changing files could result in a race condition for sync. If at the end of sync there are differences //set dirty will trigger an autosave - if(getSceneVersion(inData.scene.elements) !== this.previousSceneVersion) { - this.setDirty(); + if(this.getSceneVersion(inData.scene.elements) !== this.previousSceneVersion) { + this.setDirty(3); } this.excalidrawAPI.updateScene({elements: sceneElements}); if(reloadFiles) this.loadSceneFiles(); @@ -1632,7 +1640,7 @@ export default class ExcalidrawView extends TextFileView { this.plugin.settings.compress !== isCompressed && !this.isEditedAsMarkdownInOtherView() ) { - this.setDirty(); + this.setDirty(4); } } @@ -1645,7 +1653,8 @@ export default class ExcalidrawView extends TextFileView { ); } - public setDirty() { + public setDirty(debug?:number) { + //console.log(debug); this.semaphores.dirty = this.file?.path; this.diskIcon.querySelector("svg").addClass("excalidraw-dirty"); } @@ -1658,8 +1667,7 @@ export default class ExcalidrawView extends TextFileView { this.semaphores.dirty = null; const el = api.getSceneElements(); if (el) { - const getSceneVersion = this.plugin.getPackage(this.ownerWindow).excalidrawLib.getSceneVersion; - this.previousSceneVersion = getSceneVersion(el); + this.previousSceneVersion = this.getSceneVersion(el); } this.diskIcon.querySelector("svg").removeClass("excalidraw-dirty"); } @@ -2208,7 +2216,7 @@ export default class ExcalidrawView extends TextFileView { if (save) { await this.save(false); //preventReload=false will ensure that markdown links are paresed and displayed correctly } else { - this.setDirty(); + this.setDirty(5); } return true; }; @@ -2465,7 +2473,6 @@ export default class ExcalidrawView extends TextFileView { const { Excalidraw, - getSceneVersion, } = this.plugin.getPackage(this.ownerWindow).excalidrawLib; const excalidrawDiv = React.createElement( @@ -2589,7 +2596,7 @@ export default class ExcalidrawView extends TextFileView { if (!this.semaphores.preventAutozoom) { this.zoomToFit(false); } - this.previousSceneVersion = getSceneVersion(et); + this.previousSceneVersion = this.getSceneVersion(et); this.previousBackgroundColor = st.viewBackgroundColor; return; } @@ -2605,15 +2612,16 @@ export default class ExcalidrawView extends TextFileView { st.editingGroupId === null &&*/ st.editingLinearElement === null ) { - const sceneVersion = getSceneVersion(et); + const sceneVersion = this.getSceneVersion(et); if ( - (sceneVersion > 0 && + ((sceneVersion > 0 || + (sceneVersion === 0 && et.length > 0)) && //Addressing the rare case when the last element is deleted from the scene sceneVersion !== this.previousSceneVersion) || st.viewBackgroundColor !== this.previousBackgroundColor ) { this.previousSceneVersion = sceneVersion; this.previousBackgroundColor = st.viewBackgroundColor; - this.setDirty(); + this.setDirty(6); } } }, @@ -2861,7 +2869,7 @@ export default class ExcalidrawView extends TextFileView { if (isDeleted) { this.excalidrawData.deleteTextElement(textElement.id); - this.setDirty(); + this.setDirty(7); return [null, null, null]; } @@ -2876,7 +2884,7 @@ export default class ExcalidrawView extends TextFileView { ) { //the user made changes to the text or the text is missing from Excalidraw Data (recently copy/pasted) //setTextElement will attempt a quick parse (without processing transclusions) - this.setDirty(); + this.setDirty(8); const [parseResultWrapped, parseResultOriginal, link] = this.excalidrawData.setTextElement( textElement.id, diff --git a/src/constants.ts b/src/constants.ts index 314cb70..4e64161 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -18,7 +18,7 @@ export const SCRIPT_INSTALL_FOLDER = "Downloaded"; export const fileid = customAlphabet("1234567890abcdef", 40); export const REG_LINKINDEX_INVALIDCHARS = /[<>:"\\|?*#]/g; export const REG_BLOCK_REF_CLEAN = - /\+|\/|~|=|%|\(|\)|{|}|,|\.|\$|!|\?|;|\[|]|\^|#|\*|<|>|&|@|\||\\|"|:/g; + /\+|\/|~|=|%|\(|\)|{|}|,|&|\.|\$|!|\?|;|\[|]|\^|#|\*|<|>|&|@|\||\\|"|:|\s/g; export const IMAGE_TYPES = ["jpeg", "jpg", "png", "gif", "svg"]; export const MAX_IMAGE_SIZE = 500; export const FRONTMATTER_KEY = "excalidraw-plugin"; diff --git a/src/dialogs/Messages.ts b/src/dialogs/Messages.ts index 84831f0..6c6daeb 100644 --- a/src/dialogs/Messages.ts +++ b/src/dialogs/Messages.ts @@ -18,8 +18,8 @@ I develop this plugin as a hobby, spending most of my free time doing this. If y
`, "1.7.4": ` -- Obsidian 0.15.3 support for dragging and dropping work panes between Obsidian windows. -- Addressed Obsidian changes effecting the more-options menu. +- Obsidian 0.15.3 support dragging and dropping work panes between Obsidian windows. +- Addressed Obsidian changes affecting the more-options menu. - Addressed incompatibility with Obsidian Mobile 1.2.2. `, "1.7.3": ` diff --git a/src/main.ts b/src/main.ts index e830e58..0481f41 100644 --- a/src/main.ts +++ b/src/main.ts @@ -82,6 +82,7 @@ import { log, setLeftHandedMode, sleep, + debug, } from "./utils/Utils"; import { getAttachmentsFolderAndFilePath, getNewOrAdjacentLeaf, getParentOfClass, isObsidianThemeDark } from "./utils/ObsidianUtils"; //import { OneOffs } from "./OneOffs"; @@ -99,6 +100,7 @@ import { decompressFromBase64 } from "lz-string"; import { Packages } from "./types"; import * as React from "react"; + declare module "obsidian" { interface App { isMobile(): boolean; @@ -148,7 +150,7 @@ export default class ExcalidrawPlugin extends Plugin { public opencount: number = 0; public ea: ExcalidrawAutomate; //A master list of fileIds to facilitate copy / paste - public filesMaster: Map = + public filesMaster: Map = null; //fileId, path public equationsMaster: Map = null; //fileId, formula public mathjax: any = null; @@ -162,7 +164,7 @@ export default class ExcalidrawPlugin extends Plugin { super(app, manifest); this.filesMaster = new Map< FileId, - { path: string; hasSVGwithBitmap: boolean } + { path: string; hasSVGwithBitmap: boolean; blockrefData: string } >(); this.equationsMaster = new Map(); } @@ -1485,7 +1487,9 @@ export default class ExcalidrawPlugin extends Plugin { if (previouslyActiveEV.leaf != leaf) { //if loading new view to same leaf then don't save. Excalidarw view will take care of saving anyway. //avoid double saving - await previouslyActiveEV.save(true); //this will update transclusions in the drawing + if(previouslyActiveEV.semaphores.dirty) { + await previouslyActiveEV.save(true); //this will update transclusions in the drawing + } } if (previouslyActiveEV.file) { self.triggerEmbedUpdates(previouslyActiveEV.file.path);