This commit is contained in:
Zsolt Viczian
2022-08-19 21:01:11 +02:00
parent fdb7e97b11
commit 334e8130eb
15 changed files with 351 additions and 283 deletions

View File

@@ -92,7 +92,7 @@ export class EmbeddedFile {
if (!this.linkParts.height) {
this.linkParts.height = this.plugin.settings.mdSVGmaxHeight;
}
this.file = this.plugin.app.metadataCache.getFirstLinkpathDest(
this.file = app.metadataCache.getFirstLinkpathDest(
this.linkParts.path,
hostPath,
);
@@ -108,7 +108,7 @@ export class EmbeddedFile {
private fileChanged(): boolean {
if (!this.file) {
this.file = this.plugin.app.metadataCache.getFirstLinkpathDest(
this.file = app.metadataCache.getFirstLinkpathDest(
this.linkParts.path,
this.hostPath,
); // maybe the file has synchronized in the mean time
@@ -149,7 +149,7 @@ export class EmbeddedFile {
public isLoaded(isDark: boolean): boolean {
if (!this.file) {
this.file = this.plugin.app.metadataCache.getFirstLinkpathDest(
this.file = app.metadataCache.getFirstLinkpathDest(
this.linkParts.path,
this.hostPath,
); // maybe the file has synchronized in the mean time
@@ -218,7 +218,6 @@ export class EmbeddedFilesLoader {
};
let hasSVGwithBitmap = false;
const app = this.plugin.app;
const isExcalidrawFile = this.plugin.isExcalidrawFile(file);
if (
!(

View File

@@ -1141,7 +1141,7 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
*/
setView(view: ExcalidrawView | "first" | "active"): ExcalidrawView {
if (view == "active") {
const v = this.plugin.app.workspace.getActiveViewOfType(ExcalidrawView);
const v = app.workspace.getActiveViewOfType(ExcalidrawView);
if (!(v instanceof ExcalidrawView)) {
return;
}
@@ -1149,7 +1149,7 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
}
if (view == "first") {
const leaves =
this.plugin.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
if (!leaves || leaves.length == 0) {
return;
}
@@ -1283,7 +1283,7 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
* @returns
*/
viewToggleFullScreen(forceViewMode: boolean = false): void {
if (this.plugin.app.isMobile) {
if (app.isMobile) {
errorMessage("mobile not supported", "viewToggleFullScreen()");
return;
}
@@ -1618,7 +1618,7 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
return null;
}
const leaf = getNewOrAdjacentLeaf(this.plugin, this.targetView.leaf);
leaf.openFile(file, {active: false});
leaf.openFile(file, {active: true});
return leaf;
};
@@ -2008,7 +2008,9 @@ async function getTemplate(
let groupElements:ExcalidrawElement[] = scene.elements;
if(filenameParts.hasGroupref) {
const el = scene.elements.filter((el: ExcalidrawElement) => el.id === filenameParts.blockref);
const el = filenameParts.hasSectionref
? getTextElementsMatchingQuery(scene.elements,["# "+filenameParts.sectionref],true)
: scene.elements.filter((el: ExcalidrawElement)=>el.id===filenameParts.blockref);
if(el.length > 0) {
groupElements = plugin.ea.getElementsInTheSameGroupWithElement(el[0],scene.elements)
}
@@ -2094,6 +2096,7 @@ export async function createSVG(
: null;
let elements = template?.elements ?? [];
elements = elements.concat(automateElements);
padding = padding ?? plugin.settings.exportPaddingSVG;
const svg = await getSVG(
{
//createAndOpenDrawing
@@ -2113,8 +2116,29 @@ export async function createSVG(
exportSettings?.withBackground ?? plugin.settings.exportWithBackground,
withTheme: exportSettings?.withTheme ?? plugin.settings.exportWithTheme,
},
padding ?? plugin.settings.exportPaddingSVG,
padding,
);
const filenameParts = getEmbeddedFilenameParts(templatePath);
if(
!filenameParts.hasGroupref &&
(filenameParts.hasBlockref || filenameParts.hasSectionref)
) {
let el = filenameParts.hasSectionref
? getTextElementsMatchingQuery(elements,["# "+filenameParts.sectionref],true)
: elements.filter((el: ExcalidrawElement)=>el.id===filenameParts.blockref);
if(el.length>0) {
const containerId = el[0].containerId;
if(containerId) {
el = el.concat(elements.filter((el: ExcalidrawElement)=>el.id === containerId));
}
const elBB = plugin.ea.getBoundingBox(el);
const drawingBB = plugin.ea.getBoundingBox(elements);
svg.viewBox.baseVal.x = elBB.topX - drawingBB.topX;
svg.viewBox.baseVal.y = elBB.topY - drawingBB.topY;
svg.viewBox.baseVal.width = elBB.width + 2*padding;
svg.viewBox.baseVal.height = elBB.height + 2*padding;
}
}
if (template?.hasSVGwithBitmap) {
svg.setAttribute("hasbitmap", "true");
}
@@ -2242,3 +2266,35 @@ export const search = async (view: ExcalidrawView) => {
ea.targetView.selectElementsMatchingQuery(elements, query);
};
/**
*
* @param elements
* @param query
* @param exactMatch - when searching for section header exactMatch should be set to true
* @returns the elements matching the query
*/
export const getTextElementsMatchingQuery = (
elements: ExcalidrawElement[],
query: string[],
exactMatch: boolean = false, //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/530
): ExcalidrawElement[] => {
if (!elements || elements.length === 0 || !query || query.length === 0) {
return [];
}
return elements.filter((el: any) =>
el.type === "text" &&
query.some((q) => {
if (exactMatch) {
const text = el.rawText.toLowerCase().split("\n")[0].trim();
const m = text.match(/^#*(# .*)/);
if (!m || m.length !== 2) {
return false;
}
return m[1] === q.toLowerCase();
}
const text = el.rawText.toLowerCase().replaceAll("\n", " ").trim();
return text.match(q.toLowerCase()); //to distinguish between "# frame" and "# frame 1" https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/530
}));
}

View File

@@ -9,6 +9,7 @@ import {
MarkdownView,
request,
Platform,
requireApiVersion,
} from "obsidian";
//import * as React from "react";
//import * as ReactDOM from "react-dom";
@@ -42,7 +43,7 @@ import {
LOCAL_PROTOCOL,
} from "./Constants";
import ExcalidrawPlugin from "./main";
import { repositionElementsToCursor, ExcalidrawAutomate } from "./ExcalidrawAutomate";
import { repositionElementsToCursor, ExcalidrawAutomate, getTextElementsMatchingQuery } from "./ExcalidrawAutomate";
import { t } from "./lang/helpers";
import {
ExcalidrawData,
@@ -57,10 +58,12 @@ import {
getNewUniqueFilepath,
} from "./utils/FileUtils";
import {
awaitNextAnimationFrame,
checkExcalidrawVersion,
debug,
embedFontsInSVG,
errorlog,
getEmbeddedFilenameParts,
getExportTheme,
getLinkParts,
getPNG,
@@ -69,6 +72,7 @@ import {
getSVGPadding,
getWithBackground,
hasExportTheme,
isVersionNewerThanOther,
scaleLoadedImage,
svgToBase64,
viewportCoordsToSceneCoords,
@@ -89,6 +93,8 @@ import { ToolsPanel } from "./menu/ToolsPanel";
import { ScriptEngine } from "./Scripts";
import { getTextElementAtPointer, getImageElementAtPointer, getElementWithLinkAtPointer } from "./utils/GetElementAtPointer";
import { execArgv } from "process";
import { findLastIndex } from "@zsviczian/excalidraw/types/utils";
import { fileOpen } from "@zsviczian/excalidraw/types/data/filesystem";
export enum TextMode {
@@ -131,7 +137,7 @@ export const addFiles = async (
}
if (s.dirty) {
//debug({where:"ExcalidrawView.addFiles",file:view.file.name,dataTheme:view.excalidrawData.scene.appState.theme,before:"updateScene",state:scene.appState})
view.updateScene({
await view.updateScene({
elements: s.scene.elements,
appState: s.scene.appState,
commitToHistory: false,
@@ -315,7 +321,7 @@ export default class ExcalidrawView extends TextFileView {
}
filename = `${filename}.excalidraw`;
const folderpath = splitFolderAndFilename(this.file.path).folderpath;
await checkAndCreateFolder(app.vault, folderpath); //create folder if it does not exist
await checkAndCreateFolder(folderpath); //create folder if it does not exist
const fname = getNewUniqueFilepath(
app.vault,
filename,
@@ -1024,6 +1030,7 @@ export default class ExcalidrawView extends TextFileView {
});
this.setupAutosaveTimer();
super.onload();
}
//this is to solve sliding panes bug
@@ -1278,7 +1285,7 @@ export default class ExcalidrawView extends TextFileView {
this.clearDirty();
}
async zoomToElementId(id: string) {
async zoomToElementId(id: string, hasGroupref:boolean) {
let counter = 0;
while (!this.excalidrawAPI && counter++<100) await sleep(50); //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/734
const api = this.excalidrawAPI;
@@ -1286,17 +1293,14 @@ export default class ExcalidrawView extends TextFileView {
return;
}
const sceneElements = api.getSceneElements();
let elements = sceneElements.filter((el: ExcalidrawElement) => el.id === id);
if(elements.length === 0) {
if(!id.startsWith("group_")) return;
id = id.split("group_")[1];
elements = sceneElements.filter((el: ExcalidrawElement) => el.id === id);
if(elements.length === 0) return;
if(elements.length === 0) return;
if(hasGroupref) {
const groupElements = this.plugin.ea.getElementsInTheSameGroupWithElement(elements[0],sceneElements)
if(groupElements.length>0) {
elements = groupElements;
}
if(elements.length === 0) return;
}
this.preventAutozoom();
@@ -1325,16 +1329,13 @@ export default class ExcalidrawView extends TextFileView {
];
}
if (state.subpath && state.subpath.length > 2) {
if (state.subpath[1] === "^") {
const id = state.subpath.substring(2);
setTimeout(() => self.zoomToElementId(id), 300);
} else {
query = [`# ${state.subpath.substring(1)}`];
}
const filenameParts = getEmbeddedFilenameParts(state.subpath);
if(filenameParts.hasBlockref) {
setTimeout(()=>self.zoomToElementId(filenameParts.blockref, filenameParts.hasGroupref),300);
}
if (state.line && state.line > 0) {
if(filenameParts.hasSectionref) {
query = [`# ${filenameParts.sectionref}`]
} else if (state.line && state.line > 0) {
query = [this.data.split("\n")[state.line - 1]];
}
@@ -1347,14 +1348,14 @@ export default class ExcalidrawView extends TextFileView {
if (!api) {
return;
}
const elements = api
.getSceneElements()
.filter((el: ExcalidrawElement) => el.type === "text");
const elements = api.getSceneElements();
self.selectElementsMatchingQuery(
elements,
query,
!api.getAppState().viewModeEnabled,
state.subpath && state.subpath.length>2 && state.subpath[1]!=="^",
filenameParts.hasSectionref,
filenameParts.hasGroupref
);
}, 300);
}
@@ -1615,7 +1616,7 @@ export default class ExcalidrawView extends TextFileView {
if(this.getSceneVersion(inData.scene.elements) !== this.previousSceneVersion) {
this.setDirty(3);
}
this.excalidrawAPI.updateScene({elements: sceneElements});
await this.updateScene({elements: sceneElements});
if(reloadFiles) this.loadSceneFiles();
} catch(e) {
errorlog({
@@ -1655,7 +1656,7 @@ export default class ExcalidrawView extends TextFileView {
//debug({where:"ExcalidrawView.loadDrawing",file:this.file.name,dataTheme:excalidrawData.appState.theme,before:"updateScene"})
api.setLocalFont(this.plugin.settings.experimentalEnableFourthFont);
this.updateScene(
await this.updateScene(
{
elements: excalidrawData.elements.concat(deletedElements??[]), //need to preserve deleted elements during autosave if images, links, etc. are updated
appState: {
@@ -1727,6 +1728,12 @@ export default class ExcalidrawView extends TextFileView {
//console.log(debug);
this.semaphores.dirty = this.file?.path;
this.diskIcon.querySelector("svg").addClass("excalidraw-dirty");
if(!app.isMobile) {
if(requireApiVersion("0.16.0")) {
//@ts-ignore
this.leaf.tabHeaderInnerTitleEl.style.color="var(--color-accent)"
}
}
}
public clearDirty() {
@@ -1740,6 +1747,12 @@ export default class ExcalidrawView extends TextFileView {
this.previousSceneVersion = this.getSceneVersion(el);
}
this.diskIcon.querySelector("svg").removeClass("excalidraw-dirty");
if(!app.isMobile) {
if(requireApiVersion("0.16.0")) {
//@ts-ignore
this.leaf.tabHeaderInnerTitleEl.style.color=""
}
}
}
public initializeToolsIconPanelAfterLoading() {
@@ -1801,6 +1814,7 @@ export default class ExcalidrawView extends TextFileView {
this.plugin.openDrawing(
await this.plugin.convertSingleExcalidrawToMD(this.file),
"active-pane",
true
);
}
@@ -2270,12 +2284,13 @@ export default class ExcalidrawView extends TextFileView {
const elements = newElementsOnTop
? el.concat(newElements.filter((e) => !removeList.includes(e.id)))
: newElements.filter((e) => !removeList.includes(e.id)).concat(el);
this.updateScene({
await this.updateScene({
elements,
commitToHistory: true,
});
if (images) {
if (images && images !== {}) {
const files: BinaryFileData[] = [];
Object.keys(images).forEach((k) => {
files.push({
@@ -3140,7 +3155,7 @@ export default class ExcalidrawView extends TextFileView {
: this.leaf;
await leaf.openFile(
file,
subpath ? { active: false, eState: { subpath } } : {active:false},
subpath ? { active: false, eState: { subpath } } : {active:false}, //active false: to avoid taking the focus from ExcaliBrain
); //if file exists open file and jump to reference
//app.workspace.setActiveLeaf(leaf, true, true); //0.15.4 ExcaliBrain focus issue
} catch (e) {
@@ -3300,30 +3315,26 @@ export default class ExcalidrawView extends TextFileView {
query: string[],
selectResult: boolean = true,
exactMatch: boolean = false, //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/530
selectGroup: boolean = false,
) {
if (!elements || elements.length === 0 || !query || query.length === 0) {
return;
}
const match = elements.filter((el: any) =>
query.some((q) => {
if (exactMatch) {
const text = el.rawText.toLowerCase().split("\n")[0].trim();
const m = text.match(/^#*(# .*)/);
if (!m || m.length !== 2) {
return false;
}
return m[1] === q.toLowerCase();
}
const text = el.rawText.toLowerCase().replaceAll("\n", " ").trim();
return text.match(q.toLowerCase()); //to distinguish between "# frame" and "# frame 1" https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/530
}),
let match = getTextElementsMatchingQuery(
elements.filter((el: ExcalidrawElement) => el.type === "text"),
query,
exactMatch
);
if (match.length === 0) {
new Notice("I could not find a matching text element");
return;
}
if(selectGroup) {
const groupElements = this.plugin.ea.getElementsInTheSameGroupWithElement(match[0],elements)
if(groupElements.length>0) {
match = groupElements;
}
}
this.zoomToElements(selectResult,match);
}
@@ -3388,7 +3399,7 @@ export default class ExcalidrawView extends TextFileView {
.filter((el: ExcalidrawElement) => elementIDs.contains(el.id));
}
public async copyLinkToSelectedElementToClipboard() {
public async copyLinkToSelectedElementToClipboard(groupLink:boolean) {
const elements = this.getViewSelectedElements();
if (elements.length < 1) {
new Notice(t("INSERT_LINK_TO_ELEMENT_ERROR"));
@@ -3405,12 +3416,12 @@ export default class ExcalidrawView extends TextFileView {
"",
);
navigator.clipboard.writeText(
`[[${this.file.path}#^${elementId}${alias ? `|${alias}` : ``}]]`,
`[[${this.file.path}#^${groupLink?"group=":""}${elementId}${alias ? `|${alias}` : ``}]]`,
);
new Notice(t("INSERT_LINK_TO_ELEMENT_READY"));
}
public updateScene(
public async updateScene(
scene: {
elements?: ExcalidrawElement[];
appState?: any;
@@ -3428,6 +3439,7 @@ export default class ExcalidrawView extends TextFileView {
scene.elements = api.restore(scene).elements;
}
try {
await awaitNextAnimationFrame(); //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/747
api.updateScene(scene);
} catch (e) {
errorlog({
@@ -3440,6 +3452,7 @@ export default class ExcalidrawView extends TextFileView {
if (!shouldRestoreElements) {
//second attempt
try {
await awaitNextAnimationFrame(); //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/747
scene.elements = api.restore(scene).elements;
api.updateScene(scene);
} catch (e) {
@@ -3455,6 +3468,7 @@ export default class ExcalidrawView extends TextFileView {
warningUnknowSeriousError();
}
}
await awaitNextAnimationFrame()
}
}

View File

@@ -22,6 +22,7 @@ import {
} from "./utils/Utils";
import { isObsidianThemeDark } from "./utils/ObsidianUtils";
import { splitFolderAndFilename } from "./utils/FileUtils";
import * as internal from "stream";
interface imgElementAttributes {
file?: TFile;
@@ -120,10 +121,18 @@ const getIMG = async (
scale = 5;
}
//In case of PNG I cannot change the viewBox to select the area of the element
//being referenced. For PNG only the group reference works
const quickPNG = !filenameParts.hasGroupref
? await getQuickImagePreview(plugin, file.path, "png")
: undefined;
const png =
(await getQuickImagePreview(plugin, file.path, "png")) ??
quickPNG ??
(await createPNG(
file.path,
filenameParts.hasGroupref
? filenameParts.filepath + filenameParts.linkpartReference
: file.path,
scale,
exportSettings,
loader,
@@ -140,14 +149,17 @@ const getIMG = async (
img.src = URL.createObjectURL(png);
return img;
}
const quickSVG = await getQuickImagePreview(plugin, file.path, "svg");
if (quickSVG) {
img.setAttribute("src", svgToBase64(quickSVG));
return img;
if(!(filenameParts.hasBlockref || filenameParts.hasSectionref)) {
const quickSVG = await getQuickImagePreview(plugin, file.path, "svg");
if (quickSVG) {
img.setAttribute("src", svgToBase64(quickSVG));
return img;
}
}
const svgSnapshot = (
await createSVG(
filenameParts.hasGroupref
filenameParts.hasGroupref || filenameParts.hasBlockref || filenameParts.hasSectionref
? filenameParts.filepath + filenameParts.linkpartReference
: file.path,
true,
@@ -185,7 +197,7 @@ const createImageDiv = async (
const img = await getIMG(attr);
return createDiv(attr.style, (el) => {
el.append(img);
el.setAttribute("src", attr.file.path);
el.setAttribute("src", attr.fname);
if (attr.fwidth) {
el.setAttribute("w", attr.fwidth);
}
@@ -201,13 +213,17 @@ const createImageDiv = async (
}
const src = el.getAttribute("src");
if (src) {
const srcParts = src.match(/([^#]*)(.*)/);
if(!srcParts) return;
plugin.openDrawing(
vault.getAbstractFileByPath(src) as TFile,
vault.getAbstractFileByPath(srcParts[1]) as TFile,
ev[CTRL_OR_CMD]
? "new-pane"
: (ev.metaKey && !app.isMobile)
? "popout-window"
: "active-pane",
true,
srcParts[2],
);
} //.ctrlKey||ev.metaKey);
});
@@ -225,51 +241,56 @@ const createImageDiv = async (
});
};
const processInternalEmbeds = async (
const processReadingMode = async (
embeddedItems: NodeListOf<Element> | [HTMLElement],
ctx: MarkdownPostProcessorContext,
) => {
//if not, then we are processing a non-excalidraw file in reading mode
//in that cases embedded files will be displayed in an .internal-embed container
//We are processing a non-excalidraw file in reading mode
//Embedded files will be displayed in an .internal-embed container
//Iterating all the containers in the file to check which one is an excalidraw drawing
//This is a for loop instead of embeddedItems.forEach() because processInternalEmbed at the end
//is awaited, otherwise excalidraw images would not display in the Kanban plugin
for (const maybeDrawing of embeddedItems) {
//check to see if the file in the src attribute exists
const fname = maybeDrawing.getAttribute("src")?.split("#")[0];
if(!fname) continue;
const file = metadataCache.getFirstLinkpathDest(fname, ctx.sourcePath);
//if the embeddedFile exits and it is an Excalidraw file
//then lets replace the .internal-embed with the generated PNG or SVG image
if (file && file instanceof TFile && plugin.isExcalidrawFile(file)) {
maybeDrawing.parentElement.replaceChild(
await processInternalEmbed(maybeDrawing,file),
maybeDrawing
);
}
}
};
const processInternalEmbed = async (internalEmbedEl: Element, file: TFile ):Promise<HTMLDivElement> => {
const attr: imgElementAttributes = {
fname: "",
fheight: "",
fwidth: "",
style: "",
};
let alt: string;
let file: TFile;
//Iterating through all the containers to check which one is an excalidraw drawing
//This is a for loop instead of embeddedItems.forEach() because createImageDiv at the end
//is awaited, otherwise excalidraw images would not display in the Kanban plugin
for (const maybeDrawing of embeddedItems) {
//check to see if the file in the src attribute exists
attr.fname = maybeDrawing.getAttribute("src");
const fname = attr.fname?.split("#")[0]??"";
file = metadataCache.getFirstLinkpathDest(fname, ctx.sourcePath);
//if the embeddedFile exits and it is an Excalidraw file
//then lets replace the .internal-embed with the generated PNG or SVG image
if (file && file instanceof TFile && plugin.isExcalidrawFile(file)) {
attr.fwidth = maybeDrawing.getAttribute("width")
? maybeDrawing.getAttribute("width")
: getDefaultWidth(plugin);
attr.fheight = maybeDrawing.getAttribute("height");
alt = maybeDrawing.getAttribute("alt");
if (alt === attr.fname) {
alt = "";
} //when the filename starts with numbers followed by a space Obsidian recognizes the filename as alt-text
attr.style = "excalidraw-svg";
processAltText(fname,alt,attr);
const fnameParts = getEmbeddedFilenameParts(attr.fname);
attr.fname = file?.path + (fnameParts.hasBlockref?fnameParts.linkpartReference:"");
attr.file = file;
const div = await createImageDiv(attr);
maybeDrawing.parentElement.replaceChild(div, maybeDrawing);
}
}
};
const src = internalEmbedEl.getAttribute("src");
if(!src) return;
attr.fwidth = internalEmbedEl.getAttribute("width")
? internalEmbedEl.getAttribute("width")
: getDefaultWidth(plugin);
attr.fheight = internalEmbedEl.getAttribute("height");
let alt = internalEmbedEl.getAttribute("alt");
attr.style = "excalidraw-svg";
processAltText(src.split("#")[0],alt,attr);
const fnameParts = getEmbeddedFilenameParts(src);
attr.fname = file?.path + (fnameParts.hasBlockref||fnameParts.hasSectionref?fnameParts.linkpartReference:"");
attr.file = file;
return await createImageDiv(attr);
}
const processAltText = (
fname: string,
@@ -282,7 +303,14 @@ const processAltText = (
attr.fwidth = parts[2] ?? attr.fwidth;
attr.fheight = parts[3] ?? attr.fheight;
if (parts[4] && !parts[4].startsWith(fname)) {
attr.style = `excalidraw-svg${parts[4] ? `-${parts[4]}` : ""}`;
attr.style = `excalidraw-svg${`-${parts[4]}`}`;
}
if (
(!parts[4] || parts[4]==="") &&
(!parts[2] || parts[2]==="") &&
parts[0] && parts[0] !== ""
) {
attr.style = `excalidraw-svg${`-${parts[0]}`}`;
}
}
}
@@ -300,44 +328,9 @@ const tmpObsidianWYSIWYG = async (
return;
}
//@ts-ignore
const dataHeading = el.firstChild?.getAttribute("data-heading");
const blockrefToUnrecognizedTarget = dataHeading?.startsWith("Unable to find section")
if (!blockrefToUnrecognizedTarget && !el.querySelector(".frontmatter")) {
el.style.display = "none";
return;
}
let blockref = "";
if(blockrefToUnrecognizedTarget) {
const reg = new RegExp(`Unable to find section (.*) in ${file.basename}`);
const m = dataHeading.match(/Unable to find section (.*) in 1test/);
if(m && m.length>0) {
blockref = m[1];
}
}
const attr: imgElementAttributes = {
fname: ctx.sourcePath+blockref,
fheight: "",
fwidth: getDefaultWidth(plugin),
style: "excalidraw-svg",
};
attr.file = file;
el.empty();
if (!plugin.settings.experimentalLivePreview) {
el.appendChild(await createImageDiv(attr));
return;
}
const div = createDiv();
el.appendChild(div);
//The timeout gives time for obsidian to attach el to the displayed document
//The timeout gives time for Obsidian to attach el to the displayed document
//Once the element is attached, I can traverse up the dom tree to find .internal-embed
//If internal embed is not found, it means the that the excalidraw.md file
//is being rendered in "reading" mode. In that case, the image with the default width
@@ -350,8 +343,7 @@ const tmpObsidianWYSIWYG = async (
while(!el.parentElement && counter++<=50) await sleep(50);
if(!el.parentElement) return;
let internalEmbedDiv: HTMLElement = div;
let internalEmbedDiv: HTMLElement = el;
while (
!internalEmbedDiv.hasClass("internal-embed") &&
internalEmbedDiv.parentElement
@@ -359,57 +351,39 @@ const tmpObsidianWYSIWYG = async (
internalEmbedDiv = internalEmbedDiv.parentElement;
}
const attr: imgElementAttributes = {
fname: ctx.sourcePath,
fheight: "",
fwidth: getDefaultWidth(plugin),
style: "excalidraw-svg",
};
attr.file = file;
if (!internalEmbedDiv.hasClass("internal-embed")) {
//We are processing the markdown preview of an actual Excalidraw file
//This could be in a hover preview of the file
//Or the file could be in markdown mode and the user switched markdown
//view of the drawing to reading mode
const mdPreviewSection = el.parentElement;
if(!mdPreviewSection.hasClass("markdown-preview-section")) return;
if(mdPreviewSection.hasAttribute("ready")) {
mdPreviewSection.removeChild(el);
return;
}
mdPreviewSection.setAttribute("ready","");
el.empty();
el.appendChild(await createImageDiv(attr));
const imgDiv = await createImageDiv(attr);
el.appendChild(imgDiv);
return;
}
if(internalEmbedDiv.hasAttribute("ready")) return;
internalEmbedDiv.setAttribute("ready","");
internalEmbedDiv.empty();
const basename = splitFolderAndFilename(attr.fname).basename;
const setAttr = () => {
const hasWidth = internalEmbedDiv.getAttribute("width") && (internalEmbedDiv.getAttribute("width") !== "");
const hasHeight = internalEmbedDiv.getAttribute("height") && (internalEmbedDiv.getAttribute("height") !== "");
if (hasWidth) {
attr.fwidth = internalEmbedDiv.getAttribute("width");
}
if (hasHeight) {
attr.fheight = internalEmbedDiv.getAttribute("height");
}
if (!hasWidth && !hasHeight) {
attr.fheight = "";
attr.fwidth = getDefaultWidth(plugin);
attr.style = "excalidraw-svg";
}
const alt = internalEmbedDiv.getAttribute("alt");
processAltText(basename,alt,attr);
/* const hasAttr =
alt &&
alt !== "" &&
alt !== basename &&
alt !== internalEmbedDiv.getAttribute("src") &&
!alt.startsWith(attr.file.name + " > ");
if (hasAttr) {
//1:width, 2:height, 3:style 1 2 3
const parts = alt.match(/(\d*%?)x?(\d*%?)\|?(.*)/);
attr.fwidth = parts[1] ? parts[1] : getDefaultWidth(plugin);
attr.fheight = parts[2];
if (parts[3] != attr.fname) {
attr.style = `excalidraw-svg${parts[3] ? `-${parts[3]}` : ""}`;
}
}*/
};
const createImgElement = async () => {
setAttr();
const imgDiv = await createImageDiv(attr);
internalEmbedDiv.appendChild(imgDiv);
};
await createImgElement();
const imgDiv = await processInternalEmbed(internalEmbedDiv,file);
internalEmbedDiv.appendChild(imgDiv);
//timer to avoid the image flickering when the user is typing
let timer: NodeJS.Timeout = null;
@@ -420,11 +394,11 @@ const tmpObsidianWYSIWYG = async (
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
timer = setTimeout(async () => {
timer = null;
setAttr();
internalEmbedDiv.empty();
createImgElement();
const imgDiv = await processInternalEmbed(internalEmbedDiv,file);
internalEmbedDiv.appendChild(imgDiv);
}, 500);
});
observer.observe(internalEmbedDiv, {
@@ -459,7 +433,7 @@ export const markdownPostProcessor = async (
return;
}
await processInternalEmbeds(embeddedItems, ctx);
await processReadingMode(embeddedItems, ctx);
};
/**

View File

@@ -34,7 +34,7 @@ export class ScriptEngine {
if (!path.endsWith(".svg")) {
return;
}
const scriptFile = this.plugin.app.vault.getAbstractFileByPath(
const scriptFile = app.vault.getAbstractFileByPath(
getIMGFilename(path, "md"),
);
if (scriptFile && scriptFile instanceof TFile) {
@@ -53,7 +53,7 @@ export class ScriptEngine {
handleSvgFileChange(file.path);
};
this.plugin.registerEvent(
this.plugin.app.vault.on("delete", deleteEventHandler),
app.vault.on("delete", deleteEventHandler),
);
const createEventHandler = async (file: TFile) => {
@@ -67,7 +67,7 @@ export class ScriptEngine {
handleSvgFileChange(file.path);
};
this.plugin.registerEvent(
this.plugin.app.vault.on("create", createEventHandler),
app.vault.on("create", createEventHandler),
);
const renameEventHandler = async (file: TAbstractFile, oldPath: string) => {
@@ -86,7 +86,7 @@ export class ScriptEngine {
}
};
this.plugin.registerEvent(
this.plugin.app.vault.on("rename", renameEventHandler),
app.vault.on("rename", renameEventHandler),
);
}
@@ -101,7 +101,6 @@ export class ScriptEngine {
}
public getListofScripts(): TFile[] {
const app = this.plugin.app;
this.scriptPath = this.plugin.settings.scriptFolderPath;
if (!app.vault.getAbstractFileByPath(this.scriptPath)) {
this.scriptPath = null;
@@ -140,10 +139,10 @@ export class ScriptEngine {
async addScriptIconToMap(scriptPath: string, name: string) {
const svgFilePath = getIMGFilename(scriptPath, "svg");
const file = this.plugin.app.vault.getAbstractFileByPath(svgFilePath);
const file = app.vault.getAbstractFileByPath(svgFilePath);
const svgString: string =
file && file instanceof TFile
? await this.plugin.app.vault.read(file)
? await app.vault.read(file)
: null;
this.scriptIconMap = {
...this.scriptIconMap,
@@ -168,7 +167,7 @@ export class ScriptEngine {
const view = app.workspace.getActiveViewOfType(ExcalidrawView);
if (view) {
(async()=>{
const script = await this.plugin.app.vault.read(f);
const script = await app.vault.read(f);
if(script) {
this.executeScript(view, script, scriptName);
}
@@ -181,7 +180,6 @@ export class ScriptEngine {
}
unloadScripts() {
const app = this.plugin.app;
const scripts = app.vault
.getFiles()
.filter((f: TFile) => f.path.startsWith(this.scriptPath));
@@ -198,7 +196,6 @@ export class ScriptEngine {
this.scriptIconMap = { ...this.scriptIconMap };
this.updateToolPannels();
const app = this.plugin.app;
const commandId = `${PLUGIN_ID}:${basename}`;
// @ts-ignore
if (!app.commands.commands[commandId]) {
@@ -229,7 +226,7 @@ export class ScriptEngine {
buttons?: [{ caption: string; action: Function }],
) =>
ScriptEngine.inputPrompt(
this.plugin.app,
app,
header,
placeholder,
value,
@@ -242,7 +239,7 @@ export class ScriptEngine {
instructions?: Instruction[],
) =>
ScriptEngine.suggester(
this.plugin.app,
app,
displayItems,
items,
hint,
@@ -259,7 +256,7 @@ export class ScriptEngine {
private updateToolPannels() {
const leaves =
this.plugin.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
leaves.forEach((leaf: WorkspaceLeaf) => {
const excalidrawView = leaf.view as ExcalidrawView;
excalidrawView.toolsPanelRef?.current?.updateScriptIconMap(

View File

@@ -55,7 +55,7 @@ export class OpenFileDialog extends FuzzySuggestModal<TFile> {
onChooseItem(item: TFile): void {
switch (this.action) {
case openDialogAction.openFile:
this.plugin.openDrawing(item, this.onNewPane?"new-pane":"active-pane");
this.plugin.openDrawing(item, this.onNewPane?"new-pane":"active-pane",true);
break;
case openDialogAction.insertLinkToDrawing:
this.plugin.embedDrawing(item);

View File

@@ -13,6 +13,7 @@ import ExcalidrawView from "../ExcalidrawView";
import ExcalidrawPlugin from "../main";
import { sleep } from "../utils/Utils";
import { getNewOrAdjacentLeaf } from "../utils/ObsidianUtils";
import { checkAndCreateFolder, splitFolderAndFilename } from "src/utils/FileUtils";
export class Prompt extends Modal {
private promptEl: HTMLInputElement;
@@ -434,6 +435,8 @@ export class NewFileActions extends Modal {
if (!this.path.match(/\.md$/)) {
this.path = `${this.path}.md`;
}
const folderpath = splitFolderAndFilename(this.path).folderpath;
checkAndCreateFolder(folderpath);
const f = await this.app.vault.create(this.path, data);
return f;
};

View File

@@ -28,6 +28,7 @@ export default {
"Open an existing drawing - IN THE CURRENT ACTIVE PANE",
TRANSCLUDE: "Transclude (embed) a drawing",
TRANSCLUDE_MOST_RECENT: "Transclude (embed) the most recently edited drawing",
TOGGLE_LEFTHANDED_MODE: "Toggle left-handed mode",
NEW_IN_NEW_PANE: "Create a new drawing - IN A NEW PANE",
NEW_IN_ACTIVE_PANE: "Create a new drawing - IN THE CURRENT ACTIVE PANE",
NEW_IN_POPOUT_WINDOW: "Create a new drawing - IN A POPOUT WINDOW",
@@ -41,7 +42,11 @@ export default {
TOGGLE_LOCK: "Toggle Text Element edit RAW/PREVIEW",
DELETE_FILE: "Delete selected Image or Markdown file from Obsidian Vault",
INSERT_LINK_TO_ELEMENT:
"Copy markdown link for selected element to clipboard",
"Copy markdown link for selected element to clipboard. CTRL/CMD+Click to copy group link.",
INSERT_LINK_TO_ELEMENT_GROUP:
"Copy markdown link for selected element group to clipboard.",
INSERT_LINK_TO_ELEMENT_NORMAL:
"Copy markdown link for selected element to clipboard.",
INSERT_LINK_TO_ELEMENT_ERROR: "Select a single element in the scene",
INSERT_LINK_TO_ELEMENT_READY: "Link is READY and available on the clipboard",
INSERT_LINK: "Insert link to file",

View File

@@ -312,10 +312,10 @@ export default class ExcalidrawPlugin extends Plugin {
//@ts-ignore
win.MathJax.startup.pagePromise.then(async () => {
//https://github.com/xldenis/obsidian-latex/blob/master/main.ts
const file = self.app.vault.getAbstractFileByPath("preamble.sty");
const file = app.vault.getAbstractFileByPath("preamble.sty");
const preamble: string =
file && file instanceof TFile
? await self.app.vault.read(file)
? await app.vault.read(file)
: null;
try {
if (preamble) {
@@ -348,7 +348,7 @@ export default class ExcalidrawPlugin extends Plugin {
const self = this;
this.app.workspace.onLayoutReady(() => {
let leaf: WorkspaceLeaf;
for (leaf of self.app.workspace.getLeavesOfType("markdown")) {
for (leaf of app.workspace.getLeavesOfType("markdown")) {
if (
leaf.view instanceof MarkdownView &&
self.isExcalidrawFile(leaf.view.file)
@@ -455,7 +455,7 @@ export default class ExcalidrawPlugin extends Plugin {
if (file) {
await this.app.vault.modify(file as TFile, data);
} else {
await checkAndCreateFolder(this.app.vault, folder);
await checkAndCreateFolder(folder);
file = await this.app.vault.create(localPath, data);
}
return file;
@@ -835,7 +835,7 @@ export default class ExcalidrawPlugin extends Plugin {
).folder;
const file = await this.createDrawing(filename, folder);
await this.embedDrawing(file);
this.openDrawing(file, location);
this.openDrawing(file, location, true);
};
this.addCommand({
@@ -1044,20 +1044,62 @@ export default class ExcalidrawPlugin extends Plugin {
this.addCommand({
id: "insert-link-to-element",
hotkeys: [{ modifiers: ["Ctrl" || "Meta", "Shift"], key: "k" }],
name: t("INSERT_LINK_TO_ELEMENT"),
name: t("INSERT_LINK_TO_ELEMENT_NORMAL"),
checkCallback: (checking: boolean) => {
if (checking) {
return Boolean(this.app.workspace.getActiveViewOfType(ExcalidrawView))
}
const view = this.app.workspace.getActiveViewOfType(ExcalidrawView);
if (view) {
view.copyLinkToSelectedElementToClipboard();
view.copyLinkToSelectedElementToClipboard(false);
return true;
}
return false;
},
});
this.addCommand({
id: "insert-link-to-element-group",
name: t("INSERT_LINK_TO_ELEMENT_GROUP"),
checkCallback: (checking: boolean) => {
if (checking) {
return Boolean(this.app.workspace.getActiveViewOfType(ExcalidrawView))
}
const view = this.app.workspace.getActiveViewOfType(ExcalidrawView);
if (view) {
view.copyLinkToSelectedElementToClipboard(true);
return true;
}
return false;
},
});
this.addCommand({
id: "toggle-lefthanded-mode",
name: t("TOGGLE_LEFTHANDED_MODE"),
checkCallback: (checking: boolean) => {
if (checking) {
if(this.app.workspace.getActiveViewOfType(ExcalidrawView)) {
const view = this.app.workspace.getActiveViewOfType(ExcalidrawView);
const api = view?.excalidrawAPI;
if(!api) return false;
const st = api.getAppState();
if(!st.trayModeEnabled) return false;
return true;
}
return false;
}
const view = this.app.workspace.getActiveViewOfType(ExcalidrawView);
(async()=>{
await this.loadSettings();
this.settings.isLeftHanded = !this.settings.isLeftHanded;
this.saveSettings();
setLeftHandedMode(this.settings.isLeftHanded);
})()
return true;
},
});
this.addCommand({
id: "insert-image",
name: t("INSERT_IMAGE"),
@@ -1358,7 +1400,7 @@ export default class ExcalidrawPlugin extends Plugin {
"markdown"
) {
// Then check for the excalidraw frontMatterKey
const cache = self.app.metadataCache.getCache(state.state.file);
const cache = app.metadataCache.getCache(state.state.file);
if (cache?.frontmatter && cache.frontmatter[FRONTMATTER_KEY]) {
// If we have it, force the view type to excalidraw
@@ -1379,43 +1421,6 @@ export default class ExcalidrawPlugin extends Plugin {
},
}),
);
// Add a menu item to go back to Excalidraw view
/*this.register(
around(MarkdownView.prototype, {
onPaneMenu(next) {
return function (menu: Menu) {
const file = this.file;
const cache = file
? self.app.metadataCache.getFileCache(file)
: null;
if (
!file ||
!cache?.frontmatter ||
!cache.frontmatter[FRONTMATTER_KEY]
) {
return next.call(this, menu);
}
menu
.addItem((item) => {
item
.setTitle(t("OPEN_AS_EXCALIDRAW"))
.setIcon(ICON_NAME)
.setSection("pane")
.onClick(() => {
self.excalidrawFileModes[this.leaf.id || file.path] =
VIEW_TYPE_EXCALIDRAW;
self.setExcalidrawView(this.leaf);
});
})
.addSeparator();
next.call(this, menu);
};
},
}),
);*/
}
private popScope: Function = null;
@@ -1439,19 +1444,19 @@ export default class ExcalidrawPlugin extends Plugin {
}
[".svg", ".png", ".excalidraw"].forEach(async (ext: string) => {
const oldIMGpath = getIMGPathFromExcalidrawFile(oldPath, ext);
const imgFile = self.app.vault.getAbstractFileByPath(
const imgFile = app.vault.getAbstractFileByPath(
normalizePath(oldIMGpath),
);
if (imgFile && imgFile instanceof TFile) {
const newIMGpath = getIMGPathFromExcalidrawFile(file.path, ext);
await self.app.fileManager.renameFile(imgFile, newIMGpath);
await app.fileManager.renameFile(imgFile, newIMGpath);
}
});
};
self.registerEvent(self.app.vault.on("rename", renameEventHandler));
self.registerEvent(app.vault.on("rename", renameEventHandler));
const modifyEventHandler = async (file: TFile) => {
const leaves = self.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
const leaves = app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
leaves.forEach(async (leaf: WorkspaceLeaf) => {
const excalidrawView = leaf.view as ExcalidrawView;
if (
@@ -1484,7 +1489,7 @@ export default class ExcalidrawPlugin extends Plugin {
}
});
};
self.registerEvent(self.app.vault.on("modify", modifyEventHandler));
self.registerEvent(app.vault.on("modify", modifyEventHandler));
//watch file delete and delete corresponding .svg and .png
const deleteEventHandler = async (file: TFile) => {
@@ -1499,7 +1504,7 @@ export default class ExcalidrawPlugin extends Plugin {
}
//close excalidraw view where this file is open
const leaves = self.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
const leaves = app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
for (let i = 0; i < leaves.length; i++) {
if ((leaves[i].view as ExcalidrawView).file.path == file.path) {
await leaves[i].setViewState({
@@ -1514,27 +1519,27 @@ export default class ExcalidrawPlugin extends Plugin {
setTimeout(() => {
[".svg", ".png", ".excalidraw"].forEach(async (ext: string) => {
const imgPath = getIMGPathFromExcalidrawFile(file.path, ext);
const imgFile = self.app.vault.getAbstractFileByPath(
const imgFile = app.vault.getAbstractFileByPath(
normalizePath(imgPath),
);
if (imgFile && imgFile instanceof TFile) {
await self.app.vault.delete(imgFile);
await app.vault.delete(imgFile);
}
});
}, 500);
}
};
self.registerEvent(self.app.vault.on("delete", deleteEventHandler));
self.registerEvent(app.vault.on("delete", deleteEventHandler));
//save open drawings when user quits the application
//Removing because it is not guaranteed to run, and frequently gets terminated mid flight, causing file consistency issues
/*const quitEventHandler = async () => {
const leaves = self.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
const leaves = app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
for (let i = 0; i < leaves.length; i++) {
await (leaves[i].view as ExcalidrawView).save(true);
}
};
self.registerEvent(self.app.workspace.on("quit", quitEventHandler));*/
self.registerEvent(app.workspace.on("quit", quitEventHandler));*/
//save Excalidraw leaf and update embeds when switching to another leaf
const activeLeafChangeEventHandler = async (leaf: WorkspaceLeaf) => {
@@ -1603,7 +1608,7 @@ export default class ExcalidrawPlugin extends Plugin {
}
};
self.registerEvent(
self.app.workspace.on(
app.workspace.on(
"active-leaf-change",
activeLeafChangeEventHandler,
),
@@ -1611,7 +1616,7 @@ export default class ExcalidrawPlugin extends Plugin {
self.addFileSaveTriggerEventHandlers();
const metaCache: MetadataCache = self.app.metadataCache;
const metaCache: MetadataCache = app.metadataCache;
//@ts-ignore
metaCache.getCachedFiles().forEach((filename: string) => {
const fm = metaCache.getCache(filename)?.frontmatter;
@@ -1620,7 +1625,7 @@ export default class ExcalidrawPlugin extends Plugin {
filename.match(/\.excalidraw$/)
) {
self.updateFileCache(
self.app.vault.getAbstractFileByPath(filename) as TFile,
app.vault.getAbstractFileByPath(filename) as TFile,
fm,
);
}
@@ -1864,7 +1869,9 @@ export default class ExcalidrawPlugin extends Plugin {
public openDrawing(
drawingFile: TFile,
location: "active-pane"|"new-pane"|"popout-window"
location: "active-pane"|"new-pane"|"popout-window",
active: boolean = false,
subpath?: string
) {
let leaf: WorkspaceLeaf;
if(location === "popout-window") {
@@ -1878,10 +1885,17 @@ export default class ExcalidrawPlugin extends Plugin {
}
}
leaf.setViewState({
leaf.openFile(
drawingFile,
!subpath || subpath === ""
? {active}
: { active, eState: { subpath } }
);
/* leaf.setViewState({
type: VIEW_TYPE_EXCALIDRAW,
state: { file: drawingFile.path },
});
state: { file: drawingFile.path, eState: {subpath}},
});*/
}
public async getBlankDrawing(): Promise<string> {
@@ -1960,7 +1974,7 @@ export default class ExcalidrawPlugin extends Plugin {
const folderpath = normalizePath(
foldername ? foldername : this.settings.folder,
);
await checkAndCreateFolder(this.app.vault, folderpath); //create folder if it does not exist
await checkAndCreateFolder(folderpath); //create folder if it does not exist
const fname = getNewUniqueFilepath(this.app.vault, filename, folderpath);
const file = await this.app.vault.create(
fname,
@@ -1987,7 +2001,7 @@ export default class ExcalidrawPlugin extends Plugin {
initData?: string,
): Promise<string> {
const file = await this.createDrawing(filename, foldername, initData);
this.openDrawing(file, location);
this.openDrawing(file, location, true);
return file.path;
}
@@ -2039,7 +2053,7 @@ export default class ExcalidrawPlugin extends Plugin {
}
filename = `${filename}.excalidrawlib`;
const folderpath = normalizePath(this.settings.folder);
await checkAndCreateFolder(this.app.vault, folderpath); //create folder if it does not exist
await checkAndCreateFolder(folderpath); //create folder if it does not exist
const fname = getNewUniqueFilepath(
this.app.vault,
filename,

View File

@@ -3,7 +3,7 @@ import { Notice, TFile } from "obsidian";
import * as React from "react";
import { ActionButton } from "./ActionButton";
import { ICONS } from "./ActionIcons";
import { SCRIPT_INSTALL_FOLDER } from "../Constants";
import { SCRIPT_INSTALL_FOLDER, CTRL_OR_CMD } from "../Constants";
import { insertLaTeXToView, search } from "../ExcalidrawAutomate";
import ExcalidrawView, { TextMode } from "../ExcalidrawView";
import { t } from "../lang/helpers";
@@ -464,8 +464,8 @@ export class ToolsPanel extends React.Component<PanelProps, PanelState> {
<ActionButton
key={"link-to-element"}
title={t("INSERT_LINK_TO_ELEMENT")}
action={() => {
this.props.view.copyLinkToSelectedElementToClipboard();
action={(e:React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
this.props.view.copyLinkToSelectedElementToClipboard(e[CTRL_OR_CMD]);
}}
icon={ICONS.copyElementLink}
view={this.props.view}

View File

@@ -219,7 +219,7 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
this.plugin.saveSettings();
if (this.requestReloadDrawings) {
const exs =
this.plugin.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
for (const v of exs) {
if (v.view instanceof ExcalidrawView) {
await v.view.save(false);

View File

@@ -120,7 +120,8 @@ export function getEmbedFilename(
* Open or create a folderpath if it does not exist
* @param folderpath
*/
export async function checkAndCreateFolder(vault: Vault, folderpath: string) {
export async function checkAndCreateFolder(folderpath: string) {
const vault = app.vault;
folderpath = normalizePath(folderpath);
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/658
//@ts-ignore

View File

@@ -144,7 +144,7 @@ export const getAttachmentsFolderAndFilePath = async (
if (!folder || folder === "/") {
folder = "";
}
await checkAndCreateFolder(app.vault, folder);
await checkAndCreateFolder(folder);
return {
folder,
filepath: normalizePath(

View File

@@ -576,8 +576,8 @@ export const getEmbeddedFilenameParts = (fname:string):{
linkpartReference: string,
linkpartAlias: string
} => {
// 0 1 23 4 5 6 7 8
const parts = fname?.match(/([^#\^]*)((#\^)(group_)?([^\|]*)|(#)([^\^\|]*))(.*)/);
// 0 1 23 4 5 6 7 8 9
const parts = fname?.match(/([^#\^]*)((#\^)(group=)?([^\|]*)|(#)(group=)?([^\^\|]*))(.*)/);
if(!parts) {
return {
filepath: fname,
@@ -593,12 +593,12 @@ export const getEmbeddedFilenameParts = (fname:string):{
return {
filepath: parts[1],
hasBlockref: Boolean(parts[3]),
hasGroupref: Boolean(parts[4]),
hasGroupref: Boolean(parts[4]) || Boolean(parts[7]),
blockref: parts[5],
hasSectionref: Boolean(parts[6]),
sectionref: parts[7],
sectionref: parts[8],
linkpartReference: parts[2],
linkpartAlias: parts[8]
linkpartAlias: parts[9]
}
}
@@ -607,6 +607,7 @@ export const errorlog = (data: {}) => {
};
export const sleep = async (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
export const awaitNextAnimationFrame = async () => new Promise(requestAnimationFrame);
export const log = console.log.bind(window.console);
export const debug = console.log.bind(window.console);

View File

@@ -138,7 +138,11 @@ li[data-testid] {
}
.excalidraw-prompt-center {
text-align: center;
text-align: center !important;
}
.excalidraw-prompt-center button {
margin: 0 10px;
}
.excalidraw-prompt-center.filepath {