Compare commits
196 Commits
1.2.27
...
1.8.3-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9755be0e9 | ||
|
|
9526fb5726 | ||
|
|
c04587ab5c | ||
|
|
ab94fe304b | ||
|
|
b080fec85e | ||
|
|
c9972116b3 | ||
|
|
c254c8cc5d | ||
|
|
14c2ce3766 | ||
|
|
437a01c194 | ||
|
|
da98aca107 | ||
|
|
e81f4d3688 | ||
|
|
f280704744 | ||
|
|
9547ced85c | ||
|
|
356a0b7a63 | ||
|
|
171e37b4e5 | ||
|
|
cfb070cfe5 | ||
|
|
76e2a32998 | ||
|
|
23a4f42c27 | ||
|
|
8202cf0dde | ||
|
|
40f88bb900 | ||
|
|
e6f5f9469a | ||
|
|
0502ac3bb0 | ||
|
|
36125c9b83 | ||
|
|
cced2ca2e4 | ||
|
|
0de2c78cac | ||
|
|
7848c8f705 | ||
|
|
f6c135227b | ||
|
|
95ca41fcaa | ||
|
|
d7648d702a | ||
|
|
5033a7cccf | ||
|
|
1a83abb256 | ||
|
|
08f616b5d9 | ||
|
|
ca44699e8d | ||
|
|
e0111e264c | ||
|
|
c6196a86a9 | ||
|
|
3926e5c30b | ||
|
|
a1256422fa | ||
|
|
eeb47d4912 | ||
|
|
8ceac4ab31 | ||
|
|
225c6305d1 | ||
|
|
ba9ab61cc9 | ||
|
|
0940a8628a | ||
|
|
46ee9e9524 | ||
|
|
c044278a4a | ||
|
|
aa9118cdae | ||
|
|
d19b32d0c4 | ||
|
|
dd7f0750fd | ||
|
|
e1330cd8bb | ||
|
|
04367bd3cd | ||
|
|
7d139462bf | ||
|
|
d8e429d815 | ||
|
|
4685a6f014 | ||
|
|
03b389a2b5 | ||
|
|
024f7979a7 | ||
|
|
f9e9ac0728 | ||
|
|
c6eb5859b5 | ||
|
|
377268f30c | ||
|
|
b23afc9621 | ||
|
|
d92c95c3fd | ||
|
|
98b39ab2b0 | ||
|
|
431d5e1104 | ||
|
|
adaf6ee0ae | ||
|
|
3d7d6df2ec | ||
|
|
71d00e0c8d | ||
|
|
ed316fc2c4 | ||
|
|
83f12a8fc5 | ||
|
|
2b7253168e | ||
|
|
70a869fa05 | ||
|
|
e66c31618b | ||
|
|
91298190dc | ||
|
|
11b4091d34 | ||
|
|
78287ab5f3 | ||
|
|
f632c709a5 | ||
|
|
2499629f17 | ||
|
|
16f2240c5b | ||
|
|
f670e3db9d | ||
|
|
b5710033bc | ||
|
|
2117844fc2 | ||
|
|
650956054f | ||
|
|
5d24e4f063 | ||
|
|
994ed375b2 | ||
|
|
3acbe2c1bd | ||
|
|
8594fbc490 | ||
|
|
8b9aa8ccc4 | ||
|
|
b0bb5a00fb | ||
|
|
9bf3e899c2 | ||
|
|
db1f989f49 | ||
|
|
4c45a54ddd | ||
|
|
64d48ed867 | ||
|
|
e2d70687c1 | ||
|
|
1aac4ffdf3 | ||
|
|
b9e154330b | ||
|
|
56ae6baf2b | ||
|
|
64fd43abb8 | ||
|
|
31ae51a421 | ||
|
|
0d879b7a7e | ||
|
|
d8166bbf8c | ||
|
|
82bde38a4b | ||
|
|
36b679434f | ||
|
|
6fa90662b3 | ||
|
|
7f45dad610 | ||
|
|
0e1ee0dde2 | ||
|
|
6c7b63cbdf | ||
|
|
bca7010394 | ||
|
|
3565a5bf94 | ||
|
|
f089911e02 | ||
|
|
992af2b5ca | ||
|
|
f85fc124d9 | ||
|
|
961e75a12d | ||
|
|
3be592eeb8 | ||
|
|
5f094f3d95 | ||
|
|
a16fd53958 | ||
|
|
72d425715f | ||
|
|
4a6aed5dd0 | ||
|
|
f76964a7b7 | ||
|
|
161f7041ec | ||
|
|
334e8130eb | ||
|
|
fdb7e97b11 | ||
|
|
22b3769c20 | ||
|
|
cd96870f07 | ||
|
|
a76854d152 | ||
|
|
32319b2f6c | ||
|
|
38add10053 | ||
|
|
21dc29d1d1 | ||
|
|
e7444f5d8a | ||
|
|
cc9d7828c7 | ||
|
|
b67d70c519 | ||
|
|
5c861acea6 | ||
|
|
582c3dbf25 | ||
|
|
e38e21f3ee | ||
|
|
d946b6fbfa | ||
|
|
e6fd56d9ee | ||
|
|
de44b01e0c | ||
|
|
562f3d3f5b | ||
|
|
c0c2b0a014 | ||
|
|
16ff10b894 | ||
|
|
b4ddb7a8c9 | ||
|
|
96dcaf38c1 | ||
|
|
43176e59c3 | ||
|
|
9db43f6d4a | ||
|
|
c18262180f | ||
|
|
509b60cb69 | ||
|
|
6217a0601c | ||
|
|
be5d35e811 | ||
|
|
e759010ae0 | ||
|
|
8ff0d187df | ||
|
|
358ab82b85 | ||
|
|
92cda3b4f9 | ||
|
|
9fafbd82c2 | ||
|
|
37dadda342 | ||
|
|
b041088b59 | ||
|
|
1a04cd88bd | ||
|
|
d0e504c369 | ||
|
|
83005da1bb | ||
|
|
f574721574 | ||
|
|
a7af6b2421 | ||
|
|
e708be8eda | ||
|
|
ea39b8c6a1 | ||
|
|
e5fb705f0b | ||
|
|
8046b5dc1f | ||
|
|
08e4e1f131 | ||
|
|
108293ae5c | ||
|
|
73528596d2 | ||
|
|
d2284b8d14 | ||
|
|
7cd3ec40c6 | ||
|
|
80cbb41913 | ||
|
|
257f3d17ac | ||
|
|
2e6b76b0f3 | ||
|
|
9030a77914 | ||
|
|
461b472f20 | ||
|
|
6bacae16b2 | ||
|
|
fa0f388e4a | ||
|
|
afc4f614b7 | ||
|
|
9e05493a9d | ||
|
|
a20900749d | ||
|
|
461eeafd80 | ||
|
|
5ff8caa04f | ||
|
|
9051fe2c01 | ||
|
|
018e42b34b | ||
|
|
b29e79f2b4 | ||
|
|
1ce0051d4e | ||
|
|
c44a4a91b3 | ||
|
|
2c5a4c01d2 | ||
|
|
668c4d62e9 | ||
|
|
0ce4f5f16b | ||
|
|
56d0966d4e | ||
|
|
e000c6bf39 | ||
|
|
feb5b576cb | ||
|
|
2bd1f68276 | ||
|
|
22d1a9b90a | ||
|
|
00a6a3dcaf | ||
|
|
82061cd126 | ||
|
|
4bdd095ff0 | ||
|
|
f40ad62291 | ||
|
|
de4fc602ca | ||
|
|
f5faec8ac9 |
62
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,32 +1,30 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Environment (please complete the following information):**
|
||||
- OS including version: [e.g. iOS 15.1, Android 9, Windows 11, etc]
|
||||
- Plugin version:
|
||||
- Obsidian version:
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help me improve Excalidraw
|
||||
title: 'BUG: '
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Your environment**
|
||||
Please run `Command Palette/Show Debug info` in Obsidian and paste the result here.
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
|
||||
40
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,20 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: 'FR: '
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
||||
3
.gitignore
vendored
@@ -15,4 +15,5 @@ data.json
|
||||
lib
|
||||
|
||||
#VSCode
|
||||
.vscode
|
||||
.vscode
|
||||
yarn.lock
|
||||
|
||||
@@ -6,7 +6,7 @@ With a little work, using Excalidraw Automate you can generate simple mindmaps,
|
||||
|
||||
You can access Excalidraw Automate via the ExcalidrawAutomate object. I recommend starting your Automate scripts with the following code.
|
||||
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
@@ -27,7 +27,7 @@ You can change styling between adding different elements. My logic for separatin
|
||||
#### Create a new drawing with custom name, in a custom folder, using a template
|
||||
This simple script gives you significant additional flexibility over Excalidraw Plugin settings to name your drawings, place them into folders, and to apply templates.
|
||||
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
@@ -42,7 +42,7 @@ This simple script gives you significant additional flexibility over Excalidraw
|
||||
```
|
||||
|
||||
#### Create a simple drawing
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
@@ -63,7 +63,7 @@ The script will generate the following drawing:
|
||||
|
||||
## Attributes and functions at a glance
|
||||
Here's the interface implemented by ExcalidrawAutomate:
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
ExcalidrawAutomate: {
|
||||
style: {
|
||||
@@ -324,7 +324,7 @@ Returns a blob containing a PNG image of the generated drawing.
|
||||
### Insert new drawing into currently edited document
|
||||
This template will prompt you for the title of the drawing. It will create a new drawing with the provided title, and in the folder of the document you were editing. It will then transclude the new drawing at the cursor location and open the new drawing in a new workspace leaf by splitting the current leaf.
|
||||
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
<%*
|
||||
const defaultTitle = tp.date.now("HHmm")+' '+tp.file.title;
|
||||
@@ -345,7 +345,7 @@ This template will prompt you for the title of the drawing. It will create a new
|
||||
```
|
||||
|
||||
### Connect objects
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
@@ -362,7 +362,7 @@ This template will prompt you for the title of the drawing. It will create a new
|
||||
### Using a template
|
||||
This example is similar to the first one, but rotated 90°, and using a template, plus specifying a filename and folder to save the drawing, and opening the new drawing in a new pane.
|
||||
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
@@ -402,7 +402,7 @@ Example input:
|
||||
|
||||
The script:
|
||||
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
<%*
|
||||
const IDX = Object.freeze({"depth":0, "text":1, "parent":2, "size":3, "children": 4, "objectId":5});
|
||||
|
||||
337
README.md
@@ -1,110 +1,275 @@
|
||||
# Excalidraw
|
||||
|
||||
The Obsidian-Excalidraw plugin integrates [Excalidraw](https://excalidraw.com/), a feature rich sketching tool, into Obsidian. You can store and edit Excalidraw files in your vault, you can embed drawings into your documents, and you can link to documents and other drawings to/and from Excalidraw. For a showcase of Excalidraw features, please read my blog post [here](https://www.zsolt.blog/2021/03/showcasing-excalidraw.html) and/or watch the videos below.
|
||||
|
||||
Please upgrade to Obsidian v0.12.19 or higher to get the latest release.
|
||||
## 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>
|
||||
|
||||
# Video walkthrough
|
||||
| | | |
|
||||
|----|----|----|
|
||||
|[](https://youtu.be/o0exK-xFP3k)| | |
|
||||
|[](https://youtu.be/UxJLLYtgDKE)|[](https://youtu.be/sY4FoflGaiM)|[](https://youtu.be/Iy_oVTq12Gw)|
|
||||
|[](https://youtu.be/QOL1KF7-kdc)|[](https://youtu.be/aSgcbfspvfo)|[](https://youtu.be/MaJ5jJwBRWs)|
|
||||
|[](https://youtu.be/MXzeCOEExNo)|[](https://youtu.be/R0IAg0s-wQE)|[](https://youtu.be/ibdS7ykwpW4)|
|
||||
|[](https://youtu.be/VRZVujfVab0)|[](https://youtu.be/D1iBYo1_jjc)|[](https://www.youtube.com/watch?v=_c_0zpBJ4Xc&)|
|
||||
|[](https://youtu.be/r08wk-58DPk)|[](https://youtu.be/tsecSfnTMow)|[](https://youtu.be/K6qZkTz8GHs)|
|
||||
|[](https://youtu.be/hePJcObHIso)|[](https://youtu.be/NOuddK6xrr8)|[](https://youtu.be/lzYdOQ6z8F0)|
|
||||
|[](https://youtu.be/eKFmrSQhFA4)|[](https://youtu.be/qbPIAZguJeo)|[](https://youtu.be/2Y8OhkGiTHg)|
|
||||
|[](https://youtu.be/2v9TZmQNO8c)|[](https://youtu.be/xHPGWR3m0c8)|[](https://youtu.be/gMIKXyhS-dM)|
|
||||
|[](https://youtu.be/Etskjw7a5zo)|[](https://youtu.be/4N6efq1DtH0)|[](https://youtu.be/U2LkBRBk4LY)|
|
||||
<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;"/> 1 Getting Started</a><br>
|
||||
<a href="https://youtu.be/Iy_oVTq12Gw" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/125160312-8a743d00-e17c-11eb-9fa2-490ef4cbd59e.jpg" width="100" style="vertical-align: middle;"/> 2 Basic shapes and features</a><br>
|
||||
<a href="https://youtu.be/QOL1KF7-kdc" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/125160323-96f89580-e17c-11eb-9bce-8eb1067a51bb.jpg" width="100" style="vertical-align: middle;"/> 3 Grouping elements</a><br>
|
||||
<a href="https://youtu.be/aSgcbfspvfo" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/125160332-9f50d080-e17c-11eb-98e9-fec60fe147d9.jpg" width="100" style="vertical-align: middle;"/> 4 The stencil-library</a><br>
|
||||
<a href="https://youtu.be/MaJ5jJwBRWs" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/125160341-a546b180-e17c-11eb-9de8-d87fdc844c9c.jpg" width="100" style="vertical-align: middle;"/> 5 Embedding</a><br>
|
||||
<a href="https://youtu.be/MXzeCOEExNo" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/125160346-aa0b6580-e17c-11eb-930b-4024807040d1.jpg" width="100" style="vertical-align: middle;"/> 6 Links</a><br>
|
||||
<a href="https://youtu.be/R0IAg0s-wQE" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/125160354-b2fc3700-e17c-11eb-81af-9e71e461f6dd.jpg" width="100" style="vertical-align: middle;"/> 7 Markdown</a><br>
|
||||
<a href="https://youtu.be/ibdS7ykwpW4" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/125160360-b8f21800-e17c-11eb-8bd8-79d4e3f6e92d.jpg" width="100" style="vertical-align: middle;"/> 8 Templates</a><br>
|
||||
<a href="https://youtu.be/VRZVujfVab0" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/125160367-bdb6cc00-e17c-11eb-92f1-6f59faea85fd.jpg" width="100" style="vertical-align: middle;"/> 9 Excalidraw Automate</a><br>
|
||||
<a href="https://youtu.be/D1iBYo1_jjc" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/125160374-c3141680-e17c-11eb-8cc2-dfaffd903d15.jpg" width="100" style="vertical-align: middle;"/> 10 Miscellaneous</a><br>
|
||||
</details>
|
||||
<details><summary>Embedding stuff into Excalidraw</summary>
|
||||
<a href="https://www.youtube.com/watch?v=_c_0zpBJ4Xc&" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/138607067-ccb62f92-48a4-4880-ac6e-68c1bf86ac2c.png" width="100" style="vertical-align: middle;"/> Image Elements</a><br>
|
||||
<a href="https://youtu.be/r08wk-58DPk" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/143732412-1c65227e-4381-406d-847a-b001ab3506ca.jpg" width="100" style="vertical-align: middle;"/> LaTex Demo</a><br>
|
||||
<a href="https://youtu.be/tsecSfnTMow" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/143732440-90bfa029-8615-462e-ada3-c903d71a82c9.jpg" width="100" style="vertical-align: middle;"/> Markdown embeds</a><br>
|
||||
<a href="https://youtu.be/K6qZkTz8GHs" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/143783906-15cee494-c6d5-4495-a2ca-74634e4e7355.jpg" width="100" style="vertical-align: middle;"/> Markdown embeds advanced features</a><br>
|
||||
<a href="https://youtu.be/Etskjw7a5zo" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/156931461-0979b821-315a-41dd-86f1-31d169b7c127.jpg" width="100" style="vertical-align: middle;"/> Link to Elements, Vertical text alignment, Markdown Styling</a><br>
|
||||
</details>
|
||||
<details><summary>The Script Engine Store - Excalidraw Automation</summary>
|
||||
<a href="https://youtu.be/hePJcObHIso" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/145684531-8d9c2992-59ac-4ebc-804a-4cce1777ded2.jpg" width="100" style="vertical-align: middle;"/> Introducing the Script Engine</a><br>
|
||||
<a href="https://youtu.be/lzYdOQ6z8F0" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/147889174-6c306d0d-2d29-46cc-a53f-3f0013cf14de.jpg" width="100" style="vertical-align: middle;"/> Script Enginge Store</a><br>
|
||||
</details>
|
||||
<details><summary>Working with colors</summary>
|
||||
<a href="https://youtu.be/6PLGHBH9VZ4" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/194773147-5418a0ab-6be5-4eb0-a8e4-d6af21b1b483.png" width="100" style="vertical-align: middle;"/> Colors - Excalidraw Basics (Custom)</a><br>
|
||||
<a href="https://youtu.be/epYNx2FSf2w" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/194773211-9e871be7-0795-4dc7-947e-c6c275e690d0.png" width="100" style="vertical-align: middle;"/> Excalidraw color palettes (Custom)</a><br>
|
||||
<a href="https://youtu.be/Amhlv6r9WvM" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/194773268-400cfb1b-6bde-45e0-9e4b-91bbaa461cf0.png" width="100" style="vertical-align: middle;"/> "Artistic" Color Gradients</a><br>
|
||||
<a href="https://youtu.be/r9oB1SlK1GU" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/194773527-ef35c8b9-1a6d-4415-9c7e-b667fb17535d.png" width="100" style="vertical-align: middle;"/> Simple rules for beautiful sketches</a><br>
|
||||
<a href="https://youtu.be/7gJDwNgQ6NU" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/195988535-a133a9b9-d094-45ba-ba64-c994b9a1e0ef.png" width="100" style="vertical-align: middle;"/> ColorMaster Scripting</a><br>
|
||||
</details>
|
||||
<details><summary>Links and block references</summary>
|
||||
<a href="https://youtu.be/qiKuqMcNWgU" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/171635214-30533c45-94fa-436e-83a9-b2ec99f190e2.jpg" width="100" style="vertical-align: middle;"/> 6 strategies for linking your visual thoughts v4</a><br>
|
||||
<a href="https://youtu.be/yZQoJg2RCKI" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/185791706-3d9983ab-7cb1-4b27-a016-30c039d84e34.jpg" width="100" style="vertical-align: middle;"/> Block reference parts of images</a><br>
|
||||
<a href="https://youtu.be/Etskjw7a5zo" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/156931461-0979b821-315a-41dd-86f1-31d169b7c127.jpg" width="100" style="vertical-align: middle;"/> Link to Elements, Vertical text alignment, Markdown Styling</a><br>
|
||||
<a href="https://youtu.be/2Y8OhkGiTHg" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/152585752-7eb0371f-0bab-40f6-a194-3b48e5811735.jpg" width="100" style="vertical-align: middle;"/> How to guide for the Excalidraw-native hyperlinks</a><br>
|
||||
</details>
|
||||
<details><summary>Powertools</summary>
|
||||
<a href="https://youtu.be/NOuddK6xrr8" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/147283367-e5689385-ea51-4983-81a3-04d810d39f62.jpg" width="100" style="vertical-align: middle;"/> Sticky Notes (word wrapping)</a><br>
|
||||
<a href="https://youtu.be/eKFmrSQhFA4" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/149659524-2a4e0a24-40c9-4e66-a6b1-c92f3b88ecd5.jpg" width="100" style="vertical-align: middle;"/> Fourt Font</a><br>
|
||||
<a href="https://youtu.be/vlC1-iBvIfo" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/199207784-8bbe14e0-7d10-47d7-971d-20dce8dbd659.png" width="100" style="vertical-align: middle;"/> SVG import</a><br>
|
||||
<a href="https://youtu.be/7gu4ETx7zro" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/202916770-28f2fa64-1ba2-4b40-a7fe-d721b42634f7.png" width="100" style="vertical-align: middle;"/> OCR</a><br>
|
||||
<a href="https://youtu.be/U2LkBRBk4LY" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/159369910-6371f08d-b5fa-454d-9c6c-948f7e7a7d26.jpg" width="100" style="vertical-align: middle;"/> Bind/unbind text from container, Frontmatter tags to customize export</a><br>
|
||||
</details>
|
||||
<details><summary>Quality of life improvements</summary>
|
||||
<a href="https://youtu.be/qbPIAZguJeo" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/151705333-54e9ffd2-0bd7-4d02-b99e-0bd4e4708d4d.jpg" width="100" style="vertical-align: middle;"/> Mobile Support</a><br>
|
||||
<a href="https://youtu.be/2v9TZmQNO8c" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/153676009-6f86b2d7-c248-49a2-b802-be21c6999e4f.jpg" width="100" style="vertical-align: middle;"/> Tray-mode and Customizable Color Palette</a><br>
|
||||
<a href="https://youtu.be/xHPGWR3m0c8" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/154821232-a404b6cf-72fb-4ce4-9d53-619132dce491.jpg" width="100" style="vertical-align: middle;"/> Compressed JSON and improved save/sync support</a><br>
|
||||
<a href="https://youtu.be/gMIKXyhS-dM" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/156931428-b2269fd9-87bd-43ab-8558-5572f40dff93.jpg" width="100" style="vertical-align: middle;"/> The Obsidian Tools Panel</a><br>
|
||||
<a href="https://youtu.be/4N6efq1DtH0" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/158008902-12c6a851-237e-4edd-a631-d48e81c904b2.jpg" width="100" style="vertical-align: middle;"/> Eraser, left-handed mode, improved filename configuration</a><br>
|
||||
</details>
|
||||
|
||||
# Key features
|
||||
- The plugin aims to integrate Excalidraw seamlessly into Obsidian including Command Palette actions, File Explorer features, Option Menu commands, and the Ribbon Button.
|
||||
- CTRL/CMD+Click on the ribbon button, or in the file explorer to create / open drawings in a new pane.
|
||||
- Settings will allow you to customize Excalidraw to your needs:
|
||||
- Default folder for new drawings and define custom filename pattern for new drawings.
|
||||
- Template for new drawings. The template will restore stroke properties. This means you can set up defaults in your template for stroke color, stroke width, opacity, font family, font size, fill style, stroke style, etc. This also applies to ExcalidrawAutomate.
|
||||
- If portability is important to you: Auto-export SVG and/or PNG files including keep-in-sync feature so you can embed SVG/PNG into your documents instead of embedding excalidraw files.
|
||||
- Specify the default width of embedded drawings.
|
||||
- Compatibility features to auto-export and keep in sync markdown excalidraw files and legacy .excalidraw files.
|
||||
- Experimental feature to add custom TAG to file explorer to mark drawing files.
|
||||
- Enable / disable autosave.
|
||||
- You can customize the size and position of the embedded images using the `![[image.excalidraw|100]]`, `![[image.excalidraw|100x100]]`, `![[image.excalidraw|100|left]]`, `![[image.excalidraw|right-wrap]]`, formatting options. `![[<filename.excalidraw>|<width>x<height>|<alignment>]]`. You can add your custom alignment via CSS. Any text that appears in `<alignment>` will be added to the rendered SVG element style and to the wrapper DIV element. See [styles.css](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/styles.css) for more insight.
|
||||
- Supports hyperlinks e.g. `https://zsolt.blog`, `[Obsidian](https://obsidian.md)`, and internal links e.g. `[[My file in vault|Alias]]` in drawing text.
|
||||
- Links will update when files are moved or renamed, if you have the Obsidian setting Files & Links/Automatically Update Internal Links enabled.
|
||||
- Links in drawings will show up in backlinks of documents
|
||||
- Transclusions are supported
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
- The plugin integrates Excalidraw seamlessly into Obsidian including Command Palette actions, File
|
||||
Explorer features, Option Menu commands, and the Ribbon Button.
|
||||
- <kbd>CTRL/CMD+Click</kbd> on the ribbon button, or in the file explorer to create / open drawings
|
||||
in a new pane.
|
||||
|
||||
### Settings
|
||||
|
||||
Settings will allow you to customize Excalidraw to your needs:
|
||||
|
||||
- Default folder for new drawings and define custom filename pattern for new drawings.
|
||||
|
||||
#### Templates
|
||||
|
||||
- Template for new drawings. The template will restore stroke properties.
|
||||
This means you can set up defaults in your template for stroke color, stroke width,
|
||||
opacity, font family, font size, fill style, stroke style, etc.
|
||||
This also applies to ExcalidrawAutomate.
|
||||
- Via the template you can customize the color palette used by Excalidraw.
|
||||
- Switch to Markdown view.
|
||||
- Scroll down to the bottom of the file and find `"AppState": {`.
|
||||
- Find `"customColorPalette": {` at the end of the AppState section.
|
||||
- You may specify the 3 palettes used in Excalidraw by adding any or all of the following 3 variables:
|
||||
- `"canvasBackground":[], "elementBackground":[], "elementStroke": []`.
|
||||
- Add a comma separated list of valid HTML colors (e.g. `#FF0000` for red)
|
||||
in the array for each of the variables.
|
||||
- See my videos above for further help.
|
||||
|
||||
#### Export
|
||||
|
||||
- If portability is important to you:
|
||||
- Auto-export SVG and/or PNG files including keep-in-sync feature so you can
|
||||
embed SVG/PNG into your documents instead of embedding excalidraw files.
|
||||
- You can override export settings for an individual file by adding the `excalidraw-autoexport`
|
||||
frontmatter key. Valid values for this key are `none`, `both`, `png` and `svg`.
|
||||
|
||||
- Specify the default width of embedded drawings.
|
||||
- Compatibility features to auto-export and keep in sync markdown excalidraw files and legacy `.excalidraw` files.
|
||||
- Experimental feature to add custom TAG to file explorer to mark drawing files.
|
||||
- Enable / disable autosave.
|
||||
|
||||
### Embedded images
|
||||
|
||||
- You can customize the size and position of the embedded images using the
|
||||
- `![[image.excalidraw|100]]`,
|
||||
- `![[image.excalidraw|100x100]]`,
|
||||
- `![[image.excalidraw|100|left]]`,
|
||||
- `![[image.excalidraw|right-wrap]]`, formatting options.
|
||||
- `![[<filename.excalidraw>|<width>x<height>|<alignment>]]`.
|
||||
- You can add your custom [alignment via CSS](https://www.scaler.com/topics/align-image-in-html/).
|
||||
- Any text that appears in `<alignment>` will be added to the rendered SVG element style and to the wrapper DIV element.
|
||||
- See [styles.css](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/styles.css) for more insight.
|
||||
|
||||
### Hyperlinks
|
||||
|
||||
- Supports hyperlinks e.g.
|
||||
- `https://zsolt.blog`,
|
||||
- `[Obsidian](https://obsidian.md)`, and
|
||||
- internal links e.g. `[[My file in vault|Alias]]` in drawing text.
|
||||
- Links will update when files are moved or renamed, if you have the Obsidian
|
||||
setting Files & Links/Automatically Update Internal Links enabled.
|
||||
- Links in drawings will show up in backlinks of documents
|
||||
- Transclusions are supported
|
||||
- `![[myfile#^blockref]]` will convert in the drawing into the transcluded text of the block
|
||||
- `![[myfile#section]]` also works, this will transclude the section
|
||||
- you can also specify word wrapping for transcluded text by adding the max character count in curly brackets right after the transclusion e.g. `![[myfile#^blockref]]{40}` will wrap text at 40 characters.
|
||||
- For convenience you can also use the command palette to insert links into drawings
|
||||
- CTRL/CMD + hover to bring up the Obsidian quick preview for the link. (On Mac it is CTRL+CMD+hover).
|
||||
- CTRL/CMD + CLICK a text element to open it as a link.
|
||||
- CTRL/CMD + ALT + CLICK to create the file (if it does not yet exist) and open it
|
||||
- CTRL/CMD + SHIFT + CLICK to open the file in a new pane
|
||||
- CTRL/CMD + ALT + SHIFT + CLICK to create the file (if it does not yet exist) and open it in a new pane
|
||||
- you can also specify word wrapping for transcluded text by adding the max character count
|
||||
in curly brackets right after the transclusion e.g. `![[myfile#^blockref]]{40}` will wrap text at 40 characters.
|
||||
- For convenience you can also use the command palette to insert links into drawings
|
||||
- <kbd>CTRL/CMD + hover</kbd> to bring up the Obsidian quick preview for the link. (On Mac it is <kbd>CTRL+CMD+hover</kbd>).
|
||||
- <kbd>CTRL/CMD + CLICK</kbd> a text element to open it as a link.
|
||||
- <kbd>CTRL/CMD + ALT + CLICK</kbd> to create the file (if it does not yet exist) and open it
|
||||
- <kbd>CTRL/CMD + SHIFT + CLICK</kbd> to open the file in a new pane
|
||||
- <kbd>CTRL/CMD + ALT + SHIFT + CLICK</kbd> to create the file (if it does not yet exist) and open it in a new pane
|
||||
- Using the block reference you can also reference & transclude text that appears on drawings, in other documents
|
||||
- Insert LaTeX formulas using the Command Palette action "Insert LaTeX formula". You can edit formulas either in Markdown view, or by CTRL/CMD + Click on the formula.
|
||||
- Drag & Drop support
|
||||
- You can drag files from the Obsidian file explorer and they will become links to those files in Excalidraw.
|
||||
- Dragging image files (PNG, SVG, JPG, Excalidraw) from obsidian files explorer while pressing the CTRL/CMD button will embed the image into your drawing.
|
||||
- You can drag and drop images from outside obsidian onto Excalidraw. These images will be embedded into your drawing and saved to Obsidian.
|
||||
- You can drag and drop text from Markdown views onto Excalidraw.
|
||||
- You can drag and drop web addresses from your browser and they will become links.
|
||||
- Image support
|
||||
- On iOS and Android you can add images from your camera by pressing the add image button in Excalidraw.
|
||||
- You can copy/paste images into your drawing. Images will be saved in your vault.
|
||||
- You can drag and drop images as explained above.
|
||||
|
||||
### LaTeX
|
||||
|
||||
Insert LaTeX formulas using the Command Palette action "Insert LaTeX formula".
|
||||
You can edit formulas either in Markdown view, or by <kbd>CTRL/CMD + Click</kbd> on the formula.
|
||||
|
||||
### Drag & Drop support
|
||||
|
||||
- You can drag files from the Obsidian file explorer and they will become links to those files in Excalidraw.
|
||||
- Dragging image files (PNG, SVG, JPG, ICO, GIF, WEBP, Excalidraw) from Obsidian's file explorer while pressing the
|
||||
<kbd>CTRL</kbd> (<kbd>SHIFT</kbd> on Mac) button will embed the image into your drawing.
|
||||
- If in addition to <kbd>CTRL</kbd> or <kbd>SHIFT</kbd> you also hold down <kbd>ALT</kbd>,
|
||||
the image will be inserted at 100% of its size.
|
||||
- Note: this is a very niche feature with a very particular behavior that I built primarily for myself
|
||||
- (even more so than other features in Excalidraw Obsidian - also built primarily for myself 😉).
|
||||
- This will reset your embedded image to 100% size every time you open the Excalidraw drawing,
|
||||
or in case you have embedded an Excalidraw drawing on your canvas inserted using this function,
|
||||
every time you update the embedded drawing, it will be scaled back to 100% size.
|
||||
- This means that even if you resize the image on the drawing, it will reset to 100% the next time you open
|
||||
the file or you modify the original embedded object. This feature is useful when you
|
||||
decompose a drawing into separate Excalidraw files, but when combined onto a single canvas
|
||||
you want the individual pieces to maintain their actual sizes. I use this feature to
|
||||
construct Book-on-a-Page summaries from atomic drawings.
|
||||
- You can drag and drop text from Markdown views onto Excalidraw.
|
||||
- You can drag and drop web addresses from your browser and they will become links.
|
||||
|
||||
### Image support
|
||||
|
||||
- On iOS and Android you can add images from your camera by pressing the add image button in Excalidraw.
|
||||
- You can copy/paste images into your drawing. Images will be saved in your vault.
|
||||
- You can drag and drop images as explained above.
|
||||
|
||||
### Block referencing parts of images
|
||||
|
||||
- When referencing an element on the canvas in a link pointing to an Excalidraw file using
|
||||
- the elementId or the section header (i.e. a Text Element containing the `# <Section title>`)
|
||||
- e.g. `[[file#^elementID]]`,
|
||||
- you can add the `group=` prefix,
|
||||
- e.g. `[[file#^group=elementID]]` or
|
||||
- the `area=` prefix,
|
||||
- e.g. `[[file#area=Section heading]]`.
|
||||
- If the `group=` prefix is found Excalidraw will select the group of elements in the
|
||||
same group as the element referenced by the elementID (block reference) or the section heading.
|
||||
- If the `area=` prefix is found Excalidraw will insert a cutout of the image around the referenced element.
|
||||
- Note that the `area=` selector is not supported when embedding Excalidraw as PNG into your markdown documents.
|
||||
- Referencing the elementID of a text element without the `group=` or `area=` prefix will
|
||||
transclude the element as plain text. Referencing a non-Text Element (e.g. rectangle,
|
||||
ellipse, etc.) without the `group=` or `area=` prefix will result in an Obsidian error
|
||||
since these elementIds are not present in the Excalidraw markdown file as block
|
||||
references.
|
||||
|
||||
### Markdown
|
||||
|
||||
- Since 1.2.0 Drawing files are stored in Markdown files
|
||||
- You can add tags to drawings
|
||||
- You can add metadata to the YAML front matter of drawings
|
||||
- Anything you add between the frontmatter and the `# Text Elements` heading will be ignored by Excalidraw, i.e. you can add whatever you like here, it will be preserved as part of the document.
|
||||
- Excalidraw documents now show in graph view.
|
||||
- The following front matter keys will customize how the drawing is displayed - overriding general settings:
|
||||
- `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.
|
||||
- Frontmatter tags to customize image export at a file level [519](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/519). If these keys are present they will override the default excalidraw embed and export settings.
|
||||
- `excalidraw-export-transparent: true`: true == Transparent / false == with background.
|
||||
- `excalidraw-export-dark`: true == Dark mode / false == light mode.
|
||||
- `excalidraw-export-svgpadding`: This only affects export to SVG. Specify the export padding for the image
|
||||
- `excalidraw-export-pngscale`: This only affects export to PNG. Specify the export scale for the image. The typical range is between 0.5 and 5, but you can experiment with other values as well.
|
||||
- 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`
|
||||
- Use custom woff, woff2 or TTF font to display the document, you can set the default font to use under Excalidraw Settings.
|
||||
- You can set a custom css for rendering the snapshot image of your markdown document. Only operating system standard fonts are supported as the font-family ([Win10](https://docs.microsoft.com/en-us/typography/fonts/windows_10_font_list), [Mac & iOS](https://developer.apple.com/fonts/system-fonts/)), plus you can set one additional custom font using the setting explained above. (for a demonstration watch this [video](https://youtu.be/K6qZkTz8GHs) and check out this [sample css](https://github.com/zsviczian/obsidian-excalidraw-plugin/discussions/281)).
|
||||
- To help with styling you can observe the SVG snapshot of the markdown document created by Excalidraw. Open Obsidian Developer Console (CTRL+Shift+i) and execute the following command: `ExcalidrawAutomate.mostRecentMarkdownSVG`
|
||||
- You can control appearance of the embedded markdown file on a file by file bases by adding the following front matter keys to your markdown document:
|
||||
- You can add tags to drawings
|
||||
- You can add metadata to the YAML front matter of drawings
|
||||
- Anything you add between the frontmatter and the `# Text Elements` heading will be ignored by Excalidraw, i.e. you can add whatever you like here, it will be preserved as part of the document.
|
||||
- Excalidraw documents now show in graph view.
|
||||
- The following front matter keys will customize how the drawing is displayed - overriding general settings:
|
||||
- `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.
|
||||
- Frontmatter tags to customize image export at a file level [519](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/519). If these keys are present they will override the default excalidraw embed and export settings.
|
||||
- `excalidraw-export-transparent: true`: true == Transparent / false == with background.
|
||||
- `excalidraw-export-dark`: true == Dark mode / false == light mode.
|
||||
- `excalidraw-export-padding`: Specify the export padding for the image
|
||||
- `excalidraw-export-pngscale`: This only affects export to PNG. Specify the export scale for the image. The typical range is between 0.5 and 5, but you can experiment with other values as well.
|
||||
|
||||
### Embed complete markdown files into your drawings
|
||||
|
||||
- Drag from the desired file from the Obsidian file explorer and hold down <kbd>CTRL/CMD</kbd> while dropping the file onto the canvas.
|
||||
- Use the command palette action: `Insert markdown file from vault`
|
||||
- Use custom woff, woff2 or TTF font to display the document, you can set the default font to use under Excalidraw Settings.
|
||||
- You can set a custom css for rendering the snapshot image of your markdown document.
|
||||
Only operating system standard fonts are supported as the font-family (
|
||||
[Win10](https://docs.microsoft.com/en-us/typography/fonts/windows_10_font_list),
|
||||
[Mac & iOS](https://developer.apple.com/fonts/system-fonts/)
|
||||
), plus you can set one additional custom font using the setting explained above.
|
||||
- (for a demonstration watch this [video](https://youtu.be/K6qZkTz8GHs) and check out this
|
||||
- [sample css](https://github.com/zsviczian/obsidian-excalidraw-plugin/discussions/281)).
|
||||
- To help with styling you can observe the SVG snapshot of the markdown document created by Excalidraw.
|
||||
- Open Obsidian Developer Console (<kbd>CTRL+Shift+i</kbd>) and
|
||||
- execute the following command: `ExcalidrawAutomate.mostRecentMarkdownSVG`
|
||||
- You can control appearance of the embedded markdown file on a file by file
|
||||
bases by adding the following front matter keys to your markdown document:
|
||||
- `excalidraw-font: Virgil|Cascadia|font_file_name.extension`
|
||||
- `excalidraw-font-color: css-color-name|#HEXcolor|any-other-html-standard-format`, you can find css color names [here](https://www.w3schools.com/colors/colors_names.asp).
|
||||
- `excalidraw-font-color: css-color-name|#HEXcolor|any-other-html-standard-format`,
|
||||
- you can find css color names [here](https://www.w3schools.com/colors/colors_names.asp).
|
||||
- `excalidraw-border-color: css-color-name|#HEXcolor|any-other-html-standard-format`
|
||||
- `excalidraw-css: "css-filename|css snippet"`
|
||||
- Switch to markdown view or use CTRL/CMD+ALT/OPT click on the image to edit properties of the embed: `[[filename#^blockref|WIDTHxMAXHEIGHT]]`
|
||||
- Includes full [QuickAdd](https://github.com/chhoumann/quickadd), [Templater](https://silentvoid13.github.io/Templater/) and [Dataview](https://blacksmithgu.github.io/obsidian-dataview/docs/api/intro/) support through ExcalidrawAutomate. Check out the [detailed help + examples](https://zsviczian.github.io/obsidian-excalidraw-plugin/). I also have a [YouTube ExcalidrawAutomate Playlist](https://www.youtube.com/playlist?list=PL6mqgtMZ4NP1IR4nXxSlMA4PA5E-qpyHZ) with lots of examples.
|
||||
- Since 1.5.0 you can easily execute ExcalidrawAutomate macros and assign command palette shortcuts to them, using the ScriptEngine. You will find an intro video and a growing library of ready to install scripts [here](https://github.com/zsviczian/obsidian-excalidraw-plugin/tree/master/ea-scripts).
|
||||
- Switch to markdown view or use <kbd>CTRL/CMD+ALT/OPT</kbd> click on the image to edit properties of the embed:
|
||||
- `[[filename#^blockref|WIDTHxMAXHEIGHT]]`
|
||||
|
||||
### Other
|
||||
|
||||
- Includes full
|
||||
- [QuickAdd](https://github.com/chhoumann/quickadd),
|
||||
- [Templater](https://silentvoid13.github.io/Templater/) and
|
||||
- [Dataview](https://blacksmithgu.github.io/obsidian-dataview/docs/api/intro/) support through ExcalidrawAutomate.
|
||||
- Check out the [detailed help + examples](https://zsviczian.github.io/obsidian-excalidraw-plugin/).
|
||||
- I also have a [YouTube ExcalidrawAutomate Playlist](https://www.youtube.com/playlist?list=PL6mqgtMZ4NP1IR4nXxSlMA4PA5E-qpyHZ) with lots of examples.
|
||||
- Since 1.5.0 you can easily execute ExcalidrawAutomate macros and assign command palette
|
||||
shortcuts to them, using the ScriptEngine. You will find an intro video and a growing library
|
||||
of ready to install scripts
|
||||
[here](https://github.com/zsviczian/obsidian-excalidraw-plugin/tree/master/ea-scripts).
|
||||
- REQUIRES AN OBSIDIAN SYNC SUBSCRIPTION: Full drawing file history and synchronization between devices
|
||||
- Multilanguage support: if you'd like to help out by translating the plugin, please get in contact with me.
|
||||
|
||||
# Known issues
|
||||
- Mobile support
|
||||
- Partially mitigated in 1.0.10 by the introduction of autosave: Your drawing will not be saved when you terminate the mobile app by closing the Obsidian task.
|
||||
- Text elements "jumps off screen" when editing, if drawing is zoomed in and text element does not fit the visible screen area. I am working on a resolution.
|
||||
---
|
||||
|
||||
# Tips and tricks
|
||||
- [Ozan's Image in Editor Plugin](https://github.com/ozntel/oz-image-in-editor-obsidian). In a nice collaboration with Ozan, his Image-in-Editor plugin now supports Excalidraw. I recommend installing his plugin to display drawings also in Edit mode.
|
||||
## Feedback, questions, ideas, problems
|
||||
|
||||
# Feedback, questions, ideas, problems
|
||||
Join the conversation about the Excalidraw plugin on [forum.obsidian.md](https://forum.obsidian.md/t/excalidraw-full-featured-sketching-plugin-in-obsidian)
|
||||
Join the conversation about the Excalidraw plugin on
|
||||
[forum.obsidian.md](https://forum.obsidian.md/t/excalidraw-full-featured-sketching-plugin-in-obsidian)
|
||||
|
||||
Please head over to [GitHub](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues) to report a bug or request an enhancement.
|
||||
Please head over to [GitHub](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues) to
|
||||
report a bug or request an enhancement.
|
||||
|
||||
# Say Thank You
|
||||
If you are enjoying Excalidraw then please support my work and enthusiasm by buying me a coffee on [https://ko-fi/zsolt](https://ko-fi.com/zsolt).
|
||||
---
|
||||
|
||||
Please also help spread the word by sharing about the Obsidian Excalidraw Plugin on Twitter, Reddit, or any other social media platform you regularly use.
|
||||
## Say Thank You
|
||||
|
||||
If you are enjoying Excalidraw then please support my work and enthusiasm by buying me a coffee on
|
||||
[https://ko-fi/zsolt](https://ko-fi.com/zsolt).
|
||||
|
||||
Please also help spread the word by sharing about the Obsidian Excalidraw Plugin on Twitter, Reddit,
|
||||
or any other social media platform you regularly use.
|
||||
|
||||
You can find me on Twitter [@zsviczian](https://twitter.com/zsviczian), and on my blog [zsolt.blog](https://zsolt.blog).
|
||||
|
||||
[<img style="float:left" src="https://user-images.githubusercontent.com/14358394/115450238-f39e8100-a21b-11eb-89d0-fa4b82cdbce8.png" width="200">](https://ko-fi.com/zsolt)
|
||||
|
||||
---
|
||||
|
||||
## Friends of Excalidraw
|
||||
If you enjoy Excalidraw, consider giving [ExcaliBrain](https://github.com/zsviczian/excalibrain) a try (also available via Obsidian Community Plugins).
|
||||
|
||||
<a href="https://youtu.be/gOkniMkDPyM" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/169708346-9e41289d-9536-43ec-8f70-2d2ad2d369d6.png" width="300"/></a>
|
||||
36
dev.postprocess.config.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import fs from'fs';
|
||||
import LZString from 'lz-string';
|
||||
|
||||
const excalidraw_pkg = isProd
|
||||
? fs.readFileSync("./node_modules/@zsviczian/excalidraw/dist/excalidraw.production.min.js", "utf8")
|
||||
: fs.readFileSync("./node_modules/@zsviczian/excalidraw/dist/excalidraw.development.js", "utf8");
|
||||
const react_pkg = isProd
|
||||
? fs.readFileSync("./node_modules/react/umd/react.production.min.js", "utf8")
|
||||
: fs.readFileSync("./node_modules/react/umd/react.development.js", "utf8");
|
||||
const reactdom_pkg = isProd
|
||||
? fs.readFileSync("./node_modules/react-dom/umd/react-dom.production.min.js", "utf8")
|
||||
: fs.readFileSync("./node_modules/react-dom/umd/react-dom.development.js", "utf8");
|
||||
const lzstring_pkg = fs.readFileSync("./node_modules/lz-string/libs/lz-string.min.js", "utf8")
|
||||
|
||||
const packageString = lzstring_pkg+'const EXCALIDRAW_PACKAGES = "' + LZString.compressToBase64(react_pkg + reactdom_pkg + excalidraw_pkg) +'";var ExcalidrawPackageLoader=(d=document)=>{const excalidraw_id = "excalidraw-script";if(!d.getElementById(excalidraw_id)){const script=d.createElement("script");script.type="text/javascript";script.id=excalidraw_id;script.text=LZString.decompressFromBase64(EXCALIDRAW_PACKAGES);d.body.appendChild(script);}};ExcalidrawPackageLoader();';
|
||||
|
||||
const mainjs = fs.readFileSync("main.js", "utf8")
|
||||
|
||||
|
||||
fs.writeFileSync(
|
||||
"main2.js",
|
||||
mainjs
|
||||
.replace('(require("react"));','')
|
||||
.replace('"use strict";','"use strict";' + packageString),
|
||||
{
|
||||
encoding: "utf8",
|
||||
flag: "w",
|
||||
mode: 0o666
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
let config = {
|
||||
};
|
||||
|
||||
export default config;
|
||||
@@ -3,10 +3,12 @@
|
||||
Here's the interface implemented by ExcalidrawAutomate:
|
||||
|
||||
```typescript
|
||||
export interface ExcalidrawAutomate {
|
||||
export declare class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
|
||||
plugin: ExcalidrawPlugin;
|
||||
elementsDict: {}; //contains the ExcalidrawElements currently edited in Automate indexed by el.id
|
||||
imagesDict: {}; //the images files including DataURL, indexed by fileId
|
||||
targetView: ExcalidrawView = null; //the view currently edited
|
||||
elementsDict: {[key:string]:any}; //contains the ExcalidrawElements currently edited in Automate indexed by el.id
|
||||
imagesDict: {[key: FileId]: any}; //the images files including DataURL, indexed by fileId
|
||||
mostRecentMarkdownSVG:SVGSVGElement = null; //Markdown renderer will drop a copy of the most recent SVG here for debugging purposes
|
||||
style: {
|
||||
strokeColor: string; //https://www.w3schools.com/colors/default.asp
|
||||
backgroundColor: string;
|
||||
@@ -29,178 +31,521 @@ export interface ExcalidrawAutomate {
|
||||
viewBackgroundColor: string;
|
||||
gridSize: number;
|
||||
};
|
||||
setFillStyle(val: number): void; //0:"hachure", 1:"cross-hatch" 2:"solid"
|
||||
setStrokeStyle(val: number): void; //0:"solid", 1:"dashed", 2:"dotted"
|
||||
setStrokeSharpness(val: number): void; //0:"round", 1:"sharp"
|
||||
setFontFamily(val: number): void; //1: Virgil, 2:Helvetica, 3:Cascadia
|
||||
setTheme(val: number): void; //0:"light", 1:"dark"
|
||||
addToGroup(objectIds: []): string;
|
||||
toClipboard(templatePath?: string): void;
|
||||
getElements(): ExcalidrawElement[]; //get all elements from ExcalidrawAutomate elementsDict
|
||||
getElement(id: string): ExcalidrawElement; //get single element from ExcalidrawAutomate elementsDict
|
||||
create(params?: {
|
||||
//create a drawing and save it to filename
|
||||
filename?: string; //if null: default filename as defined in Excalidraw settings
|
||||
foldername?: string; //if null: default folder as defined in Excalidraw settings
|
||||
templatePath?: string;
|
||||
onNewPane?: boolean;
|
||||
frontmatterKeys?: {
|
||||
"excalidraw-plugin"?: "raw" | "parsed";
|
||||
"excalidraw-link-prefix"?: string;
|
||||
"excalidraw-link-brackets"?: boolean;
|
||||
"excalidraw-url-prefix"?: string;
|
||||
constructor(plugin: ExcalidrawPlugin, view?: ExcalidrawView);
|
||||
/**
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
getAPI(view?: ExcalidrawView): ExcalidrawAutomate;
|
||||
/**
|
||||
* @param val //0:"hachure", 1:"cross-hatch" 2:"solid"
|
||||
* @returns
|
||||
*/
|
||||
setFillStyle(val: number): "hachure" | "cross-hatch" | "solid";
|
||||
/**
|
||||
* @param val //0:"solid", 1:"dashed", 2:"dotted"
|
||||
* @returns
|
||||
*/
|
||||
setStrokeStyle(val: number): "solid" | "dashed" | "dotted";
|
||||
/**
|
||||
* @param val //0:"round", 1:"sharp"
|
||||
* @returns
|
||||
*/
|
||||
setStrokeSharpness(val: number): "round" | "sharp";
|
||||
/**
|
||||
* @param val //1: Virgil, 2:Helvetica, 3:Cascadia
|
||||
* @returns
|
||||
*/
|
||||
setFontFamily(val: number): "Virgil, Segoe UI Emoji" | "Helvetica, Segoe UI Emoji" | "Cascadia, Segoe UI Emoji" | "LocalFont";
|
||||
/**
|
||||
* @param val //0:"light", 1:"dark"
|
||||
* @returns
|
||||
*/
|
||||
setTheme(val: number): "light" | "dark";
|
||||
/**
|
||||
* @param objectIds
|
||||
* @returns
|
||||
*/
|
||||
addToGroup(objectIds: string[]): string;
|
||||
/**
|
||||
* @param templatePath
|
||||
*/
|
||||
toClipboard(templatePath?: string): Promise<void>;
|
||||
/**
|
||||
* get all elements from ExcalidrawAutomate elementsDict
|
||||
* @returns elements from elemenetsDict
|
||||
*/
|
||||
getElements(): ExcalidrawElement[];
|
||||
/**
|
||||
* get single element from ExcalidrawAutomate elementsDict
|
||||
* @param id
|
||||
* @returns
|
||||
*/
|
||||
getElement(id: string): ExcalidrawElement;
|
||||
/**
|
||||
* create a drawing and save it to filename
|
||||
* @param params
|
||||
* filename: if null, default filename as defined in Excalidraw settings
|
||||
* foldername: if null, default folder as defined in Excalidraw settings
|
||||
* @returns
|
||||
*/
|
||||
create(params?: {
|
||||
filename?: string;
|
||||
foldername?: string;
|
||||
templatePath?: string;
|
||||
onNewPane?: boolean;
|
||||
frontmatterKeys?: {
|
||||
"excalidraw-plugin"?: "raw" | "parsed";
|
||||
"excalidraw-link-prefix"?: string;
|
||||
"excalidraw-link-brackets"?: boolean;
|
||||
"excalidraw-url-prefix"?: string;
|
||||
"excalidraw-export-transparent"?: boolean;
|
||||
"excalidraw-export-dark"?: boolean;
|
||||
"excalidraw-export-svgpadding"?: number;
|
||||
"excalidraw-export-pngscale"?: number;
|
||||
"excalidraw-default-mode"?: "view" | "zen";
|
||||
};
|
||||
}): Promise<string>;
|
||||
/**
|
||||
*
|
||||
* @param templatePath
|
||||
* @param embedFont
|
||||
* @param exportSettings use ExcalidrawAutomate.getExportSettings(boolean,boolean)
|
||||
* @param loader use ExcalidrawAutomate.getEmbeddedFilesLoader(boolean?)
|
||||
* @param theme
|
||||
* @returns
|
||||
*/
|
||||
createSVG(templatePath?: string, embedFont?: boolean, exportSettings?: ExportSettings, loader?: EmbeddedFilesLoader, theme?: string, padding?: number): Promise<SVGSVGElement>;
|
||||
/**
|
||||
*
|
||||
* @param templatePath
|
||||
* @param scale
|
||||
* @param exportSettings use ExcalidrawAutomate.getExportSettings(boolean,boolean)
|
||||
* @param loader use ExcalidrawAutomate.getEmbeddedFilesLoader(boolean?)
|
||||
* @param theme
|
||||
* @returns
|
||||
*/
|
||||
createPNG(templatePath?: string, scale?: number, exportSettings?: ExportSettings, loader?: EmbeddedFilesLoader, theme?: string, padding?: number): Promise<any>;
|
||||
/**
|
||||
*
|
||||
* @param text
|
||||
* @param lineLen
|
||||
* @returns
|
||||
*/
|
||||
wrapText(text: string, lineLen: number): string;
|
||||
private boxedElement;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param width
|
||||
* @param height
|
||||
* @returns
|
||||
*/
|
||||
addRect(topX: number, topY: number, width: number, height: number): string;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param width
|
||||
* @param height
|
||||
* @returns
|
||||
*/
|
||||
addDiamond(topX: number, topY: number, width: number, height: number): string;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param width
|
||||
* @param height
|
||||
* @returns
|
||||
*/
|
||||
addEllipse(topX: number, topY: number, width: number, height: number): string;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param width
|
||||
* @param height
|
||||
* @returns
|
||||
*/
|
||||
addBlob(topX: number, topY: number, width: number, height: number): string;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param text
|
||||
* @param formatting
|
||||
* box: if !null, text will be boxed
|
||||
* @param id
|
||||
* @returns
|
||||
*/
|
||||
addText(topX: number, topY: number, text: string, formatting?: {
|
||||
wrapAt?: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
textAlign?: string;
|
||||
box?: boolean | "box" | "blob" | "ellipse" | "diamond";
|
||||
boxPadding?: number;
|
||||
}, id?: string): string;
|
||||
/**
|
||||
*
|
||||
* @param points
|
||||
* @returns
|
||||
*/
|
||||
addLine(points: [[x: number, y: number]]): string;
|
||||
/**
|
||||
*
|
||||
* @param points
|
||||
* @param formatting
|
||||
* @returns
|
||||
*/
|
||||
addArrow(points: [x: number, y: number][], formatting?: {
|
||||
startArrowHead?: string;
|
||||
endArrowHead?: string;
|
||||
startObjectId?: string;
|
||||
endObjectId?: string;
|
||||
}): string;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param imageFile
|
||||
* @returns
|
||||
*/
|
||||
addImage(topX: number, topY: number, imageFile: TFile): Promise<string>;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param tex
|
||||
* @returns
|
||||
*/
|
||||
addLaTex(topX: number, topY: number, tex: string): Promise<string>;
|
||||
/**
|
||||
*
|
||||
* @param objectA
|
||||
* @param connectionA type ConnectionPoint = "top" | "bottom" | "left" | "right" | null
|
||||
* @param objectB
|
||||
* @param connectionB when passed null, Excalidraw will automatically decide
|
||||
* @param formatting
|
||||
* numberOfPoints: points on the line. Default is 0 ie. line will only have a start and end point
|
||||
* startArrowHead: "triangle"|"dot"|"arrow"|"bar"|null
|
||||
* endArrowHead: "triangle"|"dot"|"arrow"|"bar"|null
|
||||
* padding:
|
||||
* @returns
|
||||
*/
|
||||
connectObjects(objectA: string, connectionA: ConnectionPoint | null, objectB: string, connectionB: ConnectionPoint | null, formatting?: {
|
||||
numberOfPoints?: number;
|
||||
startArrowHead?: "triangle" | "dot" | "arrow" | "bar" | null;
|
||||
endArrowHead?: "triangle" | "dot" | "arrow" | "bar" | null;
|
||||
padding?: number;
|
||||
}): string;
|
||||
/**
|
||||
* Adds a text label to a line or arrow. Currently only works with a straight (2 point - start & end - line)
|
||||
* @param lineId id of the line or arrow object in elementsDict
|
||||
* @param label the label text
|
||||
* @returns undefined (if unsuccessful) or the id of the new text element
|
||||
*/
|
||||
addLabelToLine(lineId: string, label: string): string;
|
||||
/**
|
||||
* clear elementsDict and imagesDict only
|
||||
*/
|
||||
clear(): void;
|
||||
/**
|
||||
* clear() + reset all style values to default
|
||||
*/
|
||||
reset(): void;
|
||||
/**
|
||||
* returns true if MD file is an Excalidraw file
|
||||
* @param f
|
||||
* @returns
|
||||
*/
|
||||
isExcalidrawFile(f: TFile): boolean;
|
||||
/**
|
||||
*
|
||||
* @param view
|
||||
* @returns
|
||||
*/
|
||||
setView(view: ExcalidrawView | "first" | "active"): ExcalidrawView;
|
||||
/**
|
||||
*
|
||||
* @returns https://github.com/excalidraw/excalidraw/tree/master/src/packages/excalidraw#ref
|
||||
*/
|
||||
getExcalidrawAPI(): any;
|
||||
/**
|
||||
* get elements in View
|
||||
* @returns
|
||||
*/
|
||||
getViewElements(): ExcalidrawElement[];
|
||||
/**
|
||||
*
|
||||
* @param elToDelete
|
||||
* @returns
|
||||
*/
|
||||
deleteViewElements(elToDelete: ExcalidrawElement[]): boolean;
|
||||
/**
|
||||
* get the selected element in the view, if more are selected, get the first
|
||||
* @returns
|
||||
*/
|
||||
getViewSelectedElement(): any;
|
||||
/**
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
getViewSelectedElements(): any[];
|
||||
/**
|
||||
*
|
||||
* @param el
|
||||
* @returns TFile file handle for the image element
|
||||
*/
|
||||
getViewFileForImageElement(el: ExcalidrawElement): TFile | null;
|
||||
/**
|
||||
* copies elements from view to elementsDict for editing
|
||||
* @param elements
|
||||
*/
|
||||
copyViewElementsToEAforEditing(elements: ExcalidrawElement[]): void;
|
||||
/**
|
||||
*
|
||||
* @param forceViewMode
|
||||
* @returns
|
||||
*/
|
||||
viewToggleFullScreen(forceViewMode?: boolean): void;
|
||||
/**
|
||||
* connect an object to the selected element in the view
|
||||
* @param objectA ID of the element
|
||||
* @param connectionA
|
||||
* @param connectionB
|
||||
* @param formatting
|
||||
* @returns
|
||||
*/
|
||||
connectObjectWithViewSelectedElement(objectA: string, connectionA: ConnectionPoint | null, connectionB: ConnectionPoint | null, formatting?: {
|
||||
numberOfPoints?: number;
|
||||
startArrowHead?: "triangle" | "dot" | "arrow" | "bar" | null;
|
||||
endArrowHead?: "triangle" | "dot" | "arrow" | "bar" | null;
|
||||
padding?: number;
|
||||
}): boolean;
|
||||
/**
|
||||
* Adds elements from elementsDict to the current view
|
||||
* @param repositionToCursor default is false
|
||||
* @param save default is true
|
||||
* @param newElementsOnTop controls whether elements created with ExcalidrawAutomate
|
||||
* are added at the bottom of the stack or the top of the stack of elements already in the view
|
||||
* Note that elements copied to the view with copyViewElementsToEAforEditing retain their
|
||||
* position in the stack of elements in the view even if modified using EA
|
||||
* default is false, i.e. the new elements get to the bottom of the stack
|
||||
* @returns
|
||||
*/
|
||||
addElementsToView(repositionToCursor?: boolean, save?: boolean, newElementsOnTop?: boolean): Promise<boolean>;
|
||||
/**
|
||||
* Register instance of EA to use for hooks with TargetView
|
||||
* By default ExcalidrawViews will check window.ExcalidrawAutomate for event hooks.
|
||||
* Using this event you can set a different instance of Excalidraw Automate for hooks
|
||||
* @returns true if successful
|
||||
*/
|
||||
registerThisAsViewEA(): boolean;
|
||||
/**
|
||||
* Sets the targetView EA to window.ExcalidrawAutomate
|
||||
* @returns true if successful
|
||||
*/
|
||||
deregisterThisAsViewEA(): boolean;
|
||||
/**
|
||||
* If set, this callback is triggered when the user closes an Excalidraw view.
|
||||
*/
|
||||
onViewUnloadHook: (view: ExcalidrawView) => void;
|
||||
/**
|
||||
* If set, this callback is triggered, when the user changes the view mode.
|
||||
* You can use this callback in case you want to do something additional when the user switches to view mode and back.
|
||||
*/
|
||||
onViewModeChangeHook: (isViewModeEnabled: boolean, view: ExcalidrawView, ea: ExcalidrawAutomate) => void;
|
||||
/**
|
||||
* If set, this callback is triggered, when the user hovers a link in the scene.
|
||||
* You can use this callback in case you want to do something additional when the onLinkHover event occurs.
|
||||
* This callback must return a boolean value.
|
||||
* In case you want to prevent the excalidraw onLinkHover action you must return true, it will stop the native excalidraw onLinkHover management flow.
|
||||
*/
|
||||
onLinkHoverHook: (element: NonDeletedExcalidrawElement, linkText: string, view: ExcalidrawView, ea: ExcalidrawAutomate) => boolean;
|
||||
/**
|
||||
* If set, this callback is triggered, when the user clicks a link in the scene.
|
||||
* You can use this callback in case you want to do something additional when the onLinkClick event occurs.
|
||||
* This callback must return a boolean value.
|
||||
* In case you want to prevent the excalidraw onLinkClick action you must return false, it will stop the native excalidraw onLinkClick management flow.
|
||||
*/
|
||||
onLinkClickHook: (element: ExcalidrawElement, linkText: string, event: MouseEvent, view: ExcalidrawView, ea: ExcalidrawAutomate) => boolean;
|
||||
/**
|
||||
* If set, this callback is triggered, when Excalidraw receives an onDrop event.
|
||||
* You can use this callback in case you want to do something additional when the onDrop event occurs.
|
||||
* This callback must return a boolean value.
|
||||
* In case you want to prevent the excalidraw onDrop action you must return false, it will stop the native excalidraw onDrop management flow.
|
||||
*/
|
||||
onDropHook: (data: {
|
||||
ea: ExcalidrawAutomate;
|
||||
event: React.DragEvent<HTMLDivElement>;
|
||||
draggable: any;
|
||||
type: "file" | "text" | "unknown";
|
||||
payload: {
|
||||
files: TFile[];
|
||||
text: string;
|
||||
};
|
||||
excalidrawFile: TFile;
|
||||
view: ExcalidrawView;
|
||||
pointerPosition: {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
}) => boolean;
|
||||
/**
|
||||
* utility function to generate EmbeddedFilesLoader object
|
||||
* @param isDark
|
||||
* @returns
|
||||
*/
|
||||
getEmbeddedFilesLoader(isDark?: boolean): EmbeddedFilesLoader;
|
||||
/**
|
||||
* utility function to generate ExportSettings object
|
||||
* @param withBackground
|
||||
* @param withTheme
|
||||
* @returns
|
||||
*/
|
||||
getExportSettings(withBackground: boolean, withTheme: boolean): ExportSettings;
|
||||
/**
|
||||
* get bounding box of elements
|
||||
* bounding box is the box encapsulating all of the elements completely
|
||||
* @param elements
|
||||
* @returns
|
||||
*/
|
||||
getBoundingBox(elements: ExcalidrawElement[]): {
|
||||
topX: number;
|
||||
topY: number;
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
}): Promise<string>;
|
||||
createSVG(
|
||||
templatePath?: string,
|
||||
embedFont?: boolean,
|
||||
exportSettings?: ExportSettings, //use ExcalidrawAutomate.getExportSettings(boolean,boolean)
|
||||
loader?: EmbeddedFilesLoader, //use ExcalidrawAutomate.getEmbeddedFilesLoader(boolean?)
|
||||
theme?: string,
|
||||
): Promise<SVGSVGElement>;
|
||||
createPNG(
|
||||
templatePath?: string,
|
||||
scale?: number,
|
||||
exportSettings?: ExportSettings, //use ExcalidrawAutomate.getExportSettings(boolean,boolean)
|
||||
loader?: EmbeddedFilesLoader, //use ExcalidrawAutomate.getEmbeddedFilesLoader(boolean?)
|
||||
theme?: string,
|
||||
): Promise<any>;
|
||||
wrapText(text: string, lineLen: number): string;
|
||||
addRect(topX: number, topY: number, width: number, height: number): string;
|
||||
addDiamond(topX: number, topY: number, width: number, height: number): string;
|
||||
addEllipse(topX: number, topY: number, width: number, height: number): string;
|
||||
addBlob(topX: number, topY: number, width: number, height: number): string;
|
||||
addText(
|
||||
topX: number,
|
||||
topY: number,
|
||||
text: string,
|
||||
formatting?: {
|
||||
wrapAt?: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
textAlign?: string;
|
||||
box?: boolean | "box" | "blob" | "ellipse" | "diamond"; //if !null, text will be boxed
|
||||
boxPadding?: number;
|
||||
},
|
||||
id?: string,
|
||||
): string;
|
||||
addLine(points: [[x: number, y: number]]): string;
|
||||
addArrow(
|
||||
points: [[x: number, y: number]],
|
||||
formatting?: {
|
||||
startArrowHead?: string;
|
||||
endArrowHead?: string;
|
||||
startObjectId?: string;
|
||||
endObjectId?: string;
|
||||
},
|
||||
): string;
|
||||
addImage(topX: number, topY: number, imageFile: TFile): Promise<string>;
|
||||
addLaTex(topX: number, topY: number, tex: string): Promise<string>;
|
||||
connectObjects(
|
||||
objectA: string,
|
||||
connectionA: ConnectionPoint, //type ConnectionPoint = "top" | "bottom" | "left" | "right" | null
|
||||
objectB: string,
|
||||
connectionB: ConnectionPoint, //when passed null, Excalidraw will automatically decide
|
||||
formatting?: {
|
||||
numberOfPoints?: number; //points on the line. Default is 0 ie. line will only have a start and end point
|
||||
startArrowHead?: string; //"triangle"|"dot"|"arrow"|"bar"|null
|
||||
endArrowHead?: string; //"triangle"|"dot"|"arrow"|"bar"|null
|
||||
padding?: number;
|
||||
},
|
||||
): void;
|
||||
clear(): void; //clear elementsDict and imagesDict only
|
||||
reset(): void; //clear() + reset all style values to default
|
||||
isExcalidrawFile(f: TFile): boolean; //returns true if MD file is an Excalidraw file
|
||||
//view manipulation
|
||||
targetView: ExcalidrawView; //the view currently edited
|
||||
setView(view: ExcalidrawView | "first" | "active"): ExcalidrawView;
|
||||
getExcalidrawAPI(): any; //https://github.com/excalidraw/excalidraw/tree/master/src/packages/excalidraw#ref
|
||||
getViewElements(): ExcalidrawElement[]; //get elements in View
|
||||
deleteViewElements(el: ExcalidrawElement[]): boolean;
|
||||
getViewSelectedElement(): ExcalidrawElement; //get the selected element in the view, if more are selected, get the first
|
||||
getViewSelectedElements(): ExcalidrawElement[];
|
||||
getViewFileForImageElement(el: ExcalidrawElement): TFile | null; //Returns the TFile file handle for the image element
|
||||
copyViewElementsToEAforEditing(elements: ExcalidrawElement[]): void; //copies elements from view to elementsDict for editing
|
||||
viewToggleFullScreen(forceViewMode?: boolean): void;
|
||||
connectObjectWithViewSelectedElement( //connect an object to the selected element in the view
|
||||
objectA: string, //see connectObjects
|
||||
connectionA: ConnectionPoint,
|
||||
connectionB: ConnectionPoint,
|
||||
formatting?: {
|
||||
numberOfPoints?: number;
|
||||
startArrowHead?: string;
|
||||
endArrowHead?: string;
|
||||
padding?: number;
|
||||
},
|
||||
): boolean;
|
||||
addElementsToView( //Adds elements from elementsDict to the current view
|
||||
repositionToCursor?: boolean, //default is false
|
||||
save?: boolean, //default is true
|
||||
//newElementsOnTop controls whether elements created with ExcalidrawAutomate
|
||||
//are added at the bottom of the stack or the top of the stack of elements already in the view
|
||||
//Note that elements copied to the view with copyViewElementsToEAforEditing retain their
|
||||
//position in the stack of elements in the view even if modified using EA
|
||||
newElementsOnTop?: boolean, //default is false, i.e. the new elements get to the bottom of the stack
|
||||
): Promise<boolean>;
|
||||
onDropHook(data: {
|
||||
//if set Excalidraw will call this function onDrop events
|
||||
ea: ExcalidrawAutomate;
|
||||
event: React.DragEvent<HTMLDivElement>;
|
||||
draggable: any; //Obsidian draggable object
|
||||
type: "file" | "text" | "unknown";
|
||||
payload: {
|
||||
files: TFile[]; //TFile[] array of dropped files
|
||||
text: string; //string
|
||||
/**
|
||||
* elements grouped by the highest level groups
|
||||
* @param elements
|
||||
* @returns
|
||||
*/
|
||||
getMaximumGroups(elements: ExcalidrawElement[]): ExcalidrawElement[][];
|
||||
/**
|
||||
* gets the largest element from a group. useful when a text element is grouped with a box, and you want to connect an arrow to the box
|
||||
* @param elements
|
||||
* @returns
|
||||
*/
|
||||
getLargestElement(elements: ExcalidrawElement[]): ExcalidrawElement;
|
||||
/**
|
||||
* Gets the groupId for the group that contains all the elements, or null if such a group does not exist
|
||||
* @param elements
|
||||
* @returns null or the groupId
|
||||
*/
|
||||
getCommonGroupForElements(elements: ExcalidrawElement[]): string;
|
||||
/**
|
||||
* Gets all the elements from elements[] that share one or more groupIds with element.
|
||||
* @param element
|
||||
* @param elements - typically all the non-deleted elements in the scene
|
||||
* @returns
|
||||
*/
|
||||
getElementsInTheSameGroupWithElement(element: ExcalidrawElement, elements: ExcalidrawElement[]): ExcalidrawElement[];
|
||||
/**
|
||||
* @param element
|
||||
* @param a
|
||||
* @param b
|
||||
* @param gap
|
||||
* @returns 2 or 0 intersection points between line going through `a` and `b`
|
||||
* and the `element`, in ascending order of distance from `a`.
|
||||
*/
|
||||
intersectElementWithLine(element: ExcalidrawBindableElement, a: readonly [number, number], b: readonly [number, number], gap?: number): Point[];
|
||||
/**
|
||||
* See OCR plugin for example on how to use scriptSettings
|
||||
* Set by the ScriptEngine
|
||||
*/
|
||||
activeScript: string;
|
||||
/**
|
||||
*
|
||||
* @returns script settings. Saves settings in plugin settings, under the activeScript key
|
||||
*/
|
||||
getScriptSettings(): {};
|
||||
/**
|
||||
* sets script settings.
|
||||
* @param settings
|
||||
* @returns
|
||||
*/
|
||||
setScriptSettings(settings: any): Promise<void>;
|
||||
/**
|
||||
* Open a file in a new workspaceleaf or reuse an existing adjacent leaf depending on Excalidraw Plugin Settings
|
||||
* @param file
|
||||
* @returns
|
||||
*/
|
||||
openFileInNewOrAdjacentLeaf(file: TFile): WorkspaceLeaf;
|
||||
/**
|
||||
* measure text size based on current style settings
|
||||
* @param text
|
||||
* @returns
|
||||
*/
|
||||
measureText(text: string): {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
excalidrawFile: TFile; //the file receiving the drop event
|
||||
view: ExcalidrawView; //the excalidraw view receiving the drop
|
||||
pointerPosition: { x: number; y: number }; //the pointer position on canvas at the time of drop
|
||||
}): boolean; //a return of true will stop the default onDrop processing in Excalidraw
|
||||
mostRecentMarkdownSVG: SVGSVGElement; //Markdown renderer will drop a copy of the most recent SVG here for debugging purposes
|
||||
getEmbeddedFilesLoader(isDark?: boolean): EmbeddedFilesLoader; //utility function to generate EmbeddedFilesLoader object
|
||||
getExportSettings( //utility function to generate ExportSettings object
|
||||
withBackground: boolean,
|
||||
withTheme: boolean,
|
||||
): ExportSettings;
|
||||
getBoundingBox(elements: ExcalidrawElement[]): {
|
||||
//get bounding box of elements
|
||||
topX: number; //bounding box is the box encapsulating all of the elements completely
|
||||
topY: number;
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
//elements grouped by the highest level groups
|
||||
getMaximumGroups(elements: ExcalidrawElement[]): ExcalidrawElement[][];
|
||||
//gets the largest element from a group. useful when a text element is grouped with a box, and you want to connect an arrow to the box
|
||||
getLargestElement(elements: ExcalidrawElement[]): ExcalidrawElement;
|
||||
// Returns 2 or 0 intersection points between line going through `a` and `b`
|
||||
// and the `element`, in ascending order of distance from `a`.
|
||||
intersectElementWithLine(
|
||||
element: ExcalidrawBindableElement,
|
||||
a: readonly [number, number],
|
||||
b: readonly [number, number],
|
||||
gap?: number, //if given, element is inflated by this value
|
||||
): Point[];
|
||||
|
||||
//See OCR plugin for example on how to use scriptSettings
|
||||
activeScript: string; //Set automatically by the ScriptEngine
|
||||
getScriptSettings(): {}; //Returns script settings. Saves settings in plugin settings, under the activeScript key
|
||||
setScriptSettings(settings: any): Promise<void>; //sets script settings.
|
||||
openFileInNewOrAdjacentLeaf(file: TFile): WorkspaceLeaf; //Open a file in a new workspaceleaf or reuse an existing adjacent leaf depending on Excalidraw Plugin Settings
|
||||
measureText(text: string): { width: number; height: number }; //measure text size based on current style settings
|
||||
//verifyMinimumPluginVersion returns true if plugin version is >= than required
|
||||
//recommended use:
|
||||
//if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.5.20")) {new Notice("message");return;}
|
||||
verifyMinimumPluginVersion(requiredVersion: string): boolean;
|
||||
selectElementsInView(elements: ExcalidrawElement[]): void; //sets selection in view
|
||||
generateElementId(): string; //returns an 8 character long random id
|
||||
cloneElement(element: ExcalidrawElement): ExcalidrawElement; //Returns a clone of the element with a new id
|
||||
moveViewElementToZIndex(elementId:number, newZIndex:number): void; //Moves the element to a specific position in the z-index
|
||||
hexStringToRgb(color: string):number[];
|
||||
rgbToHexString(color: number[]):string;
|
||||
hslToRgb(color: number[]):number[];
|
||||
rgbToHsl(color:number[]):number[];
|
||||
colorNameToHex(color:string):string;
|
||||
}
|
||||
```
|
||||
/**
|
||||
* verifyMinimumPluginVersion returns true if plugin version is >= than required
|
||||
* recommended use:
|
||||
* if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.5.20")) {new Notice("message");return;}
|
||||
* @param requiredVersion
|
||||
* @returns
|
||||
*/
|
||||
verifyMinimumPluginVersion(requiredVersion: string): boolean;
|
||||
/**
|
||||
* Check if view is instance of ExcalidrawView
|
||||
* @param view
|
||||
* @returns
|
||||
*/
|
||||
isExcalidrawView(view: any): boolean;
|
||||
/**
|
||||
* sets selection in view
|
||||
* @param elements
|
||||
* @returns
|
||||
*/
|
||||
selectElementsInView(elements: ExcalidrawElement[]): void;
|
||||
/**
|
||||
* @returns an 8 character long random id
|
||||
*/
|
||||
generateElementId(): string;
|
||||
/**
|
||||
* @param element
|
||||
* @returns a clone of the element with a new id
|
||||
*/
|
||||
cloneElement(element: ExcalidrawElement): ExcalidrawElement;
|
||||
/**
|
||||
* Moves the element to a specific position in the z-index
|
||||
*/
|
||||
moveViewElementToZIndex(elementId: number, newZIndex: number): void;
|
||||
/**
|
||||
*
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
hexStringToRgb(color: string): number[];
|
||||
/**
|
||||
*
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
rgbToHexString(color: number[]): string;
|
||||
/**
|
||||
*
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
hslToRgb(color: number[]): number[];
|
||||
/**
|
||||
*
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
rgbToHsl(color: number[]): number[];
|
||||
/**
|
||||
*
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
colorNameToHex(color: string): string;
|
||||
}```
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
## Introduction to the API
|
||||
You can access Excalidraw Automate via the ExcalidrawAutomate object. I recommend starting Templater, DataView and QuickAdd scripts with the following code:
|
||||
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
@@ -25,7 +25,7 @@ You can change the styling between adding different elements. My logic for separ
|
||||
#### Create a new drawing with custom name, in a custom folder, using a template
|
||||
This simple script gives you significant additional flexibility over Excalidraw Plugin settings to name your drawings, place them into folders, and to apply templates.
|
||||
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
@@ -40,7 +40,7 @@ This simple script gives you significant additional flexibility over Excalidraw
|
||||
```
|
||||
|
||||
#### Create a simple drawing
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
@@ -62,7 +62,7 @@ The script will generate the following drawing:
|
||||
#### Add a TextElement in a box to an open Excalidraw View.
|
||||
Position the new element under the currently selected element, with an arrow from the selected element to the added text.
|
||||
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
|
||||
@@ -143,7 +143,7 @@ getViewSelectedElement():ExcalidrawElement
|
||||
|
||||
You first need to set the view calling `setView()`.
|
||||
|
||||
If an element is selected in the targetView the function returns the selected element. If multiple elements are selected, either by SHIFT+Clicking to select multiple elements, or by selecting a group, the first of the elements will be selected. If you want to specify which element to select from a group, double click the desired element in the group.
|
||||
If an element is selected in the targetView the function returns the selected element. If multiple elements are selected, either by <kbd>SHIFT+Clicking</kbd> to select multiple elements, or by selecting a group, the first of the elements will be selected. If you want to specify which element to select from a group, double click the desired element in the group.
|
||||
|
||||
This function is helpful if you want to add a new element in relation to an existing element in your drawing.
|
||||
|
||||
@@ -218,4 +218,4 @@ ea.onDropHook = (data) => {
|
||||
console.log(data);
|
||||
return false;
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
## Applying an Excalidraw Template to a New Drawing
|
||||
This example is similar to the one in the introduction, only rotated 90°, and using a template, plus specifying a filename and folder to save the drawing, and opening the new drawing in a new pane.
|
||||
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
## Connect Objects
|
||||
This [Templater](https://github.com/SilentVoid13/Templater) template demonstrates how to connect two objects using ExcalidrawAutomate.
|
||||
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
|
||||
@@ -19,7 +19,7 @@ The input file is `Demo.md` with the following contents:
|
||||
|
||||
### dataviewjs script
|
||||
The `dataviewjs` script looks like this:
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
function crawl(subtasks) {
|
||||
let size = subtasks.length > 0 ? 0 : 1; //if no children then a leaf with size 1
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
## Insert new drawing into currently edited document
|
||||
This [Templater](https://github.com/SilentVoid13/Templater) template will prompt you for the title of the drawing. It will create a new drawing with the provided title, and in the folder of the document you were editing. It will then transclude the new drawing at the cursor location and open the new drawing in a new workspace leaf by splitting the current leaf.
|
||||
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
<%*
|
||||
const defaultTitle = tp.date.now("HHmm")+' '+tp.file.title;
|
||||
|
||||
@@ -22,7 +22,7 @@ Example input:
|
||||
```
|
||||
|
||||
### Templater script
|
||||
*Use CTRL+Shift+V to paste code into Obsidian!*
|
||||
*Use <kbd>CTRL+Shift+V</kbd> to paste code into Obsidian!*
|
||||
```javascript
|
||||
<%*
|
||||
const IDX = Object.freeze({"depth":0, "text":1, "parent":2, "size":3, "children": 4, "objectId":5});
|
||||
|
||||
@@ -11,8 +11,6 @@ if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.6.1")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const BLANK_DRAWING = ["---","","excalidraw-plugin: parsed","","---","==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. ⚠==","","","%%","# Drawing","\x60\x60\x60json",'{"type":"excalidraw","version":2,"source":"https://excalidraw.com","elements":[],"appState":{"gridSize":null,"viewBackgroundColor":"#ffffff"}}',"\x60\x60\x60","%%"].join("\n");
|
||||
|
||||
settings = ea.getScriptSettings();
|
||||
|
||||
if(!settings["Open link in active pane"]) {
|
||||
@@ -60,8 +58,9 @@ const filepath = activeFile.path.replace(activeFile.name,`${filename}.md`);
|
||||
|
||||
const file = await app.fileManager.createNewMarkdownFileFromLinktext(filepath);
|
||||
if(file && fileType==="ex") {
|
||||
await app.vault.modify(file,BLANK_DRAWING);
|
||||
await new Promise(r => setTimeout(r, 100)); //wait for metadata cache to update, so file opens as excalidraw
|
||||
const blank = await app.plugins.plugins["obsidian-excalidraw-plugin"].getBlankDrawing();
|
||||
await app.vault.modify(file,blank);
|
||||
await new Promise(r => setTimeout(r, 100)); //wait for metadata cache to update, so file opens as excalidraw
|
||||
}
|
||||
|
||||
const link = `[[${app.metadataCache.fileToLinktext(file,ea.targetView.file.path,true)}]]`;
|
||||
@@ -88,4 +87,4 @@ if(openInCurrentPane) {
|
||||
app.workspace.openLinkText(file.path,ea.targetView.file.path,false);
|
||||
return;
|
||||
}
|
||||
ea.openFileInNewOrAdjacentLeaf(file);
|
||||
ea.openFileInNewOrAdjacentLeaf(file);
|
||||
|
||||
@@ -1,120 +1,120 @@
|
||||
/*
|
||||

|
||||
|
||||
THIS SCRIPT REQUIRES EXCALIDRAW 1.5.15
|
||||
|
||||
The script will
|
||||
1) send the selected image file to [taskbone.com](https://taskbone.com) to exctract the text from the image, and
|
||||
2) will add the text to your drawing as a text element
|
||||
|
||||
I recommend also installing the [Transfer TextElements to Excalidraw markdown metadata](Transfer%20TextElements%20to%20Excalidraw%20markdown%20metadata.md) script as well.
|
||||
|
||||
The script is based on [@schlundd](https://github.com/schlundd)'s [Obsidian-OCR-Plugin](https://github.com/schlundd/obsidian-ocr-plugin)
|
||||
|
||||
See ScriptEngine documentation for more details:
|
||||
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
|
||||
|
||||
```javascript
|
||||
*/
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.5.24")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
let token = ea.getScriptSettings().token?.value??ea.getScriptSettings().token;
|
||||
const BASE_URL = "https://ocr.taskbone.com";
|
||||
|
||||
//convert setting to 1.5.21 format
|
||||
if(token && !ea.getScriptSettings().token.value) {
|
||||
ea.setScriptSettings({token: {value: token, hidden: true}});
|
||||
}
|
||||
|
||||
//get new token if token was not provided
|
||||
if (!token) {
|
||||
const tokenResponse = await fetch(
|
||||
BASE_URL + "/get-new-token", {
|
||||
method: 'post'
|
||||
});
|
||||
if (tokenResponse.status === 200) {
|
||||
jsonResponse = await tokenResponse.json();
|
||||
token = jsonResponse.token;
|
||||
ea.setScriptSettings({token: {value: token, hidden: true}});
|
||||
} else {
|
||||
notice(`Taskbone OCR Error: ${tokenResponse.status}\nPlease try again later.`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//get image element
|
||||
//if multiple image elements were selected prompt user to choose
|
||||
const imageElements = ea.getViewSelectedElements().filter((el)=>el.type==="image");
|
||||
|
||||
//need to save the view to ensure recently pasted images are saved as files
|
||||
await ea.targetView.save();
|
||||
|
||||
let selectedImageElement = null;
|
||||
switch (imageElements.length) {
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
selectedImageElement = imageElements[0];
|
||||
break;
|
||||
default:
|
||||
const files = imageElements.map((el)=>ea.getViewFileForImageElement(el));
|
||||
selectedImageElement = await utils.suggester(files.map((f)=>f.name),imageElements);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!selectedImageElement) {
|
||||
notice("No image element was selected");
|
||||
return;
|
||||
}
|
||||
const imageFile = ea.getViewFileForImageElement(selectedImageElement);
|
||||
if(!imageFile) {
|
||||
notice("Can read image file");
|
||||
return;
|
||||
}
|
||||
|
||||
//Execute the OCR
|
||||
let text = null;
|
||||
const fileBuffer = await app.vault.readBinary(imageFile);
|
||||
const formData = new FormData();
|
||||
formData.append("image", new Blob([fileBuffer]))
|
||||
try {
|
||||
const response = await fetch(
|
||||
BASE_URL + "/get-text", {
|
||||
headers: {
|
||||
Authorization: "Bearer " + token
|
||||
},
|
||||
method: "post",
|
||||
body: formData
|
||||
});
|
||||
if (response.status == 200) {
|
||||
jsonResponse = await response.json();
|
||||
text = jsonResponse?.text;
|
||||
} else {
|
||||
notice(`Could not read Text from ${file.path}:\n Error: ${response.status}`);
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
notice(`The OCR service seems unavailable right now. Please try again later.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!text) {
|
||||
notice("No text found");
|
||||
return;
|
||||
}
|
||||
console.log({text});
|
||||
|
||||
//add text element to drawing
|
||||
const id = ea.addText(selectedImageElement.x,selectedImageElement.y+selectedImageElement.height,text);
|
||||
await ea.addElementsToView();
|
||||
ea.selectElementsInView([ea.getElement(id)]);
|
||||
ea.getExcalidrawAPI().zoomToFit(ea.getViewSelectedElements(),1);
|
||||
|
||||
//utility function
|
||||
function notice(message) {
|
||||
new Notice(message,10000);
|
||||
console.log(message);
|
||||
}
|
||||
/*
|
||||

|
||||
|
||||
THIS SCRIPT REQUIRES EXCALIDRAW 1.5.15
|
||||
|
||||
The script will
|
||||
1) send the selected image file to [taskbone.com](https://taskbone.com) to exctract the text from the image, and
|
||||
2) will add the text to your drawing as a text element
|
||||
|
||||
I recommend also installing the [Transfer TextElements to Excalidraw markdown metadata](Transfer%20TextElements%20to%20Excalidraw%20markdown%20metadata.md) script as well.
|
||||
|
||||
The script is based on [@schlundd](https://github.com/schlundd)'s [Obsidian-OCR-Plugin](https://github.com/schlundd/obsidian-ocr-plugin)
|
||||
|
||||
See ScriptEngine documentation for more details:
|
||||
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
|
||||
|
||||
```javascript
|
||||
*/
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.5.24")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
let token = ea.getScriptSettings().token?.value??ea.getScriptSettings().token;
|
||||
const BASE_URL = "https://ocr.taskbone.com";
|
||||
|
||||
//convert setting to 1.5.21 format
|
||||
if(token && !ea.getScriptSettings().token.value) {
|
||||
ea.setScriptSettings({token: {value: token, hidden: true}});
|
||||
}
|
||||
|
||||
//get new token if token was not provided
|
||||
if (!token) {
|
||||
const tokenResponse = await fetch(
|
||||
BASE_URL + "/get-new-token", {
|
||||
method: 'post'
|
||||
});
|
||||
if (tokenResponse.status === 200) {
|
||||
jsonResponse = await tokenResponse.json();
|
||||
token = jsonResponse.token;
|
||||
ea.setScriptSettings({token: {value: token, hidden: true}});
|
||||
} else {
|
||||
notice(`Taskbone OCR Error: ${tokenResponse.status}\nPlease try again later.`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//get image element
|
||||
//if multiple image elements were selected prompt user to choose
|
||||
const imageElements = ea.getViewSelectedElements().filter((el)=>el.type==="image");
|
||||
|
||||
//need to save the view to ensure recently pasted images are saved as files
|
||||
await ea.targetView.save();
|
||||
|
||||
let selectedImageElement = null;
|
||||
switch (imageElements.length) {
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
selectedImageElement = imageElements[0];
|
||||
break;
|
||||
default:
|
||||
const files = imageElements.map((el)=>ea.getViewFileForImageElement(el));
|
||||
selectedImageElement = await utils.suggester(files.map((f)=>f.name),imageElements);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!selectedImageElement) {
|
||||
notice("No image element was selected");
|
||||
return;
|
||||
}
|
||||
const imageFile = ea.getViewFileForImageElement(selectedImageElement);
|
||||
if(!imageFile) {
|
||||
notice("Can read image file");
|
||||
return;
|
||||
}
|
||||
|
||||
//Execute the OCR
|
||||
let text = null;
|
||||
const fileBuffer = await app.vault.readBinary(imageFile);
|
||||
const formData = new FormData();
|
||||
formData.append("image", new Blob([fileBuffer]))
|
||||
try {
|
||||
const response = await fetch(
|
||||
BASE_URL + "/get-text", {
|
||||
headers: {
|
||||
Authorization: "Bearer " + token
|
||||
},
|
||||
method: "post",
|
||||
body: formData
|
||||
});
|
||||
if (response.status == 200) {
|
||||
jsonResponse = await response.json();
|
||||
text = jsonResponse?.text;
|
||||
} else {
|
||||
notice(`Could not read Text from ${file.path}:\n Error: ${response.status}`);
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
notice(`The OCR service seems unavailable right now. Please try again later.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!text) {
|
||||
notice("No text found");
|
||||
return;
|
||||
}
|
||||
console.log({text});
|
||||
|
||||
//add text element to drawing
|
||||
const id = ea.addText(selectedImageElement.x,selectedImageElement.y+selectedImageElement.height,text);
|
||||
await ea.addElementsToView();
|
||||
ea.selectElementsInView([ea.getElement(id)]);
|
||||
ea.getExcalidrawAPI().zoomToFit(ea.getViewSelectedElements(),1);
|
||||
|
||||
//utility function
|
||||
function notice(message) {
|
||||
new Notice(message,10000);
|
||||
console.log(message);
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 605 B After Width: | Height: | Size: 605 B |
@@ -1,44 +1,44 @@
|
||||
/*
|
||||

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

|
||||
|
||||
The script will delete the selected text elements from the canvas and will copy the text from these text elements into the Excalidraw markdown file as metadata. This means, that the text will no longer be visible in the drawing, however you will be able to search for the text in Obsidian and find the drawing containing this image.
|
||||
|
||||
See ScriptEngine documentation for more details:
|
||||
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
|
||||
|
||||
```javascript
|
||||
*/
|
||||
//get text elements
|
||||
|
||||
const textElements = ea.getViewSelectedElements().filter((el)=>el.type==="text");
|
||||
|
||||
if(textElements.length===0) {
|
||||
notice("No text elements were selected")
|
||||
return;
|
||||
}
|
||||
|
||||
metadata = "# Metadata\n" + textElements
|
||||
.map((el)=>el.rawText.replaceAll(/%|\^/g,"_")) //cleaning these characters for safety, might not be needed
|
||||
.join("/n") + "\n";
|
||||
|
||||
ea.deleteViewElements(textElements);
|
||||
await ea.targetView.save();
|
||||
data = await app.vault.read(ea.targetView.file);
|
||||
splitAfterFrontmatter = data.split(/(^---[\w\W]*?---\n)/);
|
||||
if(splitAfterFrontmatter.length !== 3) {
|
||||
notice("Error locating frontmatter in markdown file");
|
||||
console.log({file:ea.targetView.file});
|
||||
return;
|
||||
}
|
||||
newData = splitAfterFrontmatter[1]+metadata+splitAfterFrontmatter[2]
|
||||
await app.vault.modify(ea.targetView.file,newData);
|
||||
|
||||
//utility function
|
||||
function notice(message) {
|
||||
new Notice(message);
|
||||
console.log(message);
|
||||
}
|
||||
/*
|
||||

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

|
||||
|
||||
The script will delete the selected text elements from the canvas and will copy the text from these text elements into the Excalidraw markdown file as metadata. This means, that the text will no longer be visible in the drawing, however you will be able to search for the text in Obsidian and find the drawing containing this image.
|
||||
|
||||
See ScriptEngine documentation for more details:
|
||||
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
|
||||
|
||||
```javascript
|
||||
*/
|
||||
//get text elements
|
||||
|
||||
const textElements = ea.getViewSelectedElements().filter((el)=>el.type==="text");
|
||||
|
||||
if(textElements.length===0) {
|
||||
notice("No text elements were selected")
|
||||
return;
|
||||
}
|
||||
|
||||
metadata = "# Metadata\n" + textElements
|
||||
.map((el)=>el.rawText.replaceAll(/%|\^/g,"_")) //cleaning these characters for safety, might not be needed
|
||||
.join("/n") + "\n";
|
||||
|
||||
ea.deleteViewElements(textElements);
|
||||
await ea.targetView.save();
|
||||
data = await app.vault.read(ea.targetView.file);
|
||||
splitAfterFrontmatter = data.split(/(^---[\w\W]*?---\n)/);
|
||||
if(splitAfterFrontmatter.length !== 3) {
|
||||
notice("Error locating frontmatter in markdown file");
|
||||
console.log({file:ea.targetView.file});
|
||||
return;
|
||||
}
|
||||
newData = splitAfterFrontmatter[1]+metadata+splitAfterFrontmatter[2]
|
||||
await app.vault.modify(ea.targetView.file,newData);
|
||||
|
||||
//utility function
|
||||
function notice(message) {
|
||||
new Notice(message);
|
||||
console.log(message);
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
@@ -1,341 +1,348 @@
|
||||
If you are enjoying the Excalidraw plugin then please support my work and enthusiasm by buying me a coffee on [https://ko-fi/zsolt](https://ko-fi.com/zsolt).
|
||||
|
||||
[<img src="https://user-images.githubusercontent.com/14358394/115450238-f39e8100-a21b-11eb-89d0-fa4b82cdbce8.png" class="coffee">](https://ko-fi.com/zsolt)
|
||||
|
||||
---
|
||||
|
||||
Jump ahead to the [[#List of available scripts]]
|
||||
|
||||
# Intorducing Excalidraw Automate Script Engine
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/hePJcObHIso" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
Script Engine scripts are installed in the `Downloaded` subfolder of the `Excalidraw Automate script folder` specified in plugin settings.
|
||||
|
||||
In the `Command Palette` installed scripts are prefixed with `Downloaded/`, thus you can always know if you are executing a local script of your own, or one that you have downloaded from GitHub.
|
||||
|
||||
## Attention developers and hobby hackers
|
||||
<img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/hobby-programmer.svg' align='left' style='background-color:whitesmoke; width:80px; margin-right:15px; margin-bottom:10px;'/>
|
||||
If you want to modify scripts, I recommend moving them to the `Excalidraw Automate script folder` or a different subfolder under the script folder. Scripts in the `Downloaded` folder will be overwritten when you click the `Update this script` button. Note also, that at this time, I do not check if the script file has been updated on GitHub, thus the `Update this script` button is always visible once you have installed a script, not only when an update is availble (hope to build this feature in the future).
|
||||
|
||||
I would love to include your contribution in the script library. If you have a script of your own that you would like to share with the community, please open a [PR](https://github.com/zsviczian/obsidian-excalidraw-plugin/pulls) on GitHub. Be sure to include the following in your pull request
|
||||
- The [script file](https://github.com/zsviczian/obsidian-excalidraw-plugin/tree/master/ea-scripts) with a self explanetory name. The name of the file will be the name of the script in the Command Palette.
|
||||
- An [image](https://github.com/zsviczian/obsidian-excalidraw-plugin/tree/master/images) explaining the scripts purpose. Remember a picture speaks thousand words!
|
||||
- An update to this file [ea-scripts/index.md](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/index.md)
|
||||
|
||||
---
|
||||
|
||||
# List of available scripts
|
||||
- [[#Add Connector Point]]
|
||||
- [[#Add Link to Existing File and Open]]
|
||||
- [[#Add Link to New Page and Open]]
|
||||
- [[#Add Next Step in Process]]
|
||||
- [[#Box Each Selected Groups]]
|
||||
- [[#Box Selected Elements]]
|
||||
- [[#Change shape of selected elements]]
|
||||
- [[#Connect elements]]
|
||||
- [[#Convert freedraw to line]]
|
||||
- [[#Convert selected text elements to sticky notes]]
|
||||
- [[#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]]
|
||||
- [[#Elbow connectors]]
|
||||
- [[#Expand rectangles horizontally keep text centered]]
|
||||
- [[#Expand rectangles horizontally]]
|
||||
- [[#Expand rectangles vertically keep text centered]]
|
||||
- [[#Expand rectangles vertically]]
|
||||
- [[#Fixed horizontal distance between centers]]
|
||||
- [[#Fixed inner distance]]
|
||||
- [[#Fixed spacing]]
|
||||
- [[#Fixed vertical distance between centers]]
|
||||
- [[#Fixed vertical distance]]
|
||||
- [[#Lighten background color]]
|
||||
- [[#Modify background color opacity]]
|
||||
- [[#Normalize Selected Arrows]]
|
||||
- [[#OCR - Optical Character Recognition]]
|
||||
- [[#Organic Line]]
|
||||
- [[#Repeat Elements]]
|
||||
- [[#Reverse arrows]]
|
||||
- [[#Scribble Helper]]
|
||||
- [[#Select Elements of Type]]
|
||||
- [[#Set background color of unclosed line object by adding a shadow clone]]
|
||||
- [[#Set Dimensions]]
|
||||
- [[#Set Font Family]]
|
||||
- [[#Set Grid]]
|
||||
- [[#Set Link Alias]]
|
||||
- [[#Set Stroke Width of Selected Elements]]
|
||||
- [[#Set Text Alignment]]
|
||||
- [[#Split text by lines]]
|
||||
- [[#Toggle Fullscreen on Mobile]]
|
||||
- [[#Transfer TextElements to Excalidraw markdown metadata]]
|
||||
- [[#Zoom to Fit Selected Elements]]
|
||||
|
||||
## Add Connector Point
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Add%20Connector%20Point.md
|
||||
```
|
||||
<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/Add%20Connector%20Point.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will add a small circle to the top left of each text element in the selection and add the text and the "connector point" to a group. You can use the connector points to link text elements with an arrow (in for example a Wardley Map).<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-bullet-point.jpg'></td></tr></table>
|
||||
|
||||
## Add Link to Existing File and Open
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Add%20Link%20to%20Existing%20File%20and%20Open.md
|
||||
```
|
||||
<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/Add%20Link%20to%20Existing%20File%20and%20Open.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Prompts for a file from the vault. Adds a link to the selected element pointing to the selected file. You can control in settings to open the file in the current active pane or an adjacent pane.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-add-link-and-open.jpg'></td></tr></table>
|
||||
|
||||
## Add Link to New Page and Open
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Add%20Link%20to%20New%20Page%20and%20Open.md
|
||||
```
|
||||
<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/Add%20Link%20to%20New%20Page%20and%20Open.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Prompts for filename. Offers option to create and open a new Markdown or Excalidraw document. Adds link pointing to the new file, to the selected objects in the drawing. You can control in settings to open the file in the current active pane or an adjacent pane.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-add-link-to-new-page-and-pen.jpg'></td></tr></table>
|
||||
|
||||
## Add Next Step in Process
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Add%20Next%20Step%20in%20Process.md
|
||||
```
|
||||
<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/Add%20Next%20Step%20in%20Process.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will prompt you for the title of the process step, then will create a stick note with the text. If an element is selected then the script will connect this new step with an arrow to the previous step (the selected element). If no element is selected, then the script assumes this is the first step in the process and will only output the sticky note with the text that was entered.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-add-process-step.jpg'></td></tr></table>
|
||||
|
||||
## 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
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Box%20Selected%20Elements.md
|
||||
```
|
||||
<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/Box%20Selected%20Elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will add an encapsulating box around the currently selected elements in Excalidraw.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-box-elements.jpg'></td></tr></table>
|
||||
|
||||
## Change shape of selected elements
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Change%20shape%20of%20selected%20elements.md
|
||||
```
|
||||
<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/Change%20shape%20of%20selected%20elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">The script allows you to change the shape of selected Rectangles, Diamonds and Ellipses.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-change-shape.jpg'></td></tr></table>
|
||||
|
||||
## Connect elements
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Connect%20elements.md
|
||||
```
|
||||
<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/Connect%20elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">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).<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-connect-elements.jpg'></td></tr></table>
|
||||
|
||||
## Convert freedraw to line
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Convert%20freedraw%20to%20line.md
|
||||
```
|
||||
<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%20freedraw%20to%20line.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Convert selected freedraw objects into editable lines. This will allow you to adjust your drawings by dragging line points and will also allow you to select shape fill in case of enclosed lines. You can adjust conversion point density in settings.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-convert-freedraw-to-line.jpg'></td></tr></table>
|
||||
|
||||
## Convert selected text elements to sticky notes
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Convert%20selected%20text%20elements%20to%20sticky%20notes.md
|
||||
```
|
||||
<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%20selected%20text%20elements%20to%20sticky%20notes.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Converts selected plain text elements to sticky notes with transparent background and transparent stroke color (default setting, can be changed in plugin settings). Essentially converts text element into a wrappable format.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-textelement-to-transparent-stickynote.png'></td></tr></table>
|
||||
|
||||
## Convert text to link with folder and alias
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Convert%20text%20to%20link%20with%20folder%20and%20alias.md
|
||||
```
|
||||
<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
|
||||
```
|
||||
<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/Create%20new%20markdown%20file%20and%20embed%20into%20active%20drawing.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">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.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-create-and-embed-new-markdown-file.jpg'></td></tr></table>
|
||||
|
||||
## Darken background color
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Darken%20background%20color.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/Darken%20background%20color.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">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.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/darken-lighten-background-color.png'></td></tr></table>
|
||||
|
||||
## Elbow connectors
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Elbow%20connectors.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/Elbow%20connectors.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script converts the selected connectors to elbows.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/elbow-connectors.png'></td></tr></table>
|
||||
|
||||
## Expand rectangles horizontally keep text centered
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Expand%20rectangles%20horizontally%20keep%20text%20centered.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/Expand%20rectangles%20horizontally%20keep%20text%20centered.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script expands the width of the selected rectangles until they are all the same width and keep the text centered.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif'></td></tr></table>
|
||||
|
||||
## Expand rectangles horizontally
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Expand%20rectangles%20horizontally.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/Expand%20rectangles%20horizontally.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script expands the width of the selected rectangles until they are all the same width.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif'></td></tr></table>
|
||||
|
||||
## Expand rectangles vertically keep text centered
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Expand%20rectangles%20vertically%20keep%20text%20centered.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/Expand%20rectangles%20vertically%20keep%20text%20centered.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script expands the height of the selected rectangles until they are all the same height and keep the text centered.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif'></td></tr></table>
|
||||
|
||||
## Expand rectangles vertically
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Expand%20rectangles%20vertically.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/Expand%20rectangles%20vertically.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script expands the height of the selected rectangles until they are all the same height.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif'></td></tr></table>
|
||||
|
||||
## Fixed horizontal distance between centers
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Fixed%20horizontal%20distance%20between%20centers.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/Fixed%20horizontal%20distance%20between%20centers.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script arranges the selected elements horizontally with a fixed center spacing.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-fixed-horizontal-distance-between-centers.png'></td></tr></table>
|
||||
|
||||
## Fixed inner distance
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Fixed%20inner%20distance.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/Fixed%20inner%20distance.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script arranges selected elements and groups with a fixed inner distance.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-fixed-inner-distance.png'></td></tr></table>
|
||||
|
||||
## Fixed spacing
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Fixed%20spacing.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/Fixed%20spacing.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">The script arranges the selected elements horizontally with a fixed spacing. When we create an architecture diagram or mind map, we often need to arrange a large number of elements in a fixed spacing. `Fixed spacing` and `Fixed vertical Distance` scripts can save us a lot of time.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-fix-space-demo.png'></td></tr></table>
|
||||
|
||||
## Fixed vertical distance between centers
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Fixed%20vertical%20distance%20between%20centers.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/Fixed%20vertical%20distance%20between%20centers.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script arranges the selected elements vertically with a fixed center spacing.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-fixed-vertical-distance-between-centers.png'></td></tr></table>
|
||||
|
||||
## Fixed vertical distance
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Fixed%20vertical%20distance.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/Fixed%20vertical%20distance.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">The script arranges the selected elements vertically with a fixed spacing. When we create an architecture diagram or mind map, we often need to arrange a large number of elements in a fixed spacing. `Fixed spacing` and `Fixed vertical Distance` scripts can save us a lot of time.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-fixed-vertical-distance.png'></td></tr></table>
|
||||
|
||||
## Lighten background color
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Lighten%20background%20color.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/Lighten%20background%20color.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script lightens 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.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/darken-lighten-background-color.png'></td></tr></table>
|
||||
|
||||
## Modify background color opacity
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Modify%20background%20color%20opacity.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/Modify%20background%20color%20opacity.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script changes the opacity of the background color of the selected boxes. The default background color in Excalidraw is so dark that the text is hard to read. You can lighten the color a bit by setting transparency. And you can tweak the transparency over and over again until you're happy with it. Although excalidraw has the opacity option in its native property Settings, it also changes the transparency of the border. Use this script to change only the opacity of the background color without affecting the border.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-modify-background-color-opacity.png'></td></tr></table>
|
||||
|
||||
## Normalize Selected Arrows
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Normalize%20Selected%20Arrows.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/Normalize%20Selected%20Arrows.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will reset the start and end positions of the selected arrows. The arrow will point to the center of the connected box and will have a gap of 8px from the box.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-normalize-selected-arrows.png'></td></tr></table>
|
||||
|
||||
## OCR - Optical Character Recognition
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/OCR%20-%20Optical%20Character%20Recognition.md
|
||||
```
|
||||
<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/OCR%20-%20Optical%20Character%20Recognition.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">REQUIRES EXCALIDRAW 1.5.15<br>The script will 1) send the selected image file to [taskbone.com](https://taskbone.com) to exctract the text from the image, and 2) will add the text to your drawing as a text element.<br><mark>⚠ Note that you will need to manually paste your token into the script after the first run! ⚠</mark><br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-ocr.jpg'><br><iframe width="560" height="315" src="https://www.youtube.com/embed/W2NMzR8s4eE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></td></tr></table>
|
||||
|
||||
## Organic Line
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Organic%20Line.md
|
||||
```
|
||||
<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/Organic%20Line.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Converts selected freedraw lines such that pencil pressure will decrease from maximum to minimum from the beginning of the line to its end. The resulting line is placed at the back of the layers, under all other items. Helpful when drawing organic mindmaps.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-organic-line.jpg'></td></tr></table>
|
||||
|
||||
## Repeat Elements
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Repeat%20Elements.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/Repeat%20Elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will detect the difference between 2 selected elements, including position, size, angle, stroke and background color, and create several elements that repeat these differences based on the number of repetitions entered by the user.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-repeat-elements.png'></td></tr></table>
|
||||
|
||||
## Reverse arrows
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Reverse%20arrows.md
|
||||
```
|
||||
<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/Reverse%20arrows.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Reverse the direction of **arrows** within the scope of selected elements.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-reverse-arrow.jpg'></td></tr></table>
|
||||
|
||||
## Scribble Helper
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Scribble%20Helper.md
|
||||
```
|
||||
<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/Scribble%20Helper.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">iOS scribble helper for better handwriting experience with text elements. If no elements are selected then the creates a text element at pointer position and you can use the edit box to modify the text with scribble. If a text element is selected then opens the input prompt where you can modify this text with scribble.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-scribble-helper.jpg'></td></tr></table>
|
||||
|
||||
## Select Elements of Type
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Select%20Elements%20of%20Type.md
|
||||
```
|
||||
<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/Select%20Elements%20of%20Type.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Prompts you with a list of the different element types in the active image. Only elements of the selected type will be selected on the canvas. If nothing is selected when running the script, then the script will process all the elements on the canvas. If some elements are selected when the script is executed, then the script will only process the selected elements.<br>The script is useful when, for example, you want to bring to front all the arrows, or want to change the color of all the text elements, etc.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-select-element-of-type.jpg'></td></tr></table>
|
||||
|
||||
## Set background color of unclosed line object by adding a shadow clone
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20background%20color%20of%20unclosed%20line%20object%20by%20adding%20a%20shadow%20clone.md
|
||||
```
|
||||
<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/Set%20background%20color%20of%20unclosed%20line%20object%20by%20adding%20a%20shadow%20clone.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Use this script to set the background color of unclosed (i.e. open) line objects by creating a clone of the object. The script will set the stroke color of the clone to transparent and will add a straight line to close the object. Use settings to define the default background color, the fill style, and the strokeWidth of the clone. By default the clone will be grouped with the original object, you can disable this also in settings.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-set-background-color-of-unclosed-line.jpg'></td></tr></table>
|
||||
|
||||
## Set Dimensions
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Dimensions.md
|
||||
```
|
||||
<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/Set%20Dimensions.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">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.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-dimensions.jpg'></td></tr></table>
|
||||
|
||||
## Set Font Family
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Font%20Family.md
|
||||
```
|
||||
<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/Set%20Font%20Family.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Sets font family of the text block (Virgil, Helvetica, Cascadia). Useful if you want to set a keyboard shortcut for selecting font family.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-font-family.jpg'></td></tr></table>
|
||||
|
||||
## Set Grid
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Grid.md
|
||||
```
|
||||
<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/Set%20Grid.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">The default grid size in Excalidraw is 20. Currently there is no way to change the grid size via the user interface. This script offers a way to bridge this gap.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-grid.jpg'></td></tr></table>
|
||||
|
||||
## Set Link Alias
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Link%20Alias.md
|
||||
```
|
||||
<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/Set%20Link%20Alias.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Iterates all of the links in the selected TextElements and prompts the user to set or modify the alias for each link found.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-set-link-alias.jpg'></td></tr></table>
|
||||
|
||||
## Set Stroke Width of Selected Elements
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Stroke%20Width%20of%20Selected%20Elements.md
|
||||
```
|
||||
<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/Set%20Stroke%20Width%20of%20Selected%20Elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will set the stroke width of selected elements. This is helpful, for example, when you scale freedraw sketches and want to reduce or increase their line width.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-stroke-width.jpg'></td></tr></table>
|
||||
|
||||
## Set Text Alignment
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Text%20Alignment.md
|
||||
```
|
||||
<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/Set%20Text%20Alignment.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Sets text alignment of text block (cetner, right, left). Useful if you want to set a keyboard shortcut for selecting text alignment.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-text-align.jpg'></td></tr></table>
|
||||
|
||||
## Split text by lines
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Split%20text%20by%20lines.md
|
||||
```
|
||||
<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/Split%20text%20by%20lines.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Split lines of text into separate text elements for easier reorganization<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-split-lines.jpg'></td></tr></table>
|
||||
|
||||
## TheBrain-navigation
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/TheBrain-navigation.md
|
||||
```
|
||||
<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/TheBrain-navigation.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">An Excalidraw based graph user interface for your Vault. Requires the <a href='https://github.com/SkepticMystic/breadcrumbs'>Breadcrumbs plugin</a> to be installed and configured as well. Generates a user interface similar to that of <a href='https://TheBrain.com'>TheBrain</a>. Watch this introduction to this script on <a href='https://youtu.be/J4T5KHERH_o'>YouTube</a>.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/TheBrain.jpg'></td></tr></table>
|
||||
|
||||
## Toggle Fullscreen on Mobile
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Toggle%20Fullscreen%20on%20Mobile.md
|
||||
```
|
||||
<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/Toggle%20Fullscreen%20on%20Mobile.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Hides Obsidian workspace leaf padding and header (based on option in settings, default is "hide header" = false) which will take Excalidraw to full screen. ⚠ Note that if the header is not visible, it will be very difficult to invoke the command palette to end full screen. Only hide the header if you have a keyboard or you've practiced opening command palette!<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/ea-toggle-fullscreen.jpg'></td></tr></table>
|
||||
|
||||
## Transfer TextElements to Excalidraw markdown metadata
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Transfer%20TextElements%20to%20Excalidraw%20markdown%20metadata.md
|
||||
```
|
||||
<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/Transfer%20TextElements%20to%20Excalidraw%20markdown%20metadata.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">The script will delete the selected text elements from the canvas and will copy the text from these text elements into the Excalidraw markdown file as metadata. This means, that the text will no longer be visible in the drawing, however you will be able to search for the text in Obsidian and find the drawing containing this image.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-text-to-metadata.jpg'></td></tr></table>
|
||||
|
||||
## Zoom to Fit Selected Elements
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Zoom%20to%20Fit%20Selected%20Elements.md
|
||||
```
|
||||
<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/Zoom%20to%20Fit%20Selected%20Elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Similar to Excalidraw standard SHIFT+2 feature: Zoom to fit selected elements, but with the ability to zoom to 1000%. Inspiration: [#272](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/272)</td></tr></table>
|
||||
If you are enjoying the Excalidraw plugin then please support my work and enthusiasm by buying me a coffee on [https://ko-fi/zsolt](https://ko-fi.com/zsolt).
|
||||
|
||||
[<img src="https://user-images.githubusercontent.com/14358394/115450238-f39e8100-a21b-11eb-89d0-fa4b82cdbce8.png" class="coffee">](https://ko-fi.com/zsolt)
|
||||
|
||||
---
|
||||
|
||||
Jump ahead to the [[#List of available scripts]]
|
||||
|
||||
# Introducing Excalidraw Automate Script Engine
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/hePJcObHIso" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
Script Engine scripts are installed in the `Downloaded` subfolder of the `Excalidraw Automate script folder` specified in plugin settings.
|
||||
|
||||
In the `Command Palette` installed scripts are prefixed with `Downloaded/`, thus you can always know if you are executing a local script of your own, or one that you have downloaded from GitHub.
|
||||
|
||||
## Attention developers and hobby hackers
|
||||
<img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/hobby-programmer.svg' align='left' style='background-color:whitesmoke; width:80px; margin-right:15px; margin-bottom:10px;'/>
|
||||
If you want to modify scripts, I recommend moving them to the `Excalidraw Automate script folder` or a different subfolder under the script folder. Scripts in the `Downloaded` folder will be overwritten when you click the `Update this script` button. Note also, that at this time, I do not check if the script file has been updated on GitHub, thus the `Update this script` button is always visible once you have installed a script, not only when an update is availble (hope to build this feature in the future).
|
||||
|
||||
I would love to include your contribution in the script library. If you have a script of your own that you would like to share with the community, please open a [PR](https://github.com/zsviczian/obsidian-excalidraw-plugin/pulls) on GitHub. Be sure to include the following in your pull request
|
||||
- The [script file](https://github.com/zsviczian/obsidian-excalidraw-plugin/tree/master/ea-scripts) with a self explanetory name. The name of the file will be the name of the script in the Command Palette.
|
||||
- An [image](https://github.com/zsviczian/obsidian-excalidraw-plugin/tree/master/images) explaining the scripts purpose. Remember a picture speaks thousand words!
|
||||
- An update to this file [ea-scripts/index.md](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/index.md)
|
||||
|
||||
---
|
||||
|
||||
# List of available scripts
|
||||
- [[#Add Connector Point]]
|
||||
- [[#Add Link to Existing File and Open]]
|
||||
- [[#Add Link to New Page and Open]]
|
||||
- [[#Add Next Step in Process]]
|
||||
- [[#Box Each Selected Groups]]
|
||||
- [[#Box Selected Elements]]
|
||||
- [[#Change shape of selected elements]]
|
||||
- [[#Connect elements]]
|
||||
- [[#Convert freedraw to line]]
|
||||
- [[#Convert selected text elements to sticky notes]]
|
||||
- [[#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]]
|
||||
- [[#Elbow connectors]]
|
||||
- [[#Expand rectangles horizontally keep text centered]]
|
||||
- [[#Expand rectangles horizontally]]
|
||||
- [[#Expand rectangles vertically keep text centered]]
|
||||
- [[#Expand rectangles vertically]]
|
||||
- [[#Fixed horizontal distance between centers]]
|
||||
- [[#Fixed inner distance]]
|
||||
- [[#Fixed spacing]]
|
||||
- [[#Fixed vertical distance between centers]]
|
||||
- [[#Fixed vertical distance]]
|
||||
- [[#Lighten background color]]
|
||||
- [[Mindmap connector]]
|
||||
- [[#Modify background color opacity]]
|
||||
- [[#Normalize Selected Arrows]]
|
||||
- [[#OCR - Optical Character Recognition]]
|
||||
- [[#Organic Line]]
|
||||
- [[#Repeat Elements]]
|
||||
- [[#Reverse arrows]]
|
||||
- [[#Scribble Helper]]
|
||||
- [[#Select Elements of Type]]
|
||||
- [[#Set background color of unclosed line object by adding a shadow clone]]
|
||||
- [[#Set Dimensions]]
|
||||
- [[#Set Font Family]]
|
||||
- [[#Set Grid]]
|
||||
- [[#Set Link Alias]]
|
||||
- [[#Set Stroke Width of Selected Elements]]
|
||||
- [[#Set Text Alignment]]
|
||||
- [[#Split text by lines]]
|
||||
- [[#Toggle Fullscreen on Mobile]]
|
||||
- [[#Transfer TextElements to Excalidraw markdown metadata]]
|
||||
- [[#Zoom to Fit Selected Elements]]
|
||||
|
||||
## Add Connector Point
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Add%20Connector%20Point.md
|
||||
```
|
||||
<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/Add%20Connector%20Point.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will add a small circle to the top left of each text element in the selection and add the text and the "connector point" to a group. You can use the connector points to link text elements with an arrow (in for example a Wardley Map).<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-bullet-point.jpg'></td></tr></table>
|
||||
|
||||
## Add Link to Existing File and Open
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Add%20Link%20to%20Existing%20File%20and%20Open.md
|
||||
```
|
||||
<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/Add%20Link%20to%20Existing%20File%20and%20Open.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Prompts for a file from the vault. Adds a link to the selected element pointing to the selected file. You can control in settings to open the file in the current active pane or an adjacent pane.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-add-link-and-open.jpg'></td></tr></table>
|
||||
|
||||
## Add Link to New Page and Open
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Add%20Link%20to%20New%20Page%20and%20Open.md
|
||||
```
|
||||
<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/Add%20Link%20to%20New%20Page%20and%20Open.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Prompts for filename. Offers option to create and open a new Markdown or Excalidraw document. Adds link pointing to the new file, to the selected objects in the drawing. You can control in settings to open the file in the current active pane or an adjacent pane.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-add-link-to-new-page-and-pen.jpg'></td></tr></table>
|
||||
|
||||
## Add Next Step in Process
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Add%20Next%20Step%20in%20Process.md
|
||||
```
|
||||
<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/Add%20Next%20Step%20in%20Process.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will prompt you for the title of the process step, then will create a stick note with the text. If an element is selected then the script will connect this new step with an arrow to the previous step (the selected element). If no element is selected, then the script assumes this is the first step in the process and will only output the sticky note with the text that was entered.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-add-process-step.jpg'></td></tr></table>
|
||||
|
||||
## 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
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Box%20Selected%20Elements.md
|
||||
```
|
||||
<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/Box%20Selected%20Elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will add an encapsulating box around the currently selected elements in Excalidraw.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-box-elements.jpg'></td></tr></table>
|
||||
|
||||
## Change shape of selected elements
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Change%20shape%20of%20selected%20elements.md
|
||||
```
|
||||
<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/Change%20shape%20of%20selected%20elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">The script allows you to change the shape of selected Rectangles, Diamonds and Ellipses.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-change-shape.jpg'></td></tr></table>
|
||||
|
||||
## Connect elements
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Connect%20elements.md
|
||||
```
|
||||
<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/Connect%20elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">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).<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-connect-elements.jpg'></td></tr></table>
|
||||
|
||||
## Convert freedraw to line
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Convert%20freedraw%20to%20line.md
|
||||
```
|
||||
<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%20freedraw%20to%20line.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Convert selected freedraw objects into editable lines. This will allow you to adjust your drawings by dragging line points and will also allow you to select shape fill in case of enclosed lines. You can adjust conversion point density in settings.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-convert-freedraw-to-line.jpg'></td></tr></table>
|
||||
|
||||
## Convert selected text elements to sticky notes
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Convert%20selected%20text%20elements%20to%20sticky%20notes.md
|
||||
```
|
||||
<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%20selected%20text%20elements%20to%20sticky%20notes.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Converts selected plain text elements to sticky notes with transparent background and transparent stroke color (default setting, can be changed in plugin settings). Essentially converts text element into a wrappable format.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-textelement-to-transparent-stickynote.png'></td></tr></table>
|
||||
|
||||
## Convert text to link with folder and alias
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Convert%20text%20to%20link%20with%20folder%20and%20alias.md
|
||||
```
|
||||
<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
|
||||
```
|
||||
<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/Create%20new%20markdown%20file%20and%20embed%20into%20active%20drawing.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">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.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-create-and-embed-new-markdown-file.jpg'></td></tr></table>
|
||||
|
||||
## Darken background color
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Darken%20background%20color.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/Darken%20background%20color.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">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.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/darken-lighten-background-color.png'></td></tr></table>
|
||||
|
||||
## Elbow connectors
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Elbow%20connectors.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/Elbow%20connectors.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script converts the selected connectors to elbows.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/elbow-connectors.png'></td></tr></table>
|
||||
|
||||
## Expand rectangles horizontally keep text centered
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Expand%20rectangles%20horizontally%20keep%20text%20centered.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/Expand%20rectangles%20horizontally%20keep%20text%20centered.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script expands the width of the selected rectangles until they are all the same width and keep the text centered.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif'></td></tr></table>
|
||||
|
||||
## Expand rectangles horizontally
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Expand%20rectangles%20horizontally.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/Expand%20rectangles%20horizontally.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script expands the width of the selected rectangles until they are all the same width.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif'></td></tr></table>
|
||||
|
||||
## Expand rectangles vertically keep text centered
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Expand%20rectangles%20vertically%20keep%20text%20centered.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/Expand%20rectangles%20vertically%20keep%20text%20centered.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script expands the height of the selected rectangles until they are all the same height and keep the text centered.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif'></td></tr></table>
|
||||
|
||||
## Expand rectangles vertically
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Expand%20rectangles%20vertically.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/Expand%20rectangles%20vertically.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script expands the height of the selected rectangles until they are all the same height.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-expand-rectangles.gif'></td></tr></table>
|
||||
|
||||
## Fixed horizontal distance between centers
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Fixed%20horizontal%20distance%20between%20centers.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/Fixed%20horizontal%20distance%20between%20centers.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script arranges the selected elements horizontally with a fixed center spacing.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-fixed-horizontal-distance-between-centers.png'></td></tr></table>
|
||||
|
||||
## Fixed inner distance
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Fixed%20inner%20distance.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/Fixed%20inner%20distance.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script arranges selected elements and groups with a fixed inner distance.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-fixed-inner-distance.png'></td></tr></table>
|
||||
|
||||
## Fixed spacing
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Fixed%20spacing.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/Fixed%20spacing.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">The script arranges the selected elements horizontally with a fixed spacing. When we create an architecture diagram or mind map, we often need to arrange a large number of elements in a fixed spacing. `Fixed spacing` and `Fixed vertical Distance` scripts can save us a lot of time.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-fix-space-demo.png'></td></tr></table>
|
||||
|
||||
## Fixed vertical distance between centers
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Fixed%20vertical%20distance%20between%20centers.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/Fixed%20vertical%20distance%20between%20centers.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script arranges the selected elements vertically with a fixed center spacing.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-fixed-vertical-distance-between-centers.png'></td></tr></table>
|
||||
|
||||
## Fixed vertical distance
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Fixed%20vertical%20distance.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/Fixed%20vertical%20distance.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">The script arranges the selected elements vertically with a fixed spacing. When we create an architecture diagram or mind map, we often need to arrange a large number of elements in a fixed spacing. `Fixed spacing` and `Fixed vertical Distance` scripts can save us a lot of time.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-fixed-vertical-distance.png'></td></tr></table>
|
||||
|
||||
## Lighten background color
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Lighten%20background%20color.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/Lighten%20background%20color.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script lightens 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.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/darken-lighten-background-color.png'></td></tr></table>
|
||||
|
||||
## Mindmap connector
|
||||
```excalidraw-script-install
|
||||
https://github.com/xllowl/obsidian-excalidraw-plugin/blob/master/ea-scripts/Mindmap%20connector.md
|
||||
```
|
||||
<table><tr valign='top'><td class="label">Author</td><td class="data"><a href='https://github.com/xllowl'>@xllowl</a></td></tr><tr valign='top'><td class="label">Source</td><td class="data"><a href='https://github.com/xllowl/obsidian-excalidraw-plugin/blob/master/ea-scripts/Mindmap%20connector.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script creates mindmap like lines(only right side available). The line will starts according to the creation time of the elements. So you may need to create the header element first.<br><img src='https://github.com/xllowl/obsidian-excalidraw-plugin/blob/master/images/mindmap%20connector.png'></td></tr></table>
|
||||
|
||||
## Modify background color opacity
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Modify%20background%20color%20opacity.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/Modify%20background%20color%20opacity.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script changes the opacity of the background color of the selected boxes. The default background color in Excalidraw is so dark that the text is hard to read. You can lighten the color a bit by setting transparency. And you can tweak the transparency over and over again until you're happy with it. Although excalidraw has the opacity option in its native property Settings, it also changes the transparency of the border. Use this script to change only the opacity of the background color without affecting the border.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-modify-background-color-opacity.png'></td></tr></table>
|
||||
|
||||
## Normalize Selected Arrows
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Normalize%20Selected%20Arrows.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/Normalize%20Selected%20Arrows.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will reset the start and end positions of the selected arrows. The arrow will point to the center of the connected box and will have a gap of 8px from the box.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-normalize-selected-arrows.png'></td></tr></table>
|
||||
|
||||
## OCR - Optical Character Recognition
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/OCR%20-%20Optical%20Character%20Recognition.md
|
||||
```
|
||||
<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/OCR%20-%20Optical%20Character%20Recognition.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">REQUIRES EXCALIDRAW 1.5.15<br>The script will 1) send the selected image file to [taskbone.com](https://taskbone.com) to exctract the text from the image, and 2) will add the text to your drawing as a text element.<br><mark>⚠ Note that you will need to manually paste your token into the script after the first run! ⚠</mark><br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-ocr.jpg'><br><iframe width="560" height="315" src="https://www.youtube.com/embed/W2NMzR8s4eE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></td></tr></table>
|
||||
|
||||
## Organic Line
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Organic%20Line.md
|
||||
```
|
||||
<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/Organic%20Line.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Converts selected freedraw lines such that pencil pressure will decrease from maximum to minimum from the beginning of the line to its end. The resulting line is placed at the back of the layers, under all other items. Helpful when drawing organic mindmaps.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-organic-line.jpg'></td></tr></table>
|
||||
|
||||
## Repeat Elements
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Repeat%20Elements.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/Repeat%20Elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will detect the difference between 2 selected elements, including position, size, angle, stroke and background color, and create several elements that repeat these differences based on the number of repetitions entered by the user.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-repeat-elements.png'></td></tr></table>
|
||||
|
||||
## Reverse arrows
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Reverse%20arrows.md
|
||||
```
|
||||
<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/Reverse%20arrows.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Reverse the direction of **arrows** within the scope of selected elements.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-reverse-arrow.jpg'></td></tr></table>
|
||||
|
||||
## Scribble Helper
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Scribble%20Helper.md
|
||||
```
|
||||
<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/Scribble%20Helper.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">iOS scribble helper for better handwriting experience with text elements. If no elements are selected then the creates a text element at pointer position and you can use the edit box to modify the text with scribble. If a text element is selected then opens the input prompt where you can modify this text with scribble.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-scribble-helper.jpg'></td></tr></table>
|
||||
|
||||
## Select Elements of Type
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Select%20Elements%20of%20Type.md
|
||||
```
|
||||
<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/Select%20Elements%20of%20Type.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Prompts you with a list of the different element types in the active image. Only elements of the selected type will be selected on the canvas. If nothing is selected when running the script, then the script will process all the elements on the canvas. If some elements are selected when the script is executed, then the script will only process the selected elements.<br>The script is useful when, for example, you want to bring to front all the arrows, or want to change the color of all the text elements, etc.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-select-element-of-type.jpg'></td></tr></table>
|
||||
|
||||
## Set background color of unclosed line object by adding a shadow clone
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20background%20color%20of%20unclosed%20line%20object%20by%20adding%20a%20shadow%20clone.md
|
||||
```
|
||||
<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/Set%20background%20color%20of%20unclosed%20line%20object%20by%20adding%20a%20shadow%20clone.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Use this script to set the background color of unclosed (i.e. open) line objects by creating a clone of the object. The script will set the stroke color of the clone to transparent and will add a straight line to close the object. Use settings to define the default background color, the fill style, and the strokeWidth of the clone. By default the clone will be grouped with the original object, you can disable this also in settings.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-set-background-color-of-unclosed-line.jpg'></td></tr></table>
|
||||
|
||||
## Set Dimensions
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Dimensions.md
|
||||
```
|
||||
<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/Set%20Dimensions.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">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.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-dimensions.jpg'></td></tr></table>
|
||||
|
||||
## Set Font Family
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Font%20Family.md
|
||||
```
|
||||
<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/Set%20Font%20Family.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Sets font family of the text block (Virgil, Helvetica, Cascadia). Useful if you want to set a keyboard shortcut for selecting font family.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-font-family.jpg'></td></tr></table>
|
||||
|
||||
## Set Grid
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Grid.md
|
||||
```
|
||||
<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/Set%20Grid.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">The default grid size in Excalidraw is 20. Currently there is no way to change the grid size via the user interface. This script offers a way to bridge this gap.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-grid.jpg'></td></tr></table>
|
||||
|
||||
## Set Link Alias
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Link%20Alias.md
|
||||
```
|
||||
<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/Set%20Link%20Alias.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Iterates all of the links in the selected TextElements and prompts the user to set or modify the alias for each link found.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-set-link-alias.jpg'></td></tr></table>
|
||||
|
||||
## Set Stroke Width of Selected Elements
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Stroke%20Width%20of%20Selected%20Elements.md
|
||||
```
|
||||
<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/Set%20Stroke%20Width%20of%20Selected%20Elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will set the stroke width of selected elements. This is helpful, for example, when you scale freedraw sketches and want to reduce or increase their line width.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-stroke-width.jpg'></td></tr></table>
|
||||
|
||||
## Set Text Alignment
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Text%20Alignment.md
|
||||
```
|
||||
<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/Set%20Text%20Alignment.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Sets text alignment of text block (cetner, right, left). Useful if you want to set a keyboard shortcut for selecting text alignment.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-text-align.jpg'></td></tr></table>
|
||||
|
||||
## Split text by lines
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Split%20text%20by%20lines.md
|
||||
```
|
||||
<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/Split%20text%20by%20lines.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Split lines of text into separate text elements for easier reorganization<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-split-lines.jpg'></td></tr></table>
|
||||
|
||||
## TheBrain-navigation
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/TheBrain-navigation.md
|
||||
```
|
||||
<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/TheBrain-navigation.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">An Excalidraw based graph user interface for your Vault. Requires the <a href='https://github.com/SkepticMystic/breadcrumbs'>Breadcrumbs plugin</a> to be installed and configured as well. Generates a user interface similar to that of <a href='https://TheBrain.com'>TheBrain</a>. Watch this introduction to this script on <a href='https://youtu.be/J4T5KHERH_o'>YouTube</a>.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/TheBrain.jpg'></td></tr></table>
|
||||
|
||||
## Toggle Fullscreen on Mobile
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Toggle%20Fullscreen%20on%20Mobile.md
|
||||
```
|
||||
<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/Toggle%20Fullscreen%20on%20Mobile.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Hides Obsidian workspace leaf padding and header (based on option in settings, default is "hide header" = false) which will take Excalidraw to full screen. ⚠ Note that if the header is not visible, it will be very difficult to invoke the command palette to end full screen. Only hide the header if you have a keyboard or you've practiced opening command palette!<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/ea-toggle-fullscreen.jpg'></td></tr></table>
|
||||
|
||||
## Transfer TextElements to Excalidraw markdown metadata
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Transfer%20TextElements%20to%20Excalidraw%20markdown%20metadata.md
|
||||
```
|
||||
<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/Transfer%20TextElements%20to%20Excalidraw%20markdown%20metadata.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">The script will delete the selected text elements from the canvas and will copy the text from these text elements into the Excalidraw markdown file as metadata. This means, that the text will no longer be visible in the drawing, however you will be able to search for the text in Obsidian and find the drawing containing this image.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-text-to-metadata.jpg'></td></tr></table>
|
||||
|
||||
## Zoom to Fit Selected Elements
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Zoom%20to%20Fit%20Selected%20Elements.md
|
||||
```
|
||||
<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/Zoom%20to%20Fit%20Selected%20Elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Similar to Excalidraw standard <kbd>SHIFT+2</kbd> feature: Zoom to fit selected elements, but with the ability to zoom to 1000%. Inspiration: [#272](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/272)</td></tr></table>
|
||||
407
ea-scripts/Auto Layout.md
Normal file
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
|
||||

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

|
||||
|
||||
This script performs automatic layout for the selected top-level grouping objects. It is powered by [elkjs](https://github.com/kieler/elkjs) and needs to be connected to the Internet.
|
||||
|
||||
|
||||
See documentation for more details:
|
||||
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
|
||||
|
||||
```javascript
|
||||
*/
|
||||
|
||||
if (
|
||||
!ea.verifyMinimumPluginVersion ||
|
||||
!ea.verifyMinimumPluginVersion("1.5.21")
|
||||
) {
|
||||
new Notice(
|
||||
"This script requires a newer version of Excalidraw. Please install the latest version."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
settings = ea.getScriptSettings();
|
||||
//set default values on first run
|
||||
if (!settings["Layout Options JSON"]) {
|
||||
settings = {
|
||||
"Layout Options JSON": {
|
||||
height: "450px",
|
||||
value: `{\n "org.eclipse.elk.layered.crossingMinimization.semiInteractive": "true",\n "org.eclipse.elk.layered.considerModelOrder.components": "FORCE_MODEL_ORDER"\n}`,
|
||||
description: `You can use layout options to configure the layout algorithm. A list of all options and further details of their exact effects is available in <a href="http://www.eclipse.org/elk/reference.html" rel="nofollow">ELK's documentation</a>.`,
|
||||
},
|
||||
};
|
||||
ea.setScriptSettings(settings);
|
||||
}
|
||||
|
||||
if (typeof ELK === "undefined") {
|
||||
loadELK(doAutoLayout);
|
||||
} else {
|
||||
doAutoLayout();
|
||||
}
|
||||
|
||||
async function doAutoLayout() {
|
||||
const selectedElements = ea.getViewSelectedElements();
|
||||
const groups = ea
|
||||
.getMaximumGroups(selectedElements)
|
||||
.map((g) => g.filter((el) => el.containerId == null)) // ignore text in stickynote
|
||||
.filter((els) => els.length > 0);
|
||||
|
||||
const stickynotesMap = selectedElements
|
||||
.filter((el) => el.containerId != null)
|
||||
.reduce((result, el) => {
|
||||
result.set(el.containerId, el);
|
||||
return result;
|
||||
}, new Map());
|
||||
|
||||
const elk = new ELK();
|
||||
const knownLayoutAlgorithms = await elk.knownLayoutAlgorithms();
|
||||
const layoutAlgorithms = knownLayoutAlgorithms
|
||||
.map((knownLayoutAlgorithm) => ({
|
||||
id: knownLayoutAlgorithm.id,
|
||||
displayText:
|
||||
knownLayoutAlgorithm.id === "org.eclipse.elk.layered" ||
|
||||
knownLayoutAlgorithm.id === "org.eclipse.elk.radial" ||
|
||||
knownLayoutAlgorithm.id === "org.eclipse.elk.mrtree"
|
||||
? "* " +
|
||||
knownLayoutAlgorithm.name +
|
||||
": " +
|
||||
knownLayoutAlgorithm.description
|
||||
: knownLayoutAlgorithm.name + ": " + knownLayoutAlgorithm.description,
|
||||
}))
|
||||
.sort((lha, rha) => lha.displayText.localeCompare(rha.displayText));
|
||||
|
||||
const layoutAlgorithmsSimple = knownLayoutAlgorithms
|
||||
.map((knownLayoutAlgorithm) => ({
|
||||
id: knownLayoutAlgorithm.id,
|
||||
displayText:
|
||||
knownLayoutAlgorithm.id === "org.eclipse.elk.layered" ||
|
||||
knownLayoutAlgorithm.id === "org.eclipse.elk.radial" ||
|
||||
knownLayoutAlgorithm.id === "org.eclipse.elk.mrtree"
|
||||
? "* " + knownLayoutAlgorithm.name
|
||||
: knownLayoutAlgorithm.name,
|
||||
}))
|
||||
.sort((lha, rha) => lha.displayText.localeCompare(rha.displayText));
|
||||
|
||||
// const knownOptions = knownLayoutAlgorithms
|
||||
// .reduce(
|
||||
// (result, knownLayoutAlgorithm) => [
|
||||
// ...result,
|
||||
// ...knownLayoutAlgorithm.knownOptions,
|
||||
// ],
|
||||
// []
|
||||
// )
|
||||
// .filter((value, index, self) => self.indexOf(value) === index) // remove duplicates
|
||||
// .sort((lha, rha) => lha.localeCompare(rha));
|
||||
// console.log("knownOptions", knownOptions);
|
||||
|
||||
const selectedAlgorithm = await utils.suggester(
|
||||
layoutAlgorithms.map((algorithmInfo) => algorithmInfo.displayText),
|
||||
layoutAlgorithms.map((algorithmInfo) => algorithmInfo.id),
|
||||
"Layout algorithm"
|
||||
);
|
||||
|
||||
const knownNodePlacementStrategy = [
|
||||
"SIMPLE",
|
||||
"INTERACTIVE",
|
||||
"LINEAR_SEGMENTS",
|
||||
"BRANDES_KOEPF",
|
||||
"NETWORK_SIMPLEX",
|
||||
];
|
||||
|
||||
const knownDirections = [
|
||||
"UNDEFINED",
|
||||
"RIGHT",
|
||||
"LEFT",
|
||||
"DOWN",
|
||||
"UP"
|
||||
];
|
||||
|
||||
let nodePlacementStrategy = "BRANDES_KOEPF";
|
||||
let componentComponentSpacing = "10";
|
||||
let nodeNodeSpacing = "100";
|
||||
let nodeNodeBetweenLayersSpacing = "100";
|
||||
let discoComponentLayoutAlgorithm = "org.eclipse.elk.layered";
|
||||
let direction = "UNDEFINED";
|
||||
|
||||
if (selectedAlgorithm === "org.eclipse.elk.layered") {
|
||||
nodePlacementStrategy = await utils.suggester(
|
||||
knownNodePlacementStrategy,
|
||||
knownNodePlacementStrategy,
|
||||
"Node placement strategy"
|
||||
);
|
||||
|
||||
selectedDirection = await utils.suggester(
|
||||
knownDirections,
|
||||
knownDirections,
|
||||
"Direction"
|
||||
);
|
||||
direction = selectedDirection??"UNDEFINED";
|
||||
} else if (selectedAlgorithm === "org.eclipse.elk.disco") {
|
||||
const componentLayoutAlgorithms = layoutAlgorithmsSimple.filter(al => al.id !== "org.eclipse.elk.disco");
|
||||
const selectedDiscoComponentLayoutAlgorithm = await utils.suggester(
|
||||
componentLayoutAlgorithms.map((algorithmInfo) => algorithmInfo.displayText),
|
||||
componentLayoutAlgorithms.map((algorithmInfo) => algorithmInfo.id),
|
||||
"Disco Connected Components Layout Algorithm"
|
||||
);
|
||||
discoComponentLayoutAlgorithm = selectedDiscoComponentLayoutAlgorithm??"org.eclipse.elk.layered";
|
||||
}
|
||||
|
||||
if (
|
||||
selectedAlgorithm === "org.eclipse.elk.box" ||
|
||||
selectedAlgorithm === "org.eclipse.elk.rectpacking"
|
||||
) {
|
||||
nodeNodeSpacing = await utils.inputPrompt("Node Spacing", "number", "10");
|
||||
} else {
|
||||
let userSpacingStr = await utils.inputPrompt(
|
||||
"Components Spacing, Node Spacing, Node Node Between Layers Spacing",
|
||||
"number, number, number",
|
||||
"10, 100, 100"
|
||||
);
|
||||
let userSpacingArr = (userSpacingStr??"").split(",");
|
||||
componentComponentSpacing = userSpacingArr[0] ?? "10";
|
||||
nodeNodeSpacing = userSpacingArr[1] ?? "100";
|
||||
nodeNodeBetweenLayersSpacing = userSpacingArr[2] ?? "100";
|
||||
}
|
||||
|
||||
let layoutOptionsJson = {};
|
||||
try {
|
||||
layoutOptionsJson = JSON.parse(settings["Layout Options JSON"].value);
|
||||
} catch (e) {
|
||||
new Notice(
|
||||
"Error reading Layout Options JSON, see developer console for more information",
|
||||
4000
|
||||
);
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
layoutOptionsJson["elk.algorithm"] = selectedAlgorithm;
|
||||
layoutOptionsJson["org.eclipse.elk.spacing.componentComponent"] =
|
||||
componentComponentSpacing;
|
||||
layoutOptionsJson["org.eclipse.elk.spacing.nodeNode"] = nodeNodeSpacing;
|
||||
layoutOptionsJson["org.eclipse.elk.layered.spacing.nodeNodeBetweenLayers"] =
|
||||
nodeNodeBetweenLayersSpacing;
|
||||
layoutOptionsJson["org.eclipse.elk.layered.nodePlacement.strategy"] =
|
||||
nodePlacementStrategy;
|
||||
layoutOptionsJson["org.eclipse.elk.disco.componentCompaction.componentLayoutAlgorithm"] =
|
||||
discoComponentLayoutAlgorithm;
|
||||
layoutOptionsJson["org.eclipse.elk.direction"] = direction;
|
||||
|
||||
const graph = {
|
||||
id: "root",
|
||||
layoutOptions: layoutOptionsJson,
|
||||
children: [],
|
||||
edges: [],
|
||||
};
|
||||
|
||||
let groupMap = new Map();
|
||||
let targetElkMap = new Map();
|
||||
let arrowEls = [];
|
||||
|
||||
for (let i = 0; i < groups.length; i++) {
|
||||
const elements = groups[i];
|
||||
if (
|
||||
elements.length === 1 &&
|
||||
(elements[0].type === "arrow" || elements[0].type === "line")
|
||||
) {
|
||||
if (
|
||||
elements[0].type === "arrow" &&
|
||||
elements[0].startBinding &&
|
||||
elements[0].endBinding
|
||||
) {
|
||||
arrowEls.push(elements[0]);
|
||||
}
|
||||
} else {
|
||||
let elkId = "g" + i;
|
||||
elements.reduce((result, el) => {
|
||||
result.set(el.id, elkId);
|
||||
return result;
|
||||
}, targetElkMap);
|
||||
|
||||
const box = ea.getBoundingBox(elements);
|
||||
groupMap.set(elkId, {
|
||||
elements: elements,
|
||||
boundingBox: box,
|
||||
});
|
||||
|
||||
graph.children.push({
|
||||
id: elkId,
|
||||
width: box.width,
|
||||
height: box.height,
|
||||
x: box.topX,
|
||||
y: box.topY,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < arrowEls.length; i++) {
|
||||
const arrowEl = arrowEls[i];
|
||||
const startElkId = targetElkMap.get(arrowEl.startBinding.elementId);
|
||||
const endElkId = targetElkMap.get(arrowEl.endBinding.elementId);
|
||||
|
||||
graph.edges.push({
|
||||
id: "e" + i,
|
||||
sources: [startElkId],
|
||||
targets: [endElkId],
|
||||
});
|
||||
}
|
||||
|
||||
const initTopX =
|
||||
Math.min(...Array.from(groupMap.values()).map((v) => v.boundingBox.topX)) -
|
||||
12;
|
||||
const initTopY =
|
||||
Math.min(...Array.from(groupMap.values()).map((v) => v.boundingBox.topY)) -
|
||||
12;
|
||||
|
||||
elk
|
||||
.layout(graph)
|
||||
.then((resultGraph) => {
|
||||
for (const elkEl of resultGraph.children) {
|
||||
const group = groupMap.get(elkEl.id);
|
||||
for (const groupEl of group.elements) {
|
||||
const originalDistancX = groupEl.x - group.boundingBox.topX;
|
||||
const originalDistancY = groupEl.y - group.boundingBox.topY;
|
||||
const groupElDistanceX =
|
||||
elkEl.x + initTopX + originalDistancX - groupEl.x;
|
||||
const groupElDistanceY =
|
||||
elkEl.y + initTopY + originalDistancY - groupEl.y;
|
||||
|
||||
groupEl.x = groupEl.x + groupElDistanceX;
|
||||
groupEl.y = groupEl.y + groupElDistanceY;
|
||||
|
||||
if (stickynotesMap.has(groupEl.id)) {
|
||||
const stickynote = stickynotesMap.get(groupEl.id);
|
||||
stickynote.x = stickynote.x + groupElDistanceX;
|
||||
stickynote.y = stickynote.y + groupElDistanceY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ea.copyViewElementsToEAforEditing(selectedElements);
|
||||
ea.addElementsToView(false, false);
|
||||
|
||||
normalizeSelectedArrows();
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
|
||||
function loadELK(doAfterLoaded) {
|
||||
let script = document.createElement("script");
|
||||
script.onload = function () {
|
||||
if (typeof ELK !== "undefined") {
|
||||
doAfterLoaded();
|
||||
}
|
||||
};
|
||||
script.src =
|
||||
"https://cdn.jsdelivr.net/npm/elkjs@0.8.2/lib/elk.bundled.min.js";
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
/*
|
||||
* Normalize Selected Arrows
|
||||
*/
|
||||
|
||||
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 allElements = ea.getViewElements();
|
||||
for (const arrow of selectedIndividualArrows) {
|
||||
const startBindingEl = allElements.filter(
|
||||
(el) => el.id === (arrow.startBinding || {}).elementId
|
||||
)[0];
|
||||
const endBindingEl = allElements.filter(
|
||||
(el) => el.id === (arrow.endBinding || {}).elementId
|
||||
)[0];
|
||||
|
||||
if (startBindingEl) {
|
||||
recalculateStartPointOfLine(
|
||||
arrow,
|
||||
startBindingEl,
|
||||
endBindingEl,
|
||||
gapValue
|
||||
);
|
||||
}
|
||||
if (endBindingEl) {
|
||||
recalculateEndPointOfLine(arrow, endBindingEl, startBindingEl, gapValue);
|
||||
}
|
||||
}
|
||||
|
||||
ea.copyViewElementsToEAforEditing(selectedIndividualArrows);
|
||||
ea.addElementsToView(false, false);
|
||||
}
|
||||
|
||||
function recalculateStartPointOfLine(line, el, elB, gapValue) {
|
||||
const aX = el.x + el.width / 2;
|
||||
const bX =
|
||||
line.points.length <= 2 && elB
|
||||
? elB.x + elB.width / 2
|
||||
: line.x + line.points[1][0];
|
||||
const aY = el.y + el.height / 2;
|
||||
const bY =
|
||||
line.points.length <= 2 && elB
|
||||
? elB.y + elB.height / 2
|
||||
: line.y + line.points[1][1];
|
||||
|
||||
line.startBinding.gap = gapValue;
|
||||
line.startBinding.focus = 0;
|
||||
const intersectA = ea.intersectElementWithLine(
|
||||
el,
|
||||
[bX, bY],
|
||||
[aX, aY],
|
||||
line.startBinding.gap
|
||||
);
|
||||
|
||||
if (intersectA.length > 0) {
|
||||
line.points[0] = [0, 0];
|
||||
for (let i = 1; i < line.points.length; i++) {
|
||||
line.points[i][0] -= intersectA[0][0] - line.x;
|
||||
line.points[i][1] -= intersectA[0][1] - line.y;
|
||||
}
|
||||
line.x = intersectA[0][0];
|
||||
line.y = intersectA[0][1];
|
||||
}
|
||||
}
|
||||
|
||||
function recalculateEndPointOfLine(line, el, elB, gapValue) {
|
||||
const aX = el.x + el.width / 2;
|
||||
const bX =
|
||||
line.points.length <= 2 && elB
|
||||
? elB.x + elB.width / 2
|
||||
: line.x + line.points[line.points.length - 2][0];
|
||||
const aY = el.y + el.height / 2;
|
||||
const bY =
|
||||
line.points.length <= 2 && elB
|
||||
? elB.y + elB.height / 2
|
||||
: line.y + line.points[line.points.length - 2][1];
|
||||
|
||||
line.endBinding.gap = gapValue;
|
||||
line.endBinding.focus = 0;
|
||||
const intersectA = ea.intersectElementWithLine(
|
||||
el,
|
||||
[bX, bY],
|
||||
[aX, aY],
|
||||
line.endBinding.gap
|
||||
);
|
||||
|
||||
if (intersectA.length > 0) {
|
||||
line.points[line.points.length - 1] = [
|
||||
intersectA[0][0] - line.x,
|
||||
intersectA[0][1] - line.y,
|
||||
];
|
||||
}
|
||||
}
|
||||
1
ea-scripts/Auto Layout.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1670131481615" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3504" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M947.2 0H76.8C33.6 0 0 33.6 0 76.8v870.4C0 990.4 33.6 1024 76.8 1024h870.4c38.4 0 72-30.4 76.8-68.8V76.8C1024 33.6 990.4 0 947.2 0zM84.8 84.8h852.8V256H84.8V84.8z m256 256h596.8v256H340.8v-256z m-256 598.4V340.8H256v596.8H84.8z m256 0v-256h596.8v256H340.8z" p-id="3505"></path></svg>
|
||||
|
After Width: | Height: | Size: 616 B |
@@ -1,10 +1,13 @@
|
||||
/*
|
||||

|
||||
|
||||
The script allows you to change the shape of selected Rectangles, Diamonds and Ellipses.
|
||||
The script allows you to change the shape and fill style of selected Rectangles, Diamonds, Ellipses, Lines, Arrows and Freedraw.
|
||||
|
||||
```javascript
|
||||
*/
|
||||
const fillStylesDispaly=["Dots (⚠ VERY SLOW performance on large objects!)","Zigzag","Zigzag-line", "Dashed", "Hachure", "Cross-hatch", "Solid"];
|
||||
const fillStyles=["dots","zigzag","zigzag-line", "dashed", "hachure", "cross-hatch", "solid"];
|
||||
const fillShapes=["ellipse","rectangle","diamond", "freedraw", "line"];
|
||||
const boxShapesDispaly=["○ ellipse","□ rectangle","◇ diamond"];
|
||||
const boxShapes=["ellipse","rectangle","diamond"];
|
||||
const lineShapesDispaly=["- line","⭢ arrow"];
|
||||
@@ -14,18 +17,27 @@ let editedElements = [];
|
||||
|
||||
let elements = ea.getViewSelectedElements().filter(el=>boxShapes.contains(el.type));
|
||||
if (elements.length>0) {
|
||||
newShape = await utils.suggester(boxShapesDispaly, boxShapes, "Change shape of 'box' type elements in selection");
|
||||
newShape = await utils.suggester(boxShapesDispaly, boxShapes, "Change shape of 'box' type elements in selection, press ESC to skip");
|
||||
if(newShape) {
|
||||
editedElements = elements;
|
||||
elements.forEach(el=>el.type = newShape);
|
||||
}
|
||||
}
|
||||
|
||||
elements = ea.getViewSelectedElements().filter(el=>fillShapes.contains(el.type));
|
||||
if (elements.length>0) {
|
||||
newFillStyle = await utils.suggester(fillStylesDispaly, fillStyles, "Change the fill style of elements in selection, press ESC to skip");
|
||||
if(newFillStyle) {
|
||||
editedElements = editedElements.concat(elements.filter(e=>!editedElements.some(el=>el.id===e.id)));
|
||||
elements.forEach(el=>el.fillStyle = newFillStyle);
|
||||
}
|
||||
}
|
||||
|
||||
elements = ea.getViewSelectedElements().filter(el=>lineShapes.contains(el.type));
|
||||
if (elements.length>0) {
|
||||
newShape = await utils.suggester(lineShapesDispaly, lineShapes, "Change shape of 'line' type elements in selection");
|
||||
newShape = await utils.suggester(lineShapesDispaly, lineShapes, "Change shape of 'line' type elements in selection, press ESC to skip");
|
||||
if(newShape) {
|
||||
editedElements = editedElements.concat(elements);
|
||||
editedElements = editedElements.concat(elements.filter(e=>!editedElements.some(el=>el.id===e.id)));
|
||||
elements.forEach((el)=>{
|
||||
el.type = newShape;
|
||||
if(newShape === "arrow") {
|
||||
@@ -37,4 +49,4 @@ if (elements.length>0) {
|
||||
|
||||
ea.copyViewElementsToEAforEditing(editedElements);
|
||||
|
||||
ea.addElementsToView(false,false);
|
||||
ea.addElementsToView(false,false);
|
||||
|
||||
@@ -9,8 +9,7 @@ if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.5.21")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
settings = ea.getScriptSettings();
|
||||
let settings = ea.getScriptSettings();
|
||||
//set default values on first run
|
||||
if(!settings["Border color"]) {
|
||||
settings = {
|
||||
@@ -28,27 +27,44 @@ if(!settings["Border color"]) {
|
||||
valueset: ["hachure","cross-hatch","solid"]
|
||||
}
|
||||
};
|
||||
ea.setScriptSettings(settings);
|
||||
await ea.setScriptSettings(settings);
|
||||
}
|
||||
|
||||
if(!settings["Max sticky note width"]) {
|
||||
settings["Max sticky note width"] = {
|
||||
value: "600",
|
||||
description: "Maximum width of new sticky note. If text is longer, it will be wrapped",
|
||||
valueset: ["400","600","800","1000","1200","1400","2000"]
|
||||
}
|
||||
await ea.setScriptSettings(settings);
|
||||
}
|
||||
const maxWidth = parseInt(settings["Max sticky note width"].value);
|
||||
const strokeColor = settings["Border color"].value;
|
||||
const backgroundColor = settings["Background color"].value;
|
||||
const fillStyle = settings["Background fill style"].value;
|
||||
|
||||
elements = ea.getViewSelectedElements()
|
||||
.filter((el)=>(el.type==="text")&&(el.containerId===null));
|
||||
if(elements.length===0) return;
|
||||
const elements = ea
|
||||
.getViewSelectedElements()
|
||||
.filter((el)=>(el.type==="text")&&(el.containerId===null));
|
||||
if(elements.length===0) {
|
||||
new Notice("Please select a text element");
|
||||
return;
|
||||
}
|
||||
ea.style.strokeColor = strokeColor;
|
||||
ea.style.backgroundColor = backgroundColor;
|
||||
ea.style.fillStyle = fillStyle;
|
||||
const padding = 6;
|
||||
let boxes = [];
|
||||
elements.forEach((el)=>{
|
||||
const id = ea.addRect(el.x-padding,el.y-padding,el.width+2*padding,el.height+2*padding);
|
||||
const boxes = [];
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
ea.getElements().forEach((el)=>{
|
||||
const width = el.width+2*padding;
|
||||
const widthOK = width<=maxWidth;
|
||||
const id = ea.addRect(el.x-padding,el.y-padding,widthOK?width:maxWidth,el.height+2*padding);
|
||||
boxes.push(id);
|
||||
ea.getElement(id).boundElements=[{type:"text",id:el.id}];
|
||||
el.containerId = id;
|
||||
});
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
await ea.addElementsToView(false,false);
|
||||
ea.selectElementsInView(ea.getViewElements().filter(el=>boxes.includes(el.id)));
|
||||
await ea.addElementsToView(false,true);
|
||||
const containers = ea.getViewElements().filter(el=>boxes.includes(el.id));
|
||||
ea.getExcalidrawAPI().updateContainerSize(containers);
|
||||
ea.selectElementsInView(containers);
|
||||
@@ -16,274 +16,37 @@ The color conversion method was copied from [color-convert](https://github.com/Q
|
||||
```javascript
|
||||
*/
|
||||
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.7.19")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
let settings = ea.getScriptSettings();
|
||||
//set default values on first run
|
||||
if(!settings["Step size"]) {
|
||||
settings = {
|
||||
"Step size" : {
|
||||
value: 2,
|
||||
description: "Step size in percentage for making the color darker"
|
||||
}
|
||||
};
|
||||
ea.setScriptSettings(settings);
|
||||
}
|
||||
|
||||
const step = settings["Step size"].value;
|
||||
|
||||
const elements = ea
|
||||
.getViewSelectedElements()
|
||||
.filter((el) =>
|
||||
["rectangle", "ellipse", "diamond", "image", "line"].includes(el.type)
|
||||
["rectangle", "ellipse", "diamond", "image", "line", "freedraw"].includes(el.type)
|
||||
);
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
for (const el of ea.getElements()) {
|
||||
const color = colorNameToHex(el.backgroundColor);
|
||||
const rgbColor = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color);
|
||||
if (rgbColor) {
|
||||
const r = parseInt(rgbColor[1], 16);
|
||||
const g = parseInt(rgbColor[2], 16);
|
||||
const b = parseInt(rgbColor[3], 16);
|
||||
const originalRgb = [r, g, b];
|
||||
const hsl = rgbToHsl(originalRgb);
|
||||
const step = 2;
|
||||
const newLightness = hsl[2] - step;
|
||||
if (newLightness > 0) {
|
||||
hsl[2] = newLightness;
|
||||
}
|
||||
const newRgb = hslToRgb(hsl);
|
||||
el.backgroundColor = "#" + rgbToHexString(newRgb);
|
||||
const color = ea.colorNameToHex(el.backgroundColor);
|
||||
const cm = ea.getCM(color);
|
||||
if (cm) {
|
||||
const darker = cm.darkerBy(step);
|
||||
if(Math.floor(darker.lightness)>0) el.backgroundColor = darker.stringHSL();
|
||||
}
|
||||
}
|
||||
await ea.addElementsToView(false, false);
|
||||
|
||||
function rgbToHexString(args) {
|
||||
const integer =
|
||||
((Math.round(args[0]) & 0xff) << 16) +
|
||||
((Math.round(args[1]) & 0xff) << 8) +
|
||||
(Math.round(args[2]) & 0xff);
|
||||
|
||||
const string = integer.toString(16).toUpperCase();
|
||||
return "000000".substring(string.length) + string;
|
||||
}
|
||||
|
||||
function hslToRgb(hsl) {
|
||||
const h = hsl[0] / 360;
|
||||
const s = hsl[1] / 100;
|
||||
const l = hsl[2] / 100;
|
||||
let t2;
|
||||
let t3;
|
||||
let val;
|
||||
|
||||
if (s === 0) {
|
||||
val = l * 255;
|
||||
return [val, val, val];
|
||||
}
|
||||
|
||||
if (l < 0.5) {
|
||||
t2 = l * (1 + s);
|
||||
} else {
|
||||
t2 = l + s - l * s;
|
||||
}
|
||||
|
||||
const t1 = 2 * l - t2;
|
||||
|
||||
const rgb = [0, 0, 0];
|
||||
for (let i = 0; i < 3; i++) {
|
||||
t3 = h + (1 / 3) * -(i - 1);
|
||||
if (t3 < 0) {
|
||||
t3++;
|
||||
}
|
||||
|
||||
if (t3 > 1) {
|
||||
t3--;
|
||||
}
|
||||
|
||||
if (6 * t3 < 1) {
|
||||
val = t1 + (t2 - t1) * 6 * t3;
|
||||
} else if (2 * t3 < 1) {
|
||||
val = t2;
|
||||
} else if (3 * t3 < 2) {
|
||||
val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
|
||||
} else {
|
||||
val = t1;
|
||||
}
|
||||
|
||||
rgb[i] = val * 255;
|
||||
}
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
function rgbToHsl(rgb) {
|
||||
const r = rgb[0] / 255;
|
||||
const g = rgb[1] / 255;
|
||||
const b = rgb[2] / 255;
|
||||
const min = Math.min(r, g, b);
|
||||
const max = Math.max(r, g, b);
|
||||
const delta = max - min;
|
||||
let h;
|
||||
let s;
|
||||
|
||||
if (max === min) {
|
||||
h = 0;
|
||||
} else if (r === max) {
|
||||
h = (g - b) / delta;
|
||||
} else if (g === max) {
|
||||
h = 2 + (b - r) / delta;
|
||||
} else if (b === max) {
|
||||
h = 4 + (r - g) / delta;
|
||||
}
|
||||
|
||||
h = Math.min(h * 60, 360);
|
||||
|
||||
if (h < 0) {
|
||||
h += 360;
|
||||
}
|
||||
|
||||
const l = (min + max) / 2;
|
||||
|
||||
if (max === min) {
|
||||
s = 0;
|
||||
} else if (l <= 0.5) {
|
||||
s = delta / (max + min);
|
||||
} else {
|
||||
s = delta / (2 - max - min);
|
||||
}
|
||||
|
||||
return [h, s * 100, l * 100];
|
||||
}
|
||||
|
||||
function colorNameToHex(color) {
|
||||
const colors = {
|
||||
aliceblue: "#f0f8ff",
|
||||
antiquewhite: "#faebd7",
|
||||
aqua: "#00ffff",
|
||||
aquamarine: "#7fffd4",
|
||||
azure: "#f0ffff",
|
||||
beige: "#f5f5dc",
|
||||
bisque: "#ffe4c4",
|
||||
black: "#000000",
|
||||
blanchedalmond: "#ffebcd",
|
||||
blue: "#0000ff",
|
||||
blueviolet: "#8a2be2",
|
||||
brown: "#a52a2a",
|
||||
burlywood: "#deb887",
|
||||
cadetblue: "#5f9ea0",
|
||||
chartreuse: "#7fff00",
|
||||
chocolate: "#d2691e",
|
||||
coral: "#ff7f50",
|
||||
cornflowerblue: "#6495ed",
|
||||
cornsilk: "#fff8dc",
|
||||
crimson: "#dc143c",
|
||||
cyan: "#00ffff",
|
||||
darkblue: "#00008b",
|
||||
darkcyan: "#008b8b",
|
||||
darkgoldenrod: "#b8860b",
|
||||
darkgray: "#a9a9a9",
|
||||
darkgreen: "#006400",
|
||||
darkkhaki: "#bdb76b",
|
||||
darkmagenta: "#8b008b",
|
||||
darkolivegreen: "#556b2f",
|
||||
darkorange: "#ff8c00",
|
||||
darkorchid: "#9932cc",
|
||||
darkred: "#8b0000",
|
||||
darksalmon: "#e9967a",
|
||||
darkseagreen: "#8fbc8f",
|
||||
darkslateblue: "#483d8b",
|
||||
darkslategray: "#2f4f4f",
|
||||
darkturquoise: "#00ced1",
|
||||
darkviolet: "#9400d3",
|
||||
deeppink: "#ff1493",
|
||||
deepskyblue: "#00bfff",
|
||||
dimgray: "#696969",
|
||||
dodgerblue: "#1e90ff",
|
||||
firebrick: "#b22222",
|
||||
floralwhite: "#fffaf0",
|
||||
forestgreen: "#228b22",
|
||||
fuchsia: "#ff00ff",
|
||||
gainsboro: "#dcdcdc",
|
||||
ghostwhite: "#f8f8ff",
|
||||
gold: "#ffd700",
|
||||
goldenrod: "#daa520",
|
||||
gray: "#808080",
|
||||
green: "#008000",
|
||||
greenyellow: "#adff2f",
|
||||
honeydew: "#f0fff0",
|
||||
hotpink: "#ff69b4",
|
||||
"indianred ": "#cd5c5c",
|
||||
indigo: "#4b0082",
|
||||
ivory: "#fffff0",
|
||||
khaki: "#f0e68c",
|
||||
lavender: "#e6e6fa",
|
||||
lavenderblush: "#fff0f5",
|
||||
lawngreen: "#7cfc00",
|
||||
lemonchiffon: "#fffacd",
|
||||
lightblue: "#add8e6",
|
||||
lightcoral: "#f08080",
|
||||
lightcyan: "#e0ffff",
|
||||
lightgoldenrodyellow: "#fafad2",
|
||||
lightgrey: "#d3d3d3",
|
||||
lightgreen: "#90ee90",
|
||||
lightpink: "#ffb6c1",
|
||||
lightsalmon: "#ffa07a",
|
||||
lightseagreen: "#20b2aa",
|
||||
lightskyblue: "#87cefa",
|
||||
lightslategray: "#778899",
|
||||
lightsteelblue: "#b0c4de",
|
||||
lightyellow: "#ffffe0",
|
||||
lime: "#00ff00",
|
||||
limegreen: "#32cd32",
|
||||
linen: "#faf0e6",
|
||||
magenta: "#ff00ff",
|
||||
maroon: "#800000",
|
||||
mediumaquamarine: "#66cdaa",
|
||||
mediumblue: "#0000cd",
|
||||
mediumorchid: "#ba55d3",
|
||||
mediumpurple: "#9370d8",
|
||||
mediumseagreen: "#3cb371",
|
||||
mediumslateblue: "#7b68ee",
|
||||
mediumspringgreen: "#00fa9a",
|
||||
mediumturquoise: "#48d1cc",
|
||||
mediumvioletred: "#c71585",
|
||||
midnightblue: "#191970",
|
||||
mintcream: "#f5fffa",
|
||||
mistyrose: "#ffe4e1",
|
||||
moccasin: "#ffe4b5",
|
||||
navajowhite: "#ffdead",
|
||||
navy: "#000080",
|
||||
oldlace: "#fdf5e6",
|
||||
olive: "#808000",
|
||||
olivedrab: "#6b8e23",
|
||||
orange: "#ffa500",
|
||||
orangered: "#ff4500",
|
||||
orchid: "#da70d6",
|
||||
palegoldenrod: "#eee8aa",
|
||||
palegreen: "#98fb98",
|
||||
paleturquoise: "#afeeee",
|
||||
palevioletred: "#d87093",
|
||||
papayawhip: "#ffefd5",
|
||||
peachpuff: "#ffdab9",
|
||||
peru: "#cd853f",
|
||||
pink: "#ffc0cb",
|
||||
plum: "#dda0dd",
|
||||
powderblue: "#b0e0e6",
|
||||
purple: "#800080",
|
||||
rebeccapurple: "#663399",
|
||||
red: "#ff0000",
|
||||
rosybrown: "#bc8f8f",
|
||||
royalblue: "#4169e1",
|
||||
saddlebrown: "#8b4513",
|
||||
salmon: "#fa8072",
|
||||
sandybrown: "#f4a460",
|
||||
seagreen: "#2e8b57",
|
||||
seashell: "#fff5ee",
|
||||
sienna: "#a0522d",
|
||||
silver: "#c0c0c0",
|
||||
skyblue: "#87ceeb",
|
||||
slateblue: "#6a5acd",
|
||||
slategray: "#708090",
|
||||
snow: "#fffafa",
|
||||
springgreen: "#00ff7f",
|
||||
steelblue: "#4682b4",
|
||||
tan: "#d2b48c",
|
||||
teal: "#008080",
|
||||
thistle: "#d8bfd8",
|
||||
tomato: "#ff6347",
|
||||
turquoise: "#40e0d0",
|
||||
violet: "#ee82ee",
|
||||
wheat: "#f5deb3",
|
||||
white: "#ffffff",
|
||||
whitesmoke: "#f5f5f5",
|
||||
yellow: "#ffff00",
|
||||
yellowgreen: "#9acd32",
|
||||
};
|
||||
if (typeof colors[color.toLowerCase()] != "undefined")
|
||||
return colors[color.toLowerCase()];
|
||||
return color;
|
||||
}
|
||||
|
||||
71
ea-scripts/Deconstruct selected elements into new drawing.md
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||

|
||||
|
||||
Select some elements in the scene. The script will take these elements and move them into a new Excalidraw file, and open that file. The selected elements will also be replaced in your original drawing with the embedded Excalidraw file (the one that was just created). You will be prompted for the file name of the new deconstructed image. The script is useful if you want to break a larger drawing into smaller reusable parts that you want to reference in multiple drawings.
|
||||
|
||||
```javascript
|
||||
*/
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.7.29")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
const els = ea.getViewSelectedElements();
|
||||
if (els.length === 0) {
|
||||
new Notice("You must select elements first")
|
||||
return;
|
||||
}
|
||||
|
||||
const bb = ea.getBoundingBox(els);
|
||||
ea.copyViewElementsToEAforEditing(els);
|
||||
|
||||
ea.getElements().filter(el=>el.type==="image").forEach(el=>{
|
||||
const img = ea.targetView.excalidrawData.getFile(el.fileId);
|
||||
const path = (img?.linkParts?.original)??(img?.file?.path);
|
||||
if(img && path) {
|
||||
ea.imagesDict[el.fileId] = {
|
||||
mimeType: img.mimeType,
|
||||
id: el.fileId,
|
||||
dataURL: img.img,
|
||||
created: img.mtime,
|
||||
file: path,
|
||||
hasSVGwithBitmap: img.isSVGwithBitmap,
|
||||
latex: null,
|
||||
};
|
||||
return;
|
||||
}
|
||||
const equation = ea.targetView.excalidrawData.getEquation(el.fileId);
|
||||
eqImg = ea.targetView.getScene()?.files[el.fileId]
|
||||
if(equation && eqImg) {
|
||||
ea.imagesDict[el.fileId] = {
|
||||
mimeType: eqImg.mimeType,
|
||||
id: el.fileId,
|
||||
dataURL: eqImg.dataURL,
|
||||
created: eqImg.created,
|
||||
file: null,
|
||||
hasSVGwithBitmap: null,
|
||||
latex: equation.latex,
|
||||
};
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
let folder = ea.targetView.file.path;
|
||||
folder = folder.lastIndexOf("/")===-1?"":folder.substring(0,folder.lastIndexOf("/"))+"/";
|
||||
const fname = await utils.inputPrompt("Filename for new file","Filename","");
|
||||
const template = app.metadataCache.getFirstLinkpathDest(ea.plugin.settings.templateFilePath,"");
|
||||
|
||||
const newPath = await ea.create ({
|
||||
filename: fname + ".md",
|
||||
foldername: folder,
|
||||
templatePath: template?.path,
|
||||
onNewPane: true
|
||||
});
|
||||
|
||||
setTimeout(async ()=>{
|
||||
const file = app.metadataCache.getFirstLinkpathDest(newPath,"")
|
||||
ea.deleteViewElements(els);
|
||||
ea.clear();
|
||||
await ea.addImage(bb.topX,bb.topY,file,false);
|
||||
ea.addElementsToView(false, true, true);
|
||||
},1000);
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M169.7 .9c-22.8-1.6-41.9 14-47.5 34.7L110.4 80c.5 0 1.1 0 1.6 0c176.7 0 320 143.3 320 320c0 .5 0 1.1 0 1.6l44.4-11.8c20.8-5.5 36.3-24.7 34.7-47.5C498.5 159.5 352.5 13.5 169.7 .9zM399.8 410.2c.1-3.4 .2-6.8 .2-10.2c0-159.1-128.9-288-288-288c-3.4 0-6.8 .1-10.2 .2L.5 491.9c-1.5 5.5 .1 11.4 4.1 15.4s9.9 5.6 15.4 4.1L399.8 410.2zM176 272c-17.7 0-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32s-14.3 32-32 32zm128 64c0 17.7-14.3 32-32 32s-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32zM160 384c0 17.7-14.3 32-32 32s-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32z"/></svg>
|
||||
|
After Width: | Height: | Size: 624 B |
@@ -58,9 +58,9 @@ for (var i = 0; i < topGroups.length; 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 groupWidth = groupHeights[i].height;
|
||||
if (groupWidth < maxGroupHeight) {
|
||||
const distance = maxGroupHeight - groupWidth;
|
||||
const perRectDistance = distance / rects.length;
|
||||
for (var j = 0; j < rects.length; j++) {
|
||||
const rect = rects[j];
|
||||
@@ -128,4 +128,4 @@ function recalculateEndPointOfLine(line, el) {
|
||||
if(intersectA.length > 0) {
|
||||
line.points[line.points.length - 1] = [intersectA[0][0] - line.x, intersectA[0][1] - line.y];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
67
ea-scripts/Grid Selected Images.md
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||

|
||||
|
||||
This script arranges selected images into compact grid view, removing gaps in-between, resizing when necessary and breaking into multiple rows/columns.
|
||||
|
||||
```javascript
|
||||
*/
|
||||
|
||||
try {
|
||||
let els = ea.getViewSelectedElements().filter(el => el.type == 'image');
|
||||
|
||||
new Notice(els.length);
|
||||
|
||||
if (els.length == 0) throw new Error('No image elements selected');
|
||||
|
||||
const bounds = ea.getBoundingBox(els);
|
||||
const { topX, topY, width, height } = bounds;
|
||||
|
||||
els.sort((a, b) => a.x + a.y < b.x + b.y);
|
||||
|
||||
const areaAvailable = width * height;
|
||||
|
||||
let elWidth = els[0].width;
|
||||
let elHeight = els[0].height;
|
||||
|
||||
if (elWidth * elHeight > areaAvailable) {
|
||||
while (elWidth * elHeight > areaAvailable) {
|
||||
elWidth /= 1.1;
|
||||
elHeight /= 1.1;
|
||||
}
|
||||
} else if (elWidth * elHeight < areaAvailable) {
|
||||
while (elWidth * elHeight > areaAvailable) {
|
||||
elWidth *= 1.1;
|
||||
elHeight *= 1.1;
|
||||
}
|
||||
}
|
||||
|
||||
const rows = (width - elWidth) / elWidth;
|
||||
|
||||
let row = 0, column = 0;
|
||||
for (const element of els) {
|
||||
element.x = topX + (elWidth * row);
|
||||
element.y = topY + (elHeight * column);
|
||||
|
||||
if (element.width > elWidth) {
|
||||
while (element.width >= elWidth) {
|
||||
element.width /= 1.1;
|
||||
element.height /= 1.1;
|
||||
}
|
||||
} else if (element.width < elWidth) {
|
||||
while (element.width <= elWidth) {
|
||||
element.width *= 1.1;
|
||||
element.height *= 1.1;
|
||||
}
|
||||
}
|
||||
|
||||
row++;
|
||||
if (row > rows) {
|
||||
row = 0;
|
||||
column++;
|
||||
}
|
||||
}
|
||||
|
||||
ea.addElementsToView(false, true, true);
|
||||
} catch (err) {
|
||||
_ = new Notice(err.toString())
|
||||
}
|
||||
2
ea-scripts/Grid Selected Images.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 376.3492303436433 256.64929991179815" stroke="#000">
|
||||
<g stroke-linecap="round" transform="translate(10 10) rotate(0 58.5858154296875 58.5858154296875)"><path d="M-1.64 1.57 C38.67 2.87, 77.63 0.2, 117.31 1.14 M-0.05 -0.5 C40.75 0.3, 82.48 0.12, 118.09 0.99 M116.67 0.11 C118.02 47.69, 116.43 92.18, 118.63 118.15 M117.41 0.39 C116.57 38.93, 117.51 79.53, 116.57 116.49 M118.65 117.22 C92.96 119.01, 66.56 117.46, -0.42 117.17 M117.21 116.56 C91.43 117.53, 63.4 117.03, -0.23 117.71 M1.5 116.9 C-2.3 91.83, 1.37 68.12, -0.05 -0.85 M-0.84 116.86 C-1.03 87.92, -0.86 61.1, 0.54 0.72" stroke-width="2" fill="none"></path></g><g stroke-linecap="round" transform="translate(128.96603337932902 10.2586194164669) rotate(0 58.5858154296875 58.5858154296875)"><path d="M0.05 1.78 C24.68 -1.8, 48.73 0.22, 118.17 0.33 M-0.27 0.22 C34.72 0.61, 69.52 1.58, 118.12 0.36 M117.6 1.43 C115.71 34.53, 118.33 70.74, 117.89 116.98 M116.68 -0.46 C117.9 41.7, 116.85 81.21, 116.34 117.29 M118.4 119.11 C83.22 117.59, 48.31 117.2, -1.44 117.99 M118.15 116.77 C74.14 115.56, 31.55 116.99, -0.96 117.69 M-1.69 115.77 C1.1 78.33, -0.93 41, -1.14 1.03 M-0.43 116.37 C0.72 90.14, 1.52 62.17, 0.55 -0.66" stroke-width="2" fill="none"></path></g><g stroke-linecap="round" transform="translate(248.3020093440573 10.465294492851172) rotate(0 58.5858154296875 58.5858154296875)"><path d="M0.39 -0.88 C44.51 0.1, 89.74 -0.71, 117.03 -0.11 M0.42 0.03 C30.22 0.74, 59.56 0.11, 117.15 -0.25 M116 -0.35 C118.88 36.78, 118.14 71.41, 118.16 117.65 M117.62 0.75 C115.99 39.07, 115.76 79.63, 117.09 117.91 M117.44 117.56 C81.29 118.3, 44.81 119.12, 1.29 117.25 M116.84 116.27 C88.98 117.24, 60.29 117.22, 0.21 117.92 M1.97 115.99 C0.94 82.75, -0.15 51.05, -1.24 -1.67 M-0.26 118 C1.05 86.36, 1.06 53.45, 0.95 0.65" stroke-width="2" fill="none"></path></g><g stroke-linecap="round" transform="translate(10.875590140210988 129.01237455957016) rotate(0 58.5858154296875 58.5858154296875)"><path d="M0.24 -0.16 C29.59 1.02, 57.45 2.91, 117.44 0.38 M0.41 0.64 C32.74 0.23, 66.39 0.45, 116.84 -0.9 M118.21 0.43 C119.3 32.21, 116.11 63.55, 119.15 115.99 M117.68 -0.62 C115.84 34.54, 116.24 68.9, 116.91 118 M115.86 119.08 C76.96 118.61, 32.48 117.59, -1.75 116.45 M117.39 116.77 C85.7 116.42, 54.91 116.16, 0.1 118.13 M-0.18 118.45 C-0.52 71.18, -0.96 24.41, 1.23 0.16 M0.3 117.66 C0.57 92.18, 0.07 65.33, -0.4 0.17" stroke-width="2" fill="none"></path></g><g stroke-linecap="round" transform="translate(129.84162351954 129.27099397603888) rotate(0 58.5858154296875 58.5858154296875)"><path d="M-0.16 1.48 C27.24 1.09, 56.31 0.13, 117.56 -0.42 M0.64 0.04 C34.52 0.5, 69.88 -0.81, 116.27 -0.23 M117.6 1.5 C115.78 39.75, 114.64 84.85, 115.99 117.12 M116.55 -0.84 C116.19 29.74, 115.7 60.09, 118 117.71 M119.08 118.46 C74.37 114.72, 29.76 114.66, -0.72 116.45 M116.77 116.64 C81.73 117.03, 46.47 117.52, 0.96 118.05 M1.28 117.07 C0.37 77.34, -0.95 39.83, 0.16 -1.64 M0.49 117.63 C0.17 83.07, -1.11 48.64, 0.17 0.23" stroke-width="2" fill="none"></path></g><g stroke-linecap="round" transform="translate(249.17759948426828 129.47766905242315) rotate(0 58.5858154296875 58.5858154296875)"><path d="M1.48 0.05 C26.67 2.03, 51.16 0.48, 116.75 0 M0.04 -0.61 C27.7 -1.15, 53.12 -1.65, 116.94 0.54 M118.67 -0.27 C116.09 22.53, 119.75 46.69, 117.12 116.32 M116.34 -0.31 C117.34 27.65, 117.51 57.73, 117.71 117.89 M118.46 117.96 C73.87 118.06, 32.19 117.57, -0.72 117.14 M116.64 116.71 C84.55 115.98, 52.82 117.66, 0.88 117.52 M-0.11 116.63 C-0.44 89.26, 1.33 65.24, -1.64 -0.19 M0.46 117.75 C-0.38 77.25, -0.75 38.91, 0.23 0.69" stroke-width="2" fill="none"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
@@ -16,274 +16,37 @@ The color conversion method was copied from [color-convert](https://github.com/Q
|
||||
```javascript
|
||||
*/
|
||||
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.7.19")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
let settings = ea.getScriptSettings();
|
||||
//set default values on first run
|
||||
if(!settings["Step size"]) {
|
||||
settings = {
|
||||
"Step size" : {
|
||||
value: 2,
|
||||
description: "Step size in percentage for making the color lighter"
|
||||
}
|
||||
};
|
||||
ea.setScriptSettings(settings);
|
||||
}
|
||||
|
||||
const step = settings["Step size"].value;
|
||||
|
||||
const elements = ea
|
||||
.getViewSelectedElements()
|
||||
.filter((el) =>
|
||||
["rectangle", "ellipse", "diamond", "image", "line"].includes(el.type)
|
||||
["rectangle", "ellipse", "diamond", "image", "line", "freedraw"].includes(el.type)
|
||||
);
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
for (const el of ea.getElements()) {
|
||||
const color = colorNameToHex(el.backgroundColor);
|
||||
const rgbColor = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color);
|
||||
if (rgbColor) {
|
||||
const r = parseInt(rgbColor[1], 16);
|
||||
const g = parseInt(rgbColor[2], 16);
|
||||
const b = parseInt(rgbColor[3], 16);
|
||||
const originalRgb = [r, g, b];
|
||||
const hsl = rgbToHsl(originalRgb);
|
||||
const step = 2;
|
||||
const newLightness = hsl[2] + step;
|
||||
if (newLightness < 100) {
|
||||
hsl[2] = newLightness;
|
||||
}
|
||||
const newRgb = hslToRgb(hsl);
|
||||
el.backgroundColor = "#" + rgbToHexString(newRgb);
|
||||
const color = ea.colorNameToHex(el.backgroundColor);
|
||||
const cm = ea.getCM(color);
|
||||
if (cm) {
|
||||
const lighter = cm.lighterBy(step);
|
||||
if(Math.ceil(lighter.lightness)<100) el.backgroundColor = lighter.stringHSL();
|
||||
}
|
||||
}
|
||||
await ea.addElementsToView(false, false);
|
||||
|
||||
function rgbToHexString(args) {
|
||||
const integer =
|
||||
((Math.round(args[0]) & 0xff) << 16) +
|
||||
((Math.round(args[1]) & 0xff) << 8) +
|
||||
(Math.round(args[2]) & 0xff);
|
||||
|
||||
const string = integer.toString(16).toUpperCase();
|
||||
return "000000".substring(string.length) + string;
|
||||
}
|
||||
|
||||
function hslToRgb(hsl) {
|
||||
const h = hsl[0] / 360;
|
||||
const s = hsl[1] / 100;
|
||||
const l = hsl[2] / 100;
|
||||
let t2;
|
||||
let t3;
|
||||
let val;
|
||||
|
||||
if (s === 0) {
|
||||
val = l * 255;
|
||||
return [val, val, val];
|
||||
}
|
||||
|
||||
if (l < 0.5) {
|
||||
t2 = l * (1 + s);
|
||||
} else {
|
||||
t2 = l + s - l * s;
|
||||
}
|
||||
|
||||
const t1 = 2 * l - t2;
|
||||
|
||||
const rgb = [0, 0, 0];
|
||||
for (let i = 0; i < 3; i++) {
|
||||
t3 = h + (1 / 3) * -(i - 1);
|
||||
if (t3 < 0) {
|
||||
t3++;
|
||||
}
|
||||
|
||||
if (t3 > 1) {
|
||||
t3--;
|
||||
}
|
||||
|
||||
if (6 * t3 < 1) {
|
||||
val = t1 + (t2 - t1) * 6 * t3;
|
||||
} else if (2 * t3 < 1) {
|
||||
val = t2;
|
||||
} else if (3 * t3 < 2) {
|
||||
val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
|
||||
} else {
|
||||
val = t1;
|
||||
}
|
||||
|
||||
rgb[i] = val * 255;
|
||||
}
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
function rgbToHsl(rgb) {
|
||||
const r = rgb[0] / 255;
|
||||
const g = rgb[1] / 255;
|
||||
const b = rgb[2] / 255;
|
||||
const min = Math.min(r, g, b);
|
||||
const max = Math.max(r, g, b);
|
||||
const delta = max - min;
|
||||
let h;
|
||||
let s;
|
||||
|
||||
if (max === min) {
|
||||
h = 0;
|
||||
} else if (r === max) {
|
||||
h = (g - b) / delta;
|
||||
} else if (g === max) {
|
||||
h = 2 + (b - r) / delta;
|
||||
} else if (b === max) {
|
||||
h = 4 + (r - g) / delta;
|
||||
}
|
||||
|
||||
h = Math.min(h * 60, 360);
|
||||
|
||||
if (h < 0) {
|
||||
h += 360;
|
||||
}
|
||||
|
||||
const l = (min + max) / 2;
|
||||
|
||||
if (max === min) {
|
||||
s = 0;
|
||||
} else if (l <= 0.5) {
|
||||
s = delta / (max + min);
|
||||
} else {
|
||||
s = delta / (2 - max - min);
|
||||
}
|
||||
|
||||
return [h, s * 100, l * 100];
|
||||
}
|
||||
|
||||
function colorNameToHex(color) {
|
||||
const colors = {
|
||||
aliceblue: "#f0f8ff",
|
||||
antiquewhite: "#faebd7",
|
||||
aqua: "#00ffff",
|
||||
aquamarine: "#7fffd4",
|
||||
azure: "#f0ffff",
|
||||
beige: "#f5f5dc",
|
||||
bisque: "#ffe4c4",
|
||||
black: "#000000",
|
||||
blanchedalmond: "#ffebcd",
|
||||
blue: "#0000ff",
|
||||
blueviolet: "#8a2be2",
|
||||
brown: "#a52a2a",
|
||||
burlywood: "#deb887",
|
||||
cadetblue: "#5f9ea0",
|
||||
chartreuse: "#7fff00",
|
||||
chocolate: "#d2691e",
|
||||
coral: "#ff7f50",
|
||||
cornflowerblue: "#6495ed",
|
||||
cornsilk: "#fff8dc",
|
||||
crimson: "#dc143c",
|
||||
cyan: "#00ffff",
|
||||
darkblue: "#00008b",
|
||||
darkcyan: "#008b8b",
|
||||
darkgoldenrod: "#b8860b",
|
||||
darkgray: "#a9a9a9",
|
||||
darkgreen: "#006400",
|
||||
darkkhaki: "#bdb76b",
|
||||
darkmagenta: "#8b008b",
|
||||
darkolivegreen: "#556b2f",
|
||||
darkorange: "#ff8c00",
|
||||
darkorchid: "#9932cc",
|
||||
darkred: "#8b0000",
|
||||
darksalmon: "#e9967a",
|
||||
darkseagreen: "#8fbc8f",
|
||||
darkslateblue: "#483d8b",
|
||||
darkslategray: "#2f4f4f",
|
||||
darkturquoise: "#00ced1",
|
||||
darkviolet: "#9400d3",
|
||||
deeppink: "#ff1493",
|
||||
deepskyblue: "#00bfff",
|
||||
dimgray: "#696969",
|
||||
dodgerblue: "#1e90ff",
|
||||
firebrick: "#b22222",
|
||||
floralwhite: "#fffaf0",
|
||||
forestgreen: "#228b22",
|
||||
fuchsia: "#ff00ff",
|
||||
gainsboro: "#dcdcdc",
|
||||
ghostwhite: "#f8f8ff",
|
||||
gold: "#ffd700",
|
||||
goldenrod: "#daa520",
|
||||
gray: "#808080",
|
||||
green: "#008000",
|
||||
greenyellow: "#adff2f",
|
||||
honeydew: "#f0fff0",
|
||||
hotpink: "#ff69b4",
|
||||
"indianred ": "#cd5c5c",
|
||||
indigo: "#4b0082",
|
||||
ivory: "#fffff0",
|
||||
khaki: "#f0e68c",
|
||||
lavender: "#e6e6fa",
|
||||
lavenderblush: "#fff0f5",
|
||||
lawngreen: "#7cfc00",
|
||||
lemonchiffon: "#fffacd",
|
||||
lightblue: "#add8e6",
|
||||
lightcoral: "#f08080",
|
||||
lightcyan: "#e0ffff",
|
||||
lightgoldenrodyellow: "#fafad2",
|
||||
lightgrey: "#d3d3d3",
|
||||
lightgreen: "#90ee90",
|
||||
lightpink: "#ffb6c1",
|
||||
lightsalmon: "#ffa07a",
|
||||
lightseagreen: "#20b2aa",
|
||||
lightskyblue: "#87cefa",
|
||||
lightslategray: "#778899",
|
||||
lightsteelblue: "#b0c4de",
|
||||
lightyellow: "#ffffe0",
|
||||
lime: "#00ff00",
|
||||
limegreen: "#32cd32",
|
||||
linen: "#faf0e6",
|
||||
magenta: "#ff00ff",
|
||||
maroon: "#800000",
|
||||
mediumaquamarine: "#66cdaa",
|
||||
mediumblue: "#0000cd",
|
||||
mediumorchid: "#ba55d3",
|
||||
mediumpurple: "#9370d8",
|
||||
mediumseagreen: "#3cb371",
|
||||
mediumslateblue: "#7b68ee",
|
||||
mediumspringgreen: "#00fa9a",
|
||||
mediumturquoise: "#48d1cc",
|
||||
mediumvioletred: "#c71585",
|
||||
midnightblue: "#191970",
|
||||
mintcream: "#f5fffa",
|
||||
mistyrose: "#ffe4e1",
|
||||
moccasin: "#ffe4b5",
|
||||
navajowhite: "#ffdead",
|
||||
navy: "#000080",
|
||||
oldlace: "#fdf5e6",
|
||||
olive: "#808000",
|
||||
olivedrab: "#6b8e23",
|
||||
orange: "#ffa500",
|
||||
orangered: "#ff4500",
|
||||
orchid: "#da70d6",
|
||||
palegoldenrod: "#eee8aa",
|
||||
palegreen: "#98fb98",
|
||||
paleturquoise: "#afeeee",
|
||||
palevioletred: "#d87093",
|
||||
papayawhip: "#ffefd5",
|
||||
peachpuff: "#ffdab9",
|
||||
peru: "#cd853f",
|
||||
pink: "#ffc0cb",
|
||||
plum: "#dda0dd",
|
||||
powderblue: "#b0e0e6",
|
||||
purple: "#800080",
|
||||
rebeccapurple: "#663399",
|
||||
red: "#ff0000",
|
||||
rosybrown: "#bc8f8f",
|
||||
royalblue: "#4169e1",
|
||||
saddlebrown: "#8b4513",
|
||||
salmon: "#fa8072",
|
||||
sandybrown: "#f4a460",
|
||||
seagreen: "#2e8b57",
|
||||
seashell: "#fff5ee",
|
||||
sienna: "#a0522d",
|
||||
silver: "#c0c0c0",
|
||||
skyblue: "#87ceeb",
|
||||
slateblue: "#6a5acd",
|
||||
slategray: "#708090",
|
||||
snow: "#fffafa",
|
||||
springgreen: "#00ff7f",
|
||||
steelblue: "#4682b4",
|
||||
tan: "#d2b48c",
|
||||
teal: "#008080",
|
||||
thistle: "#d8bfd8",
|
||||
tomato: "#ff6347",
|
||||
turquoise: "#40e0d0",
|
||||
violet: "#ee82ee",
|
||||
wheat: "#f5deb3",
|
||||
white: "#ffffff",
|
||||
whitesmoke: "#f5f5f5",
|
||||
yellow: "#ffff00",
|
||||
yellowgreen: "#9acd32",
|
||||
};
|
||||
if (typeof colors[color.toLowerCase()] != "undefined")
|
||||
return colors[color.toLowerCase()];
|
||||
return color;
|
||||
}
|
||||
|
||||
113
ea-scripts/Mindmap connector.md
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
|
||||

|
||||
|
||||

|
||||
This script creates mindmap like lines(only right and down side are available). The line will starts according to the creation time of the elements. So you may need to create the header element first.
|
||||
|
||||
```javascript
|
||||
*/
|
||||
const elements = ea.getViewSelectedElements();
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
groups = ea.getMaximumGroups(elements);
|
||||
|
||||
els=[];
|
||||
elsx=[];
|
||||
elsy=[];
|
||||
for (i = 0, len =groups.length; i < len; i++) {
|
||||
els.push(ea.getLargestElement(groups[i]));
|
||||
elsx.push(ea.getLargestElement(groups[i]).x);
|
||||
elsy.push(ea.getLargestElement(groups[i]).y);
|
||||
}
|
||||
//line style setting
|
||||
ea.style.strokeColor = els[0].strokeColor;
|
||||
ea.style.strokeWidth = els[0].strokeWidth;
|
||||
ea.style.strokeStyle = els[0].strokeStyle;
|
||||
ea.style.strokeSharpness = els[0].strokeSharpness;
|
||||
//all min max x y
|
||||
let maxy = Math.max.apply(null, elsy);
|
||||
let indexmaxy=elsy.indexOf(maxy);
|
||||
let miny = Math.min.apply(null, elsy);
|
||||
let indexminy = elsy.indexOf(miny);
|
||||
let maxx = Math.max.apply(null, elsx);
|
||||
let indexmaxx = elsx.indexOf(maxx);
|
||||
let minx = Math.min.apply(null, elsx);
|
||||
let indexminx = elsx.indexOf(minx);
|
||||
//child max min x y
|
||||
let gmaxy = Math.max.apply(null, elsy.slice(1));
|
||||
let gindexmaxy=elsy.indexOf(gmaxy);
|
||||
let gminy = Math.min.apply(null, elsy.slice(1));
|
||||
let gindexminy = elsy.indexOf(gminy);
|
||||
let gmaxx = Math.max.apply(null, elsx.slice(1));
|
||||
let gindexmaxx = elsx.indexOf(gmaxx);
|
||||
let gminx = Math.min.apply(null, elsx.slice(1));
|
||||
let gindexminx = elsx.indexOf(gminx);
|
||||
let s=0;//Set line direction down as default
|
||||
if (indexminx==0 && els[0].x + els[0].width<=gminx) {
|
||||
s=1;
|
||||
}
|
||||
else if (indexminy == 0) {
|
||||
s=0;
|
||||
}
|
||||
var length_left;
|
||||
if(els[0].x + els[0].width * 2<=gminx){length_left=els[0].x + els[0].width * 1.5;}
|
||||
else {length_left=(els[0].x + els[0].width+gminx)/2;}
|
||||
|
||||
var length_down;
|
||||
if(els[0].y + els[0].height* 2.5<=gminy){length_down=els[0].y + els[0].height * 2;}
|
||||
else {length_down=(els[0].y + els[0].height+gminy)/2;}
|
||||
if(s) {
|
||||
ea.addLine(
|
||||
[[length_left,
|
||||
maxy + els[indexmaxy].height / 2],
|
||||
[length_left,
|
||||
miny + els[indexminy].height / 2]]
|
||||
);
|
||||
for (i = 1, len = groups.length; i < len; i++) {
|
||||
ea.addLine(
|
||||
[[els[i].x,
|
||||
els[i].y + els[i].height/2],
|
||||
[length_left,
|
||||
els[i].y + els[i].height/2]]
|
||||
);
|
||||
}
|
||||
ea.addArrow(
|
||||
[[els[0].x+els[0].width,
|
||||
els[0].y + els[0].height / 2],
|
||||
[length_left,
|
||||
els[0].y + els[0].height / 2]],
|
||||
{
|
||||
startArrowHead: "none",
|
||||
endArrowHead: "dot"
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
else {
|
||||
ea.addLine(
|
||||
[[maxx + els[indexmaxx].width / 2,
|
||||
length_down],
|
||||
[minx + els[indexminx].width / 2,
|
||||
length_down]]
|
||||
);
|
||||
for (i = 1, len = groups.length; i < len; i++) {
|
||||
ea.addLine(
|
||||
[[els[i].x + els[i].width / 2,
|
||||
els[i].y],
|
||||
[els[i].x + els[i].width / 2,
|
||||
length_down]]
|
||||
);
|
||||
}
|
||||
ea.addArrow(
|
||||
[[els[0].x + els[0].width / 2,
|
||||
els[0].y + els[0].height],
|
||||
[els[0].x + els[0].width / 2,
|
||||
length_down]],
|
||||
{
|
||||
startArrowHead: "none",
|
||||
endArrowHead: "dot"
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
await ea.addElementsToView(false,false,true);
|
||||
12
ea-scripts/Mindmap connector.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<svg width="607" height="541" viewBox="0 0 607 541" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M280 43.355V253.355H140V206.687L0 206.691V346.691H140V300.023H280V510.023C280 522.925 290.453 533.355 303.332 533.355H490.002C502.904 533.355 513.334 522.925 513.334 510.023C513.334 497.144 502.904 486.691 490.002 486.691H326.672V300.021H490.002C502.904 300.021 513.334 289.568 513.334 276.689C513.334 263.81 502.904 253.357 490.002 253.357H326.672V66.6869H490.002C502.904 66.6869 513.334 56.2569 513.334 43.3549C513.334 30.4529 502.904 20.0229 490.002 20.0229H303.332C290.453 20.019 280 30.4489 280 43.3509V43.355ZM46.67 300.025V253.357H93.338V300.025H46.67Z" fill="black"/>
|
||||
<rect x="540" y="23" width="39" height="39" fill="#D9D9D9"/>
|
||||
<rect x="503" width="104" height="95" fill="#D9D9D9"/>
|
||||
<rect x="503.5" y="0.5" width="103" height="94" fill="black" stroke="black"/>
|
||||
<rect x="503" y="223" width="104" height="95" fill="black"/>
|
||||
<rect x="503.5" y="446.5" width="103" height="94" fill="black" stroke="black"/>
|
||||
<path d="M532 243H580V291H532V243Z" fill="white"/>
|
||||
<path d="M532 475H580V523H532V475Z" fill="white"/>
|
||||
<path d="M532 243H580V291H532V243Z" fill="white"/>
|
||||
<path d="M532 23H580V71H532V23Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -14,7 +14,10 @@ if(elements.length === 0) {
|
||||
}
|
||||
elements = [elements[len]];
|
||||
}
|
||||
elements.forEach((el)=>{
|
||||
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
|
||||
ea.getElements().forEach((el)=>{
|
||||
el.simulatePressure = false;
|
||||
el.type = "freedraw";
|
||||
el.pressures = [];
|
||||
@@ -22,6 +25,8 @@ elements.forEach((el)=>{
|
||||
for(i=0;i<len;i++)
|
||||
el.pressures.push((len-i)/len);
|
||||
});
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
await ea.addElementsToView(false,false);
|
||||
elements.forEach((el)=>ea.moveViewElementToZIndex(el.id,0));
|
||||
|
||||
await ea.addElementsToView(false,true);
|
||||
elements.forEach((el)=>ea.moveViewElementToZIndex(el.id,0));
|
||||
const ids=ea.getElements().map(el=>el.id);
|
||||
ea.selectElementsInView(ea.getViewElements().filter(el=>ids.contains(el.id)));
|
||||
188
ea-scripts/Palette loader.md
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
Design your palette at http://paletton.com/
|
||||
Once you are happy with your colors, click Tables/Export in the bottom right of the screen:
|
||||

|
||||
Then click "Color swatches/as Sketch Palette"
|
||||

|
||||
Copy the contents of the page to a markdown file in your vault. Place the file in the Excalidraw/Palettes folder (you can change this folder in settings).
|
||||

|
||||

|
||||
|
||||
```javascript
|
||||
*/
|
||||
//--------------------------
|
||||
// Load settings
|
||||
//--------------------------
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.7.19")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
const api = ea.getExcalidrawAPI();
|
||||
let settings = ea.getScriptSettings();
|
||||
//set default values on first run
|
||||
if(!settings["Palette folder"]) {
|
||||
settings = {
|
||||
"Palette folder" : {
|
||||
value: "Excalidraw/Palettes",
|
||||
description: "The path to the folder where you store the Excalidraw Palettes"
|
||||
},
|
||||
"Light-gray" : {
|
||||
value: "#505050",
|
||||
description: "Base light-gray used for mixing with the accent color to generate the palette light-gray"
|
||||
},
|
||||
"Dark-gray" : {
|
||||
value: "#e0e0e0",
|
||||
description: "Base dark-gray used for mixing with the accent color to generate the palette dark-gray"
|
||||
}
|
||||
};
|
||||
ea.setScriptSettings(settings);
|
||||
}
|
||||
|
||||
const lightGray = settings["Light-gray"].value;
|
||||
const darkGray = settings["Dark-gray"].value;
|
||||
|
||||
let paletteFolder = settings["Palette folder"].value.toLowerCase();
|
||||
if(paletteFolder === "" || paletteFolder === "/") {
|
||||
new Notice("The palette folder cannot be the root folder of your vault");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!paletteFolder.endsWith("/")) paletteFolder += "/";
|
||||
|
||||
|
||||
//--------------------------
|
||||
// Select palette
|
||||
//--------------------------
|
||||
const palettes = app.vault.getFiles()
|
||||
.filter(f=>f.extension === "md" && f.path.toLowerCase() === paletteFolder + f.name.toLowerCase())
|
||||
.sort((a,b)=>a.basename.toLowerCase()<b.basename.toLowerCase()?-1:1);
|
||||
const file = await utils.suggester(["Excalidraw Default"].concat(palettes.map(f=>f.name)),["Default"].concat(palettes), "Choose a palette, press ESC to abort");
|
||||
if(!file) return;
|
||||
|
||||
if(file === "Default") {
|
||||
api.updateScene({
|
||||
appState: {
|
||||
colorPalette: {}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
//--------------------------
|
||||
// Load palette
|
||||
//--------------------------
|
||||
const sketchPalette = await app.vault.read(file);
|
||||
|
||||
const parseJSON = (data) => {
|
||||
try {
|
||||
return JSON.parse(data);
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const loadPaletteFromPlainText = (data) => {
|
||||
const colors = [];
|
||||
data.replaceAll("\r","").split("\n").forEach(c=>{
|
||||
c = c.trim();
|
||||
if(c==="") return;
|
||||
if(c.match(/[^hslrga-fA-F\(\d\.\,\%\s)#]/)) return;
|
||||
const cm = ea.getCM(c);
|
||||
if(cm) colors.push(cm.stringHEX({alpha: false}));
|
||||
})
|
||||
return colors;
|
||||
}
|
||||
|
||||
const paletteJSON = parseJSON(sketchPalette);
|
||||
|
||||
const colors = paletteJSON
|
||||
? paletteJSON.colors.map(c=>ea.getCM({r:c.red*255,g:c.green*255,b:c.blue*255,a:c.alpha}).stringHEX({alpha: false}))
|
||||
: loadPaletteFromPlainText(sketchPalette);
|
||||
const baseColor = ea.getCM(colors[0]);
|
||||
|
||||
// Add black, white, transparent, gary
|
||||
const palette = [[
|
||||
"transparent",
|
||||
"black",
|
||||
baseColor.mix({color: lightGray, ratio:0.95}).stringHEX({alpha: false}),
|
||||
baseColor.mix({color: darkGray, ratio:0.95}).stringHEX({alpha: false}),
|
||||
"white"
|
||||
]];
|
||||
|
||||
// Create Excalidraw palette
|
||||
for(i=0;i<Math.floor(colors.length/5);i++) {
|
||||
palette.push([
|
||||
colors[i*5+1],
|
||||
colors[i*5+2],
|
||||
colors[i*5],
|
||||
colors[i*5+3],
|
||||
colors[i*5+4]
|
||||
]);
|
||||
}
|
||||
|
||||
const paletteSize = palette.flat().length;
|
||||
const newPalette = {
|
||||
canvasBackground: palette.flat(),
|
||||
elementStroke: palette.flat(),
|
||||
elementBackground: palette.flat()
|
||||
};
|
||||
|
||||
|
||||
//--------------------------
|
||||
// Check if palette has the same size as the current. Is re-paint possible?
|
||||
//--------------------------
|
||||
const oldPalette = api.getAppState().colorPalette;
|
||||
|
||||
//You can only switch and repaint equal size palettes
|
||||
let canRepaint = Object.keys(oldPalette).length === 3 &&
|
||||
oldPalette.canvasBackground.length === paletteSize &&
|
||||
oldPalette.elementBackground.length === paletteSize &&
|
||||
oldPalette.elementStroke.length === paletteSize;
|
||||
|
||||
//Check that the palette for canvas background, element stroke and element background are the same
|
||||
for(i=0;canRepaint && i<paletteSize;i++) {
|
||||
if(
|
||||
oldPalette.canvasBackground[i] !== oldPalette.elementBackground[i] ||
|
||||
oldPalette.canvasBackground[i] !== oldPalette.elementStroke[i]
|
||||
) {
|
||||
canRepaint = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const shouldRepaint = canRepaint && await utils.suggester(["Try repainting the drawing with the new palette","Just load the new palette"], [true, false],"ESC will load the palette without repainting");
|
||||
|
||||
|
||||
//--------------------------
|
||||
// Apply palette
|
||||
//--------------------------
|
||||
if(shouldRepaint) {
|
||||
const map = new Map();
|
||||
for(i=0;i<paletteSize;i++) {
|
||||
map.set(oldPalette.canvasBackground[i],newPalette.canvasBackground[i])
|
||||
}
|
||||
|
||||
ea.copyViewElementsToEAforEditing(ea.getViewElements());
|
||||
ea.getElements().forEach(el=>{
|
||||
el.strokeColor = map.get(el.strokeColor)??el.strokeColor;
|
||||
el.backgroundColor = map.get(el.backgroundColor)??el.backgroundColor;
|
||||
})
|
||||
|
||||
const canvasColor = api.getAppState().viewBackgroundColor;
|
||||
|
||||
await api.updateScene({
|
||||
appState: {
|
||||
colorPalette: newPalette,
|
||||
viewBackgroundColor: map.get(canvasColor)??canvasColor
|
||||
}
|
||||
});
|
||||
|
||||
ea.addElementsToView();
|
||||
} else {
|
||||
api.updateScene({
|
||||
appState: {
|
||||
colorPalette: newPalette
|
||||
}
|
||||
});
|
||||
}
|
||||
1
ea-scripts/Palette loader.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M512 255.1C512 256.9 511.1 257.8 511.1 258.7C511.6 295.2 478.4 319.1 441.9 319.1H344C317.5 319.1 296 341.5 296 368C296 371.4 296.4 374.7 297 377.9C299.2 388.1 303.5 397.1 307.9 407.8C313.9 421.6 320 435.3 320 449.8C320 481.7 298.4 510.5 266.6 511.8C263.1 511.9 259.5 512 256 512C114.6 512 0 397.4 0 256C0 114.6 114.6 0 256 0C397.4 0 512 114.6 512 256V255.1zM96 255.1C78.33 255.1 64 270.3 64 287.1C64 305.7 78.33 319.1 96 319.1C113.7 319.1 128 305.7 128 287.1C128 270.3 113.7 255.1 96 255.1zM128 191.1C145.7 191.1 160 177.7 160 159.1C160 142.3 145.7 127.1 128 127.1C110.3 127.1 96 142.3 96 159.1C96 177.7 110.3 191.1 128 191.1zM256 63.1C238.3 63.1 224 78.33 224 95.1C224 113.7 238.3 127.1 256 127.1C273.7 127.1 288 113.7 288 95.1C288 78.33 273.7 63.1 256 63.1zM384 191.1C401.7 191.1 416 177.7 416 159.1C416 142.3 401.7 127.1 384 127.1C366.3 127.1 352 142.3 352 159.1C352 177.7 366.3 191.1 384 191.1z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -3,13 +3,28 @@ Click to watch the intro video:
|
||||
|
||||
[](https://youtu.be/hePJcObHIso)
|
||||
|
||||
> **Warning**
|
||||
> There is an easier way to install/manage scripts than what is shown in this video
|
||||
|
||||
See the [Excalidraw Script Engine](https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html) documentation for more details.
|
||||
|
||||
## How to install scripts into your Obsidian Vault
|
||||
To install one of the built-in scripts:
|
||||
- Open up an excalidraw drawing in Obsidian
|
||||
- In the pane dropdown menu select "Install or update Excalidraw Scripts"
|
||||
- Click on one of the available scripts
|
||||
- Click on "Install this script" (note if the script is already installed you will instead see an option to update it)
|
||||
- Restart Obsidian so the script will be picked up
|
||||
|
||||
Note: By default this will install the script into your vault in the `Excalidraw/Scripts/Downloaded` folder
|
||||
|
||||
<details><summary>Manual installation of scripts</summary>
|
||||
|
||||
Open the script you are interested in and save it to your Obsidian Vault including the first line `/*`, or open it in "Raw" and copy the entire contents to Obsidian.
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
## List of available scripts
|
||||
|Title|Description|Icon|Contributor|
|
||||
@@ -39,6 +54,7 @@ Open the script you are interested in and save it to your Obsidian Vault includi
|
||||
|[Fixed vertical distance between centers](Fixed%20vertical%20distance%20between%20centers.md)|This script arranges the selected elements vertically with a fixed center spacing.||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[Fixed vertical distance](Fixed%20vertical%20distance.md)|The script arranges the selected elements vertically with a fixed spacing. When we create an architecture diagram or mind map, we often need to arrange a large number of elements in a fixed spacing. `Fixed spacing` and `Fixed vertical Distance` scripts can save us a lot of time.||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[Lighten background color](Lighten%20background%20color.md)|This script lightens 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.||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[Mindmap connector](Mindmap%20connector.md)|This script creates mindmap like lines (only right side and down available currently) for selected elements. The line will start according to the creation time of the elements. So you should create the header element first.||[@xllowl](https://github.com/xllowl)|
|
||||
|[Modify background color opacity](Modify%20background%20color%20opacity.md)|This script changes the opacity of the background color of the selected boxes. The default background color in Excalidraw is so dark that the text is hard to read. You can lighten the color a bit by setting transparency. And you can tweak the transparency over and over again until you're happy with it. Although excalidraw has the opacity option in its native property Settings, it also changes the transparency of the border. Use this script to change only the opacity of the background color without affecting the border.||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[Normalize Selected Arrows](Normalize%20Selected%20Arrows.md)|This script will reset the start and end positions of the selected arrows. The arrow will point to the center of the connected box and will have a gap of 8px from the box.||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[OCR - Optical Character Recognition](OCR%20-%20Optical%20Character%20Recognition.md)|The script will 1) send the selected image file to [taskbone.com](https://taskbone.com) to exctract the text from the image, and 2) will add the text to your drawing as a text element.||[@zsviczian](https://github.com/zsviczian)|
|
||||
@@ -58,4 +74,4 @@ Open the script you are interested in and save it to your Obsidian Vault includi
|
||||
|[TheBrain-navigation](TheBrain-navigation.md)|An Excalidraw based graph user interface for your Vault. Requires the [Dataview plugin](https://github.com/blacksmithgu/obsidian-dataview). Generates a graph view similar to that of [TheBrain](https://TheBrain.com) plex. Watch introduction to this script on [YouTube](https://youtu.be/plYobK-VufM).||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[Toggle Fullscreen on Mobile](Toggle%20Fullscreen%20on%20Mobile.md)|Hides Obsidian workspace leaf padding and header (based on option in settings, default is "hide header" = false) which will take Excalidraw to full screen. ⚠ Note that if the header is not visible, it will be very difficult to invoke the command palette to end full screen. Only hide the header if you have a keyboard or you've practiced opening command palette!||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[Transfer TextElements to Excalidraw markdown metadata](Transfer%20TextElements%20to%20Excalidraw%20markdown%20metadata.md)|The script will delete the selected text elements from the canvas and will copy the text from these text elements into the Excalidraw markdown file as metadata. This means, that the text will no longer be visible in the drawing, however you will be able to search for the text in Obsidian and find the drawing containing this image.||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[Zoom to Fit Selected Elements](Zoom%20to%20Fit%20Selected%20Elements.md)|Similar to Excalidraw standard SHIFT+2 feature: Zoom to fit selected elements, but with the ability to zoom to 1000%. Inspiration: [#272](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/272)||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[Zoom to Fit Selected Elements](Zoom%20to%20Fit%20Selected%20Elements.md)|Similar to Excalidraw standard <kbd>SHIFT+2</kbd> feature: Zoom to fit selected elements, but with the ability to zoom to 1000%. Inspiration: [#272](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/272)||[@zsviczian](https://github.com/zsviczian)|
|
||||
|
||||
29
ea-scripts/Rename Image.md
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
|
||||

|
||||
|
||||
Select an image on the canvas and run the script. You will be prompted to provide a new filename / filepath. This cuts down the time to name images you paste from the web or drag and drop from your file system.
|
||||
|
||||
```javascript
|
||||
*/
|
||||
await ea.addElementsToView(); //to ensure all images are saved into the file
|
||||
|
||||
const img = ea.getViewSelectedElements().filter(el=>el.type === "image");
|
||||
if(img.length === 0) {
|
||||
new Notice("No image is selected");
|
||||
return;
|
||||
}
|
||||
|
||||
for(i of img) {
|
||||
const currentPath = ea.plugin.filesMaster.get(i.fileId).path;
|
||||
const file = app.vault.getAbstractFileByPath(currentPath);
|
||||
if(!file) {
|
||||
new Notice("Can't find file: " + currentPath);
|
||||
continue;
|
||||
}
|
||||
const pathNoExtension = file.path.substring(0,file.path.length-file.extension.length-1);
|
||||
const newPath = await utils.inputPrompt("Please provide the filename","file path",pathNoExtension);
|
||||
if(newPath && newPath !== pathNoExtension) {
|
||||
await app.fileManager.renameFile(file,`${newPath}.${file.extension}`);
|
||||
}
|
||||
}
|
||||
1
ea-scripts/Rename Image.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" stroke="#000" viewBox="0 0 122.88 102.06"><path stroke-linecap="round" stroke-width="4" d="M8.18,23.12h67.09v5.39H8.18c-0.77,0-1.47,0.31-1.98,0.82c-0.5,0.51-0.82,1.21-0.82,1.98v39.46c0,0.77,0.31,1.47,0.82,1.98 c0.51,0.5,1.21,0.82,1.98,0.82h67.09v5.39H8.18c-2.24,0-4.29-0.92-5.77-2.4L2.4,76.53C0.92,75.05,0,73.01,0,70.76V31.3 c0-2.24,0.92-4.29,2.4-5.77l0.01-0.01C3.89,24.04,5.94,23.12,8.18,23.12L8.18,23.12z M71.77,53.85c-1.52,0-2.75-1.23-2.75-2.75 c0-1.52,1.23-2.75,2.75-2.75h12.78V18.04c-0.39-3.8-1.56-6.62-3.34-8.6c-1.93-2.16-4.67-3.43-7.99-3.98 c-1.49-0.24-2.51-1.65-2.26-3.15c0.24-1.49,1.65-2.51,3.15-2.26c4.54,0.75,8.37,2.57,11.19,5.74c0.72,0.8,1.37,1.69,1.94,2.66 c0.72-1.25,1.58-2.35,2.56-3.32c2.94-2.92,6.88-4.51,11.59-5.1c1.51-0.18,2.88,0.89,3.06,2.4c0.18,1.51-0.89,2.88-2.4,3.06 c-3.52,0.44-6.38,1.54-8.39,3.53c-1.99,1.97-3.25,4.91-3.61,9.04v5.07h24.65c2.24,0,4.29,0.92,5.77,2.4l0.01,0.01 c1.48,1.48,2.4,3.53,2.4,5.77v39.46c0,2.24-0.92,4.29-2.4,5.77l-0.01,0.01c-1.48,1.48-3.53,2.4-5.77,2.4H90.05v5.07 c0.36,4.13,1.62,7.08,3.61,9.04c2,1.98,4.86,3.09,8.39,3.53c1.51,0.18,2.58,1.56,2.4,3.06c-0.18,1.51-1.55,2.58-3.06,2.4 c-4.7-0.59-8.65-2.18-11.59-5.1c-0.98-0.97-1.84-2.07-2.56-3.32c-0.57,0.97-1.22,1.85-1.94,2.66c-2.83,3.16-6.66,4.99-11.19,5.74 c-1.49,0.24-2.9-0.77-3.15-2.26c-0.24-1.49,0.77-2.9,2.26-3.15c3.32-0.55,6.06-1.81,7.99-3.98c1.78-1.99,2.94-4.81,3.34-8.6 l0-30.17H71.77L71.77,53.85L71.77,53.85z M90.05,28.5v19.84h12.98c1.52,0,2.75,1.23,2.75,2.75c0,1.52-1.23,2.75-2.75,2.75H90.05 v19.71h24.65c0.77,0,1.47-0.31,1.98-0.82c0.5-0.51,0.82-1.21,0.82-1.98V31.3c0-0.77-0.31-1.47-0.82-1.98 c-0.51-0.5-1.21-0.82-1.98-0.82H90.05L90.05,28.5z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -14,6 +14,11 @@ https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.h
|
||||
```javascript
|
||||
*/
|
||||
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.7.19")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
let repeatNum = parseInt(await utils.inputPrompt("repeat times?","number","5"));
|
||||
if(!repeatNum) {
|
||||
new Notice("Please enter a number.");
|
||||
@@ -43,38 +48,25 @@ const heightDistance = selectedElements[1].height - selectedElements[0].height;
|
||||
const angleDistance = selectedElements[1].angle - selectedElements[0].angle;
|
||||
|
||||
const bgColor1 = ea.colorNameToHex(selectedElements[0].backgroundColor);
|
||||
const rgbBgColor1 = parseColorString(bgColor1);
|
||||
const cmBgColor1 = ea.getCM(bgColor1);
|
||||
const bgColor2 = ea.colorNameToHex(selectedElements[1].backgroundColor);
|
||||
const rgbBgColor2 = parseColorString(bgColor2);
|
||||
let bgHDistance = 0;
|
||||
let bgSDistance = 0;
|
||||
let bgLDistance = 0;
|
||||
|
||||
if(rgbBgColor1 && rgbBgColor2) {
|
||||
const bgHsl1 = ea.rgbToHsl([rgbBgColor1.value[0], rgbBgColor1.value[1], rgbBgColor1.value[2]]);
|
||||
const bgHsl2 = ea.rgbToHsl([rgbBgColor2.value[0], rgbBgColor2.value[1], rgbBgColor2.value[2]]);
|
||||
|
||||
bgHDistance = bgHsl2[0] - bgHsl1[0];
|
||||
bgSDistance = bgHsl2[1] - bgHsl1[1];
|
||||
bgLDistance = bgHsl2[2] - bgHsl1[2];
|
||||
}
|
||||
let cmBgColor2 = ea.getCM(bgColor2);
|
||||
const isBgTransparent = cmBgColor1.alpha === 0 || cmBgColor2.alpha === 0;
|
||||
const bgHDistance = cmBgColor2.hue - cmBgColor1.hue;
|
||||
const bgSDistance = cmBgColor2.saturation - cmBgColor1.saturation;
|
||||
const bgLDistance = cmBgColor2.lightness - cmBgColor1.lightness;
|
||||
const bgADistance = cmBgColor2.alpha - cmBgColor1.alpha;
|
||||
|
||||
const strokeColor1 = ea.colorNameToHex(selectedElements[0].strokeColor);
|
||||
const rgbStrokeColor1 = parseColorString(strokeColor1);
|
||||
const cmStrokeColor1 = ea.getCM(strokeColor1);
|
||||
const strokeColor2 = ea.colorNameToHex(selectedElements[1].strokeColor);
|
||||
const rgbStrokeColor2 = parseColorString(strokeColor2);
|
||||
let strokeHDistance = 0;
|
||||
let strokeSDistance = 0;
|
||||
let strokeLDistance = 0;
|
||||
let cmStrokeColor2 = ea.getCM(strokeColor2);
|
||||
const isStrokeTransparent = cmStrokeColor1.alpha === 0 || cmStrokeColor2.alpha ===0;
|
||||
const strokeHDistance = cmStrokeColor2.hue - cmStrokeColor1.hue;
|
||||
const strokeSDistance = cmStrokeColor2.saturation - cmStrokeColor1.saturation;
|
||||
const strokeLDistance = cmStrokeColor2.lightness - cmStrokeColor1.lightness;
|
||||
const strokeADistance = cmStrokeColor2.alpha - cmStrokeColor1.alpha;
|
||||
|
||||
if(rgbStrokeColor1 && rgbStrokeColor2) {
|
||||
const strokeHsl1 = ea.rgbToHsl([rgbStrokeColor1.value[0], rgbStrokeColor1.value[1], rgbStrokeColor1.value[2]]);
|
||||
const strokeHsl2 = ea.rgbToHsl([rgbStrokeColor2.value[0], rgbStrokeColor2.value[1], rgbStrokeColor2.value[2]]);
|
||||
|
||||
strokeHDistance = strokeHsl2[0] - strokeHsl1[0];
|
||||
strokeSDistance = strokeHsl2[1] - strokeHsl1[1];
|
||||
strokeLDistance = strokeHsl2[2] - strokeHsl1[2];
|
||||
}
|
||||
|
||||
ea.copyViewElementsToEAforEditing(selectedElements);
|
||||
for(let i=0; i<repeatNum; i++) {
|
||||
@@ -106,262 +98,19 @@ for(let i=0; i<repeatNum; i++) {
|
||||
}
|
||||
}
|
||||
|
||||
if(rgbBgColor1 && rgbBgColor2) {
|
||||
const bgHsl2 = ea.rgbToHsl([rgbBgColor2.value[0], rgbBgColor2.value[1], rgbBgColor2.value[2]]);
|
||||
const newBgH = bgHsl2[0] + bgHDistance * (i + 1);
|
||||
const newBgS = bgHsl2[1] + bgSDistance * (i + 1);
|
||||
const newBgL = bgHsl2[2] + bgLDistance * (i + 1);
|
||||
|
||||
if(newBgH >= 0 && newBgH <= 360 && newBgS >= 0 && newBgS <= 100 && newBgL >= 0 && newBgL <= 100) {
|
||||
const newBgRgb = ea.hslToRgb([newBgH, newBgS, newBgL]);
|
||||
newEl.backgroundColor = rgbColorToString(newBgRgb, rgbBgColor1.model);
|
||||
}
|
||||
if(!isBgTransparent) {
|
||||
cmBgColor2 = cmBgColor2.hueBy(bgHDistance).saturateBy(bgSDistance).lighterBy(bgLDistance).alphaBy(bgADistance);
|
||||
newEl.backgroundColor = cmBgColor2.stringHEX();
|
||||
} else {
|
||||
newEl.backgroundColor = "transparent";
|
||||
}
|
||||
|
||||
if(rgbStrokeColor1 && rgbStrokeColor2) {
|
||||
const strokeHsl2 = ea.rgbToHsl([rgbStrokeColor2.value[0], rgbStrokeColor2.value[1], rgbStrokeColor2.value[2]]);
|
||||
const newStrokeH = strokeHsl2[0] + strokeHDistance * (i + 1);
|
||||
const newStrokeS = strokeHsl2[1] + strokeSDistance * (i + 1);
|
||||
const newStrokeL = strokeHsl2[2] + strokeLDistance * (i + 1);
|
||||
|
||||
if(newStrokeH >= 0 && newStrokeH <= 360 && newStrokeS >= 0 && newStrokeS <= 100 && newStrokeL >= 0 && newStrokeL <= 100) {
|
||||
const newStrokeRgb = ea.hslToRgb([newStrokeH, newStrokeS, newStrokeL]);
|
||||
newEl.strokeColor = rgbColorToString(newStrokeRgb, rgbStrokeColor1.model);
|
||||
}
|
||||
if(!isStrokeTransparent) {
|
||||
cmStrokeColor2 = cmStrokeColor2.hueBy(strokeHDistance).saturateBy(strokeSDistance).lighterBy(strokeLDistance).alphaBy(strokeADistance);
|
||||
newEl.strokeColor = cmStrokeColor2.stringHEX();
|
||||
} else {
|
||||
newEl.strokeColor = "transparent";
|
||||
}
|
||||
}
|
||||
|
||||
await ea.addElementsToView(false, false, true);
|
||||
|
||||
function parseColorString(string) {
|
||||
var prefix = string.substring(0, 3).toLowerCase();
|
||||
var val;
|
||||
var model;
|
||||
switch (prefix) {
|
||||
case 'hsl':
|
||||
val = ea.hslToRgb(parseHslColorString(string));
|
||||
model = 'hsl';
|
||||
break;
|
||||
case 'hwb':
|
||||
val = hwbToRgb(parseHwbColorString(string));
|
||||
model = 'hwb';
|
||||
break;
|
||||
default:
|
||||
val = parseRgbColorString(string);
|
||||
model = 'rgb';
|
||||
break;
|
||||
}
|
||||
|
||||
if (!val) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {model: model, value: val};
|
||||
};
|
||||
|
||||
function parseRgbColorString(string) {
|
||||
if (!string) {
|
||||
return null;
|
||||
}
|
||||
var colorNames={};
|
||||
|
||||
var abbr = /^#([a-f0-9]{3,4})$/i;
|
||||
var hex = /^#([a-f0-9]{6})([a-f0-9]{2})?$/i;
|
||||
var rgba = /^rgba?\(\s*([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)\s*(?:[,|\/]\s*([+-]?[\d\.]+)(%?)\s*)?\)$/;
|
||||
var per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,?\s*([+-]?[\d\.]+)\%\s*,?\s*([+-]?[\d\.]+)\%\s*(?:[,|\/]\s*([+-]?[\d\.]+)(%?)\s*)?\)$/;
|
||||
var keyword = /^(\w+)$/;
|
||||
|
||||
var rgb = [0, 0, 0, 1];
|
||||
var match;
|
||||
var i;
|
||||
var hexAlpha;
|
||||
|
||||
if (match = string.match(hex)) {
|
||||
hexAlpha = match[2];
|
||||
match = match[1];
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
var i2 = i * 2;
|
||||
rgb[i] = parseInt(match.slice(i2, i2 + 2), 16);
|
||||
}
|
||||
|
||||
if (hexAlpha) {
|
||||
rgb[3] = parseInt(hexAlpha, 16) / 255;
|
||||
}
|
||||
} else if (match = string.match(abbr)) {
|
||||
match = match[1];
|
||||
hexAlpha = match[3];
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
rgb[i] = parseInt(match[i] + match[i], 16);
|
||||
}
|
||||
|
||||
if (hexAlpha) {
|
||||
rgb[3] = parseInt(hexAlpha + hexAlpha, 16) / 255;
|
||||
}
|
||||
} else if (match = string.match(rgba)) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
rgb[i] = parseInt(match[i + 1], 0);
|
||||
}
|
||||
|
||||
if (match[4]) {
|
||||
if (match[5]) {
|
||||
rgb[3] = parseFloat(match[4]) * 0.01;
|
||||
} else {
|
||||
rgb[3] = parseFloat(match[4]);
|
||||
}
|
||||
}
|
||||
} else if (match = string.match(per)) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55);
|
||||
}
|
||||
|
||||
if (match[4]) {
|
||||
if (match[5]) {
|
||||
rgb[3] = parseFloat(match[4]) * 0.01;
|
||||
} else {
|
||||
rgb[3] = parseFloat(match[4]);
|
||||
}
|
||||
}
|
||||
} else if (match = string.match(keyword)) {
|
||||
if (match[1] === 'transparent') {
|
||||
return [0, 0, 0, 0];
|
||||
}
|
||||
|
||||
if (!hasOwnProperty.call(colorNames, match[1])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
rgb = colorNames[match[1]];
|
||||
rgb[3] = 1;
|
||||
|
||||
return rgb;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
rgb[i] = clamp(rgb[i], 0, 255);
|
||||
}
|
||||
rgb[3] = clamp(rgb[3], 0, 1);
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
function parseHslColorString(string) {
|
||||
if (!string) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var hsl = /^hsla?\(\s*([+-]?(?:\d{0,3}\.)?\d+)(?:deg)?\s*,?\s*([+-]?[\d\.]+)%\s*,?\s*([+-]?[\d\.]+)%\s*(?:[,|\/]\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/;
|
||||
var match = string.match(hsl);
|
||||
|
||||
if (match) {
|
||||
var alpha = parseFloat(match[4]);
|
||||
var h = ((parseFloat(match[1]) % 360) + 360) % 360;
|
||||
var s = clamp(parseFloat(match[2]), 0, 100);
|
||||
var l = clamp(parseFloat(match[3]), 0, 100);
|
||||
var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1);
|
||||
|
||||
return [h, s, l, a];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function parseHwbColorString(string) {
|
||||
if (!string) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var hwb = /^hwb\(\s*([+-]?\d{0,3}(?:\.\d+)?)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/;
|
||||
var match = string.match(hwb);
|
||||
|
||||
if (match) {
|
||||
var alpha = parseFloat(match[4]);
|
||||
var h = ((parseFloat(match[1]) % 360) + 360) % 360;
|
||||
var w = clamp(parseFloat(match[2]), 0, 100);
|
||||
var b = clamp(parseFloat(match[3]), 0, 100);
|
||||
var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1);
|
||||
return [h, w, b, a];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function rgbColorToString(color, model) {
|
||||
switch (model) {
|
||||
case 'hsl':
|
||||
return rgbColorToHslString(color);
|
||||
case 'hwb':
|
||||
return rgbColorToHwbString(color);
|
||||
default:
|
||||
return ea.rgbToHexString(color);
|
||||
}
|
||||
}
|
||||
|
||||
function rgbColorToHslString(rgb) {
|
||||
var hsl = ea.rgbToHsl(rgb);
|
||||
return 'hsl(' + hsl[0] + ', ' + hsl[1] + '%, ' + hsl[2] + '%)'
|
||||
};
|
||||
|
||||
function rgbColorToHwbString(rgb) {
|
||||
var hwb = rgbToHwb(rgb);
|
||||
|
||||
return 'hwb(' + hwb[0] + ', ' + hwb[1] + '%, ' + hwb[2] + '%)';
|
||||
};
|
||||
|
||||
function rgbToHwb(rgb) {
|
||||
const r = rgb[0];
|
||||
const g = rgb[1];
|
||||
let b = rgb[2];
|
||||
const h = convert.rgb.hsl(rgb)[0];
|
||||
const w = 1 / 255 * Math.min(r, Math.min(g, b));
|
||||
|
||||
b = 1 - 1 / 255 * Math.max(r, Math.max(g, b));
|
||||
|
||||
return [h, w * 100, b * 100];
|
||||
};
|
||||
|
||||
function hwbToRgb(hwb) {
|
||||
const h = hwb[0] / 360;
|
||||
let wh = hwb[1] / 100;
|
||||
let bl = hwb[2] / 100;
|
||||
const ratio = wh + bl;
|
||||
let f;
|
||||
|
||||
// Wh + bl cant be > 1
|
||||
if (ratio > 1) {
|
||||
wh /= ratio;
|
||||
bl /= ratio;
|
||||
}
|
||||
|
||||
const i = Math.floor(6 * h);
|
||||
const v = 1 - bl;
|
||||
f = 6 * h - i;
|
||||
|
||||
if ((i & 0x01) !== 0) {
|
||||
f = 1 - f;
|
||||
}
|
||||
|
||||
const n = wh + f * (v - wh);
|
||||
let r;
|
||||
let g;
|
||||
let b;
|
||||
switch (i) {
|
||||
default:
|
||||
case 6:
|
||||
case 0: r = v; g = n; b = wh; break;
|
||||
case 1: r = n; g = v; b = wh; break;
|
||||
case 2: r = wh; g = v; b = n; break;
|
||||
case 3: r = wh; g = n; b = v; break;
|
||||
case 4: r = n; g = wh; b = v; break;
|
||||
case 5: r = v; g = wh; b = n; break;
|
||||
}
|
||||
|
||||
return [r * 255, g * 255, b * 255];
|
||||
}
|
||||
|
||||
function clamp(num, min, max) {
|
||||
return Math.min(Math.max(min, num), max);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||

|
||||
|
||||
Use this script to set the background color of unclosed (i.e. open) line objects by creating a clone of the object. The script will set the stroke color of the clone to transparent and will add a straight line to close the object. Use settings to define the default background color, the fill style, and the strokeWidth of the clone. By default the clone will be grouped with the original object, you can disable this also in settings.
|
||||
Use this script to set the background color of unclosed (i.e. open) line and freedraw objects by creating a clone of the object. The script will set the stroke color of the clone to transparent and will add a straight line to close the object. Use settings to define the default background color, the fill style, and the strokeWidth of the clone. By default the clone will be grouped with the original object, you can disable this also in settings.
|
||||
|
||||
```javascript
|
||||
*/
|
||||
@@ -41,9 +41,9 @@ const backgroundColor = settings["Background Color"].value;
|
||||
const fillStyle = settings["Fill Style"].value;
|
||||
const shouldGroup = settings["Group 'shadow' with original"].value;
|
||||
|
||||
const elements = ea.getViewSelectedElements().filter(el=>el.type==="line");
|
||||
const elements = ea.getViewSelectedElements().filter(el=>el.type==="line" || el.type==="freedraw");
|
||||
if(elements.length === 0) {
|
||||
new Notice("No line object is selected");
|
||||
new Notice("No line or freedraw object is selected");
|
||||
}
|
||||
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
|
||||
282
ea-scripts/Slideshow.md
Normal file
@@ -0,0 +1,282 @@
|
||||
/*
|
||||

|
||||

|
||||
The script will convert your drawing into a slideshow presentation.
|
||||
|
||||
```javascript
|
||||
*/
|
||||
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.8.2")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
//constants
|
||||
const STEPCOUNT = 100;
|
||||
const FRAME_SLEEP = 1; //milliseconds
|
||||
|
||||
//utility & convenience functions
|
||||
const doc = ea.targetView.ownerDocument;
|
||||
const win = ea.targetView.ownerWindow;
|
||||
const api = ea.getExcalidrawAPI();
|
||||
const contentEl = ea.targetView.contentEl;
|
||||
const sleep = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
//clean up potential clutter from previous run
|
||||
window.removePresentationEventHandlers?.();
|
||||
|
||||
//check if line or arrow is selected, if not inform the user and terminate presentation
|
||||
const lineEl = ea.getViewSelectedElement();
|
||||
if(!lineEl || !["line","arrow"].contains(lineEl.type)) {
|
||||
new Notice("Please select the line or arrow for the presentation path");
|
||||
return;
|
||||
}
|
||||
|
||||
//goto fullscreen
|
||||
if(app.isMobile) {
|
||||
ea.viewToggleFullScreen(true);
|
||||
} else {
|
||||
await contentEl.requestFullscreen();
|
||||
await sleep(50);
|
||||
ea.setViewModeEnabled(true);
|
||||
}
|
||||
const deltaWidth = () => contentEl.clientWidth-api.getAppState().width;
|
||||
let watchdog = 0;
|
||||
while (deltaWidth()>50 && watchdog++<20) await sleep(100); //wait for Excalidraw to resize to fullscreen
|
||||
contentEl.querySelector(".layer-ui__wrapper").addClass("excalidraw-hidden");
|
||||
|
||||
//hide the arrow and save the arrow color before doing so
|
||||
const originalColor = {
|
||||
strokeColor: lineEl.strokeColor,
|
||||
backgroundColor: lineEl.backgroundColor
|
||||
}
|
||||
ea.copyViewElementsToEAforEditing([lineEl]);
|
||||
ea.getElement(lineEl.id).strokeColor = "transparent";
|
||||
ea.getElement(lineEl.id).backgroundColor = "transparent";
|
||||
await ea.addElementsToView();
|
||||
|
||||
//----------------------------
|
||||
//scroll-to-location functions
|
||||
//----------------------------
|
||||
let slide = -1;
|
||||
const slideCount = Math.floor(lineEl.points.length/2)-1;
|
||||
|
||||
const getNextSlide = (forward) => {
|
||||
slide = forward
|
||||
? slide < slideCount ? slide + 1 : 0
|
||||
: slide <= 0 ? slideCount : slide - 1;
|
||||
return {pointA:lineEl.points[slide*2], pointB:lineEl.points[slide*2+1]}
|
||||
}
|
||||
|
||||
const getSlideRect = ({pointA, pointB}) => {
|
||||
const {width, height} = api.getAppState();
|
||||
const x1 = lineEl.x+pointA[0];
|
||||
const y1 = lineEl.y+pointA[1];
|
||||
const x2 = lineEl.x+pointB[0];
|
||||
const y2 = lineEl.y+pointB[1];
|
||||
const ratioX = width/Math.abs(x1-x2);
|
||||
const ratioY = height/Math.abs(y1-y2);
|
||||
let ratio = ratioX<ratioY?ratioX:ratioY;
|
||||
if (ratio < 0.1) ratio = 0.1;
|
||||
if (ratio > 10) ratio = 10;
|
||||
const deltaX = (ratio===ratioY)?(width/ratio - Math.abs(x1-x2))/2:0;
|
||||
const deltaY = (ratio===ratioX)?(height/ratio - Math.abs(y1-y2))/2:0;
|
||||
return {
|
||||
left: (x1<x2?x1:x2)-deltaX,
|
||||
top: (y1<y2?y1:y2)-deltaY,
|
||||
right: (x1<x2?x2:x1)+deltaX,
|
||||
bottom: (y1<y2?y2:y1)+deltaY,
|
||||
nextZoom: ratio
|
||||
};
|
||||
}
|
||||
|
||||
let busy = false;
|
||||
const scrollToNextRect = async ({left,top,right,bottom,nextZoom}) => {
|
||||
let watchdog = 0;
|
||||
while(busy && watchdog++<15) await(100);
|
||||
if(busy && watchdog >= 15) return;
|
||||
busy = true;
|
||||
const {scrollX, scrollY, zoom} = api.getAppState();
|
||||
const zoomStep = (zoom.value-nextZoom)/STEPCOUNT;
|
||||
const xStep = (left+scrollX)/STEPCOUNT;
|
||||
const yStep = (top+scrollY)/STEPCOUNT;
|
||||
for(i=1;i<=STEPCOUNT;i++) {
|
||||
api.updateScene({
|
||||
appState: {
|
||||
scrollX:scrollX-(xStep*i),
|
||||
scrollY:scrollY-(yStep*i),
|
||||
zoom:{value:zoom.value-zoomStep*i},
|
||||
shouldCacheIgnoreZoom:true,
|
||||
}
|
||||
});
|
||||
await sleep(FRAME_SLEEP);
|
||||
}
|
||||
api.updateScene({appState:{shouldCacheIgnoreZoom:false}});
|
||||
busy = false;
|
||||
}
|
||||
|
||||
const navigate = async (dir) => {
|
||||
const forward = dir === "fwd";
|
||||
const prevSlide = slide;
|
||||
const nextSlide = getNextSlide(forward);
|
||||
|
||||
//exit if user navigates from last slide forward or first slide backward
|
||||
const shouldExit = forward
|
||||
? slide<=prevSlide
|
||||
: slide>=prevSlide;
|
||||
if(shouldExit) {
|
||||
if(!app.isMobile) await doc.exitFullscreen();
|
||||
exitPresentation();
|
||||
return;
|
||||
}
|
||||
if(slideNumberEl) slideNumberEl.innerText = (slide+1).toString();
|
||||
const nextRect = getSlideRect(nextSlide);
|
||||
await scrollToNextRect(nextRect);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
//Slideshow control
|
||||
//--------------------------------------
|
||||
//create slideshow controlpanel container
|
||||
const top = contentEl.innerHeight;
|
||||
const left = contentEl.innerWidth;
|
||||
const containerEl = contentEl.createDiv({
|
||||
cls: ["excalidraw","excalidraw-presentation-panel"],
|
||||
attr: {
|
||||
style: `
|
||||
width: calc(var(--default-button-size)*3);
|
||||
z-index:5;
|
||||
position: absolute;
|
||||
top:calc(${top}px - var(--default-button-size)*2);
|
||||
left:calc(${left}px - var(--default-button-size)*3.5);`
|
||||
}
|
||||
});
|
||||
const panelColumn = containerEl.createDiv({
|
||||
cls: "panelColumn",
|
||||
});
|
||||
let slideNumberEl;
|
||||
panelColumn.createDiv({
|
||||
cls: ["Island", "buttonList"],
|
||||
attr: {
|
||||
style: `
|
||||
height: calc(var(--default-button-size)*1.5);
|
||||
width: 100%;
|
||||
background: var(--island-bg-color);`,
|
||||
}
|
||||
}, el=>{
|
||||
el.createEl("button",{
|
||||
text: "<",
|
||||
attr: {
|
||||
style: `
|
||||
margin-top: calc(var(--default-button-size)*0.25);
|
||||
margin-left: calc(var(--default-button-size)*0.25);`
|
||||
}
|
||||
}, button => button .onclick = () => navigate("bkwd"));
|
||||
el.createEl("button",{
|
||||
text: ">",
|
||||
attr: {
|
||||
style: `
|
||||
margin-top: calc(var(--default-button-size)*0.25);
|
||||
margin-right: calc(var(--default-button-size)*0.25);`
|
||||
}
|
||||
}, button => button.onclick = () => navigate("fwd"));
|
||||
slideNumberEl = el.createEl("span",{
|
||||
text: "1",
|
||||
cls: ["ToolIcon__keybinding"],
|
||||
})
|
||||
});
|
||||
|
||||
//keyboard navigation
|
||||
const keydownListener = (e) => {
|
||||
e.preventDefault();
|
||||
switch(e.key) {
|
||||
case "escape":
|
||||
if(app.isMobile) exitPresentation();
|
||||
break;
|
||||
case "ArrowRight":
|
||||
case "ArrowDown":
|
||||
navigate("fwd");
|
||||
break;
|
||||
case "ArrowLeft":
|
||||
case "ArrowUp":
|
||||
navigate("bkwd");
|
||||
break;
|
||||
}
|
||||
}
|
||||
doc.addEventListener('keydown',keydownListener);
|
||||
|
||||
//slideshow panel drag
|
||||
let pos1 = pos2 = pos3 = pos4 = 0;
|
||||
|
||||
const updatePosition = (deltaY = 0, deltaX = 0) => {
|
||||
const {
|
||||
offsetTop,
|
||||
offsetLeft,
|
||||
clientWidth: width,
|
||||
clientHeight: height,
|
||||
} = containerEl;
|
||||
containerEl.style.top = (offsetTop - deltaY) + 'px';
|
||||
containerEl.style.left = (offsetLeft - deltaX) + 'px';
|
||||
}
|
||||
|
||||
const pointerUp = () => {
|
||||
win.removeEventListener('pointermove', onDrag, true);
|
||||
}
|
||||
|
||||
const pointerDown = (e) => {
|
||||
pos3 = e.clientX;
|
||||
pos4 = e.clientY;
|
||||
win.addEventListener('pointermove', onDrag, true);
|
||||
}
|
||||
|
||||
const onDrag = (e) => {
|
||||
e.preventDefault();
|
||||
pos1 = pos3 - e.clientX;
|
||||
pos2 = pos4 - e.clientY;
|
||||
pos3 = e.clientX;
|
||||
pos4 = e.clientY;
|
||||
updatePosition(pos2, pos1);
|
||||
}
|
||||
|
||||
containerEl.addEventListener('pointerdown', pointerDown, false);
|
||||
win.addEventListener('pointerup', pointerUp, false);
|
||||
|
||||
//event listners for terminating the presentation
|
||||
window.removePresentationEventHandlers = () => {
|
||||
ea.onLinkClickHook = null;
|
||||
containerEl.parentElement?.removeChild(containerEl);
|
||||
if(!app.isMobile) win.removeEventListener('fullscreenchange', fullscreenListener);
|
||||
doc.removeEventListener('keydown',keydownListener);
|
||||
win.removeEventListener('pointerup',pointerUp);
|
||||
contentEl.querySelector(".layer-ui__wrapper").removeClass("excalidraw-hidden");
|
||||
delete window.removePresentationEventHandlers;
|
||||
}
|
||||
|
||||
const exitPresentation = () => {
|
||||
window.removePresentationEventHandlers?.();
|
||||
if(app.isMobile) ea.viewToggleFullScreen(true);
|
||||
else ea.setViewModeEnabled(false);
|
||||
ea.clear();
|
||||
ea.copyViewElementsToEAforEditing(ea.getViewElements().filter(el=>el.id === lineEl.id));
|
||||
ea.getElement(lineEl.id).strokeColor = originalColor.strokeColor;
|
||||
ea.getElement(lineEl.id).backgroundColor = originalColor.backgroundColor;
|
||||
ea.addElementsToView();
|
||||
ea.selectElementsInView(ea.getElements());
|
||||
}
|
||||
|
||||
ea.onLinkClickHook = () => {
|
||||
exitPresentation();
|
||||
return true;
|
||||
};
|
||||
|
||||
const fullscreenListener = (e) => {
|
||||
e.preventDefault();
|
||||
exitPresentation();
|
||||
}
|
||||
|
||||
if(!app.isMobile) {
|
||||
win.addEventListener('fullscreenchange', fullscreenListener);
|
||||
}
|
||||
|
||||
//navigate to the first slide on start
|
||||
setTimeout(()=>navigate("fwd"));
|
||||
1
ea-scripts/Slideshow.svg
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
49
ea-scripts/Text Arch.md
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||

|
||||
|
||||
Fit a text to the arch of a circle. The script will prompt you for the radius of the circle and then split your text to individual letters and place each letter to the arch defined by the radius. Setting a lower radius value will increase the arching of the text. Note that the arched-text will no longer be editable as a text element and it will no longer function as a markdown link. Emojis are currently not supported.
|
||||
|
||||
```javascript
|
||||
*/
|
||||
el = ea.getViewSelectedElement();
|
||||
if(!el || el.type!=="text") {
|
||||
new Notice("Please select a text element");
|
||||
return;
|
||||
}
|
||||
|
||||
ea.style.fontSize = el.fontSize;
|
||||
ea.style.fontFamily = el.fontFamily;
|
||||
ea.style.strokeColor = el.strokeColor;
|
||||
ea.style.opacity = el.opacity;
|
||||
|
||||
const r = parseInt (await utils.inputPrompt("The radius of the arch you'd like to fit the text to","number","150"));
|
||||
const archAbove = await utils.suggester(["Arch above","Arch below"],[true,false]);
|
||||
|
||||
if(isNaN(r)) {
|
||||
new Notice("The radius is not a number");
|
||||
return;
|
||||
}
|
||||
|
||||
circlePoint = (angle) => archAbove
|
||||
? [
|
||||
r * Math.sin(angle),
|
||||
-r * Math.cos(angle)
|
||||
]
|
||||
: [
|
||||
-r * Math.sin(angle),
|
||||
r * Math.cos(angle)
|
||||
];
|
||||
|
||||
let rot = (archAbove ? -0.5 : 0.5) * ea.measureText(el.text).width/r;
|
||||
|
||||
let objectIDs = [];
|
||||
for(i=0;i<el.text.length;i++) {
|
||||
const character = el.text.substring(i,i+1);
|
||||
const width = ea.measureText(character).width;
|
||||
ea.style.angle = rot;
|
||||
const [x,y] = circlePoint(rot);
|
||||
rot += (archAbove ? 1 : -1) *width / r;
|
||||
objectIDs.push(ea.addText(x,y,character));
|
||||
}
|
||||
ea.addToGroup(objectIDs);
|
||||
ea.addElementsToView(true);
|
||||
1
ea-scripts/Text Arch.svg
Normal file
@@ -0,0 +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>
|
||||
|
After Width: | Height: | Size: 309 B |
52
ea-scripts/Uniform size.md
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
|
||||

|
||||
|
||||
The script will standardize the sizes of rectangles, diamonds and ellipses adjusting all the elements to match the largest width and height within the group.
|
||||
|
||||
```javascript
|
||||
*/
|
||||
const boxShapesDispaly=["○ ellipse","□ rectangle","◇ diamond"];
|
||||
const boxShapes=["ellipse","rectangle","diamond"];
|
||||
|
||||
let editedElements = [];
|
||||
|
||||
const elements = ea.getViewSelectedElements().filter(el=>boxShapes.contains(el.type));
|
||||
if(elements.length===0) {
|
||||
new Notice("No rectangle, or diamond or ellipse elements are selected. Please select some elements");
|
||||
return;
|
||||
}
|
||||
|
||||
const typeSet = new Set();
|
||||
elements.forEach(el=>typeSet.add(el.type));
|
||||
|
||||
const elementType = await utils.suggester(
|
||||
Array.from(typeSet).map((item) => {
|
||||
switch(item) {
|
||||
case "ellipse": return "○ ellipse";
|
||||
case "rectangle": return "□ rectangle";
|
||||
case "diamond": return "◇ diamond";
|
||||
default: return item;
|
||||
}
|
||||
}),
|
||||
Array.from(typeSet),
|
||||
"Select element types to resize"
|
||||
);
|
||||
|
||||
if(!elementType) return;
|
||||
|
||||
ea.copyViewElementsToEAforEditing(elements.filter(el=>el.type===elementType));
|
||||
let width = height = 0;
|
||||
ea.getElements().forEach(el=>{
|
||||
if(el.width>width) width = el.width;
|
||||
if(el.height>height) height = el.height;
|
||||
})
|
||||
|
||||
ea.getElements().forEach(el=>{
|
||||
el.width = width;
|
||||
el.height = height;
|
||||
})
|
||||
|
||||
const ids = ea.getElements().map(el=>el.id);
|
||||
await ea.addElementsToView(false,true);
|
||||
ea.getExcalidrawAPI().updateContainerSize(ea.getViewElements().filter(el=>ids.contains(el.id)));
|
||||
1
ea-scripts/Uniform size.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M40 352c-22.1 0-40 17.9-40 40l0 48c0 22.1 17.9 40 40 40l48 0c22.1 0 40-17.9 40-40l0-48c0-22.1-17.9-40-40-40l-48 0zm192 0c-22.1 0-40 17.9-40 40l0 48c0 22.1 17.9 40 40 40l48 0c22.1 0 40-17.9 40-40l0-48c0-22.1-17.9-40-40-40l-48 0zM40 320l48 0c22.1 0 40-17.9 40-40l0-48c0-22.1-17.9-40-40-40l-48 0c-22.1 0-40 17.9-40 40l0 48c0 22.1 17.9 40 40 40zM232 192c-22.1 0-40 17.9-40 40l0 48c0 22.1 17.9 40 40 40l48 0c22.1 0 40-17.9 40-40l0-48c0-22.1-17.9-40-40-40l-48 0zM40 160l48 0c22.1 0 40-17.9 40-40l0-48c0-22.1-17.9-40-40-40L40 32C17.9 32 0 49.9 0 72l0 48c0 22.1 17.9 40 40 40zM232 32c-22.1 0-40 17.9-40 40l0 48c0 22.1 17.9 40 40 40l48 0c22.1 0 40-17.9 40-40l0-48c0-22.1-17.9-40-40-40l-48 0z"/></svg>
|
||||
|
After Width: | Height: | Size: 930 B |
@@ -3,7 +3,7 @@
|
||||
|
||||
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.
|
||||
|
||||
Similar to Excalidraw standard SHIFT+2 feature: Zoom to fit selected elements, but with the ability to zoom to 1000%. Inspiration: [#272](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/272)
|
||||
Similar to Excalidraw standard <kbd>SHIFT+2</kbd> feature: Zoom to fit selected elements, but with the ability to zoom to 1000%. Inspiration: [#272](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/272)
|
||||
|
||||
See documentation for more details:
|
||||
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
|
||||
|
||||
@@ -6,7 +6,7 @@ If you are enjoying the Excalidraw plugin then please support my work and enthus
|
||||
|
||||
Jump ahead to the [[#List of available scripts]]
|
||||
|
||||
# Intorducing Excalidraw Automate Script Engine
|
||||
# Introducing Excalidraw Automate Script Engine
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/hePJcObHIso" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
Script Engine scripts are installed in the `Downloaded` subfolder of the `Excalidraw Automate script folder` specified in plugin settings.
|
||||
@@ -31,6 +31,7 @@ I would love to include your contribution in the script library. If you have a s
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Add%20Link%20to%20Existing%20File%20and%20Open.svg"/></div>|[[#Add Link to Existing File and Open]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Add%20Link%20to%20New%20Page%20and%20Open.svg"/></div>|[[#Add Link to New Page and Open]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Add%20Next%20Step%20in%20Process.svg"/></div>|[[#Add Next Step in Process]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Auto%20Layout.svg"/></div>|[[#Auto Layout]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Box%20Each%20Selected%20Groups.svg"/></div>|[[#Box Each Selected Groups]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Box%20Selected%20Elements.svg"/></div>|[[#Box Selected Elements]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Change%20shape%20of%20selected%20elements.svg"/></div>|[[#Change shape of selected elements]]|
|
||||
@@ -41,6 +42,7 @@ I would love to include your contribution in the script library. If you have a s
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Copy%20Selected%20Element%20Styles%20to%20Global.svg"/></div>|[[#Copy Selected Element Styles to Global]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Create%20new%20markdown%20file%20and%20embed%20into%20active%20drawing.svg"/></div>|[[#Create new markdown file and embed into active drawing]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Darken%20background%20color.svg"/></div>|[[#Darken background color]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Deconstruct%20selected%20elements%20into%20new%20drawing.svg"/></div>|[[#Deconstruct selected elements into new drawing]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Elbow%20connectors.svg"/></div>|[[#Elbow connectors]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Expand%20rectangles%20horizontally%20keep%20text%20centered.svg"/></div>|[[#Expand rectangles horizontally keep text centered]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Expand%20rectangles%20horizontally.svg"/></div>|[[#Expand rectangles horizontally]]|
|
||||
@@ -51,11 +53,14 @@ I would love to include your contribution in the script library. If you have a s
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Fixed%20spacing.svg"/></div>|[[#Fixed spacing]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Fixed%20vertical%20distance%20between%20centers.svg"/></div>|[[#Fixed vertical distance between centers]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Fixed%20vertical%20distance.svg"/></div>|[[#Fixed vertical distance]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Grid%20Selected%20Images.svg"/></div>|[[#Grid selected images]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Lighten%20background%20color.svg"/></div>|[[#Lighten background color]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Mindmap%20connector.svg"/></div>|[[#Mindmap connector]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Modify%20background%20color%20opacity.svg"/></div>|[[#Modify background color opacity]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Normalize%20Selected%20Arrows.svg"/></div>|[[#Normalize Selected Arrows]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/OCR%20-%20Optical%20Character%20Recognition.svg"/></div>|[[#OCR - Optical Character Recognition]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Organic%20Line.svg"/></div>|[[#Organic Line]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Palette%20loader.svg"/></div>|[[#Palette Loader]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Rename%20Image.svg"/></div>|[[#Rename Image]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Repeat%20Elements.svg"/></div>|[[#Repeat Elements]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Reverse%20arrows.svg"/></div>|[[#Reverse arrows]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Scribble%20Helper.svg"/></div>|[[#Scribble Helper]]|
|
||||
@@ -67,9 +72,10 @@ I would love to include your contribution in the script library. If you have a s
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Link%20Alias.svg"/></div>|[[#Set Link Alias]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Stroke%20Width%20of%20Selected%20Elements.svg"/></div>|[[#Set Stroke Width of Selected Elements]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Text%20Alignment.svg"/></div>|[[#Set Text Alignment]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Slideshow.svg"/></div>|[[#Slideshow]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Split%20text%20by%20lines.svg"/></div>|[[#Split text by lines]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/TheBrain-navigation.svg"/></div>|[[#TheBrain-navigation]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Transfer%20TextElements%20to%20Excalidraw%20markdown%20metadata.svg"/></div>|[[#Transfer TextElements to Excalidraw markdown metadata]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Text%20Arch.svg"/></div>|[[#Text Arch]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Uniform%20size.svg"/></div>|[[#Uniform Size]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Zoom%20to%20Fit%20Selected%20Elements.svg"/></div>|[[#Zoom to Fit Selected Elements]]|
|
||||
|
||||
## Add Connector Point
|
||||
@@ -96,6 +102,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/Add%20Next%20Step%20in%20Process.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will prompt you for the title of the process step, then will create a stick note with the text. If an element is selected then the script will connect this new step with an arrow to the previous step (the selected element). If no element is selected, then the script assumes this is the first step in the process and will only output the sticky note with the text that was entered.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-add-process-step.jpg'></td></tr></table>
|
||||
|
||||
## Auto Layout
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Auto%20Layout.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/Auto%20Layout.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script performs automatic layout for the selected top-level grouping objects. It is powered by <a href='https://github.com/kieler/elkjs'>elkjs</a> and needs to be connected to the Internet.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-auto-layout.png'></td></tr></table>
|
||||
|
||||
## Box Each Selected Groups
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Box%20Each%20Selected%20Groups.md
|
||||
@@ -112,7 +124,7 @@ https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Change%20shape%20of%20selected%20elements.md
|
||||
```
|
||||
<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/Change%20shape%20of%20selected%20elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">The script allows you to change the shape of selected Rectangles, Diamonds and Ellipses.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-change-shape.jpg'></td></tr></table>
|
||||
<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/Change%20shape%20of%20selected%20elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">The script allows you to change the shape and fill style of selected Rectangles, Diamonds, Ellipses, Lines, Arrows and Freedraw.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-change-shape.jpg'></td></tr></table>
|
||||
|
||||
## Connect elements
|
||||
```excalidraw-script-install
|
||||
@@ -156,6 +168,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/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/Darken%20background%20color.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">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.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/darken-lighten-background-color.png'></td></tr></table>
|
||||
|
||||
## Deconstruct selected elements into new drawing
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Deconstruct%20selected%20elements%20into%20new%20drawing.md
|
||||
```
|
||||
<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/Deconstruct%20selected%20elements%20into%20new%20drawing.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Select some elements in the scene. The script will take these elements and move them into a new Excalidraw file, and open that file. The selected elements will also be replaced in your original drawing with the embedded Excalidraw file (the one that was just created). You will be prompted for the file name of the new deconstructed image. The script is useful if you want to break a larger drawing into smaller reusable parts that you want to reference in multiple drawings.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-deconstruct.jpg'></td></tr></table>
|
||||
|
||||
## Elbow connectors
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Elbow%20connectors.md
|
||||
@@ -216,12 +234,24 @@ 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/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/Fixed%20vertical%20distance.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">The script arranges the selected elements vertically with a fixed spacing. When we create an architecture diagram or mind map, we often need to arrange a large number of elements in a fixed spacing. `Fixed spacing` and `Fixed vertical Distance` scripts can save us a lot of time.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-fixed-vertical-distance.png'></td></tr></table>
|
||||
|
||||
## Grid selected images
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Grid%20Selected%20Images.md
|
||||
```
|
||||
<table><tr valign='top'><td class="label">Author</td><td class="data"><a href='https://github.com/7flash'>@7flash</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/Grid%20Selected%20Images.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script arranges selected images into compact grid view, removing gaps in-between, resizing when necessary and breaking into multiple rows/columns.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-grid-selected-images.png'></td></tr></table>
|
||||
|
||||
## Lighten background color
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Lighten%20background%20color.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/Lighten%20background%20color.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script lightens 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.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/darken-lighten-background-color.png'></td></tr></table>
|
||||
|
||||
## Mindmap connector
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Mindmap%20connector.md
|
||||
```
|
||||
<table><tr valign='top'><td class="label">Author</td><td class="data"><a href='https://github.com/xllowl'>@xllowl</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/Mindmap%20connector.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script creates mindmap like lines (only right side and down available currently) for selected elements. The line will start according to the creation time of the elements. So you should create the header element first.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/mindmap%20connector.png'></td></tr></table>
|
||||
|
||||
## Modify background color opacity
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Modify%20background%20color%20opacity.md
|
||||
@@ -234,18 +264,24 @@ 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/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/Normalize%20Selected%20Arrows.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will reset the start and end positions of the selected arrows. The arrow will point to the center of the connected box and will have a gap of 8px from the box.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-normalize-selected-arrows.png'></td></tr></table>
|
||||
|
||||
## OCR - Optical Character Recognition
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/OCR%20-%20Optical%20Character%20Recognition.md
|
||||
```
|
||||
<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/OCR%20-%20Optical%20Character%20Recognition.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">REQUIRES EXCALIDRAW 1.5.15<br>The script will 1) send the selected image file to [taskbone.com](https://taskbone.com) to exctract the text from the image, and 2) will add the text to your drawing as a text element.<br><mark>⚠ Note that you will need to manually paste your token into the script after the first run! ⚠</mark><br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-ocr.jpg'><br><iframe width="560" height="315" src="https://www.youtube.com/embed/W2NMzR8s4eE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></td></tr></table>
|
||||
|
||||
## Organic Line
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Organic%20Line.md
|
||||
```
|
||||
<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/Organic%20Line.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Converts selected freedraw lines such that pencil pressure will decrease from maximum to minimum from the beginning of the line to its end. The resulting line is placed at the back of the layers, under all other items. Helpful when drawing organic mindmaps.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-organic-line.jpg'></td></tr></table>
|
||||
|
||||
## Palette Loader
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Palette%20loader.md
|
||||
```
|
||||
<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/Palette%20loader.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Design your palette at <a href="http://paletton.com/" target="_blank">paletton.com</a> Once you are happy with your colors, click Tables/Export in the bottom right of the screen. Then click "Color swatches/as Sketch Palette", and copy the contents of the page to a markdown file in the palette folder of your vault (default is Excalidraw/Palette)<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-sketch-palette-loader-1.jpg'></td></tr></table>
|
||||
|
||||
## Rename Image
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Rename%20Image.md
|
||||
```
|
||||
<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/Rename%20Image.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Select an image on the canvas and run the script. You will be prompted to provide a new filename / filepath. This cuts down the time to name images you paste from the web or drag and drop from your file system.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/rename-image.png'></td></tr></table>
|
||||
|
||||
## Repeat Elements
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Repeat%20Elements.md
|
||||
@@ -274,7 +310,7 @@ https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20background%20color%20of%20unclosed%20line%20object%20by%20adding%20a%20shadow%20clone.md
|
||||
```
|
||||
<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/Set%20background%20color%20of%20unclosed%20line%20object%20by%20adding%20a%20shadow%20clone.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Use this script to set the background color of unclosed (i.e. open) line objects by creating a clone of the object. The script will set the stroke color of the clone to transparent and will add a straight line to close the object. Use settings to define the default background color, the fill style, and the strokeWidth of the clone. By default the clone will be grouped with the original object, you can disable this also in settings.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-set-background-color-of-unclosed-line.jpg'></td></tr></table>
|
||||
<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/Set%20background%20color%20of%20unclosed%20line%20object%20by%20adding%20a%20shadow%20clone.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Use this script to set the background color of unclosed (i.e. open) line and freedraw objects by creating a clone of the object. The script will set the stroke color of the clone to transparent and will add a straight line to close the object. Use settings to define the default background color, the fill style, and the strokeWidth of the clone. By default the clone will be grouped with the original object, you can disable this also in settings.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-set-background-color-of-unclosed-line.jpg'></td></tr></table>
|
||||
|
||||
## Set Dimensions
|
||||
```excalidraw-script-install
|
||||
@@ -312,26 +348,32 @@ 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/Set%20Text%20Alignment.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Sets text alignment of text block (cetner, right, left). Useful if you want to set a keyboard shortcut for selecting text alignment.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-text-align.jpg'></td></tr></table>
|
||||
|
||||
## Slideshow
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Slideshow.md
|
||||
```
|
||||
<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/Slideshow.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">The script will convert your drawing into a slideshow presentation.<br><iframe width="560" height="315" src="https://www.youtube.com/embed/HhRHFhWkmCk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></td></tr></table>
|
||||
|
||||
## Split text by lines
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Split%20text%20by%20lines.md
|
||||
```
|
||||
<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/Split%20text%20by%20lines.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Split lines of text into separate text elements for easier reorganization<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-split-lines.jpg'></td></tr></table>
|
||||
|
||||
## TheBrain-navigation
|
||||
## Text Arch
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/TheBrain-navigation.md
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Text%20Arch.md
|
||||
```
|
||||
<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/TheBrain-navigation.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">An Excalidraw based graph user interface for your Vault. Requires the <a href="https://github.com/blacksmithgu/obsidian-dataview">Dataview plugin</a>. Generates a graph view similar to that of <a href="https://TheBrain.com">TheBrain</a> plex.<br>Watch an introduction to this script on <a href="https://youtu.be/plYobK-VufM">YouTube</a>.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/TheBrain.jpg'></td></tr></table>
|
||||
<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/Text%20Arch.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Fit a text to the arch of a circle. The script will prompt you for the radius of the circle and then split your text to individual letters and place each letter to the arch defined by the radius. Setting a lower radius value will increase the arching of the text. Note that the arched-text will no longer be editable as a text element and it will no longer function as a markdown link. Emojis are currently not supported.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/text-arch.jpg'></td></tr></table>
|
||||
|
||||
## Transfer TextElements to Excalidraw markdown metadata
|
||||
## Uniform Size
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Transfer%20TextElements%20to%20Excalidraw%20markdown%20metadata.md
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Uniform%20size.md
|
||||
```
|
||||
<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/Transfer%20TextElements%20to%20Excalidraw%20markdown%20metadata.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">The script will delete the selected text elements from the canvas and will copy the text from these text elements into the Excalidraw markdown file as metadata. This means, that the text will no longer be visible in the drawing, however you will be able to search for the text in Obsidian and find the drawing containing this image.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-text-to-metadata.jpg'></td></tr></table>
|
||||
<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/Uniform%20size.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data"><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-uniform-size.jpg"><br>The script will standardize the sizes of rectangles, diamonds and ellipses adjusting all the elements to match the largest width and height within the group.</td></tr></table>
|
||||
|
||||
## Zoom to Fit Selected Elements
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Zoom%20to%20Fit%20Selected%20Elements.md
|
||||
```
|
||||
<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/Zoom%20to%20Fit%20Selected%20Elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Similar to Excalidraw standard SHIFT+2 feature: Zoom to fit selected elements, but with the ability to zoom to 1000%. Inspiration: [#272](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/272)</td></tr></table>
|
||||
<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/Zoom%20to%20Fit%20Selected%20Elements.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Similar to Excalidraw standard <kbd>SHIFT+2</kbd> feature: Zoom to fit selected elements, but with the ability to zoom to 1000%. Inspiration: [#272](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/272)</td></tr></table>
|
||||
|
||||
BIN
images/Mindmap connector1.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
images/mindmap connector.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
images/rename-image.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
images/scripts-auto-layout.png
Normal file
|
After Width: | Height: | Size: 189 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 68 KiB |
BIN
images/scripts-deconstruct.jpg
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
images/scripts-grid-selected-images.png
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
images/scripts-sketch-palette-loader-1.jpg
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
images/scripts-sketch-palette-loader-2.jpg
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
images/scripts-sketch-palette-loader-3.jpg
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
images/scripts-sketch-palette-loader-4.jpg
Normal file
|
After Width: | Height: | Size: 247 KiB |
BIN
images/scripts-slideshow-1.jpg
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
images/scripts-slideshow-2.jpg
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
images/scripts-uniform-size.jpg
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
images/text-arch.jpg
Normal file
|
After Width: | Height: | Size: 95 KiB |
10
manifest-beta.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "1.7.28-beta",
|
||||
"minAppVersion": "0.15.6",
|
||||
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
|
||||
"author": "Zsolt Viczian",
|
||||
"authorUrl": "https://zsolt.blog",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "1.6.27",
|
||||
"minAppVersion": "0.12.16",
|
||||
"version": "1.8.2",
|
||||
"minAppVersion": "0.16.0",
|
||||
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
|
||||
"author": "Zsolt Viczian",
|
||||
"authorUrl": "https://zsolt.blog",
|
||||
|
||||
61
package.json
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "obsidian-excalidraw-plugin",
|
||||
"version": "1.6.27",
|
||||
"version": "1.7.26",
|
||||
"description": "This is an Obsidian.md plugin that lets you view and edit Excalidraw drawings",
|
||||
"main": "lib/index.js",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"files": [
|
||||
"lib/**/*"
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "cross-env NODE_ENV=development rollup --config rollup.config.js -w",
|
||||
"build": "cross-env NODE_ENV=production rollup --config rollup.config.js && terser main.js --compress toplevel=true,passes=2 --output main.js",
|
||||
"build": "cross-env NODE_ENV=production rollup --config rollup.config.js",
|
||||
"lib": "cross-env NODE_ENV=lib rollup --config rollup.config.js -w",
|
||||
"code:fix": "eslint --max-warnings=0 --ext .ts,.tsx ./src --fix"
|
||||
},
|
||||
@@ -17,48 +17,53 @@
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@zsviczian/excalidraw": "0.11.0-obsidian-16",
|
||||
"monkey-around": "^2.3.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "^5.0.0",
|
||||
"roughjs": "^4.5.2",
|
||||
"lz-string": "^1.4.4",
|
||||
"@types/lz-string": "^1.3.34",
|
||||
"clsx": "1.1.1"
|
||||
"@zsviczian/excalidraw": "0.13.0-obsidian-1",
|
||||
"clsx": "^1.1.1",
|
||||
"lz-string": "^1.4.4",
|
||||
"monkey-around": "^2.3.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-scripts": "^5.0.1",
|
||||
"roughjs": "^4.5.2",
|
||||
"colormaster": "1.2.1",
|
||||
"chroma-js": "^2.4.2",
|
||||
"gl-matrix": "^3.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.16.12",
|
||||
"@babel/preset-env": "^7.16.11",
|
||||
"@babel/preset-react": "^7.16.7",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@excalidraw/eslint-config": "1.0.0",
|
||||
"@excalidraw/prettier-config": "1.0.2",
|
||||
"@popperjs/core": "^2.11.5",
|
||||
"@rollup/plugin-babel": "^5.3.0",
|
||||
"@rollup/plugin-commonjs": "^21.0.1",
|
||||
"@rollup/plugin-node-resolve": "^13.1.3",
|
||||
"@rollup/plugin-replace": "^3.0.1",
|
||||
"@rollup/plugin-typescript": "^8.3.0",
|
||||
"rollup-plugin-typescript2": "^0.31.2",
|
||||
"rollup-plugin-web-worker-loader": "^1.6.1",
|
||||
"@types/js-beautify": "^1.13.3",
|
||||
"@types/chroma-js": "^2.1.4",
|
||||
"@types/node": "^15.12.4",
|
||||
"@types/react-dom": "^17.0.11",
|
||||
"@types/react-dom": "^18.0.9",
|
||||
"@zerollup/ts-transform-paths": "^1.7.18",
|
||||
"@popperjs/core": "^2.11.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"html2canvas": "^1.4.0",
|
||||
"nanoid": "^3.1.31",
|
||||
"obsidian": "^0.14.6",
|
||||
"rollup": "^2.70.1",
|
||||
"rollup-plugin-visualizer": "^5.6.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
"tslib": "^2.3.1",
|
||||
"typescript": "^4.5.5",
|
||||
"ttypescript": "^1.5.13",
|
||||
"eslint-config-prettier": "8.3.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"html2canvas": "^1.4.0",
|
||||
"nanoid": "^4.0.0",
|
||||
"obsidian": "^0.16.3",
|
||||
"prettier": "^2.5.1",
|
||||
"@excalidraw/eslint-config": "1.0.0",
|
||||
"@excalidraw/prettier-config": "1.0.2"
|
||||
"rollup": "^2.70.1",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
"rollup-plugin-postprocess": "github:brettz9/rollup-plugin-postprocess#update",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"rollup-plugin-typescript2": "^0.31.2",
|
||||
"rollup-plugin-visualizer": "^5.6.0",
|
||||
"rollup-plugin-web-worker-loader": "^1.6.1",
|
||||
"tslib": "^2.3.1",
|
||||
"ttypescript": "^1.5.13",
|
||||
"typescript": "^4.5.5"
|
||||
},
|
||||
"resolutions": {
|
||||
"@typescript-eslint/typescript-estree": "5.3.0"
|
||||
|
||||
32
prod.postprocess.config.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import fs from'fs';
|
||||
import LZString from 'lz-string';
|
||||
|
||||
const excalidraw_pkg = fs.readFileSync("./node_modules/@zsviczian/excalidraw/dist/excalidraw.production.min.js", "utf8");
|
||||
const react_pkg = fs.readFileSync("./node_modules/react/umd/react.production.min.js", "utf8");
|
||||
const reactdom_pkg = fs.readFileSync("./node_modules/react-dom/umd/react-dom.production.min.js", "utf8");
|
||||
const lzstring_pkg = fs.readFileSync("./node_modules/lz-string/libs/lz-string.min.js", "utf8");
|
||||
const mainjs = fs.readFileSync("main.js", "utf8")
|
||||
|
||||
const packageString = lzstring_pkg+'const EXCALIDRAW_PACKAGES="' + LZString.compressToBase64(react_pkg + reactdom_pkg + excalidraw_pkg) +'";var ExcalidrawPackageLoader=(d=document)=>{if(!d.getElementById("excalidraw-script")){const script=d.createElement("script");script.type="text/javascript";script.id="excalidraw-script";script.text=LZString.decompressFromBase64(EXCALIDRAW_PACKAGES);d.body.appendChild(script);}};ExcalidrawPackageLoader();';
|
||||
|
||||
fs.writeFileSync(
|
||||
"main2.js",
|
||||
mainjs
|
||||
.replace('(require("react"))','')
|
||||
.replace('"use strict";','"use strict";' + packageString),
|
||||
{
|
||||
encoding: "utf8",
|
||||
flag: "w",
|
||||
mode: 0o666
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
export default ({
|
||||
input: 'foo',
|
||||
plugins: [],
|
||||
output: [{
|
||||
file: 'foo.js',
|
||||
format: 'es'
|
||||
}]
|
||||
});
|
||||
@@ -9,13 +9,38 @@ import copy from "rollup-plugin-copy";
|
||||
import ttypescript from "ttypescript";
|
||||
import typescript2 from "rollup-plugin-typescript2";
|
||||
import webWorker from "rollup-plugin-web-worker-loader";
|
||||
import fs from'fs';
|
||||
import LZString from 'lz-string';
|
||||
import postprocess from 'rollup-plugin-postprocess';
|
||||
|
||||
const isProd = (process.env.NODE_ENV === "production");
|
||||
console.log("Is production", isProd);
|
||||
|
||||
const excalidraw_pkg = isProd
|
||||
? fs.readFileSync("./node_modules/@zsviczian/excalidraw/dist/excalidraw.production.min.js", "utf8")
|
||||
: fs.readFileSync("./node_modules/@zsviczian/excalidraw/dist/excalidraw.development.js", "utf8");
|
||||
const react_pkg = isProd
|
||||
? fs.readFileSync("./node_modules/react/umd/react.production.min.js", "utf8")
|
||||
: fs.readFileSync("./node_modules/react/umd/react.development.js", "utf8");
|
||||
const reactdom_pkg = isProd
|
||||
? fs.readFileSync("./node_modules/react-dom/umd/react-dom.production.min.js", "utf8")
|
||||
: fs.readFileSync("./node_modules/react-dom/umd/react-dom.development.js", "utf8");
|
||||
const lzstring_pkg = fs.readFileSync("./node_modules/lz-string/libs/lz-string.min.js", "utf8");
|
||||
|
||||
const manifestStr = fs.readFileSync("manifest.json", "utf-8");
|
||||
const manifest = JSON.parse(manifestStr);
|
||||
console.log(manifest.version);
|
||||
|
||||
const packageString = ';'+lzstring_pkg+'const EXCALIDRAW_PACKAGES = "' + LZString.compressToBase64(react_pkg + reactdom_pkg + excalidraw_pkg) + '";' +
|
||||
'const {react, reactDOM, excalidrawLib} = window.eval.call(window, `(function() {' +
|
||||
'${LZString.decompressFromBase64(EXCALIDRAW_PACKAGES)};' +
|
||||
'return {react:React, reactDOM:ReactDOM, excalidrawLib: ExcalidrawLib};})();`);' +
|
||||
'const PLUGIN_VERSION="'+manifest.version+'";';
|
||||
|
||||
|
||||
|
||||
const BASE_CONFIG = {
|
||||
input: 'src/main.ts',
|
||||
external: ['obsidian'],
|
||||
external: ['obsidian', '@zsviczian/excalidraw', 'react', 'react-dom'],
|
||||
}
|
||||
|
||||
const getRollupPlugins = (tsconfig, ...plugins) =>
|
||||
@@ -30,7 +55,7 @@ const BUILD_CONFIG = {
|
||||
...BASE_CONFIG,
|
||||
output: {
|
||||
dir: '.',
|
||||
sourcemap: 'inline',
|
||||
sourcemap: isProd?false:'inline',
|
||||
format: 'cjs',
|
||||
exports: 'default',
|
||||
},
|
||||
@@ -43,11 +68,23 @@ const BUILD_CONFIG = {
|
||||
exclude: "node_modules/**"
|
||||
}),
|
||||
commonjs(),
|
||||
nodeResolve({ browser: true, preferBuiltins: true }),
|
||||
nodeResolve({ browser: true, preferBuiltins: false }),
|
||||
typescript({inlineSources: !isProd}),
|
||||
...isProd ? [
|
||||
terser({toplevel: true, compress: {passes: 2}})
|
||||
] : []
|
||||
...isProd
|
||||
? [
|
||||
terser({toplevel: false, compress: {passes: 2}}),
|
||||
//!postprocess - the version available on npmjs does not work, need this update:
|
||||
// npm install brettz9/rollup-plugin-postprocess#update --save-dev
|
||||
// https://github.com/developit/rollup-plugin-postprocess/issues/10
|
||||
postprocess([
|
||||
[/,React=require\("react"\);/, packageString],
|
||||
])
|
||||
]
|
||||
: [
|
||||
postprocess([
|
||||
[/var React = require\('react'\);/, packageString],
|
||||
])
|
||||
],
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
REG_BLOCK_REF_CLEAN,
|
||||
FRONTMATTER_KEY_LINKBUTTON_OPACITY,
|
||||
FRONTMATTER_KEY_ONLOAD_SCRIPT,
|
||||
FRONTMATTER_KEY_AUTOEXPORT,
|
||||
} from "./Constants";
|
||||
import { _measureText } from "./ExcalidrawAutomate";
|
||||
import ExcalidrawPlugin from "./main";
|
||||
@@ -26,11 +27,12 @@ import {
|
||||
decompress,
|
||||
//getBakPath,
|
||||
getBinaryFileFromDataURL,
|
||||
getContainerElement,
|
||||
getExportTheme,
|
||||
getLinkParts,
|
||||
hasExportTheme,
|
||||
LinkParts,
|
||||
wrapText,
|
||||
wrapTextAtCharLength,
|
||||
} from "./utils/Utils";
|
||||
import { getAttachmentsFolderAndFilePath, isObsidianThemeDark } from "./utils/ObsidianUtils";
|
||||
import {
|
||||
@@ -51,6 +53,21 @@ declare module "obsidian" {
|
||||
}
|
||||
}
|
||||
|
||||
const {
|
||||
wrapText,
|
||||
getFontString,
|
||||
getMaxContainerWidth,
|
||||
//@ts-ignore
|
||||
} = excalidrawLib;
|
||||
|
||||
export enum AutoexportPreference {
|
||||
none,
|
||||
both,
|
||||
png,
|
||||
svg,
|
||||
inherit
|
||||
}
|
||||
|
||||
export const REGEX_LINK = {
|
||||
//![[link|alias]] [alias](link){num}
|
||||
// 1 2 3 4 5 67 8 9
|
||||
@@ -201,37 +218,41 @@ const estimateMaxLineLen = (text: string, originalText: string): number => {
|
||||
return null;
|
||||
}
|
||||
for (const line of splitText) {
|
||||
if (line.length > maxLineLen) {
|
||||
maxLineLen = line.length;
|
||||
const l = line.trim();
|
||||
if (l.length > maxLineLen) {
|
||||
maxLineLen = l.length;
|
||||
}
|
||||
}
|
||||
return maxLineLen;
|
||||
};
|
||||
|
||||
const wrap = (text: string, lineLen: number) =>
|
||||
lineLen ? wrapText(text, lineLen, false, 0) : text;
|
||||
lineLen ? wrapTextAtCharLength(text, lineLen, false, 0) : text;
|
||||
|
||||
export class ExcalidrawData {
|
||||
private textElements: Map<
|
||||
public textElements: Map<
|
||||
string,
|
||||
{ raw: string; parsed: string; wrapAt: number | null }
|
||||
> = null;
|
||||
private elementLinks: Map<string, string> = null;
|
||||
public elementLinks: Map<string, string> = null;
|
||||
public scene: any = null;
|
||||
private file: TFile = null;
|
||||
public deletedElements: ExcalidrawElement[] = [];
|
||||
public file: TFile = null;
|
||||
private app: App;
|
||||
private showLinkBrackets: boolean;
|
||||
private linkPrefix: string;
|
||||
private urlPrefix: string;
|
||||
public autoexportPreference: AutoexportPreference = AutoexportPreference.inherit;
|
||||
private textMode: TextMode = TextMode.raw;
|
||||
private plugin: ExcalidrawPlugin;
|
||||
public loaded: boolean = false;
|
||||
private files: Map<FileId, EmbeddedFile> = null; //fileId, path
|
||||
private equations: Map<FileId, { latex: string; isLoaded: boolean }> = null; //fileId, path
|
||||
private compatibilityMode: boolean = false;
|
||||
selectedElementIds: {[key:string]:boolean} = {}; //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/609
|
||||
|
||||
constructor(plugin: ExcalidrawPlugin) {
|
||||
this.plugin = plugin;
|
||||
constructor(
|
||||
private plugin: ExcalidrawPlugin,
|
||||
) {
|
||||
this.app = plugin.app;
|
||||
this.files = new Map<FileId, EmbeddedFile>();
|
||||
this.equations = new Map<FileId, { latex: string; isLoaded: boolean }>();
|
||||
@@ -374,12 +395,13 @@ export class ExcalidrawData {
|
||||
public async loadData(
|
||||
data: string,
|
||||
file: TFile,
|
||||
textMode: TextMode,
|
||||
textMode: TextMode
|
||||
): Promise<boolean> {
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
this.loaded = false;
|
||||
this.selectedElementIds = {};
|
||||
this.textElements = new Map<
|
||||
string,
|
||||
{ raw: string; parsed: string; wrapAt: number }
|
||||
@@ -398,6 +420,7 @@ export class ExcalidrawData {
|
||||
this.setShowLinkBrackets();
|
||||
this.setLinkPrefix();
|
||||
this.setUrlPrefix();
|
||||
this.setAutoexportPreferences();
|
||||
|
||||
this.scene = null;
|
||||
|
||||
@@ -431,17 +454,10 @@ export class ExcalidrawData {
|
||||
}
|
||||
return sceneJSONandPOS;
|
||||
};
|
||||
//try {
|
||||
sceneJSONandPOS = loadJSON();
|
||||
/*} catch (e) {
|
||||
if(await this.app.vault.adapter.exists(getBakPath(file))) {
|
||||
data = await this.app.vault.adapter.read(getBakPath(file))
|
||||
sceneJSONandPOS = loadJSON();
|
||||
new Notice(t("LOAD_FROM_BACKUP"), 4000);
|
||||
} else {
|
||||
throw e;
|
||||
|
||||
}*/
|
||||
|
||||
this.deletedElements = this.scene.elements.filter((el:ExcalidrawElement)=>el.isDeleted);
|
||||
this.scene.elements = this.scene.elements.filter((el:ExcalidrawElement)=>!el.isDeleted);
|
||||
|
||||
if (!this.scene.files) {
|
||||
this.scene.files = {}; //loading legacy scenes that do not yet have the files attribute.
|
||||
@@ -481,7 +497,7 @@ export class ExcalidrawData {
|
||||
let res = data.matchAll(/\s\^(.{8})[\n]+/g);
|
||||
let parts;
|
||||
while (!(parts = res.next()).done) {
|
||||
const text = data.substring(position, parts.value.index);
|
||||
let text = data.substring(position, parts.value.index);
|
||||
const id: string = parts.value[1];
|
||||
const textEl = this.scene.elements.filter((el: any) => el.id === id)[0];
|
||||
if (textEl) {
|
||||
@@ -495,6 +511,13 @@ export class ExcalidrawData {
|
||||
this.elementLinks.set(id, text);
|
||||
} else {
|
||||
const wrapAt = estimateMaxLineLen(textEl.text, textEl.originalText);
|
||||
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/566
|
||||
const elementLinkRes = text.matchAll(/^%%\*\*\*>>>text element-link:(\[\[[^<*\]]*]])<<<\*\*\*%%/gm);
|
||||
const elementLink = elementLinkRes.next();
|
||||
if(!elementLink.done) {
|
||||
text = text.replace(/^%%\*\*\*>>>text element-link:\[\[[^<*\]]*]]<<<\*\*\*%%/gm,"");
|
||||
textEl.link = elementLink.value[1];
|
||||
}
|
||||
const parseRes = await this.parse(text);
|
||||
this.textElements.set(id, {
|
||||
raw: text,
|
||||
@@ -552,6 +575,7 @@ export class ExcalidrawData {
|
||||
return false;
|
||||
}
|
||||
this.loaded = false;
|
||||
this.selectedElementIds = {};
|
||||
this.compatibilityMode = true;
|
||||
this.file = file;
|
||||
this.textElements = new Map<
|
||||
@@ -580,6 +604,7 @@ export class ExcalidrawData {
|
||||
}
|
||||
|
||||
public async setTextMode(textMode: TextMode, forceupdate: boolean = false) {
|
||||
if(!this.scene) return;
|
||||
this.textMode = textMode;
|
||||
await this.updateSceneTextElements(forceupdate);
|
||||
}
|
||||
@@ -622,12 +647,17 @@ export class ExcalidrawData {
|
||||
//first get scene text elements
|
||||
const texts = this.scene.elements?.filter((el: any) => el.type === "text");
|
||||
for (const te of texts) {
|
||||
const container = getContainerElement(te,this.scene);
|
||||
const originalText =
|
||||
(await this.getText(te.id, false)) ?? te.originalText ?? te.text;
|
||||
(await this.getText(te.id)) ?? te.originalText ?? te.text;
|
||||
const wrapAt = this.textElements.get(te.id)?.wrapAt;
|
||||
this.updateTextElement(
|
||||
te,
|
||||
wrap(originalText, wrapAt),
|
||||
wrapAt ? wrapText(
|
||||
originalText,
|
||||
getFontString({fontSize: te.fontSize, fontFamily: te.fontFamily}),
|
||||
getMaxContainerWidth(container)
|
||||
) : originalText,
|
||||
originalText,
|
||||
forceupdate,
|
||||
); //(await this.getText(te.id))??te.text serves the case when the whole #Text Elements section is deleted by accident
|
||||
@@ -636,28 +666,28 @@ export class ExcalidrawData {
|
||||
|
||||
private async getText(
|
||||
id: string,
|
||||
wrapResult: boolean = true,
|
||||
): Promise<string> {
|
||||
const t = this.textElements.get(id);
|
||||
if (!t) {
|
||||
const text = this.textElements.get(id);
|
||||
if (!text) {
|
||||
return null;
|
||||
}
|
||||
if (this.textMode === TextMode.parsed) {
|
||||
if (!t.parsed) {
|
||||
if (!text.parsed) {
|
||||
this.textElements.set(id, {
|
||||
raw: t.raw,
|
||||
parsed: (await this.parse(t.raw)).parsed,
|
||||
wrapAt: t.wrapAt,
|
||||
raw: text.raw,
|
||||
parsed: (await this.parse(text.raw)).parsed,
|
||||
wrapAt: text.wrapAt,
|
||||
});
|
||||
}
|
||||
//console.log("parsed",this.textElements.get(id).parsed);
|
||||
return wrapResult ? wrap(t.parsed, t.wrapAt) : t.parsed;
|
||||
return text.parsed;
|
||||
}
|
||||
//console.log("raw",this.textElements.get(id).raw);
|
||||
return t.raw;
|
||||
return text.raw;
|
||||
}
|
||||
|
||||
private findNewElementLinksInScene(): boolean {
|
||||
let result = false;
|
||||
const elements = this.scene.elements?.filter((el: any) => {
|
||||
return (
|
||||
el.type !== "text" &&
|
||||
@@ -667,34 +697,37 @@ export class ExcalidrawData {
|
||||
);
|
||||
});
|
||||
if (elements.length === 0) {
|
||||
return false;
|
||||
return result;
|
||||
}
|
||||
|
||||
let jsonString = JSON.stringify(this.scene);
|
||||
|
||||
let id: string; //will be used to hold the new 8 char long ID for textelements that don't yet appear under # Text Elements
|
||||
|
||||
for (const el of elements) {
|
||||
id = el.id;
|
||||
//replacing Excalidraw element IDs with my own nanoid, because default IDs may contain
|
||||
//characters not recognized by Obsidian block references
|
||||
//also Excalidraw IDs are inconveniently long
|
||||
if (el.id.length > 8) {
|
||||
result = true;
|
||||
id = nanoid();
|
||||
jsonString = jsonString.replaceAll(el.id, id); //brute force approach to replace all occurances (e.g. links, groups,etc.)
|
||||
}
|
||||
this.elementLinks.set(id, el.link);
|
||||
}
|
||||
this.scene = JSON.parse(jsonString);
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* check for textElements in Scene missing from textElements Map
|
||||
* @returns {boolean} - true if there were changes
|
||||
*/
|
||||
private findNewTextElementsInScene(): boolean {
|
||||
private findNewTextElementsInScene(selectedElementIds: {[key: string]: boolean} = {}): boolean {
|
||||
//console.log("Excalidraw.Data.findNewTextElementsInScene()");
|
||||
//get scene text elements
|
||||
this.selectedElementIds = selectedElementIds;
|
||||
const texts = this.scene.elements?.filter((el: any) => el.type === "text");
|
||||
|
||||
let jsonString = JSON.stringify(this.scene);
|
||||
@@ -709,14 +742,18 @@ export class ExcalidrawData {
|
||||
if (te.id.length > 8) {
|
||||
dirty = true;
|
||||
id = nanoid();
|
||||
if(this.selectedElementIds[te.id]) { //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/609
|
||||
delete this.selectedElementIds[te.id];
|
||||
this.selectedElementIds[id] = true;
|
||||
}
|
||||
jsonString = jsonString.replaceAll(te.id, id); //brute force approach to replace all occurances (e.g. links, groups,etc.)
|
||||
if (this.textElements.has(te.id)) {
|
||||
//element was created with onBeforeTextSubmit
|
||||
const t = this.textElements.get(te.id);
|
||||
const text = this.textElements.get(te.id);
|
||||
this.textElements.set(id, {
|
||||
raw: t.raw,
|
||||
parsed: t.parsed,
|
||||
wrapAt: t.wrapAt,
|
||||
raw: text.raw,
|
||||
parsed: text.parsed,
|
||||
wrapAt: text.wrapAt,
|
||||
});
|
||||
this.textElements.delete(te.id); //delete the old ID from the Map
|
||||
}
|
||||
@@ -726,7 +763,13 @@ export class ExcalidrawData {
|
||||
this.textElements.set(id, { raw, parsed: null, wrapAt });
|
||||
this.parseasync(id, raw, wrapAt);
|
||||
}
|
||||
} else if (!this.textElements.has(te.id)) {
|
||||
const raw = te.rawText && te.rawText !== "" ? te.rawText : te.text; //this is for compatibility with drawings created before the rawText change on ExcalidrawTextElement
|
||||
const wrapAt = estimateMaxLineLen(te.text, te.originalText);
|
||||
this.textElements.set(id, { raw, parsed: null, wrapAt });
|
||||
this.parseasync(id, raw, wrapAt);
|
||||
}
|
||||
|
||||
}
|
||||
if (dirty) {
|
||||
//reload scene json in case it has changed
|
||||
@@ -767,12 +810,15 @@ export class ExcalidrawData {
|
||||
if (el.length === 0) {
|
||||
this.textElements.delete(key); //if no longer in the scene, delete the text element
|
||||
} else {
|
||||
const text = await this.getText(key, false);
|
||||
const text = await this.getText(key);
|
||||
const raw = this.scene.prevTextMode === TextMode.parsed
|
||||
? el[0].rawText
|
||||
: (el[0].originalText ?? el[0].text);
|
||||
if (text !== (el[0].originalText ?? el[0].text)) {
|
||||
const wrapAt = estimateMaxLineLen(el[0].text, el[0].originalText);
|
||||
this.textElements.set(key, {
|
||||
raw: el[0].originalText ?? el[0].text,
|
||||
parsed: (await this.parse(el[0].originalText ?? el[0].text)).parsed,
|
||||
raw,
|
||||
parsed: (await this.parse(raw)).parsed,
|
||||
wrapAt,
|
||||
});
|
||||
}
|
||||
@@ -824,6 +870,7 @@ export class ExcalidrawData {
|
||||
* @returns
|
||||
*/
|
||||
private async parse(text: string): Promise<{ parsed: string; link: string }> {
|
||||
text = this.parseCheckbox(text);
|
||||
let outString = "";
|
||||
let link = null;
|
||||
let position = 0;
|
||||
@@ -846,11 +893,17 @@ export class ExcalidrawData {
|
||||
}
|
||||
if (REGEX_LINK.isTransclusion(parts)) {
|
||||
//transclusion //parts.value[1] || parts.value[4]
|
||||
const contents = (await this.getTransclusion(REGEX_LINK.getLink(parts)))
|
||||
.contents;
|
||||
let contents = this
|
||||
.parseCheckbox((await this.getTransclusion(REGEX_LINK.getLink(parts))).contents)
|
||||
.replaceAll(/%%[^%]*%%/gm,""); //remove comments, consequence of https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/566
|
||||
if(this.plugin.settings.removeTransclusionQuoteSigns) {
|
||||
//remove leading > signs from transcluded quotations; the first > sign is not explicitlyl removed becuse
|
||||
//Obsidian app.metadataCache.blockCache returns the block position already discarding the first '> '
|
||||
contents = contents.replaceAll(/\n\s*>\s?/gm,"\n");
|
||||
}
|
||||
outString +=
|
||||
text.substring(position, parts.value.index) +
|
||||
wrapText(
|
||||
wrapTextAtCharLength(
|
||||
contents,
|
||||
REGEX_LINK.getWrapLength(
|
||||
parts,
|
||||
@@ -884,6 +937,16 @@ export class ExcalidrawData {
|
||||
return { parsed: outString, link };
|
||||
}
|
||||
|
||||
private parseCheckbox(text:string):string {
|
||||
return this.plugin.settings.parseTODO
|
||||
? text
|
||||
.replaceAll(/^- \[\s] /g,`${this.plugin.settings.todo} `)
|
||||
.replaceAll(/\n- \[\s] /g,`\n${this.plugin.settings.todo} `)
|
||||
.replaceAll(/^- \[[^\s]] /g,`${this.plugin.settings.done} `)
|
||||
.replaceAll(/\n- \[[^\s]] /g,`\n${this.plugin.settings.done} `)
|
||||
: text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a quick parse of the raw text. Returns the parsed string if raw text does not include a transclusion.
|
||||
* Return null if raw text includes a transclusion.
|
||||
@@ -905,7 +968,7 @@ export class ExcalidrawData {
|
||||
if (hasTransclusion(text)) {
|
||||
return [null, null];
|
||||
}
|
||||
|
||||
text = this.parseCheckbox(text);
|
||||
let outString = "";
|
||||
let link = null;
|
||||
let position = 0;
|
||||
@@ -954,10 +1017,18 @@ export class ExcalidrawData {
|
||||
* @returns markdown string
|
||||
*/
|
||||
disableCompression: boolean = false;
|
||||
generateMD(): string {
|
||||
generateMD(deletedElements: ExcalidrawElement[] = []): string {
|
||||
let outString = "# Text Elements\n";
|
||||
for (const key of this.textElements.keys()) {
|
||||
outString += `${this.textElements.get(key).raw} ^${key}\n\n`;
|
||||
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/566
|
||||
const element = this.scene.elements.filter((el:any)=>el.id===key);
|
||||
let elementString = this.textElements.get(key).raw;
|
||||
if(element && element.length===1 && element[0].link && element[0].rawText === element[0].originalText) {
|
||||
if(element[0].link.match(/^\[\[[^\]]*]]$/g)) { //apply this only to markdown links
|
||||
elementString = `%%***>>>text element-link:${element[0].link}<<<***%%` + elementString;
|
||||
}
|
||||
}
|
||||
outString += `${elementString} ^${key}\n\n`;
|
||||
}
|
||||
|
||||
for (const key of this.elementLinks.keys()) {
|
||||
@@ -975,12 +1046,25 @@ export class ExcalidrawData {
|
||||
}
|
||||
if (this.files.size > 0) {
|
||||
for (const key of this.files.keys()) {
|
||||
outString += `${key}: [[${this.files.get(key).linkParts.original}]]\n`;
|
||||
const PATHREG = /(^[^#\|]*)/;
|
||||
const ef = this.files.get(key);
|
||||
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/829
|
||||
const path = ef.file
|
||||
? ef.linkParts.original.replace(PATHREG,app.metadataCache.fileToLinktext(ef.file,this.file.path))
|
||||
: ef.linkParts.original;
|
||||
outString += `${key}: [[${path}]]\n`;
|
||||
}
|
||||
}
|
||||
outString += this.equations.size > 0 || this.files.size > 0 ? "\n" : "";
|
||||
|
||||
const sceneJSONstring = JSON.stringify(this.scene, null, "\t");
|
||||
const sceneJSONstring = JSON.stringify({
|
||||
type: this.scene.type,
|
||||
version: this.scene.version,
|
||||
source: this.scene.source,
|
||||
elements: this.scene.elements.concat(deletedElements),
|
||||
appState: this.scene.appState,
|
||||
files: this.scene.files
|
||||
}, null, "\t");
|
||||
return (
|
||||
outString +
|
||||
getMarkdownDrawingSection(
|
||||
@@ -1019,7 +1103,7 @@ export class ExcalidrawData {
|
||||
});
|
||||
|
||||
//check if there are any images that need to be processed in the new scene
|
||||
if (!scene.files || scene.files == {}) {
|
||||
if (!scene.files || Object.keys(scene.files).length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1030,10 +1114,12 @@ export class ExcalidrawData {
|
||||
const processedIds = new Set<string>();
|
||||
fileIds.forEach(fileId=>{
|
||||
if(processedIds.has(fileId)) {
|
||||
const file = this.files.get(fileId as FileId);
|
||||
const equation = this.equations.get(fileId as FileId);
|
||||
const file = this.getFile(fileId);
|
||||
//const file = this.files.get(fileId as FileId);
|
||||
const equation = this.getEquation(fileId);
|
||||
//const equation = this.equations.get(fileId as FileId);
|
||||
//images should have a single reference, but equations and markdown embeds should have as many as instances of the file in the scene
|
||||
if(file && file.file.extension !== "md") {
|
||||
if(file && file.file && (file.file.extension !== "md" || this.plugin.isExcalidrawFile(file.file))) {
|
||||
return;
|
||||
}
|
||||
const newId = fileid();
|
||||
@@ -1042,10 +1128,12 @@ export class ExcalidrawData {
|
||||
dirty = true;
|
||||
processedIds.add(newId);
|
||||
if(file) {
|
||||
this.files.set(newId as FileId,new EmbeddedFile(this.plugin,this.file.path,file.linkParts.original))
|
||||
this.setFile(newId as FileId,new EmbeddedFile(this.plugin,this.file.path,file.linkParts.original));
|
||||
//this.files.set(newId as FileId,new EmbeddedFile(this.plugin,this.file.path,file.linkParts.original))
|
||||
}
|
||||
if(equation) {
|
||||
this.equations.set(newId as FileId, equation);
|
||||
this.setEquation(newId as FileId, {latex:equation.latex, isLoaded:false});
|
||||
//this.equations.set(newId as FileId, equation);
|
||||
}
|
||||
}
|
||||
processedIds.add(fileId);
|
||||
@@ -1131,7 +1219,7 @@ export class ExcalidrawData {
|
||||
return dirty;
|
||||
}
|
||||
|
||||
public async syncElements(newScene: any): Promise<boolean> {
|
||||
public async syncElements(newScene: any, selectedElementIds?: {[key: string]: boolean}): Promise<boolean> {
|
||||
this.scene = newScene;
|
||||
let result = false;
|
||||
if (!this.compatibilityMode) {
|
||||
@@ -1146,7 +1234,7 @@ export class ExcalidrawData {
|
||||
this.setShowLinkBrackets() ||
|
||||
this.findNewElementLinksInScene();
|
||||
await this.updateTextElementsFromScene();
|
||||
return result || this.findNewTextElementsInScene();
|
||||
return result || this.findNewTextElementsInScene(selectedElementIds);
|
||||
}
|
||||
|
||||
public async updateScene(newScene: any) {
|
||||
@@ -1307,6 +1395,24 @@ export class ExcalidrawData {
|
||||
return urlPrefix != this.urlPrefix;
|
||||
}
|
||||
|
||||
private setAutoexportPreferences() {
|
||||
const fileCache = this.app.metadataCache.getFileCache(this.file);
|
||||
if (
|
||||
fileCache?.frontmatter &&
|
||||
fileCache.frontmatter[FRONTMATTER_KEY_AUTOEXPORT] != null
|
||||
) {
|
||||
switch ((fileCache.frontmatter[FRONTMATTER_KEY_AUTOEXPORT]).toLowerCase()) {
|
||||
case "none": this.autoexportPreference = AutoexportPreference.none; break;
|
||||
case "both": this.autoexportPreference = AutoexportPreference.both; break;
|
||||
case "png": this.autoexportPreference = AutoexportPreference.png; break;
|
||||
case "svg": this.autoexportPreference = AutoexportPreference.svg; break;
|
||||
default: this.autoexportPreference = AutoexportPreference.inherit;
|
||||
};
|
||||
} else {
|
||||
this.autoexportPreference = AutoexportPreference.inherit;
|
||||
}
|
||||
}
|
||||
|
||||
private setShowLinkBrackets(): boolean {
|
||||
const showLinkBrackets = this.showLinkBrackets;
|
||||
const fileCache = this.app.metadataCache.getFileCache(this.file);
|
||||
@@ -1341,14 +1447,35 @@ export class ExcalidrawData {
|
||||
if (!data.file) {
|
||||
return;
|
||||
}
|
||||
|
||||
const parts = data.linkParts.original.split("#");
|
||||
this.plugin.filesMaster.set(fileId, {
|
||||
path: data.file.path,
|
||||
path:data.file.path + (data.shouldScale()?"":"|100%"),
|
||||
blockrefData: parts.length === 1
|
||||
? null
|
||||
: parts[1],
|
||||
hasSVGwithBitmap: data.isSVGwithBitmap,
|
||||
});
|
||||
}
|
||||
|
||||
public getFiles(): EmbeddedFile[] {
|
||||
return Object.values(this.files);
|
||||
}
|
||||
|
||||
public getFile(fileId: FileId): EmbeddedFile {
|
||||
return this.files.get(fileId);
|
||||
let embeddedFile = this.files.get(fileId);
|
||||
if(embeddedFile) return embeddedFile;
|
||||
const masterFile = this.plugin.filesMaster.get(fileId);
|
||||
if(!masterFile) return embeddedFile;
|
||||
embeddedFile = new EmbeddedFile(
|
||||
this.plugin,
|
||||
this.file.path,
|
||||
masterFile.blockrefData
|
||||
? masterFile.path + "#" + masterFile.blockrefData
|
||||
: masterFile.path
|
||||
);
|
||||
this.files.set(fileId,embeddedFile);
|
||||
return embeddedFile;
|
||||
}
|
||||
|
||||
public getFileEntries() {
|
||||
@@ -1367,15 +1494,19 @@ export class ExcalidrawData {
|
||||
return true;
|
||||
}
|
||||
if (this.plugin.filesMaster.has(fileId)) {
|
||||
const fileMaster = this.plugin.filesMaster.get(fileId);
|
||||
if (!this.app.vault.getAbstractFileByPath(fileMaster.path)) {
|
||||
const masterFile = this.plugin.filesMaster.get(fileId);
|
||||
const path = masterFile.path.split("|")[0].split("#")[0];
|
||||
if (!this.app.vault.getAbstractFileByPath(path)) {
|
||||
this.plugin.filesMaster.delete(fileId);
|
||||
return true;
|
||||
} // the file no longer exists
|
||||
const fixScale = masterFile.path.endsWith("100%");
|
||||
const embeddedFile = new EmbeddedFile(
|
||||
this.plugin,
|
||||
this.file.path,
|
||||
fileMaster.path,
|
||||
(masterFile.blockrefData
|
||||
? path + "#" + masterFile.blockrefData
|
||||
: path) + (fixScale?"|100%":"")
|
||||
);
|
||||
this.files.set(fileId, embeddedFile);
|
||||
return true;
|
||||
@@ -1392,7 +1523,12 @@ export class ExcalidrawData {
|
||||
}
|
||||
|
||||
public getEquation(fileId: FileId): { latex: string; isLoaded: boolean } {
|
||||
return this.equations.get(fileId);
|
||||
let result = this.equations.get(fileId);
|
||||
if(result) return result;
|
||||
const latex = this.plugin.equationsMaster.get(fileId);
|
||||
if(!latex) return result;
|
||||
this.equations.set(fileId, {latex, isLoaded: false});
|
||||
return {latex, isLoaded: false};
|
||||
}
|
||||
|
||||
public getEquationEntries() {
|
||||
@@ -1461,15 +1597,15 @@ export const getTransclusion = async (
|
||||
if (!para) {
|
||||
return { contents: linkParts.original.trim(), lineNum: 0 };
|
||||
}
|
||||
if (["blockquote", "listItem"].includes(para.type)) {
|
||||
if (["blockquote"].includes(para.type)) {
|
||||
para = para.children[0];
|
||||
} //blockquotes are special, they have one child, which has the paragraph
|
||||
const startPos = para.position.start.offset;
|
||||
const lineNum = para.position.start.line;
|
||||
const endPos =
|
||||
para.children[para.children.length - 1]?.position.start.offset - 1; //alternative: filter((c:any)=>c.type=="blockid")[0]
|
||||
const endPos = para.position.end.offset; //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/853
|
||||
//para.children[para.children.length - 1]?.position.start.offset - 1; //!not clear what the side effect of the #853 change is
|
||||
return {
|
||||
contents: contents.substring(startPos, endPos).trim(),
|
||||
contents: contents.substring(startPos, endPos).replaceAll(/ \^\S*$|^\^\S*$/gm,"").trim(), //remove the block reference from the end of the line, or from the beginning of a new line
|
||||
lineNum,
|
||||
};
|
||||
}
|
||||
@@ -1491,7 +1627,7 @@ export const getTransclusion = async (
|
||||
lineNum
|
||||
};
|
||||
}
|
||||
endPos = headings[i].node.position.start.offset - 1;
|
||||
endPos = headings[j].node.position.start.offset - 1;
|
||||
return {
|
||||
leadingHashes: "#".repeat(depth)+" ",
|
||||
contents: contents.substring(startPos, endPos).trim(),
|
||||
@@ -1501,6 +1637,7 @@ export const getTransclusion = async (
|
||||
const c = headings[i].node.children[0];
|
||||
const dataHeading = headings[i].node.data?.hProperties?.dataHeading;
|
||||
const cc = c?.children;
|
||||
//const refNoSpace = linkParts.ref.replaceAll(" ","");
|
||||
if (
|
||||
!startPos &&
|
||||
(c?.value?.replaceAll(REG_BLOCK_REF_CLEAN, "") === linkParts.ref ||
|
||||
@@ -1519,7 +1656,7 @@ export const getTransclusion = async (
|
||||
return {
|
||||
leadingHashes: "#".repeat(depth) + " ",
|
||||
contents: contents.substring(startPos).trim(),
|
||||
lineNum
|
||||
lineNum
|
||||
};
|
||||
}
|
||||
return { contents: linkParts.original.trim(), lineNum: 0 };
|
||||
|
||||
11
src/LaTeX.ts
@@ -3,10 +3,9 @@ import ExcalidrawView from "./ExcalidrawView";
|
||||
import ExcalidrawPlugin from "./main";
|
||||
import { FileData, MimeType } from "./EmbeddedFileLoader";
|
||||
import { FileId } from "@zsviczian/excalidraw/types/element/types";
|
||||
import { getImageSize, log, sleep, svgToBase64 } from "./utils/Utils";
|
||||
import { errorlog, getImageSize, log, sleep, svgToBase64 } from "./utils/Utils";
|
||||
import { fileid } from "./Constants";
|
||||
import html2canvas from "html2canvas";
|
||||
import { count } from "console";
|
||||
import { Notice } from "obsidian";
|
||||
|
||||
declare let window: any;
|
||||
@@ -28,6 +27,7 @@ export const updateEquation = async (
|
||||
created: data.created,
|
||||
size: data.size,
|
||||
hasSVGwithBitmap: false,
|
||||
shouldScale: true,
|
||||
});
|
||||
addFiles(files, view);
|
||||
}
|
||||
@@ -46,11 +46,14 @@ export async function tex2dataURL(
|
||||
//if network is slow, or not available, or mathjax has not yet fully loaded
|
||||
let counter = 0;
|
||||
while (!plugin.mathjax && !plugin.mathjaxLoaderFinished && counter < 10) {
|
||||
log({ where: "tex2dataURL", counter });
|
||||
await sleep(100);
|
||||
counter++;
|
||||
}
|
||||
|
||||
if(!plugin.mathjaxLoaderFinished) {
|
||||
errorlog({where: "text2dataURL", fn: tex2dataURL, message:"mathjaxLoader not ready, using fallback. Try reloading Obsidian or restarting the Excalidraw plugin"});
|
||||
}
|
||||
|
||||
//it is not clear why this works, but it seems that after loading the plugin sometimes only the third attempt is successful.
|
||||
try {
|
||||
return await mathjaxSVG(tex, plugin);
|
||||
@@ -79,7 +82,7 @@ export async function tex2dataURL(
|
||||
}
|
||||
}
|
||||
|
||||
async function mathjaxSVG(
|
||||
export async function mathjaxSVG(
|
||||
tex: string,
|
||||
plugin: ExcalidrawPlugin,
|
||||
): Promise<{
|
||||
|
||||
@@ -34,7 +34,7 @@ export class ScriptEngine {
|
||||
if (!path.endsWith(".svg")) {
|
||||
return;
|
||||
}
|
||||
const scriptFile = this.plugin.app.vault.getAbstractFileByPath(
|
||||
const scriptFile = app.vault.getAbstractFileByPath(
|
||||
getIMGFilename(path, "md"),
|
||||
);
|
||||
if (scriptFile && scriptFile instanceof TFile) {
|
||||
@@ -53,7 +53,7 @@ export class ScriptEngine {
|
||||
handleSvgFileChange(file.path);
|
||||
};
|
||||
this.plugin.registerEvent(
|
||||
this.plugin.app.vault.on("delete", deleteEventHandler),
|
||||
app.vault.on("delete", deleteEventHandler),
|
||||
);
|
||||
|
||||
const createEventHandler = async (file: TFile) => {
|
||||
@@ -67,7 +67,7 @@ export class ScriptEngine {
|
||||
handleSvgFileChange(file.path);
|
||||
};
|
||||
this.plugin.registerEvent(
|
||||
this.plugin.app.vault.on("create", createEventHandler),
|
||||
app.vault.on("create", createEventHandler),
|
||||
);
|
||||
|
||||
const renameEventHandler = async (file: TAbstractFile, oldPath: string) => {
|
||||
@@ -86,7 +86,7 @@ export class ScriptEngine {
|
||||
}
|
||||
};
|
||||
this.plugin.registerEvent(
|
||||
this.plugin.app.vault.on("rename", renameEventHandler),
|
||||
app.vault.on("rename", renameEventHandler),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -101,7 +101,6 @@ export class ScriptEngine {
|
||||
}
|
||||
|
||||
public getListofScripts(): TFile[] {
|
||||
const app = this.plugin.app;
|
||||
this.scriptPath = this.plugin.settings.scriptFolderPath;
|
||||
if (!app.vault.getAbstractFileByPath(this.scriptPath)) {
|
||||
this.scriptPath = null;
|
||||
@@ -140,10 +139,10 @@ export class ScriptEngine {
|
||||
|
||||
async addScriptIconToMap(scriptPath: string, name: string) {
|
||||
const svgFilePath = getIMGFilename(scriptPath, "svg");
|
||||
const file = this.plugin.app.vault.getAbstractFileByPath(svgFilePath);
|
||||
const file = app.vault.getAbstractFileByPath(svgFilePath);
|
||||
const svgString: string =
|
||||
file && file instanceof TFile
|
||||
? await this.plugin.app.vault.read(file)
|
||||
? await app.vault.read(file)
|
||||
: null;
|
||||
this.scriptIconMap = {
|
||||
...this.scriptIconMap,
|
||||
@@ -163,15 +162,12 @@ export class ScriptEngine {
|
||||
name: `(Script) ${scriptName}`,
|
||||
checkCallback: (checking: boolean) => {
|
||||
if (checking) {
|
||||
return (
|
||||
this.plugin.app.workspace.activeLeaf.view.getViewType() ==
|
||||
VIEW_TYPE_EXCALIDRAW
|
||||
);
|
||||
return Boolean(app.workspace.getActiveViewOfType(ExcalidrawView));
|
||||
}
|
||||
const view = this.plugin.app.workspace.activeLeaf.view;
|
||||
if (view instanceof ExcalidrawView) {
|
||||
const view = app.workspace.getActiveViewOfType(ExcalidrawView);
|
||||
if (view) {
|
||||
(async()=>{
|
||||
const script = await this.plugin.app.vault.read(f);
|
||||
const script = await app.vault.read(f);
|
||||
if(script) {
|
||||
this.executeScript(view, script, scriptName);
|
||||
}
|
||||
@@ -184,7 +180,6 @@ export class ScriptEngine {
|
||||
}
|
||||
|
||||
unloadScripts() {
|
||||
const app = this.plugin.app;
|
||||
const scripts = app.vault
|
||||
.getFiles()
|
||||
.filter((f: TFile) => f.path.startsWith(this.scriptPath));
|
||||
@@ -201,7 +196,6 @@ export class ScriptEngine {
|
||||
this.scriptIconMap = { ...this.scriptIconMap };
|
||||
this.updateToolPannels();
|
||||
|
||||
const app = this.plugin.app;
|
||||
const commandId = `${PLUGIN_ID}:${basename}`;
|
||||
// @ts-ignore
|
||||
if (!app.commands.commands[commandId]) {
|
||||
@@ -232,7 +226,7 @@ export class ScriptEngine {
|
||||
buttons?: [{ caption: string; action: Function }],
|
||||
) =>
|
||||
ScriptEngine.inputPrompt(
|
||||
this.plugin.app,
|
||||
app,
|
||||
header,
|
||||
placeholder,
|
||||
value,
|
||||
@@ -245,7 +239,7 @@ export class ScriptEngine {
|
||||
instructions?: Instruction[],
|
||||
) =>
|
||||
ScriptEngine.suggester(
|
||||
this.plugin.app,
|
||||
app,
|
||||
displayItems,
|
||||
items,
|
||||
hint,
|
||||
@@ -262,7 +256,7 @@ export class ScriptEngine {
|
||||
|
||||
private updateToolPannels() {
|
||||
const leaves =
|
||||
this.plugin.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
|
||||
app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
|
||||
leaves.forEach((leaf: WorkspaceLeaf) => {
|
||||
const excalidrawView = leaf.view as ExcalidrawView;
|
||||
excalidrawView.toolsPanelRef?.current?.updateScriptIconMap(
|
||||
|
||||
@@ -18,14 +18,17 @@ export const SCRIPT_INSTALL_FOLDER = "Downloaded";
|
||||
export const fileid = customAlphabet("1234567890abcdef", 40);
|
||||
export const REG_LINKINDEX_INVALIDCHARS = /[<>:"\\|?*#]/g;
|
||||
export const REG_BLOCK_REF_CLEAN =
|
||||
/\+|\/|~|=|%|\(|\)|{|}|,|\.|\$|!|\?|;|\[|]|\^|#|\*|<|>|&|@|\||\\|"|:/g;
|
||||
export const IMAGE_TYPES = ["jpeg", "jpg", "png", "gif", "svg"];
|
||||
/[!"#$%&()*+,.:;<=>?@^`{|}~\/\[\]\\]/g; //https://discord.com/channels/686053708261228577/989603365606531104/1000128926619816048
|
||||
// /\+|\/|~|=|%|\(|\)|{|}|,|&|\.|\$|!|\?|;|\[|]|\^|#|\*|<|>|&|@|\||\\|"|:|\s/g;
|
||||
export const IMAGE_TYPES = ["jpeg", "jpg", "png", "gif", "svg", "webp", "bmp", "ico"];
|
||||
export const EXPORT_TYPES = ["svg", "dark.svg", "light.svg", "png", "dark.png", "light.png"];
|
||||
export const MAX_IMAGE_SIZE = 500;
|
||||
export const FRONTMATTER_KEY = "excalidraw-plugin";
|
||||
export const FRONTMATTER_KEY_EXPORT_TRANSPARENT =
|
||||
"excalidraw-export-transparent";
|
||||
export const FRONTMATTER_KEY_EXPORT_DARK = "excalidraw-export-dark";
|
||||
export const FRONTMATTER_KEY_EXPORT_SVGPADDING = "excalidraw-export-svgpadding";
|
||||
export const FRONTMATTER_KEY_EXPORT_SVGPADDING = "excalidraw-export-svgpadding"; //depricated
|
||||
export const FRONTMATTER_KEY_EXPORT_PADDING = "excalidraw-export-padding";
|
||||
export const FRONTMATTER_KEY_EXPORT_PNGSCALE = "excalidraw-export-pngscale";
|
||||
export const FRONTMATTER_KEY_CUSTOM_PREFIX = "excalidraw-link-prefix";
|
||||
export const FRONTMATTER_KEY_CUSTOM_URL_PREFIX = "excalidraw-url-prefix";
|
||||
@@ -37,6 +40,7 @@ export const FRONTMATTER_KEY_FONT = "excalidraw-font";
|
||||
export const FRONTMATTER_KEY_FONTCOLOR = "excalidraw-font-color";
|
||||
export const FRONTMATTER_KEY_BORDERCOLOR = "excalidraw-border-color";
|
||||
export const FRONTMATTER_KEY_MD_STYLE = "excalidraw-css";
|
||||
export const FRONTMATTER_KEY_AUTOEXPORT = "excalidraw-autoexport"
|
||||
export const LOCAL_PROTOCOL = "md://";
|
||||
export const VIEW_TYPE_EXCALIDRAW = "excalidraw";
|
||||
export const ICON_NAME = "excalidraw-icon";
|
||||
@@ -206,10 +210,9 @@ COLOR_NAMES.set("white", "#ffffff");
|
||||
COLOR_NAMES.set("whitesmoke", "#f5f5f5");
|
||||
COLOR_NAMES.set("yellow", "#ffff00");
|
||||
COLOR_NAMES.set("yellowgreen", "#9acd32");
|
||||
export const DEFAULT_MD_EMBED_CSS = `.excalidraw-md-host{padding:0px 10px}.excalidraw-md-footer{height:5px}foreignObject{background-color:transparent}p{display:block;margin-block-start:1em;margin-block-end:1em;margin-inline-start:0px;margin-inline-end:0px;color:inherit}table,tr,th,td{color:inherit;border:1px solid;border-collapse:collapse;padding:3px}th{font-weight:bold;border-bottom:double;background-color:silver}.copy-code-button{display:none}code[class*=language-],pre[class*=language-]{color:#393a34;font-family:"Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace;direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;font-size:.9em;line-height:1.2em;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre>code[class*=language-]{font-size:1em}pre[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,code[class*=language-] ::-moz-selection{background:#C1DEF1}pre[class*=language-]::selection,pre[class*=language-] ::selection,code[class*=language-]::selection,code[class*=language-] ::selection{background:#C1DEF1}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;background-color:#0000001a}:not(pre)>code[class*=language-]{padding:.2em;padding-top:1px;padding-bottom:1px;background:#f8f8f8;border:1px solid #dddddd}.token.comment,.token.prolog,.token.doctype,.token.cdata{color:green;font-style:italic}.token.namespace{opacity:.7}.token.string{color:#a31515}.token.punctuation,.token.operator{color:#393a34}.token.url,.token.symbol,.token.number,.token.boolean,.token.variable,.token.constant,.token.inserted{color:#36acaa}.token.atrule,.token.keyword,.token.attr-value,.language-autohotkey .token.selector,.language-json .token.boolean,.language-json .token.number,code[class*=language-css]{color:#00f}.token.function{color:#393a34}.token.deleted,.language-autohotkey .token.tag{color:#9a050f}.token.selector,.language-autohotkey .token.keyword{color:#00009f}.token.important{color:#e90}.token.important,.token.bold{font-weight:bold}.token.italic{font-style:italic}.token.class-name,.language-json .token.property{color:#2b91af}.token.tag,.token.selector{color:maroon}.token.attr-name,.token.property,.token.regex,.token.entity{color:red}.token.directive.tag .tag{background:#ffff00;color:#393a34}.line-numbers.line-numbers .line-numbers-rows{border-right-color:#a5a5a5}.line-numbers .line-numbers-rows>span:before{color:#2b91af}.line-highlight.line-highlight{background:rgba(193,222,241,.2);background:-webkit-linear-gradient(left,rgba(193,222,241,.2) 70%,rgba(221,222,241,0));background:linear-gradient(to right,rgba(193,222,241,.2) 70%,rgba(221,222,241,0))}blockquote{ font-style:italic;background-color:rgb(46,43,42,0.1);margin:0;margin-left:1em;border-radius:0 4px 4px 0;border:1px solid hsl(0,80%,32%);border-left-width:8px;border-top-width:0px;border-right-width:0px;border-bottom-width:0px;padding:10px 20px;margin-inline-start:30px;margin-inline-end:30px;}`;
|
||||
export const DEFAULT_MD_EMBED_CSS = `.snw-reference{display: none;}.excalidraw-md-host{padding:0px 10px}.excalidraw-md-footer{height:5px}foreignObject{background-color:transparent}p{display:block;margin-block-start:1em;margin-block-end:1em;margin-inline-start:0px;margin-inline-end:0px;color:inherit}table,tr,th,td{color:inherit;border:1px solid;border-collapse:collapse;padding:3px}th{font-weight:bold;border-bottom:double;background-color:silver}.copy-code-button{display:none}code[class*=language-],pre[class*=language-]{color:#393a34;font-family:"Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace;direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;font-size:.9em;line-height:1.2em;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre>code[class*=language-]{font-size:1em}pre[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,code[class*=language-] ::-moz-selection{background:#C1DEF1}pre[class*=language-]::selection,pre[class*=language-] ::selection,code[class*=language-]::selection,code[class*=language-] ::selection{background:#C1DEF1}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;background-color:#0000001a}:not(pre)>code[class*=language-]{padding:.2em;padding-top:1px;padding-bottom:1px;background:#f8f8f8;border:1px solid #dddddd}.token.comment,.token.prolog,.token.doctype,.token.cdata{color:green;font-style:italic}.token.namespace{opacity:.7}.token.string{color:#a31515}.token.punctuation,.token.operator{color:#393a34}.token.url,.token.symbol,.token.number,.token.boolean,.token.variable,.token.constant,.token.inserted{color:#36acaa}.token.atrule,.token.keyword,.token.attr-value,.language-autohotkey .token.selector,.language-json .token.boolean,.language-json .token.number,code[class*=language-css]{color:#00f}.token.function{color:#393a34}.token.deleted,.language-autohotkey .token.tag{color:#9a050f}.token.selector,.language-autohotkey .token.keyword{color:#00009f}.token.important{color:#e90}.token.important,.token.bold{font-weight:bold}.token.italic{font-style:italic}.token.class-name,.language-json .token.property{color:#2b91af}.token.tag,.token.selector{color:maroon}.token.attr-name,.token.property,.token.regex,.token.entity{color:red}.token.directive.tag .tag{background:#ffff00;color:#393a34}.line-numbers.line-numbers .line-numbers-rows{border-right-color:#a5a5a5}.line-numbers .line-numbers-rows>span:before{color:#2b91af}.line-highlight.line-highlight{background:rgba(193,222,241,.2);background:-webkit-linear-gradient(left,rgba(193,222,241,.2) 70%,rgba(221,222,241,0));background:linear-gradient(to right,rgba(193,222,241,.2) 70%,rgba(221,222,241,0))}blockquote{ font-style:italic;background-color:rgb(46,43,42,0.1);margin:0;margin-left:1em;border-radius:0 4px 4px 0;border:1px solid hsl(0,80%,32%);border-left-width:8px;border-top-width:0px;border-right-width:0px;border-bottom-width:0px;padding:10px 20px;margin-inline-start:30px;margin-inline-end:30px;}`;
|
||||
export const SCRIPTENGINE_ICON = `<g transform="translate(-8,-8)"><path d="M24.318 37.983c-1.234-1.232-8.433-3.903-7.401-7.387 1.057-3.484 9.893-12.443 13.669-13.517 3.776-1.074 6.142 6.523 9.012 7.073 2.87.55 6.797-1.572 8.207-3.694 1.384-2.148-3.147-7.413.15-9.168 3.298-1.755 16.389-2.646 19.611-1.284 3.247 1.363-1.611 7.335-.151 9.483 1.46 2.148 6.067 3.746 8.836 3.38 2.769-.368 4.154-6.733 7.728-5.633 3.575 1.1 12.36 8.828 13.67 12.233 1.308 3.406-5.186 5.423-5.79 8.2-.58 2.75-.026 6.705 2.265 8.355 2.266 1.65 9.642-1.78 11.404 1.598 1.762 3.38 1.007 15.35-.806 18.651-1.787 3.353-7.753-.367-9.969 1.31-2.215 1.65-3.901 5.92-3.373 8.67.504 2.777 7.754 4.48 6.445 7.885C96.49 87.543 87.15 95.454 83.5 96.685c-3.65 1.231-4.96-4.741-7.577-5.16-2.593-.393-6.57.707-8.03 2.75-1.436 2.017 2.668 7.806-.63 9.483-3.323 1.676-15.759 2.226-19.157.655-3.373-1.598.554-7.964-1.108-10.138-1.687-2.174-6.394-3.431-9.012-2.907-2.643.55-3.273 7.282-6.747 6.103-3.499-1.126-12.788-9.535-14.172-13.019-1.36-3.484 5.437-5.108 5.966-7.858.529-2.777-.68-7.073-2.744-8.697-2.064-1.624-7.93 2.41-9.642-1.126-1.737-3.537-2.441-16.765-.654-20.118 1.787-3.3 9.062 1.598 11.429.183 2.366-1.44 2.316-7.282 2.769-8.749m.126-.104c-1.234-1.232-8.433-3.903-7.401-7.387 1.057-3.484 9.893-12.443 13.669-13.517 3.776-1.074 6.142 6.523 9.012 7.073 2.87.55 6.797-1.572 8.207-3.694 1.384-2.148-3.147-7.413.15-9.168 3.298-1.755 16.389-2.646 19.611-1.284 3.247 1.363-1.611 7.335-.151 9.483 1.46 2.148 6.067 3.746 8.836 3.38 2.769-.368 4.154-6.733 7.728-5.633 3.575 1.1 12.36 8.828 13.67 12.233 1.308 3.406-5.186 5.423-5.79 8.2-.58 2.75-.026 6.705 2.265 8.355 2.266 1.65 9.642-1.78 11.404 1.598 1.762 3.38 1.007 15.35-.806 18.651-1.787 3.353-7.753-.367-9.969 1.31-2.215 1.65-3.901 5.92-3.373 8.67.504 2.777 7.754 4.48 6.445 7.885C96.49 87.543 87.15 95.454 83.5 96.685c-3.65 1.231-4.96-4.741-7.577-5.16-2.593-.393-6.57.707-8.03 2.75-1.436 2.017 2.668 7.806-.63 9.483-3.323 1.676-15.759 2.226-19.157.655-3.373-1.598.554-7.964-1.108-10.138-1.687-2.174-6.394-3.431-9.012-2.907-2.643.55-3.273 7.282-6.747 6.103-3.499-1.126-12.788-9.535-14.172-13.019-1.36-3.484 5.437-5.108 5.966-7.858.529-2.777-.68-7.073-2.744-8.697-2.064-1.624-7.93 2.41-9.642-1.126-1.737-3.537-2.441-16.765-.654-20.118 1.787-3.3 9.062 1.598 11.429.183 2.366-1.44 2.316-7.282 2.769-8.749" fill="none" stroke-width="2" stroke-linecap="round" stroke="currentColor"/><path d="M81.235 56.502a23.3 23.3 0 0 1-1.46 8.068 20.785 20.785 0 0 1-1.762 3.72 24.068 24.068 0 0 1-5.337 6.26 22.575 22.575 0 0 1-3.449 2.358 23.726 23.726 0 0 1-7.803 2.803 24.719 24.719 0 0 1-8.333 0 24.102 24.102 0 0 1-4.028-1.074 23.71 23.71 0 0 1-3.776-1.729 23.259 23.259 0 0 1-6.369-5.265 23.775 23.775 0 0 1-2.416-3.353 24.935 24.935 0 0 1-1.762-3.72 23.765 23.765 0 0 1-1.083-3.981 23.454 23.454 0 0 1 0-8.173c.252-1.336.604-2.698 1.083-3.956a24.935 24.935 0 0 1 1.762-3.72 22.587 22.587 0 0 1 2.416-3.378c.881-1.048 1.888-2.017 2.946-2.908a24.38 24.38 0 0 1 3.423-2.357 23.71 23.71 0 0 1 3.776-1.73 21.74 21.74 0 0 1 4.028-1.047 23.437 23.437 0 0 1 8.333 0 24.282 24.282 0 0 1 7.803 2.777 26.198 26.198 0 0 1 3.45 2.357 24.62 24.62 0 0 1 5.336 6.287 20.785 20.785 0 0 1 1.762 3.72 21.32 21.32 0 0 1 1.083 3.955c.251 1.336.302 3.405.377 4.086.05.681.05-.68 0 0" fill="none" stroke-width="4" stroke-linecap="round" stroke="currentColor"/><path d="M69.404 56.633c-6.596-3.3-13.216-6.6-19.51-9.744m19.51 9.744c-6.747-3.379-13.493-6.758-19.51-9.744m0 0v19.489m0-19.49v19.49m0 0c4.355-2.148 8.71-4.322 19.51-9.745m-19.51 9.745c3.978-1.965 7.93-3.956 19.51-9.745m0 0h0m0 0h0" fill="currentColor" stroke-linecap="round" stroke="currentColor" stroke-width="4"/></g>`;
|
||||
export const DISK_ICON_NAME = "disk";
|
||||
export const DISK_ICON = `<path fill="none" stroke="currentColor" fill="#fff" d="M0 0h100v100H0z"/><path fill="none" stroke="currentColor" d="M20.832 4.168c21.824.145 43.645.289 74.68.5m-74.68-.5c17.09.113 34.176.227 74.68.5m0 0c.094 27.3.191 54.602.32 91.164m-.32-91.164c.113 32.633.23 65.27.32 91.164m0 0H4.168m91.664 0H4.168m0 0v-75m0 75v-75m0 0L20.832 4.168M4.168 20.832L20.832 4.168M20.832 4.168h58.336m-58.336 0h58.336m0 0v25m0-25v25m0 0H20.832m58.336 0H20.832m0 0v-25m0 25v-25" stroke-width="1.66668" /><path fill="none" stroke="currentColor" d="M29.168 4.168h16.664v16.664H29.168"/><path fill="none" stroke="currentColor" d="M29.168 4.168h16.664m-16.664 0h16.664m0 0v16.664m0-16.664v16.664m0 0H29.168m16.664 0H29.168m0 0V4.168m0 16.664V4.168M12.5 54.168h75m-75 0h75m0 0v41.664m0-41.664v41.664m0 0h-75m75 0h-75m0 0V54.168m0 41.664V54.168M20.832 62.5c20.11-.18 40.219-.36 55.68-.5m-55.68.5c14.656-.133 29.313-.262 55.68-.5M20.832 71.332c13.098-.117 26.2-.234 55.68-.5m-55.68.5l55.68-.5M21.117 79.582c20.645-.184 41.285-.371 55.68-.5m-55.68.5c18.153-.16 36.301-.324 55.68-.5" stroke-width="1.66668"/>`;
|
||||
export const DISK_ICON_NAME = "save";
|
||||
export const PNG_ICON_NAME = "save-png";
|
||||
export const PNG_ICON = `<defs><symbol overflow="visible" id="aa"><path fill="currentColor" stroke="currentColor" d="M6.578-10.984h8.188c2.03 0 3.64-.594 5.046-1.844 1.563-1.422 2.25-3.094 2.25-5.469 0-4.875-2.906-7.61-8.046-7.61H3.25V0h3.328zm0-2.907v-9.093h6.938c3.171 0 5.078 1.703 5.078 4.547 0 2.843-1.907 4.546-5.078 4.546zm0 0"></path></symbol><symbol overflow="visible" id="bb"><path fill="currentColor" stroke="currentColor" d="M23.094-25.906h-3.14V-4.72L6.327-25.906h-3.61V0H5.86v-21L19.344 0h3.75zm0 0"></path></symbol><symbol overflow="visible" id="cc"><path fill="currentColor" stroke="currentColor" d="M25.344-13.672h-10.86v2.906h7.938v.704c0 4.624-3.438 7.968-8.188 7.968-2.656 0-5.046-.969-6.578-2.625-1.718-1.86-2.765-4.953-2.765-8.14 0-6.36 3.656-10.563 9.156-10.563 3.969 0 6.828 2.031 7.547 5.375h3.39c-.922-5.265-4.922-8.281-10.906-8.281-3.172 0-5.75.812-7.781 2.484-3.047 2.485-4.719 6.5-4.719 11.157 0 7.968 4.89 13.5 11.938 13.5 3.53 0 6.328-1.313 8.906-4.11l.812 3.438h2.11zm0 0"></path></symbol></defs><path fill="none" stroke="currentColor" d="M-.003.003v59.999m0-60v60m0 0h220.006m-220.006 0h220.006m0 0v-60m0 60v-60" transform="matrix(.40833 0 0 .40574 4.083 68.975)" stroke-width="4"></path><use xlink:href="#aa" x="11.023" y="86.651"></use><use xlink:href="#bb" x="33.944" y="86.651"></use><use xlink:href="#cc" x="59.724" y="86.651"></use><path fill="currentColor" stroke="currentColor" d="M40.832 4.059h16.336v32.457h8.164L49 52.746l-16.332-16.23h8.164V4.059" fill-rule="evenodd"></path><path fill="currentColor" stroke="currentColor" d="M-.003.003h40.006m-40.006 0h40.006m0 0v79.995m0-79.995v79.995m0 0h19.994m-19.994 0h19.994m0 0C51.55 88.451 43.093 96.904 20 120m39.997-40.002A196001.962 196001.962 0 0120 120m0 0C8.406 108.41-3.18 96.817-19.997 79.998M20 120C9.43 109.43-1.142 98.858-19.997 79.998m0 0H-.003m-19.994 0H-.003m0 0V.003m0 79.995V.003m0 0h0m0 0h0" transform="matrix(.40833 0 0 .40574 40.833 4.057)" stroke-width="4"></path>`;
|
||||
export const SVG_ICON_NAME = "save-svg";
|
||||
|
||||
54
src/dialogs/ImportSVGDialog.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { App, FuzzySuggestModal, TFile } from "obsidian";
|
||||
import { REG_LINKINDEX_INVALIDCHARS } from "../Constants";
|
||||
import ExcalidrawView from "../ExcalidrawView";
|
||||
import { t } from "../lang/helpers";
|
||||
import ExcalidrawPlugin from "../main";
|
||||
|
||||
export class ImportSVGDialog extends FuzzySuggestModal<TFile> {
|
||||
public app: App;
|
||||
public plugin: ExcalidrawPlugin;
|
||||
private view: ExcalidrawView;
|
||||
|
||||
constructor(plugin: ExcalidrawPlugin) {
|
||||
super(plugin.app);
|
||||
this.plugin = plugin;
|
||||
this.app = plugin.app;
|
||||
this.limit = 20;
|
||||
this.setInstructions([
|
||||
{
|
||||
command: t("SELECT_FILE"),
|
||||
purpose: "",
|
||||
},
|
||||
]);
|
||||
this.setPlaceholder(t("SELECT_DRAWING"));
|
||||
this.emptyStateText = t("NO_MATCH");
|
||||
}
|
||||
|
||||
getItems(): TFile[] {
|
||||
return (this.app.vault.getFiles() || []).filter(
|
||||
(f: TFile) => f.extension === "svg" &&
|
||||
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/422
|
||||
!f.path.match(REG_LINKINDEX_INVALIDCHARS),
|
||||
);
|
||||
}
|
||||
|
||||
getItemText(item: TFile): string {
|
||||
return item.path;
|
||||
}
|
||||
|
||||
async onChooseItem(item: TFile, event: KeyboardEvent): Promise<void> {
|
||||
if(!item) return;
|
||||
const ea = this.plugin.ea;
|
||||
ea.reset();
|
||||
ea.setView(this.view);
|
||||
const svg = await app.vault.read(item);
|
||||
if(!svg || svg === "") return;
|
||||
ea.importSVG(svg);
|
||||
ea.addElementsToView(true, true, true);
|
||||
}
|
||||
|
||||
public start(view: ExcalidrawView) {
|
||||
this.view = view;
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
@@ -17,12 +17,23 @@ export class InsertImageDialog extends FuzzySuggestModal<TFile> {
|
||||
this.limit = 20;
|
||||
this.setInstructions([
|
||||
{
|
||||
command: t("SELECT_FILE"),
|
||||
command: t("SELECT_FILE_WITH_OPTION_TO_SCALE"),
|
||||
purpose: "",
|
||||
},
|
||||
]);
|
||||
this.setPlaceholder(t("SELECT_DRAWING"));
|
||||
this.emptyStateText = t("NO_MATCH");
|
||||
this.inputEl.onkeyup = (e) => {
|
||||
//@ts-ignore
|
||||
if (e.key === "Enter" && e.altKey && this.chooser.values) {
|
||||
this.onChooseItem(
|
||||
//@ts-ignore
|
||||
this.chooser.values[this.chooser.selectedItem].item,
|
||||
new KeyboardEvent("keypress",{altKey: true})
|
||||
);
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getItems(): TFile[] {
|
||||
@@ -39,13 +50,13 @@ export class InsertImageDialog extends FuzzySuggestModal<TFile> {
|
||||
return item.path;
|
||||
}
|
||||
|
||||
onChooseItem(item: TFile): void {
|
||||
onChooseItem(item: TFile, event: KeyboardEvent): void {
|
||||
const ea = this.plugin.ea;
|
||||
ea.reset();
|
||||
ea.setView(this.view);
|
||||
ea.canvas.theme = this.view.excalidrawAPI.getAppState().theme;
|
||||
(async () => {
|
||||
await ea.addImage(0, 0, item);
|
||||
await ea.addImage(0, 0, item, !event.altKey);
|
||||
ea.addElementsToView(true, false, true);
|
||||
})();
|
||||
}
|
||||
|
||||
@@ -11,12 +11,490 @@ Thank you & Enjoy!
|
||||
`;
|
||||
|
||||
export const RELEASE_NOTES: { [k: string]: string } = {
|
||||
Intro: `I want to help you keep up with all the updates. After installing each release, you'll be prompted with a summary of new features and fixes. You can disable these popup messages in plugin settings.
|
||||
Intro: `After each update you'll be prompted with the release notes. You can disable this in plugin settings.
|
||||
|
||||
I develop this plugin as a hobby, spending most of my free time doing this. If you'd like to contribute to the on-going work, I have a simple membership scheme with Bronze, Silver and Gold tiers. Many of you have already bought me a coffee. THANK YOU! It really means a lot to me! If you find this plugin valuable, please consider supporting me.
|
||||
I develop this plugin as a hobby, spending my free time doing this. If you find it valuable, then please say THANK YOU or...
|
||||
|
||||
<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.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>
|
||||
<iframe src="https://www.youtube.com/embed/HhRHFhWkmCk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div></div>
|
||||
|
||||
## Fixed
|
||||
- Obsidian tools panel gets misplaced after switching Obsidian workspace tabs
|
||||
|
||||
## New in ExcalidrawAutomate
|
||||
- changed ${String.fromCharCode(96)}viewToggleFullScreen(forceViewMode: boolean = false): void${String.fromCharCode(96)}: the function will toggle view mode on when going to full screen and view mode off when terminating full screen.
|
||||
- new functions
|
||||
${String.fromCharCode(96, 96, 96)}typescript
|
||||
setViewModeEnabled(enabled: boolean):void;
|
||||
viewUpdateScene(
|
||||
scene: {
|
||||
elements?: ExcalidrawElement[];
|
||||
appState?: AppState;
|
||||
files?: BinaryFileData;
|
||||
commitToHistory?: boolean;
|
||||
},
|
||||
restore: boolean = false,
|
||||
):void;
|
||||
viewZoomToElements(
|
||||
selectElements: boolean,
|
||||
elements: ExcalidrawElement[]
|
||||
):void;
|
||||
${String.fromCharCode(96, 96, 96)}
|
||||
|
||||
`,
|
||||
"1.8.1": `
|
||||
## New and fixes from Excalidraw.com
|
||||
- New text paste behavior. Pasting multiline text will generate separate text elements unless you hold down the shift button while pasting [#5786](https://github.com/excalidraw/excalidraw/pull/5786)
|
||||
- line editor fixes [#5927](https://github.com/excalidraw/excalidraw/pull/5927)
|
||||
|
||||
## Fixed
|
||||
- The Command Palette "Insert link" action now inserts the new link at the top drawing layer, not at the bottom.
|
||||
- Updated, hopefully, better organized, Plugin Readme.
|
||||
|
||||
## New
|
||||
- Second attempt at moving to React 18. This upgrade is required to maintain alignment with the core Excalidraw product and to continue to benefit from Excalidraw.com enhancements.
|
||||
- Added options to Plugin Settings
|
||||
- to disable autozoom when loading a drawing for the first time [#907](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/907)
|
||||
- to modify autosave interval. You can now set an autosave interval for desktop and for mobile [#888](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/888)
|
||||
|
||||
## New in ExcalidrawAutomate
|
||||
- Published the obsidian_module on the ExcalidrawAutomate object. ${String.fromCharCode(96)}ExcalidrawAutomate.obsidian${String.fromCharCode(96)}. Publishing this object will give script developers increased flexibility and control over script automation.
|
||||
`,
|
||||
"1.8.0": `
|
||||
<div class="excalidraw-videoWrapper"><div>
|
||||
<iframe src="https://www.youtube.com/embed/7gu4ETx7zro" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div></div>
|
||||
|
||||
## New
|
||||
- Optical Character Recognition (OCR). Introducing the MVP (minimum viable product) release of the integration of [Taskbone](https://taskbone.com) OCR into Excalidraw. See the new scan button on the Obsidian tools panel.
|
||||
- New and improved full-screen mode
|
||||
- Activate using the Obsidian tools panel, the Obsidian Command Palette, or the Alt+F11 shortcut
|
||||
- The ESC key no longer closes full-screen
|
||||
- Full-screen mode works properly on iOS as well
|
||||
- Improved Icon visibility on the Obsidian tools panel
|
||||
- Added 3 additional buttons to the tools panel
|
||||
- Force save
|
||||
- Open link (useful on Mobile devices). In the case of LaTeX equations, the button opens the equation properties.
|
||||
- Open the link in a new pane. In the case of embedded markdown documents, the button opens the embed properties.
|
||||
|
||||
## Fixed
|
||||
- The [deconstruct selected elements into a new drawing](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/Deconstruct%20selected%20elements%20into%20new%20drawing.md) script now also correctly decomposes transcluded text elements.
|
||||
`,
|
||||
"1.7.30":`
|
||||
Fix:
|
||||
- Forcing the embedded image to always scale to 100% (a feature introduced in [1.7.26](https://github.com/zsviczian/obsidian-excalidraw-plugin/releases/tag/1.7.26)) scaled the embedded excalidraw drawings incorrectly on devices with a pixel ratio of 2 or 3 (e.g. iPads). This is now fixed, however, this fix might retrospectively impact drawings that use this feature. Sorry for that.
|
||||
`,
|
||||
"1.7.29":`
|
||||
- This is a big update that accommodates the **UI redesign** on Excalidraw.com [#5780](https://github.com/excalidraw/excalidraw/pull/5780). The change on the surface may seem superficial, however, I had to tweak a number of things to make it work in Obsidian. I hope I found everything that broke and fixed it, if not, I'll try to fix it quickly...
|
||||
- This update also comes with changes under the hood that **fix issues with Excalidraw Automate** - paving the way for further scripts, plus some smaller bug fixes.
|
||||
- I **reworked text wrapping**. In some cases, text wrapping in SVG exports looked different compared to how the text looked in Excalidraw. This should now be fixed.
|
||||
- If you are using the **Experimental Dynamic Styling** of the Excalidraw Toolbar, then I recommend updating your styling script following base on [this](https://gist.github.com/zsviczian/c7223c5b4af30d5c88a0cae05300305c)
|
||||
`,
|
||||
"1.7.27":`## New
|
||||
- Import SVG drawing as an Excalidraw object. [#679](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/679)
|
||||
|
||||
<div class="excalidraw-videoWrapper"><div>
|
||||
<iframe src="https://www.youtube.com/embed/vlC1-iBvIfo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div></div>
|
||||
|
||||
## Fixed
|
||||
- Large drawings freeze on the iPad when opening the file. I implemented a workaround whereby Excalidraw will avoid zoom-to-fit drawings with over 1000 elements. [#863](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/863)
|
||||
- Reintroduced copy/paste to the context menu
|
||||
`,
|
||||
"1.7.26":`## Fixed
|
||||
- Transcluded block with a parent bullet does not embed sub-bullet [#853](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/853)
|
||||
- Transcluded text will now exclude ^block-references at end of lines
|
||||
- Phantom duplicates of the drawing appear when "zoom to fit" results in a zoom value below 10% and there are many objects on the canvas [#850](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/850)
|
||||
- CTRL+Wheel will increase/decrease zoom in steps of 5% matching the behavior of the "+" & "-" zoom buttons.
|
||||
- Latest updates from Excalidarw.com
|
||||
- Freedraw flip not scaling correctly [#5752](https://github.com/excalidraw/excalidraw/pull/5752)
|
||||
- Multiple elements resizing regressions [#5586](https://github.com/excalidraw/excalidraw/pull/5586)
|
||||
|
||||
## New - power user features
|
||||
- Force the embedded image to always scale to 100%. Note: this is a very niche feature with a very particular behavior that I built primarily for myself (even more so than other features in Excalidraw Obsidian - also built primarily for myself 😉)... This will reset your embedded image to 100% size every time you open the Excalidraw drawing, or in case you have embedded an Excalidraw drawing on your canvas inserted using this function, every time you update the embedded drawing, it will be scaled back to 100% size. This means that even if you resize the image on the drawing, it will reset to 100% the next time you open the file or you modify the original embedded object. This feature is useful when you decompose a drawing into separate Excalidraw files, but when combined onto a single canvas you want the individual pieces to maintain their actual sizes. I use this feature to construct Book-on-a-Page summaries from atomic drawings.
|
||||
- I added an action to the command palette to temporarily disable/enable Excalidraw autosave. When autosave is disabled, Excalidraw will still save your drawing when changing to another Obsidian window, but it will not save every 10 seconds. On a mobile device (but also on a desktop) this can lead to data loss if you terminate Obsidian abruptly (i.e. swipe the application away, or close Obsidian without first closing the drawing). Use this feature if you find Excalidraw laggy.`,
|
||||
"1.7.25":`## Fixed
|
||||
- Tool buttons did not "stick" the first time you clicked them.
|
||||
- Tray (in tray mode) was higher when the help button was visible. The tray in tablet mode was too large and the help button was missing.
|
||||
- ExcalidrawAutomate ${String.fromCharCode(96)}getCM(color:TInput): ColorMaster;${String.fromCharCode(96)} function will now properly convert valid [css color names](https://www.w3schools.com/colors/colors_names.asp) to ColorMaster objects.
|
||||
- The downloaded script icons in the Excalidraw-Obsidian menu were not always correct
|
||||
- The obsidian mobile navigation bar at the bottom overlapped with Excalidraw
|
||||
|
||||
## New
|
||||
- Created ExcalidrawAutomate hook for styling script when the canvas color changes. See sample [onCanvasColorChangeHook](https://gist.github.com/zsviczian/c7223c5b4af30d5c88a0cae05300305c) implementation following the link.
|
||||
|
||||
<div class="excalidraw-videoWrapper"><div>
|
||||
<iframe src="https://www.youtube.com/embed/LtR04fNTKTM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div></div>
|
||||
|
||||
${String.fromCharCode(96, 96, 96)}typescript
|
||||
/**
|
||||
* If set, this callback is triggered whenever the active canvas color changes
|
||||
*/
|
||||
onCanvasColorChangeHook: (
|
||||
ea: ExcalidrawAutomate,
|
||||
view: ExcalidrawView, //the Excalidraw view
|
||||
color: string,
|
||||
) => void = null;
|
||||
${String.fromCharCode(96, 96, 96)}
|
||||
`,
|
||||
"1.7.24":`
|
||||
# New and improved
|
||||
- **Updated Chinese translation**. Thanks, @tswwe!
|
||||
- **Improved update for TextElement links**: Until now, when you attached a link to a file to a TextElement using the "Create Link" command, this link did not get updated when the file was renamed or moved. Only links created as markdown links in the TextElement text were updated. Now both approaches work. Keep in mind however, that if you have a link in the TextElemenet text, it will override the link attached to the text element using the create link command. [#566](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/566)
|
||||
- **Transclusion filters markdown comments**: Text transclusion in a TextElement using the ${String.fromCharCode(96)}![[file]]${String.fromCharCode(96)} or ${String.fromCharCode(96)}![[file#section]]${String.fromCharCode(96)} format did not filter out markdown comments in the file placed ${String.fromCharCode(96)}%% inside a comment block %%${String.fromCharCode(96)}. Now they do.
|
||||
- **Remove leading '>' from trancluded quotes**: Added a new option in settings under **Links and Transclusion** to remove the leading ${String.fromCharCode(96)}> ${String.fromCharCode(96)} characters from quotes you transclude as a text element in your drawing.
|
||||

|
||||
- **Added support for ${String.fromCharCode(96)}webp${String.fromCharCode(96)}, ${String.fromCharCode(96)}bmp${String.fromCharCode(96)}, and ${String.fromCharCode(96)}ico${String.fromCharCode(96)} images**. This extends the already supported formats (${String.fromCharCode(96)}jpg${String.fromCharCode(96)}, ${String.fromCharCode(96)}gif${String.fromCharCode(96)}, ${String.fromCharCode(96)}png${String.fromCharCode(96)}, ${String.fromCharCode(96)}svg${String.fromCharCode(96)}).
|
||||
- **Added command palette action to reset images to original size**. Select a single image or embedded Excalidraw drawing on your canvas and choose ${String.fromCharCode(96)}Set selected image element size to 100% of original${String.fromCharCode(96)} from the command palette. This function is especially helpful when you combine atomic drawings on a single canvas, keeping each atomic piece in its original excalidraw file (i.e. the way I create [book on a page summaries](https://www.youtube.com/playlist?list=PL6mqgtMZ4NP1-mbCYc3T7mr-unmsIXpEG))
|
||||
- The ${String.fromCharCode(96)}async getOriginalImageSize(imageElement: ExcalidrawImageElement): Promise<{width: number; height: number}>${String.fromCharCode(96)} function is also avaiable via ExcalidrawAutomate. You may use this function to resize images to custom scales (e.g. 50% size, or to fit a certain bounding rectangle).
|
||||
|
||||
# Fixed
|
||||
- **Upgraded perfect freehand package to resolve unwanted dots on end of lines** [#5727](https://github.com/excalidraw/excalidraw/pull/5727)
|
||||
- **Pinch zoom in View mode opens images** resulting in a very annoying behavior [#837](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/837)
|
||||
- **Embedded files** such as transcluded markdown documents and images **did not honor the Obsidian "New Link Format" setting** (shortest path, relative path, absolute path). [#829](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/829)
|
||||
- **Fixed error with dataview queries involving Excalidraw files**: In case you created a task on an Excalidraw canvas (${String.fromCharCode(96)}docA.md${String.fromCharCode(96)}) by typing ${String.fromCharCode(96)}- [ ] Task [[owner]] #tag${String.fromCharCode(96)}, and then you created a Dataview tasklist in another document (${String.fromCharCode(96)}docB.md${String.fromCharCode(96)}) such that the query criteria matched the task in ${String.fromCharCode(96)}docA.md${String.fromCharCode(96)}, then the task from ${String.fromCharCode(96)}docA.md${String.fromCharCode(96)} only appeared as an empty line when viewing ${String.fromCharCode(96)}docB.md${String.fromCharCode(96)}. If you now embedded ${String.fromCharCode(96)}docB.md${String.fromCharCode(96)} into a third markdown document (${String.fromCharCode(96)}docC.md${String.fromCharCode(96)}), then instead of the contents of ${String.fromCharCode(96)}docB.md${String.fromCharCode(96)} Obsidian rendered ${String.fromCharCode(96)}docA.md${String.fromCharCode(96)}. [#835](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/835)
|
||||
`,
|
||||
"1.7.22":`
|
||||
# Fixed
|
||||
- Text size in sticky notes increased when opening the drawing and when editing a sticky note [#824](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/824)
|
||||
- ToDo rendering did not work properly when there were parsed links in the text
|
||||
- Horizontal text alignment in sticky notes did not honor text alignment setting when resizing text. The text was always aligned center even when text alignment was left or right. [#5720](https://github.com/excalidraw/excalidraw/issues/5720)
|
||||
`,
|
||||
"1.7.21":`
|
||||
# New from Excalidraw.com
|
||||
- Image-mirroring in export preview and in exported SVG [#5700](https://github.com/excalidraw/excalidraw/pull/5700), [#811](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/811), [#617](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/617)
|
||||
|
||||
# New
|
||||
- Ctrl+s will force-save your drawing and update all your transclusions
|
||||
- Added setting to parse ${String.fromCharCode(96)}- [ ] ${String.fromCharCode(96)} and ${String.fromCharCode(96)}- [x] ${String.fromCharCode(96)} todo items. Parsing is disabled by default. This feature can be found under "Links and Transclusions" in Plugin Settings. [#819](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/819)
|
||||
|
||||

|
||||
|
||||
<iframe src="https://user-images.githubusercontent.com/14358394/192151120-3c61c822-0352-4ba7-9900-b38078fb373c.mp4" title="Demo" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div></div>
|
||||
|
||||
- Added new scripts to the script library
|
||||
- [Rename Image](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/Rename%20Image.md)
|
||||
- [Text Arch](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/Text%20Arch.md)
|
||||
|
||||
<iframe src="https://user-images.githubusercontent.com/14358394/192151105-78c0115b-4e30-4296-b647-e3c05851a48f.mp4" title="Demo" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div></div>
|
||||
|
||||
# Fixed
|
||||
- Fixed toast message to display script name on press and hold on mobile and iPad.
|
||||
- Fixed save error when the embedded image file is not found (i.e. it was moved, renamed, or deleted)
|
||||
|
||||
`,
|
||||
"1.7.20":`
|
||||
# New from Excalidraw.com
|
||||
- support segment midpoints in line editor [#5641](https://github.com/excalidraw/excalidraw/pull/5641)
|
||||
<div class="excalidraw-videoWrapper"><div>
|
||||
<iframe src="https://user-images.githubusercontent.com/11256141/187417807-3efeb673-6c96-4744-be0e-70119b0c6839.mp4" title="Demo" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div></div>
|
||||
|
||||
# Fixed
|
||||
- When editing a line or arrow and selecting a tool on the toolbar, the tool jumps back to the selection tool and you need to click again to select the tool [#5703](https://github.com/excalidraw/excalidraw/issues/5703)
|
||||
- Minor improvement of autosave, hopefully decreasing occasional lagging
|
||||
`,
|
||||
"1.7.19":`
|
||||
# QoL improvements
|
||||
- Reintroduced the help button. I also added the help button to the Tray (in Tray Mode) and moved help to the canvas action panel (in non-TrayMode) because in Obsidian 0.16.0 the status bar hides the help icon.
|
||||
- Resetting the canvas with the "Reset Canvas" button will now preserve your custom color palette.
|
||||
- I updated the [Set background color of unlclosed line object](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/Set%20background%20color%20of%20unclosed%20line%20object%20by%20adding%20a%20shadow%20clone.md) script. The script will now add background color to open freedraw objects as well. You no longer need to convert freedraw objects to lines before setting the background color. Check the Script Engine library to download the update.
|
||||
|
||||
# New in Excalidraw Automate
|
||||
- I added the [ColorMaster](https://github.com/lbragile/ColorMaster#readme) library to ExcalidrawAutomate. You can get a CM object by calling ${String.fromCharCode(96)}ExcalidrawAutomate.getCM(<your color comes here>)${String.fromCharCode(96)}. Color master introduces many new ways to manipulate colors from script. I will publish scripts that make use of this new functionality including supporting videos on my YouTube channel in the coming days.
|
||||
`,
|
||||
"1.7.18":`
|
||||
## Critical fix
|
||||
- duplicating text elements, adding text elements from the library, and pasting excalidraw text elements results in a corrupted file!!`,
|
||||
"1.7.17":`
|
||||
## Fixed
|
||||
- Block transclusions sometimes got lost when switching between RAW mode and PREVIEW mode. [#769](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/769)
|
||||
|
||||
## New
|
||||
- Added feature to disable "new Excalidraw version" notification [#770](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/770)
|
||||
- Added option to export both light- and dark-themed images at the same time. If this is enabled Excalidraw will create two files "filename.dark.png" and "filename.light.png" (or .svg depending on your other settings). See practical use case here: [Aadam's Notes](https://notes.aadam.dev/SBYNtPHqsTW9Ck1Kuoxsu/)
|
||||
- Added custom export padding for PNG images. Use the frontmatter key ${String.fromCharCode(96)}excalidraw-export-padding${String.fromCharCode(96)} to set the padding at a file level, or set padding for all your files in plugin settings. The new feature replaces the old "SVG Padding" option and applies to both SVG and PNG exports.
|
||||
|
||||
## ExcalidrawAutomate
|
||||
- Added ${String.fromCharCode(96)}padding${String.fromCharCode(96)} to the createPNG function call.
|
||||
${String.fromCharCode(96, 96, 96)}typescript
|
||||
async createPNG(
|
||||
templatePath?: string,
|
||||
scale: number = 1,
|
||||
exportSettings?: ExportSettings,
|
||||
loader?: EmbeddedFilesLoader,
|
||||
theme?: string,
|
||||
padding?: number,
|
||||
)
|
||||
${String.fromCharCode(96, 96, 96)}
|
||||
`,
|
||||
"1.7.16":`
|
||||
## Fixed
|
||||
- Excalidraw canvas is empty after saving the drawing and re-opening it at a later time. If you accidentally paste Excalidraw elements from the clipboard as the contents of a text element, in certain situations this can corrupt the Excalidraw file and as a result, Excalidraw will load an empty-looking drawing the next time. Changing to markdown view, these files can be repaired, however, to avoid accidental data loss, I have prevented pasting of excalidraw clipboard contents as text elements. [#768](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/768)
|
||||
|
||||
## New
|
||||
- Add zoom % display in tray-mode [737](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/737)
|
||||
`,
|
||||
"1.7.15":`
|
||||
## Fixed
|
||||
- Canvas turns white when adding point for curved line [#760](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/760), [#738](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/738), [#5602](https://github.com/excalidraw/excalidraw/issues/5602)
|
||||
`,
|
||||
"1.7.14": `
|
||||
<div class="excalidraw-videoWrapper"><div>
|
||||
<iframe src="https://www.youtube.com/embed/yZQoJg2RCKI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div></div>
|
||||
|
||||
## New
|
||||
- The ${String.fromCharCode(96)}Copy markdown link for selected element to clipboard${String.fromCharCode(96)} action in the Obsidian menu is now more intelligent. If multiple elements are selected it will copy the Element Reference for the largest element.
|
||||
- When referencing an element in a link pointing to an Excalidraw file using the elementId or the section header as the block reference e.g. ${String.fromCharCode(96)}[[file#^elementID]]${String.fromCharCode(96)}, you can now add the ${String.fromCharCode(96)}group=${String.fromCharCode(96)} prefix, e.g. ${String.fromCharCode(96)}[[file#^group=elementID]]${String.fromCharCode(96)} and the ${String.fromCharCode(96)}area=${String.fromCharCode(96)} prefix, e.g. ${String.fromCharCode(96)}[[file#area=Section heading]]${String.fromCharCode(96)}.
|
||||
- If the ${String.fromCharCode(96)}group=${String.fromCharCode(96)} prefix is found, Excalidraw will select the group of elements in the same group as the element referenced by the elementID or heading section.
|
||||
- If the ${String.fromCharCode(96)}area=${String.fromCharCode(96)} prefix is found, excalidraw will insert a cutout of the image around the referenced element.
|
||||
- The ${String.fromCharCode(96)}area=${String.fromCharCode(96)} selector is not supported when embedding Excalidraw as PNG into your markdown documents.
|
||||
- I added "Toggle left-handed mode" to the Command Palette. The action is only visible if tray-mode is enabled. It will move the tray from left to right and back. [749](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/749)
|
||||
|
||||
## Fixed
|
||||
- Zooming with CTRL+Wheel will no longer trigger hover preview.
|
||||
- When editing text in a text element CTRL+C will not launch the hover preview in case the mouse pointer is over the text element being edited. Hover preview will only show if the element is not in editing mode.
|
||||
- ExcalidrawAutomate did not reliably save changes. This caused issues for example in the "Add link to an existing file and open" script. [#747](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/747)
|
||||
- Create a new folder not working when clicking on a link in Erxcalidraw that points to a file that is in a folder that does not yet exist. [741](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/741)
|
||||
- Downgraded to React 17 due to various stability issues, including [#738](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/738) and [#747](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/747)
|
||||
|
||||
## New in Excalidraw Automate
|
||||
- I added two new Excalidraw Automate functions
|
||||
${String.fromCharCode(96, 96, 96)}typescript
|
||||
/**
|
||||
* Gets the groupId for the group that contains all the elements, or null if such a group does not exist
|
||||
* @param elements
|
||||
* @returns null or the groupId
|
||||
*/
|
||||
getCommonGroupForElements(elements: ExcalidrawElement[]): string;
|
||||
|
||||
/**
|
||||
* Gets all the elements from elements[] that share one or more groupIds with element.
|
||||
* @param element
|
||||
* @param elements - typically all the non-deleted elements in the scene
|
||||
* @returns
|
||||
*/
|
||||
getElementsInTheSameGroupWithElement(element: ExcalidrawElement, elements: ExcalidrawElement[]): ExcalidrawElement[];
|
||||
${String.fromCharCode(96, 96, 96)}`,
|
||||
"1.7.13": `
|
||||
## Fix from Excalidraw.com
|
||||
- Resize multiple elements from center ([#5560](https://github.com/excalidraw/excalidraw/pull/5560))
|
||||
|
||||
## Obsidian 0.16.0 compatibility (getting ready, because 0.16.0 will be available to insiders soon)
|
||||
- ${String.fromCharCode(96)}Install or update Excalidraw Scripts${String.fromCharCode(96)} was only available via the page header button. Because the page header is hidden by default, the install script action is now available through the pane menu and through the command palette as well.
|
||||
- ${String.fromCharCode(96)}Open selected text as link${String.fromCharCode(96)} page header button is now also available via the pane menu
|
||||
- ${String.fromCharCode(96)}Open in Adjacent Pane${String.fromCharCode(96)} and ${String.fromCharCode(96)}Open in Main Workspace${String.fromCharCode(96)} Excalidraw plugin settings is fixed
|
||||
`,
|
||||
"1.7.12": `
|
||||
## New from Excalidraw.com:
|
||||
- Showing a mid-point for lines and arrows. By touching the mid-point you can easily add an additional point to a two-point line. This is especially helpful when working on a tablet with touch input. ([#5534](https://github.com/excalidraw/excalidraw/pull/5534))
|
||||
- Lock angle when editing a line or an arrow with SHIFT pressed. Pressing SHIFT will restrict the edited point to snap to certain discrete angles. ([#5527](https://github.com/excalidraw/excalidraw/pull/5527))
|
||||
|
||||
## Fixed:
|
||||
- Clicking Obsidian search-results pointing to an element on the canvas works again ([#734](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/734))
|
||||
- The feature to allow resizing and rotation of lines and arrows consisting of 3 or more points by showing the bounding box when selected is back ([#5554](https://github.com/excalidraw/excalidraw/pull/5554))
|
||||
|
||||
## New
|
||||
- You can now use the following frontmatter key to allow/prevent automatic export of PNG/SVG images at a file level. This frontmatter will override export settings for the given file. ([#732](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/732)
|
||||
${String.fromCharCode(96)}excalidraw-autoexport: none|both|svg|png${String.fromCharCode(96)}
|
||||
`,
|
||||
"1.7.11": `
|
||||
## Fixed
|
||||
- Markdown files embed into the Excalidraw canvas crashed when the embedded markdown file included a nested Markdown embed with a block reference (i.e. the markdown document you are dropping into Excalidraw included a quote you referenced from another file using a ${String.fromCharCode(96)}[[other-file#^blockref]]${String.fromCharCode(96)} block or section reference.
|
||||
- Horizontal flipping of arrows and lines broke in 1.7.10. ([#726](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/726))
|
||||
`,
|
||||
"1.7.10": `
|
||||
## New from Excalidraw.com
|
||||
- Improved handling of arrows and lines. ([#5501](https://github.com/excalidraw/excalidraw/pull/5501))
|
||||
|
||||
## Fixed
|
||||
- When opening a document in view-mode or zen-mode the panel buttons no longer flash up for a moment before switching to the desired mode. ([#479](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/479))
|
||||
- The "blinding white screen" no longer flashes up while loading the scene if the scene is dark ([#241](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/241))
|
||||
|
||||
## Under the hood
|
||||
- Finalized migration to React 18 (no longer showing an error about React 17 compatibility mode in console log)
|
||||
`,
|
||||
"1.7.9": `
|
||||
## New features and fixes from Excalidraw.com:
|
||||
- The right-click context menu is now scrollable on smaller screens ([#4030](https://github.com/excalidraw/excalidraw/pull/4030), [#5520](https://github.com/excalidraw/excalidraw/pull/5520))
|
||||
- Holding down the shift key while rotating an object will rotate it at discrete angles. Rotation is continuous without the SHIFT key. ([#5500](https://github.com/excalidraw/excalidraw/pull/5500))
|
||||
- Improved cursor alignment when resizing an element proportionally (maintain aspect ratio) by holding SHIFT during resizing. ([#5513](https://github.com/excalidraw/excalidraw/pull/5515))
|
||||
- Improved freedraw performance during editing (now has proper canvas caching), and no more blurry freedraw shapes when exporting on a higher scale. ([#5481](https://github.com/excalidraw/excalidraw/pull/5481))
|
||||
- Sidebar stencil library now correctly scrolls vertically ([#5459](https://github.com/excalidraw/excalidraw/pull/5459))
|
||||
|
||||
## New in Obsidian:
|
||||
- Fullscreen mode on iPad. When there are multiple work panes open, clicking the fullscreen action in the Excalidraw Obsidian menu will hide the other work panes and make Excalidraw fullscreen.
|
||||
|
||||
## Fixes in Obsidian:
|
||||
- Drag&Drop an image from a web browser into Excalidraw ([#697](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/697))
|
||||
- On Obsidian Mobile 1.3.0, when the drawing included an embedded image, switching from markdown-view to Excalidraw-view caused the drawing to disappear (it had to be recovered from backup or synchronization history). ([#715](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/715))
|
||||
- When working on a mobile device (tablet and phone) and using two work panes (one for drawing and the other for editing a markdown document) if you switched focus from the drawing to the markdown document auto-zoom changed the zoom level of the drawing. ([#723](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/723)), ([#705](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/705))
|
||||
- Actions on the Command Palette to create a new drawing in a new pane or reusing an existing adjacent pane; on the main workspace or in the Hover Editor or Popout window, were not working well. See related settings in plugin settings under "Links and transclusions" ([#718](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/718))
|
||||
- There was a problem with links with section references when the header contained space characters ([#704](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/704))
|
||||
- I added additional controls to avoid the fantom warnings about a problem with saving the Excalidraw file. Hopefully, from now on, you'll see this error less frequently ([#701](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/701))
|
||||
`,
|
||||
"1.7.8": `
|
||||
# Optimized for Obsidian 0.15.5
|
||||
- I reworked how the plugin treats the "More options" menu because the old approach was interfering with Obsidian
|
||||
- Did thorough testing of handling of work panes on link click. There are two settings (open in the adjacent pane, and open in the main workspace), and three broad scenarios (Excalidraw in a work pane in the main Obsidian window, Excalidraw in a hover editor, and Excalidraw in an Obsidian popout window). All should work correctly now.
|
||||
`,
|
||||
"1.7.7": `
|
||||
# New
|
||||
- Optimized for Obsidian 0.15.4
|
||||
- On a desktop, you can now use the META key when clicking on a link and it will open the link in a new popout Window.
|
||||
- ([#685](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/685)) Markdown embeds will now display correctly in Excalidraw even if they include photos and recursive markdown embeds. Unfortunately due to the limitations of Safari the inversion of colors on iPads in dark mode will not work well.
|
||||
See an 18 second long demo video [here](https://user-images.githubusercontent.com/14358394/177213263-2a7ef1ca-0614-4190-8955-e830ca6b424b.mp4).
|
||||
|
||||
|
||||
# Fixed
|
||||
- ([#683](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/683)) Copy/Paste Markdown embeds to create another instance of the embed, thus you can reference different sections of the document in your drawing (something I broke in 1.7.6)
|
||||
- ([#684](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/684)) Transclusions incorrectly did not pick up subsections of a section. To understand this change, imagine for example the following document:
|
||||
${String.fromCharCode(96, 96, 96)}markdown
|
||||
# A
|
||||
abc
|
||||
# B
|
||||
xyz
|
||||
## b1
|
||||
123
|
||||
## b2
|
||||
456
|
||||
# C
|
||||
${String.fromCharCode(96, 96, 96)}
|
||||
When you transclude ${String.fromCharCode(96)}![[document#B]]${String.fromCharCode(96)} you expect the following result
|
||||
${String.fromCharCode(96, 96, 96)}markdown
|
||||
B
|
||||
xyz
|
||||
|
||||
b1
|
||||
123
|
||||
|
||||
b2
|
||||
456
|
||||
${String.fromCharCode(96, 96, 96)}
|
||||
Until this fix you only got
|
||||
${String.fromCharCode(96, 96, 96)}markdown
|
||||
B
|
||||
xyz
|
||||
${String.fromCharCode(96, 96, 96)}`,
|
||||
"1.7.6": `
|
||||
This release is the same as 1.7.5 except for two minor fixes
|
||||
- a fix for ExcaliBrain, becuase 1.7.5 broke ExcaliBrain.
|
||||
- I left out the release note from 1.7.5.
|
||||
|
||||
# New
|
||||
- Deployed sidebar for libraries panel from excalidraw.com ([#5274](https://github.com/excalidraw/excalidraw/pull/5274)). You can dock the library to the right side depending on the screen real estate available (i.e. does not work on mobiles).
|
||||
|
||||
# Fixed
|
||||
- When copying 2 identical images from one drawing to another, the second image got corrupted in the process ([#672]https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/672)).
|
||||
- When making a copy of an equation in a drawing and then without first closing/opening the file, immediately copying the new equation to another drawing, the equation did not get displayed until the file was closed and reopened.
|
||||
- Copying a markdown embed from one drawing to another, in the destination the markdown embed appeared without the section/block reference and without the width & height (i.e. these settings had to be done again)
|
||||
- Improved the parsing of section references in embeds. When you had ${String.fromCharCode(96)}&${String.fromCharCode(96)} in the section name in a markdown file, when embedding that markdown document into Excalidraw, the section reference did not work as expected ([#681 ](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/681)).
|
||||
- Improved the logic for autosave to better detect changes to the document, and to reduce too frequent export of ${String.fromCharCode(96)}.png${String.fromCharCode(96)} and/or ${String.fromCharCode(96)}.svg${String.fromCharCode(96)} files, when auto export is enabled in plugin settings.
|
||||
`,
|
||||
"1.7.5": `
|
||||
# New
|
||||
- Deployed sidebar for libraries panel from excalidraw.com ([#5274](https://github.com/excalidraw/excalidraw/pull/5274)). You can dock the library to the right side depending on the screen real estate available (i.e. does not work on mobiles).
|
||||
|
||||
# Fixed
|
||||
- When copying 2 identical images from one drawing to another, the second image got corrupted in the process ([#672]https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/672)).
|
||||
- When making a copy of an equation in a drawing and then without first closing/opening the file, immediately copying the new equation to another drawing, the equation did not get displayed until the file was closed and reopened.
|
||||
- Copying a markdown embed from one drawing to another, in the destination the markdown embed appeared without the section/block reference and without the width & height (i.e. these settings had to be done again)
|
||||
- Improved the parsing of section references in embeds. When you had ${String.fromCharCode(96)}&${String.fromCharCode(96)} in the section name in a markdown file, when embedding that markdown document into Excalidraw, the section reference did not work as expected ([#681 ](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/681)).
|
||||
- Improved the logic for autosave to better detect changes to the document, and to reduce too frequent export of ${String.fromCharCode(96)}.png${String.fromCharCode(96)} and/or ${String.fromCharCode(96)}.svg${String.fromCharCode(96)} files, when auto export is enabled in plugin settings.
|
||||
`,
|
||||
"1.7.4": `
|
||||
- Obsidian 0.15.3 support dragging and dropping work panes between Obsidian windows.
|
||||
- Addressed Obsidian changes affecting the more-options menu.
|
||||
- Addressed incompatibility with Obsidian Mobile 1.2.2.
|
||||
`,
|
||||
"1.7.3": `
|
||||
Obsidian 0.15.3 support for dragging and dropping work panes between Obsidian windows.
|
||||
`,
|
||||
"1.7.2": `
|
||||
Due to some of the changes to the code, I highly recommend restarting Obsidian after installing this update to Excalidraw.
|
||||
|
||||
# Fixed
|
||||
- Stability improvements
|
||||
- Opening links in new panes and creating new drawings from the file explorer works properly again
|
||||
|
||||
# New feature
|
||||
- Two new command palette actions:
|
||||
- Create a new drawing - IN A POPOUT WINDOW
|
||||
- Create a new drawing - IN A POPOUT WINDOW - and embed into active document
|
||||

|
||||
- Added setting to prefer opening the link in the popout window or in the main workspace.
|
||||

|
||||
`,
|
||||
"1.7.1": `
|
||||
Support for Obsidian 0.15.0 popout windows. While there are no new features (apart from the popout window support) under the hood there were some major changes required to make this happen.
|
||||
`,
|
||||
"1.7.0": `
|
||||
This is the first test version of Excalidraw Obsidian supporting Obsidian 0.15.0 popout windows. The current technical solution is not really sustainable, it's more of a working concept. I don't expect any real big issues with this version - on the contrary, this works much better with Obsidian 0.15.0 popout windows, but some of the features aren't working as expected in the Obsidian popouts yet. Also as a consequence of Obsidian 0.15.0 compatibility, multiple hover previews are no longer supported.
|
||||
`,
|
||||
"1.6.34": `
|
||||
With 0.15.1 Obsidian is implementing some exciting, but significant changes to how windows are managed. I need to make some heavy/invasive changes to Excalidraw to adapt. The next version of the Excalidraw Plugin will require Obsidian 0.15.1 or newer. If you are not signed up for Obsidian Insider Builds, you will need to wait few weeks until the new Obsidian version will be made public.
|
||||
|
||||
# Fixed
|
||||
- Error saving when the attachments folder exists but with a different letter case (i.e. ATTACHMENTS instead of attachments) [658](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/658). I added more error tolerance. As a general rule, however, I recommend treating file paths as case-sensitive as some platforms like iOS or LINUX have case-sensitive filenames, and synchronizing your Vault to these platforms will cause you headaches in the future.
|
||||
- Text detached from the container if you immediately clicked the text-align buttons on the properties pane while still editing the text in the container for the very first time. [#657](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/657).
|
||||
- Can't add text to the second container if the first container has text and the second container is centered around the first one. [#5300](https://github.com/excalidraw/excalidraw/issues/5300)
|
||||
`,
|
||||
"1.6.33": `
|
||||
# Fixed
|
||||
- Under some special circumstances when you embedded a drawing (guest) into another drawing (host), the host did not update when you modified the guest, until you closed Excalidraw completely and reopened the host. [#637](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/637)
|
||||
|
||||
# New
|
||||
- ExcalidrawAutomate ${String.fromCharCode(96)}addLabelToLine${String.fromCharCode(96)} adds a text label to a line or arrow. Currently this function only works with simple straight 2-point (start & end) lines.
|
||||
${String.fromCharCode(96, 96, 96)}typescript
|
||||
addLabelToLine(lineId: string, label: string): string
|
||||
${String.fromCharCode(96, 96, 96)}
|
||||
- ExcalidrawAutomate ${String.fromCharCode(96)}ConnectObjects${String.fromCharCode(96)} now returns the ID of the arrow that was created.`,
|
||||
"1.6.32": `
|
||||
## Fixed
|
||||
- Filenames of embedded images and markdown documents did not get updated if the drawing was open in a work-pane while you changed the filename of the embedded file (image or markdown document) [632](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/632).
|
||||
- When you created a new text element and immediately dragged it, sometimes autosave interrupted the drag action and Excalidraw dropped the element you were dragging [630](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/630)
|
||||
- In some edge cases when you had the drawing open on your desktop and you also opened the same image on your tablet, Sync seemed to work in the background but the changes did not appear on the desktop until you closed and opened the drawing again. [629](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/629)
|
||||
- LaTeX support: Excalidraw must download a javascript library from one of the hosting sites for MathJax tex2svg. It seems that some people do not have access to the URL recommended in the first place by [MathJax](https://docs.mathjax.org/en/latest/web/start.html). If LaTeX formulas do not render correctly in Excalidraw, try changing the source server under Compatibility Settings in Excalidraw Plugin Settings. [628](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/628)`,
|
||||
"1.6.31": `
|
||||
Minor update:
|
||||
|
||||
## Fixes
|
||||
- Color picker hotkeys were not working. They are working again [627](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/627)
|
||||
- I updated MathJax (LaTeX) to the newest (3.2.1) release.`,
|
||||
"1.6.30": `
|
||||
## Fixed
|
||||
- The load stencil library button stopped working after 1.6.29 due to an error in the core Excalidraw package. It is now fixed. [#625](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/625).
|
||||
- On iPad (probably other Obsidian mobile devices as well) after opening the command palette the positioning of the pointer was off. From now on, the pointer is automatically re-calibrated every 5 seconds.
|
||||
- I improved shared-vault collaboration sync. If the open file has not been saved for the last 5 minutes (i.e. you are not working on the drawing actively), and a newer remote version of the file is received via sync, then the remote file will simply overwrite the local file (i.e. the behavior of Excalidraw Obsidian prior to implementing Shared (Multiplayer) Vault Synchronization support in 1.6.29). This solution will support active collaboration when parties participating are actively editing the drawing, but also caters to the scenario when you open a drawing on one device (e.g. your desktop) and once you are finished editing you do not close the drawing, but simply put your PC to sleep... then later you edit the same drawing on your tablet. When you turn your desktop PC on the next time, the changes you've made on your tablet will be synchronized by Obsidian sync. In this case the changes from your tablet should be honored. If you have not edited the open drawing for more then 5 minutes (like in this scenario) there is no value in running the file comparison between the local version and the received one. This approach reduces the probability of running into sync conflicts.`,
|
||||
"1.6.29": `
|
||||
## New
|
||||
- I implemented sync support inspired by the new [Obsidian Multiplayer Sync](https://youtu.be/ZyCPhbd51eo) feature (available in insider build v0.14.10).
|
||||
- To manage expectations, this is not real-time collaboration like on Excalidraw.com. Synchronization is delayed by the frequency of the autosave timer (every 10 secs) and the speed of Obsidian sync. Also if a file has conflicting versions, Obsidian sync may delay the delivery of the changed file.
|
||||
- Even if you are not using multiplayer Obsidian Vaults, you may benefit from the improved synchronization, for example when using the freedraw tool on your tablet or phone, and in parallel editing the same drawing (e.g. typing text) on your desktop. I frequently do this in a mind-mapping scenario.
|
||||
- If the same Excalidraw sketch is open on multiple devices then Excalidraw will try to merge changes into the open drawing, thus parallel modifications on different devices are possible. If the same element is edited by multiple parties at the same time, then the foreign (received) version will be honored and the local changes lost.
|
||||
|
||||
## Fixed:
|
||||
- Default embed width setting stopped working. [#622](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/622)
|
||||
- The link tooltip gets stuck on screen after Excalidraw closes [#621](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/621)
|
||||
- Layout error when using the Workspaces core plugin. [#28](https://github.com/zsviczian/excalibrain/issues/28)`,
|
||||
"1.6.28": `
|
||||
## New
|
||||
- When dropping a link from a DataView query into Excalidraw the link will honor your "New link format" preferences in Obsidian. It will add the "shortest path when possible", if that is your setting. If the link includes a block or section reference, then the link will automatically include an alias, such that only the filename is displayed (shortest path possible allowing) [#610](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/610)
|
||||
- If Excalidraw is in a Hover Editor and you open a link in another pane by CTRL+SHIFT+Click then the new page will open in the main workspace, and not in a split pane in the hover editor.
|
||||
|
||||
## Fixed
|
||||
- New text elements get de-selected after auto-save [#609](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/609)
|
||||
- Update opacity of bound text when the opacity of the container is updated [#5142](https://github.com/excalidraw/excalidraw/pull/5142)
|
||||
- ExcalidrawAutomate: openFileInNewOrAdjacentLeaf() function. This also caused an error when clicking a link in Excalidraw in a hover window, when there were no leaves in the main workspace view.`,
|
||||
"1.6.27": `
|
||||
## New Features
|
||||
- While these new features are benefitial for all Excalidraw Automation projects, the current changes are mainly in support of the [ExcaliBrain](https://youtu.be/O2s-h5VKCas) integration. See detailed [Release Notes](https://github.com/zsviczian/obsidian-excalidraw-plugin/releases/tag/1.6.27) on GitHub.
|
||||
|
||||
@@ -33,7 +33,7 @@ export class OpenFileDialog extends FuzzySuggestModal<TFile> {
|
||||
if (this.containerEl.innerText.includes(EMPTY_MESSAGE)) {
|
||||
this.plugin.createAndOpenDrawing(
|
||||
`${this.plugin.settings.folder}/${this.inputEl.value}.excalidraw.md`,
|
||||
this.onNewPane,
|
||||
this.onNewPane?"new-pane":"active-pane",
|
||||
);
|
||||
this.close();
|
||||
}
|
||||
@@ -55,7 +55,7 @@ export class OpenFileDialog extends FuzzySuggestModal<TFile> {
|
||||
onChooseItem(item: TFile): void {
|
||||
switch (this.action) {
|
||||
case openDialogAction.openFile:
|
||||
this.plugin.openDrawing(item, this.onNewPane);
|
||||
this.plugin.openDrawing(item, this.onNewPane?"new-pane":"active-pane",true);
|
||||
break;
|
||||
case openDialogAction.insertLinkToDrawing:
|
||||
this.plugin.embedDrawing(item);
|
||||
|
||||
@@ -13,6 +13,7 @@ import ExcalidrawView from "../ExcalidrawView";
|
||||
import ExcalidrawPlugin from "../main";
|
||||
import { sleep } from "../utils/Utils";
|
||||
import { getNewOrAdjacentLeaf } from "../utils/ObsidianUtils";
|
||||
import { checkAndCreateFolder, splitFolderAndFilename } from "src/utils/FileUtils";
|
||||
|
||||
export class Prompt extends Modal {
|
||||
private promptEl: HTMLInputElement;
|
||||
@@ -219,7 +220,7 @@ export class GenericInputPrompt extends Modal {
|
||||
}
|
||||
|
||||
private removeInputListener() {
|
||||
this.inputComponent.inputEl.removeEventListener(
|
||||
this.inputComponent?.inputEl?.removeEventListener(
|
||||
"keydown",
|
||||
this.submitEnterCallback,
|
||||
);
|
||||
@@ -370,6 +371,7 @@ export class NewFileActions extends Modal {
|
||||
private plugin: ExcalidrawPlugin,
|
||||
private path: string,
|
||||
private newPane: boolean,
|
||||
private newWindow: boolean,
|
||||
private view: ExcalidrawView,
|
||||
) {
|
||||
super(plugin.app);
|
||||
@@ -385,11 +387,14 @@ export class NewFileActions extends Modal {
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
const leaf = this.newPane
|
||||
? getNewOrAdjacentLeaf(this.plugin, this.view.leaf)
|
||||
: this.view.leaf;
|
||||
leaf.openFile(file);
|
||||
this.app.workspace.setActiveLeaf(leaf, true, true);
|
||||
const leaf = this.newWindow
|
||||
//@ts-ignore
|
||||
? app.workspace.openPopoutLeaf()
|
||||
: this.newPane
|
||||
? getNewOrAdjacentLeaf(this.plugin, this.view.leaf)
|
||||
: this.view.leaf;
|
||||
leaf.openFile(file, {active:true});
|
||||
//this.app.workspace.setActiveLeaf(leaf, true, true);
|
||||
}
|
||||
|
||||
createForm(): void {
|
||||
@@ -430,6 +435,8 @@ export class NewFileActions extends Modal {
|
||||
if (!this.path.match(/\.md$/)) {
|
||||
this.path = `${this.path}.md`;
|
||||
}
|
||||
const folderpath = splitFolderAndFilename(this.path).folderpath;
|
||||
checkAndCreateFolder(folderpath);
|
||||
const f = await this.app.vault.create(this.path, data);
|
||||
return f;
|
||||
};
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { App, MarkdownRenderer, Modal } from "obsidian";
|
||||
import { isVersionNewerThanOther } from "src/utils/Utils";
|
||||
import ExcalidrawPlugin from "../main";
|
||||
import { FIRST_RUN, RELEASE_NOTES } from "./Messages";
|
||||
|
||||
declare const PLUGIN_VERSION:string;
|
||||
|
||||
export class ReleaseNotes extends Modal {
|
||||
private plugin: ExcalidrawPlugin;
|
||||
private version: string;
|
||||
@@ -9,13 +12,12 @@ export class ReleaseNotes extends Modal {
|
||||
constructor(app: App, plugin: ExcalidrawPlugin, version: string) {
|
||||
super(app);
|
||||
this.plugin = plugin;
|
||||
//@ts-ignore
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
onOpen(): void {
|
||||
this.contentEl.classList.add("excalidraw-release");
|
||||
this.containerEl.classList.add(".excalidraw-release");
|
||||
//this.contentEl.classList.add("excalidraw-release");
|
||||
this.containerEl.classList.add("excalidraw-release");
|
||||
this.titleEl.setText(`Welcome to Excalidraw ${this.version ?? ""}`);
|
||||
this.createForm();
|
||||
}
|
||||
@@ -23,20 +25,18 @@ export class ReleaseNotes extends Modal {
|
||||
async onClose() {
|
||||
this.contentEl.empty();
|
||||
await this.plugin.loadSettings();
|
||||
this.plugin.settings.previousRelease =
|
||||
//@ts-ignore
|
||||
this.app.plugins.manifests["obsidian-excalidraw-plugin"].version;
|
||||
this.plugin.settings.previousRelease = PLUGIN_VERSION
|
||||
await this.plugin.saveSettings();
|
||||
}
|
||||
|
||||
async createForm() {
|
||||
let prevRelease = this.plugin.settings.previousRelease;
|
||||
prevRelease = this.version === prevRelease ? "0" : prevRelease;
|
||||
prevRelease = this.version === prevRelease ? "0.0.0" : prevRelease;
|
||||
const message = this.version
|
||||
? Object.keys(RELEASE_NOTES)
|
||||
.filter((key) => key > prevRelease)
|
||||
.map((key: string) => `# ${key}\n${RELEASE_NOTES[key]}`)
|
||||
.slice(0, 6)
|
||||
.filter((key) => key === "Intro" || isVersionNewerThanOther(key,prevRelease))
|
||||
.map((key: string) => `${key==="Intro" ? "" : `# ${key}\n`}${RELEASE_NOTES[key]}`)
|
||||
.slice(0, 10)
|
||||
.join("\n\n---\n")
|
||||
: FIRST_RUN;
|
||||
await MarkdownRenderer.renderMarkdown(
|
||||
|
||||
@@ -224,8 +224,8 @@ export const EXCALIDRAW_AUTOMATE_INFO: SuggesterInfo[] = [
|
||||
},
|
||||
{
|
||||
field: "addImage",
|
||||
code: "addImage(topX: number, topY: number, imageFile: TFile): Promise<string>;",
|
||||
desc: null,
|
||||
code: "addImage(topX: number, topY: number, imageFile: TFile, scale: boolean): Promise<string>;",
|
||||
desc: "set scale to false if you want to embed the image at 100% of its original size. Default is true which will insert a scaled image",
|
||||
after: "",
|
||||
},
|
||||
{
|
||||
@@ -236,10 +236,16 @@ export const EXCALIDRAW_AUTOMATE_INFO: SuggesterInfo[] = [
|
||||
},
|
||||
{
|
||||
field: "connectObjects",
|
||||
code: "connectObjects(objectA: string, connectionA: ConnectionPoint, objectB: string, connectionB: ConnectionPoint, formatting?: {numberOfPoints?: number; startArrowHead?: string; endArrowHead?: string; padding?: number;},): void;",
|
||||
code: "connectObjects(objectA: string, connectionA: ConnectionPoint, objectB: string, connectionB: ConnectionPoint, formatting?: {numberOfPoints?: number; startArrowHead?: string; endArrowHead?: string; padding?: number;},): string;",
|
||||
desc: 'type ConnectionPoint = "top" | "bottom" | "left" | "right" | null\nWhen null is passed as ConnectionPoint then Excalidraw will automatically decide\nnumberOfPoints is the number of points on the line. Default is 0 i.e. line will only have a start and end point.\nArrowHead: "triangle"|"dot"|"arrow"|"bar"|null',
|
||||
after: "",
|
||||
},
|
||||
{
|
||||
field: "addLabelToLine",
|
||||
code: "addLabelToLine(lineId: string, label: string): string;",
|
||||
desc: 'Adds a text label to a line or arrow. Currently only works with a simple straight 2-point (start & end) line',
|
||||
after: "",
|
||||
},
|
||||
{
|
||||
field: "clear",
|
||||
code: "clear(): void;",
|
||||
@@ -379,11 +385,17 @@ export const EXCALIDRAW_AUTOMATE_INFO: SuggesterInfo[] = [
|
||||
after: "",
|
||||
},
|
||||
{
|
||||
field: "getLargestElement",
|
||||
code: "getLargestElement(elements: ExcalidrawElement[]): ExcalidrawElement;",
|
||||
desc: "Gets the largest element from a group. useful when a text element is grouped with a box, and you want to connect an arrow to the box",
|
||||
field: "getCommonGroupForElements",
|
||||
code: "getCommonGroupForElements(elements: ExcalidrawElement[]): string;",
|
||||
desc: "Gets the groupId for the group that contains all the elements, or null if such a group does not exist",
|
||||
after: "",
|
||||
},
|
||||
{
|
||||
field: "getElementsInTheSameGroupWithElement",
|
||||
code: "getElementsInTheSameGroupWithElement(element: ExcalidrawElement, elements: ExcalidrawElement[]): ExcalidrawElement[];",
|
||||
desc: "Gets all the elements from elements[] that share one or more groupIds with element.",
|
||||
after: ""
|
||||
},
|
||||
{
|
||||
field: "activeScript",
|
||||
code: "activeScript: string;",
|
||||
@@ -474,6 +486,30 @@ export const EXCALIDRAW_AUTOMATE_INFO: SuggesterInfo[] = [
|
||||
desc: "Converts a CSS color name to its HEX color equivalent. 'White' to #FFFFFF",
|
||||
after: "",
|
||||
},
|
||||
{
|
||||
field: "obsidian",
|
||||
code: "obsidian",
|
||||
desc: "Access functions and objects available on the <a onclick='window.open(\"https://github.com/obsidianmd/obsidian-api/blob/master/obsidian.d.ts\")'>Obsidian Module</a>",
|
||||
after: "",
|
||||
},
|
||||
{
|
||||
field: "setViewModeEnabled",
|
||||
code: "setViewModeEnabled(enabled: boolean): void;",
|
||||
desc: "Sets Excalidraw in the targetView to view-mode",
|
||||
after: "",
|
||||
},
|
||||
{
|
||||
field: "viewUpdateScene",
|
||||
code: "viewUpdateScene(scene:{elements?:ExcalidrawElement[],appState?: AppState,files?: BinaryFileData,commitToHistory?: boolean,},restore:boolean=false):void",
|
||||
desc: "Calls the ExcalidrawAPI updateScene function for the targetView. When restore=true, excalidraw will try to correct errors in the scene such as setting default values to missing element properties.",
|
||||
after: "",
|
||||
},
|
||||
{
|
||||
field: "viewZoomToElements",
|
||||
code: "viewZoomToElements(selectElements: boolean,elements: ExcalidrawElement[]):void",
|
||||
desc: "Zoom tarteView to fit elements provided as input. elements === [] will zoom to fit the entire scene. SelectElements toggles whether the elements should be in a selected state at the end of the operation.",
|
||||
after: "",
|
||||
},
|
||||
];
|
||||
|
||||
export const EXCALIDRAW_SCRIPTENGINE_INFO: SuggesterInfo[] = [
|
||||
@@ -575,9 +611,9 @@ export const FRONTMATTER_KEYS_INFO: SuggesterInfo[] = [
|
||||
after: ": true",
|
||||
},
|
||||
{
|
||||
field: "export-svgpadding",
|
||||
field: "export-padding",
|
||||
code: null,
|
||||
desc: "If this key is present it will override the default excalidraw embed and export setting. This only affects export to SVG. Specify the export padding for the image.",
|
||||
desc: "If this key is present it will override the default excalidraw embed and export setting. This only affects both SVG and PNG export. Specify the export padding for the image.",
|
||||
after: ": 5",
|
||||
},
|
||||
{
|
||||
@@ -586,4 +622,11 @@ export const FRONTMATTER_KEYS_INFO: SuggesterInfo[] = [
|
||||
desc: "If this key is present it will override the default excalidraw embed and export setting. This only affects export to PNG. Specify the export scale for the image. The typical range is between 0.5 and 5, but you can experiment with other values as well.",
|
||||
after: ": 1",
|
||||
},
|
||||
{
|
||||
field: "autoexport",
|
||||
code: null,
|
||||
desc: "Override autoexport settings for this file. Valid values are\nnone\nboth\npng\nsvg",
|
||||
after: ": png",
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
@@ -28,29 +28,43 @@ export default {
|
||||
"Open an existing drawing - IN THE CURRENT ACTIVE PANE",
|
||||
TRANSCLUDE: "Transclude (embed) a drawing",
|
||||
TRANSCLUDE_MOST_RECENT: "Transclude (embed) the most recently edited drawing",
|
||||
TOGGLE_LEFTHANDED_MODE: "Toggle left-handed mode",
|
||||
NEW_IN_NEW_PANE: "Create a new drawing - IN A NEW PANE",
|
||||
NEW_IN_ACTIVE_PANE: "Create a new drawing - IN THE CURRENT ACTIVE PANE",
|
||||
NEW_IN_POPOUT_WINDOW: "Create a new drawing - IN A POPOUT WINDOW",
|
||||
NEW_IN_NEW_PANE_EMBED:
|
||||
"Create a new drawing - IN A NEW PANE - and embed into active document",
|
||||
NEW_IN_ACTIVE_PANE_EMBED:
|
||||
"Create a new drawing - IN THE CURRENT ACTIVE PANE - and embed into active document",
|
||||
NEW_IN_POPOUT_WINDOW_EMBED: "Create a new drawing - IN A POPOUT WINDOW - and embed into active document",
|
||||
EXPORT_SVG: "Save as SVG next to the current file",
|
||||
EXPORT_PNG: "Save as PNG next to the current file",
|
||||
TOGGLE_LOCK: "Toggle Text Element edit RAW/PREVIEW",
|
||||
DELETE_FILE: "Delete selected Image or Markdown file from Obsidian Vault",
|
||||
INSERT_LINK_TO_ELEMENT:
|
||||
"Copy markdown link for selected element to clipboard",
|
||||
"Copy markdown link for selected element to clipboard. CTRL/CMD+Click to copy group link. SHIFT+click to copy an area link.",
|
||||
INSERT_LINK_TO_ELEMENT_GROUP:
|
||||
"Copy 'group=' markdown link for selected element to clipboard.",
|
||||
INSERT_LINK_TO_ELEMENT_AREA:
|
||||
"Copy 'area=' markdown link for selected element to clipboard.",
|
||||
INSERT_LINK_TO_ELEMENT_NORMAL:
|
||||
"Copy markdown link for selected element to clipboard.",
|
||||
INSERT_LINK_TO_ELEMENT_ERROR: "Select a single element in the scene",
|
||||
INSERT_LINK_TO_ELEMENT_READY: "Link is READY and available on the clipboard",
|
||||
INSERT_LINK: "Insert link to file",
|
||||
INSERT_IMAGE: "Insert image from vault",
|
||||
INSERT_IMAGE: "Insert image or Excalidraw drawing from your vault",
|
||||
IMPORT_SVG: "Import an SVG file as Excalidraw strokes (limited SVG support, TEXT currently not supported)",
|
||||
INSERT_MD: "Insert markdown file from vault",
|
||||
INSERT_LATEX:
|
||||
"Insert LaTeX formula (e.g. \\binom{n}{k} = \\frac{n!}{k!(n-k)!})",
|
||||
ENTER_LATEX: "Enter a valid LaTeX expression",
|
||||
READ_RELEASE_NOTES: "Read latest release notes",
|
||||
RUN_OCR: "OCR: Grab text from freedraw scribble and pictures to clipboard",
|
||||
TRAY_MODE: "Toggle property-panel tray-mode",
|
||||
SEARCH: "Search for text in drawing",
|
||||
RESET_IMG_TO_100: "Set selected image element size to 100% of original",
|
||||
TEMPORARY_DISABLE_AUTOSAVE: "Disable autosave until next time Obsidian starts (only set this if you know what you are doing)",
|
||||
TEMPORARY_ENABLE_AUTOSAVE: "Enable autosave",
|
||||
|
||||
//ExcalidrawView.ts
|
||||
INSTALL_SCRIPT_BUTTON: "Install or update Excalidraw Scripts",
|
||||
@@ -68,7 +82,7 @@ export default {
|
||||
FILE_DOES_NOT_EXIST:
|
||||
"File does not exist. Hold down ALT (or ALT+SHIFT) and CLICK link button to create a new file.",
|
||||
FORCE_SAVE:
|
||||
"Force-save to update transclusions in adjacent panes.\n(Check autosave settings in plugin settings.)",
|
||||
"Save (will also update transclusions)",
|
||||
RAW: "Change to PREVIEW mode (only effects text-elements with links or transclusions)",
|
||||
PARSED:
|
||||
"Change to RAW mode (only effects text-elements with links or transclusions)",
|
||||
@@ -82,6 +96,11 @@ export default {
|
||||
RELEASE_NOTES_DESC:
|
||||
"<b>Toggle ON:</b> Display release notes each time you update Excalidraw to a newer version.<br>" +
|
||||
"<b>Toggle OFF:</b> Silent mode. You can still read release notes on <a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/releases'>GitHub</a>.",
|
||||
NEWVERSION_NOTIFICATION_NAME: "Plugin update notification",
|
||||
NEWVERSION_NOTIFICATION_DESC:
|
||||
"<b>Toggle ON:</b> Show a notification when a new version of the plugin is available.<br>" +
|
||||
"<b>Toggle OFF:</b> Silent mode. You need to check for plugin updates in Community Plugins.",
|
||||
|
||||
FOLDER_NAME: "Excalidraw folder",
|
||||
FOLDER_DESC:
|
||||
"Default location for new drawings. If empty, drawings will be created in the Vault root.",
|
||||
@@ -89,21 +108,22 @@ export default {
|
||||
"Use Excalidraw folder when embedding a drawing into the active document",
|
||||
FOLDER_EMBED_DESC:
|
||||
"Define which folder to place the newly inserted drawing into " +
|
||||
"when using the command palette action: 'Create a new drawing and embed into active document'. " +
|
||||
"ON: Use Excalidraw folder; OFF: use attachments folder defined in Obsidian settings",
|
||||
"when using the command palette action: 'Create a new drawing and embed into active document'.<br>" +
|
||||
"<b>Toggle ON:</b> Use Excalidraw folder<br><b>Toggle OFF:</b> Use the attachments folder defined in Obsidian settings.",
|
||||
TEMPLATE_NAME: "Excalidraw template file",
|
||||
TEMPLATE_DESC:
|
||||
"Full filepath to the Excalidraw template. " +
|
||||
"E.g.: If your template is in the default Excalidraw folder and it's name is " +
|
||||
"E.g.: If your template is in the default Excalidraw folder and its name is " +
|
||||
"Template.md, the setting would be: Excalidraw/Template.md (or just Excalidraw/Template - you may omit the .md file extension). " +
|
||||
"If you are using Excalidraw in compatibility mode, then your template must be a legacy Excalidraw file as well " +
|
||||
"such as Excalidraw/Template.excalidraw.",
|
||||
SCRIPT_FOLDER_NAME: "Excalidraw Automate script folder",
|
||||
SCRIPT_FOLDER_NAME: "Excalidraw Automate script folder (CASE SeNSitiVE!)",
|
||||
SCRIPT_FOLDER_DESC:
|
||||
"The files you place in this folder will be treated as Excalidraw Automate scripts. " +
|
||||
"You can access your scripts from Excalidraw via the Obsidian Command Palette. Assign " +
|
||||
"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",
|
||||
COMPRESS_NAME: "Compress Excalidraw JSON in Markdown",
|
||||
COMPRESS_DESC:
|
||||
"By enabling this feature Excalidraw will store the drawing JSON in a Base64 compressed " +
|
||||
@@ -114,16 +134,19 @@ export default {
|
||||
"be saved without compression, so that you can read and edit the JSON string. The drawing will be compressed again " +
|
||||
"once you switch back to Excalidraw view. " +
|
||||
"The setting only has effect 'point forward', meaning, existing drawings will not be effected by the setting " +
|
||||
"until you open them and save them. ",
|
||||
AUTOSAVE_NAME: "Enable Autosave",
|
||||
AUTOSAVE_DESC:
|
||||
"Automatically save the active drawing, in case there are changes, every 15, 30 seconds, or 1, 2, 3, 4, or 5 minute. Save normally happens when you close Excalidraw or Obsidian, or move " +
|
||||
"focus to another pane. I created this feature with mobile " +
|
||||
"phones and tablets in mind, where 'swiping out Obsidian to close it' led to some data loss.",
|
||||
AUTOSAVE_INTERVAL_NAME: "Interval for autosave",
|
||||
AUTOSAVE_INTERVAL_DESC:
|
||||
"The time interval between saves. Autosave will skip if there are no changes in the drawing.",
|
||||
FILENAME_HEAD: "Filename",
|
||||
"until you open them and save them.<br><b>Toggle ON:</b> Compress drawing JSON<br><b>Toggle OFF:</b> Leave drawing JSON uncompressed",
|
||||
AUTOSAVE_INTERVAL_DESKTOP_NAME: "Interval for autosave on Desktop",
|
||||
AUTOSAVE_INTERVAL_DESKTOP_DESC:
|
||||
"The time interval between saves. Autosave will skip if there are no changes in the drawing. " +
|
||||
"Excalidraw will also save the file when closing a workspace tab or navigating within Obsidian, but away from the active Excalidraw tab (i.e. clicking on the Obsidian ribbon or checking backlinks, etc.). " +
|
||||
"Excalidraw will not be able to save your work when terminating Obsidian directly either by killing the Obsidian process, or clicking to close Obsidian altogether.",
|
||||
AUTOSAVE_INTERVAL_MOBILE_NAME: "Interval for autosave on Mobile",
|
||||
AUTOSAVE_INTERVAL_MOBILE_DESC:
|
||||
"I recommend a more frequent interval for Mobiles. " +
|
||||
"Excalidraw will also save the file when closing a workspace tab or navigating within Obsidian, but away from the active Excalidraw tab (i.e. tapping on the Obsidian ribbon or checking backlinks, etc.). " +
|
||||
"Excalidraw will not be able to save your work when terminating Obsidian directly (i.e. swiping it away). Also note, that when you switch apps on a Mobile device, sometimes Android and iOS closes " +
|
||||
"Obsidian in the background to save system resources. In such a case Excalidraw will not be able to save the latest changes.",
|
||||
FILENAME_HEAD: "Filename",
|
||||
FILENAME_DESC:
|
||||
"<p>Click this link for the <a href='https://momentjs.com/docs/#/displaying/format/'>" +
|
||||
"date and time format reference</a>.</p>",
|
||||
@@ -135,47 +158,50 @@ export default {
|
||||
"Filename prefix when embedding a new drawing into a markdown note",
|
||||
FILENAME_PREFIX_EMBED_DESC:
|
||||
"Should the filename of the newly inserted drawing start with the name of the active markdown note " +
|
||||
"when using the command palette action: <code>Create a new drawing and embed into active document</code>? " +
|
||||
"ON: Yes, OFF: Not",
|
||||
"when using the command palette action: <code>Create a new drawing and embed into active document</code>?<br>" +
|
||||
"<b>Toggle ON:</b> Yes, the filename of a new drawing should start with filename of the active document<br><b>Toggle OFF:</b> No, filename of a new drawing should not include the filename of the active document",
|
||||
FILENAME_POSTFIX_NAME:
|
||||
"Custom text after markdown Note's name when embedding",
|
||||
FILENAME_POSTFIX_DESC:
|
||||
"Effects filename only when embedding into a markdown document. This is text will be inserted after the note's name, but before the date.",
|
||||
"Effects filename only when embedding into a markdown document. This text will be inserted after the note's name, but before the date.",
|
||||
FILENAME_DATE_NAME: "Filename Date",
|
||||
FILENAME_DATE_DESC:
|
||||
"The last part of the filename. Leave empty if you do not want a date.",
|
||||
FILENAME_EXCALIDRAW_EXTENSION_NAME: ".excalidraw.md or .md",
|
||||
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. Toggle ON = filename ends with .excalidraw.md, Toggle OFF = filename ends with .md",
|
||||
/*SVG_IN_MD_NAME: "SVG Snapshot to markdown file",
|
||||
SVG_IN_MD_DESC: "If the switch is 'on' Excalidraw will include an SVG snapshot in the markdown file. "+
|
||||
"When SVG snapshots are saved to the Excalidraw.md file, drawings that include large png, jpg, gif images may take extreme long time to open in markdown view. " +
|
||||
"On the other hand, SVG snapshots provide some level of platform independence and longevity to your drawings. Even if Excalidraw will no longer exist, the snapshot " +
|
||||
"can be opened with an app that reads SVGs. In addition hover previews will be less resource intensive if SVG snapshots are enabled.",*/
|
||||
"i.e. you are not using Excalidraw markdown files.<br><b>Toggle ON:</b> filename ends with .excalidraw.md<br><b>Toggle OFF:</b> filename ends with .md",
|
||||
DISPLAY_HEAD: "Display",
|
||||
LEFTHANDED_MODE_NAME: "Left-handed mode",
|
||||
LEFTHANDED_MODE_DESC:
|
||||
"Currently only has effect in tray-mode. If turned on, the tray will be on the right side.",
|
||||
"Currently only has effect in tray-mode. If turned on, the tray will be on the right side." +
|
||||
"<br><b>Toggle ON:</b> Left-handed mode.<br><b>Toggle OFF:</b> Right-handed moded",
|
||||
MATCH_THEME_NAME: "New drawing to match Obsidian theme",
|
||||
MATCH_THEME_DESC:
|
||||
"If theme is dark, new drawing will be created in dark mode. This does not apply when you use a template for new drawings. " +
|
||||
"Also this will not effect when you open an existing drawing. Those will follow the theme of the template/drawing respectively.",
|
||||
"Also this will not effect when you open an existing drawing. Those will follow the theme of the template/drawing respectively." +
|
||||
"<br><b>Toggle ON:</b> Follow Obsidian Theme<br><b>Toggle OFF:</b> Follow theme defined in your template",
|
||||
MATCH_THEME_ALWAYS_NAME: "Existing drawings to match Obsidian theme",
|
||||
MATCH_THEME_ALWAYS_DESC:
|
||||
"If theme is dark, drawings will be opened in dark mode. If your theme is light, they will be opened in light mode. ",
|
||||
"If theme is dark, drawings will be opened in dark mode. If your theme is light, they will be opened in light mode. " +
|
||||
"<br><b>Toggle ON:</b> Match Obsidian theme<br><b>Toggle OFF:</b> Open with the same theme as last saved",
|
||||
MATCH_THEME_TRIGGER_NAME: "Excalidraw to follow when Obsidian Theme changes",
|
||||
MATCH_THEME_TRIGGER_DESC:
|
||||
"If this option is enabled open Excalidraw pane will switch to light/dark mode when Obsidian theme changes. ",
|
||||
"If this option is enabled open Excalidraw pane will switch to light/dark mode when Obsidian theme changes. " +
|
||||
"<br><b>Toggle ON:</b> Follow theme changes<br><b>Toggle OFF:</b> Drawings are not effected by Obsidian theme changes",
|
||||
DEFAULT_OPEN_MODE_NAME: "Default mode when opening Excalidraw",
|
||||
DEFAULT_OPEN_MODE_DESC:
|
||||
"Specifies the mode how Excalidraw opens: Normal, Zen, or View mode. You may also set this behavior on a file level by " +
|
||||
"adding the excalidraw-default-mode frontmatter key with a value of: normal,view, or zen to your document.",
|
||||
"adding the excalidraw-default-mode frontmatter key with a value of: normal, view, or zen to your document.",
|
||||
DEFAULT_PEN_MODE_NAME: "Pen mode",
|
||||
DEFAULT_PEN_MODE_DESC:
|
||||
"Should pen mode be automatically enabled when opening Excalidraw?",
|
||||
ZOOM_TO_FIT_NAME: "Zoom to fit on view resize",
|
||||
ZOOM_TO_FIT_DESC: "Zoom to fit drawing when the pane is resized",
|
||||
ZOOM_TO_FIT_DESC: "Zoom to fit drawing when the pane is resized" +
|
||||
"<br><b>Toggle ON:</b> Zoom to fit<br><b>Toggle OFF:</b> Auto zoom disabled",
|
||||
ZOOM_TO_FIT_ONOPEN_NAME: "Zoom to fit on file open",
|
||||
ZOOM_TO_FIT_ONOPEN_DESC: "Zoom to fit drawing when the drawing is first opened" +
|
||||
"<br><b>Toggle ON:</b> Zoom to fit<br><b>Toggle OFF:</b> Auto zoom disabled",
|
||||
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%).",
|
||||
@@ -189,10 +215,14 @@ export default {
|
||||
"If you don't want text accidentally changing in your drawings use <code>[[links|with aliases]]</code>.",
|
||||
ADJACENT_PANE_NAME: "Open in adjacent pane",
|
||||
ADJACENT_PANE_DESC:
|
||||
"When CTRL/CMD+SHIFT clicking a link in Excalidraw by default the plugin will open the link in a new pane. " +
|
||||
"When CTRL/CMD+SHIFT clicking a link in Excalidraw, by default the plugin will open the link in a new pane. " +
|
||||
"Turning this setting on, Excalidraw will first look for an existing adjacent pane, and try to open the link there. " +
|
||||
"Excalidraw will first look too the right, then to the left, then down, then up. If no pane is found, Excalidraw will open " +
|
||||
"a new pane.",
|
||||
"Excalidraw will look for the adjacent pane based on your focus/navigation history, i.e. the workpane that was active before you " +
|
||||
"activated Excalidraw.",
|
||||
MAINWORKSPACE_PANE_NAME: "Open in main workspace",
|
||||
MAINWORKSPACE_PANE_DESC:
|
||||
"When CTRL/CMD+SHIFT clicking a link in Excalidraw, by default the plugin will open the link in a new pane in the current active window. " +
|
||||
"Turning this setting on, Excalidraw will open the link in an existing or new pane in the main workspace. ",
|
||||
LINK_BRACKETS_NAME: "Show <code>[[brackets]]</code> around links",
|
||||
LINK_BRACKETS_DESC: `${
|
||||
"In PREVIEW mode, when parsing Text Elements, place brackets around links. " +
|
||||
@@ -208,6 +238,12 @@ export default {
|
||||
"In PREVIEW mode, if the Text Element contains a URL link, precede the text with these characters. " +
|
||||
"You can override this setting for a specific drawing by adding <code>"
|
||||
}${FRONTMATTER_KEY_CUSTOM_URL_PREFIX}: "🌐 "</code> to the file's frontmatter.`,
|
||||
PARSE_TODO_NAME: "Parse todo",
|
||||
PARSE_TODO_DESC: "Convert '- [ ] ' and '- [x] ' to checkpox and tick in the box.",
|
||||
TODO_NAME: "Open TODO icon",
|
||||
TODO_DESC: "Icon to use for open TODO items",
|
||||
DONE_NAME: "Completed TODO icon",
|
||||
DONE_DESC: "Icon to use for completed TODO items",
|
||||
HOVERPREVIEW_NAME: "Hover preview without CTRL/CMD key",
|
||||
HOVERPREVIEW_DESC:
|
||||
"<b>Toggle On</b>: In Exalidraw <u>view mode</u> the hover preview for [[wiki links]] will be shown immediately, without the need to hold the CTRL/CMD key. " +
|
||||
@@ -228,13 +264,16 @@ export default {
|
||||
"text (i.e. no overflow), or OFF to soft-wrap text (at the nearest whitespace).",
|
||||
TRANSCLUSION_DEFAULT_WRAP_NAME: "Transclusion word wrap default",
|
||||
TRANSCLUSION_DEFAULT_WRAP_DESC:
|
||||
"You can set manually set/override word wrapping length using the `![[page#^block]]{NUMBER}` format. " +
|
||||
"You can manually set/override word wrapping length using the `![[page#^block]]{NUMBER}` format. " +
|
||||
"Normally you will not want to set a default, because if you transclude text inside a sticky note, then Excalidraw will automatically take care of word wrapping. " +
|
||||
"Set this value to `0` if you do not want to set a default. ",
|
||||
PAGE_TRANSCLUSION_CHARCOUNT_NAME: "Page transclusion max char count",
|
||||
PAGE_TRANSCLUSION_CHARCOUNT_DESC:
|
||||
"The maximum number of characters to display from the page when transcluding an entire page with the " +
|
||||
"![[markdown page]] format.",
|
||||
QUOTE_TRANSCLUSION_REMOVE_NAME: "Quote translusion: remove leading '> ' from each line",
|
||||
QUOTE_TRANSCLUSION_REMOVE_DESC: "Remove the leading '> ' from each line of the transclusion. This will improve readability of quotes in text only transclusions<br>" +
|
||||
"<b>Toggle ON:</b> Remove leading '> '<br><b>Toggle OFF:</b> Do not remove leading '> ' (note it will still be removed from the first row due to Obsidian API functionality)",
|
||||
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",
|
||||
@@ -288,7 +327,8 @@ export default {
|
||||
"For a number of reasons, the same approach cannot be used to expedite the loading of drawings with many embedded objects. See demonstration <a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/releases/tag/1.6.23' target='_blank'>here</a>.",
|
||||
EMBED_PREVIEW_SVG_NAME: "Display SVG in markdown preview",
|
||||
EMBED_PREVIEW_SVG_DESC:
|
||||
"The default is to display drawings as SVG images in the markdown preview. Turning this feature off, the markdown preview will display the drawing as an embedded PNG image.",
|
||||
"<b>Toggle ON</b>: Embed drawing as an <a href='https://en.wikipedia.org/wiki/Scalable_Vector_Graphics' target='_blank'>SVG</a> image into the markdown preview.<br>" +
|
||||
"<b>Toggle OFF</b>: Embed drawing as a <a href='' target='_blank'>PNG</a> image. Note, that some of the <a href='https://www.youtube.com/watch?v=yZQoJg2RCKI&t=633s' target='_blank'>image block referencing features</a> do not work with PNG embeds.",
|
||||
PREVIEW_MATCH_OBSIDIAN_NAME: "Excalidraw preview to match Obsidian theme",
|
||||
PREVIEW_MATCH_OBSIDIAN_DESC:
|
||||
"Image preview in documents should match the Obsidian theme. If enabled, when Obsidian is in dark mode, Excalidraw images will render in dark mode. " +
|
||||
@@ -312,9 +352,11 @@ export default {
|
||||
EXPORT_BACKGROUND_NAME: "Export image with background",
|
||||
EXPORT_BACKGROUND_DESC:
|
||||
"If turned off, the exported image will be transparent.",
|
||||
EXPORT_SVG_PADDING_NAME: "SVG Padding",
|
||||
EXPORT_SVG_PADDING_DESC:
|
||||
"The padding (in pixels) around the exported SVG image. If you have curved lines close to the edge of the image they might get cropped during SVG export. You can increase this value to avoid cropping.",
|
||||
EXPORT_PADDING_NAME: "Image Padding",
|
||||
EXPORT_PADDING_DESC:
|
||||
"The padding (in pixels) around the exported SVG or PNG image. " +
|
||||
"If you have curved lines close to the edge of the image they might get cropped during image export. You can increase this value to avoid cropping. " +
|
||||
"You can also override this setting at a file level by adding the <code>excalidraw-export-padding: 5<code> frontmatter key.",
|
||||
EXPORT_THEME_NAME: "Export image with theme",
|
||||
EXPORT_THEME_DESC:
|
||||
"Export the image matching the dark/light theme of your drawing. If turned off, " +
|
||||
@@ -330,9 +372,14 @@ export default {
|
||||
"Automatically create an SVG export of your drawing matching the title of your file. " +
|
||||
"The plugin will save the *.SVG file in the same folder as the drawing. " +
|
||||
"Embed the .svg file into your documents instead of Excalidraw making you embeds platform independent. " +
|
||||
"While the auto-export switch is on, this file will get updated every time you edit the Excalidraw drawing with the matching name.",
|
||||
"While the auto-export switch is on, this file will get updated every time you edit the Excalidraw drawing with the matching name. " +
|
||||
"You can override this setting on a file level by adding the <code>excalidraw-autoexport</code> frontmatter key. Valid values for this key are " +
|
||||
"<code>none</code>,<code>both</code>,<code>svg</code>, and <code>png</code>",
|
||||
EXPORT_PNG_NAME: "Auto-export PNG",
|
||||
EXPORT_PNG_DESC: "Same as the auto-export SVG, but for *.PNG",
|
||||
EXPORT_BOTH_DARK_AND_LIGHT_NAME: "Export both dark- and light-themed image",
|
||||
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",
|
||||
EXPORT_EXCALIDRAW_NAME: "Auto-export Excalidraw",
|
||||
EXPORT_EXCALIDRAW_DESC: "Same as the auto-export SVG, but for *.Excalidraw",
|
||||
@@ -346,6 +393,10 @@ export default {
|
||||
"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.",
|
||||
MATHJAX_NAME: "MathJax (LaTeX) javascript library host",
|
||||
MATHJAX_DESC: "If you are using LaTeX equiations in Excalidraw then the plugin needs to load a javascript library for that. " +
|
||||
"Some users are unable to access certain host servers. If you are experiencing issues try changing the host here. You may need to "+
|
||||
"restart Obsidian after closing settings, for this change to take effect.",
|
||||
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.",
|
||||
@@ -375,12 +426,25 @@ export default {
|
||||
"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",
|
||||
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. " +
|
||||
"Having the text in the frontmatter will enable you to search in Obsidian for the text contents of these. " +
|
||||
"Note, that the process of extracting the text from the image is not done locally, but via an online API. The taskbone service stores the image on its servers only as long as necessary for the text extraction. However, if this is a dealbreaker, then please don't use this feature.",
|
||||
TASKBONE_ENABLE_NAME: "Enable Taskbone",
|
||||
TASKBONE_ENABLE_DESC: "By enabling this service your agree to the Taskbone <a href='https://www.taskbone.com/legal/terms/' target='_blank'>Terms and Conditaions</a> and the " +
|
||||
"<a href='https://www.taskbone.com/legal/privacy/' target='_blank'>Privacy Policy</a>.",
|
||||
TASKBONE_APIKEY_NAME: "Taskbone API Key",
|
||||
TASKBONE_APIKEY_DESC: "Taskbone offers a free service with a reasonable number of scans per month. If you want to use this feature more frequently, or you want to supoprt " +
|
||||
"the developer of Taskbone (as you can imagine, there is no such thing as 'free', providing this awesome OCR service costs some money to the developer of Taskbone), you can " +
|
||||
"purchase a paid API key from <a href='https://www.taskbone.com/' target='_blank'>taskbone.com</a>. In case you have purchased a key, simply overwrite this auto generated free-tier API-key with your paid key.",
|
||||
|
||||
//openDrawings.ts
|
||||
SELECT_FILE: "Select a file then press enter.",
|
||||
SELECT_FILE_WITH_OPTION_TO_SCALE: "Select a file then press ENTER, or ALT+ENTER to insert at 100% scale.",
|
||||
NO_MATCH: "No file matches your query.",
|
||||
SELECT_FILE_TO_LINK: "Select the file you want to insert the link for.",
|
||||
SELECT_DRAWING: "Select the drawing you want to insert",
|
||||
SELECT_DRAWING: "Select the image or drawing you want to insert",
|
||||
TYPE_FILENAME: "Type name of drawing to select.",
|
||||
SELECT_FILE_OR_TYPE_NEW:
|
||||
"Select existing drawing or type name of a new drawing then press Enter.",
|
||||
@@ -402,4 +466,6 @@ export default {
|
||||
GOTO_FULLSCREEN: "Goto fullscreen mode",
|
||||
EXIT_FULLSCREEN: "Exit fullscreen mode",
|
||||
TOGGLE_FULLSCREEN: "Toggle fullscreen mode",
|
||||
OPEN_LINK_CLICK: "Navigate to selected element link",
|
||||
OPEN_LINK_PROPS: "Open markdown-embed properties or open link in new window"
|
||||
};
|
||||
|
||||
@@ -9,10 +9,13 @@ export default {
|
||||
// main.ts
|
||||
INSTALL_SCRIPT: "安装此脚本",
|
||||
UPDATE_SCRIPT: "发现可用更新 - 点击安装",
|
||||
CHECKING_SCRIPT: "检查脚本更新 - 点击重新安装",
|
||||
UNABLETOCHECK_SCRIPT: "检查更新失败 - 点击重新安装",
|
||||
UPTODATE_SCRIPT: "已安装最新脚本 - 点击重新安装",
|
||||
OPEN_AS_EXCALIDRAW: "打开为 Excalidraw 绘图(Excalidraw 模式)",
|
||||
CHECKING_SCRIPT:
|
||||
"检查脚本更新 - 点击重新安装",
|
||||
UNABLETOCHECK_SCRIPT:
|
||||
"检查更新失败 - 点击重新安装",
|
||||
UPTODATE_SCRIPT:
|
||||
"已安装最新脚本 - 点击重新安装",
|
||||
OPEN_AS_EXCALIDRAW: "打开为 Excalidraw 绘图",
|
||||
TOGGLE_MODE: "在 Excalidraw 和 Markdown 模式之间切换",
|
||||
CONVERT_NOTE_TO_EXCALIDRAW: "转换空白笔记为 Excalidraw 绘图",
|
||||
CONVERT_EXCALIDRAW: "转换 *.excalidraw 为 *.md 文件",
|
||||
@@ -20,33 +23,47 @@ export default {
|
||||
CONVERT_FILE_KEEP_EXT: "*.excalidraw => *.excalidraw.md",
|
||||
CONVERT_FILE_REPLACE_EXT: "*.excalidraw => *.md (兼容 Logseq)",
|
||||
DOWNLOAD_LIBRARY: "导出 stencil 库为 *.excalidrawlib 文件",
|
||||
OPEN_EXISTING_NEW_PANE: "打开已有的绘图(在新面板)",
|
||||
OPEN_EXISTING_ACTIVE_PANE: "打开已有的绘图(在当前面板)",
|
||||
TRANSCLUDE: "插入(嵌入)绘图到当前文档",
|
||||
TRANSCLUDE_MOST_RECENT: "插入(嵌入)最近编辑的绘图到当前文档",
|
||||
NEW_IN_NEW_PANE: "新建绘图(在新面板)",
|
||||
NEW_IN_ACTIVE_PANE: "新建绘图(在当前面板)",
|
||||
NEW_IN_NEW_PANE_EMBED: "新建绘图(在新面板),并插入(嵌入)到当前文档",
|
||||
NEW_IN_ACTIVE_PANE_EMBED: "新建绘图(在当前面板),并插入(嵌入)到当前文档",
|
||||
OPEN_EXISTING_NEW_PANE: "打开已有的绘图 - 于新面板",
|
||||
OPEN_EXISTING_ACTIVE_PANE:
|
||||
"打开已有的绘图 - 于当前面板",
|
||||
TRANSCLUDE: "嵌入绘图(形如 ![[drawing]])到当前文档",
|
||||
TRANSCLUDE_MOST_RECENT: "嵌入最近编辑过的绘图(形如 ![[drawing]])到当前文档",
|
||||
TOGGLE_LEFTHANDED_MODE: "切换为左手模式",
|
||||
NEW_IN_NEW_PANE: "新建绘图 - 于新面板",
|
||||
NEW_IN_ACTIVE_PANE: "新建绘图 - 于当前面板",
|
||||
NEW_IN_POPOUT_WINDOW: "新建绘图 - 于新窗口",
|
||||
NEW_IN_NEW_PANE_EMBED:
|
||||
"新建绘图 - 于新面板 - 并将其嵌入(形如 ![[drawing]])到当前文档",
|
||||
NEW_IN_ACTIVE_PANE_EMBED:
|
||||
"新建绘图 - 于当前面板 - 并将其嵌入(形如 ![[drawing]])到当前文档",
|
||||
NEW_IN_POPOUT_WINDOW_EMBED: "新建绘图 - 于新窗口 - 并将其嵌入(形如 ![[drawing]])到当前文档",
|
||||
EXPORT_SVG: "导出 SVG 文件到当前目录",
|
||||
EXPORT_PNG: "导出 PNG 文件到当前目录",
|
||||
TOGGLE_LOCK: "切换文本元素的原文/预览模式",
|
||||
DELETE_FILE: "删除所选的图像或以图像形式嵌入的 Markdown 文档(包括其源文件)",
|
||||
INSERT_LINK_TO_ELEMENT: "复制所选元素(以链接形式)",
|
||||
TOGGLE_LOCK: "切换文本元素为原文模式(RAW)/预览模式(PREVIEW)",
|
||||
DELETE_FILE: "从库中删除所选图像(或 MD-Embed)的源文件",
|
||||
INSERT_LINK_TO_ELEMENT:
|
||||
"复制所选元素的内部链接。按住 CTRL/CMD 可复制元素所在分组的内部链接。按住 SHIFT 可复制元素周围区域的内部链接。",
|
||||
INSERT_LINK_TO_ELEMENT_GROUP:
|
||||
"复制所选元素所在分组的内部链接(形如 [[file#^group=elementID]])",
|
||||
INSERT_LINK_TO_ELEMENT_AREA:
|
||||
"复制所选元素周围区域的内部链接(形如 [[file#^area=elementID]])",
|
||||
INSERT_LINK_TO_ELEMENT_NORMAL:
|
||||
"复制所选元素的引用链接(形如 [[file#^elementID]])",
|
||||
INSERT_LINK_TO_ELEMENT_ERROR: "未选择画布里的单个元素",
|
||||
INSERT_LINK_TO_ELEMENT_READY: "链接已生成并复制到剪贴板",
|
||||
INSERT_LINK: "插入(链接)文件到当前绘图",
|
||||
INSERT_IMAGE: "插入(以图像形式嵌入)图像到当前绘图",
|
||||
INSERT_MD: "插入(以图像形式嵌入) Markdown 文档到当前绘图",
|
||||
INSERT_LATEX: "插入 LaTeX 公式",
|
||||
INSERT_LINK: "插入文件的内部链接(形如 [[drawing]])到当前绘图",
|
||||
INSERT_IMAGE: "插入图像(以图像形式嵌入)到当前绘图",
|
||||
INSERT_MD: "插入 Markdown 文档(以图像形式嵌入)到当前绘图",
|
||||
INSERT_LATEX:
|
||||
"插入 LaTeX 公式到当前绘图",
|
||||
ENTER_LATEX: "输入 LaTeX 表达式",
|
||||
READ_RELEASE_NOTES: "阅读本插件的最新发行版本说明",
|
||||
TRAY_MODE: "切换绘图工具属性页的面板(Panel)/托盘(Tray)模式",
|
||||
TRAY_MODE: "切换绘图工具属性页为面板模式(Panel)/托盘模式(Tray)",
|
||||
SEARCH: "搜索文本",
|
||||
|
||||
//ExcalidrawView.ts
|
||||
INSTALL_SCRIPT_BUTTON: "安装或更新 Excalidraw 自动化脚本",
|
||||
OPEN_AS_MD: "打开为 Markdown 文件(Markdown 模式)",
|
||||
OPEN_AS_MD: "打开为 Markdown 文件",
|
||||
SAVE_AS_PNG: "导出 PNG 到当前目录(按住 CTRL/CMD 设定导出路径)",
|
||||
SAVE_AS_SVG: "导出 SVG 到当前目录(按住 CTRL/CMD 设定导出路径)",
|
||||
OPEN_LINK: "打开所选元素里的链接 \n(按住 SHIFT 在新面板打开)",
|
||||
@@ -55,13 +72,12 @@ export default {
|
||||
"请选择一个含有链接的图形或文本元素。\n" +
|
||||
"按住 SHIFT 并点击此按钮可在新面板中打开链接。\n" +
|
||||
"您也可以直接在画布中按住 CTRL/CMD 并点击图形或文本元素来打开链接。",
|
||||
TEXT_ELEMENT_EMPTY:
|
||||
"未选中图形或文本元素,或者元素不包含有效的链接([[链接|别名]] 或 [别名](链接))",
|
||||
FILENAME_INVALID_CHARS: '文件名不能含有以下符号: * " \\ < > : | ? #',
|
||||
FILENAME_INVALID_CHARS:
|
||||
'文件名不能含有以下符号: * " \\ < > : | ? #',
|
||||
FILE_DOES_NOT_EXIST:
|
||||
"文件不存在。按住 ALT(或 ALT + SHIFT)并点击链接来创建新文件。",
|
||||
FORCE_SAVE:
|
||||
"立刻保存该绘图,并更新其他嵌入了该绘图的面板。\n(详见插件设置中的定期保存选项)",
|
||||
"立刻保存该绘图(并更新嵌入了该绘图的面板)。\n详见插件设置中的定期保存选项",
|
||||
RAW: "文本元素正以原文(RAW)模式显示链接。\n点击切换到预览(PREVIEW)模式",
|
||||
PARSED:
|
||||
"文本元素正以预览(PREVIEW)模式显示链接。\n点击切换到原文(RAW)模式",
|
||||
@@ -75,13 +91,20 @@ export default {
|
||||
RELEASE_NOTES_DESC:
|
||||
"<b>开启:</b>每次更新本插件后,显示最新发行版本的说明。<br>" +
|
||||
"<b>关闭:</b>您仍可以在 <a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/releases'>GitHub</a> 上阅读更新说明。",
|
||||
NEWVERSION_NOTIFICATION_NAME: "通知插件更新",
|
||||
NEWVERSION_NOTIFICATION_DESC:
|
||||
"<b>开启:</b>当本插件存在可用更新时,显示通知。<br>" +
|
||||
"<b>关闭:</b>您需要手动检查本插件的更新(设置 - 第三方插件 - 检查更新)。",
|
||||
|
||||
FOLDER_NAME: "Excalidraw 文件夹",
|
||||
FOLDER_DESC: "新绘图的默认存储路径。若为空,将在库的根目录中创建新绘图。",
|
||||
FOLDER_EMBED_NAME: "将 Excalidraw 文件夹用于“新建绘图”命令创建的绘图",
|
||||
FOLDER_DESC:
|
||||
"新绘图的默认存储路径。若为空,将在库的根目录中创建新绘图。",
|
||||
FOLDER_EMBED_NAME:
|
||||
"将 Excalidraw 文件夹用于“新建绘图”命令创建的绘图",
|
||||
FOLDER_EMBED_DESC:
|
||||
"在命令面板中执行“新建绘图,并插入(嵌入)到当前文档”之类命令时," +
|
||||
"在命令面板中执行“新建绘图”系列命令时," +
|
||||
"新绘图的存储路径。<br>" +
|
||||
"<b>开启:</b>使用 Excalidraw 文件夹。 <b>关闭:</b>使用 Obsidian 设置的新附件默认位置。",
|
||||
"<b>开启:</b>使用 Excalidraw 文件夹。 <br><b>关闭:</b>使用 Obsidian 设置的新附件默认位置。",
|
||||
TEMPLATE_NAME: "Excalidraw 模板文件",
|
||||
TEMPLATE_DESC:
|
||||
"Excalidraw 模板文件的完整路径。<br>" +
|
||||
@@ -113,89 +136,107 @@ export default {
|
||||
"但是在手机或平板上通过滑动手势退出 Obsidian 时,可能无法顺利触发自动保存。因此我添加了定期保存功能作为弥补。",
|
||||
AUTOSAVE_INTERVAL_NAME: "定期保存的时间间隔",
|
||||
AUTOSAVE_INTERVAL_DESC:
|
||||
"每隔多长时间执行一次保存。如果当前绘图没有发生改变,将不会进行定期保存。",
|
||||
"每隔多长时间执行一次保存。如果当前绘图没有发生改变,将不会触发保存。",
|
||||
FILENAME_HEAD: "文件名",
|
||||
FILENAME_DESC:
|
||||
"<p>点击阅读" +
|
||||
"<a href='https://momentjs.com/docs/#/displaying/format/'>日期和时间格式参考</a>。</p>",
|
||||
FILENAME_SAMPLE: "当前设置下,新绘图的文件名形如:",
|
||||
FILENAME_EMBED_SAMPLE: "“新建绘图”命令创建的绘图的文件名形如:",
|
||||
FILENAME_PREFIX_NAME: "文件名前缀",
|
||||
FILENAME_PREFIX_DESC: "文件名的第一部分",
|
||||
FILENAME_PREFIX_EMBED_NAME: "“新建绘图”命令创建的绘图的文件名前缀",
|
||||
FILENAME_SAMPLE: "“新建绘图”系列命令创建的文件名形如:",
|
||||
FILENAME_EMBED_SAMPLE: "“新建绘图并嵌入到当前文档”系列命令创建的文件名形如:",
|
||||
FILENAME_PREFIX_NAME: "“新建绘图”系列命令创建的文件名前缀",
|
||||
FILENAME_PREFIX_DESC: "执行“新建绘图”系列命令时,创建的绘图文件名的第一部分",
|
||||
FILENAME_PREFIX_EMBED_NAME:
|
||||
"“新建绘图并嵌入到当前文档”系列命令创建的文件名前缀",
|
||||
FILENAME_PREFIX_EMBED_DESC:
|
||||
"若开启此项," +
|
||||
"则在命令面板中执行“新建绘图,并插入(嵌入)到当前文档”之类命令时," +
|
||||
"创建的绘图文件名将以当前文档名作为开头。",
|
||||
FILENAME_POSTFIX_NAME: "“新建绘图”命令创建的绘图的文件名后缀",
|
||||
"执行“新建绘图并嵌入到当前文档”系列命令时," +
|
||||
"创建的绘图文件名是否以当前文档名作为前缀?<br>" +
|
||||
"<b>开启:</b>是<br><b>关闭:</b>否",
|
||||
FILENAME_POSTFIX_NAME:
|
||||
"“新建绘图并嵌入到当前文档”系列命令创建的文件名的中间部分",
|
||||
FILENAME_POSTFIX_DESC:
|
||||
"介于文件名前缀和文件名日期之间的文本。仅对“新建绘图”命令创建的绘图生效。",
|
||||
FILENAME_DATE_NAME: "文件名日期",
|
||||
FILENAME_DATE_DESC: "文件名的最后一部分",
|
||||
"介于文件名前缀和日期时间之间的文本。仅对“新建绘图并嵌入到当前文档”系列命令创建的绘图生效。",
|
||||
FILENAME_DATE_NAME: "文件名里的日期时间",
|
||||
FILENAME_DATE_DESC:
|
||||
"文件名的最后一部分。允许留空。",
|
||||
FILENAME_EXCALIDRAW_EXTENSION_NAME: "文件扩展名(.excalidraw.md 或 .md)",
|
||||
FILENAME_EXCALIDRAW_EXTENSION_DESC:
|
||||
"该选项在兼容模式(即非 Excalidraw 专用 Markdown 文件)下不会生效。<br>" +
|
||||
"<b>开启:</b>使用 .excalidraw.md 作为扩展名;<b>关闭:</b>使用 .md 作为扩展名。",
|
||||
/*SVG_IN_MD_NAME: "SVG Snapshot to markdown file",
|
||||
SVG_IN_MD_DESC: "If the switch is 'on' Excalidraw will include an SVG snapshot in the markdown file. "+
|
||||
"When SVG snapshots are saved to the Excalidraw.md file, drawings that include large png, jpg, gif images may take extreme long time to open in markdown view. " +
|
||||
"On the other hand, SVG snapshots provide some level of platform independence and longevity to your drawings. Even if Excalidraw will no longer exist, the snapshot " +
|
||||
"can be opened with an app that reads SVGs. In addition hover previews will be less resource intensive if SVG snapshots are enabled.",*/
|
||||
"<b>开启:</b>使用 .excalidraw.md 作为扩展名。<br><b>关闭:</b>使用 .md 作为扩展名。",
|
||||
DISPLAY_HEAD: "显示",
|
||||
LEFTHANDED_MODE_NAME: "左手模式",
|
||||
LEFTHANDED_MODE_DESC:
|
||||
"目前只影响托盘模式下,绘图工具属性页的位置。若开启此项,则托盘处于右侧。",
|
||||
"目前只在托盘模式下生效。若开启此项,则托盘(绘图工具属性页)将位于右侧。" +
|
||||
"<br><b>开启:</b>左手模式。<br><b>关闭:</b>右手模式。",
|
||||
MATCH_THEME_NAME: "使新建的绘图匹配 Obsidian 主题",
|
||||
MATCH_THEME_DESC:
|
||||
"如果 Obsidian 使用黑暗主题,新建的绘图文件也将使用黑暗主题。<br>" +
|
||||
"但是若设置了模板,新建的绘图文件将跟随模板主题;另外,此功能不会作用于已有的绘图。",
|
||||
"但是若设置了模板,新建的绘图文件将跟随模板主题;另外,此功能不会作用于已有的绘图。" +
|
||||
"<br><b>开启:</b>跟随 Obsidian 主题风格。<br><b>关闭:</b>跟随模板主题风格。",
|
||||
MATCH_THEME_ALWAYS_NAME: "使已有的绘图匹配 Obsidian 主题",
|
||||
MATCH_THEME_ALWAYS_DESC:
|
||||
"如果 Obsidian 使用黑暗主题,则绘图文件也将以黑暗主题打开;反之亦然。",
|
||||
"如果 Obsidian 使用黑暗主题,则绘图文件也将以黑暗主题打开;反之亦然。" +
|
||||
"<br><b>开启:</b>匹配 Obsidian 主题风格。<br><b>关闭:</b>采用上次保存时的主题风格。",
|
||||
MATCH_THEME_TRIGGER_NAME: "Excalidraw 主题跟随 Obsidian 主题变化",
|
||||
MATCH_THEME_TRIGGER_DESC:
|
||||
"开启此项,则切换 Obsidian 的黑暗/明亮主题时,当前活动的 Excalidraw 面板的主题会随之改变。",
|
||||
"开启此项,则切换 Obsidian 的黑暗/明亮主题时,已打开的 Excalidraw 面板的主题会随之改变。" +
|
||||
"<br><b>开启:</b>跟随主题变化。<br><b>关闭:</b>不跟随主题变化。",
|
||||
DEFAULT_OPEN_MODE_NAME: "Excalidraw 的默认运行模式",
|
||||
DEFAULT_OPEN_MODE_DESC:
|
||||
"设置 Excalidraw 的运行模式:普通模式,禅模式,或者阅读模式。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 Frontmatter 中添加形如 <code>excalidraw-default-mode: normal/zen/view</code> 的键值对。",
|
||||
"设置 Excalidraw 的运行模式:普通模式(Normal)/禅模式(Zen)/阅读模式(View)。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 frontmatter 中添加形如 <code>excalidraw-default-mode: normal/zen/view</code> 的键值对。",
|
||||
DEFAULT_PEN_MODE_NAME: "触控笔模式(Pen mode)",
|
||||
DEFAULT_PEN_MODE_DESC:
|
||||
"打开绘图时,是否自动开启触控笔模式?",
|
||||
ZOOM_TO_FIT_NAME: "自动缩放以适应面板调整",
|
||||
ZOOM_TO_FIT_DESC: "调整面板大小时,自适应地缩放画布",
|
||||
ZOOM_TO_FIT_DESC: "调整面板大小时,自适应地缩放画布" +
|
||||
"<br><b>开启:</b>自动缩放。<br><b>关闭:</b>禁用自动缩放。",
|
||||
ZOOM_TO_FIT_MAX_LEVEL_NAME: "自动缩放的最高级别",
|
||||
ZOOM_TO_FIT_MAX_LEVEL_DESC:
|
||||
"自动缩放画布时,允许放大的最高级别。该值不能低于 0.5(50%)且不能超过 10(1000%)。",
|
||||
LINKS_HEAD: "链接(Links) & 嵌入到绘图中的文档(Transclusion)",
|
||||
LINKS_HEAD: "链接(Links) & 以文本形式嵌入到绘图中的文档(Transclusion)",
|
||||
LINKS_DESC:
|
||||
"按住 CTRL/CMD 并点击包含 <code>[[链接]]</code> 的文本元素可以打开其中的链接。" +
|
||||
"如果所选文本元素包含多个 <code>[[有效的 Obsidian 链接]]</code> ,只会打开第一个链接;" +
|
||||
"按住 CTRL/CMD 并点击包含 <code>[[链接]]</code> 的文本元素可以打开其中的链接。<br>" +
|
||||
"如果所选文本元素包含多个 <code>[[有效的内部链接]]</code> ,只会打开第一个链接;" +
|
||||
"如果所选文本元素包含有效的 URL 链接 (如 <code>https://</code> 或 <code>http://</code>)," +
|
||||
"插件会在浏览器中打开 URL 链接。<br>" +
|
||||
"链接的源文件被重命名时,绘图中相应的 <code>[[链接]]</code> 也会同步更新。" +
|
||||
"若您不愿绘图中的链接文本因此而变化,可用 <code>[[链接|别名]]</code> 来使用别名。",
|
||||
"插件会在浏览器中打开链接。<br>" +
|
||||
"链接的源文件被重命名时,绘图中相应的 <code>[[内部链接]]</code> 也会同步更新。" +
|
||||
"若您不愿绘图中的链接外观因此而变化,可使用 <code>[[内部链接|别名]]</code>。",
|
||||
ADJACENT_PANE_NAME: "在相邻面板中打开",
|
||||
ADJACENT_PANE_DESC:
|
||||
"按住 CTRL/CMD + SHIFT 并点击链接时,插件默认会在新面板中打开该链接。<br>" +
|
||||
"按住 CTRL/CMD + SHIFT 并点击绘图里的内部链接时,插件默认会在新面板中打开该链接。<br>" +
|
||||
"若开启此项,Excalidraw 会先尝试寻找已有的相邻面板(按照右侧、左侧、上方、下方的顺序)," +
|
||||
"并在其中打开链接。如果找不到," +
|
||||
"再在新面板中打开链接。",
|
||||
"并在其中打开该链接。如果找不到," +
|
||||
"再在新面板中打开。",
|
||||
MAINWORKSPACE_PANE_NAME: "在主工作区中打开",
|
||||
MAINWORKSPACE_PANE_DESC:
|
||||
"按住 CTRL/CMD + SHIFT 并点击绘图里的内部链接时,插件默认会在当前窗口的新面板中打开该链接。<br>" +
|
||||
"若开启此项,Excalidraw 会在主工作区的面板中打开该链接。",
|
||||
LINK_BRACKETS_NAME: "在链接的两侧显示 [[中括号]]",
|
||||
LINK_BRACKETS_DESC: `${
|
||||
"文本元素处于预览模式时,在链接的两侧显示中括号。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 Frontmatter 中添加形如 <code>"
|
||||
"文本元素处于预览模式时,在内部链接的两侧显示中括号。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 frontmatter 中添加形如 <code>"
|
||||
}${FRONTMATTER_KEY_CUSTOM_LINK_BRACKETS}: true/false</code> 的键值对。`,
|
||||
LINK_PREFIX_NAME: "链接的前缀",
|
||||
LINK_PREFIX_NAME: "内部链接的前缀",
|
||||
LINK_PREFIX_DESC: `${
|
||||
"文本元素处于预览模式时,如果其中包含链接,则添加此前缀。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 Frontmatter 中添加形如 <code>"
|
||||
"您可为某个绘图单独设置此项,方法是在其 frontmatter 中添加形如 <code>"
|
||||
}${FRONTMATTER_KEY_CUSTOM_PREFIX}: "📍 "</code> 的键值对。`,
|
||||
URL_PREFIX_NAME: "URL 的前缀",
|
||||
URL_PREFIX_NAME: "外部链接的前缀",
|
||||
URL_PREFIX_DESC: `${
|
||||
"预览模式下,如果文本元素包含 URL 链接,则添加此前缀。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 Frontmatter 中添加形如 <code>"
|
||||
"文本元素处于预览模式时,如果其中包含外部链接,则添加此前缀。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 frontmatter 中添加形如 <code>"
|
||||
}${FRONTMATTER_KEY_CUSTOM_URL_PREFIX}: "🌐 "</code> 的键值对。`,
|
||||
HOVERPREVIEW_NAME: "鼠标悬停预览链接",
|
||||
PARSE_TODO_NAME: "解析任务列表(Todo)",
|
||||
PARSE_TODO_DESC: "将文本元素中的 <code>- [ ]</code> 和 <code>- [x]</code> 前缀显示为方框。",
|
||||
TODO_NAME: "未完成的 Todo 项目",
|
||||
TODO_DESC: "未完成的 Todo 项目的符号",
|
||||
DONE_NAME: "已完成的 Todo 项目",
|
||||
DONE_DESC: "已完成的 Todo 项目的符号",
|
||||
HOVERPREVIEW_NAME: "鼠标悬停预览内部链接",
|
||||
HOVERPREVIEW_DESC:
|
||||
"<b>开启:</b>鼠标悬停在 <code>[[链接]]</code> 上即可预览。<br><b>关闭:</b>鼠标悬停在 <code>[[链接]]</code> 上,并且按住 CTRL/CMD 时进行预览。",
|
||||
"<b>开启:</b>在 Excalidraw <u>阅读模式(View)</u>下,鼠标悬停在 <code>[[内部链接]]</code> 上即可预览;" +
|
||||
"而在<u>普通模式(Normal)</u>下, 鼠标悬停在内部链接右上角的蓝色标识上即可预览。<br> " +
|
||||
"<b>关闭:</b>鼠标悬停在 <code>[[内部链接]]</code> 上,并且按住 CTRL/CMD 时进行预览。",
|
||||
LINKOPACITY_NAME: "链接标识的透明度",
|
||||
LINKOPACITY_DESC:
|
||||
"含有链接的元素,其右上角的链接标识的透明度。介于 0(全透明)到 1(不透明)之间。",
|
||||
@@ -204,48 +245,52 @@ export default {
|
||||
LINK_CTRL_CLICK_DESC:
|
||||
"如果此功能影响到您使用某些原版 Excalidraw 功能,可将其关闭。" +
|
||||
"关闭后,您只能通过绘图面板标题栏中的链接按钮来打开链接。",
|
||||
TRANSCLUSION_WRAP_NAME: "嵌入文档(Translusion)的折行方式",
|
||||
TRANSCLUSION_WRAP_NAME: "Transclusion 的折行方式",
|
||||
TRANSCLUSION_WRAP_DESC:
|
||||
"中的 number 表示嵌入的文本溢出时,在第几个字符处进行折行。<br>" +
|
||||
"此开关控制具体的折行方式。若开启,则严格在 number 处折行,禁止溢出;" +
|
||||
"若关闭,则允许在 number 位置后最近的空格处折行。",
|
||||
TRANSCLUSION_DEFAULT_WRAP_NAME: "嵌入文档(Translusion)的默认折行位置",
|
||||
TRANSCLUSION_DEFAULT_WRAP_NAME: "Transclusion 的默认折行位置",
|
||||
TRANSCLUSION_DEFAULT_WRAP_DESC:
|
||||
"除了通过 <code>![[doc#^block]]{number}</code> 中的 number 来控制折行位置,您也可以在此设置 number 的默认值。<br>" +
|
||||
"一般设为 0 即可,表示不设置固定的默认值,这样当您需要嵌入文档到便签中时," +
|
||||
"Excalidraw 能更好地帮您自动处理。",
|
||||
PAGE_TRANSCLUSION_CHARCOUNT_NAME: "嵌入文档(Translusion)的最大显示字符数",
|
||||
PAGE_TRANSCLUSION_CHARCOUNT_NAME: "Transclusion 的最大显示字符数",
|
||||
PAGE_TRANSCLUSION_CHARCOUNT_DESC:
|
||||
"以 <code>![[Markdown 文档]]</code> 的形式将文档嵌入到绘图中时," +
|
||||
"以 <code>![[内部链接]]</code> 或 <code></code> 的形式将文档以文本形式嵌入到绘图中时," +
|
||||
"该文档在绘图中可显示的最大字符数量。",
|
||||
GET_URL_TITLE_NAME: "使用 iframly 获取页面标题",
|
||||
GET_URL_TITLE_DESC:
|
||||
"拖放链接到 Excalidraw 时,使用 <code>http://iframely.server.crestify.com/iframely?url=</code> 来获取页面的标题。",
|
||||
MD_HEAD: "以图像形式嵌入到绘图中的 Markdown 文档(MD-Embed)",
|
||||
MD_HEAD_DESC:
|
||||
"您可以将 Markdown 文档以图像(而非链接)的形式嵌入到绘图中," +
|
||||
"方法是按住 CTRL/CMD 并从文件管理器中把文档拖入绘图,或者使用命令面板里的相关命令。",
|
||||
"您还可以将 Markdown 文档以图像形式(而非文本形式)嵌入到绘图中。" +
|
||||
"方法是按住 CTRL/CMD 并从文件管理器中把文档拖入绘图,或者执行“以图像形式嵌入”系列命令。",
|
||||
MD_TRANSCLUDE_WIDTH_NAME: "MD-Embed 的默认宽度",
|
||||
MD_TRANSCLUDE_WIDTH_DESC:
|
||||
"MD-Embed 图像的宽度。该选项会影响到折行,以及图像元素的宽度。<br>" +
|
||||
"MD-Embed 的宽度。该选项会影响到折行,以及图像元素的宽度。<br>" +
|
||||
"您可为绘图中的某个 MD-Embed 单独设置此项,方法是将绘图切换至 Markdown 模式," +
|
||||
"并修改相应的 <code>[[Embed文件名#标题|宽度x最大高度]]</code>。",
|
||||
MD_TRANSCLUDE_HEIGHT_NAME: "MD-Embed 的默认最大高度",
|
||||
MD_TRANSCLUDE_HEIGHT_NAME:
|
||||
"MD-Embed 的默认最大高度",
|
||||
MD_TRANSCLUDE_HEIGHT_DESC:
|
||||
"MD-Embed 图像的高度取决于文档内容的多少,但最大不会超过该值。<br>" +
|
||||
"MD-Embed 的高度取决于 Markdown 文档内容的多少,但最大不会超过该值。<br>" +
|
||||
"您可为绘图中的某个 MD-Embed 单独设置此项,方法是将绘图切换至 Markdown 模式,并修改相应的 <code>[[Embed文件名#^块引ID|宽度x最大高度]]</code>。",
|
||||
MD_DEFAULT_FONT_NAME: "MD-Embed 的默认字体",
|
||||
MD_DEFAULT_FONT_NAME:
|
||||
"MD-Embed 的默认字体",
|
||||
MD_DEFAULT_FONT_DESC:
|
||||
"可以设为 <code>Virgil</code>,<code>Casadia</code> 或其他有效的 .ttf/.woff/.woff2 字体文件(如 <code>我的字体.woff2</code>)。<br>" +
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 Frontmatter 中添加形如 <code>excalidraw-font: 字体名或文件名</code> 的键值对。",
|
||||
MD_DEFAULT_COLOR_NAME: "MD-Embed 的默认文本颜色",
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 frontmatter 中添加形如 <code>excalidraw-font: 字体名或文件名</code> 的键值对。",
|
||||
MD_DEFAULT_COLOR_NAME:
|
||||
"MD-Embed 的默认文本颜色",
|
||||
MD_DEFAULT_COLOR_DESC:
|
||||
"可以填写 HTML 颜色名,如 steelblue(参考 <a href='https://www.w3schools.com/colors/colors_names.asp'>HTML Color Names</a>),或者有效的 16 进制颜色值,例如 #e67700,或者任何其他有效的 CSS 颜色。<br>" +
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 Frontmatter 中添加形如 <code>excalidraw-font-color: steelblue</code> 的键值对。",
|
||||
MD_DEFAULT_BORDER_COLOR_NAME: "MD-Embed 的默认边框颜色",
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 frontmatter 中添加形如 <code>excalidraw-font-color: steelblue</code> 的键值对。",
|
||||
MD_DEFAULT_BORDER_COLOR_NAME:
|
||||
"MD-Embed 的默认边框颜色",
|
||||
MD_DEFAULT_BORDER_COLOR_DESC:
|
||||
"可以填写 HTML 颜色名,如 steelblue(参考 <a href='https://www.w3schools.com/colors/colors_names.asp'>HTML Color Names</a>),或者有效的 16 进制颜色值,例如 #e67700,或者任何其他有效的 CSS 颜色。<br>" +
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 Frontmatter 中添加形如 <code>excalidraw-border-color: gray</code> 的键值对。<br>" +
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 frontmatter 中添加形如 <code>excalidraw-border-color: gray</code> 的键值对。<br>" +
|
||||
"如果您不想要边框,请留空。",
|
||||
MD_CSS_NAME: "MD-Embed 的默认 CSS 样式表",
|
||||
MD_CSS_DESC:
|
||||
@@ -255,58 +300,76 @@ export default {
|
||||
"<code>ExcalidrawAutomate.mostRecentMarkdownSVG</code> —— 这将显示 Excalidraw 最近生成的 SVG。<br>" +
|
||||
"此外,在 CSS 中不能任意地设置字体,您一般只能使用系统默认的标准字体(详见 README)," +
|
||||
"但可以通过上面的设置来额外添加一个自定义字体。<br>" +
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 Frontmatter 中添加形如 <code>excalidraw-css: 库中的CSS文件或CSS片段</code> 的键值对。",
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 frontmatter 中添加形如 <code>excalidraw-css: 库中的CSS文件或CSS片段</code> 的键值对。",
|
||||
EMBED_HEAD: "嵌入到文档中的绘图(Embed) & 导出",
|
||||
EMBED_PREVIEW_SVG_NAME: "在 Markdown 阅读视图下显示 SVG 格式的预览图",
|
||||
EMBED_REUSE_EXPORTED_IMAGE_NAME:
|
||||
"将之前已导出的图像作为 Embed 的预览图(如果存在的话)",
|
||||
EMBED_REUSE_EXPORTED_IMAGE_DESC:
|
||||
"该选项与“自动导出 SVG/PNG 副本”选项配合使用。如果存在文件名相匹配的 SVG/PNG 副本,则将其作为 Embed 的预览图,而不再重新生成预览图。<br>" +
|
||||
"该选项能够提高性能,尤其是当 Embed 中含有大量图像或 MD-Embed 时。" +
|
||||
"但是,该选项也可能导致预览图无法立即响应你最新的修改,或者你对 Obsidian 主题风格的改变。<br>" +
|
||||
"该选项仅作用于嵌入到文档中的绘图。" +
|
||||
"由于种种原因,该技术无法用于加快绘图文件的打开速度。详见<a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/releases/tag/1.6.23' target='_blank'>此说明</a>。",
|
||||
EMBED_PREVIEW_SVG_NAME: "生成 SVG 格式的 Embed 预览图",
|
||||
EMBED_PREVIEW_SVG_DESC:
|
||||
"Obsidian 的 Markdown 阅读视图默认会将嵌入的绘图显示为 SVG 格式的预览图。若关闭此项,则显示为 PNG 格式。",
|
||||
PREVIEW_MATCH_OBSIDIAN_NAME: "预览图匹配 Obsidian 主题",
|
||||
"<b>开启:</b>在 Markdown 预览模式下,为 Embed 生成 <a href='https://en.wikipedia.org/wiki/Scalable_Vector_Graphics' target='_blank'>SVG</a> 格式的预览图。<br>" +
|
||||
"<b>关闭:</b>为 Embed 生成 <a href='' target='_blank'>PNG</a> 格式的预览图。注意:PNG 格式预览图不支持某些 <a href='https://www.youtube.com/watch?v=yZQoJg2RCKI&t=633s' target='_blank'>绘图元素的块引用特性</a>。",
|
||||
PREVIEW_MATCH_OBSIDIAN_NAME: "Embed 预览图匹配 Obsidian 主题",
|
||||
PREVIEW_MATCH_OBSIDIAN_DESC:
|
||||
"开启此项,则当 Obsidian 处于黑暗模式时,预览图也会以黑暗模式渲染;" +
|
||||
"当 Obsidian 处于明亮模式时,的预览图也会以明亮模式渲染。<br>您可能还需要关闭“导出的图像包含背景”开关,来获得与 Obsidian 更加协调的观感。",
|
||||
EMBED_WIDTH_NAME: "预览图的默认宽度",
|
||||
"开启此项,则当 Obsidian 处于黑暗模式时,Embed 的预览图也会以黑暗模式渲染;当 Obsidian 处于明亮模式时,预览图也会以明亮模式渲染。<br>" +
|
||||
"您可能还需要关闭“导出的图像包含背景”开关,来获得与 Obsidian 更加协调的观感。",
|
||||
EMBED_WIDTH_NAME: "Embed 预览图的默认宽度",
|
||||
EMBED_WIDTH_DESC:
|
||||
"该选项同时作用于 Obsidian 实时预览模式下的编辑视图和阅读视图,以及鼠标悬停时的预览图。<br>" +
|
||||
"您可为嵌入到文档中的某个绘图单独设置此项," +
|
||||
"该选项同时作用于 Obsidian 实时预览模式下的编辑视图和阅读视图,以及鼠标悬停时浮现的预览图。<br>" +
|
||||
"您可为某个要嵌入到文档中的绘图(Embed)单独设置此项," +
|
||||
"方法是修改相应的链接格式为形如 <code>![[drawing.excalidraw|100]]</code> 或 <code>[[drawing.excalidraw|100x100]]</code> 的格式。",
|
||||
EMBED_TYPE_NAME: "“嵌入绘图到当前文档”命令的源文件类型",
|
||||
EMBED_TYPE_NAME: "“嵌入绘图到当前文档”系列命令的源文件类型",
|
||||
EMBED_TYPE_DESC:
|
||||
"在命令面板中执行“嵌入绘图到当前文档”之类命令时,要嵌入绘图文件,还是嵌入其 PNG 或 SVG 副本。<br>" +
|
||||
"如果您想在该下拉框中选择 PNG 或 SVG 副本,需要先开启下方的“自动导出 PNG 格式副本”或“自动导出 SVG 格式副本”开关。" +
|
||||
"若您选择了嵌入 PNG 或 SVG 副本,当绘图缺少对应的 PNG 或 SVG 副本时,该命令将会插入一条损坏的链接,您需要打开绘图文件并手动导出副本才能修复 —— " +
|
||||
"该选项不会帮您自动生成 PNG/SVG 副本,而只会引用已经存在的 PNG/SVG 副本。",
|
||||
EMBED_WIKILINK_NAME: "“嵌入绘图到当前文档”命令产生的链接类型",
|
||||
"在命令面板中执行“嵌入绘图到当前文档”系列命令时,要嵌入绘图文件本身,还是嵌入其 PNG 或 SVG 副本。<br>" +
|
||||
"如果您想选择 PNG 或 SVG 副本,需要先开启下方的“自动导出 PNG 副本”或“自动导出 SVG 副本”开关。<br>" +
|
||||
"如果您选择了 PNG 或 SVG 副本,当副本不存在时,该命令将会插入一条损坏的链接,您需要打开绘图文件并手动导出副本才能修复 —— " +
|
||||
"也就是说,该选项不会自动帮您生成 PNG/SVG 副本,而只会引用已有的 PNG/SVG 副本。",
|
||||
EMBED_WIKILINK_NAME: "“嵌入绘图到当前文档”命令产生的内部链接类型",
|
||||
EMBED_WIKILINK_DESC:
|
||||
"<b>开启:</b>将产生 <code>![[Wiki 链接]]</code>。<b>关闭:</b>将产生 <code></code>。",
|
||||
EXPORT_PNG_SCALE_NAME: "导出 PNG 图像的比例",
|
||||
EXPORT_PNG_SCALE_NAME: "导出的 PNG 图像的比例",
|
||||
EXPORT_PNG_SCALE_DESC: "导出的 PNG 图像的大小比例",
|
||||
EXPORT_BACKGROUND_NAME: "导出的图像包含背景",
|
||||
EXPORT_BACKGROUND_DESC: "如果关闭,将导出透明背景的图像。",
|
||||
EXPORT_SVG_PADDING_NAME: "导出 SVG 图像的边距",
|
||||
EXPORT_SVG_PADDING_DESC:
|
||||
"导出的 PNG 图像的空白边距(像素)。增加该值,可以避免在导出 SVG 图像时,过于靠近画布边缘的图形被裁掉。",
|
||||
EXPORT_BACKGROUND_DESC:
|
||||
"如果关闭,将导出透明背景的图像。",
|
||||
EXPORT_PADDING_NAME: "导出的图像的空白边距",
|
||||
EXPORT_PADDING_DESC:
|
||||
"导出的 SVG/PNG 图像四周的空白边距(单位:像素)。<br>" +
|
||||
"增加该值,可以避免在导出图像时,靠近图像边缘的图形被裁掉。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 frontmatter 中添加形如 <code>excalidraw-export-padding: 5<code> 的键值对。",
|
||||
EXPORT_THEME_NAME: "导出的图像包含主题",
|
||||
EXPORT_THEME_DESC:
|
||||
"导出与绘图的黑暗/明亮主题匹配的图像。" +
|
||||
"如果关闭,在黑暗主题下导出的图像将和明亮主题一样。",
|
||||
EXPORT_HEAD: "导出设置",
|
||||
EXPORT_SYNC_NAME: "保持 .SVG 和 .PNG 文件名与绘图文件同步",
|
||||
EXPORT_SYNC_NAME:
|
||||
"保持 SVG/PNG 文件名与绘图文件同步",
|
||||
EXPORT_SYNC_DESC:
|
||||
"打开后,当绘图文件被重命名时,插件将同步更新同文件夹下的同名 .SVG 和 .PNG 文件。" +
|
||||
"当绘图文件被删除时,插件将自动删除同文件夹下的同名 .SVG 和 .PNG 文件。",
|
||||
EXPORT_SVG_NAME: "自动导出 SVG 格式副本",
|
||||
EXPORT_SVG_NAME: "自动导出 SVG 副本",
|
||||
EXPORT_SVG_DESC:
|
||||
"自动导出和绘图文件同名的 SVG 格式副本。" +
|
||||
"自动导出和绘图文件同名的 SVG 副本。" +
|
||||
"插件会将副本保存到绘图文件所在的文件夹中。" +
|
||||
"在文档中嵌入这个 SVG 文件,相比直接嵌入绘图文件,具有更强的跨平台能力。<br>" +
|
||||
"此开关开启时,每次您编辑 Excalidraw 绘图,其 SVG 文件副本都会同步更新。",
|
||||
EXPORT_PNG_NAME: "自动导出 PNG 格式副本",
|
||||
EXPORT_PNG_DESC: "和“自动导出 SVG 格式副本”类似,但是导出格式为 *.PNG。",
|
||||
"此开关开启时,每次您编辑 Excalidraw 绘图,其 SVG 文件副本都会同步更新。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 frontmatter 中添加形如 <code>excalidraw-autoexport: none/both/svg/png</code>" +
|
||||
"的键值对",
|
||||
EXPORT_PNG_NAME: "自动导出 PNG 副本",
|
||||
EXPORT_PNG_DESC: "和“自动导出 SVG 副本”类似,但是导出格式为 *.PNG。",
|
||||
EXPORT_BOTH_DARK_AND_LIGHT_NAME: "同时导出黑暗和明亮风格的图像",
|
||||
EXPORT_BOTH_DARK_AND_LIGHT_DESC: "若开启,Excalidraw 将导出两个文件:filename.dark.png(或 filename.dark.svg)和 filename.light.png(或 filename.light.svg)。<br>"+
|
||||
"该选项可作用于“自动导出 SVG 副本”、“自动导出 PNG 副本”,以及其他的手动的导出命令。",
|
||||
COMPATIBILITY_HEAD: "兼容性设置",
|
||||
EXPORT_EXCALIDRAW_NAME: "自动导出 Excalidraw 格式副本",
|
||||
EXPORT_EXCALIDRAW_DESC:
|
||||
"和“自动导出 SVG 格式副本”类似,但是导出格式为 *.excalidraw。",
|
||||
SYNC_EXCALIDRAW_NAME: "保持同一绘图的新旧格式文件内容一致",
|
||||
EXPORT_EXCALIDRAW_NAME: "自动导出 Excalidraw 旧格式副本",
|
||||
EXPORT_EXCALIDRAW_DESC: "和“自动导出 SVG 副本”类似,但是导出格式为 *.excalidraw。",
|
||||
SYNC_EXCALIDRAW_NAME:
|
||||
"新旧格式绘图文件的内容保持同步",
|
||||
SYNC_EXCALIDRAW_DESC:
|
||||
"如果旧格式(*.excalidraw)绘图文件的修改日期比新格式(*.md)更新," +
|
||||
"则根据旧格式文件的内容来更新新格式文件。",
|
||||
@@ -315,15 +378,20 @@ export default {
|
||||
"开启此功能后,您通过功能区按钮、命令面板、" +
|
||||
"文件浏览器等创建的绘图都将是旧格式(*.excalidraw)。" +
|
||||
"此外,您打开旧格式绘图文件时将不再收到提醒消息。",
|
||||
MATHJAX_NAME: "MathJax (LaTeX) 的 javascript 库服务器",
|
||||
MATHJAX_DESC: "如果您在绘图中使用 LaTeX,插件需要从服务器获取并加载一个 javascript 库。" +
|
||||
"如果您的网络无法访问某些库服务器,可以尝试通过此选项更换库服务器。"+
|
||||
"更改此选项后,您可能需要重启 Obsidian 来使其生效。",
|
||||
EXPERIMENTAL_HEAD: "实验性功能",
|
||||
EXPERIMENTAL_DESC:
|
||||
"以下部分设置不会立即生效,需要刷新文件资源管理器或者重启 Obsidian 才会生效。",
|
||||
FIELD_SUGGESTER_NAME: "开启 Field Suggester",
|
||||
FIELD_SUGGESTER_NAME: "开启字段建议",
|
||||
FIELD_SUGGESTER_DESC:
|
||||
"开启后,当您在编辑器中输入 <code>excalidraw-</code> 或者 <code>ea.</code> 时,会弹出一个带有函数说明的自动补全提示菜单。<br>" +
|
||||
"该功能借鉴了 Breadcrumbs 和 Templater 插件。",
|
||||
FILETYPE_NAME: "在文件浏览器中为 excalidraw.md 文件添加类型标识符(如 ✏️)",
|
||||
FILETYPE_DESC: "可通过下一项设置来自定义类型标识符。",
|
||||
FILETYPE_DESC:
|
||||
"可通过下一项设置来自定义类型标识符。",
|
||||
FILETAG_NAME: "excalidraw.md 文件的类型标识符",
|
||||
FILETAG_DESC: "要显示为类型标识符的 emoji 或文本。",
|
||||
INSERT_EMOJI: "插入 emoji",
|
||||
@@ -350,7 +418,8 @@ export default {
|
||||
SELECT_FILE_TO_LINK: "选择要插入(链接)到当前绘图中的文件。",
|
||||
SELECT_DRAWING: "选择要插入(以图像形式嵌入)到当前绘图中的图像。",
|
||||
TYPE_FILENAME: "键入要选择的绘图名称。",
|
||||
SELECT_FILE_OR_TYPE_NEW: "选择已有绘图,或者新绘图的类型,然后按回车。",
|
||||
SELECT_FILE_OR_TYPE_NEW:
|
||||
"选择已有绘图,或者新绘图的类型,然后按回车。",
|
||||
SELECT_TO_EMBED: "选择要插入(嵌入)到当前文档中的绘图。",
|
||||
SELECT_MD: "选择要插入(以图像形式嵌入)到当前绘图中的 Markdown 文档。",
|
||||
|
||||
@@ -359,7 +428,8 @@ export default {
|
||||
"EXCALIDRAW 警告\n停止加载嵌入的图像,因为此文件中存在死循环:\n",
|
||||
|
||||
//Scripts.ts
|
||||
SCRIPT_EXECUTION_ERROR: "脚本运行错误。请在开发者控制台中查看错误信息。",
|
||||
SCRIPT_EXECUTION_ERROR:
|
||||
"脚本运行错误。请在开发者控制台中查看错误信息。",
|
||||
|
||||
//ExcalidrawData.ts
|
||||
LOAD_FROM_BACKUP: "Excalidraw 文件已损坏。尝试从备份文件中加载。",
|
||||
|
||||
4288
src/main.ts
@@ -26,9 +26,9 @@ export class ActionButton extends React.Component<ButtonProps, ButtonState> {
|
||||
return (
|
||||
<button
|
||||
style={{
|
||||
width: "fit-content",
|
||||
padding: "2px",
|
||||
margin: "4px",
|
||||
//width: "fit-content",
|
||||
//padding: "2px",
|
||||
//margin: "4px",
|
||||
}}
|
||||
className="ToolIcon_type_button ToolIcon_size_small ToolIcon_type_button--show ToolIcon"
|
||||
title={this.props.title}
|
||||
@@ -42,7 +42,7 @@ export class ActionButton extends React.Component<ButtonProps, ButtonState> {
|
||||
onPointerDown={() => {
|
||||
this.toastMessageTimeout = window.setTimeout(
|
||||
() =>
|
||||
this.props.view.excalidrawAPI?.setToastMessage(this.props.title),
|
||||
this.props.view.excalidrawAPI?.setToast({message:this.props.title}),
|
||||
300,
|
||||
);
|
||||
}}
|
||||
|
||||
21
src/menu/MenuLinks.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { AppState } from "@zsviczian/excalidraw/types/types";
|
||||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
import ExcalidrawPlugin from "../main";
|
||||
|
||||
|
||||
export class MenuLinks {
|
||||
plugin: ExcalidrawPlugin;
|
||||
ref: React.MutableRefObject<any>;
|
||||
|
||||
constructor(plugin: ExcalidrawPlugin, ref: React.MutableRefObject<any>) {
|
||||
this.plugin = plugin;
|
||||
this.ref = ref;
|
||||
}
|
||||
|
||||
render = (isMobile: boolean, appState: AppState) => {
|
||||
return (
|
||||
<div>Hello</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
147
src/ocr/Taskbone.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
import { createPNG, ExcalidrawAutomate } from "../ExcalidrawAutomate";
|
||||
import {Notice, requestUrl} from "obsidian"
|
||||
import ExcalidrawPlugin from "../main"
|
||||
import {log} from "../utils/Utils"
|
||||
import ExcalidrawView, { ExportSettings } from "../ExcalidrawView"
|
||||
import FrontmatterEditor from "src/utils/Frontmatter";
|
||||
import { ExcalidrawElement, ExcalidrawImageElement } from "@zsviczian/excalidraw/types/element/types";
|
||||
import { EmbeddedFilesLoader } from "src/EmbeddedFileLoader";
|
||||
|
||||
const TASKBONE_URL = "https://api.taskbone.com/"; //"https://excalidraw-preview.onrender.com/";
|
||||
const TASKBONE_OCR_FN = "execute?id=60f394af-85f6-40bc-9613-5d26dc283cbb";
|
||||
|
||||
export default class Taskbone {
|
||||
get apiKey() {
|
||||
return this.plugin.settings.taskboneAPIkey;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private plugin: ExcalidrawPlugin
|
||||
) {
|
||||
}
|
||||
|
||||
public async initialize(save:boolean = true):Promise<string> {
|
||||
if(this.plugin.settings.taskboneAPIkey !== "") return;
|
||||
const response = await requestUrl({
|
||||
url: `${TASKBONE_URL}users/excalidraw-obsidian/identities`,
|
||||
method: "post",
|
||||
contentType: "application/json",
|
||||
throw: false
|
||||
});
|
||||
if(!response) return;
|
||||
const apiKey = response.json?.apiKey;
|
||||
if(apiKey && typeof apiKey === "string") {
|
||||
if(save) await this.plugin.loadSettings();
|
||||
this.plugin.settings.taskboneAPIkey = apiKey;
|
||||
if(save) await this.plugin.saveSettings();
|
||||
}
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
public async getTextForView(view: ExcalidrawView, forceReScan: boolean) {
|
||||
await view.forceSave(true);
|
||||
const viewElements = view.excalidrawAPI.getSceneElements().filter((el:ExcalidrawElement) =>
|
||||
el.type==="freedraw" ||
|
||||
( el.type==="image" &&
|
||||
!this.plugin.isExcalidrawFile(view.excalidrawData.getFile(el.fileId)?.file)
|
||||
));
|
||||
if(viewElements.length === 0) {
|
||||
new Notice ("Aborting OCR because there are no image or freedraw elements on the canvas.",4000);
|
||||
return;
|
||||
}
|
||||
const fe = new FrontmatterEditor(view.data);
|
||||
if(fe.hasKey("taskbone-ocr") && !forceReScan) {
|
||||
new Notice ("The drawing has already been processed, you will find the result in the frontmatter in markdown view mode. If you ran the command from the Obsidian Panel in Excalidraw then you can CTRL(CMD)+click the command to force the rescaning.",4000)
|
||||
return;
|
||||
}
|
||||
const bb = this.plugin.ea.getBoundingBox(viewElements);
|
||||
const size = (bb.width*bb.height);
|
||||
const minRatio = Math.sqrt(360000/size);
|
||||
const maxRatio = Math.sqrt(size/16000000);
|
||||
const scale = minRatio > 1
|
||||
? minRatio
|
||||
: (
|
||||
maxRatio > 1
|
||||
? 1/maxRatio
|
||||
: 1
|
||||
);
|
||||
|
||||
const loader = new EmbeddedFilesLoader(
|
||||
this.plugin,
|
||||
false,
|
||||
);
|
||||
|
||||
const exportSettings: ExportSettings = {
|
||||
withBackground: true,
|
||||
withTheme: true,
|
||||
};
|
||||
|
||||
const img =
|
||||
await createPNG(
|
||||
view.file.path + "#^taskbone",
|
||||
scale,
|
||||
exportSettings,
|
||||
loader,
|
||||
"light",
|
||||
null,
|
||||
null,
|
||||
[],
|
||||
this.plugin,
|
||||
0
|
||||
);
|
||||
|
||||
const text = await this.getTextForImage(img);
|
||||
if(text) {
|
||||
fe.setKey("taskbone-ocr",text);
|
||||
view.data = fe.data;
|
||||
view.save(false);
|
||||
window.navigator.clipboard.writeText(text);
|
||||
new Notice("I placed the recognized in the drawing's frontmatter and onto the system clipboard.");
|
||||
}
|
||||
}
|
||||
|
||||
private async getTextForImage(image: Blob):Promise<string> {
|
||||
const url = TASKBONE_URL+TASKBONE_OCR_FN;
|
||||
if(this.apiKey === "") {
|
||||
await this.initialize();
|
||||
}
|
||||
const base64Image = await this.blobToBase64(image);
|
||||
const input = {
|
||||
records: [{
|
||||
image: base64Image
|
||||
}]
|
||||
};
|
||||
|
||||
const apiResponse = await requestUrl ({
|
||||
url: url,
|
||||
method: "post",
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify(input),
|
||||
headers: {
|
||||
authorization: `Bearer ${this.apiKey}`
|
||||
},
|
||||
throw: false
|
||||
});
|
||||
const content = apiResponse?.json;
|
||||
|
||||
if(!content || apiResponse.status !== 200) {
|
||||
new Notice("Something went wrong while processing your request. Please check developer console for more information");
|
||||
log(apiResponse);
|
||||
return;
|
||||
}
|
||||
return content.records[0].text;
|
||||
}
|
||||
|
||||
|
||||
private async blobToBase64(blob: Blob): Promise<string> {
|
||||
const arrayBuffer = await blob.arrayBuffer()
|
||||
const bytes = new Uint8Array(arrayBuffer)
|
||||
var binary = '';
|
||||
var len = bytes.byteLength;
|
||||
for (var i = 0; i < len; i++) {
|
||||
binary += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
return btoa(binary);
|
||||
}
|
||||
}
|
||||
|
||||
269
src/settings.ts
@@ -4,6 +4,7 @@ import {
|
||||
normalizePath,
|
||||
PluginSettingTab,
|
||||
Setting,
|
||||
TextComponent,
|
||||
TFile,
|
||||
} from "obsidian";
|
||||
import { VIEW_TYPE_EXCALIDRAW } from "./Constants";
|
||||
@@ -15,6 +16,7 @@ import {
|
||||
getEmbedFilename,
|
||||
} from "./utils/FileUtils";
|
||||
import {
|
||||
fragWithHTML,
|
||||
setLeftHandedMode,
|
||||
} from "./utils/Utils";
|
||||
|
||||
@@ -26,6 +28,8 @@ export interface ExcalidrawSettings {
|
||||
compress: boolean;
|
||||
autosave: boolean;
|
||||
autosaveInterval: number;
|
||||
autosaveIntervalDesktop: number;
|
||||
autosaveIntervalMobile: number;
|
||||
drawingFilenamePrefix: string;
|
||||
drawingEmbedPrefixWithFilename: boolean;
|
||||
drawingFilnameEmbedPostfix: string;
|
||||
@@ -41,18 +45,24 @@ export interface ExcalidrawSettings {
|
||||
matchThemeTrigger: boolean;
|
||||
defaultMode: string;
|
||||
defaultPenMode: "never" | "mobile" | "always";
|
||||
zoomToFitOnOpen: boolean;
|
||||
zoomToFitOnResize: boolean;
|
||||
zoomToFitMaxLevel: number;
|
||||
openInAdjacentPane: boolean;
|
||||
openInMainWorkspace: boolean;
|
||||
showLinkBrackets: boolean;
|
||||
linkPrefix: string;
|
||||
urlPrefix: string;
|
||||
parseTODO: boolean;
|
||||
todo: string;
|
||||
done: string;
|
||||
hoverPreviewWithoutCTRL: boolean;
|
||||
linkOpacity: number;
|
||||
allowCtrlClick: boolean; //if disabled only the link button in the view header will open links
|
||||
forceWrap: boolean;
|
||||
pageTransclusionCharLimit: number;
|
||||
wordWrappingDefault: number;
|
||||
removeTransclusionQuoteSigns: boolean;
|
||||
iframelyAllowed: boolean;
|
||||
pngExportScale: number;
|
||||
exportWithTheme: boolean;
|
||||
@@ -61,6 +71,7 @@ export interface ExcalidrawSettings {
|
||||
keepInSync: boolean;
|
||||
autoexportSVG: boolean;
|
||||
autoexportPNG: boolean;
|
||||
autoExportLightAndDark: boolean;
|
||||
autoexportExcalidraw: boolean;
|
||||
embedType: "excalidraw" | "PNG" | "SVG";
|
||||
embedWikiLink: boolean;
|
||||
@@ -100,6 +111,10 @@ export interface ExcalidrawSettings {
|
||||
defaultTrayMode: boolean;
|
||||
previousRelease: string;
|
||||
showReleaseNotes: boolean;
|
||||
showNewVersionNotification: boolean;
|
||||
mathjaxSourceURL: string;
|
||||
taskboneEnabled: boolean;
|
||||
taskboneAPIkey: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
@@ -110,6 +125,8 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
compress: false,
|
||||
autosave: true,
|
||||
autosaveInterval: 15000,
|
||||
autosaveIntervalDesktop: 15000,
|
||||
autosaveIntervalMobile: 10000,
|
||||
drawingFilenamePrefix: "Drawing ",
|
||||
drawingEmbedPrefixWithFilename: true,
|
||||
drawingFilnameEmbedPostfix: " ",
|
||||
@@ -125,26 +142,33 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
matchThemeTrigger: false,
|
||||
defaultMode: "normal",
|
||||
defaultPenMode: "never",
|
||||
zoomToFitOnOpen: true,
|
||||
zoomToFitOnResize: true,
|
||||
zoomToFitMaxLevel: 2,
|
||||
linkPrefix: "📍",
|
||||
urlPrefix: "🌐",
|
||||
parseTODO: false,
|
||||
todo: "☐",
|
||||
done: "🗹",
|
||||
hoverPreviewWithoutCTRL: false,
|
||||
linkOpacity: 1,
|
||||
openInAdjacentPane: false,
|
||||
openInMainWorkspace: true,
|
||||
showLinkBrackets: true,
|
||||
allowCtrlClick: true,
|
||||
forceWrap: false,
|
||||
pageTransclusionCharLimit: 200,
|
||||
wordWrappingDefault: 0,
|
||||
removeTransclusionQuoteSigns: true,
|
||||
iframelyAllowed: true,
|
||||
pngExportScale: 1,
|
||||
exportWithTheme: true,
|
||||
exportWithBackground: true,
|
||||
exportPaddingSVG: 10,
|
||||
exportPaddingSVG: 10, //since 1.6.17, not only SVG but also PNG
|
||||
keepInSync: false,
|
||||
autoexportSVG: false,
|
||||
autoexportPNG: false,
|
||||
autoExportLightAndDark: false,
|
||||
autoexportExcalidraw: false,
|
||||
embedType: "excalidraw",
|
||||
embedWikiLink: true,
|
||||
@@ -177,17 +201,19 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
mdCSS: "",
|
||||
scriptEngineSettings: {},
|
||||
defaultTrayMode: false,
|
||||
previousRelease: "1.6.13",
|
||||
previousRelease: "0.0.0",
|
||||
showReleaseNotes: true,
|
||||
showNewVersionNotification: true,
|
||||
mathjaxSourceURL: "https://cdn.jsdelivr.net/npm/mathjax@3.2.1/es5/tex-svg.js",
|
||||
taskboneEnabled: false,
|
||||
taskboneAPIkey: "",
|
||||
};
|
||||
|
||||
const fragWithHTML = (html: string) =>
|
||||
createFragment((frag) => (frag.createDiv().innerHTML = html));
|
||||
|
||||
export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
plugin: ExcalidrawPlugin;
|
||||
private requestEmbedUpdate: boolean = false;
|
||||
private requestReloadDrawings: boolean = false;
|
||||
private reloadMathJax: boolean = false;
|
||||
//private applyDebounceTimer: number = 0;
|
||||
|
||||
constructor(app: App, plugin: ExcalidrawPlugin) {
|
||||
@@ -214,7 +240,7 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
this.plugin.saveSettings();
|
||||
if (this.requestReloadDrawings) {
|
||||
const exs =
|
||||
this.plugin.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
|
||||
app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
|
||||
for (const v of exs) {
|
||||
if (v.view instanceof ExcalidrawView) {
|
||||
await v.view.save(false);
|
||||
@@ -228,6 +254,9 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
this.plugin.triggerEmbedUpdates();
|
||||
}
|
||||
this.plugin.scriptEngine.updateScriptPath();
|
||||
if(this.reloadMathJax) {
|
||||
this.plugin.loadMathJax();
|
||||
}
|
||||
}
|
||||
|
||||
async display() {
|
||||
@@ -261,6 +290,18 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("NEWVERSION_NOTIFICATION_NAME"))
|
||||
.setDesc(fragWithHTML(t("NEWVERSION_NOTIFICATION_DESC")))
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.showNewVersionNotification)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.showNewVersionNotification = value;
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("FOLDER_NAME"))
|
||||
.setDesc(fragWithHTML(t("FOLDER_DESC")))
|
||||
@@ -312,6 +353,8 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
}),
|
||||
);
|
||||
|
||||
this.containerEl.createEl("h1", { text: t("SAVING_HEAD") });
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("COMPRESS_NAME"))
|
||||
.setDesc(fragWithHTML(t("COMPRESS_DESC")))
|
||||
@@ -322,7 +365,45 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
this.plugin.settings.compress = value;
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("AUTOSAVE_INTERVAL_DESKTOP_NAME"))
|
||||
.setDesc(fragWithHTML(t("AUTOSAVE_INTERVAL_DESKTOP_DESC")))
|
||||
.addDropdown((dropdown) =>
|
||||
dropdown
|
||||
.addOption("15000", "Frequent (every 15 seconds)")
|
||||
.addOption("60000", "Moderate (every 60 seconds)")
|
||||
.addOption("300000", "Rare (every 5 minutes)")
|
||||
.addOption("900000", "Practically never (every 15 minutes)")
|
||||
.setValue(this.plugin.settings.autosaveIntervalDesktop.toString())
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.autosaveIntervalDesktop = parseInt(value);
|
||||
this.plugin.settings.autosaveInterval = app.isMobile
|
||||
? this.plugin.settings.autosaveIntervalMobile
|
||||
: this.plugin.settings.autosaveIntervalDesktop;
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("AUTOSAVE_INTERVAL_MOBILE_NAME"))
|
||||
.setDesc(fragWithHTML(t("AUTOSAVE_INTERVAL_MOBILE_DESC")))
|
||||
.addDropdown((dropdown) =>
|
||||
dropdown
|
||||
.addOption("10000", "Frequent (every 10 seconds)")
|
||||
.addOption("30000", "Moderate (every 30 seconds)")
|
||||
.addOption("60000", "Rare (every 1 minute)")
|
||||
.addOption("300000", "Practically never (every 5 minutes)")
|
||||
.setValue(this.plugin.settings.autosaveIntervalMobile.toString())
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.autosaveIntervalMobile = parseInt(value);
|
||||
this.plugin.settings.autosaveInterval = app.isMobile
|
||||
? this.plugin.settings.autosaveIntervalMobile
|
||||
: this.plugin.settings.autosaveIntervalDesktop;
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
|
||||
this.containerEl.createEl("h1", { text: t("FILENAME_HEAD") });
|
||||
containerEl.createDiv("", (el) => {
|
||||
@@ -435,7 +516,10 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
.setValue(this.plugin.settings.isLeftHanded)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.isLeftHanded = value;
|
||||
setLeftHandedMode(value);
|
||||
//not clear why I need to do this. If I don't double apply the stylesheet changes
|
||||
//then the style won't be applied in the popout windows
|
||||
setLeftHandedMode(value);
|
||||
setTimeout(()=>setLeftHandedMode(value));
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
@@ -506,6 +590,18 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("ZOOM_TO_FIT_ONOPEN_NAME"))
|
||||
.setDesc(fragWithHTML(t("ZOOM_TO_FIT_ONOPEN_DESC")))
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.zoomToFitOnOpen)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.zoomToFitOnOpen = value;
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("ZOOM_TO_FIT_NAME"))
|
||||
.setDesc(fragWithHTML(t("ZOOM_TO_FIT_DESC")))
|
||||
@@ -555,17 +651,30 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
.setValue(this.plugin.settings.openInAdjacentPane)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.openInAdjacentPane = value;
|
||||
this.applySettingsUpdate(true);
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("MAINWORKSPACE_PANE_NAME"))
|
||||
.setDesc(fragWithHTML(t("MAINWORKSPACE_PANE_DESC")))
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.openInMainWorkspace)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.openInMainWorkspace = value;
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("LINK_BRACKETS_NAME"))
|
||||
.setName(fragWithHTML(t("LINK_BRACKETS_NAME")))
|
||||
.setDesc(fragWithHTML(t("LINK_BRACKETS_DESC")))
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.showLinkBrackets)
|
||||
.onChange(async (value) => {
|
||||
.onChange(value => {
|
||||
this.plugin.settings.showLinkBrackets = value;
|
||||
this.applySettingsUpdate(true);
|
||||
}),
|
||||
@@ -578,7 +687,7 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
text
|
||||
.setPlaceholder(t("INSERT_EMOJI"))
|
||||
.setValue(this.plugin.settings.linkPrefix)
|
||||
.onChange((value) => {
|
||||
.onChange(value => {
|
||||
this.plugin.settings.linkPrefix = value;
|
||||
this.applySettingsUpdate(true);
|
||||
}),
|
||||
@@ -591,12 +700,61 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
text
|
||||
.setPlaceholder(t("INSERT_EMOJI"))
|
||||
.setValue(this.plugin.settings.urlPrefix)
|
||||
.onChange(async (value) => {
|
||||
.onChange(value => {
|
||||
this.plugin.settings.urlPrefix = value;
|
||||
this.applySettingsUpdate(true);
|
||||
}),
|
||||
);
|
||||
|
||||
let todoPrefixSetting:TextComponent, donePrefixSetting:TextComponent;
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("PARSE_TODO_NAME"))
|
||||
.setDesc(fragWithHTML(t("PARSE_TODO_DESC")))
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.parseTODO)
|
||||
.onChange(value => {
|
||||
this.plugin.settings.parseTODO = value;
|
||||
todoPrefixSetting.setDisabled(!value);
|
||||
donePrefixSetting.setDisabled(!value);
|
||||
this.applySettingsUpdate(true);
|
||||
})
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("TODO_NAME"))
|
||||
.setDesc(fragWithHTML(t("TODO_DESC")))
|
||||
.addText((text) => {
|
||||
todoPrefixSetting = text;
|
||||
text
|
||||
.setPlaceholder(t("INSERT_EMOJI"))
|
||||
.setValue(this.plugin.settings.todo)
|
||||
.onChange(value => {
|
||||
this.plugin.settings.todo = value;
|
||||
this.applySettingsUpdate(true);
|
||||
})
|
||||
}
|
||||
);
|
||||
todoPrefixSetting.setDisabled(!this.plugin.settings.parseTODO);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("DONE_NAME"))
|
||||
.setDesc(fragWithHTML(t("DONE_DESC")))
|
||||
.setDisabled(!this.plugin.settings.parseTODO)
|
||||
.addText((text) => {
|
||||
donePrefixSetting = text;
|
||||
text
|
||||
.setPlaceholder(t("INSERT_EMOJI"))
|
||||
.setValue(this.plugin.settings.done)
|
||||
.onChange(value => {
|
||||
this.plugin.settings.done = value;
|
||||
this.applySettingsUpdate(true);
|
||||
})
|
||||
}
|
||||
);
|
||||
donePrefixSetting.setDisabled(!this.plugin.settings.parseTODO);
|
||||
|
||||
let opacityText: HTMLDivElement;
|
||||
new Setting(containerEl)
|
||||
.setName(t("LINKOPACITY_NAME"))
|
||||
@@ -713,6 +871,19 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("QUOTE_TRANSCLUSION_REMOVE_NAME"))
|
||||
.setDesc(fragWithHTML(t("QUOTE_TRANSCLUSION_REMOVE_DESC")))
|
||||
.addToggle(toggle =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.removeTransclusionQuoteSigns)
|
||||
.onChange(value => {
|
||||
this.plugin.settings.removeTransclusionQuoteSigns = value;
|
||||
this.requestEmbedUpdate = true;
|
||||
this.applySettingsUpdate(true);
|
||||
})
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("GET_URL_TITLE_NAME"))
|
||||
.setDesc(fragWithHTML(t("GET_URL_TITLE_DESC")))
|
||||
@@ -972,8 +1143,8 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
let exportPadding: HTMLDivElement;
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("EXPORT_SVG_PADDING_NAME"))
|
||||
.setDesc(fragWithHTML(t("EXPORT_SVG_PADDING_DESC")))
|
||||
.setName(t("EXPORT_PADDING_NAME"))
|
||||
.setDesc(fragWithHTML(t("EXPORT_PADDING_DESC")))
|
||||
.addSlider((slider) =>
|
||||
slider
|
||||
.setLimits(0, 50, 5)
|
||||
@@ -1069,6 +1240,18 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("EXPORT_BOTH_DARK_AND_LIGHT_NAME"))
|
||||
.setDesc(fragWithHTML(t("EXPORT_BOTH_DARK_AND_LIGHT_DESC")))
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.autoExportLightAndDark)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.autoExportLightAndDark = value;
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
|
||||
this.containerEl.createEl("h1", { text: t("COMPATIBILITY_HEAD") });
|
||||
|
||||
new Setting(containerEl)
|
||||
@@ -1108,6 +1291,24 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
}),
|
||||
);
|
||||
|
||||
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/628
|
||||
new Setting(containerEl)
|
||||
.setName(t("MATHJAX_NAME"))
|
||||
.setDesc(t("MATHJAX_DESC"))
|
||||
.addDropdown((dropdown) => {
|
||||
dropdown
|
||||
.addOption("https://cdn.jsdelivr.net/npm/mathjax@3.2.1/es5/tex-svg.js", "jsdelivr")
|
||||
.addOption("https://unpkg.com/mathjax@3.2.1/es5/tex-svg.js", "unpkg")
|
||||
.addOption("https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.1/es5/tex-svg-full.min.js","cdnjs")
|
||||
.setValue(this.plugin.settings.mathjaxSourceURL)
|
||||
.onChange((value)=> {
|
||||
this.plugin.settings.mathjaxSourceURL = value;
|
||||
this.reloadMathJax = true;
|
||||
this.applySettingsUpdate();
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
this.containerEl.createEl("h1", { text: t("EXPERIMENTAL_HEAD") });
|
||||
this.containerEl.createEl("p", { text: t("EXPERIMENTAL_DESC") });
|
||||
|
||||
@@ -1195,6 +1396,44 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
);
|
||||
});
|
||||
|
||||
this.containerEl.createEl("h2", { text: t("TASKBONE_HEAD") });
|
||||
this.containerEl.createEl("p", { text: t("TASKBONE_DESC") });
|
||||
let taskboneAPIKeyText: TextComponent;
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("TASKBONE_ENABLE_NAME"))
|
||||
.setDesc(fragWithHTML(t("TASKBONE_ENABLE_DESC")))
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.taskboneEnabled)
|
||||
.onChange(async (value) => {
|
||||
taskboneAPIKeyText.setDisabled(!value);
|
||||
this.plugin.settings.taskboneEnabled = value;
|
||||
if(this.plugin.settings.taskboneAPIkey === "") {
|
||||
const apiKey = await this.plugin.taskbone.initialize(false);
|
||||
if(apiKey) {
|
||||
taskboneAPIKeyText.setValue(apiKey);
|
||||
}
|
||||
}
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("TASKBONE_APIKEY_NAME"))
|
||||
.setDesc(fragWithHTML(t("TASKBONE_APIKEY_DESC")))
|
||||
.addText((text) => {
|
||||
taskboneAPIKeyText = text;
|
||||
taskboneAPIKeyText
|
||||
.setValue(this.plugin.settings.taskboneAPIkey)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.taskboneAPIkey = value;
|
||||
this.applySettingsUpdate();
|
||||
})
|
||||
.setDisabled(!this.plugin.settings.taskboneEnabled);
|
||||
}
|
||||
);
|
||||
|
||||
//-------------------------------------
|
||||
//Script settings
|
||||
//-------------------------------------
|
||||
|
||||
133
src/svgToExcalidraw/attributes.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import chroma from "chroma-js";
|
||||
import { ExcalidrawElementBase } from "./elements/ExcalidrawElement";
|
||||
|
||||
export function hexWithAlpha(color: string, alpha: number): string {
|
||||
return chroma(color).alpha(alpha).css();
|
||||
}
|
||||
|
||||
export function has(el: Element, attr: string): boolean {
|
||||
return el.hasAttribute(attr);
|
||||
}
|
||||
|
||||
export function get(el: Element, attr: string, backup?: string): string {
|
||||
return el.getAttribute(attr) || backup || "";
|
||||
}
|
||||
|
||||
export function getNum(el: Element, attr: string, backup?: number): number {
|
||||
const numVal = Number(get(el, attr));
|
||||
return numVal === NaN ? backup || 0 : numVal;
|
||||
}
|
||||
|
||||
const presAttrs = {
|
||||
stroke: "stroke",
|
||||
"stroke-opacity": "stroke-opacity",
|
||||
"stroke-width": "stroke-width",
|
||||
fill: "fill",
|
||||
"fill-opacity": "fill-opacity",
|
||||
opacity: "opacity",
|
||||
} as const;
|
||||
|
||||
type ExPartialElement = Partial<ExcalidrawElementBase>;
|
||||
|
||||
type AttrHandlerArgs = {
|
||||
el: Element;
|
||||
exVals: ExPartialElement;
|
||||
};
|
||||
|
||||
type PresAttrHandlers = {
|
||||
[key in keyof typeof presAttrs]: (args: AttrHandlerArgs) => void;
|
||||
};
|
||||
|
||||
const attrHandlers: PresAttrHandlers = {
|
||||
stroke: ({ el, exVals }) => {
|
||||
const strokeColor = get(el, "stroke");
|
||||
|
||||
exVals.strokeColor = has(el, "stroke-opacity")
|
||||
? hexWithAlpha(strokeColor, getNum(el, "stroke-opacity"))
|
||||
: strokeColor;
|
||||
},
|
||||
|
||||
"stroke-opacity": ({ el, exVals }) => {
|
||||
exVals.strokeColor = hexWithAlpha(
|
||||
get(el, "stroke", "#000000"),
|
||||
getNum(el, "stroke-opacity"),
|
||||
);
|
||||
},
|
||||
|
||||
"stroke-width": ({ el, exVals }) => {
|
||||
exVals.strokeWidth = getNum(el, "stroke-width");
|
||||
},
|
||||
|
||||
fill: ({ el, exVals }) => {
|
||||
const fill = get(el, `fill`);
|
||||
|
||||
exVals.backgroundColor = fill === "none" ? "#00000000" : fill;
|
||||
},
|
||||
|
||||
"fill-opacity": ({ el, exVals }) => {
|
||||
exVals.backgroundColor = hexWithAlpha(
|
||||
get(el, "fill", "#000000"),
|
||||
getNum(el, "fill-opacity"),
|
||||
);
|
||||
},
|
||||
|
||||
opacity: ({ el, exVals }) => {
|
||||
exVals.opacity = getNum(el, "opacity", 100);
|
||||
},
|
||||
};
|
||||
|
||||
// Presentation Attributes for SVG Elements:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation
|
||||
export function presAttrsToElementValues(
|
||||
el: Element,
|
||||
): Partial<ExcalidrawElementBase> {
|
||||
const exVals = [...el.attributes].reduce((exVals, attr) => {
|
||||
const name = attr.name;
|
||||
|
||||
if (Object.keys(attrHandlers).includes(name)) {
|
||||
attrHandlers[name as keyof PresAttrHandlers]({ el, exVals });
|
||||
}
|
||||
|
||||
return exVals;
|
||||
}, {} as ExPartialElement);
|
||||
|
||||
return exVals;
|
||||
}
|
||||
|
||||
type FilterAttrs = Partial<
|
||||
Pick<ExcalidrawElementBase, "x" | "y" | "width" | "height">
|
||||
>;
|
||||
|
||||
export function filterAttrsToElementValues(el: Element): FilterAttrs {
|
||||
const filterVals: FilterAttrs = {};
|
||||
|
||||
if (has(el, "x")) {
|
||||
filterVals.x = getNum(el, "x");
|
||||
}
|
||||
|
||||
if (has(el, "y")) {
|
||||
filterVals.y = getNum(el, "y");
|
||||
}
|
||||
|
||||
if (has(el, "width")) {
|
||||
filterVals.width = getNum(el, "width");
|
||||
}
|
||||
|
||||
if (has(el, "height")) {
|
||||
filterVals.height = getNum(el, "height");
|
||||
}
|
||||
|
||||
return filterVals;
|
||||
}
|
||||
|
||||
export function pointsAttrToPoints(el: Element): number[][] {
|
||||
let points: number[][] = [];
|
||||
|
||||
if (has(el, "points")) {
|
||||
points = get(el, "points")
|
||||
.split(" ")
|
||||
.map((p) => p.split(",").map(parseFloat));
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
117
src/svgToExcalidraw/elements/ExcalidrawElement.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { randomId, randomInteger } from "../utils";
|
||||
|
||||
import { ExcalidrawLinearElement, FillStyle, GroupId, StrokeSharpness, StrokeStyle } from "@zsviczian/excalidraw/types/element/types";
|
||||
|
||||
export type Point = [number, number];
|
||||
|
||||
export type ExcalidrawElementBase = {
|
||||
id: string;
|
||||
x: number;
|
||||
y: number;
|
||||
strokeColor: string;
|
||||
backgroundColor: string;
|
||||
fillStyle: FillStyle;
|
||||
strokeWidth: number;
|
||||
strokeStyle: StrokeStyle;
|
||||
strokeSharpness: StrokeSharpness;
|
||||
roughness: number;
|
||||
opacity: number;
|
||||
width: number;
|
||||
height: number;
|
||||
angle: number;
|
||||
/** Random integer used to seed shape generation so that the roughjs shape
|
||||
doesn't differ across renders. */
|
||||
seed: number;
|
||||
/** Integer that is sequentially incremented on each change. Used to reconcile
|
||||
elements during collaboration or when saving to server. */
|
||||
version: number;
|
||||
/** Random integer that is regenerated on each change.
|
||||
Used for deterministic reconciliation of updates during collaboration,
|
||||
in case the versions (see above) are identical. */
|
||||
versionNonce: number;
|
||||
isDeleted: boolean;
|
||||
/** List of groups the element belongs to.
|
||||
Ordered from deepest to shallowest. */
|
||||
groupIds: GroupId[];
|
||||
/** Ids of (linear) elements that are bound to this element. */
|
||||
boundElementIds: ExcalidrawLinearElement["id"][] | null;
|
||||
};
|
||||
|
||||
export type ExcalidrawRectangle = ExcalidrawElementBase & {
|
||||
type: "rectangle";
|
||||
};
|
||||
|
||||
export type ExcalidrawLine = ExcalidrawElementBase & {
|
||||
type: "line";
|
||||
points: readonly Point[];
|
||||
};
|
||||
|
||||
export type ExcalidrawEllipse = ExcalidrawElementBase & {
|
||||
type: "ellipse";
|
||||
};
|
||||
|
||||
export type ExcalidrawGenericElement =
|
||||
| ExcalidrawRectangle
|
||||
| ExcalidrawEllipse
|
||||
| ExcalidrawLine
|
||||
| ExcalidrawDraw;
|
||||
|
||||
export type ExcalidrawDraw = ExcalidrawElementBase & {
|
||||
type: "line";
|
||||
points: readonly Point[];
|
||||
};
|
||||
|
||||
export function createExElement(): ExcalidrawElementBase {
|
||||
return {
|
||||
id: randomId(),
|
||||
x: 0,
|
||||
y: 0,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#000000",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
strokeSharpness: "sharp",
|
||||
roughness: 0,
|
||||
opacity: 100,
|
||||
width: 0,
|
||||
height: 0,
|
||||
angle: 0,
|
||||
seed: randomInteger(),
|
||||
version: 0,
|
||||
versionNonce: 0,
|
||||
isDeleted: false,
|
||||
groupIds: [],
|
||||
boundElementIds: null,
|
||||
};
|
||||
}
|
||||
|
||||
export function createExRect(): ExcalidrawRectangle {
|
||||
return {
|
||||
...createExElement(),
|
||||
type: "rectangle",
|
||||
};
|
||||
}
|
||||
|
||||
export function createExLine(): ExcalidrawLine {
|
||||
return {
|
||||
...createExElement(),
|
||||
type: "line",
|
||||
points: [],
|
||||
};
|
||||
}
|
||||
|
||||
export function createExEllipse(): ExcalidrawEllipse {
|
||||
return {
|
||||
...createExElement(),
|
||||
type: "ellipse",
|
||||
};
|
||||
}
|
||||
|
||||
export function createExDraw(): ExcalidrawDraw {
|
||||
return {
|
||||
...createExElement(),
|
||||
type: "line",
|
||||
points: [],
|
||||
};
|
||||
}
|
||||
21
src/svgToExcalidraw/elements/ExcalidrawScene.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { ExcalidrawGenericElement } from "./ExcalidrawElement";
|
||||
|
||||
class ExcalidrawScene {
|
||||
type = "excalidraw";
|
||||
version = 2;
|
||||
source = "https://excalidraw.com";
|
||||
elements: ExcalidrawGenericElement[] = [];
|
||||
|
||||
constructor(elements:any = []) {
|
||||
this.elements = elements;
|
||||
}
|
||||
|
||||
toExJSON(): any {
|
||||
return {
|
||||
...this,
|
||||
elements: this.elements.map((el) => ({ ...el })),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default ExcalidrawScene;
|
||||