Compare commits

...

2 Commits

Author SHA1 Message Date
zsviczian
ee9364b645 2.6.0-beta-4 2024-10-26 14:41:10 +02:00
zsviczian
5bbe66900e 2.6.0-beta-3 2024-10-26 13:53:08 +02:00
9 changed files with 177 additions and 66 deletions

View File

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

View File

@@ -8,6 +8,7 @@ import fs from 'fs';
import LZString from 'lz-string';
import postprocess from '@zsviczian/rollup-plugin-postprocess';
import cssnano from 'cssnano';
import jsesc from 'jsesc';
// Load environment variables
import dotenv from 'dotenv';
@@ -52,11 +53,13 @@ if (!isLib) console.log(manifest.version);
const packageString = isLib
? ""
: ';' + lzstring_pkg +
'\nlet EXCALIDRAW_PACKAGES = LZString.decompressFromBase64("' + LZString.compressToBase64(react_pkg + reactdom_pkg + excalidraw_pkg) + '");\n' +
'let {react, reactDOM, excalidrawLib} = window.eval.call(window, `(function() {' +
'${EXCALIDRAW_PACKAGES};' +
'return {react: React, reactDOM: ReactDOM, excalidrawLib: ExcalidrawLib};})();`);\n' +
'let PLUGIN_VERSION="' + manifest.version + '";';
'\nlet REACT_PACKAGES = `' +
jsesc(react_pkg + reactdom_pkg, { quotes: 'backtick' }) +
'`;\n' +
'let EXCALIDRAW_PACKAGE = ""; const unpackExcalidraw = () => {EXCALIDRAW_PACKAGE = LZString.decompressFromBase64("' + LZString.compressToBase64(excalidraw_pkg) + '");};\n' +
'let {react, reactDOM } = window.eval.call(window, `(function() {' + '${REACT_PACKAGES};' + 'return {react: React, reactDOM: ReactDOM};})();`);\n' +
`let excalidrawLib = {};\n` +
'let PLUGIN_VERSION="' + manifest.version + '";';
const BASE_CONFIG = {
input: 'src/main.ts',

View File

@@ -754,7 +754,7 @@ export class ExcalidrawData {
notice.noticeEl.oncontextmenu = () => {
displayFontMessage(this.app);
}
},2000);
},5000);
await loadSceneFonts(this.scene.elements);
clearTimeout(timer);

View File

@@ -1575,6 +1575,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
if(!this.plugin) {
return;
}
await this.plugin.awaitInit();
//implemented to overcome issue that activeLeafChangeEventHandler is not called when view is initialized from a saved workspace, since Obsidian 1.6.0
let counter = 0;
while(counter++<50 && (!Boolean(this?.plugin?.activeLeafChangeEventHandler) || !Boolean(this.canvasNodeFactory))) {
@@ -2245,6 +2246,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
//I am using last loaded file to control when the view reloads.
//It seems text file view gets the modified file event after sync before the modifyEventHandler in main.ts
//reload can only be triggered via reload()
await this.plugin.awaitInit();
if(this.lastLoadedFile === this.file) return;
this.isLoaded = false;
if(!this.file) return;
@@ -2275,6 +2277,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
if(!this?.app) {
return;
}
await this.plugin.awaitInit();
let counter = 0;
while ((!this.file || !this.plugin.fourthFontLoaded) && counter++<50) await sleep(50);
if(!this.file) return;
@@ -5875,6 +5878,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
}
) {
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.instantiateExcalidraw, "ExcalidrawView.instantiateExcalidraw", initdata);
await this.plugin.awaitInit();
while(!this.semaphores.scriptsReady) {
await sleep(50);
}

View File

@@ -353,7 +353,8 @@ const getIMG = async (
);
const cacheReady = imageCache.isReady();
await plugin.awaitInit();
switch (plugin.settings.previewImageType) {
case PreviewImageType.PNG: {
const img = createEl("img");

View File

@@ -82,7 +82,7 @@ export const obsidianToExcalidrawMap: { [key: string]: string } = {
};
export const {
export let {
sceneCoordsToViewportCoords,
viewportCoordsToSceneCoords,
determineFocusDistance,
@@ -106,6 +106,32 @@ export const {
loadSceneFonts,
} = excalidrawLib;
export function updateExcalidrawLib() {
({
sceneCoordsToViewportCoords,
viewportCoordsToSceneCoords,
determineFocusDistance,
intersectElementWithLine,
getCommonBoundingBox,
getMaximumGroups,
measureText,
getLineHeight,
wrapText,
getFontString,
getBoundTextMaxWidth,
exportToSvg,
exportToBlob,
mutateElement,
restore,
mermaidToExcalidraw,
getFontFamilyString,
getContainerElement,
refreshTextDimensions,
getCSSFontDefinition,
loadSceneFonts,
} = excalidrawLib);
}
export const FONTS_STYLE_ID = "excalidraw-custom-fonts";
export const CJK_STYLE_ID = "excalidraw-cjk-fonts";

View File

@@ -0,0 +1,44 @@
import { FileView, TextFileView, View, WorkspaceLeaf } from "obsidian";
import ExcalidrawPlugin from "src/main";
import { setExcalidrawView } from "src/utils/ObsidianUtils";
export default class ExcalidrawLoading extends FileView {
constructor(leaf: WorkspaceLeaf, private plugin: ExcalidrawPlugin) {
super(leaf);
this.switchToeExcalidraw();
this.displayLoadingText();
}
public onload() {
super.onload();
this.displayLoadingText();
}
private async switchToeExcalidraw() {
await this.plugin.awaitInit();
setExcalidrawView(this.leaf);
}
getViewType(): string {
return "excalidra-loading";
}
getDisplayText() {
return "Loading Excalidraw... " + (this.file?.basename ?? "");
}
private displayLoadingText() {
// Create a div element for displaying the text
const loadingTextEl = this.contentEl.createEl("div", {
text: this.getDisplayText()
});
// Apply styling to center the text
loadingTextEl.style.display = "flex";
loadingTextEl.style.alignItems = "center";
loadingTextEl.style.justifyContent = "center";
loadingTextEl.style.height = "100%";
loadingTextEl.style.fontSize = "1.5em"; // Adjust size as needed
}
}

View File

@@ -46,6 +46,7 @@ import {
sceneCoordsToViewportCoords,
FONTS_STYLE_ID,
CJK_STYLE_ID,
updateExcalidrawLib,
} from "./constants/constants";
import ExcalidrawView, { TextMode, getTextMode } from "./ExcalidrawView";
import {
@@ -142,8 +143,11 @@ import { RankMessage } from "./dialogs/RankMessage";
import { initCompressionWorker, terminateCompressionWorker } from "./workers/compression-worker";
import { WeakArray } from "./utils/WeakArray";
import { getCJKDataURLs } from "./utils/CJKLoader";
import ExcalidrawLoading from "./dialogs/ExcalidrawLoading";
declare let EXCALIDRAW_PACKAGES:string;
declare let EXCALIDRAW_PACKAGE:string;
declare let REACT_PACKAGES:string;
declare const unpackExcalidraw: Function;
declare let react:any;
declare let reactDOM:any;
declare let excalidrawLib: typeof ExcalidrawLib;
@@ -196,6 +200,7 @@ export default class ExcalidrawPlugin extends Plugin {
private ribbonIcon:HTMLElement;
public loadTimestamp:number;
private isLocalCJKFontAvailabe:boolean = undefined
public isReady = false;
constructor(app: App, manifest: PluginManifest) {
super(app, manifest);
@@ -270,7 +275,7 @@ export default class ExcalidrawPlugin extends Plugin {
//@ts-ignore
const {react:r, reactDOM:rd, excalidrawLib:e} = win.eval.call(win,
`(function() {
${EXCALIDRAW_PACKAGES};
${REACT_PACKAGES + EXCALIDRAW_PACKAGE};
return {react:React,reactDOM:ReactDOM,excalidrawLib:ExcalidrawLib};
})()`);
this.packageMap.set(win,{react:r, reactDOM:rd, excalidrawLib:e});
@@ -345,11 +350,18 @@ export default class ExcalidrawPlugin extends Plugin {
}
async onload() {
initCompressionWorker();
this.loadTimestamp = Date.now();
addIcon(ICON_NAME, EXCALIDRAW_ICON);
addIcon(SCRIPTENGINE_ICON_NAME, SCRIPTENGINE_ICON);
addIcon(EXPORT_IMG_ICON_NAME, EXPORT_IMG_ICON);
this.registerView(
VIEW_TYPE_EXCALIDRAW,
(leaf: WorkspaceLeaf) => {
if(this.isReady) {
return new ExcalidrawView(leaf, this);
} else {
return new ExcalidrawLoading(leaf, this);
}
},
);
//Compatibility mode with .excalidraw files
this.registerExtensions(["excalidraw"], VIEW_TYPE_EXCALIDRAW);
await this.loadSettings({reEnableAutosave:true});
const updateSettings = !this.settings.onceOffCompressFlagReset || !this.settings.onceOffGPTVersionReset;
@@ -365,68 +377,83 @@ export default class ExcalidrawPlugin extends Plugin {
if(updateSettings) {
await this.saveSettings();
}
this.excalidrawConfig = new ExcalidrawConfig(this);
await loadMermaid();
this.editorHandler = new EditorHandler(this);
this.editorHandler.setup();
this.addSettingTab(new ExcalidrawSettingTab(this.app, this));
this.ea = await initExcalidrawAutomate(this);
this.registerView(
VIEW_TYPE_EXCALIDRAW,
(leaf: WorkspaceLeaf) => new ExcalidrawView(leaf, this),
);
//Compatibility mode with .excalidraw files
this.registerExtensions(["excalidraw"], VIEW_TYPE_EXCALIDRAW);
this.addMarkdownPostProcessor();
this.registerInstallCodeblockProcessor();
this.addThemeObserver();
this.experimentalFileTypeDisplayToggle(this.settings.experimentalFileType);
this.registerCommands();
this.registerEventListeners();
this.runStartupScript();
this.initializeFonts();
this.registerEditorSuggest(new FieldSuggester(this));
this.setPropertyTypes();
this.app.workspace.onLayoutReady(async () => {
unpackExcalidraw();
excalidrawLib = window.eval.call(window,`(function() {${EXCALIDRAW_PACKAGE};return ExcalidrawLib;})()`);
this.packageMap.set(window,{react, reactDOM, excalidrawLib});
updateExcalidrawLib();
initCompressionWorker();
this.loadTimestamp = Date.now();
addIcon(ICON_NAME, EXCALIDRAW_ICON);
addIcon(SCRIPTENGINE_ICON_NAME, SCRIPTENGINE_ICON);
addIcon(EXPORT_IMG_ICON_NAME, EXPORT_IMG_ICON);
//inspiration taken from kanban:
//https://github.com/mgmeyers/obsidian-kanban/blob/44118e25661bff9ebfe54f71ae33805dc88ffa53/src/main.ts#L267
this.registerMonkeyPatches();
this.excalidrawConfig = new ExcalidrawConfig(this);
await loadMermaid();
this.editorHandler = new EditorHandler(this);
this.editorHandler.setup();
this.registerInstallCodeblockProcessor();
this.addThemeObserver();
this.experimentalFileTypeDisplayToggle(this.settings.experimentalFileType);
this.registerCommands();
this.registerEventListeners();
this.runStartupScript();
this.initializeFonts();
this.registerEditorSuggest(new FieldSuggester(this));
this.setPropertyTypes();
this.stylesManager = new StylesManager(this);
//inspiration taken from kanban:
//https://github.com/mgmeyers/obsidian-kanban/blob/44118e25661bff9ebfe54f71ae33805dc88ffa53/src/main.ts#L267
this.registerMonkeyPatches();
// const patches = new OneOffs(this);
if (this.settings.showReleaseNotes) {
//I am repurposing imageElementNotice, if the value is true, this means the plugin was just newly installed to Obsidian.
const obsidianJustInstalled = this.settings.previousRelease === "0.0.0"
this.stylesManager = new StylesManager(this);
if (isVersionNewerThanOther(PLUGIN_VERSION, this.settings.previousRelease)) {
new ReleaseNotes(
this.app,
this,
obsidianJustInstalled ? null : PLUGIN_VERSION,
).open();
// const patches = new OneOffs(this);
if (this.settings.showReleaseNotes) {
//I am repurposing imageElementNotice, if the value is true, this means the plugin was just newly installed to Obsidian.
const obsidianJustInstalled = this.settings.previousRelease === "0.0.0"
if (isVersionNewerThanOther(PLUGIN_VERSION, this.settings.previousRelease)) {
new ReleaseNotes(
this.app,
this,
obsidianJustInstalled ? null : PLUGIN_VERSION,
).open();
}
}
}
this.switchToExcalidarwAfterLoad();
this.switchToExcalidarwAfterLoad();
this.app.workspace.onLayoutReady(() => {
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.onload,"ExcalidrawPlugin.onload > app.workspace.onLayoutReady");
this.scriptEngine = new ScriptEngine(this);
imageCache.initializeDB(this);
this.taskbone = new Taskbone(this);
this.isReady = true;
this.app.workspace.onLayoutReady(() => {
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.onload,"ExcalidrawPlugin.onload > app.workspace.onLayoutReady");
this.scriptEngine = new ScriptEngine(this);
imageCache.initializeDB(this);
});
});
this.taskbone = new Taskbone(this);
}
public async awaitInit() {
let counter = 0;
while(!this.isReady && counter < 150) {
await sleep(50);
}
}
private setPropertyTypes() {
if(!this.settings.loadPropertySuggestions) return;
const app = this.app;
this.app.workspace.onLayoutReady(() => {
this.app.workspace.onLayoutReady(async () => {
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.setPropertyTypes, `ExcalidrawPlugin.setPropertyTypes > app.workspace.onLayoutReady`);
await this.awaitInit();
Object.keys(FRONTMATTER_KEYS).forEach((key) => {
if(FRONTMATTER_KEYS[key].depricated === true) return;
const {name, type} = FRONTMATTER_KEYS[key];
@@ -438,7 +465,7 @@ export default class ExcalidrawPlugin extends Plugin {
public initializeFonts() {
this.app.workspace.onLayoutReady(async () => {
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.initializeFonts, `ExcalidrawPlugin.initializeFonts > app.workspace.onLayoutReady`);
await this.awaitInit();
const cjkFontDataURLs = await getCJKDataURLs(this);
if(typeof cjkFontDataURLs === "boolean" && !cjkFontDataURLs) {
new Notice(t("FONTS_LOAD_ERROR") + this.settings.fontAssetsPath,6000);
@@ -534,8 +561,9 @@ export default class ExcalidrawPlugin extends Plugin {
}
private switchToExcalidarwAfterLoad() {
this.app.workspace.onLayoutReady(() => {
this.app.workspace.onLayoutReady(async () => {
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.switchToExcalidarwAfterLoad, `ExcalidrawPlugin.switchToExcalidarwAfterLoad > app.workspace.onLayoutReady`);
await this.awaitInit();
let leaf: WorkspaceLeaf;
for (leaf of this.app.workspace.getLeavesOfType("markdown")) {
if ( leaf.view instanceof MarkdownView && this.isExcalidrawFile(leaf.view.file)) {
@@ -767,9 +795,9 @@ export default class ExcalidrawPlugin extends Plugin {
initializeMarkdownPostProcessor(this);
this.registerMarkdownPostProcessor(markdownPostProcessor);
this.app.workspace.onLayoutReady(() => {
this.app.workspace.onLayoutReady(async () => {
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.addMarkdownPostProcessor, `ExcalidrawPlugin.addMarkdownPostProcessor > app.workspace.onLayoutReady`);
await this.awaitInit();
// internal-link quick preview
this.registerEvent(this.app.workspace.on("hover-link", hoverEvent));
@@ -889,8 +917,9 @@ export default class ExcalidrawPlugin extends Plugin {
? new CustomMutationObserver(fileExplorerObserverFn, "fileExplorerObserver")
: new MutationObserver(fileExplorerObserverFn);
this.app.workspace.onLayoutReady(() => {
this.app.workspace.onLayoutReady(async () => {
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.experimentalFileTypeDisplay, `ExcalidrawPlugin.experimentalFileTypeDisplay > app.workspace.onLayoutReady`);
await this.awaitInit();
document.querySelectorAll(".nav-file-title").forEach(insertFiletype); //apply filetype to files already displayed
const container = document.querySelector(".nav-files-container");
if (container) {
@@ -2762,6 +2791,7 @@ export default class ExcalidrawPlugin extends Plugin {
}
this.app.workspace.onLayoutReady(async () => {
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.runStartupScript, `ExcalidrawPlugin.runStartupScript > app.workspace.onLayoutReady, scriptPath:${this.settings?.startupScriptPath}`);
await this.awaitInit();
const path = this.settings.startupScriptPath.endsWith(".md")
? this.settings.startupScriptPath
: `${this.settings.startupScriptPath}.md`;
@@ -2922,6 +2952,7 @@ export default class ExcalidrawPlugin extends Plugin {
private registerEventListeners() {
this.app.workspace.onLayoutReady(async () => {
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.registerEventListeners,`ExcalidrawPlugin.registerEventListeners > app.workspace.onLayoutReady`);
await this.awaitInit();
const onPasteHandler = (
evt: ClipboardEvent,
editor: Editor,
@@ -3370,7 +3401,8 @@ export default class ExcalidrawPlugin extends Plugin {
this.settings = null;
clearMathJaxVariables();
EXCALIDRAW_PACKAGES = "";
EXCALIDRAW_PACKAGE = "";
REACT_PACKAGES = "";
//pluginPackages = null;
PLUGIN_VERSION = null;
//@ts-ignore

View File

@@ -41,6 +41,7 @@ export class StylesManager {
this.plugin = plugin;
plugin.app.workspace.onLayoutReady(async () => {
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(undefined, "StylesManager.constructor > app.workspace.onLayoutReady", this);
await plugin.awaitInit();
await this.harvestStyles();
getAllWindowDocuments(plugin.app).forEach(doc => this.copyPropertiesToTheme(doc));