feat(excalidraw): support .excalidraw.md (Obsidian plugin format) with lz-string decompression
CI / lint (push) Failing after 14s
CI / test (push) Has been skipped
CI / build (push) Has been skipped
CI / e2e (push) Has been skipped
CI / security (push) Successful in 13s
Desktop Build / build-windows (push) Has been cancelled
Desktop Build / build-linux (push) Has been cancelled

This commit is contained in:
2026-07-29 16:08:03 -04:00
parent a4ea322c75
commit 9804cf9a6d
5 changed files with 55 additions and 11 deletions
+20 -5
View File
@@ -107,6 +107,7 @@
<script type="module">
import React from "react";
import ReactDOM from "react-dom";
import { decompressFromBase64 } from "https://esm.sh/[email protected]";
import * as ExcalidrawLib from "https://esm.sh/@excalidraw/[email protected]?alias=react:[email protected],react-dom:[email protected]";
window.React = React;
@@ -223,11 +224,25 @@
switch (msg.type) {
case "init":
if (msg.data) {
const initialData = {
elements: msg.data.elements || [],
appState: msg.data.appState || {},
files: msg.data.files || {},
};
let elements, appState, files;
// Handle compressed .excalidraw.md format
if (msg.data.compressed) {
try {
const decompressed = decompressFromBase64(msg.data.compressed);
const parsed = JSON.parse(decompressed);
elements = parsed.elements || [];
appState = parsed.appState || {};
files = parsed.files || {};
} catch(e) {
console.error("Failed to decompress Excalidraw data:", e);
elements = []; appState = {}; files = {};
}
} else {
elements = msg.data.elements || [];
appState = msg.data.appState || {};
files = msg.data.files || {};
}
const initialData = { elements, appState, files };
currentTheme = msg.theme || "light";
setTheme(currentTheme);
+6 -5
View File
@@ -75,13 +75,14 @@ export function renderExcalidraw(container, data, vaultName, filePath, opts = {}
case 'ready':
// Iframe is mounted — send initial data
editorState.ready = true;
// Support both pure .excalidraw and compressed .excalidraw.md
const initData = data.excalidraw_data || {};
if (data.excalidraw_data_compressed) {
initData.compressed = data.excalidraw_data_compressed;
}
iframe.contentWindow.postMessage({
type: 'init',
data: data.excalidraw_data || {
elements: [],
appState: { viewBackgroundColor: '#ffffff' },
files: {},
},
data: initData,
theme: theme,
}, '*');
break;
+5
View File
@@ -80,6 +80,7 @@ const EXT_ICONS = {
".csv": "table",
".tsv": "table",
".excalidraw": "pen-tool",
".excalidraw.md": "pen-tool",
".sql": "database",
".db": "database",
".sqlite": "database",
@@ -206,6 +207,10 @@ const EXT_ICONS = {
};
function getFileIcon(name) {
const lower = name.toLowerCase();
// Check for double extensions first (e.g., .excalidraw.md)
if (lower.endsWith(".excalidraw.md")) return EXT_ICONS[".excalidraw.md"] || "pen-tool";
if (lower.endsWith(".md.excalidraw")) return EXT_ICONS[".excalidraw"] || "pen-tool";
const ext = "." + name.split(".").pop().toLowerCase();
return EXT_ICONS[ext] || "file";
}