diff --git a/manifest.json b/manifest.json index 6f00012..d7317bb 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "obsidian-excalidraw-plugin", "name": "Excalidraw", - "version": "1.6.8", + "version": "1.6.9", "minAppVersion": "0.12.16", "description": "An Obsidian plugin to edit and view Excalidraw drawings", "author": "Zsolt Viczian", diff --git a/package.json b/package.json index 950db29..6b8192a 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,18 @@ { "name": "obsidian-excalidraw-plugin", - "version": "1.3.21", + "version": "1.6.9", "description": "This is an Obsidian.md plugin that lets you view and edit Excalidraw drawings", "main": "main.js", "scripts": { "dev": "cross-env NODE_ENV=development rollup --config rollup.config.js -w", - "build": "cross-env NODE_ENV=production rollup --config rollup.config.js", + "build": "cross-env NODE_ENV=production rollup --config rollup.config.js && terser main.js --compress toplevel=true,passes=2 --output main.js", "code:fix": "eslint --max-warnings=0 --ext .ts,.tsx ./src --fix" }, "keywords": [], "author": "", "license": "MIT", "dependencies": { - "@zsviczian/excalidraw": "0.10.0-obsidian-48", + "@zsviczian/excalidraw": "0.10.0-obsidian-49", "monkey-around": "^2.3.0", "react": "^17.0.2", "react-dom": "^17.0.2", @@ -38,6 +38,7 @@ "obsidian": "^0.13.21", "rollup": "^2.66.0", "rollup-plugin-visualizer": "^5.5.4", + "rollup-plugin-terser": "^7.0.2", "tslib": "^2.3.1", "typescript": "^4.5.5", "eslint-config-prettier": "8.3.0", diff --git a/rollup.config.js b/rollup.config.js index 46096b4..4a09a2f 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -5,6 +5,7 @@ import { env } from "process"; import babel from '@rollup/plugin-babel'; import replace from "@rollup/plugin-replace"; import visualizer from "rollup-plugin-visualizer"; +import { terser } from "rollup-plugin-terser"; const isProd = (process.env.NODE_ENV === "production"); console.log("Is production", isProd); @@ -30,5 +31,8 @@ export default { nodeResolve({ browser: true, preferBuiltins: true }), typescript({inlineSources: !isProd}), visualizer(), + ...isProd ? [ + terser({toplevel: true, compress: {passes: 2}}) + ] : [] ], }; \ No newline at end of file diff --git a/src/ExcalidrawData.ts b/src/ExcalidrawData.ts index 86c0b42..9168bb6 100644 --- a/src/ExcalidrawData.ts +++ b/src/ExcalidrawData.ts @@ -21,6 +21,7 @@ import { JSON_parse } from "./constants"; import { TextMode } from "./ExcalidrawView"; import { getAttachmentsFolderAndFilePath, + getBakPath, getBinaryFileFromDataURL, getLinkParts, isObsidianThemeDark, @@ -267,9 +268,8 @@ export class ExcalidrawData { try { sceneJSONandPOS = loadJSON(); } catch (e) { - const bakfile = this.app.vault.getAbstractFileByPath(`${file.path}.bak`); - if (bakfile && bakfile instanceof TFile) { - data = await this.app.vault.read(bakfile); + if(await this.app.vault.adapter.exists(getBakPath(file))) { + data = await this.app.vault.adapter.read(getBakPath(file)) sceneJSONandPOS = loadJSON(); new Notice(t("LOAD_FROM_BACKUP"), 4000); } else { diff --git a/src/ExcalidrawView.ts b/src/ExcalidrawView.ts index 1d0c03c..26afce7 100644 --- a/src/ExcalidrawView.ts +++ b/src/ExcalidrawView.ts @@ -53,6 +53,7 @@ import { download, embedFontsInSVG, errorlog, + getBakPath, getIMGFilename, getNewOrAdjacentLeaf, getNewUniqueFilepath, @@ -276,14 +277,14 @@ export default class ExcalidrawView extends TextFileView { } //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/396 - const bakfilepath = `${this.file.path}.bak`; + const bakfilepath = getBakPath(this.file); try { if (await this.app.vault.adapter.exists(bakfilepath)) { await this.app.vault.adapter.remove(bakfilepath); } await this.app.vault.adapter.copy(this.file.path, bakfilepath); } catch(e) { - console.error({where: "ExcalidrawView.save copy bak", error: e}); + console.error({where: "ExcalidrawView.save copy backup file", error: e}); } await super.save(); @@ -291,7 +292,7 @@ export default class ExcalidrawView extends TextFileView { try { await this.app.vault.adapter.remove(bakfilepath); } catch(e) { - console.error({where: "ExcalidrawView.save remove bak", error: e}); + console.error({where: "ExcalidrawView.save removing backup file", error: e}); } if (!this.autosaving) { @@ -788,7 +789,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 .bak file with last working version in the same folder. Note the .bak file might not get synchronized, so look for .bak 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). Note the backup files do not get synchronized, so look for the backup file on other devices as well.`, 10000, ); this.setMarkdownView(); @@ -829,6 +830,15 @@ export default class ExcalidrawView extends TextFileView { } } + setDefaultTrayMode() { + setTimeout(()=> { + if(!this.excalidrawAPI) return; + const st = this.excalidrawAPI.getAppState(); + st.trayModeEnabled = this.plugin.settings.defaultTrayMode; + this.excalidrawAPI.updateScene({appState:st}); + }, 500); + } + /** * * @param justloaded - a flag to trigger zoom to fit after the drawing has been loaded @@ -882,6 +892,7 @@ export default class ExcalidrawView extends TextFileView { //debug({where:"ExcalidrawView.loadDrawing",file:this.file.name,before:"this.loadSceneFiles"}); this.loadSceneFiles(); this.updateContainerSize(null, true); + this.setDefaultTrayMode(); } else { this.instantiateExcalidraw({ elements: excalidrawData.elements, @@ -1120,6 +1131,7 @@ export default class ExcalidrawView extends TextFileView { this.loadSceneFiles(); this.updateContainerSize(null, true); + this.setDefaultTrayMode(); }); }, [excalidrawRef]); @@ -1772,6 +1784,7 @@ export default class ExcalidrawView extends TextFileView { showHoverPreview(); } }, + autoFocus: true, onChange: (et: ExcalidrawElement[], st: AppState) => { viewModeEnabled = st.viewModeEnabled; if (this.justLoaded) { @@ -1996,11 +2009,11 @@ export default class ExcalidrawView extends TextFileView { //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/318 //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/299 - if (!this.app.isMobile) { + /*if (!this.app.isMobile) { setTimeout(() => { this?.excalidrawWrapperRef?.current?.firstElementChild?.focus(); }, 50); - } + }*/ const containerId = textElement.containerId; diff --git a/src/MarkdownPostProcessor.ts b/src/MarkdownPostProcessor.ts index ec3f8a8..02fc631 100644 --- a/src/MarkdownPostProcessor.ts +++ b/src/MarkdownPostProcessor.ts @@ -29,6 +29,12 @@ let plugin: ExcalidrawPlugin; let vault: Vault; let metadataCache: MetadataCache; +const getDefaultWidth = (plugin: ExcalidrawPlugin):string => { + const width = parseInt(plugin.settings.width); + if(isNaN(width) || width === 0) return "400"; + return plugin.settings.width; +} + export const initializeMarkdownPostProcessor = (p: ExcalidrawPlugin) => { plugin = p; vault = p.app.vault; @@ -218,7 +224,7 @@ const processInternalEmbeds = async ( if (file && file instanceof TFile && plugin.isExcalidrawFile(file)) { attr.fwidth = maybeDrawing.getAttribute("width") ? maybeDrawing.getAttribute("width") - : plugin.settings.width; + : getDefaultWidth(plugin); attr.fheight = maybeDrawing.getAttribute("height"); alt = maybeDrawing.getAttribute("alt"); if (alt == attr.fname) { @@ -232,9 +238,9 @@ const processInternalEmbeds = async ( if (maybeDrawing.tagName.toLowerCase() == "span") { alt = `|${alt}`; } - //1:width, 2:height, 3:style 1 2 3 + //1:width, 2:height, 3:style 1 2 3 parts = alt.match(/[^\|]*\|?(\d*%?)x?(\d*%?)\|?(.*)/); - attr.fwidth = parts[1] ? parts[1] : plugin.settings.width; + attr.fwidth = parts[1] ? parts[1] : getDefaultWidth(plugin); attr.fheight = parts[2]; if (parts[3] != attr.fname) { attr.style = `excalidraw-svg${parts[3] ? `-${parts[3]}` : ""}`; @@ -269,7 +275,7 @@ const tmpObsidianWYSIWYG = async ( const attr: imgElementAttributes = { fname: ctx.sourcePath, fheight: "", - fwidth: plugin.settings.width, + fwidth: getDefaultWidth(plugin), style: "excalidraw-svg", }; @@ -328,7 +334,7 @@ const tmpObsidianWYSIWYG = async ( if (hasAttr) { //1:width, 2:height, 3:style 1 2 3 const parts = alt.match(/(\d*%?)x?(\d*%?)\|?(.*)/); - attr.fwidth = parts[1] ? parts[1] : plugin.settings.width; + attr.fwidth = parts[1] ? parts[1] : getDefaultWidth(plugin); attr.fheight = parts[2]; if (parts[3] != attr.fname) { attr.style = `excalidraw-svg${parts[3] ? `-${parts[3]}` : ""}`; @@ -336,7 +342,7 @@ const tmpObsidianWYSIWYG = async ( } if (!hasWidth && !hasHeight && !hasAttr) { attr.fheight = ""; - attr.fwidth = plugin.settings.width; + attr.fwidth = getDefaultWidth(plugin); attr.style = "excalidraw-svg"; } }; diff --git a/src/Prompt.ts b/src/Prompt.ts index fde4cdb..21eb03b 100644 --- a/src/Prompt.ts +++ b/src/Prompt.ts @@ -7,6 +7,7 @@ import { FuzzySuggestModal, Instruction, TFile, + Notice, } from "obsidian"; import ExcalidrawView from "./ExcalidrawView"; import ExcalidrawPlugin from "./main"; @@ -405,20 +406,36 @@ export class NewFileActions extends Modal { //files manually follow one of two options: el.style.textAlign = "right"; + const checks = ():boolean => { + if(!this.path || this.path === "") { + new Notice ("Error: Filename for new file may not be empty"); + return false; + } + if(!this.view.file) { + new Notice ("Unknown error. It seems as if your drawing was closed or the drawing file is missing"); + return false; + } + return true; + } + 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.viewFile); + const f = await this.app.fileManager.createNewMarkdownFileFromLinktext(this.path,this.view.file); this.openFile(f); this.close(); }; - 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.viewFile) - if(!f) return; + 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()); await sleep(200); //wait for metadata cache to update, so file opens as excalidraw this.openFile(f); diff --git a/src/Utils.ts b/src/Utils.ts index 83ad0b5..ef674ff 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -5,6 +5,7 @@ import { Notice, request, TAbstractFile, + TFile, TFolder, Vault, WorkspaceLeaf, @@ -124,6 +125,11 @@ export function getIMGPathFromExcalidrawFile( ); } +export function getBakPath(file:TFile):string { + const re = new RegExp(`${file.name}$`,"g"); + return file.path.replace(re,`.${file.name}`); +} + /** * Create new file, if file already exists find first unique filename by adding a number to the end of the filename * @param filename diff --git a/src/lang/locale/en.ts b/src/lang/locale/en.ts index 90f3995..897233d 100644 --- a/src/lang/locale/en.ts +++ b/src/lang/locale/en.ts @@ -237,7 +237,7 @@ export default { "When Obsidian is in light mode, Excalidraw will render light mode as well. You may want to switch 'Export image with background' off for a more Obsidian-integrated look and feel.", EMBED_WIDTH_NAME: "Default width of embedded (transcluded) image", EMBED_WIDTH_DESC: - "Only relevant if embed type is excalidraw. Has no effect on PNG and SVG embeds. The default width of an embedded drawing. You can specify a custom " + + "The default width of an embedded drawing. This applies to live preview edit and reading mode, as well as to hover previews. You can specify a custom " + "width when embedding an image using the ![[drawing.excalidraw|100]] or " + "[[drawing.excalidraw|100x100]] format.", EMBED_TYPE_NAME: "Type of file to insert into the document", diff --git a/src/main.ts b/src/main.ts index ff88409..1947ed6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -884,8 +884,15 @@ export default class ExcalidrawPlugin extends Plugin { const view = this.app.workspace.activeLeaf.view; if (view instanceof ExcalidrawView && view.excalidrawAPI) { const st = view.excalidrawAPI.getAppState(); - st.isMobile = !st.isMobile; + st.trayModeEnabled = !st.trayModeEnabled; view.excalidrawAPI.updateScene({appState:st}); + //placed in an async function because I need to load settings first + //just in case settings were updated via sync + (async()=>{ + await this.loadSettings(); + this.settings.defaultTrayMode = st.trayModeEnabled; + this.saveSettings(); + })(); return true; } return false; @@ -1505,8 +1512,19 @@ export default class ExcalidrawPlugin extends Plugin { (template.extension == "md" && !this.settings.compatibilityMode) || (template.extension == "excalidraw" && this.settings.compatibilityMode) ) { - const data = await this.app.vault.read(template); + let data = await this.app.vault.read(template); if (data) { + if(this.settings.matchTheme) { + if(isObsidianThemeDark) { + if((data.match(/"theme"\s*:\s*"light"\s*,/g)||[]).length === 1) { + data = data.replace(/"theme"\s*:\s*"light"\s*,/,`"theme": "dark",`); + } + } else { + if((data.match(/"theme"\s*:\s*"dark"\s*,/g)||[]).length === 1) { + data = data.replace(/"theme"\s*:\s*"dark"\s*,/,`"theme": "light",`); + } + } + } return data; } } diff --git a/src/settings.ts b/src/settings.ts index 5b46364..68bb55f 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -71,6 +71,7 @@ export interface ExcalidrawSettings { mdFontColor: string; mdCSS: string; scriptEngineSettings: {}; + defaultTrayMode: boolean; } export const DEFAULT_SETTINGS: ExcalidrawSettings = { @@ -138,6 +139,7 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = { mdFontColor: "Black", mdCSS: "", scriptEngineSettings: {}, + defaultTrayMode: false, }; const fragWithHTML = (html: string) => diff --git a/tsconfig.json b/tsconfig.json index fba6823..25bf498 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,7 @@ "baseUrl": ".", "inlineSourceMap": true, "inlineSources": true, - "module": "ESNext", + "module": "es2015", "target": "es2017", "allowJs": true, "noImplicitAny": true, diff --git a/versions.json b/versions.json index 295c04f..909ff79 100644 --- a/versions.json +++ b/versions.json @@ -1,4 +1,4 @@ { - "1.6.8": "0.12.16", + "1.6.9": "0.12.16", "1.4.2": "0.11.13" } diff --git a/yarn.lock b/yarn.lock index 464c8c5..273ee59 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2127,10 +2127,10 @@ "resolved" "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" "version" "4.2.2" -"@zsviczian/excalidraw@0.10.0-obsidian-48": - "integrity" "sha512-EC5TKr8uSwgd888xGDF1gjtx23sIjNSLUWs7uHV0dSlIm//xyq2vSmh2nOf9YH5KKP2MxR+LR6U2oF2Qs16WJQ==" - "resolved" "https://registry.npmjs.org/@zsviczian/excalidraw/-/excalidraw-0.10.0-obsidian-48.tgz" - "version" "0.10.0-obsidian-48" +"@zsviczian/excalidraw@0.10.0-obsidian-49": + "integrity" "sha512-32XoMHNyvzWOkkwBMzlS7L6ijabWxCmmA24Pvpn0PUkVQf9dy8OhDDtMHd7NmxD8zglnAXihlAMhTX/l+CLo3A==" + "resolved" "https://registry.npmjs.org/@zsviczian/excalidraw/-/excalidraw-0.10.0-obsidian-49.tgz" + "version" "0.10.0-obsidian-49" dependencies: "dotenv" "10.0.0" @@ -7482,7 +7482,7 @@ dependencies: "glob" "^7.1.3" -"rollup-plugin-terser@^7.0.0": +"rollup-plugin-terser@^7.0.0", "rollup-plugin-terser@^7.0.2": "integrity" "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==" "resolved" "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz" "version" "7.0.2"