mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
Compare commits
7 Commits
2.7.0-beta
...
2.7.0-bugs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd4c07cbf9 | ||
|
|
6a86de3e1e | ||
|
|
ff8c649c6a | ||
|
|
ae34e124a7 | ||
|
|
5d084ffc30 | ||
|
|
b0a9cf848e | ||
|
|
37e06efa43 |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "2.7.0-beta-6",
|
||||
"version": "2.7.0",
|
||||
"minAppVersion": "1.1.6",
|
||||
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
|
||||
"author": "Zsolt Viczian",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "2.6.8",
|
||||
"version": "2.7.0",
|
||||
"minAppVersion": "1.1.6",
|
||||
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
|
||||
"author": "Zsolt Viczian",
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@zsviczian/excalidraw": "0.17.6-21",
|
||||
"@zsviczian/excalidraw": "0.17.6-22",
|
||||
"chroma-js": "^2.4.2",
|
||||
"clsx": "^2.0.0",
|
||||
"@zsviczian/colormaster": "^1.2.2",
|
||||
@@ -73,7 +73,7 @@
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"lz-string": "^1.5.0",
|
||||
"obsidian": "1.5.7-1",
|
||||
"obsidian": "^1.7.2",
|
||||
"prettier": "^3.0.1",
|
||||
"rollup": "^2.70.1",
|
||||
"rollup-plugin-copy": "^3.5.0",
|
||||
|
||||
@@ -31,13 +31,8 @@ function trimLastSemicolon(input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
function compressLanguageFile(lang) {
|
||||
const inputDir = "./src/lang/locale";
|
||||
const filePath = `${inputDir}/${lang}.ts`;
|
||||
let content = fs.readFileSync(filePath, "utf-8");
|
||||
content = trimLastSemicolon(content.split("export default")[1].trim());
|
||||
|
||||
const minified = minify(`x = ${content};`,{
|
||||
function minifyCode(code) {
|
||||
const minified = minify(code,{
|
||||
compress: true,
|
||||
mangle: true,
|
||||
output: {
|
||||
@@ -49,18 +44,26 @@ function compressLanguageFile(lang) {
|
||||
if (minified.error) {
|
||||
throw new Error(minified.error);
|
||||
}
|
||||
return LZString.compressToBase64(minified.code);
|
||||
return minified.code;
|
||||
}
|
||||
|
||||
const excalidraw_pkg = isLib ? "" : isProd
|
||||
function compressLanguageFile(lang) {
|
||||
const inputDir = "./src/lang/locale";
|
||||
const filePath = `${inputDir}/${lang}.ts`;
|
||||
let content = fs.readFileSync(filePath, "utf-8");
|
||||
content = trimLastSemicolon(content.split("export default")[1].trim());
|
||||
return LZString.compressToBase64(minifyCode(`x = ${content};`));
|
||||
}
|
||||
|
||||
const excalidraw_pkg = isLib ? "" : minifyCode( isProd
|
||||
? fs.readFileSync("./node_modules/@zsviczian/excalidraw/dist/excalidraw.production.min.js", "utf8")
|
||||
: fs.readFileSync("./node_modules/@zsviczian/excalidraw/dist/excalidraw.development.js", "utf8");
|
||||
const react_pkg = isLib ? "" : isProd
|
||||
: fs.readFileSync("./node_modules/@zsviczian/excalidraw/dist/excalidraw.development.js", "utf8"));
|
||||
const react_pkg = isLib ? "" : minifyCode(isProd
|
||||
? fs.readFileSync("./node_modules/react/umd/react.production.min.js", "utf8")
|
||||
: fs.readFileSync("./node_modules/react/umd/react.development.js", "utf8");
|
||||
const reactdom_pkg = isLib ? "" : isProd
|
||||
: fs.readFileSync("./node_modules/react/umd/react.development.js", "utf8"));
|
||||
const reactdom_pkg = isLib ? "" : minifyCode(isProd
|
||||
? fs.readFileSync("./node_modules/react-dom/umd/react-dom.production.min.js", "utf8")
|
||||
: fs.readFileSync("./node_modules/react-dom/umd/react-dom.development.js", "utf8");
|
||||
: fs.readFileSync("./node_modules/react-dom/umd/react-dom.development.js", "utf8"));
|
||||
|
||||
const lzstring_pkg = isLib ? "" : fs.readFileSync("./node_modules/lz-string/libs/lz-string.min.js", "utf8");
|
||||
if (!isLib) {
|
||||
@@ -91,15 +94,10 @@ const packageString = isLib
|
||||
'\nlet REACT_PACKAGES = `' +
|
||||
jsesc(react_pkg + reactdom_pkg, { quotes: 'backtick' }) +
|
||||
'`;\n' +
|
||||
/* 'let EXCALIDRAW_PACKAGE = `' +
|
||||
jsesc(excalidraw_pkg, { quotes: 'backtick' }) +
|
||||
'`;\n' +*/
|
||||
'const unpackExcalidraw = () => LZString.decompressFromBase64("' + LZString.compressToBase64(excalidraw_pkg) + '");\n' +
|
||||
'let {react, reactDOM } = window.eval.call(window, `(function() {' + '${REACT_PACKAGES};' + 'return {react: React, reactDOM: ReactDOM};})();`);\n' +
|
||||
'let {react, reactDOM } = new Function(`${REACT_PACKAGES}; return {react: React, reactDOM: ReactDOM};`)();\n' +
|
||||
'let excalidrawLib = {};\n' +
|
||||
'const loadMathjaxToSVG = () => window.eval.call(window, `(function() {' +
|
||||
'${LZString.decompressFromBase64("' + LZString.compressToBase64(mathjaxtosvg_pkg) + '")}' +
|
||||
'return MathjaxToSVG;})();`);\n' +
|
||||
'const loadMathjaxToSVG = () => new Function(`${LZString.decompressFromBase64("' + LZString.compressToBase64(mathjaxtosvg_pkg) + '")}; return MathjaxToSVG;`)();\n' +
|
||||
`const PLUGIN_LANGUAGES = {${LANGUAGES.map(lang => `"${lang}": "${compressLanguageFile(lang)}"`).join(",")}};\n` +
|
||||
'const PLUGIN_VERSION="' + manifest.version + '";';
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ export class EmbeddedFile {
|
||||
public isLoaded(isDark: boolean): boolean {
|
||||
if(!this.isHyperLink && !this.isLocalLink) {
|
||||
if (!this.file) {
|
||||
this.file = app.metadataCache.getFirstLinkpathDest(
|
||||
this.file = this.plugin.app.metadataCache.getFirstLinkpathDest(
|
||||
this.linkParts.path,
|
||||
this.hostPath,
|
||||
); // maybe the file has synchronized in the mean time
|
||||
|
||||
@@ -38,6 +38,7 @@ import {
|
||||
mermaidToExcalidraw,
|
||||
refreshTextDimensions,
|
||||
getFontFamilyString,
|
||||
EXCALIDRAW_PLUGIN,
|
||||
} from "src/constants/constants";
|
||||
import { blobToBase64, checkAndCreateFolder, getDrawingFilename, getExcalidrawEmbeddedFilesFiletree, getListOfTemplateFiles, getNewUniqueFilepath, hasExcalidrawEmbeddedImagesTreeChanged, } from "src/utils/FileUtils";
|
||||
import {
|
||||
@@ -246,7 +247,7 @@ export class ExcalidrawAutomate {
|
||||
* @returns
|
||||
*/
|
||||
public getNewUniqueFilepath(filename: string, folderpath: string): string {
|
||||
return getNewUniqueFilepath(app.vault, filename, folderpath);
|
||||
return getNewUniqueFilepath(this.plugin.app.vault, filename, folderpath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -278,8 +279,8 @@ export class ExcalidrawAutomate {
|
||||
errorMessage("targetView not set", "getAttachmentFolderAndFilePath()");
|
||||
return null;
|
||||
}
|
||||
const folderAndPath = await getAttachmentsFolderAndFilePath(app,this.targetView.file.path, filename);
|
||||
return getNewUniqueFilepath(app.vault, filename, folderAndPath.folder);
|
||||
const folderAndPath = await getAttachmentsFolderAndFilePath(this.plugin.app,this.targetView.file.path, filename);
|
||||
return getNewUniqueFilepath(this.plugin.app.vault, filename, folderAndPath.folder);
|
||||
}
|
||||
|
||||
public compressToBase64(str:string): string {
|
||||
@@ -1049,7 +1050,7 @@ export class ExcalidrawAutomate {
|
||||
width,
|
||||
height,
|
||||
url ? url : file ? `[[${
|
||||
app.metadataCache.fileToLinktext(
|
||||
this.plugin.app.metadataCache.fileToLinktext(
|
||||
file,
|
||||
this.targetView.file.path,
|
||||
false, //file.extension === "md", //changed this to false because embedable link navigation in ExcaliBrain
|
||||
@@ -3164,14 +3165,14 @@ export const updateElementLinksToObsidianLinks = ({elements, hostFile}:{
|
||||
if (linkText.match(REG_LINKINDEX_INVALIDCHARS)) {
|
||||
return el;
|
||||
}
|
||||
const file = app.metadataCache.getFirstLinkpathDest(
|
||||
const file = EXCALIDRAW_PLUGIN.app.metadataCache.getFirstLinkpathDest(
|
||||
linkText,
|
||||
hostFile.path,
|
||||
);
|
||||
if(!file) {
|
||||
return el;
|
||||
}
|
||||
let link = app.getObsidianUrl(file);
|
||||
let link = EXCALIDRAW_PLUGIN.app.getObsidianUrl(file);
|
||||
if(window.ExcalidrawAutomate?.onUpdateElementLinkForExportHook) {
|
||||
link = window.ExcalidrawAutomate.onUpdateElementLinkForExportHook({
|
||||
originalLink: el.link,
|
||||
|
||||
3
src/ExcalidrawLib.d.ts
vendored
3
src/ExcalidrawLib.d.ts
vendored
@@ -2,7 +2,7 @@ import { RestoredDataState } from "@zsviczian/excalidraw/types/excalidraw/data/r
|
||||
import { ImportedDataState } from "@zsviczian/excalidraw/types/excalidraw/data/types";
|
||||
import { BoundingBox } from "@zsviczian/excalidraw/types/excalidraw/element/bounds";
|
||||
import { ElementsMap, ExcalidrawBindableElement, ExcalidrawElement, ExcalidrawFrameElement, ExcalidrawFrameLikeElement, ExcalidrawTextContainer, ExcalidrawTextElement, FontFamilyValues, FontString, NonDeleted, NonDeletedExcalidrawElement, Theme } from "@zsviczian/excalidraw/types/excalidraw/element/types";
|
||||
import { FontMetadata } from "@zsviczian/excalidraw/types/excalidraw/fonts/metadata";
|
||||
import { FontMetadata } from "@zsviczian/excalidraw/types/excalidraw/fonts/FontMetadata";
|
||||
import { AppState, BinaryFiles, DataURL, GenerateDiagramToCode, Zoom } from "@zsviczian/excalidraw/types/excalidraw/types";
|
||||
import { Mutable } from "@zsviczian/excalidraw/types/excalidraw/utility-types";
|
||||
import { GlobalPoint } from "@zsviczian/excalidraw/types/math/types";
|
||||
@@ -220,5 +220,6 @@ declare namespace ExcalidrawLib {
|
||||
): string;
|
||||
function safelyParseJSON (json: string): Record<string, any> | null;
|
||||
function loadSceneFonts(elements: NonDeletedExcalidrawElement[]): Promise<void>;
|
||||
function loadMermaid(): Promise<any>;
|
||||
}
|
||||
|
||||
|
||||
@@ -1521,7 +1521,6 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
if(!silent) new Notice("Save successful", 1000);
|
||||
}
|
||||
|
||||
|
||||
onload() {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.onload, "ExcalidrawView.onload");
|
||||
if(this.plugin.settings.overrideObsidianFontSize) {
|
||||
@@ -2737,7 +2736,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
isEditedAsMarkdownInOtherView(): boolean {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.isEditedAsMarkdownInOtherView, "ExcalidrawView.isEditedAsMarkdownInOtherView");
|
||||
//if the user is editing the same file in markdown mode, do not compress it
|
||||
const leaves = app.workspace.getLeavesOfType("markdown");
|
||||
const leaves = this.app.workspace.getLeavesOfType("markdown");
|
||||
return (
|
||||
leaves.filter((leaf) => (leaf.view as MarkdownView).file === this.file)
|
||||
.length > 0
|
||||
@@ -3569,7 +3568,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
private dropAction(transfer: DataTransfer) {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.dropAction, "ExcalidrawView.dropAction");
|
||||
// Return a 'copy' or 'link' action according to the content types, or undefined if no recognized type
|
||||
const files = (app as any).dragManager.draggable?.files;
|
||||
const files = (this.app as any).dragManager.draggable?.files;
|
||||
if (files) {
|
||||
if (files[0] == this.file) {
|
||||
files.shift();
|
||||
@@ -3719,7 +3718,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
return;
|
||||
}
|
||||
|
||||
const f = app.metadataCache.getFirstLinkpathDest(
|
||||
const f = this.app.metadataCache.getFirstLinkpathDest(
|
||||
linktext.split("#")[0],
|
||||
this.file.path,
|
||||
);
|
||||
@@ -4311,7 +4310,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
|
||||
//internalDragAction === "link"
|
||||
this.addText(
|
||||
`[[${app.metadataCache.fileToLinktext(
|
||||
`[[${this.app.metadataCache.fileToLinktext(
|
||||
draggable.file,
|
||||
this.file.path,
|
||||
true,
|
||||
@@ -4374,7 +4373,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
//internalDragAction === "link"
|
||||
for (const f of draggable.files) {
|
||||
await this.addText(
|
||||
`[[${app.metadataCache.fileToLinktext(
|
||||
`[[${this.app.metadataCache.fileToLinktext(
|
||||
f,
|
||||
this.file.path,
|
||||
true,
|
||||
|
||||
@@ -33,7 +33,7 @@ export const updateEquation = async (
|
||||
addFiles: Function,
|
||||
) => {
|
||||
await loadMathJax();
|
||||
const data = await tex2dataURLExternal(equation, 4, app);
|
||||
const data = await tex2dataURLExternal(equation, 4, view.app);
|
||||
if (data) {
|
||||
const files: FileData[] = [];
|
||||
files.push({
|
||||
|
||||
@@ -268,7 +268,7 @@ export class CommandManager {
|
||||
id: "excalidraw-publish-svg-check",
|
||||
name: t("PUBLISH_SVG_CHECK"),
|
||||
checkCallback: (checking: boolean) => {
|
||||
const publish = app.internalPlugins.plugins["publish"].instance;
|
||||
const publish = this.app.internalPlugins.plugins["publish"].instance;
|
||||
if (!publish) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { WorkspaceLeaf, TFile, Editor, MarkdownView, MarkdownFileInfo, MetadataCache, App, EventRef, Menu } from "obsidian";
|
||||
import { WorkspaceLeaf, TFile, Editor, MarkdownView, MarkdownFileInfo, MetadataCache, App, EventRef, Menu, FileView } from "obsidian";
|
||||
import { ExcalidrawElement } from "@zsviczian/excalidraw/types/excalidraw/element/types";
|
||||
import { getLink } from "../utils/FileUtils";
|
||||
import { editorInsertText, getParentOfClass, setExcalidrawView } from "../utils/ObsidianUtils";
|
||||
@@ -19,6 +19,8 @@ export class EventManager {
|
||||
private app: App;
|
||||
public leafChangeTimeout: number|null = null;
|
||||
private removeEventLisnters:(()=>void)[] = []; //only used if I register an event directly, not via Obsidian's registerEvent
|
||||
private previouslyActiveLeaf: WorkspaceLeaf;
|
||||
private splitViewLeafSwitchTimestamp: number = 0;
|
||||
|
||||
get settings() {
|
||||
return this.plugin.settings;
|
||||
@@ -63,8 +65,11 @@ export class EventManager {
|
||||
console.error("Error registering event listeners", e);
|
||||
}
|
||||
this.plugin.logStartupEvent("Event listeners registered");
|
||||
}
|
||||
|
||||
}
|
||||
public isRecentSplitViewSwitch():boolean {
|
||||
return (Date.now() - this.splitViewLeafSwitchTimestamp) < 3000;
|
||||
}
|
||||
|
||||
public async registerEvents() {
|
||||
await this.plugin.awaitInit();
|
||||
@@ -172,7 +177,16 @@ export class EventManager {
|
||||
const newActiveviewEV: ExcalidrawView =
|
||||
leaf.view instanceof ExcalidrawView ? leaf.view : null;
|
||||
this.activeExcalidrawView = newActiveviewEV;
|
||||
|
||||
const previousFile = (this.previouslyActiveLeaf?.view as FileView)?.file;
|
||||
const currentFile = (leaf?.view as FileView).file;
|
||||
//editing the same file in a different leaf
|
||||
if(currentFile && (previousFile === currentFile)) {
|
||||
if((this.previouslyActiveLeaf.view instanceof MarkdownView && leaf.view instanceof ExcalidrawView)) {
|
||||
this.splitViewLeafSwitchTimestamp = Date.now();
|
||||
}
|
||||
}
|
||||
this.previouslyActiveLeaf = leaf;
|
||||
|
||||
if (newActiveviewEV) {
|
||||
this.plugin.addModalContainerObserver();
|
||||
this.plugin.lastActiveExcalidrawFilePath = newActiveviewEV.file?.path;
|
||||
|
||||
@@ -372,7 +372,7 @@ export class PluginFileManager {
|
||||
}
|
||||
[EXPORT_TYPES, "excalidraw"].flat().forEach(async (ext: string) => {
|
||||
const oldIMGpath = getIMGFilename(oldPath, ext);
|
||||
const imgFile = app.vault.getAbstractFileByPath(
|
||||
const imgFile = this.app.vault.getAbstractFileByPath(
|
||||
normalizePath(oldIMGpath),
|
||||
);
|
||||
if (imgFile && imgFile instanceof TFile) {
|
||||
@@ -402,11 +402,30 @@ export class PluginFileManager {
|
||||
excalidrawView.semaphores.preventReload = false;
|
||||
return;
|
||||
}
|
||||
//if the user hasn't touched the file for 5 minutes, don't synchronize, reload.
|
||||
//this is to avoid complex sync scenarios of multiple remote changes outside an active collaboration session
|
||||
|
||||
|
||||
// Avoid synchronizing or reloading if the user hasn't interacted with the file for 5 minutes.
|
||||
// This prevents complex sync issues when multiple remote changes occur outside an active collaboration session.
|
||||
|
||||
// The following logic handles a rare edge case where:
|
||||
// 1. The user opens an Excalidraw file.
|
||||
// 2. Immediately splits the view without saving Excalidraw (since no changes were made).
|
||||
// 3. Switches the new split view to Markdown, edits the file, and quickly returns to Excalidraw.
|
||||
// 4. The "modify" event may fire while Excalidraw is active, triggering an unwanted reload and zoom reset.
|
||||
|
||||
// To address this:
|
||||
// - We check if the user is currently editing the Markdown version of the Excalidraw file in a split view.
|
||||
// - As a heuristic, we also check for recent leaf switches.
|
||||
// This is not perfectly accurate (e.g., rapid switching between views within a few seconds),
|
||||
// but it is sufficient to avoid most edge cases without introducing complexity.
|
||||
|
||||
// Edge case impact:
|
||||
// - In extremely rare situations, an update arriving within the "recent switch" timeframe (e.g., from Obsidian Sync)
|
||||
// might not trigger a reload. This is unlikely and an acceptable trade-off for better user experience.
|
||||
const activeView = this.app.workspace.activeLeaf.view;
|
||||
const isEditingMarkdownSideInSplitView = (activeView !== excalidrawView) &&
|
||||
activeView instanceof MarkdownView && activeView.file === excalidrawView.file;
|
||||
const isEditingMarkdownSideInSplitView = ((activeView !== excalidrawView) &&
|
||||
activeView instanceof MarkdownView && activeView.file === excalidrawView.file) ||
|
||||
(activeView === excalidrawView && this.plugin.isRecentSplitViewSwitch());
|
||||
|
||||
if(!isEditingMarkdownSideInSplitView && (excalidrawView.lastSaveTimestamp + 300000 < Date.now())) {
|
||||
excalidrawView.reload(true, excalidrawView.file);
|
||||
|
||||
@@ -1,18 +1,31 @@
|
||||
import { updateExcalidrawLib } from "src/constants/constants";
|
||||
import { ExcalidrawLib } from "../ExcalidrawLib";
|
||||
import { Packages } from "../types/types";
|
||||
import { debug, DEBUGGING } from "../utils/DebugHelper";
|
||||
import { Notice } from "obsidian";
|
||||
import ExcalidrawPlugin from "src/main";
|
||||
|
||||
declare let REACT_PACKAGES:string;
|
||||
declare let react:any;
|
||||
declare let reactDOM:any;
|
||||
declare let excalidrawLib: typeof ExcalidrawLib;
|
||||
declare const unpackExcalidraw: Function;
|
||||
|
||||
export class PackageManager {
|
||||
private packageMap: Map<Window, Packages> = new Map<Window, Packages>();
|
||||
private EXCALIDRAW_PACKAGE: string;
|
||||
|
||||
constructor() {
|
||||
this.packageMap.set(window,{react, reactDOM, excalidrawLib});
|
||||
constructor(plugin: ExcalidrawPlugin) {
|
||||
try {
|
||||
this.EXCALIDRAW_PACKAGE = unpackExcalidraw();
|
||||
excalidrawLib = window.eval.call(window,`(function() {${this.EXCALIDRAW_PACKAGE};return ExcalidrawLib;})()`);
|
||||
updateExcalidrawLib();
|
||||
this.setPackage(window,{react, reactDOM, excalidrawLib});
|
||||
} catch (e) {
|
||||
new Notice("Error loading the Excalidraw package", 6000);
|
||||
console.error("Error loading the Excalidraw package", e);
|
||||
}
|
||||
plugin.logStartupEvent("Excalidraw package unpacked");
|
||||
}
|
||||
|
||||
public setPackage(window: Window, pkg: Packages) {
|
||||
@@ -29,7 +42,7 @@ export class PackageManager {
|
||||
if(this.packageMap.has(win)) {
|
||||
return this.packageMap.get(win);
|
||||
}
|
||||
|
||||
|
||||
const {react:r, reactDOM:rd, excalidrawLib:e} = win.eval.call(win,
|
||||
`(function() {
|
||||
${REACT_PACKAGES + this.EXCALIDRAW_PACKAGE};
|
||||
@@ -76,5 +89,9 @@ export class PackageManager {
|
||||
delete p.react;
|
||||
});
|
||||
this.packageMap.clear();
|
||||
this.EXCALIDRAW_PACKAGE = "";
|
||||
react = null;
|
||||
reactDOM = null;
|
||||
excalidrawLib = null;
|
||||
}
|
||||
}
|
||||
@@ -105,6 +105,7 @@ export let {
|
||||
refreshTextDimensions,
|
||||
getCSSFontDefinition,
|
||||
loadSceneFonts,
|
||||
loadMermaid,
|
||||
} = excalidrawLib;
|
||||
|
||||
export function updateExcalidrawLib() {
|
||||
@@ -130,6 +131,7 @@ export function updateExcalidrawLib() {
|
||||
refreshTextDimensions,
|
||||
getCSSFontDefinition,
|
||||
loadSceneFonts,
|
||||
loadMermaid,
|
||||
} = excalidrawLib);
|
||||
}
|
||||
|
||||
@@ -153,7 +155,12 @@ export const DEVICE: DeviceType = {
|
||||
isAndroid: document.body.hasClass("is-android"),
|
||||
};
|
||||
|
||||
export const ROOTELEMENTSIZE = (() => {
|
||||
export let ROOTELEMENTSIZE: number = 16;
|
||||
export function setRootElementSize(size?:number) {
|
||||
if(size) {
|
||||
ROOTELEMENTSIZE = size;
|
||||
return;
|
||||
}
|
||||
const tempElement = document.createElement('div');
|
||||
tempElement.style.fontSize = '1rem';
|
||||
tempElement.style.display = 'none'; // Hide the element
|
||||
@@ -162,7 +169,7 @@ export const ROOTELEMENTSIZE = (() => {
|
||||
const pixelSize = parseFloat(computedStyle.fontSize);
|
||||
document.body.removeChild(tempElement);
|
||||
return pixelSize;
|
||||
})();
|
||||
};
|
||||
|
||||
export const nanoid = customAlphabet(
|
||||
"1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
|
||||
@@ -170,8 +170,8 @@ function RenderObsidianView(
|
||||
containerRef.current.parentElement.style.padding = "";
|
||||
|
||||
const doc = view.ownerDocument;
|
||||
const rootSplit:WorkspaceSplit = new (WorkspaceSplit as ConstructableWorkspaceSplit)(app.workspace, "vertical");
|
||||
rootSplit.getRoot = () => app.workspace[doc === document ? 'rootSplit' : 'floatingSplit'];
|
||||
const rootSplit:WorkspaceSplit = new (WorkspaceSplit as ConstructableWorkspaceSplit)(view.app.workspace, "vertical");
|
||||
rootSplit.getRoot = () => view.app.workspace[doc === document ? 'rootSplit' : 'floatingSplit'];
|
||||
rootSplit.getContainer = () => getContainerForDocument(doc);
|
||||
rootSplit.containerEl.style.width = '100%';
|
||||
rootSplit.containerEl.style.height = '100%';
|
||||
@@ -183,7 +183,7 @@ function RenderObsidianView(
|
||||
};
|
||||
|
||||
const setKeepOnTop = () => {
|
||||
const keepontop = (app.workspace.activeLeaf === view.leaf) && DEVICE.isDesktop;
|
||||
const keepontop = (view.app.workspace.activeLeaf === view.leaf) && DEVICE.isDesktop;
|
||||
if (keepontop) {
|
||||
//@ts-ignore
|
||||
if(!view.ownerWindow.electronWindow.isAlwaysOnTop()) {
|
||||
@@ -315,7 +315,6 @@ function RenderObsidianView(
|
||||
const canvasNode = containerRef.current;
|
||||
if(!canvasNode.hasClass("canvas-node")) return;
|
||||
setColors(canvasNode, element, mdProps, canvasColor);
|
||||
console.log("Setting colors");
|
||||
}, [
|
||||
mdProps?.useObsidianDefaults,
|
||||
mdProps?.backgroundMatchCanvas,
|
||||
|
||||
@@ -5,7 +5,7 @@ export const showFrameSettings = (ea: ExcalidrawAutomate) => {
|
||||
const {enabled, clip, name, outline} = ea.getExcalidrawAPI().getAppState().frameRendering;
|
||||
|
||||
// Create modal dialog
|
||||
const frameSettingsModal = new ea.obsidian.Modal(app);
|
||||
const frameSettingsModal = new ea.obsidian.Modal(ea.plugin.app);
|
||||
|
||||
frameSettingsModal.onOpen = () => {
|
||||
const {contentEl} = frameSettingsModal;
|
||||
|
||||
@@ -17,6 +17,24 @@ 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://storage.ko-fi.com/cdn/kofi6.png?v=6" border="0" alt="Buy Me a Coffee at ko-fi.com" height=45></a></div>
|
||||
`,
|
||||
"2.7.0":`
|
||||
## Fixed
|
||||
- Various Markdown embeddable "fuzziness":
|
||||
- Fixed issues with appearance settings and edit mode toggling when single-click editing is enabled.
|
||||
- Ensured embeddable file editing no longer gets interrupted unexpectedly.
|
||||
- **Hover Preview**: Disabled hover preview for back-of-the-note cards to reduce distractions.
|
||||
- **Settings Save**: Fixed an issue where plugin settings unnecessarily saved on every startup.
|
||||
|
||||
## New Features
|
||||
- **Image Cropping Snaps to Objects**: When snapping is enabled in the scene, image cropping now aligns to nearby objects.
|
||||
- **Session Persistence for Pen Mode**: Excalidraw remembers the last pen mode when switching between drawings within the same session.
|
||||
|
||||
## Refactoring
|
||||
- **Mermaid Diagrams**: Excalidraw now uses its own Mermaid package, breaking future dependencies on Obsidian's Mermaid updates. This ensures stability and includes all fixes and improvements made to Excalidraw Mermaid since February 2024. The plugin file size has increased slightly, but this change significantly improves maintainability while remaining invisible to users.
|
||||
- **MathJax Optimization**: MathJax (LaTeX equation SVG image generation) now loads only on demand, with the package compressed to minimize the startup and file size impact caused by the inclusion of Mermaid.
|
||||
- **On-Demand Language Loading**: Non-English language files are now compressed and load only when needed, counterbalancing the increase in file size due to Mermaid and improving load speeds.
|
||||
- **Codebase Restructuring**: Improved type safety by removing many ${String.fromCharCode(96)}//@ts-ignore${String.fromCharCode(96)} commands and enhancing modularity. Introduced new management classes: **CommandManager**, **EventManager**, **PluginFileManager**, **ObserverManager**, and **PackageManager**. Further restructuring is planned for upcoming releases to improve maintainability and stability.
|
||||
`,
|
||||
"2.6.8":`
|
||||
## New
|
||||
- **QoL improvements**:
|
||||
|
||||
@@ -53,7 +53,7 @@ export class PenSettingsModal extends Modal {
|
||||
private view: ExcalidrawView,
|
||||
private pen: number,
|
||||
) {
|
||||
super(app);
|
||||
super(plugin.app);
|
||||
this.api = view.excalidrawAPI;
|
||||
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ export class UniversalInsertFileModal extends Modal {
|
||||
button
|
||||
.setButtonText("as Embeddable")
|
||||
.onClick(async () => {
|
||||
const path = app.metadataCache.fileToLinktext(
|
||||
const path = this.app.metadataCache.fileToLinktext(
|
||||
file,
|
||||
this.view.file.path,
|
||||
file.extension === "md",
|
||||
|
||||
52
src/main.ts
52
src/main.ts
@@ -36,6 +36,8 @@ import {
|
||||
FONTS_STYLE_ID,
|
||||
CJK_STYLE_ID,
|
||||
updateExcalidrawLib,
|
||||
loadMermaid,
|
||||
setRootElementSize,
|
||||
} from "./constants/constants";
|
||||
import { ExcalidrawSettings, DEFAULT_SETTINGS, ExcalidrawSettingTab } from "./settings";
|
||||
import { initExcalidrawAutomate, ExcalidrawAutomate } from "./ExcalidrawAutomate";
|
||||
@@ -87,12 +89,8 @@ import ExcalidrawView from "./ExcalidrawView";
|
||||
import { CommandManager } from "./Managers/CommandManager";
|
||||
import { EventManager } from "./Managers/EventManager";
|
||||
|
||||
declare const unpackExcalidraw: Function;
|
||||
declare const PLUGIN_VERSION:string;
|
||||
declare const INITIAL_TIMESTAMP: number;
|
||||
declare let react:any;
|
||||
declare let reactDOM:any;
|
||||
declare let excalidrawLib: typeof ExcalidrawLib;
|
||||
|
||||
export default class ExcalidrawPlugin extends Plugin {
|
||||
private fileManager: PluginFileManager;
|
||||
@@ -100,7 +98,6 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
private packageManager: PackageManager;
|
||||
private commandManager: CommandManager;
|
||||
private eventManager: EventManager;
|
||||
private EXCALIDRAW_PACKAGE: string;
|
||||
public eaInstances = new WeakArray<ExcalidrawAutomate>();
|
||||
public fourthFontLoaded: boolean = false;
|
||||
public excalidrawConfig: ExcalidrawConfig;
|
||||
@@ -147,6 +144,10 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
>();
|
||||
this.equationsMaster = new Map<FileId, string>();
|
||||
this.mermaidsMaster = new Map<FileId, string>();
|
||||
|
||||
//isExcalidraw function is used already is already used by MarkdownPostProcessor in onLoad before onLayoutReady
|
||||
this.fileManager = new PluginFileManager(this);
|
||||
|
||||
setExcalidrawPlugin(this);
|
||||
/*if((process.env.NODE_ENV === 'development')) {
|
||||
this.slob = new Array(200 * 1024 * 1024 + 1).join('A'); // Create a 200MB blob
|
||||
@@ -213,6 +214,14 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
};
|
||||
}*/
|
||||
|
||||
/**
|
||||
* used by Excalidraw to getSharedMermaidInstance
|
||||
* @returns shared mermaid instance
|
||||
*/
|
||||
public async getMermaid() {
|
||||
return await loadMermaid();
|
||||
}
|
||||
|
||||
public isPenMode() {
|
||||
return this.wasPenModeActivePreviously ||
|
||||
(this.settings.defaultPenMode === "always") ||
|
||||
@@ -323,24 +332,15 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
this.logStartupEvent("\n----------------------------------\nWorkspace onLayoutReady event fired (these actions are outside the plugin initialization)");
|
||||
await this.awaitSettings();
|
||||
this.logStartupEvent("Settings awaited");
|
||||
if(!this.settings.overrideObsidianFontSize) {
|
||||
setRootElementSize();
|
||||
}
|
||||
|
||||
this.packageManager = new PackageManager();
|
||||
this.fileManager = new PluginFileManager(this);
|
||||
this.packageManager = new PackageManager(this);
|
||||
this.eventManager = new EventManager(this);
|
||||
this.observerManager = new ObserverManager(this);
|
||||
this.commandManager = new CommandManager(this);
|
||||
|
||||
try {
|
||||
this.EXCALIDRAW_PACKAGE = unpackExcalidraw();
|
||||
excalidrawLib = window.eval.call(window,`(function() {${this.EXCALIDRAW_PACKAGE};return ExcalidrawLib;})()`);
|
||||
this.packageManager.setPackage(window,{react, reactDOM, excalidrawLib});
|
||||
updateExcalidrawLib();
|
||||
} catch (e) {
|
||||
new Notice("Error loading the Excalidraw package", 6000);
|
||||
console.error("Error loading the Excalidraw package", e);
|
||||
}
|
||||
this.logStartupEvent("Excalidraw package unpacked");
|
||||
|
||||
try {
|
||||
initCompressionWorker();
|
||||
} catch (e) {
|
||||
@@ -713,7 +713,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
}
|
||||
const fname = decodedURI.substring(decodedURI.lastIndexOf("/") + 1);
|
||||
const folder = `${this.settings.scriptFolderPath}/${SCRIPT_INSTALL_FOLDER}`;
|
||||
const downloaded = app.vault.getFiles().filter(f=>f.path.startsWith(folder) && f.name === fname).sort((a,b)=>a.path>b.path?1:-1);
|
||||
const downloaded = this.app.vault.getFiles().filter(f=>f.path.startsWith(folder) && f.name === fname).sort((a,b)=>a.path>b.path?1:-1);
|
||||
let scriptFile = downloaded[0];
|
||||
const scriptPath = scriptFile?.path ?? `${folder}/${fname}`;
|
||||
const svgPath = getIMGFilename(scriptPath, "svg");
|
||||
@@ -990,15 +990,15 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
markdownViewLoaded &&
|
||||
self.excalidrawFileModes[this.id || state.state.file] !== "markdown"
|
||||
) {
|
||||
const file = state.state.file;
|
||||
if ((self.forceToOpenInMarkdownFilepath !== file) && fileShouldDefaultAsExcalidraw(file,this.app)) {
|
||||
const filepath:string = state.state.file as string;
|
||||
if ((self.forceToOpenInMarkdownFilepath !== filepath) && fileShouldDefaultAsExcalidraw(filepath,this.app)) {
|
||||
// If we have it, force the view type to excalidraw
|
||||
const newState = {
|
||||
...state,
|
||||
type: VIEW_TYPE_EXCALIDRAW,
|
||||
};
|
||||
|
||||
self.excalidrawFileModes[file] =
|
||||
self.excalidrawFileModes[filepath] =
|
||||
VIEW_TYPE_EXCALIDRAW;
|
||||
|
||||
return next.apply(this, [newState, ...rest]);
|
||||
@@ -1197,7 +1197,6 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
|
||||
this.settings = null;
|
||||
clearMathJaxVariables();
|
||||
this.EXCALIDRAW_PACKAGE = "";
|
||||
//pluginPackages = null;
|
||||
//PLUGIN_VERSION = null;
|
||||
//@ts-ignore
|
||||
@@ -1205,9 +1204,6 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
this.packageManager.destroy();
|
||||
this.commandManager?.destroy();
|
||||
this.eventManager.destroy();
|
||||
react = null;
|
||||
reactDOM = null;
|
||||
excalidrawLib = null;
|
||||
terminateCompressionWorker();
|
||||
}
|
||||
|
||||
@@ -1427,6 +1423,10 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
return this.commandManager?.importSVGDialog;
|
||||
}
|
||||
|
||||
public isRecentSplitViewSwitch():boolean {
|
||||
return this.eventManager.isRecentSplitViewSwitch();
|
||||
}
|
||||
|
||||
get leafChangeTimeout() {
|
||||
return this.eventManager.leafChangeTimeout;
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ export class EmbeddableMenu {
|
||||
|
||||
private async actionMarkdownSelection (file: TFile, isExcalidrawFile: boolean, subpath: string, element: ExcalidrawEmbeddableElement) {
|
||||
this.view.updateScene({appState: {activeEmbeddable: null}, storeAction: "update"});
|
||||
const sections = (await app.metadataCache.blockCache
|
||||
const sections = (await this.view.app.metadataCache.blockCache
|
||||
.getForFile({ isCancelled: () => false },file))
|
||||
.blocks.filter((b: any) => b.display && b.node?.type === "heading")
|
||||
.filter((b: any) => !isExcalidrawFile || !MD_EX_SECTIONS.includes(b.display));
|
||||
@@ -88,7 +88,7 @@ export class EmbeddableMenu {
|
||||
);
|
||||
}
|
||||
const newSubpath = await ScriptEngine.suggester(
|
||||
app, display, values, "Select section from document"
|
||||
this.view.app, display, values, "Select section from document"
|
||||
);
|
||||
if(!newSubpath && newSubpath!=="") return;
|
||||
if (newSubpath !== subpath) {
|
||||
@@ -99,7 +99,7 @@ export class EmbeddableMenu {
|
||||
private async actionMarkdownBlock (file: TFile, subpath: string, element: ExcalidrawEmbeddableElement) {
|
||||
if(!file) return;
|
||||
this.view.updateScene({appState: {activeEmbeddable: null}, storeAction: "update"});
|
||||
const paragraphs = (await app.metadataCache.blockCache
|
||||
const paragraphs = (await this.view.app.metadataCache.blockCache
|
||||
.getForFile({ isCancelled: () => false },file))
|
||||
.blocks.filter((b: any) => b.display && b.node &&
|
||||
(b.node.type === "paragraph" || b.node.type === "blockquote" || b.node.type === "listItem" || b.node.type === "table" || b.node.type === "callout")
|
||||
@@ -109,7 +109,7 @@ export class EmbeddableMenu {
|
||||
paragraphs.map((b: any) => `${b.node?.id ? `#^${b.node.id}: ` : ``}${b.display.trim()}`));
|
||||
|
||||
const selectedBlock = await ScriptEngine.suggester(
|
||||
app, display, values, "Select section from document"
|
||||
this.view.app, display, values, "Select section from document"
|
||||
);
|
||||
if(!selectedBlock) return;
|
||||
|
||||
@@ -125,7 +125,7 @@ export class EmbeddableMenu {
|
||||
const offset = selectedBlock.node?.position?.end?.offset;
|
||||
if(!offset) return;
|
||||
blockID = nanoid();
|
||||
const fileContents = await app.vault.cachedRead(file);
|
||||
const fileContents = await this.view.app.vault.cachedRead(file);
|
||||
if(!fileContents) return;
|
||||
await this.view.app.vault.modify(file, fileContents.slice(0, offset) + ` ^${blockID}` + fileContents.slice(offset));
|
||||
await sleep(200); //wait for cache to update
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
TextComponent,
|
||||
TFile,
|
||||
} from "obsidian";
|
||||
import { GITHUB_RELEASES } from "./constants/constants";
|
||||
import { GITHUB_RELEASES, setRootElementSize } from "./constants/constants";
|
||||
import { t } from "./lang/helpers";
|
||||
import type ExcalidrawPlugin from "./main";
|
||||
import { PenStyle } from "./types/PenTypes";
|
||||
@@ -521,8 +521,10 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
async hide() {
|
||||
if(this.plugin.settings.overrideObsidianFontSize) {
|
||||
document.documentElement.style.fontSize = "";
|
||||
setRootElementSize(16);
|
||||
} else if(!document.documentElement.style.fontSize) {
|
||||
document.documentElement.style.fontSize = getComputedStyle(document.body).getPropertyValue("--font-text-size");
|
||||
setRootElementSize();
|
||||
}
|
||||
|
||||
this.plugin.settings.scriptFolderPath = normalizePath(
|
||||
|
||||
@@ -57,10 +57,10 @@ export class CanvasNodeFactory {
|
||||
await canvasPlugin.load();
|
||||
}
|
||||
const doc = this.view.ownerDocument;
|
||||
const rootSplit:WorkspaceSplit = new (WorkspaceSplit as ConstructableWorkspaceSplit)(app.workspace, "vertical");
|
||||
rootSplit.getRoot = () => app.workspace[doc === document ? 'rootSplit' : 'floatingSplit'];
|
||||
const rootSplit:WorkspaceSplit = new (WorkspaceSplit as ConstructableWorkspaceSplit)(this.view.app.workspace, "vertical");
|
||||
rootSplit.getRoot = () => this.view.app.workspace[doc === document ? 'rootSplit' : 'floatingSplit'];
|
||||
rootSplit.getContainer = () => getContainerForDocument(doc);
|
||||
this.leaf = app.workspace.createLeafInParent(rootSplit, 0);
|
||||
this.leaf = this.view.app.workspace.createLeafInParent(rootSplit, 0);
|
||||
this.canvas = canvasPlugin.views.canvas(this.leaf).canvas;
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ export const processLinkText = (linkText: string, view:ExcalidrawView): { subpat
|
||||
return {subpath, file: null};
|
||||
}
|
||||
|
||||
const file = app.metadataCache.getFirstLinkpathDest(
|
||||
const file = view.app.metadataCache.getFirstLinkpathDest(
|
||||
linkText,
|
||||
view.file.path,
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DataURL } from "@zsviczian/excalidraw/types/excalidraw/types";
|
||||
import { App, loadPdfJs, normalizePath, Notice, requestUrl, RequestUrlResponse, TAbstractFile, TFile, TFolder, Vault } from "obsidian";
|
||||
import { DEVICE, FRONTMATTER_KEYS, URLFETCHTIMEOUT } from "src/constants/constants";
|
||||
import { DEVICE, EXCALIDRAW_PLUGIN, FRONTMATTER_KEYS, URLFETCHTIMEOUT } from "src/constants/constants";
|
||||
import { IMAGE_MIME_TYPES, MimeType } from "src/EmbeddedFileLoader";
|
||||
import { ExcalidrawSettings } from "src/settings";
|
||||
import { errorlog, getDataURL } from "./Utils";
|
||||
@@ -142,7 +142,7 @@ export function getEmbedFilename(
|
||||
* @param folderpath
|
||||
*/
|
||||
export async function checkAndCreateFolder(folderpath: string):Promise<TFolder> {
|
||||
const vault = app.vault;
|
||||
const vault = EXCALIDRAW_PLUGIN.app.vault;
|
||||
folderpath = normalizePath(folderpath);
|
||||
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/658
|
||||
//@ts-ignore
|
||||
@@ -292,7 +292,7 @@ export const blobToBase64 = async (blob: Blob): Promise<string> => {
|
||||
|
||||
export const getPDFDoc = async (f: TFile): Promise<any> => {
|
||||
if(typeof window.pdfjsLib === "undefined") await loadPdfJs();
|
||||
return await window.pdfjsLib.getDocument(app.vault.getResourcePath(f)).promise;
|
||||
return await window.pdfjsLib.getDocument(EXCALIDRAW_PLUGIN.app.vault.getResourcePath(f)).promise;
|
||||
}
|
||||
|
||||
export const readLocalFile = async (filePath:string): Promise<string> => {
|
||||
@@ -330,9 +330,14 @@ export const getPathWithoutExtension = (f:TFile): string => {
|
||||
return f.path.substring(0, f.path.lastIndexOf("."));
|
||||
}
|
||||
|
||||
const VAULT_BASE_URL = DEVICE.isDesktop
|
||||
? app.vault.adapter.url.pathToFileURL(app.vault.adapter.basePath).toString()
|
||||
let _VAULT_BASE_URL:string = null;
|
||||
const VAULT_BASE_URL = () => {
|
||||
if(_VAULT_BASE_URL) return _VAULT_BASE_URL;
|
||||
_VAULT_BASE_URL = DEVICE.isDesktop
|
||||
? EXCALIDRAW_PLUGIN.app.vault.adapter.url.pathToFileURL(EXCALIDRAW_PLUGIN.app.vault.adapter.basePath).toString()
|
||||
: "";
|
||||
return _VAULT_BASE_URL;
|
||||
}
|
||||
|
||||
export const getInternalLinkOrFileURLLink = (
|
||||
path: string, plugin:ExcalidrawPlugin, alias?: string, sourceFile?: TFile
|
||||
@@ -344,8 +349,8 @@ export const getInternalLinkOrFileURLLink = (
|
||||
}
|
||||
const vault = plugin.app.vault;
|
||||
const fileURLString = vault.adapter.url.pathToFileURL(path).toString();
|
||||
if (fileURLString.startsWith(VAULT_BASE_URL)) {
|
||||
const internalPath = normalizePath(unescape(fileURLString.substring(VAULT_BASE_URL.length)));
|
||||
if (fileURLString.startsWith(VAULT_BASE_URL())) {
|
||||
const internalPath = normalizePath(unescape(fileURLString.substring(VAULT_BASE_URL().length)));
|
||||
const file = vault.getAbstractFileByPath(internalPath);
|
||||
if(file && file instanceof TFile) {
|
||||
const link = plugin.app.metadataCache.fileToLinktext(
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
import ExcalidrawPlugin from "../main";
|
||||
import { checkAndCreateFolder, splitFolderAndFilename } from "./FileUtils";
|
||||
import { linkClickModifierType, ModifierKeys } from "./ModifierkeyHelper";
|
||||
import { REG_BLOCK_REF_CLEAN, REG_SECTION_REF_CLEAN, VIEW_TYPE_EXCALIDRAW } from "src/constants/constants";
|
||||
import { EXCALIDRAW_PLUGIN, REG_BLOCK_REF_CLEAN, REG_SECTION_REF_CLEAN, VIEW_TYPE_EXCALIDRAW } from "src/constants/constants";
|
||||
import yaml from "js-yaml";
|
||||
import { debug, DEBUGGING } from "./DebugHelper";
|
||||
import ExcalidrawView from "src/ExcalidrawView";
|
||||
@@ -36,7 +36,7 @@ export const getLeaf = (
|
||||
ev: ModifierKeys
|
||||
) => {
|
||||
const newTab = ():WorkspaceLeaf => {
|
||||
if(!plugin.settings.openInMainWorkspace) return app.workspace.getLeaf('tab');
|
||||
if(!plugin.settings.openInMainWorkspace) return plugin.app.workspace.getLeaf('tab');
|
||||
const [leafLoc, mainLeavesIds] = getLeafLoc(origo);
|
||||
if(leafLoc === 'main') return plugin.app.workspace.getLeaf('tab');
|
||||
return getNewOrAdjacentLeaf(plugin,origo);
|
||||
@@ -56,7 +56,7 @@ export const getLeaf = (
|
||||
const getLeafLoc = (leaf: WorkspaceLeaf): ["main" | "popout" | "left" | "right" | "hover",any] => {
|
||||
//@ts-ignore
|
||||
const leafId = leaf.id;
|
||||
const layout = app.workspace.getLayout();
|
||||
const layout = EXCALIDRAW_PLUGIN.app.workspace.getLayout();
|
||||
const getLeaves = (l:any)=> l.children
|
||||
.filter((c:any)=>c.type!=="leaf")
|
||||
.map((c:any)=>getLeaves(c))
|
||||
@@ -95,7 +95,7 @@ export const getNewOrAdjacentLeaf = (
|
||||
const [leafLoc, mainLeavesIds] = getLeafLoc(leaf);
|
||||
|
||||
const getMostRecentOrAvailableLeafInMainWorkspace = (inDifferentTabGroup?: boolean):WorkspaceLeaf => {
|
||||
let mainLeaf = app.workspace.getMostRecentLeaf();
|
||||
let mainLeaf = plugin.app.workspace.getMostRecentLeaf();
|
||||
if(mainLeaf && mainLeaf !== leaf && mainLeaf.view?.containerEl.ownerDocument === document) {
|
||||
//Found a leaf in the main workspace that is not the originating leaf
|
||||
return mainLeaf;
|
||||
@@ -104,7 +104,7 @@ export const getNewOrAdjacentLeaf = (
|
||||
mainLeaf = null;
|
||||
mainLeavesIds
|
||||
.forEach((id:any)=> {
|
||||
const l = app.workspace.getLeafById(id);
|
||||
const l = plugin.app.workspace.getLeafById(id);
|
||||
if(mainLeaf ||
|
||||
!l.view?.navigation ||
|
||||
leaf === l ||
|
||||
@@ -121,28 +121,28 @@ export const getNewOrAdjacentLeaf = (
|
||||
//1.1 - Create new leaf in main workspace
|
||||
if(!plugin.settings.openInAdjacentPane) {
|
||||
if(leafLoc === "main") {
|
||||
return app.workspace.createLeafBySplit(leaf);
|
||||
return plugin.app.workspace.createLeafBySplit(leaf);
|
||||
}
|
||||
const ml = getMostRecentOrAvailableLeafInMainWorkspace();
|
||||
return ml
|
||||
? (ml.view.getViewType() === "empty" ? ml : app.workspace.createLeafBySplit(ml))
|
||||
: app.workspace.getLeaf(true);
|
||||
? (ml.view.getViewType() === "empty" ? ml : plugin.app.workspace.createLeafBySplit(ml))
|
||||
: plugin.app.workspace.getLeaf(true);
|
||||
}
|
||||
|
||||
//1.2 - Reuse leaf if it is adjacent
|
||||
const ml = getMostRecentOrAvailableLeafInMainWorkspace(true);
|
||||
return ml ?? app.workspace.createLeafBySplit(leaf); //app.workspace.getLeaf(true);
|
||||
return ml ?? plugin.app.workspace.createLeafBySplit(leaf); //app.workspace.getLeaf(true);
|
||||
}
|
||||
|
||||
//2
|
||||
if(!plugin.settings.openInAdjacentPane) {
|
||||
return app.workspace.createLeafBySplit(leaf);
|
||||
return plugin.app.workspace.createLeafBySplit(leaf);
|
||||
}
|
||||
|
||||
//3
|
||||
if(leafLoc === "hover") {
|
||||
const leaves = new Set<WorkspaceLeaf>();
|
||||
app.workspace.iterateAllLeaves(l=>{
|
||||
plugin.app.workspace.iterateAllLeaves(l=>{
|
||||
//@ts-ignore
|
||||
if(l!==leaf && leaf.containerEl.parentElement === l.containerEl.parentElement) leaves.add(l);
|
||||
})
|
||||
@@ -155,13 +155,13 @@ export const getNewOrAdjacentLeaf = (
|
||||
//4
|
||||
if(leafLoc === "popout") {
|
||||
const popoutLeaves = new Set<WorkspaceLeaf>();
|
||||
app.workspace.iterateAllLeaves(l=>{
|
||||
plugin.app.workspace.iterateAllLeaves(l=>{
|
||||
if(l !== leaf && l.view.navigation && l.view.containerEl.ownerDocument === leaf.view.containerEl.ownerDocument) {
|
||||
popoutLeaves.add(l);
|
||||
}
|
||||
});
|
||||
if(popoutLeaves.size === 0) {
|
||||
return app.workspace.createLeafBySplit(leaf);
|
||||
return plugin.app.workspace.createLeafBySplit(leaf);
|
||||
}
|
||||
return Array.from(popoutLeaves)[0];
|
||||
}
|
||||
@@ -201,12 +201,12 @@ export const isObsidianThemeDark = () => document.body.classList.contains("theme
|
||||
export type ConstructableWorkspaceSplit = new (ws: Workspace, dir: "horizontal"|"vertical") => WorkspaceSplit;
|
||||
|
||||
export const getContainerForDocument = (doc:Document) => {
|
||||
if (doc !== document && app.workspace.floatingSplit) {
|
||||
for (const container of app.workspace.floatingSplit.children) {
|
||||
if (doc !== document && EXCALIDRAW_PLUGIN.app.workspace.floatingSplit) {
|
||||
for (const container of EXCALIDRAW_PLUGIN.app.workspace.floatingSplit.children) {
|
||||
if (container.doc === doc) return container;
|
||||
}
|
||||
}
|
||||
return app.workspace.rootSplit;
|
||||
return EXCALIDRAW_PLUGIN.app.workspace.rootSplit;
|
||||
};
|
||||
|
||||
export const cleanSectionHeading = (heading:string) => {
|
||||
|
||||
@@ -533,7 +533,7 @@ export function setDocLeftHandedMode(isLeftHanded: boolean, ownerDocument:Docume
|
||||
|
||||
export function setLeftHandedMode (isLeftHanded: boolean) {
|
||||
const visitedDocs = new Set<Document>();
|
||||
app.workspace.iterateAllLeaves((leaf) => {
|
||||
EXCALIDRAW_PLUGIN.app.workspace.iterateAllLeaves((leaf) => {
|
||||
const ownerDocument = DEVICE.isMobile?document:leaf.view.containerEl.ownerDocument;
|
||||
if(!ownerDocument) return;
|
||||
if(visitedDocs.has(ownerDocument)) return;
|
||||
|
||||
Reference in New Issue
Block a user