Compare commits

..

13 Commits

Author SHA1 Message Date
Zsolt Viczian
d8a5e26030 1.5.19 2022-01-16 21:00:50 +01:00
Zsolt Viczian
d6c686d230 1.5.18 2022-01-16 20:35:46 +01:00
Zsolt Viczian
d7446d20dd 1.5.17 2022-01-16 13:19:04 +01:00
zsviczian
541db2ca2f Merge pull request #368 from 1-2-3/master
Ignore individual lines when calculating maximum width and height
2022-01-16 06:20:58 +01:00
zahuifan
b0fc21b70a Ignore individual lines when calculating max width 2022-01-16 11:16:49 +08:00
zsviczian
0b36759f09 Update README.md 2022-01-15 12:09:15 +01:00
zsviczian
c94ebb6bcd Merge pull request #362 from 1-2-3/master
Add two new ea-scripts
2022-01-15 11:56:04 +01:00
zahuifan
75e179041d Add two new ea-scripts 2022-01-15 15:34:48 +08:00
zsviczian
3d41690359 Create codeql-analysis.yml 2022-01-14 21:52:35 +01:00
zsviczian
e3d31f49de Merge pull request #358 from 1-2-3/master
Fix unnecessary changes to text placement
2022-01-14 19:07:13 +01:00
zahuifan
ee48840421 Fix unnecessary changes to text placement 2022-01-14 13:40:48 +08:00
zsviczian
b8b08b3edb Merge pull request #356 from 1-2-3/master
Fixed rearranging text incorrectly when a rectangle contains multiple text elements.
2022-01-13 11:16:34 +01:00
zahuifan
d1f994a8d1 Fixed incorrect text placement 2022-01-13 17:50:44 +08:00
26 changed files with 842 additions and 449 deletions

70
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,70 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '38 14 * * 4'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@@ -13,6 +13,7 @@ Please upgrade to Obsidian v0.12.19 or higher to get the latest release.
|[![9 Excalidraw Automate](https://user-images.githubusercontent.com/14358394/125160367-bdb6cc00-e17c-11eb-92f1-6f59faea85fd.jpg)](https://youtu.be/VRZVujfVab0)|[![10 Miscellaneous](https://user-images.githubusercontent.com/14358394/125160374-c3141680-e17c-11eb-8cc2-dfaffd903d15.jpg)](https://youtu.be/D1iBYo1_jjc)|[![Image Elements](https://user-images.githubusercontent.com/14358394/138607067-ccb62f92-48a4-4880-ac6e-68c1bf86ac2c.png)](https://www.youtube.com/watch?v=_c_0zpBJ4Xc&)|
|[![LaTex Demo](https://user-images.githubusercontent.com/14358394/143732412-1c65227e-4381-406d-847a-b001ab3506ca.jpg)](https://youtu.be/r08wk-58DPk)|[![markdown embeds](https://user-images.githubusercontent.com/14358394/143732440-90bfa029-8615-462e-ada3-c903d71a82c9.jpg)](https://youtu.be/tsecSfnTMow)|[![markdownAdvanced](https://user-images.githubusercontent.com/14358394/143783906-15cee494-c6d5-4495-a2ca-74634e4e7355.jpg)](https://youtu.be/K6qZkTz8GHs)|
|[![Script Engine](https://user-images.githubusercontent.com/14358394/145684531-8d9c2992-59ac-4ebc-804a-4cce1777ded2.jpg)](https://youtu.be/hePJcObHIso)|[![sticky notes thumbnail](https://user-images.githubusercontent.com/14358394/147283367-e5689385-ea51-4983-81a3-04d810d39f62.jpg)](https://youtu.be/NOuddK6xrr8)|[![plugin store](https://user-images.githubusercontent.com/14358394/147889174-6c306d0d-2d29-46cc-a53f-3f0013cf14de.jpg)](https://youtu.be/lzYdOQ6z8F0)|
|[![fourtfont](https://user-images.githubusercontent.com/14358394/149659524-2a4e0a24-40c9-4e66-a6b1-c92f3b88ecd5.jpg)](https://youtu.be/eKFmrSQhFA4)|||
# Key features
@@ -61,6 +62,7 @@ Please upgrade to Obsidian v0.12.19 or higher to get the latest release.
- `excalidraw-link-prefix: "📍"` preview prefix for internal links
- `excalidraw-url-prefix: "🌐"` preview prefix for external links
- `excalidraw-link-brackets: true|false` whether or not to display brackets around links in preview
- `excalidraw-default-mode: view|zen` Open this document in view mode or zen mode by defult. Default view mode is excellent for presentation slides.
- Embed complete markdown files into your drawings
- Drag from the desired file from the Obsidian file explorer and hold down CTRL/CMD while dropping the file onto the canvas.
- Use the command palette action: `Insert markdown file from vault`

View File

@@ -17,7 +17,7 @@ export interface ExcalidrawAutomate {
roughness: number;
opacity: number;
strokeSharpness: StrokeSharpness; //type StrokeSharpness = "round" | "sharp"
fontFamily: number; //1: Virgil, 2:Helvetica, 3:Cascadia
fontFamily: number; //1: Virgil, 2:Helvetica, 3:Cascadia, 4:LocalFont
fontSize: number;
textAlign: string; //"left"|"right"|"center"
verticalAlign: string; //"top"|"bottom"|"middle" :for future use, has no effect currently

View File

@@ -0,0 +1,78 @@
/*
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-download-raw.jpg)
Download this file and save to your Obsidian Vault including the first line, or open it in "Raw" and copy the entire contents to Obsidian.
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-box-each-selected-groups.png)
This script will add encapsulating boxes around each of the currently selected groups in Excalidraw.
You can focus on content creation first, and then batch add consistent style boxes to each group of text.
Tips 1: You can copy the desired style to the global state using script `Copy Selected Element Style to Global`, then add boxes with the same global style using script `Box Each Selected Groups`.
Tips 2: Next you can use scripts `Expand rectangles horizontally keep text centered` and `Expand rectangles vertically keep text centered` to make the boxes the same size, if you wish.
Tips 3: If you want the left and right margins to be different from the top and bottom margins, input something like `32,16`, this will create a box with left and right margins of `32` and top and bottom margins of `16`.
See documentation for more details:
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
```javascript
*/
const paddingStr = await utils.inputPrompt("padding?","string","8");
var paddingLR = 0;
var paddingTB = 0;
if(paddingStr.indexOf(',') > 0) {
const paddingParts = paddingStr.split(',');
paddingLR = parseInt(paddingParts[0]);
paddingTB = parseInt(paddingParts[1]);
}
else {
paddingLR = paddingTB = parseInt(paddingStr);
}
if(isNaN(paddingLR) || isNaN(paddingTB)) {
return;
}
const elements = ea.getViewSelectedElements();
const groups = ea.getMaximumGroups(elements);
for(const elements of groups) {
if(elements.length === 1 && elements[0].type ==="arrow" || elements[0].type==="line") {
// individual arrows or lines are not affected
continue;
}
const box = ea.getBoundingBox(elements);
color = ea
.getExcalidrawAPI()
.getAppState()
.currentItemStrokeColor;
// use current stroke with and style
const appState = ea.getExcalidrawAPI().getAppState();
const strokeWidth = appState.currentItemStrokeWidth;
const strokeStyle = appState.currentItemStrokeStyle;
const strokeSharpness = appState.currentItemStrokeSharpness;
const roughness = appState.currentItemRoughness;
const fillStyle = appState.currentItemFillStyle;
const backgroundColor = appState.currentItemBackgroundColor;
ea.style.strokeWidth = strokeWidth;
ea.style.strokeStyle = strokeStyle;
ea.style.strokeSharpness = strokeSharpness;
ea.style.roughness = roughness;
ea.style.fillStyle = fillStyle;
ea.style.backgroundColor = backgroundColor;
ea.style.strokeColor = color;
const id = ea.addRect(
box.topX - paddingLR,
box.topY - paddingTB,
box.width + 2*paddingLR,
box.height + 2*paddingTB
);
ea.copyViewElementsToEAforEditing(elements);
ea.addToGroup([id].concat(elements.map((el)=>el.id)));
ea.addElementsToView(false);
ea.reset();
}

View File

@@ -0,0 +1,43 @@
/*
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-download-raw.jpg)
Download this file and save to your Obsidian Vault including the first line, or open it in "Raw" and copy the entire contents to Obsidian.
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-copy-selected-element-styles-to-global.png)
This script will copy styles of any selected element into Excalidraw's global styles.
After copying the styles of element such as box, text, or arrow using this script, You can then use Excalidraw's box, arrow, and other tools to create several elements with the same style. This is sometimes more convenient than `Copy Styles` and `Paste Styles`, especially when used with the script `Box Each Selected Groups`.
See documentation for more details:
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
```javascript
*/
const element = ea.getViewSelectedElement();
const appState = ea.getExcalidrawAPI().getAppState();
if(!element) {
return;
}
appState.currentItemStrokeWidth = element.strokeWidth;
appState.currentItemStrokeStyle = element.strokeStyle;
appState.currentItemStrokeSharpness = element.strokeSharpness;
appState.currentItemRoughness = element.roughness;
appState.currentItemFillStyle = element.fillStyle;
appState.currentItemBackgroundColor = element.backgroundColor;
appState.currentItemStrokeColor = element.strokeColor;
if(element.type === 'text') {
appState.currentItemFontFamily = element.fontFamily;
appState.currentItemFontSize = element.fontSize;
appState.currentItemTextAlign = element.textAlign;
}
if(element.type === 'arrow') {
appState.currentItemStartArrowhead = element.startArrowhead;
appState.currentItemEndArrowhead = element.endArrowhead;
}

View File

@@ -1,75 +1,86 @@
/*
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-download-raw.jpg)
Download this file and save to your Obsidian Vault including the first line, or open it in "Raw" and copy the entire contents to Obsidian.
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif)
This script expands the width of the selected rectangles until they are all the same width and keep the text centered.
See documentation for more details:
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
```javascript
*/
const elements = ea.getViewSelectedElements();
const topGroups = ea.getMaximumGroups(elements);
const groupWidths = topGroups
.map((g) =>
g.reduce(
(pre, cur, i) => {
if (i === 0) {
return {
minLeft: cur.x,
maxRight: cur.x + cur.width,
index: i,
};
} else {
return {
minLeft: cur.x < pre.minLeft ? cur.x : pre.minLeft,
maxRight:
cur.x + cur.width > pre.maxRight
? cur.x + cur.width
: pre.maxRight,
index: i,
};
}
},
{ minLeft: 0, maxRight: 0 }
)
)
.map((r) => {
r.width = r.maxRight - r.minLeft;
return r;
});
const maxGroupWidth = Math.max(...groupWidths.map((g) => g.width));
for (var i = 0; i < topGroups.length; i++) {
const rects = topGroups[i]
.filter((el) => el.type === "rectangle")
.sort((lha, rha) => lha.x - rha.x);
const texts = topGroups[i]
.filter((el) => el.type === "text")
.sort((lha, rha) => lha.x - rha.x);
const groupWith = groupWidths[i].width;
if (groupWith < maxGroupWidth) {
const distance = maxGroupWidth - groupWith;
const perRectDistance = distance / rects.length;
for (var j = 0; j < rects.length; j++) {
const rect = rects[j];
rect.x = rect.x + perRectDistance * j - perRectDistance / 2;
rect.width += perRectDistance;
}
for (var j = 0; j < texts.length; j++) {
const text = texts[j];
text.x = text.x + perRectDistance * j;
}
}
}
ea.copyViewElementsToEAforEditing(elements);
ea.addElementsToView(false, false);
/*
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-download-raw.jpg)
Download this file and save to your Obsidian Vault including the first line, or open it in "Raw" and copy the entire contents to Obsidian.
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif)
This script expands the width of the selected rectangles until they are all the same width and keep the text centered.
See documentation for more details:
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
```javascript
*/
const elements = ea.getViewSelectedElements();
const topGroups = ea.getMaximumGroups(elements);
const groupWidths = topGroups
.map((g) => {
if(g.length === 1 && (g[0].type === 'arrow' || g[0].type === 'line')) {
// ignore individual lines
return { minLeft: 0, maxRight: 0 };
}
return g.reduce(
(pre, cur, i) => {
if (i === 0) {
return {
minLeft: cur.x,
maxRight: cur.x + cur.width,
index: i,
};
} else {
return {
minLeft: cur.x < pre.minLeft ? cur.x : pre.minLeft,
maxRight:
cur.x + cur.width > pre.maxRight
? cur.x + cur.width
: pre.maxRight,
index: i,
};
}
},
{ minLeft: 0, maxRight: 0 }
);
})
.map((r) => {
r.width = r.maxRight - r.minLeft;
return r;
});
const maxGroupWidth = Math.max(...groupWidths.map((g) => g.width));
for (var i = 0; i < topGroups.length; i++) {
const rects = topGroups[i]
.filter((el) => el.type === "rectangle")
.sort((lha, rha) => lha.x - rha.x);
const texts = topGroups[i]
.filter((el) => el.type === "text")
.sort((lha, rha) => lha.x - rha.x);
const groupWith = groupWidths[i].width;
if (groupWith < maxGroupWidth) {
const distance = maxGroupWidth - groupWith;
const perRectDistance = distance / rects.length;
for (var j = 0; j < rects.length; j++) {
const rect = rects[j];
const rectLeft = rect.x;
const rectTop = rect.y;
const rectRight = rect.x + rect.width;
const rectBottom = rect.y + rect.height;
rect.x = rect.x + perRectDistance * j - perRectDistance / 2;
rect.width += perRectDistance;
const textsWithRect = texts.filter(text => text.x >= rectLeft && text.x <= rectRight
&& text.y >= rectTop && text.y <= rectBottom);
for(const text of textsWithRect) {
text.x = text.x + perRectDistance * j;
}
}
}
}
ea.copyViewElementsToEAforEditing(elements);
ea.addElementsToView(false, false);

View File

@@ -1,76 +1,74 @@
/*
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-download-raw.jpg)
Download this file and save to your Obsidian Vault including the first line, or open it in "Raw" and copy the entire contents to Obsidian.
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif)
This script expands the width of the selected rectangles until they are all the same width.
See documentation for more details:
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
```javascript
*/
const elements = ea.getViewSelectedElements();
const topGroups = ea.getMaximumGroups(elements);
const groupWidths = topGroups
.map((g) =>
g.reduce(
(pre, cur, i) => {
if (i === 0) {
return {
minLeft: cur.x,
maxRight: cur.x + cur.width,
index: i,
};
} else {
return {
minLeft: cur.x < pre.minLeft ? cur.x : pre.minLeft,
maxRight:
cur.x + cur.width > pre.maxRight
? cur.x + cur.width
: pre.maxRight,
index: i,
};
}
},
{ minLeft: 0, maxRight: 0 }
)
)
.map((r) => {
r.width = r.maxRight - r.minLeft;
return r;
});
const maxGroupWidth = Math.max(...groupWidths.map((g) => g.width));
for (var i = 0; i < topGroups.length; i++) {
const rects = topGroups[i]
.filter((el) => el.type === "rectangle")
.sort((lha, rha) => lha.x - rha.x);
const texts = topGroups[i]
.filter((el) => el.type === "text")
.sort((lha, rha) => lha.x - rha.x);
const groupWith = groupWidths[i].width;
if (groupWith < maxGroupWidth) {
const distance = maxGroupWidth - groupWith;
const perRectDistance = distance / rects.length;
for (var j = 0; j < rects.length; j++) {
const rect = rects[j];
rect.x = rect.x + perRectDistance * j;
rect.width += perRectDistance;
}
for (var j = 0; j < texts.length; j++) {
const text = texts[j];
text.x = text.x + perRectDistance * j;
}
}
}
ea.copyViewElementsToEAforEditing(elements);
ea.addElementsToView(false, false);
/*
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-download-raw.jpg)
Download this file and save to your Obsidian Vault including the first line, or open it in "Raw" and copy the entire contents to Obsidian.
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif)
This script expands the width of the selected rectangles until they are all the same width.
See documentation for more details:
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
```javascript
*/
const elements = ea.getViewSelectedElements();
const topGroups = ea.getMaximumGroups(elements);
const groupWidths = topGroups
.map((g) => {
if(g.length === 1 && (g[0].type === 'arrow' || g[0].type === 'line')) {
// ignore individual lines
return { minLeft: 0, maxRight: 0 };
}
return g.reduce(
(pre, cur, i) => {
if (i === 0) {
return {
minLeft: cur.x,
maxRight: cur.x + cur.width,
index: i,
};
} else {
return {
minLeft: cur.x < pre.minLeft ? cur.x : pre.minLeft,
maxRight:
cur.x + cur.width > pre.maxRight
? cur.x + cur.width
: pre.maxRight,
index: i,
};
}
},
{ minLeft: 0, maxRight: 0 }
);
})
.map((r) => {
r.width = r.maxRight - r.minLeft;
return r;
});
const maxGroupWidth = Math.max(...groupWidths.map((g) => g.width));
for (var i = 0; i < topGroups.length; i++) {
const rects = topGroups[i]
.filter((el) => el.type === "rectangle")
.sort((lha, rha) => lha.x - rha.x);
const groupWith = groupWidths[i].width;
if (groupWith < maxGroupWidth) {
const distance = maxGroupWidth - groupWith;
const perRectDistance = distance / rects.length;
for (var j = 0; j < rects.length; j++) {
const rect = rects[j];
rect.x = rect.x + perRectDistance * j;
rect.width += perRectDistance;
}
}
}
ea.copyViewElementsToEAforEditing(elements);
ea.addElementsToView(false, false);

View File

@@ -1,75 +1,86 @@
/*
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-download-raw.jpg)
Download this file and save to your Obsidian Vault including the first line, or open it in "Raw" and copy the entire contents to Obsidian.
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif)
This script expands the height of the selected rectangles until they are all the same height and keep the text centered.
See documentation for more details:
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
```javascript
*/
const elements = ea.getViewSelectedElements();
const topGroups = ea.getMaximumGroups(elements);
const groupHeights = topGroups
.map((g) =>
g.reduce(
(pre, cur, i) => {
if (i === 0) {
return {
minTop: cur.y,
maxBottom: cur.y + cur.height,
index: i,
};
} else {
return {
minTop: cur.y < pre.minTop ? cur.y : pre.minTop,
maxBottom:
cur.y + cur.height > pre.maxBottom
? cur.y + cur.height
: pre.maxBottom,
index: i,
};
}
},
{ minTop: 0, maxBottom: 0 }
)
)
.map((r) => {
r.height = r.maxBottom - r.minTop;
return r;
});
const maxGroupHeight = Math.max(...groupHeights.map((g) => g.height));
for (var i = 0; i < topGroups.length; i++) {
const rects = topGroups[i]
.filter((el) => el.type === "rectangle")
.sort((lha, rha) => lha.y - rha.y);
const texts = topGroups[i]
.filter((el) => el.type === "text")
.sort((lha, rha) => lha.y - rha.y);
const groupWith = groupHeights[i].height;
if (groupWith < maxGroupHeight) {
const distance = maxGroupHeight - groupWith;
const perRectDistance = distance / rects.length;
for (var j = 0; j < rects.length; j++) {
const rect = rects[j];
rect.y = rect.y + perRectDistance * j - perRectDistance / 2;
rect.height += perRectDistance;
}
for (var j = 0; j < texts.length; j++) {
const text = texts[j];
text.y = text.y + perRectDistance * j;
}
}
}
ea.copyViewElementsToEAforEditing(elements);
ea.addElementsToView(false, false);
/*
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-download-raw.jpg)
Download this file and save to your Obsidian Vault including the first line, or open it in "Raw" and copy the entire contents to Obsidian.
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif)
This script expands the height of the selected rectangles until they are all the same height and keep the text centered.
See documentation for more details:
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
```javascript
*/
const elements = ea.getViewSelectedElements();
const topGroups = ea.getMaximumGroups(elements);
const groupHeights = topGroups
.map((g) => {
if(g.length === 1 && (g[0].type === 'arrow' || g[0].type === 'line')) {
// ignore individual lines
return { minTop: 0, maxBottom: 0 };
}
return g.reduce(
(pre, cur, i) => {
if (i === 0) {
return {
minTop: cur.y,
maxBottom: cur.y + cur.height,
index: i,
};
} else {
return {
minTop: cur.y < pre.minTop ? cur.y : pre.minTop,
maxBottom:
cur.y + cur.height > pre.maxBottom
? cur.y + cur.height
: pre.maxBottom,
index: i,
};
}
},
{ minTop: 0, maxBottom: 0 }
);
})
.map((r) => {
r.height = r.maxBottom - r.minTop;
return r;
});
const maxGroupHeight = Math.max(...groupHeights.map((g) => g.height));
for (var i = 0; i < topGroups.length; i++) {
const rects = topGroups[i]
.filter((el) => el.type === "rectangle")
.sort((lha, rha) => lha.y - rha.y);
const texts = topGroups[i]
.filter((el) => el.type === "text")
.sort((lha, rha) => lha.y - rha.y);
const groupWith = groupHeights[i].height;
if (groupWith < maxGroupHeight) {
const distance = maxGroupHeight - groupWith;
const perRectDistance = distance / rects.length;
for (var j = 0; j < rects.length; j++) {
const rect = rects[j];
const rectLeft = rect.x;
const rectTop = rect.y;
const rectRight = rect.x + rect.width;
const rectBottom = rect.y + rect.height;
rect.y = rect.y + perRectDistance * j - perRectDistance / 2;
rect.height += perRectDistance;
const textsWithRect = texts.filter(text => text.x >= rectLeft && text.x <= rectRight
&& text.y >= rectTop && text.y <= rectBottom);
for(const text of textsWithRect) {
text.y = text.y + perRectDistance * j;
}
}
}
}
ea.copyViewElementsToEAforEditing(elements);
ea.addElementsToView(false, false);

View File

@@ -1,73 +1,71 @@
/*
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-download-raw.jpg)
Download this file and save to your Obsidian Vault including the first line, or open it in "Raw" and copy the entire contents to Obsidian.
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif)
This script expands the height of the selected rectangles until they are all the same height.
```javascript
*/
const elements = ea.getViewSelectedElements();
const topGroups = ea.getMaximumGroups(elements);
const groupHeights = topGroups
.map((g) =>
g.reduce(
(pre, cur, i) => {
if (i === 0) {
return {
minTop: cur.y,
maxBottom: cur.y + cur.height,
index: i,
};
} else {
return {
minTop: cur.y < pre.minTop ? cur.y : pre.minTop,
maxBottom:
cur.y + cur.height > pre.maxBottom
? cur.y + cur.height
: pre.maxBottom,
index: i,
};
}
},
{ minTop: 0, maxBottom: 0 }
)
)
.map((r) => {
r.height = r.maxBottom - r.minTop;
return r;
});
const maxGroupHeight = Math.max(...groupHeights.map((g) => g.height));
for (var i = 0; i < topGroups.length; i++) {
const rects = topGroups[i]
.filter((el) => el.type === "rectangle")
.sort((lha, rha) => lha.y - rha.y);
const texts = topGroups[i]
.filter((el) => el.type === "text")
.sort((lha, rha) => lha.y - rha.y);
const groupWith = groupHeights[i].height;
if (groupWith < maxGroupHeight) {
const distance = maxGroupHeight - groupWith;
const perRectDistance = distance / rects.length;
for (var j = 0; j < rects.length; j++) {
const rect = rects[j];
rect.y = rect.y + perRectDistance * j;
rect.height += perRectDistance;
}
for (var j = 0; j < texts.length; j++) {
const text = texts[j];
text.y = text.y + perRectDistance * j;
}
}
}
ea.copyViewElementsToEAforEditing(elements);
ea.addElementsToView(false, false);
/*
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-download-raw.jpg)
Download this file and save to your Obsidian Vault including the first line, or open it in "Raw" and copy the entire contents to Obsidian.
![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif)
This script expands the height of the selected rectangles until they are all the same height.
```javascript
*/
const elements = ea.getViewSelectedElements();
const topGroups = ea.getMaximumGroups(elements);
const groupHeights = topGroups
.map((g) => {
if(g.length === 1 && (g[0].type === 'arrow' || g[0].type === 'line')) {
// ignore individual lines
return { minTop: 0, maxBottom: 0 };
}
return g.reduce(
(pre, cur, i) => {
if (i === 0) {
return {
minTop: cur.y,
maxBottom: cur.y + cur.height,
index: i,
};
} else {
return {
minTop: cur.y < pre.minTop ? cur.y : pre.minTop,
maxBottom:
cur.y + cur.height > pre.maxBottom
? cur.y + cur.height
: pre.maxBottom,
index: i,
};
}
},
{ minTop: 0, maxBottom: 0 }
);
})
.map((r) => {
r.height = r.maxBottom - r.minTop;
return r;
});
const maxGroupHeight = Math.max(...groupHeights.map((g) => g.height));
for (var i = 0; i < topGroups.length; i++) {
const rects = topGroups[i]
.filter((el) => el.type === "rectangle")
.sort((lha, rha) => lha.y - rha.y);
const groupWith = groupHeights[i].height;
if (groupWith < maxGroupHeight) {
const distance = maxGroupHeight - groupWith;
const perRectDistance = distance / rects.length;
for (var j = 0; j < rects.length; j++) {
const rect = rects[j];
rect.y = rect.y + perRectDistance * j;
rect.height += perRectDistance;
}
}
}
ea.copyViewElementsToEAforEditing(elements);
ea.addElementsToView(false, false);

View File

@@ -14,10 +14,12 @@ Open the script you are interested in and save it to your Obsidian Vault includi
## List of available scripts
|Title|Description|Icon|Contributor|
|----|----|----|----|
|[Box Each Selected Groups](Box%20Each%20Selected%20Groups.md)|This script will add encapsulating boxes around each of the currently selected groups in Excalidraw.|![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-box-each-selected-groups.png)|[@1-2-3](https://github.com/1-2-3)|
|[Box Selected Elements](Box%20Selected%20Elements.md)|This script will add an encapsulating box around the currently selected elements in Excalidraw.|![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-box-elements.jpg)|[@zsviczian](https://github.com/zsviczian)|
|[Bullet Point](Bullet%20Point.md)|This script will add a small circle to the top left of each text element in the selection and add the text and the "bullet point" into a group.|![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-bullet-point.jpg)|[@zsviczian](https://github.com/zsviczian)|
|[Connect elements](Connect%20elements.md)|This script will connect two objects with an arrow. If either of the objects are a set of grouped elements (e.g. a text element grouped with an encapsulating rectangle), the script will identify these groups, and connect the arrow to the largest object in the group (assuming you want to connect the arrow to the box around the text element).|![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-connect-elements.jpg)|[@zsviczian](https://github.com/zsviczian)|
|[Convert text to link with folder and alias](Convert%20text%20to%20link%20with%20folder%20and%20alias.md)|Converts text elements to links pointing to a file in a selected folder and with the alias set as the original text. The script will prompt the user to select an existing folder from the vault.|`original text` => `[[selected folder/original text\|original text]]`|[@zsviczian](https://github.com/zsviczian)|
|[Copy Selected Element Styles to Global](Copy%20Selected%20Element%20Styles%20to%20Global)|This script will copy styles of any selected element into Excalidraw's global styles.|![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-copy-selected-element-styles-to-global.png)|[@1-2-3](https://github.com/1-2-3)|
|[Create new markdown file and embed into active drawing](Create%20new%20markdown%20file%20and%20embed%20into%20active%20drawing.md)|The script will prompt you for a filename, then create a new markdown document with the file name provided, open the new markdown document in an adjacent pane, and embed the markdown document into the active Excalidraw drawing.|![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-create-and-embed-new-markdown-file.jpg)|[@zsviczian](https://github.com/zsviczian)|
|[Darken background color](Darken%20background%20color.md)|This script darkens the background color of the selected element by 2% at a time. You can use this script several times until you are satisfied. It is recommended to set a shortcut key for this script so that you can quickly try to DARKEN and LIGHTEN the color effect. In contrast to the `Modify background color opacity` script, the advantage is that the background color of the element is not affected by the canvas color, and the color value does not appear in a strange rgba() form.|![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/darken-lighten-background-color.png)|[@1-2-3](https://github.com/1-2-3)|
|[Dimensions](Dimensions.md)|Currently there is no way to specify the exact location and size of objects in Excalidraw. You can bridge this gap with the following simple script.|![](https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-dimensions.jpg)|[@zsviczian](https://github.com/zsviczian)|

View File

@@ -25,10 +25,12 @@ I would love to include your contribution in the script library. If you have a s
---
# List of available scripts
- [[#Box Each Selected Groups]]
- [[#Box Selected Elements]]
- [[#Bullet Point]]
- [[#Connect elements]]
- [[#Convert text to link with folder and alias]]
- [[#Copy Selected Element Styles to Global]]
- [[#Create new markdown file and embed into active drawing]]
- [[#Darken background color]]
- [[#Dimensions]]
@@ -52,6 +54,11 @@ I would love to include your contribution in the script library. If you have a s
- [[#Transfer TextElements to Excalidraw markdown metadata]]
- [[#Zoom to Fit Selected Elements]]
## Box Each Selected Groups
```excalidraw-script-install
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Box%20Each%20Selected%20Groups.md
```
<table><tr valign='top'><td class="label">Author</td><td class="data"><a href='https://github.com/1-2-3'>@1-2-3</a></td></tr><tr valign='top'><td class="label">Source</td><td class="data"><a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/Box%20Each%20Selected%20Groups.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will add encapsulating boxes around each of the currently selected groups in Excalidraw.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-box-each-selected-groups.png'></td></tr></table>
## Box Selected Elements
```excalidraw-script-install
@@ -77,6 +84,12 @@ https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea
```
<table><tr valign='top'><td class="label">Author</td><td class="data"><a href='https://github.com/zsviczian'>@zsviczian</a></td></tr><tr valign='top'><td class="label">Source</td><td class="data"><a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/Convert%20text%20to%20link%20with%20folder%20and%20alias.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Converts text elements to links pointing to a file in a selected folder and with the alias set as the original text. The script will prompt the user to select an existing folder from the vault.<br><code>original text</code> - <code>[[selected folder/original text|original text]]</code></td></tr></table>
## Copy Selected Element Styles to Global
```excalidraw-script-install
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Copy%20Selected%20Element%20Styles%20to%20Global.md
```
<table><tr valign='top'><td class="label">Author</td><td class="data"><a href='https://github.com/1-2-3'>@1-2-3</a></td></tr><tr valign='top'><td class="label">Source</td><td class="data"><a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/Copy%20Selected%20Element%20Styles%20to%20Global.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will copy styles of any selected element into Excalidraw's global styles.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-copy-selected-element-styles-to-global.png'></td></tr></table>
## Create new markdown file and embed into active drawing
```excalidraw-script-install
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Create%20new%20markdown%20file%20and%20embed%20into%20active%20drawing.md

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

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

View File

@@ -12,7 +12,7 @@
"author": "",
"license": "MIT",
"dependencies": {
"@zsviczian/excalidraw": "0.10.0-obsidian-33",
"@zsviczian/excalidraw": "0.10.0-obsidian-35",
"monkey-around": "^2.2.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",

View File

@@ -19,6 +19,8 @@ import { tex2dataURL } from "./LaTeX";
import ExcalidrawPlugin from "./main";
import {
errorlog,
getDataURL,
getFontDataURL,
getImageSize,
getLinkParts,
LinkParts,
@@ -397,25 +399,9 @@ const convertMarkdownToSVG = async (
fontDef = "";
break;
default:
const f = plugin.app.metadataCache.getFirstLinkpathDest(
fontName,
file.path,
);
if (f) {
const ab = await plugin.app.vault.readBinary(f);
const mimeType = f.extension.startsWith("woff")
? "application/font-woff"
: "font/truetype";
fontName = f.basename;
fontDef = ` @font-face {font-family: "${fontName}";src: url("${await getDataURL(
ab,
mimeType,
)}") format("${f.extension === "ttf" ? "truetype" : f.extension}");}`;
const split = fontDef.split(";base64,", 2);
fontDef = `${split[0]};charset=utf-8;base64,${split[1]}`;
} else {
fontDef = "";
}
const font = await getFontDataURL(plugin.app,fontName,file.path);
fontDef = font.fontDef;
fontName = font.fontName;
}
const fontColor = fileCache?.frontmatter
@@ -552,21 +538,6 @@ const convertMarkdownToSVG = async (
return svgToBase64(finalSVG) as DataURL;
};
const getDataURL = async (
file: ArrayBuffer,
mimeType: string,
): Promise<DataURL> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const dataURL = reader.result as DataURL;
resolve(dataURL);
};
reader.onerror = (error) => reject(error);
reader.readAsDataURL(new Blob([new Uint8Array(file)], { type: mimeType }));
});
};
const generateIdFromFile = async (file: ArrayBuffer): Promise<FileId> => {
let id: FileId;
try {

View File

@@ -52,7 +52,7 @@ export interface ExcalidrawAutomate {
roughness: number;
opacity: number;
strokeSharpness: StrokeSharpness; //type StrokeSharpness = "round" | "sharp"
fontFamily: number; //1: Virgil, 2:Helvetica, 3:Cascadia
fontFamily: number; //1: Virgil, 2:Helvetica, 3:Cascadia, 4:LocalFont
fontSize: number;
textAlign: string; //"left"|"right"|"center"
verticalAlign: string; //"top"|"bottom"|"middle" :for future use, has no effect currently
@@ -289,14 +289,17 @@ export async function initExcalidrawAutomate(
setFontFamily(val: number) {
switch (val) {
case 1:
this.style.fontFamily = 1;
return getFontFamily(1);
this.style.fontFamily = 4;
return getFontFamily(4);
case 2:
this.style.fontFamily = 2;
return getFontFamily(2);
default:
case 3:
this.style.strokeSharpness = 3;
return getFontFamily(3);
default:
this.style.strokeSharpness = 1;
return getFontFamily(1);
}
},
setTheme(val: number) {
@@ -1333,6 +1336,8 @@ function getFontFamily(id: number) {
return "Helvetica, Segoe UI Emoji";
case 3:
return "Cascadia, Segoe UI Emoji";
case 4:
return "LocalFont";
}
}
@@ -1546,7 +1551,7 @@ export async function createSVG(
if (template?.hasSVGwithBitmap) {
svg.setAttribute("hasbitmap", "true");
}
return embedFont ? embedFontsInSVG(svg) : svg;
return embedFont ? embedFontsInSVG(svg,plugin) : svg;
}
function estimateLineBound(points: any): [number, number, number, number] {

View File

@@ -152,9 +152,9 @@ export default class ExcalidrawView extends TextFileView {
private preventReload: boolean = true;
public compatibilityMode: boolean = false;
//store key state for view mode link resolution
private ctrlKeyDown = false;
/*private ctrlKeyDown = false;
private shiftKeyDown = false;
private altKeyDown = false;
private altKeyDown = false;*/
//https://stackoverflow.com/questions/27132796/is-there-any-javascript-event-fired-when-the-on-screen-keyboard-on-mobile-safari
private isEditingText: boolean = false;
@@ -205,7 +205,7 @@ export default class ExcalidrawView extends TextFileView {
return;
}
const serializer = new XMLSerializer();
const svgString = serializer.serializeToString(embedFontsInSVG(svg));
const svgString = serializer.serializeToString(embedFontsInSVG(svg,this.plugin));
if (file && file instanceof TFile) {
await this.app.vault.modify(file, svgString);
} else {
@@ -823,6 +823,10 @@ export default class ExcalidrawView extends TextFileView {
? om.zenModeEnabled
: this.excalidrawAPI.getAppState().zenModeEnabled;
//debug({where:"ExcalidrawView.loadDrawing",file:this.file.name,dataTheme:excalidrawData.appState.theme,before:"updateScene"})
this.excalidrawAPI.setLocalFont(
this.plugin.settings.experimentalEnableFourthFont
);
this.excalidrawAPI.updateScene({
elements: excalidrawData.elements,
appState: {
@@ -1007,7 +1011,7 @@ export default class ExcalidrawView extends TextFileView {
if (!svg) {
return null;
}
svg = embedFontsInSVG(svg);
svg = embedFontsInSVG(svg,this.plugin);
download(
null,
svgToBase64(svg.outerHTML),
@@ -1070,6 +1074,10 @@ export default class ExcalidrawView extends TextFileView {
this.excalidrawAPI = api;
//console.log({where:"ExcalidrawView.React.ReadyPromise"});
//debug({where:"ExcalidrawView.React.useEffect",file:this.file.name,before:"this.loadSceneFiles"});
this.excalidrawAPI.setLocalFont(
this.plugin.settings.experimentalEnableFourthFont
);
this.loadSceneFiles();
this.updateContainerSize(null, true);
});
@@ -1517,8 +1525,8 @@ export default class ExcalidrawView extends TextFileView {
const event = new MouseEvent("click", {
ctrlKey: true,
metaKey: true,
shiftKey: this.shiftKeyDown,
altKey: this.altKeyDown,
shiftKey: this.plugin.shiftKeyDown,
altKey: this.plugin.altKeyDown,
});
this.handleLinkClick(this, event);
selectedTextElement = null;
@@ -1528,8 +1536,8 @@ export default class ExcalidrawView extends TextFileView {
const event = new MouseEvent("click", {
ctrlKey: true,
metaKey: true,
shiftKey: this.shiftKeyDown,
altKey: this.altKeyDown,
shiftKey: this.plugin.shiftKeyDown,
altKey: this.plugin.altKeyDown,
});
this.handleLinkClick(this, event);
selectedImageElement = null;
@@ -1538,6 +1546,73 @@ export default class ExcalidrawView extends TextFileView {
let mouseEvent: any = null;
const showHoverPreview = () => {
let linktext = "";
const selectedElement = getTextElementAtPointer(currentPosition);
if (!selectedElement || !selectedElement.text) {
const selectedImgElement =
getImageElementAtPointer(currentPosition);
if (!selectedImgElement || !selectedImgElement.fileId) {
return;
}
if (!this.excalidrawData.hasFile(selectedImgElement.fileId)) {
return;
}
const ef = this.excalidrawData.getFile(
selectedImgElement.fileId,
);
const ref = ef.linkParts.ref
? `#${ef.linkParts.isBlockRef ? "^" : ""}${ef.linkParts.ref}`
: "";
linktext =
this.excalidrawData.getFile(selectedImgElement.fileId).file
.path + ref;
} else {
const text: string =
this.textMode === TextMode.parsed
? 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;
}
}
this.plugin.hover.linkText = linktext;
this.plugin.hover.sourcePath = this.file.path;
hoverPreviewTarget = this.contentEl; //e.target;
this.app.workspace.trigger("hover-link", {
event: mouseEvent,
source: VIEW_TYPE_EXCALIDRAW,
hoverParent: hoverPreviewTarget,
targetEl: hoverPreviewTarget,
linktext: this.plugin.hover.linkText,
sourcePath: this.plugin.hover.sourcePath,
});
hoverPoint = currentPosition;
if (this.isFullscreen()) {
const self = this;
setTimeout(() => {
const popover = document.body.querySelector("div.popover");
if (popover) {
self.contentEl.append(popover);
}
}, 100);
}
}
const excalidrawDiv = React.createElement(
"div",
{
@@ -1554,83 +1629,20 @@ export default class ExcalidrawView extends TextFileView {
this.exitFullscreen();
}
/*
this.ctrlKeyDown = e[CTRL_OR_CMD]; //.ctrlKey||e.metaKey;
this.shiftKeyDown = e.shiftKey;
this.altKeyDown = e.altKey;
this.altKeyDown = e.altKey;*/
if (e[CTRL_OR_CMD] && !e.shiftKey && !e.altKey) {
//.ctrlKey||e.metaKey) && !e.shiftKey && !e.altKey) {
let linktext = "";
const selectedElement = getTextElementAtPointer(currentPosition);
if (!selectedElement || !selectedElement.text) {
const selectedImgElement =
getImageElementAtPointer(currentPosition);
if (!selectedImgElement || !selectedImgElement.fileId) {
return;
}
if (!this.excalidrawData.hasFile(selectedImgElement.fileId)) {
return;
}
const ef = this.excalidrawData.getFile(
selectedImgElement.fileId,
);
const ref = ef.linkParts.ref
? `#${ef.linkParts.isBlockRef ? "^" : ""}${ef.linkParts.ref}`
: "";
linktext =
this.excalidrawData.getFile(selectedImgElement.fileId).file
.path + ref;
} else {
const text: string =
this.textMode === TextMode.parsed
? 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;
}
}
this.plugin.hover.linkText = linktext;
this.plugin.hover.sourcePath = this.file.path;
hoverPreviewTarget = this.contentEl; //e.target;
this.app.workspace.trigger("hover-link", {
event: mouseEvent,
source: VIEW_TYPE_EXCALIDRAW,
hoverParent: hoverPreviewTarget,
targetEl: hoverPreviewTarget,
linktext: this.plugin.hover.linkText,
sourcePath: this.plugin.hover.sourcePath,
});
hoverPoint = currentPosition;
if (this.isFullscreen()) {
const self = this;
setTimeout(() => {
const popover = document.body.querySelector("div.popover");
if (popover) {
self.contentEl.append(popover);
}
}, 100);
}
showHoverPreview();
}
},
onKeyUp: (e: any) => {
/* onKeyUp: (e: any) => {
this.ctrlKeyDown = e[CTRL_OR_CMD]; //.ctrlKey||e.metaKey;
this.shiftKeyDown = e.shiftKey;
this.altKeyDown = e.altKey;
},
},*/
onClick: (e: MouseEvent): any => {
if (!e[CTRL_OR_CMD]) {
return;
@@ -1699,7 +1711,7 @@ export default class ExcalidrawView extends TextFileView {
blockOnMouseButtonDown = true;
//ctrl click
if (this.ctrlKeyDown) {
if (this.plugin.ctrlKeyDown) {
handleLinkClick();
return;
}
@@ -1715,6 +1727,9 @@ export default class ExcalidrawView extends TextFileView {
if (p.button === "up") {
blockOnMouseButtonDown = false;
}
if (this.plugin.ctrlKeyDown) {
showHoverPreview();
}
},
onChange: (et: ExcalidrawElement[], st: AppState) => {
viewModeEnabled = st.viewModeEnabled;

View File

@@ -127,7 +127,7 @@ const getIMG = async (
if (!svg) {
return null;
}
svg = embedFontsInSVG(svg);
svg = embedFontsInSVG(svg,plugin);
svg.removeAttribute("width");
svg.removeAttribute("height");
img.setAttribute("src", svgToBase64(svg.outerHTML));
@@ -312,7 +312,10 @@ const tmpObsidianWYSIWYG = async (
if(hasHeight)
attr.fheight = internalEmbedDiv.getAttribute("height");
const alt = internalEmbedDiv.getAttribute("alt");
const hasAttr = alt && alt!=="" && alt!==basename;
const hasAttr = alt
&& alt !== ""
&& alt !== basename
&& alt !== internalEmbedDiv.getAttribute("src");
if(hasAttr) {
//1:width, 2:height, 3:style 1 2 3
const parts = alt.match(/(\d*%?)x?(\d*%?)\|?(.*)/);

View File

@@ -3,13 +3,14 @@ import {
App,
normalizePath,
Notice,
request,
TAbstractFile,
TFolder,
Vault,
WorkspaceLeaf,
} from "obsidian";
import { Random } from "roughjs/bin/math";
import { Zoom } from "@zsviczian/excalidraw/types/types";
import { DataURL, Zoom } from "@zsviczian/excalidraw/types/types";
import { CASCADIA_FONT, REG_BLOCK_REF_CLEAN, VIRGIL_FONT } from "./constants";
import ExcalidrawPlugin from "./main";
import { ExcalidrawElement } from "@zsviczian/excalidraw/types/element/types";
@@ -34,14 +35,35 @@ export const checkExcalidrawVersion = async (app:App) => {
versionUpdateChecked = true;
//@ts-ignore
const manifest = app.plugins.manifests["obsidian-excalidraw-plugin"];
//@ts-ignore
const latestVersion = await app.plugins.getLatestVersion("obsidian-excalidraw-plugin",manifest)
if(latestVersion>manifest.version) {
new Notice(`A newer version of Excalidraw is available in Community Plugins. You are using ${manifest.version}. The latest version is ${latestVersion}`);
try {
const gitAPIrequest = async () => {
return JSON.parse(await request({
url: `https://api.github.com/repos/zsviczian/obsidian-excalidraw-plugin/releases?per_page=5&page=1`,
}))
}
const latestVersion = ((await gitAPIrequest())
.map((el:any) => {
return {
version: el.tag_name,
published: new Date(el.published_at),
};
})
.filter((el:any) => el.version.match(/^\d+\.\d+\.\d+$/))
.sort((el1:any,el2:any)=>el2.published-el1.published))[0].version;
if(latestVersion>manifest.version) {
new Notice(`A newer version of Excalidraw is available in Community Plugins.\n\nYou are using ${manifest.version}.\nThe latest is ${latestVersion}`);
}
} catch(e) {
errorlog({where:"Utils/checkExcalidrawVersion", error:e});
}
setTimeout(()=>versionUpdateChecked=false,28800000);//reset after 8 hours
}
/**
* Splits a full path including a folderpath and a filename into separate folderpath and filename components
* @param filepath
@@ -281,6 +303,53 @@ export const getNewOrAdjacentLeaf = (
return plugin.app.workspace.createLeafBySplit(leaf);
};
export const getDataURL = async (
file: ArrayBuffer,
mimeType: string,
): Promise<DataURL> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const dataURL = reader.result as DataURL;
resolve(dataURL);
};
reader.onerror = (error) => reject(error);
reader.readAsDataURL(new Blob([new Uint8Array(file)], { type: mimeType }));
});
};
export const getFontDataURL = async (
app:App,
fontFileName: string,
sourcePath: string,
name?:string
):Promise<{fontDef: string, fontName: string, dataURL: string}> => {
let fontDef:string = "";
let fontName = "";
let dataURL = "";
const f = app.metadataCache.getFirstLinkpathDest(
fontFileName,
sourcePath,
);
if (f) {
const ab = await app.vault.readBinary(f);
const mimeType = f.extension.startsWith("woff")
? "application/font-woff"
: "font/truetype";
fontName = name??f.basename;
dataURL = await getDataURL(
ab,
mimeType,
);
fontDef = ` @font-face {font-family: "${fontName}";src: url("${
dataURL
}") format("${f.extension === "ttf" ? "truetype" : f.extension}");}`;
const split = fontDef.split(";base64,", 2);
fontDef = `${split[0]};charset=utf-8;base64,${split[1]}`;
}
return {fontDef,fontName,dataURL};
}
export const svgToBase64 = (svg: string): string => {
return `data:image/svg+xml;base64,${btoa(
unescape(encodeURIComponent(svg.replaceAll("&nbsp;", " "))),
@@ -379,17 +448,19 @@ export const getPNG = async (
}
};
export const embedFontsInSVG = (svg: SVGSVGElement): SVGSVGElement => {
export const embedFontsInSVG = (svg: SVGSVGElement, plugin: ExcalidrawPlugin): SVGSVGElement => {
//replace font references with base64 fonts
const includesVirgil =
svg.querySelector("text[font-family^='Virgil']") != null;
const includesCascadia =
svg.querySelector("text[font-family^='Cascadia']") != null;
const includesLocalFont =
svg.querySelector("text[font-family^='LocalFont']") != null;
const defs = svg.querySelector("defs");
if (defs && (includesCascadia || includesVirgil)) {
if (defs && (includesCascadia || includesVirgil || includesLocalFont)) {
defs.innerHTML = `<style>${includesVirgil ? VIRGIL_FONT : ""}${
includesCascadia ? CASCADIA_FONT : ""
}</style>`;
}${includesLocalFont ? plugin.fourthFontDef : ""}</style>`;
}
return svg;
};

File diff suppressed because one or more lines are too long

View File

@@ -275,6 +275,15 @@ export default {
LIVEPREVIEW_DESC: "Turn this on to support image embedding styles such as ![[drawing|width|style]] in live preview editing mode. " +
"The setting will not effect the currently open documents. You need close the open documents and re-open them for the change " +
"to take effect.",
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. " +
"Files that use this fourth font will (partly) lose their paltform independence. " +
"Depending on the cutom font set in settings, they will look differently when loaded in another vault, or at a later time. " +
"Also the 4th font will display as system default font on excalidraw.com, or other Excalidraw versions.",
FOURTH_FONT_NAME: "Forth font file",
FOURTH_FONT_DESC: "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.",
//openDrawings.ts
SELECT_FILE: "Select a file then press enter.",

View File

@@ -39,6 +39,8 @@ import {
CTRL_OR_CMD,
SCRIPT_INSTALL_CODEBLOCK,
SCRIPT_INSTALL_FOLDER,
VIRGIL_FONT,
VIRGIL_DATAURL,
} from "./constants";
import ExcalidrawView, { ExportSettings, TextMode } from "./ExcalidrawView";
import { getMarkdownDrawingSection } from "./ExcalidrawData";
@@ -67,6 +69,7 @@ import {
embedFontsInSVG,
errorlog,
getAttachmentsFolderAndFilePath,
getFontDataURL,
getIMGFilename,
getIMGPathFromExcalidrawFile,
getNewUniqueFilepath,
@@ -120,7 +123,7 @@ export default class ExcalidrawPlugin extends Plugin {
public mathjax: any = null;
private mathjaxDiv: HTMLDivElement = null;
public scriptEngine: ScriptEngine;
public fourthFontDef: string = VIRGIL_FONT;
constructor(app: App, manifest: PluginManifest) {
super(app, manifest);
this.filesMaster = new Map<
@@ -155,6 +158,7 @@ export default class ExcalidrawPlugin extends Plugin {
this.experimentalFileTypeDisplayToggle(this.settings.experimentalFileType);
this.registerCommands();
this.registerEventListeners();
this.initializeFourthFont();
//inspiration taken from kanban:
//https://github.com/mgmeyers/obsidian-kanban/blob/44118e25661bff9ebfe54f71ae33805dc88ffa53/src/main.ts#L267
@@ -186,6 +190,31 @@ export default class ExcalidrawPlugin extends Plugin {
});
}
public initializeFourthFont() {
this.app.workspace.onLayoutReady(async() => {
const font = (await getFontDataURL(this.app,this.settings.experimantalFourthFont,"","LocalFont"));
const fourthFontDataURL = font.dataURL === "" ? VIRGIL_DATAURL : font.dataURL;
this.fourthFontDef = font.fontDef
const newStylesheet = document.createElement("style");
newStylesheet.id = "local-font-stylesheet";
newStylesheet.textContent = `
@font-face {
font-family: 'LocalFont';
src: url("${fourthFontDataURL}");
font-display: swap;
}
`;
// replace the old local font <style> element with the one we just created
const oldStylesheet = document.getElementById(newStylesheet.id);
document.head.appendChild(newStylesheet);
if (oldStylesheet) {
document.head.removeChild(oldStylesheet);
}
await (document as any).fonts.load(`20px LocalFont`);
});
}
private loadMathJax() {
//loading Obsidian MathJax as fallback
this.app.workspace.onLayoutReady(() => {
@@ -1097,10 +1126,32 @@ export default class ExcalidrawPlugin extends Plugin {
);
}
public ctrlKeyDown:boolean;
public shiftKeyDown:boolean;
public altKeyDown:boolean;
public onKeyUp:any;
public onKeyDown:any;
private popScope: Function = null;
private registerEventListeners() {
const self = this;
this.app.workspace.onLayoutReady(async () => {
self.onKeyUp = (e:KeyboardEvent) => {
self.ctrlKeyDown = e[CTRL_OR_CMD];
self.shiftKeyDown = e.shiftKey;
self.altKeyDown = e.altKey;
}
self.onKeyDown = (e:KeyboardEvent) => {
this.ctrlKeyDown = e[CTRL_OR_CMD];
this.shiftKeyDown = e.shiftKey;
this.altKeyDown = e.altKey;
}
window.addEventListener("keydown",self.onKeyDown,false);
window.addEventListener("keyup",self.onKeyUp,false);
//watch filename change to rename .svg, .png; to sync to .md; to update links
const renameEventHandler = async (
file: TAbstractFile,
@@ -1273,6 +1324,9 @@ export default class ExcalidrawPlugin extends Plugin {
}
onunload() {
window.removeEventListener("keydown",this.onKeyDown,false);
window.removeEventListener("keyup",this.onKeyUp,false);
destroyExcalidrawAutomate();
if (this.popScope) {
this.popScope();

View File

@@ -4,6 +4,7 @@ import {
normalizePath,
PluginSettingTab,
Setting,
TFile,
} from "obsidian";
import { VIEW_TYPE_EXCALIDRAW } from "./constants";
import ExcalidrawView from "./ExcalidrawView";
@@ -46,6 +47,8 @@ export interface ExcalidrawSettings {
experimentalFileType: boolean;
experimentalFileTag: string;
experimentalLivePreview: boolean;
experimentalEnableFourthFont: boolean;
experimantalFourthFont: string;
loadCount: number; //version 1.2 migration counter
drawingOpenCount: number;
library: string;
@@ -97,6 +100,8 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
experimentalFileType: false,
experimentalFileTag: "✏️",
experimentalLivePreview: true,
experimentalEnableFourthFont: false,
experimantalFourthFont: "Virgil",
compatibilityMode: false,
loadCount: 0,
drawingOpenCount: 0,
@@ -131,11 +136,6 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
}
applySettingsUpdate(requestReloadDrawings: boolean = false) {
/*clearTimeout(this.applyDebounceTimer);
const plugin = this.plugin;
this.applyDebounceTimer = window.setTimeout(() => {
plugin.saveSettings();
}, 500);*/
if (requestReloadDrawings) {
this.requestReloadDrawings = true;
}
@@ -542,18 +542,24 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
);
new Setting(containerEl)
.setName(t("MD_DEFAULT_FONT_NAME"))
.setDesc(t("MD_DEFAULT_FONT_DESC"))
.addText((text) =>
text
.setPlaceholder("Virgil|Cascadia|Filename")
.setValue(this.plugin.settings.mdFont)
.setName(t("MD_DEFAULT_FONT_NAME"))
.setDesc(t("MD_DEFAULT_FONT_DESC"))
.addDropdown(async (d: DropdownComponent) => {
d.addOption("Virgil", "Virgil");
d.addOption("Cascadia", "Cascadia");
this.app.vault.getFiles()
.filter((f)=>["ttf", "woff", "woff2"].contains(f.extension))
.forEach((f:TFile)=>{
d.addOption(f.path,f.name)
})
d.setValue(this.plugin.settings.mdFont)
.onChange((value) => {
this.requestReloadDrawings = true;
this.plugin.settings.mdFont = value;
this.applySettingsUpdate(true);
}),
);
});
});
new Setting(containerEl)
.setName(t("MD_DEFAULT_COLOR_NAME"))
@@ -844,5 +850,37 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
}),
);
new Setting(containerEl)
.setName(t("ENABLE_FOURTH_FONT_NAME"))
.setDesc(t("ENABLE_FOURTH_FONT_DESC"))
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.experimentalEnableFourthFont)
.onChange(async (value) => {
this.requestReloadDrawings = true;
this.plugin.settings.experimentalEnableFourthFont = value;
this.applySettingsUpdate();
}),
);
new Setting(containerEl)
.setName(t("FOURTH_FONT_NAME"))
.setDesc(t("FOURTH_FONT_DESC"))
.addDropdown(async (d: DropdownComponent) => {
d.addOption("Virgil", "Virgil");
this.app.vault.getFiles()
.filter((f)=>["ttf", "woff", "woff2"].contains(f.extension))
.forEach((f:TFile)=>{
d.addOption(f.path,f.name)
})
d.setValue(this.plugin.settings.experimantalFourthFont)
.onChange((value) => {
this.requestReloadDrawings = true;
this.plugin.settings.experimantalFourthFont = value;
this.applySettingsUpdate(true);
this.plugin.initializeFourthFont();
});
});
}
}

View File

@@ -1,4 +1,4 @@
{
"1.5.16": "0.12.16",
"1.5.19": "0.12.16",
"1.4.2": "0.11.13"
}

View File

@@ -1232,10 +1232,10 @@
"@typescript-eslint/types" "5.6.0"
"eslint-visitor-keys" "^3.0.0"
"@zsviczian/excalidraw@0.10.0-obsidian-33":
"integrity" "sha512-ych61N48QASpcU3YJGX5nCWmnsdku5vsm6RLp7eiE8HzAdGGDFTlbwYg6p+uBw7MeJIu9gQx2hET9Gnx79LFRg=="
"resolved" "https://registry.npmjs.org/@zsviczian/excalidraw/-/excalidraw-0.10.0-obsidian-33.tgz"
"version" "0.10.0-obsidian-33"
"@zsviczian/excalidraw@0.10.0-obsidian-35":
"integrity" "sha512-ENNMBqXb1keqZzOlyaMswmpOBh+Drr7EeuZ9sp4psdtFbjHyS3ZmPpQ9EIZEcFd75sbciK2Klu439/ioogC+Yg=="
"resolved" "https://registry.npmjs.org/@zsviczian/excalidraw/-/excalidraw-0.10.0-obsidian-35.tgz"
"version" "0.10.0-obsidian-35"
dependencies:
"dotenv" "10.0.0"