Compare commits

..

2 Commits
2.2.0 ... 2.2.2

Author SHA1 Message Date
zsviczian
ff1d7b44b4 2.2.2 2024-05-20 12:25:53 +02:00
zsviczian
2b86ba2128 2.2.1 2024-05-20 09:37:14 +02:00
10 changed files with 93 additions and 22 deletions

View File

@@ -1,7 +1,7 @@
{
"id": "obsidian-excalidraw-plugin",
"name": "Excalidraw",
"version": "2.2.0",
"version": "2.2.2",
"minAppVersion": "1.1.6",
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
"author": "Zsolt Viczian",

View File

@@ -19,7 +19,7 @@
"license": "MIT",
"dependencies": {
"@popperjs/core": "^2.11.8",
"@zsviczian/excalidraw": "0.17.1-obsidian-22",
"@zsviczian/excalidraw": "0.17.1-obsidian-23",
"chroma-js": "^2.4.2",
"clsx": "^2.0.0",
"colormaster": "^1.2.1",

View File

@@ -361,7 +361,7 @@ export class EmbeddedFilesLoader {
isMask,
};
const shouldUseCache = file && imageCache.isReady();
const shouldUseCache = this.plugin.settings.allowImageCacheInScene && file && imageCache.isReady();
const cacheKey:ImageKey = {
filepath: file.path,
blockref: null,
@@ -380,7 +380,9 @@ export class EmbeddedFilesLoader {
linkpartAlias: null,
}
const maybeSVG = await imageCache.getImageFromCache(cacheKey);
const maybeSVG = shouldUseCache
? await imageCache.getImageFromCache(cacheKey)
: undefined;
const svg = (maybeSVG && (maybeSVG instanceof SVGSVGElement))
? maybeSVG

View File

@@ -262,7 +262,7 @@ const RE_TEXTELEMENTS_FALLBACK_1 = new RegExp(`(.*)%%\n##? Text Elements(?:\n|$)
const RE_TEXTELEMENTS_FALLBACK_2 = new RegExp(`(.*)##? Text Elements(?:\n|$)`, "m");
const RE_DRAWING = new RegExp(`(%%\n)?##? Drawing\n`);
const RE_DRAWING = new RegExp(`^(%%\n)?##? Drawing\n`, "m");
export const getExcalidrawMarkdownHeaderSection = (data:string, keys?:[string,string][]):string => {
//The base case scenario is at the top, continued with fallbacks in order of likelihood and file structure
@@ -274,6 +274,13 @@ export const getExcalidrawMarkdownHeaderSection = (data:string, keys?:[string,st
%%
# Excalidraw Data
*/
//trimming the json because in legacy excalidraw files the JSON was a single string resulting in very slow regexp parsing
const drawingTrimLocation = data.search(RE_DRAWING);
if(drawingTrimLocation>0) {
data = data.substring(0, drawingTrimLocation);
}
let trimLocation = data.search(RE_EXCALIDRAWDATA_WITHSECTION_OK);
let shouldFixTrailingHashtag = false;
if(trimLocation > 0) {
@@ -386,7 +393,9 @@ export const getExcalidrawMarkdownHeaderSection = (data:string, keys?:[string,st
# Drawing
*/
if (trimLocation === -1) {
trimLocation = data.search(RE_DRAWING);
if (drawingTrimLocation > 0) {
trimLocation = drawingTrimLocation;
}
}
if (trimLocation === -1) {
return data.endsWith("\n") ? data : (data + "\n");
@@ -515,6 +524,18 @@ export class ExcalidrawData {
if (el.fontSize === null) {
el.fontSize = 20;
}
if (el.type === "text" && !el.hasOwnProperty("autoResize")) {
el.autoResize = true;
}
if (el.type === "text" && !el.hasOwnProperty("lineHeight")) {
el.lineHeight = getDefaultLineHeight(el.fontFamily);
}
if (el.type === "image" && !el.hasOwnProperty("roundness")) {
el.roundness = null;
}
}
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/569
@@ -952,7 +973,7 @@ export class ExcalidrawData {
//update text in scene based on textElements Map
//first get scene text elements
const elementsMap = arrayToMap(this.scene.elements);
const texts = this.scene.elements?.filter((el: any) => el.type === "text") as Mutable<ExcalidrawTextElement>[];
const texts = this.scene.elements?.filter((el: any) => el.type === "text" && !el.isDeleted) as Mutable<ExcalidrawTextElement>[];
for (const te of texts) {
const container = getContainerElement(te, elementsMap);
const originalText =

View File

@@ -1309,7 +1309,11 @@ export default class ExcalidrawView extends TextFileView {
this.app.workspace.onLayoutReady(async () => {
debug(`ExcalidrawView.onload app.workspace.onLayoutReady, file: ${self.file?.name}, isActiveLeaf: ${self.app.workspace.activeLeaf === self.leaf}, is activeExcalidrawView set: ${Boolean(self.plugin.activeExcalidrawView)}`);
//implemented to overcome issue that activeLeafChangeEventHandler is not called when view is initialized from a saved workspace, since Obsidian 1.6.0
if (self.app.workspace.activeLeaf === self.leaf) {
let counter = 0;
while(counter++<50 && !Boolean(self.plugin.activeLeafChangeEventHandler)) {
await(sleep(50));
}
if (Boolean(self.plugin.activeLeafChangeEventHandler) && (self.app.workspace.activeLeaf === self.leaf)) {
self.plugin.activeLeafChangeEventHandler(self.leaf);
}
self.canvasNodeFactory.initialize();
@@ -2318,17 +2322,25 @@ export default class ExcalidrawView extends TextFileView {
}
}
public initializeToolsIconPanelAfterLoading() {
public async initializeToolsIconPanelAfterLoading() {
if(this.semaphores.viewunload) return;
const api = this.excalidrawAPI;
if (!api) {
return;
}
const st = api.getAppState();
//since Obsidian 1.6.0 onLayoutReady calls happen asynchronously compared to starting Excalidraw view
//these validations are just to make sure that initialization is complete
let counter = 0;
while(!this.plugin.scriptEngine && counter++<50) {
sleep(50);
}
const panel = this.toolsPanelRef?.current;
if (!panel) {
if (!panel || !this.plugin.scriptEngine) {
return;
}
panel.setTheme(st.theme);
panel.setExcalidrawViewMode(st.viewModeEnabled);
panel.setPreviewMode(
@@ -2817,7 +2829,7 @@ export default class ExcalidrawView extends TextFileView {
//@ts-ignore
textElement.link = link;
}
if (this.textMode == TextMode.parsed) {
if (this.textMode === TextMode.parsed && !textElement?.isDeleted) {
const {text, x, y, width, height} = refreshTextDimensions(
textElement,null,elementsMap,parseResult
);
@@ -4021,14 +4033,16 @@ export default class ExcalidrawView extends TextFileView {
if(el.length === 1) {
const container = getContainerElement(el[0],elementsMap);
const clone = cloneElement(el[0]);
const {text, x, y, width, height} = refreshTextDimensions(el[0], container, elementsMap, parsedText);
if(!el[0]?.isDeleted) {
const {text, x, y, width, height} = refreshTextDimensions(el[0], container, elementsMap, parsedText);
clone.x = x;
clone.y = y;
clone.width = width;
clone.height = height;
clone.originalText = parsedText;
clone.text = text;
clone.x = x;
clone.y = y;
clone.width = width;
clone.height = height;
clone.originalText = parsedText;
clone.text = text;
}
elements[elements.indexOf(el[0])] = clone;
this.updateScene({elements});

View File

@@ -17,6 +17,19 @@ I develop this plugin as a hobby, spending my free time doing this. If you find
<div class="ex-coffee-div"><a href="https://ko-fi.com/zsolt"><img src="https://cdn.ko-fi.com/cdn/kofi3.png?v=3" height=45></a></div>
`,
"2.2.2":`
## Fixed
- ExcaliBrain stopped working with 2.2.0
![I apologize](https://github.com/zsviczian/obsidian-excalidraw-plugin/assets/14358394/3b05aa28-788d-4329-9721-798ad58a6ca2)
`,
"2.2.1":`
## Fixed
- Text height becomes unreadable after 2.2.0 update [#1784](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1784)
- Images are loaded with a rounded border when loading old Excalidraw files
- Embedded Excalidraw images cache gets stuck with old version of the image
- Extremely long loading times with legacy (3+ years old) Excalidraw files
`,
"2.2.0":`
<div class="excalidraw-videoWrapper"><div>
<iframe src="https://www.youtube.com/embed/dV0NEOwn5NM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

View File

@@ -489,6 +489,10 @@ FILENAME_HEAD: "Filename",
EMBED_IMAGE_CACHE_NAME: "Cache images for embedding in markdown",
EMBED_IMAGE_CACHE_DESC: "Cache images for embedding in markdown. This will speed up the embedding process, but in case you compose images of several sub-component drawings, " +
"the embedded image in Markdown won't update until you open the drawing and save it to trigger an update of the cache.",
SCENE_IMAGE_CACHE_NAME: "Cache nested Excalidraws in Scene",
SCENE_IMAGE_CACHE_DESC: "Cache nested Excalidraws in the Scene for faster scene rendering. This will speed up the rendering process, especially if you have deeply nested Excalidraws in your scene. " +
"Excalidraw will try to intelligently identify if any children of a nested Excalidraw have changed and will update the cache accordingly. " +
"You may want to turn this off, in case you are suspecting that the cache is not updating properly.",
EMBED_IMAGE_CACHE_CLEAR: "Purge Cache",
BACKUP_CACHE_CLEAR: "Purge Backups",
BACKUP_CACHE_CLEAR_CONFIRMATION: "This action will delete all Excalidraw drawing backups. Backups are used as a safety measure in case your drawing file gets damaged. Each time you open Obsidian the plugin automatically deletes backups for files that no longer exist in your Vault. Are you sure you want to clear all backups?",

View File

@@ -2964,10 +2964,10 @@ export default class ExcalidrawPlugin extends Plugin {
const excalidrawLeaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
excalidrawLeaves.forEach(async (leaf) => {
const ev: ExcalidrawView = leaf.view as ExcalidrawView;
console.log(ev.file.name, ev.semaphores.dirty);
//console.log(ev.file.name, ev.semaphores.dirty);
await this.setMarkdownView(leaf);
//@ts-ignore
console.log(leaf?.view?.file);
//console.log(leaf?.view?.file);
});
document.body.removeChild(this.textMeasureDiv);

View File

@@ -61,6 +61,7 @@ export interface ExcalidrawSettings {
displaySVGInPreview: boolean; //No longer used since 1.9.13
previewImageType: PreviewImageType; //Introduced with 1.9.13
allowImageCache: boolean;
allowImageCacheInScene: boolean;
displayExportedImageIfAvailable: boolean;
previewMatchObsidianTheme: boolean;
width: string;
@@ -220,6 +221,7 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
displaySVGInPreview: undefined,
previewImageType: undefined,
allowImageCache: true,
allowImageCacheInScene: true,
displayExportedImageIfAvailable: false,
previewMatchObsidianTheme: false,
width: "400",
@@ -1720,6 +1722,19 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
this.applySettingsUpdate();
})
)
new Setting(detailsEl)
.setName(t("SCENE_IMAGE_CACHE_NAME"))
.setDesc(fragWithHTML(t("SCENE_IMAGE_CACHE_DESC")))
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.allowImageCacheInScene)
.onChange((value) => {
this.plugin.settings.allowImageCacheInScene = value;
this.applySettingsUpdate();
})
)
new Setting(detailsEl)
.setName(t("EMBED_IMAGE_CACHE_CLEAR"))
.addButton((button) =>
button
.setButtonText(t("EMBED_IMAGE_CACHE_CLEAR"))
@@ -1727,6 +1742,8 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
imageCache.clearImageCache();
})
)
new Setting(detailsEl)
.setName(t("BACKUP_CACHE_CLEAR"))
.addButton((button) =>
button
.setButtonText(t("BACKUP_CACHE_CLEAR"))

View File

@@ -156,7 +156,7 @@ class ImageCache {
const filepath = key.split("#")[0];
const fileExists = files.some((f: TFile) => f.path === filepath);
const file = fileExists ? files.find((f: TFile) => f.path === filepath) : null;
if (isLegacyKey || !file || (file && file.stat.mtime > cursor.value.mtime) || (!cursor.value.blob && !cursor.value.svg)) {
if (isLegacyKey || !file || (file && (file.stat.mtime > cursor.value.mtime)) || (!cursor.value.blob && !cursor.value.svg)) {
deletePromises.push(
new Promise<void>((innerResolve, innerReject) => {
const deleteRequest = store.delete(cursor.primaryKey);
@@ -293,7 +293,7 @@ class ImageCache {
const file = this.app.vault.getAbstractFileByPath(key_.filepath.split("#")[0]);
if (!file || !(file instanceof TFile)) return undefined;
if (cachedData && cachedData.mtime >= file.stat.mtime) {
if (cachedData && (cachedData.mtime >= file.stat.mtime)) {
if(hasExcalidrawEmbeddedImagesTreeChanged(file, cachedData.mtime, this.plugin)) {
return undefined;
}