Compare commits

..

6 Commits

Author SHA1 Message Date
zsviczian
18821e1a67 1.9.28 2023-11-04 14:28:30 +01:00
zsviczian
5dd65d691c mermaid to retain SVG for legacy, LASER-config, PDF import improvements, image link click improvements, hover on image with link, dynamic styling fix, image cache fix 2023-11-03 23:02:09 +01:00
zsviczian
8f96dbc21d 1.9.27 2023-10-28 20:51:55 +02:00
zsviczian
f71623f8a1 1.9.26 2023-10-25 18:55:18 +02:00
zsviczian
b380420cac Update README.md 2023-10-23 07:50:52 +02:00
zsviczian
21cccd4475 updated readme 2023-10-23 07:50:10 +02:00
19 changed files with 1093 additions and 466 deletions

View File

@@ -4,7 +4,9 @@ The Obsidian-Excalidraw plugin integrates [Excalidraw](https://excalidraw.com/),
## Video Walkthrough
<a href="https://youtu.be/o0exK-xFP3k" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/156931370-aa4d88de-c4a8-46cc-aeb2-dc09aa0bea39.jpg" width="300"/></a>
<a href="https://youtu.be/o0exK-xFP3k" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/156931370-aa4d88de-c4a8-46cc-aeb2-dc09aa0bea39.jpg" width="300"/></a>
<a href="https://youtu.be/QKnQgSjJVuc" target="_blank"><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/thumbnail-getting-started.jpg" width="300"/></a>
<details><summary>10 Part (slightly outdated) Video Walkthrough</summary>
<a href="https://youtu.be/sY4FoflGaiM" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/125160304-7f211180-e17c-11eb-8363-c52723de1ffd.jpg" width="100" style="vertical-align: middle;"/>&nbsp;&nbsp;1 Getting Started</a><br>

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

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

View File

@@ -18,7 +18,7 @@
"author": "",
"license": "MIT",
"dependencies": {
"@zsviczian/excalidraw": "0.16.1-obsidian-5",
"@zsviczian/excalidraw": "0.16.1-obsidian-8",
"chroma-js": "^2.4.2",
"clsx": "^2.0.0",
"colormaster": "^1.2.1",

View File

@@ -39,7 +39,6 @@ import {
svgToBase64,
} from "./utils/Utils";
import { ValueOf } from "./types";
import { has } from "./svgToExcalidraw/attributes";
import { getMermaidImageElements, getMermaidText, shouldRenderMermaid } from "./utils/MermaidUtils";
import { mermaidToExcalidraw } from "src/constants";
@@ -594,7 +593,7 @@ export class EmbeddedFilesLoader {
continue;
}
const data = getMermaidText(element);
const result = await mermaidToExcalidraw(data, {fontSize: 20});
const result = await mermaidToExcalidraw(data, {fontSize: 20}, true);
if(!result) {
continue;
}

View File

@@ -109,6 +109,10 @@ export class ExcalidrawAutomate {
return obsidian_module;
};
get LASERPOINTER() {
return this.plugin.settings.laserSettings;
}
get DEVICE():DeviceType {
return DEVICE;
}

View File

@@ -293,8 +293,18 @@ export class ExcalidrawData {
if (el.boundElements) {
const map = new Map<string, string>();
let alreadyHasText:boolean = false;
el.boundElements.forEach((item: { id: string; type: string }) => {
map.set(item.id, item.type);
if(item.type === "text") {
if(!alreadyHasText) {
map.set(item.id, item.type);
alreadyHasText = true;
} else {
elements.find((el:ExcalidrawElement)=>el.id===item.id).containerId = null;
}
} else {
map.set(item.id, item.type);
}
});
const boundElements = Array.from(map, ([id, type]) => ({ id, type }));
if (boundElements.length !== el.boundElements.length) {
@@ -616,7 +626,7 @@ export class ExcalidrawData {
}
//Load Equations
const REG_FILEID_EQUATION = /([\w\d]*):\s*\$\$(.*)(\$\$\s*\n)/gm;
const REG_FILEID_EQUATION = /([\w\d]*):\s*\$\$([\s\S]*?)(\$\$\s*\n)/gm;
res = data.matchAll(REG_FILEID_EQUATION);
while (!(parts = res.next()).done) {
this.setEquation(parts.value[1] as FileId, {

View File

@@ -129,6 +129,7 @@ declare namespace ExcalidrawLib {
function mermaidToExcalidraw(
mermaidDefinition: string,
opts: {fontSize: number},
forceSVG?: boolean,
): Promise<{
elements: ExcalidrawElement[],
files:any

View File

@@ -15,6 +15,7 @@ import {
//import Excalidraw from "@zsviczian/excalidraw";
import {
ExcalidrawElement,
ExcalidrawImageElement,
ExcalidrawTextElement,
FileId,
NonDeletedExcalidrawElement,
@@ -126,6 +127,7 @@ import { EmbeddableMenu } from "./menu/EmbeddableActionsMenu";
import { useDefaultExcalidrawFrame } from "./utils/CustomEmbeddableUtils";
import { UniversalInsertFileModal } from "./dialogs/UniversalInsertFileModal";
import { shouldRenderMermaid } from "./utils/MermaidUtils";
import { link } from "fs";
declare const PLUGIN_VERSION:string;
@@ -873,7 +875,7 @@ export default class ExcalidrawView extends TextFileView {
}
openExternalLink(link:string, element?: ExcalidrawElement):boolean {
if (link.match(/cmd:\/\/.*/)) {
if (link.match(/^cmd:\/\/.*/)) {
const cmd = link.replace("cmd://", "");
//@ts-ignore
this.app.commands.executeCommandById(cmd);
@@ -899,7 +901,7 @@ export default class ExcalidrawView extends TextFileView {
}
//@ts-ignore
search[0].view.setQuery(`tag:${tags.value[1]}`);
app.workspace.revealLeaf(search[0]);
this.app.workspace.revealLeaf(search[0]);
if (this.isFullscreen()) {
this.exitFullscreen();
@@ -907,6 +909,46 @@ export default class ExcalidrawView extends TextFileView {
return;
}
async linkPrompt(linkText:string):Promise<[file:TFile, linkText:string, subpath: string]> {
const partsArray = REGEX_LINK.getResList(linkText);
let subpath: string = null;
let file: TFile = null;
let parts = partsArray[0];
if (partsArray.length > 1) {
parts = await ScriptEngine.suggester(
this.app,
partsArray.filter(p=>Boolean(p.value)).map(p => REGEX_LINK.getLink(p)),
partsArray.filter(p=>Boolean(p.value)),
"Select link to open"
);
if(!parts) return;
}
if(!parts) return;
if (!parts.value) {
this.openTagSearch(linkText);
return;
}
linkText = REGEX_LINK.getLink(parts);
if(this.openExternalLink(linkText)) return;
if (linkText.search("#") > -1) {
const linkParts = getLinkParts(linkText, this.file);
subpath = `#${linkParts.isBlockRef ? "^" : ""}${linkParts.ref}`;
linkText = linkParts.path;
}
if (linkText.match(REG_LINKINDEX_INVALIDCHARS)) {
new Notice(t("FILENAME_INVALID_CHARS"), 4000);
return;
}
file = this.app.metadataCache.getFirstLinkpathDest(
linkText,
this.file.path,
);
return [file, linkText, subpath];
}
async linkClick(
ev: MouseEvent,
selectedText: SelectedElementWithLink,
@@ -941,47 +983,16 @@ export default class ExcalidrawView extends TextFileView {
if(this.handleLinkHookCall(el,linkText,ev)) return;
if(this.openExternalLink(linkText)) return;
const partsArray = REGEX_LINK.getResList(linkText);
let parts = partsArray[0];
if (partsArray.length > 1) {
parts = await ScriptEngine.suggester(
app,
partsArray.filter(p=>Boolean(p.value)).map(p => REGEX_LINK.getLink(p)),
partsArray.filter(p=>Boolean(p.value)),
"Select link to open"
);
if(!parts) return;
}
//parts = REGEX_LINK.getRes(linkText).next();
if (!parts?.value) {
this.openTagSearch(linkText);
return;
}
linkText = REGEX_LINK.getLink(parts);
if(this.openExternalLink(linkText)) return;
if (linkText.search("#") > -1) {
const linkParts = getLinkParts(linkText, this.file);
subpath = `#${linkParts.isBlockRef ? "^" : ""}${linkParts.ref}`;
linkText = linkParts.path;
}
if (linkText.match(REG_LINKINDEX_INVALIDCHARS)) {
new Notice(t("FILENAME_INVALID_CHARS"), 4000);
return;
}
file = this.app.metadataCache.getFirstLinkpathDest(
linkText,
this.file.path,
);
const result = await this.linkPrompt(linkText);
if(!result) return;
[file, linkText, subpath] = result;
}
if (selectedImage?.id) {
const imageElement = this.getScene().elements.find((el:ExcalidrawElement)=>el.id === selectedImage.id) as ExcalidrawImageElement;
if (this.excalidrawData.hasEquation(selectedImage.fileId)) {
(async () => {
debugger;
await this.save(false);
selectedImage.fileId = this.getScene().elements.filter((el:ExcalidrawElement)=>el.id === selectedImage.id)[0].fileId;
selectedImage.fileId = imageElement.fileId;
const equation = this.excalidrawData.getEquation(
selectedImage.fileId,
).latex;
@@ -1018,11 +1029,7 @@ export default class ExcalidrawView extends TextFileView {
await this.save(false); //in case pasted images haven't been saved yet
if (this.excalidrawData.hasFile(selectedImage.fileId)) {
const ef = this.excalidrawData.getFile(selectedImage.fileId);
if(ef.isHyperLink || ef.isLocalLink) {
window.open(ef.hyperlink,"_blank");
return;
}
if (linkClickType === "md-properties") {
if (!ef.isHyperLink && !ef.isLocalLink && linkClickType === "md-properties") {
if (
ef.file.extension === "md" &&
!this.plugin.isExcalidrawFile(ef.file)
@@ -1052,11 +1059,20 @@ export default class ExcalidrawView extends TextFileView {
return;
}
}
linkText = ef.file.path;
file = ef.file;
if(file.extension.toLowerCase() === "pdf") {
subpath = ef.linkParts.original.match(/(#.*)$/)?.[1];
}
const linkString = (ef.isHyperLink || ef.isLocalLink
? `[](${ef.hyperlink}) `
: `[[${ef.linkParts.original}]] `
) + (imageElement.link
? (imageElement.link.match(/$cmd:\/\/.*/) || imageElement.link.match(REG_LINKINDEX_HYPERLINK))
? `[](${imageElement.link})`
: imageElement.link
: "");
const result = await this.linkPrompt(linkString);
if(!result) return;
[file, linkText, subpath] = result;
}
}
@@ -2123,7 +2139,7 @@ export default class ExcalidrawView extends TextFileView {
if(!this.semaphores.viewunload && this.toolsPanelRef?.current) {
this.toolsPanelRef.current.setDirty(true);
}
if(!app.isMobile) {
if(!this.app.isMobile) {
if(requireApiVersion("0.16.0")) {
//@ts-ignore
this.leaf.tabHeaderInnerTitleEl.style.color="var(--color-accent)"
@@ -2855,13 +2871,13 @@ export default class ExcalidrawView extends TextFileView {
if (files[0] == this.file) {
files.shift();
(
app as any
this.app as any
).dragManager.draggable.title = `${files.length} files`;
}
}
if (
["file", "files"].includes(
(app as any).dragManager.draggable?.type,
(this.app as any).dragManager.draggable?.type,
)
) {
return "link";
@@ -2918,6 +2934,19 @@ export default class ExcalidrawView extends TextFileView {
let mouseEvent: any = null;
const getLinkTextFromLink = (text: string): string => {
if (!text) return;
if (text.match(REG_LINKINDEX_HYPERLINK)) return;
const parts = REGEX_LINK.getRes(text).next();
if (!parts.value) return;
const linktext = REGEX_LINK.getLink(parts); //parts.value[2] ? parts.value[2]:parts.value[6];
if (linktext.match(REG_LINKINDEX_HYPERLINK)) return;
return linktext;
}
const showHoverPreview = (linktext?: string, element?: ExcalidrawElement) => {
if(!mouseEvent) return;
const st = this.excalidrawAPI?.getAppState();
@@ -2931,7 +2960,7 @@ export default class ExcalidrawView extends TextFileView {
if (!selectedElement || !selectedElement.text) {
const selectedImgElement =
getImageElementAtPointer(this.currentPosition, this);
element = this.excalidrawAPI.getSceneElements().filter((el:ExcalidrawElement)=>el.id === selectedImgElement.id)[0];
element = this.excalidrawAPI.getSceneElements().find((el:ExcalidrawElement)=>el.id === selectedImgElement.id);
if (!selectedImgElement || !selectedImgElement.fileId) {
return;
}
@@ -2939,15 +2968,21 @@ export default class ExcalidrawView extends TextFileView {
return;
}
const ef = this.excalidrawData.getFile(selectedImgElement.fileId);
if(ef.isHyperLink || ef.isLocalLink) return; //web images don't have a preview
if(IMAGE_TYPES.contains(ef.file.extension)) return; //images don't have a preview
if(ef.file.extension.toLowerCase() === "pdf") return; //pdfs don't have a preview
if(this.plugin.ea.isExcalidrawFile(ef.file)) return; //excalidraw files don't have a preview
const ref = ef.linkParts.ref
? `#${ef.linkParts.isBlockRef ? "^" : ""}${ef.linkParts.ref}`
: "";
linktext =
ef.file.path + ref;
if (
(ef.isHyperLink || ef.isLocalLink) || //web images don't have a preview
(IMAGE_TYPES.contains(ef.file.extension)) || //images don't have a preview
(ef.file.extension.toLowerCase() === "pdf") || //pdfs don't have a preview
(this.plugin.ea.isExcalidrawFile(ef.file))
) {//excalidraw files don't have a preview
linktext = getLinkTextFromLink(element.link);
if(!linktext) return;
} else {
const ref = ef.linkParts.ref
? `#${ef.linkParts.isBlockRef ? "^" : ""}${ef.linkParts.ref}`
: "";
linktext =
ef.file.path + ref;
}
} else {
element = this.excalidrawAPI.getSceneElements().filter((el:ExcalidrawElement)=>el.id === selectedElement.id)[0];
const text: string =
@@ -2955,21 +2990,8 @@ export default class ExcalidrawView extends TextFileView {
? this.excalidrawData.getRawText(selectedElement.id)
: selectedElement.text;
if (!text) {
return;
}
if (text.match(REG_LINKINDEX_HYPERLINK)) {
return;
}
const parts = REGEX_LINK.getRes(text).next();
if (!parts.value) {
return;
}
linktext = REGEX_LINK.getLink(parts); //parts.value[2] ? parts.value[2]:parts.value[6];
if (linktext.match(REG_LINKINDEX_HYPERLINK)) {
return;
}
linktext = getLinkTextFromLink(text);
if(!linktext) return;
}
}
@@ -3818,10 +3840,9 @@ export default class ExcalidrawView extends TextFileView {
const match = originalText.trim().matchAll(REG_TRANSCLUSION).next(); //reset the iterator
if(match?.value?.[0]) {
const link = match.value[1] ?? match.value[2];
const file = app.metadataCache.getFirstLinkpathDest(link, this.file.path);
const file = this.app.metadataCache.getFirstLinkpathDest(link, this.file.path);
if(file && file instanceof TFile) {
if (file.extension !== "md" || this.plugin.isExcalidrawFile(file))
{
if (file.extension !== "md" || this.plugin.isExcalidrawFile(file)) {
setTimeout(async ()=>{
const elements = this.excalidrawAPI.getSceneElements();
const el = elements.filter((el:ExcalidrawElement)=>el.id === textElement.id) as ExcalidrawTextElement[];

View File

@@ -11,6 +11,7 @@ import ExcalidrawPlugin from "./main";
import { ButtonDefinition, GenericInputPrompt, GenericSuggester } from "./dialogs/Prompt";
import { getIMGFilename } from "./utils/FileUtils";
import { splitFolderAndFilename } from "./utils/FileUtils";
import { getEA } from "src";
export type ScriptIconMap = {
[key: string]: { name: string; group: string; svgString: string };
@@ -199,27 +200,26 @@ export class ScriptEngine {
const commandId = `${PLUGIN_ID}:${basename}`;
// @ts-ignore
if (!app.commands.commands[commandId]) {
if (!this.plugin.app.commands.commands[commandId]) {
return;
}
// @ts-ignore
delete app.commands.commands[commandId];
delete this.plugin.app.commands.commands[commandId];
}
async executeScript(view: ExcalidrawView, script: string, title: string, file: TFile) {
if (!view || !script || !title) {
return;
}
this.plugin.ea.reset();
this.plugin.ea.setView(view);
this.plugin.ea.activeScript = title;
const ea = getEA(view);
ea.activeScript = title;
//https://stackoverflow.com/questions/45381204/get-asyncfunction-constructor-in-typescript changed tsconfig to es2017
//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncFunction
const AsyncFunction = Object.getPrototypeOf(async () => {}).constructor;
let result = null;
//try {
result = await new AsyncFunction("ea", "utils", script)(this.plugin.ea, {
result = await new AsyncFunction("ea", "utils", script)(ea, {
inputPrompt: (
header: string,
placeholder?: string,
@@ -233,7 +233,7 @@ export class ScriptEngine {
ScriptEngine.inputPrompt(
view,
this.plugin,
app,
this.plugin.app,
header,
placeholder,
value,
@@ -262,7 +262,7 @@ export class ScriptEngine {
new Notice(t("SCRIPT_EXECUTION_ERROR"), 4000);
errorlog({ script: this.plugin.ea.activeScript, error: e });
}*/
this.plugin.ea.activeScript = null;
ea.activeScript = null;
return result;
}

File diff suppressed because one or more lines are too long

View File

@@ -11,7 +11,10 @@ import { ExcalidrawImperativeAPI } from "@zsviczian/excalidraw/types/types";
export class InsertPDFModal extends Modal {
private borderBox: boolean = true;
private gapSize:number = 20;
private groupPages: boolean = false;
private direction: "down" | "right" = "right";
private numColumns: number = 1;
private numRows: number = 1;
private lockAfterImport: boolean = true;
private pagesToImport:number[] = [];
private pageDimensions: {width: number, height: number} = {width: 0, height: 0};
@@ -21,7 +24,6 @@ export class InsertPDFModal extends Modal {
private pdfFile: TFile;
private dirty: boolean = false;
constructor(
private plugin: ExcalidrawPlugin,
private view: ExcalidrawView,
@@ -47,7 +49,10 @@ export class InsertPDFModal extends Modal {
this.plugin.settings.pdfImportScale = this.importScale;
this.plugin.settings.pdfBorderBox = this.borderBox;
this.plugin.settings.pdfGapSize = this.gapSize;
this.plugin.settings.pdfGroupPages = this.groupPages;
this.plugin.settings.pdfNumColumns = this.numColumns;
this.plugin.settings.pdfNumRows = this.numRows;
this.plugin.settings.pdfDirection = this.direction;
this.plugin.settings.pdfLockAfterImport = this.lockAfterImport;
this.plugin.saveSettings();
}
@@ -111,7 +116,10 @@ export class InsertPDFModal extends Modal {
await this.plugin.loadSettings();
this.borderBox = this.plugin.settings.pdfBorderBox;
this.gapSize = this.plugin.settings.pdfGapSize;
this.groupPages = this.plugin.settings.pdfGroupPages;
this.numColumns = this.plugin.settings.pdfNumColumns;
this.numRows = this.plugin.settings.pdfNumRows;
this.direction = this.plugin.settings.pdfDirection;
this.lockAfterImport = this.plugin.settings.pdfLockAfterImport;
this.importScale = this.plugin.settings.pdfImportScale;
@@ -211,7 +219,18 @@ export class InsertPDFModal extends Modal {
this.borderBox = value;
this.dirty = true;
}))
new Setting(ce)
.setName("Group pages")
.setDesc("This will group all pages into a single group. This is recommended if you are locking the pages after import, because the group will be easier to unlock later rather than unlocking one by one.")
.addToggle(toggle => toggle
.setValue(this.groupPages)
.onChange((value) => {
this.groupPages = value
this.dirty = true;
}))
new Setting(ce)
.setName("Lock pages on canvas after import")
.addToggle(toggle => toggle
@@ -221,8 +240,38 @@ export class InsertPDFModal extends Modal {
this.dirty = true;
}))
let columnsText: HTMLDivElement;
let numColumnsSetting: Setting;
let numRowsSetting: Setting;
const colRowVisibility = () => {
switch(this.direction) {
case "down":
numColumnsSetting.settingEl.style.display = "none";
numRowsSetting.settingEl.style.display = "";
break;
case "right":
numColumnsSetting.settingEl.style.display = "";
numRowsSetting.settingEl.style.display = "none";
break;
}
}
new Setting(ce)
.setName("Import direction")
.addDropdown(dropdown => dropdown
.addOptions({
"down": "Top > Down",
"right": "Left > Right"
})
.setValue(this.direction)
.onChange(value => {
this.direction = value as "down" | "right";
colRowVisibility();
this.dirty = true;
}))
let columnsText: HTMLDivElement;
numColumnsSetting = new Setting(ce);
numColumnsSetting
.setName("Number of columns")
.addSlider(slider => slider
.setLimits(1, 100, 1)
@@ -239,6 +288,26 @@ export class InsertPDFModal extends Modal {
el.innerText = ` ${this.numColumns.toString()}`;
});
let rowsText: HTMLDivElement;
numRowsSetting = new Setting(ce);
numRowsSetting
.setName("Number of rows")
.addSlider(slider => slider
.setLimits(1, 100, 1)
.setValue(this.numRows)
.onChange(value => {
this.numRows = value;
rowsText.innerText = ` ${value.toString()}`;
this.dirty = true;
}))
.settingEl.createDiv("", (el) => {
rowsText = el;
el.style.minWidth = "2.3em";
el.style.textAlign = "right";
el.innerText = ` ${this.numRows.toString()}`;
});
colRowVisibility();
let gapSizeText: HTMLDivElement;
new Setting(ce)
.setName("Size of gap between pages")
@@ -256,7 +325,7 @@ export class InsertPDFModal extends Modal {
el.style.textAlign = "right";
el.innerText = ` ${this.gapSize.toString()}`;
});
const importSizeSetting = new Setting(ce)
.setName("Imported page size")
.setDesc(`${this.pageDimensions.width*this.importScale} x ${this.pageDimensions.height*this.importScale}`)
@@ -303,6 +372,7 @@ export class InsertPDFModal extends Modal {
topX,
topY,
this.pdfFile.path + `#page=${page}`,
false,
false);
const imgEl = ea.getElement(imageID) as any;
imgEl.width = imgWidth;
@@ -310,9 +380,21 @@ export class InsertPDFModal extends Modal {
if(this.lockAfterImport) imgEl.locked = true;
ea.addToGroup([boxID,imageID]);
column = (column + 1) % this.numColumns;
if(column === 0) row++;
switch(this.direction) {
case "right":
column = (column + 1) % this.numColumns;
if(column === 0) row++;
break;
case "down":
row = (row + 1) % this.numRows;
if(row === 0) column++;
break;
}
}
if(this.groupPages) {
const ids = ea.getElements().map(el => el.id);
ea.addToGroup(ids);
}
await ea.addElementsToView(true,true,false);
const api = ea.getExcalidrawAPI() as ExcalidrawImperativeAPI;

View File

@@ -17,6 +17,42 @@ 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://cdn.ko-fi.com/cdn/kofi3.png?v=3" height=45></a></div>
`,
"1.9.28":`
## Fixed & Improved
- Fixed an issue where the toolbar lost focus, requiring two clicks. This caused a problem when the hand tool was activated from ExcalidrawAutomate script when opening a drawing, causing buttons to stop working. [#1344](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1344)
- Resolved a caching issue affecting image area-links and group-links, making them work inconsistently. For more details, refer to the discussion on [Discord](https://discord.com/channels/1026825302900494357/1169311900308361318).
- Improved frame colors with Dynamic Coloring.
- Added support for multiline LaTeX formulas. [#1403](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1403)
- Fixed the issue of Chinese characters overlapping in MathJax. [#1406](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1406)
## New
- Added support for Mermaid to Excalidraw **Sequence Diagrams**.
- If an image contains an element link, clicking on the image will now open the link chooser, allowing you to decide whether to open the image or follow the element link.
- When hovering over an image that also has an element link, the hover preview will display the contents of the link.
- You can now choose to **import PDFs** in columns instead of rows. Additionally, you have the option to group all pages after import, which will improve the unlocking experience if you also lock pages on import.
- Introduced configuration options for the **Laser Tool**, including pointer color, decay length, and time. ([#1408](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1408), [#1220](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1220))
![image](https://github.com/zsviczian/obsidian-excalidraw-plugin/assets/14358394/c0cad40a-1afc-42af-b41b-f912dd8a4e78)
`,
"1.9.27": `
## New
- Restructured plugin settings, added additional comments and relevant videos
- Added setting to change PDF to Image resolution/scale. This has an effect when embedding PDF pages to Excalidraw. A lower value will result in less-sharp pages, but better overall performance. Also, larger pages (higher scale value) were not accepted by Excalidraw.com when copying from Obsidian due to the 2MB image file limit. Find the "PDF to Image" setting under "Embedding Excalidraw into your Notes and Exporting" setting. [#1393](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1393)
## Fixed
- When multiple Excalidraw Scripts were executed parallel a race condition occurred causing scripts to override each other
- I implemented a partial fix to "text detaching from figures when dragging them" [#1400](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1400)
- Regression: extra thin stroke removed with 1.9.26 [#1399](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1399)`,
"1.9.26":`
## Fixes and improvements from Excalidraw.com
- Freedraw shape selection issue, when fill-pattern is not solid [#7193](https://github.com/excalidraw/excalidraw/pull/7193)
- Actions panel UX improvement [#6850](https://github.com/excalidraw/excalidraw/pull/6850)
## Fixed in plugin
- After inserting PDF pages as image the size of inserted images were incorrectly anchored preventing resizing of pages. The fix does not solve the issue with already imported pages, but pages you import in the future will not be anchored.
- Mobile toolbar flashes up on tab change on desktop
- Toolbar buttons are active on the first click after opening a drawing. This addresses the "hand" issue raised here: [#1344](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1344)
`,
"1.9.25":`
## Fixed
- Fixed issues with creating Markdown or Excalidraw files for non-existing documents [#1385](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1385)

View File

@@ -111,6 +111,8 @@ export default {
"<b><u>Toggle ON:</u></b> Show a notification when a new version of the plugin is available.<br>" +
"<b><u>Toggle OFF:</u></b> Silent mode. You need to check for plugin updates in Community Plugins.",
BASIC_HEAD: "Basic",
BASIC_DESC: `In the "Basic" settings, you can configure options such as displaying release notes after updates, receiving plugin update notifications, setting the default location for new drawings, specifying the Excalidraw folder for embedding drawings into active documents, defining an Excalidraw template file, and designating an Excalidraw Automate script folder for managing automation scripts.`,
FOLDER_NAME: "Excalidraw folder",
FOLDER_DESC:
"Default location for new drawings. If empty, drawings will be created in the Vault root.",
@@ -134,6 +136,7 @@ export default {
"hotkeys to your favorite scripts just like to any other Obsidian command. " +
"The folder may not be the root folder of your Vault. ",
SAVING_HEAD: "Saving",
SAVING_DESC: "In the 'Saving' section of Excalidraw Settings, you can configure how your drawings are saved. This includes options for compressing Excalidraw JSON in Markdown, setting autosave intervals for both desktop and mobile, defining filename formats, and choosing whether to use the .excalidraw.md or .md file extension. ",
COMPRESS_NAME: "Compress Excalidraw JSON in Markdown",
COMPRESS_DESC:
"By enabling this feature Excalidraw will store the drawing JSON in a Base64 compressed " +
@@ -181,7 +184,8 @@ FILENAME_HEAD: "Filename",
FILENAME_EXCALIDRAW_EXTENSION_DESC:
"This setting does not apply if you use Excalidraw in compatibility mode, " +
"i.e. you are not using Excalidraw markdown files.<br><b><u>Toggle ON:</u></b> filename ends with .excalidraw.md<br><b><u>Toggle OFF:</u></b> filename ends with .md",
DISPLAY_HEAD: "Display",
DISPLAY_HEAD: "Excalidraw appearance and behavior",
DISPLAY_DESC: "In the 'appearance and behavior' section of Excalidraw Settings, you can fine-tune how Excalidraw appears and behaves. This includes options for dynamic styling, left-handed mode, matching Excalidraw and Obsidian themes, default modes, and more.",
DYNAMICSTYLE_NAME: "Dynamic styling",
DYNAMICSTYLE_DESC:
"Change Excalidraw UI colors to match the canvas color",
@@ -214,7 +218,8 @@ FILENAME_HEAD: "Filename",
DEFAULT_PEN_MODE_NAME: "Pen mode",
DEFAULT_PEN_MODE_DESC:
"Should pen mode be automatically enabled when opening Excalidraw?",
THEME_HEAD: "Theme and styling",
ZOOM_HEAD: "Zoom",
DEFAULT_PINCHZOOM_NAME: "Allow pinch zoom in pen mode",
DEFAULT_PINCHZOOM_DESC:
"Pinch zoom in pen mode when using the freedraw tool is disabled by default to prevent unwanted accidental zooming with your palm.<br>" +
@@ -233,7 +238,14 @@ FILENAME_HEAD: "Filename",
ZOOM_TO_FIT_MAX_LEVEL_NAME: "Zoom to fit max ZOOM level",
ZOOM_TO_FIT_MAX_LEVEL_DESC:
"Set the maximum level to which zoom to fit will enlarge the drawing. Minimum is 0.5 (50%) and maximum is 10 (1000%).",
LINKS_HEAD: "Links and transclusion",
LASER_HEAD: "Laser pointer",
LASER_COLOR: "Laser pointer color",
LASER_DECAY_TIME_NAME: "Laser pointer decay time",
LASER_DECAY_TIME_DESC: "Laser pointer decay time in milliseconds. Default is 1000 (i.e. 1 second).",
LASER_DECAY_LENGTH_NAME: "Laser pointer decay length.",
LASER_DECAY_LENGTH_DESC: "Laser pointer decay length in line points. Default is 50.",
LINKS_HEAD: "Links, transclusion and TODOs",
LINKS_HEAD_DESC: "In the 'Links, transclusion and TODOs' section of Excalidraw Settings, you can configure how Excalidraw handles links, transclusions, and TODO items. This includes options for opening links, managing panes, displaying links with brackets, customizing link prefixes, handling TODO items, and more. ",
LINKS_DESC:
`${labelCTRL()}+CLICK on <code>[[Text Elements]]</code> to open them as links. ` +
"If the selected text has more than one <code>[[valid Obsidian links]]</code>, only the first will be opened. " +
@@ -305,11 +317,12 @@ FILENAME_HEAD: "Filename",
GET_URL_TITLE_NAME: "Use iframely to resolve page title",
GET_URL_TITLE_DESC:
"Use the <code>http://iframely.server.crestify.com/iframely?url=</code> to get title of page when dropping a link into Excalidraw",
MD_HEAD: "Markdown-embed settings",
MD_HEAD_DESC:
`You can transclude formatted markdown documents into drawings as images ${labelSHIFT()} drop from the file explorer or using ` +
"the command palette action.",
PDF_TO_IMAGE: "PDF to Image",
PDF_TO_IMAGE_SCALE_NAME: "PDF to Image conversion scale",
PDF_TO_IMAGE_SCALE_DESC: "Sets the resolution of the image that is generated from the PDF page. Higher resolution will result in bigger images in memory and consequently a higher load on your system (slower performance), but sharper imagee. " +
"Additionally, if you want to copy PDF pages (as images) to Excalidraw.com, the bigger image size may result in exceeding the 2MB limit on Excalidraw.com.",
MD_HEAD: "Embed markdown into Excalidraw as image",
MD_HEAD_DESC: `In the "Embed markdown as image settings," you can configure various options for how markdown documents are embedded as images within Excalidraw. These settings allow you to control the default width and maximum height of embedded markdown files, choose the font typeface, font color, and border color for embedded markdown content. Additionally, you can specify a custom CSS file to style the embedded markdown content. Note you can also embed markdown documents as interactive frames. The color setting of frames is under the Display Settings section.`,
MD_TRANSCLUDE_WIDTH_NAME: "Default width of a transcluded markdown document",
MD_TRANSCLUDE_WIDTH_DESC:
"The width of the markdown page. This affects the word wrapping when transcluding longer paragraphs, and the width of " +
@@ -345,8 +358,11 @@ FILENAME_HEAD: "Filename",
"Setting the font-family in the css is has limitations. By default only your operating system's standard fonts are available (see README for details). " +
"You can add one custom font beyond that using the setting above. " +
'You can override this css setting by adding the following frontmatter-key to the embedded markdown file: "excalidraw-css: css_file_in_vault|css-snippet".',
EMBED_HEAD: "Embed & Export",
EMBED_HEAD: "Embedding Excalidraw into your Notes and Exporting",
EMBED_DESC: `In the "Embed & Export" settings, you can configure how images and Excalidraw drawings are embedded and exported within your documents. Key settings include choosing the image type for markdown preview (such as Native SVG or PNG), specifying the type of file to insert into the document (original Excalidraw, PNG, or SVG), and managing image caching for embedding in markdown. You can also control image sizing, whether to embed drawings using wiki links or markdown links, and adjust settings related to image themes, background colors, and Obsidian integration.
Additionally, there are settings for auto-export, which automatically generates SVG and/or PNG files to match the title of your Excalidraw drawings, keeping them in sync with file renames and deletions.`,
EMBED_CACHING: "Image caching",
EXPORT_SUBHEAD: "Export Settings",
EMBED_SIZING: "Image sizing",
EMBED_THEME_BACKGROUND: "Image theme and background color",
EMBED_IMAGE_CACHE_NAME: "Cache images for embedding in markdown",
@@ -424,6 +440,7 @@ FILENAME_HEAD: "Filename",
EXPORT_BOTH_DARK_AND_LIGHT_DESC: "When enabled, Excalidraw will export two files instead of one: filename.dark.png, filename.light.png and/or filename.dark.svg and filename.light.svg<br>"+
"Double files will be exported both if auto-export SVG or PNG (or both) are enabled, as well as when clicking export on a single image.",
COMPATIBILITY_HEAD: "Compatibility features",
COMPATIBILITY_DESC: "You should only enable these features if you have a strong reason for wanting to work with excalidraw.com files instead of markdown files. Many of the plugin features are not supported on legacy files. Typical usecase would be if you use set your vault up on top of a Visual Studio Code project folder and you have .excalidraw drawings you want to access from Visual Studio Code as well. Another usecase might be using Excalidraw in Logseq and Obsidian in parallel.",
EXPORT_EXCALIDRAW_NAME: "Auto-export Excalidraw",
EXPORT_EXCALIDRAW_DESC: "Same as the auto-export SVG, but for *.Excalidraw",
SYNC_EXCALIDRAW_NAME:
@@ -433,6 +450,7 @@ FILENAME_HEAD: "Filename",
"then update the drawing in the .md file based on the .excalidraw file",
COMPATIBILITY_MODE_NAME: "New drawings as legacy files",
COMPATIBILITY_MODE_DESC:
"⚠️ Enable this only if you know what you are doing. In 99.9% of the cases you DO NOT want this on. " +
"By enabling this feature drawings you create with the ribbon icon, the command palette actions, " +
"and the file explorer are going to be all legacy *.excalidraw files. This setting will also turn off the reminder message " +
"when you open a legacy file for editing.",
@@ -443,12 +461,13 @@ FILENAME_HEAD: "Filename",
LATEX_DEFAULT_NAME: "Default LaTeX formual for new equations",
LATEX_DEFAULT_DESC: "Leave empty if you don't want a default formula. You can add default formatting here such as <code>\\color{white}</code>.",
NONSTANDARD_HEAD: "Non-Excalidraw.com supported features",
NONSTANDARD_DESC: "These features are not available on excalidraw.com. When exporting the drawing to Excalidraw.com these features will appear different.",
NONSTANDARD_DESC: `These settings in the "Non-Excalidraw.com Supported Features" section provide customization options beyond the default Excalidraw.com features. These features are not available on excalidraw.com. When exporting the drawing to Excalidraw.com these features will appear different.
You can configure the number of custom pens displayed next to the Obsidian Menu on the canvas, allowing you to choose from a range of options. Additionally, you can enable a fourth font option, which adds a fourth font button to the properties panel for text elements. `,
CUSTOM_PEN_HEAD: "Custom pens",
CUSTOM_PEN_NAME: "Number of custom pens",
CUSTOM_PEN_DESC: "You will see these pens next to the Obsidian Menu on the canvas. You can customize the pens on the canvas by long-pressing the pen button.",
EXPERIMENTAL_HEAD: "Experimental features",
EXPERIMENTAL_DESC:
"Some of these setting will not take effect immediately, only when the File Explorer is refreshed, or Obsidian restarted.",
EXPERIMENTAL_HEAD: "Miscellaneous features",
EXPERIMENTAL_DESC: `These miscellaneous features in Excalidraw include options for setting default LaTeX formulas for new equations, enabling a Field Suggester for autocompletion, displaying type indicators for Excalidraw files, enabling immersive image embedding in live preview editing mode, and experimenting with Taskbone Optical Character Recognition for text extraction from images and drawings. Users can also enter a Taskbone API key for extended usage of the OCR service.`,
FIELD_SUGGESTER_NAME: "Enable Field Suggester",
FIELD_SUGGESTER_DESC:
"Field Suggester borrowed from Breadcrumbs and Templater plugins. The Field Suggester will show an autocomplete menu " +
@@ -464,6 +483,7 @@ FILENAME_HEAD: "Filename",
"Turn this on to support image embedding styles such as ![[drawing|width|style]] in live preview editing mode. " +
"The setting will not affect the currently open documents. You need close the open documents and re-open them for the change " +
"to take effect.",
CUSTOM_FONT_HEAD: "Fourth font",
ENABLE_FOURTH_FONT_NAME: "Enable fourth font option",
ENABLE_FOURTH_FONT_DESC:
"By turning this on, you will see a fourth font button on the properties panel for text elements. " +
@@ -475,6 +495,7 @@ FILENAME_HEAD: "Filename",
"Select a .ttf, .woff or .woff2 font file from your vault to use as the fourth font. " +
"If no file is selected, Excalidraw will use the Virgil font by default.",
SCRIPT_SETTINGS_HEAD: "Settings for installed Scripts",
SCRIPT_SETTINGS_DESC: "Some of the Excalidraw Automate Scripts include settings. Settings are organized by script. Settings will only become visible in this list after you have executed the newly downloaded script once.",
TASKBONE_HEAD: "Taskbone Optical Character Recogntion",
TASKBONE_DESC: "This is an experimental integration of optical character recognition into Excalidraw. Please note, that taskbone is an independent external service not provided by Excalidraw, nor the Excalidraw-Obsidian plugin project. " +
"The OCR service will grab legible text from freedraw lines and embedded pictures on your canvas and place the recognized text in the frontmatter of your drawing as well as onto clipboard. " +

View File

@@ -154,7 +154,6 @@ export default class ExcalidrawPlugin extends Plugin {
public equationsMaster: Map<FileId, string> = null; //fileId, formula
public mermaidsMaster: Map<FileId, string> = null; //fileId, mermaidText
public mathjax: any = null;
private mathjaxDiv: HTMLDivElement = null;
public mathjaxLoaderFinished: boolean = false;
public scriptEngine: ScriptEngine;
public fourthFontDef: string = VIRGIL_FONT;
@@ -294,11 +293,91 @@ export default class ExcalidrawPlugin extends Plugin {
});
}
private removeMathJax() {
if("ExcalidrawMathJax" in window) {
delete window.ExcalidrawMathJax;
}
const scriptElement = document.getElementById("ExcalidrawMathJax");
if(scriptElement) {
scriptElement.parentNode.removeChild(scriptElement);
}
}
public loadMathJax() {
const self = this;
this.app.workspace.onLayoutReady(async () => {
//loading Obsidian MathJax as fallback
await loadMathJax();
//@ts-ignore
const backup = window.MathJax;
try {
this.removeMathJax();
const script = document.createElement("script");
script.setAttribute("id","ExcalidrawMathJax");
script.type = "text/javascript";
script.onload = () => {
//@ts-ignore
window.ExcalidrawMathJax.startup.pagePromise.then(async () => {
// Set the 'all' package to load all MathJax modules
const mathJaxConfig = {
tex: {
packages: { '[+]': ['all'] }, //this is required because during runtime loading fails due to the renaming of the package
// Add any other configurations you need here
},
};
// Set the MathJax configuration
//@ts-ignore
window.ExcalidrawMathJax = {
//@ts-ignore
...window.ExcalidrawMathJax,
options: {
//@ts-ignore
...window.ExcalidrawMathJax.options,
...mathJaxConfig,
},
};
//https://github.com/xldenis/obsidian-latex/blob/master/main.ts
const file = this.app.vault.getAbstractFileByPath("preamble.sty");
const preamble: string =
file && file instanceof TFile
? await this.app.vault.read(file)
: null;
try {
if (preamble) {
//@ts-ignore
await window.ExcalidrawMathJax.tex2svg(preamble);
}
} catch (e) {
errorlog({
where: self.loadMathJax,
description: "Unexpected error while loading preamble.sty",
error: e,
});
}
//@ts-ignore
self.mathjax = window.ExcalidrawMathJax;
self.mathjaxLoaderFinished = true;
});
};
script.src = "data:text/javascript;base64," + decompressFromBase64(MATHJAX_SOURCE_LZCOMPRESSED); //self.settings.mathjaxSourceURL; // "https://cdn.jsdelivr.net/npm/mathjax@3.2.2/es5/tex-svg.js";
//script.src = MATHJAX_DATAURL;
document.head.appendChild(script);
} catch {
new Notice("Excalidraw: Error initializing LaTeX support");
self.mathjaxLoaderFinished = true;
}
});
}
/* public loadMathJax() {
const self = this;
this.app.workspace.onLayoutReady(async () => {
//loading Obsidian MathJax as fallback
await loadMathJax();
//@ts-ignore
try {
if(self.mathjaxDiv) {
document.body.removeChild(self.mathjaxDiv);
@@ -350,7 +429,7 @@ export default class ExcalidrawPlugin extends Plugin {
self.mathjaxLoaderFinished = true;
}
});
}
}*/
private switchToExcalidarwAfterLoad() {
const self = this;
@@ -2197,9 +2276,11 @@ export default class ExcalidrawPlugin extends Plugin {
excalidrawLeaves.forEach((leaf) => {
this.setMarkdownView(leaf);
});
if (this.mathjaxDiv) {
this.removeMathJax();
/* if (this.mathjaxDiv) {
document.body.removeChild(this.mathjaxDiv);
}
}*/
Object.values(this.packageMap).forEach((p:Packages)=>{
delete p.excalidrawLib;

File diff suppressed because it is too large Load Diff

View File

@@ -64,58 +64,70 @@ export const setDynamicStyle = (
const text = cmBG().mix({color:isDark?lighter:darker, ratio:mixRatio});
const str = (cm: ColorMaster) => cm.stringHEX({alpha:false});
const style = `--color-primary: ${str(accent())};` +
`--color-surface-low: ${str(gray1)};` +
`--color-surface-mid: ${str(gray1)};` +
`--color-surface-lowest: ${str(gray2)};` +
`--color-surface-high: ${str(gray1.lighterBy(step))};` +
`--color-on-primary-container: ${str(!isDark?accent().darkerBy(15):accent().lighterBy(15))};` +
`--color-surface-primary-container: ${str(isDark?accent().darkerBy(step):accent().lighterBy(step))};` +
//`--color-primary-darker: ${str(accent().darkerBy(step))};` +
//`--color-primary-darkest: ${str(accent().darkerBy(step))};` +
`--button-gray-1: ${str(gray1)};` +
`--button-gray-2: ${str(gray2)};` +
`--input-border-color: ${str(gray1)};` +
`--input-bg-color: ${str(gray2)};` +
`--input-label-color: ${str(text)};` +
`--island-bg-color: ${gray2.alphaTo(0.93).stringHEX()};` +
`--popup-secondary-bg-color: ${gray2.alphaTo(0.93).stringHEX()};` +
`--icon-fill-color: ${str(text)};` +
`--text-primary-color: ${str(text)};` +
`--overlay-bg-color: ${gray2.alphaTo(0.6).stringHEX()};` +
`--popup-bg-color: ${str(gray1)};` +
`--color-on-surface: ${str(text)};` +
//`--color-gray-100: ${str(text)};` +
//`--color-gray-40: ${str(text)};` +
`--color-surface-highlight: ${str(gray1)};` +
//`--color-gray-30: ${str(gray1)};` +
`--color-gray-80: ${str(gray1)};` +
`--sidebar-border-color: ${str(gray1)};` +
`--color-primary-light: ${str(accent().lighterBy(step))};` +
`--button-hover-bg: ${str(gray1)};` +
`--sidebar-bg-color: ${gray2.alphaTo(0.93).stringHEX()};` +
`--sidebar-shadow: ${str(gray1)};` +
`--popup-text-color: ${str(text)};` +
`--code-normal: ${str(text)};` +
`--code-background: ${str(gray2)};` +
`--h1-color: ${str(text)};` +
`--h2-color: ${str(text)};` +
`--h3-color: ${str(text)};` +
`--h4-color: ${str(text)};` +
`color: ${str(text)};` +
`--select-highlight-color: ${str(gray1)};`;
const styleObject:{[x: string]: string;} = {
[`--color-primary`]: str(accent()),
[`--color-surface-low`]: str(gray1),
[`--color-surface-mid`]: str(gray1),
[`--color-surface-lowest`]: str(gray2),
[`--color-surface-high`]: str(gray1.lighterBy(step)),
[`--color-on-primary-container`]: str(!isDark?accent().darkerBy(15):accent().lighterBy(15)),
[`--color-surface-primary-container`]: str(isDark?accent().darkerBy(step):accent().lighterBy(step)),
//[`--color-primary-darker`]: str(accent().darkerBy(step)),
//[`--color-primary-darkest`]: str(accent().darkerBy(step)),
[`--button-gray-1`]: str(gray1),
[`--button-gray-2`]: str(gray2),
[`--input-border-color`]: str(gray1),
[`--input-bg-color`]: str(gray2),
[`--input-label-color`]: str(text),
[`--island-bg-color`]: gray2.alphaTo(0.93).stringHEX(),
[`--popup-secondary-bg-color`]: gray2.alphaTo(0.93).stringHEX(),
[`--icon-fill-color`]: str(text),
[`--text-primary-color`]: str(text),
[`--overlay-bg-color`]: gray2.alphaTo(0.6).stringHEX(),
[`--popup-bg-color`]: str(gray1),
[`--color-on-surface`]: str(text),
//[`--color-gray-100`]: str(text),
[`--color-gray-40`]: str(text), //frame
[`--color-gray-50`]: str(text), //frame
[`--color-surface-highlight`]: str(gray1),
//[`--color-gray-30`]: str(gray1),
[`--color-gray-80`]: str(isDark?text.lighterBy(15):text.darkerBy(15)), //frame
[`--sidebar-border-color`]: str(gray1),
[`--color-primary-light`]: str(accent().lighterBy(step)),
[`--button-hover-bg`]: str(gray1),
[`--sidebar-bg-color`]: gray2.alphaTo(0.93).stringHEX(),
[`--sidebar-shadow`]: str(gray1),
[`--popup-text-color`]: str(text),
[`--code-normal`]: str(text),
[`--code-background`]: str(gray2),
[`--h1-color`]: str(text),
[`--h2-color`]: str(text),
[`--h3-color`]: str(text),
[`--h4-color`]: str(text),
[`color`]: str(text),
[`--select-highlight-color`]: str(gray1),
};
view.excalidrawContainer?.setAttribute(
"style",
style
)
const styleString = Object.keys(styleObject)
.map((property) => `${property}: ${styleObject[property]}`)
.join("; ");
setTimeout(()=>view.updateScene({appState:{dynamicStyle: style}}));
/*view.excalidrawContainer?.setAttribute(
"style",
styleString
)*/
setTimeout(()=>view.updateScene({appState:{
frameColor: {
stroke: isDark?str(gray2.lighterBy(15)):str(gray2.darkerBy(15)),
fill: str((isDark?gray2.lighterBy(30):gray2.darkerBy(30)).alphaTo(0.2)),
},
dynamicStyle: styleObject
}}));
const toolspanel = view.toolsPanelRef?.current?.containerRef?.current;
if(toolspanel) {
let toolsStyle = toolspanel.getAttribute("style");
toolsStyle = toolsStyle.replace(/\-\-color\-primary.*/,"");
toolspanel.setAttribute("style",toolsStyle+style);
toolspanel.setAttribute("style",toolsStyle+styleString);
}
}

View File

@@ -1,7 +1,7 @@
import { App, Notice, TFile } from "obsidian";
import ExcalidrawPlugin from "src/main";
import { convertSVGStringToElement } from "./Utils";
import { PreviewImageType } from "./UtilTypes";
import { FILENAMEPARTS, PreviewImageType } from "./UtilTypes";
//@ts-ignore
const DB_NAME = "Excalidraw " + app.appId;
@@ -19,10 +19,11 @@ export type ImageKey = {
isDark: boolean;
previewImageType: PreviewImageType;
scale: number;
};
} & FILENAMEPARTS;
const getKey = (key: ImageKey): string =>
`${key.filepath}#${key.blockref}#${key.sectionref}#${key.isDark ? 1 : 0}#${
`${key.filepath}#${key.blockref??""}#${key.sectionref??""}#${key.isDark ? 1 : 0}#${
key.hasGroupref}#${key.hasArearef}#${key.hasFrameref}#${key.hasSectionref}#${
key.previewImageType === PreviewImageType.SVGIMG
? 1
: key.previewImageType === PreviewImageType.PNG
@@ -149,10 +150,11 @@ class ImageCache {
const cursor = (event.target as IDBRequest<IDBCursorWithValue | null>).result;
if(cursor) {
const key = cursor.key as string;
const isLegacyKey = key.replaceAll(/[^#]/g,"").length < 9; // introduced hasGroupref, etc. in 1.9.28
const filepath = key.split("#")[0];
const fileExists = files.some((f: TFile) => f.path === filepath);
const file = fileExists ? files.find((f: TFile) => f.path === filepath) : null;
if (!file || (file && file.stat.mtime > cursor.value.mtime) || (!cursor.value.blob && !cursor.value.svg)) {
if (isLegacyKey || !file || (file && file.stat.mtime > cursor.value.mtime) || (!cursor.value.blob && !cursor.value.svg)) {
deletePromises.push(
new Promise<void>((innerResolve, innerReject) => {
const deleteRequest = store.delete(cursor.primaryKey);

View File

@@ -183,15 +183,24 @@ li[data-testid] {
}
.excalidraw-videoWrapper {
max-width:600px
max-width:600px;
}
.excalidraw-videoWrapper div {
.excalidraw-videoWrapper.settings {
max-width:340px;
}
.excalidraw-videoWrapper div{
position: relative;
padding-bottom: 56.25%;
height: 0;
margin: 0 auto;
}
.excalidraw-videoWrapper.settings iframe {
position: relative;
margin-bottom: 1rem;
}
.excalidraw-videoWrapper iframe {
position: absolute;
top: 0;
@@ -423,4 +432,47 @@ div.excalidraw-draginfo {
max-height: initial;
width: initial;
height: initial;
}
summary.excalidraw-setting-h1 {
font-variant: var(--h1-variant);
letter-spacing: -0.015em;
line-height: var(--h1-line-height);
font-size: var(--h1-size);
color: var(--h1-color);
font-weight: var(--h1-weight);
font-style: var(--h1-style);
font-family: var(--h1-font);
/*margin-block-start: var(--p-spacing);*/
margin-block-end: var(--p-spacing);
}
summary.excalidraw-setting-h3 {
font-variant: var(--h3-variant);
letter-spacing: -0.015em;
line-height: var(--h3-line-height);
font-size: var(--h3-size);
color: var(--h3-color);
font-weight: var(--h3-weight);
font-style: var(--h3-style);
font-family: var(--h3-font);
margin-block-start: var(--p-spacing);
margin-block-end: var(--p-spacing);
}
summary.excalidraw-setting-h4 {
font-variant: var(--h4-variant);
letter-spacing: -0.015em;
line-height: var(--h4-line-height);
font-size: var(--h4-size);
color: var(--h4-color);
font-weight: var(--h4-weight);
font-style: var(--h4-style);
font-family: var(--h4-font);
margin-block-start: var(--p-spacing);
margin-block-end: var(--p-spacing);
}
hr.excalidraw-setting-hr {
margin: 1rem 0rem 0rem 0rem;
}