Compare commits

...

12 Commits

Author SHA1 Message Date
zsviczian
90c377f125 1.8.5 2022-12-17 12:41:31 +01:00
zsviczian
df85138890 updated elbow connectors 2022-12-15 18:55:43 +01:00
zsviczian
654b656a2f Merge pull request #935 from 1-2-3/master
feat:add "Center connect points" option to "Elbow connectors" script
2022-12-15 18:54:26 +01:00
zsviczian
1d22dcb488 roundness 2022-12-12 23:17:50 +01:00
zahuifan
a42e907d0c feat:add "Center connect points" option. 2022-12-11 12:19:18 +08:00
zsviczian
353cad21d6 Update directory-info.json 2022-12-07 10:14:46 +01:00
zsviczian
2b02f186a6 Update Text Arch.svg 2022-12-07 10:13:47 +01:00
zsviczian
3e12d1e815 Update directory-info.json 2022-12-07 10:03:54 +01:00
zsviczian
539bbdf07f Merge pull request #929 from 1-2-3/master
fix: scripts not work with arrows that contain text.
2022-12-07 10:02:07 +01:00
zsviczian
b993b358fe 1.8.4 2022-12-06 22:51:54 +01:00
zahuifan
0639ea5969 fix: not work with arrows that contain text. 2022-12-06 12:15:46 +08:00
zsviczian
05b7bc6029 1.8.3-beta 2022-12-05 23:27:21 +01:00
24 changed files with 316 additions and 192 deletions

View File

@@ -308,16 +308,8 @@ function loadELK(doAfterLoaded) {
function normalizeSelectedArrows() {
let gapValue = 2;
const selectedIndividualArrows = ea
.getMaximumGroups(ea.getViewSelectedElements())
.reduce(
(result, group) =>
group.length === 1 &&
(group[0].type === "arrow" || group[0].type === "line")
? [...result, group[0]]
: result,
[]
);
const selectedIndividualArrows = ea.getMaximumGroups(ea.getViewSelectedElements())
.reduce((result, g) => [...result, ...g.filter(el => el.type === 'arrow')], []);
const allElements = ea.getViewElements();
for (const arrow of selectedIndividualArrows) {

View File

@@ -13,12 +13,49 @@ https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.h
```javascript
*/
const selectedCenterConnectPoints = await utils.suggester(
['Yes', 'No'],
[true, false],
"Center connect points?"
);
const centerConnectPoints = selectedCenterConnectPoints??false;
const allElements = ea.getViewElements();
const elements = ea.getViewSelectedElements();
const lines = elements.filter((el)=>el.type==="arrow" || el.type==="line");
for (const line of lines) {
if (line.points.length >= 3) {
if(centerConnectPoints) {
const startBindingEl = allElements.filter(el => el.id === (line.startBinding||{}).elementId)[0];
const endBindingEl = allElements.filter(el => el.id === (line.endBinding||{}).elementId)[0];
if(startBindingEl) {
const startPointX = line.x +line.points[0][0];
if(startPointX >= startBindingEl.x && startPointX <= startBindingEl.x + startBindingEl.width) {
line.points[0][0] = startBindingEl.x + startBindingEl.width / 2 - line.x;
}
const startPointY = line.y +line.points[0][1];
if(startPointY >= startBindingEl.y && startPointY <= startBindingEl.y + startBindingEl.height) {
line.points[0][1] = startBindingEl.y + startBindingEl.height / 2 - line.y;
}
}
if(endBindingEl) {
const startPointX = line.x +line.points[line.points.length-1][0];
if(startPointX >= endBindingEl.x && startPointX <= endBindingEl.x + endBindingEl.width) {
line.points[line.points.length-1][0] = endBindingEl.x + endBindingEl.width / 2 - line.x;
}
const startPointY = line.y +line.points[line.points.length-1][1];
if(startPointY >= endBindingEl.y && startPointY <= endBindingEl.y + endBindingEl.height) {
line.points[line.points.length-1][1] = endBindingEl.y + endBindingEl.height / 2 - line.y;
}
}
}
for (var i = 0; i < line.points.length - 2; i++) {
var p1;
var p3;

View File

@@ -26,8 +26,7 @@ if(!settings["Gap"]) {
let gapValue = settings["Gap"].value;
const selectedIndividualArrows = ea.getMaximumGroups(ea.getViewSelectedElements())
.reduce((result, group) => (group.length === 1 && (group[0].type === 'arrow' || group[0].type === 'line')) ?
[...result, group[0]] : result, []);
.reduce((result, g) => [...result, ...g.filter(el => el.type === 'arrow')], []);
const allElements = ea.getViewElements();
for(const arrow of selectedIndividualArrows) {

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" stroke="#000" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><g fill="none"><circle cx="12" cy="12" r="10"></circle><path d="M17 12h.01"></path><path d="M12 12h.01"></path><path d="M7 12h.01"></path></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" stroke="#000" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><g stroke-width="2" fill="none"><circle cx="12" cy="12" r="10"></circle><path d="M17 12h.01"></path><path d="M12 12h.01"></path><path d="M7 12h.01"></path></g></svg>

Before

Width:  |  Height:  |  Size: 309 B

After

Width:  |  Height:  |  Size: 327 B

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +1,8 @@
{
"id": "obsidian-excalidraw-plugin",
"name": "Excalidraw",
"version": "1.7.28-beta",
"minAppVersion": "0.15.6",
"version": "1.8.3-beta",
"minAppVersion": "0.16.0",
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
"author": "Zsolt Viczian",
"authorUrl": "https://zsolt.blog",

View File

@@ -1,8 +1,8 @@
{
"id": "obsidian-excalidraw-plugin",
"name": "Excalidraw",
"version": "1.8.2",
"minAppVersion": "0.16.0",
"version": "1.8.5",
"minAppVersion": "1.0.0",
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
"author": "Zsolt Viczian",
"authorUrl": "https://zsolt.blog",

View File

@@ -18,7 +18,7 @@
"license": "MIT",
"dependencies": {
"@types/lz-string": "^1.3.34",
"@zsviczian/excalidraw": "0.13.0-obsidian-1",
"@zsviczian/excalidraw": "0.13.0-obsidian-2",
"clsx": "^1.1.1",
"lz-string": "^1.4.4",
"monkey-around": "^2.3.0",

View File

@@ -2,13 +2,14 @@ import ExcalidrawPlugin from "./main";
import {
FillStyle,
StrokeStyle,
StrokeSharpness,
ExcalidrawElement,
ExcalidrawBindableElement,
FileId,
NonDeletedExcalidrawElement,
ExcalidrawImageElement,
ExcalidrawTextElement,
StrokeRoundness,
RoundnessType,
} from "@zsviczian/excalidraw/types/element/types";
import { normalizePath, Notice, TFile, WorkspaceLeaf } from "obsidian";
import * as obsidian_module from "obsidian";
@@ -61,6 +62,7 @@ import RYBPlugin from "colormaster/plugins/ryb";
import CMYKPlugin from "colormaster/plugins/cmyk";
import { TInput } from "colormaster/types";
import {ConversionResult, svgToExcalidraw} from "./svgToExcalidraw/parser"
import { ROUNDNESS } from "./Constants";
extendPlugins([
HarmonyPlugin,
@@ -118,7 +120,8 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
strokeStyle: StrokeStyle; //type StrokeStyle = "solid" | "dashed" | "dotted"
roughness: number;
opacity: number;
strokeSharpness: StrokeSharpness; //type StrokeSharpness = "round" | "sharp"
strokeSharpness?: StrokeRoundness; //defaults to undefined, use strokeRoundess and roundess instead. Only kept for legacy script compatibility type StrokeRoundness = "round" | "sharp"
roundness: null | { type: RoundnessType; value?: number };
fontFamily: number; //1: Virgil, 2:Helvetica, 3:Cascadia, 4:LocalFont
fontSize: number;
textAlign: string; //"left"|"right"|"center"
@@ -190,10 +193,12 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
setStrokeSharpness(val: number) {
switch (val) {
case 0:
this.style.strokeSharpness = "round";
this.style.roundness = {
type: ROUNDNESS.LEGACY
}
return "round";
default:
this.style.strokeSharpness = "sharp";
this.style.roundness = null; //sharp
return "sharp";
}
};
@@ -383,18 +388,17 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
template?.appState?.currentItemFontSize ?? this.style.fontSize,
currentItemTextAlign:
template?.appState?.currentItemTextAlign ?? this.style.textAlign,
currentItemStrokeSharpness:
template?.appState?.currentItemStrokeSharpness ??
this.style.strokeSharpness,
currentItemStartArrowhead:
template?.appState?.currentItemStartArrowhead ??
this.style.startArrowHead,
currentItemEndArrowhead:
template?.appState?.currentItemEndArrowhead ??
this.style.endArrowHead,
currentItemLinearStrokeSharpness:
template?.appState?.currentItemLinearStrokeSharpness ??
this.style.strokeSharpness,
currentItemRoundness: //type StrokeRoundness = "round" | "sharp"
template?.appState?.currentItemLinearStrokeSharpness ?? //legacy compatibility
template?.appState?.currentItemStrokeSharpness ?? //legacy compatibility
template?.appState?.currentItemRoundness ??
this.style.roundness ? "round":"sharp",
gridSize: template?.appState?.gridSize ?? this.canvas.gridSize,
colorPalette: template?.appState?.colorPalette ?? this.colorPalette,
},
@@ -584,7 +588,11 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
strokeStyle: this.style.strokeStyle,
roughness: this.style.roughness,
opacity: this.style.opacity,
strokeSharpness: this.style.strokeSharpness,
roundness: this.style.strokeSharpness
? (this.style.strokeSharpness === "round"
? {type: ROUNDNESS.LEGACY}
: null)
: this.style.roundness,
seed: Math.floor(Math.random() * 100000),
version: 1,
versionNonce: Math.floor(Math.random() * 1000000000),
@@ -1186,7 +1194,7 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
strokeStyle: "solid",
roughness: 1,
opacity: 100,
strokeSharpness: "sharp",
roundness: null,
fontFamily: 1,
fontSize: 20,
textAlign: "left",

View File

@@ -615,6 +615,7 @@ export class ExcalidrawData {
newText: string,
newOriginalText: string,
forceUpdate: boolean = false,
containerType?: string,
) {
if (forceUpdate || newText != sceneTextElement.text) {
const measure = _measureText(
@@ -625,7 +626,7 @@ export class ExcalidrawData {
sceneTextElement.text = newText;
sceneTextElement.originalText = newOriginalText;
if (!sceneTextElement.containerId) {
if (!sceneTextElement.containerId || containerType==="arrow") {
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/376
//I leave the setting of text width to excalidraw, when text is in a container
//because text width is fixed to the container width
@@ -660,6 +661,7 @@ export class ExcalidrawData {
) : originalText,
originalText,
forceupdate,
container?.type,
); //(await this.getText(te.id))??te.text serves the case when the whole #Text Elements section is deleted by accident
}
}
@@ -1326,7 +1328,9 @@ export class ExcalidrawData {
public getOpenMode(): { viewModeEnabled: boolean; zenModeEnabled: boolean } {
const fileCache = this.app.metadataCache.getFileCache(this.file);
let mode = this.plugin.settings.defaultMode;
let mode = this.plugin.settings.defaultMode === "view-mobile"
? (this.plugin.device.isPhone ? "view" : "normal")
: this.plugin.settings.defaultMode;
if (
fileCache?.frontmatter &&
fileCache.frontmatter[FRONTMATTER_KEY_DEFAULT_MODE] != null

View File

@@ -2083,7 +2083,7 @@ export default class ExcalidrawView extends TextFileView {
return { id: selectedElement[0].id, text: selectedElement[0].text };
} //a text element was selected. Return text
if (selectedElement[0].type === "image") {
if (["image","arrow"].contains(selectedElement[0].type)) {
return { id: null, text: null };
}
@@ -2375,14 +2375,12 @@ export default class ExcalidrawView extends TextFileView {
currentItemFontFamily: st.currentItemFontFamily,
currentItemFontSize: st.currentItemFontSize,
currentItemTextAlign: st.currentItemTextAlign,
currentItemStrokeSharpness: st.currentItemStrokeSharpness,
currentItemStartArrowhead: st.currentItemStartArrowhead,
currentItemEndArrowhead: st.currentItemEndArrowhead,
scrollX: st.scrollX,
scrollY: st.scrollY,
zoom: st.zoom,
currentItemLinearStrokeSharpness:
st.currentItemLinearStrokeSharpness,
currentItemRoundness: st.currentItemRoundness,
gridSize: st.gridSize,
colorPalette: st.colorPalette,
},
@@ -3078,14 +3076,18 @@ export default class ExcalidrawView extends TextFileView {
const el = elements.filter((el:ExcalidrawElement)=>el.id === textElement.id);
if(el.length === 1) {
const clone = cloneElement(el[0]);
const containerType = el[0].containerId
? api.getSceneElements().filter((e:ExcalidrawElement)=>e.id===el[0].containerId)?.[0]?.type
: undefined;
this.excalidrawData.updateTextElement(
clone,
wrappedParsedText,
parsedText,
true
true,
containerType
);
elements[elements.indexOf(el[0])] = clone;
await this.updateScene({elements});
this.updateScene({elements});
if(clone.containerId) this.updateContainerSize(clone.containerId);
}
@@ -3322,11 +3324,11 @@ export default class ExcalidrawView extends TextFileView {
const containers = containerId
? api
.getSceneElements()
.filter((el: ExcalidrawElement) => el.id === containerId)
.filter((el: ExcalidrawElement) => el.id === containerId && el.type!=="arrow")
: api
.getSceneElements()
.filter((el: ExcalidrawElement) =>
el.boundElements?.map((e) => e.type).includes("text"),
el.type!=="arrow" && el.boundElements?.map((e) => e.type).includes("text"),
);
if (containers.length > 0) {
if (this.initialContainerSizeUpdate) {

View File

@@ -21,6 +21,7 @@ import {
svgToBase64,
} from "./utils/Utils";
import { isObsidianThemeDark } from "./utils/ObsidianUtils";
import { image } from "html2canvas/dist/types/css/types/image";
interface imgElementAttributes {
file?: TFile;
@@ -185,54 +186,77 @@ const getIMG = async (
return img;
};
const createImgElement = async (
attr: imgElementAttributes,
) :Promise<HTMLElement> => {
const img = await getIMG(attr);
img.setAttribute("fileSource", attr.fname);
if (attr.fwidth) {
img.setAttribute("w", attr.fwidth);
}
if (attr.fheight) {
img.setAttribute("h", attr.fheight);
}
let timer:NodeJS.Timeout;
const clickEvent = (ev:PointerEvent) => {
if (
ev.target instanceof Element &&
ev.target.tagName.toLowerCase() != "img"
) {
return;
}
const src = img.getAttribute("fileSource");
if (src) {
const srcParts = src.match(/([^#]*)(.*)/);
if(!srcParts) return;
plugin.openDrawing(
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);
};
img.addEventListener("pointerdown",(ev)=>{
if(img?.parentElement?.hasClass("canvas-node-content")) return;
timer = setTimeout(()=>clickEvent(ev),500);
});
img.addEventListener("pointerup",()=>{
if(timer) clearTimeout(timer);
timer = null;
})
img.addEventListener("dblclick",clickEvent);
img.addEventListener(RERENDER_EVENT, async (e) => {
e.stopPropagation();
const parent = img.parentElement;
const imgMaxWidth = img.style.maxWidth;
const imgMaxHeigth = img.style.maxHeight;
const fileSource = img.getAttribute("fileSource");
const newImg = await createImgElement({
fname: fileSource,
fwidth: img.getAttribute("w"),
fheight: img.getAttribute("h"),
style: img.getAttribute("class"),
});
parent.empty();
newImg.style.maxHeight = imgMaxHeigth;
newImg.style.maxWidth = imgMaxWidth;
newImg.setAttribute("fileSource",fileSource);
parent.append(newImg);
});
return img;
}
const createImageDiv = async (
attr: imgElementAttributes,
): Promise<HTMLDivElement> => {
const img = await getIMG(attr);
return createDiv(attr.style, (el) => {
el.append(img);
el.setAttribute("src", attr.fname);
if (attr.fwidth) {
el.setAttribute("w", attr.fwidth);
}
if (attr.fheight) {
el.setAttribute("h", attr.fheight);
}
el.onClickEvent((ev) => {
if (
ev.target instanceof Element &&
ev.target.tagName.toLowerCase() != "img"
) {
return;
}
const src = el.getAttribute("src");
if (src) {
const srcParts = src.match(/([^#]*)(.*)/);
if(!srcParts) return;
plugin.openDrawing(
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);
});
el.addEventListener(RERENDER_EVENT, async (e) => {
e.stopPropagation();
el.empty();
const img = await getIMG({
fname: el.getAttribute("src"),
fwidth: el.getAttribute("w"),
fheight: el.getAttribute("h"),
style: el.getAttribute("class"),
});
el.append(img);
});
});
const img = await createImgElement(attr);
return createDiv(attr.style, (el) => el.append(img));
};
const processReadingMode = async (
@@ -336,101 +360,106 @@ const tmpObsidianWYSIWYG = async (
return;
}
//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
//specified in setting should be displayed
//if .internal-embed is found, then contents is replaced with the image using the
//internal-embed: Excalidraw is embedded into a markdown document
//markdown-reading-view: we are processing the markdown reading view of an actual Excalidraw file
//markdown-embed: we are processing the hover preview of a markdown file
//alt, width, and height attributes of .internal-embed to size and style the image
setTimeout(async () => {
//wait for el to be attached to the displayed document
let counter = 0;
while(!el.parentElement && counter++<=50) await sleep(50);
if(!el.parentElement) return;
let internalEmbedDiv: HTMLElement = el;
while (
!internalEmbedDiv.hasClass("dataview") &&
!internalEmbedDiv.hasClass("cm-preview-code-block") &&
!internalEmbedDiv.hasClass("cm-embed-block") &&
!internalEmbedDiv.hasClass("internal-embed") &&
internalEmbedDiv.parentElement
) {
internalEmbedDiv = internalEmbedDiv.parentElement;
}
if(
internalEmbedDiv.hasClass("dataview") ||
internalEmbedDiv.hasClass("cm-preview-code-block") ||
internalEmbedDiv.hasClass("cm-embed-block")
) {
return; //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/835
}
const attr: imgElementAttributes = {
fname: ctx.sourcePath,
fheight: "",
fwidth: getDefaultWidth(plugin),
style: "excalidraw-svg",
};
attr.file = file;
//@ts-ignore
const containerEl = ctx.containerEl;
let internalEmbedDiv: HTMLElement = containerEl;
while (
!internalEmbedDiv.hasClass("dataview") &&
!internalEmbedDiv.hasClass("cm-preview-code-block") &&
!internalEmbedDiv.hasClass("cm-embed-block") &&
!internalEmbedDiv.hasClass("internal-embed") &&
!internalEmbedDiv.hasClass("markdown-reading-view") &&
!internalEmbedDiv.hasClass("markdown-embed") &&
internalEmbedDiv.parentElement
) {
internalEmbedDiv = internalEmbedDiv.parentElement;
}
if(
internalEmbedDiv.hasClass("dataview") ||
internalEmbedDiv.hasClass("cm-preview-code-block") ||
internalEmbedDiv.hasClass("cm-embed-block")
) {
return; //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/835
}
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
el.empty();
const mdPreviewSection = el.parentElement;
if(!mdPreviewSection.hasClass("markdown-preview-section")) return;
if(mdPreviewSection.hasAttribute("ready")) {
mdPreviewSection.removeChild(el);
return;
}
mdPreviewSection.setAttribute("ready","");
const imgDiv = await createImageDiv(attr);
el.appendChild(imgDiv);
return;
}
if(isTextOnlyEmbed(internalEmbedDiv)) {
//legacy reference to a block or section as text
//should be embedded as legacy text
return;
}
const attr: imgElementAttributes = {
fname: ctx.sourcePath,
fheight: "",
fwidth: getDefaultWidth(plugin),
style: "excalidraw-svg",
};
attr.file = file;
const markdownEmbed = internalEmbedDiv.hasClass("markdown-embed");
const markdownReadingView = internalEmbedDiv.hasClass("markdown-reading-view");
if (!internalEmbedDiv.hasClass("internal-embed") &&
( markdownEmbed || markdownReadingView)
) {
//We are processing the markdown preview of an actual Excalidraw file
//the excalidraw file in markdown preview mode
const isFrontmatterDiv = Boolean(el.querySelector(".frontmatter"));
el.empty();
if(internalEmbedDiv.hasAttribute("ready")) {
if(!isFrontmatterDiv) {
containerEl.removeChild(el);
return;
}
internalEmbedDiv.setAttribute("ready","");
internalEmbedDiv.empty();
const imgDiv = await processInternalEmbed(internalEmbedDiv,file);
const imgDiv = await createImageDiv(attr);
if(markdownEmbed) {
internalEmbedDiv.addClass("markdown-embed");
if(imgDiv.firstChild instanceof HTMLElement) {
imgDiv.firstChild.style.maxHeight = "100%";
imgDiv.firstChild.style.maxWidth = null;
internalEmbedDiv.appendChild(imgDiv.firstChild);
return;
}
}
internalEmbedDiv.appendChild(imgDiv);
return;
}
//timer to avoid the image flickering when the user is typing
let timer: NodeJS.Timeout = null;
const observer = new MutationObserver((m) => {
if (!["alt", "width", "height"].contains(m[0]?.attributeName)) {
return;
}
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(async () => {
timer = null;
internalEmbedDiv.empty();
const imgDiv = await processInternalEmbed(internalEmbedDiv,file);
internalEmbedDiv.appendChild(imgDiv);
}, 500);
});
observer.observe(internalEmbedDiv, {
attributes: true, //configure it to listen to attribute changes
});
if(isTextOnlyEmbed(internalEmbedDiv)) {
//legacy reference to a block or section as text
//should be embedded as legacy text
return;
}
el.empty();
if(internalEmbedDiv.hasAttribute("ready")) {
return;
}
internalEmbedDiv.setAttribute("ready","");
internalEmbedDiv.empty();
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;
const observer = new MutationObserver((m) => {
if (!["alt", "width", "height"].contains(m[0]?.attributeName)) {
return;
}
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(async () => {
timer = null;
internalEmbedDiv.empty();
const imgDiv = await processInternalEmbed(internalEmbedDiv,file);
internalEmbedDiv.appendChild(imgDiv);
}, 500);
});
observer.observe(internalEmbedDiv, {
attributes: true, //configure it to listen to attribute changes
});
};

View File

@@ -12,6 +12,11 @@ export const nanoid = customAlphabet(
export const KEYCODE = {
ESC: 27,
};
export const ROUNDNESS = { //should at one point publish @zsviczian/excalidraw/types/constants
LEGACY: 1,
PROPORTIONAL_RADIUS: 2,
ADAPTIVE_RADIUS: 3,
} as const;
export const PLUGIN_ID = "obsidian-excalidraw-plugin";
export const SCRIPT_INSTALL_CODEBLOCK = "excalidraw-script-install";
export const SCRIPT_INSTALL_FOLDER = "Downloaded";

View File

@@ -17,6 +17,50 @@ 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.8.5":`
## New from Excalidraw.com:
- Better default radius for rectangles [#5553](https://github.com/excalidraw/excalidraw/pull/5553). Existing drawings will look unchanged, this applies only to new rectangles.
![image|200](https://user-images.githubusercontent.com/5153846/206264345-59fd7436-e87b-4bc9-ade8-9e6f6a6fd8c1.png)
> [!attention]- ExcalidrawAutomate technical details
> - ${String.fromCharCode(96)}strokeSharpness${String.fromCharCode(96)} is now deprecated
> - use roundness instead
> - ${String.fromCharCode(96)}roundness === null${String.fromCharCode(96)} is legacy ${String.fromCharCode(96)}strokeSharpness = "sharp"${String.fromCharCode(96)}
> - ${String.fromCharCode(96)}roundness = { type: RoundnessType; value?: number }${String.fromCharCode(96)}
> - type: 1, LEGACY, type:2 PROPORTIONAL_RADIUS, type:3 ADAPTIVE_RADIUS: 3
> - value:
> - Radius represented as % of element's largest side (width/height).
> DEFAULT_PROPORTIONAL_RADIUS = 0.25;
> - Fixed radius for the ADAPTIVE_RADIUS algorithm. In pixels.
> DEFAULT_ADAPTIVE_RADIUS = 32;
## New
- Improved embedding into Obsidian Canvas
- Improved embedding into Markdown documents
- Added setting under ${String.fromCharCode(96)}Display/Default mode when opening Excalidraw${String.fromCharCode(96)} to always open the drawing in view mode on Mobile, but in normal mode on desktop. [#939](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/939)
## Fixed
- Zoom reset tooltip appears twice [#942](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/942)
- Hid export library from library menu as it does not work due to Obsidian limitations. Use the command palette export library instead.
- Arrow with label did not get exported and embedded correctly [#941](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/941)
![image|200](https://user-images.githubusercontent.com/22638687/207845868-b352ddb1-7994-4f13-a0b2-f2e19bd72935.png)
`,
"1.8.4":`
## New from Excalidraw.com
- Labels on Arrows!!! [#5723](https://github.com/excalidraw/excalidraw/pull/5723)
- To add a label press "Enter" or "Double click" on the arrow
- Use "Cmd/Ctrl+double click" to enter the line editor
<div class="excalidraw-videoWrapper"><div>
<iframe src="https://user-images.githubusercontent.com/11256141/192515552-6b6ddc06-5de0-4931-abdd-6ac3a804656d.mp4" title="Demo" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></div>
## New
- **Changed behavior**: In the Obsidian markdown editor clicking an Excalidraw image will not open the image (to avoid accidentally opening the image on a tablet). To open a drawing for editing in Excalidraw double click or long-tap on it. [#920](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/920)
## Fixed
- Text stroke color is not honored when pasting a HEX color string to an Excalidraw canvas open in an Obsidian popout window [#921](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/921)
- The new [multi-line >> multi-element paste behavior](https://github.com/excalidraw/excalidraw/pull/5786) introduced in the previous release did not work as expected in Obsidian. Now it does.
`,
"1.8.2":`
Introducing the [Excalidraw Slideshow Script](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/Slideshow.md) - available in the script store
<div class="excalidraw-videoWrapper"><div>

View File

@@ -73,9 +73,9 @@ export const EXCALIDRAW_AUTOMATE_INFO: SuggesterInfo[] = [
after: "",
},
{
field: "style.strokeSharpness",
code: "[string]",
desc: "'round' | 'sharp'",
field: "style.roundness",
code: "[null | { type: RoundnessType; value?: number };]",
desc: "set to null for 'sharp', else the stroke will be 'round'<br>type: 1==LEGACY,<br>2==PROPORTIONAL RADIUS,<br>3==ADAPTIVE RADIUS, value: adaptive factor defaults to 32",
after: "",
},
{

View File

@@ -1,7 +1,7 @@
import "obsidian";
//import { ExcalidrawAutomate } from "./ExcalidrawAutomate";
export {ExcalidrawAutomateInterface} from "./types";
export type { ExcalidrawBindableElement, ExcalidrawElement, FileId, FillStyle, StrokeSharpness, StrokeStyle } from "@zsviczian/excalidraw/types/element/types";
export type { ExcalidrawBindableElement, ExcalidrawElement, FileId, FillStyle, StrokeRoundness, StrokeStyle } from "@zsviczian/excalidraw/types/element/types";
export type { Point } from "@zsviczian/excalidraw/types/types";
export const getEA = (view?:any): any => {
try {

View File

@@ -2099,8 +2099,8 @@ export default class ExcalidrawPlugin extends Plugin {
e.initEvent(RERENDER_EVENT, true, false);
ownerDocument
.querySelectorAll(
`div[class^='excalidraw-svg']${
filepath ? `[src='${filepath.replaceAll("'", "\\'")}']` : ""
`img[class^='excalidraw-svg']${
filepath ? `[fileSource='${filepath.replaceAll("'", "\\'")}']` : ""
}`,
)
.forEach((el) => el.dispatchEvent(e));

View File

@@ -565,9 +565,10 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
.setDesc(fragWithHTML(t("DEFAULT_OPEN_MODE_DESC")))
.addDropdown((dropdown) =>
dropdown
.addOption("normal", "Normal Mode")
.addOption("zen", "Zen Mode")
.addOption("view", "View Mode")
.addOption("normal", "Always in normal-mode")
.addOption("zen", "Always in zen-mode")
.addOption("view", "Always in view-mode")
.addOption("view-mobile", "Usually normal, but view-mode on Phone")
.setValue(this.plugin.settings.defaultMode)
.onChange(async (value) => {
this.plugin.settings.defaultMode = value;

View File

@@ -1,6 +1,6 @@
import { randomId, randomInteger } from "../utils";
import { ExcalidrawLinearElement, FillStyle, GroupId, StrokeSharpness, StrokeStyle } from "@zsviczian/excalidraw/types/element/types";
import { ExcalidrawLinearElement, FillStyle, GroupId, RoundnessType, StrokeStyle } from "@zsviczian/excalidraw/types/element/types";
export type Point = [number, number];
@@ -13,7 +13,7 @@ export type ExcalidrawElementBase = {
fillStyle: FillStyle;
strokeWidth: number;
strokeStyle: StrokeStyle;
strokeSharpness: StrokeSharpness;
roundness: null | { type: RoundnessType; value?: number };
roughness: number;
opacity: number;
width: number;
@@ -71,7 +71,7 @@ export function createExElement(): ExcalidrawElementBase {
fillStyle: "solid",
strokeWidth: 1,
strokeStyle: "solid",
strokeSharpness: "sharp",
roundness: null,
roughness: 0,
opacity: 100,
width: 0,

View File

@@ -1,4 +1,4 @@
import { ExcalidrawElement, ExcalidrawLinearElement, ExcalidrawTextElement, FillStyle, GroupId, StrokeSharpness, StrokeStyle } from "@zsviczian/excalidraw/types/element/types";
import { ExcalidrawElement, ExcalidrawLinearElement, ExcalidrawTextElement, FillStyle, GroupId, RoundnessType, StrokeStyle } from "@zsviczian/excalidraw/types/element/types";
export type PathCommand = {
type: string;
@@ -53,7 +53,7 @@ type _ExcalidrawElementBase = Readonly<{
fillStyle: FillStyle;
strokeWidth: number;
strokeStyle: StrokeStyle;
strokeSharpness: StrokeSharpness;
roundness: null | { type: RoundnessType; value?: number };
roughness: number;
opacity: number;
width: number;

View File

@@ -25,6 +25,7 @@ import {
import { getTransformMatrix, transformPoints } from "./transform";
import { pointsOnPath } from "points-on-path";
import { randomId, getWindingOrder } from "./utils";
import { ROUNDNESS } from "../Constants";
const SUPPORTED_TAGS = [
"svg",
@@ -352,7 +353,7 @@ const walkers = {
y: result[13],
width: result[0],
height: result[5],
strokeSharpness: isRound ? "round" : "sharp",
roundness: isRound ? {type:ROUNDNESS.LEGACY} : null,
};
scene.elements.push(rect);

5
src/types.d.ts vendored
View File

@@ -1,4 +1,4 @@
import { ExcalidrawBindableElement, ExcalidrawElement, ExcalidrawImageElement, FileId, FillStyle, NonDeletedExcalidrawElement, StrokeSharpness, StrokeStyle } from "@zsviczian/excalidraw/types/element/types";
import { ExcalidrawBindableElement, ExcalidrawElement, ExcalidrawImageElement, FileId, FillStyle, NonDeletedExcalidrawElement, RoundnessType, StrokeRoundness, StrokeStyle } from "@zsviczian/excalidraw/types/element/types";
import { Point } from "@zsviczian/excalidraw/types/types";
import { TFile, WorkspaceLeaf } from "obsidian";
import { EmbeddedFilesLoader } from "./EmbeddedFileLoader";
@@ -28,7 +28,8 @@ export interface ExcalidrawAutomateInterface {
strokeStyle: StrokeStyle; //type StrokeStyle = "solid" | "dashed" | "dotted"
roughness: number;
opacity: number;
strokeSharpness: StrokeSharpness; //type StrokeSharpness = "round" | "sharp"
strokeSharpness?: StrokeRoundness; //defaults to undefined, use strokeRoundess and roundess instead. Only kept for legacy script compatibility type StrokeRoundness = "round" | "sharp"
roundness: null | { type: RoundnessType; value?: number };
fontFamily: number; //1: Virgil, 2:Helvetica, 3:Cascadia, 4:LocalFont
fontSize: number;
textAlign: string; //"left"|"right"|"center"

View File

@@ -1,4 +1,5 @@
{
"1.8.5": "1.0.0",
"1.7.13": "0.15.6",
"1.7.8": "0.15.5",
"1.7.7": "0.15.4",

View File

@@ -2221,10 +2221,10 @@
dependencies:
"@zerollup/ts-helpers" "^1.7.18"
"@zsviczian/excalidraw@0.13.0-obsidian-1":
"integrity" "sha512-gHfuEX/qrBa+4kolxEkQ/3W5hGfSLoJSXDpuhb8Mvvyyl148hsuWmhUQGFWcNee73YbuQ0arb3hXqwnMUgK0Ig=="
"resolved" "https://registry.npmjs.org/@zsviczian/excalidraw/-/excalidraw-0.13.0-obsidian-1.tgz"
"version" "0.13.0-obsidian-1"
"@zsviczian/excalidraw@0.13.0-obsidian-2":
"integrity" "sha512-gKB+V8EgxFimjaTmRZzBPumh1q7UeG7ri9MbVcBovpeWxnz7q/PROCgGv3tJvHzwZLzts3f+pL66l9pTecXoUA=="
"resolved" "https://registry.npmjs.org/@zsviczian/excalidraw/-/excalidraw-0.13.0-obsidian-2.tgz"
"version" "0.13.0-obsidian-2"
"abab@^2.0.3", "abab@^2.0.5":
"integrity" "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q=="