Compare commits
1251 Commits
1.6.7
...
2.14.1-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41065ce9f9 | ||
|
|
351977f0d3 | ||
|
|
01b0b64a08 | ||
|
|
938e93cc43 | ||
|
|
cebcd2b43c | ||
|
|
80b6e30040 | ||
|
|
6e92a6a399 | ||
|
|
992ae8b238 | ||
|
|
5cd07e7766 | ||
|
|
07817a4d2d | ||
|
|
a22bb4c58c | ||
|
|
43e00a51be | ||
|
|
049b5bfa85 | ||
|
|
743afa73b4 | ||
|
|
6469eec051 | ||
|
|
9f46821a41 | ||
|
|
1fb3a47bdc | ||
|
|
bcd0cdda65 | ||
|
|
207fea3f57 | ||
|
|
e55ba3cc21 | ||
|
|
71c87a7630 | ||
|
|
e598a91f43 | ||
|
|
972fe1baea | ||
|
|
d7e1268afa | ||
|
|
7a3b937ea7 | ||
|
|
c850cd15ae | ||
|
|
e9f70fd09e | ||
|
|
2083443dfe | ||
|
|
69d9b8c1c9 | ||
|
|
65f4c9f3b3 | ||
|
|
b89a106523 | ||
|
|
6434a6e58a | ||
|
|
68180db2aa | ||
|
|
63505d17e9 | ||
|
|
0851b45977 | ||
|
|
16332a3e83 | ||
|
|
8240d87fa8 | ||
|
|
a7db044715 | ||
|
|
339c274f1b | ||
|
|
d5a19cbc09 | ||
|
|
400cffcd01 | ||
|
|
e5438c1e56 | ||
|
|
7e2ef3f115 | ||
|
|
ad091df4d9 | ||
|
|
0837c017a1 | ||
|
|
32d0301366 | ||
|
|
5accd657d9 | ||
|
|
8da97a63e0 | ||
|
|
a5d7731533 | ||
|
|
acb83fd697 | ||
|
|
271f21f85a | ||
|
|
371fb54787 | ||
|
|
3f19f9771a | ||
|
|
5a8596d113 | ||
|
|
6edd8b9a4e | ||
|
|
778346b0dd | ||
|
|
85ac633263 | ||
|
|
ff404e4dd6 | ||
|
|
d0845a7d68 | ||
|
|
954eaefe29 | ||
|
|
175b202a6f | ||
|
|
b77b4df56d | ||
|
|
dd7abe2547 | ||
|
|
cac27fb936 | ||
|
|
d9aef84e13 | ||
|
|
c6a81bef24 | ||
|
|
6824a1aa68 | ||
|
|
00de9d639b | ||
|
|
5a66c78428 | ||
|
|
d1be193125 | ||
|
|
f4c8d21a33 | ||
|
|
d588f749d2 | ||
|
|
c1f909427b | ||
|
|
2b38c03840 | ||
|
|
8cca77dcab | ||
|
|
5b341cb5fb | ||
|
|
526299e41f | ||
|
|
ae82bce4da | ||
|
|
499ca87759 | ||
|
|
aa4fbe1f6c | ||
|
|
05b72f9f07 | ||
|
|
53ffa50b15 | ||
|
|
bd9721f308 | ||
|
|
875bd4cb35 | ||
|
|
ec575c307a | ||
|
|
05087874e2 | ||
|
|
4a803f4b46 | ||
|
|
a48222022e | ||
|
|
eebbde1c40 | ||
|
|
c0a7686338 | ||
|
|
4840470b60 | ||
|
|
091d9b9669 | ||
|
|
d5b86289b6 | ||
|
|
dceb6ce690 | ||
|
|
c29c25d252 | ||
|
|
a2fb36671d | ||
|
|
6e57d4e69a | ||
|
|
063bef92b9 | ||
|
|
2bf9156808 | ||
|
|
391363c419 | ||
|
|
85ae7f7bec | ||
|
|
03718bc927 | ||
|
|
768aebf5d2 | ||
|
|
9e31e74d15 | ||
|
|
2acc99d307 | ||
|
|
20892f8541 | ||
|
|
e0f96a2650 | ||
|
|
e793526cb2 | ||
|
|
d1eb4cae57 | ||
|
|
f33fa33a08 | ||
|
|
858ae11c8b | ||
|
|
99a7e74825 | ||
|
|
304cef4d7d | ||
|
|
7dba9b88dc | ||
|
|
bfb5de1525 | ||
|
|
8071a2888b | ||
|
|
8b9abb13d0 | ||
|
|
6dbae61212 | ||
|
|
75c65d61c5 | ||
|
|
37e0de41af | ||
|
|
57f9e43508 | ||
|
|
3b7f931f28 | ||
|
|
b37a7aad4f | ||
|
|
667ab31ed9 | ||
|
|
b15ddef7fe | ||
|
|
ef785e5fb0 | ||
|
|
15ba4146ac | ||
|
|
9956fd1756 | ||
|
|
b6f2161f1c | ||
|
|
e6fca1a2d0 | ||
|
|
a9cad8c9f1 | ||
|
|
22b8b1f707 | ||
|
|
98f6871caa | ||
|
|
aae588249a | ||
|
|
ef890d51e3 | ||
|
|
b0bc03437a | ||
|
|
23b94da8f0 | ||
|
|
1f227ddd24 | ||
|
|
01a88a25a2 | ||
|
|
12152665af | ||
|
|
064e17b29d | ||
|
|
0aaba80c82 | ||
|
|
1744668fbd | ||
|
|
8e3e2ffb25 | ||
|
|
f5475bfde6 | ||
|
|
27fa270b42 | ||
|
|
15ece75b5d | ||
|
|
a796621f93 | ||
|
|
3c943c6685 | ||
|
|
4209774b4e | ||
|
|
b18637f7d0 | ||
|
|
af8a848d14 | ||
|
|
01e392158d | ||
|
|
fc47b7aa0d | ||
|
|
a0e0627a49 | ||
|
|
efcb0c0580 | ||
|
|
23d7105fb1 | ||
|
|
5d9565bd7c | ||
|
|
59785523ae | ||
|
|
2a21ed5fc7 | ||
|
|
3d3ce73fa1 | ||
|
|
c35bd385fe | ||
|
|
a790b04547 | ||
|
|
5171978c37 | ||
|
|
ea4a0c91e8 | ||
|
|
34af6dd447 | ||
|
|
ed2e700946 | ||
|
|
7eb23ab5e1 | ||
|
|
7cccf1d4e2 | ||
|
|
2a5545964c | ||
|
|
4ce22883cc | ||
|
|
272804afc8 | ||
|
|
dc0b50f717 | ||
|
|
a0eb625b8a | ||
|
|
524dc54d03 | ||
|
|
918718be90 | ||
|
|
78ee784be1 | ||
|
|
7e0e016bf9 | ||
|
|
4f875a03a0 | ||
|
|
63c56e0e98 | ||
|
|
46477208be | ||
|
|
3194c014c7 | ||
|
|
25ccb9dc43 | ||
|
|
fa46f8c39d | ||
|
|
8ffe5c3942 | ||
|
|
88f256cd8f | ||
|
|
1562600cd3 | ||
|
|
d759abbc47 | ||
|
|
90533138e5 | ||
|
|
80d8f0e5b6 | ||
|
|
9829fab97c | ||
|
|
a33c8b6eab | ||
|
|
f0921856c1 | ||
|
|
31e06ac0e0 | ||
|
|
033d764b1c | ||
|
|
00f98dd14e | ||
|
|
0f601d969a | ||
|
|
8fa0fb37b2 | ||
|
|
5a58d17d99 | ||
|
|
982958a4c6 | ||
|
|
d425884bb8 | ||
|
|
d3b61a0df1 | ||
|
|
4bab0162ba | ||
|
|
d3f4437478 | ||
|
|
a64586c3e6 | ||
|
|
7a92e78851 | ||
|
|
af0122b21a | ||
|
|
1f95f57e97 | ||
|
|
f384e95e44 | ||
|
|
a40521f07b | ||
|
|
9649b36175 | ||
|
|
6cb1394793 | ||
|
|
e5b2977c0c | ||
|
|
22d3f25dc4 | ||
|
|
d9534fcc4f | ||
|
|
fd1604c3a4 | ||
|
|
8f0f8d64df | ||
|
|
5a413ab910 | ||
|
|
d3133f055c | ||
|
|
fe05518e31 | ||
|
|
8adcb7d850 | ||
|
|
be383f2b48 | ||
|
|
682307b51d | ||
|
|
60328613ea | ||
|
|
4a2e054ac6 | ||
|
|
eebc428f1b | ||
|
|
ab8ba66eb5 | ||
|
|
97b3050270 | ||
|
|
6733f76fbf | ||
|
|
1dcc45585d | ||
|
|
0c5ceaa3f7 | ||
|
|
2e602d49a2 | ||
|
|
84bcdf8bee | ||
|
|
6d60bcf6eb | ||
|
|
b832a51a5b | ||
|
|
dd4c07cbf9 | ||
|
|
6a86de3e1e | ||
|
|
ff8c649c6a | ||
|
|
ae34e124a7 | ||
|
|
5d084ffc30 | ||
|
|
b0a9cf848e | ||
|
|
37e06efa43 | ||
|
|
3a6ad7d762 | ||
|
|
2846b358f4 | ||
|
|
8b3c22cc7f | ||
|
|
ee7fc3eddd | ||
|
|
639ccdf83e | ||
|
|
2b901c473b | ||
|
|
b419079734 | ||
|
|
5c4d37cce4 | ||
|
|
7b5f701f8f | ||
|
|
0eca97bf18 | ||
|
|
f620263fc6 | ||
|
|
4e299677bd | ||
|
|
b8655cff5e | ||
|
|
be452fee6d | ||
|
|
90589dd075 | ||
|
|
9c5b48c037 | ||
|
|
4406709920 | ||
|
|
b7ba0f8909 | ||
|
|
c28911c739 | ||
|
|
28088754ad | ||
|
|
9e1d491981 | ||
|
|
ab5caa4877 | ||
|
|
44b580ae78 | ||
|
|
3859eddc80 | ||
|
|
6098e1b42e | ||
|
|
6ad8d2f620 | ||
|
|
5b3f3a56ad | ||
|
|
f746b4f4ac | ||
|
|
3e4a3ace56 | ||
|
|
c72f6add40 | ||
|
|
6cfb125a38 | ||
|
|
c91e57e341 | ||
|
|
0ddd75e5fe | ||
|
|
382d4ca827 | ||
|
|
198e8f8cb7 | ||
|
|
d3baa74ce7 | ||
|
|
995bfe962e | ||
|
|
59255fd954 | ||
|
|
1e9bed9192 | ||
|
|
a747a6f698 | ||
|
|
b0d3976c27 | ||
|
|
7f77ab0743 | ||
|
|
79da8afa0b | ||
|
|
bb83523c0f | ||
|
|
f83c0a8458 | ||
|
|
7411d51477 | ||
|
|
55ce6456d8 | ||
|
|
da6619d55e | ||
|
|
6033c057c2 | ||
|
|
0efda1d6a6 | ||
|
|
59107f0c2a | ||
|
|
f7cd05f6c4 | ||
|
|
5cbd98e543 | ||
|
|
e2d5966ca3 | ||
|
|
dec2909db0 | ||
|
|
7233d1e037 | ||
|
|
5972f83369 | ||
|
|
0edfd7622c | ||
|
|
8f14f97007 | ||
|
|
758585a4c2 | ||
|
|
854eafaf91 | ||
|
|
ee89b80ce1 | ||
|
|
3e6200ac7e | ||
|
|
ee9364b645 | ||
|
|
5bbe66900e | ||
|
|
a775a858c7 | ||
|
|
2dab801ff5 | ||
|
|
07f8a87580 | ||
|
|
91be6e2a2f | ||
|
|
5c709588dd | ||
|
|
19a46e5b11 | ||
|
|
e132d4a9fc | ||
|
|
cf2d9bea24 | ||
|
|
09cbffed1e | ||
|
|
368de8c1f4 | ||
|
|
7dcf9173c2 | ||
|
|
eac312c3a2 | ||
|
|
7a420a9d2d | ||
|
|
7cac94bf2f | ||
|
|
43e98db174 | ||
|
|
253575bf23 | ||
|
|
7a08ced65a | ||
|
|
5a64e1c75e | ||
|
|
fc0ac92dd3 | ||
|
|
4e2d7eb637 | ||
|
|
f8f280c7d5 | ||
|
|
00b87f99c0 | ||
|
|
0b5c74dde8 | ||
|
|
906b3bdf92 | ||
|
|
0c28e82212 | ||
|
|
beb4301f14 | ||
|
|
e96fe9c491 | ||
|
|
268680f494 | ||
|
|
a1512fce26 | ||
|
|
c2e79f3439 | ||
|
|
01780a2bf8 | ||
|
|
10e54eb03e | ||
|
|
2760a9966b | ||
|
|
a297dbbe52 | ||
|
|
74c0af2032 | ||
|
|
813c85accd | ||
|
|
c97d08c997 | ||
|
|
097d1bcd1b | ||
|
|
7c91186ed5 | ||
|
|
904bc7c994 | ||
|
|
9fd4ae2615 | ||
|
|
18fbb0934e | ||
|
|
3ae59c85d2 | ||
|
|
55db9b0ddb | ||
|
|
3cca2fedb0 | ||
|
|
a0682b8e3c | ||
|
|
da19ce1b84 | ||
|
|
2b1f504b5b | ||
|
|
d8f2776b40 | ||
|
|
2fd800e0a0 | ||
|
|
712402f7b1 | ||
|
|
b5c034ed92 | ||
|
|
d2805e7a8a | ||
|
|
4011b1c89a | ||
|
|
5bc348611c | ||
|
|
dd24affdbb | ||
|
|
d8542824a1 | ||
|
|
c6bf24ed60 | ||
|
|
a910550e34 | ||
|
|
01e53471d7 | ||
|
|
5569cff20e | ||
|
|
757c12c386 | ||
|
|
4cfe6cecda | ||
|
|
a34fbad038 | ||
|
|
6138ef03e0 | ||
|
|
9eb2821c9b | ||
|
|
628bd7bdb2 | ||
|
|
a3914da4ff | ||
|
|
6a1e7f08f4 | ||
|
|
15b400a3d9 | ||
|
|
e447cc3b67 | ||
|
|
8240c7e240 | ||
|
|
6f020e9574 | ||
|
|
c9d5f74ed4 | ||
|
|
78034f6dea | ||
|
|
b81cb52614 | ||
|
|
56280cd893 | ||
|
|
e515586e6b | ||
|
|
424af4c60d | ||
|
|
0a7048aca1 | ||
|
|
dd812e0684 | ||
|
|
51b7aebbc3 | ||
|
|
01b1698934 | ||
|
|
1025054bf4 | ||
|
|
06b4986997 | ||
|
|
31716ebcbc | ||
|
|
2e1f28f67e | ||
|
|
7f2e2b2d45 | ||
|
|
b961435e01 | ||
|
|
c54fab9603 | ||
|
|
cc6832afd6 | ||
|
|
29c41cb45a | ||
|
|
c18984a26b | ||
|
|
23d1ad0da6 | ||
|
|
49173dc766 | ||
|
|
03a563856d | ||
|
|
c3809c409d | ||
|
|
dfdca90ca5 | ||
|
|
6a8e1735db | ||
|
|
c0e9a0553e | ||
|
|
e1501165d9 | ||
|
|
3b0f706059 | ||
|
|
7d19662f68 | ||
|
|
5c949dc71c | ||
|
|
0439d67a0c | ||
|
|
d3446a20b1 | ||
|
|
5b37dc2e38 | ||
|
|
eee264918e | ||
|
|
89172a88f1 | ||
|
|
ffdb054291 | ||
|
|
200d39c408 | ||
|
|
4306574ace | ||
|
|
12e3b90458 | ||
|
|
03364b5d2e | ||
|
|
4e268991dc | ||
|
|
429c84f940 | ||
|
|
e890e4489b | ||
|
|
8466c42217 | ||
|
|
353732f597 | ||
|
|
5599d2507f | ||
|
|
70cf6ffe70 | ||
|
|
61c9277097 | ||
|
|
401052efd3 | ||
|
|
a57a0e797d | ||
|
|
8f48853e2c | ||
|
|
a62148dc07 | ||
|
|
3ae890bd86 | ||
|
|
65a4cd4ba5 | ||
|
|
f63b473bc1 | ||
|
|
859a5ba03a | ||
|
|
832b97b179 | ||
|
|
e98d688d36 | ||
|
|
39318337fe | ||
|
|
f21215be84 | ||
|
|
0690525af8 | ||
|
|
b3176425c5 | ||
|
|
9f2c18b6b6 | ||
|
|
d529a04f48 | ||
|
|
8786c5aa99 | ||
|
|
013279ab60 | ||
|
|
06193b6d49 | ||
|
|
ac6f4af5d6 | ||
|
|
bf148adc68 | ||
|
|
0f9dafb01d | ||
|
|
9fc0452b70 | ||
|
|
83eda9b3f5 | ||
|
|
9bfbf47963 | ||
|
|
252bf411b1 | ||
|
|
5622c019dd | ||
|
|
b32fab7865 | ||
|
|
cafdad1f7a | ||
|
|
9da40944ab | ||
|
|
f678203a64 | ||
|
|
a9572e08e9 | ||
|
|
ee9b042cdf | ||
|
|
bc138fa78a | ||
|
|
67dbe256f7 | ||
|
|
8b066d46e2 | ||
|
|
1769a65a82 | ||
|
|
941eb56769 | ||
|
|
a317613ef4 | ||
|
|
173571846f | ||
|
|
ab1078d393 | ||
|
|
681321a595 | ||
|
|
fcd50d4bc2 | ||
|
|
7e214e5aaa | ||
|
|
de39053857 | ||
|
|
f543e3218e | ||
|
|
e668aea214 | ||
|
|
d810daa735 | ||
|
|
b94b3118eb | ||
|
|
06cbd0c92d | ||
|
|
96ebbbf11d | ||
|
|
fc1467b05b | ||
|
|
53c27f2a59 | ||
|
|
db80f5c715 | ||
|
|
405c98ca50 | ||
|
|
4892aed9e6 | ||
|
|
1b04b94db2 | ||
|
|
4a430f5fe7 | ||
|
|
325bfd825f | ||
|
|
471553f913 | ||
|
|
a43d0689d8 | ||
|
|
afacb8a94b | ||
|
|
afe5300e00 | ||
|
|
ef85d0e323 | ||
|
|
d3aeedb9f6 | ||
|
|
7718f69269 | ||
|
|
af50b0c5c6 | ||
|
|
b576faad82 | ||
|
|
4583e603e9 | ||
|
|
7ee316a605 | ||
|
|
7dca225691 | ||
|
|
8a27d0240a | ||
|
|
939bd6fd91 | ||
|
|
dfbd385de7 | ||
|
|
0d791070dd | ||
|
|
94fbac38bf | ||
|
|
73cf8e75d3 | ||
|
|
395cbc104c | ||
|
|
9a24db8379 | ||
|
|
934a5f4838 | ||
|
|
9022500087 | ||
|
|
795807b6cf | ||
|
|
9eff79733c | ||
|
|
c4e95d9207 | ||
|
|
32cd3a62b6 | ||
|
|
a5771625df | ||
|
|
d05ccc0055 | ||
|
|
ff1d7b44b4 | ||
|
|
2b86ba2128 | ||
|
|
44a3b30e3b | ||
|
|
bb9389c7dd | ||
|
|
ba4bfe9de7 | ||
|
|
3a73b14ebb | ||
|
|
31f54db433 | ||
|
|
26812dd297 | ||
|
|
ae4f4b4f08 | ||
|
|
4ac0a4c565 | ||
|
|
69c9f824a0 | ||
|
|
6a2220c960 | ||
|
|
aa501c2843 | ||
|
|
efce44f0a7 | ||
|
|
491eb83d35 | ||
|
|
35cf0802d1 | ||
|
|
f768548f60 | ||
|
|
37789f9907 | ||
|
|
131294464e | ||
|
|
b7652a41f8 | ||
|
|
91c5f85ec6 | ||
|
|
985983b31d | ||
|
|
9a27e38ce2 | ||
|
|
0017ed7c92 | ||
|
|
d5cf4ace21 | ||
|
|
1c899746fd | ||
|
|
9ea09c0fdd | ||
|
|
cda674c289 | ||
|
|
ef7d7ccc91 | ||
|
|
21aa5eb2d6 | ||
|
|
e725fb9b65 | ||
|
|
fbd634bfce | ||
|
|
9a686f3827 | ||
|
|
999219a0c9 | ||
|
|
65fd370cc5 | ||
|
|
232f0c38fa | ||
|
|
fa03968508 | ||
|
|
78dace32d4 | ||
|
|
a21e7aa0c5 | ||
|
|
9b7d828209 | ||
|
|
a1071426c0 | ||
|
|
23baf21ef5 | ||
|
|
d280b33073 | ||
|
|
d1ab6bb7a1 | ||
|
|
146d04ea64 | ||
|
|
fd46a3f8ac | ||
|
|
9974ca1e2e | ||
|
|
2c8a733359 | ||
|
|
4c9eeb9a61 | ||
|
|
de23be8c2d | ||
|
|
bb25a1fde9 | ||
|
|
9267c27bc5 | ||
|
|
591f073413 | ||
|
|
9c28c1ee00 | ||
|
|
120d41ea2f | ||
|
|
80b24a45ad | ||
|
|
e8db9cbff6 | ||
|
|
5db4f8dd95 | ||
|
|
820b2ff6c4 | ||
|
|
596102fb68 | ||
|
|
fa5c63b224 | ||
|
|
aa66b8f716 | ||
|
|
c06cdfcfa0 | ||
|
|
e6943cf7f5 | ||
|
|
b3a2f067ab | ||
|
|
35407cf13d | ||
|
|
d671faf712 | ||
|
|
815ad559ac | ||
|
|
d2cf594756 | ||
|
|
6709f6cf87 | ||
|
|
f463f79222 | ||
|
|
51cf3a9219 | ||
|
|
8700405af8 | ||
|
|
d1d082b4f9 | ||
|
|
6dd9d1a056 | ||
|
|
46b03725e9 | ||
|
|
65d6577b28 | ||
|
|
97967f5b70 | ||
|
|
9323e1fad4 | ||
|
|
3e4e741b54 | ||
|
|
4e2d8374e6 | ||
|
|
2b3037402a | ||
|
|
bc67c27a82 | ||
|
|
ffb8f6f00f | ||
|
|
d179dfe703 | ||
|
|
5701020901 | ||
|
|
1f2d795b58 | ||
|
|
c123b3ef51 | ||
|
|
d565c7e9e9 | ||
|
|
710a40c36b | ||
|
|
64f9a5dd7d | ||
|
|
323fe33c2f | ||
|
|
2470f6f531 | ||
|
|
42968d8299 | ||
|
|
7a50b6c77e | ||
|
|
0a10d5fbc9 | ||
|
|
40d2345501 | ||
|
|
ab97ae5ebc | ||
|
|
7c93e90fc0 | ||
|
|
d44cf3306b | ||
|
|
324609999f | ||
|
|
3f54b851ae | ||
|
|
8bbb04b421 | ||
|
|
dc396c8707 | ||
|
|
52cc5d3aa7 | ||
|
|
87b6335905 | ||
|
|
17358f16c8 | ||
|
|
23eb268031 | ||
|
|
27f4cb248d | ||
|
|
bbaf4f7a34 | ||
|
|
559455bf5b | ||
|
|
bd519aff08 | ||
|
|
febeb787b5 | ||
|
|
9f8a9bfa8a | ||
|
|
8b1daed0ef | ||
|
|
44c828c7e7 | ||
|
|
afabeaa2f3 | ||
|
|
e72c1676c2 | ||
|
|
5a17eb7054 | ||
|
|
75d52c07b8 | ||
|
|
4dc6c17486 | ||
|
|
e780930799 | ||
|
|
49cd6a36a1 | ||
|
|
d4830983e2 | ||
|
|
a69fefffdc | ||
|
|
1d0466dae7 | ||
|
|
6e5a853d0f | ||
|
|
0c702ddf7b | ||
|
|
fdbffce1f9 | ||
|
|
2872b4e3ce | ||
|
|
0ba55e51e9 | ||
|
|
5887bf377d | ||
|
|
c440dd9cf0 | ||
|
|
21bc1f7fa6 | ||
|
|
4279b13554 | ||
|
|
0e106b7c7b | ||
|
|
4d7d1fba3a | ||
|
|
a35ea5e9da | ||
|
|
48466f624d | ||
|
|
f306b20449 | ||
|
|
fc4fd685ba | ||
|
|
7449df6ac6 | ||
|
|
1390333c4c | ||
|
|
a9f545a1b2 | ||
|
|
f80a96c703 | ||
|
|
f291c15bbc | ||
|
|
18821e1a67 | ||
|
|
5dd65d691c | ||
|
|
8f96dbc21d | ||
|
|
f71623f8a1 | ||
|
|
b380420cac | ||
|
|
21cccd4475 | ||
|
|
06475aea78 | ||
|
|
84af0c2d5c | ||
|
|
84648f5a56 | ||
|
|
60b7988860 | ||
|
|
732b7ad424 | ||
|
|
a664c34418 | ||
|
|
eaf3b7f7d7 | ||
|
|
03edbaf545 | ||
|
|
c3edf23023 | ||
|
|
5f765609f9 | ||
|
|
3c1beac822 | ||
|
|
f30f66969c | ||
|
|
4e6fb48bf0 | ||
|
|
53225ba5a7 | ||
|
|
c04967d775 | ||
|
|
6bb7a3c0e5 | ||
|
|
2c85191671 | ||
|
|
637235eb9d | ||
|
|
13e4203c44 | ||
|
|
d04b628d55 | ||
|
|
2eab13661d | ||
|
|
6eefb49eb0 | ||
|
|
6878b1f969 | ||
|
|
0ba784564f | ||
|
|
62804cdc63 | ||
|
|
ff900b4b61 | ||
|
|
e34f03c0d1 | ||
|
|
2a9cf1cf6b | ||
|
|
d4159dbe75 | ||
|
|
7cd68304c3 | ||
|
|
0d7a76310c | ||
|
|
056be574ef | ||
|
|
f6e2886185 | ||
|
|
7b178ce2c8 | ||
|
|
e4d05ac284 | ||
|
|
5311f53612 | ||
|
|
f20ce396f0 | ||
|
|
996f1f79f1 | ||
|
|
cd58d1af06 | ||
|
|
9d9201b4d1 | ||
|
|
684b2f6268 | ||
|
|
de08f4584d | ||
|
|
a937b5d70a | ||
|
|
95b99edede | ||
|
|
cdf7591e0f | ||
|
|
f373867356 | ||
|
|
041efcab74 | ||
|
|
e1fe3eeaab | ||
|
|
3793148c77 | ||
|
|
5dbfeb085e | ||
|
|
f79181c76a | ||
|
|
c0df46cb7b | ||
|
|
aa7dcf7604 | ||
|
|
fe4a39afc5 | ||
|
|
4185192954 | ||
|
|
3a9ee63c97 | ||
|
|
d2d2537867 | ||
|
|
97fe819737 | ||
|
|
9fdca28579 | ||
|
|
261e093700 | ||
|
|
07a651c2c8 | ||
|
|
6c0a1f9a4d | ||
|
|
9d941a4e44 | ||
|
|
cbb8f676af | ||
|
|
3bcf460ce4 | ||
|
|
23dd4883e3 | ||
|
|
ce2e0fd408 | ||
|
|
9438031b4a | ||
|
|
d5e584c1f0 | ||
|
|
8624671c4c | ||
|
|
88094c056c | ||
|
|
fa918e1c76 | ||
|
|
d89d35e420 | ||
|
|
ddcfddd698 | ||
|
|
bdce2477c3 | ||
|
|
83aa04396c | ||
|
|
c9c5468fe4 | ||
|
|
4d6ec72717 | ||
|
|
b8ce29214f | ||
|
|
66197e81b3 | ||
|
|
d925ece80a | ||
|
|
8b3c61ae24 | ||
|
|
3f0086359a | ||
|
|
9a807e4f8a | ||
|
|
2eb5fc476c | ||
|
|
bb2d30f9e3 | ||
|
|
71582220ee | ||
|
|
cfc872f3f1 | ||
|
|
d914bd0678 | ||
|
|
a5fdf6efbb | ||
|
|
02b1f035d3 | ||
|
|
395fde7982 | ||
|
|
8edab82308 | ||
|
|
d483ac55b5 | ||
|
|
982f206ca4 | ||
|
|
1a9f56bb09 | ||
|
|
8ff312b8e4 | ||
|
|
d92349925a | ||
|
|
d8cd929ebe | ||
|
|
58d8780ac8 | ||
|
|
d3a0e43a2b | ||
|
|
0f5744eb43 | ||
|
|
85386c6b9b | ||
|
|
f708bf14fc | ||
|
|
64388096b8 | ||
|
|
ee92f91b86 | ||
|
|
d82815c56a | ||
|
|
1d6005f3c5 | ||
|
|
a6ec0ceab5 | ||
|
|
65ecd8556f | ||
|
|
9067f2b79a | ||
|
|
159166d03e | ||
|
|
b869bd6861 | ||
|
|
de5b8b64a6 | ||
|
|
ea01c73e57 | ||
|
|
4f726cbcd0 | ||
|
|
2f77988473 | ||
|
|
d00247029b | ||
|
|
1692d07b37 | ||
|
|
24a2d39e63 | ||
|
|
a9847ec864 | ||
|
|
81fc788adc | ||
|
|
834343f821 | ||
|
|
6b4f9fddae | ||
|
|
791f98309d | ||
|
|
fa86ef1136 | ||
|
|
bf20919552 | ||
|
|
5931be2aa4 | ||
|
|
ef20226ace | ||
|
|
fdec83d3a4 | ||
|
|
90b1bcbc3b | ||
|
|
c3650fd0ff | ||
|
|
ba8c2a7995 | ||
|
|
1a0783b56a | ||
|
|
e9bce326f9 | ||
|
|
0956f41b92 | ||
|
|
25473770c6 | ||
|
|
81c5a2cca1 | ||
|
|
90bc310643 | ||
|
|
b8ab8e1084 | ||
|
|
cc7d3d894c | ||
|
|
8d04ac01a1 | ||
|
|
81ddbec324 | ||
|
|
35bc366f10 | ||
|
|
9aee982e8e | ||
|
|
5638f91b25 | ||
|
|
443fd0eae3 | ||
|
|
454db1f315 | ||
|
|
c3440e2b54 | ||
|
|
0b51636d8a | ||
|
|
f52b011817 | ||
|
|
7b76acd9c9 | ||
|
|
2de1ba1f45 | ||
|
|
5e702499b0 | ||
|
|
79d67bc1f4 | ||
|
|
9fca82bb6f | ||
|
|
00c801e338 | ||
|
|
dd0c0cd021 | ||
|
|
12594baac6 | ||
|
|
b03bd7e4f9 | ||
|
|
02b21aeea9 | ||
|
|
a67bdfa5e8 | ||
|
|
52407e89fb | ||
|
|
7e930c2339 | ||
|
|
7ab8f07d1f | ||
|
|
d34086a395 | ||
|
|
334f122cca | ||
|
|
f80202e5e7 | ||
|
|
29736f10fc | ||
|
|
0654663dff | ||
|
|
4e12f7cc4c | ||
|
|
a42dbc0cdc | ||
|
|
5c40cdb3d3 | ||
|
|
d47a206206 | ||
|
|
ba0eaf067b | ||
|
|
f80edce3dc | ||
|
|
21968214af | ||
|
|
7770eb51dc | ||
|
|
d0229259a6 | ||
|
|
00cbea3705 | ||
|
|
e85857c29f | ||
|
|
1704a016b1 | ||
|
|
f5af19557a | ||
|
|
17b8b154c2 | ||
|
|
5c1030880a | ||
|
|
1b62983016 | ||
|
|
52fb7ab546 | ||
|
|
604bfbf23f | ||
|
|
3c1a3c18c2 | ||
|
|
f531c361de | ||
|
|
4609ea33bb | ||
|
|
41b1a170f7 | ||
|
|
e6d39eca75 | ||
|
|
2a1e3731ba | ||
|
|
8ca6a9fe96 | ||
|
|
6f2248ffa0 | ||
|
|
48e47f333e | ||
|
|
3091ed629a | ||
|
|
a9193dd695 | ||
|
|
3122e86e22 | ||
|
|
a6efe27146 | ||
|
|
adbec35e30 | ||
|
|
205a94d3a3 | ||
|
|
6e88c8f0eb | ||
|
|
32a05322d0 | ||
|
|
8738b74236 | ||
|
|
aa0ddd85fd | ||
|
|
bcd47ddb8e | ||
|
|
50f24b42cb | ||
|
|
0a5d511c96 | ||
|
|
70d93602f7 | ||
|
|
68c7c9f55e | ||
|
|
42f1fa88b9 | ||
|
|
3a2d064024 | ||
|
|
38cfdd4e0e | ||
|
|
fb93c0c352 | ||
|
|
f4fb1e3cc8 | ||
|
|
5c11e5733e | ||
|
|
8d8f7a7866 | ||
|
|
da89e32213 | ||
|
|
b6d36e5076 | ||
|
|
90c377f125 | ||
|
|
df85138890 | ||
|
|
654b656a2f | ||
|
|
1d22dcb488 | ||
|
|
a42e907d0c | ||
|
|
353cad21d6 | ||
|
|
2b02f186a6 | ||
|
|
3e12d1e815 | ||
|
|
539bbdf07f | ||
|
|
b993b358fe | ||
|
|
0639ea5969 | ||
|
|
05b7bc6029 | ||
|
|
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 | ||
|
|
8834762004 | ||
|
|
48477c7ee9 | ||
|
|
f0f65fb9a3 | ||
|
|
26e12e8cec | ||
|
|
fa2fe5e462 | ||
|
|
83a70828ae | ||
|
|
b2e246bdf4 | ||
|
|
fd0f39c214 | ||
|
|
2862fbc983 | ||
|
|
5f42ed8f8d | ||
|
|
afe01bf660 | ||
|
|
646b63e3dd | ||
|
|
e0266c6731 | ||
|
|
d577c3d121 | ||
|
|
d6f2303160 | ||
|
|
9625b624d1 | ||
|
|
c330415ca8 | ||
|
|
e52c4c4403 | ||
|
|
d5c6ce5c33 | ||
|
|
0a3d49408a | ||
|
|
4b3c5e9859 | ||
|
|
1bbb785ce8 | ||
|
|
cef882642e | ||
|
|
560807285f | ||
|
|
a2f6801e5f | ||
|
|
1ca8e48278 | ||
|
|
c7acb45f85 | ||
|
|
902eda0d79 | ||
|
|
0141790985 | ||
|
|
7b98a48f5b | ||
|
|
f4bdc56d71 | ||
|
|
83eac25e6d | ||
|
|
dd144bd173 | ||
|
|
ce30c0db0b | ||
|
|
fe9a9d6aa2 | ||
|
|
58ed3f8e0a | ||
|
|
e5f04faa6e | ||
|
|
9753613ae2 | ||
|
|
3736c2ca5a | ||
|
|
083fdead73 | ||
|
|
7a2509911b | ||
|
|
d5e01a8c23 | ||
|
|
a25eebfa28 | ||
|
|
1aa092fcc4 | ||
|
|
23e6e2e33f | ||
|
|
e93684a555 | ||
|
|
226b7477a9 | ||
|
|
a8d9931477 | ||
|
|
d4e1737758 | ||
|
|
94adea8095 | ||
|
|
8492850d12 | ||
|
|
dc03fed415 | ||
|
|
2a0623cb93 | ||
|
|
ec4915e88c | ||
|
|
b60618c514 | ||
|
|
635930eccb | ||
|
|
654d12f2a1 | ||
|
|
51f7438fe7 | ||
|
|
13ed74bf73 | ||
|
|
2327b138eb | ||
|
|
87f91d5156 | ||
|
|
cbe6197782 | ||
|
|
5335dc0860 | ||
|
|
6096eefe06 | ||
|
|
18b755a937 | ||
|
|
8d9e62b621 | ||
|
|
5c303a5787 | ||
|
|
8b0c015359 | ||
|
|
8eee8ba69c | ||
|
|
70d0e0ec30 | ||
|
|
6c07235c9b | ||
|
|
62f4dddc8d | ||
|
|
61c6865ad2 | ||
|
|
a85b5f7a36 | ||
|
|
30350c6fec | ||
|
|
857f41ad07 | ||
|
|
b944b348fc | ||
|
|
196821371c | ||
|
|
746aa30ccc | ||
|
|
6ae5765691 | ||
|
|
538ecb959e | ||
|
|
51b96699f0 | ||
|
|
730d8ba675 | ||
|
|
71fbb3ecbe | ||
|
|
55ff6efb26 | ||
|
|
91da878e43 | ||
|
|
e547392dbe | ||
|
|
a6771c1c47 | ||
|
|
f6be4b096b | ||
|
|
90362b0fe2 | ||
|
|
7b917585d5 | ||
|
|
0d566e1998 | ||
|
|
b3f7ecfb8f | ||
|
|
d8e11f6068 | ||
|
|
f3c0808f7f | ||
|
|
043999417c | ||
|
|
ab4ebd1009 | ||
|
|
945411fffc | ||
|
|
ce8792815c | ||
|
|
447001554c | ||
|
|
09812c21d5 | ||
|
|
be2321191f | ||
|
|
be5a9a9c94 | ||
|
|
49940777ed | ||
|
|
211f6af563 | ||
|
|
658c04401e | ||
|
|
9c5331719b | ||
|
|
4be8adcc3e | ||
|
|
8434825706 | ||
|
|
1ca87741a5 | ||
|
|
463eb1d228 | ||
|
|
935febf337 | ||
|
|
e4c7fe7fc9 | ||
|
|
e98b1755ee | ||
|
|
bc71bde9b7 | ||
|
|
2dc10af004 | ||
|
|
46d21f53e5 | ||
|
|
44d9b44c88 | ||
|
|
5875f268f4 | ||
|
|
bc1120ac3a | ||
|
|
40a10620c1 | ||
|
|
28295deaa0 | ||
|
|
b783d9b992 | ||
|
|
98df940f52 | ||
|
|
ab3b84a765 | ||
|
|
5fc6905ac7 | ||
|
|
00c7a0e934 | ||
|
|
60ed7f21f6 | ||
|
|
9e0c5c48d4 | ||
|
|
7e76c2b693 | ||
|
|
dd9b363427 | ||
|
|
90b693151a | ||
|
|
d280c7e953 | ||
|
|
b227ad05fd | ||
|
|
cf07458fbb | ||
|
|
c191b7264d | ||
|
|
109fe05302 | ||
|
|
d55bb1a2c4 | ||
|
|
1362c7f416 | ||
|
|
dc718bbfe1 | ||
|
|
3ab2a3d7fc | ||
|
|
494556b501 | ||
|
|
76b767f505 | ||
|
|
8178328ce8 | ||
|
|
766bf25773 | ||
|
|
ccf81efa7b | ||
|
|
4e101f8786 | ||
|
|
05a7ee8270 | ||
|
|
0e5004ae08 | ||
|
|
77f103d46e | ||
|
|
e2ad92a19c | ||
|
|
0eb3bc6798 | ||
|
|
b11cf139a8 | ||
|
|
81ce31dfbf |
17
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "Node.js 20",
|
||||
"image": "mcr.microsoft.com/devcontainers/javascript-node:20",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
"version": "20"
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "npm install",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"ms-vscode.vscode-typescript-next"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
50
.github/ISSUE_TEMPLATE/Contribution.yml.old
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
name: Contribution Request
|
||||
|
||||
description: Request access to contribute to the Excalidraw plugin documentation on the wiki
|
||||
|
||||
title: '[Contribution] Request to Contribute to Wiki'
|
||||
|
||||
labels: [collaboration-request]
|
||||
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Contribution Request
|
||||
|
||||
Thank you for your interest in contributing to the Excalidraw Plugin wiki! To help me understand how you’d like to contribute, please provide the following details:
|
||||
|
||||
1. **Contribution Area**: Describe what areas of the wiki you’re interested in contributing to (e.g., fixing typos, adding new tutorials, improving existing content).
|
||||
2. **Experience**: Briefly describe your experience with Excalidraw or Obsidian and any relevant background that will help with the contribution.
|
||||
3. **Additional Information**: Any other information or questions you may have.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
- Contribution Area: Adding a tutorial on advanced Excalidraw features
|
||||
- Experience: Regular user of Excalidraw and experienced in creating tutorials
|
||||
- Additional Information: Looking forward to contributing!
|
||||
```
|
||||
|
||||
Once I review your request, I will get back to you with instructions on how to proceed. Thank you for helping improve our documentation!
|
||||
|
||||
---
|
||||
Zsolt
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Contribution Details
|
||||
description: Provide details about your contribution request.
|
||||
placeholder: |
|
||||
- Contribution Area: Adding a tutorial on advanced Excalidraw features
|
||||
- Experience: Regular user of Excalidraw and experienced in creating tutorials
|
||||
- Additional Information: Looking forward to contributing!
|
||||
|
||||
- type: checkboxes
|
||||
id: verify_guidelines
|
||||
attributes:
|
||||
label: Please read the WIKI Contributors Guidelines before submitting your request!
|
||||
options:
|
||||
- label: Yes, I have read and understood the [Contributors Guidelines](https://github.com/zsviczian/obsidian-excalidraw-plugin/wiki/Contributor-Guidelines)
|
||||
|
||||
77
.github/ISSUE_TEMPLATE/How-to.yml
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
name: How to? Support request
|
||||
description: Ask for help with using the plugin or understanding its features.
|
||||
title: "SUPPORT: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
ℹ️ **Important: Please Read Before Submitting a Support Request** ℹ️
|
||||
|
||||
I am a one-person team working on this plugin as a part-time hobby. Please help me manage the workload by following these guidelines. **Support requests that don't include enough details may be closed without review**.
|
||||
|
||||
Before submitting a support request, please:
|
||||
1. **Review the [documentation](https://github.com/zsviczian/obsidian-excalidraw-plugin/wiki)** – your question may already be answered.
|
||||
2. **[Search issues](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues) (including closed ones)** to see if your question has already been addressed.
|
||||
3. **[Watch the Feature Walkthrough Video](https://youtu.be/P_Q6avJGoWI)**: As it infact answers 90% of the typical questions I receive
|
||||
4. **[Consult NotebookLM with your question](https://excalidraw-obsidian.online/WIKI/09+Video+Transcripts/Videos/Turn+any+YouTube+Channel+into+your+AI+Mentor+-+Obsidian+is+the+ultimate+automation+workbench+for+PKM)**
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please help by providing the following details. Requests without this information may be closed without review.
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
---
|
||||
|
||||
- type: checkboxes
|
||||
id: search_existing_resources
|
||||
attributes:
|
||||
label: Have you checked the documentation and searched existing issues?
|
||||
description: Please confirm that you've reviewed available resources before submitting your request.
|
||||
options:
|
||||
- label: Yes, I have reviewed the documentation and searched for related issues.
|
||||
|
||||
- type: textarea
|
||||
id: notebook_lm
|
||||
attributes:
|
||||
label: "Your NotebookLM query"
|
||||
description: "See point 4) above. Paste the question and answer you received from NotebookLM. This serves partly as proof, partly to help me see where the model is incorrect"
|
||||
placeholder: "Copy/Paste your question and the resulting answer you got from NotebookLM"
|
||||
|
||||
- type: textarea
|
||||
id: support_question
|
||||
attributes:
|
||||
label: "Your question"
|
||||
description: "Provide a clear and concise description of the question or issue you need help with."
|
||||
placeholder: "Describe your question or the problem you are trying to solve..."
|
||||
|
||||
- type: textarea
|
||||
id: steps_tried
|
||||
attributes:
|
||||
label: "Steps you've already tried"
|
||||
description: "List any steps you've taken to try to resolve or understand the issue."
|
||||
placeholder: |
|
||||
1. Tried reading the documentation.
|
||||
2. Searched the issues for similar questions.
|
||||
|
||||
- type: textarea
|
||||
id: expected_outcome
|
||||
attributes:
|
||||
label: "Expected outcome"
|
||||
description: "Describe what you expected to happen or what you are trying to achieve."
|
||||
placeholder: "Describe the result you are aiming for..."
|
||||
|
||||
- type: textarea
|
||||
id: additional_context
|
||||
attributes:
|
||||
label: "Additional context"
|
||||
description: "Add any other context or details that may help."
|
||||
placeholder: "Include any other information that may be relevant..."
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Attachments: Screenshots and files are critical!**
|
||||
A picture speaks a thousand words, and a screen recording even more. **Please attach screenshots, screen recordings, or sample files** to help illustrate your question or issue. Drag and drop them into the comment area or directly into any of the text fields above.
|
||||
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,38 +0,0 @@
|
||||
---
|
||||
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.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
40
.github/ISSUE_TEMPLATE/bug_report.md.x
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: When something is clearly broken. Everything else is a feature request.
|
||||
title: 'BUG: '
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Help me help you. I am a one man show doing this plugin as a part time hobby. There is no point in flooding me with issues, if there are too many, and they are poorly documented, I will just ignore them. Sorry...
|
||||
|
||||
Before creating a bug report, please
|
||||
1. review recent release notes - maybe there is already an answer,
|
||||
2. search issues (including closed ones) to see if there is anything similar.
|
||||
|
||||
⚠️ I will have to close all recorded bugs that do not provide this background information. Sorry, I need to control my workload/time. ⚠️
|
||||
|
||||
--------
|
||||
|
||||
**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.
|
||||
94
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
name: Bug report
|
||||
description: If something is clearly broken, it’s a bug. **Everything else** is a feature or support request. Most reported “bugs” are actually how-to questions or feature requests.
|
||||
title: "BUG: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
⚠️ **Important: Please Read Before Submitting a Bug Report** ⚠️
|
||||
|
||||
I am a one-person team working on this plugin as a part-time hobby. I cannot handle a flood of poorly documented issues. **To ensure your report is considered, you must follow these guidelines**. If you don't, I will close the issue without review.
|
||||
|
||||
Before creating a bug report, please:
|
||||
1. **Review recent [release notes](https://github.com/zsviczian/obsidian-excalidraw-plugin/releases)** – maybe there is already an answer.
|
||||
2. **[Search issues](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues) (including closed ones)** to see if there is anything similar.
|
||||
3. **[Watch the Feature Walkthrough Video](https://youtu.be/P_Q6avJGoWI)**: As it infact answers 90% of the typical questions I receive
|
||||
4. **[Consult NotebookLM with your question](https://excalidraw-obsidian.online/WIKI/09+Video+Transcripts/Videos/Turn+any+YouTube+Channel+into+your+AI+Mentor+-+Obsidian+is+the+ultimate+automation+workbench+for+PKM)** Here's the [direct link to a preloaded NotebookLM](https://notebooklm.google.com/notebook/42d76a2f-c11d-4002-9286-1683c43d0ab0)
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please help by providing the following details. Bugs reported without the required information may be closed without review.
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
---
|
||||
|
||||
- type: checkboxes
|
||||
id: search_existing_issues
|
||||
attributes:
|
||||
label: Have you searched for existing issues (including closed ones)?
|
||||
description: Please confirm that you have searched the issue tracker before reporting a new issue.
|
||||
options:
|
||||
- label: Yes, I have searched the existing issues.
|
||||
|
||||
- type: checkboxes
|
||||
id: verify_bug
|
||||
attributes:
|
||||
label: Does this bug persist in a new vault with only Excalidraw installed?
|
||||
description: Please confirm that you have tested this issue in an empty Obsidian vault with no other plugins or themes installed.
|
||||
options:
|
||||
- label: Yes, I have verified the issue persists.
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: "Your environment"
|
||||
description: "Run `Command Palette/Show Debug info` in Obsidian and paste the result here."
|
||||
placeholder: "Paste your Obsidian debug info here..."
|
||||
|
||||
- type: textarea
|
||||
id: notebook_lm
|
||||
attributes:
|
||||
label: "Your NotebookLM query"
|
||||
description: "See point 4) above. Paste the question and answer you received from NotebookLM. This serves partly as proof, partly to help me see where the model is incorrect"
|
||||
placeholder: "Copy/Paste your question and the resulting answer you got from NotebookLM"
|
||||
|
||||
- type: textarea
|
||||
id: bug_description
|
||||
attributes:
|
||||
label: "Describe the bug"
|
||||
description: "A clear and concise description of what the bug is."
|
||||
placeholder: "Provide a detailed description of the issue..."
|
||||
|
||||
- type: textarea
|
||||
id: steps_to_reproduce
|
||||
attributes:
|
||||
label: "Steps to reproduce"
|
||||
description: "List the steps to reproduce the behavior."
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. See error
|
||||
|
||||
- type: textarea
|
||||
id: expected_behavior
|
||||
attributes:
|
||||
label: "Expected behavior"
|
||||
description: "A clear and concise description of what you expected to happen."
|
||||
placeholder: "Describe what you expected to happen..."
|
||||
|
||||
- type: textarea
|
||||
id: additional_context
|
||||
attributes:
|
||||
label: "Additional context"
|
||||
description: "Add any other context about the problem here."
|
||||
placeholder: "Include any other information that may be helpful..."
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Attachments:**
|
||||
If applicable, please attach any screenshots, screen recordings, or files by dragging and dropping them into the comment area or directly into any of the text fields above.
|
||||
|
||||
69
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
name: Feature request
|
||||
description: Request a new feature for the Excalidraw plugin.
|
||||
title: "FR: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
🛠️ **Important: Please Read Before Submitting a Feature Request** 🛠️
|
||||
|
||||
I develop Excalidraw primarily as a hobby, and I prioritize features that I personally use regularly. Features I don't use often break without me noticing, which is why the plugin is as stable as it is—because I rely on it every day.
|
||||
|
||||
**Your task isn't just to describe the feature you want, but to sell me on the idea**. If I'm not convinced that the feature would significantly benefit my own workflow, it's unlikely I'll spend my free hobby time on it.
|
||||
|
||||
When creating your feature request:
|
||||
- **Provide real-life usage scenarios**: How will this feature help you? How do you imagine using it in practice?
|
||||
- **Sell the idea**: Convince me that I need this feature too.
|
||||
- **Include supporting materials**: Reference other solutions? Include relevant screenshots, screen recordings, and links. The more work I need to do to understand your request, the less likely it is to be implemented.
|
||||
|
||||
**Additional Guidelines:**
|
||||
- **Excalidraw Core Features**: If your request relates to core Excalidraw features, and not the Obsidian integration specifically, please raise it with the Excalidraw product team here: [Excalidraw Issues](https://github.com/excalidraw/excalidraw/issues).
|
||||
- **Cross-Platform Compatibility**: Obsidian and Excalidraw are cross-platform solutions. I cannot develop platform-specific features like Apple Pencil or Samsung S-Pen support due to technical limitations. Please only request features that make sense across all platforms (Windows, Linux, ChromeOS, macOS, Android, iOS).
|
||||
|
||||
Remember: You're not asking from a genie. You're pitching to someone who will need to spend hours (even for small changes) on testing, releasing, documenting, and supporting the feature. If you don't sell it well, it won't get done.
|
||||
|
||||
**Explore Scripting First:**
|
||||
Many feature requests can already be achieved with scripts using Excalidraw Automate. While the documentation is somewhat dated, there are nearly a hundred published scripts available. With a little determination, you can explore the possibilities. Feeding relevant scripts into GPT can often generate a working solution. Start here: [Excalidraw Automate Documentation](https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html).
|
||||
|
||||
- type: textarea
|
||||
id: problem_description
|
||||
attributes:
|
||||
label: "Is your feature request related to a problem? Please describe."
|
||||
description: "Provide a clear and concise description of the problem. Ex. I'm always frustrated when..."
|
||||
placeholder: "Describe the problem you are facing..."
|
||||
|
||||
- type: textarea
|
||||
id: solution_description
|
||||
attributes:
|
||||
label: "Describe the solution you'd like"
|
||||
description: "Provide a clear and concise description of what you want to happen."
|
||||
placeholder: "Describe the feature you are requesting..."
|
||||
|
||||
- type: textarea
|
||||
id: usage_scenario
|
||||
attributes:
|
||||
label: "Real-life usage scenarios"
|
||||
description: "Provide specific examples of how you would use this feature. Convince me that this is a feature I need in my own workflow."
|
||||
placeholder: |
|
||||
1. In this scenario, I would use the feature to...
|
||||
2. Another use case is when I...
|
||||
|
||||
- type: textarea
|
||||
id: alternatives_considered
|
||||
attributes:
|
||||
label: "Describe alternatives you've considered"
|
||||
description: "Provide a clear and concise description of any alternative solutions or features you've considered."
|
||||
placeholder: "Describe any alternative approaches you have considered..."
|
||||
|
||||
- type: textarea
|
||||
id: additional_context
|
||||
attributes:
|
||||
label: "Additional context"
|
||||
description: "Include any other context, screenshots, or references about the feature request."
|
||||
placeholder: "Include screenshots, recordings, or other supporting material..."
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Attachments: Make your case visually!**
|
||||
Supporting images, screenshots, or screen recordings are critical for helping me understand your request. Drag and drop them into the comment area or directly into any of the text fields above. Every bit of detail increases the chance of your request being understood and prioritized.
|
||||
@@ -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.
|
||||
7
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
target-branch: "master"
|
||||
11
.gitignore
vendored
@@ -4,7 +4,6 @@
|
||||
|
||||
# npm
|
||||
node_modules
|
||||
package-lock.json
|
||||
|
||||
# build
|
||||
main.js
|
||||
@@ -12,3 +11,13 @@ main.js
|
||||
stats.html
|
||||
hot-reload.bat
|
||||
data.json
|
||||
lib
|
||||
dist
|
||||
tmp
|
||||
|
||||
#VSCode
|
||||
.vscode
|
||||
yarn.lock
|
||||
.DS_Store
|
||||
.lock
|
||||
.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: {
|
||||
@@ -161,7 +161,7 @@ Number between 0 and 100. The opacity of an object, both stroke and fill.
|
||||
### strokeSharpness, setStrokeSharpness()
|
||||
```typescript
|
||||
type StrokeSharpness = "round" | "sharp";
|
||||
setStrokeSharpness(val:nmuber);
|
||||
setStrokeSharpness(val:number);
|
||||
```
|
||||
strokeSharpness is a string.
|
||||
|
||||
@@ -195,7 +195,7 @@ This is relevant when setting a fix height using the `addText()` function.
|
||||
### startArrowHead, endArrowHead
|
||||
String. Valid values are "arrow", "bar", "dot", and "none". Specifies the beginning and ending of an arrow.
|
||||
|
||||
This is relavant when using the `addArrow()` and the `connectObjects()` functions.
|
||||
This is relevant when using the `addArrow()` and the `connectObjects()` functions.
|
||||
|
||||
## canvas
|
||||
Sets the properties of the canvas.
|
||||
@@ -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});
|
||||
|
||||
110
MathjaxToSVG/index.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import {mathjax} from "mathjax-full/js/mathjax";
|
||||
import {TeX} from 'mathjax-full/js/input/tex.js';
|
||||
import {SVG} from 'mathjax-full/js/output/svg.js';
|
||||
import {LiteAdaptor, liteAdaptor} from 'mathjax-full/js/adaptors/liteAdaptor.js';
|
||||
import {RegisterHTMLHandler} from 'mathjax-full/js/handlers/html.js';
|
||||
import {AllPackages} from 'mathjax-full/js/input/tex/AllPackages.js';
|
||||
import { customAlphabet } from "nanoid";
|
||||
|
||||
type DataURL = string & { _brand: "DataURL" };
|
||||
type FileId = string & { _brand: "FileId" };
|
||||
const fileid = customAlphabet("1234567890abcdef", 40);
|
||||
|
||||
let adaptor: LiteAdaptor;
|
||||
let html: any;
|
||||
let preamble: string;
|
||||
|
||||
function svgToBase64(svg: string): string {
|
||||
const cleanSvg = svg.replaceAll(" ", " ");
|
||||
|
||||
// Convert the string to UTF-8 and handle non-Latin1 characters
|
||||
const encodedData = encodeURIComponent(cleanSvg)
|
||||
.replace(/%([0-9A-F]{2})/g,
|
||||
(match, p1) => String.fromCharCode(parseInt(p1, 16))
|
||||
);
|
||||
|
||||
return `data:image/svg+xml;base64,${btoa(encodedData)}`;
|
||||
}
|
||||
|
||||
async function getImageSize(src: string): Promise<{ height: number; width: number }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.onload = () => resolve({ height: img.naturalHeight, width: img.naturalWidth });
|
||||
img.onerror = reject;
|
||||
img.src = src;
|
||||
});
|
||||
}
|
||||
|
||||
export async function tex2dataURL(
|
||||
tex: string,
|
||||
scale: number = 4,
|
||||
plugin?: any
|
||||
): Promise<{
|
||||
mimeType: string;
|
||||
fileId: FileId;
|
||||
dataURL: DataURL;
|
||||
created: number;
|
||||
size: { height: number; width: number };
|
||||
}> {
|
||||
let input: TeX<unknown, unknown, unknown>;
|
||||
let output: SVG<unknown, unknown, unknown>;
|
||||
|
||||
if(!adaptor) {
|
||||
if (plugin) {
|
||||
const file = plugin.app.vault.getAbstractFileByPath(plugin.settings.latexPreambleLocation || "preamble.sty");
|
||||
preamble = file ? await plugin.app.vault.read(file) : null;
|
||||
}
|
||||
adaptor = liteAdaptor();
|
||||
RegisterHTMLHandler(adaptor);
|
||||
input = new TeX({
|
||||
packages: AllPackages,
|
||||
...(preamble ? {
|
||||
inlineMath: [['$', '$']],
|
||||
displayMath: [['$$', '$$']]
|
||||
} : {}),
|
||||
});
|
||||
output = new SVG({ fontCache: "local" });
|
||||
html = mathjax.document("", { InputJax: input, OutputJax: output });
|
||||
}
|
||||
|
||||
try {
|
||||
const node = html.convert(
|
||||
preamble ? `${preamble}\n${tex}` : tex,
|
||||
{ display: true, scale }
|
||||
);
|
||||
const svg = new DOMParser().parseFromString(adaptor.innerHTML(node), "image/svg+xml").firstChild as SVGSVGElement;
|
||||
|
||||
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/2195
|
||||
//https://stackoverflow.com/a/77181931
|
||||
let styleNode = document.createElement('style');
|
||||
styleNode.setAttribute("type", "text/css");
|
||||
styleNode.appendChild(document.createTextNode(".mjx-solid { stroke-width: 80px; }"));
|
||||
svg.appendChild(styleNode);
|
||||
|
||||
if (svg) {
|
||||
if(svg.width.baseVal.valueInSpecifiedUnits < 2) {
|
||||
svg.width.baseVal.valueAsString = `${(svg.width.baseVal.valueInSpecifiedUnits+1).toFixed(3)}ex`;
|
||||
}
|
||||
const img = svgToBase64(svg.outerHTML);
|
||||
svg.width.baseVal.valueAsString = (svg.width.baseVal.valueInSpecifiedUnits * 10).toFixed(3);
|
||||
svg.height.baseVal.valueAsString = (svg.height.baseVal.valueInSpecifiedUnits * 10).toFixed(3);
|
||||
const dataURL = svgToBase64(svg.outerHTML);
|
||||
return {
|
||||
mimeType: "image/svg+xml",
|
||||
fileId: fileid() as FileId,
|
||||
dataURL: dataURL as DataURL,
|
||||
created: Date.now(),
|
||||
size: await getImageSize(img),
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function clearMathJaxVariables(): void {
|
||||
adaptor = null;
|
||||
html = null;
|
||||
preamble = null;
|
||||
}
|
||||
1340
MathjaxToSVG/package-lock.json
generated
Normal file
24
MathjaxToSVG/package.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "@zsviczian/mathjax-to-svg",
|
||||
"version": "1.0.0",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "cross-env NODE_ENV=production rollup --config rollup.config.js",
|
||||
"dev": "cross-env NODE_ENV=development rollup --config rollup.config.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"mathjax-full": "^3.2.2",
|
||||
"nanoid": "^4.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^26.0.1",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@rollup/plugin-typescript": "^12.1.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"obsidian": "1.5.7-1",
|
||||
"rollup": "^2.70.1",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.7.3"
|
||||
}
|
||||
}
|
||||
35
MathjaxToSVG/rollup.config.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import typescript from '@rollup/plugin-typescript';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
|
||||
const isProd = (process.env.NODE_ENV === 'production');
|
||||
|
||||
export default {
|
||||
input: './index.ts',
|
||||
output: {
|
||||
dir: 'dist',
|
||||
format: 'iife',
|
||||
name: 'MathjaxToSVG', // Global variable name
|
||||
exports: 'named',
|
||||
sourcemap: !isProd,
|
||||
},
|
||||
plugins: [
|
||||
typescript({
|
||||
tsconfig: 'tsconfig.json',
|
||||
}),
|
||||
commonjs(),
|
||||
nodeResolve({
|
||||
browser: true,
|
||||
preferBuiltins: false
|
||||
}),
|
||||
isProd && terser({
|
||||
format: {
|
||||
comments: false,
|
||||
},
|
||||
compress: {
|
||||
passes: 2,
|
||||
}
|
||||
})
|
||||
].filter(Boolean)
|
||||
};
|
||||
26
MathjaxToSVG/tsconfig.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"sourceMap": false,
|
||||
"module": "es2020",
|
||||
"target": "es2022", //min es2017 because script engine requires for async execution and min es2018 for named capture groups
|
||||
"allowJs": false,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"importHelpers": true,
|
||||
"resolveJsonModule": true,
|
||||
"lib": [
|
||||
"dom",
|
||||
"scripthost",
|
||||
"es2022",
|
||||
"DOM.Iterable"
|
||||
],
|
||||
"jsx": "react",
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx", "src/shared/Dialogs/OpenDrawing.ts",
|
||||
"src/types/types.d.ts",
|
||||
]
|
||||
}
|
||||
366
README.md
@@ -1,102 +1,308 @@
|
||||
# Excalidraw
|
||||
|
||||
【English | [简体中文](./docs/zh-cn/README.md)】
|
||||
|
||||
👉👉👉 Check out and contribute to the new [Obsidian-Excalidraw Community Wiki](https://excalidraw-obsidian.online/WIKI/Welcome+to+the+WIKI)
|
||||
|
||||
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/P_Q6avJGoWI" target="_blank"><img src="https://github.com/zsviczian/obsidian-excalidraw-plugin/assets/14358394/da34bb33-7610-45e6-b36f-cb7a02a9141b" width="300"/></a>
|
||||
<a href="https://youtu.be/o0exK-xFP3k" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/156931370-aa4d88de-c4a8-46cc-aeb2-dc09aa0bea39.jpg" width="300"/></a>
|
||||
<a href="https://youtu.be/QKnQgSjJVuc" target="_blank"><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/thumbnail-getting-started.jpg" width="300"/></a>
|
||||
|
||||

|
||||
### Here's my complete catalog of videos:
|
||||
<a href="https://excalidraw-obsidian.online/Hobbies/Excalidraw+Blog/Catalogue+of+Videos"><img width="380" alt="image" src="https://github.com/zsviczian/obsidian-excalidraw-plugin/assets/14358394/2577e5ad-7a21-4c62-acd5-4fe80c8a8a95"></a>
|
||||
<br>
|
||||
|
||||
# Video walkthrough
|
||||
| | | |
|
||||
|----|----|----|
|
||||
|[](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)|
|
||||
<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 Engine 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;"/> Fourth 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>
|
||||
<a href="https://youtu.be/uZz5MgzWXiM" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/211054371-8872e01a-77d6-4afc-a0c2-86a55410a8d3.png" width="100" style="vertical-align: middle;"/> Custom pen support</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>
|
||||
|
||||
### Beta testing
|
||||
The plugin follows a monthly release schedule. If you want to receive more frequent updates with new features (e.g. shiny new stuff available on excalidraw.com, but not yet in Obsidian) and minor bug fixes, then join the beta community.
|
||||
|
||||
# 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. Check below and 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
|
||||
- `![[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
|
||||
- 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.
|
||||
- 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.
|
||||
[](https://youtu.be/2poSS-Z91lY)
|
||||
|
||||
[](https://github.com/user-attachments/assets/120a0790-7239-48ae-bfbd-eb249f8b518d)
|
||||
|
||||
---
|
||||
|
||||
## 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. The plugin comes with tons of settings. I tried adding meaningful explanations to these settings, so please be patient and look for the setting, for most requests, a setting already exists.
|
||||
|
||||
Plugin settings are grouped into the following sections:
|
||||
- **Basic settings**: such as default folders to use.
|
||||
- **Saving**: compression and autosave timer.
|
||||
- **Filename**: configure the automatically created Excalidraw filename.
|
||||
- **Display**: settings that affect the handling of Excalidraw (e.g.: left-handed mode, theme settings, mouse wheel and pinch zoom settings, zoom to fit settings).
|
||||
- **Links and transclusions**: Settings that affect how links and embedded items behave on the Excalidraw canvas.
|
||||
- **Markdown-embed settings**: These settings control how markdown documents from your Vault embedded into Excalidraw drawings will behave.
|
||||
- **Embed & Export**: Settings that control how Excalidraw images are displayed when embedding them into markdown documents.
|
||||
- **Auto-export Settings**: You can configure Excalidraw to create a PNG or SVG copy of your drawing each time it gets saved.
|
||||
- **Compatibility features**: Check these settings if you edit the Excalidraw drawings outside Obsidian (e.g. in LogSeq, Visual Studio, on the web, etc.).
|
||||
- **Experimental features**: There are advanced features that are implemented as "clever" hacks. Features include defining a fourth font, adding a custom icon to distinguish Exalidraw files in the Obsidian file explorer, OCR settings, and more.
|
||||
- **Settings for installed Scripts**: Some of the scripts you install from the Script Library come with settings. Script settings are installed the first time you run the script. So to access settings for a script, install the script, run it for the first time and then look for the settings in plugin settings.
|
||||
|
||||
#### 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. With versions 1.6.13 or higher make sure to enable "Decompress Excalidraw JSON in Markdown View" in the settings before editing the JSON in the template. This can be disabled after the canges are performed.
|
||||
- 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 `"colorPalette": {` 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.
|
||||
- To change the previewed colors, a `"topPicks": {` may be specified containing the same three keys:
|
||||
- `"canvasBackground":[], "elementBackground":[], "elementStroke": []`.
|
||||
- Note that the corresponding arrays must contain 5 elements.
|
||||
- See my videos above for further help.
|
||||
|
||||
#### Export
|
||||
|
||||
- If portability is important to you:
|
||||
- Auto-export SVG and/or PNG files, including the 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.
|
||||
|
||||
### Embedding your drawings into markdown documents
|
||||
|
||||
- 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.
|
||||
- Excalidraw drawings do not display in Obsidian Publish. If you want to use Excalidraw in your published documents, you can configure in plugin settings, under `Embed & Export`, to automatically insert a PNG or SVG version of the drawing in your document when creating a new file. See `type of file to insert into document`
|
||||
- Under `Export settings`, you can also configure to automatically export a dark and light version of the image, in case your published site supports dark and light modes.
|
||||
|
||||
### Hyperlinks and Drag & Drop support
|
||||
|
||||

|
||||
|
||||
#### 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 the backlinks of documents.
|
||||
- Transclusions are supported:
|
||||
- `![[myfile#^blockref]]` will convert 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.
|
||||
- <kbd>CTRL/CMD + hover</kbd> to bring up the Obsidian quick preview for the link. (On Mac, it is <kbd>CTRL+CMD+hover</kbd>).
|
||||
- Using the block reference, you can also reference & transclude text that appears on drawings, in other documents.
|
||||
|
||||
#### Drag & Drop support
|
||||
|
||||
- You can drag files from the Obsidian file explorer, and they will become links to those files in Excalidraw. See the table above for the various modifier key combinations.
|
||||
- Note: Anchoring an image to 100% of its size 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.
|
||||
- You can drag and drop YouTube links and thumbnails, and they will be YouTube links with thumbnails in Excalidraw.
|
||||
|
||||
### 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.
|
||||
|
||||
### 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.
|
||||
- URL link to images on the web: You can drag images from a webpage to Excalidraw. If you hold down the CTRL button while dropping the image to Excalidraw, the image will not be saved to your vault. Excalidraw will load the image from the URL. Note that if you do not have internet access or if these images are deleted from the internet, they will also disappear from your drawing.
|
||||
- If you page an image URL to excalidraw (simply click copy on the url, then click paste on the excalidraw canvas), the image will be inserted with a link to the image on the web. Again, the image won't be saved to your vault, only the link.
|
||||
- If you drop a YouTube video link, it will be converted into a thumbnail photo with an element link pointing to the video.
|
||||
|
||||
### Block referencing parts of images
|
||||
|
||||
For more details, see this [video](https://youtu.be/yZQoJg2RCKI)
|
||||
- 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 a 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, and it will be preserved as part of the document.
|
||||
- Excalidraw documents now show up 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.
|
||||
- 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:
|
||||
- `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-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).
|
||||
- `excalidraw-default-mode: view|zen` Open this document in view mode or zen mode by defult. The 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.
|
||||
- Since 1.6.13, enable "Decompress Excalidraw JSON in Markdown View" in the settings if you want to change any JSON content.
|
||||
|
||||
### Embed complete markdown files into your drawings
|
||||
|
||||
Drag the desired file from the Obsidian file explorer and hold down <kbd>SHIFT</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>/<kbd>CMD+OPT+i</kbd>) and
|
||||
- Execute the following command: `ExcalidrawAutomate.mostRecentMarkdownSVG`
|
||||
- You can control the 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-border-color: css-color-name|#HEXcolor|any-other-html-standard-format`
|
||||
- `excalidraw-css: "css-filename|css snippet"`
|
||||
- Switch to markdown view or use <kbd>WIN+CTRL</kbd>/<kbd>CMD+CTRL</kbd> click on the image to edit the properties of the embed:
|
||||
- `[[filename#^blockref|WIDTHxMAXHEIGHT]]`
|
||||
|
||||
### Custom Font, Custom Pen, OCR support, SVG import
|
||||
|
||||
- In plugin settings, you can add a custom fourth font. For more details, see this [video](https://youtu.be/eKFmrSQhFA4)
|
||||
- The plugin includes OCR support using Taskbone OCR. For more details, see this [video](https://youtu.be/7gu4ETx7zro)
|
||||
- You can convert SVG files into Excalidraw drawings (with some limitation). For more details, see this [video](https://youtu.be/vlC1-iBvIfo)
|
||||
- You can define custom pens and higlighters and pin them to the sidebar. For more details, see this [video](https://youtu.be/OjNhjaH2KjI). Using ExcalidrawAutomate, you can add support for [auto-toggling](<ea-scripts/Auto Draw for Pen.md>) pen & support for [hardware eraser buttons](<ea-scripts/Hardware Eraser Support.md>).
|
||||
|
||||
### Script Engine
|
||||
|
||||
- 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](ea-scripts/README.md).
|
||||
- You can organize scripts into groups on the Obsidian Tools Panel in Excalidraw by moving scripts and accompanying SVG icon files to folders. See the demo [video](https://youtu.be/wTtaXmRJ7wg?t=16).
|
||||
|
||||
### Other
|
||||
|
||||
- Left-handed mode
|
||||
- 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.
|
||||
- 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>
|
||||
|
||||
14
TODO.md
@@ -1,14 +0,0 @@
|
||||
[x] do not embed font into SVG when embedding Excalidraw into other Excalidraw
|
||||
[x] add ```html <SVG>...</SVG> ``` codeblock to excalidraw markdown
|
||||
[x] read pre-saved `<SVG>` when generating image preview
|
||||
[x] update code to adopt change files moving from AppState to App
|
||||
- Add "files" to legacy excalidraw export
|
||||
|
||||
[x] PNG preview
|
||||
[x] markdown embed SVG 190
|
||||
[x] markdown embed PNG
|
||||
[x] embed Excalidraw into other Excalidraw
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
assets/excalidraw-fonts.zip
Normal file
1119
docs/API/ExcalidrawAutomate.d.ts
vendored
Normal file
@@ -2,199 +2,779 @@
|
||||
## Attributes and functions overview
|
||||
Here's the interface implemented by ExcalidrawAutomate:
|
||||
|
||||
```typescript
|
||||
export interface ExcalidrawAutomate {
|
||||
plugin: ExcalidrawPlugin;
|
||||
elementsDict: {}; //contains the ExcalidrawElements currently edited in Automate indexed by el.id
|
||||
imagesDict: {}; //the images files including DataURL, indexed by fileId
|
||||
style: {
|
||||
strokeColor: string; //https://www.w3schools.com/colors/default.asp
|
||||
backgroundColor: string;
|
||||
angle: number; //radian
|
||||
fillStyle: FillStyle; //type FillStyle = "hachure" | "cross-hatch" | "solid"
|
||||
strokeWidth: number;
|
||||
strokeStyle: StrokeStyle; //type StrokeStyle = "solid" | "dashed" | "dotted"
|
||||
roughness: number;
|
||||
opacity: number;
|
||||
strokeSharpness: StrokeSharpness; //type StrokeSharpness = "round" | "sharp"
|
||||
fontFamily: number; //1: Virgil, 2:Helvetica, 3:Cascadia, 4:LocalFont
|
||||
fontSize: number;
|
||||
textAlign: string; //"left"|"right"|"center"
|
||||
verticalAlign: string; //"top"|"bottom"|"middle" :for future use, has no effect currently
|
||||
startArrowHead: string; //"triangle"|"dot"|"arrow"|"bar"|null
|
||||
endArrowHead: string;
|
||||
};
|
||||
canvas: {
|
||||
theme: string; //"dark"|"light"
|
||||
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;
|
||||
};
|
||||
}): 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
|
||||
};
|
||||
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[];
|
||||
You can find the source file here: [ExcalidrawAutomate.d.ts](ExcalidrawAutomate.d.ts).
|
||||
|
||||
//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
|
||||
```javascript
|
||||
/// <reference types="react" />
|
||||
import ExcalidrawPlugin from "src/main";
|
||||
import { FillStyle, StrokeStyle, ExcalidrawElement, ExcalidrawBindableElement, FileId, NonDeletedExcalidrawElement, ExcalidrawImageElement, StrokeRoundness, RoundnessType } from "@zsviczian/excalidraw/types/element/types";
|
||||
import { Editor, OpenViewState, TFile, WorkspaceLeaf } from "obsidian";
|
||||
import * as obsidian_module from "obsidian";
|
||||
import ExcalidrawView, { ExportSettings } from "src/ExcalidrawView";
|
||||
import { AppState, BinaryFileData, DataURL, ExcalidrawImperativeAPI, Point } from "@zsviczian/excalidraw/types/types";
|
||||
import { EmbeddedFilesLoader } from "src/EmbeddedFileLoader";
|
||||
import { ConnectionPoint, DeviceType } from "src/types";
|
||||
import { ColorMaster } from "colormaster";
|
||||
import { TInput } from "colormaster/types";
|
||||
import { ClipboardData } from "@zsviczian/excalidraw/types/clipboard";
|
||||
import { PaneTarget } from "src/utils/modifierkeyHelper";
|
||||
export declare class ExcalidrawAutomate {
|
||||
/**
|
||||
* Utility function that returns the Obsidian Module object.
|
||||
*/
|
||||
get obsidian(): typeof obsidian_module;
|
||||
get DEVICE(): DeviceType;
|
||||
getAttachmentFilepath(filename: string): Promise<string>;
|
||||
/**
|
||||
* Prompts the user with a dialog to select new file action.
|
||||
* - create markdown file
|
||||
* - create excalidraw file
|
||||
* - cancel action
|
||||
* The new file will be relative to this.targetView.file.path, unless parentFile is provided.
|
||||
* If shouldOpenNewFile is true, the new file will be opened in a workspace leaf.
|
||||
* targetPane control which leaf will be used for the new file.
|
||||
* Returns the TFile for the new file or null if the user cancelled the action.
|
||||
* @param newFileNameOrPath
|
||||
* @param shouldOpenNewFile
|
||||
* @param targetPane //type PaneTarget = "active-pane"|"new-pane"|"popout-window"|"new-tab"|"md-properties";
|
||||
* @param parentFile
|
||||
* @returns
|
||||
*/
|
||||
newFilePrompt(newFileNameOrPath: string, shouldOpenNewFile: boolean, targetPane?: PaneTarget, parentFile?: TFile): Promise<TFile | null>;
|
||||
/**
|
||||
* Generates a new Obsidian Leaf following Excalidraw plugin settings such as open in Main Workspace or not, open in adjacent pane if available, etc.
|
||||
* @param origo // the currently active leaf, the origin of the new leaf
|
||||
* @param targetPane //type PaneTarget = "active-pane"|"new-pane"|"popout-window"|"new-tab"|"md-properties";
|
||||
* @returns
|
||||
*/
|
||||
getLeaf(origo: WorkspaceLeaf, targetPane?: PaneTarget): WorkspaceLeaf;
|
||||
/**
|
||||
* Returns the editor or leaf.view of the currently active embedded obsidian file.
|
||||
* If view is not provided, ea.targetView is used.
|
||||
* If the embedded file is a markdown document the function will return
|
||||
* {file:TFile, editor:Editor} otherwise it will return {view:any}. You can check view type with view.getViewType();
|
||||
* @param view
|
||||
* @returns
|
||||
*/
|
||||
getActiveEmbeddableViewOrEditor(view?: ExcalidrawView): {
|
||||
view: any;
|
||||
} | {
|
||||
file: TFile;
|
||||
editor: Editor;
|
||||
} | null;
|
||||
plugin: ExcalidrawPlugin;
|
||||
elementsDict: {
|
||||
[key: string]: any;
|
||||
};
|
||||
imagesDict: {
|
||||
[key: FileId]: any;
|
||||
};
|
||||
mostRecentMarkdownSVG: SVGSVGElement;
|
||||
style: {
|
||||
strokeColor: string;
|
||||
backgroundColor: string;
|
||||
angle: number;
|
||||
fillStyle: FillStyle;
|
||||
strokeWidth: number;
|
||||
strokeStyle: StrokeStyle;
|
||||
roughness: number;
|
||||
opacity: number;
|
||||
strokeSharpness?: StrokeRoundness;
|
||||
roundness: null | {
|
||||
type: RoundnessType;
|
||||
value?: number;
|
||||
};
|
||||
fontFamily: number;
|
||||
fontSize: number;
|
||||
textAlign: string;
|
||||
verticalAlign: string;
|
||||
startArrowHead: string;
|
||||
endArrowHead: string;
|
||||
};
|
||||
canvas: {
|
||||
theme: string;
|
||||
viewBackgroundColor: string;
|
||||
gridSize: number;
|
||||
};
|
||||
colorPalette: {};
|
||||
constructor(plugin: ExcalidrawPlugin, view?: ExcalidrawView);
|
||||
/**
|
||||
*
|
||||
* @returns the last recorded pointer position on the Excalidraw canvas
|
||||
*/
|
||||
getViewLastPointerPosition(): {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @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>;
|
||||
/**
|
||||
* @param file: TFile
|
||||
* @returns ExcalidrawScene
|
||||
*/
|
||||
getSceneFromFile(file: TFile): Promise<{
|
||||
elements: ExcalidrawElement[];
|
||||
appState: AppState;
|
||||
}>;
|
||||
/**
|
||||
* get all elements from ExcalidrawAutomate elementsDict
|
||||
* @returns elements from elementsDict
|
||||
*/
|
||||
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-padding"?: number;
|
||||
"excalidraw-export-pngscale"?: number;
|
||||
"excalidraw-default-mode"?: "view" | "zen";
|
||||
"excalidraw-onload-script"?: string;
|
||||
"excalidraw-linkbutton-opacity"?: number;
|
||||
"excalidraw-autoexport"?: boolean;
|
||||
};
|
||||
plaintext?: string;
|
||||
}): 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;
|
||||
addIFrame(topX: number, topY: number, width: number, height: number, url?: string, file?: TFile): string;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param width
|
||||
* @param height
|
||||
* @returns
|
||||
*/
|
||||
addEmbeddable(topX: number, topY: number, width: number, height: number, url?: string, file?: TFile): string;
|
||||
/**
|
||||
*
|
||||
* @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;
|
||||
/**
|
||||
* Refresh the size of a text element to fit its contents
|
||||
* @param id - the id of the text element
|
||||
*/
|
||||
refreshTextElementSize(id: string): void;
|
||||
/**
|
||||
*
|
||||
* @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?: "left" | "center" | "right";
|
||||
box?: boolean | "box" | "blob" | "ellipse" | "diamond";
|
||||
boxPadding?: number;
|
||||
boxStrokeColor?: string;
|
||||
textVerticalAlign?: "top" | "middle" | "bottom";
|
||||
}, 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 | string, scale?: boolean, //default is true which will scale the image to MAX_IMAGE_SIZE, false will insert image at 100% of its size
|
||||
anchor?: boolean): 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;
|
||||
targetView: ExcalidrawView;
|
||||
/**
|
||||
* sets the target view for EA. All the view operations and the access to Excalidraw API will be performend on this view
|
||||
* if view is null or undefined, the function will first try setView("active"), then setView("first").
|
||||
* @param view
|
||||
* @returns targetView
|
||||
*/
|
||||
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;
|
||||
setViewModeEnabled(enabled: boolean): void;
|
||||
/**
|
||||
* This function gives you a more hands on access to Excalidraw.
|
||||
* @param scene - The scene you want to load to Excalidraw
|
||||
* @param restore - Use this if the scene includes legacy excalidraw file elements that need to be converted to the latest excalidraw data format (not a typical usecase)
|
||||
* @returns
|
||||
*/
|
||||
viewUpdateScene(scene: {
|
||||
elements?: ExcalidrawElement[];
|
||||
appState?: AppState;
|
||||
files?: BinaryFileData;
|
||||
commitToHistory?: boolean;
|
||||
}, restore?: 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;
|
||||
/**
|
||||
* 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
|
||||
* @param selectElements
|
||||
* @param elements
|
||||
*/
|
||||
viewZoomToElements(selectElements: boolean, elements: ExcalidrawElement[]): void;
|
||||
/**
|
||||
* 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
|
||||
* @param shouldRestoreElements - restore elements - auto-corrects broken, incomplete or old elements included in the update
|
||||
* @returns
|
||||
*/
|
||||
addElementsToView(repositionToCursor?: boolean, save?: boolean, newElementsOnTop?: boolean, shouldRestoreElements?: 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 false, 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;
|
||||
/**
|
||||
* If set, this callback is triggered, when Excalidraw receives an onPaste event.
|
||||
* You can use this callback in case you want to do something additional when the
|
||||
* onPaste event occurs.
|
||||
* This callback must return a boolean value.
|
||||
* In case you want to prevent the excalidraw onPaste action you must return false,
|
||||
* it will stop the native excalidraw onPaste management flow.
|
||||
*/
|
||||
onPasteHook: (data: {
|
||||
ea: ExcalidrawAutomate;
|
||||
payload: ClipboardData;
|
||||
event: ClipboardEvent;
|
||||
excalidrawFile: TFile;
|
||||
view: ExcalidrawView;
|
||||
pointerPosition: {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
}) => boolean;
|
||||
/**
|
||||
* if set, this callback is triggered, when an Excalidraw file is opened
|
||||
* You can use this callback in case you want to do something additional when the file is opened.
|
||||
* This will run before the file level script defined in the `excalidraw-onload-script` frontmatter.
|
||||
*/
|
||||
onFileOpenHook: (data: {
|
||||
ea: ExcalidrawAutomate;
|
||||
excalidrawFile: TFile;
|
||||
view: ExcalidrawView;
|
||||
}) => Promise<void>;
|
||||
/**
|
||||
* if set, this callback is triggered, when an Excalidraw file is created
|
||||
* see also: https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1124
|
||||
*/
|
||||
onFileCreateHook: (data: {
|
||||
ea: ExcalidrawAutomate;
|
||||
excalidrawFile: TFile;
|
||||
view: ExcalidrawView;
|
||||
}) => Promise<void>;
|
||||
/**
|
||||
* If set, this callback is triggered whenever the active canvas color changes
|
||||
*/
|
||||
onCanvasColorChangeHook: (ea: ExcalidrawAutomate, view: ExcalidrawView, //the excalidraw view
|
||||
color: string) => void;
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* @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[];
|
||||
/**
|
||||
* 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[];
|
||||
/**
|
||||
* Gets all the elements from elements[] that are contained in the frame.
|
||||
* @param element
|
||||
* @param elements - typically all the non-deleted elements in the scene
|
||||
* @returns
|
||||
*/
|
||||
getElementsInFrame(frameElement: ExcalidrawElement, elements: ExcalidrawElement[]): ExcalidrawElement[];
|
||||
/**
|
||||
* 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
|
||||
* @param openState - if not provided {active: true} will be used
|
||||
* @returns
|
||||
*/
|
||||
openFileInNewOrAdjacentLeaf(file: TFile, openState?: OpenViewState): WorkspaceLeaf;
|
||||
/**
|
||||
* measure text size based on current style settings
|
||||
* @param text
|
||||
* @returns
|
||||
*/
|
||||
measureText(text: string): {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
/**
|
||||
* Returns the size of the image element at 100% (i.e. the original size)
|
||||
* @param imageElement an image element from the active scene on targetView
|
||||
*/
|
||||
getOriginalImageSize(imageElement: ExcalidrawImageElement): Promise<{
|
||||
width: number;
|
||||
height: number;
|
||||
}>;
|
||||
/**
|
||||
* 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[] | string[]): 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;
|
||||
/**
|
||||
* Deprecated. Use getCM / ColorMaster instead
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
hexStringToRgb(color: string): number[];
|
||||
/**
|
||||
* Deprecated. Use getCM / ColorMaster instead
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
rgbToHexString(color: number[]): string;
|
||||
/**
|
||||
* Deprecated. Use getCM / ColorMaster instead
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
hslToRgb(color: number[]): number[];
|
||||
/**
|
||||
* Deprecated. Use getCM / ColorMaster instead
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
rgbToHsl(color: number[]): number[];
|
||||
/**
|
||||
*
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
colorNameToHex(color: string): string;
|
||||
/**
|
||||
* https://github.com/lbragile/ColorMaster
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
getCM(color: TInput): ColorMaster;
|
||||
importSVG(svgString: string): boolean;
|
||||
}
|
||||
```
|
||||
|
||||
export declare function initExcalidrawAutomate(plugin: ExcalidrawPlugin): Promise<ExcalidrawAutomate>;
|
||||
export declare function destroyExcalidrawAutomate(): void;
|
||||
export declare function _measureText(newText: string, fontSize: number, fontFamily: number, lineHeight: number): {
|
||||
w: number;
|
||||
h: number;
|
||||
baseline: number;
|
||||
};
|
||||
export declare const generatePlaceholderDataURL: (width: number, height: number) => DataURL;
|
||||
export declare function createPNG(templatePath: string, scale: number, exportSettings: ExportSettings, loader: EmbeddedFilesLoader, forceTheme: string, canvasTheme: string, canvasBackgroundColor: string, automateElements: ExcalidrawElement[], plugin: ExcalidrawPlugin, depth: number, padding?: number, imagesDict?: any): Promise<Blob>;
|
||||
export declare function createSVG(templatePath: string, embedFont: boolean, exportSettings: ExportSettings, loader: EmbeddedFilesLoader, forceTheme: string, canvasTheme: string, canvasBackgroundColor: string, automateElements: ExcalidrawElement[], plugin: ExcalidrawPlugin, depth: number, padding?: number, imagesDict?: any, convertMarkdownLinksToObsidianURLs?: boolean): Promise<SVGSVGElement>;
|
||||
export declare function estimateBounds(elements: ExcalidrawElement[]): [number, number, number, number];
|
||||
export declare function repositionElementsToCursor(elements: ExcalidrawElement[], newPosition: {
|
||||
x: number;
|
||||
y: number;
|
||||
}, center: boolean, api: ExcalidrawImperativeAPI): ExcalidrawElement[];
|
||||
export declare const insertLaTeXToView: (view: ExcalidrawView) => void;
|
||||
export declare const search: (view: ExcalidrawView) => Promise<void>;
|
||||
/**
|
||||
*
|
||||
* @param elements
|
||||
* @param query
|
||||
* @param exactMatch - when searching for section header exactMatch should be set to true
|
||||
* @returns the elements matching the query
|
||||
*/
|
||||
export declare const getTextElementsMatchingQuery: (elements: ExcalidrawElement[], query: string[], exactMatch?: boolean) => ExcalidrawElement[];
|
||||
/**
|
||||
*
|
||||
* @param elements
|
||||
* @param query
|
||||
* @param exactMatch - when searching for section header exactMatch should be set to true
|
||||
* @returns the elements matching the query
|
||||
*/
|
||||
export declare const getFrameElementsMatchingQuery: (elements: ExcalidrawElement[], query: string[], exactMatch?: boolean) => ExcalidrawElement[];
|
||||
export declare const cloneElement: (el: ExcalidrawElement) => any;
|
||||
export declare const verifyMinimumPluginVersion: (requiredVersion: string) => boolean;
|
||||
```
|
||||
@@ -54,7 +54,7 @@ Number between 0 and 100. The opacity of an object, both stroke and fill.
|
||||
### strokeSharpness, setStrokeSharpness()
|
||||
```typescript
|
||||
type StrokeSharpness = "round" | "sharp";
|
||||
setStrokeSharpness(val:nmuber);
|
||||
setStrokeSharpness(val:number);
|
||||
```
|
||||
strokeSharpness is a string.
|
||||
|
||||
@@ -88,4 +88,4 @@ This is relevant when setting a fix height using the `addText()` function.
|
||||
### startArrowHead, endArrowHead
|
||||
String. Valid values are "arrow", "bar", "dot", and "none". Specifies the beginning and ending of an arrow.
|
||||
|
||||
This is relavant when using the `addArrow()` and the `connectObjects()` functions.
|
||||
This is relevant when using the `addArrow()` and the `connectObjects()` functions.
|
||||
@@ -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();
|
||||
@@ -21,11 +21,11 @@ The second line resets ExcalidrawAutomate to defaults. This is important as you
|
||||
|
||||
You can change the styling between adding different elements. My logic for separating element styling and creation is based on the assumption that you will probably set a stroke color, stroke style, stroke roughness, etc. and draw most of your elements using that. There would be no point in setting all these parameters each time you add an element.
|
||||
|
||||
### Before we dive deeper, here are three a simple example [Templater](https://github.com/SilentVoid13/Templater) scripts
|
||||
### Before we dive deeper, here are three simple example [Templater](https://github.com/SilentVoid13/Templater) scripts
|
||||
#### 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;
|
||||
|
||||
@@ -22,7 +22,7 @@ Places the generated drawing to the clipboard. Useful when you don't want to cre
|
||||
```typescript
|
||||
getElements():ExcalidrawElement[];
|
||||
```
|
||||
Returns the elements in ExcalidrawAutomate as an array of ExcalidrawElements. This format is usefull when working with ExcalidrawRef.
|
||||
Returns the elements in ExcalidrawAutomate as an array of ExcalidrawElements. This format is useful when working with ExcalidrawRef.
|
||||
|
||||
### getElement()
|
||||
```typescript
|
||||
@@ -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.
|
||||
|
||||
@@ -156,7 +156,7 @@ You first need to set the view calling `setView()`.
|
||||
|
||||
Gets the array of selected elements in the scene. Returns [] if no elements are selected.
|
||||
|
||||
Note: you can call `getExcalidrawAPI().getSceneElements()` to retreive all the elements in the scene.
|
||||
Note: you can call `getExcalidrawAPI().getSceneElements()` to retrieve all the elements in the scene.
|
||||
|
||||
#### viewToggleFullScreen()
|
||||
```typescript
|
||||
@@ -178,7 +178,7 @@ Same as `connectObjects()`, but ObjectB is the currently selected element in the
|
||||
async addElementsToView(repositionToCursor:boolean=false, save:boolean=false):Promise<boolean>
|
||||
```
|
||||
Adds elements created with ExcalidrawAutomate to the target ExcalidrawView.
|
||||
`repositionToCursor` dafault is false
|
||||
`repositionToCursor` default is false
|
||||
- true: the elements will be moved such that the center point of the elements will be aligned with the current position of the pointer on ExcalidrawView. You can point and place elements to a desired location in your drawing using this switch.
|
||||
- false: elements will be positioned as defined by the x&y coordinates of each element.
|
||||
|
||||
@@ -204,7 +204,7 @@ onDropHook (data: {
|
||||
```
|
||||
|
||||
Callback function triggered when an draggable item is dropped on Excalidraw.
|
||||
The function should return a boolean value. True if the drop was handled by the hook and futher native processing should be stopped, and false if Excalidraw should continue with the processing of the drop.
|
||||
The function should return a boolean value. True if the drop was handled by the hook and further native processing should be stopped, and false if Excalidraw should continue with the processing of the drop.
|
||||
type of drop can be one of:
|
||||
- "file" if a file from Obsidian file explorer is dropped onto Excalidraw. In this case payload.files will contain the list of files dropped.
|
||||
- "text" if a link (e.g. url, or wiki link) or other text is dropped. In this case payload.text will contain the received string
|
||||
@@ -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;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# [◀ Excalidraw Automate How To](../readme.md)
|
||||
## Generating a simple mindmap from a text outline
|
||||
This is a slightly more elaborate example. This will generate an a mindmap from a tabulated outline.
|
||||
This is a slightly more elaborate example. This will generate a mindmap from a tabulated outline.
|
||||
|
||||
### Output
|
||||

|
||||
@@ -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});
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# [◀ Excalidraw Automate How To](./readme.md)
|
||||
|
||||
【English | [简体中文](zh-cn/docs/ExcalidrawScriptsEngine.md)】
|
||||
|
||||
[](https://youtu.be/hePJcObHIso)
|
||||
|
||||
## Introduction
|
||||
@@ -21,7 +23,7 @@ This will allow you to assign hotkeys to your favorite scripts just like to any
|
||||
|
||||
## Script development
|
||||
An Excalidraw script will automatically receive two objects:
|
||||
- `ea`: The Script Enginge will initialize the `ea` object including setting the active view to the View from which the script was called.
|
||||
- `ea`: The Script Engine will initialize the `ea` object including setting the active view to the View from which the script was called.
|
||||
- `utils`: I have borrowed functions exposed on utils from [QuickAdd](https://github.com/chhoumann/quickadd/blob/master/docs/QuickAddAPI.md), though currently not all QuickAdd utility functions are implemented in Excalidraw. As of now, these are the available functions. See the example below for details.
|
||||
- `inputPrompt: (header: string, placeholder?: string, value?: string, buttons?: [{caption:string, action:Function}])`
|
||||
- Opens a prompt that asks for an input. Returns a string with the input.
|
||||
|
||||
5782
docs/Release-notes.md
Normal file
@@ -1,5 +1,7 @@
|
||||
# Excalidraw Automate How To
|
||||
|
||||
【English | [简体中文](zh-cn/docs/readme.md)】
|
||||
|
||||
Use ExcalidrawAutomate to create or manipulate Excalidraw drawings using the [ExcalidrawAutomate Script Engine](ExcalidrawScriptsEngine.md), the [Templater](https://silentvoid13.github.io/Templater/docs/) or the [QuickAdd](https://github.com/chhoumann/quickadd) plugins, and to generate embedded SVG and PNG images using [DataviewJS](https://blacksmithgu.github.io/obsidian-dataview/docs/api/intro/)
|
||||
|
||||
With a little work, using ExcalidrawAutomate you can generate simple mindmaps, build a family tree, fill out SVG forms, create customized charts, or automate simple tasks (i.e. create macros) in Excalidraw.
|
||||
@@ -8,7 +10,7 @@ With a little work, using ExcalidrawAutomate you can generate simple mindmaps, b
|
||||
## API documentation
|
||||
- **start here** [Introduction to the API](API/introduction.md)
|
||||
- [Overview of Attributes and Functions](API/attributes_functions_overview.md)
|
||||
- [Element Sytle](API/element_style.md)
|
||||
- [Element Style](API/element_style.md)
|
||||
- [Canvas Style](API/canvas_style.md)
|
||||
- [Adding Objects](API/objects.md)
|
||||
- [Utility Functions](API/utility.md)
|
||||
|
||||
484
docs/zh-cn/AutomateHowTo.md
Normal file
@@ -0,0 +1,484 @@
|
||||
# Excalidraw 自动化使用指南
|
||||
|
||||
> 此说明当前更新至 `5569cff`。
|
||||
|
||||
[English](../../AutomateHowTo.md)
|
||||
|
||||
Excalidraw 自动化允许您使用 [Templater](https://github.com/SilentVoid13/Templater) 插件创建 Excalidraw 绘图。
|
||||
|
||||
通过一些工作,使用 Excalidraw 自动化,您可以根据保管库中的文档生成简单的思维导图、填写 SVG 表单、创建自定义图表等。
|
||||
|
||||
您可以通过 ExcalidrawAutomate 对象访问 Excalidraw 自动化。我建议您以以下代码开始您的自动化脚本。
|
||||
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
|
||||
```javascript
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
```
|
||||
|
||||
第一行创建了一个实用的常量,这样您就可以避免写 100 次 `ExcalidrawAutomate`。
|
||||
|
||||
第二行将 `ExcalidrawAutomate` 重置为默认值。这一点很重要,因为您将不知道之前执行了哪个模板,因此您也不知道 `Excalidraw` 的状态。
|
||||
|
||||
## 使用 Excalidraw 自动化的基本逻辑
|
||||
|
||||
1. 设置您想要绘制的元素的样式
|
||||
2. 添加元素。每添加一个新元素,它都会在上一个元素的上方添加一层,因此在重叠对象的情况下,后添加的元素会在前一个元素之上。
|
||||
3. 调用 `await ea.create();` 来实例化绘图
|
||||
|
||||
您可以在添加不同元素之间更改样式。我将元素样式与创建分开是基于这样的假设:您可能会设置描边颜色、描边样式、描边粗糙度等,并使用这些设置绘制大多数元素。每次添加元素时设置所有这些参数是没有意义的。
|
||||
|
||||
### 在深入探讨之前,这里有两个简单的示例脚本
|
||||
#### 使用模板在自定义文件夹中创建具有自定义名称的新绘图
|
||||
这个简单的脚本为您提供了比 Excalidraw 插件设置更大的灵活性,可以为您的绘图命名、将其放入文件夹中,并应用模板。
|
||||
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
await ea.create({
|
||||
filename : tp.date.now("HH.mm"),
|
||||
foldername : tp.date.now("YYYY-MM-DD"),
|
||||
templatePath: "Excalidraw/Template1.excalidraw",
|
||||
onNewPane : false
|
||||
});
|
||||
%>
|
||||
```
|
||||
|
||||
#### 创建一个简单的绘图
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
ea.addRect(-150,-50,450,300);
|
||||
ea.addText(-100,70,"Left to right");
|
||||
ea.addArrow([[-100,100],[100,100]]);
|
||||
|
||||
ea.style.strokeColor = "red";
|
||||
ea.addText(100,-30,"top to bottom",{width:200,textAligh:"center"});
|
||||
ea.addArrow([[200,0],[200,200]]);
|
||||
await ea.create();
|
||||
%>
|
||||
```
|
||||
该脚本将生成以下绘图:
|
||||
|
||||

|
||||
|
||||
## 属性和功能一览
|
||||
这是 ExcalidrawAutomate 实现的接口:
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
```javascript
|
||||
ExcalidrawAutomate: {
|
||||
style: {
|
||||
strokeColor: string;
|
||||
backgroundColor: string;
|
||||
angle: number;
|
||||
fillStyle: FillStyle;
|
||||
strokeWidth: number;
|
||||
storkeStyle: StrokeStyle;
|
||||
roughness: number;
|
||||
opacity: number;
|
||||
strokeSharpness: StrokeSharpness;
|
||||
fontFamily: FontFamily;
|
||||
fontSize: number;
|
||||
textAlign: string;
|
||||
verticalAlign: string;
|
||||
startArrowHead: string;
|
||||
endArrowHead: string;
|
||||
}
|
||||
canvas: {theme: string, viewBackgroundColor: string};
|
||||
setFillStyle: Function;
|
||||
setStrokeStyle: Function;
|
||||
setStrokeSharpness: Function;
|
||||
setFontFamily: Function;
|
||||
setTheme: Function;
|
||||
addRect: Function;
|
||||
addDiamond: Function;
|
||||
addEllipse: Function;
|
||||
addText: Function;
|
||||
addLine: Function;
|
||||
addArrow: Function;
|
||||
connectObjects: Function;
|
||||
addToGroup: Function;
|
||||
toClipboard: Function;
|
||||
create: Function;
|
||||
createPNG: Function;
|
||||
createSVG: Function;
|
||||
clear: Function;
|
||||
reset: Function;
|
||||
};
|
||||
```
|
||||
|
||||
## 元素样式
|
||||
正如您所注意到的,某些样式具有设置函数。这是为了帮助您浏览属性的可用值。不过,您并不需要使用设置函数,您也可以直接设置值。
|
||||
|
||||
### strokeColor
|
||||
字符串。线条的颜色。[CSS 合法颜色值](https://www.w3schools.com/cssref/css_colors_legal.asp)
|
||||
|
||||
允许的值包括 [HTML 颜色名称](https://www.w3schools.com/colors/colors_names.asp)、十六进制 RGB 字符串,例如 `#FF0000` 表示红色。
|
||||
|
||||
### backgroundColor
|
||||
字符串。对象的填充颜色。[CSS 合法颜色值](https://www.w3schools.com/cssref/css_colors_legal.asp)
|
||||
|
||||
允许的值包括 [HTML 颜色名称](https://www.w3schools.com/colors/colors_names.asp)、十六进制 RGB 字符串,例如 `#FF0000` 表示红色,或 `transparent`(透明)。
|
||||
|
||||
### angle
|
||||
数字。以弧度表示的旋转。90° == `Math.PI/2`。
|
||||
|
||||
### fillStyle, setFillStyle()
|
||||
```typescript
|
||||
type FillStyle = "hachure" | "cross-hatch" | "solid";
|
||||
setFillStyle (val:number);
|
||||
```
|
||||
fillStyle 是一个字符串.
|
||||
|
||||
`setFillStyle()` 接受一个数字:
|
||||
- 0: "hachure"(斜线填充)
|
||||
- 1: "cross-hatch"(交叉斜线填充)
|
||||
- 其他任何数字: "solid"(实心填充)
|
||||
|
||||
### strokeWidth
|
||||
数字,设置描边的宽度。
|
||||
|
||||
### strokeStyle, setStrokeStyle()
|
||||
```typescript
|
||||
type StrokeStyle = "solid" | "dashed" | "dotted";
|
||||
setStrokeStyle (val:number);
|
||||
```
|
||||
strokeStyle 是一个字符串。
|
||||
|
||||
`setStrokeStyle()` 接受一个数字:
|
||||
- 0: "solid"(实线)
|
||||
- 1: "dashed"(虚线)
|
||||
- 其他任何数字: "dotted"(点线)
|
||||
|
||||
### roughness
|
||||
数字。在 Excalidraw 中称为“粗糙度”。接受三个值:
|
||||
- 0: 建筑师
|
||||
- 1: 艺术家
|
||||
- 2: 卡通画家
|
||||
|
||||
### opacity
|
||||
介于 0 和 100 之间的数字。对象的透明度,包括描边和填充。
|
||||
|
||||
### strokeSharpness, setStrokeSharpness()
|
||||
```typescript
|
||||
type StrokeSharpness = "round" | "sharp";
|
||||
setStrokeSharpness(val:number);
|
||||
```
|
||||
strokeSharpness 是一个字符串。
|
||||
|
||||
“round” 线条是曲线,“sharp” 线条在转折点处断开(硬弯折)。
|
||||
|
||||
`setStrokeSharpness()` 接受一个数字:
|
||||
- 0: "round"(圆滑)
|
||||
- 其他任何数字: "sharp"(尖锐)
|
||||
|
||||
### fontFamily, setFontFamily()
|
||||
数字。有效值为 1、2 和 3。
|
||||
|
||||
`setFontFamily()` 也会接受一个数字并返回字体名称。
|
||||
- 1: "Virgil, Segoe UI Emoji"
|
||||
- 2: "Helvetica, Segoe UI Emoji"
|
||||
- 3: "Cascadia, Segoe UI Emoji"
|
||||
|
||||
### fontSize
|
||||
数字。默认值为 20 像素。
|
||||
|
||||
### textAlign
|
||||
字符串。文本的水平对齐方式。有效值为 "left"(左对齐)、"center"(居中对齐)、"right"(右对齐)。
|
||||
|
||||
在使用 `addText()` 函数设置固定宽度时,这一点很重要。
|
||||
|
||||
### verticalAlign
|
||||
字符串。文本的垂直对齐方式。有效值为 "top"(顶部)和 "middle"(中间)。
|
||||
|
||||
在使用 `addText()` 函数设置固定高度时,这一点很重要。
|
||||
|
||||
### startArrowHead, endArrowHead
|
||||
字符串。有效值为 "arrow"(箭头)、"bar"(线条)、"dot"(点)和 "none"(无)。指定箭头的起始和结束。
|
||||
|
||||
在使用 `addArrow()` 和 `connectObjects()` 函数时,这一点很重要。
|
||||
|
||||
## canvas
|
||||
设置画布的属性。
|
||||
|
||||
### theme, setTheme()
|
||||
字符串。有效值为 "light"(明亮)和 "dark"(黑暗)。
|
||||
|
||||
`setTheme()` 接受一个数字:
|
||||
- 0: "light"(明亮)
|
||||
- 其他任何数字: "dark"(黑暗)
|
||||
|
||||
### viewBackgroundColor
|
||||
字符串。对象的填充颜色。[CSS 合法颜色值](https://www.w3schools.com/cssref/css_colors_legal.asp)
|
||||
|
||||
允许的值包括 [HTML 颜色名称](https://www.w3schools.com/colors/colors_names.asp)、十六进制 RGB 字符串,例如 `#FF0000` 表示红色,或 `transparent`(透明)。
|
||||
|
||||
## 添加对象
|
||||
这些函数将向您的绘图中添加对象。画布是无限的,接受负值和正值的 X 和 Y 坐标。X 值从左到右增加,Y 值从上到下增加。
|
||||
|
||||

|
||||
|
||||
### addRect(), addDiamond(), addEllipse()
|
||||
```typescript
|
||||
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
|
||||
```
|
||||
返回对象的 `id`。在用线连接对象时,需要使用 `id`。请参见后文。
|
||||
### addText
|
||||
```typescript
|
||||
addText(topX:number, topY:number, text:string, formatting?:{width:number, height:number,textAlign: string, verticalAlign:string, box: boolean, boxPadding: number}):string
|
||||
```
|
||||
|
||||
向绘图中添加文本。
|
||||
|
||||
格式参数是可选的:
|
||||
- 如果未指定 `width`(宽度)和 `height`(高度),函数将根据 `fontFamily`、`fontSize` 和提供的文本计算宽度和高度。
|
||||
- 如果您希望文本相对于绘图中的其他元素居中,可以提供固定的高度和宽度,同时可以指定 `textAlign` 和 `verticalAlign`,如上所述。例如:`{width:500, textAlign:"center"}`。
|
||||
- 如果您想在文本周围添加一个框,请设置 `{box:true}`。
|
||||
|
||||
返回对象的 `id`。在用线连接对象时,需要使用 `id`。请参见后文。如果 `{box:true}`,则返回包围框的 `id`。
|
||||
|
||||
### addLine()
|
||||
```typescript
|
||||
addLine(points: [[x:number,y:number]]):void
|
||||
```
|
||||
添加一条连接提供的点的线。必须至少包含两个点 `points.length >= 2`。如果提供的点超过两个,间隔点将作为断点添加。如果 `strokeSharpness` 设置为 "sharp",线条将在转折处断开;如果设置为 "round",线条将是曲线。
|
||||
|
||||
### addArrow()
|
||||
```typescript
|
||||
addArrow(points: [[x:number,y:number]],formatting?:{startArrowHead:string,endArrowHead:string,startObjectId:string,endObjectId:string}):void
|
||||
```
|
||||
|
||||
添加一条连接提供的点的箭头。必须至少包含两个点 `points.length >= 2`。如果提供的点超过两个,间隔点将作为断点添加。如果元素 `style.strokeSharpness` 设置为 "sharp",线条将在转折处断开;如果设置为 "round",线条将是曲线。
|
||||
|
||||
`startArrowHead` 和 `endArrowHead` 指定要使用的箭头类型,如上所述。有效值为 "none"(无)、"arrow"(箭头)、"dot"(点)和 "bar"(线条)。例如:`{startArrowHead: "dot", endArrowHead: "arrow"}`。
|
||||
|
||||
`startObjectId` 和 `endObjectId` 是连接对象的对象 ID。我建议使用 `connectObjects` 而不是调用 `addArrow()` 来连接对象。
|
||||
|
||||
### connectObjects()
|
||||
```typescript
|
||||
declare type ConnectionPoint = "top"|"bottom"|"left"|"right";
|
||||
connectObjects(objectA: string, connectionA: ConnectionPoint, objectB: string, connectionB: ConnectionPoint, formatting?:{numberOfPoints: number,startArrowHead:string,endArrowHead:string, padding: number}):void
|
||||
```
|
||||
连接两个对象的箭头。
|
||||
|
||||
`objectA` 和 `objectB` 是字符串。这些是要连接的对象的 ID。这些 ID 是通过 `addRect()`、`addDiamond()`、`addEllipse()` 和 `addText()` 创建这些对象时返回的。
|
||||
|
||||
`connectionA` 和 `connectionB` 指定在对象上的连接位置。有效值为:"top"(上)、"bottom"(下)、"left"(左)和 "right"(右)。
|
||||
|
||||
`numberOfPoints` 设置线条的间隔断点数量。默认值为零,意味着箭头的起点和终点之间不会有断点。当在绘图中移动对象时,这些断点将影响 Excalidraw 如何重新调整线条。
|
||||
|
||||
`startArrowHead` 和 `endArrowHead` 的功能与 `addArrow()` 中描述的一致。
|
||||
|
||||
### addToGroup()
|
||||
```typescript
|
||||
addToGroup(objectIds:[]):void
|
||||
```
|
||||
将 `objectIds` 中列出的对象进行分组。
|
||||
|
||||
## 实用函数
|
||||
### clear()
|
||||
`clear()` 将从缓存中清除对象,但会保留元素样式设置。
|
||||
|
||||
### reset()
|
||||
`reset()` 将首先调用 `clear()`,然后将元素样式重置为默认值。
|
||||
|
||||
### toClipboard()
|
||||
```typescript
|
||||
async toClipboard(templatePath?:string)
|
||||
```
|
||||
将生成的图形放入剪贴板。当您不想创建新图形,而是想将其他项目粘贴到现有图形上时,这非常有用。
|
||||
|
||||
### create()
|
||||
```typescript
|
||||
async create(params?:{filename: string, foldername:string, templatePath:string, onNewPane: boolean})
|
||||
```
|
||||
创建图形并打开它。
|
||||
|
||||
`filename` 是要创建的图形的文件名(不带扩展名)。如果为 `null`,则 Excalidraw 会生成一个文件名。
|
||||
|
||||
`foldername` 是文件应创建的文件夹。如果为 `null`,则将根据 Excalidraw 设置使用新图形的默认文件夹。
|
||||
|
||||
`templatePath` 是包含完整路径和扩展名的模板文件名。该模板文件将作为基础层添加,所有通过 ExcalidrawAutomate 添加的额外对象将出现在模板元素之上。如果为 `null`,则不使用模板,即空白图形将作为添加对象的基础。
|
||||
|
||||
`onNewPane` 定义新图形应创建的位置。`false` 将在当前活动的标签页中打开图形;`true` 将通过垂直分割当前标签页来打开图形。
|
||||
|
||||
示例:
|
||||
|
||||
```javascript
|
||||
create({filename:"my drawing", foldername:"myfolder/subfolder/", templatePath: "Excalidraw/template.excalidraw", onNewPane: true});
|
||||
```
|
||||
### createSVG()
|
||||
```typescript
|
||||
async createSVG(templatePath?:string)
|
||||
```
|
||||
返回一个包含生成图形的 HTML `SVGSVGElement`。
|
||||
|
||||
### createPNG()
|
||||
```typescript
|
||||
async createPNG(templatePath?:string)
|
||||
```
|
||||
返回一个包含生成图形的 PNG 图像的 blob。
|
||||
|
||||
## 示例
|
||||
### 将新图形插入到当前编辑的文档中
|
||||
此模板将提示您输入图形的标题。它将在您提供的标题下创建一个新图形,并在您正在编辑的文档的文件夹中。然后,它将在光标位置插入新图形,并通过分割当前标签页在新的工作区标签页中打开新图形。
|
||||
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
```javascript
|
||||
<%*
|
||||
const defaultTitle = tp.date.now("HHmm")+' '+tp.file.title;
|
||||
const title = await tp.system.prompt("Title of the drawing?", defaultTitle);
|
||||
const folder = tp.file.folder(true);
|
||||
const transcludePath = (folder== '/' ? '' : folder + '/') + title + '.excalidraw';
|
||||
tR = String.fromCharCode(96,96,96)+'excalidraw\n[['+transcludePath+']]\n'+String.fromCharCode(96,96,96);
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
ea.setTheme(1); //set Theme to dark
|
||||
await ea.create({
|
||||
filename : title,
|
||||
foldername : folder,
|
||||
//templatePath: 'Excalidraw/Template.excalidraw', //uncomment if you want to use a template
|
||||
onNewPane : true
|
||||
});
|
||||
%>
|
||||
```
|
||||
|
||||
### 连接对象
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
ea.addText(-130,-100,"Connecting two objects");
|
||||
const a = ea.addRect(-100,-100,100,100);
|
||||
const b = ea.addEllipse(200,200,100,100);
|
||||
ea.connectObjects(a,"bottom",b,"left",{numberOfPoints: 2}); //see how the line breaks differently when moving objects around
|
||||
ea.style.strokeColor = "red";
|
||||
ea.connectObjects(a,"right",b,"top",1);
|
||||
await ea.create();
|
||||
%>
|
||||
```
|
||||
### 使用模板
|
||||
这个示例与第一个类似,但旋转了 90°,并使用了模板,同时指定了文件名和保存图形的文件夹,并在新的标签页中打开新图形。
|
||||
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
ea.style.angle = Math.PI/2;
|
||||
ea.style.strokeWidth = 3.5;
|
||||
ea.addRect(-150,-50,450,300);
|
||||
ea.addText(-100,70,"Left to right");
|
||||
ea.addArrow([[-100,100],[100,100]]);
|
||||
|
||||
ea.style.strokeColor = "red";
|
||||
await ea.addText(100,-30,"top to bottom",{width:200,textAlign:"center"});
|
||||
ea.addArrow([[200,0],[200,200]]);
|
||||
await ea.create({filename:"My Drawing",foldername:"myfolder/fordemo/",templatePath:"Excalidraw/Template2.excalidraw",onNewPane:true});
|
||||
%>
|
||||
```
|
||||
|
||||
### 从文本大纲生成简单思维导图
|
||||
这是一个稍微复杂一些的示例。这个示例将从一个表格化的大纲生成思维导图。
|
||||
|
||||

|
||||
|
||||
输入示例:
|
||||
|
||||
```
|
||||
- Test 1
|
||||
- Test 1.1
|
||||
- Test 2
|
||||
- Test 2.1
|
||||
- Test 2.2
|
||||
- Test 2.2.1
|
||||
- Test 2.2.2
|
||||
- Test 2.2.3
|
||||
- Test 2.2.3.1
|
||||
- Test 3
|
||||
- Test 3.1
|
||||
```
|
||||
|
||||
脚本:
|
||||
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
```javascript
|
||||
<%*
|
||||
const IDX = Object.freeze({"depth":0, "text":1, "parent":2, "size":3, "children": 4, "objectId":5});
|
||||
|
||||
//check if an editor is the active view
|
||||
const editor = this.app.workspace.activeLeaf?.view?.editor;
|
||||
if(!editor) return;
|
||||
|
||||
//initialize the tree with the title of the document as the first element
|
||||
let tree = [[0,this.app.workspace.activeLeaf?.view?.getDisplayText(),-1,0,[],0]];
|
||||
const linecount = editor.lineCount();
|
||||
|
||||
//helper function, use regex to calculate indentation depth, and to get line text
|
||||
function getLineProps (i) {
|
||||
props = editor.getLine(i).match(/^(\t*)-\s+(.*)/);
|
||||
return [props[1].length+1, props[2]];
|
||||
}
|
||||
|
||||
//a vector that will hold last valid parent for each depth
|
||||
let parents = [0];
|
||||
|
||||
//load outline into tree
|
||||
for(i=0;i<linecount;i++) {
|
||||
[depth,text] = getLineProps(i);
|
||||
if(depth>parents.length) parents.push(i+1);
|
||||
else parents[depth] = i+1;
|
||||
tree.push([depth,text,parents[depth-1],1,[]]);
|
||||
tree[parents[depth-1]][IDX.children].push(i+1);
|
||||
}
|
||||
|
||||
//recursive function to crawl the tree and identify height aka. size of each node
|
||||
function crawlTree(i) {
|
||||
if(i>linecount) return 0;
|
||||
size = 0;
|
||||
if((i+1<=linecount && tree[i+1][IDX.depth] <= tree[i][IDX.depth])|| i == linecount) { //I am a leaf
|
||||
tree[i][IDX.size] = 1;
|
||||
return 1;
|
||||
}
|
||||
tree[i][IDX.children].forEach((node)=>{
|
||||
size += crawlTree(node);
|
||||
});
|
||||
tree[i][IDX.size] = size;
|
||||
return size;
|
||||
}
|
||||
|
||||
crawlTree(0);
|
||||
|
||||
//Build the mindmap in Excalidraw
|
||||
const width = 300;
|
||||
const height = 100;
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
|
||||
//stores position offset of branch/leaf in height units
|
||||
offsets = [0];
|
||||
|
||||
for(i=0;i<=linecount;i++) {
|
||||
depth = tree[i][IDX.depth];
|
||||
if (depth == 1) ea.style.strokeColor = '#'+(Math.random()*0xFFFFFF<<0).toString(16);
|
||||
tree[i][IDX.objectId] = ea.addText(depth*width,((tree[i][IDX.size]/2)+offsets[depth])*height,tree[i][IDX.text],{box:true});
|
||||
//set child offset equal to parent offset
|
||||
if((depth+1)>offsets.length) offsets.push(offsets[depth]);
|
||||
else offsets[depth+1] = offsets[depth];
|
||||
offsets[depth] += tree[i][IDX.size];
|
||||
if(tree[i][IDX.parent]!=-1) {
|
||||
ea.connectObjects(tree[tree[i][IDX.parent]][IDX.objectId],"right",tree[i][IDX.objectId],"left",{startArrowHead: 'dot'});
|
||||
}
|
||||
}
|
||||
|
||||
await ea.create({onNewPane: true});
|
||||
%>
|
||||
```
|
||||
290
docs/zh-cn/README.md
Normal file
@@ -0,0 +1,290 @@
|
||||
# Excalidraw
|
||||
|
||||
> 此说明当前更新至 `5569cff`。
|
||||
|
||||
【[English](../../README.md) | 简体中文】
|
||||
|
||||
👉👉👉 快来查看并为新的 [Obsidian-Excalidraw 社区维基](https://excalidraw-obsidian.online/Hobbies/Excalidraw+Blog/WIKI/Welcome+to+the+WIKI)贡献你的力量吧
|
||||
|
||||
Obsidian-Excalidraw 插件将 [Excalidraw](https://excalidraw.com/) 这一功能丰富的草图工具集成到 Obsidian 中。您可以在您的库中存储和编辑 Excalidraw 文件,可以将图形嵌入到文档中,还可以在 Excalidraw 中链接到文档和其他图形。有关 Excalidraw 功能的展示,请查看我的博客文章 [这里](https://www.zsolt.blog/2021/03/showcasing-excalidraw.html) 或观看以下视频。
|
||||
|
||||
## 视频演示
|
||||
|
||||
<a href="https://youtu.be/P_Q6avJGoWI" target="_blank"><img src="https://github.com/zsviczian/obsidian-excalidraw-plugin/assets/14358394/da34bb33-7610-45e6-b36f-cb7a02a9141b" width="300"/></a>
|
||||
<a href="https://youtu.be/o0exK-xFP3k" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/156931370-aa4d88de-c4a8-46cc-aeb2-dc09aa0bea39.jpg" width="300"/></a>
|
||||
<a href="https://youtu.be/QKnQgSjJVuc" target="_blank"><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/thumbnail-getting-started.jpg" width="300"/></a>
|
||||
|
||||
### 这是我完整的视频目录:
|
||||
|
||||
<a href="https://excalidraw-obsidian.online/Hobbies/Excalidraw+Blog/Catalogue+of+Videos"><img width="380" alt="image" src="https://github.com/zsviczian/obsidian-excalidraw-plugin/assets/14358394/2577e5ad-7a21-4c62-acd5-4fe80c8a8a95"></a>
|
||||
<br>
|
||||
|
||||
<details><summary>10 部分(稍微过时)视频演示</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 入门</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 基本形状和功能</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 元素分组</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 模板库</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 嵌入</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 链接</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 模板</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 自动化</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 杂项</a><br>
|
||||
</details>
|
||||
|
||||
<details><summary>将内容嵌入 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;"/> 图像元素</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 演示</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 嵌入</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 嵌入高级功能</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;"/> 链接到元素、垂直文本对齐、Markdown 样式</a><br>
|
||||
</details>
|
||||
<details><summary>脚本引擎商店 - Excalidraw 自动化</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;"/> 介绍脚本引擎</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;"/> 脚本引擎商店</a><br>
|
||||
</details>
|
||||
<details><summary>使用颜色</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;"/> 颜色 - Excalidraw 基础(自定义)</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 调色板(自定义)</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;"/> “艺术”颜色渐变</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;"/> 美丽草图的简单规则</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 脚本编写</a><br>
|
||||
</details>
|
||||
<details><summary>链接和块引用</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 种策略 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;"/> 图像的块引用部分</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;"/> 链接到元素、垂直文本对齐、Markdown 样式</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;"/> Excalidraw 原生超链接使用指南</a><br>
|
||||
</details>
|
||||
<details><summary>强大工具</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;"/> 便签(自动换行)</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;"/> 本地字体</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 导入</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;"/> 绑定/解绑文本与容器,前置标签自定义导出</a><br>
|
||||
<a href="https://youtu.be/uZz5MgzWXiM" target="_blank"><img src="https://user-images.githubusercontent.com/14358394/211054371-8872e01a-77d6-4afc-a0c2-86a55410a8d3.png" width="100" style="vertical-align: middle;"/> 自定义笔支持</a><br>
|
||||
</details>
|
||||
<details><summary>生活质量改善</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;"/> 移动支持</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;"/> 托盘模式和可自定义调色板</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;"/> 压缩 JSON 和改进的保存/同步支持</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;"/> Obsidian 工具面板</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;"/> 橡皮擦、左利手模式、改进的文件名配置</a><br>
|
||||
</details>
|
||||
|
||||
### Beta 测试
|
||||
|
||||
该插件遵循每月发布的计划。如果您希望获得更频繁的更新,包括新功能(例如,excalidraw.com 上的新内容,但尚未在 Obsidian 中提供)和小的 bug 修复,请加入 beta 社区。
|
||||
|
||||
[](https://youtu.be/2poSS-Z91lY)
|
||||
|
||||
[](https://github.com/user-attachments/assets/120a0790-7239-48ae-bfbd-eb249f8b518d)
|
||||
|
||||
---
|
||||
|
||||
## 功能
|
||||
|
||||
- 该插件将 Excalidraw 无缝集成到 Obsidian 中,包括命令面板操作、文件资源管理器功能、选项菜单命令和工具栏按钮。
|
||||
- 在工具栏按钮或文件资源管理器中 <kbd>CTRL/CMD+鼠标左键</kbd> 以在新面板中创建/打开绘图。
|
||||
|
||||
### 设置
|
||||
|
||||
设置将允许您根据需要自定义 Excalidraw。该插件提供了大量设置。我尝试为这些设置添加有意义的解释,所以请耐心查找,对于大多数请求,已经存在相关设置。
|
||||
|
||||
插件设置分为以下几个部分:
|
||||
|
||||
- **基本设置**:例如使用的默认文件夹。
|
||||
- **保存**:压缩和自动保存间隔。
|
||||
- **文件名**:配置自动生成的 Excalidraw 文件名。
|
||||
- **显示**:影响 Excalidraw 处理的设置(例如:左利手模式、主题设置、鼠标滚轮和捏合缩放设置、适应缩放设置)。
|
||||
- **链接和嵌入**:影响链接和嵌入项在 Excalidraw 画布上行为的设置。
|
||||
- **Markdown 嵌入设置**:这些设置控制从您的 Vault 嵌入到 Excalidraw 绘图中的 Markdown 文档的行为。
|
||||
- **嵌入与导出**:控制 Excalidraw 图像在嵌入到 Markdown 文档时的显示方式的设置。
|
||||
- **自动导出设置**:您可以配置 Excalidraw 在每次保存时创建绘图的 PNG 或 SVG 副本。
|
||||
- **兼容性功能**:如果您在 Obsidian 之外编辑 Excalidraw 绘图(例如在 LogSeq、Visual Studio、网页等),请检查这些设置。
|
||||
- **实验性功能**:有一些高级功能作为“巧妙”的 hacks 实现,包括定义本地字体、添加自定义图标以区分 Obsidian 文件资源管理器中的 Excalidraw 文件、OCR 设置等。
|
||||
- **已安装脚本的设置**:从脚本库安装的一些脚本附带设置。脚本设置在您第一次运行脚本时安装。因此,要访问脚本的设置,请安装脚本,首次运行后在插件设置中查找设置。
|
||||
|
||||
#### 模板
|
||||
|
||||
- 新绘图的模板。该模板将恢复笔画属性。这意味着您可以在模板中设置笔画颜色、笔画宽度、不透明度、字体系列、字体大小、填充样式、笔画样式等的默认值。这同样适用于 ExcalidrawAutomate。对于 1.6.13 或更高版本,在编辑模板中的 JSON 之前,请确保在设置中启用"在 Markdown 视图中解压缩 Excalidraw JSON"。完成更改后可以禁用此选项。
|
||||
- 通过模板,您可以自定义 Excalidraw 使用的调色板。
|
||||
- 切换到 Markdown 视图。
|
||||
- 滚动到文件底部,找到 `"AppState": {`。
|
||||
- 在 AppState 部分末尾找到 `"customColorPalette": {`。
|
||||
- 您可以通过添加以下三个变量中的任何一个或全部来指定 Excalidraw 使用的 3 个调色板:
|
||||
- `"canvasBackground":[], "elementBackground":[], "elementStroke": []`。
|
||||
- 在每个变量的数组中添加有效 HTML 颜色的逗号分隔列表(例如,`#FF0000` 表示红色)。
|
||||
- 有关更多帮助,请查看我上面的录像。
|
||||
|
||||
#### 导出
|
||||
|
||||
- 如果便携性对您很重要:
|
||||
- 自动导出 SVG 和/或 PNG 文件,包括同步保持功能,这样您可以将 SVG/PNG 嵌入到文档中,而不是嵌入 Excalidraw 文件。
|
||||
- 您可以通过添加 `excalidraw-autoexport` 前置字段键来覆盖单个文件的导出设置。该键的有效值为 `none`、`both`、`png` 和 `svg`。
|
||||
|
||||
- 指定嵌入绘图的默认宽度。
|
||||
- 兼容性功能以自动导出和保持同步 Markdown Excalidraw 文件及旧版 `.excalidraw` 文件。
|
||||
- 实验性功能可在文件资源管理器中添加自定义标签以标记绘图文件。
|
||||
- 启用/禁用自动保存。
|
||||
|
||||
### 将您的绘图嵌入到 Markdown 文档中
|
||||
|
||||
- 您可以使用以下格式自定义嵌入图像的大小和位置:
|
||||
- `![[image.excalidraw|100]]`,
|
||||
- `![[image.excalidraw|100x100]]`,
|
||||
- `![[image.excalidraw|100|left]]`,
|
||||
- `![[image.excalidraw|right-wrap]]`,
|
||||
- `![[<filename.excalidraw>|<width>x<height>|<alignment>]]`。
|
||||
- 您可以通过 CSS 添加自定义 [对齐方式](https://www.scaler.com/topics/align-image-in-html/)。
|
||||
- 出现在 `<alignment>` 中的任何文本将被添加到渲染的 SVG 元素样式和包装 DIV 元素中。
|
||||
- 有关更多信息,请参见 [styles.css](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/styles.css)。
|
||||
- Excalidraw 绘图在 Obsidian Publish 中不显示。如果您希望在发布的文档中使用 Excalidraw,可以在插件设置中的 `Embed & Export` 下进行配置,以便在创建新文件时自动将绘图的 PNG 或 SVG 版本插入到文档中。请参见 `type of file to insert into document`。
|
||||
- 在 `Export settings` 下,您还可以配置自动导出图像的深色和浅色版本,以便您的发布网站支持深色和浅色模式。
|
||||
|
||||
### 超链接和拖放支持
|
||||
|
||||

|
||||
|
||||
#### 超链接
|
||||
|
||||
- 支持超链接,例如:
|
||||
- `https://zsolt.blog`,
|
||||
- `[Obsidian](https://obsidian.md)`,以及
|
||||
- 内部链接,例如在绘图文本中使用 `[[My file in vault|Alias]]`。
|
||||
- 如果您启用了 Obsidian 设置中的“文件与链接/自动更新内部链接”,则文件移动或重命名时链接会自动更新。
|
||||
- 绘图中的链接会出现在文档的反向链接中。
|
||||
- 支持嵌入:
|
||||
- `![[myfile#^blockref]]` 将绘图转换为该块的嵌入文本。
|
||||
- `![[myfile#section]]` 也有效,这将嵌入该部分。
|
||||
- 您还可以通过在嵌入后加上最大字符数的花括号来指定嵌入文本的换行,例如 `![[myfile#^blockref]]{40}` 将在 40 个字符处换行。
|
||||
- 为了方便,您还可以使用命令面板将链接插入到绘图中。
|
||||
- <kbd>CTRL/CMD + 鼠标悬停</kbd> 可以调出链接的 Obsidian 快速预览。(在 Mac 上为 <kbd>CTRL+CMD+鼠标悬停</kbd>)。
|
||||
- 使用块引用,您还可以在其他文档中引用和嵌入绘图中出现的文本。
|
||||
|
||||
#### 拖放支持
|
||||
|
||||
- 您可以从 Obsidian 文件资源管理器中拖动文件,它们将成为 Excalidraw 中指向这些文件的链接。有关各种修饰键组合,请参见上面的表格。
|
||||
- 注意:将图像锚定到其 100% 尺寸是一个非常小众的功能,具有非常特定的行为,我主要是为自己开发的。
|
||||
- (甚至 Excalidraw Obsidian 中的其他功能更是如此 - 也是主要为自己开发的 😉)。
|
||||
- 每次打开 Excalidraw 绘图时,这将重置您嵌入的图像为 100% 尺寸,或者如果您在画布上嵌入了使用此功能插入的 Excalidraw 绘图,每次更新嵌入的绘图时,它将缩放回 100% 尺寸。
|
||||
- 这意味着即使您在绘图中调整了图像的大小,下次打开文件或修改原始嵌入对象时,它也会重置为 100%。此功能在将绘图分解为单独的 Excalidraw 文件时非常有用,但当它们组合到单个画布上时,您希望各个部分保持其实际大小。我使用此功能从原子绘图构建“一页书”摘要。
|
||||
- 您可以将文本从 Markdown 视图拖放到 Excalidraw 中。
|
||||
- 您可以从浏览器中拖放网页地址,它们将成为链接。
|
||||
- 您可以拖放 YouTube 链接和缩略图,它们将在 Excalidraw 中成为带缩略图的 YouTube 链接。
|
||||
|
||||
### LaTeX
|
||||
|
||||
使用命令面板操作“插入 LaTeX 公式”插入 LaTeX 公式。您可以在 Markdown 视图中编辑公式,或者通过 <kbd>CTRL/CMD + 鼠标左键</kbd> 点击公式进行编辑。
|
||||
|
||||
### 图像支持
|
||||
|
||||
- 在 iOS 和 Android 上,您可以通过按下 Excalidraw 中的添加图像按钮从相机添加图像。
|
||||
- 您可以将图像复制/粘贴到绘图中。图像将保存在您的 Vault 中。
|
||||
- 您可以按照上面的说明拖放图像。
|
||||
- URL 链接到网络上的图像:您可以从网页将图像拖放到 Excalidraw。如果在将图像拖放到 Excalidraw 时按住 CTRL 键,图像将不会保存到您的 Vault 中。Excalidraw 将从 URL 加载图像。请注意,如果您没有互联网连接,或者这些图像从互联网上被删除,它们也会从您的绘图中消失。
|
||||
- 如果您将图像 URL 粘贴到 Excalidraw(只需点击 URL 复制,然后在 Excalidraw 画布上点击粘贴),图像将以链接形式插入到网络图像上。同样,图像不会保存到您的 Vault 中,只有链接会被保存。
|
||||
- 如果您拖放 YouTube 视频链接,它将转换为一个缩略图,并带有指向视频的元素链接。
|
||||
|
||||
### 引用图像部分的块
|
||||
|
||||
有关更多详细信息,请参见此 [视频](https://youtu.be/yZQoJg2RCKI)。
|
||||
- 当通过链接引用 Excalidraw 文件中的画布元素时,可以使用:
|
||||
- 元素 ID 或章节标题(即包含 `# <章节标题>` 的文本元素)
|
||||
- 例如 `[[file#^elementID]]`,
|
||||
- 您可以添加 `group=` 前缀,
|
||||
- 例如 `[[file#^group=elementID]]`,或
|
||||
- `area=` 前缀,
|
||||
- 例如 `[[file#area=Section heading]]`。
|
||||
- 如果找到 `group=` 前缀,Excalidraw 将选择与通过元素 ID(块引用)或章节标题引用的元素在同一组中的元素。
|
||||
- 如果找到 `area=` 前缀,Excalidraw 将在引用的元素周围插入图像的剪切部分。
|
||||
- 请注意,当将 Excalidraw 嵌入为 PNG 到您的 Markdown 文档时,不支持 `area=` 选择器。
|
||||
- 引用文本元素的元素 ID 而不带 `group=` 或 `area=` 前缀将以普通文本嵌入该元素。引用非文本元素(例如矩形、椭圆等)而不带 `group=` 或 `area=` 前缀将导致 Obsidian 错误,因为这些元素 ID 在 Excalidraw Markdown 文件中不能够作为块引用。
|
||||
|
||||
### Markdown
|
||||
|
||||
- 从 1.2.0 版本开始,绘图文件存储在 Markdown 文件中。
|
||||
- 您可以为绘图添加标签。
|
||||
- 您可以在绘图的 YAML 前置字段中添加元数据。
|
||||
- 您在前置字段和 `# Text Elements` 标题之间添加的任何内容将被 Excalidraw 忽略,即您可以在这里添加任何内容,它将作为文档的一部分被保留。
|
||||
- Excalidraw 文档现在会在图形视图中显示。
|
||||
- 以下前置字段键将自定义绘图的显示方式 - 覆盖一般设置:
|
||||
- `excalidraw-link-prefix: "📍"` 内部链接的预览前缀
|
||||
- `excalidraw-url-prefix: "🌐"` 外部链接的预览前缀
|
||||
- `excalidraw-link-brackets: true|false` 是否在预览中显示链接周围的括号
|
||||
- `excalidraw-default-mode: view|zen` 默认以查看模式或禅模式打开此文档。默认查看模式非常适合演示幻灯片。
|
||||
- 前置字段标签用于在文件级别自定义图像导出 [519](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/519)。如果这些键存在,它们将覆盖默认的 Excalidraw 嵌入和导出设置。
|
||||
- `excalidraw-export-transparent: true`: true == 透明 / false == 有背景。
|
||||
- `excalidraw-export-dark`: true == 深色模式 / false == 浅色模式。
|
||||
- `excalidraw-export-padding`:指定图像的导出边距。
|
||||
- `excalidraw-export-pngscale`:这仅影响导出为 PNG。指定图像的导出比例。典型范围在 0.5 到 5 之间,但您也可以尝试其他值。
|
||||
- 从 1.6.13 版本开始,如果您想修改任何 JSON 内容,请在设置中启用"在 Markdown 视图中解压缩 Excalidraw JSON"。
|
||||
|
||||
### 将完整的 Markdown 文件嵌入到您的绘图中
|
||||
|
||||
从 Obsidian 文件资源管理器中拖动所需文件,同时按住 <kbd>SHIFT</kbd> 将文件放到画布上。
|
||||
- 使用命令面板操作:`从 Vault 插入 Markdown 文件`
|
||||
- 使用自定义的 woff、woff2 或 TTF 字体来显示文档,您可以在 Excalidraw 设置中设置默认字体。
|
||||
- 您可以为渲染 Markdown 文档的快照图像设置自定义 CSS。仅支持操作系统标准字体作为字体系列([Win10](https://docs.microsoft.com/en-us/typography/fonts/windows_10_font_list)、[Mac & iOS](https://developer.apple.com/fonts/system-fonts/)),此外,您可以使用上述设置添加一个额外的自定义字体。
|
||||
- (要查看演示,请观看此 [视频](https://youtu.be/K6qZkTz8GHs) 并查看此
|
||||
- [示例 CSS](https://github.com/zsviczian/obsidian-excalidraw-plugin/discussions/281))。
|
||||
- 为了帮助样式设置,您可以查看 Excalidraw 创建的 Markdown 文档的 SVG 快照。
|
||||
- 打开 Obsidian 开发者控制台 (<kbd>CTRL+Shift+i</kbd>/<kbd>CMD+OPT+i</kbd>),并
|
||||
- 执行以下命令:`ExcalidrawAutomate.mostRecentMarkdownSVG`
|
||||
- 您可以通过将以下前置字段键添加到您的 Markdown 文档,按文件控制嵌入 Markdown 文件的外观:
|
||||
- `excalidraw-font: Virgil|Cascadia|font_file_name.extension`
|
||||
- `excalidraw-font-color: css-color-name|#HEXcolor|any-other-html-standard-format`,
|
||||
- 您可以在 [这里](https://www.w3schools.com/colors/colors_names.asp) 找到 CSS 颜色名称。
|
||||
- `excalidraw-border-color: css-color-name|#HEXcolor|any-other-html-standard-format`
|
||||
- `excalidraw-css: "css-filename|css snippet"`
|
||||
- 切换到 Markdown 视图或使用 <kbd>WIN+CTRL</kbd>/<kbd>CMD+CTRL</kbd> 点击图像以编辑嵌入的属性:
|
||||
- `[[filename#^blockref|WIDTHxMAXHEIGHT]]`
|
||||
|
||||
### 自定义字体、自定义笔、OCR 支持、SVG 导入
|
||||
|
||||
- 在插件设置中,您可以添加自定义的本地字体。有关更多详细信息,请参见此 [视频](https://youtu.be/eKFmrSQhFA4)。
|
||||
- 该插件包括使用 Taskbone OCR 的 OCR 支持。有关更多详细信息,请参见此 [视频](https://youtu.be/7gu4ETx7zro)。
|
||||
- 您可以将 SVG 文件转换为 Excalidraw 绘图(有一些限制)。有关更多详细信息,请参见此 [视频](https://youtu.be/vlC1-iBvIfo)。
|
||||
- 您可以定义自定义笔和荧光笔,并将其固定到侧边栏。有关更多详细信息,请参见此 [视频](https://youtu.be/OjNhjaH2KjI)。使用 ExcalidrawAutomate,您可以添加对 [自动切换](<ea-scripts/Auto Draw for Pen.md>) 笔的支持,以及对 [硬件橡皮擦按钮](<ea-scripts/Hardware Eraser Support.md>) 的支持。
|
||||
|
||||
### 脚本引擎
|
||||
|
||||
- 从 1.5.0 版本开始,您可以轻松执行 ExcalidrawAutomate 宏,并为它们分配命令面板快捷键,使用脚本引擎。您可以在 [这里](ea-scripts/README.md) 找到介绍视频和不断增加的可安装脚本库。
|
||||
- 您可以通过将脚本和随附的 SVG 图标文件移动到文件夹中,将脚本组织成组,放在 Excalidraw 的 Obsidian 工具面板中。请参见演示 [视频](https://youtu.be/wTtaXmRJ7wg?t=16)。
|
||||
|
||||
### 其他
|
||||
|
||||
- 左利手模式
|
||||
- 包含完整的
|
||||
- [QuickAdd](https://github.com/chhoumann/quickadd),
|
||||
- [Templater](https://silentvoid13.github.io/Templater/) 和
|
||||
- [Dataview](https://blacksmithgu.github.io/obsidian-dataview/docs/api/intro/) 支持,通过 ExcalidrawAutomate 实现。
|
||||
- 查看 [详细帮助 + 示例](https://zsviczian.github.io/obsidian-excalidraw-plugin/)。
|
||||
- 我还有一个 [YouTube ExcalidrawAutomate 播放列表](https://www.youtube.com/playlist?list=PL6mqgtMZ4NP1IR4nXxSlMA4PA5E-qpyHZ),里面有很多示例。
|
||||
- 需要 Obsidian Sync 订阅:完整的绘图文件历史记录和设备之间的同步。
|
||||
- 多语言支持:如果您想通过翻译插件来帮助,请与我联系。
|
||||
|
||||
## 反馈、问题、想法、问题
|
||||
|
||||
请在 [forum.obsidian.md](https://forum.obsidian.md/t/excalidraw-full-featured-sketching-plugin-in-obsidian) 上参与关于 Excalidraw 插件的讨论。
|
||||
|
||||
请前往 [GitHub](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues) 报告错误或请求增强功能。
|
||||
|
||||
---
|
||||
|
||||
## 感谢支持
|
||||
|
||||
如果您喜欢 Excalidraw,请通过在 [https://ko-fi/zsolt](https://ko-fi.com/zsolt) 上请我喝杯咖啡来支持我的工作和热情。
|
||||
|
||||
请通过在 Twitter、Reddit 或其他您常用的社交媒体平台上分享 Obsidian Excalidraw 插件来帮助传播消息。
|
||||
|
||||
您可以在 Twitter 上找到我 [@zsviczian](https://twitter.com/zsviczian),以及我的博客 [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)
|
||||
|
||||
---
|
||||
|
||||
## Excalidraw 的朋友们
|
||||
如果您喜欢 Excalidraw,可以考虑尝试 [ExcaliBrain](https://github.com/zsviczian/excalibrain)(也可通过 Obsidian 社区插件获得)。
|
||||
|
||||
<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>
|
||||
1119
docs/zh-cn/docs/API/ExcalidrawAutomate.d.ts
vendored
Normal file
782
docs/zh-cn/docs/API/attributes_functions_overview.md
Normal file
@@ -0,0 +1,782 @@
|
||||
# [◀ Excalidraw 自动化使用指南](../readme.md)
|
||||
|
||||
## 属性和函数概览
|
||||
|
||||
以下是 ExcalidrawAutomate 实现的接口:
|
||||
|
||||
你可以在这里找到源文件: [ExcalidrawAutomate.d.ts](ExcalidrawAutomate.d.ts)。
|
||||
|
||||
```javascript
|
||||
/// <reference types="react" />
|
||||
import ExcalidrawPlugin from "src/main";
|
||||
import { FillStyle, StrokeStyle, ExcalidrawElement, ExcalidrawBindableElement, FileId, NonDeletedExcalidrawElement, ExcalidrawImageElement, StrokeRoundness, RoundnessType } from "@zsviczian/excalidraw/types/element/types";
|
||||
import { Editor, OpenViewState, TFile, WorkspaceLeaf } from "obsidian";
|
||||
import * as obsidian_module from "obsidian";
|
||||
import ExcalidrawView, { ExportSettings } from "src/ExcalidrawView";
|
||||
import { AppState, BinaryFileData, DataURL, ExcalidrawImperativeAPI, Point } from "@zsviczian/excalidraw/types/types";
|
||||
import { EmbeddedFilesLoader } from "src/EmbeddedFileLoader";
|
||||
import { ConnectionPoint, DeviceType } from "src/types";
|
||||
import { ColorMaster } from "colormaster";
|
||||
import { TInput } from "colormaster/types";
|
||||
import { ClipboardData } from "@zsviczian/excalidraw/types/clipboard";
|
||||
import { PaneTarget } from "src/utils/modifierkeyHelper";
|
||||
export declare class ExcalidrawAutomate {
|
||||
/**
|
||||
* Utility function that returns the Obsidian Module object.
|
||||
*/
|
||||
get obsidian(): typeof obsidian_module;
|
||||
get DEVICE(): DeviceType;
|
||||
getAttachmentFilepath(filename: string): Promise<string>;
|
||||
/**
|
||||
* Prompts the user with a dialog to select new file action.
|
||||
* - create markdown file
|
||||
* - create excalidraw file
|
||||
* - cancel action
|
||||
* The new file will be relative to this.targetView.file.path, unless parentFile is provided.
|
||||
* If shouldOpenNewFile is true, the new file will be opened in a workspace leaf.
|
||||
* targetPane control which leaf will be used for the new file.
|
||||
* Returns the TFile for the new file or null if the user cancelled the action.
|
||||
* @param newFileNameOrPath
|
||||
* @param shouldOpenNewFile
|
||||
* @param targetPane //type PaneTarget = "active-pane"|"new-pane"|"popout-window"|"new-tab"|"md-properties";
|
||||
* @param parentFile
|
||||
* @returns
|
||||
*/
|
||||
newFilePrompt(newFileNameOrPath: string, shouldOpenNewFile: boolean, targetPane?: PaneTarget, parentFile?: TFile): Promise<TFile | null>;
|
||||
/**
|
||||
* Generates a new Obsidian Leaf following Excalidraw plugin settings such as open in Main Workspace or not, open in adjacent pane if available, etc.
|
||||
* @param origo // the currently active leaf, the origin of the new leaf
|
||||
* @param targetPane //type PaneTarget = "active-pane"|"new-pane"|"popout-window"|"new-tab"|"md-properties";
|
||||
* @returns
|
||||
*/
|
||||
getLeaf(origo: WorkspaceLeaf, targetPane?: PaneTarget): WorkspaceLeaf;
|
||||
/**
|
||||
* Returns the editor or leaf.view of the currently active embedded obsidian file.
|
||||
* If view is not provided, ea.targetView is used.
|
||||
* If the embedded file is a markdown document the function will return
|
||||
* {file:TFile, editor:Editor} otherwise it will return {view:any}. You can check view type with view.getViewType();
|
||||
* @param view
|
||||
* @returns
|
||||
*/
|
||||
getActiveEmbeddableViewOrEditor(view?: ExcalidrawView): {
|
||||
view: any;
|
||||
} | {
|
||||
file: TFile;
|
||||
editor: Editor;
|
||||
} | null;
|
||||
plugin: ExcalidrawPlugin;
|
||||
elementsDict: {
|
||||
[key: string]: any;
|
||||
};
|
||||
imagesDict: {
|
||||
[key: FileId]: any;
|
||||
};
|
||||
mostRecentMarkdownSVG: SVGSVGElement;
|
||||
style: {
|
||||
strokeColor: string;
|
||||
backgroundColor: string;
|
||||
angle: number;
|
||||
fillStyle: FillStyle;
|
||||
strokeWidth: number;
|
||||
strokeStyle: StrokeStyle;
|
||||
roughness: number;
|
||||
opacity: number;
|
||||
strokeSharpness?: StrokeRoundness;
|
||||
roundness: null | {
|
||||
type: RoundnessType;
|
||||
value?: number;
|
||||
};
|
||||
fontFamily: number;
|
||||
fontSize: number;
|
||||
textAlign: string;
|
||||
verticalAlign: string;
|
||||
startArrowHead: string;
|
||||
endArrowHead: string;
|
||||
};
|
||||
canvas: {
|
||||
theme: string;
|
||||
viewBackgroundColor: string;
|
||||
gridSize: number;
|
||||
};
|
||||
colorPalette: {};
|
||||
constructor(plugin: ExcalidrawPlugin, view?: ExcalidrawView);
|
||||
/**
|
||||
*
|
||||
* @returns the last recorded pointer position on the Excalidraw canvas
|
||||
*/
|
||||
getViewLastPointerPosition(): {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @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>;
|
||||
/**
|
||||
* @param file: TFile
|
||||
* @returns ExcalidrawScene
|
||||
*/
|
||||
getSceneFromFile(file: TFile): Promise<{
|
||||
elements: ExcalidrawElement[];
|
||||
appState: AppState;
|
||||
}>;
|
||||
/**
|
||||
* get all elements from ExcalidrawAutomate elementsDict
|
||||
* @returns elements from elementsDict
|
||||
*/
|
||||
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-padding"?: number;
|
||||
"excalidraw-export-pngscale"?: number;
|
||||
"excalidraw-default-mode"?: "view" | "zen";
|
||||
"excalidraw-onload-script"?: string;
|
||||
"excalidraw-linkbutton-opacity"?: number;
|
||||
"excalidraw-autoexport"?: boolean;
|
||||
};
|
||||
plaintext?: string;
|
||||
}): 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;
|
||||
addIFrame(topX: number, topY: number, width: number, height: number, url?: string, file?: TFile): string;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param width
|
||||
* @param height
|
||||
* @returns
|
||||
*/
|
||||
addEmbeddable(topX: number, topY: number, width: number, height: number, url?: string, file?: TFile): string;
|
||||
/**
|
||||
*
|
||||
* @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;
|
||||
/**
|
||||
* Refresh the size of a text element to fit its contents
|
||||
* @param id - the id of the text element
|
||||
*/
|
||||
refreshTextElementSize(id: string): void;
|
||||
/**
|
||||
*
|
||||
* @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?: "left" | "center" | "right";
|
||||
box?: boolean | "box" | "blob" | "ellipse" | "diamond";
|
||||
boxPadding?: number;
|
||||
boxStrokeColor?: string;
|
||||
textVerticalAlign?: "top" | "middle" | "bottom";
|
||||
}, 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 | string, scale?: boolean, //default is true which will scale the image to MAX_IMAGE_SIZE, false will insert image at 100% of its size
|
||||
anchor?: boolean): 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;
|
||||
targetView: ExcalidrawView;
|
||||
/**
|
||||
* sets the target view for EA. All the view operations and the access to Excalidraw API will be performend on this view
|
||||
* if view is null or undefined, the function will first try setView("active"), then setView("first").
|
||||
* @param view
|
||||
* @returns targetView
|
||||
*/
|
||||
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;
|
||||
setViewModeEnabled(enabled: boolean): void;
|
||||
/**
|
||||
* This function gives you a more hands on access to Excalidraw.
|
||||
* @param scene - The scene you want to load to Excalidraw
|
||||
* @param restore - Use this if the scene includes legacy excalidraw file elements that need to be converted to the latest excalidraw data format (not a typical usecase)
|
||||
* @returns
|
||||
*/
|
||||
viewUpdateScene(scene: {
|
||||
elements?: ExcalidrawElement[];
|
||||
appState?: AppState;
|
||||
files?: BinaryFileData;
|
||||
commitToHistory?: boolean;
|
||||
}, restore?: 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;
|
||||
/**
|
||||
* 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
|
||||
* @param selectElements
|
||||
* @param elements
|
||||
*/
|
||||
viewZoomToElements(selectElements: boolean, elements: ExcalidrawElement[]): void;
|
||||
/**
|
||||
* 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
|
||||
* @param shouldRestoreElements - restore elements - auto-corrects broken, incomplete or old elements included in the update
|
||||
* @returns
|
||||
*/
|
||||
addElementsToView(repositionToCursor?: boolean, save?: boolean, newElementsOnTop?: boolean, shouldRestoreElements?: 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 false, 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;
|
||||
/**
|
||||
* If set, this callback is triggered, when Excalidraw receives an onPaste event.
|
||||
* You can use this callback in case you want to do something additional when the
|
||||
* onPaste event occurs.
|
||||
* This callback must return a boolean value.
|
||||
* In case you want to prevent the excalidraw onPaste action you must return false,
|
||||
* it will stop the native excalidraw onPaste management flow.
|
||||
*/
|
||||
onPasteHook: (data: {
|
||||
ea: ExcalidrawAutomate;
|
||||
payload: ClipboardData;
|
||||
event: ClipboardEvent;
|
||||
excalidrawFile: TFile;
|
||||
view: ExcalidrawView;
|
||||
pointerPosition: {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
}) => boolean;
|
||||
/**
|
||||
* if set, this callback is triggered, when an Excalidraw file is opened
|
||||
* You can use this callback in case you want to do something additional when the file is opened.
|
||||
* This will run before the file level script defined in the `excalidraw-onload-script` frontmatter.
|
||||
*/
|
||||
onFileOpenHook: (data: {
|
||||
ea: ExcalidrawAutomate;
|
||||
excalidrawFile: TFile;
|
||||
view: ExcalidrawView;
|
||||
}) => Promise<void>;
|
||||
/**
|
||||
* if set, this callback is triggered, when an Excalidraw file is created
|
||||
* see also: https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1124
|
||||
*/
|
||||
onFileCreateHook: (data: {
|
||||
ea: ExcalidrawAutomate;
|
||||
excalidrawFile: TFile;
|
||||
view: ExcalidrawView;
|
||||
}) => Promise<void>;
|
||||
/**
|
||||
* If set, this callback is triggered whenever the active canvas color changes
|
||||
*/
|
||||
onCanvasColorChangeHook: (ea: ExcalidrawAutomate, view: ExcalidrawView, //the excalidraw view
|
||||
color: string) => void;
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* @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[];
|
||||
/**
|
||||
* 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[];
|
||||
/**
|
||||
* Gets all the elements from elements[] that are contained in the frame.
|
||||
* @param element
|
||||
* @param elements - typically all the non-deleted elements in the scene
|
||||
* @returns
|
||||
*/
|
||||
getElementsInFrame(frameElement: ExcalidrawElement, elements: ExcalidrawElement[]): ExcalidrawElement[];
|
||||
/**
|
||||
* 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
|
||||
* @param openState - if not provided {active: true} will be used
|
||||
* @returns
|
||||
*/
|
||||
openFileInNewOrAdjacentLeaf(file: TFile, openState?: OpenViewState): WorkspaceLeaf;
|
||||
/**
|
||||
* measure text size based on current style settings
|
||||
* @param text
|
||||
* @returns
|
||||
*/
|
||||
measureText(text: string): {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
/**
|
||||
* Returns the size of the image element at 100% (i.e. the original size)
|
||||
* @param imageElement an image element from the active scene on targetView
|
||||
*/
|
||||
getOriginalImageSize(imageElement: ExcalidrawImageElement): Promise<{
|
||||
width: number;
|
||||
height: number;
|
||||
}>;
|
||||
/**
|
||||
* 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[] | string[]): 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;
|
||||
/**
|
||||
* Deprecated. Use getCM / ColorMaster instead
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
hexStringToRgb(color: string): number[];
|
||||
/**
|
||||
* Deprecated. Use getCM / ColorMaster instead
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
rgbToHexString(color: number[]): string;
|
||||
/**
|
||||
* Deprecated. Use getCM / ColorMaster instead
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
hslToRgb(color: number[]): number[];
|
||||
/**
|
||||
* Deprecated. Use getCM / ColorMaster instead
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
rgbToHsl(color: number[]): number[];
|
||||
/**
|
||||
*
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
colorNameToHex(color: string): string;
|
||||
/**
|
||||
* https://github.com/lbragile/ColorMaster
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
getCM(color: TInput): ColorMaster;
|
||||
importSVG(svgString: string): boolean;
|
||||
}
|
||||
export declare function initExcalidrawAutomate(plugin: ExcalidrawPlugin): Promise<ExcalidrawAutomate>;
|
||||
export declare function destroyExcalidrawAutomate(): void;
|
||||
export declare function _measureText(newText: string, fontSize: number, fontFamily: number, lineHeight: number): {
|
||||
w: number;
|
||||
h: number;
|
||||
baseline: number;
|
||||
};
|
||||
export declare const generatePlaceholderDataURL: (width: number, height: number) => DataURL;
|
||||
export declare function createPNG(templatePath: string, scale: number, exportSettings: ExportSettings, loader: EmbeddedFilesLoader, forceTheme: string, canvasTheme: string, canvasBackgroundColor: string, automateElements: ExcalidrawElement[], plugin: ExcalidrawPlugin, depth: number, padding?: number, imagesDict?: any): Promise<Blob>;
|
||||
export declare function createSVG(templatePath: string, embedFont: boolean, exportSettings: ExportSettings, loader: EmbeddedFilesLoader, forceTheme: string, canvasTheme: string, canvasBackgroundColor: string, automateElements: ExcalidrawElement[], plugin: ExcalidrawPlugin, depth: number, padding?: number, imagesDict?: any, convertMarkdownLinksToObsidianURLs?: boolean): Promise<SVGSVGElement>;
|
||||
export declare function estimateBounds(elements: ExcalidrawElement[]): [number, number, number, number];
|
||||
export declare function repositionElementsToCursor(elements: ExcalidrawElement[], newPosition: {
|
||||
x: number;
|
||||
y: number;
|
||||
}, center: boolean, api: ExcalidrawImperativeAPI): ExcalidrawElement[];
|
||||
export declare const insertLaTeXToView: (view: ExcalidrawView) => void;
|
||||
export declare const search: (view: ExcalidrawView) => Promise<void>;
|
||||
/**
|
||||
*
|
||||
* @param elements
|
||||
* @param query
|
||||
* @param exactMatch - when searching for section header exactMatch should be set to true
|
||||
* @returns the elements matching the query
|
||||
*/
|
||||
export declare const getTextElementsMatchingQuery: (elements: ExcalidrawElement[], query: string[], exactMatch?: boolean) => ExcalidrawElement[];
|
||||
/**
|
||||
*
|
||||
* @param elements
|
||||
* @param query
|
||||
* @param exactMatch - when searching for section header exactMatch should be set to true
|
||||
* @returns the elements matching the query
|
||||
*/
|
||||
export declare const getFrameElementsMatchingQuery: (elements: ExcalidrawElement[], query: string[], exactMatch?: boolean) => ExcalidrawElement[];
|
||||
export declare const cloneElement: (el: ExcalidrawElement) => any;
|
||||
export declare const verifyMinimumPluginVersion: (requiredVersion: string) => boolean;
|
||||
```
|
||||
19
docs/zh-cn/docs/API/canvas_style.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# [◀ Excalidraw 自动化指南](../readme.md)
|
||||
|
||||
## 画布样式设置
|
||||
设置画布的属性。
|
||||
|
||||
### theme, setTheme()
|
||||
字符串。有效值为 "light"(明亮)和 "dark"(黑暗)。
|
||||
|
||||
`setTheme()` 接受一个数字参数:
|
||||
- 0:"light"(明亮)
|
||||
- 其他任何数字:"dark"(黑暗)
|
||||
|
||||
### viewBackgroundColor
|
||||
字符串。这是对象的填充颜色。[CSS 合法颜色值](https://www.w3schools.com/cssref/css_colors_legal.asp)
|
||||
|
||||
允许的值包括 [HTML 颜色名称](https://www.w3schools.com/colors/colors_names.asp)、十六进制 RGB 字符串(例如红色使用 `#FF0000`)或 `transparent`(透明)。
|
||||
|
||||
### gridSize
|
||||
数字。网格的大小。如果设置为零,则不显示网格。
|
||||
110
docs/zh-cn/docs/API/element_style.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# [◀ Excalidraw 自动化指南](../readme.md)
|
||||
|
||||
## 元素样式设置
|
||||
|
||||
你会注意到,一些样式有setter函数。这是为了帮助你设置属性的允许值。但是你不必使用setter函数,也可以直接设置值。
|
||||
|
||||
### strokeColor
|
||||
|
||||
字符串类型。线条的颜色。[CSS合法颜色值](https://www.w3schools.com/cssref/css_colors_legal.asp)
|
||||
|
||||
允许的值包括[HTML颜色名称](https://www.w3schools.com/colors/colors_names.asp)、十六进制RGB字符串,例如红色为`#FF0000`。
|
||||
|
||||
### backgroundColor
|
||||
|
||||
字符串类型。这是对象的填充颜色。[CSS合法颜色值](https://www.w3schools.com/cssref/css_colors_legal.asp)
|
||||
|
||||
允许的值包括[HTML颜色名称](https://www.w3schools.com/colors/colors_names.asp)、十六进制RGB字符串,例如红色为`#FF0000`,或者`transparent`(透明)。
|
||||
|
||||
### angle
|
||||
|
||||
数字类型。以弧度为单位的旋转角度。90度等于`Math.PI/2`。
|
||||
|
||||
### fillStyle, setFillStyle()
|
||||
|
||||
```typescript
|
||||
type FillStyle = "hachure" | "cross-hatch" | "solid";
|
||||
setFillStyle (val:number);
|
||||
```
|
||||
|
||||
fillStyle 是一个字符串。
|
||||
|
||||
`setFillStyle()` 接受一个数字参数:
|
||||
- 0: "hachure"(斜线填充)
|
||||
- 1: "cross-hatch"(交叉填充)
|
||||
- 其他任意数字: "solid"(实心填充)
|
||||
|
||||
### strokeWidth
|
||||
|
||||
数字类型。设置线条的宽度。
|
||||
|
||||
### strokeStyle, setStrokeStyle()
|
||||
|
||||
```typescript
|
||||
type StrokeStyle = "solid" | "dashed" | "dotted";
|
||||
setStrokeStyle (val:number);
|
||||
```
|
||||
|
||||
strokeStyle 是一个字符串。
|
||||
|
||||
`setStrokeStyle()` 接受一个数字参数:
|
||||
- 0: "solid"(实线)
|
||||
- 1: "dashed"(虚线)
|
||||
- 其他任意数字: "dotted"(点线)
|
||||
|
||||
### roughness
|
||||
|
||||
数字类型。在 Excalidraw 中称为随意度。接受三个值:
|
||||
- 0:建筑师风格
|
||||
- 1:艺术家风格
|
||||
- 2:卡通家风格
|
||||
|
||||
### opacity
|
||||
|
||||
数字类型,取值范围在 0~100 之间。用于设置对象的不透明度,同时影响线条和填充的透明度。
|
||||
|
||||
### strokeSharpness, setStrokeSharpness()
|
||||
|
||||
```typescript
|
||||
type StrokeSharpness = "round" | "sharp";
|
||||
setStrokeSharpness(val:number);
|
||||
```
|
||||
|
||||
strokeSharpness 是一个字符串。
|
||||
|
||||
"round"(圆滑)线条是弯曲的,"sharp"(尖锐)线条在转折点处会形成尖角。
|
||||
|
||||
`setStrokeSharpness()` 接受一个数字参数:
|
||||
- 0:"round"(圆滑)
|
||||
- 其他任意数字:"sharp"(尖锐)
|
||||
|
||||
### fontFamily, setFontFamily()
|
||||
|
||||
数字类型。有效值为 1、2 和 3。
|
||||
|
||||
`setFontFamily()` 也接受一个数字参数并返回字体名称:
|
||||
- 1: "Virgil, Segoe UI Emoji"
|
||||
- 2: "Helvetica, Segoe UI Emoji"
|
||||
- 3: "Cascadia, Segoe UI Emoji"
|
||||
|
||||
### fontSize
|
||||
|
||||
数字类型。默认值为 20px。
|
||||
|
||||
### textAlign
|
||||
|
||||
字符串类型。文本的水平对齐方式。有效值为 "left"(左对齐)、"center"(居中对齐)、"right"(右对齐)。
|
||||
|
||||
这在使用 `addText()` 函数设置固定宽度时很有用。
|
||||
|
||||
### verticalAlign
|
||||
|
||||
字符串类型。文本的垂直对齐方式。有效值为 "top"(顶部对齐)和 "middle"(居中对齐)。
|
||||
|
||||
这在使用 `addText()` 函数设置固定高度时很有用。
|
||||
|
||||
### startArrowHead, endArrowHead
|
||||
|
||||
字符串类型。有效值为 "arrow"(箭头)、"bar"(线段)、"dot"(圆点)和 "none"(无)。用于指定箭头的起始和结束样式。
|
||||
|
||||
这在使用 `addArrow()` 和 `connectObjects()` 函数时很有用。
|
||||
113
docs/zh-cn/docs/API/introduction.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# [◀ Excalidraw Automate 使用指南](../readme.md)
|
||||
|
||||
## API 介绍
|
||||
|
||||
你可以通过 ExcalidrawAutomate 对象来访问 Excalidraw Automate。我建议在 Templater、DataView 和 QuickAdd 脚本中使用以下代码开始:
|
||||
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
|
||||
```javascript
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
```
|
||||
|
||||
第一行创建了一个常量,这样你就可以避免重复写 ExcalidrawAutomate 上百次。
|
||||
|
||||
第二行将 ExcalidrawAutomate 重置为默认值。这一步很重要,因为你不会知道之前执行了哪个模板,因此也不知道 Excalidraw 处于什么状态。
|
||||
|
||||
**⚠ 注意:** 如果你正在使用 Excalidraw 插件内置的[脚本引擎](../ExcalidrawScriptsEngine.md),引擎会自动处理 `ea` 对象的初始化。
|
||||
|
||||
### Excalidraw Automate 的基本使用逻辑
|
||||
|
||||
1. 设置要绘制元素的样式
|
||||
2. 添加元素。当你添加元素时,每个新元素都会被添加到前一个元素的上层,因此在元素重叠的情况下,后添加的元素会显示在先添加元素的上方。
|
||||
3. 调用 `await ea.create();` 来实例化绘图,或使用 `ea.setView();` 后跟 `ea.addElementsToView();` 将元素添加到现有视图中,或使用 `await ea.createSVG();` 或 `await ea.createPNG();` 从你的元素创建 PNG 或 SVG 图像。
|
||||
|
||||
你可以在添加不同元素之间改变样式。我将元素样式和创建分开的逻辑基于这样一个假设:你可能会设置一个描边颜色、描边样式、描边粗糙度等,并使用这些设置来绘制大多数元素。每次添加元素时都重新设置所有这些参数是没有意义的。
|
||||
|
||||
### 在深入了解之前,这里有三个简单的 [Templater](https://github.com/SilentVoid13/Templater) 脚本示例
|
||||
|
||||
#### 使用模板在自定义文件夹中创建具有自定义名称的新绘图
|
||||
|
||||
这个简单的脚本相比 Excalidraw 插件设置提供了更大的灵活性,让你可以为绘图命名、将其放入文件夹中并应用模板。
|
||||
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
await ea.create({
|
||||
filename : tp.date.now("HH.mm"),
|
||||
foldername : tp.date.now("YYYY-MM-DD"),
|
||||
templatePath: "Excalidraw/Template1.excalidraw",
|
||||
onNewPane : false
|
||||
});
|
||||
%>
|
||||
```
|
||||
|
||||
#### 创建一个简单的绘图
|
||||
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
ea.addRect(-150,-50,450,300);
|
||||
ea.addText(-100,70,"Left to right");
|
||||
ea.addArrow([[-100,100],[100,100]]);
|
||||
|
||||
ea.style.strokeColor = "red";
|
||||
ea.addText(100,-30,"top to bottom",{width:200,textAligh:"center"});
|
||||
ea.addArrow([[200,0],[200,200]]);
|
||||
await ea.create();
|
||||
%>
|
||||
```
|
||||
|
||||
该脚本将生成以下绘图:
|
||||
|
||||

|
||||
|
||||
#### 在打开的 Excalidraw 视图中添加一个带框的文本元素
|
||||
|
||||
将新元素放置在当前选中元素的下方,并用箭头从选中的元素指向新添加的文本。
|
||||
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
ea.setView("first");
|
||||
selectedElement = ea.getViewSelectedElement();
|
||||
ea.setStrokeSharpness(0);
|
||||
const boxPadding = 5;
|
||||
id = ea.addText(
|
||||
selectedElement.x + boxPadding,
|
||||
selectedElement.y+selectedElement.height+100,
|
||||
"[[Next process step]]",
|
||||
{
|
||||
textAlign:"center",
|
||||
box:true,
|
||||
boxPadding:boxPadding,
|
||||
width:selectedElement.width-boxPadding*2,
|
||||
}
|
||||
);
|
||||
ea.setStrokeSharpness(1);
|
||||
ea.style.roughness= 0;
|
||||
ea.connectObjectWithViewSelectedElement(
|
||||
id,
|
||||
"top",
|
||||
"bottom",
|
||||
{
|
||||
numberOfPoints:2,
|
||||
startArrowHead:"arrow",
|
||||
endArrowHead:"dot",
|
||||
padding:5
|
||||
});
|
||||
ea.addElementsToView();
|
||||
%>
|
||||
```
|
||||
|
||||
[点击此处查看动画演示](https://user-images.githubusercontent.com/14358394/131967188-2a488e38-f742-49d9-ae98-33238a8d4712.mp4)
|
||||
94
docs/zh-cn/docs/API/objects.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# [◀ Excalidraw 自动化使用指南](../readme.md)
|
||||
|
||||
## 添加对象
|
||||
|
||||
这些函数将向你的绘图中添加对象。画布是无限的,可以接受负数和正数的 X 和 Y 值。X 值从左到右递增,Y 值从上到下递增。
|
||||
|
||||

|
||||
|
||||
### addRect(), addDiamond(), addEllipse()
|
||||
|
||||
```typescript
|
||||
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
|
||||
```
|
||||
|
||||
返回对象的 `id`。当使用线条连接对象时需要用到这个 `id`,详见后文。
|
||||
|
||||
### addText()
|
||||
|
||||
```typescript
|
||||
addText(
|
||||
topX:number,
|
||||
topY:number,
|
||||
text:string,
|
||||
formatting?:{
|
||||
wrapAt?:number,
|
||||
width?:number,
|
||||
height?:number,
|
||||
textAlign?:string,
|
||||
box?: "box"|"blob"|"ellipse"|"diamond",
|
||||
boxPadding?:number
|
||||
},
|
||||
id?:string
|
||||
):string
|
||||
```
|
||||
|
||||
向绘图中添加文本。
|
||||
|
||||
格式化参数是可选的:
|
||||
- 如果未指定 `width` 和 `height`,函数将根据字体系列(fontFamily)、字体大小(fontSize)和提供的文本来计算宽度和高度。
|
||||
- 如果你想要将文本相对于绘图中的其他元素居中对齐,你可以提供固定的高度和宽度,并且可以像上面描述的那样指定 `textAlign` 和 `verticalAlign`。例如:`{width:500, textAlign:"center"}`
|
||||
- 如果你想在文本周围添加一个框,设置 `{box:"box"|"blob"|"ellipse"|"diamond"}`(分别对应矩形框、气泡框、椭圆框、菱形框)
|
||||
|
||||
返回对象的 `id`。当使用线条连接对象时需要用到这个 `id`,详见后文。如果设置了 `{box:}`,则返回包围框对象的 id。
|
||||
|
||||
### addLine()
|
||||
|
||||
```typescript
|
||||
addLine(points: [[x:number,y:number]]):string
|
||||
```
|
||||
|
||||
根据提供的点添加一条线。必须包含至少两个点 `points.length >= 2`。如果提供了超过 2 个点,中间点将被添加为断点。当 `strokeSharpness` 设置为 "sharp" 时,线条会以角度方式折断;设置为 "round" 时,线条会呈现曲线。
|
||||
|
||||
返回对象的 `id`。
|
||||
|
||||
### addArrow()
|
||||
|
||||
```typescript
|
||||
addArrow(points: [[x:number,y:number]],formatting?:{startArrowHead?:string,endArrowHead?:string,startObjectId?:string,endObjectId?:string}):string ;
|
||||
```
|
||||
|
||||
根据提供的点添加一个箭头。必须包含至少两个点 `points.length >= 2`。如果提供了超过 2 个点,中间点将被添加为断点。当元素的 `style.strokeSharpness` 设置为 "sharp" 时,线条会以角度方式折断;设置为 "round" 时,线条会呈现曲线。
|
||||
|
||||
`startArrowHead` 和 `endArrowHead` 指定要使用的箭头类型,如上所述。有效值包括 "none"(无)、"arrow"(箭头)、"dot"(圆点)和 "bar"(线条)。例如:`{startArrowHead: "dot", endArrowHead: "arrow"}`
|
||||
|
||||
`startObjectId` 和 `endObjectId` 是连接对象的 ID。如果是为了连接对象,建议使用 `connectObjects` 而不是调用 addArrow()。
|
||||
|
||||
返回对象的 `id`。
|
||||
|
||||
### connectObjects()
|
||||
|
||||
```typescript
|
||||
declare type ConnectionPoint = "top"|"bottom"|"left"|"right";
|
||||
connectObjects(objectA: string, connectionA: ConnectionPoint, objectB: string, connectionB: ConnectionPoint, formatting?:{numberOfPoints: number,startArrowHead:string,endArrowHead:string, padding: number}):void
|
||||
```
|
||||
|
||||
使用箭头连接两个对象。如果两个元素中的任何一个是 `line`(线条)、`arrow`(箭头)或 `freedraw`(自由绘制)类型,则不会执行任何操作。
|
||||
|
||||
`objectA` 和 `objectB` 是字符串类型,表示要连接的对象的 ID。这些 ID 是在创建对象时由 addRect()、addDiamond()、addEllipse() 和 addText() 函数返回的。
|
||||
|
||||
`connectionA` 和 `connectionB` 指定在对象上的连接位置。有效值包括:"top"(顶部)、"bottom"(底部)、"left"(左侧)和 "right"(右侧)。
|
||||
|
||||
`numberOfPoints` 设置线条的中间断点数量。默认值为零,表示箭头的起点和终点之间没有断点。当在绘图上移动对象时,这些断点会影响 Excalidraw 重新路由线条的方式。
|
||||
|
||||
`startArrowHead` 和 `endArrowHead` 的工作方式如上文 `addArrow()` 中所述。
|
||||
|
||||
### addToGroup()
|
||||
|
||||
```typescript
|
||||
addToGroup(objectIds:[]):string
|
||||
```
|
||||
|
||||
将 `objectIds` 中列出的对象组合成一个组。返回该组的 `id`。
|
||||
219
docs/zh-cn/docs/API/utility.md
Normal file
@@ -0,0 +1,219 @@
|
||||
# [◀ Excalidraw Automate How To](../readme.md)
|
||||
|
||||
## 实用工具函数
|
||||
|
||||
### isExcalidrawFile()
|
||||
```typescript
|
||||
isExcalidrawFile(f:TFile): boolean
|
||||
```
|
||||
如果提供的文件是有效的 Excalidraw 文件(可以是传统的 `*.excalidraw` 文件或在 front-matter 中包含 excalidraw 键的 markdown 文件),则返回 true。
|
||||
|
||||
### clear()
|
||||
`clear()` 将清除缓存中的对象,但会保留元素样式设置。
|
||||
|
||||
### reset()
|
||||
`reset()` 会先调用 `clear()`,然后将元素样式重置为默认值。
|
||||
|
||||
### toClipboard()
|
||||
```typescript
|
||||
async toClipboard(templatePath?:string)
|
||||
```
|
||||
将生成的绘图放置到剪贴板中。当你不想创建新的绘图,而是想将额外的元素粘贴到现有绘图上时,这个功能很有用。
|
||||
|
||||
### getElements()
|
||||
```typescript
|
||||
getElements():ExcalidrawElement[];
|
||||
```
|
||||
以数组形式返回 ExcalidrawAutomate 中的 ExcalidrawElement 元素。这种格式在使用 ExcalidrawRef 时特别有用。
|
||||
|
||||
### getElement()
|
||||
```typescript
|
||||
getElement(id:string):ExcalidrawElement;
|
||||
```
|
||||
返回与指定 id 匹配的元素对象。如果元素不存在,则返回 null。
|
||||
|
||||
### create()
|
||||
```typescript
|
||||
async create(params?:{filename: string, foldername:string, templatePath:string, onNewPane: boolean})
|
||||
```
|
||||
创建并打开绘图。返回创建文件的完整路径。
|
||||
|
||||
`filename` 是要创建的绘图文件名(不包含扩展名)。如果为 `null`,Excalidraw 将自动生成文件名。
|
||||
|
||||
`foldername` 是文件创建的目标文件夹。如果为 `null`,则会根据 Excalidraw 设置使用默认的新建绘图文件夹。
|
||||
|
||||
`templatePath` 是模板文件的完整路径(包含文件名和扩展名)。该模板文件将作为基础图层,所有通过 ExcalidrawAutomate 添加的对象都会显示在模板元素的上层。如果为 `null`,则不使用模板,即使用空白画布作为添加对象的基础。
|
||||
|
||||
`onNewPane` 定义新绘图的创建位置。`false` 将在当前活动页签中打开绘图。`true` 将通过垂直分割当前页签来打开绘图。
|
||||
|
||||
`frontmatterKeys` 是要应用到文档的 frontmatter 键值集合
|
||||
{
|
||||
excalidraw-plugin?: "raw"|"parsed",
|
||||
excalidraw-link-prefix?: string,
|
||||
excalidraw-link-brackets?: boolean,
|
||||
excalidraw-url-prefix?: string
|
||||
}
|
||||
|
||||
示例:
|
||||
```javascript
|
||||
create (
|
||||
{
|
||||
filename:"my drawing",
|
||||
foldername:"myfolder/subfolder/",
|
||||
templatePath: "Excalidraw/template.excalidraw",
|
||||
onNewPane: true,
|
||||
frontmatterKeys: {
|
||||
"excalidraw-plugin": "parsed",
|
||||
"excalidraw-link-prefix": "",
|
||||
"excalidraw-link-brackets": true,
|
||||
"excalidraw-url-prefix": "🌐",
|
||||
}
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
### createSVG()
|
||||
```typescript
|
||||
async createSVG(templatePath?:string)
|
||||
```
|
||||
返回包含生成绘图的 HTML SVGSVGElement 元素。
|
||||
|
||||
### createPNG()
|
||||
```typescript
|
||||
async createPNG(templatePath?:string, scale:number=1)
|
||||
```
|
||||
返回包含生成绘图的 PNG 图像 blob 对象。
|
||||
|
||||
### wrapText()
|
||||
```typescript
|
||||
wrapText(text:string, lineLen:number):string
|
||||
```
|
||||
返回一个按照指定最大行长度换行的字符串。
|
||||
|
||||
### 访问打开的 Excalidraw 视图
|
||||
在使用任何视图操作函数之前,你需要先初始化 targetView。
|
||||
|
||||
#### targetView
|
||||
```typescript
|
||||
targetView: ExcalidrawView
|
||||
```
|
||||
已打开的 Excalidraw 视图,被配置为视图操作的目标。使用 `setView` 进行初始化。
|
||||
|
||||
#### setView()
|
||||
```typescript
|
||||
setView(view:ExcalidrawView|"first"|"active"):ExcalidrawView
|
||||
```
|
||||
设置将作为视图操作目标的 ExcalidrawView。有效的 `view` 输入值包括:
|
||||
- ExcalidrawView 的对象实例
|
||||
- "first":如果打开了多个 Excalidraw 视图,则选择 `app.workspace.getLeavesOfType("Excalidraw")` 返回的第一个视图
|
||||
- "active":表示当前活动的视图
|
||||
|
||||
#### getExcalidrawAPI()
|
||||
```typescript
|
||||
getExcalidrawAPI():any
|
||||
```
|
||||
返回在 `targetView` 中指定的当前活动绘图的原生 Excalidraw API(ref.current)。
|
||||
查看 Excalidraw 文档请访问:https://www.npmjs.com/package/@excalidraw/excalidraw#ref
|
||||
|
||||
#### getViewElements()
|
||||
```typescript
|
||||
getViewElements():ExcalidrawElement[]
|
||||
```
|
||||
返回视图中的所有元素。
|
||||
|
||||
#### deleteViewElements()
|
||||
```typescript
|
||||
deleteViewElements(elToDelete: ExcalidrawElement[]):boolean
|
||||
```
|
||||
从视图中删除与输入参数中提供的元素相匹配的元素。
|
||||
|
||||
示例:从视图中删除选中的元素:
|
||||
```typescript
|
||||
ea = ExcalidrawAutomate;
|
||||
ea.setView("active");
|
||||
el = ea.getViewSelectedElements();
|
||||
ea.deleteViewElements();
|
||||
```
|
||||
|
||||
#### getViewSelectedElement()
|
||||
```typescript
|
||||
getViewSelectedElement():ExcalidrawElement
|
||||
```
|
||||
首先需要调用 `setView()` 来设置视图。
|
||||
|
||||
如果在目标视图 (targetView) 中选中了一个元素,该函数将返回被选中的元素。如果选中了多个元素(通过 <kbd>SHIFT+点击</kbd> 选择多个元素,或者选择一个组),将返回第一个元素。如果你想从一个组中指定要选择的元素,请双击该组中想要的元素。
|
||||
|
||||
当你想要添加一个与绘图中现有元素相关的新元素时,这个函数会很有帮助。
|
||||
|
||||
#### getViewSelectedElements()
|
||||
```typescript
|
||||
getViewSelectedElements():ExcalidrawElement[]
|
||||
```
|
||||
首先需要调用 `setView()` 来设置视图。
|
||||
|
||||
获取场景中选中元素的数组。如果没有选中任何元素,则返回 []。
|
||||
|
||||
注意:你可以调用 `getExcalidrawAPI().getSceneElements()` 来获取场景中的所有元素。
|
||||
|
||||
#### viewToggleFullScreen()
|
||||
```typescript
|
||||
viewToggleFullScreen(forceViewMode?:boolean):void;
|
||||
```
|
||||
在目标视图 (targetView) 中切换全屏模式和普通模式。通过将 forceViewMode 设置为 `true` 可以将 Excalidraw 切换到查看模式。默认值为 `false`。
|
||||
|
||||
此功能在 Obsidian 移动端上不生效。
|
||||
|
||||
#### connectObjectWithViewSelectedElement()
|
||||
```typescript
|
||||
connectObjectWithViewSelectedElement(objectA:string,connectionA: ConnectionPoint, connectionB: ConnectionPoint, formatting?:{numberOfPoints?: number,startArrowHead?:string,endArrowHead?:string, padding?: number}):boolean
|
||||
```
|
||||
与 `connectObjects()` 功能相同,但 ObjectB 是目标 ExcalidrawView 中当前选中的元素。该函数有助于在新创建的对象和目标 ExcalidrawView 中选中的元素之间放置一个箭头。
|
||||
|
||||
#### addElementsToView()
|
||||
```typescript
|
||||
async addElementsToView(repositionToCursor:boolean=false, save:boolean=false):Promise<boolean>
|
||||
```
|
||||
将使用 ExcalidrawAutomate 创建的元素添加到目标 ExcalidrawView 中。
|
||||
|
||||
`repositionToCursor` 默认值为 false
|
||||
- true:元素将被移动,使其中心点与 ExcalidrawView 上当前指针的位置对齐。你可以使用此开关将元素指向并放置到绘图中的所需位置。
|
||||
- false:元素将按照每个元素的 x&y 坐标定义的位置进行放置。
|
||||
|
||||
`save` 默认值为 false
|
||||
- true:元素添加后绘图将被保存。
|
||||
- false:绘图将在下一个自动保存周期时保存。当连续添加多个元素时使用 false。否则,最好使用 true 以最小化数据丢失的风险。
|
||||
|
||||
### onDropHook
|
||||
```typescript
|
||||
onDropHook (data: {
|
||||
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
|
||||
},
|
||||
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;
|
||||
```
|
||||
当可拖拽项被拖放到 Excalidraw 上时触发的回调函数。
|
||||
|
||||
该函数应返回一个布尔值。如果拖放由钩子函数处理且应停止进一步的原生处理,则返回 true;如果应让 Excalidraw 继续处理拖放操作,则返回 false。
|
||||
|
||||
拖放类型可以是以下之一:
|
||||
- "file":当从 Obsidian 文件浏览器中拖放文件到 Excalidraw 时。在这种情况下,payload.files 将包含被拖放文件的列表。
|
||||
- "text":当拖放链接(如 URL 或 wiki 链接)或其他文本时。在这种情况下,payload.text 将包含接收到的字符串。
|
||||
- "unknown":当 Excalidraw 插件无法识别拖放对象的类型时。在这种情况下,你可以使用 React.DragEvent 来分析拖放的对象。
|
||||
|
||||
使用 Templater 启动模板或类似方法来设置钩子函数。
|
||||
|
||||
```typescript
|
||||
ea = ExcalidrawAutomate;
|
||||
ea.onDropHook = (data) => {
|
||||
console.log(data);
|
||||
return false;
|
||||
}
|
||||
```
|
||||
28
docs/zh-cn/docs/Examples/apply_template.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# [◀ Excalidraw 自动化使用指南](../readme.md)
|
||||
|
||||
## 将 Excalidraw 模板应用到新绘图
|
||||
|
||||
这个示例与介绍中的类似,只是将图形旋转了90度,并且使用了模板,同时指定了保存绘图的文件名和文件夹,还会在新窗格中打开这个新绘图。
|
||||
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
ea.style.angle = Math.PI/2;
|
||||
ea.style.strokeWidth = 3.5;
|
||||
ea.addRect(-150,-50,450,300);
|
||||
ea.addText(-100,70,"Left to right");
|
||||
ea.addArrow([[-100,100],[100,100]]);
|
||||
|
||||
ea.style.strokeColor = "red";
|
||||
await ea.addText(100,-30,"top to bottom",{width:200,textAlign:"center"});
|
||||
ea.addArrow([[200,0],[200,200]]);
|
||||
await ea.create({
|
||||
filename :"My Drawing",
|
||||
foldername :"myfolder/fordemo/",
|
||||
templatePath:"Excalidraw/Template2.excalidraw",
|
||||
onNewPane :true});
|
||||
%>
|
||||
```
|
||||
21
docs/zh-cn/docs/Examples/connect_objects.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# [◀ Excalidraw Automate 使用指南](../readme.md)
|
||||
|
||||
## 连接对象
|
||||
|
||||
这个 [Templater](https://github.com/SilentVoid13/Templater) 模板演示了如何使用 ExcalidrawAutomate 连接两个对象。
|
||||
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
|
||||
```javascript
|
||||
<%*
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
ea.addText(-130,-100,"Connecting two objects");
|
||||
const a = ea.addRect(-100,-100,100,100);
|
||||
const b = ea.addEllipse(200,200,100,100);
|
||||
ea.connectObjects(a,"bottom",b,"left",{numberOfPoints: 2}); //see how the line breaks differently when moving objects around
|
||||
ea.style.strokeColor = "red";
|
||||
ea.connectObjects(a,"right",b,"top",1);
|
||||
await ea.create();
|
||||
%>
|
||||
```
|
||||
70
docs/zh-cn/docs/Examples/dataviewjs_familytree.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# [◀ Excalidraw Automate 使用指南](../readme.md)
|
||||
|
||||
## 使用 dataviewjs 生成家谱树
|
||||
|
||||
这个示例与使用 dataviewjs 生成思维导图的脚本类似,但输出结果是垂直呈现的。
|
||||
|
||||
### 输出效果
|
||||
|
||||

|
||||
|
||||
### 输入文件
|
||||
|
||||
任务列表格式如下:
|
||||
|
||||
```markdown
|
||||
- [ ] OBSIDIAN
|
||||
- [ ] Silver
|
||||
- [ ] PawPaw Silv
|
||||
- [ ] MawMaw Silv
|
||||
- [ ] Licat
|
||||
- [ ] PeePaw Li
|
||||
- [ ] MeeMaw Li
|
||||
```
|
||||
|
||||
### dataviewjs 脚本
|
||||
|
||||
渲染 Excalidraw 图形的代码如下:
|
||||
|
||||
```javascript
|
||||
function crawl(subtasks) {
|
||||
let size = subtasks.length > 0 ? 0 : 1; //if no children then a leaf with size 1
|
||||
for (let task of subtasks) {
|
||||
task["size"] = crawl(task.subtasks);
|
||||
size += task.size;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
const tasks = dv.page("FamilyTree.md").file.tasks[0];
|
||||
tasks["size"] = crawl(tasks.subtasks);
|
||||
|
||||
const width = 300;
|
||||
const height = 150;
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
|
||||
function buildMindmap(subtasks, depth, offset, parentObjectID) {
|
||||
if (subtasks.length == 0) return;
|
||||
let task;
|
||||
|
||||
for (let i = 0; i < subtasks.length; i++) {
|
||||
task = subtasks[i]
|
||||
if (depth == 1) ea.style.strokeColor = '#'+(Math.random()*0xFFFFFF<<0).toString(16).padStart(6,"0");
|
||||
task["objectID"] = ea.addText((task.size/2+offset)*width,depth*height,task.text,{box:true})
|
||||
ea.connectObjects(parentObjectID,"top",task.objectID,"bottom",{startArrowHead: 'arrow', endArrowHead: 'dot'});
|
||||
if (i >= 1) {
|
||||
ea.connectObjects(subtasks[i-1]['objectID'],"right",task.objectID,"left", {endArrowHead: 'none'});
|
||||
}
|
||||
|
||||
buildMindmap(task.subtasks, depth-1,offset,task.objectID);
|
||||
offset += task.size/1.5;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tasks["objectID"] = ea.addText(width*1.5,height*(tasks.size-1),tasks.text,{box:true, textAlign:"center"});
|
||||
buildMindmap(tasks.subtasks, 2, 0, tasks.objectID);
|
||||
|
||||
ea.createSVG().then((svg)=>dv.span(svg.outerHTML));
|
||||
```
|
||||
64
docs/zh-cn/docs/Examples/dataviewjs_mindmap.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# [◀ Excalidraw Automate 使用指南](../readme.md)
|
||||
|
||||
## 使用 dataviewjs 从任务列表生成思维导图
|
||||
|
||||
这个方法与使用 templater 生成思维导图的脚本类似,但由于 dataview 已经以树形结构返回任务,所以实现起来稍微简单一些
|
||||
|
||||
### 输出效果
|
||||
|
||||

|
||||
|
||||
### 输入文件
|
||||
|
||||
输入文件是 `Demo.md`,其内容如下:
|
||||
|
||||
```markdown
|
||||
- [ ] Root task
|
||||
- [ ] task 1.1
|
||||
- [ ] task 1.2
|
||||
- [ ] task 1.2.1
|
||||
- [ ] task 1.2.2
|
||||
- [ ] task 1.3
|
||||
- [ ] task 1.3.1
|
||||
```
|
||||
|
||||
### dataviewjs 脚本
|
||||
|
||||
`dataviewjs` 脚本如下所示:
|
||||
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
|
||||
```javascript
|
||||
function crawl(subtasks) {
|
||||
let size = subtasks.length > 0 ? 0 : 1; //if no children then a leaf with size 1
|
||||
for (let task of subtasks) {
|
||||
task["size"] = crawl(task.subtasks);
|
||||
size += task.size;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
const tasks = dv.page("Demo.md").file.tasks[0];
|
||||
tasks["size"] = crawl(tasks.subtasks);
|
||||
|
||||
const width = 300;
|
||||
const height = 100;
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
|
||||
function buildMindmap(subtasks, depth, offset, parentObjectID) {
|
||||
if (subtasks.length == 0) return;
|
||||
for (let task of subtasks) {
|
||||
if (depth == 1) ea.style.strokeColor = '#'+(Math.random()*0xFFFFFF<<0).toString(16).padStart(6,"0");
|
||||
task["objectID"] = ea.addText(depth*width,(task.size/2+offset)*height,task.text,{box:true})
|
||||
ea.connectObjects(parentObjectID,"right",task.objectID,"left",{startArrowHead: 'dot'});
|
||||
buildMindmap(task.subtasks, depth+1,offset,task.objectID);
|
||||
offset += task.size;
|
||||
}
|
||||
}
|
||||
|
||||
tasks["objectID"] = ea.addText(0,(tasks.size/2)*height,tasks.text,{box:true});
|
||||
buildMindmap(tasks.subtasks, 1, 0, tasks.objectID);
|
||||
|
||||
ea.createSVG().then((svg)=>dv.span(svg.outerHTML));
|
||||
```
|
||||
26
docs/zh-cn/docs/Examples/insert_new_drawing.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# [◀ Excalidraw 自动化使用指南](../readme.md)
|
||||
|
||||
## 在当前编辑的文档中插入新绘图
|
||||
|
||||
这个 [Templater](https://github.com/SilentVoid13/Templater) 模板会提示你输入绘图的标题。它将使用提供的标题创建一个新的绘图,并将其保存在你正在编辑的文档所在的文件夹中。然后,它会在光标位置嵌入新绘图,并通过拆分当前页面的方式在新的工作区中打开这个绘图。
|
||||
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
|
||||
```javascript
|
||||
<%*
|
||||
const defaultTitle = tp.date.now("HHmm")+' '+tp.file.title;
|
||||
const title = await tp.system.prompt("Title of the drawing?", defaultTitle);
|
||||
const folder = tp.file.folder(true);
|
||||
const transcludePath = (folder== '/' ? '' : folder + '/') + title + '.excalidraw';
|
||||
tR = '![['+transcludePath+']]';
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
ea.setTheme(1); //set Theme to dark
|
||||
await ea.create({
|
||||
filename : title,
|
||||
foldername : folder,
|
||||
//templatePath: 'Excalidraw/Template.excalidraw', //uncomment if you want to use a template
|
||||
onNewPane : true
|
||||
});
|
||||
%>
|
||||
```
|
||||
103
docs/zh-cn/docs/Examples/templater_mindmap.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# [◀ Excalidraw Automate 使用指南](../readme.md)
|
||||
|
||||
## 从文本大纲生成简单思维导图
|
||||
|
||||
这是一个稍微复杂一点的示例。它将从制表符缩进的大纲生成思维导图。
|
||||
|
||||
### 输出效果
|
||||
|
||||

|
||||
|
||||
### 输入文件
|
||||
|
||||
示例输入:
|
||||
```
|
||||
- Test 1
|
||||
- Test 1.1
|
||||
- Test 2
|
||||
- Test 2.1
|
||||
- Test 2.2
|
||||
- Test 2.2.1
|
||||
- Test 2.2.2
|
||||
- Test 2.2.3
|
||||
- Test 2.2.3.1
|
||||
- Test 3
|
||||
- Test 3.1
|
||||
```
|
||||
|
||||
### Templater 脚本
|
||||
|
||||
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
|
||||
|
||||
```javascript
|
||||
<%*
|
||||
const IDX = Object.freeze({"depth":0, "text":1, "parent":2, "size":3, "children": 4, "objectId":5});
|
||||
|
||||
//check if an editor is the active view
|
||||
const editor = this.app.workspace.activeLeaf?.view?.editor;
|
||||
if(!editor) return;
|
||||
|
||||
//initialize the tree with the title of the document as the first element
|
||||
let tree = [[0,this.app.workspace.activeLeaf?.view?.getDisplayText(),-1,0,[],0]];
|
||||
const linecount = editor.lineCount();
|
||||
|
||||
//helper function, use regex to calculate indentation depth, and to get line text
|
||||
function getLineProps (i) {
|
||||
props = editor.getLine(i).match(/^(\t*)-\s+(.*)/);
|
||||
return [props[1].length+1, props[2]];
|
||||
}
|
||||
|
||||
//a vector that will hold last valid parent for each depth
|
||||
let parents = [0];
|
||||
|
||||
//load outline into tree
|
||||
for(i=0;i<linecount;i++) {
|
||||
[depth,text] = getLineProps(i);
|
||||
if(depth>parents.length) parents.push(i+1);
|
||||
else parents[depth] = i+1;
|
||||
tree.push([depth,text,parents[depth-1],1,[]]);
|
||||
tree[parents[depth-1]][IDX.children].push(i+1);
|
||||
}
|
||||
|
||||
//recursive function to crawl the tree and identify height aka. size of each node
|
||||
function crawlTree(i) {
|
||||
if(i>linecount) return 0;
|
||||
size = 0;
|
||||
if((i+1<=linecount && tree[i+1][IDX.depth] <= tree[i][IDX.depth])|| i == linecount) { //I am a leaf
|
||||
tree[i][IDX.size] = 1;
|
||||
return 1;
|
||||
}
|
||||
tree[i][IDX.children].forEach((node)=>{
|
||||
size += crawlTree(node);
|
||||
});
|
||||
tree[i][IDX.size] = size;
|
||||
return size;
|
||||
}
|
||||
|
||||
crawlTree(0);
|
||||
|
||||
//Build the mindmap in Excalidraw
|
||||
const width = 300;
|
||||
const height = 100;
|
||||
const ea = ExcalidrawAutomate;
|
||||
ea.reset();
|
||||
|
||||
//stores position offset of branch/leaf in height units
|
||||
offsets = [0];
|
||||
|
||||
for(i=0;i<=linecount;i++) {
|
||||
depth = tree[i][IDX.depth];
|
||||
if (depth == 1) ea.style.strokeColor = '#'+(Math.random()*0xFFFFFF<<0).toString(16).padStart(6,"0");
|
||||
tree[i][IDX.objectId] = ea.addText(depth*width,((tree[i][IDX.size]/2)+offsets[depth])*height,tree[i][IDX.text],{box:true});
|
||||
//set child offset equal to parent offset
|
||||
if((depth+1)>offsets.length) offsets.push(offsets[depth]);
|
||||
else offsets[depth+1] = offsets[depth];
|
||||
offsets[depth] += tree[i][IDX.size];
|
||||
if(tree[i][IDX.parent]!=-1) {
|
||||
ea.connectObjects(tree[tree[i][IDX.parent]][IDX.objectId],"right",tree[i][IDX.objectId],"left",{startArrowHead: 'dot'});
|
||||
}
|
||||
}
|
||||
|
||||
await ea.create({onNewPane: true});
|
||||
%>
|
||||
```
|
||||
410
docs/zh-cn/docs/ExcalidrawScriptsEngine.md
Normal file
@@ -0,0 +1,410 @@
|
||||
# [◀ Excalidraw 自动化使用指南](./readme.md)
|
||||
|
||||
> 此说明当前更新至 `768aebf`。
|
||||
|
||||
【[English](../../ExcalidrawScriptsEngine.md) | 简体中文】
|
||||
|
||||
[](https://youtu.be/hePJcObHIso)
|
||||
|
||||
## 简介
|
||||
|
||||
请将你的 ExcalidrawAutomate 脚本放入 Excalidraw 设置中定义的文件夹中。脚本文件夹不能是你的 Vault 根目录。
|
||||
|
||||

|
||||
|
||||
EA 脚本可以是 markdown 文件、纯文本文件或 .js 文件。唯一的要求是它们必须包含有效的 JavaScript 代码。
|
||||
|
||||

|
||||
|
||||
你可以通过 Obsidian 命令面板从 Excalidraw 访问你的脚本。
|
||||
|
||||

|
||||
|
||||
这样你就可以像设置其他 Obsidian 命令一样,为你喜欢的脚本分配快捷键。
|
||||
|
||||

|
||||
|
||||
## 脚本开发
|
||||
|
||||
Excalidraw 脚本会自动接收两个对象:
|
||||
|
||||
- `ea`:脚本引擎会初始化 `ea` 对象,包括设置调用脚本时的活动视图为当前视图。
|
||||
- `utils`:我从 [QuickAdd](https://github.com/chhoumann/quickadd/blob/master/docs/QuickAddAPI.md) 借用了一些实用函数,但目前并非所有 QuickAdd 实用函数都在 Excalidraw 中实现。目前可用的函数如下。详见下方示例。
|
||||
- `inputPrompt: (header: string, placeholder?: string, value?: string, buttons?: [{caption:string, action:Function}])`
|
||||
- 打开一个提示框请求输入。返回输入的字符串。
|
||||
- 你需要使用 await 等待 inputPrompt 的结果。
|
||||
- `buttons.action(input: string) => string`。按钮动作将接收当前输入字符串。如果动作返回 null,输入将保持不变。如果动作返回字符串,inputPrompt 将解析为该值。
|
||||
```typescript
|
||||
let fileType = "";
|
||||
const filename = await utils.inputPrompt (
|
||||
"Filename for new document",
|
||||
"Placeholder",
|
||||
"DefaultFilename.md",
|
||||
[
|
||||
{
|
||||
caption: "Markdown",
|
||||
action: ()=>{fileType="md";return;}
|
||||
},
|
||||
{
|
||||
caption: "Excalidraw",
|
||||
action: ()=>{fileType="ex";return;}
|
||||
}
|
||||
]
|
||||
);
|
||||
|
||||
```
|
||||
- `suggester: (displayItems: string[], items: any[], hint?: string, instructions?:Instruction[])`
|
||||
- 打开一个建议器。显示 displayItems 并返回 items[] 中对应的项。
|
||||
- 你需要使用 await 等待 suggester 的结果。
|
||||
- 如果用户取消(按ESC键),suggester 将返回 `undefined`
|
||||
- Hint(提示)和 instructions(说明)参数是可选的。
|
||||
```typescript
|
||||
interface Instruction {
|
||||
command: string;
|
||||
purpose: string;
|
||||
}
|
||||
```
|
||||
- 脚本可以有设置。这些设置作为插件设置的一部分存储,用户也可以通过 Obsidian 插件设置窗口更改。
|
||||
- 你可以使用 `ea.getScriptSettings()` 访问当前脚本的设置,并使用 `ea.setScriptSettings(settings:any)` 存储设置值
|
||||
- 在插件设置中显示脚本设置的规则如下:
|
||||
- 如果设置是简单的字面量(布尔值、数字、字符串),这些将按原样显示在设置中。设置的名称将作为值的键。
|
||||
```javascript
|
||||
ea.setScriptSettings({
|
||||
"value 1": true,
|
||||
"value 2": 1,
|
||||
"value 3": "my string"
|
||||
})
|
||||
```
|
||||

|
||||
- 如果设置是一个对象并遵循以下结构,则可以添加描述和值集。也可以使用 `hidden` 键从用户界面中隐藏值。
|
||||
```javascript
|
||||
ea.setScriptSettings({
|
||||
"value 1": {
|
||||
"value": true,
|
||||
"description": "This is the description for my boolean value"
|
||||
},
|
||||
"value 2": {
|
||||
"value": 1,
|
||||
"description": "This is the description for my numeric value"
|
||||
},
|
||||
"value 3": {
|
||||
"value": "my string",
|
||||
"description": "This is the description for my string value",
|
||||
"valueset": ["allowed 1","allowed 2","allowed 3"]
|
||||
},
|
||||
"value 4": {
|
||||
"value": "my value",
|
||||
"hidden": true
|
||||
}
|
||||
});
|
||||
```
|
||||

|
||||
|
||||
---------
|
||||
|
||||
## Excalidraw 自动化脚本示例
|
||||
|
||||
这些脚本可以在 GitHub [这个](https://github.com/zsviczian/obsidian-excalidraw-plugin/tree/master/ea-scripts)文件夹 📂 中下载为 `.md` 文件。
|
||||
|
||||
### 为选中元素添加边框
|
||||
|
||||

|
||||
|
||||
此脚本将在 Excalidraw 中当前选中的元素周围添加一个包围框
|
||||
|
||||
```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();
|
||||
//check if settings exist. If not, set default values on first run
|
||||
if(!settings["Default padding"]) {
|
||||
settings = {
|
||||
"Prompt for padding?": true,
|
||||
"Default padding" : {
|
||||
value: 10,
|
||||
description: "Padding between the bounding box of the selected elements, and the box the script creates"
|
||||
}
|
||||
};
|
||||
ea.setScriptSettings(settings);
|
||||
}
|
||||
|
||||
let padding = settings["Default padding"].value;
|
||||
|
||||
if(settings["Prompt for padding?"]) {
|
||||
padding = parseInt (await utils.inputPrompt("padding?","number",padding.toString()));
|
||||
}
|
||||
|
||||
if(isNaN(padding)) {
|
||||
new Notice("The padding value provided is not a number");
|
||||
return;
|
||||
}
|
||||
elements = ea.getViewSelectedElements();
|
||||
const box = ea.getBoundingBox(elements);
|
||||
color = ea
|
||||
.getExcalidrawAPI()
|
||||
.getAppState()
|
||||
.currentItemStrokeColor;
|
||||
//uncomment for random color:
|
||||
//color = '#'+(Math.random()*0xFFFFFF<<0).toString(16).padStart(6,"0");
|
||||
ea.style.strokeColor = color;
|
||||
id = ea.addRect(
|
||||
box.topX - padding,
|
||||
box.topY - padding,
|
||||
box.width + 2*padding,
|
||||
box.height + 2*padding
|
||||
);
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
ea.addToGroup([id].concat(elements.map((el)=>el.id)));
|
||||
ea.addElementsToView(false);
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
### 用箭头连接选中的元素
|
||||
|
||||

|
||||
|
||||
此脚本将用箭头连接两个对象。如果任一对象是一组分组元素(例如,一个文本元素与一个包围它的矩形分组),脚本会识别这些组,并将箭头连接到组中最大的对象(假设你想将箭头连接到文本元素周围的框)。
|
||||
```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["Starting arrowhead"]) {
|
||||
settings = {
|
||||
"Starting arrowhead" : {
|
||||
value: "none",
|
||||
valueset: ["none","arrow","triangle","bar","dot"]
|
||||
},
|
||||
"Ending arrowhead" : {
|
||||
value: "triangle",
|
||||
valueset: ["none","arrow","triangle","bar","dot"]
|
||||
},
|
||||
"Line points" : {
|
||||
value: 1,
|
||||
description: "Number of line points between start and end"
|
||||
}
|
||||
};
|
||||
ea.setScriptSettings(settings);
|
||||
}
|
||||
|
||||
const arrowStart = settings["Starting arrowhead"].value === "none" ? null : settings["Starting arrowhead"].value;
|
||||
const arrowEnd = settings["Ending arrowhead"].value === "none" ? null : settings["Ending arrowhead"].value;
|
||||
const linePoints = Math.floor(settings["Line points"].value);
|
||||
|
||||
const elements = ea.getViewSelectedElements();
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
groups = ea.getMaximumGroups(elements);
|
||||
|
||||
if(groups.length !== 2) {
|
||||
//unfortunately getMaxGroups returns duplicated resultset for sticky notes
|
||||
//needs additional filtering
|
||||
cleanGroups=[];
|
||||
idList = [];
|
||||
for (group of groups) {
|
||||
keep = true;
|
||||
for(item of group) if(idList.contains(item.id)) keep = false;
|
||||
if(keep) {
|
||||
cleanGroups.push(group);
|
||||
idList = idList.concat(group.map(el=>el.id))
|
||||
}
|
||||
}
|
||||
if(cleanGroups.length !== 2) return;
|
||||
groups = cleanGroups;
|
||||
}
|
||||
|
||||
els = [
|
||||
ea.getLargestElement(groups[0]),
|
||||
ea.getLargestElement(groups[1])
|
||||
];
|
||||
|
||||
ea.style.strokeColor = els[0].strokeColor;
|
||||
ea.style.strokeWidth = els[0].strokeWidth;
|
||||
ea.style.strokeStyle = els[0].strokeStyle;
|
||||
ea.style.strokeSharpness = els[0].strokeSharpness;
|
||||
|
||||
ea.connectObjects(
|
||||
els[0].id,
|
||||
null,
|
||||
els[1].id,
|
||||
null,
|
||||
{
|
||||
endArrowHead: arrowEnd,
|
||||
startArrowHead: arrowStart,
|
||||
numberOfPoints: linePoints
|
||||
}
|
||||
);
|
||||
ea.addElementsToView();
|
||||
```
|
||||
|
||||
----
|
||||
### 反转选中的箭头
|
||||
|
||||

|
||||
|
||||
反转选中元素范围内**箭头**的方向。
|
||||
|
||||
```javascript
|
||||
elements = ea.getViewSelectedElements().filter((el)=>el.type==="arrow");
|
||||
if(!elements || elements.length===0) return;
|
||||
elements.forEach((el)=>{
|
||||
const start = el.startArrowhead;
|
||||
el.startArrowhead = el.endArrowhead;
|
||||
el.endArrowhead = start;
|
||||
});
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
ea.addElementsToView();
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
### 设置选中元素的线条宽度
|
||||
|
||||

|
||||
|
||||
当你缩放自由绘制的草图并想要减小或增加它们的线条宽度时,这个脚本会很有帮助。
|
||||
```javascript
|
||||
let width = (ea.getViewSelectedElement().strokeWidth??1).toString();
|
||||
width = await utils.inputPrompt("Width?","number",width);
|
||||
const elements=ea.getViewSelectedElements();
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
ea.getElements().forEach((el)=>el.strokeWidth=width);
|
||||
ea.addElementsToView();
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
### 设置网格大小
|
||||
|
||||

|
||||
|
||||
Excalidraw 中默认的网格大小是 20。目前通过用户界面无法更改网格大小。
|
||||
```javascript
|
||||
const grid = parseInt(await utils.inputPrompt("Grid size?",null,"20"));
|
||||
const api = ea.getExcalidrawAPI();
|
||||
let appState = api.getAppState();
|
||||
appState.gridSize = grid;
|
||||
api.updateScene({
|
||||
appState,
|
||||
commitToHistory:false
|
||||
});
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
### 设置元素尺寸和位置
|
||||
|
||||

|
||||
|
||||
目前在 Excalidraw 中还没有办法指定对象的精确位置和大小。你可以使用以下简单脚本来解决这个问题。
|
||||
```javascript
|
||||
const elements = ea.getViewSelectedElements();
|
||||
if(elements.length === 0) return;
|
||||
const el = ea.getLargestElement(elements);
|
||||
const sizeIn = [el.x,el.y,el.width,el.height].join(",");
|
||||
let res = await utils.inputPrompt("x,y,width,height?",null,sizeIn);
|
||||
res = res.split(",");
|
||||
if(res.length !== 4) return;
|
||||
let size = [];
|
||||
for (v of res) {
|
||||
const i = parseInt(v);
|
||||
if(isNaN(i)) return;
|
||||
size.push(i);
|
||||
}
|
||||
el.x = size[0];
|
||||
el.y = size[1];
|
||||
el.width = size[2];
|
||||
el.height = size[3];
|
||||
ea.copyViewElementsToEAforEditing([el]);
|
||||
ea.addElementsToView();
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
### 项目符号
|
||||
|
||||

|
||||
|
||||
此脚本会在选中的每个文本元素的左上角添加一个小圆圈,并将文本和"项目符号"组合成一个组。
|
||||
```javascript
|
||||
elements = ea.getViewSelectedElements().filter((el)=>el.type==="text");
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
const padding = 10;
|
||||
elements.forEach((el)=>{
|
||||
ea.style.strokeColor = el.strokeColor;
|
||||
const size = el.fontSize/2;
|
||||
const ellipseId = ea.addEllipse(
|
||||
el.x-padding-size,
|
||||
el.y+size/2,
|
||||
size,
|
||||
size
|
||||
);
|
||||
ea.addToGroup([el.id,ellipseId]);
|
||||
});
|
||||
ea.addElementsToView();
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
### 按行分割文本
|
||||
|
||||
**!!!需要 Excalidraw 1.5.1 或更高版本**
|
||||
|
||||

|
||||
|
||||
将文本块按行分割成单独的文本元素,以便更容易重新组织
|
||||
```javascript
|
||||
elements = ea.getViewSelectedElements().filter((el)=>el.type==="text");
|
||||
elements.forEach((el)=>{
|
||||
ea.style.strokeColor = el.strokeColor;
|
||||
ea.style.fontFamily = el.fontFamily;
|
||||
ea.style.fontSize = el.fontSize;
|
||||
const text = el.text.split("\n");
|
||||
for(i=0;i<text.length;i++) {
|
||||
ea.addText(el.x,el.y+i*el.height/text.length,text[i]);
|
||||
}
|
||||
});
|
||||
ea.addElementsToView();
|
||||
ea.deleteViewElements(elements);
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
### 设置文本对齐方式
|
||||
|
||||

|
||||
|
||||
设置文本块的对齐方式(居中、右对齐、左对齐)。如果你想为选择文本对齐方式设置键盘快捷键,这个脚本会很有用。
|
||||
```javascript
|
||||
elements = ea.getViewSelectedElements().filter((el)=>el.type==="text");
|
||||
if(elements.length===0) return;
|
||||
let align = ["left","right","center"];
|
||||
align = await utils.suggester(align,align);
|
||||
elements.forEach((el)=>el.textAlign = align);
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
ea.addElementsToView();
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
### 设置字体
|
||||
|
||||

|
||||
|
||||
设置文本块的字体(Virgil、Helvetica、Cascadia)。如果你想为选择字体设置键盘快捷键,这个功能会很有用。
|
||||
```javascript
|
||||
elements = ea.getViewSelectedElements().filter((el)=>el.type==="text");
|
||||
if(elements.length===0) return;
|
||||
let font = ["Virgil","Helvetica","Cascadia"];
|
||||
font = parseInt(await utils.suggester(font,["1","2","3"]));
|
||||
if (isNaN(font)) return;
|
||||
elements.forEach((el)=>el.fontFamily = font);
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
ea.addElementsToView();
|
||||
```
|
||||
5804
docs/zh-cn/docs/Release-notes.md
Normal file
57
docs/zh-cn/docs/readme.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Excalidraw 自动化使用指南
|
||||
|
||||
> 此说明当前更新至 `e793526`。
|
||||
|
||||
【[English](../../readme.md) | 简体中文】
|
||||
|
||||
使用 ExcalidrawAutomate 可以通过 [ExcalidrawAutomate 脚本引擎](ExcalidrawScriptsEngine.md)、[Templater](https://silentvoid13.github.io/Templater/docs/) 或 [QuickAdd](https://github.com/chhoumann/quickadd) 插件来创建或操作 Excalidraw 绘图,并使用 [DataviewJS](https://blacksmithgu.github.io/obsidian-dataview/docs/api/intro/) 生成嵌入式的 SVG 和 PNG 图像。
|
||||
|
||||
通过一些简单的配置,使用 ExcalidrawAutomate 你可以:
|
||||
- 生成简单的思维导图
|
||||
- 构建家谱
|
||||
- 填写 SVG 表单
|
||||
- 创建自定义图表
|
||||
- 在 Excalidraw 中自动化简单任务(即创建宏)
|
||||
|
||||

|
||||
|
||||
## API 文档
|
||||
|
||||
- **从这里开始** [API 介绍](API/introduction.md)
|
||||
- [属性和函数概览](API/attributes_functions_overview.md)
|
||||
- [元素样式](API/element_style.md)
|
||||
- [画布样式](API/canvas_style.md)
|
||||
- [添加对象](API/objects.md)
|
||||
- [实用函数](API/utility.md)
|
||||
|
||||
## ExcalidrawAutomate 脚本引擎
|
||||
|
||||
当你想要自动化一些简单的步骤时,比如在文本元素周围添加一个框、用箭头连接两个对象、或者设置自定义的线宽或网格值等类似"宏"的自动化操作,我建议使用脚本引擎。
|
||||
- [ExcalidrawAutomate 脚本引擎](ExcalidrawScriptsEngine.md)
|
||||
|
||||
## 示例
|
||||
- **Templater**
|
||||
- [在当前编辑的文档中插入新绘图](Examples/insert_new_drawing.md)
|
||||
- [连接对象](Examples/connect_objects.md)
|
||||
- [应用 Excalidraw 模板](Examples/apply_template.md)
|
||||
- [使用 Templater 创建思维导图](Examples/templater_mindmap.md)
|
||||
|
||||
- **Dataview**
|
||||
- [使用 Dataview 创建思维导图](Examples/dataviewjs_mindmap.md)
|
||||
- [使用 Dataview 创建家谱](Examples/dataviewjs_familytree.md)
|
||||
|
||||
## 支持与反馈
|
||||
|
||||
### 支持原作者
|
||||
|
||||
如果你喜欢这个插件,请通过以下方式支持:
|
||||
- 在社交媒体上分享这个插件
|
||||
- 在 Twitter 上关注作者 [@zsviczian](https://twitter.com/zsviczian)
|
||||
- 访问作者的博客 [zsolt.blog](https://zsolt.blog)
|
||||
- [赞助作者](https://ko-fi.com/zsolt)
|
||||
|
||||
[<img src="https://user-images.githubusercontent.com/14358394/115450238-f39e8100-a21b-11eb-89d0-fa4b82cdbce8.png" width="150" alt="赞助按钮">](https://ko-fi.com/zsolt)
|
||||
|
||||
### 支持中文翻译
|
||||
|
||||
如果这些中文翻译对你有帮助,欢迎通过 [爱发电](https://afdian.com/a/daomishu) 支持译者。
|
||||
91
docs/zh-cn/ea-scripts/README.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Excalidraw 脚本引擎脚本库
|
||||
|
||||
> 此说明当前更新至 `768aebf`。
|
||||
|
||||
【[English](../../../ea-scripts/README.md) | 简体中文】
|
||||
|
||||
点击观看介绍视频:
|
||||
|
||||
[](https://youtu.be/hePJcObHIso)
|
||||
|
||||
> **警告**
|
||||
> 相比视频中展示的方法,现在有更简单的方式来安装/管理脚本
|
||||
|
||||
查看 [Excalidraw 脚本引擎](../../ExcalidrawScriptsEngine.md) 文档了解更多详情。
|
||||
|
||||
## 如何在 Obsidian 仓库中安装脚本
|
||||
|
||||
安装内置脚本的步骤:
|
||||
|
||||
- 在 Obsidian 中打开一个 Excalidraw 绘图
|
||||
- 在面板下拉菜单中选择"安装或更新 Excalidraw 脚本"
|
||||
- 点击其中一个可用脚本
|
||||
- 点击"安装此脚本"(注意如果脚本已经安装,你会看到更新选项)
|
||||
- 重启 Obsidian 使脚本生效
|
||||
|
||||
注意:默认情况下,脚本会被安装到你仓库中的 `Excalidraw/Scripts/Downloaded` 文件夹
|
||||
|
||||
<details><summary>手动安装脚本</summary>
|
||||
|
||||
打开你感兴趣的脚本,将其保存到你的 Obsidian 仓库中(包括第一行的 `/*`),或者在"Raw"模式下打开并将全部内容复制到 Obsidian 中。
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
## 可用脚本列表
|
||||
|
||||
|标题|描述|图标|贡献者|
|
||||
|----|----|----|----|
|
||||
|[添加连接点](../../../ea-scripts/Add%20Connector%20Point.md)|此脚本将在选中文本元素的左上角添加一个小圆圈,并将文本和"圆点"组合成一组。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[添加现有文件链接并打开](../../../ea-scripts/Add%20Link%20to%20Existing%20File%20and%20Open.md)|提示从保险库(Vault)中选择文件。为选中的元素添加指向所选文件的链接。你可以在设置中控制是在当前活动面板还是相邻面板中打开文件。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[添加新页面链接并打开](../../../ea-scripts/Add%20Link%20and%20Open%20Page.md)|提示输入文件名。提供创建和打开新的 Markdown 或 Excalidraw 文档的选项。为绘图中选中的对象添加指向新文件的链接。你可以在设置中控制是在当前活动面板或是相邻面板中打开文件。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[添加流程下一步](../../../ea-scripts/Add%20Link%20to%20New%20Page%20and%20Open.md)|此脚本将提示你输入流程步骤的标题,然后创建带有该文本的便签。如果选中了某个元素,脚本将用箭头将这个新步骤与上一步骤(选中的元素)连接起来。如果没有选中元素,脚本会假定这是流程的第一步,只会输出带有输入文本的便签。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[分割椭圆](../../../ea-scripts/Boolean%20Operations.md)|使用此脚本可以对形状进行布尔运算。||[@GColoy](https://github.com/GColoy)|
|
||||
|[为每个选中的组添加边框](../../../ea-scripts/Box%20Each%20Selected%20Groups.md)|此脚本将为 Excalidraw 中当前选中的每个组添加封装框。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[为选中元素添加边框](../../../ea-scripts/Box%20Selected%20Elements.md)|此脚本将为 Excalidraw 中当前选中的元素添加一个封装框。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[更改选中元素的形状](../../../ea-scripts/Change%20shape%20of%20selected%20elements.md)|此脚本允许你更改选中的矩形、菱形和椭圆的形状||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[连接元素](../../../ea-scripts/Connect%20elements.md)|此脚本将用箭头连接两个对象。如果任一对象是一组分组的元素(例如,与封装矩形分组的文本元素),脚本将识别这些组,并将箭头连接到组中最大的对象(假设你想将箭头连接到文本元素周围的框)。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[将自由绘制转换为线条](../../../ea-scripts/Convert%20freedraw%20to%20line.md)|将选中的自由绘制对象转换为可编辑的线条。这样你就可以通过拖动线条点来调整绘图,如果是封闭线条还可以选择形状填充。你可以在设置中调整转换点的密度||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[将选中的文本元素转换为便签](../../../ea-scripts/Convert%20selected%20text%20elements%20to%20sticky%20notes.md)|将选中的纯文本元素转换为具有透明背景和透明描边颜色的便签。本质上是将文本元素转换为可换行的格式。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[将文本转换为带文件夹和别名的链接](../../../ea-scripts/Convert%20text%20to%20link%20with%20folder%20and%20alias.md)|将文本元素转换为指向所选文件夹中文件的链接,并将原始文本设置为别名。脚本会提示用户从保险库(Vault)中选择一个现有文件夹。|`原始文本` => `[[选定文件夹/原始文本\|原始文本]]`|[@zsviczian](https://github.com/zsviczian)|
|
||||
|[将选中元素样式复制到全局](../../../ea-scripts/Copy%20Selected%20Element%20Styles%20to%20Global)|此脚本会将任何选中元素的样式复制到 Excalidraw 的全局样式中。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[创建新的 Markdown 文件并嵌入到当前绘图中](../../../ea-scripts/Create%20new%20markdown%20file%20and%20embed%20into%20active%20drawing.md)|此脚本会提示你输入文件名,然后创建一个具有该文件名的新 Markdown 文档,在相邻面板中打开新的 Markdown 文档,并将该 Markdown 文档嵌入到当前的 Excalidraw 绘图中。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[加深背景颜色](../../../ea-scripts/Darken%20background%20color.md)|此脚本每次将选中元素的背景颜色加深 2%。你可以多次使用此脚本直到满意为止。建议为此脚本设置快捷键,这样你就可以快速尝试加深和减淡颜色效果。与"修改背景颜色不透明度"脚本相比,其优点是元素的背景颜色不受画布颜色影响,并且颜色值不会以奇怪的 rgba() 形式出现。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[肘形连接器](../../../ea-scripts/Elbow%20connectors.md)|此脚本将选中的连接器转换为肘形。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[水平扩展矩形并保持文本居中](../../../ea-scripts/Expand%20rectangles%20horizontally%20keep%20text20%centered.md)|此脚本会扩展选中矩形的宽度,直到它们都具有相同的宽度,并保持文本居中。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[水平扩展矩形](../../../ea-scripts/Expand%20rectangles%20horizontally.md)|此脚本会扩展选中矩形的宽度,直到它们都具有相同的宽度。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[垂直扩展矩形并保持文本居中](../../../ea-scripts/Expand%20rectangles%20vertically%20keep%20text%20centered.md)|此脚本会扩展选中矩形的高度,直到它们都具有相同的高度,并保持文本居中。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[垂直扩展矩形](../../../ea-scripts/Expand%20rectangles%20vertically.md)|此脚本会扩展选中矩形的高度,直到它们都具有相同的高度。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[固定中心点水平距离](../../../ea-scripts/Fixed%20horizontal%20distance%20between%20centers.md)|此脚本会以固定的中心点间距水平排列选中的元素。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[固定内部距离](../../../ea-scripts/Fixed%20inner%20distance.md)|此脚本会以固定的内部距离排列选中的元素和组。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[固定间距](../../../ea-scripts/Fixed%20spacing.md)|此脚本会以固定的间距水平排列选中的元素。当我们创建架构图或思维导图时,经常需要以固定间距排列大量元素。"固定间距"和"固定垂直距离"脚本可以为我们节省大量时间。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[固定中心点垂直距离](../../../ea-scripts/Fixed%20vertical%20distance%20between%20centers.md)|此脚本会以固定的中心点间距垂直排列选中的元素。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[固定垂直距离](../../../ea-scripts/Fixed%20vertical%20distance.md)|此脚本会以固定间距垂直排列选中的元素。当我们创建架构图或思维导图时,经常需要以固定间距排列大量元素。`固定间距`和`固定垂直距离`脚本可以为我们节省大量时间。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[减淡背景颜色](../../../ea-scripts/Lighten%20background%20color.md)|此脚本每次将选中元素的背景颜色减淡 2%。你可以多次使用此脚本直到满意为止。建议为此脚本设置快捷键,这样你就可以快速尝试加深和减淡颜色效果。与"修改背景颜色不透明度"脚本相比,其优点是元素的背景颜色不受画布颜色影响,并且颜色值不会以奇怪的 rgba() 形式出现。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[思维导图连接器](../../../ea-scripts/Mindmap%20connector.md)|此脚本为选中的元素创建类似思维导图的连线(目前仅支持右侧和向下方向)。连线的起点将根据元素的创建时间确定。因此你应该先创建标题元素。||[@xllowl](https://github.com/xllowl)|
|
||||
|[修改背景颜色不透明度](../../../ea-scripts/Modify%20background%20color%20opacity.md)|此脚本会更改选中框的背景颜色不透明度。Excalidraw 中的默认背景颜色太深,导致文字难以阅读。你可以通过设置透明度来使颜色变浅。你可以反复调整透明度直到满意为止。虽然 Excalidraw 在其原生属性设置中有不透明度选项,但它也会改变边框的透明度。使用此脚本可以只更改背景颜色的不透明度而不影响边框。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[标准化选中箭头](../../../ea-scripts/Normalize%20Selected%20Arrows.md)|此脚本将重置选中箭头的起点和终点位置。箭头将指向连接框的中心,并与框保持 8px 的间距。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[OCR - 光学字符识别](../../../ea-scripts/OCR%20-%20Optical%20Character%20Recognition.md)|此脚本将 1) 把选中的图片文件发送到 [taskbone.com](https://taskbone.com) 提取图片中的文字,并 2) 将文字作为文本元素添加到你的绘图中。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[有机线条](../../../ea-scripts/Organic%20Line.md)|将选中的自由绘制线条转换为从开始到结束笔压逐渐减小的线条。转换后的线条会被放置在图层的最底层,位于所有其他元素之下。在绘制有机思维导图时很有帮助。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[重复元素](../../../ea-scripts/Repeat%20Elements.md)|此脚本会检测两个选中元素之间的差异,包括位置、大小、角度、描边和背景颜色,并根据用户输入的重复次数创建多个具有相同差异的元素。||[@1-2-3](https://github.com/1-2-3)|
|
||||
|[重置 LaTeX 大小](../../../ea-scripts/Reset%20LaTeX%20Size.md)|将嵌入的 LaTeX 公式大小重置为默认大小或默认大小的倍数。||[@firai](https://github.com/firai)|
|
||||
|[反转箭头](../../../ea-scripts/Reverse%20arrows.md)|反转选中元素范围内的**箭头**方向。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[手写助手](../../../ea-scripts/Scribble%20Helper.md)|iOS 手写助手,用于改善文本元素的手写体验。如果没有选中元素,则会在指针位置创建一个文本元素,你可以使用编辑框通过手写来修改文本。如果选中了文本元素,则会打开输入提示框,你可以在其中通过手写修改文本。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[选择特定类型元素](../../../ea-scripts/Select%20Elements%20of%20Type.md)|显示当前图像中不同元素类型的列表供选择。只有选定类型的元素会在画布上被选中。如果运行脚本时没有选中任何元素,则脚本会处理画布上的所有元素。如果执行脚本时已选中某些元素,则脚本只会处理这些选中的元素。<br>此脚本在以下情况下很有用,例如,当你想要将所有箭头置于顶层,或想要更改所有文本元素的颜色等。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[通过添加阴影克隆为未闭合线条对象设置背景颜色](../../../ea-scripts/Set%20background%20color%20of%20unclosed%20line%20object%20by%20adding%20a%20shadow%20clone.md)|使用此脚本为未闭合(即开放)线条对象设置背景颜色,方法是创建对象的克隆。脚本会将克隆的描边颜色设置为透明,并添加一条直线来闭合对象。使用设置来定义默认背景颜色、填充样式和克隆的描边宽度。默认情况下,克隆会与原始对象组合在一起,你也可以在设置中禁用此功能。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[设置尺寸](../../../ea-scripts/Set%20Dimensions.md)|目前在 Excalidraw 中无法指定对象的确切位置和大小。你可以使用这个简单的脚本来弥补这个不足。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[设置字体](../../../ea-scripts/Set%20Font%20Family.md)|设置文本块的字体(Virgil、Helvetica、Cascadia)。如果你想为选择字体设置键盘快捷键,这个脚本很有用。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[设置网格](../../../ea-scripts/Set%20Grid.md)|Excalidraw 中的默认网格大小是 20。目前无法通过用户界面更改网格大小。这个脚本提供了一种方法来弥补这个不足。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[设置链接别名](../../../ea-scripts/Set20%Link20%Alias.md)|遍历选中文本元素中的所有链接,并提示用户为每个找到的链接设置或修改别名。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[设置选中元素的描边宽度](../../../ea-scripts/Set%20Stroke%20Width%20of%20Selected%20Elements.md)|此脚本将设置选中元素的描边宽度。这在缩放自由绘制草图并想要减小或增加其线条宽度时很有用。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[按行分割文本](../../../ea-scripts/Split%20text%20by%20lines.md)|将文本行分割成单独的文本元素,以便更容易重新组织||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[设置文本对齐方式](../../../ea-scripts/Set%20Text%20Alignment.md)|设置文本块的对齐方式(居中、右对齐、左对齐)。如果你想为选择文本对齐方式设置键盘快捷键,这个脚本很有用。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[分割椭圆](../../../ea-scripts/Split%20Ellipse.md)|此脚本会在线条与椭圆相交的任何点处分割椭圆。||[@GColoy](https://github.com/GColoy)|
|
||||
|[TheBrain导航](../../../ea-scripts/TheBrain-navigation.md)|基于Excalidraw的保险库(Vault)图形用户界面。需要[Dataview插件](https://github.com/blacksmithgu/obsidian-dataview)。生成类似于[TheBrain](https://TheBrain.com)的图形视图。在[YouTube](https://youtu.be/plYobK-VufM)上观看此脚本的介绍。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[移动端切换全屏](../../../ea-scripts/Toggle%20Fullscreen%20on%20Mobile.md)|隐藏Obsidian工作区叶片填充和标题(基于设置中的选项,默认"隐藏标题"=false),这将使Excalidraw全屏显示。⚠ 注意,如果标题不可见,将很难调用命令面板来结束全屏。只有在你有键盘或已经练习过打开命令面板的情况下才隐藏标题!||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[切换网格](../../../ea-scripts/Toggle%20Grid.md)|切换网格的显示与隐藏。||[@GColoy](https://github.com/GColoy)|
|
||||
|[将文本元素转移到Excalidraw markdown元数据](../../../ea-scripts/Transfer%20TextElements%20to%20Excalidraw%20markdown%20metadata.md)|此脚本将从画布中删除选中的文本元素,并将这些文本元素中的文本复制到Excalidraw markdown文件的元数据中。这意味着,文本将不再在绘图中可见,但你可以在Obsidian中搜索文本并找到包含此图像的绘图。||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[缩放以适应选中元素](../../../ea-scripts/Zoom%20to%20Fit%20Selected%20Elements.md)|类似于Excalidraw标准的<kbd>SHIFT+2</kbd>功能:缩放以适应选中元素,但可以缩放到1000%。灵感来源:[#272](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/272)||[@zsviczian](https://github.com/zsviczian)|
|
||||
|[硬件橡皮擦支持](../../../ea-scripts/Hardware%20Eraser%20Support.md)|允许在支持的笔上使用笔反转/硬件橡皮擦。|[@threethan](https://github.com/threethan)|
|
||||
|[笔的自动绘制](../../../ea-scripts/Auto%20Draw%20for%20Pen.md)|当悬停笔时自动从选择工具切换到绘制工具,然后再切换回来。|[@threethan](https://github.com/threethan)|
|
||||
@@ -22,4 +22,4 @@ elements.forEach((el)=>{
|
||||
);
|
||||
ea.addToGroup([el.id,ellipseId]);
|
||||
});
|
||||
ea.addElementsToView();
|
||||
await ea.addElementsToView(false,false,true);
|
||||
|
||||
1
ea-scripts/Add Connector Point.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="100 100 500 400"><path fill-rule="evenodd" d="M414.57 183.49a11.194 11.194 0 0 0-10.344 6.914 11.21 11.21 0 0 0-.851 4.285v74.086h-110.09c-5.57-47.172-45.852-83.945-94.48-83.945-52.418 0-95.2 42.715-95.2 95.145 0 52.43 42.782 95.141 95.2 95.141 48.629 0 88.91-36.773 94.48-83.945h110.09v74.145c0 1.465.293 2.93.851 4.285a11.184 11.184 0 0 0 10.344 6.91H585.2c1.465 0 2.93-.292 4.285-.85a11.184 11.184 0 0 0 6.91-10.344v-170.63c0-1.466-.293-2.93-.851-4.286a11.246 11.246 0 0 0-2.426-3.633c-1.035-1.035-2.277-1.867-3.633-2.43s-2.82-.851-4.285-.851z"/></svg>
|
||||
|
After Width: | Height: | Size: 604 B |
@@ -45,7 +45,7 @@ ea.style.strokeColor = "rgba(70,130,180,0.05)"
|
||||
ea.style.strokeWidth = 2;
|
||||
ea.style.roughness = 0;
|
||||
|
||||
if(elements.lenght===1 && elements[0].type !== "text") {
|
||||
if(elements.length===1 && elements[0].type !== "text") {
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
ea.getElements()[0].link = link;
|
||||
} else {
|
||||
@@ -62,4 +62,4 @@ if(openInCurrentPane) {
|
||||
app.workspace.openLinkText(file.path,ea.targetView.file.path,false);
|
||||
return;
|
||||
}
|
||||
ea.openFileInNewOrAdjacentLeaf(file);
|
||||
ea.openFileInNewOrAdjacentLeaf(file);
|
||||
|
||||
1
ea-scripts/Add Link to Existing File and Open.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="5 5 130 110" stroke="#000"><path fill="none" stroke-linecap="round" stroke-width="4" d="M10 30h40m-40 0h40m0 0 20 20M50 30l20 20m0 0v60m0-60v60m0 0H10m60 0H10m0 0V30m0 80V30"/><path fill="none" stroke-linecap="round" stroke-width="2" d="M50 30v20m0-20v20m0 0h20m-20 0h20"/><path fill="none" stroke-linecap="round" stroke-width="4" d="M110 10H90m20 0H90m0 0v40m0-40v40m0 0h40m-40 0h40m0 0V30m0 20V30M110 30l20-20m-20 20 20-20M120 10h10m-10 0h10m0 0v10m0-10v10"/></svg>
|
||||
|
After Width: | Height: | Size: 519 B |
@@ -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)}]]`;
|
||||
@@ -71,7 +70,7 @@ ea.style.strokeColor = "rgba(70,130,180,0.05)"
|
||||
ea.style.strokeWidth = 2;
|
||||
ea.style.roughness = 0;
|
||||
|
||||
if(elements.lenght===1 && elements[0].type !== "text") {
|
||||
if(elements.length===1 && elements[0].type !== "text") {
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
ea.getElements()[0].link = link;
|
||||
} else {
|
||||
@@ -88,4 +87,4 @@ if(openInCurrentPane) {
|
||||
app.workspace.openLinkText(file.path,ea.targetView.file.path,false);
|
||||
return;
|
||||
}
|
||||
ea.openFileInNewOrAdjacentLeaf(file);
|
||||
ea.openFileInNewOrAdjacentLeaf(file);
|
||||
|
||||
1
ea-scripts/Add Link to New Page and Open.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="5 5 130 110" stroke="#000"><path fill="none" stroke-linecap="round" stroke-width="4" d="M10 30h40m-40 0h40m0 0 20 20M50 30l20 20m0 0v60m0-60v60m0 0H10m60 0H10m0 0V30m0 80V30"/><path fill="none" stroke-linecap="round" stroke-width="2" d="M50 30v20m0-20v20m0 0h20m-20 0h20"/><path fill="none" stroke-linecap="round" stroke-width="4" d="M110 10H90m20 0H90m0 0v40m0-40v40m0 0h40m-40 0h40m0 0V30m0 20V30M110 30l20-20m-20 20 20-20M120 10h10m-10 0h10m0 0v10m0-10v10"/><path fill="none" stroke-linecap="round" stroke-width="8" d="M40.351 60.667v27m0-27v27M26.851 74.167h26.69m-26.69 0h26.69"/></svg>
|
||||
|
After Width: | Height: | Size: 643 B |
@@ -67,6 +67,7 @@ if(!isFirst) {
|
||||
ea.copyViewElementsToEAforEditing([fromElement]);
|
||||
|
||||
const previousTextElements = elements.filter((el)=>el.type==="text");
|
||||
const previousRectElements = elements.filter((el)=> ['ellipse', 'rectangle', 'diamond'].includes(el.type));
|
||||
if(previousTextElements.length>0) {
|
||||
const el = previousTextElements[0];
|
||||
ea.style.strokeColor = el.strokeColor;
|
||||
@@ -77,7 +78,7 @@ if(!isFirst) {
|
||||
textWidth = ea.measureText(text).width;
|
||||
|
||||
id = ea.addText(
|
||||
fixWidth
|
||||
fixWidth
|
||||
? fromElement.x+fromElement.width/2-width/2
|
||||
: fromElement.x+fromElement.width/2-textWidth/2-textPadding,
|
||||
fromElement.y+fromElement.height+gapBetweenElements,
|
||||
@@ -85,7 +86,8 @@ if(!isFirst) {
|
||||
{
|
||||
wrapAt: wrapLineLen,
|
||||
textAlign: "center",
|
||||
box: "rectangle",
|
||||
textVerticalAlign: "middle",
|
||||
box: previousRectElements.length > 0 ? previousRectElements[0].type : false,
|
||||
...fixWidth
|
||||
? {width: width, boxPadding:0}
|
||||
: {boxPadding: textPadding}
|
||||
@@ -104,16 +106,21 @@ if(!isFirst) {
|
||||
}
|
||||
);
|
||||
|
||||
const rect = ea.getElement(id);
|
||||
rect.strokeColor = fromElement.strokeColor;
|
||||
rect.strokeWidth = fromElement.strokeWidth;
|
||||
rect.strokeStyle = fromElement.strokeStyle;
|
||||
rect.roughness = fromElement.roughness;
|
||||
rect.strokeSharpness = fromElement.strokeSharpness;
|
||||
rect.backgroundColor = fromElement.backgroundColor;
|
||||
rect.fillStyle = fromElement.fillStyle;
|
||||
if (previousRectElements.length>0) {
|
||||
const rect = ea.getElement(id);
|
||||
rect.strokeColor = fromElement.strokeColor;
|
||||
rect.strokeWidth = fromElement.strokeWidth;
|
||||
rect.strokeStyle = fromElement.strokeStyle;
|
||||
rect.roughness = fromElement.roughness;
|
||||
rect.roundness = fromElement.roundness;
|
||||
rect.strokeSharpness = fromElement.strokeSharpness;
|
||||
rect.backgroundColor = fromElement.backgroundColor;
|
||||
rect.fillStyle = fromElement.fillStyle;
|
||||
rect.width = fromElement.width;
|
||||
rect.height = fromElement.height;
|
||||
}
|
||||
|
||||
await ea.addElementsToView(false);
|
||||
await ea.addElementsToView(false,false);
|
||||
} else {
|
||||
id = ea.addText(
|
||||
0,
|
||||
@@ -122,12 +129,13 @@ if(!isFirst) {
|
||||
{
|
||||
wrapAt: wrapLineLen,
|
||||
textAlign: "center",
|
||||
textVerticalAlign: "middle",
|
||||
box: "rectangle",
|
||||
boxPadding: textPadding,
|
||||
...fixWidth?{width: width}:null
|
||||
}
|
||||
);
|
||||
await ea.addElementsToView(true);
|
||||
await ea.addElementsToView(true,false);
|
||||
}
|
||||
|
||||
ea.selectElementsInView([ea.getElement(id)]);
|
||||
1
ea-scripts/Add Next Step in Process.svg
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
208
ea-scripts/Archive/Alternative Pens.md
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
IF YOU ACCIDENTLY MODIFY THIS FILE AND IT STOPS WORKING, SIMPLY DOWNLOAD IT AGAIN FROM THE SCRIPT LIBRARY.
|
||||
|
||||

|
||||
|
||||
# How to create a new pen template
|
||||
It takes a bit of experimentation and skill to create a new pen, so be patient.
|
||||
|
||||
1. Create a folder in your Vault for your pen options. The default is `Excalidraw/Pens`.
|
||||
2. Create a new markdown file in your in the `pen folder` (e.g. `My pen`).
|
||||
3. Copy the following template to the markdown file.
|
||||
```json
|
||||
{
|
||||
"highlighter": true,
|
||||
"constantPressure": false,
|
||||
"hasOutline": true,
|
||||
"outlineWidth": 4,
|
||||
"options": PASTE_PREFECT_FREEHAND_OPTIONS_HERE
|
||||
}
|
||||
```
|
||||
4. If you don't want your pen to have an outline around your line, change `hasOutline` to `false`. You can also modify `outlineWidth` if you want a thinner or thicker outline around your line.
|
||||
5. If you want your pen to be pressure sensitive (when drawing with a mouse the pressure is simulated based on the speed of your hand) leave `constantPressure` as `false`. If you want a constant line width regardless of speed and pen pressure, change it to `true`.
|
||||
6. `highlighter` true will place the new line behind the existing strokes (i.e. like a highlighter pen). If `highlighter` is missing or it is set to `false` the new line will appear at the top of the existing strokes (the default behavior of Excalidraw pens).
|
||||
7. Go to https://perfect-freehand-example.vercel.app/ and configure your pen.
|
||||
8. Click `Copy Options`.
|
||||
9. Go back to the pen file you created in step No.2 and replace the placeholder text with the options you just copied from perfect-freehand.
|
||||
10. Look for `easing` in the file and replace the function e.g. `(t) => t*t,` with the name of the function in brackets (in this example it would be `easeInQuad`). You will find the function name on the perfect-freehand website, only change the first letter to be lower case.
|
||||
11. Test your pen in Excalidraw by clicking the `Alternative Pens` script and selecting your new pen.
|
||||
|
||||
# Example pens
|
||||
My pens: https://github.com/zsviczian/obsidian-excalidraw-plugin/tree/master/ea-scripts/pens
|
||||
|
||||
**Fine tipped pen:**
|
||||
```json
|
||||
{
|
||||
constantPressure: true,
|
||||
options: {
|
||||
smoothing: 0.4,
|
||||
thinning: -0.5,
|
||||
streamline: 0.4,
|
||||
easing: "linear",
|
||||
start: {
|
||||
taper: 5,
|
||||
cap: false,
|
||||
},
|
||||
end: {
|
||||
taper: 5,
|
||||
cap: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Thick marker:**
|
||||
```json
|
||||
{
|
||||
constantPressure: true,
|
||||
hasOutline: true,
|
||||
outlineWidth: 4,
|
||||
options: {
|
||||
thinning: 1,
|
||||
smoothing: 0.5,
|
||||
streamline: 0.5,
|
||||
easing: "linear",
|
||||
start: {
|
||||
taper: 0,
|
||||
cap: true
|
||||
},
|
||||
end: {
|
||||
taper: 0,
|
||||
cap: true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Fountain pen:**
|
||||
```json
|
||||
{
|
||||
options: {
|
||||
smoothing: 0.22,
|
||||
thinning: 0.8,
|
||||
streamline: 0.22,
|
||||
easing: "easeInQuad",
|
||||
start: {
|
||||
taper: true,
|
||||
cap: true,
|
||||
},
|
||||
end: {
|
||||
taper: 1,
|
||||
cap: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
# Notes about the pen options
|
||||
|
||||
Note, that custom pens are currently not supported by Excalidraw.com. I've submitted a [PR](https://github.com/excalidraw/excalidraw/pull/6069) but there is no guarantee that it will get pushed to production. Your Excalidraw drawing can still be loaded to Excalidraw, but the special pen effects will not be visible there.
|
||||
|
||||
If you set a pen in your Excalidraw template file, that pen will be loaded automatically when you create a file using that template. Similarly, when you save a document, it will save your current pen settings as well. The next time you open the document, you can continue to use the same pen.
|
||||
|
||||
Pen options are saved with the stroke. This means, that even if you change the ped definition later on, your existing drawings will not be effected.
|
||||
|
||||
`outlineWidth` is relative to `strokeWidth`. i.e. if you make the stroke thinner in Excalidraw, the outline will become proportionally thinner as well. `outlineWidth` is only used if `hasOutline` is set to true.
|
||||
|
||||
If you don't want your pen to be pressure/speed sensitive, set `constantPressure` to `true`. Setting `constantPressure` to `true` automatically sets `simulatePressure` to `false`.
|
||||
|
||||
If you want your pen to be speed sensitive (i.e. the faster you draw the line the thinner it gets), set `options.simulatePressure` to `true`. If you omit `simulatePressure` from `options` then excalidraw will detect if you are drawing with a mouse or a pen and use pen pressures if available.
|
||||
|
||||
You can read more about configuring perfect freehand here: https://github.com/steveruizok/perfect-freehand#documentation
|
||||
|
||||
Excalidraw supports all of the easing functions listed here: https://easings.net/#, plus "linear". You can also find details about these easing functions here:
|
||||
https://github.com/ai/easings.net/blob/master/src/easings/easingsFunctions.ts
|
||||
|
||||
From a performance perspective I recommend linear easing.
|
||||
|
||||
# The script
|
||||
|
||||
```javascript */
|
||||
|
||||
//--------------------------
|
||||
// Load settings
|
||||
//--------------------------
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.8.8")) {
|
||||
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["Pen folder"]) {
|
||||
settings = {
|
||||
"Pen folder" : {
|
||||
value: "Excalidraw/Pens",
|
||||
description: "The path to the folder where you store the perfect freehand options"
|
||||
}
|
||||
};
|
||||
ea.setScriptSettings(settings);
|
||||
}
|
||||
|
||||
let penFolder = settings["Pen folder"].value.toLowerCase();
|
||||
if(penFolder === "" || penFolder === "/") {
|
||||
new Notice("The pen folder cannot be the root folder of your vault");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!penFolder.endsWith("/")) penFolder += "/";
|
||||
|
||||
|
||||
//--------------------------
|
||||
// Select pen
|
||||
//--------------------------
|
||||
const pens = app.vault.getFiles()
|
||||
.filter(f=>f.extension === "md" && f.path.toLowerCase() === penFolder + f.name.toLowerCase())
|
||||
.sort((a,b)=>a.basename.toLowerCase()<b.basename.toLowerCase()?-1:1);
|
||||
if(pens.length === 0) {
|
||||
const notice = new Notice(`You don't seem to have any pen definition files. Click this message to open the how-to guide.`,4000);
|
||||
notice.noticeEl.onclick = async () => app.workspace.openLinkText(utils.scriptFile.path,"","tab");
|
||||
return;
|
||||
}
|
||||
const file = await utils.suggester(["Excalidraw Default"].concat(pens.map(f=>(f.name.slice(0,f.name.length-3)))),["Default"].concat(pens), "Choose a pen preset, press ESC to abort");
|
||||
if(!file) return;
|
||||
|
||||
if(file === "Default") {
|
||||
api.updateScene({
|
||||
appState: {
|
||||
currentStrokeOptions: undefined
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
//--------------------------
|
||||
// Load pen
|
||||
//--------------------------
|
||||
const pen = await app.vault.read(file);
|
||||
|
||||
const parseJSON = (data) => {
|
||||
try {
|
||||
return JSON.parse(data);
|
||||
} catch(e) {
|
||||
try {
|
||||
return JSON.parse(data.replaceAll(/\s(\w*)\:\s/g,' "$1": ').replaceAll(/,([^\w]*?})/gm,"$1"));
|
||||
} catch(ee) {
|
||||
const notice = new Notice(`Error loading the pen file. Maybe you accidently copy/pasted the easing function from perfect freehand website? Check the error message in Developer Console.\n(click=dismiss, right-click=Info) `,5000);
|
||||
notice.noticeEl.oncontextmenu = async () => app.workspace.openLinkText(utils.scriptFile.path,"","tab");
|
||||
console.error(ee);
|
||||
console.error(data.replaceAll(/\s(\w*)\:\s/g,' "$1": ').replaceAll(/,([^\w]*?})/gm,"$1"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
penJSON = parseJSON(pen);
|
||||
|
||||
|
||||
if(!penJSON || typeof penJSON !== 'object') return;
|
||||
|
||||
//--------------------------
|
||||
// Apply pen
|
||||
//--------------------------
|
||||
await api.updateScene({
|
||||
appState: {
|
||||
currentStrokeOptions: penJSON
|
||||
}
|
||||
});
|
||||
api.setActiveTool({type:"freedraw"});
|
||||
1
ea-scripts/Archive/Alternative Pens.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 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="M373.5 27.1C388.5 9.9 410.2 0 433 0c43.6 0 79 35.4 79 79c0 22.8-9.9 44.6-27.1 59.6L277.7 319l-10.3-10.3-64-64L193 234.3 373.5 27.1zM170.3 256.9l10.4 10.4 64 64 10.4 10.4-19.2 83.4c-3.9 17.1-16.9 30.7-33.8 35.4L24.4 510.3l95.4-95.4c2.6 .7 5.4 1.1 8.3 1.1c17.7 0 32-14.3 32-32s-14.3-32-32-32s-32 14.3-32 32c0 2.9 .4 5.6 1.1 8.3L1.7 487.6 51.5 310c4.7-16.9 18.3-29.9 35.4-33.8l83.4-19.2z"/></svg>
|
||||
|
After Width: | Height: | Size: 632 B |
@@ -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 extract 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);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="100 120 500 320"><path d="M474.32 295.68H225.68c-8.398 0-15.68-6.719-15.68-15.68 0-8.398 6.719-15.68 15.68-15.68h248.64c8.398 0 15.68 6.719 15.68 15.68 0 8.398-6.719 15.68-15.68 15.68z"/><path d="m454.16 182-53.199-53.199c-2.8-2.8-6.719-4.48-11.199-4.48h-117.6c-17.359 0-31.359 14-31.359 31.358v108.64h31.359v-100.8c0-4.48 3.36-7.84 7.84-7.84h77.84v42c0 15.68 12.32 28 28 28h42v38.642H459.2V193.2c-.559-4.48-1.68-8.399-5.04-11.2zm-65.52 12.32v-33.602l33.602 33.602zM427.84 396.48c0 4.48-3.36 7.84-7.84 7.84H280c-4.48 0-7.84-3.36-7.84-7.84v-54.32c0-8.398-6.718-15.68-15.68-15.68-8.398 0-15.68 6.719-15.68 15.68v62.16c0 17.359 14 31.359 31.36 31.359h155.68c17.358 0 31.358-14 31.358-31.359v-62.16c0-8.398-6.718-15.68-15.68-15.68-8.398 0-15.68 6.719-15.68 15.68zM370.16 326.48h-66.641c-4.48 0-7.84-3.36-7.84-7.84s3.36-7.84 7.84-7.84h66.641c4.48 0 7.84 3.36 7.84 7.84s-3.922 7.84-7.84 7.84z"/><path d="M350 357.84h-46.48c-4.48 0-7.84-3.36-7.84-7.84s3.36-7.84 7.84-7.84H350c4.48 0 7.84 3.36 7.84 7.84s-3.36 7.84-7.84 7.84z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
1080
ea-scripts/Archive/TheBrain-navigation.md
Normal file
1
ea-scripts/Archive/TheBrain-navigation.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M380.6 365.6C401.1 379.9 416 404.3 416 432C416 476.2 380.2 512 336 512C291.8 512 256 476.2 256 432C256 423.6 257.3 415.4 259.7 407.8L114.1 280.4C103.8 285.3 92.21 288 80 288C35.82 288 0 252.2 0 208C0 163.8 35.82 128 80 128C101.9 128 121.7 136.8 136.2 151.1L320 77.52C321.3 34.48 356.6 0 400 0C444.2 0 480 35.82 480 80C480 117.9 453.7 149.6 418.4 157.9L380.6 365.6zM156.3 232.2L301.9 359.6C306.9 357.3 312.1 355.4 317.6 354.1L355.4 146.4C351.2 143.6 347.4 140.4 343.8 136.9L159.1 210.5C159.7 218 158.5 225.3 156.3 232.2V232.2z"/></svg>
|
||||
|
After Width: | Height: | Size: 605 B |
49
ea-scripts/Archive/Toggle Fullscreen on Mobile.md
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||

|
||||
|
||||
Hides Obsidian workspace leaf padding and header (based on option in settings, default is "hide header" = true) 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!
|
||||
|
||||
```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();
|
||||
|
||||
if(!settings["Hide header"]) {
|
||||
settings = {
|
||||
"Hide header": {
|
||||
value: false,
|
||||
},
|
||||
...settings
|
||||
};
|
||||
await ea.setScriptSettings(settings);
|
||||
}
|
||||
|
||||
if(!settings["Hide header"].description) {
|
||||
settings["Hide header"].description = "⚠ 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!";
|
||||
await ea.setScriptSettings(settings);
|
||||
}
|
||||
|
||||
const hideHeader = settings["Hide header"].value;
|
||||
|
||||
const newStylesheet = document.createElement("style");
|
||||
newStylesheet.id = "excalidraw-full-screen";
|
||||
newStylesheet.textContent = `
|
||||
.workspace-leaf-content .view-content {
|
||||
padding: 0px !important;
|
||||
}
|
||||
${hideHeader?`
|
||||
.view-header {
|
||||
height: 1px !important;
|
||||
}`:""}
|
||||
.status-bar {
|
||||
display: none !important;
|
||||
}
|
||||
`;
|
||||
|
||||
const oldStylesheet = document.getElementById(newStylesheet.id);
|
||||
if(oldStylesheet) document.head.removeChild(oldStylesheet);
|
||||
else document.head.appendChild(newStylesheet);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="100 60 500 450"><path d="M563.9 229.44V77.77c0-6.441-5.219-11.668-11.668-11.668h-151.67c-3.098 0-6.063 1.23-8.25 3.418l-252.79 252.79c-4.559 4.559-4.559 11.941 0 16.496l151.67 151.67a11.636 11.636 0 0 0 8.25 3.418c2.984 0 5.969-1.14 8.25-3.418l48.582-48.57c20.082 31.219 55.047 51.988 94.844 51.988 62.184 0 112.78-50.598 112.78-112.78 0-39.797-20.781-74.773-52-94.848l48.582-48.582a11.683 11.683 0 0 0 3.414-8.246zm-23.336 151.68c0 49.32-40.125 89.449-89.449 89.449-49.32 0-89.445-40.125-89.445-89.449 0-49.32 40.125-89.445 89.445-89.445 49.324 0 89.449 40.125 89.449 89.445zm0-156.51-50.723 50.723c-12.098-4.441-25.109-6.996-38.727-6.996-62.184 0-112.78 50.598-112.78 112.78 0 13.625 2.55 26.625 6.996 38.727l-45.887 45.89-135.17-135.17 241.12-241.12h135.17zm-64.176-34.043c20.371 0 36.945-16.578 36.945-36.949s-16.574-36.945-36.945-36.945-36.949 16.578-36.949 36.949c0 20.367 16.578 36.945 36.949 36.945zm0-50.562c7.508 0 13.613 6.106 13.613 13.613 0 7.508-6.106 13.613-13.613 13.613-7.508 0-13.613-6.106-13.613-13.613-.004-7.508 6.102-13.613 13.613-13.613zm-25.285 178.9c6.45 0 11.668 5.219 11.668 11.668v38.887l38.898-.004c6.45 0 11.668 5.219 11.668 11.668 0 6.45-5.219 11.668-11.668 11.668h-38.898v38.883c0 6.45-5.219 11.668-11.668 11.668a11.661 11.661 0 0 1-11.668-11.668v-38.887h-38.887c-6.45 0-11.668-5.219-11.668-11.668s5.219-11.668 11.668-11.668h38.887v-38.887c.004-6.445 5.223-11.66 11.668-11.66z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -1,314 +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]]
|
||||
- [[#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]]
|
||||
- [[#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>
|
||||
|
||||
## 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>
|
||||
|
||||
## 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 available (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 extract 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>
|
||||
399
ea-scripts/Auto Layout.md
Normal file
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
|
||||

|
||||
|
||||
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, g) => [...result, ...g.filter(el => el.type === 'arrow')], []);
|
||||
|
||||
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 |
374
ea-scripts/Boolean Operations.md
Normal file
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
With This Script it is possible to make boolean Operations on Shapes.
|
||||
The style of the resulting shape will be the style of the highest ranking Element that was used.
|
||||
The ranking of the elements is based on their background. The "denser" the background, the higher the ranking (the order of backgroundstyles is shown below). If they have the same background the opacity will decide. If thats also the same its decided by the order they were created.
|
||||
The ranking is also important for the difference operation, so a transparent object for example will cut a hole into a solid object.
|
||||

|
||||

|
||||
|
||||
|
||||
See documentation for more details:
|
||||
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
|
||||
|
||||
```javascript
|
||||
*/
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.9.20")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
const ShadowGroupMarker = "ShadowCloneOf-";
|
||||
|
||||
const elements = ea.getViewSelectedElements().filter(
|
||||
el=>["ellipse", "rectangle", "diamond"].includes(el.type) ||
|
||||
el.groupIds.some(id => id.startsWith(ShadowGroupMarker)) ||
|
||||
(["line", "arrow"].includes(el.type) && el.roundness === null)
|
||||
);
|
||||
if(elements.length < 2) {
|
||||
new Notice ("Select ellipses, rectangles, diamonds; or lines and arrows with sharp edges");
|
||||
return;
|
||||
}
|
||||
|
||||
const PolyBool = ea.getPolyBool();
|
||||
const polyboolAction = await utils.suggester(["union (a + b)", "intersect (a && b)", "difference (a - b)", "reversed difference (b - a)", "xor"], [
|
||||
PolyBool.union, PolyBool.intersect, PolyBool.difference, PolyBool.differenceRev, PolyBool.xor
|
||||
], "What would you like todo with the object");
|
||||
|
||||
const shadowClones = elements.filter(element => element.groupIds.some(id => id.startsWith(ShadowGroupMarker)));
|
||||
shadowClones.forEach(shadowClone => {
|
||||
let parentId = shadowClone.groupIds
|
||||
.filter(id => id.startsWith(ShadowGroupMarker))[0]
|
||||
.slice(ShadowGroupMarker.length);
|
||||
const shadowCloneIndex = elements.findIndex(element => element.id == parentId);
|
||||
if (shadowCloneIndex == -1) return;
|
||||
elements[shadowCloneIndex].backgroundColor = shadowClone.backgroundColor;
|
||||
elements[shadowCloneIndex].fillStyle = shadowClone.fillStyle;
|
||||
})
|
||||
const borderElements = elements.filter(element => !element.groupIds.some(id => id.startsWith(ShadowGroupMarker)));
|
||||
groups = ea.getMaximumGroups(borderElements);
|
||||
groups = groups.map((group) => group.sort((a, b) => RankElement(b) - RankElement(a)));
|
||||
groups.sort((a, b) => RankElement(b[0]) - RankElement(a[0]));
|
||||
|
||||
ea.style.strokeColor = groups[0][0].strokeColor;
|
||||
ea.style.backgroundColor = groups[0][0].backgroundColor;
|
||||
ea.style.fillStyle = groups[0][0].fillStyle;
|
||||
ea.style.strokeWidth = groups[0][0].strokeWidth;
|
||||
ea.style.strokeStyle = groups[0][0].strokeStyle;
|
||||
ea.style.roughness = groups[0][0].roughness;
|
||||
ea.style.opacity = groups[0][0].opacity;
|
||||
|
||||
const basePolygons = groups.shift().map(element => traceElement(element));
|
||||
const toolPolygons = groups.flatMap(group => group.map(element => traceElement(element)));
|
||||
|
||||
const result = polyboolAction({
|
||||
regions: basePolygons,
|
||||
inverted: false
|
||||
}, {
|
||||
regions: toolPolygons,
|
||||
inverted: false
|
||||
});
|
||||
const polygonHierachy = subordinateInnerPolygons(result.regions);
|
||||
drawPolygonHierachy(polygonHierachy);
|
||||
ea.deleteViewElements(elements);
|
||||
setPolygonTrue();
|
||||
ea.addElementsToView(false,false,true);
|
||||
return;
|
||||
|
||||
function setPolygonTrue() {
|
||||
ea.getElements().filter(el=>el.type==="line").forEach(el => {
|
||||
el.polygon = true;
|
||||
});
|
||||
}
|
||||
|
||||
function traceElement(element) {
|
||||
const diamondPath = (diamond) => [
|
||||
SxVEC(1/2, [0, diamond.height]),
|
||||
SxVEC(1/2, [diamond.width, 0]),
|
||||
addVec([SxVEC(1/2, [0, diamond.height]), ([diamond.width, 0])]),
|
||||
addVec([SxVEC(1/2, [diamond.width, 0]), ([0, diamond.height])]),
|
||||
SxVEC(1/2, [0, diamond.height])
|
||||
];
|
||||
const rectanglePath = (rectangle) => [
|
||||
[0,0],
|
||||
[0, rectangle.height],
|
||||
[rectangle.width, rectangle.height],
|
||||
[rectangle.width, 0],
|
||||
[0, 0]
|
||||
]
|
||||
const ellipsePath = (ellipse) => {
|
||||
const angle = ellipse.angle;
|
||||
const width = ellipse.width;
|
||||
const height = ellipse.height;
|
||||
const ellipseAtPoint = (t) => {
|
||||
const spanningVector = [width/2*Math.cos(t), height/2*Math.sin(t)];
|
||||
const baseVector = [width/2, height/2];
|
||||
return addVec([spanningVector, baseVector]);
|
||||
}
|
||||
let points = [];
|
||||
step = (2*Math.PI)/64
|
||||
for (let t = 0; t < 2*Math.PI; t = t + step) {
|
||||
points.push(ellipseAtPoint(t));
|
||||
}
|
||||
return points;
|
||||
}
|
||||
let polygon;
|
||||
let correctForPolygon = [0, 0];
|
||||
switch (element.type) {
|
||||
case "diamond":
|
||||
polygon = diamondPath(element);
|
||||
break;
|
||||
case "rectangle":
|
||||
polygon = rectanglePath(element);
|
||||
break;
|
||||
case "ellipse":
|
||||
polygon = ellipsePath(element);
|
||||
break;
|
||||
case "line":
|
||||
case "arrow":
|
||||
if (element.angle != 0) {
|
||||
let smallestX = 0;
|
||||
let smallestY = 0;
|
||||
element.points.forEach(point => {
|
||||
if (point[0] < smallestX) smallestX = point[0];
|
||||
if (point[1] < smallestY) smallestY = point[1];
|
||||
});
|
||||
polygon = element.points.map(point => {
|
||||
return [
|
||||
point[0] -= smallestX,
|
||||
point[1] -= smallestY
|
||||
];
|
||||
});
|
||||
correctForPolygon = [smallestX, smallestY];
|
||||
break;
|
||||
}
|
||||
if (element.roundness) {
|
||||
new Notice("This script does not work with curved lines or arrows yet!");
|
||||
return [];
|
||||
}
|
||||
polygon = element.points;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (element.angle == 0) return polygon.map(v => addVec([v, [element.x, element.y]]));
|
||||
|
||||
polygon = polygon.map(v => addVec([v, SxVEC(-1/2, [element.width, element.height])]));
|
||||
polygon = rotateVectorsByAngle(polygon, element.angle);
|
||||
return polygon.map(v => addVec([v, [element.x, element.y], SxVEC(1/2, [element.width, element.height]), correctForPolygon]));
|
||||
}
|
||||
|
||||
function RankElement(element) {
|
||||
let score = 0;
|
||||
const backgroundRank = [
|
||||
"dashed",
|
||||
"none",
|
||||
"hachure",
|
||||
"zigzag",
|
||||
"zigzag-line",
|
||||
"cross-hatch",
|
||||
"solid"
|
||||
]
|
||||
score += (backgroundRank.findIndex((fillStyle) => fillStyle == element.fillStyle) + 1) * 10;
|
||||
if (element.backgroundColor == "transparent") score -= 100;
|
||||
if (element.points && getVectorLength(element.points[element.points.length - 1]) > 8) score -= 100;
|
||||
if (score < 0) score = 0;
|
||||
score += element.opacity / 100;
|
||||
return score;
|
||||
}
|
||||
|
||||
function drawPolygonHierachy(polygonHierachy) {
|
||||
const backgroundColor = ea.style.backgroundColor;
|
||||
const strokeColor = ea.style.strokeColor;
|
||||
const setInnerStyle = () => {
|
||||
ea.style.backgroundColor = backgroundColor;
|
||||
ea.style.strokeColor = "transparent";
|
||||
}
|
||||
const setBorderStyle = () => {
|
||||
ea.style.backgroundColor = "transparent";
|
||||
ea.style.strokeColor = strokeColor;
|
||||
}
|
||||
const setFilledStyle = () => {
|
||||
ea.style.backgroundColor = backgroundColor;
|
||||
ea.style.strokeColor = strokeColor;
|
||||
}
|
||||
|
||||
polygonHierachy.forEach(polygon => {
|
||||
setFilledStyle();
|
||||
let path = polygon.path;
|
||||
path.push(polygon.path[0]);
|
||||
if (polygon.innerPolygons.length === 0) {
|
||||
ea.addLine(path);
|
||||
return;
|
||||
}
|
||||
const outerBorder = path;
|
||||
const innerPolygons = addInnerPolygons(polygon.innerPolygons);
|
||||
path = path.concat(innerPolygons.backgroundPath);
|
||||
path.push(polygon.path[0]);
|
||||
setInnerStyle();
|
||||
const backgroundId = ea.addLine(path);
|
||||
setBorderStyle();
|
||||
const outerBorderId = ea.addLine(outerBorder)
|
||||
const innerBorderIds = innerPolygons.borderPaths.map(path => ea.addLine(path));
|
||||
const allIds = [innerBorderIds, outerBorderId, backgroundId].flat();
|
||||
ea.addToGroup(allIds);
|
||||
const background = ea.getElement(backgroundId);
|
||||
background.groupIds.push(ShadowGroupMarker + outerBorderId);
|
||||
});
|
||||
}
|
||||
|
||||
function addInnerPolygons(polygonHierachy) {
|
||||
let firstPath = [];
|
||||
let secondPath = [];
|
||||
let borderPaths = [];
|
||||
polygonHierachy.forEach(polygon => {
|
||||
let path = polygon.path;
|
||||
path.push(polygon.path[0]);
|
||||
borderPaths.push(path);
|
||||
firstPath = firstPath.concat(path);
|
||||
secondPath.push(polygon.path[0]);
|
||||
drawPolygonHierachy(polygon.innerPolygons);
|
||||
});
|
||||
return {
|
||||
backgroundPath: firstPath.concat(secondPath.reverse()),
|
||||
borderPaths: borderPaths
|
||||
};
|
||||
}
|
||||
|
||||
function subordinateInnerPolygons(polygons) {
|
||||
const polygonObjectPrototype = (polygon) => {
|
||||
return {
|
||||
path: polygon,
|
||||
innerPolygons: []
|
||||
};
|
||||
}
|
||||
|
||||
const insertPolygonIntoHierachy = (polygon, hierarchy) => {
|
||||
for (let i = 0; i < hierarchy.length; i++) {
|
||||
const polygonObject = hierarchy[i];
|
||||
let inside = null;
|
||||
let pointIndex = 0;
|
||||
do {
|
||||
inside = pointInPolygon(polygon[pointIndex], polygonObject.path);
|
||||
pointIndex++
|
||||
} while (inside === null);
|
||||
if (inside) {
|
||||
hierarchy[i].innerPolygons = insertPolygonIntoHierachy(polygon, hierarchy[i].innerPolygons);
|
||||
return hierarchy;
|
||||
}
|
||||
}
|
||||
polygon = polygonObjectPrototype(polygon);
|
||||
for (let i = 0; i < hierarchy.length; i++) {
|
||||
const polygonObject = hierarchy[i];
|
||||
let inside = null;
|
||||
let pointIndex = 0;
|
||||
do {
|
||||
inside = pointInPolygon(polygonObject.path[pointIndex], polygon.path);
|
||||
pointIndex++
|
||||
} while (inside === null);
|
||||
if (inside) {
|
||||
polygon.innerPolygons.push(hierarchy.splice(i, 1)[0]);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
hierarchy.push(polygon);
|
||||
return hierarchy;
|
||||
}
|
||||
|
||||
let polygonHierachy = [];
|
||||
polygons.forEach(polygon => {
|
||||
polygonHierachy = insertPolygonIntoHierachy(polygon, polygonHierachy);
|
||||
})
|
||||
|
||||
return polygonHierachy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given point lays in the polygon
|
||||
* @param point array [x, y]
|
||||
* @param polygon array [[x, y], ...]
|
||||
* @returns true if inside, false if not, null if the point is on one of the polygons vertecies
|
||||
*/
|
||||
function pointInPolygon(point, polygon) {
|
||||
const x = point[0];
|
||||
const y = point[1];
|
||||
let inside = false;
|
||||
|
||||
// odd even test if point is in polygon
|
||||
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
||||
const xi = polygon[i][0];
|
||||
const yi = polygon[i][1];
|
||||
const xj = polygon[j][0];
|
||||
const yj = polygon[j][1];
|
||||
|
||||
const intersect =
|
||||
yi > y !== yj > y &&
|
||||
x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
|
||||
|
||||
if (intersect) {
|
||||
inside = !inside;
|
||||
}
|
||||
|
||||
if ((x === xi && y === yi) || (x === xj && y === yj)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return inside;
|
||||
}
|
||||
|
||||
|
||||
function getVectorLength(vector) {
|
||||
return Math.sqrt(vector[0]**2+vector[1]**2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two Vectors together
|
||||
*/
|
||||
function addVec(vectors) {
|
||||
return vectors.reduce((acc, vec) => [acc[0] + vec[0], acc[1] + vec[1]], [0, 0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negative of the vector
|
||||
*/
|
||||
function negVec(vector) {
|
||||
return [-vector[0], -vector[1]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies Vector with a scalar
|
||||
*/
|
||||
function SxVEC(scalar, vector) {
|
||||
return [vector[0] * scalar, vector[1] * scalar];
|
||||
}
|
||||
|
||||
function rotateVector (vec, ang) {
|
||||
var cos = Math.cos(ang);
|
||||
var sin = Math.sin(ang);
|
||||
return [vec[0] * cos - vec[1] * sin, vec[0] * sin + vec[1] * cos];
|
||||
}
|
||||
|
||||
function rotateVectorsByAngle(vectors, angle) {
|
||||
const cosAngle = Math.cos(angle);
|
||||
const sinAngle = Math.sin(angle);
|
||||
|
||||
const rotationMatrix = [
|
||||
[cosAngle, -sinAngle],
|
||||
[sinAngle, cosAngle]
|
||||
];
|
||||
|
||||
return applyTranformationMatrix(vectors, rotationMatrix);
|
||||
}
|
||||
|
||||
function applyTranformationMatrix(vectors, transformationMatrix) {
|
||||
const result = [];
|
||||
for (const vector of vectors) {
|
||||
const x = vector[0];
|
||||
const y = vector[1];
|
||||
|
||||
const newX = transformationMatrix[0][0] * x + transformationMatrix[0][1] * y;
|
||||
const newY = transformationMatrix[1][0] * x + transformationMatrix[1][1] * y;
|
||||
|
||||
result.push([newX, newY]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
5
ea-scripts/Boolean Operations.svg
Normal file
|
After Width: | Height: | Size: 17 KiB |
@@ -130,10 +130,10 @@ for(const elements of groups) {
|
||||
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
ea.addToGroup([id].concat(elements.map((el)=>el.id)));
|
||||
ea.addElementsToView(false);
|
||||
ea.reset();
|
||||
}
|
||||
|
||||
await ea.addElementsToView(false,false);
|
||||
|
||||
function recalculateStartPointOfLine(line, el) {
|
||||
const aX = el.x + el.width/2;
|
||||
const bX = line.x + line.points[1][0];
|
||||
@@ -178,4 +178,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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
ea-scripts/Box Each Selected Groups.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 250 160" stroke="#000"><path fill="none" stroke-linecap="round" stroke-width="4" d="M10 30h70m-70 0h70M10 20h70m-70 0h70M60 55c0 .87-.08 1.75-.23 2.6-.15.86-.38 1.71-.67 2.53-.3.82-.68 1.62-1.11 2.37-.43.75-.94 1.48-1.5 2.14-.56.67-1.18 1.29-1.85 1.85-.66.56-1.39 1.07-2.14 1.5-.75.43-1.55.81-2.37 1.11-.82.29-1.67.52-2.53.67-.85.15-1.73.23-2.6.23-.87 0-1.75-.08-2.6-.23-.86-.15-1.71-.38-2.53-.67-.82-.3-1.62-.68-2.37-1.11-.75-.43-1.48-.94-2.14-1.5-.67-.56-1.29-1.18-1.85-1.85-.56-.66-1.07-1.39-1.5-2.14-.43-.75-.81-1.55-1.11-2.37-.29-.82-.52-1.67-.67-2.53-.15-.85-.23-1.73-.23-2.6 0-.87.08-1.75.23-2.6.15-.86.38-1.71.67-2.53.3-.82.68-1.62 1.11-2.37.43-.75.94-1.48 1.5-2.14.56-.67 1.18-1.29 1.85-1.85.66-.56 1.39-1.07 2.14-1.5.75-.43 1.55-.81 2.37-1.11.82-.29 1.67-.52 2.53-.67.85-.15 1.73-.23 2.6-.23.87 0 1.75.08 2.6.23.86.15 1.71.38 2.53.67.82.3 1.62.68 2.37 1.11.75.43 1.48.94 2.14 1.5.67.56 1.29 1.18 1.85 1.85.56.66 1.07 1.39 1.5 2.14.43.75.81 1.55 1.11 2.37.29.82.52 1.67.67 2.53.15.85.19 2.17.23 2.6.04.43.04-.43 0 0M26 110c4.05 4.62 8.09 9.25 14 16m-14-16 14 16m0 0-14 14m14-14-14 14m0 0-16-14m16 14c-3.54-3.1-7.09-6.2-16-14m0 0 16-16m-16 16 16-16M50 110h30m-30 0h30M50 140h30m-30 0h30M160 30h70m-70 0h70M160 20h70m-70 0h70M210 55c0 .87-.08 1.75-.23 2.6-.15.86-.38 1.71-.67 2.53-.3.82-.68 1.62-1.11 2.37-.43.75-.94 1.48-1.5 2.14-.56.67-1.18 1.29-1.85 1.85-.66.56-1.39 1.07-2.14 1.5-.75.43-1.55.81-2.37 1.11-.82.29-1.67.52-2.53.67-.85.15-1.73.23-2.6.23-.87 0-1.75-.08-2.6-.23-.86-.15-1.71-.38-2.53-.67-.82-.3-1.62-.68-2.37-1.11-.75-.43-1.48-.94-2.14-1.5-.67-.56-1.29-1.18-1.85-1.85-.56-.66-1.07-1.39-1.5-2.14-.43-.75-.81-1.55-1.11-2.37-.29-.82-.52-1.67-.67-2.53-.15-.85-.23-1.73-.23-2.6 0-.87.08-1.75.23-2.6.15-.86.38-1.71.67-2.53.3-.82.68-1.62 1.11-2.37.43-.75.94-1.48 1.5-2.14.56-.67 1.18-1.29 1.85-1.85.66-.56 1.39-1.07 2.14-1.5.75-.43 1.55-.81 2.37-1.11.82-.29 1.67-.52 2.53-.67.85-.15 1.73-.23 2.6-.23.87 0 1.75.08 2.6.23.86.15 1.71.38 2.53.67.82.3 1.62.68 2.37 1.11.75.43 1.48.94 2.14 1.5.67.56 1.29 1.18 1.85 1.85.56.66 1.07 1.39 1.5 2.14.43.75.81 1.55 1.11 2.37.29.82.52 1.67.67 2.53.15.85.19 2.17.23 2.6.04.43.04-.43 0 0M176 110c4.53 5.17 9.05 10.34 14 16m-14-16c5.5 6.28 10.99 12.56 14 16m0 0-14 14m14-14-14 14m0 0-16-14m16 14c-5.47-4.79-10.94-9.57-16-14m0 0 16-16m-16 16 16-16M200 110h30m-30 0h30M200 140h30m-30 0h30M150 10h90m-90 0h90m0 0v70m0-70v70m0 0h-90m90 0h-90m0 0V10m0 70V10M150 100h90m-90 0h90m0 0v50m0-50v50m0 0h-90m90 0h-90m0 0v-50m0 50v-50"/><g fill-rule="evenodd" stroke-linecap="round"><path stroke-width="0" d="m100 20 31.17 59.33-28.84 60L100 20"/><path fill="none" stroke-width="4" d="M100 20c11.09 21.12 22.19 42.24 31.17 59.33M100 20c9.23 17.58 18.47 35.16 31.17 59.33m0 0c-8.1 16.84-16.19 33.68-28.84 60m28.84-60c-10.41 21.65-20.81 43.3-28.84 60m0 0C101.45 94.2 100.57 49.07 100 20m2.33 119.33c-.57-29.27-1.15-58.55-2.33-119.33m0 0s0 0 0 0m0 0s0 0 0 0"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@@ -52,4 +52,4 @@ id = ea.addRect(
|
||||
);
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
ea.addToGroup([id].concat(elements.map((el)=>el.id)));
|
||||
ea.addElementsToView(false);
|
||||
ea.addElementsToView(false,false);
|
||||
1
ea-scripts/Box Selected Elements.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="100 80 500 400"><path d="M164.27 110.96h158.32v-28H136.27v170.87h28zM377.42 110.96h158.32v142.87h28V82.96H377.42zM535.73 449.04H377.41v28h186.32V306.17h-28zM164.27 306.16h-28v170.87h186.32v-28H164.27z"/><path d="M197.86 220.36v119.3c0 42.34 34.445 76.789 76.793 76.789h150.68c42.348 0 76.793-34.445 76.793-76.789l.004-119.3c0-42.34-34.445-76.789-76.793-76.789h-150.69c-42.348-.004-76.793 34.445-76.793 76.789zm276.27 0v119.3c0 26.902-21.887 48.789-48.793 48.789l-150.69-.004c-26.906 0-48.793-21.887-48.793-48.789v-119.29c0-26.902 21.887-48.789 48.793-48.789h150.68c26.91-.004 48.797 21.88 48.797 48.79z"/></svg>
|
||||
|
After Width: | Height: | Size: 660 B |
@@ -1,16 +1,52 @@
|
||||
/*
|
||||

|
||||
|
||||
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 shapesDispaly=["○ ellipse","□ rectangle","◇ diamond"];
|
||||
const shapes=["ellipse","rectangle","diamond"];
|
||||
elements = ea.getViewSelectedElements().filter(el=>shapes.contains(el.type));
|
||||
newShape = await utils.suggester(shapesDispaly, shapes);
|
||||
if(!newShape) return;
|
||||
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"];
|
||||
const lineShapes=["line","arrow"];
|
||||
|
||||
elements.forEach(el=>el.type = newShape);
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
ea.addElementsToView();
|
||||
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, 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, press ESC to skip");
|
||||
if(newShape) {
|
||||
editedElements = editedElements.concat(elements.filter(e=>!editedElements.some(el=>el.id===e.id)));
|
||||
elements.forEach((el)=>{
|
||||
el.type = newShape;
|
||||
if(newShape === "arrow") {
|
||||
el.endArrowhead = "triangle";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ea.copyViewElementsToEAforEditing(editedElements);
|
||||
|
||||
ea.addElementsToView(false,false);
|
||||
|
||||
1
ea-scripts/Change shape of selected elements.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="5 5 170 70" stroke="#000"><path fill="none" stroke-linecap="round" stroke-width="4" d="M10 10h60m-60 0h60m0 0v60m0-60v60m0 0H10m60 0H10m0 0V10m0 60V10M141 10c6.47 6.91 12.94 13.83 29 31m-29-31c9.29 9.93 18.57 19.86 29 31m0 0-29 29m29-29-29 29m0 0c-10.49-9.82-20.99-19.64-31-29m31 29c-7.35-6.88-14.71-13.76-31-29m0 0 31-31m-31 31 31-31"/><g stroke-linecap="round"><path fill="none" stroke-width="4" d="M80 40h20m-20 0h20"/><path fill-rule="evenodd" stroke-width="0" d="m100 40-9.06 4.23v-8.46L100 40"/><path fill="none" stroke-width="4" d="M100 40c-3.14 1.47-6.29 2.93-9.06 4.23M100 40c-3.13 1.46-6.27 2.92-9.06 4.23m0 0v-8.46m0 8.46v-8.46m0 0c3.38 1.58 6.76 3.16 9.06 4.23m-9.06-4.23c2.17 1.02 4.34 2.03 9.06 4.23m0 0s0 0 0 0m0 0s0 0 0 0"/></g></svg>
|
||||
|
After Width: | Height: | Size: 802 B |
158
ea-scripts/Concatenate lines.md
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
Connects two lines. Lines may be type of arrow or line. The resulting line will carry the style of the line higher in the drawing layers (bring to front the one you want to control the look and feel). Arrows are connected intelligently.
|
||||

|
||||
```js*/
|
||||
const lines = ea.getViewSelectedElements().filter(el=>el.type==="line" || el.type==="arrow");
|
||||
if(lines.length !== 2) {
|
||||
new Notice ("Select two lines or arrows");
|
||||
return;
|
||||
}
|
||||
|
||||
//Same line but with angle=0
|
||||
function getNormalizedLine(originalElement) {
|
||||
if(originalElement.angle === 0) return originalElement;
|
||||
|
||||
// Get absolute coordinates for all points first
|
||||
const pointRotateRads = (point, center, angle) => {
|
||||
const [x, y] = point;
|
||||
const [cx, cy] = center;
|
||||
return [
|
||||
(x - cx) * Math.cos(angle) - (y - cy) * Math.sin(angle) + cx,
|
||||
(x - cx) * Math.sin(angle) + (y - cy) * Math.cos(angle) + cy
|
||||
];
|
||||
};
|
||||
|
||||
// Get element absolute coordinates (matching Excalidraw's approach)
|
||||
const getElementAbsoluteCoords = (element) => {
|
||||
const points = element.points;
|
||||
let minX = Infinity;
|
||||
let minY = Infinity;
|
||||
let maxX = -Infinity;
|
||||
let maxY = -Infinity;
|
||||
|
||||
for (const [x, y] of points) {
|
||||
const absX = x + element.x;
|
||||
const absY = y + element.y;
|
||||
minX = Math.min(minX, absX);
|
||||
minY = Math.min(minY, absY);
|
||||
maxX = Math.max(maxX, absX);
|
||||
maxY = Math.max(maxY, absY);
|
||||
}
|
||||
|
||||
return [minX, minY, maxX, maxY];
|
||||
};
|
||||
|
||||
// Calculate center point based on absolute coordinates
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(originalElement);
|
||||
const centerX = (x1 + x2) / 2;
|
||||
const centerY = (y1 + y2) / 2;
|
||||
|
||||
// Calculate absolute coordinates of all points
|
||||
const absolutePoints = originalElement.points.map(([x, y]) => [
|
||||
x + originalElement.x,
|
||||
y + originalElement.y
|
||||
]);
|
||||
|
||||
// Rotate all points around the center
|
||||
const rotatedPoints = absolutePoints.map(point =>
|
||||
pointRotateRads(point, [centerX, centerY], originalElement.angle)
|
||||
);
|
||||
|
||||
// Convert back to relative coordinates
|
||||
const newPoints = rotatedPoints.map(([x, y]) => [
|
||||
x - rotatedPoints[0][0],
|
||||
y - rotatedPoints[0][1]
|
||||
]);
|
||||
|
||||
const newLineId = ea.addLine(newPoints);
|
||||
|
||||
// Set the position of the new line to the first rotated point
|
||||
const newLine = ea.getElement(newLineId);
|
||||
newLine.x = rotatedPoints[0][0];
|
||||
newLine.y = rotatedPoints[0][1];
|
||||
newLine.angle = 0;
|
||||
delete ea.elementsDict[newLine.id];
|
||||
return newLine;
|
||||
}
|
||||
|
||||
|
||||
const points = lines.map(getNormalizedLine).map(
|
||||
el=>el.points.map(p=>[p[0]+el.x, p[1]+el.y])
|
||||
);
|
||||
|
||||
const last = (p) => p[p.length-1];
|
||||
const first = (p) => p[0];
|
||||
const distance = (p1,p2) => Math.sqrt((p1[0]-p2[0])**2+(p1[1]-p2[1])**2);
|
||||
|
||||
const distances = [
|
||||
distance(first(points[0]),first(points[1])),
|
||||
distance(first(points[0]),last (points[1])),
|
||||
distance(last (points[0]),first(points[1])),
|
||||
distance(last (points[0]),last (points[1]))
|
||||
];
|
||||
|
||||
const connectDirection = distances.indexOf(Math.min(...distances));
|
||||
|
||||
let newPoints = [];
|
||||
switch(connectDirection) {
|
||||
case 0: //first-first
|
||||
newPoints = [...points[0].reverse(),...points[1].slice(1)];
|
||||
break;
|
||||
case 1: //first-last
|
||||
newPoints = [...points[0].reverse(),...points[1].reverse().slice(1)];
|
||||
break;
|
||||
case 2: //last-first
|
||||
newPoints = [...points[0],...points[1].slice(1)];
|
||||
break;
|
||||
case 3: //last-last
|
||||
newPoints = [...points[0],...points[1].reverse().slice(1)];
|
||||
break;
|
||||
}
|
||||
|
||||
["strokeColor", "backgrounColor", "fillStyle", "roundness", "roughness", "strokeWidth", "strokeStyle", "opacity"].forEach(prop=>{
|
||||
ea.style[prop] = lines[1][prop];
|
||||
})
|
||||
|
||||
ea.style.startArrowHead = null;
|
||||
ea.style.endArrowHead = null;
|
||||
|
||||
ea.copyViewElementsToEAforEditing(lines);
|
||||
ea.getElements().forEach(el=>{el.isDeleted = true});
|
||||
|
||||
const lineTypes = parseInt(lines.map(line => line.type === "line" ? '1' : '0').join(''),2);
|
||||
|
||||
switch (lineTypes) {
|
||||
case 0: //arrow - arrow
|
||||
ea.addArrow(
|
||||
newPoints,
|
||||
connectDirection === 0 //first-first
|
||||
? { startArrowHead: lines[0].endArrowhead, endArrowHead: lines[1].endArrowhead }
|
||||
: connectDirection === 1 //first-last
|
||||
? { startArrowHead: lines[0].endArrowhead, endArrowHead: lines[1].startArrowhead }
|
||||
: connectDirection === 2 //last-first
|
||||
? { startArrowHead: lines[0].startArrowhead, endArrowHead: lines[1].endArrowhead }
|
||||
//3: last-last
|
||||
: { startArrowHead: lines[0].startArrowhead, endArrowHead: lines[1].startArrowhead }
|
||||
);
|
||||
break;
|
||||
case 1: //arrow - line
|
||||
reverse = connectDirection === 0 || connectDirection === 1;
|
||||
ea.addArrow(newPoints,{
|
||||
startArrowHead: reverse ? lines[0].endArrowhead : lines[0].startArrowhead,
|
||||
endArrowHead: reverse ? lines[0].startArrowhead : lines[0].endArrowhead
|
||||
});
|
||||
break;
|
||||
case 2: //line - arrow
|
||||
reverse = connectDirection === 1 || connectDirection === 3;
|
||||
ea.addArrow(newPoints,{
|
||||
startArrowHead: reverse ? lines[1].endArrowhead : lines[1].startArrowhead,
|
||||
endArrowHead: reverse ? lines[1].startArrowhead : lines[1].endArrowhead
|
||||
});
|
||||
break;
|
||||
case 3: //line - line
|
||||
ea.addLine(newPoints);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
await ea.addElementsToView();
|
||||
17
ea-scripts/Concatenate lines.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72.75819749055177 80.03703336574608" width="72.75819749055177" height="80.03703336574608">
|
||||
<!-- svg-source:excalidraw -->
|
||||
|
||||
<defs>
|
||||
<style class="style-fonts">
|
||||
@font-face {
|
||||
font-family: "Virgil";
|
||||
src: url("https://excalidraw.com/Virgil.woff2");
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Cascadia";
|
||||
src: url("https://excalidraw.com/Cascadia.woff2");
|
||||
}
|
||||
</style>
|
||||
|
||||
</defs>
|
||||
<g stroke-linecap="round"><g transform="translate(4 4) rotate(0 12.71901889991409 17.183109917454658)"><path d="M0 0 C0 7.02, 0 14.05, 0 34.37 M0 34.37 C7.62 34.37, 15.24 34.37, 25.44 34.37" stroke="black" stroke-width="4.5" fill="none" stroke-dasharray="1.5 10"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(51.379765518092086 61.93633577499986) rotate(0 5.684341886080802e-14 7.050348795373111)"><path d="M0 0 C0 4.06, 0 8.11, 0 14.1" stroke="black" stroke-width="4.5" fill="none" stroke-dasharray="1.5 10"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(34.0013341989918 20.987787610339183) rotate(0 17.378431645779926 17.378431645779983)"><path d="M34.76 17.38 C34.76 18.38, 34.67 19.41, 34.49 20.4 C34.32 21.39, 34.05 22.38, 33.71 23.32 C33.36 24.27, 32.93 25.2, 32.43 26.07 C31.93 26.94, 31.34 27.78, 30.69 28.55 C30.04 29.32, 29.32 30.04, 28.55 30.69 C27.78 31.34, 26.94 31.93, 26.07 32.43 C25.2 32.93, 24.27 33.36, 23.32 33.71 C22.38 34.05, 21.39 34.32, 20.4 34.49 C19.41 34.67, 18.38 34.76, 17.38 34.76 C16.37 34.76, 15.35 34.67, 14.36 34.49 C13.37 34.32, 12.38 34.05, 11.43 33.71 C10.49 33.36, 9.56 32.93, 8.69 32.43 C7.82 31.93, 6.98 31.34, 6.21 30.69 C5.44 30.04, 4.71 29.32, 4.07 28.55 C3.42 27.78, 2.83 26.94, 2.33 26.07 C1.83 25.2, 1.39 24.27, 1.05 23.32 C0.7 22.38, 0.44 21.39, 0.26 20.4 C0.09 19.41, 0 18.38, 0 17.38 C0 16.37, 0.09 15.35, 0.26 14.36 C0.44 13.37, 0.7 12.38, 1.05 11.43 C1.39 10.49, 1.83 9.56, 2.33 8.69 C2.83 7.82, 3.42 6.98, 4.07 6.21 C4.71 5.44, 5.44 4.71, 6.21 4.07 C6.98 3.42, 7.82 2.83, 8.69 2.33 C9.56 1.83, 10.49 1.39, 11.43 1.05 C12.38 0.7, 13.37 0.44, 14.36 0.26 C15.35 0.09, 16.37 0, 17.38 0 C18.38 0, 19.41 0.09, 20.4 0.26 C21.39 0.44, 22.38 0.7, 23.32 1.05 C24.27 1.39, 25.2 1.83, 26.07 2.33 C26.94 2.83, 27.78 3.42, 28.55 4.07 C29.32 4.71, 30.04 5.44, 30.69 6.21 C31.34 6.98, 31.93 7.82, 32.43 8.69 C32.93 9.56, 33.36 10.49, 33.71 11.43 C34.05 12.38, 34.32 13.37, 34.49 14.36 C34.67 15.35, 34.71 16.88, 34.76 17.38 C34.8 17.88, 34.8 16.88, 34.76 17.38" stroke="black" stroke-width="4" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(41.72257566145686 38.36621939788711) rotate(0 9.65718949485347 0)"><path d="M0 0 C4.11 0, 8.22 0, 19.31 0 M0 0 C6.95 0, 13.9 0, 19.31 0" stroke="black" stroke-width="4" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(41.72257587602678 38.36622004108449) rotate(89.99999999999994 9.65718949485347 0)"><path d="M0 0 C5.31 0, 10.62 0, 19.31 0 M0 0 C4.56 0, 9.13 0, 19.31 0" stroke="black" stroke-width="4" fill="none"></path></g></g><mask></mask></svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
@@ -78,4 +78,4 @@ ea.connectObjects(
|
||||
numberOfPoints: linePoints
|
||||
}
|
||||
);
|
||||
ea.addElementsToView(false,true,true);
|
||||
ea.addElementsToView(false,false,true);
|
||||
1
ea-scripts/Connect elements.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="5 5 170 70" stroke="#000"><path fill="none" stroke-linecap="round" stroke-width="4" d="M10 10h60m-60 0h60m0 0v60m0-60v60m0 0H10m60 0H10m0 0V10m0 60V10"/><g stroke-linecap="round"><path fill="none" stroke-width="4" d="M70 40h40m-40 0h40"/><path fill-rule="evenodd" stroke-width="0" d="m110 40-13.59 6.34V33.66L110 40"/><path fill="none" stroke-width="4" d="M110 40c-4.72 2.2-9.43 4.4-13.59 6.34M110 40c-4.7 2.19-9.4 4.38-13.59 6.34m0 0V33.66m0 12.68V33.66m0 0c5.07 2.37 10.14 4.73 13.59 6.34m-13.59-6.34c3.25 1.52 6.51 3.04 13.59 6.34m0 0s0 0 0 0m0 0s0 0 0 0"/></g><path fill="none" stroke-linecap="round" stroke-width="4" d="M110 10h60m-60 0h60m0 0v60m0-60v60m0 0h-60m60 0h-60m0 0V10m0 60V10"/></svg>
|
||||
|
After Width: | Height: | Size: 753 B |
@@ -60,5 +60,5 @@ elements.forEach((el)=>{
|
||||
});
|
||||
|
||||
ea.deleteViewElements(elements);
|
||||
await ea.addElementsToView(false,true,true);
|
||||
await ea.addElementsToView(false,false,true);
|
||||
ea.selectElementsInView(ea.getElements());
|
||||
1
ea-scripts/Convert freedraw to line.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M480 256c-17.67 0-32 14.31-32 32c0 52.94-43.06 96-96 96H192L192 344c0-9.469-5.578-18.06-14.23-21.94C169.1 318.3 159 319.8 151.9 326.2l-80 72C66.89 402.7 64 409.2 64 416s2.891 13.28 7.938 17.84l80 72C156.4 509.9 162.2 512 168 512c3.312 0 6.615-.6875 9.756-2.062C186.4 506.1 192 497.5 192 488L192 448h160c88.22 0 160-71.78 160-160C512 270.3 497.7 256 480 256zM160 128h159.1L320 168c0 9.469 5.578 18.06 14.23 21.94C337.4 191.3 340.7 192 343.1 192c5.812 0 11.57-2.125 16.07-6.156l80-72C445.1 109.3 448 102.8 448 95.1s-2.891-13.28-7.938-17.84l-80-72c-7.047-6.312-17.19-7.875-25.83-4.094C325.6 5.938 319.1 14.53 319.1 24L320 64H160C71.78 64 0 135.8 0 224c0 17.69 14.33 32 32 32s32-14.31 32-32C64 171.1 107.1 128 160 128z"/></svg>
|
||||
|
After Width: | Height: | Size: 794 B |
@@ -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,24 +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;
|
||||
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);
|
||||
ea.addElementsToView();
|
||||
await ea.addElementsToView(false,true);
|
||||
const containers = ea.getViewElements().filter(el=>boxes.includes(el.id));
|
||||
ea.getExcalidrawAPI().updateContainerSize(containers);
|
||||
ea.selectElementsInView(containers);
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 170 90" stroke="#000"><path fill="none" stroke-linecap="round" stroke-width="4" d="M100 10h40m-40 0h40m0 0 20 20m-20-20 20 20m0 0v50m0-50v50m0 0h-60m60 0h-60m0 0V10m0 70V10M140 10v20m0-20v20m0 0h20m-20 0h20M110 40c11.87.13 23.73.26 31 .33M110 40c6.44.07 12.89.14 31 .33M110 50c10.03.11 20.05.22 31 .33M110 50l31 .33M110 60c9.93.11 19.86.21 31 .33M110 60c11.38.12 22.75.24 31 .33M10 20c8.88.1 17.77.19 31 .33M10 20c6.49.07 12.98.14 31 .33M10 40c11.73.13 23.47.25 31 .33M10 40c10.52.11 21.04.23 31 .33M10 60c11.67.13 23.34.25 31 .33M10 60c6.23.07 12.46.13 31 .33"/><g fill-rule="evenodd" stroke-linecap="round"><path stroke-width="0" d="m80 20 9.33 19.67L80 60V50H60V30h20V20"/><path fill="none" stroke-width="4" d="M80 20c2.84 5.99 5.68 11.98 9.33 19.67M80 20c2.52 5.31 5.04 10.63 9.33 19.67m0 0C87.01 44.73 84.69 49.79 80 60m9.33-20.33C87.4 43.88 85.47 48.09 80 60m0 0V50m0 10V50m0 0H60m20 0H60m0 0V30m0 20V30m0 0h20m-20 0h20m0 0V20m0 10V20m0 0s0 0 0 0m0 0s0 0 0 0"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 170.322 103.335" stroke="#000"><path fill="none" stroke-linecap="round" stroke-width="4" d="M10 30c11.75.1 23.5.19 41 .33M10 30c8.59.07 17.17.14 41 .33M10 50c15.52.13 31.04.25 41 .33M10 50c13.91.11 27.82.23 41 .33M10 70c15.43.13 30.87.25 41 .33M10 70c8.24.07 16.47.13 41 .33"/><g fill-rule="evenodd" stroke-linecap="round"><path stroke-width="0" d="m90 30 9.33 19.67L90 70V60H70V40h20V30"/><path fill="none" stroke-width="4" d="M90 30c2.84 5.99 5.68 11.98 9.33 19.67M90 30c2.52 5.31 5.04 10.63 9.33 19.67m0 0C97.01 54.73 94.69 59.79 90 70m9.33-20.33C97.4 53.88 95.47 58.09 90 70m0 0V60m0 10V60m0 0H70m20 0H70m0 0V40m0 20V40m0 0h20m-20 0h20m0 0V30m0 10V30m0 0s0 0 0 0m0 0s0 0 0 0"/></g><path fill="none" stroke-linecap="round" stroke-width="4" d="m123.787 39.591 13.742-24.59m-13.742 24.59 13.742-24.59m0 0c1.863-3.335 4.462-4.071 7.797-2.208M137.529 15c1.863-3.334 4.462-4.07 7.797-2.207m0 0 9.995 5.586m-9.995-5.586 9.995 5.586m0 0c3.335 1.863 4.07 4.462 2.207 7.797m-2.207-7.797c3.335 1.863 4.07 4.462 2.207 7.797m0 0-13.741 24.591m13.741-24.591-13.741 24.591m0 0c-1.864 3.335-4.463 4.07-7.798 2.207m7.798-2.207c-1.864 3.335-4.463 4.07-7.798 2.207m0 0-9.995-5.585m9.995 5.585-9.995-5.585m0 0c-3.335-1.864-4.07-4.463-2.207-7.798m2.207 7.798c-3.335-1.864-4.07-4.463-2.207-7.798M102.795 77.158l13.742-24.591m-13.742 24.59 13.742-24.59m0 0c1.863-3.335 4.462-4.07 7.797-2.207m-7.797 2.207c1.863-3.335 4.462-4.07 7.797-2.207m0 0 9.995 5.585m-9.995-5.585 9.995 5.585m0 0c3.335 1.864 4.07 4.463 2.207 7.797m-2.207-7.797c3.335 1.864 4.07 4.463 2.207 7.797m0 0-13.742 24.591m13.742-24.59-13.742 24.59m0 0c-1.863 3.335-4.462 4.07-7.797 2.207m7.797-2.207c-1.863 3.335-4.462 4.07-7.797 2.207m0 0-9.995-5.585m9.995 5.585-9.995-5.585m0 0c-3.335-1.864-4.07-4.463-2.207-7.797m2.207 7.797c-3.335-1.864-4.07-4.463-2.207-7.797"/><g stroke-linecap="round"><path fill="#fff" stroke-width="0" d="m119.734 61.096 11.366-20.34 7.865 4.396-11.366 20.34"/><path fill="none" stroke="transparent" stroke-width="4" d="m119.734 61.096 11.366-20.34m-11.366 20.34 11.366-20.34m0 0c1.64.918 3.29 1.84 7.865 4.396m-7.865-4.396 7.865 4.396m0 0-11.366 20.34m11.366-20.34-11.366 20.34m0 0-7.865-4.396m7.865 4.395-7.865-4.395"/></g><g stroke-linecap="round"><path stroke-width="0" d="m118.676 68.759 18.727-33.513 2.95 1.65-18.726 33.512"/><path fill="none" stroke-width="4" d="m118.676 68.759 18.727-33.513M118.676 68.76l18.727-33.513m0 0 2.95 1.65m-2.95-1.65 2.95 1.65m0 0-18.726 33.512m18.726-33.513c-6.907 12.361-13.82 24.73-18.726 33.513m0 0-2.951-1.65m2.95 1.65-2.95-1.65"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
1
ea-scripts/Copy Selected Element Styles to Global.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path d="M224 0H336C362.5 0 384 21.49 384 48V256H0V48C0 21.49 21.49 0 48 0H64L96 64L128 0H160L192 64L224 0zM384 288V320C384 355.3 355.3 384 320 384H256V448C256 483.3 227.3 512 192 512C156.7 512 128 483.3 128 448V384H64C28.65 384 0 355.3 0 320V288H384zM192 464C200.8 464 208 456.8 208 448C208 439.2 200.8 432 192 432C183.2 432 176 439.2 176 448C176 456.8 183.2 464 192 464z"/></svg>
|
||||
|
After Width: | Height: | Size: 443 B |
33
ea-scripts/Create DrawIO file.md
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Creates a new draw.io diagram file and opens the file in the [Diagram plugin](https://github.com/zapthedingbat/drawio-obsidian) in a new tab.
|
||||
```js*/
|
||||
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.9.7")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
const drawIO = app.plugins.plugins["drawio-obsidian"];
|
||||
if(!drawIO || !drawIO?._loaded) {
|
||||
new Notice("Can't find the draw.io diagram plugin");
|
||||
}
|
||||
|
||||
filename = await utils.inputPrompt("Diagram name?");
|
||||
if(!filename) return;
|
||||
filename = filename.toLowerCase().endsWith(".svg") ? filename : filename + ".svg";
|
||||
const filepath = await ea.getAttachmentFilepath(filename);
|
||||
if(!filepath) return;
|
||||
const leaf = app.workspace.getLeaf('tab')
|
||||
if(!leaf) return;
|
||||
|
||||
const file = await this.app.vault.create(filepath, `<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><!--${ea.generateElementId()}--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300px" height="300px" viewBox="-0.5 -0.5 1 1" content="<mxGraphModel><root><mxCell id="0"/><mxCell id="1" parent="0"/></root></mxGraphModel>"></svg>`);
|
||||
|
||||
await ea.addImage(0,0,file);
|
||||
await ea.addElementsToView(true,true);
|
||||
|
||||
leaf.setViewState({
|
||||
type: "diagram-edit",
|
||||
state: {
|
||||
file: filepath
|
||||
}
|
||||
});
|
||||
1
ea-scripts/Create DrawIO file.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="24 26 68 68" stroke="#000"><path fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="3.553" d="m58.069 43.384-17.008 29.01"/><path fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="3.501" d="m58.068 43.384 17.008 29.01"/><path fill="#000" d="M52.773 77.084a3.564 3.564 0 0 1-3.553 3.553H36.999a3.564 3.564 0 0 1-3.553-3.553v-9.379a3.564 3.564 0 0 1 3.553-3.553h12.222a3.564 3.564 0 0 1 3.553 3.553v9.379zM67.762 48.074a3.564 3.564 0 0 1-3.553 3.553H51.988a3.564 3.564 0 0 1-3.553-3.553v-9.379a3.564 3.564 0 0 1 3.553-3.553H64.21a3.564 3.564 0 0 1 3.553 3.553v9.379zM82.752 77.084a3.564 3.564 0 0 1-3.553 3.553H66.977a3.564 3.564 0 0 1-3.553-3.553v-9.379a3.564 3.564 0 0 1 3.553-3.553h12.222a3.564 3.564 0 0 1 3.553 3.553v9.379z"/></svg>
|
||||
|
After Width: | Height: | Size: 830 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 170 160" stroke="#000"><text y="47.436" font-family="Helvetica, Segoe UI Emoji" font-size="52.832" style="white-space:pre" transform="translate(68.667 52.333)">MD</text><path fill="none" stroke-linecap="round" stroke-width="8" d="M60 150c34.92.23 69.85.47 99.33.67M60 150c25.08.17 50.16.34 99.33.67m0 0c.31-36.8.62-73.6 1-120m-1 120 1-120m0 0c-4.15-4.45-8.3-8.9-18.66-20m18.66 20c-6.97-7.48-13.95-14.95-18.66-20m0 0c-18.65-.08-37.31-.15-82-.34m82 .34c-24.26-.1-48.51-.2-82-.34m0 0c.11 47.28.22 94.55.33 139.67m-.33-139.67c.1 44.54.21 89.07.33 139.67M30 10v40m0-40v40M10 30h40m-40 0h40"/><path fill="none" stroke-linecap="round" stroke-width="4" d="M140 10v20m0-20v20m0 0h20m-20 0h20"/></svg>
|
||||
|
After Width: | Height: | Size: 746 B |
75
ea-scripts/Crop Vintage Mask.md
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
Adds a rounded mask to the image by adding a full cover black mask and a rounded rectangle white mask. The script is also useful for adding just a black mask. In this case, run the script, then delete the white mask and add your custom white mask.
|
||||

|
||||
```js*/
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("2.0.18")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!ea.isExcalidrawMaskFile()) {
|
||||
new Notice("This script only works with Mask Files");
|
||||
return;
|
||||
}
|
||||
|
||||
const frames = ea.getViewElements().filter(el=>el.type==="frame")
|
||||
if(frames.length !== 1) {
|
||||
new Notice("Multiple frames found");
|
||||
return;
|
||||
}
|
||||
const frame = frames[0];
|
||||
ea.copyViewElementsToEAforEditing(ea.getViewElements().filter(el=>el.frameId === frame.id));
|
||||
const frameId = ea.generateElementId();
|
||||
ea.style.fillStyle = "solid";
|
||||
ea.style.roughness = 0;
|
||||
ea.style.strokeColor = "transparent";
|
||||
ea.style.strokeWidth = 0.1;
|
||||
ea.style.opacity = 50;
|
||||
|
||||
let blackEl = ea.getViewElements().find(el=>el.id === "allblack");
|
||||
let whiteEl = ea.getViewElements().find(el=>el.id === "whiteovr");
|
||||
|
||||
if(blackEl && whiteEl) {
|
||||
ea.copyViewElementsToEAforEditing([blackEl, whiteEl]);
|
||||
} else
|
||||
if (blackEl && !whiteEl) {
|
||||
ea.copyViewElementsToEAforEditing([blackEl]);
|
||||
ea.style.backgroundColor = "white";
|
||||
ea.addRect(frame.x,frame.y,frame.width,frame.height, "whiteovr");
|
||||
} else
|
||||
if (!blackEl && whiteEl) {
|
||||
ea.style.backgroundColor = "black";
|
||||
ea.addRect(frame.x-2,frame.y-2,frame.width+4,frame.height+4, "allblack");
|
||||
ea.copyViewElementsToEAforEditing([whiteEl]);
|
||||
} else {
|
||||
ea.style.backgroundColor = "black";
|
||||
ea.addRect(frame.x-2,frame.y-2,frame.width+4,frame.height+4, "allblack");
|
||||
ea.style.backgroundColor = "white";
|
||||
ea.addRect(frame.x,frame.y,frame.width,frame.height, "whiteovr");
|
||||
}
|
||||
blackEl = ea.getElement("allblack");
|
||||
whiteEl = ea.getElement("whiteovr");
|
||||
|
||||
//this "magic" is required to ensure the frame element is above in sequence of the new rectangle elements
|
||||
ea.getElements().forEach(el=>{el.frameId = frameId});
|
||||
ea.copyViewElementsToEAforEditing(ea.getViewElements().filter(el=>el.id === frame.id));
|
||||
const newFrame = ea.getElement(frame.id);
|
||||
newFrame.id = frameId;
|
||||
ea.elementsDict[frameId] = newFrame;
|
||||
ea.copyViewElementsToEAforEditing(ea.getViewElements().filter(el=>el.id === frame.id));
|
||||
ea.getElement(frame.id).isDeleted = true;
|
||||
|
||||
let curve = await utils.inputPrompt(
|
||||
"Set roundess",
|
||||
"Positive whole number",
|
||||
`${whiteEl.roundness?.value ?? "500"}`
|
||||
);
|
||||
|
||||
if(!curve) return;
|
||||
curve = parseInt(curve);
|
||||
if(isNaN(curve) || curve < 0) {
|
||||
new Notice ("Roudness is not a valid positive whole number");
|
||||
return;
|
||||
}
|
||||
whiteEl.roundness = {type: 3, value: curve};
|
||||
ea.addElementsToView(false,false,true);
|
||||
1
ea-scripts/Crop Vintage Mask.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-squircle"><path fill="none" d="M12 3c7.2 0 9 1.8 9 9s-1.8 9-9 9-9-1.8-9-9 1.8-9 9-9"/></svg>
|
||||
|
After Width: | Height: | Size: 294 B |
15
ea-scripts/Custom Zoom.md
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
You can set a custom zoom level with this script. This allows you to set a zoom level below 10% or set the zoom level to a specific value. Note however, that Excalidraw has a bug under 10% zoom, and a phantom copy of your image may appear on screen. If this happens, increase the zoom and the phantom should disappear, if it doesn't then close and open the drawing.
|
||||
|
||||
```js*/
|
||||
const api = ea.getExcalidrawAPI();
|
||||
const appState = api.getAppState();
|
||||
const zoomStr = await utils.inputPrompt("Zoom [%]",null,`${appState.zoom.value*100}%`);
|
||||
if(!zoomStr) return;
|
||||
const zoomNum = parseFloat(zoomStr.match(/^\d*/)[0]);
|
||||
if(isNaN(zoomNum)) {
|
||||
new Notice("You must provide a number");
|
||||
return;
|
||||
}
|
||||
|
||||
ea.getExcalidrawAPI().updateScene({appState:{zoom:{value: zoomNum/100 }}});
|
||||
1
ea-scripts/Custom Zoom.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-scan-search"><g stroke-width="2"><path d="M3 7V5a2 2 0 0 1 2-2h2"/><path d="M17 3h2a2 2 0 0 1 2 2v2"/><path d="M21 17v2a2 2 0 0 1-2 2h-2"/><path d="M7 21H5a2 2 0 0 1-2-2v-2"/><circle cx="12" cy="12" r="3"/><path d="m16 16-1.9-1.9"/></g></svg>
|
||||
|
After Width: | Height: | Size: 444 B |
@@ -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();
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
await ea.addElementsToView(false, false);
|
||||
|
||||
1
ea-scripts/Darken background color.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="120 30 500 500" stroke="#000"><path d="M365.4 56a224.009 224.009 0 0 0-158.39 65.609 223.994 223.994 0 0 0 0 316.78 224.001 224.001 0 0 0 158.39 65.609c59.41 0 116.39-23.602 158.39-65.609a223.99 223.99 0 0 0 65.605-158.39c0-39.32-10.348-77.949-30.008-112s-47.938-62.328-81.992-81.988a224 224 0 0 0-112-30.012zm92.398 243.6h-72.801v72.801l.004-.004a19.602 19.602 0 0 1-39.2 0v-72.8h-72.8v.003a19.6 19.6 0 0 1-16.974-9.8 19.59 19.59 0 0 1 0-19.603c3.5-6.062 9.97-9.8 16.973-9.8h72.801v-72.802.004a19.602 19.602 0 0 1 39.2 0V260.4h72.8v-.004a19.604 19.604 0 0 1 16.974 29.403 19.604 19.604 0 0 1-16.973 9.801z"/></svg>
|
||||
|
After Width: | Height: | Size: 664 B |
206
ea-scripts/Deconstruct selected elements into new drawing.md
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||

|
||||
|
||||
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.
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/HRtaaD34Zzg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/mvMQcz401yo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
```javascript
|
||||
*/
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("2.7.3")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
// -------------------------------
|
||||
// Utility variables and functions
|
||||
// -------------------------------
|
||||
const excalidrawTemplates = ea.getListOfTemplateFiles();
|
||||
if(typeof window.ExcalidrawDeconstructElements === "undefined") {
|
||||
window.ExcalidrawDeconstructElements = {
|
||||
openDeconstructedImage: true,
|
||||
templatePath: excalidrawTemplates?.[0].path??""
|
||||
};
|
||||
}
|
||||
|
||||
const splitFolderAndFilename = (filepath) => {
|
||||
const lastIndex = filepath.lastIndexOf("/");
|
||||
return {
|
||||
foldername: ea.obsidian.normalizePath(filepath.substring(0, lastIndex)),
|
||||
filename: (lastIndex == -1 ? filepath : filepath.substring(lastIndex + 1)) + ".md"
|
||||
};
|
||||
}
|
||||
|
||||
let settings = ea.getScriptSettings();
|
||||
//set default values on first run
|
||||
if(!settings["Templates"]) {
|
||||
settings = {
|
||||
"Templates" : {
|
||||
value: "",
|
||||
description: "Comma-separated list of template filepaths"
|
||||
}
|
||||
};
|
||||
await ea.setScriptSettings(settings);
|
||||
}
|
||||
|
||||
if(!settings["Default file name"]) {
|
||||
settings["Default file name"] = {
|
||||
value: "deconstructed",
|
||||
description: "The default filename to use when deconstructing elements."
|
||||
};
|
||||
await ea.setScriptSettings(settings);
|
||||
}
|
||||
|
||||
const DEFAULT_FILENAME = settings["Default file name"].value;
|
||||
|
||||
const templates = settings["Templates"]
|
||||
.value
|
||||
.split(",")
|
||||
.map(p=>app.metadataCache.getFirstLinkpathDest(p.trim(),""))
|
||||
.concat(excalidrawTemplates)
|
||||
.filter(f=>Boolean(f))
|
||||
.sort((a,b) => a.basename.localeCompare(b.basename));
|
||||
|
||||
|
||||
// ------------------------------------
|
||||
// Prepare elements to be deconstructed
|
||||
// ------------------------------------
|
||||
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);
|
||||
const hyperlink = img?.hyperlink;
|
||||
if(img && (path || hyperlink)) {
|
||||
const colorMap = ea.getColorMapForImageElement(el);
|
||||
ea.imagesDict[el.fileId] = {
|
||||
mimeType: img.mimeType,
|
||||
id: el.fileId,
|
||||
dataURL: img.img,
|
||||
created: img.mtime,
|
||||
file: path,
|
||||
hyperlink,
|
||||
hasSVGwithBitmap: img.isSVGwithBitmap,
|
||||
latex: null,
|
||||
colorMap,
|
||||
};
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// ------------
|
||||
// Input prompt
|
||||
// ------------
|
||||
let shouldAnchor = false;
|
||||
const actionButtons = [
|
||||
{
|
||||
caption: "Insert @100%",
|
||||
tooltip: "Anchor to 100% size",
|
||||
action: () => {
|
||||
shouldAnchor = true;
|
||||
}
|
||||
},
|
||||
{
|
||||
caption: "Insert",
|
||||
tooltip: "Insert without anchoring",
|
||||
action: () => {
|
||||
shouldAnchor = false;
|
||||
}
|
||||
}];
|
||||
|
||||
const customControls = (container) => {
|
||||
new ea.obsidian.Setting(container)
|
||||
.setName(`Select template`)
|
||||
.addDropdown(dropdown => {
|
||||
templates.forEach(file => dropdown.addOption(file.path, file.basename));
|
||||
if(templates.length === 0) dropdown.addOption(null, "none");
|
||||
dropdown
|
||||
.setValue(window.ExcalidrawDeconstructElements.templatePath)
|
||||
.onChange(value => {
|
||||
window.ExcalidrawDeconstructElements.templatePath = value;
|
||||
})
|
||||
})
|
||||
|
||||
new ea.obsidian.Setting(container)
|
||||
.setName(`Open deconstructed image`)
|
||||
.addToggle((toggle) => toggle
|
||||
.setValue(window.ExcalidrawDeconstructElements.openDeconstructedImage)
|
||||
.onChange(value => {
|
||||
window.ExcalidrawDeconstructElements.openDeconstructedImage = value;
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const path = await utils.inputPrompt(
|
||||
"Filename for new file",
|
||||
"Filename",
|
||||
await ea.getAttachmentFilepath(DEFAULT_FILENAME),
|
||||
actionButtons,
|
||||
2,
|
||||
false,
|
||||
customControls
|
||||
);
|
||||
|
||||
if(!path) return;
|
||||
|
||||
// ----------------------
|
||||
// Execute deconstruction
|
||||
// ----------------------
|
||||
const {foldername, filename} = splitFolderAndFilename(path);
|
||||
|
||||
const newPath = await ea.create ({
|
||||
filename,
|
||||
foldername,
|
||||
templatePath: window.ExcalidrawDeconstructElements.templatePath,
|
||||
onNewPane: true,
|
||||
silent: !window.ExcalidrawDeconstructElements.openDeconstructedImage
|
||||
});
|
||||
|
||||
let f = app.vault.getAbstractFileByPath(newPath);
|
||||
let counter = 0;
|
||||
while((!f || !ea.isExcalidrawFile(f)) && counter++<100) {
|
||||
await sleep(50);
|
||||
f = app.vault.getAbstractFileByPath(newPath);
|
||||
}
|
||||
|
||||
if(!f || !ea.isExcalidrawFile(f)) {
|
||||
new Notice("Something went wrong");
|
||||
return;
|
||||
}
|
||||
|
||||
let padding = parseFloat(app.metadataCache.getCache(f.path)?.frontmatter["excalidraw-export-padding"]);
|
||||
if(isNaN(padding)) {
|
||||
padding = ea.plugin.settings.exportPaddingSVG;
|
||||
}
|
||||
|
||||
ea.getElements().forEach(el=>el.isDeleted = true);
|
||||
await ea.addImage(bb.topX-padding,bb.topY-padding,f,false, shouldAnchor);
|
||||
await ea.addElementsToView(false, true, true);
|
||||
ea.getExcalidrawAPI().history.clear();
|
||||
if(!window.ExcalidrawDeconstructElements.openDeconstructedImage) {
|
||||
new Notice("Deconstruction ready");
|
||||
}
|
||||