Merge pull request #2160 from zsviczian/2.7.0-bugs

Fix ROOTELEMENTSIZE calc, view switch timestamp logic, update global app refs, minify packages, fix FileManager init, add 2.7.0 notes
This commit is contained in:
zsviczian
2024-12-17 18:01:02 +01:00
committed by GitHub
25 changed files with 164 additions and 86 deletions

View File

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

View File

@@ -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",

View File

@@ -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",

View File

@@ -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) {

View File

@@ -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

View File

@@ -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,

View File

@@ -2736,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
@@ -3568,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();
@@ -3718,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,
);
@@ -4310,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,
@@ -4373,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,

View File

@@ -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({

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -155,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
@@ -164,7 +169,7 @@ export const ROOTELEMENTSIZE = (() => {
const pixelSize = parseFloat(computedStyle.fontSize);
document.body.removeChild(tempElement);
return pixelSize;
})();
};
export const nanoid = customAlphabet(
"1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",

View File

@@ -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()) {

View File

@@ -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;

View File

@@ -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**:

View File

@@ -53,7 +53,7 @@ export class PenSettingsModal extends Modal {
private view: ExcalidrawView,
private pen: number,
) {
super(app);
super(plugin.app);
this.api = view.excalidrawAPI;
}

View File

@@ -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",

View File

@@ -37,6 +37,7 @@ import {
CJK_STYLE_ID,
updateExcalidrawLib,
loadMermaid,
setRootElementSize,
} from "./constants/constants";
import { ExcalidrawSettings, DEFAULT_SETTINGS, ExcalidrawSettingTab } from "./settings";
import { initExcalidrawAutomate, ExcalidrawAutomate } from "./ExcalidrawAutomate";
@@ -143,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
@@ -327,9 +332,11 @@ 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);
this.fileManager = new PluginFileManager(this);
this.eventManager = new EventManager(this);
this.observerManager = new ObserverManager(this);
this.commandManager = new CommandManager(this);
@@ -706,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");
@@ -983,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]);
@@ -1416,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;
}

View File

@@ -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

View File

@@ -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(

View File

@@ -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;
}

View File

@@ -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,
);

View File

@@ -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(

View File

@@ -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) => {

View File

@@ -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;