diff --git a/TODO.md b/TODO.md index 33fccff..b666370 100644 --- a/TODO.md +++ b/TODO.md @@ -1,13 +1,13 @@ -[ ] do not embed font into SVG when embedding Excalidraw into other Excalidraw +[x] do not embed font into SVG when embedding Excalidraw into other Excalidraw [x] add ```html ... ``` codeblock to excalidraw markdown -[ ] read pre-saved `` when generating image preview +[x] read pre-saved `` when generating image preview [x] update code to adopt change files moving from AppState to App - Add "files" to legacy excalidraw export [x] PNG preview [x] markdown embed SVG 190 [x] markdown embed PNG -[ ] embed Excalidraw into other Excalidraw +[x] embed Excalidraw into other Excalidraw diff --git a/package.json b/package.json index aa5b01f..7f92af3 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "author": "", "license": "MIT", "dependencies": { - "@zsviczian/excalidraw": "0.10.0-obsidian-image-support-3", + "@zsviczian/excalidraw": "0.10.0-obsidian-image-support-4", "monkey-around": "^2.2.0", "react": "^17.0.2", "react-dom": "^17.0.2", diff --git a/src/ExcalidrawAutomate.ts b/src/ExcalidrawAutomate.ts index e463970..6b17bc5 100644 --- a/src/ExcalidrawAutomate.ts +++ b/src/ExcalidrawAutomate.ts @@ -18,7 +18,7 @@ import { VIEW_TYPE_EXCALIDRAW, MAX_IMAGE_SIZE } from "./constants"; -import { embedFontsInSVG, generateSVGString, getObsidianImage, getPNG, getSVG, loadSceneFiles, svgToBase64, wrapText } from "./Utils"; +import { embedFontsInSVG, generateSVGString, getObsidianImage, getPNG, getSVG, loadSceneFiles, scaleLoadedImage, svgToBase64, wrapText } from "./Utils"; import { AppState } from "@zsviczian/excalidraw/types/types"; declare type ConnectionPoint = "top"|"bottom"|"left"|"right"; @@ -828,7 +828,7 @@ async function getTemplate(fileWithPath:string, loadFiles:boolean = false):Promi const file = app.metadataCache.getFirstLinkpathDest(normalizePath(fileWithPath),''); if(file && file instanceof TFile) { const data = (await vault.read(file)).replaceAll("\r\n","\n").replaceAll("\r","\n"); - const excalidrawData:ExcalidrawData = new ExcalidrawData(window.ExcalidrawAutomate.plugin); + let excalidrawData:ExcalidrawData = new ExcalidrawData(window.ExcalidrawAutomate.plugin); if(file.extension === "excalidraw") { await excalidrawData.loadLegacyData(data,file); @@ -852,6 +852,8 @@ async function getTemplate(fileWithPath:string, loadFiles:boolean = false):Promi for(const f of fileArray) { excalidrawData.scene.files[f.id] = f; } + let foo; + [foo,excalidrawData] = scaleLoadedImage(excalidrawData,fileArray); }); } diff --git a/src/ExcalidrawView.ts b/src/ExcalidrawView.ts index 0a7a660..ce1ce75 100644 --- a/src/ExcalidrawView.ts +++ b/src/ExcalidrawView.ts @@ -10,7 +10,7 @@ import { import * as React from "react"; import * as ReactDOM from "react-dom"; import Excalidraw, {exportToSvg, getSceneVersion} from "@zsviczian/excalidraw"; -import { ExcalidrawElement,ExcalidrawTextElement, FileId } from "@zsviczian/excalidraw/types/element/types"; +import { ExcalidrawElement,ExcalidrawImageElement,ExcalidrawTextElement, FileId } from "@zsviczian/excalidraw/types/element/types"; import { AppState, BinaryFileData, @@ -36,9 +36,10 @@ import ExcalidrawPlugin from './main'; import {ExcalidrawAutomate, repositionElementsToCursor} from './ExcalidrawAutomate'; import { t } from "./lang/helpers"; import { ExcalidrawData, REG_LINKINDEX_HYPERLINK, REGEX_LINK } from "./ExcalidrawData"; -import { checkAndCreateFolder, download, embedFontsInSVG, generateSVGString, getNewOrAdjacentLeaf, getNewUniqueFilepath, getObsidianImage, getPNG, getSVG, loadSceneFiles, rotatedDimensions, splitFolderAndFilename, svgToBase64, viewportCoordsToSceneCoords } from "./Utils"; +import { checkAndCreateFolder, download, embedFontsInSVG, generateSVGString, getNewOrAdjacentLeaf, getNewUniqueFilepath, getPNG, getSVG, loadSceneFiles, rotatedDimensions, scaleLoadedImage, splitFolderAndFilename, svgToBase64, viewportCoordsToSceneCoords } from "./Utils"; import { Prompt } from "./Prompt"; import { ClipboardData } from "@zsviczian/excalidraw/types/clipboard"; +import { ifStatement } from "@babel/types"; declare let window: ExcalidrawAutomate; @@ -446,7 +447,7 @@ export default class ExcalidrawView extends TextFileView { if((this.app.workspace.activeLeaf === this.leaf) && this.excalidrawWrapperRef) { this.excalidrawWrapperRef.current.focus(); } - loadSceneFiles(this.app,this.excalidrawData.files,this.excalidrawAPI.addFiles); + loadSceneFiles(this.app,this.excalidrawData.files,(files:any)=>this.addFiles(files)); } else { this.instantiateExcalidraw({ elements: excalidrawData.elements, @@ -458,6 +459,21 @@ export default class ExcalidrawView extends TextFileView { } } + private addFiles(files:any) { + if(files.length === 0) return; + const [dirty, scene] = scaleLoadedImage(this.getScene(),files); + + if(dirty) { + this.excalidrawAPI.updateScene({ + elements: scene.elements, + appState: scene.appState, + commitToHistory: false, + }); + } + + this.excalidrawAPI.addFiles(files); + } + //Compatibility mode with .excalidraw files canAcceptExtension(extension: string) { return extension == "excalidraw"; @@ -633,7 +649,7 @@ export default class ExcalidrawView extends TextFileView { React.useEffect(() => { excalidrawRef.current.readyPromise.then((api) => { this.excalidrawAPI = api; - loadSceneFiles(this.app,this.excalidrawData.files,this.excalidrawAPI.addFiles); + loadSceneFiles(this.app,this.excalidrawData.files,(files:any)=>this.addFiles(files)); }); }, [excalidrawRef]); @@ -821,7 +837,7 @@ export default class ExcalidrawView extends TextFileView { return x<=pointer.x && x+w>=pointer.x && y<=pointer.y && y+h>=pointer.y; }); - if(elements.length==0) return null; + if(elements.length==0) return {id:null, text:null}; if(elements.length===1) return {id:elements[0].id,text:elements[0].text}; //if more than 1 text elements are at the location, look for one that has a link const elementsWithLinks = elements.filter((e:ExcalidrawTextElement)=> { @@ -848,8 +864,8 @@ export default class ExcalidrawView extends TextFileView { return x<=pointer.x && x+w>=pointer.x && y<=pointer.y && y+h>=pointer.y; }); - if(elements.length==0) return null; - if(elements.length>1) return {id:elements[0].id,fileId:elements[0].fileId}; + if(elements.length===0) return {id:null, fileId:null}; + if(elements.length>=1) return {id:elements[0].id,fileId:elements[0].fileId}; //if more than 1 image elements are at the location, return the first } @@ -885,13 +901,13 @@ export default class ExcalidrawView extends TextFileView { let viewModeEnabled = false; const handleLinkClick = () => { selectedTextElement = getTextElementAtPointer(currentPosition); - if(selectedTextElement) { + if(selectedTextElement && selectedTextElement.id) { const event = new MouseEvent("click", {ctrlKey: true, shiftKey: this.shiftKeyDown, altKey:this.altKeyDown}); this.handleLinkClick(this,event); selectedTextElement = null; } selectedImageElement = getImageElementAtPointer(currentPosition); - if(selectedImageElement) { + if(selectedImageElement && selectedImageElement.id) { const event = new MouseEvent("click", {ctrlKey: true, shiftKey: this.shiftKeyDown, altKey:this.altKeyDown}); this.handleLinkClick(this,event); selectedImageElement = null; diff --git a/src/Utils.ts b/src/Utils.ts index 262c9c2..8bd4865 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -376,7 +376,9 @@ export const loadSceneFiles = async (app:App, filesMap: Map,addF mimeType : data.mimeType, id: entry.value[0], dataURL: data.dataURL, - created: data.created + created: data.created, + //@ts-ignore + size: data.size, }); } } @@ -386,4 +388,29 @@ export const loadSceneFiles = async (app:App, filesMap: Map,addF } catch(e) { } +} + +export const scaleLoadedImage = (scene:any, files:any):[boolean,any] => { + let dirty = false; + for(const f of files) { + const [w_image,h_image] = [f.size.width,f.size.height]; + const imageAspectRatio = f.size.width/f.size.height; + scene + .elements + .filter((e:any)=>(e.type === "image" && e.fileId === f.id)) + .forEach((el:any)=>{ + const [w_old,h_old] = [el.width,el.height]; + const elementAspectRatio = w_old/h_old; + if(imageAspectRatio != elementAspectRatio) { + dirty = true; + const h_new = Math.sqrt(w_old*h_old*h_image/w_image); + const w_new = Math.sqrt(w_old*h_old*w_image/h_image); + el.height = h_new; + el.width = w_new; + el.y += (h_old-h_new)/2; + el.x += (w_old-w_new)/2; + } + }); + return [dirty,scene]; + } } \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index ff4c69f..e8d5c37 100644 --- a/src/main.ts +++ b/src/main.ts @@ -110,7 +110,6 @@ export default class ExcalidrawPlugin extends Plugin { //inspiration taken from kanban: //https://github.com/mgmeyers/obsidian-kanban/blob/44118e25661bff9ebfe54f71ae33805dc88ffa53/src/main.ts#L267 this.registerMonkeyPatches(); - new Notice("Excalidraw was updated. Files opened with this version will not open with the older version. Please update plugin on all your devices.\n\nI will remove this message with next update.",8000); if(this.settings.loadCount<1) this.migrationNotice(); const electron:string = process.versions.electron; if(electron.startsWith("8.")) { diff --git a/yarn.lock b/yarn.lock index 30714be..1ed7b6b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1067,10 +1067,10 @@ dependencies: "@types/estree" "*" -"@zsviczian/excalidraw@0.10.0-obsidian-image-support-3": - "integrity" "sha512-hxTFoc10mljFkHA9q/zbr9ftCpBxnjMl42B6RsBOSVKzO/IHABBGq969bqzLX8LnYl94ugtFN0NPnnF4SS3qzA==" - "resolved" "https://registry.npmjs.org/@zsviczian/excalidraw/-/excalidraw-0.10.0-obsidian-image-support-3.tgz" - "version" "0.10.0-obsidian-image-support-3" +"@zsviczian/excalidraw@0.10.0-obsidian-image-support-4": + "integrity" "sha512-xDRS5xK/8o1GVZtGkFkaq9Y9H3l+UQIyaGHtUgG7zc4d9iUNCf9OtAszMiufRAD8NMKdRuuRwNuPrBxFbm+CkQ==" + "resolved" "https://registry.npmjs.org/@zsviczian/excalidraw/-/excalidraw-0.10.0-obsidian-image-support-4.tgz" + "version" "0.10.0-obsidian-image-support-4" "abab@^1.0.3": "integrity" "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4="