mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-12-23 08:47:50 +00:00
Compare commits
1597 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bfe655ada | ||
|
|
506a97d495 | ||
|
|
0e334a2bfd | ||
|
|
ede7fcaed7 | ||
|
|
ea824b521f | ||
|
|
26f51f7a74 | ||
|
|
0bc10c4152 | ||
|
|
991add1a4a | ||
|
|
626c51ce4c | ||
|
|
c26dc8de85 | ||
|
|
ff76fb17d6 | ||
|
|
6528e36919 | ||
|
|
ba8f1deaaa | ||
|
|
a90cd25a87 | ||
|
|
8661aea1d0 | ||
|
|
5954e76ae3 | ||
|
|
5310b9dd98 | ||
|
|
bc61e150ec | ||
|
|
b2e286dfb5 | ||
|
|
3c5bba0ad4 | ||
|
|
0714d19e29 | ||
|
|
391d40ce42 | ||
|
|
2a0a5ab3ae | ||
|
|
a42700c04b | ||
|
|
91d11177ba | ||
|
|
f3762eb40a | ||
|
|
f5db6e8d31 | ||
|
|
9d5beb196b | ||
|
|
575b0e301e | ||
|
|
15100abdde | ||
|
|
06c2240caa | ||
|
|
c206933bf5 | ||
|
|
c63162959d | ||
|
|
9f8501c42a | ||
|
|
052149a509 | ||
|
|
1e761e8f00 | ||
|
|
a6adbaa926 | ||
|
|
7c00eba127 | ||
|
|
f13532964d | ||
|
|
bb5d3f476f | ||
|
|
70d3443656 | ||
|
|
358301cf6c | ||
|
|
e23530b96e | ||
|
|
00e1c07782 | ||
|
|
e1edf1e719 | ||
|
|
f2a10fec2f | ||
|
|
f6abe0c800 | ||
|
|
6b6a1bdad2 | ||
|
|
f011022097 | ||
|
|
a6c39d4306 | ||
|
|
4bcb4dad40 | ||
|
|
cba1d34064 | ||
|
|
8c07fbefe6 | ||
|
|
d561ec5f14 | ||
|
|
5feebb31d2 | ||
|
|
850852fc3b | ||
|
|
38f6b40ee7 | ||
|
|
2c198a3d6a | ||
|
|
cee5bfa4e6 | ||
|
|
29a10c144e | ||
|
|
d80199d744 | ||
|
|
baca369c29 | ||
|
|
bcd6af975e | ||
|
|
1ca1d82901 | ||
|
|
80ae0e5277 | ||
|
|
515747c0b7 | ||
|
|
8a28ff4afc | ||
|
|
6876a38c99 | ||
|
|
42e3a3eb73 | ||
|
|
9961cc9b69 | ||
|
|
9ab2ecdc4d | ||
|
|
a03d715fa7 | ||
|
|
8ce498751b | ||
|
|
b239224a63 | ||
|
|
c8e723fac7 | ||
|
|
d617b145e2 | ||
|
|
a4d256d75b | ||
|
|
326c54ec75 | ||
|
|
53488dad22 | ||
|
|
d2a747372f | ||
|
|
34bc516466 | ||
|
|
6b52aa70ba | ||
|
|
3b6de80a2f | ||
|
|
5ac358ef6a | ||
|
|
51f9cdec81 | ||
|
|
45100d6d16 | ||
|
|
22089e5e27 | ||
|
|
3bc77f06bf | ||
|
|
8be6a12256 | ||
|
|
ab20cfc988 | ||
|
|
916a5cea7d | ||
|
|
3324b12620 | ||
|
|
f74c104b9c | ||
|
|
4c8d34cdb2 | ||
|
|
6799951ee3 | ||
|
|
4ebdd906c2 | ||
|
|
a1be6a6824 | ||
|
|
ef08eaa93b | ||
|
|
c7b10d1b6c | ||
|
|
6e386e2838 | ||
|
|
8d4052e612 | ||
|
|
985c0c16b8 | ||
|
|
ce447185d1 | ||
|
|
1c9db1ce69 | ||
|
|
731cd23ec8 | ||
|
|
4324f8fd70 | ||
|
|
25d5bfa222 | ||
|
|
955af95c20 | ||
|
|
b938914ecf | ||
|
|
66351570a6 | ||
|
|
6573ed917b | ||
|
|
2fc5d919e9 | ||
|
|
856a1e4485 | ||
|
|
2cbf081408 | ||
|
|
fee9b27e00 | ||
|
|
468e993649 | ||
|
|
6f4b5f773d | ||
|
|
3699450369 | ||
|
|
9a8476ecfb | ||
|
|
40cbe07ea5 | ||
|
|
e584beb926 | ||
|
|
b7845cb785 | ||
|
|
cfe6d95261 | ||
|
|
d85717f81e | ||
|
|
5ee01b59a9 | ||
|
|
846e6ffbbf | ||
|
|
532f25abe9 | ||
|
|
4ce0a59862 | ||
|
|
b78b5fa48c | ||
|
|
dc233fe436 | ||
|
|
4bec3e4ac1 | ||
|
|
f964d9d91a | ||
|
|
05280aec4d | ||
|
|
d227ad2a53 | ||
|
|
310c911996 | ||
|
|
3a51577b28 | ||
|
|
c73e7f5863 | ||
|
|
98062430b4 | ||
|
|
bf081ec347 | ||
|
|
2c552ce985 | ||
|
|
a561059a4e | ||
|
|
5613bd29be | ||
|
|
f7f2760520 | ||
|
|
ce5ab81760 | ||
|
|
79f68dc94d | ||
|
|
b102b42d2c | ||
|
|
8431f386ce | ||
|
|
7a9e1cfb3c | ||
|
|
14c7a92944 | ||
|
|
a732861f67 | ||
|
|
039d911d1e | ||
|
|
7406cc273e | ||
|
|
8367f3a606 | ||
|
|
12c1a0abf8 | ||
|
|
f511aa005a | ||
|
|
5838c7d300 | ||
|
|
c3fa0c5cb2 | ||
|
|
bd688f354e | ||
|
|
a0d0b17206 | ||
|
|
7455d11629 | ||
|
|
58b43c006c | ||
|
|
39e23e18b3 | ||
|
|
920a318df4 | ||
|
|
46e7eca2b4 | ||
|
|
8898a2a45f | ||
|
|
858831993d | ||
|
|
65ee92b1ac | ||
|
|
bc09736cc6 | ||
|
|
4c242c54e8 | ||
|
|
27893b5302 | ||
|
|
451a10869a | ||
|
|
ce43c4bbd9 | ||
|
|
c08b63bd3d | ||
|
|
615f834822 | ||
|
|
d7fa34f2fe | ||
|
|
a2f8928066 | ||
|
|
fb1c8b3b35 | ||
|
|
f33f612f43 | ||
|
|
2667fdb91b | ||
|
|
5c686f4641 | ||
|
|
24f4900025 | ||
|
|
959174e236 | ||
|
|
700745e46e | ||
|
|
1eb1828d92 | ||
|
|
6406870391 | ||
|
|
55228c76a6 | ||
|
|
e8e6df319a | ||
|
|
ab774377f7 | ||
|
|
2ecdbd42a5 | ||
|
|
9e96aefa0e | ||
|
|
bf30b5458a | ||
|
|
e8a72a5fe3 | ||
|
|
cf0fb1c00d | ||
|
|
f118d81464 | ||
|
|
cf82fc78c2 | ||
|
|
3aa9c9def0 | ||
|
|
9f7c21bb0c | ||
|
|
7e925890fa | ||
|
|
3a4fa98b42 | ||
|
|
f9c348c7d7 | ||
|
|
cf20c66b26 | ||
|
|
3821861134 | ||
|
|
641b28fc45 | ||
|
|
75fc5f3bca | ||
|
|
5d2f32945c | ||
|
|
e9ae352dfd | ||
|
|
315168da1f | ||
|
|
d59a15df1a | ||
|
|
0025a71951 | ||
|
|
42b7a1205b | ||
|
|
9181619e95 | ||
|
|
ca22cf9e05 | ||
|
|
2dc138f4d3 | ||
|
|
2955d67751 | ||
|
|
c58a6d2a5e | ||
|
|
3c40385cd2 | ||
|
|
489689063d | ||
|
|
b12bd4b694 | ||
|
|
debab53887 | ||
|
|
3b732c9750 | ||
|
|
357210c678 | ||
|
|
e6c1894ce4 | ||
|
|
1359e9975b | ||
|
|
35e8f447b0 | ||
|
|
97b5325f68 | ||
|
|
d571f1680f | ||
|
|
d409b30f03 | ||
|
|
b4a53274c2 | ||
|
|
4c676c1a8d | ||
|
|
c5e4136add | ||
|
|
9bb784e6f0 | ||
|
|
0849d6c641 | ||
|
|
1258c0f2ca | ||
|
|
f7e04d1d2c | ||
|
|
6821eea6a8 | ||
|
|
1210b54515 | ||
|
|
0f748d24ba | ||
|
|
355fac08bd | ||
|
|
4426b31ed7 | ||
|
|
9787432029 | ||
|
|
f897f5ac47 | ||
|
|
5d27a8668e | ||
|
|
f74ef0ef67 | ||
|
|
f5a7a30164 | ||
|
|
2b7482b263 | ||
|
|
32bd813be6 | ||
|
|
25418e9d2f | ||
|
|
c767c37cc1 | ||
|
|
1478280a07 | ||
|
|
38a1d48a6f | ||
|
|
cec7019b1a | ||
|
|
dc4e43c5d8 | ||
|
|
4cd8c634d5 | ||
|
|
9ca77d5382 | ||
|
|
eedcbc477c | ||
|
|
5c6c118b9c | ||
|
|
80c4bd9848 | ||
|
|
b13b020933 | ||
|
|
c46b6e1166 | ||
|
|
a0d5d7bee7 | ||
|
|
d0a478929e | ||
|
|
db7e031bbe | ||
|
|
c03898cd3d | ||
|
|
0191e55978 | ||
|
|
592c9d53ea | ||
|
|
f4bab00168 | ||
|
|
878d8aaf08 | ||
|
|
d76cd90ef5 | ||
|
|
b0c9b2ef86 | ||
|
|
9f458f8630 | ||
|
|
4bfb5c22da | ||
|
|
96510385a1 | ||
|
|
ba7fcb588f | ||
|
|
756075a161 | ||
|
|
b58334cd0e | ||
|
|
483de6f00d | ||
|
|
4658fe7218 | ||
|
|
59c6e1c48e | ||
|
|
7ee2e53189 | ||
|
|
8e86a401ff | ||
|
|
bc15eb55ce | ||
|
|
ee528810fb | ||
|
|
79fee262d7 | ||
|
|
9a11729eda | ||
|
|
a24c516148 | ||
|
|
9d9d360db9 | ||
|
|
c0d5f0c800 | ||
|
|
8fb118f3ff | ||
|
|
9a44074629 | ||
|
|
aa7e71fef3 | ||
|
|
25a446cd99 | ||
|
|
5a2509327d | ||
|
|
5343fb5fc2 | ||
|
|
ed3704b0a3 | ||
|
|
c85247a85c | ||
|
|
7a30cbdc73 | ||
|
|
3d24320674 | ||
|
|
ae99016cd9 | ||
|
|
51db97ffcc | ||
|
|
646dd81a35 | ||
|
|
08a104cd9c | ||
|
|
cecb424b1e | ||
|
|
39368da55f | ||
|
|
b46b341d90 | ||
|
|
ac0f8fbef7 | ||
|
|
7de64aefe5 | ||
|
|
7499dcb8c4 | ||
|
|
223a337736 | ||
|
|
dd03bf22c8 | ||
|
|
a33ab6a79b | ||
|
|
953f997281 | ||
|
|
28d416b852 | ||
|
|
5bf177637a | ||
|
|
7e54270bda | ||
|
|
864f8aed2a | ||
|
|
8b0cef92b9 | ||
|
|
58b5df97e1 | ||
|
|
38974a3b5e | ||
|
|
d6d3766b6f | ||
|
|
890ecd93a5 | ||
|
|
4ded5a624a | ||
|
|
29893aa15f | ||
|
|
90efb38c7e | ||
|
|
8f0d9c25d7 | ||
|
|
e4ed9defb1 | ||
|
|
d85bd7428a | ||
|
|
6b7ca47f23 | ||
|
|
3ba3211d1a | ||
|
|
33a9ea6088 | ||
|
|
f35d1056ff | ||
|
|
170dd7b948 | ||
|
|
3103f3933c | ||
|
|
c66d2996dd | ||
|
|
647cda29a0 | ||
|
|
1108b39e3f | ||
|
|
6118b346d6 | ||
|
|
11cfb08be5 | ||
|
|
4871cd3917 | ||
|
|
c869cde2c5 | ||
|
|
0552d4bb4f | ||
|
|
48976dd1dd | ||
|
|
f4a6d2b271 | ||
|
|
9a91e77ee9 | ||
|
|
7df144ccff | ||
|
|
f33ea4913c | ||
|
|
f503298f48 | ||
|
|
042fc2a477 | ||
|
|
2b3eb252f0 | ||
|
|
3520c90244 | ||
|
|
84569fb98c | ||
|
|
5ee874d6b3 | ||
|
|
bef0f839e2 | ||
|
|
670f2713a5 | ||
|
|
e26d817b79 | ||
|
|
258cf85601 | ||
|
|
d3134926e5 | ||
|
|
923155a2e2 | ||
|
|
dddae6f549 | ||
|
|
8f4f07673f | ||
|
|
94416c4b5d | ||
|
|
a3758038ee | ||
|
|
c4090158b1 | ||
|
|
d5aad257e7 | ||
|
|
8dff9b953e | ||
|
|
2345607df7 | ||
|
|
fc5757a5bc | ||
|
|
b56ba42984 | ||
|
|
84c211c7eb | ||
|
|
9d1007a4f3 | ||
|
|
212c575415 | ||
|
|
14f0a20ed6 | ||
|
|
4d13734fed | ||
|
|
92c5e40abd | ||
|
|
979e0b2a55 | ||
|
|
2709aaf429 | ||
|
|
39d13c83f6 | ||
|
|
031b56205b | ||
|
|
3d6c712565 | ||
|
|
9c98876dfb | ||
|
|
58ec6ab1e1 | ||
|
|
1cd566aedc | ||
|
|
a7a22c0d70 | ||
|
|
4265bc25bc | ||
|
|
23f10a2648 | ||
|
|
6cf7739fb6 | ||
|
|
fcb060280d | ||
|
|
5c6d9a5dee | ||
|
|
054d3aecc0 | ||
|
|
01afa463f4 | ||
|
|
d6bce89e68 | ||
|
|
ac506dcc31 | ||
|
|
72e33e461d | ||
|
|
769fc93df9 | ||
|
|
35b718452e | ||
|
|
d3bcef5fd9 | ||
|
|
e3f41f81ef | ||
|
|
7f5bb5dc45 | ||
|
|
04c013f3a4 | ||
|
|
ec5be5d2b0 | ||
|
|
bceb93b944 | ||
|
|
d7424abed8 | ||
|
|
59fda809d5 | ||
|
|
195b717eda | ||
|
|
d0c5b28d26 | ||
|
|
677983075d | ||
|
|
03a30f241e | ||
|
|
64044ea514 | ||
|
|
b97335c0ef | ||
|
|
71116758ef | ||
|
|
4844419bd8 | ||
|
|
daf0c5381b | ||
|
|
e6c0a9b10d | ||
|
|
53ceba2801 | ||
|
|
7b74506dcc | ||
|
|
d49695b884 | ||
|
|
96e0f0dfe6 | ||
|
|
9376b89b08 | ||
|
|
90f9949f8c | ||
|
|
e443c3172b | ||
|
|
c33542739c | ||
|
|
8c4bfe21c7 | ||
|
|
c234e86070 | ||
|
|
41f8881e8e | ||
|
|
ee1c0ace46 | ||
|
|
e4a4fc568f | ||
|
|
c102ace9ab | ||
|
|
d4fffe3543 | ||
|
|
9790153381 | ||
|
|
10ec787cc9 | ||
|
|
5b42231a77 | ||
|
|
9d38c8fd38 | ||
|
|
6ea14bb180 | ||
|
|
553b53e173 | ||
|
|
6f945c0c80 | ||
|
|
97bcc486fd | ||
|
|
87651913af | ||
|
|
af78414788 | ||
|
|
d86205d181 | ||
|
|
10c8fa8852 | ||
|
|
ff920b1a96 | ||
|
|
92e9f797de | ||
|
|
27c31c7238 | ||
|
|
67c4e6e24c | ||
|
|
e33688336d | ||
|
|
f555fc3840 | ||
|
|
92bb24b4ac | ||
|
|
3ae8b01325 | ||
|
|
d4f00b86b0 | ||
|
|
fadf85e68a | ||
|
|
1039e6f4fe | ||
|
|
8d9a8f8bed | ||
|
|
766a41f4d5 | ||
|
|
fd7fa57925 | ||
|
|
57ce935f54 | ||
|
|
88eeef978d | ||
|
|
13fb22f4fa | ||
|
|
9b9a674118 | ||
|
|
5ebc7224e4 | ||
|
|
c8c891fbc3 | ||
|
|
4bb16b5b93 | ||
|
|
4e8959851a | ||
|
|
157703ef67 | ||
|
|
b4e5f4ff62 | ||
|
|
c67b2020e5 | ||
|
|
6a5bea8bcf | ||
|
|
42fd5d3bc9 | ||
|
|
c65b69be26 | ||
|
|
7fb81604be | ||
|
|
8a8cac096e | ||
|
|
b5a629435a | ||
|
|
1b5d4ac786 | ||
|
|
47410c89e8 | ||
|
|
1e9fea0337 | ||
|
|
b2e9d7bbcd | ||
|
|
520a26f088 | ||
|
|
ffb8ebd52f | ||
|
|
478842c6bc | ||
|
|
3d83885778 | ||
|
|
36bc5226ba | ||
|
|
bc5960ec39 | ||
|
|
75aa73ba69 | ||
|
|
c96ea6d77f | ||
|
|
99900b2c76 | ||
|
|
4cbe35a286 | ||
|
|
dc9013e253 | ||
|
|
1f22001cd3 | ||
|
|
bcb6cf559a | ||
|
|
7a78d039c2 | ||
|
|
e81a071a00 | ||
|
|
be79119b61 | ||
|
|
648523967c | ||
|
|
7399fccd5a | ||
|
|
8424df13f9 | ||
|
|
774227d328 | ||
|
|
a68399c92e | ||
|
|
a0140a6263 | ||
|
|
4bf6cdb9ed | ||
|
|
db1ff20a6d | ||
|
|
b4312eea83 | ||
|
|
57d6c8a830 | ||
|
|
e1ddb0e585 | ||
|
|
d9442409bd | ||
|
|
288243c2f5 | ||
|
|
732b1488f6 | ||
|
|
a572e3c5c0 | ||
|
|
ce90489017 | ||
|
|
5a038c99ec | ||
|
|
d4ca9870d4 | ||
|
|
3e3196baba | ||
|
|
da5abdfa42 | ||
|
|
ab24e90679 | ||
|
|
795c51c3a5 | ||
|
|
06971443d0 | ||
|
|
512f93176f | ||
|
|
e8507fea96 | ||
|
|
be9c0478f6 | ||
|
|
62815ae028 | ||
|
|
7b35973741 | ||
|
|
1b141868eb | ||
|
|
20746e3acd | ||
|
|
a21c68ba91 | ||
|
|
ab944669f3 | ||
|
|
17417e4259 | ||
|
|
be1bf802c0 | ||
|
|
2639dbd49e | ||
|
|
d35afa679a | ||
|
|
2ec7a26420 | ||
|
|
987758869f | ||
|
|
1ad14833dd | ||
|
|
689fa914b8 | ||
|
|
65fdf33263 | ||
|
|
368aaa087c | ||
|
|
40e5bcfb68 | ||
|
|
f2355ac3b7 | ||
|
|
03cd35e9a0 | ||
|
|
621f8f2de0 | ||
|
|
156896c4b3 | ||
|
|
10962ae0a0 | ||
|
|
334cb2ba1c | ||
|
|
d76494380b | ||
|
|
4e9460758f | ||
|
|
3ef71747c9 | ||
|
|
f13b632ad2 | ||
|
|
78b80d41e4 | ||
|
|
9acf9fbfa7 | ||
|
|
7f0131c333 | ||
|
|
2c235a4259 | ||
|
|
7c78171987 | ||
|
|
5babd2b8f8 | ||
|
|
afc5d31377 | ||
|
|
51530034f7 | ||
|
|
5102017777 | ||
|
|
0c89cd82c7 | ||
|
|
0cb12786b3 | ||
|
|
1fe422f963 | ||
|
|
96cdab38f6 | ||
|
|
ebfc93c104 | ||
|
|
a191b7c852 | ||
|
|
7faef58186 | ||
|
|
4c06ffeaa9 | ||
|
|
8da796c8bc | ||
|
|
8fcd045f37 | ||
|
|
ddd503f180 | ||
|
|
4145139534 | ||
|
|
bbed728b82 | ||
|
|
208ce3dbad | ||
|
|
1c313e4d7f | ||
|
|
78b2d57a81 | ||
|
|
21c6492254 | ||
|
|
791a7f8314 | ||
|
|
15f2329bc1 | ||
|
|
9b3ff2c319 | ||
|
|
7abf925a10 | ||
|
|
0e9d8933af | ||
|
|
dc3482594b | ||
|
|
99bc4ac03d | ||
|
|
3590774383 | ||
|
|
d003db776c | ||
|
|
a5e210813a | ||
|
|
1589cdd5df | ||
|
|
7c0d9130eb | ||
|
|
e9eb6e6c95 | ||
|
|
c5c33e3c77 | ||
|
|
548f64aec9 | ||
|
|
c877c2bb9d | ||
|
|
489d2b9595 | ||
|
|
09b79330b8 | ||
|
|
3858fbb440 | ||
|
|
5fefec6e5e | ||
|
|
fee3da7195 | ||
|
|
4af0784f6d | ||
|
|
af64fc13d9 | ||
|
|
213951aff6 | ||
|
|
2a67f1a153 | ||
|
|
3db931a1bb | ||
|
|
91ba33b274 | ||
|
|
265a6f09c4 | ||
|
|
8004ae646e | ||
|
|
6130a0062c | ||
|
|
5278a9ef45 | ||
|
|
9ad8722ac8 | ||
|
|
876e402b26 | ||
|
|
5c56ade2c4 | ||
|
|
98bdd3c788 | ||
|
|
400dc7b722 | ||
|
|
b4a0957f6e | ||
|
|
4f57e0f0b1 | ||
|
|
4ce4e79d4c | ||
|
|
22ce78dd1e | ||
|
|
d21ebc38dc | ||
|
|
0260bfb527 | ||
|
|
f3329b8dc4 | ||
|
|
cdd9282c37 | ||
|
|
98c36483fc | ||
|
|
82ed2a1aa5 | ||
|
|
d470cb061f | ||
|
|
5285da4ae0 | ||
|
|
6d2de24a05 | ||
|
|
5a05d12fdd | ||
|
|
9904189910 | ||
|
|
cb51d67e7d | ||
|
|
497c82588d | ||
|
|
803cc1ffaf | ||
|
|
5b72f760bb | ||
|
|
63e368c2bb | ||
|
|
d3e7027d67 | ||
|
|
0c64bea89e | ||
|
|
26fd50febf | ||
|
|
5920b1b671 | ||
|
|
f5fb352a2a | ||
|
|
55f8392692 | ||
|
|
7b8e275089 | ||
|
|
deb1425e74 | ||
|
|
f4f3e24cb1 | ||
|
|
33df227b17 | ||
|
|
b24a7fd497 | ||
|
|
cddb193b18 | ||
|
|
0badfac6de | ||
|
|
d05a0d1104 | ||
|
|
47fff57cbb | ||
|
|
ca11890426 | ||
|
|
c38a1a52ad | ||
|
|
25624baad3 | ||
|
|
3799db6dd4 | ||
|
|
2c335b25d1 | ||
|
|
70d4d82cdb | ||
|
|
4b5a99adcf | ||
|
|
9864d438c9 | ||
|
|
6b31d4418d | ||
|
|
a4ac6780fe | ||
|
|
d0188a768e | ||
|
|
5b2b34ee9e | ||
|
|
a82d96bc2c | ||
|
|
a778c8c10c | ||
|
|
39bc123866 | ||
|
|
1178d4fbe9 | ||
|
|
3bc5f19cf5 | ||
|
|
30a08e79ab | ||
|
|
d1196bffd6 | ||
|
|
7b8739487e | ||
|
|
5069a89d5d | ||
|
|
4ce405a89b | ||
|
|
0eb6837fd6 | ||
|
|
85cb9096d2 | ||
|
|
8aef1974db | ||
|
|
8d05e5081c | ||
|
|
88912bc12e | ||
|
|
d534325c83 | ||
|
|
36d07464c1 | ||
|
|
74c68f5485 | ||
|
|
4eb747f883 | ||
|
|
902b9c6d8c | ||
|
|
2b56e71435 | ||
|
|
8d588c1057 | ||
|
|
0451a1089d | ||
|
|
eac275c28d | ||
|
|
af47f578e4 | ||
|
|
3227b2f6f7 | ||
|
|
7647d807ec | ||
|
|
0f588c99d7 | ||
|
|
1979469f28 | ||
|
|
f1f88cb548 | ||
|
|
ecd6cf97e9 | ||
|
|
0b4014be80 | ||
|
|
b541daf50e | ||
|
|
ebd811db13 | ||
|
|
ea331a5aa6 | ||
|
|
1b80d8c31d | ||
|
|
86d3b912d4 | ||
|
|
5ee0e4e21d | ||
|
|
4bebc00df2 | ||
|
|
0a91f0d2b4 | ||
|
|
ac25cc1365 | ||
|
|
8ca6c8118c | ||
|
|
04f688e122 | ||
|
|
6d1e40d3a9 | ||
|
|
89c178295a | ||
|
|
a325c6f6c8 | ||
|
|
d5ecf052d4 | ||
|
|
e4bf2e9e46 | ||
|
|
02a14c9cc9 | ||
|
|
40c176ccf6 | ||
|
|
3577ed3b2f | ||
|
|
1f01ec1f6c | ||
|
|
8481b77e3c | ||
|
|
884a4b50e7 | ||
|
|
56714675b7 | ||
|
|
a25d208124 | ||
|
|
a5cf15a701 | ||
|
|
1779209337 | ||
|
|
6180e343e0 | ||
|
|
a9437b2772 | ||
|
|
68f451715a | ||
|
|
c5630aa7bd | ||
|
|
270734612d | ||
|
|
5659b0bc6c | ||
|
|
448ce484d8 | ||
|
|
31b22d9333 | ||
|
|
faf807edb2 | ||
|
|
0aafee1d13 | ||
|
|
7d6311e8fb | ||
|
|
dcef04c867 | ||
|
|
25bb1b2fbc | ||
|
|
17192ca9ae | ||
|
|
92f1d7fa18 | ||
|
|
2168b22b16 | ||
|
|
3dd76f7a3d | ||
|
|
8ceb78f699 | ||
|
|
a33f12ea7b | ||
|
|
4ab9680078 | ||
|
|
e3581e452d | ||
|
|
9cf5f294e9 | ||
|
|
0149663a6f | ||
|
|
18d37433b3 | ||
|
|
6813a1081e | ||
|
|
8e918cb132 | ||
|
|
0e2874a6c9 | ||
|
|
c0d8f0db1c | ||
|
|
6fa10f63fc | ||
|
|
da16d14d2d | ||
|
|
f43a8e116c | ||
|
|
ec121070d8 | ||
|
|
5a23d41cb7 | ||
|
|
30f242d393 | ||
|
|
c0e0e330c3 | ||
|
|
c2e8f6e5f6 | ||
|
|
50ae35a623 | ||
|
|
bdfc1ed648 | ||
|
|
59390aced5 | ||
|
|
c2aa453af4 | ||
|
|
fb717ef4d5 | ||
|
|
db62791908 | ||
|
|
ce1d4f4f43 | ||
|
|
fcb9fec712 | ||
|
|
34fe823ab7 | ||
|
|
d831d1183e | ||
|
|
c9cd572bea | ||
|
|
470386dabb | ||
|
|
354022d2be | ||
|
|
6aa9138131 | ||
|
|
fe34e2c6de | ||
|
|
903a2fe41b | ||
|
|
02591124a3 | ||
|
|
13e7325b7b | ||
|
|
691a28ef55 | ||
|
|
d4d8345166 | ||
|
|
a6a6d88143 | ||
|
|
bc2e07bb0c | ||
|
|
42bfb8de1c | ||
|
|
f6dd6f782c | ||
|
|
9fb7b3f289 | ||
|
|
03ac73bd52 | ||
|
|
4a44a69196 | ||
|
|
a00e5f12e5 | ||
|
|
b7feb5dcca | ||
|
|
bb66b4b97a | ||
|
|
fd33024915 | ||
|
|
957e017966 | ||
|
|
975e4a27bf | ||
|
|
671783a964 | ||
|
|
626efa0d78 | ||
|
|
d4ba43c773 | ||
|
|
d7dd2f30cf | ||
|
|
d32f6261f1 | ||
|
|
2464c5b66c | ||
|
|
c8b6c123c4 | ||
|
|
0ba8be333f | ||
|
|
cd64e4019d | ||
|
|
d526469d1f | ||
|
|
b686b11018 | ||
|
|
3d805e0511 | ||
|
|
98c61d0023 | ||
|
|
81d3ea64c2 | ||
|
|
c5981b81db | ||
|
|
978e4d6f4e | ||
|
|
ef4714c195 | ||
|
|
451dc9dbdd | ||
|
|
282b1d7b4d | ||
|
|
fb528ec70a | ||
|
|
9c8d1461b7 | ||
|
|
1059ea7e66 | ||
|
|
38941b8169 | ||
|
|
1dcb034b91 | ||
|
|
98a0e60b20 | ||
|
|
53b19dda24 | ||
|
|
db20807153 | ||
|
|
c66615934c | ||
|
|
dd67518248 | ||
|
|
7e3c0b2e18 | ||
|
|
223a142931 | ||
|
|
e5f88431dd | ||
|
|
8f88f248a9 | ||
|
|
7fdfca9201 | ||
|
|
a5133b0146 | ||
|
|
0078874088 | ||
|
|
fde578c7a6 | ||
|
|
249de8250f | ||
|
|
b7f44e882a | ||
|
|
8a88b50cb1 | ||
|
|
362f625949 | ||
|
|
1cf20585f4 | ||
|
|
497a1e0aea | ||
|
|
5db1cf984a | ||
|
|
458695b3a0 | ||
|
|
a814c7a63d | ||
|
|
a4de68a1ca | ||
|
|
97541d54f8 | ||
|
|
1c157adadf | ||
|
|
6d36195964 | ||
|
|
d9cec6e89b | ||
|
|
1eb63870fd | ||
|
|
980571ad61 | ||
|
|
39243ba626 | ||
|
|
7dbaca8851 | ||
|
|
2ba650a0fd | ||
|
|
de8e45a539 | ||
|
|
9017e05afa | ||
|
|
be1d659719 | ||
|
|
ad0c1e8aca | ||
|
|
902bd17cba | ||
|
|
0f512dd09e | ||
|
|
142138297e | ||
|
|
e116b0b645 | ||
|
|
c0c6503f17 | ||
|
|
5f8a11bdc0 | ||
|
|
b1bb3196b7 | ||
|
|
83fe1e7987 | ||
|
|
df03b36880 | ||
|
|
d3269f521a | ||
|
|
80d9106520 | ||
|
|
0a42b8728f | ||
|
|
9d93e3bb27 | ||
|
|
3cdd9f2508 | ||
|
|
2712654457 | ||
|
|
0a97de3cf5 | ||
|
|
def730f32a | ||
|
|
2a42ff67f5 | ||
|
|
c54d1d31cb | ||
|
|
cb3b648fcb | ||
|
|
b18c3ca71c | ||
|
|
b19810ea6f | ||
|
|
511ec2b5a8 | ||
|
|
382d73ddeb | ||
|
|
ca3c29fc2d | ||
|
|
57e209f7e0 | ||
|
|
5747dd6ba6 | ||
|
|
a86f7a494a | ||
|
|
4f5c9c7735 | ||
|
|
3473fb88a5 | ||
|
|
dd60ce5781 | ||
|
|
10d72f139e | ||
|
|
dde3f5dff1 | ||
|
|
678b2d2111 | ||
|
|
0d4cd77d2c | ||
|
|
c430e3d051 | ||
|
|
2f882378bc | ||
|
|
00195884de | ||
|
|
f665d7c50c | ||
|
|
969cc6d339 | ||
|
|
ab234634a9 | ||
|
|
fee46d2123 | ||
|
|
2eddcbd87f | ||
|
|
a54bc5d80c | ||
|
|
0464af6acf | ||
|
|
9dd14d0232 | ||
|
|
44b3f3f8c1 | ||
|
|
4a236e88cd | ||
|
|
5dd9badc11 | ||
|
|
b73bafd269 | ||
|
|
9efc3d55d5 | ||
|
|
0d40da4ada | ||
|
|
22d2ed88a3 | ||
|
|
9b3eaf9926 | ||
|
|
b4ecb7f14b | ||
|
|
a7f203a31c | ||
|
|
d5c07b1ae3 | ||
|
|
356fc2daad | ||
|
|
00aecd9eae | ||
|
|
c0d20cd1b2 | ||
|
|
27460a9c53 | ||
|
|
d88cd90899 | ||
|
|
7efbaf35d2 | ||
|
|
c6fcfb4d96 | ||
|
|
62c91b5286 | ||
|
|
ace3df5409 | ||
|
|
e8b8188c1f | ||
|
|
b38e9bdf0e | ||
|
|
672a95c908 | ||
|
|
3c98d574a2 | ||
|
|
fb98a7102a | ||
|
|
0001121432 | ||
|
|
0ded9e7d79 | ||
|
|
d9717fffa2 | ||
|
|
e1a5f0cdd7 | ||
|
|
032c81e93a | ||
|
|
531b8d6737 | ||
|
|
63b31c6186 | ||
|
|
982c430338 | ||
|
|
1a41dfeb2d | ||
|
|
e158ba63fc | ||
|
|
d4141c8e74 | ||
|
|
692e53880b | ||
|
|
ed79045588 | ||
|
|
8b495fe2ab | ||
|
|
6fa07b6777 | ||
|
|
adef0381be | ||
|
|
5423976278 | ||
|
|
b8f65cf2ec | ||
|
|
6d5c353fc0 | ||
|
|
f75dc17e02 | ||
|
|
e189b46be5 | ||
|
|
b3573029cc | ||
|
|
3ed4323089 | ||
|
|
146d33e0a3 | ||
|
|
6f4aba4aa8 | ||
|
|
3eee445dab | ||
|
|
709946ce54 | ||
|
|
162ff73f0f | ||
|
|
da6d6e970f | ||
|
|
27816e421f | ||
|
|
ce125a2ed1 | ||
|
|
e1848488f0 | ||
|
|
254c4ce087 | ||
|
|
42e97d83f7 | ||
|
|
422971c8b6 | ||
|
|
49d33e5047 | ||
|
|
30d619a348 | ||
|
|
94ea230645 | ||
|
|
3207f57a78 | ||
|
|
5e498ef864 | ||
|
|
5ad2113e2b | ||
|
|
b72eee6b84 | ||
|
|
b336a7ad69 | ||
|
|
a2cf51a790 | ||
|
|
67e659a878 | ||
|
|
1ba6b6c1e0 | ||
|
|
a13c8e41ba | ||
|
|
644494b1dc | ||
|
|
6f4b916598 | ||
|
|
9885c45fb2 | ||
|
|
19a83bc942 | ||
|
|
18c6cdd9d4 | ||
|
|
06773da8af | ||
|
|
ba2f1bcfb2 | ||
|
|
d8ee287b77 | ||
|
|
e2c8418c35 | ||
|
|
6c342eb23e | ||
|
|
698d86f9b0 | ||
|
|
6f8d9750d7 | ||
|
|
37ea3b8d3d | ||
|
|
e95e4284b1 | ||
|
|
ac62abeb0b | ||
|
|
ab3716d866 | ||
|
|
d0b40dbfa6 | ||
|
|
a1a15a6795 | ||
|
|
ccd3cea08c | ||
|
|
256dd3b3a5 | ||
|
|
90626f0a5f | ||
|
|
8a15eb9d66 | ||
|
|
a9800bc802 | ||
|
|
c551950a85 | ||
|
|
a2e7e4c88c | ||
|
|
378d412cf7 | ||
|
|
78a4117ec6 | ||
|
|
263458a80b | ||
|
|
8e36f25cf2 | ||
|
|
d2afe78fee | ||
|
|
0a8010fe53 | ||
|
|
57c6c7a4f6 | ||
|
|
d618430f6e | ||
|
|
434f222855 | ||
|
|
5ce0a8feba | ||
|
|
52a8d0e678 | ||
|
|
9f36fea62b | ||
|
|
da1e68ad1f | ||
|
|
8b3a0e986a | ||
|
|
a2eb405430 | ||
|
|
f18ed7d1b2 | ||
|
|
c6047f8712 | ||
|
|
4581d10703 | ||
|
|
b844240212 | ||
|
|
dd2a22a67d | ||
|
|
bbcca41909 | ||
|
|
1c08256e9c | ||
|
|
808da99092 | ||
|
|
c128f633d4 | ||
|
|
7ab125bbc2 | ||
|
|
3469e215eb | ||
|
|
fc3099a27c | ||
|
|
61f2273e2e | ||
|
|
cadc70ceec | ||
|
|
41868aa0f4 | ||
|
|
58b8015386 | ||
|
|
41e8e1105f | ||
|
|
8a5d687da6 | ||
|
|
5616a3fb34 | ||
|
|
0babb8b451 | ||
|
|
bdb127109f | ||
|
|
d8886b2065 | ||
|
|
22621a966c | ||
|
|
a4bcd802ec | ||
|
|
bbee391995 | ||
|
|
adbf05d366 | ||
|
|
662ae488be | ||
|
|
411f29fd53 | ||
|
|
3da56a4dd2 | ||
|
|
d75fd7e74e | ||
|
|
d02fa18617 | ||
|
|
a402d6d4ae | ||
|
|
c035f42676 | ||
|
|
7dfa0fb498 | ||
|
|
c830048b61 | ||
|
|
f1f77065d7 | ||
|
|
67367b03bf | ||
|
|
8f3566366e | ||
|
|
1c1bc19caf | ||
|
|
8129c6741e | ||
|
|
ac97c34d0f | ||
|
|
b97907cde6 | ||
|
|
493f8a8695 | ||
|
|
e8f5f6185a | ||
|
|
9385b95c81 | ||
|
|
9c87fe2fb4 | ||
|
|
5dd1226cdc | ||
|
|
c798d3037e | ||
|
|
15785f1deb | ||
|
|
c4c9a704ce | ||
|
|
8ca953dbed | ||
|
|
1d49e110e2 | ||
|
|
2c38695b6f | ||
|
|
81ebc8a635 | ||
|
|
136b162360 | ||
|
|
79ada570b7 | ||
|
|
5d89acfd3a | ||
|
|
ace46062a1 | ||
|
|
464b83dcf8 | ||
|
|
b1efa88161 | ||
|
|
7a54bc1030 | ||
|
|
4437b3bffb | ||
|
|
7ed731b0e5 | ||
|
|
ff535a1924 | ||
|
|
66fff06dfe | ||
|
|
d9d10df7a4 | ||
|
|
e57cf36f9b | ||
|
|
e35b9f9c73 | ||
|
|
39f343d536 | ||
|
|
6d62bffdeb | ||
|
|
0a008c8cc5 | ||
|
|
de130dcc2c | ||
|
|
4d23b57785 | ||
|
|
02bbdbf8d9 | ||
|
|
a3f100e7cb | ||
|
|
1f5be314a7 | ||
|
|
b9da92175e | ||
|
|
d121e8279d | ||
|
|
957b58687e | ||
|
|
190b7dfd45 | ||
|
|
c17e0c787e | ||
|
|
4aeb3747bc | ||
|
|
3ed401740e | ||
|
|
c8e11e92f1 | ||
|
|
f2cb8805b4 | ||
|
|
242a9253c6 | ||
|
|
6124ac2837 | ||
|
|
7bc30bf2fa | ||
|
|
28f2645c40 | ||
|
|
e9ec60d2b5 | ||
|
|
5898c60de1 | ||
|
|
191c943936 | ||
|
|
cc29728fc9 | ||
|
|
0e41ea33b2 | ||
|
|
0bdaadbacd | ||
|
|
ae08ce8723 | ||
|
|
69aef36184 | ||
|
|
406b6bcb34 | ||
|
|
f5520691fa | ||
|
|
471b2fd349 | ||
|
|
654a5d1aa5 | ||
|
|
7b0fb6036d | ||
|
|
c9846b1d0d | ||
|
|
2334593ec4 | ||
|
|
5ae003efcd | ||
|
|
df5dafbf75 | ||
|
|
3aa8f1233d | ||
|
|
24751130a5 | ||
|
|
fbefcb3a78 | ||
|
|
b0f5398412 | ||
|
|
d4492e0436 | ||
|
|
d6fae74773 | ||
|
|
be9bf5ec66 | ||
|
|
80c4bc8491 | ||
|
|
8eaa65499b | ||
|
|
578928135f | ||
|
|
485adc7761 | ||
|
|
43796a3dce | ||
|
|
3e58f97866 | ||
|
|
58ff9ab846 | ||
|
|
f3ccb4a186 | ||
|
|
114955194f | ||
|
|
3d886a021b | ||
|
|
67bc986e01 | ||
|
|
dc6a4482c1 | ||
|
|
fcde0efb22 | ||
|
|
6ce6bb8018 | ||
|
|
58fea291ad | ||
|
|
78f3893185 | ||
|
|
b06447ffe2 | ||
|
|
ce107efc7e | ||
|
|
ffa12bc2c9 | ||
|
|
50fadf453f | ||
|
|
3ab4fa625f | ||
|
|
a92d477d88 | ||
|
|
67f148ce44 | ||
|
|
5b1d5ce331 | ||
|
|
b8d933615d | ||
|
|
a7951b3832 | ||
|
|
0fa1bab9d0 | ||
|
|
9f9c710906 | ||
|
|
c6da5590ca | ||
|
|
666e95c540 | ||
|
|
1f9a42c2e8 | ||
|
|
233a04af9f | ||
|
|
0438808fe8 | ||
|
|
4ffe52399f | ||
|
|
0c2d06969c | ||
|
|
5396c270c1 | ||
|
|
a53b9d92d7 | ||
|
|
b2b9715218 | ||
|
|
f21e5bbd27 | ||
|
|
ccaf83e2ec | ||
|
|
cfa04bdd1b | ||
|
|
1b9255e04e | ||
|
|
fbd22d2601 | ||
|
|
b67cec2918 | ||
|
|
093f2af6dc | ||
|
|
41e83b38e2 | ||
|
|
78a8d4a579 | ||
|
|
66be9ec533 | ||
|
|
ba26c673b5 | ||
|
|
9609d137c1 | ||
|
|
63ade4f893 | ||
|
|
68911d91cb | ||
|
|
1295c8754a | ||
|
|
0fce237d57 | ||
|
|
6b8380ade7 | ||
|
|
190b09d4b5 | ||
|
|
606486b9fd | ||
|
|
18c201d9c1 | ||
|
|
a95b07de27 | ||
|
|
61f8b25c94 | ||
|
|
1d71ad4ae8 | ||
|
|
3cbf75c369 | ||
|
|
3a6ace59a7 | ||
|
|
555da7e5a5 | ||
|
|
99f9d6ccb7 | ||
|
|
f8472e9a3e | ||
|
|
bbeca48e2e | ||
|
|
5381914951 | ||
|
|
04cdcd3ac2 | ||
|
|
98570a00f0 | ||
|
|
ee50b24ce4 | ||
|
|
97100bc7e1 | ||
|
|
67515c163b | ||
|
|
810a4d766f | ||
|
|
ad553c0741 | ||
|
|
7da938f46c | ||
|
|
c4c3d6f3fa | ||
|
|
11f9965c48 | ||
|
|
fb0a300bc2 | ||
|
|
1bfeead39d | ||
|
|
a3095c2d5a | ||
|
|
85c459d4c8 | ||
|
|
56e20b2590 | ||
|
|
140299f0ce | ||
|
|
60f3200088 | ||
|
|
859fb468e2 | ||
|
|
05f1645ccd | ||
|
|
0134de41c1 | ||
|
|
04de6a2806 | ||
|
|
d2689a120e | ||
|
|
acd22b71a5 | ||
|
|
bc3bd9f762 | ||
|
|
6ef09724dd | ||
|
|
1726596a49 | ||
|
|
abcdadda50 | ||
|
|
0c9d6623b4 | ||
|
|
a6c81c80b0 | ||
|
|
08b9c10aa1 | ||
|
|
4162b6c65f | ||
|
|
651d7f7148 | ||
|
|
56b47fb01d | ||
|
|
f97c6c1222 | ||
|
|
9978d8f4eb | ||
|
|
4ead324c7e | ||
|
|
daad0b331c | ||
|
|
22aea0e075 | ||
|
|
96d5ba0c00 | ||
|
|
d9767a63f6 | ||
|
|
7b8b3938a2 | ||
|
|
ff72962334 | ||
|
|
ab3c642038 | ||
|
|
379359a19f | ||
|
|
f8c4218534 | ||
|
|
81a95816b6 | ||
|
|
c5222661b1 | ||
|
|
1bbf800643 | ||
|
|
ede592796d | ||
|
|
5b7794a587 | ||
|
|
d6d69b28bf | ||
|
|
e704c44707 | ||
|
|
31d22e3285 | ||
|
|
7aca6a657f | ||
|
|
39a3bd8634 | ||
|
|
624a533833 | ||
|
|
103e0f3b3e | ||
|
|
25c449c2b2 | ||
|
|
61d6578fb7 | ||
|
|
bb9ba23b3e | ||
|
|
755979f2bb | ||
|
|
a1b7550d2d | ||
|
|
4538e5f042 | ||
|
|
aeb0ad0694 | ||
|
|
65875adbc3 | ||
|
|
77837d062a | ||
|
|
1d011155cf | ||
|
|
8413c66c51 | ||
|
|
134bd063be | ||
|
|
74fc066602 | ||
|
|
b8de9f9553 | ||
|
|
077feae5fd | ||
|
|
0c0e77ab24 | ||
|
|
a223bb37a5 | ||
|
|
28899d801f | ||
|
|
76d87e5ec6 | ||
|
|
696dc20c87 | ||
|
|
d4a24ea993 | ||
|
|
764376de1d | ||
|
|
ee2d97eba4 | ||
|
|
0d84553390 | ||
|
|
27a0aa9e2b | ||
|
|
6a142dca01 | ||
|
|
69c50fef4a | ||
|
|
46f6342a50 | ||
|
|
dd25091ae9 | ||
|
|
50ffb75b50 | ||
|
|
72e7a1e0fa | ||
|
|
70ffc3ac73 | ||
|
|
4f5c962852 | ||
|
|
e983a338d4 | ||
|
|
adff5a8a96 | ||
|
|
4acc39b237 | ||
|
|
1b769a4ddd | ||
|
|
96c8e08b50 | ||
|
|
653789c1e6 | ||
|
|
1e424eca8a | ||
|
|
1d1f4bf6e5 | ||
|
|
1662d58cb8 | ||
|
|
b13643ebf7 | ||
|
|
7cf100ec96 | ||
|
|
30a446086e | ||
|
|
6a8a9f6eab | ||
|
|
80d0114264 | ||
|
|
5979c98bc4 | ||
|
|
7bcd4c65e3 | ||
|
|
675ac1b351 | ||
|
|
692b87eeb8 | ||
|
|
4b1f8cd80c | ||
|
|
d95041deb2 | ||
|
|
83eef2f168 | ||
|
|
ad79b29fd2 | ||
|
|
8852109b10 | ||
|
|
be75ab3d2c | ||
|
|
8cb41afc63 | ||
|
|
8a8419b609 | ||
|
|
bd08e15d96 | ||
|
|
1714103316 | ||
|
|
1b57bec161 | ||
|
|
db314c2ea9 | ||
|
|
cbe6d3ec71 | ||
|
|
a8d470222f | ||
|
|
39158070d7 | ||
|
|
d5456c05b0 | ||
|
|
1a5b146d36 | ||
|
|
c51bc163c4 | ||
|
|
194e8adeb0 | ||
|
|
4c949e8816 | ||
|
|
023513e085 | ||
|
|
bc98d13eeb | ||
|
|
23a31df815 | ||
|
|
849f7a894d | ||
|
|
9aa7a22bd7 | ||
|
|
230b36de4b | ||
|
|
02437eb8af | ||
|
|
54b0207fe1 | ||
|
|
7f1de87765 | ||
|
|
ce8baa80b2 | ||
|
|
6967dc5a22 | ||
|
|
0a1c625397 | ||
|
|
a3724bc87f | ||
|
|
00ec24e18f | ||
|
|
7faf7973ef | ||
|
|
eccfe42d1a | ||
|
|
39d6c0affe | ||
|
|
c7d0ebd3bd | ||
|
|
6fcad1c1c7 | ||
|
|
5e4e1e9877 | ||
|
|
7d65829ed7 | ||
|
|
b265dd49d6 | ||
|
|
82a9b3b8c3 | ||
|
|
bb9f30fcdf | ||
|
|
8784a07b2b | ||
|
|
1c653d5fd2 | ||
|
|
a08ba75a49 | ||
|
|
340410fe63 | ||
|
|
a1bd1c6698 | ||
|
|
95a68d2559 | ||
|
|
8d753d8c56 | ||
|
|
27fa1beb26 | ||
|
|
257a6bcb86 | ||
|
|
10b0fd7ea3 | ||
|
|
82e75f362a | ||
|
|
eb12ef0671 | ||
|
|
de610aa28b | ||
|
|
9d4700aee3 | ||
|
|
933352b0ea | ||
|
|
0e853363dd | ||
|
|
247c6d5848 | ||
|
|
49c665de66 | ||
|
|
8a577d5be5 | ||
|
|
8f5725f51a | ||
|
|
071d9072e1 | ||
|
|
71591b1f08 | ||
|
|
937f6f042f | ||
|
|
caaeb8efe8 | ||
|
|
7336c61453 | ||
|
|
9835ffe6ab | ||
|
|
c182c5fadc | ||
|
|
d995ded9b2 | ||
|
|
c8977f0052 | ||
|
|
cfd94b9416 | ||
|
|
bf64d3f004 | ||
|
|
235f2e49ae | ||
|
|
3cd86a06a7 | ||
|
|
8cbd32c724 | ||
|
|
04dd06313a | ||
|
|
c90a766fdc | ||
|
|
66e6aff2b4 | ||
|
|
f66d50c51f | ||
|
|
6b9bd73d8a | ||
|
|
43946b9bd3 | ||
|
|
99aed49f8d | ||
|
|
0f08a4d2b0 | ||
|
|
6a438e79c4 | ||
|
|
fff227f3ae | ||
|
|
d9df64bca7 | ||
|
|
95db52b068 | ||
|
|
e2b7bc4b56 | ||
|
|
6d669461f9 | ||
|
|
01f72c3d75 | ||
|
|
869960a89c | ||
|
|
94a0a1b23a | ||
|
|
d05c5012ff | ||
|
|
ca5d8f61cc | ||
|
|
398f2afb04 | ||
|
|
f0442b7269 | ||
|
|
7e59b9dbcb | ||
|
|
806fb9bdfc | ||
|
|
1f9719a420 | ||
|
|
ca5b87efba | ||
|
|
5c83fb56ab | ||
|
|
bbded48a1b | ||
|
|
c640d53396 | ||
|
|
4fae99d767 | ||
|
|
73a5742c09 | ||
|
|
b0c71a0961 | ||
|
|
25ae4afcbb | ||
|
|
f167ad1524 | ||
|
|
c406d5bab1 | ||
|
|
d8c3a97f24 | ||
|
|
64c8be64d3 | ||
|
|
3490a3244c | ||
|
|
b8143e7090 | ||
|
|
6ad9258740 | ||
|
|
68bcc2b571 | ||
|
|
3b93643091 | ||
|
|
bf8a505135 | ||
|
|
d774304574 | ||
|
|
c133d81d36 | ||
|
|
abb89ed3e8 | ||
|
|
46f524de57 | ||
|
|
0b566f83de | ||
|
|
27f992bd87 | ||
|
|
10fad2ecde | ||
|
|
97043b9789 | ||
|
|
0a76b4b18a | ||
|
|
f87659f2e3 | ||
|
|
c544283bbf | ||
|
|
1814f42165 | ||
|
|
60fa22c4df | ||
|
|
9767e33bdd | ||
|
|
c1583f065d | ||
|
|
5fdf3353b7 | ||
|
|
bbc6e3e4e9 | ||
|
|
5ad5294fca | ||
|
|
65cbd3d658 | ||
|
|
8293f9e2cc | ||
|
|
09c5882c97 | ||
|
|
f3a63ebd96 | ||
|
|
b5164d844e | ||
|
|
73c64470fd | ||
|
|
4227f864a2 | ||
|
|
786814b09c | ||
|
|
e54d74812e | ||
|
|
f79a83e616 | ||
|
|
9c9e4977b1 | ||
|
|
c33f14e761 | ||
|
|
b52ad52760 | ||
|
|
b35d897919 | ||
|
|
4ec4305fd5 | ||
|
|
fa0899b7cf | ||
|
|
f6f2454d37 | ||
|
|
0982686258 | ||
|
|
3393b998aa | ||
|
|
879d95a74b | ||
|
|
a09c068d1d | ||
|
|
68ce4701c6 | ||
|
|
878a414646 | ||
|
|
f98470a0f5 | ||
|
|
882dd6ad27 | ||
|
|
987a7da867 | ||
|
|
76de22b676 | ||
|
|
4b1057efaf | ||
|
|
6e3af65749 | ||
|
|
71ad5aaaed | ||
|
|
0c4a898c97 | ||
|
|
c22f70b49e | ||
|
|
ebed95cbcd | ||
|
|
e7acb31a54 | ||
|
|
59ca5bdabc | ||
|
|
da70c0d31c | ||
|
|
6c8074852f | ||
|
|
4afe4b30d9 | ||
|
|
8a3fdbc642 | ||
|
|
76c88c43d1 | ||
|
|
8378d06ab6 | ||
|
|
61851f1300 | ||
|
|
3cc078e501 | ||
|
|
7613712137 | ||
|
|
f60d78a3ca | ||
|
|
c2f2b214a2 | ||
|
|
703c8b4c1d | ||
|
|
6722b2501f | ||
|
|
454127e354 | ||
|
|
84f7e27654 | ||
|
|
c0878fc627 | ||
|
|
2ba806359a | ||
|
|
1c5c6bd929 | ||
|
|
36eea552ac | ||
|
|
3945c59be1 | ||
|
|
d256ff0556 | ||
|
|
bd610b2323 | ||
|
|
d71dd38b98 | ||
|
|
d708bdfe2d | ||
|
|
631f6e288c | ||
|
|
de5df05b67 | ||
|
|
b43dfcf11e | ||
|
|
d6e58ea961 | ||
|
|
c420b10540 | ||
|
|
00e32a1db0 | ||
|
|
7e453872b1 | ||
|
|
2e39afde78 | ||
|
|
38c54a70da | ||
|
|
b635f06619 | ||
|
|
f7fd47d62c | ||
|
|
36536bbc6b | ||
|
|
90ef2e6f72 | ||
|
|
edbb7bc1af | ||
|
|
b76e80bad3 | ||
|
|
c32e6e3097 | ||
|
|
edd21deaca | ||
|
|
4e318e023f | ||
|
|
21a872bbe8 | ||
|
|
2c13d7efdd | ||
|
|
0eae40dec6 | ||
|
|
858c100146 | ||
|
|
529b422189 | ||
|
|
d53bd80d14 | ||
|
|
b364160fdd | ||
|
|
3a0e8e3d26 | ||
|
|
5f27135419 | ||
|
|
d4dda9e06f | ||
|
|
0114bf4a3b | ||
|
|
b84aaec294 | ||
|
|
3380bfdb7d | ||
|
|
e4148ef51e | ||
|
|
c0ac418e87 | ||
|
|
2daec9cc9c | ||
|
|
bf739d8367 | ||
|
|
d908648582 | ||
|
|
2ae86922a4 | ||
|
|
3344eebe3f | ||
|
|
de2504b15f | ||
|
|
4d21026661 | ||
|
|
876827d39b | ||
|
|
63d332f8d9 | ||
|
|
413c2e8deb | ||
|
|
e649ad308f | ||
|
|
90484cb8e6 | ||
|
|
1cd6e03529 | ||
|
|
8f91615839 | ||
|
|
37982a6870 | ||
|
|
76b4e91046 | ||
|
|
f0a9c3e880 | ||
|
|
b6dd6671c3 | ||
|
|
9b09d6458e | ||
|
|
a0c434477c | ||
|
|
67a05a97c8 | ||
|
|
4139491019 | ||
|
|
81ed159e90 | ||
|
|
0cdbeaa38b | ||
|
|
e62001530f | ||
|
|
2e7c7732dc | ||
|
|
10c3e0134a | ||
|
|
14ef2e78e2 | ||
|
|
5c70b310de | ||
|
|
bc9e2aa1e1 | ||
|
|
13e3562424 | ||
|
|
a3948df5da | ||
|
|
14fc4819f1 | ||
|
|
b780a2a885 | ||
|
|
7e94c7d47c | ||
|
|
fb503ede1a | ||
|
|
cc1f418423 | ||
|
|
c6509325a8 | ||
|
|
2fe992e933 | ||
|
|
5d123221db | ||
|
|
342c8969dc | ||
|
|
cfca8b1dba | ||
|
|
d937153888 | ||
|
|
512d33b734 | ||
|
|
e0c2c575bf | ||
|
|
3c37ce174a | ||
|
|
d8cc783c14 | ||
|
|
c27bf6a3c4 | ||
|
|
9b7b4d7f56 | ||
|
|
c92149fa3e | ||
|
|
f4fd0fc276 | ||
|
|
222681ca97 | ||
|
|
d5c7bcdd18 | ||
|
|
f683426753 | ||
|
|
be244840b2 | ||
|
|
2d2857e6f3 | ||
|
|
da7028f59c | ||
|
|
5fa4f8f94f | ||
|
|
fe25933d0e | ||
|
|
c88e37ffba | ||
|
|
4aa60c5acb | ||
|
|
61be2f78e4 | ||
|
|
dbd1726d08 | ||
|
|
9d344570b4 | ||
|
|
c7825c3174 | ||
|
|
8ca5807801 | ||
|
|
51c30f4f66 | ||
|
|
f7860bd4b7 | ||
|
|
1f5f38895d | ||
|
|
32d74194c0 | ||
|
|
1a05e4274c | ||
|
|
ee131ac68a | ||
|
|
f8194c76b0 | ||
|
|
3fe61971b5 | ||
|
|
47a9b88c90 | ||
|
|
9823dfa4f5 | ||
|
|
746afddd89 | ||
|
|
92b1789b11 | ||
|
|
50a4f1b5d4 | ||
|
|
c2dedcdbd7 | ||
|
|
8bfbe7706e |
2437 changed files with 179125 additions and 13545 deletions
10
.dockerignore
Normal file
10
.dockerignore
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Ignored for `Dockerfile` build tinymist cli
|
||||
target
|
||||
node_modules
|
||||
editors
|
||||
tools
|
||||
refs
|
||||
local
|
||||
syntaxes
|
||||
docs
|
||||
contrib
|
||||
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.zed/settings.json linguist-language=json5
|
||||
59
.github/ISSUE_TEMPLATE/bug_report.md
vendored
59
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
|
@ -1,59 +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 (Library test):
|
||||
1. Declare a rust test 'fn test_xxx() { ... }' or typescript test 'it_should(function () { ... })'
|
||||
2. Execute test function
|
||||
3. See error
|
||||
|
||||
Or (Shell code):
|
||||
|
||||
1. Attach necessary resources to execute shell code
|
||||
2. Put down some shell code 'cargo run --bin typst-ts-cli -- ...'
|
||||
3. Execute shell code
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Package/Software version:**
|
||||
|
||||
VSCode version(Help -> About):
|
||||
```plain
|
||||
Version: 1.81.1
|
||||
Commit: 6c3e3dba23e8fadc360aed75ce363ba185c49794
|
||||
Date: 2023-08-09T22:18:39.991Z
|
||||
Electron: 22.3.18
|
||||
ElectronBuildId: 22689846
|
||||
Chromium: 108.0.5359.215
|
||||
Node.js: 16.17.1
|
||||
V8: 10.8.168.25-electron.0
|
||||
OS: Linux x64 6.4.12-x64v4-xanmod1
|
||||
```
|
||||
|
||||
tinymist extension version: `v0.7.3`
|
||||
|
||||
**Logs:**
|
||||
|
||||
tinymist server log(Output Panel -> tinymist):
|
||||
```plain
|
||||
|
||||
```
|
||||
|
||||
tinymist client log(Help -> Toggle Developer Tools -> Console):
|
||||
```plain
|
||||
|
||||
```
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
92
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
92
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
name: Bug report
|
||||
description: File a bug/issue
|
||||
labels: ["bug", "need-to-investigate"]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for this?
|
||||
description: Please search to see if an issue already exists for the bug you encountered.
|
||||
options:
|
||||
- label: I have searched the existing issues
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Platform
|
||||
description: Which platform are you on?
|
||||
options:
|
||||
- x64 Windows (win32-x64, Most Common)
|
||||
- x64 Linux (linux-x64, Most Common)
|
||||
- Apple Silicon macOS (darwin-arm64, Most Common)
|
||||
- ARM64 Windows (win32-arm64)
|
||||
- ARM64 Linux (linux-arm64)
|
||||
- ARMv7 Linux (linux-armhf)
|
||||
- Intel macOS (darwin-x64)
|
||||
- x64 Alpine Linux (alpine-x64)
|
||||
- ARM64 Alpine Linux (alpine-arm64)
|
||||
- Browser (web)
|
||||
- Other Platforms (universal)
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Editor
|
||||
description: Which editor are you using?
|
||||
options:
|
||||
- VS Cod(e,ium)
|
||||
- Neovim
|
||||
- Emacs
|
||||
- Sublime Text
|
||||
- Helix
|
||||
- Zed
|
||||
- CLI (Command Line Interface)
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Editor Version
|
||||
description: |
|
||||
For example, in VSCode, get the version in (Help -> About)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: A clear and concise description of what the bug is.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Server Logs
|
||||
description: |
|
||||
For example, in Neovim, the log is oftenly stored in the `~/.local/state/nvim/lsp`.
|
||||
For example, in VSCode, get the logs in (Output Panel -> Tinymist).
|
||||
We may close a bug report if there is no full logs. Please don't truncate it for us, attach it as a file if it's too long.
|
||||
value: |
|
||||
```log
|
||||
Paste your logs here
|
||||
```
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Browser Logs
|
||||
description: |
|
||||
For example, in VSCode, get the logs in (Help -> Toggle Developer Tools -> Console).
|
||||
If you open preview in browser, the console log in the browser is also helpful.
|
||||
We may close a bug report if there is no full logs. Please don't truncate it for us, attach it as a file if it's too long.
|
||||
value: |
|
||||
```log
|
||||
Paste your logs here
|
||||
```
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: |
|
||||
Links? References? Anything that will give us more context about the issue you are encountering!
|
||||
|
||||
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||
validations:
|
||||
required: false
|
||||
26
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
26
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
name: Feature request
|
||||
description: Create a feature request
|
||||
labels: ["enhancement", "need-to-investigate"]
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Motivation
|
||||
description: |
|
||||
A brief use case, scenario, or other argument used in support of this *feature*.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: |
|
||||
A clear and concise description of this *feature*.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: More Examples/Questions
|
||||
description: |
|
||||
- Using examples to profile how you imagine the *feature* should be
|
||||
- Raising questions to highlight the uncertain design for the *feature*.
|
||||
validations:
|
||||
required: false
|
||||
337
.github/copilot-instructions-l10n.md
vendored
Normal file
337
.github/copilot-instructions-l10n.md
vendored
Normal file
|
|
@ -0,0 +1,337 @@
|
|||
# Localization Instructions for Claude/Copilot
|
||||
|
||||
This document provides comprehensive guidance for adding, updating, and maintaining localization (l10n) in the Tinymist project.
|
||||
|
||||
## Overview
|
||||
|
||||
Tinymist's localization system supports multiple languages across two main components:
|
||||
- **Rust backend** (`crates/`): Language server functionality
|
||||
- **VSCode extension** (`editors/vscode/`): Editor integration
|
||||
|
||||
The localization process has two main phases:
|
||||
1. **Marking and Extracting Messages**: Adding localization calls in code and extracting them
|
||||
2. **Translating Messages**: Adding translations to locale files
|
||||
|
||||
## Phase 1: Marking and Extracting Messages
|
||||
|
||||
### Rust Backend (`crates/`)
|
||||
|
||||
#### Adding Localized Messages
|
||||
|
||||
Use the `tinymist_l10n::t!` macro with a key and default English message:
|
||||
|
||||
```rust
|
||||
// Simple message
|
||||
let message = tinymist_l10n::t!("error.file-not-found", "File not found");
|
||||
|
||||
// Message with parameters
|
||||
let message = tinymist_l10n::t!(
|
||||
"error.invalid-config",
|
||||
"Invalid configuration: {key}",
|
||||
key = config_key
|
||||
);
|
||||
```
|
||||
|
||||
**Note**: Use the full `tinymist_l10n::t!` path - no need to import the macro separately.
|
||||
|
||||
#### Key Naming Convention
|
||||
|
||||
Use hierarchical dot-separated keys:
|
||||
- `component.category.specific-action`
|
||||
- Examples:
|
||||
- `tinymist-query.code-action.exportPdf`
|
||||
- `tinymist.config.badServerConfig`
|
||||
- `tinymist-project.validate-error.root-path-not-absolute`
|
||||
|
||||
### TypeScript/VSCode Extension (`editors/vscode/`)
|
||||
|
||||
#### Adding Localized Messages
|
||||
|
||||
Use the `l10nMsg` function imported from `../l10n`:
|
||||
|
||||
```typescript
|
||||
import { l10nMsg } from "../l10n";
|
||||
|
||||
// Simple message
|
||||
const message = l10nMsg("Export as PDF");
|
||||
|
||||
// Message with parameters
|
||||
const message = l10nMsg("Processing {count} files", { count: fileCount });
|
||||
```
|
||||
|
||||
#### Import Pattern
|
||||
|
||||
Always import `l10nMsg` from the relative path to `l10n.ts`:
|
||||
|
||||
```typescript
|
||||
import { l10nMsg } from "../l10n"; // Adjust path as needed
|
||||
```
|
||||
|
||||
### Extracting Messages
|
||||
|
||||
After adding localized messages to code, extract them using:
|
||||
|
||||
```bash
|
||||
yarn build:l10n
|
||||
```
|
||||
|
||||
This command:
|
||||
1. Scans Rust and TypeScript files for localization calls
|
||||
2. Extracts messages to TOML files in `locales/`:
|
||||
- `locales/tinymist-rt.toml` (Rust messages)
|
||||
- `locales/tinymist-vscode-rt.toml` (TypeScript messages)
|
||||
3. Updates existing translations while preserving manual edits
|
||||
|
||||
#### When to Run Extraction
|
||||
|
||||
- **Required**: After adding new localized messages to code
|
||||
- **Not needed**: When only editing translations in `locales/` files
|
||||
|
||||
## Phase 2: Translating Messages
|
||||
|
||||
### Locale File Format
|
||||
|
||||
Locale files use TOML format designed for easy modification by LLMs:
|
||||
|
||||
```toml
|
||||
# The translations are partially generated by copilot
|
||||
|
||||
[key.name]
|
||||
en = "English message"
|
||||
zh = "Chinese translation"
|
||||
zh-TW = "Traditional Chinese translation"
|
||||
fr = "French translation"
|
||||
```
|
||||
|
||||
### Available Locale Files
|
||||
|
||||
- `locales/tinymist-vscode.toml` - VSCode extension UI (manual translations)
|
||||
- `locales/tinymist-vscode-rt.toml` - VSCode extension runtime (auto-extracted)
|
||||
- `locales/tinymist-rt.toml` - Rust backend runtime (auto-extracted)
|
||||
|
||||
### Adding Translations
|
||||
|
||||
#### Example: Adding a French Translation
|
||||
|
||||
```toml
|
||||
[extension.tinymist.command.tinymist.exportCurrentPdf]
|
||||
en = "Export the Opened File as PDF"
|
||||
zh = "将当前打开的文件导出为 PDF"
|
||||
fr = "Exporter le fichier ouvert en PDF" # Add this line
|
||||
```
|
||||
|
||||
#### Example: Adding Support for a New Language
|
||||
|
||||
```toml
|
||||
[extension.tinymist.command.tinymist.restartServer]
|
||||
en = "Restart server"
|
||||
zh = "重启服务器"
|
||||
es = "Reiniciar servidor" # New Spanish translation
|
||||
de = "Server neu starten" # New German translation
|
||||
```
|
||||
|
||||
### Translation Guidelines
|
||||
|
||||
1. **Preserve Parameters**: Keep parameter placeholders like `{key}`, `{count}`, `{value}`
|
||||
2. **Maintain Formatting**: Preserve newlines and special characters
|
||||
3. **Context Awareness**: Consider the UI context where the message appears
|
||||
4. **Consistency**: Use consistent terminology across related messages
|
||||
|
||||
### Language Codes
|
||||
|
||||
Use standard language codes:
|
||||
- `en` - English (required, default)
|
||||
- `zh` - Simplified Chinese
|
||||
- `zh-TW` - Traditional Chinese
|
||||
- `fr` - French
|
||||
- `de` - German
|
||||
- `es` - Spanish
|
||||
- `ja` - Japanese
|
||||
- `ru` - Russian
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: Adding a New Error Message (Rust)
|
||||
|
||||
1. **Add to Rust code**:
|
||||
```rust
|
||||
return Err(tinymist_l10n::t!(
|
||||
"compilation.invalid-syntax",
|
||||
"Invalid syntax at line {line}",
|
||||
line = line_number
|
||||
).into());
|
||||
```
|
||||
|
||||
2. **Extract messages**:
|
||||
```bash
|
||||
yarn build:l10n
|
||||
```
|
||||
|
||||
3. **Add translations** in `locales/tinymist-rt.toml`:
|
||||
```toml
|
||||
[compilation.invalid-syntax]
|
||||
en = "Invalid syntax at line {line}"
|
||||
zh = "第 {line} 行语法错误"
|
||||
fr = "Syntaxe invalide à la ligne {line}"
|
||||
```
|
||||
|
||||
### Example 2: Adding a New UI Label (TypeScript)
|
||||
|
||||
1. **Add to TypeScript code**:
|
||||
```typescript
|
||||
const exportButton = vscode.window.createQuickPick();
|
||||
exportButton.title = l10nMsg("Select Export Format");
|
||||
```
|
||||
|
||||
2. **Extract messages**:
|
||||
```bash
|
||||
yarn build:l10n
|
||||
```
|
||||
|
||||
3. **Add translations** in `locales/tinymist-vscode-rt.toml`:
|
||||
```toml
|
||||
["Select Export Format"]
|
||||
en = "Select Export Format"
|
||||
zh = "选择导出格式"
|
||||
fr = "Sélectionner le format d'exportation"
|
||||
```
|
||||
|
||||
### Example 3: Complex Message with Multiple Parameters
|
||||
|
||||
```rust
|
||||
let message = tinymist_l10n::t!(
|
||||
"preview.compilation-stats",
|
||||
"Compiled {pages} pages in {duration}ms",
|
||||
pages = page_count,
|
||||
duration = compile_time
|
||||
);
|
||||
```
|
||||
|
||||
Corresponding translation:
|
||||
```toml
|
||||
[preview.compilation-stats]
|
||||
en = "Compiled {pages} pages in {duration}ms"
|
||||
zh = "在 {duration} 毫秒内编译了 {pages} 页"
|
||||
fr = "Compilé {pages} pages en {duration}ms"
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### When to Localize
|
||||
|
||||
**DO localize:**
|
||||
- User-facing error messages
|
||||
- UI labels and buttons
|
||||
- Status messages
|
||||
- Command descriptions
|
||||
- Configuration descriptions
|
||||
|
||||
**DON'T localize:**
|
||||
- Log messages for developers
|
||||
- Debug output
|
||||
- Technical error codes
|
||||
- File paths or URLs
|
||||
- Code identifiers
|
||||
|
||||
### Message Design
|
||||
|
||||
1. **Keep messages concise** but informative
|
||||
2. **Use parameters** for dynamic content instead of string concatenation
|
||||
3. **Design for translation** - avoid culture-specific references
|
||||
4. **Group related messages** using consistent key prefixes
|
||||
|
||||
### Key Naming
|
||||
|
||||
```rust
|
||||
// Good: Hierarchical, descriptive
|
||||
tinymist_l10n::t!("export.pdf.success", "PDF exported successfully")
|
||||
tinymist_l10n::t!("export.pdf.error.permission", "Permission denied for PDF export")
|
||||
|
||||
// Bad: Flat, unclear
|
||||
tinymist_l10n::t!("msg1", "PDF exported successfully")
|
||||
tinymist_l10n::t!("err", "Permission denied")
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Build errors after adding localization**:
|
||||
- Ensure proper import of `tinymist_l10n` or `l10nMsg`
|
||||
- Check for typos in macro/function calls
|
||||
- Run `yarn build:l10n` to extract new messages
|
||||
|
||||
2. **Missing translations**:
|
||||
- Verify the key exists in the appropriate locale file
|
||||
- Check if extraction was run after adding the message
|
||||
- Ensure locale file syntax is valid TOML
|
||||
|
||||
3. **Parameter substitution not working**:
|
||||
- Verify parameter names match between code and translation
|
||||
- Check for missing or extra parameters in translations
|
||||
|
||||
### Testing Localization
|
||||
|
||||
1. **Test message extraction**:
|
||||
```bash
|
||||
yarn build:l10n
|
||||
```
|
||||
|
||||
2. **Verify locale files** contain your new messages
|
||||
|
||||
3. **Test in different languages** by changing VSCode language settings
|
||||
|
||||
## File Structure Reference
|
||||
|
||||
```
|
||||
locales/
|
||||
├── README.md # Documentation
|
||||
├── tinymist-vscode.toml # Manual VSCode translations
|
||||
├── tinymist-vscode-rt.toml # Auto-extracted VSCode messages
|
||||
└── tinymist-rt.toml # Auto-extracted Rust messages
|
||||
|
||||
crates/
|
||||
├── tinymist-l10n/ # Localization library
|
||||
└── */src/**/*.rs # Rust source files (use tinymist_l10n::t!)
|
||||
|
||||
editors/vscode/
|
||||
├── src/l10n.ts # TypeScript l10n helper
|
||||
└── src/**/*.ts # TypeScript source files (use l10nMsg)
|
||||
|
||||
scripts/
|
||||
└── build-l10n.mjs # Message extraction script
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Conditional Messages
|
||||
|
||||
```rust
|
||||
let message = if is_error {
|
||||
tinymist_l10n::t!("status.error", "Error occurred")
|
||||
} else {
|
||||
tinymist_l10n::t!("status.success", "Operation completed")
|
||||
};
|
||||
```
|
||||
|
||||
### Pluralization
|
||||
|
||||
Handle plurals with parameters:
|
||||
|
||||
```rust
|
||||
let message = tinymist_l10n::t!(
|
||||
"files.count",
|
||||
"{count} file(s) processed",
|
||||
count = file_count
|
||||
);
|
||||
```
|
||||
|
||||
Translation:
|
||||
```toml
|
||||
[files.count]
|
||||
en = "{count} file(s) processed"
|
||||
zh = "已处理 {count} 个文件"
|
||||
fr = "{count} fichier(s) traité(s)"
|
||||
```
|
||||
|
||||
Remember to run `yarn build:l10n` after adding any new localized messages to code, and only edit translation files manually for languages other than English.
|
||||
128
.github/copilot-instructions.md
vendored
Normal file
128
.github/copilot-instructions.md
vendored
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
This is a Rust+JavaScript repository. It builds:
|
||||
- A Rust binary serves language features:
|
||||
- `lsp`: Runs language server
|
||||
- `dap`: Runs debug adapter
|
||||
- `preview`: Runs preview server
|
||||
- The JavaScript VS Code extension.
|
||||
- The lua plugin for Neovim.
|
||||
|
||||
It is primarily responsible for providing integrated typst language service to various editors like VS Code, Neovim, Emacs, and Zed. Please follow these guidelines when contributing:
|
||||
|
||||
## Specialized Instructions
|
||||
|
||||
- **Localization**: See [copilot-instructions-l10n.md](./copilot-instructions-l10n.md) for comprehensive guidance on adding, updating, and maintaining localization in the project.
|
||||
|
||||
## Code Standards
|
||||
|
||||
### Keep Good PR Title
|
||||
|
||||
Determine a good PR prefix **only** by the PR description before work. Add a prefix to indicate what kind of release this pull request corresponds to. For reference, see https://www.conventionalcommits.org/
|
||||
|
||||
Available types:
|
||||
- dev
|
||||
- feat
|
||||
- fix
|
||||
- docs
|
||||
- style
|
||||
- refactor
|
||||
- perf
|
||||
- test
|
||||
- build
|
||||
- ci
|
||||
- chore
|
||||
- revert
|
||||
|
||||
### Required Before Each Commit
|
||||
- Run `yarn fmt` to format Rust/JavaScript files
|
||||
- This will run formatters on all necessary files to maintain consistent style
|
||||
|
||||
### Development Flow
|
||||
- Build Server: `cargo build`
|
||||
- Build VS Code Extension: `cd editors/vscode && yarn build`
|
||||
- Full CI check: `cargo clippy --workspace --all-targets`
|
||||
- Test Server: `cargo test --workspace -- --skip=e2e`
|
||||
Note that, in the envoironment where network is not available (copilot or nix actions), we should also skip following tests:
|
||||
```
|
||||
completion::tests::test_pkgs
|
||||
docs::package::tests::cetz
|
||||
docs::package::tests::fletcher
|
||||
docs::package::tests::tidy
|
||||
docs::package::tests::touying
|
||||
```
|
||||
|
||||
## Repository Structure
|
||||
- `crates/`: rust crates for the server and related functionality
|
||||
- `editors/vscode/`: VS Code extension code
|
||||
- `editors/neovim/`: Lua plugin for Neovim (canonical implementation - see [CONTRIBUTING.md](editors/neovim/CONTRIBUTING.md) and [Specification.md](editors/neovim/Specification.md))
|
||||
- `tools/editor-tools`: utility GUI tools for typst
|
||||
- `tools/typst-preview-frontend`: Preview GUI for typst
|
||||
- `docs/`: documentation for the project
|
||||
- `locales/`: localization files for the entire project
|
||||
- `tests/`: integration tests for the server and editors
|
||||
- `syntaxes/`: textmate syntax definitions for typst
|
||||
|
||||
## Key Guidelines
|
||||
1. Follow Rust and JavaScript best practices and idiomatic patterns
|
||||
2. Maintain existing code structure and organization
|
||||
4. Write unit tests for new functionality. Use snapshot-based unit tests when possible.
|
||||
5. Document public APIs and complex logic in code comments
|
||||
|
||||
## Editor Integration Guidelines
|
||||
|
||||
### Neovim Canonical Implementation
|
||||
|
||||
The Neovim plugin in `editors/neovim/` serves as the **canonical implementation** of a Tinymist editor language client. When working on editor integrations:
|
||||
|
||||
- **Reference Implementation**: Use the Neovim plugin as the reference for LSP client patterns, configuration handling, and event subscription mechanisms
|
||||
- **Test Suite**: Refer to `editors/neovim/spec/` for comprehensive test coverage examples
|
||||
- **Documentation**: See [editors/neovim/Specification.md](editors/neovim/Specification.md) for complete API and functionality documentation
|
||||
- **Development Workflow**: Use `./bootstrap.sh editor` for interactive testing and `./bootstrap.sh test` for automated validation
|
||||
- **Contributing**: Follow patterns established in [editors/neovim/CONTRIBUTING.md](editors/neovim/CONTRIBUTING.md)
|
||||
|
||||
## Development Guidelines
|
||||
|
||||
### `tools/editor-tools`
|
||||
|
||||
The frontend-side and backend-side can be developed independently. For example, a data object passed from backend to frontend can be coded as `van.state<T>` as follows:
|
||||
|
||||
- Intermediate arguments:
|
||||
|
||||
```ts
|
||||
const documentMetricsData = `:[[preview:DocumentMetrics]]:`;
|
||||
const docMetrics = van.state<DocumentMetrics>(
|
||||
documentMetricsData.startsWith(":") ? DOC_MOCK : JSON.parse(base64Decode(documentMetricsData)),
|
||||
);
|
||||
```
|
||||
|
||||
- Server-pushing arguments (e.g. `programTrace` in `tools/editor-tools/src/vscode.ts`):
|
||||
|
||||
```ts
|
||||
export const programTrace = van.state<TraceReport | undefined>(undefined /* init value */);
|
||||
|
||||
export function setupVscodeChannel() {
|
||||
if (vscodeAPI?.postMessage) {
|
||||
// Handle messages sent from the extension to the webview
|
||||
window.addEventListener("message", (event: any) => {
|
||||
switch (event.data.type) {
|
||||
case "traceData": {
|
||||
programTrace.val = event.data.data;
|
||||
break;
|
||||
}
|
||||
// other cases
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Tool request arguments (e.g. `requestSaveFontsExportConfigure` in `tools/editor-tools/src/vscode.ts`):
|
||||
|
||||
```ts
|
||||
export function requestSaveFontsExportConfigure(data: fontsExportConfigure) {
|
||||
if (vscodeAPI?.postMessage) {
|
||||
vscodeAPI.postMessage({ type: "saveFontsExportConfigure", data });
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`DOC_MOCK` is a mock data object for the frontend to display so that the frontend can be developed directly with `yarn dev`.
|
||||
70
.github/workflows/announce.yml
vendored
Normal file
70
.github/workflows/announce.yml
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
name: tinymist::announce
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
tag:
|
||||
description: Release Tag
|
||||
required: true
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: Release Tag
|
||||
required: true
|
||||
type: string
|
||||
permissions:
|
||||
"contents": "write"
|
||||
|
||||
env:
|
||||
isNightly: ${{ ((!((!contains(inputs.tag, 'rc') && (endsWith(inputs.tag, '0') || endsWith(inputs.tag, '2') || endsWith(inputs.tag, '4') || endsWith(inputs.tag, '6') || endsWith(inputs.tag, '8')))))) }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-22.04"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install dist
|
||||
# we specify bash to get pipefail; it guards against the `curl` command
|
||||
# failing. otherwise `sh` won't catch that `curl` returned non-0
|
||||
shell: bash
|
||||
run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/Myriad-Dreamin/cargo-dist/releases/download/v0.28.6-tinymist.3/cargo-dist-installer.sh | sh"
|
||||
- name: Install parse changelog
|
||||
uses: taiki-e/install-action@parse-changelog
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'yarn'
|
||||
- name: Install deps
|
||||
run: yarn install
|
||||
- id: announce
|
||||
name: "Generate announcement"
|
||||
run: |
|
||||
yarn draft-release ${{ inputs.tag }}
|
||||
echo "draft-release ran successfully"
|
||||
- name: "Upload announcement changelog"
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: announcement-changelog.md
|
||||
path: target/announcement-changelog.md
|
||||
- name: "Upload announcement"
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: announcement-dist.md
|
||||
path: target/announcement-dist.md
|
||||
- name: "Upload announcement"
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: announcement.gen.md
|
||||
path: target/announcement.gen.md
|
||||
- name: Create GitHub Release
|
||||
env:
|
||||
PRERELEASE_FLAG: "${{ (fromJson(env.isNightly) && '--prerelease') || '' }}"
|
||||
ANNOUNCEMENT_TITLE: "${{ steps.announce.outputs.tag }}"
|
||||
RELEASE_COMMIT: "${{ github.sha }}"
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
echo "Creating release for ${{ steps.announce.outputs.tag }} with PRERELEASE_FLAG=$PRERELEASE_FLAG (isNightly=$isNightly)"
|
||||
gh release create "${{ steps.announce.outputs.tag }}" $PRERELEASE_FLAG --title "$ANNOUNCEMENT_TITLE" --notes-file target/announcement.gen.md --draft=true
|
||||
151
.github/workflows/auto-tag.yml
vendored
Normal file
151
.github/workflows/auto-tag.yml
vendored
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
name: tinymist::auto_tag
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
auto-tag:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.REPO_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get merged PR info
|
||||
id: get-pr
|
||||
run: |
|
||||
COMMIT_SHA="${{ github.sha }}"
|
||||
|
||||
PR_NUMBER=$(gh pr list --state merged --limit 50 --json number,mergeCommit \
|
||||
--jq ".[] | select(.mergeCommit.oid == \"$COMMIT_SHA\") | .number")
|
||||
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
|
||||
echo "Found merged PR: #$PR_NUMBER"
|
||||
else
|
||||
echo "pr_number=" >> $GITHUB_OUTPUT
|
||||
echo "No merged PR found for this commit"
|
||||
fi
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Check for tag directive in merged PR
|
||||
if: steps.get-pr.outputs.pr_number != ''
|
||||
id: check-tag
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const prNumber = '${{ steps.get-pr.outputs.pr_number }}';
|
||||
|
||||
if (!prNumber) {
|
||||
console.log('No PR number found');
|
||||
core.setOutput('tag_found', 'false');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { data: pr } = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: parseInt(prNumber)
|
||||
});
|
||||
|
||||
const prBody = pr.body || '';
|
||||
console.log('PR Body:', prBody);
|
||||
|
||||
const tagRegex = /^\+tag\s+(v\d+\.\d+\.\d+(?:-[a-zA-Z0-9]+)?)/m;
|
||||
|
||||
const match = prBody.match(tagRegex);
|
||||
|
||||
if (match) {
|
||||
const tagVersion = match[1];
|
||||
console.log('Found tag directive:', tagVersion);
|
||||
|
||||
core.setOutput('tag_found', 'true');
|
||||
core.setOutput('tag_version', tagVersion);
|
||||
} else {
|
||||
console.log('No tag directive found in merged PR');
|
||||
core.setOutput('tag_found', 'false');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching PR:', error);
|
||||
core.setOutput('tag_found', 'false');
|
||||
}
|
||||
|
||||
- name: Check if tag already exists
|
||||
if: steps.check-tag.outputs.tag_found == 'true'
|
||||
id: check-existing-tag
|
||||
run: |
|
||||
TAG="${{ steps.check-tag.outputs.tag_version }}"
|
||||
|
||||
if git tag -l | grep -q "^$TAG$"; then
|
||||
echo "tag_exists=true" >> $GITHUB_OUTPUT
|
||||
echo "Tag $TAG already exists"
|
||||
else
|
||||
echo "tag_exists=false" >> $GITHUB_OUTPUT
|
||||
echo "Tag $TAG does not exist, safe to create"
|
||||
fi
|
||||
|
||||
- name: Create tag
|
||||
if: steps.check-tag.outputs.tag_found == 'true' && steps.check-existing-tag.outputs.tag_exists == 'false'
|
||||
run: |
|
||||
TAG="${{ steps.check-tag.outputs.tag_version }}"
|
||||
PR_NUMBER="${{ steps.get-pr.outputs.pr_number }}"
|
||||
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
git tag -a "$TAG" -m "Auto-created tag $TAG from PR #$PR_NUMBER"
|
||||
git push origin "$TAG"
|
||||
|
||||
echo "Created and pushed tag: $TAG"
|
||||
|
||||
- name: Comment on merged PR
|
||||
if: steps.check-tag.outputs.tag_found == 'true' && steps.check-existing-tag.outputs.tag_exists == 'false'
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const tagVersion = '${{ steps.check-tag.outputs.tag_version }}';
|
||||
const prNumber = '${{ steps.get-pr.outputs.pr_number }}';
|
||||
|
||||
const comment = `**Tag Created Successfully**
|
||||
|
||||
Tag \`${tagVersion}\` has been automatically created and pushed to the repository following the merge of this PR.
|
||||
|
||||
You can view the tag here: https://github.com/${{ github.repository }}/releases/tag/${tagVersion}`;
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: parseInt(prNumber),
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
|
||||
- name: Handle tag creation error
|
||||
if: steps.check-tag.outputs.tag_found == 'true' && steps.check-existing-tag.outputs.tag_exists == 'true'
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const tagVersion = '${{ steps.check-tag.outputs.tag_version }}';
|
||||
const prNumber = '${{ steps.get-pr.outputs.pr_number }}';
|
||||
const actionUrl = `${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}`;
|
||||
|
||||
const comment = `**Tag Creation Failed**
|
||||
|
||||
Could not create tag \`${tagVersion}\`.
|
||||
|
||||
Please refer to [this action run](${actionUrl}) for more information.`;
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: parseInt(prNumber),
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
96
.github/workflows/build-vsc-assets.yml
vendored
Normal file
96
.github/workflows/build-vsc-assets.yml
vendored
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
|
||||
name: tinymist::build::vsc_assets
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
target: x86_64-unknown-linux-gnu
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'yarn'
|
||||
- name: Install deps
|
||||
run: yarn install
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
- name: Download tinymist binary artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: artifacts-build-local-${{ env.target }}
|
||||
path: prebuilts
|
||||
- name: Unzip tinymist binary artifact (Windows)
|
||||
run: 7z x -y -oprebuilts prebuilts/tinymist-${{ env.target }}.zip
|
||||
if: contains(env.target, 'windows')
|
||||
- name: Unzip tinymist binary artifact (Linux)
|
||||
run: |
|
||||
tar -xvf prebuilts/tinymist-${{ env.target }}.tar.gz -C prebuilts
|
||||
mv prebuilts/tinymist-${{ env.target }}/tinymist prebuilts/tinymist
|
||||
if: ${{ !contains(env.target, 'windows') }}
|
||||
- name: Download font assets
|
||||
# use fonts in stable releases
|
||||
run: |
|
||||
mkdir -p assets/fonts/
|
||||
curl -L https://github.com/Myriad-Dreamin/shiroa/releases/download/v0.1.2/font-assets.tar.gz | tar -xvz -C assets/fonts
|
||||
curl -L https://github.com/Myriad-Dreamin/shiroa/releases/download/v0.1.0/charter-font-assets.tar.gz | tar -xvz -C assets/fonts
|
||||
curl -L https://github.com/Myriad-Dreamin/shiroa/releases/download/v0.1.5/source-han-serif-font-assets.tar.gz | tar -xvz -C assets/fonts
|
||||
- name: Download & install shiroa
|
||||
run: |
|
||||
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/Myriad-Dreamin/shiroa/releases/download/v0.3.1-rc3/shiroa-installer.sh | sh
|
||||
- name: Build Book
|
||||
run: |
|
||||
shiroa build --font-path ./assets/typst-fonts/ --font-path ./assets/fonts/ --path-to-root /tinymist/ -w . docs/tinymist --mode=static-html
|
||||
- name: Build PDF Documentation
|
||||
run: |
|
||||
prebuilts/tinymist compile --font-path assets/fonts --root . docs/tinymist/ebook.typ tinymist-docs.pdf
|
||||
# todo: this is a bug
|
||||
- name: Install PDF Documentation
|
||||
run: |
|
||||
mkdir -p editors/vscode/out/ contrib/html/editors/vscode/out/
|
||||
cp tinymist-docs.pdf editors/vscode/out/tinymist-docs.pdf
|
||||
cp tinymist-docs.pdf contrib/html/editors/vscode/out/tinymist-docs.pdf
|
||||
- name: Upload PDF Documentation
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-docs.pdf
|
||||
path: tinymist-docs.pdf
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Build typst-preview vscode extension
|
||||
run: |
|
||||
yarn
|
||||
yarn run compile
|
||||
working-directory: ./contrib/typst-preview/editors/vscode
|
||||
- name: Build tinymist vscode extension
|
||||
run: |
|
||||
yarn
|
||||
yarn run compile
|
||||
working-directory: ./editors/vscode
|
||||
|
||||
- name: Pre-bundle tinymist vscode extension
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: vscode-artifacts-tinymist
|
||||
path: editors/vscode/out
|
||||
- name: Pre-bundle tinymist vscode extension (L10n)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: vscode-artifacts-tinymist-l10n
|
||||
path: |
|
||||
editors/vscode/l10n/**/*
|
||||
editors/vscode/package.nls.json
|
||||
editors/vscode/package.nls.*.json
|
||||
- name: Pre-bundle typst-preview vscode extension
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: vscode-artifacts-typst-preview
|
||||
path: contrib/typst-preview/editors/vscode/out
|
||||
|
||||
181
.github/workflows/build-vscode-main.yml
vendored
Normal file
181
.github/workflows/build-vscode-main.yml
vendored
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
name: tinymist::build::vscode::main
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-latest
|
||||
rust-target: x86_64-pc-windows-msvc
|
||||
platform: win32
|
||||
arch: x64
|
||||
regular_build: 'true'
|
||||
- os: windows-latest
|
||||
rust-target: aarch64-pc-windows-msvc
|
||||
platform: win32
|
||||
arch: arm64
|
||||
- os: ubuntu-22.04
|
||||
rust-target: x86_64-unknown-linux-gnu
|
||||
platform: linux
|
||||
arch: x64
|
||||
regular_build: 'true'
|
||||
- os: ubuntu-22.04
|
||||
rust-target: aarch64-unknown-linux-gnu
|
||||
platform: linux
|
||||
arch: arm64
|
||||
- os: ubuntu-22.04
|
||||
rust-target: arm-unknown-linux-gnueabihf
|
||||
platform: linux
|
||||
arch: armhf
|
||||
- os: macos-14
|
||||
rust-target: x86_64-apple-darwin
|
||||
platform: darwin
|
||||
arch: x64
|
||||
- os: macos-14
|
||||
rust-target: aarch64-apple-darwin
|
||||
platform: darwin
|
||||
arch: arm64
|
||||
regular_build: 'true'
|
||||
name: build (${{ matrix.platform }}-${{ matrix.arch }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
target: ${{ matrix.platform }}-${{ matrix.arch }}
|
||||
isRelease: ${{ (startsWith(github.ref, 'refs/tags/') && (!contains(github.ref, 'rc') && (endsWith(github.ref, '0') || endsWith(github.ref, '2') || endsWith(github.ref, '4') || endsWith(github.ref, '6') || endsWith(github.ref, '8')))) }}
|
||||
isNightly: ${{ ((startsWith(github.ref, 'refs/tags/') && !((!contains(github.ref, 'rc') && (endsWith(github.ref, '0') || endsWith(github.ref, '2') || endsWith(github.ref, '4') || endsWith(github.ref, '6') || endsWith(github.ref, '8'))))) || (!startsWith(github.ref, 'refs/tags/') && matrix.regular_build == 'true')) }}
|
||||
isTest: ${{ matrix.rust-target == 'x86_64-unknown-linux-gnu' || matrix.rust-target == 'x86_64-pc-windows-msvc' }}
|
||||
isUniversal: ${{ matrix.rust-target == 'x86_64-unknown-linux-gnu' }}
|
||||
steps:
|
||||
- name: "Print Env"
|
||||
run: |
|
||||
echo "Running on ${{ matrix.os }}"
|
||||
echo "Target: ${{ env.target }}"
|
||||
echo "Is Release: ${{ fromJson(env.isRelease) }}"
|
||||
echo "Is Nightly: ${{ fromJson(env.isNightly) }}"
|
||||
echo "Is Test: ${{ fromJson(env.isTest) }}"
|
||||
echo "Is Universal (No Server): ${{ fromJson(env.isUniversal) }}"
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
if: (fromJson(env.isRelease) || fromJson(env.isNightly))
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'yarn'
|
||||
if: (fromJson(env.isRelease) || fromJson(env.isNightly))
|
||||
- name: Install deps
|
||||
run: yarn install
|
||||
if: (fromJson(env.isRelease) || fromJson(env.isNightly))
|
||||
|
||||
- name: Download tinymist binary artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: artifacts-build-local-${{ matrix.rust-target }}
|
||||
path: prebuilts
|
||||
if: (fromJson(env.isRelease) || fromJson(env.isNightly))
|
||||
- name: Unzip tinymist binary artifact (Windows)
|
||||
run: 7z x -y -oprebuilts prebuilts/tinymist-${{ matrix.rust-target }}.zip
|
||||
if: matrix.platform == 'win32' && (fromJson(env.isRelease) || fromJson(env.isNightly))
|
||||
- name: Unzip tinymist binary artifact (Linux)
|
||||
run: |
|
||||
tar -xvf prebuilts/tinymist-${{ matrix.rust-target }}.tar.gz -C prebuilts
|
||||
mv prebuilts/tinymist-${{ matrix.rust-target }}/tinymist prebuilts/tinymist
|
||||
if: matrix.platform != 'win32' && (fromJson(env.isRelease) || fromJson(env.isNightly))
|
||||
|
||||
- name: Download VSC Assets
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: vscode-artifacts-tinymist
|
||||
path: editors/vscode/out
|
||||
if: (fromJson(env.isRelease) || fromJson(env.isNightly))
|
||||
- name: Download VSC Assets (L10n)
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: vscode-artifacts-tinymist-l10n
|
||||
path: editors/vscode
|
||||
if: (fromJson(env.isRelease) || fromJson(env.isNightly))
|
||||
- name: Download VSC Assets (Preview)
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: vscode-artifacts-typst-preview
|
||||
path: contrib/typst-preview/editors/vscode/out
|
||||
if: (fromJson(env.isRelease) || fromJson(env.isNightly))
|
||||
|
||||
- name: Copy binary to output directory
|
||||
if: (fromJson(env.isRelease) || fromJson(env.isNightly))
|
||||
run: |
|
||||
cp "prebuilts/tinymist${{ ( matrix.platform == 'win32' ) && '.exe' || '' }}" "editors/vscode/out/"
|
||||
cp "prebuilts/tinymist${{ ( matrix.platform == 'win32' ) && '.exe' || '' }}" "contrib/typst-preview/editors/vscode/out/"
|
||||
cp "prebuilts/tinymist${{ ( matrix.platform == 'win32' ) && '.exe' || '' }}" "tinymist-${{ env.target }}${{ ( matrix.platform == 'win32' ) && '.exe' || '' }}"
|
||||
|
||||
- name: Package typst-preview extension
|
||||
if: fromJson(env.isRelease)
|
||||
run: yarn run package -- --target ${{ env.target }} -o typst-preview-${{ env.target }}.vsix
|
||||
working-directory: ./contrib/typst-preview/editors/vscode
|
||||
- name: Package tinymist extension
|
||||
if: fromJson(env.isRelease)
|
||||
run: yarn run package -- --target ${{ env.target }} -o tinymist-${{ env.target }}.vsix
|
||||
working-directory: ./editors/vscode
|
||||
- name: Package typst-preview extension (Nightly)
|
||||
if: fromJson(env.isNightly)
|
||||
run: yarn run package -- --target ${{ env.target }} -o typst-preview-${{ env.target }}.vsix --pre-release
|
||||
working-directory: ./contrib/typst-preview/editors/vscode
|
||||
- name: Package tinymist extension (Nightly)
|
||||
if: fromJson(env.isNightly)
|
||||
run: yarn run package -- --target ${{ env.target }} -o tinymist-${{ env.target }}.vsix --pre-release
|
||||
working-directory: ./editors/vscode
|
||||
|
||||
- name: Upload binary artifact
|
||||
if: (fromJson(env.isRelease) || fromJson(env.isNightly))
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-${{ env.target }}
|
||||
path: tinymist-${{ env.target }}${{ fromJSON('["", ".exe"]')[matrix.platform == 'win32'] }}
|
||||
- name: Upload typst-preview VSIX artifact
|
||||
if: (fromJson(env.isRelease) || fromJson(env.isNightly))
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: typst-preview-${{ env.target }}.vsix
|
||||
path: contrib/typst-preview/editors/vscode/typst-preview-${{ env.target }}.vsix
|
||||
- name: Upload VSIX artifact
|
||||
if: (fromJson(env.isRelease) || fromJson(env.isNightly))
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-${{ env.target }}.vsix
|
||||
path: editors/vscode/tinymist-${{ env.target }}.vsix
|
||||
|
||||
- name: Test tinymist extension
|
||||
uses: coactions/setup-xvfb@v1
|
||||
with:
|
||||
run: yarn test
|
||||
working-directory: ./editors/vscode
|
||||
if: (fromJson(env.isRelease) || fromJson(env.isNightly)) && fromJson(env.isTest)
|
||||
- name: Upload Tinymist Testing log
|
||||
if: ${{ always() && ((fromJson(env.isRelease) || fromJson(env.isNightly)) && fromJson(env.isTest))}}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-lsp-tests.${{ env.target }}.log
|
||||
path: editors/vscode/e2e-workspaces/simple-docs/tinymist-lsp.log
|
||||
|
||||
# The universal target doesn't bundle the binary. Users of that must install
|
||||
# tinymist by themselves.
|
||||
- name: Remove server binary
|
||||
if: fromJson(env.isUniversal)
|
||||
run: rm "editors/vscode/out/tinymist"
|
||||
- name: Package extension (Universal)
|
||||
if: fromJson(env.isRelease) && fromJson(env.isUniversal)
|
||||
run: yarn run package -- -o tinymist-universal.vsix
|
||||
working-directory: ./editors/vscode
|
||||
- name: Package extension (Universal, Nightly)
|
||||
if: fromJson(env.isNightly) && fromJson(env.isUniversal)
|
||||
run: yarn run package -- -o tinymist-universal.vsix --pre-release
|
||||
working-directory: ./editors/vscode
|
||||
- name: Upload tinymist VSIX artifact (Universal)
|
||||
if: (fromJson(env.isRelease) || fromJson(env.isNightly)) && fromJson(env.isUniversal)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-universal.vsix
|
||||
path: editors/vscode/tinymist-universal.vsix
|
||||
188
.github/workflows/build-vscode-others.yml
vendored
Normal file
188
.github/workflows/build-vscode-others.yml
vendored
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
|
||||
name: tinymist::build::vscode::others
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
RUSTFLAGS: '-Dwarnings'
|
||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
||||
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
|
||||
|
||||
jobs:
|
||||
build_alpine:
|
||||
name: build extension (alpine-${{ matrix.arch }})
|
||||
runs-on: ${{ matrix.runner }}
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
container:
|
||||
image: rust:alpine
|
||||
volumes:
|
||||
- /usr/local/cargo/registry:/usr/local/cargo/registry
|
||||
- /opt:/opt:rw,rshared
|
||||
- /opt:/__e/node20:ro,rshared
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: x64
|
||||
target: alpine-x64
|
||||
RUST_TARGET: x86_64-unknown-linux-musl
|
||||
runner: ubuntu-24.04
|
||||
- arch: arm64
|
||||
target: alpine-arm64
|
||||
RUST_TARGET: aarch64-unknown-linux-musl
|
||||
runner: ubuntu-24.04-arm
|
||||
env:
|
||||
target: ${{ matrix.target }}
|
||||
RUST_TARGET: ${{ matrix.RUST_TARGET }}
|
||||
RUSTFLAGS: "-Dwarnings -C link-arg=-fuse-ld=lld -C target-feature=-crt-static"
|
||||
isRelease: ${{ (startsWith(github.ref, 'refs/tags/') && (!contains(github.ref, 'rc') && (endsWith(github.ref, '0') || endsWith(github.ref, '2') || endsWith(github.ref, '4') || endsWith(github.ref, '6') || endsWith(github.ref, '8')))) }}
|
||||
isNightly: ${{ ((startsWith(github.ref, 'refs/tags/') && !((!contains(github.ref, 'rc') && (endsWith(github.ref, '0') || endsWith(github.ref, '2') || endsWith(github.ref, '4') || endsWith(github.ref, '6') || endsWith(github.ref, '8')))))) }}
|
||||
steps:
|
||||
- name: Allow Linux musl containers on ARM64 runners
|
||||
if: matrix.runner == 'ubuntu-24.04-arm'
|
||||
run: |
|
||||
sed -i "/^ID=/s/alpine/NotpineForGHA/" /etc/os-release
|
||||
apk add nodejs --update-cache
|
||||
mkdir /opt/bin
|
||||
ln -s /usr/bin/node /opt/bin/node
|
||||
|
||||
- name: Install dependencies
|
||||
# bash is required by setup-rust-toolchain
|
||||
run: apk add --no-cache git clang lld musl-dev nodejs-current npm yarn binutils bash
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
- name: Install deps
|
||||
run: yarn install
|
||||
- name: Build typst-preview vscode extension
|
||||
run: yarn run compile
|
||||
working-directory: ./contrib/typst-preview/editors/vscode
|
||||
- name: Build tinymist vscode extension
|
||||
run: yarn run compile
|
||||
working-directory: ./editors/vscode
|
||||
- name: Build tinymist binary
|
||||
run: |
|
||||
cargo build --profile=gh-release --bin tinymist --target $RUST_TARGET
|
||||
- name: Split debug symbols
|
||||
run: |
|
||||
cd target/$RUST_TARGET/gh-release
|
||||
objcopy --compress-debug-sections --only-keep-debug "tinymist" "tinymist-${{ env.target }}.debug"
|
||||
objcopy --strip-debug --add-gnu-debuglink="tinymist-${{ env.target }}.debug" "tinymist"
|
||||
- name: Upload split debug symbols
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-${{ env.target }}.debug
|
||||
path: target/${{ env.RUST_TARGET }}/gh-release/tinymist-${{ env.target }}.debug
|
||||
- name: Copy binary to output directory
|
||||
run: |
|
||||
mkdir -p editors/vscode/out
|
||||
cp "target/${{ env.RUST_TARGET }}/gh-release/tinymist" "editors/vscode/out/"
|
||||
cp "target/${{ env.RUST_TARGET }}/gh-release/tinymist" "contrib/typst-preview/editors/vscode/out/"
|
||||
cp "target/${{ env.RUST_TARGET }}/gh-release/tinymist" "tinymist-${{ env.target }}"
|
||||
- name: Upload binary artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-${{ env.target }}
|
||||
path: tinymist-${{ env.target }}
|
||||
|
||||
- name: Download PDF Documentation
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: tinymist-docs.pdf
|
||||
if: (fromJson(env.isRelease) || fromJson(env.isNightly))
|
||||
- name: Install PDF Documentation
|
||||
run: |
|
||||
mkdir -p editors/vscode/out/
|
||||
cp tinymist-docs.pdf editors/vscode/out/tinymist-docs.pdf
|
||||
if: (fromJson(env.isRelease) || fromJson(env.isNightly))
|
||||
|
||||
- name: Package typst-preview extension
|
||||
if: fromJson(env.isRelease)
|
||||
run: yarn run package -- --target ${{ env.target }} -o typst-preview-${{ env.target }}.vsix
|
||||
working-directory: ./contrib/typst-preview/editors/vscode
|
||||
- name: Package extension
|
||||
if: fromJson(env.isRelease)
|
||||
run: yarn run package -- --target ${{ env.target }} -o tinymist-${{ env.target }}.vsix
|
||||
working-directory: ./editors/vscode
|
||||
- name: Package typst-preview extension (Nightly)
|
||||
if: fromJson(env.isNightly)
|
||||
run: yarn run package -- --target ${{ env.target }} -o typst-preview-${{ env.target }}.vsix --pre-release
|
||||
working-directory: ./contrib/typst-preview/editors/vscode
|
||||
- name: Package extension (Nightly)
|
||||
if: fromJson(env.isNightly)
|
||||
run: yarn run package -- --target ${{ env.target }} -o tinymist-${{ env.target }}.vsix --pre-release
|
||||
working-directory: ./editors/vscode
|
||||
|
||||
- name: Upload typst-preview VSIX artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: typst-preview-${{ env.target }}.vsix
|
||||
path: contrib/typst-preview/editors/vscode/typst-preview-${{ env.target }}.vsix
|
||||
- name: Upload tinymist VSIX artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-${{ env.target }}.vsix
|
||||
path: editors/vscode/tinymist-${{ env.target }}.vsix
|
||||
|
||||
build_web:
|
||||
name: build extension (web)
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
target: web
|
||||
RUST_TARGET: wasm32-unknown-unknown
|
||||
isNightly: ${{ ((startsWith(github.ref, 'refs/tags/') && !((!contains(github.ref, 'rc') && (endsWith(github.ref, '0') || endsWith(github.ref, '2') || endsWith(github.ref, '4') || endsWith(github.ref, '6') || endsWith(github.ref, '8')))))) }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'yarn'
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
- uses: jetli/wasm-pack-action@v0.4.0
|
||||
with:
|
||||
version: "v0.13.1"
|
||||
- name: Install deps
|
||||
run: yarn install
|
||||
- name: Build tinymist library
|
||||
run: yarn build:web
|
||||
working-directory: .
|
||||
- name: Pack tinymist npm library
|
||||
run: |
|
||||
npm pack > package-name
|
||||
mv $(cat package-name) tinymist-${{ env.target }}.tar.gz
|
||||
working-directory: ./crates/tinymist
|
||||
- name: Upload tinymist npm library
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-${{ env.target }}-npm
|
||||
path: crates/tinymist/tinymist-${{ env.target }}.tar.gz
|
||||
|
||||
- name: Download PDF Documentation
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: tinymist-docs.pdf
|
||||
- name: Install PDF Documentation
|
||||
run: |
|
||||
mkdir -p editors/vscode/out/
|
||||
cp tinymist-docs.pdf editors/vscode/out/tinymist-docs.pdf
|
||||
|
||||
- name: Package extension
|
||||
if: '!fromJson(env.isNightly)'
|
||||
run: yarn run package -- --target ${{ env.target }} -o tinymist-${{ env.target }}.vsix
|
||||
working-directory: ./editors/vscode
|
||||
- name: Package extension (Nightly)
|
||||
if: fromJson(env.isNightly)
|
||||
run: yarn run package -- --target ${{ env.target }} -o tinymist-${{ env.target }}.vsix --pre-release
|
||||
working-directory: ./editors/vscode
|
||||
|
||||
- name: Upload tinymist VSIX artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-${{ env.target }}.vsix
|
||||
path: editors/vscode/tinymist-${{ env.target }}.vsix
|
||||
91
.github/workflows/build-vscode.yml
vendored
Normal file
91
.github/workflows/build-vscode.yml
vendored
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
name: tinymist::build::vscode
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
plan:
|
||||
description: 'A description of the plan input'
|
||||
required: true # or false, depending on whether the input is mandatory
|
||||
type: string # or other appropriate type like boolean, number, etc.
|
||||
|
||||
env:
|
||||
RUSTFLAGS: '-Dwarnings'
|
||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
||||
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
|
||||
|
||||
jobs:
|
||||
build-vsc-assets:
|
||||
uses: ./.github/workflows/build-vsc-assets.yml
|
||||
|
||||
build-vscode-main:
|
||||
needs: [build-vsc-assets]
|
||||
uses: ./.github/workflows/build-vscode-main.yml
|
||||
|
||||
build-vscode-others:
|
||||
needs: [build-vsc-assets]
|
||||
uses: ./.github/workflows/build-vscode-others.yml
|
||||
|
||||
release:
|
||||
needs: [build-vscode-main, build-vscode-others] # , announce
|
||||
runs-on: ubuntu-latest
|
||||
if: success() && startsWith(github.ref, 'refs/tags/')
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
pattern: '{tinymist,typst-preview}-*'
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R artifacts
|
||||
- uses: ncipollo/release-action@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
artifacts: "artifacts/*/*"
|
||||
allowUpdates: true
|
||||
omitBodyDuringUpdate: true
|
||||
omitDraftDuringUpdate: true
|
||||
omitNameDuringUpdate: true
|
||||
omitPrereleaseDuringUpdate: true
|
||||
|
||||
publish:
|
||||
needs: [build-vscode-main, build-vscode-others] # , announce
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
isRelease: ${{ (startsWith(github.ref, 'refs/tags/') && (!contains(github.ref, 'rc') && (endsWith(github.ref, '0') || endsWith(github.ref, '2') || endsWith(github.ref, '4') || endsWith(github.ref, '6') || endsWith(github.ref, '8')))) }}
|
||||
isNightly: ${{ ((startsWith(github.ref, 'refs/tags/') && !((!contains(github.ref, 'rc') && (endsWith(github.ref, '0') || endsWith(github.ref, '2') || endsWith(github.ref, '4') || endsWith(github.ref, '6') || endsWith(github.ref, '8')))))) }}
|
||||
if: success() && startsWith(github.ref, 'refs/tags/') && !contains(github.ref, 'rc')
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: actions/download-artifact@v4
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'yarn'
|
||||
- name: Install deps
|
||||
run: yarn install
|
||||
- name: Deploy to VS Code Marketplace
|
||||
if: fromJson(env.isRelease)
|
||||
run: npx @vscode/vsce publish --packagePath $(find . -type f -iname 'tinymist-*.vsix') --skip-duplicate
|
||||
env:
|
||||
VSCE_PAT: ${{ secrets.VSCODE_MARKETPLACE_TOKEN }}
|
||||
- name: Deploy to OpenVSX
|
||||
if: fromJson(env.isRelease)
|
||||
run: npx ovsx publish --packagePath $(find . -type f -iname 'tinymist-*.vsix') --skip-duplicate
|
||||
env:
|
||||
OVSX_PAT: ${{ secrets.OPENVSX_ACCESS_TOKEN }}
|
||||
- name: Deploy to VS Code Marketplace (Nightly)
|
||||
if: fromJson(env.isNightly)
|
||||
run: npx @vscode/vsce publish --packagePath $(find . -type f -iname 'tinymist-*.vsix') --skip-duplicate --pre-release
|
||||
env:
|
||||
VSCE_PAT: ${{ secrets.VSCODE_MARKETPLACE_TOKEN }}
|
||||
- name: Deploy to OpenVSX (Nightly)
|
||||
if: fromJson(env.isNightly)
|
||||
run: npx ovsx publish --packagePath $(find . -type f -iname 'tinymist-*.vsix') --skip-duplicate --pre-release
|
||||
env:
|
||||
OVSX_PAT: ${{ secrets.OPENVSX_ACCESS_TOKEN }}
|
||||
67
.github/workflows/ci-check-e2e.yml
vendored
Normal file
67
.github/workflows/ci-check-e2e.yml
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
name: tinymist::check-e2e
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
plan:
|
||||
description: 'A description of the plan input'
|
||||
required: true # or false, depending on whether the input is mandatory
|
||||
type: string # or other appropriate type like boolean, number, etc.
|
||||
|
||||
env:
|
||||
RUSTFLAGS: '-Dwarnings'
|
||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
||||
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
|
||||
|
||||
jobs:
|
||||
checks-e2e:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-2022
|
||||
rust-target: x86_64-pc-windows-msvc
|
||||
platform: win32
|
||||
arch: x64
|
||||
- os: windows-latest
|
||||
rust-target: x86_64-pc-windows-msvc
|
||||
platform: win32
|
||||
arch: x64
|
||||
- os: ubuntu-22.04
|
||||
rust-target: x86_64-unknown-linux-gnu
|
||||
platform: linux
|
||||
arch: x64
|
||||
- os: ubuntu-latest
|
||||
rust-target: x86_64-unknown-linux-gnu
|
||||
platform: linux
|
||||
arch: x64
|
||||
- os: macos-latest
|
||||
rust-target: aarch64-apple-darwin
|
||||
platform: darwin
|
||||
arch: arm64
|
||||
name: E2E Tests (${{ matrix.platform }}-${{ matrix.arch }} on ${{ matrix.os }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Download tinymist binary artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: artifacts-build-local-${{ matrix.rust-target }}
|
||||
path: editors/vscode/out
|
||||
- name: Unzip tinymist binary artifact (Windows)
|
||||
run: 7z x -y -oeditors/vscode/out editors/vscode/out/tinymist-${{ matrix.rust-target }}.zip
|
||||
if: matrix.platform == 'win32'
|
||||
- name: Unzip tinymist binary artifact (Linux)
|
||||
run: |
|
||||
tar -xvf editors/vscode/out/tinymist-${{ matrix.rust-target }}.tar.gz -C editors/vscode/out
|
||||
mv editors/vscode/out/tinymist-${{ matrix.rust-target }}/tinymist editors/vscode/out/tinymist
|
||||
if: matrix.platform != 'win32'
|
||||
- name: Test GLIBC
|
||||
run: node ./scripts/test-glibc.mjs editors/vscode/out/tinymist
|
||||
if: matrix.platform != 'win32'
|
||||
- name: Test Tinymist (E2E)
|
||||
run: cargo test -p tests -- e2e
|
||||
- name: Upload Tinymist E2E Test Snapshot
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: e2e-snapshot-${{ matrix.rust-target }}-${{ matrix.os }}
|
||||
path: target/e2e
|
||||
138
.github/workflows/ci.yml
vendored
Normal file
138
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
name: tinymist::ci
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- nightly
|
||||
tags:
|
||||
- "*"
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
branches:
|
||||
- main
|
||||
- nightly
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
RUSTFLAGS: '-Dwarnings'
|
||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
||||
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
|
||||
|
||||
jobs:
|
||||
pre_build:
|
||||
permissions:
|
||||
actions: write
|
||||
contents: read
|
||||
name: Duplicate Actions Detection
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||
steps:
|
||||
- id: skip_check
|
||||
uses: fkirc/skip-duplicate-actions@v5
|
||||
with:
|
||||
cancel_others: "true"
|
||||
|
||||
checks-linux:
|
||||
name: Check Clippy, Formatting, Completion, Documentation, and Tests (Linux)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: typst-community/setup-typst@v4
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
components: clippy, rustfmt
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'yarn'
|
||||
- name: Install deps
|
||||
run: yarn install
|
||||
- name: Check and build assets
|
||||
run: |
|
||||
yarn build:preview
|
||||
yarn build:l10n
|
||||
- run: cargo clippy --workspace --all-targets
|
||||
- run: scripts/feature-testing.sh
|
||||
- run: cargo fmt --check --all
|
||||
- run: cargo doc --workspace --no-deps
|
||||
- run: yarn build:typlite
|
||||
- run: node ./scripts/link-docs.mjs --check
|
||||
- name: Generate completions
|
||||
run: |
|
||||
mkdir -p completions/{zsh,bash,fish/vendor_completions.d,elvish/lib,nushell/vendor/autoload,powershell}/
|
||||
cargo run --bin tinymist -- completion zsh > completions/zsh/_tinymist
|
||||
cargo run --bin tinymist -- completion bash > completions/bash/tinymist
|
||||
cargo run --bin tinymist -- completion fish > completions/fish/vendor_completions.d/tinymist.fish
|
||||
cargo run --bin tinymist -- completion elvish > completions/elvish/lib/tinymist.elv
|
||||
cargo run --bin tinymist -- completion nushell > completions/nushell/vendor/autoload/tinymist.nu
|
||||
cargo run --bin tinymist -- completion powershell > completions/powershell/tinymist.ps1
|
||||
tar -czvf tinymist-completions.tar.gz completions
|
||||
- name: upload completions
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-completion-scripts
|
||||
path: tinymist-completions.tar.gz
|
||||
- name: Test tinymist
|
||||
run: cargo test --workspace -- --skip=e2e
|
||||
- name: Test Lockfile (Prepare)
|
||||
run: ./scripts/test-lock.sh
|
||||
- name: Test Lockfile (Check)
|
||||
run: cargo test --package tinymist --lib -- route::tests --show-output --ignored
|
||||
|
||||
checks-windows:
|
||||
name: Check Minimum Rust version and Tests (Windows)
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
toolchain: 1.89.0 # check-min-version
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
- name: Install deps
|
||||
run: yarn install
|
||||
- name: Check Rust Version
|
||||
run: yarn check-msrv
|
||||
- name: Check and build assets
|
||||
run: |
|
||||
yarn build:preview
|
||||
yarn build:l10n
|
||||
- run: cargo check --workspace
|
||||
- name: Test tinymist
|
||||
run: cargo test --workspace -- --skip=e2e
|
||||
|
||||
prepare-build:
|
||||
runs-on: "ubuntu-latest"
|
||||
outputs:
|
||||
tag: ${{ steps.tag.outputs.tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- id: tag # get the tag from package.json
|
||||
run:
|
||||
echo "tag=v$(jq -r '.version' editors/vscode/package.json)" >> $GITHUB_OUTPUT
|
||||
- name: Show tag
|
||||
run: echo "Tag is ${{ steps.tag.outputs.tag }}"
|
||||
|
||||
announce:
|
||||
needs: [prepare-build]
|
||||
permissions:
|
||||
contents: write
|
||||
uses: ./.github/workflows/announce.yml
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
secrets: inherit
|
||||
with:
|
||||
tag: ${{ needs.prepare-build.outputs.tag }}
|
||||
|
||||
build:
|
||||
needs: [prepare-build] # , announce
|
||||
permissions:
|
||||
contents: write
|
||||
uses: ./.github/workflows/release.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
tag: ${{ (startsWith(github.ref, 'refs/tags/') && needs.prepare-build.outputs.tag) || '' }}
|
||||
targets: ${{ (!startsWith(github.ref, 'refs/tags/') && 'aarch64-apple-darwin,x86_64-pc-windows-msvc,x86_64-unknown-linux-gnu') || 'all' }}
|
||||
62
.github/workflows/detect-pr-tag.yml
vendored
Normal file
62
.github/workflows/detect-pr-tag.yml
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
name: tinymist::detect_pr_tag
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited]
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
detect-tag:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check tag in PR body
|
||||
id: check-tag
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const prBody = context.payload.pull_request.body || '';
|
||||
console.log('PR Body:', prBody);
|
||||
|
||||
const tagRegex = /^\+tag\s+(v\d+\.\d+\.\d+(?:-[a-zA-Z0-9]+)?)/m;
|
||||
const match = prBody.match(tagRegex);
|
||||
|
||||
if (match) {
|
||||
const tagVersion = match[1];
|
||||
console.log('Found tag:', tagVersion);
|
||||
|
||||
core.setOutput('tag_found', 'true');
|
||||
core.setOutput('tag_version', tagVersion);
|
||||
} else {
|
||||
console.log('No tag found in PR description');
|
||||
core.setOutput('tag_found', 'false');
|
||||
}
|
||||
|
||||
- name: Comment on PR
|
||||
if: steps.check-tag.outputs.tag_found == 'true'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const tagVersion = '${{ steps.check-tag.outputs.tag_version }}';
|
||||
const comment = `**Tag Detection Notice**
|
||||
|
||||
This PR contains a tag directive: \`+tag ${tagVersion}\`
|
||||
|
||||
If this PR is merged, it will automatically create tag \`${tagVersion}\` on the main branch.
|
||||
|
||||
Please ensure before merging:
|
||||
- [ ] **Cargo.toml & Cargo.lock**: No \`git\` dependencies with \`branch\`, use \`tag\` or \`rev\` dependencies instead
|
||||
- [ ] **Publish tokens**: Both \`VSCODE_MARKETPLACE_TOKEN\` and \`OPENVSX_ACCESS_TOKEN\` are valid and not expired
|
||||
- [ ] **Version updates**: All version numbers in \`Cargo.toml\`, \`package.json\` and other files have been updated consistently
|
||||
- [ ] **Changelog**: \`editors/vscode/CHANGELOG.md\` has been updated with correct format
|
||||
- [ ] **tinymist-assets**: If needed, the crate has been published and version updated in \`Cargo.toml\`
|
||||
`
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
79
.github/workflows/gh-pages.yml
vendored
Normal file
79
.github/workflows/gh-pages.yml
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
name: tinymist::gh_pages
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
||||
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
|
||||
concurrency:
|
||||
group: 'pages'
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
build-gh-pages:
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- run: git submodule update --init --recursive
|
||||
- name: Make directories
|
||||
run: |
|
||||
if [ ! -d "${XDG_DATA_HOME:-$HOME/.local/share}" ]; then
|
||||
echo "Creating data directory: ${XDG_DATA_HOME:-$HOME/.local/share}"
|
||||
mkdir -p ${XDG_DATA_HOME:-$HOME/.local/share}
|
||||
else
|
||||
echo "Data directory already exists: ${XDG_DATA_HOME:-$HOME/.local/share}"
|
||||
fi
|
||||
if [ ! -d "${XDG_CACHE_HOME:-$HOME/.cache}" ]; then
|
||||
echo "Creating cache directory: ${XDG_CACHE_HOME:-$HOME/.cache}"
|
||||
mkdir -p ${XDG_CACHE_HOME:-$HOME/.cache}
|
||||
else
|
||||
echo "Cache directory already exists: ${XDG_CACHE_HOME:-$HOME/.cache}"
|
||||
fi
|
||||
- name: Download font assets
|
||||
# use fonts in stable releases
|
||||
run: |
|
||||
mkdir -p assets/fonts/
|
||||
curl -L https://github.com/Myriad-Dreamin/shiroa/releases/download/v0.1.2/font-assets.tar.gz | tar -xvz -C assets/fonts
|
||||
curl -L https://github.com/Myriad-Dreamin/shiroa/releases/download/v0.1.0/charter-font-assets.tar.gz | tar -xvz -C assets/fonts
|
||||
curl -L https://github.com/Myriad-Dreamin/shiroa/releases/download/v0.1.5/source-han-serif-font-assets.tar.gz | tar -xvz -C assets/fonts
|
||||
- name: Download & install shiroa
|
||||
run: |
|
||||
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/Myriad-Dreamin/shiroa/releases/download/v0.3.1-rc3/shiroa-installer.sh | sh
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'yarn'
|
||||
- name: Install deps
|
||||
run: yarn install
|
||||
- name: Build Preview Html
|
||||
run: |
|
||||
yarn build:preview
|
||||
- name: Build Book
|
||||
run: |
|
||||
shiroa build --font-path ./assets/typst-fonts/ --font-path ./assets/fonts/ --path-to-root /tinymist/ -w . docs/tinymist --mode=static-html
|
||||
- name: Build Cargo Docs
|
||||
run: |
|
||||
cargo doc --workspace --no-deps
|
||||
cp -r target/doc dist/tinymist/rs
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v5
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
# Upload `/github-pages` sub directory
|
||||
path: './dist/tinymist'
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
59
.github/workflows/lint-pr-title.yml
vendored
Normal file
59
.github/workflows/lint-pr-title.yml
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
name: tinymist::lint_pr_title
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, synchronize]
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
main:
|
||||
name: Validate PR title
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v5
|
||||
id: lint_pr_title
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
# Configure which types are allowed (newline-delimited).
|
||||
# Default: https://github.com/commitizen/conventional-commit-types
|
||||
# extraType: dev: internal development
|
||||
types: |
|
||||
dev
|
||||
feat
|
||||
fix
|
||||
docs
|
||||
style
|
||||
refactor
|
||||
perf
|
||||
test
|
||||
build
|
||||
ci
|
||||
chore
|
||||
revert
|
||||
ignoreLabels: |
|
||||
bot
|
||||
ignore-semantic-pull-request
|
||||
- uses: marocchino/sticky-pull-request-comment@v2
|
||||
# When the previous steps fails, the workflow would stop. By adding this
|
||||
# condition you can continue the execution with the populated error message.
|
||||
if: always() && (steps.lint_pr_title.outputs.error_message != null)
|
||||
with:
|
||||
header: pr-title-lint-error
|
||||
message: |
|
||||
Hey there and thank you for opening this pull request! 👋🏼
|
||||
|
||||
We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted.
|
||||
|
||||
Details:
|
||||
|
||||
```
|
||||
${{ steps.lint_pr_title.outputs.error_message }}
|
||||
```
|
||||
# Delete a previous comment when the issue has been resolved
|
||||
- if: ${{ steps.lint_pr_title.outputs.error_message == null }}
|
||||
uses: marocchino/sticky-pull-request-comment@v2
|
||||
with:
|
||||
header: pr-title-lint-error
|
||||
delete: true
|
||||
42
.github/workflows/release-asset-crate.yml
vendored
Normal file
42
.github/workflows/release-asset-crate.yml
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
name: tinymist::assets::publish
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
RUSTFLAGS: '-Dwarnings'
|
||||
|
||||
jobs:
|
||||
|
||||
publish-crates:
|
||||
name: build
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
cache: false
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'yarn'
|
||||
- name: Install llvm
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install llvm
|
||||
- name: Install deps
|
||||
run: yarn install
|
||||
- name: Check and build assets
|
||||
run: |
|
||||
yarn build:preview
|
||||
yarn build:l10n
|
||||
- name: Publish crates
|
||||
run: |
|
||||
cargo publish --allow-dirty --no-verify -p tinymist-assets || true
|
||||
- name: Verifies crate health (Optional)
|
||||
run: |
|
||||
cargo publish --allow-dirty --dry-run -p tinymist-assets
|
||||
72
.github/workflows/release-crates.yml
vendored
Normal file
72
.github/workflows/release-crates.yml
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
name: tinymist::crates::publish
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
RUSTFLAGS: '-Dwarnings'
|
||||
|
||||
jobs:
|
||||
|
||||
publish-crates:
|
||||
name: build
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
# https://github.com/dtolnay/rust-toolchain/issues/133
|
||||
# https://github.com/rust-lang/rustup/issues/3635
|
||||
# Only needed if your action will run two or more rust
|
||||
# commands concurrently, otherwise rustup will lazily
|
||||
# install your rust-toolchain.toml when needed:
|
||||
- name: 'Install from rust-toolchain.toml'
|
||||
run: rustup show
|
||||
- name: Install llvm
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install llvm
|
||||
- name: Publish crates
|
||||
run: |
|
||||
cargo publish --no-verify -p typst-shim || true
|
||||
cargo publish --no-verify -p tinymist-derive || true
|
||||
cargo publish --no-verify -p tinymist-l10n || true
|
||||
cargo publish --no-verify -p tinymist-std || true
|
||||
cargo publish --no-verify -p sync-ls || true
|
||||
cargo publish --no-verify -p tinymist-package || true
|
||||
cargo publish --no-verify -p tinymist-vfs || true
|
||||
cargo publish --no-verify -p tinymist-world || true
|
||||
cargo publish --no-verify -p tinymist-analysis || true
|
||||
cargo publish --no-verify -p tinymist-task || true
|
||||
cargo publish --no-verify -p tinymist-project || true
|
||||
cargo publish --no-verify -p typlite || true
|
||||
cargo publish --no-verify -p crityp || true
|
||||
|
||||
cargo publish --no-verify -p tinymist-debug || true
|
||||
cargo publish --no-verify -p tinymist-lint || true
|
||||
cargo publish --no-verify -p tinymist-query || true
|
||||
cargo publish --no-verify -p tinymist-render || true
|
||||
cargo publish --no-verify -p tinymist-preview || true
|
||||
cargo publish --no-verify -p tinymist || true
|
||||
cargo publish --no-verify -p tinymist-cli || true
|
||||
- name: Verifies crate health (Optional)
|
||||
run: |
|
||||
cargo publish --dry-run -p typst-shim
|
||||
cargo publish --dry-run -p tinymist-derive
|
||||
cargo publish --dry-run -p tinymist-l10n
|
||||
cargo publish --dry-run -p tinymist-std
|
||||
cargo publish --dry-run -p sync-ls
|
||||
cargo publish --dry-run -p tinymist-vfs
|
||||
cargo publish --dry-run -p tinymist-package
|
||||
cargo publish --dry-run -p tinymist-world
|
||||
cargo publish --dry-run -p tinymist-task --features no-content-hint
|
||||
cargo publish --dry-run -p tinymist-project --features no-content-hint
|
||||
cargo publish --dry-run -p typlite
|
||||
cargo publish --dry-run -p crityp
|
||||
# needs patched typst
|
||||
# cargo publish --dry-run -p tinymist-analysis
|
||||
|
||||
350
.github/workflows/release-nightly.yml
vendored
Normal file
350
.github/workflows/release-nightly.yml
vendored
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
name: Nightly Release
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
- cron: '0 23 * * *'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_type:
|
||||
description: 'Release type'
|
||||
required: true
|
||||
default: 'nightly'
|
||||
type: choice
|
||||
options:
|
||||
- nightly
|
||||
- canary
|
||||
|
||||
jobs:
|
||||
check-and-release:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: nightly
|
||||
token: ${{ secrets.REPO_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'yarn'
|
||||
- name: Install deps
|
||||
run: yarn install
|
||||
|
||||
- name: Setup Git
|
||||
run: |
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Determine release type
|
||||
id: release_type
|
||||
run: |
|
||||
if [[ "${{ github.event_name }}" == "schedule" ]]; then
|
||||
if [[ "${{ github.event.schedule }}" == "0 0 * * *" ]]; then
|
||||
echo "release_type=nightly" >> $GITHUB_ENV
|
||||
else
|
||||
echo "release_type=canary" >> $GITHUB_ENV
|
||||
fi
|
||||
else
|
||||
echo "release_type=${{ github.event.inputs.release_type }}" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Check for updates
|
||||
id: check_updates
|
||||
run: |
|
||||
echo "Checking for updates in dependency repositories..."
|
||||
|
||||
# Get current revs using script
|
||||
eval "$(node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . get-current-revs)"
|
||||
|
||||
# Get latest revs
|
||||
latest_typst_rev=$(curl -s "https://api.github.com/repos/ParaN3xus/typst/commits/nightly" | jq -r '.sha')
|
||||
latest_typst_content_hint_rev=$(curl -s "https://api.github.com/repos/ParaN3xus/typst/commits/nightly-content-hint" | jq -r '.sha')
|
||||
latest_reflexo_rev=$(curl -s "https://api.github.com/repos/ParaN3xus/typst.ts/commits/nightly" | jq -r '.sha')
|
||||
latest_typstyle_rev=$(curl -s "https://api.github.com/repos/ParaN3xus/typstyle/commits/nightly" | jq -r '.sha')
|
||||
latest_typst_ansi_hl_rev=$(curl -s "https://api.github.com/repos/ParaN3xus/typst-ansi-hl/commits/nightly" | jq -r '.sha')
|
||||
|
||||
echo "Current revs: typst=$current_typst_rev, typst.ts=$current_reflexo_rev, typstyle=$current_typstyle_rev, hl=$current_typst_ansi_hl_rev"
|
||||
echo "Latest revs: typst=$latest_typst_rev, typst.ts=$latest_reflexo_rev, typstyle=$latest_typstyle_rev, hl=$latest_typst_ansi_hl_rev"
|
||||
|
||||
# Check for updates
|
||||
need_update=false
|
||||
if [[ "$current_typst_rev" != "$latest_typst_rev" ]] || [[ -z "$current_typst_rev" ]]; then
|
||||
echo "Typst needs update"
|
||||
need_update=true
|
||||
fi
|
||||
if [[ "$current_reflexo_rev" != "$latest_reflexo_rev" ]] || [[ -z "$current_reflexo_rev" ]]; then
|
||||
echo "Typst.ts needs update"
|
||||
need_update=true
|
||||
fi
|
||||
if [[ "$current_typstyle_rev" != "$latest_typstyle_rev" ]] || [[ -z "$current_typstyle_rev" ]]; then
|
||||
echo "Typstyle needs update"
|
||||
need_update=true
|
||||
fi
|
||||
if [[ "$current_typst_ansi_hl_rev" != "$latest_typst_ansi_hl_rev" ]] || [[ -z "$current_typst_ansi_hl_rev" ]]; then
|
||||
echo "Typst-ansi-hl needs update"
|
||||
need_update=true
|
||||
fi
|
||||
|
||||
current_version=$(grep '^version = ' Cargo.toml | head -1 | cut -d'"' -f2)
|
||||
echo "current_version=$current_version" >> $GITHUB_ENV
|
||||
|
||||
# Updates can only be performed when releasing an RC.
|
||||
# When an RC has been released and there are no subsequent updates,
|
||||
# this indicates that the RC release was successful. Only at this
|
||||
# point will the nightly release be published.
|
||||
|
||||
need_release=false
|
||||
if [ "$release_type" = "nightly" ]; then
|
||||
if [ "$need_update" = "false" ] && echo "$current_version" | grep -q -- '-rc[0-9]\+$'; then
|
||||
echo "RC version detected with no updates needed, nightly release condition met"
|
||||
need_release=true
|
||||
else
|
||||
echo "Nightly release condition not met (requires stable RC version)"
|
||||
fi
|
||||
elif [ "$release_type" = "canary" ]; then
|
||||
if [ "$need_update" = "true" ]; then
|
||||
echo "Code updates detected, canary release condition met"
|
||||
need_release=true
|
||||
else
|
||||
echo "No code updates, skipping canary release"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Final decision: need_release=$need_release"
|
||||
|
||||
echo "need_release=$need_release" >> $GITHUB_OUTPUT
|
||||
echo "latest_typst_rev=$latest_typst_rev" >> $GITHUB_ENV
|
||||
echo "latest_typst_content_hint_rev=$latest_typst_content_hint_rev" >> $GITHUB_ENV
|
||||
|
||||
- name: Calculate new version
|
||||
id: version
|
||||
if: steps.check_updates.outputs.need_release == 'true'
|
||||
run: |
|
||||
echo "Current version: $current_version"
|
||||
echo "Release type: $release_type"
|
||||
|
||||
new_version=$(node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . calculate-version "$current_version" "$release_type")
|
||||
|
||||
echo "New version: $new_version"
|
||||
echo "new_version=$new_version" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
if: steps.check_updates.outputs.need_release == 'true'
|
||||
|
||||
- name: Get typst information
|
||||
id: typst_info
|
||||
if: steps.check_updates.outputs.need_release == 'true'
|
||||
run: |
|
||||
# Clone typst repository
|
||||
git clone --depth 50 --single-branch --branch nightly-content-hint \
|
||||
--filter=blob:limit=1k https://github.com/ParaN3xus/typst.git /tmp/typst
|
||||
cd /tmp/typst
|
||||
git checkout nightly-content-hint
|
||||
|
||||
# Get version
|
||||
typst_version=$(grep '^version = ' Cargo.toml | head -1 | cut -d'"' -f2)
|
||||
|
||||
typst_assets_rev=$(grep 'typst-assets.*git' Cargo.toml | grep 'rev = ' | cut -d'"' -f4)
|
||||
|
||||
echo "typst_version=$typst_version" >> $GITHUB_ENV
|
||||
echo "typst_assets_rev=$typst_assets_rev" >> $GITHUB_ENV
|
||||
|
||||
# Get base commit
|
||||
git remote add upstream https://github.com/typst/typst.git && git fetch upstream main --prune
|
||||
typst_base_commit=$(git merge-base HEAD upstream/main 2>/dev/null)
|
||||
typst_base_msg=$(git --no-pager log --format="%s" -1 $typst_base_commit)
|
||||
echo "typst_base_commit=$typst_base_commit" >> $GITHUB_ENV
|
||||
echo "typst_base_msg=$typst_base_msg" >> $GITHUB_ENV
|
||||
|
||||
- name: Update typst dependencies in tinymist
|
||||
if: steps.check_updates.outputs.need_release == 'true'
|
||||
run: |
|
||||
node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . update-typst-deps \
|
||||
"$typst_version" \
|
||||
"$typst_assets_rev"
|
||||
|
||||
revs_json=$(cat <<EOF
|
||||
{
|
||||
"typst": "${latest_typst_rev}"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . update-patch-revs "$revs_json"
|
||||
|
||||
- name: Bump world crates version
|
||||
if: steps.check_updates.outputs.need_release == 'true'
|
||||
run: |
|
||||
# node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . bump-world-crates "$new_version"
|
||||
|
||||
cargo update
|
||||
git add -A
|
||||
git commit -m "build: bump world crates to $new_version" || true
|
||||
git push origin nightly
|
||||
|
||||
world_commit=$(git rev-parse HEAD)
|
||||
echo "world_commit=$world_commit" >> $GITHUB_ENV
|
||||
|
||||
- name: Update typst.ts
|
||||
if: steps.check_updates.outputs.need_release == 'true'
|
||||
run: |
|
||||
# Clone typst.ts
|
||||
git clone https://${{ secrets.NIGHTLY_REPO_TOKEN }}@github.com/ParaN3xus/typst.ts.git /tmp/typst.ts
|
||||
cd /tmp/typst.ts
|
||||
git checkout nightly
|
||||
|
||||
new_version="$new_version"
|
||||
|
||||
# node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . update-world-crates "$new_version"
|
||||
|
||||
# Update typst dependencies
|
||||
node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . update-typst-deps \
|
||||
"$typst_version" \
|
||||
"$typst_assets_rev"
|
||||
|
||||
# Update patches
|
||||
revs_json=$(cat <<EOF
|
||||
{
|
||||
"tinymist": "${world_commit}",
|
||||
"typst": "${latest_typst_content_hint_rev}"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . update-patch-revs "$revs_json"
|
||||
|
||||
cargo update
|
||||
git add -A
|
||||
git commit -m "build: update tinymist and typst" || true
|
||||
git push origin nightly
|
||||
|
||||
reflexo_commit=$(git rev-parse HEAD)
|
||||
echo "reflexo_commit=$reflexo_commit" >> $GITHUB_ENV
|
||||
|
||||
- name: Update typstyle
|
||||
if: steps.check_updates.outputs.need_release == 'true'
|
||||
run: |
|
||||
# Clone typstyle
|
||||
git clone https://${{ secrets.NIGHTLY_REPO_TOKEN }}@github.com/ParaN3xus/typstyle.git /tmp/typstyle
|
||||
cd /tmp/typstyle
|
||||
git checkout nightly
|
||||
|
||||
# node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . update-world-crates "$new_version"
|
||||
node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . update-typst-deps \
|
||||
"$typst_version" \
|
||||
"$typst_assets_rev"
|
||||
|
||||
# Update patches
|
||||
revs_json=$(cat <<EOF
|
||||
{
|
||||
"tinymist": "${world_commit}",
|
||||
"typst": "${latest_typst_rev}"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . update-patch-revs "$revs_json"
|
||||
|
||||
cargo update
|
||||
git add -A
|
||||
git commit -m "build: update tinymist to ${new_version}" || true
|
||||
git push origin nightly
|
||||
|
||||
typstyle_commit=$(git rev-parse HEAD)
|
||||
echo "typstyle_commit=$typstyle_commit" >> $GITHUB_ENV
|
||||
|
||||
- name: Update typst-ansi-hl
|
||||
if: steps.check_updates.outputs.need_release == 'true'
|
||||
run: |
|
||||
# Clone typst-ansi-hl
|
||||
git clone https://${{ secrets.NIGHTLY_REPO_TOKEN }}@github.com/ParaN3xus/typst-ansi-hl.git /tmp/typst-ansi-hl
|
||||
cd /tmp/typst-ansi-hl
|
||||
git checkout nightly
|
||||
|
||||
node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . update-typst-deps \
|
||||
"$typst_version" \
|
||||
"$typst_assets_rev"
|
||||
|
||||
# Update patches
|
||||
revs_json=$(cat <<EOF
|
||||
{
|
||||
"typst": "${latest_typst_rev}"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . update-patch-revs "$revs_json"
|
||||
|
||||
cargo update
|
||||
git add -A
|
||||
git commit -m "build: update typst-syntax" || true
|
||||
git push origin nightly
|
||||
|
||||
hl_commit=$(git rev-parse HEAD)
|
||||
echo "hl_commit=$hl_commit" >> $GITHUB_ENV
|
||||
|
||||
- name: Update tinymist patches and versions
|
||||
if: steps.check_updates.outputs.need_release == 'true'
|
||||
run: |
|
||||
# Update patch revisions using script
|
||||
revs_json=$(cat <<EOF
|
||||
{
|
||||
"reflexo": "${reflexo_commit}",
|
||||
"typst-ansi-hl": "${hl_commit}",
|
||||
"typstyle": "${typstyle_commit}"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . update-patch-revs "$revs_json"
|
||||
|
||||
# Update main version
|
||||
node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . update-main-version "$new_version"
|
||||
|
||||
- name: Update version files
|
||||
if: steps.check_updates.outputs.need_release == 'true'
|
||||
run: |
|
||||
node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . update-version-files "$new_version"
|
||||
|
||||
- name: Generate changelog
|
||||
if: steps.check_updates.outputs.need_release == 'true'
|
||||
run: |
|
||||
tinymist_base_commit=$(git merge-base HEAD origin/main)
|
||||
tinymist_base_msg=$(git --no-pager log --format="%s" -1 $tinymist_base_commit)
|
||||
|
||||
node $GITHUB_WORKSPACE/scripts/nightly-utils.mjs . generate-changelog \
|
||||
"$new_version" \
|
||||
"$tinymist_base_commit" \
|
||||
"$tinymist_base_msg" \
|
||||
"$latest_typst_rev" \
|
||||
"$typst_base_commit" \
|
||||
"$typst_base_msg"
|
||||
|
||||
- name: Final commit and tag
|
||||
if: steps.check_updates.outputs.need_release == 'true'
|
||||
run: |
|
||||
new_version="$new_version"
|
||||
|
||||
cargo update
|
||||
git add -A
|
||||
git commit -m "build: bump version to ${new_version}"
|
||||
bump_commit=$(git rev-parse HEAD)
|
||||
|
||||
git push origin nightly
|
||||
|
||||
curl -L \
|
||||
-X POST \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${{ secrets.REPO_TOKEN }}" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/repos/${{ github.repository }}/git/refs \
|
||||
-d "{\"ref\":\"refs/tags/v${new_version}\",\"sha\":\"${bump_commit}\"}"
|
||||
|
||||
echo "Successfully released tinymist ${new_version}!"
|
||||
|
||||
- name: No updates needed
|
||||
if: steps.check_updates.outputs.need_release != 'true'
|
||||
run: |
|
||||
echo "No updates needed. All dependencies are up to date."
|
||||
585
.github/workflows/release.yml
vendored
585
.github/workflows/release.yml
vendored
|
|
@ -1,304 +1,341 @@
|
|||
# stolen from https://github.com/nvarner/tinymist/blob/master/.github/workflows/release.yml
|
||||
name: CI
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
tags:
|
||||
- "*"
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
# This file was autogenerated by dist: https://github.com/astral-sh/cargo-dist
|
||||
#
|
||||
# Copyright 2022-2024, axodotdev
|
||||
# Copyright 2025 Astral Software Inc.
|
||||
# SPDX-License-Identifier: MIT or Apache-2.0
|
||||
#
|
||||
# CI that:
|
||||
#
|
||||
# * checks for a Git Tag that looks like a release
|
||||
# * builds artifacts with dist (archives, installers, hashes)
|
||||
# * uploads those artifacts to temporary workflow zip
|
||||
# * on success, uploads the artifacts to a GitHub Release
|
||||
#
|
||||
# Note that a GitHub Release with this tag is assumed to exist as a draft
|
||||
# with the appropriate title/body, and will be undrafted for you.
|
||||
|
||||
env:
|
||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
||||
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
RUSTC_WRAPPER: "sccache"
|
||||
name: Release
|
||||
permissions:
|
||||
"contents": "write"
|
||||
|
||||
# This task will run whenever you workflow_dispatch with a tag that looks like a version
|
||||
# like "1.0.0", "v0.1.0-prerelease.1", "my-app/0.1.0", "releases/v1.0.0", etc.
|
||||
# Various formats will be parsed into a VERSION and an optional PACKAGE_NAME, where
|
||||
# PACKAGE_NAME must be the name of a Cargo package in your workspace, and VERSION
|
||||
# must be a Cargo-style SemVer Version (must have at least major.minor.patch).
|
||||
#
|
||||
# If PACKAGE_NAME is specified, then the announcement will be for that
|
||||
# package (erroring out if it doesn't have the given version or isn't dist-able).
|
||||
#
|
||||
# If PACKAGE_NAME isn't specified, then the announcement will be for all
|
||||
# (dist-able) packages in the workspace with that version (this mode is
|
||||
# intended for workspaces with only one dist-able package, or with all dist-able
|
||||
# packages versioned/released in lockstep).
|
||||
#
|
||||
# If you push multiple tags at once, separate instances of this workflow will
|
||||
# spin up, creating an independent announcement for each one. However, GitHub
|
||||
# will hard limit this to 3 tags per commit, as it will assume more tags is a
|
||||
# mistake.
|
||||
#
|
||||
# If there's a prerelease-style suffix to the version, then the release(s)
|
||||
# will be marked as a prerelease.
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
tag:
|
||||
description: Release Tag
|
||||
required: true
|
||||
default: dry-run
|
||||
type: string
|
||||
targets:
|
||||
description: Targets to build
|
||||
required: true
|
||||
default: all
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: Release Tag
|
||||
required: true
|
||||
default: dry-run
|
||||
type: string
|
||||
targets:
|
||||
description: Targets to build
|
||||
required: true
|
||||
default: all
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
pre_build:
|
||||
permissions:
|
||||
actions: write
|
||||
contents: read
|
||||
name: Duplicate Actions Detection
|
||||
runs-on: ubuntu-latest
|
||||
# Run 'dist plan' (or host) to determine what tasks we need to do
|
||||
plan:
|
||||
runs-on: "ubuntu-22.04"
|
||||
outputs:
|
||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||
val: ${{ steps.plan.outputs.manifest }}
|
||||
tag: ${{ (inputs.tag != 'dry-run' && inputs.tag) || '' }}
|
||||
tag-flag: ${{ inputs.tag && inputs.tag != 'dry-run' && format('--tag={0}', inputs.tag) || '' }}
|
||||
publishing: ${{ inputs.tag && inputs.tag != 'dry-run' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- id: skip_check
|
||||
uses: fkirc/skip-duplicate-actions@v5
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
cancel_others: "true"
|
||||
build:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Install dist
|
||||
# we specify bash to get pipefail; it guards against the `curl` command
|
||||
# failing. otherwise `sh` won't catch that `curl` returned non-0
|
||||
shell: bash
|
||||
run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/Myriad-Dreamin/cargo-dist/releases/download/v0.28.6-tinymist.3/cargo-dist-installer.sh | sh"
|
||||
- name: Cache dist
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cargo-dist-cache
|
||||
path: ~/.cargo/bin/dist
|
||||
# sure would be cool if github gave us proper conditionals...
|
||||
# so here's a doubly-nested ternary-via-truthiness to try to provide the best possible
|
||||
# functionality based on whether this is a pull_request, and whether it's from a fork.
|
||||
# (PRs run on the *source* but secrets are usually on the *target* -- that's *good*
|
||||
# but also really annoying to build CI around when it needs secrets to work right.)
|
||||
- id: plan
|
||||
run: |
|
||||
dist ${{ (inputs.tag && inputs.tag != 'dry-run' && format('host --steps=create --tag={0}', inputs.tag)) || 'plan' }} --output-format=json > plan-dist-manifest.json
|
||||
echo "dist ran successfully"
|
||||
cat plan-dist-manifest.json
|
||||
echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT"
|
||||
- name: "Upload dist-manifest.json"
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: artifacts-plan-dist-manifest
|
||||
path: plan-dist-manifest.json
|
||||
|
||||
# Build and packages all the platform-specific things
|
||||
build-local-artifacts:
|
||||
name: build-local-artifacts (${{ join(matrix.targets, ', ') }})
|
||||
# Let the initial task tell us to not run (currently very blunt)
|
||||
needs:
|
||||
- plan
|
||||
if: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix.include != null && (needs.plan.outputs.publishing == 'true' || (fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload') || (inputs.targets == 'all' || contains(inputs.targets, join(fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix.targets, '')))) || inputs.tag == 'dry-run' }}
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-latest
|
||||
rust-target: x86_64-pc-windows-msvc
|
||||
platform: win32
|
||||
arch: x64
|
||||
- os: windows-latest
|
||||
rust-target: aarch64-pc-windows-msvc
|
||||
platform: win32
|
||||
arch: arm64
|
||||
- os: ubuntu-20.04
|
||||
rust-target: x86_64-unknown-linux-gnu
|
||||
platform: linux
|
||||
arch: x64
|
||||
- os: ubuntu-20.04
|
||||
rust-target: aarch64-unknown-linux-gnu
|
||||
platform: linux
|
||||
arch: arm64
|
||||
- os: ubuntu-20.04
|
||||
rust-target: arm-unknown-linux-gnueabihf
|
||||
platform: linux
|
||||
arch: armhf
|
||||
- os: macos-11
|
||||
rust-target: x86_64-apple-darwin
|
||||
platform: darwin
|
||||
arch: x64
|
||||
- os: macos-11
|
||||
rust-target: aarch64-apple-darwin
|
||||
platform: darwin
|
||||
arch: arm64
|
||||
|
||||
name: build (${{ matrix.platform }}-${{ matrix.arch }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
fail-fast: false
|
||||
# Target platforms/runners are computed by dist in create-release.
|
||||
# Each member of the matrix has the following arguments:
|
||||
#
|
||||
# - runner: the github runner
|
||||
# - dist-args: cli flags to pass to dist
|
||||
# - install-dist: expression to run to install dist on the runner
|
||||
#
|
||||
# Typically there will be:
|
||||
# - 1 "global" task that builds universal installers
|
||||
# - N "local" tasks that build each platform's binaries and platform-specific installers
|
||||
matrix: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
container: ${{ matrix.container && matrix.container.image || null }}
|
||||
env:
|
||||
target: ${{ matrix.platform }}-${{ matrix.arch }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BUILD_MANIFEST_NAME: target/distrib/${{ join(matrix.targets, '-') }}-dist-manifest.json
|
||||
steps:
|
||||
- name: enable windows longpaths
|
||||
run: |
|
||||
git config --global core.longpaths true
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Rust non-interactively if not already installed
|
||||
if: ${{ matrix.container }}
|
||||
run: |
|
||||
if ! command -v cargo > /dev/null 2>&1; then
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
|
||||
fi
|
||||
- uses: swatinem/rust-cache@v2
|
||||
with:
|
||||
repository: Enter-tainer/typst-preview
|
||||
path: external/typst-preview
|
||||
- name: Run sccache-cache
|
||||
uses: mozilla-actions/sccache-action@v0.0.4
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
key: ${{ join(matrix.targets, '-') }}
|
||||
cache-provider: ${{ matrix.cache_provider }}
|
||||
- name: Install dist
|
||||
run: ${{ matrix.install_dist.run }}
|
||||
# Get the dist-manifest
|
||||
- name: Fetch local artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Hack typst-preview
|
||||
run: |
|
||||
mv src/main.rs src/main.rsx
|
||||
working-directory: ./external/typst-preview
|
||||
- name: Build typst-dom
|
||||
run: |
|
||||
yarn
|
||||
yarn build
|
||||
working-directory: ./external/typst-preview/addons/typst-dom
|
||||
- name: Build frontend
|
||||
run: yarn
|
||||
working-directory: ./external/typst-preview/addons/frontend
|
||||
- name: Build typst-preview
|
||||
run: |
|
||||
yarn
|
||||
yarn run compile
|
||||
working-directory: ./external/typst-preview/addons/vscode
|
||||
- name: Build vscode extension
|
||||
run: |
|
||||
yarn
|
||||
yarn run compile
|
||||
working-directory: ./editors/vscode
|
||||
- name: rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.rust-target }}
|
||||
- name: Install llvm
|
||||
if: matrix.platform == 'linux'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install llvm
|
||||
- name: Install AArch64 target toolchain
|
||||
if: matrix.rust-target == 'aarch64-unknown-linux-gnu'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install gcc-aarch64-linux-gnu
|
||||
- name: Install ARM target toolchain
|
||||
if: matrix.rust-target == 'arm-unknown-linux-gnueabihf'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install gcc-arm-linux-gnueabihf
|
||||
- name: Build tinymist binary
|
||||
shell: pwsh
|
||||
run: |
|
||||
cargo build --release -p tinymist --target ${{ matrix.rust-target }}
|
||||
- name: Rename debug symbols for windows
|
||||
if: matrix.platform == 'win32'
|
||||
run: |
|
||||
cd target/${{ matrix.rust-target }}/release
|
||||
cp tinymist.pdb tinymist-${{ env.target }}.pdb
|
||||
- name: Upload split debug symbols for windows
|
||||
if: matrix.platform == 'win32'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-${{ env.target }}.pdb
|
||||
path: target/${{ matrix.rust-target }}/release/tinymist-${{ env.target }}.pdb
|
||||
- name: Split debug symbols for linux
|
||||
if: matrix.platform == 'linux'
|
||||
run: |
|
||||
cd target/${{ matrix.rust-target }}/release
|
||||
llvm-objcopy --compress-debug-sections --only-keep-debug "tinymist" "tinymist-${{ env.target }}.debug"
|
||||
llvm-objcopy --strip-debug --add-gnu-debuglink="tinymist-${{ env.target }}.debug" "tinymist"
|
||||
- name: Upload split debug symbols for linux
|
||||
if: matrix.platform == 'linux'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-${{ env.target }}.debug
|
||||
path: target/${{ matrix.rust-target }}/release/tinymist-${{ env.target }}.debug
|
||||
compression-level: 0
|
||||
- name: Collect debug symbols for mac
|
||||
if: matrix.platform == 'darwin'
|
||||
run: |
|
||||
dsymutil -f "target/${{ matrix.rust-target }}/release/tinymist"
|
||||
mv "target/${{ matrix.rust-target }}/release/tinymist.dwarf" "target/${{ matrix.rust-target }}/release/tinymist-${{ env.target }}.dwarf"
|
||||
- name: Upload split debug symbols for mac
|
||||
if: matrix.platform == 'darwin'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-${{ env.target }}.dwarf
|
||||
path: target/${{ matrix.rust-target }}/release/tinymist-${{ env.target }}.dwarf
|
||||
- name: Copy binary to output directory
|
||||
shell: pwsh
|
||||
run: |
|
||||
cp "target/${{ matrix.rust-target }}/release/tinymist$(If ('${{ matrix.platform }}' -eq 'win32') { '.exe' } else { '' } )" "editors/vscode/out/"
|
||||
cp "target/${{ matrix.rust-target }}/release/tinymist$(If ('${{ matrix.platform }}' -eq 'win32') { '.exe' } else { '' } )" "tinymist-${{ env.target }}$(If ('${{ matrix.platform }}' -eq 'win32') { '.exe' } else { '' } )"
|
||||
- name: Upload binary artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-${{ env.target }}
|
||||
path: tinymist-${{ env.target }}${{ fromJSON('["", ".exe"]')[matrix.platform == 'win32'] }}
|
||||
- name: Package extension
|
||||
shell: pwsh
|
||||
run: yarn run package -- --target ${{ env.target }} -o tinymist-${{ env.target }}.vsix
|
||||
working-directory: ./editors/vscode
|
||||
- name: Upload VSIX artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-${{ env.target }}.vsix
|
||||
path: editors/vscode/tinymist-${{ env.target }}.vsix
|
||||
|
||||
build_alpine:
|
||||
name: build (x86_64-unknown-linux-musl)
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: rust:alpine
|
||||
volumes:
|
||||
- /usr/local/cargo/registry:/usr/local/cargo/registry
|
||||
env:
|
||||
target: alpine-x64
|
||||
RUST_TARGET: x86_64-unknown-linux-musl
|
||||
RUSTFLAGS: "-C link-arg=-fuse-ld=lld -C target-feature=-crt-static"
|
||||
steps:
|
||||
pattern: artifacts-*
|
||||
path: target/distrib/
|
||||
merge-multiple: true
|
||||
- name: Install dependencies
|
||||
run: apk add --no-cache git clang lld musl-dev nodejs npm yarn binutils
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
run: |
|
||||
${{ matrix.packages_install }}
|
||||
- name: Build artifacts
|
||||
run: |
|
||||
# Actually do builds and make zips and whatnot
|
||||
dist build ${{ needs.plan.outputs.tag-flag }} --print=linkage --output-format=json ${{ matrix.dist_args }} > dist-manifest.json
|
||||
echo "dist ran successfully"
|
||||
- id: cargo-dist
|
||||
name: Post-build
|
||||
# We force bash here just because github makes it really hard to get values up
|
||||
# to "real" actions without writing to env-vars, and writing to env-vars has
|
||||
# inconsistent syntax between shell and powershell.
|
||||
shell: bash
|
||||
run: |
|
||||
# Parse out what we just built and upload it to scratch storage
|
||||
echo "paths<<EOF" >> "$GITHUB_OUTPUT"
|
||||
dist print-upload-files-from-manifest --manifest dist-manifest.json >> "$GITHUB_OUTPUT"
|
||||
echo "EOF" >> "$GITHUB_OUTPUT"
|
||||
|
||||
cp dist-manifest.json "$BUILD_MANIFEST_NAME"
|
||||
- name: "Upload artifacts"
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Run sccache-cache
|
||||
uses: mozilla-actions/sccache-action@v0.0.4
|
||||
name: artifacts-build-local-${{ join(matrix.targets, '_') }}
|
||||
path: |
|
||||
${{ steps.cargo-dist.outputs.paths }}
|
||||
${{ env.BUILD_MANIFEST_NAME }}
|
||||
|
||||
# Build and package all the platform-agnostic(ish) things
|
||||
build-global-artifacts:
|
||||
needs:
|
||||
- plan
|
||||
- build-local-artifacts
|
||||
runs-on: "ubuntu-22.04"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: Enter-tainer/typst-preview
|
||||
path: external/typst-preview
|
||||
- name: Hack typst-preview
|
||||
run: |
|
||||
mv src/main.rs src/main.rsx
|
||||
working-directory: ./external/typst-preview
|
||||
- name: Build typst-dom
|
||||
run: |
|
||||
yarn
|
||||
yarn build
|
||||
working-directory: ./external/typst-preview/addons/typst-dom
|
||||
- name: Build frontend
|
||||
run: yarn
|
||||
working-directory: ./external/typst-preview/addons/frontend
|
||||
- name: Build typst-preview
|
||||
run: |
|
||||
yarn
|
||||
yarn run compile
|
||||
working-directory: ./external/typst-preview/addons/vscode
|
||||
- name: Build vscode extension
|
||||
run: |
|
||||
yarn
|
||||
yarn run compile
|
||||
working-directory: ./editors/vscode
|
||||
- name: Build tinymist binary
|
||||
run: |
|
||||
cargo build --release -p tinymist --target $RUST_TARGET
|
||||
mkdir -p editors/vscode/out
|
||||
- name: Split debug symbols
|
||||
run: |
|
||||
cd target/$RUST_TARGET/release
|
||||
objcopy --compress-debug-sections --only-keep-debug "tinymist" "tinymist-${{ env.target }}.debug"
|
||||
objcopy --strip-debug --add-gnu-debuglink="tinymist-${{ env.target }}.debug" "tinymist"
|
||||
- name: Upload split debug symbols
|
||||
uses: actions/upload-artifact@v4
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Install cached dist
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: tinymist-${{ env.target }}.debug
|
||||
path: target/${{ env.RUST_TARGET }}/release/tinymist-${{ env.target }}.debug
|
||||
- name: Copy binary to output directory
|
||||
name: cargo-dist-cache
|
||||
path: ~/.cargo/bin/
|
||||
- run: chmod +x ~/.cargo/bin/dist
|
||||
# Get all the local artifacts for the global tasks to use (for e.g. checksums)
|
||||
- name: Fetch local artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: artifacts-*
|
||||
path: target/distrib/
|
||||
merge-multiple: true
|
||||
- id: cargo-dist
|
||||
shell: bash
|
||||
run: |
|
||||
cp "target/${{ env.RUST_TARGET }}/release/tinymist" "editors/vscode/out/"
|
||||
cp "target/${{ env.RUST_TARGET }}/release/tinymist" "tinymist-${{ env.target }}"
|
||||
- name: Upload binary artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-${{ env.target }}
|
||||
path: tinymist-${{ env.target }}
|
||||
- name: Package extension
|
||||
run: yarn run package -- --target ${{ env.target }} -o tinymist-${{ env.target }}.vsix
|
||||
working-directory: ./editors/vscode
|
||||
- name: Upload VSIX artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tinymist-${{ env.target }}.vsix
|
||||
path: editors/vscode/tinymist-${{ env.target }}.vsix
|
||||
dist build ${{ needs.plan.outputs.tag-flag }} --output-format=json "--artifacts=global" > dist-manifest.json
|
||||
echo "dist ran successfully"
|
||||
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, build_alpine]
|
||||
if: success() && startsWith(github.ref, 'refs/tags/')
|
||||
# Parse out what we just built and upload it to scratch storage
|
||||
echo "paths<<EOF" >> "$GITHUB_OUTPUT"
|
||||
jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT"
|
||||
echo "EOF" >> "$GITHUB_OUTPUT"
|
||||
|
||||
cp dist-manifest.json "$BUILD_MANIFEST_NAME"
|
||||
- name: "Upload artifacts"
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: artifacts-build-global
|
||||
path: |
|
||||
${{ steps.cargo-dist.outputs.paths }}
|
||||
${{ env.BUILD_MANIFEST_NAME }}
|
||||
|
||||
custom-build-vscode:
|
||||
needs:
|
||||
- plan
|
||||
- build-local-artifacts
|
||||
uses: ./.github/workflows/build-vscode.yml
|
||||
with:
|
||||
plan: ${{ needs.plan.outputs.val }}
|
||||
secrets: inherit
|
||||
permissions:
|
||||
contents: write
|
||||
"contents": "write"
|
||||
|
||||
custom-ci-check-e2e:
|
||||
needs:
|
||||
- plan
|
||||
- build-local-artifacts
|
||||
uses: ./.github/workflows/ci-check-e2e.yml
|
||||
with:
|
||||
plan: ${{ needs.plan.outputs.val }}
|
||||
secrets: inherit
|
||||
# Determines if we should publish/announce
|
||||
host:
|
||||
needs:
|
||||
- plan
|
||||
- build-local-artifacts
|
||||
- build-global-artifacts
|
||||
- custom-build-vscode
|
||||
- custom-ci-check-e2e
|
||||
# Only run if we're "publishing", and only if local and global didn't fail (skipped is fine)
|
||||
if: ${{ always() && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.custom-build-vscode.result == 'skipped' || needs.custom-build-vscode.result == 'success') && (needs.custom-ci-check-e2e.result == 'skipped' || needs.custom-ci-check-e2e.result == 'success') && (needs.build-local-artifacts.result == 'skipped' || needs.build-local-artifacts.result == 'success') }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
runs-on: "ubuntu-22.04"
|
||||
outputs:
|
||||
val: ${{ steps.host.outputs.manifest }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- uses: actions/download-artifact@v4
|
||||
- name: Install cached dist
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: cargo-dist-cache
|
||||
path: ~/.cargo/bin/
|
||||
- run: chmod +x ~/.cargo/bin/dist
|
||||
# Fetch artifacts from scratch-storage
|
||||
- name: Fetch artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: artifacts-*
|
||||
path: target/distrib/
|
||||
merge-multiple: true
|
||||
- id: host
|
||||
shell: bash
|
||||
run: |
|
||||
dist host ${{ needs.plan.outputs.tag-flag }} --steps=upload --steps=release --output-format=json > dist-manifest.json
|
||||
echo "artifacts uploaded and released successfully"
|
||||
cat dist-manifest.json
|
||||
echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT"
|
||||
- name: "Upload dist-manifest.json"
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
# Overwrite the previous copy
|
||||
name: artifacts-dist-manifest
|
||||
path: dist-manifest.json
|
||||
# Create a GitHub Release while uploading all files to it
|
||||
- name: "Download GitHub Artifacts"
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: artifacts-*
|
||||
path: artifacts
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R artifacts
|
||||
- uses: ncipollo/release-action@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
artifacts: "artifacts/*/*"
|
||||
allowUpdates: true
|
||||
omitBodyDuringUpdate: true
|
||||
omitDraftDuringUpdate: true
|
||||
omitNameDuringUpdate: true
|
||||
omitPrereleaseDuringUpdate: true
|
||||
merge-multiple: true
|
||||
- name: Cleanup
|
||||
run: |
|
||||
# Remove the granular manifests
|
||||
rm -f artifacts/*-dist-manifest.json
|
||||
- name: Create GitHub Release
|
||||
env:
|
||||
PRERELEASE_FLAG: "${{ fromJson(steps.host.outputs.manifest).announcement_is_prerelease && '--prerelease' || '' }}"
|
||||
RELEASE_COMMIT: "${{ github.sha }}"
|
||||
run: |
|
||||
# If we're editing a release in place, we need to upload things ahead of time
|
||||
gh release upload "${{ needs.plan.outputs.tag }}" artifacts/*
|
||||
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build]
|
||||
if: success() && startsWith(github.ref, 'refs/tags/')
|
||||
gh release edit "${{ needs.plan.outputs.tag }}" --target "$RELEASE_COMMIT" $PRERELEASE_FLAG --draft=false
|
||||
|
||||
announce:
|
||||
needs:
|
||||
- plan
|
||||
- host
|
||||
# use "always() && ..." to allow us to wait for all publish jobs while
|
||||
# still allowing individual publish jobs to skip themselves (for prereleases).
|
||||
# "host" however must run to completion, no skipping allowed!
|
||||
if: ${{ always() && needs.host.result == 'success' }}
|
||||
runs-on: "ubuntu-22.04"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
|
||||
- name: Deploy to VS Code Marketplace
|
||||
run: npx vsce publish --packagePath $(find . -type f -iname '*.vsix')
|
||||
env:
|
||||
VSCE_PAT: ${{ secrets.VSCODE_MARKETPLACE_TOKEN }}
|
||||
|
||||
- name: Deploy to OpenVSX
|
||||
run: npx ovsx publish --packagePath $(find . -type f -iname '*.vsix')
|
||||
env:
|
||||
OVSX_PAT: ${{ secrets.OPENVSX_ACCESS_TOKEN }}
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
|
|
|||
11
.gitignore
vendored
11
.gitignore
vendored
|
|
@ -5,6 +5,11 @@ result*
|
|||
.envrc
|
||||
node_modules/
|
||||
/local/
|
||||
/editors/vscode/out/
|
||||
/editors/lapce/out/
|
||||
/external/typst-preview
|
||||
editors/vscode/out/
|
||||
editors/lapce/out/
|
||||
/external/typst-preview
|
||||
/dist
|
||||
|
||||
*.pdf
|
||||
.vscode/*.code-workspace
|
||||
refs/
|
||||
|
|
@ -1,10 +1,25 @@
|
|||
.DS_Store
|
||||
.git/**
|
||||
.github/**
|
||||
.vscode/**
|
||||
assets/**
|
||||
src/**
|
||||
target/**
|
||||
dist/**
|
||||
icons/
|
||||
node_modules/
|
||||
editors/vscode/test-dist/
|
||||
editors/vscode/out/
|
||||
editors/vscode/.vscode-test/**
|
||||
*.toml
|
||||
*.txt
|
||||
*.lock
|
||||
*.md
|
||||
|
||||
.env
|
||||
.env.*
|
||||
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
|
|
|||
13
.prettierrc.cjs
Normal file
13
.prettierrc.cjs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
module.exports = {
|
||||
// same options as rust-analyzer, otherwise defaults from prettier
|
||||
printWidth: 100,
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
semi: true,
|
||||
singleQuote: false,
|
||||
quoteProps: "as-needed",
|
||||
trailingComma: "all",
|
||||
bracketSpacing: true,
|
||||
arrowParens: "always",
|
||||
singleAttributePerLine: false,
|
||||
};
|
||||
107
.vscode/launch.json
vendored
107
.vscode/launch.json
vendored
|
|
@ -15,7 +15,21 @@
|
|||
"preLaunchTask": "VS Code Extension Prelaunch"
|
||||
},
|
||||
{
|
||||
"name": "Run Extension [Jaeger]",
|
||||
"name": "Run Extension [Web]",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentKind=web",
|
||||
"--extensionDevelopmentPath=${workspaceFolder}/editors/vscode"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/editors/vscode/out/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "VS Code Extension Prelaunch [Web]"
|
||||
},
|
||||
{
|
||||
"name": "Run Extension [Release]",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
|
|
@ -25,7 +39,96 @@
|
|||
"outFiles": [
|
||||
"${workspaceFolder}/editors/vscode/out/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "VS Code Extension Prelaunch [Jaeger]"
|
||||
"preLaunchTask": "VS Code Extension Prelaunch [Release]"
|
||||
},
|
||||
{
|
||||
"name": "Run Extension [Typst Preview]",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}/contrib/typst-preview/editors/vscode"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/contrib/typst-preview/editors/vscode/out/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "VS Code Extension Prelaunch Preview"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug unit tests in executable 'tinymist'",
|
||||
"cargo": {
|
||||
"args": [
|
||||
"test",
|
||||
"--no-run",
|
||||
"--bin=tinymist",
|
||||
"--package=tinymist"
|
||||
],
|
||||
"filter": {
|
||||
"name": "tinymist",
|
||||
"kind": "bin"
|
||||
}
|
||||
},
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug unit tests in library 'tinymist-query'",
|
||||
"cargo": {
|
||||
"args": [
|
||||
"test",
|
||||
"--no-run",
|
||||
"--lib",
|
||||
"--package=tinymist-query"
|
||||
],
|
||||
"filter": {
|
||||
"name": "tinymist-query",
|
||||
"kind": "lib"
|
||||
}
|
||||
},
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug unit tests in library 'tinymist-render'",
|
||||
"cargo": {
|
||||
"args": [
|
||||
"test",
|
||||
"--no-run",
|
||||
"--lib",
|
||||
"--package=tinymist-render"
|
||||
],
|
||||
"filter": {
|
||||
"name": "tinymist-render",
|
||||
"kind": "lib"
|
||||
}
|
||||
},
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug integration test 'tinymist-e2e-tests'",
|
||||
"cargo": {
|
||||
"args": [
|
||||
"test",
|
||||
"--no-run",
|
||||
"--test=tinymist-e2e-tests",
|
||||
"--package=tests"
|
||||
],
|
||||
"filter": {
|
||||
"name": "tinymist-e2e-tests",
|
||||
"kind": "test"
|
||||
}
|
||||
},
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
|
|
@ -2,5 +2,8 @@
|
|||
"eslint.format.enable": true,
|
||||
"eslint.workingDirectories": [
|
||||
"editors/vscode"
|
||||
]
|
||||
],
|
||||
"tinymist.fontPaths": [
|
||||
"assets/fonts"
|
||||
],
|
||||
}
|
||||
|
|
|
|||
137
.vscode/tasks.json
vendored
137
.vscode/tasks.json
vendored
|
|
@ -3,10 +3,30 @@
|
|||
"tasks": [
|
||||
{
|
||||
"label": "VS Code Extension Prelaunch",
|
||||
"type": "npm",
|
||||
"script": "prelaunch:vscode",
|
||||
"group": "build",
|
||||
},
|
||||
{
|
||||
"label": "VS Code Extension Prelaunch [Web]",
|
||||
"type": "npm",
|
||||
"script": "build:web",
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "VS Code Extension Prelaunch Preview",
|
||||
"dependsOn": [
|
||||
"Compile Typst Preview Extension",
|
||||
"Copy Debug LSP Binary to Typst Preview Extension"
|
||||
],
|
||||
"dependsOrder": "sequence",
|
||||
},
|
||||
{
|
||||
"label": "VS Code Extension Prelaunch [Release]",
|
||||
"dependsOn": [
|
||||
"Compile VS Code Extension",
|
||||
"Build Debug LSP Binary",
|
||||
"Copy Debug LSP Binary to VS Code Extension"
|
||||
"Build Release LSP Binary",
|
||||
"Copy Release LSP Binary to VS Code Extension"
|
||||
],
|
||||
"dependsOrder": "sequence",
|
||||
},
|
||||
|
|
@ -16,7 +36,10 @@
|
|||
"Compile VS Code Extension",
|
||||
"Build Release LSP Binary",
|
||||
"Copy Release LSP Binary to VS Code Extension",
|
||||
"Generate VS Code Extension Bundle"
|
||||
"Generate VS Code Extension Bundle",
|
||||
"Compile Typst Preview Extension",
|
||||
"Copy Release LSP Binary to Typst Preview Extension",
|
||||
"Generate Typst Preview Extension Bundle"
|
||||
],
|
||||
"dependsOrder": "sequence",
|
||||
},
|
||||
|
|
@ -27,6 +50,13 @@
|
|||
"path": "editors/vscode",
|
||||
"group": "build",
|
||||
},
|
||||
{
|
||||
"label": "Compile VS Code Extension [Web]",
|
||||
"type": "npm",
|
||||
"script": "compile:web",
|
||||
"path": "editors/vscode",
|
||||
"group": "build",
|
||||
},
|
||||
{
|
||||
"label": "Generate VS Code Extension Bundle",
|
||||
"type": "npm",
|
||||
|
|
@ -35,50 +65,33 @@
|
|||
"group": "build",
|
||||
},
|
||||
{
|
||||
"label": "Build Debug LSP Binary",
|
||||
"type": "cargo",
|
||||
"command": "build",
|
||||
"args": [ "--bin", "tinymist" ],
|
||||
"problemMatcher": [
|
||||
"$rustc"
|
||||
],
|
||||
"group": "build"
|
||||
"label": "Compile Typst Preview Extension",
|
||||
"type": "npm",
|
||||
"script": "compile",
|
||||
"path": "contrib/typst-preview/editors/vscode",
|
||||
"group": "build",
|
||||
},
|
||||
{
|
||||
"label": "Generate Typst Preview Extension Bundle",
|
||||
"type": "npm",
|
||||
"script": "package",
|
||||
"path": "contrib/typst-preview/editors/vscode",
|
||||
"group": "build",
|
||||
},
|
||||
{
|
||||
"label": "Build Release LSP Binary",
|
||||
"type": "cargo",
|
||||
"command": "build",
|
||||
"args": [ "--release", "--bin", "tinymist" ],
|
||||
"args": [
|
||||
"--release",
|
||||
"--bin",
|
||||
"tinymist"
|
||||
],
|
||||
"problemMatcher": [
|
||||
"$rustc"
|
||||
],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "Copy Debug LSP Binary to VS Code Extension",
|
||||
"type": "shell",
|
||||
"windows": {
|
||||
"command": "cp",
|
||||
"args": [
|
||||
"${workspaceFolder}\\target\\debug\\tinymist.exe",
|
||||
"${workspaceFolder}\\editors\\vscode\\out\\"
|
||||
]
|
||||
},
|
||||
"linux": {
|
||||
"command": "cp",
|
||||
"args": [
|
||||
"${workspaceFolder}/target/debug/tinymist",
|
||||
"${workspaceFolder}/editors/vscode/out/"
|
||||
]
|
||||
},
|
||||
"osx": {
|
||||
"command": "cp",
|
||||
"args": [
|
||||
"${workspaceFolder}/target/debug/tinymist",
|
||||
"${workspaceFolder}/editors/vscode/out/"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Copy Release LSP Binary to VS Code Extension",
|
||||
"type": "shell",
|
||||
|
|
@ -103,6 +116,56 @@
|
|||
"${workspaceFolder}/editors/vscode/out/"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Copy Debug LSP Binary to Typst Preview Extension",
|
||||
"type": "shell",
|
||||
"windows": {
|
||||
"command": "cp",
|
||||
"args": [
|
||||
"${workspaceFolder}\\target\\debug\\tinymist.exe",
|
||||
"${workspaceFolder}\\contrib\\typst-preview\\editors\\vscode\\out\\"
|
||||
]
|
||||
},
|
||||
"linux": {
|
||||
"command": "cp",
|
||||
"args": [
|
||||
"${workspaceFolder}/target/debug/tinymist",
|
||||
"${workspaceFolder}/contrib/typst-preview/editors/vscode/out/"
|
||||
]
|
||||
},
|
||||
"osx": {
|
||||
"command": "cp",
|
||||
"args": [
|
||||
"${workspaceFolder}/target/debug/tinymist",
|
||||
"${workspaceFolder}/contrib/typst-preview/editors/vscode/out/"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Copy Release LSP Binary to Typst Preview Extension",
|
||||
"type": "shell",
|
||||
"windows": {
|
||||
"command": "cp",
|
||||
"args": [
|
||||
"${workspaceFolder}\\target\\release\\tinymist.exe",
|
||||
"${workspaceFolder}\\contrib\\typst-preview\\editors\\vscode\\out\\"
|
||||
]
|
||||
},
|
||||
"linux": {
|
||||
"command": "cp",
|
||||
"args": [
|
||||
"${workspaceFolder}/target/release/tinymist",
|
||||
"${workspaceFolder}/contrib/typst-preview/editors/vscode/out/"
|
||||
]
|
||||
},
|
||||
"osx": {
|
||||
"command": "cp",
|
||||
"args": [
|
||||
"${workspaceFolder}/target/release/tinymist",
|
||||
"${workspaceFolder}/contrib/typst-preview/editors/vscode/out/"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
37
.vscode/tinymist.code-workspace.tmpl.json
vendored
Normal file
37
.vscode/tinymist.code-workspace.tmpl.json
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"$schema": "vscode://schemas/workspaceConfig",
|
||||
"folders": [
|
||||
{
|
||||
"path": ".."
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"tinymist.fontPaths": [
|
||||
"assets/fonts"
|
||||
],
|
||||
"[javascript]":{
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
},
|
||||
"[json]": {
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"eslint.format.enable": true,
|
||||
"eslint.workingDirectories": [
|
||||
"editors/vscode"
|
||||
],
|
||||
"rust-analyzer.check.command": "clippy",
|
||||
"rust-analyzer.rustfmt.extraArgs": ["--config=wrap_comments=true"],
|
||||
"files.watcherExclude": {
|
||||
"**/target": true
|
||||
},
|
||||
},
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode",
|
||||
"myriad-dreamin.tinymist",
|
||||
]
|
||||
},
|
||||
}
|
||||
22
.zed/settings.json
Normal file
22
.zed/settings.json
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// Folder-specific settings
|
||||
//
|
||||
// For a full list of overridable settings, and general information on folder-specific settings,
|
||||
// see the documentation: https://zed.dev/docs/configuring-zed#settings-files
|
||||
{
|
||||
"lsp": {
|
||||
"rust-analyzer": {
|
||||
"initialization_options": {
|
||||
"check": {
|
||||
"command": "clippy"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tinymist": {
|
||||
"initialization_options": {
|
||||
"exportPdf": "onSave",
|
||||
"fontPaths": ["assets/fonts"],
|
||||
"outputPath": "$root/target/typst/$dir/$name"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1
CHANGELOG.md
Normal file
1
CHANGELOG.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
[CHANGELOG.md](./editors/vscode/CHANGELOG.md)
|
||||
1255
CHANGELOG/CHANGELOG-2024.md
Normal file
1255
CHANGELOG/CHANGELOG-2024.md
Normal file
File diff suppressed because it is too large
Load diff
4
CHANGELOG/README.md
Normal file
4
CHANGELOG/README.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# CHANGELOGs
|
||||
|
||||
- [CHANGELOG-2025.md](/editors/vscode/CHANGELOG.md)
|
||||
- [CHANGELOG-2024.md](./CHANGELOG-2024.md)
|
||||
2
CODEOWNERS
Normal file
2
CODEOWNERS
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
# Only Myriad-Dreamin and Enter-tainer can merge changes to this repository.
|
||||
* @Myriad-Dreamin @Enter-tainer
|
||||
22
CONTRIBUTING.md
Normal file
22
CONTRIBUTING.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
# Contributing
|
||||
|
||||
Thank you for your interest in contributing to tinymist! There are many ways to contribute and we appreciate all of them.
|
||||
|
||||
Before contributing, you can read the [Development Guide](./docs/dev-guide.md) to learn more about the project structure and how to build and run the project.
|
||||
|
||||
## Fixing a bug or improving a feature
|
||||
|
||||
Generally it's fine to just work on these kinds of things and put a pull-request out for it. If there is an issue accompanying it make sure to link it in the pull request description so it can be closed afterwards or linked for context.
|
||||
|
||||
If you want to find something to fix or work on keep a look out for the [`bug`](https://github.com/Myriad-Dreamin/tinymist/issues?q=is%3Aissue+is%3Aopen+label%3Abug) and [`enhancement`](https://github.com/Myriad-Dreamin/tinymist/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement)
|
||||
labels. Among issues, the [`good first issue`](https://github.com/Myriad-Dreamin/tinymist/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) label is a good place to start.
|
||||
|
||||
## Localization
|
||||
|
||||
Tinymist is localized in multiple languages. You can contribute to the localization of Tinymist by translating or correcting the locale files in the [locales](./locales) folder. This is also a good start of contributing to the project.
|
||||
|
||||
## Implementing a new feature
|
||||
|
||||
It's advised to first open an issue for any kind of new feature so the team can tell upfront whether the feature is desirable or not before any implementation work happens. We want to minimize the possibility of someone putting a lot of work into a feature that is then going to waste as we deem it out of scope (be it due to generally not fitting in with tinymist, or just not having the maintenance capacity). If there already is a feature issue open but it is not clear whether it is considered accepted feel free to just drop a comment and ask!
|
||||
|
||||
4996
Cargo.lock
generated
4996
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
339
Cargo.toml
339
Cargo.toml
|
|
@ -1,73 +1,220 @@
|
|||
[workspace.package]
|
||||
description = "An integrated language service for Typst."
|
||||
authors = ["Myriad-Dreamin <camiyoru@gmail.com>", "Nathan Varner"]
|
||||
version = "0.10.1"
|
||||
edition = "2021"
|
||||
version = "0.14.6-rc1"
|
||||
edition = "2024"
|
||||
readme = "README.md"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://github.com/Myriad-Dreamin/tinymist"
|
||||
repository = "https://github.com/Myriad-Dreamin/tinymist"
|
||||
rust-version = "1.74"
|
||||
# also change in ci.yml
|
||||
rust-version = "1.89"
|
||||
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["crates/*", "external/typst-preview"]
|
||||
members = ["benches/*", "crates/*", "tests"]
|
||||
|
||||
[workspace.dependencies]
|
||||
|
||||
once_cell = "1"
|
||||
# Basic Infra
|
||||
anyhow = "1"
|
||||
itertools = "0.13"
|
||||
paste = "1.0"
|
||||
cfg-if = "1.0"
|
||||
strum = { version = "0.27.2", features = ["derive"] }
|
||||
quote = "1"
|
||||
syn = "2"
|
||||
triomphe = { version = "0.1.10", default-features = false, features = ["std"] }
|
||||
|
||||
fxhash = "0.2.1"
|
||||
ecow = "0.2.0"
|
||||
comemo = "0.4"
|
||||
ena = "0.14.2"
|
||||
# Asynchoronous and Multi-threading
|
||||
async-trait = "0.1.89"
|
||||
futures = "0.3"
|
||||
regex = "1.8.1"
|
||||
itertools = "0.12.0"
|
||||
lazy_static = "1.4.0"
|
||||
env_logger = "0.11.1"
|
||||
log = "0.4.17"
|
||||
strum = { version = "0.25.0", features = ["derive"] }
|
||||
async-trait = "0.1.73"
|
||||
rayon = "1.11.0"
|
||||
tokio = { version = "1.48.0", features = ["macros"] }
|
||||
tokio-util = { version = "0.7.16", features = ["compat"] }
|
||||
|
||||
# System
|
||||
battery = "0.7.8"
|
||||
temp-env = "0.3.6"
|
||||
open = { version = "5.3.2" }
|
||||
parking_lot = "0.12.1"
|
||||
thiserror = "1.0.44"
|
||||
walkdir = "2"
|
||||
chrono = { version = "0.4", default-features = false }
|
||||
time = "0.3"
|
||||
dirs = "6"
|
||||
fontdb = { version = "0.23", default-features = false }
|
||||
notify = "6"
|
||||
path-clean = "1.0.1"
|
||||
windows-sys = "0.61.2"
|
||||
tempfile = "3.19.1"
|
||||
same-file = "1.0.6"
|
||||
libc = "0.2.155"
|
||||
core-foundation = { version = "0.10.0", features = ["mac_os_10_7_support"] }
|
||||
half = "=2.6.0"
|
||||
|
||||
typst = "0.10.0"
|
||||
typst-ide = "0.10.0"
|
||||
typst-pdf = "0.10.0"
|
||||
typst-assets = { git = "https://github.com/typst/typst-assets", rev = "4d1211a" }
|
||||
typst-ts-core = { version = "0.4.2-rc7" }
|
||||
typst-ts-compiler = { version = "0.4.2-rc7" }
|
||||
typst-preview = { path = "external/typst-preview" }
|
||||
# Web
|
||||
js-sys = "^0.3"
|
||||
wasm-bindgen = "^0.2"
|
||||
wasm-bindgen-futures = "^0.4"
|
||||
wasm-bindgen-test = "0.3.45"
|
||||
web-sys = "^0.3"
|
||||
web-time = { version = "1.1.0" }
|
||||
console_error_panic_hook = { version = "0.1.7" }
|
||||
|
||||
lsp-server = "0.7.3"
|
||||
# Networking
|
||||
hyper = { version = "1", features = ["full"] }
|
||||
hyper-util = { version = "0.1.17", features = ["tokio"] }
|
||||
hyper-tungstenite = "0.19.0"
|
||||
reqwest = { version = "^0.12", default-features = false, features = [
|
||||
"rustls-tls",
|
||||
"blocking",
|
||||
"multipart",
|
||||
] }
|
||||
http-body-util = "0.1.3"
|
||||
|
||||
# Algorithms
|
||||
base64 = "0.22"
|
||||
regex = "1.12.2"
|
||||
|
||||
# Cryptography and data processing
|
||||
rustc-hash = { version = "2", features = ["std"] }
|
||||
siphasher = "1"
|
||||
fxhash = "0.2.1"
|
||||
sha2 = "0.10.9"
|
||||
nohash-hasher = "0.2.0"
|
||||
fastrand = "2.3.0"
|
||||
|
||||
# Data Structures
|
||||
bitvec = "1"
|
||||
comemo = "0.5.0"
|
||||
# We need to freeze the version of the crate, as the raw-api feature is considered unstable
|
||||
dashmap = { version = "=5.5.3", features = ["raw-api"] }
|
||||
ecow = "0.2.6"
|
||||
ena = "0.14.3"
|
||||
hashbrown = { version = "0.14", features = [
|
||||
"inline-more",
|
||||
], default-features = false }
|
||||
indexmap = "2.12.0"
|
||||
rpds = "1"
|
||||
|
||||
# Data/Text Format and Processing
|
||||
biblatex = "0.11"
|
||||
bytes = "1"
|
||||
cmark-writer = { version = "0.9.0", features = [
|
||||
"gfm",
|
||||
], path = "crates/cmark-writer" }
|
||||
docx-rs = { version = "0.4.18-rc19", git = "https://github.com/Myriad-Dreamin/docx-rs", default-features = false, rev = "db49a729f68dbdb9e8e91857fbb1c3d414209871" }
|
||||
hayagriva = "0.9.1"
|
||||
hex = "0.4.3"
|
||||
flate2 = "1"
|
||||
# typst can only support these formats.
|
||||
image = { version = "0.25.5", default-features = false, features = [
|
||||
"png",
|
||||
"jpeg",
|
||||
"gif",
|
||||
] }
|
||||
pathdiff = "0.2"
|
||||
percent-encoding = "2"
|
||||
rust_iso639 = "0.0.3"
|
||||
rust_iso3166 = "0.1.4"
|
||||
resvg = { version = "0.45" }
|
||||
rkyv = "0.7.42"
|
||||
semver = "1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
serde_repr = "0.1"
|
||||
serde_with = { version = "3.6", features = ["base64"] }
|
||||
serde_yaml = "0.9"
|
||||
serde-wasm-bindgen = "^0.6"
|
||||
tar = "0.4"
|
||||
toml = { version = "0.8", default-features = false, features = [
|
||||
"parse",
|
||||
"display",
|
||||
] }
|
||||
ttf-parser = "0.25.0"
|
||||
unicode-script = "0.5"
|
||||
unscanny = "0.1"
|
||||
yaml-rust2 = "0.9"
|
||||
|
||||
# Logging
|
||||
codespan-reporting = "0.11"
|
||||
env_logger = "0.11.3"
|
||||
log = "0.4"
|
||||
|
||||
# Typst
|
||||
reflexo = { version = "=0.7.0-rc2", default-features = false, features = [
|
||||
"flat-vector",
|
||||
] }
|
||||
reflexo-typst = { version = "=0.7.0-rc2", default-features = false }
|
||||
reflexo-vec2svg = { version = "=0.7.0-rc2" }
|
||||
|
||||
typst = "0.14.2"
|
||||
typst-html = "0.14.2"
|
||||
typst-library = "0.14.2"
|
||||
typst-macros = "0.14.2"
|
||||
typst-timing = "0.14.2"
|
||||
typst-svg = "0.14.2"
|
||||
typst-render = "0.14.2"
|
||||
typst-pdf = "0.14.2"
|
||||
typst-syntax = "0.14.2"
|
||||
typst-eval = "0.14.2"
|
||||
typst-assets = "0.14.2"
|
||||
typstfmt = { version = "0", git = "https://github.com/Myriad-Dreamin/typstfmt", tag = "v0.13.1" }
|
||||
typst-ansi-hl = "0.4.0"
|
||||
typstyle-core = { version = "=0.14.0", default-features = false }
|
||||
|
||||
# LSP
|
||||
crossbeam-channel = "0.5.15"
|
||||
lsp-types = { version = "=0.95.0", features = ["proposed"] }
|
||||
crossbeam-channel = "0.5.8"
|
||||
dapts = "0.0.6"
|
||||
|
||||
clap = { version = "4.4", features = ["derive", "env", "unicode", "wrap_help"] }
|
||||
clap_builder = { version = "4", features = ["string"] }
|
||||
clap_complete = "4.4"
|
||||
clap_complete_fig = "4.4"
|
||||
clap_mangen = { version = "0.2.15" }
|
||||
vergen = { version = "8.2.5", features = [
|
||||
# CLI
|
||||
clap = { version = "4.5", features = ["derive", "env", "unicode"] }
|
||||
clap_builder = { version = "4.5", features = ["string"] }
|
||||
clap_complete = "4.5"
|
||||
clap_complete_fig = "4.5"
|
||||
clap_complete_nushell = "4.5.3"
|
||||
clap_mangen = { version = "0.2.22" }
|
||||
vergen = { version = "8.3.1", features = [
|
||||
"build",
|
||||
"cargo",
|
||||
"git",
|
||||
"gitcl",
|
||||
"rustc",
|
||||
] }
|
||||
tokio = { version = "1.34.0", features = [
|
||||
"macros",
|
||||
"rt-multi-thread",
|
||||
"io-std",
|
||||
] }
|
||||
tokio-util = "0.7.10"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
|
||||
divan = "0.1.7"
|
||||
insta = { vesrion = "1.34", features = ["glob"] }
|
||||
# Testing
|
||||
dhat = "0.3.3"
|
||||
divan = "0.1.21"
|
||||
insta = { version = "1.43", features = ["glob", "filters"] }
|
||||
insta-cmd = "0.6.0"
|
||||
|
||||
|
||||
# Our Own Crates
|
||||
tinymist-assets = { version = "=0.14.6-rc1" }
|
||||
|
||||
tinymist-derive = { path = "./crates/tinymist-derive/", version = "0.14.6-rc2" }
|
||||
tinymist-l10n = { path = "./crates/tinymist-l10n/", version = "0.14.6-rc2" }
|
||||
tinymist-package = { path = "./crates/tinymist-package/", version = "0.14.6-rc2" }
|
||||
tinymist-std = { path = "./crates/tinymist-std/", version = "0.14.6-rc2", default-features = false }
|
||||
tinymist-vfs = { path = "./crates/tinymist-vfs/", version = "0.14.6-rc2", default-features = false }
|
||||
tinymist-world = { path = "./crates/tinymist-world/", version = "0.14.6-rc2", default-features = false }
|
||||
tinymist-project = { path = "./crates/tinymist-project/", version = "0.14.6-rc2" }
|
||||
tinymist-task = { path = "./crates/tinymist-task/", version = "0.14.6-rc2" }
|
||||
typst-shim = { path = "./crates/typst-shim", version = "0.14.6-rc2" }
|
||||
|
||||
tinymist-tests = { path = "./crates/tinymist-tests/" }
|
||||
|
||||
sync-ls = { path = "./crates/sync-lsp", version = "0.14.6-rc1" }
|
||||
tinymist = { path = "./crates/tinymist/", version = "0.14.6-rc1", default-features = false }
|
||||
tinymist-analysis = { path = "./crates/tinymist-analysis/", version = "0.14.6-rc1" }
|
||||
tinymist-cli = { path = "./crates/tinymist-cli/", version = "0.14.6-rc1" }
|
||||
tinymist-debug = { path = "./crates/tinymist-debug/", version = "0.14.6-rc1" }
|
||||
tinymist-lint = { path = "./crates/tinymist-lint/", version = "0.14.6-rc1" }
|
||||
tinymist-query = { path = "./crates/tinymist-query/", version = "0.14.6-rc1" }
|
||||
tinymist-render = { path = "./crates/tinymist-render/", version = "0.14.6-rc1" }
|
||||
tinymist-preview = { path = "./crates/typst-preview", version = "0.14.6-rc1" }
|
||||
typlite = { path = "./crates/typlite", version = "0.14.6-rc1", default-features = false }
|
||||
|
||||
[profile.dev.package.insta]
|
||||
opt-level = 3
|
||||
|
|
@ -76,33 +223,115 @@ opt-level = 3
|
|||
opt-level = 3
|
||||
|
||||
[profile.release]
|
||||
lto = true # Enable link-time optimization
|
||||
debug = true
|
||||
opt-level = 3 # Optimize for speed
|
||||
# lto = true # Enable link-time optimization
|
||||
codegen-units = 1 # Reduce number of codegen units to increase optimizations
|
||||
panic = 'abort' # Abort on panic
|
||||
panic = "abort" # Abort on panic
|
||||
|
||||
[profile.gh-release]
|
||||
inherits = "release"
|
||||
debug = true
|
||||
|
||||
# The profile that 'dist' will build with
|
||||
[profile.dist]
|
||||
inherits = "release"
|
||||
lto = "thin"
|
||||
|
||||
[workspace.lints.rustdoc]
|
||||
broken_intra_doc_links = "warn"
|
||||
|
||||
[workspace.lints.rust]
|
||||
missing_docs = "warn"
|
||||
# missing_crate_level_docs = "warn"
|
||||
|
||||
unexpected_cfgs = { level = "allow", check-cfg = [
|
||||
'cfg(wasm_bindgen_unstable_test_coverage)',
|
||||
'cfg(noop)',
|
||||
'cfg(used_linker)',
|
||||
] }
|
||||
|
||||
[workspace.lints.clippy]
|
||||
uninlined_format_args = "warn"
|
||||
# missing_errors_doc = "warn"
|
||||
# missing_panics_doc = "warn"
|
||||
# missing_docs_in_private_items = "warn"
|
||||
missing_safety_doc = "warn"
|
||||
undocumented_unsafe_blocks = "warn"
|
||||
|
||||
[patch.crates-io]
|
||||
typst = { git = "https://github.com/Myriad-Dreamin/typst.git", branch = "tinymist-v0.11.0" }
|
||||
typst-ide = { git = "https://github.com/Myriad-Dreamin/typst.git", branch = "tinymist-v0.11.0" }
|
||||
typst-pdf = { git = "https://github.com/Myriad-Dreamin/typst.git", branch = "tinymist-v0.11.0" }
|
||||
typst-syntax = { git = "https://github.com/Myriad-Dreamin/typst.git", branch = "tinymist-v0.11.0" }
|
||||
[workspace.metadata.typos.default]
|
||||
locale = "en-us"
|
||||
|
||||
[workspace.metadata.typos.default.extend-words]
|
||||
labelled = "labelled"
|
||||
onces = "onces"
|
||||
withs = "withs"
|
||||
|
||||
[workspace.metadata.typos.files]
|
||||
ignore-hidden = false
|
||||
extend-exclude = ["/.git", "fixtures"]
|
||||
|
||||
[patch.crates-io]
|
||||
|
||||
# This patch is used to bundle a locally built frontend (HTML) of `typst-preview`.
|
||||
# The shortcoming is that you cannot install tinymist from git source then, i.e. `cargo install --git ..`, with this patch.
|
||||
# However, it is not suggested to install it in that way. The suggested ways are:
|
||||
# - Installation: https://github.com/Myriad-Dreamin/tinymist?tab=readme-ov-file#installation
|
||||
# - Installing pre-built artifacts from GitHub : https://github.com/Myriad-Dreamin/tinymist?tab=readme-ov-file#installing-regularnightly-prebuilds-from-github
|
||||
# tinymist-assets = { path = "./crates/tinymist-assets/" }
|
||||
|
||||
# These patches use a different version of `typst`, which only exports some private functions and information for code analysis.
|
||||
#
|
||||
# A regular build MUST use `tag` or `rev` to specify the version of the patched crate to ensure stability.
|
||||
typst = { git = "https://github.com/Myriad-Dreamin/typst.git", tag = "tinymist/v0.14.6-rc2" }
|
||||
typst-macros = { git = "https://github.com/Myriad-Dreamin/typst.git", tag = "tinymist/v0.14.6-rc2" }
|
||||
typst-library = { git = "https://github.com/Myriad-Dreamin/typst.git", tag = "tinymist/v0.14.6-rc2" }
|
||||
typst-html = { git = "https://github.com/Myriad-Dreamin/typst.git", tag = "tinymist/v0.14.6-rc2" }
|
||||
typst-timing = { git = "https://github.com/Myriad-Dreamin/typst.git", tag = "tinymist/v0.14.6-rc2" }
|
||||
typst-svg = { git = "https://github.com/Myriad-Dreamin/typst.git", tag = "tinymist/v0.14.6-rc2" }
|
||||
typst-render = { git = "https://github.com/Myriad-Dreamin/typst.git", tag = "tinymist/v0.14.6-rc2" }
|
||||
typst-pdf = { git = "https://github.com/Myriad-Dreamin/typst.git", tag = "tinymist/v0.14.6-rc2" }
|
||||
typst-syntax = { git = "https://github.com/Myriad-Dreamin/typst.git", tag = "tinymist/v0.14.6-rc2" }
|
||||
typst-eval = { git = "https://github.com/Myriad-Dreamin/typst.git", tag = "tinymist/v0.14.6-rc2" }
|
||||
|
||||
# typst-ansi-hl = { git = "https://github.com/ParaN3xus/typst-ansi-hl.git", branch = "nightly" }
|
||||
# typstyle-core = { git = "https://github.com/ParaN3xus/typstyle/", rev = "34869bfa9db089c5196be5fac2a5e9d752904ca2" }
|
||||
|
||||
# These patches use local `typst` for development.
|
||||
# typst = { path = "../typst/crates/typst" }
|
||||
# typst-ide = { path = "../typst/crates/typst-ide" }
|
||||
# typst-timing = { path = "../typst/crates/typst-timing" }
|
||||
# typst-svg = { path = "../typst/crates/typst-svg" }
|
||||
# typst-pdf = { path = "../typst/crates/typst-pdf" }
|
||||
# typst-render = { path = "../typst/crates/typst-render" }
|
||||
# typst-syntax = { path = "../typst/crates/typst-syntax" }
|
||||
|
||||
typst-ts-svg-exporter = { git = "https://github.com/Myriad-Dreamin/typst.ts", rev = "58c2c6b07831cffb8915776c45058754c505033b", package = "typst-ts-svg-exporter" }
|
||||
typst-ts-core = { git = "https://github.com/Myriad-Dreamin/typst.ts", rev = "58c2c6b07831cffb8915776c45058754c505033b", package = "typst-ts-core" }
|
||||
typst-ts-compiler = { git = "https://github.com/Myriad-Dreamin/typst.ts", rev = "58c2c6b07831cffb8915776c45058754c505033b", package = "typst-ts-compiler" }
|
||||
# These patches use local `typstyle-core` for development.
|
||||
# typstyle-core = { path = "../typstyle/crates/typstyle-core" }
|
||||
|
||||
# These patches use a different version of `reflexo`.
|
||||
#
|
||||
# A regular build MUST use `tag` or `rev` to specify the version of the patched crate to ensure stability.
|
||||
reflexo = { git = "https://github.com/Myriad-Dreamin/typst.ts/", rev = "c078ddf869d9438b36e1cacb65100e4514780dc1" }
|
||||
reflexo-typst = { git = "https://github.com/Myriad-Dreamin/typst.ts/", rev = "c078ddf869d9438b36e1cacb65100e4514780dc1" }
|
||||
reflexo-vec2svg = { git = "https://github.com/Myriad-Dreamin/typst.ts/", rev = "c078ddf869d9438b36e1cacb65100e4514780dc1" }
|
||||
|
||||
# These patches use local `reflexo` for development.
|
||||
# reflexo = { path = "../typst.ts/crates/reflexo/" }
|
||||
# reflexo-typst = { path = "../typst.ts/crates/reflexo-typst/" }
|
||||
# reflexo-vec2svg = { path = "../typst.ts/crates/conversion/vec2svg/" }
|
||||
|
||||
typst-shim = { path = "crates/typst-shim" }
|
||||
tinymist-analysis = { path = "crates/tinymist-analysis" }
|
||||
tinymist-std = { path = "crates/tinymist-std" }
|
||||
tinymist-vfs = { path = "crates/tinymist-vfs" }
|
||||
tinymist-world = { path = "crates/tinymist-world" }
|
||||
tinymist-project = { path = "crates/tinymist-project" }
|
||||
tinymist-task = { path = "crates/tinymist-task" }
|
||||
|
||||
# If reflexo use the tinymist from git, you should use the following patch.
|
||||
# [patch."https://github.com/ParaN3xus/tinymist.git"]
|
||||
# typst-shim = { path = "crates/typst-shim" }
|
||||
# tinymist-analysis = { path = "crates/tinymist-analysis" }
|
||||
# tinymist-std = { path = "crates/tinymist-std" }
|
||||
# tinymist-vfs = { path = "crates/tinymist-vfs" }
|
||||
# tinymist-world = { path = "crates/tinymist-world" }
|
||||
# tinymist-project = { path = "crates/tinymist-project" }
|
||||
# tinymist-task = { path = "crates/tinymist-task" }
|
||||
|
|
|
|||
48
Dockerfile
Normal file
48
Dockerfile
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# ```shell
|
||||
# docker build -t myriaddreamin/tinymist:latest .
|
||||
# ```
|
||||
#
|
||||
# ## References
|
||||
#
|
||||
# https://stackoverflow.com/questions/58473606/cache-rust-dependencies-with-docker-build
|
||||
# https://stackoverflow.com/a/64528456
|
||||
# https://depot.dev/blog/rust-dockerfile-best-practices
|
||||
|
||||
ARG RUST_VERSION=1.89.0
|
||||
|
||||
FROM rust:${RUST_VERSION}-bookworm AS base
|
||||
RUN apt-get install -y git
|
||||
RUN cargo install sccache --version ^0.7
|
||||
RUN cargo install cargo-chef --version ^0.1
|
||||
ENV RUSTC_WRAPPER=sccache SCCACHE_DIR=/sccache
|
||||
# to download the toolchain
|
||||
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
||||
--mount=type=cache,target=$SCCACHE_DIR,sharing=locked \
|
||||
rustup update
|
||||
|
||||
FROM base as planner
|
||||
WORKDIR app
|
||||
# We only pay the installation cost once,
|
||||
# it will be cached from the second build onwards
|
||||
RUN cargo install cargo-chef
|
||||
COPY . .
|
||||
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
||||
--mount=type=cache,target=$SCCACHE_DIR,sharing=locked \
|
||||
cargo +${RUST_VERSION} chef prepare --recipe-path recipe.json
|
||||
|
||||
FROM base as builder
|
||||
WORKDIR app
|
||||
RUN cargo install cargo-chef
|
||||
COPY --from=planner /app/recipe.json recipe.json
|
||||
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
||||
--mount=type=cache,target=$SCCACHE_DIR,sharing=locked \
|
||||
cargo +${RUST_VERSION} chef cook --release --recipe-path recipe.json
|
||||
COPY . .
|
||||
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
||||
--mount=type=cache,target=$SCCACHE_DIR,sharing=locked \
|
||||
cargo +${RUST_VERSION} build --bin tinymist --release
|
||||
|
||||
FROM debian:12
|
||||
WORKDIR /app/
|
||||
COPY --from=builder /app/target/release/tinymist /usr/local/bin
|
||||
ENTRYPOINT ["/usr/local/bin/tinymist"]
|
||||
2
LICENSE
2
LICENSE
|
|
@ -186,7 +186,7 @@
|
|||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2023 Myriad Dreamin, Nathan Varner
|
||||
Copyright 2023-2025 Myriad Dreamin, Nathan Varner
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
56
MAINTAINERS.md
Normal file
56
MAINTAINERS.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<!-- This file is generated by scripts/link-docs.mjs. Do not edit manually. -->
|
||||
|
||||
# Tinymist Maintainers
|
||||
|
||||
|
||||
Tinymist [ˈtaɪni mɪst] is an integrated language service for [Typst](https://typst.app/) [taɪpst].
|
||||
|
||||
This page is generated from [./MAINTAINERS.typ](./MAINTAINERS.typ) and renders information of [maintainers](#maintainers) and [features.](#features)
|
||||
|
||||
## Maintainers
|
||||
|
||||
- [**Myriad-Dreamin**](https://github.com/Myriad-Dreamin)
|
||||
- Email: camiyoru@gmail.com
|
||||
- Maintains: *[Editor Integration](#editor-integration)*, *[Language Service](#language-service)*, *[Document Previewing](#document-previewing)*, *[VS Code Client-Side Support](#vs-code-client-side-support)*, and *[Nightly Releases](#nightly-releases)*
|
||||
|
||||
- [**Enter-tainer**](https://github.com/Enter-tainer)
|
||||
- Email: mgt@oi-wiki.org
|
||||
- Maintains: *[Editor Integration](#editor-integration)*, *[Language Service](#language-service)*, *[Document Previewing](#document-previewing)*, and *[VS Code Client-Side Support](#vs-code-client-side-support)*
|
||||
|
||||
- [**ParaN3xus**](https://github.com/ParaN3xus)
|
||||
- Email: paran3xus007@gmail.com
|
||||
- Maintains: *[Nightly Releases](#nightly-releases)*
|
||||
|
||||
- [**Max397**](https://github.com/max397574)
|
||||
- Email: undefined
|
||||
- Maintains: *[Editor Integration](#editor-integration)*
|
||||
|
||||
- [**Ericoolen**](https://github.com/Eric-Song-Nop)
|
||||
- Email: EricYFSong@gmail.com
|
||||
- Maintains: *[Language Service](#language-service)*
|
||||
|
||||
- [**Caleb Maclennan**](https://github.com/alerque)
|
||||
- Email: caleb@alerque.com
|
||||
- Maintains: *[Editor Integration](#editor-integration)*
|
||||
|
||||
- [**SylvanFranklin**](https://github.com/SylvanFranklin)
|
||||
- Email: sylvanfranklin@icloud.com
|
||||
- Maintains: *[Editor Integration](#editor-integration)*, and *[Document Previewing](#document-previewing)*
|
||||
|
||||
## Features
|
||||
|
||||
### Editor Integration
|
||||
Integrate tinymist server with popular editors like VS Code, Neovim, etc.
|
||||
- Scope: [`crates/tinymist/`](./crates/tinymist/), [`editors/`](./editors/)
|
||||
### Language Service
|
||||
Perform code analysis and provide language support for Typst.
|
||||
- Scope: [`crates/tinymist/`](./crates/tinymist/), [`crates/tinymist-analysis/`](./crates/tinymist-analysis/), [`crates/tinymist-query/`](./crates/tinymist-query/)
|
||||
### Document Previewing
|
||||
Provide instant preview of the document being edited.
|
||||
- Scope: [`crates/tinymist/`](./crates/tinymist/), [`crates/typst-preview/`](./crates/typst-preview/), [`contrib/typst-preview/`](./contrib/typst-preview/), [`tools/typst-dom/`](./tools/typst-dom/), [`tools/typst-preview-frontend/`](./tools/typst-preview-frontend/)
|
||||
### VS Code Client-Side Support
|
||||
Enrich the VS Code features with the client-side extension.
|
||||
- Scope: [`crates/tinymist/`](./crates/tinymist/), [`editors/vscode/`](./editors/vscode/), [`tools/editor-tools/`](./tools/editor-tools/)
|
||||
### Nightly Releases
|
||||
Build and Publish nightly releases of tinymist. The nightly releases are built upon the main branches of both tinymist and typst.
|
||||
- Scope: [`crates/tinymist/`](./crates/tinymist/), [`crates/typst-shim/`](./crates/typst-shim/)
|
||||
99
MAINTAINERS.typ
Normal file
99
MAINTAINERS.typ
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
|
||||
#import "typ/templates/maintainer.typ": *
|
||||
#show: main
|
||||
|
||||
#let editor-integration = [Editor Integration]
|
||||
#let language-service = [Language Service]
|
||||
#let document-previewing = [Document Previewing]
|
||||
#let vs-code-client-side-support = [VS Code Client-Side Support]
|
||||
#let nightly-releases = [Nightly Releases]
|
||||
|
||||
== Maintainers
|
||||
|
||||
#maintainers[
|
||||
- Myriad-Dreamin
|
||||
- #github("Myriad-Dreamin")
|
||||
- #email("camiyoru@gmail.com")
|
||||
- #maintains[
|
||||
- #editor-integration
|
||||
- #language-service
|
||||
- #document-previewing
|
||||
- #vs-code-client-side-support
|
||||
- #nightly-releases
|
||||
]
|
||||
- Enter-tainer
|
||||
- #github("Enter-tainer")
|
||||
- #email("mgt@oi-wiki.org")
|
||||
- #maintains[
|
||||
- #editor-integration
|
||||
- #language-service
|
||||
- #document-previewing
|
||||
- #vs-code-client-side-support
|
||||
]
|
||||
- ParaN3xus
|
||||
- #github("ParaN3xus")
|
||||
- #email("paran3xus007@gmail.com")
|
||||
- #maintains[
|
||||
- #nightly-releases
|
||||
]
|
||||
- Max397
|
||||
- #github("max397574")
|
||||
- #maintains[
|
||||
- #editor-integration
|
||||
]
|
||||
- Ericoolen
|
||||
- #github("Eric-Song-Nop")
|
||||
- #email("EricYFSong@gmail.com")
|
||||
- #maintains[
|
||||
- #language-service
|
||||
]
|
||||
- Caleb Maclennan
|
||||
- #github("alerque")
|
||||
- #email("caleb@alerque.com")
|
||||
- #maintains[
|
||||
- #editor-integration
|
||||
]
|
||||
- SylvanFranklin
|
||||
- #github("SylvanFranklin")
|
||||
- #email("sylvanfranklin@icloud.com")
|
||||
- #maintains[
|
||||
- #editor-integration
|
||||
- #document-previewing
|
||||
]
|
||||
]
|
||||
|
||||
== Features
|
||||
|
||||
#features[
|
||||
- #editor-integration
|
||||
- #scope("crates/tinymist/", "editors/")
|
||||
- #description[
|
||||
Integrate tinymist server with popular editors like VS Code, Neovim, etc.
|
||||
]
|
||||
- #language-service
|
||||
- #scope("crates/tinymist/", "crates/tinymist-analysis/", "crates/tinymist-query/")
|
||||
- #description[
|
||||
Perform code analysis and provide language support for Typst.
|
||||
]
|
||||
- #document-previewing
|
||||
- #scope(
|
||||
"crates/tinymist/",
|
||||
"crates/typst-preview/",
|
||||
"contrib/typst-preview/",
|
||||
"tools/typst-dom/",
|
||||
"tools/typst-preview-frontend/",
|
||||
)
|
||||
- #description[
|
||||
Provide instant preview of the document being edited.
|
||||
]
|
||||
- #vs-code-client-side-support
|
||||
- #scope("crates/tinymist/", "editors/vscode/", "tools/editor-tools/")
|
||||
- #description[
|
||||
Enrich the VS Code features with the client-side extension.
|
||||
]
|
||||
- #nightly-releases
|
||||
- #scope("crates/tinymist/", "crates/typst-shim/")
|
||||
- #description[
|
||||
Build and Publish nightly releases of tinymist. The nightly releases are built upon the main branches of both tinymist and typst.
|
||||
]
|
||||
]
|
||||
211
README.md
211
README.md
|
|
@ -1,49 +1,228 @@
|
|||
<!-- This file is generated by scripts/link-docs.mjs. Do not edit manually. -->
|
||||
# Tinymist
|
||||
|
||||
Tinymist [ˈtaɪni mɪst] is an integrated language service for [Typst](https://typst.app/) [taɪpst]. You can also call it "微霭" [wēi ǎi] in Chinese.
|
||||
[<img src="https://img.shields.io/github/license/Myriad-Dreamin/tinymist" alt="GitHub license" />](https://github.com/Myriad-Dreamin/tinymist/blob/main/LICENSE)[<img src="https://github.com/Myriad-Dreamin/tinymist/actions/workflows/ci.yml/badge.svg?event=push" alt="Actions status" />](https://github.com/Myriad-Dreamin/tinymist/actions/workflows/ci.yml)[<img src="https://img.shields.io/badge/view-documentation-blue" alt="Documentation" />](https://myriad-dreamin.github.io/tinymist/)[<img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki" />](https://deepwiki.com/Myriad-Dreamin/tinymist)
|
||||
|
||||
Tinymist \[ˈtaɪni mɪst\] is an integrated language service for [Typst](https://typst.app/) \[taɪpst\]. You can also call it <ruby>
|
||||
|
||||
微<rt>
|
||||
|
||||
wēi
|
||||
|
||||
</rt>
|
||||
|
||||
</ruby><ruby>
|
||||
|
||||
霭<rt>
|
||||
|
||||
ǎi
|
||||
|
||||
</rt>
|
||||
|
||||
</ruby> in Chinese.
|
||||
|
||||
It contains:
|
||||
- an analyzing library for Typst, see [tinymist-query](./crates/tinymist-query/).
|
||||
- a CLI for Typst, see [tinymist](./crates/tinymist/).
|
||||
- which provides a language server for Typst.
|
||||
- a VSCode extension for Typst, see [Tinymist VSCode Extension](./editors/vscode/).
|
||||
|
||||
- an analyzing library for Typst, see [tinymist-query](/crates/tinymist-query/).
|
||||
- a CLI for Typst, see [tinymist](/crates/tinymist/).
|
||||
- which provides a language server for Typst, see [Language Features](https://myriad-dreamin.github.io/tinymist/feature/language.html).
|
||||
- which provides a preview server for Typst, see [Preview Feature](https://myriad-dreamin.github.io/tinymist/feature/preview.html).
|
||||
- a VSCode extension for Typst, see [Tinymist VSCode Extension](/editors/vscode/).
|
||||
|
||||
## Features
|
||||
|
||||
Language service (LSP) features:
|
||||
|
||||
- [Semantic highlighting](https://code.visualstudio.com/api/language-extensions/semantic-highlight-guide)
|
||||
- Also known as "syntax highlighting".
|
||||
- [Diagnostics](https://code.visualstudio.com/api/language-extensions/programmatic-language-features#provide-diagnostics)
|
||||
- Also known as "error checking" or "error reporting".
|
||||
- The “semantic highlighting” is supplementary to [“syntax highlighting”](https://code.visualstudio.com/api/language-extensions/syntax-highlight-guide).
|
||||
- [Code actions](https://code.visualstudio.com/api/language-extensions/programmatic-language-features#provide-code-actions)
|
||||
- Also known as “quick fixes” or “refactorings”.
|
||||
- [Formatting (Reformatting)](https://code.visualstudio.com/api/language-extensions/programmatic-language-features#format-source-code-in-an-editor)
|
||||
- Provide the user with support for formatting whole documents, using [typstfmt](https://github.com/astrale-sharp/typstfmt) or [typstyle](https://github.com/Enter-tainer/typstyle).
|
||||
- [Document highlight](https://code.visualstudio.com/api/language-extensions/programmatic-language-features#highlight-all-occurrences-of-a-symbol-in-a-document)
|
||||
- Highlight all break points in a loop context.
|
||||
- (Todo) Highlight all exit points in a function context.
|
||||
- (Todo) Highlight all captures in a closure context.
|
||||
- (Todo) Highlight all occurrences of a symbol in a document.
|
||||
- [Document links](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentLink)
|
||||
- Renders path or link references in the document, such as `image("path.png")` or `bibliography(style: "path.csl")`.
|
||||
- [Document symbols](https://code.visualstudio.com/docs/getstarted/userinterface#_outline-view)
|
||||
- Also known as "document outline" or "table of contents" **in Typst**.
|
||||
- Also known as “document outline” or “table of contents” _in Typst_.
|
||||
- [Folding ranges](https://burkeholland.gitbook.io/vs-code-can-do-that/exercise-3-navigation-and-refactoring/folding-sections)
|
||||
- You can collapse code/content blocks and headings.
|
||||
- [Goto definitions](https://code.visualstudio.com/api/language-extensions/programmatic-language-features#show-definitions-of-a-symbol)
|
||||
- Right-click on a symbol and select "Go to Definition".
|
||||
- Right-click on a symbol and select “Go to Definition”.
|
||||
- Or ctrl+click on a symbol.
|
||||
- [References](https://code.visualstudio.com/api/language-extensions/programmatic-language-features#find-all-references-to-a-symbol)
|
||||
- Right-click on a symbol and select “Go to References” or “Find References”.
|
||||
- Or ctrl+click on a symbol.
|
||||
<!-- - [Goto declarations](https://code.visualstudio.com/api/language-extensions/programmatic-language-features#find-all-references-to-a-symbol)
|
||||
- Also known as "find all references". -->
|
||||
- [Hover tips](https://code.visualstudio.com/api/language-extensions/programmatic-language-features#show-hovers)
|
||||
- Also known as "hovering tooltip".
|
||||
- Also known as “hovering tooltip”.
|
||||
- Render docs according to [tidy](https://github.com/Mc-Zen/tidy) style.
|
||||
- [Inlay hints](https://www.jetbrains.com/help/idea/inlay-hints.html)
|
||||
- Inlay hints are special markers that appear in the editor and provide you with additional information about your code, like the names of the parameters that a called method expects.
|
||||
- [Color Provider](https://code.visualstudio.com/api/language-extensions/programmatic-language-features#show-color-decorators)
|
||||
- View all inlay colorful label for color literals in your document.
|
||||
- Change the color literal’s value by a color picker or its code presentation.
|
||||
- [Code Lens](https://code.visualstudio.com/blogs/2017/02/12/code-lens-roundup)
|
||||
- Should give contextual buttons along with code. For example, a button for exporting your document to various formats at the start of the document.
|
||||
- [Rename symbols](https://code.visualstudio.com/api/language-extensions/programmatic-language-features#rename-symbols)
|
||||
- [Rename symbols and embedded paths](https://code.visualstudio.com/api/language-extensions/programmatic-language-features#rename-symbols)
|
||||
- [Help with function and method signatures](https://code.visualstudio.com/api/language-extensions/programmatic-language-features#help-with-function-and-method-signatures)
|
||||
- [Workspace Symbols](https://code.visualstudio.com/api/language-extensions/programmatic-language-features#show-all-symbol-definitions-in-folder)
|
||||
- [Code Action](https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/devenv-code-actions)
|
||||
- Increasing/Decreasing heading levels.
|
||||
- Turn equation into “inline”, “block” or “multiple-line block” styles.
|
||||
- [experimental/onEnter](https://github.com/rust-lang/rust-analyzer/blob/master/docs/dev/lsp-extensions.md#on-enter)
|
||||
- <kbd>
|
||||
|
||||
Enter
|
||||
|
||||
</kbd> inside triple-slash comments automatically inserts `///`
|
||||
- <kbd>
|
||||
|
||||
Enter
|
||||
|
||||
</kbd> in the middle or after a trailing space in `//` inserts `//`
|
||||
- <kbd>
|
||||
|
||||
Enter
|
||||
|
||||
</kbd> inside `//!` doc comments automatically inserts `//!`
|
||||
- <kbd>
|
||||
|
||||
Enter
|
||||
|
||||
</kbd> inside equation markups automatically inserts indents.
|
||||
|
||||
Extra features:
|
||||
|
||||
- Compiles to PDF on save (configurable to as-you-type, or other options)
|
||||
- Compiles to PDF on save (configurable to as-you-type, or other options). Check [Docs: Exporting Documents](https://myriad-dreamin.github.io/tinymist/feature/export.html).
|
||||
- Also compiles to SVG, PNG, HTML, Markdown, Text, and other formats by commands, vscode tasks, or code lenses.
|
||||
- Provides test, benchmark, coverage collecting on documents and modules. Check [Docs: Testing Features](https://myriad-dreamin.github.io/tinymist/feature/testing.html).
|
||||
- Provides builtin linting. Check [Docs: Linting Features](https://myriad-dreamin.github.io/tinymist/feature/linting.html).
|
||||
- Provides a status bar item to show the current document’s compilation status and words count.
|
||||
- [Editor tools](/tools/editor-tools/):
|
||||
- View a list of templates in template gallery. (`tinymist.showTemplateGallery`)
|
||||
- Click a button in template gallery to initialize a new project with a template. (`tinymist.initTemplate` and `tinymist.initTemplateInPlace`)
|
||||
- Trace execution in current document (`tinymist.profileCurrentFile`).
|
||||
|
||||
## Versioning and Release Cycle
|
||||
|
||||
Tinymist’s versions follow the [Semantic Versioning](https://semver.org/) scheme, in format of `MAJOR.MINOR.PATCH`. Besides, tinymist follows special rules for the version number:
|
||||
|
||||
- If a version is suffixed with `-rcN` (<picture>
|
||||
|
||||
<source media="(prefers-color-scheme: dark)" srcset="assets/images/introduction/frame_0.svg" /><img src="assets/images/introduction/frame_1.svg" alt="typst-frame" />
|
||||
|
||||
</picture>), e.g. `0.11.0-rc1` and `0.12.1-rc1`, it means this version is a release candidate. It is used to test publish script and E2E functionalities. These versions will not be published to the marketplace.
|
||||
- If the `PATCH` number is odd, e.g. `0.11.1` and `0.12.3`, it means this version is a nightly release. The nightly release will use both [tinymist](https://github.com/Myriad-Dreamin/tinymist/tree/main) and [typst](https://github.com/typst/typst/tree/main) at **main branch**. They will be published as prerelease version to the marketplace. Note that in nightly releases, we change `#sys.version` to the next minor release to help develop documents with nightly features. For example, in tinymist nightly v0.12.1 or v0.12.3, the `#sys.version` is changed to `version(0, 13, 0)`.
|
||||
- Otherwise, if the `PATCH` number is even, e.g. `0.11.0` and `0.12.2`, it means this version is a regular release. The regular release will always use the recent stable version of tinymist and typst.
|
||||
|
||||
The release cycle is as follows:
|
||||
|
||||
- If there is a typst version update, a new major or minor version will be released intermediately. This means tinymist will always align the minor version with typst.
|
||||
- If there is at least a bug or feature added this week, a new patch version will be released.
|
||||
|
||||
## Installation
|
||||
|
||||
Follow the instructions to enable tinymist in your favorite editor.
|
||||
+ [VSCode](./editors/vscode/README.md)
|
||||
|
||||
- [VS Cod(e,ium)](https://myriad-dreamin.github.io/tinymist/frontend/vscode.html)
|
||||
- [Neovim](https://myriad-dreamin.github.io/tinymist/frontend/neovim.html)
|
||||
- [Emacs](https://myriad-dreamin.github.io/tinymist/frontend/emacs.html)
|
||||
- [Sublime Text](https://myriad-dreamin.github.io/tinymist/frontend/sublime-text.html)
|
||||
- [Helix](https://myriad-dreamin.github.io/tinymist/frontend/helix.html)
|
||||
- [Zed](https://myriad-dreamin.github.io/tinymist/frontend/zed.html)
|
||||
|
||||
## Installing Regular/Nightly Prebuilds from GitHub
|
||||
|
||||
Note: if you are not knowing what is a regular/nightly release, please don’t follow this section.
|
||||
|
||||
Besides published releases specific for each editors, you can also download the latest regular/nightly prebuilts from GitHub and install them manually.
|
||||
|
||||
- Regular prebuilts can be found in [GitHub Releases](https://github.com/Myriad-Dreamin/tinymist/releases).
|
||||
- Nightly prebuilts can be found in [GitHub Actions](https://github.com/Myriad-Dreamin/tinymist/actions).
|
||||
- (Suggested) Use the [tinymist-nightly-installer](https://github.com/hongjr03/tinymist-nightly-installer) to install the nightly prebuilts automatically.
|
||||
- Unix (Bash):
|
||||
```bash
|
||||
curl -sSL https://github.com/hongjr03/tinymist-nightly-installer/releases/latest/download/run.sh | bash
|
||||
```
|
||||
- Windows (PowerShell):
|
||||
```bash
|
||||
iwr https://github.com/hongjr03/tinymist-nightly-installer/releases/latest/download/run.ps1 -UseBasicParsing | iex
|
||||
```
|
||||
- The prebuilts for other revisions can also be found manually. For example, if you are seeking a nightly release for the featured [PR: build: bump version to 0.11.17-rc1](https://github.com/Myriad-Dreamin/tinymist/pull/468), you could click and go to the [action page](https://github.com/Myriad-Dreamin/tinymist/actions/runs/10120639466) run for the related commits and download the artifacts.
|
||||
|
||||
To install extension file (the file with `.vsix` extension) manually, please <kbd>
|
||||
|
||||
Ctrl+Shift+X
|
||||
|
||||
</kbd> in the editor window and drop the downloaded vsix file into the opened extensions view.
|
||||
|
||||
## Documentation
|
||||
|
||||
See [Online Documentation](https://myriad-dreamin.github.io/tinymist/).
|
||||
|
||||
## Packaging
|
||||
|
||||
Stable Channel:
|
||||
|
||||
<a href="https://repology.org/project/tinymist/versions" target="_blank" rel="noopener noreferrer">
|
||||
|
||||
<img src="https://repology.org/badge/vertical-allrepos/tinymist.svg" alt="Packaging status" style="max-width: 100%; height: auto;" />
|
||||
|
||||
</a>
|
||||
|
||||
Nightly Channel:
|
||||
|
||||
<a href="https://repology.org/project/tinymist-nightly/versions" target="_blank" rel="noopener noreferrer">
|
||||
|
||||
<img src="https://repology.org/badge/vertical-allrepos/tinymist-nightly.svg" alt="Packaging status" style="max-width: 100%; height: auto;" />
|
||||
|
||||
</a>
|
||||
|
||||
## Roadmap
|
||||
|
||||
### Short Terms
|
||||
|
||||
To encourage contributions, we create many [Pull Requests](https://github.com/Myriad-Dreamin/tinymist/pulls) in draft to navigate short-term plans. They give you a hint of what or where to start in this large repository.
|
||||
|
||||
### Long Terms
|
||||
|
||||
We are planning to implement the following features in typst v0.14.0 or spare time in weekend:
|
||||
|
||||
- Type checking: complete the type checker.
|
||||
- Periscope renderer: It is disabled since vscode reject to render SVGs containing foreignObjects.
|
||||
- Inlay hint: It is disabled _by default_ because of performance issues.
|
||||
- Find references of dictionary fields and named function arguments.
|
||||
- Improve symbol view’s appearance.
|
||||
- Improve package view.
|
||||
- Navigate to symbols by clicking on the symbol name in the view.
|
||||
- Automatically locate the symbol item in the view when viewing local documentation.
|
||||
- Remember the recently invoked package commands, e.g. “Open Docs of @preview/cetz:0.3.1”, “Open directory of @preview/touying:0.5.3”.
|
||||
- Improve label view.
|
||||
- Group labels.
|
||||
- Search labels.
|
||||
- Keep (persist) group preferences.
|
||||
- Improve Typst Preview.
|
||||
- Pin drop-down: Set the file to preview in the drop-down for clients that doesn’t support passing arguments to the preview command.
|
||||
- Render in web worker (another thread) to reduce overhead on the electron’s main thread.
|
||||
- Spell checking: There is already a branch but no suitable (default) spell checking library is found.
|
||||
- [typos](https://github.com/crate-ci/typos) is great for typst. [harper](https://github.com/Automattic/harper) looks promise.
|
||||
|
||||
If you are interested by any above features, please feel free to send Issues to discuss or PRs to implement to [GitHub.](https://github.com/Myriad-Dreamin/tinymist)
|
||||
|
||||
## Contributing
|
||||
|
||||
Please read the [CONTRIBUTING.md](CONTRIBUTING.md) file for contribution guidelines.
|
||||
|
||||
## Sponsoring
|
||||
|
||||
Tinymist thrives on community love and remains proudly independent. While we don’t accept direct project funding, we warmly welcome support for our maintainers’ personal efforts. Please go to [Maintainers Page](/MAINTAINERS.md) and [Contributors Page](https://github.com/Myriad-Dreamin/tinymist/graphs/contributors) and find their personal pages for more information. It is also welcomed to directly ask questions about sponsoring on the [GitHub Issues](https://github.com/Myriad-Dreamin/tinymist/issues/new).
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
- Partially code is inherited from [typst-lsp](https://github.com/nvarner/typst-lsp)
|
||||
- The [integrating](/editors/vscode#symbol-view) **offline** handwritten-stroke recognizer is powered by [Detypify](https://detypify.quarticcat.com/).
|
||||
- The [integrating](/editors/vscode#preview-command) preview service is powered by [typst-preview](https://github.com/Enter-tainer/typst-preview).
|
||||
- The [integrating](/editors/vscode#managing-local-packages) local package management functions are adopted from [vscode-typst-sync](https://github.com/OrangeX4/vscode-typst-sync).
|
||||
|
|
|
|||
4
_typos.toml
Normal file
4
_typos.toml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
files.extend-exclude = [
|
||||
"locales/**/*",
|
||||
"editors/vscode/e2e-workspaces/ieee-paper/ieee-tex.typ",
|
||||
]
|
||||
1
assets/.gitignore
vendored
Normal file
1
assets/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
fonts
|
||||
30
assets/images/introduction/frame_0.svg
Normal file
30
assets/images/introduction/frame_0.svg
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<svg class="typst-doc" viewBox="0 0 28.796833333333332 7.171500000000001" width="28.796833333333332pt" height="7.171500000000001pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:h5="http://www.w3.org/1999/xhtml">
|
||||
<g>
|
||||
<g transform="translate(0 7.171500000000001)">
|
||||
<g class="typst-text" transform="scale(1, -1)">
|
||||
<use xlink:href="#gE8D41A7B821A6DA6449385730041271C" x="0" fill="#f0f6fc" fill-rule="nonzero"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="translate(12.461166666666667 7.171500000000001)">
|
||||
<g class="typst-text" transform="scale(1, -1)">
|
||||
<use xlink:href="#g4026F2AE0915FEFF1AFA11899F67637E" x="0" fill="#f0f6fc" fill-rule="nonzero"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="translate(23.546833333333332 7.171500000000001)">
|
||||
<g class="typst-text" transform="scale(1, -1)">
|
||||
<use xlink:href="#g5C0D1D2E151935F3439EF1D4CB39DF87" x="0" fill="#f0f6fc" fill-rule="nonzero"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs id="glyph">
|
||||
<symbol id="gE8D41A7B821A6DA6449385730041271C" overflow="visible">
|
||||
<path d="M 9.072 7.1714997 C 8.872499 7.1714997 8.221499 7.14 8.022 7.14 C 7.8224998 7.14 7.161 7.1714997 6.9614997 7.1714997 C 6.804 7.1714997 6.7304997 7.0875 6.7304997 6.9195 C 6.7304997 6.825 6.804 6.7725 6.9614997 6.762 C 7.4024997 6.762 7.6229997 6.6254997 7.6229997 6.3525 C 7.6229997 6.2894998 7.6124997 6.216 7.6019998 6.1425 L 6.468 1.6485 L 4.2105 6.9509997 C 4.1265 7.1505 4.1054997 7.1714997 3.843 7.1714997 L 2.4465 7.1714997 C 2.1945 7.1714997 2.1 7.1505 2.1 6.9195 C 2.1 6.8145 2.2154999 6.762 2.4359999 6.762 C 2.8769999 6.762 3.0974998 6.7515 3.108 6.72 L 1.7114999 1.155 C 1.617 0.74549997 1.3755 0.5145 0.9975 0.44099998 C 0.7245 0.4095 0.4095 0.4515 0.4095 0.1575 C 0.4095 0.0525 0.4725 0 0.588 0 C 0.777 0 1.428 0.0315 1.6274999 0.0315 C 1.827 0.0315 2.499 0 2.6985 0 C 2.856 0 2.9294999 0.084 2.9294999 0.252 C 2.9294999 0.3465 2.8455 0.399 2.6775 0.4095 C 2.247 0.42 2.037 0.5565 2.037 0.819 C 2.037 0.8715 2.0475 0.945 2.0685 1.05 L 3.4229999 6.4154997 L 6.048 0.22049999 C 6.111 0.0735 6.1949997 0 6.2894998 0 C 6.384 0 6.447 0.084 6.489 0.252 L 7.9484997 6.027 C 8.085 6.5625 8.379 6.7515 9.03 6.762 C 9.177 6.7725 9.2505 6.8564997 9.2505 7.0245 C 9.219 7.119 9.2085 7.1714997 9.072 7.1714997 Z "/>
|
||||
</symbol>
|
||||
<symbol id="g4026F2AE0915FEFF1AFA11899F67637E" overflow="visible">
|
||||
<path d="M 7.203 2.3834999 C 7.308 2.4359999 7.3605 2.5095 7.3605 2.625 C 7.3605 2.7405 7.308 2.814 7.203 2.8665 L 1.176 5.7225 C 1.1445 5.733 1.1025 5.7434998 1.0605 5.7434998 C 0.8925 5.7434998 0.8085 5.6595 0.8085 5.481 C 0.8085 5.3865 0.861 5.3129997 0.9555 5.271 L 6.5625 2.625 L 0.9555 -0.021 C 0.861 -0.063 0.8085 -0.1365 0.8085 -0.23099999 C 0.8085 -0.4095 0.8925 -0.4935 1.0605 -0.4935 C 1.1025 -0.4935 1.1445 -0.48299998 1.176 -0.4725 Z "/>
|
||||
</symbol>
|
||||
<symbol id="g5C0D1D2E151935F3439EF1D4CB39DF87" overflow="visible">
|
||||
<path d="M 2.6145 -0.23099999 C 4.095 -0.23099999 4.83 0.96599996 4.83 3.36 C 4.83 4.9665 4.494 6.0375 3.8325 6.5625 C 3.465 6.8459997 3.0555 6.993 2.625 6.993 C 1.1445 6.993 0.4095 5.7855 0.4095 3.36 C 0.4095 1.428 0.92399997 -0.23099999 2.6145 -0.23099999 Z M 3.7905 5.502 C 3.8639998 5.1345 3.8955 4.4625 3.8955 3.486 C 3.8955 2.52 3.8535 1.806 3.78 1.344 C 3.6434999 0.504 3.2549999 0.084 2.6145 0.084 C 2.373 0.084 2.1315 0.1785 1.911 0.357 C 1.6274999 0.5985 1.4595 1.092 1.386 1.8479999 C 1.3544999 2.1104999 1.344 2.6564999 1.344 3.486 C 1.344 4.3995 1.3755 5.04 1.428 5.3865 C 1.5225 5.9639997 1.7114999 6.3315 2.0055 6.489 C 2.2365 6.615 2.4359999 6.678 2.6145 6.678 C 3.297 6.678 3.675 6.1215 3.7905 5.502 Z "/>
|
||||
</symbol>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
30
assets/images/introduction/frame_1.svg
Normal file
30
assets/images/introduction/frame_1.svg
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<svg class="typst-doc" viewBox="0 0 28.796833333333332 7.171500000000001" width="28.796833333333332pt" height="7.171500000000001pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:h5="http://www.w3.org/1999/xhtml">
|
||||
<g>
|
||||
<g transform="translate(0 7.171500000000001)">
|
||||
<g class="typst-text" transform="scale(1, -1)">
|
||||
<use xlink:href="#gE8D41A7B821A6DA6449385730041271C" x="0" fill="#262625" fill-rule="nonzero"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="translate(12.461166666666667 7.171500000000001)">
|
||||
<g class="typst-text" transform="scale(1, -1)">
|
||||
<use xlink:href="#g4026F2AE0915FEFF1AFA11899F67637E" x="0" fill="#262625" fill-rule="nonzero"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="translate(23.546833333333332 7.171500000000001)">
|
||||
<g class="typst-text" transform="scale(1, -1)">
|
||||
<use xlink:href="#g5C0D1D2E151935F3439EF1D4CB39DF87" x="0" fill="#262625" fill-rule="nonzero"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs id="glyph">
|
||||
<symbol id="gE8D41A7B821A6DA6449385730041271C" overflow="visible">
|
||||
<path d="M 9.072 7.1714997 C 8.872499 7.1714997 8.221499 7.14 8.022 7.14 C 7.8224998 7.14 7.161 7.1714997 6.9614997 7.1714997 C 6.804 7.1714997 6.7304997 7.0875 6.7304997 6.9195 C 6.7304997 6.825 6.804 6.7725 6.9614997 6.762 C 7.4024997 6.762 7.6229997 6.6254997 7.6229997 6.3525 C 7.6229997 6.2894998 7.6124997 6.216 7.6019998 6.1425 L 6.468 1.6485 L 4.2105 6.9509997 C 4.1265 7.1505 4.1054997 7.1714997 3.843 7.1714997 L 2.4465 7.1714997 C 2.1945 7.1714997 2.1 7.1505 2.1 6.9195 C 2.1 6.8145 2.2154999 6.762 2.4359999 6.762 C 2.8769999 6.762 3.0974998 6.7515 3.108 6.72 L 1.7114999 1.155 C 1.617 0.74549997 1.3755 0.5145 0.9975 0.44099998 C 0.7245 0.4095 0.4095 0.4515 0.4095 0.1575 C 0.4095 0.0525 0.4725 0 0.588 0 C 0.777 0 1.428 0.0315 1.6274999 0.0315 C 1.827 0.0315 2.499 0 2.6985 0 C 2.856 0 2.9294999 0.084 2.9294999 0.252 C 2.9294999 0.3465 2.8455 0.399 2.6775 0.4095 C 2.247 0.42 2.037 0.5565 2.037 0.819 C 2.037 0.8715 2.0475 0.945 2.0685 1.05 L 3.4229999 6.4154997 L 6.048 0.22049999 C 6.111 0.0735 6.1949997 0 6.2894998 0 C 6.384 0 6.447 0.084 6.489 0.252 L 7.9484997 6.027 C 8.085 6.5625 8.379 6.7515 9.03 6.762 C 9.177 6.7725 9.2505 6.8564997 9.2505 7.0245 C 9.219 7.119 9.2085 7.1714997 9.072 7.1714997 Z "/>
|
||||
</symbol>
|
||||
<symbol id="g4026F2AE0915FEFF1AFA11899F67637E" overflow="visible">
|
||||
<path d="M 7.203 2.3834999 C 7.308 2.4359999 7.3605 2.5095 7.3605 2.625 C 7.3605 2.7405 7.308 2.814 7.203 2.8665 L 1.176 5.7225 C 1.1445 5.733 1.1025 5.7434998 1.0605 5.7434998 C 0.8925 5.7434998 0.8085 5.6595 0.8085 5.481 C 0.8085 5.3865 0.861 5.3129997 0.9555 5.271 L 6.5625 2.625 L 0.9555 -0.021 C 0.861 -0.063 0.8085 -0.1365 0.8085 -0.23099999 C 0.8085 -0.4095 0.8925 -0.4935 1.0605 -0.4935 C 1.1025 -0.4935 1.1445 -0.48299998 1.176 -0.4725 Z "/>
|
||||
</symbol>
|
||||
<symbol id="g5C0D1D2E151935F3439EF1D4CB39DF87" overflow="visible">
|
||||
<path d="M 2.6145 -0.23099999 C 4.095 -0.23099999 4.83 0.96599996 4.83 3.36 C 4.83 4.9665 4.494 6.0375 3.8325 6.5625 C 3.465 6.8459997 3.0555 6.993 2.625 6.993 C 1.1445 6.993 0.4095 5.7855 0.4095 3.36 C 0.4095 1.428 0.92399997 -0.23099999 2.6145 -0.23099999 Z M 3.7905 5.502 C 3.8639998 5.1345 3.8955 4.4625 3.8955 3.486 C 3.8955 2.52 3.8535 1.806 3.78 1.344 C 3.6434999 0.504 3.2549999 0.084 2.6145 0.084 C 2.373 0.084 2.1315 0.1785 1.911 0.357 C 1.6274999 0.5985 1.4595 1.092 1.386 1.8479999 C 1.3544999 2.1104999 1.344 2.6564999 1.344 3.486 C 1.344 4.3995 1.3755 5.04 1.428 5.3865 C 1.5225 5.9639997 1.7114999 6.3315 2.0055 6.489 C 2.2365 6.615 2.4359999 6.678 2.6145 6.678 C 3.297 6.678 3.675 6.1215 3.7905 5.502 Z "/>
|
||||
</symbol>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
21
benches/font-load/Cargo.toml
Normal file
21
benches/font-load/Cargo.toml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
name = "tinymist-bench-font-load"
|
||||
description = "Font loading bench for tinymist."
|
||||
authors.workspace = true
|
||||
version.workspace = true
|
||||
license.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
divan.workspace = true
|
||||
tinymist.workspace = true
|
||||
|
||||
[[bench]]
|
||||
name = "tinymist-bench-font-load"
|
||||
path = "src/load.rs"
|
||||
harness = false
|
||||
|
||||
[features]
|
||||
the-thesis = []
|
||||
39
benches/font-load/src/load.rs
Normal file
39
benches/font-load/src/load.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use tinymist::{Config, project::LspUniverseBuilder};
|
||||
|
||||
fn main() {
|
||||
// initialize global variables
|
||||
|
||||
// Run registered benchmarks.
|
||||
divan::main();
|
||||
}
|
||||
|
||||
// Checks font loading performance of embedded fonts
|
||||
#[divan::bench]
|
||||
fn load_embedded() {
|
||||
let _embedded_fonts = Arc::new(LspUniverseBuilder::only_embedded_fonts().unwrap());
|
||||
}
|
||||
|
||||
// Checks font loading performance of system fonts
|
||||
#[divan::bench]
|
||||
fn load_system() {
|
||||
let config = Config::default();
|
||||
|
||||
let _fonts = config.fonts();
|
||||
}
|
||||
|
||||
/*
|
||||
Without Parallelization
|
||||
Timer precision: 17 ns
|
||||
tinymist_bench_font_load fastest │ slowest │ median │ mean │ samples │ iters
|
||||
├─ load_embedded 1.167 ms │ 1.697 ms │ 1.176 ms │ 1.188 ms │ 100 │ 100
|
||||
╰─ load_system 111.8 ms │ 123 ms │ 113.6 ms │ 114.3 ms │ 100 │ 100
|
||||
|
||||
With Parallelization
|
||||
Timer precision: 17 ns
|
||||
tinymist_bench_font_load fastest │ slowest │ median │ mean │ samples │ iters
|
||||
├─ load_embedded 130.8 µs │ 1.164 ms │ 157 µs │ 170.3 µs │ 100 │ 100
|
||||
╰─ load_system 14.44 ms │ 18.22 ms │ 15.37 ms │ 15.54 ms │ 100 │ 100
|
||||
|
||||
*/
|
||||
39
biome.json
Normal file
39
biome.json
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"$schema": "https://biomejs.dev/schemas/2.3.5/schema.json",
|
||||
"vcs": {
|
||||
"enabled": false,
|
||||
"clientKind": "git",
|
||||
"useIgnoreFile": false
|
||||
},
|
||||
"files": {
|
||||
"ignoreUnknown": false
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"indentStyle": "space",
|
||||
"indentWidth": 2,
|
||||
"lineWidth": 100
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true
|
||||
}
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"arrowParentheses": "always",
|
||||
"bracketSpacing": true,
|
||||
"quoteStyle": "double",
|
||||
"semicolons": "always",
|
||||
"trailingCommas": "all"
|
||||
}
|
||||
},
|
||||
"assist": {
|
||||
"actions": {
|
||||
"source": {
|
||||
"organizeImports": "on"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
6
contrib/html/editors/vscode/.gitignore
vendored
Normal file
6
contrib/html/editors/vscode/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
tinymist-*.vsix
|
||||
*.log
|
||||
test-dist
|
||||
.vscode-test
|
||||
coverage
|
||||
out/
|
||||
12
contrib/html/editors/vscode/.vscodeignore
Normal file
12
contrib/html/editors/vscode/.vscodeignore
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
**
|
||||
!out/tinymist-docs.pdf
|
||||
!out/extension.js
|
||||
!out/extension.web.js
|
||||
!out/server.js
|
||||
!package.json
|
||||
!package-lock.json
|
||||
!icons/**
|
||||
!syntaxes/**
|
||||
!README.md
|
||||
!LICENSE
|
||||
!CHANGELOG.md
|
||||
11
contrib/html/editors/vscode/CHANGELOG.md
Normal file
11
contrib/html/editors/vscode/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Change Log
|
||||
|
||||
All notable changes to the "tinymist-html-ext" extension will be documented in this file.
|
||||
|
||||
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
|
||||
|
||||
The changelog lines unspecified with authors are all written by the @Myriad-Dreamin.
|
||||
|
||||
## v0.13.0 - [2025-02-22]
|
||||
|
||||
Initial release of the extension.
|
||||
201
contrib/html/editors/vscode/LICENSE
Normal file
201
contrib/html/editors/vscode/LICENSE
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2023-2025 Myriad Dreamin, Nathan Varner
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
16
contrib/html/editors/vscode/esbuild.system.mjs
Normal file
16
contrib/html/editors/vscode/esbuild.system.mjs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import { build } from "esbuild";
|
||||
import * as fs from "fs";
|
||||
|
||||
if (!fs.existsSync("./out/extension.web.js")) {
|
||||
fs.mkdirSync("./out", { recursive: true });
|
||||
fs.writeFileSync("./out/extension.web.js", "");
|
||||
}
|
||||
|
||||
build({
|
||||
entryPoints: ["./src/extension.mts", "./src/server.mts"],
|
||||
bundle: true,
|
||||
outdir: "./out",
|
||||
external: ["vscode"],
|
||||
format: "cjs",
|
||||
platform: "node",
|
||||
}).catch(() => process.exit(1));
|
||||
29
contrib/html/editors/vscode/esbuild.web.mjs
Normal file
29
contrib/html/editors/vscode/esbuild.web.mjs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import { build } from "esbuild";
|
||||
import { polyfillNode } from "esbuild-plugin-polyfill-node";
|
||||
import * as fs from "fs";
|
||||
|
||||
if (!fs.existsSync("./out/extension.js")) {
|
||||
fs.mkdirSync("./out", { recursive: true });
|
||||
fs.writeFileSync("./out/extension.js", "");
|
||||
}
|
||||
|
||||
build({
|
||||
entryPoints: ["./src/extension.web.ts"],
|
||||
bundle: true,
|
||||
outfile: "./out/extension.web.js",
|
||||
external: ["vscode"],
|
||||
format: "cjs",
|
||||
target: ["es2020", "chrome61", "edge18", "firefox60"],
|
||||
// Node.js global to browser globalThis
|
||||
define: {
|
||||
global: "globalThis",
|
||||
},
|
||||
plugins: [
|
||||
polyfillNode({
|
||||
polyfills: {
|
||||
crypto: "empty",
|
||||
},
|
||||
// Options (optional)
|
||||
}),
|
||||
],
|
||||
}).catch(() => process.exit(1));
|
||||
BIN
contrib/html/editors/vscode/icons/ti-white.png
Normal file
BIN
contrib/html/editors/vscode/icons/ti-white.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3 KiB |
80
contrib/html/editors/vscode/package.json
Normal file
80
contrib/html/editors/vscode/package.json
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
{
|
||||
"name": "tinymist-vscode-html",
|
||||
"version": "0.14.6-rc1",
|
||||
"description": "Extending Typst with HTML features",
|
||||
"keywords": [
|
||||
"html",
|
||||
"typst",
|
||||
"language-server"
|
||||
],
|
||||
"categories": [
|
||||
"Programming Languages"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Myriad-Dreamin/tinymist.git"
|
||||
},
|
||||
"displayName": "Tinymist Typst HTML",
|
||||
"author": "Myriad-Dreamin",
|
||||
"contributors": [
|
||||
"Myriad-Dreamin"
|
||||
],
|
||||
"publisher": "myriad-dreamin",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"vscode": "^1.97.0"
|
||||
},
|
||||
"activationEvents": [
|
||||
"onLanguage:typst"
|
||||
],
|
||||
"main": "./out/extension.js",
|
||||
"browser": "./out/extension.web.js",
|
||||
"icon": "./icons/ti-white.png",
|
||||
"contributes": {
|
||||
"commands": [
|
||||
{
|
||||
"command": "tinymist.showHtmlExtensionLog",
|
||||
"title": "Show Log of the HTML extension",
|
||||
"description": "Show log of the tinymist HTML extension",
|
||||
"category": "Typst",
|
||||
"icon": "$(list-flat)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"build-web-base": "node esbuild.web.mjs",
|
||||
"build-system-base": "node esbuild.system.mjs",
|
||||
"build-base": "yarn run build-web-base && yarn run build-system-base",
|
||||
"compile-shared": "node scripts/check-version.mjs && node scripts/postinstall.cjs",
|
||||
"compile:web": "yarn run build-web-base -- --minify && yarn run compile-shared",
|
||||
"compile:system": "yarn run build-system-base -- --minify && yarn run compile-shared",
|
||||
"package": "npx @vscode/vsce package --yarn",
|
||||
"compile": "yarn run compile:system",
|
||||
"watch": "yarn run build-system-base -- --sourcemap --watch",
|
||||
"check": "tsc --noEmit",
|
||||
"format-check": "prettier --check .",
|
||||
"format": "prettier --write .",
|
||||
"test": "rimraf test-dist/ && tsc -p tsconfig.test.json && node test-dist/test/runTests.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"css": "^3.0.0",
|
||||
"esbuild-plugin-polyfill-node": "^0.3.0",
|
||||
"lodash.flow": "^3.5.0",
|
||||
"vscode-languageclient": "^9.0.0",
|
||||
"vscode-languageserver": "^9.0.0",
|
||||
"xxhashjs": "^0.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^5.0.1",
|
||||
"@types/css": "^0.0.38",
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@types/node": "^22.13.4",
|
||||
"@types/vscode": "^1.97.0",
|
||||
"@vscode/test-electron": "^2.3.9",
|
||||
"@vscode/vsce": "^2.22.0",
|
||||
"chai": "^5.1.1",
|
||||
"mocha": "^10.2.0",
|
||||
"ovsx": "^0.8.3",
|
||||
"vscode-html-languageservice": "^5.3.1"
|
||||
}
|
||||
}
|
||||
15
contrib/html/editors/vscode/scripts/check-version.mjs
Normal file
15
contrib/html/editors/vscode/scripts/check-version.mjs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import { readFileSync } from "fs";
|
||||
|
||||
function check() {
|
||||
const cargoToml = readFileSync("../../../../Cargo.toml", "utf8");
|
||||
const cargoVersion = cargoToml.match(/version = "(.*?)"/)[1];
|
||||
const pkgVersion = JSON.parse(readFileSync("package.json", "utf8")).version;
|
||||
|
||||
if (cargoVersion !== pkgVersion) {
|
||||
throw new Error(
|
||||
`Version mismatch: ${cargoVersion} (in Cargo.toml) !== ${pkgVersion} (in package.json)`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
check();
|
||||
0
contrib/html/editors/vscode/scripts/postinstall.cjs
Normal file
0
contrib/html/editors/vscode/scripts/postinstall.cjs
Normal file
9
contrib/html/editors/vscode/src/css/LICENSE
Normal file
9
contrib/html/editors/vscode/src/css/LICENSE
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 Anders Ellenshøj Andersen <andersa@atlab.dk>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
35
contrib/html/editors/vscode/src/css/arrayUtils.ts
Normal file
35
contrib/html/editors/vscode/src/css/arrayUtils.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
let XXH = require("xxhashjs").h32;
|
||||
|
||||
export function flatten<T>(nestedArray: T[][]): T[] {
|
||||
if (nestedArray.length === 0) {
|
||||
throw new RangeError("Can't flatten an empty array.");
|
||||
} else {
|
||||
return nestedArray.reduce((a, b) => a.concat(b));
|
||||
}
|
||||
}
|
||||
|
||||
export function distinct<T>(items: T[] | Thenable<T[]>): Thenable<T[]> {
|
||||
return Promise.resolve(items).then((items) => Array.from(new Set(items)));
|
||||
}
|
||||
|
||||
export function distinctByXXHash<T>(items: T[] | Thenable<T[]>): Thenable<T[]> {
|
||||
const initialValue = {
|
||||
distinctItems: <T[]>[],
|
||||
hashSet: new Set(),
|
||||
};
|
||||
|
||||
const accumulatorPromise = Promise.resolve(items).then((items) =>
|
||||
items.reduce((acc, item) => {
|
||||
const hash = XXH(item, 0x1337).toNumber();
|
||||
|
||||
if (!acc.hashSet.has(hash)) {
|
||||
acc.distinctItems.push(item);
|
||||
acc.hashSet.add(hash);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, initialValue),
|
||||
);
|
||||
|
||||
return accumulatorPromise.then((accumulator) => accumulator.distinctItems);
|
||||
}
|
||||
34
contrib/html/editors/vscode/src/css/cssAggregator.ts
Normal file
34
contrib/html/editors/vscode/src/css/cssAggregator.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import { workspace, window } from "vscode";
|
||||
// @ts-ignore
|
||||
import flow from "lodash.flow";
|
||||
import uriFilesReader from "./uriFilesReader";
|
||||
import { distinct, distinctByXXHash } from "./arrayUtils";
|
||||
import { parseCssTexts, getCSSRules, getCSSSelectors, getCSSClasses } from "./cssUtils";
|
||||
|
||||
const styleSheetsReader = flow(uriFilesReader, distinctByXXHash, parseCssTexts);
|
||||
const distinctCSSClassesExtractor = flow(getCSSRules, getCSSSelectors, getCSSClasses, distinct);
|
||||
|
||||
export default function (): Thenable<string[]> {
|
||||
const startTime = process.hrtime();
|
||||
|
||||
return styleSheetsReader(
|
||||
workspace.findFiles("**/*.css", ""),
|
||||
workspace.getConfiguration("files").get("encoding", "utf8"),
|
||||
).then((parseResult: any) => {
|
||||
return distinctCSSClassesExtractor(parseResult.styleSheets).then((distinctCssClasses: any) => {
|
||||
const elapsedTime = process.hrtime(startTime);
|
||||
|
||||
console.log(`Elapsed time: ${elapsedTime[0]} s ${Math.trunc(elapsedTime[1] / 1e6)} ms`);
|
||||
console.log(`Files processed: ${parseResult.styleSheets.length}`);
|
||||
console.log(`Skipped due to parse errors: ${parseResult.unparsable.length}`);
|
||||
console.log(`CSS classes discovered: ${distinctCssClasses.length}`);
|
||||
|
||||
window.setStatusBarMessage(
|
||||
`HTML Class Suggestions processed ${parseResult.styleSheets.length} distinct css files and discovered ${distinctCssClasses.length} css classes.`,
|
||||
10000,
|
||||
);
|
||||
|
||||
return distinctCssClasses;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
"use strict";
|
||||
import * as vscode from "vscode";
|
||||
import aggregator from "./cssAggregator";
|
||||
|
||||
export class CssCompletionItemProvider {
|
||||
public completionItems?: PromiseLike<vscode.CompletionItem[]>;
|
||||
|
||||
constructor() {
|
||||
this.refreshCompletionItems();
|
||||
}
|
||||
|
||||
// public provideCompletionItems(
|
||||
// document: vscode.TextDocument,
|
||||
// position: vscode.Position,
|
||||
// token: vscode.CancellationToken,
|
||||
// ): Thenable<vscode.CompletionItem[]> {
|
||||
// if (canTriggerCompletion(document, position)) {
|
||||
// return this.completionItems as PromiseLike<vscode.CompletionItem[]>;
|
||||
// } else {
|
||||
// return Promise.reject<vscode.CompletionItem[]>("Not inside html class attribute.");
|
||||
// }
|
||||
// }
|
||||
|
||||
public refreshCompletionItems() {
|
||||
this.completionItems = aggregator().then((cssClasses) => {
|
||||
const completionItems = cssClasses.map((cssClass) => {
|
||||
const completionItem = new vscode.CompletionItem(cssClass);
|
||||
completionItem.detail = `Insert ${cssClass}`;
|
||||
completionItem.insertText = cssClass;
|
||||
completionItem.kind = vscode.CompletionItemKind.Value;
|
||||
|
||||
// make sure our completion item group are first
|
||||
completionItem.preselect = true;
|
||||
return completionItem;
|
||||
});
|
||||
return completionItems;
|
||||
});
|
||||
}
|
||||
}
|
||||
105
contrib/html/editors/vscode/src/css/cssUtils.ts
Normal file
105
contrib/html/editors/vscode/src/css/cssUtils.ts
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import { parse, Stylesheet, Rule, Media } from "css";
|
||||
import { flatten } from "./arrayUtils";
|
||||
|
||||
export interface CSSTextsParseResult {
|
||||
styleSheets: Stylesheet[];
|
||||
unparsable: string[];
|
||||
}
|
||||
|
||||
export function parseCssTexts(
|
||||
cssTexts: string[] | Thenable<string[]>,
|
||||
): Thenable<CSSTextsParseResult> {
|
||||
const initialValue = {
|
||||
styleSheets: <Stylesheet[]>[],
|
||||
unparsable: <string[]>[],
|
||||
};
|
||||
|
||||
return Promise.resolve(cssTexts).then((cssTexts) =>
|
||||
cssTexts.reduce((acc, cssText) => {
|
||||
try {
|
||||
acc.styleSheets.push(parse(cssText));
|
||||
} catch (error) {
|
||||
acc.unparsable.push(cssText);
|
||||
}
|
||||
return acc;
|
||||
}, initialValue),
|
||||
);
|
||||
}
|
||||
|
||||
export function getCSSRules(styleSheets: Stylesheet[] | Thenable<Stylesheet[]>): Thenable<Rule[]> {
|
||||
return Promise.resolve(styleSheets).then((styleSheets) =>
|
||||
styleSheets.reduce((acc, styleSheet) => {
|
||||
return acc.concat(findRootRules(styleSheet), findMediaRules(styleSheet));
|
||||
}, [] as Rule[]),
|
||||
);
|
||||
}
|
||||
|
||||
export function getCSSSelectors(rules: Rule[] | Thenable<Rule[]>): Thenable<string[]> {
|
||||
return Promise.resolve(rules).then((rules) => {
|
||||
if (rules.length > 0) {
|
||||
return flatten(rules.map((rule) => rule.selectors!)).filter(
|
||||
(value) => value && value.length > 0,
|
||||
);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function getCSSClasses(selectors: string[] | Thenable<string[]>): Thenable<string[]> {
|
||||
return Promise.resolve(selectors).then((selectors) =>
|
||||
selectors.reduce((acc, selector) => {
|
||||
const className = findClassName(selector);
|
||||
|
||||
if (className && className.length > 0) {
|
||||
acc.push(sanitizeClassName(className));
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, [] as string[]),
|
||||
);
|
||||
}
|
||||
|
||||
export function findRootRules(cssAST: Stylesheet): Rule[] {
|
||||
// @ts-ignore
|
||||
return cssAST.stylesheet!.rules.filter((node) => (<Rule>node).type === "rule");
|
||||
}
|
||||
|
||||
export function findMediaRules(cssAST: Stylesheet): Rule[] {
|
||||
let mediaNodes = <Rule[]>cssAST.stylesheet!.rules.filter((node) => {
|
||||
// @ts-ignore
|
||||
return (<Rule>node).type === "media";
|
||||
});
|
||||
if (mediaNodes.length > 0) {
|
||||
// @ts-ignore
|
||||
return flatten(mediaNodes.map((node) => (<Media>node).rules!));
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export function findClassName(selector: string): string {
|
||||
let classNameStartIndex = selector.lastIndexOf(".");
|
||||
if (classNameStartIndex >= 0) {
|
||||
let classText = selector.substr(classNameStartIndex + 1);
|
||||
// Search for one of ' ', '[', ':' or '>', that isn't escaped with a backslash
|
||||
let classNameEndIndex = classText.search(/[^\\][\s\[:>]/);
|
||||
if (classNameEndIndex >= 0) {
|
||||
return classText.substr(0, classNameEndIndex + 1);
|
||||
} else {
|
||||
return classText;
|
||||
}
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
export function sanitizeClassName(className: string): string {
|
||||
return className.replace(/\\[!"#$%&'()*+,\-./:;<=>?@[\\\]^`{|}~]/g, (substr, ...args) => {
|
||||
if (args.length === 2) {
|
||||
return substr.slice(1);
|
||||
} else {
|
||||
return substr;
|
||||
}
|
||||
});
|
||||
}
|
||||
23
contrib/html/editors/vscode/src/css/test/runTest.ts
Normal file
23
contrib/html/editors/vscode/src/css/test/runTest.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import * as path from 'path';
|
||||
|
||||
import { runTests } from '@vscode/test-electron';
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
// The folder containing the Extension Manifest package.json
|
||||
// Passed to `--extensionDevelopmentPath`
|
||||
const extensionDevelopmentPath = path.resolve(__dirname, '../../');
|
||||
|
||||
// The path to test runner
|
||||
// Passed to --extensionTestsPath
|
||||
const extensionTestsPath = path.resolve(__dirname, './suite/index');
|
||||
|
||||
// Download VS Code, unzip it and run the integration test
|
||||
await runTests({ extensionDevelopmentPath, extensionTestsPath });
|
||||
} catch (err) {
|
||||
console.error('Failed to run tests', err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import { findClassName, sanitizeClassName } from '../../cssUtils';
|
||||
|
||||
import * as assert from 'assert';
|
||||
|
||||
suite('Test cssUtils', () => {
|
||||
suite('#findClassName', () => {
|
||||
test('finds \'container\' in \'.container\'', () => {
|
||||
assert.equal(findClassName('.container'), 'container');
|
||||
});
|
||||
test('finds \'bg-warning\' in \'a.bg-warning:hover\'', () => {
|
||||
assert.equal(findClassName('a.bg-warning:hover'), 'bg-warning');
|
||||
});
|
||||
test('finds \'u-1\\/2\' in \'.u-1\\/2\'', () => {
|
||||
assert.equal(findClassName('.u-1\\/2'), 'u-1\\/2');
|
||||
});
|
||||
test('finds \'ratio-16\\:9\' in \'.ratio-16\\:9\'', () => {
|
||||
assert.equal(findClassName('.ratio-16\\:9'), 'ratio-16\\:9');
|
||||
});
|
||||
test('finds \'margin\\@palm\' in \'.margin\\@palm\'', () => {
|
||||
assert.equal(findClassName('.margin\\@palm'), 'margin\\@palm');
|
||||
});
|
||||
|
||||
});
|
||||
suite('#sanitizeClassName', () => {
|
||||
test('sanitizes \'u-1\\/2\' to \'u-1/2\'', () =>{
|
||||
assert.equal(sanitizeClassName('u-1\\/2'), 'u-1/2');
|
||||
});
|
||||
test('sanitizes \'ratio-16\\:9\' to \'ratio-16:9\'', () =>{
|
||||
assert.equal(sanitizeClassName('ratio-16\\:9'), 'ratio-16:9');
|
||||
});
|
||||
test('sanitizes \'margin\\@palm\' to \'margin@palm\'', () =>{
|
||||
assert.equal(sanitizeClassName('margin\\@palm'), 'margin@palm');
|
||||
});
|
||||
test('sanitizes \'foo-1\\/2\\@bar\' to \'foo-1/2@bar\'', () =>{
|
||||
assert.equal(sanitizeClassName('foo-1\\/2\\@bar'), 'foo-1/2@bar');
|
||||
});
|
||||
});
|
||||
});
|
||||
38
contrib/html/editors/vscode/src/css/test/suite/index.ts
Normal file
38
contrib/html/editors/vscode/src/css/test/suite/index.ts
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import * as path from "path";
|
||||
import * as Mocha from "mocha";
|
||||
import * as glob from "glob";
|
||||
|
||||
export function run(): Promise<void> {
|
||||
// Create the mocha test
|
||||
const mocha = new Mocha({
|
||||
ui: "tdd",
|
||||
color: true,
|
||||
});
|
||||
|
||||
const testsRoot = path.resolve(__dirname, "..");
|
||||
|
||||
return new Promise((c, e) => {
|
||||
glob("**/**.test.js", { cwd: testsRoot }, (err, files) => {
|
||||
if (err) {
|
||||
return e(err);
|
||||
}
|
||||
|
||||
// Add files to the test suite
|
||||
files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f)));
|
||||
|
||||
try {
|
||||
// Run the mocha test
|
||||
mocha.run((failures) => {
|
||||
if (failures > 0) {
|
||||
e(new Error(`${failures} tests failed.`));
|
||||
} else {
|
||||
c();
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
e(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import uriFilesReader from "../../uriFilesReader";
|
||||
import * as assert from "assert";
|
||||
import { Uri } from "vscode";
|
||||
|
||||
suite("Test uriFilesReader", () => {
|
||||
test("Can't load http protocol", () => {
|
||||
const httpsUri = Uri.parse("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css");
|
||||
return uriFilesReader([httpsUri], "utf8").then((data: any) => {
|
||||
assert(false, "Expected promise to be rejected.");
|
||||
},(err: any) => {
|
||||
assert(err.code === "ENOENT");
|
||||
});
|
||||
});
|
||||
});
|
||||
16
contrib/html/editors/vscode/src/css/uriFilesReader.ts
Normal file
16
contrib/html/editors/vscode/src/css/uriFilesReader.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import { Uri } from "vscode";
|
||||
import { readFile } from "fs";
|
||||
|
||||
export default (uris: Uri[]|Thenable<Uri[]>, encoding: BufferEncoding): Thenable<string[]> => {
|
||||
return Promise.resolve(uris).then(uris => {
|
||||
return Promise.all(uris.map(uri => new Promise<string>((resolve, reject) => {
|
||||
readFile(uri.fsPath, encoding, (err, data) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(data.toString());
|
||||
}
|
||||
});
|
||||
})));
|
||||
});
|
||||
};
|
||||
224
contrib/html/editors/vscode/src/embeddedSupport.ts
Normal file
224
contrib/html/editors/vscode/src/embeddedSupport.ts
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
interface EmbeddedRegion {
|
||||
languageId: string | undefined;
|
||||
start: number;
|
||||
end: number;
|
||||
attributeValue?: boolean;
|
||||
}
|
||||
|
||||
enum TokenKind {
|
||||
Unknown,
|
||||
Colon,
|
||||
String,
|
||||
Identifier,
|
||||
}
|
||||
|
||||
class BackScanner {
|
||||
currentToken: TokenKind = TokenKind.Unknown;
|
||||
tokenContent: string = "";
|
||||
|
||||
constructor(
|
||||
private documentText: string,
|
||||
private offset: number,
|
||||
) {
|
||||
this.scanBack();
|
||||
}
|
||||
|
||||
getCurrentToken() {
|
||||
return this.currentToken;
|
||||
}
|
||||
|
||||
scanBack() {
|
||||
let i = this.offset;
|
||||
this.currentToken = TokenKind.Unknown;
|
||||
while (i >= 0) {
|
||||
const ch = this.documentText[i];
|
||||
i--;
|
||||
// console.log("scanBack", ch, this.currentToken, this.tokenContent);
|
||||
if (this.currentToken === TokenKind.Unknown) {
|
||||
if (ch === ":") {
|
||||
this.currentToken = TokenKind.Colon;
|
||||
this.tokenContent = ch;
|
||||
break;
|
||||
} else if (ch === '"') {
|
||||
this.currentToken = TokenKind.String;
|
||||
this.tokenContent = ch;
|
||||
} else if (/[a-zA-Z0-9\-]/.test(ch)) {
|
||||
this.currentToken = TokenKind.Identifier;
|
||||
this.tokenContent = ch;
|
||||
} else if (/\s/.test(ch)) {
|
||||
// ignore
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if (this.currentToken === TokenKind.String) {
|
||||
this.tokenContent = ch + this.tokenContent;
|
||||
if (ch === '"') {
|
||||
break;
|
||||
}
|
||||
} else if (this.currentToken === TokenKind.Identifier) {
|
||||
if (/[a-zA-Z0-9\-]/.test(ch)) {
|
||||
this.tokenContent = ch + this.tokenContent;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.offset = i;
|
||||
}
|
||||
}
|
||||
|
||||
export function isInsideClassAttribute(documentText: string, offset: number) {
|
||||
console.log("isInsideClassAttribute", offset);
|
||||
|
||||
// string start
|
||||
let start = offset - 1;
|
||||
while (start >= 0) {
|
||||
if (documentText[start] === '"') {
|
||||
let shashCount = 0;
|
||||
while (start > 0) {
|
||||
if (documentText[start - 1] === "\\") {
|
||||
shashCount++;
|
||||
start--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shashCount % 2 === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
start--;
|
||||
} else {
|
||||
start--;
|
||||
}
|
||||
}
|
||||
|
||||
if (start >= 0 && documentText[start] === '"') {
|
||||
start -= 1;
|
||||
|
||||
// find class attribute
|
||||
const reverseScanner = new BackScanner(documentText, start);
|
||||
if (reverseScanner.getCurrentToken() !== TokenKind.Colon) {
|
||||
return false;
|
||||
}
|
||||
reverseScanner.scanBack();
|
||||
if (reverseScanner.getCurrentToken() === TokenKind.Identifier) {
|
||||
console.log("found class attribute", reverseScanner.tokenContent);
|
||||
return reverseScanner.tokenContent === "class";
|
||||
}
|
||||
if (reverseScanner.getCurrentToken() === TokenKind.String) {
|
||||
console.log("found class attribute", reverseScanner.tokenContent);
|
||||
return reverseScanner.tokenContent === '"class"';
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function parseRawBlockRegion(
|
||||
documentText: string,
|
||||
offset: number,
|
||||
): EmbeddedRegion | undefined {
|
||||
let start = offset - 1;
|
||||
while (start >= 0) {
|
||||
if (documentText[start] === "`") {
|
||||
start -= 2;
|
||||
if (start < 0 || documentText.slice(start, start + 3) !== "```") {
|
||||
break;
|
||||
}
|
||||
|
||||
let languageOffset = start + 3;
|
||||
let backtickStart = start;
|
||||
while (backtickStart > 0 && documentText[backtickStart - 1] === "`") {
|
||||
backtickStart -= 1;
|
||||
}
|
||||
|
||||
let numOfBackticks = languageOffset - backtickStart;
|
||||
|
||||
let languageStart = languageOffset;
|
||||
while (languageOffset < offset) {
|
||||
if (/\s/.test(documentText[languageOffset])) {
|
||||
break;
|
||||
}
|
||||
languageOffset++;
|
||||
}
|
||||
let languageId = documentText.slice(languageStart, languageOffset);
|
||||
|
||||
console.log("numOfBackticks", numOfBackticks, languageOffset, languageId);
|
||||
|
||||
let rawOffset = languageOffset;
|
||||
let rawEnd = languageOffset;
|
||||
let accumulatedBacktick = 0;
|
||||
|
||||
while (rawEnd < documentText.length) {
|
||||
const isBacktick = documentText[rawEnd] === "`";
|
||||
rawEnd++;
|
||||
if (isBacktick) {
|
||||
accumulatedBacktick++;
|
||||
} else {
|
||||
if (accumulatedBacktick >= numOfBackticks) {
|
||||
break;
|
||||
}
|
||||
|
||||
accumulatedBacktick = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (accumulatedBacktick > rawEnd) {
|
||||
return;
|
||||
}
|
||||
rawEnd -= accumulatedBacktick;
|
||||
|
||||
const rawContent = documentText.slice(rawOffset, rawEnd);
|
||||
|
||||
console.log("raw content", languageId, rawOffset, rawEnd, rawContent);
|
||||
|
||||
// return [languageId, rawOffset, rawEnd];
|
||||
return {
|
||||
languageId,
|
||||
start: rawOffset,
|
||||
end: rawEnd,
|
||||
};
|
||||
}
|
||||
start--;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract embedded regions from a document
|
||||
*
|
||||
* @param documentText The content of the document
|
||||
* @param regions The regions to embed
|
||||
* @param langId The language id to extract
|
||||
* @returns The content of the document with the regions embedded
|
||||
*/
|
||||
export function getVirtualContent(
|
||||
documentText: string,
|
||||
regions: EmbeddedRegion[],
|
||||
langId: string,
|
||||
): string {
|
||||
// Keeps space.
|
||||
let content = documentText
|
||||
.split("\n")
|
||||
.map((line) => {
|
||||
return " ".repeat(line.length);
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
regions.forEach((r) => {
|
||||
if (r.languageId === langId) {
|
||||
content =
|
||||
content.slice(0, r.start) + documentText.slice(r.start, r.end) + content.slice(r.end);
|
||||
}
|
||||
});
|
||||
|
||||
return content;
|
||||
}
|
||||
142
contrib/html/editors/vscode/src/extension.mts
Normal file
142
contrib/html/editors/vscode/src/extension.mts
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import * as path from "path";
|
||||
import * as vscode from "vscode";
|
||||
import { commands, CompletionList, ExtensionContext, Uri } from "vscode";
|
||||
import {
|
||||
type LanguageClientOptions,
|
||||
type ServerOptions,
|
||||
LanguageClient,
|
||||
TransportKind,
|
||||
} from "vscode-languageclient/node";
|
||||
import { getVirtualContent, isInsideClassAttribute, parseRawBlockRegion } from "./embeddedSupport";
|
||||
import { cssActivate } from "./features/css";
|
||||
|
||||
let client: LanguageClient;
|
||||
|
||||
export function activate(context: ExtensionContext) {
|
||||
const tinymistExtension = vscode.extensions.getExtension("myriad-dreamin.tinymist");
|
||||
if (!tinymistExtension) {
|
||||
void vscode.window.showWarningMessage(
|
||||
"Tinymist HTML:\n\nTinymist LSP feature is required. Please install Tinymist Typst Extension (myriad-dreamin.tinymist).",
|
||||
);
|
||||
}
|
||||
|
||||
const provider = cssActivate(context);
|
||||
|
||||
// The server is implemented in node
|
||||
const serverModule = context.asAbsolutePath(path.join("out", "server.js"));
|
||||
|
||||
// If the extension is launched in debug mode then the debug server options are used
|
||||
// Otherwise the run options are used
|
||||
const serverOptions: ServerOptions = {
|
||||
run: { module: serverModule, transport: TransportKind.ipc },
|
||||
debug: {
|
||||
module: serverModule,
|
||||
transport: TransportKind.ipc,
|
||||
},
|
||||
};
|
||||
|
||||
const virtualDocumentContents = new Map<string, string>();
|
||||
|
||||
const removeSuffix = (uri: string) => uri.replace(/\.(html|css)$/, "");
|
||||
vscode.workspace.registerTextDocumentContentProvider("embedded-content", {
|
||||
provideTextDocumentContent: (uri) => {
|
||||
const originalUri = removeSuffix(uri.path.slice(1));
|
||||
const decodedUri = decodeURIComponent(originalUri);
|
||||
console.log("provideTextDocumentContent gg", uri.path, originalUri, decodedUri);
|
||||
return virtualDocumentContents.get(decodedUri);
|
||||
},
|
||||
});
|
||||
|
||||
const clientOptions: LanguageClientOptions = {
|
||||
documentSelector: [{ scheme: "file", language: "typst" }],
|
||||
middleware: {
|
||||
provideCompletionItem: async (document, position, context, token, next) => {
|
||||
const res = await vscode.commands.executeCommand<
|
||||
[{ mode: "math" | "markup" | "code" | "comment" | "string" | "raw" }]
|
||||
>("tinymist.interactCodeContext", {
|
||||
textDocument: {
|
||||
uri: document.uri.toString(),
|
||||
},
|
||||
query: [
|
||||
{
|
||||
kind: "modeAt",
|
||||
position: {
|
||||
line: position.line,
|
||||
character: position.character,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const inString = res[0]?.mode === "string";
|
||||
const inRaw = res[0]?.mode === "raw";
|
||||
|
||||
// If completes the content of a `class` attribute, completes classes found in the css
|
||||
// files.
|
||||
if (inString && isInsideClassAttribute(document.getText(), document.offsetAt(position))) {
|
||||
return provider.completionItems;
|
||||
}
|
||||
|
||||
if (!inRaw) {
|
||||
return await next(document, position, context, token);
|
||||
}
|
||||
|
||||
// If not in `<style>`, do not perform request forwarding
|
||||
const virtualContent = parseRawBlockRegion(document.getText(), document.offsetAt(position));
|
||||
|
||||
if (!virtualContent) {
|
||||
return await next(document, position, context, token);
|
||||
}
|
||||
|
||||
const langId = virtualContent.languageId;
|
||||
if (langId !== "html" && langId !== "css") {
|
||||
return await next(document, position, context, token);
|
||||
}
|
||||
|
||||
const originalUri = document.uri.toString(true);
|
||||
virtualDocumentContents.set(
|
||||
originalUri,
|
||||
getVirtualContent(document.getText(), [virtualContent], langId!),
|
||||
);
|
||||
|
||||
const vdocUriString = `embedded-content://${langId}/${encodeURIComponent(originalUri)}.${langId}`;
|
||||
const vdocUri = Uri.parse(vdocUriString);
|
||||
return await commands.executeCommand<CompletionList>(
|
||||
"vscode.executeCompletionItemProvider",
|
||||
vdocUri,
|
||||
position,
|
||||
context.triggerCharacter,
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Create the language client and start the client.
|
||||
client = new LanguageClient(
|
||||
"TinymistTypstHTMLExtension",
|
||||
"Tinymist Typst HTML Extension",
|
||||
serverOptions,
|
||||
clientOptions,
|
||||
);
|
||||
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand("tinymist-html-ext.showLog", () => {
|
||||
client.outputChannel?.show();
|
||||
}),
|
||||
);
|
||||
|
||||
// Start the client. This will also launch the server
|
||||
client.start();
|
||||
}
|
||||
|
||||
export function deactivate(): Thenable<void> | undefined {
|
||||
if (!client) {
|
||||
return undefined;
|
||||
}
|
||||
return client.stop();
|
||||
}
|
||||
16
contrib/html/editors/vscode/src/features/css.ts
Normal file
16
contrib/html/editors/vscode/src/features/css.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import * as vscode from "vscode";
|
||||
import { CssCompletionItemProvider } from "../css/cssCompletionItemProvider";
|
||||
|
||||
export function cssActivate(context: vscode.ExtensionContext) {
|
||||
let provider = new CssCompletionItemProvider();
|
||||
|
||||
context.subscriptions.push(
|
||||
vscode.workspace.onDidSaveTextDocument((e) => {
|
||||
if (e.languageId === "css") {
|
||||
provider.refreshCompletionItems();
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
return provider;
|
||||
}
|
||||
62
contrib/html/editors/vscode/src/server.mts
Normal file
62
contrib/html/editors/vscode/src/server.mts
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import { getLanguageService } from "vscode-html-languageservice/lib/esm/htmlLanguageService";
|
||||
import {
|
||||
createConnection,
|
||||
InitializeParams,
|
||||
ProposedFeatures,
|
||||
TextDocuments,
|
||||
TextDocumentSyncKind,
|
||||
} from "vscode-languageserver/node";
|
||||
import { TextDocument } from "vscode-languageserver-textdocument";
|
||||
|
||||
// Create a connection for the server. The connection uses Node's IPC as a transport.
|
||||
// Also include all preview / proposed LSP features.
|
||||
const connection = createConnection(ProposedFeatures.all);
|
||||
|
||||
// Create a simple text document manager. The text document manager
|
||||
// supports full document sync only
|
||||
const documents = new TextDocuments(TextDocument);
|
||||
|
||||
const htmlLanguageService = getLanguageService();
|
||||
|
||||
connection.onInitialize((_params: InitializeParams) => {
|
||||
console.log("initialize server");
|
||||
return {
|
||||
capabilities: {
|
||||
textDocumentSync: TextDocumentSyncKind.Full,
|
||||
// Tell the client that the server supports code completion
|
||||
completionProvider: {
|
||||
triggerCharacters: [
|
||||
..."abcdefghijklmnopqrstuvwxyz".split(""),
|
||||
..."ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""),
|
||||
],
|
||||
resolveProvider: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
connection.onCompletion(async (textDocumentPosition, _token) => {
|
||||
console.log(
|
||||
"provideCompletionItem server",
|
||||
textDocumentPosition.textDocument.uri,
|
||||
textDocumentPosition.position,
|
||||
);
|
||||
const document = documents.get(textDocumentPosition.textDocument.uri);
|
||||
if (!document) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return htmlLanguageService.doComplete(
|
||||
document,
|
||||
textDocumentPosition.position,
|
||||
htmlLanguageService.parseHTMLDocument(document),
|
||||
);
|
||||
});
|
||||
|
||||
documents.listen(connection);
|
||||
connection.listen();
|
||||
14
contrib/html/editors/vscode/tsconfig.json
Normal file
14
contrib/html/editors/vscode/tsconfig.json
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"types": ["mocha", "chai", "node"],
|
||||
"target": "es2020",
|
||||
"lib": ["es2020"],
|
||||
"outDir": "out",
|
||||
"rootDir": "src",
|
||||
"sourceMap": true,
|
||||
"strict": true
|
||||
},
|
||||
"include": ["src", "scripts"],
|
||||
"exclude": ["node_modules/*", "../../node_modules/*"]
|
||||
}
|
||||
8
contrib/html/editors/vscode/tsconfig.test.json
Normal file
8
contrib/html/editors/vscode/tsconfig.test.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "test-dist"
|
||||
},
|
||||
"include": ["src/test"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
120
contrib/nix/dev/flake.nix
Normal file
120
contrib/nix/dev/flake.nix
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
fenix = {
|
||||
url = "github:nix-community/fenix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
rust-manifest = {
|
||||
url = "https://static.rust-lang.org/dist/channel-rust-1.88.0.toml";
|
||||
flake = false;
|
||||
};
|
||||
};
|
||||
|
||||
outputs = inputs @ { self, flake-parts, nixpkgs, fenix, rust-manifest, }:
|
||||
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
systems = [ "x86_64-linux" ];
|
||||
|
||||
perSystem = {config, lib, pkgs, system, ...}:
|
||||
let
|
||||
rust-toolchain = (fenix.packages.${system}.fromManifestFile rust-manifest).defaultToolchain;
|
||||
tinymist = (pkgs.makeRustPlatform {
|
||||
cargo = rust-toolchain;
|
||||
rustc = rust-toolchain;
|
||||
}).buildRustPackage (finalAttrs: {
|
||||
pname = "tinymist";
|
||||
# Please update the corresponding vscode extension when updating
|
||||
# this derivation.
|
||||
version = "0.14.6-rc1";
|
||||
|
||||
src = pkgs.lib.cleanSource ../../..;
|
||||
|
||||
useFetchCargoVendor = true;
|
||||
cargoHash = "sha256-IyGYBbb8ilK+8fsFAm1N2A0Cw0qrbTqG20TgQs+1yaA=";
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.installShellFiles
|
||||
pkgs.pkg-config
|
||||
];
|
||||
|
||||
checkFlags = [
|
||||
"--skip=e2e"
|
||||
|
||||
# Require internet access
|
||||
"--skip=docs::package::tests::cetz"
|
||||
"--skip=docs::package::tests::fletcher"
|
||||
"--skip=docs::package::tests::tidy"
|
||||
"--skip=docs::package::tests::touying"
|
||||
|
||||
# Tests are flaky for unclear reasons since the 0.12.3 release
|
||||
# Reported upstream: https://github.com/Myriad-Dreamin/tinymist/issues/868
|
||||
"--skip=analysis::expr_tests::scope"
|
||||
"--skip=analysis::post_type_check_tests::test"
|
||||
"--skip=analysis::type_check_tests::test"
|
||||
"--skip=completion::tests::test_pkgs"
|
||||
"--skip=folding_range::tests::test"
|
||||
"--skip=goto_definition::tests::test"
|
||||
"--skip=hover::tests::test"
|
||||
"--skip=inlay_hint::tests::smart"
|
||||
"--skip=prepare_rename::tests::prepare"
|
||||
"--skip=references::tests::test"
|
||||
"--skip=rename::tests::test"
|
||||
"--skip=semantic_tokens_full::tests::test"
|
||||
];
|
||||
|
||||
postInstall = lib.optionalString (pkgs.stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages) (
|
||||
let
|
||||
emulator = pkgs.stdenv.hostPlatform.emulator pkgs.buildPackages;
|
||||
in
|
||||
''
|
||||
installShellCompletion --cmd tinymist \
|
||||
--bash <(${emulator} $out/bin/tinymist completion bash) \
|
||||
--fish <(${emulator} $out/bin/tinymist completion fish) \
|
||||
--zsh <(${emulator} $out/bin/tinymist completion zsh)
|
||||
''
|
||||
);
|
||||
|
||||
nativeInstallCheckInputs = [
|
||||
pkgs.versionCheckHook
|
||||
];
|
||||
versionCheckProgramArg = "-V";
|
||||
doInstallCheck = true;
|
||||
|
||||
meta = {
|
||||
description = "Tinymist is an integrated language service for Typst";
|
||||
homepage = "https://github.com/Myriad-Dreamin/tinymist";
|
||||
changelog = "https://github.com/Myriad-Dreamin/tinymist/blob/v${finalAttrs.version}/editors/vscode/CHANGELOG.md";
|
||||
license = lib.licenses.asl20;
|
||||
mainProgram = "tinymist";
|
||||
maintainers = with lib.maintainers; [
|
||||
GaetanLepage
|
||||
lampros
|
||||
];
|
||||
};
|
||||
});
|
||||
in {
|
||||
# export the project devshell as the default devshell
|
||||
devShells.default = pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
rust-analyzer
|
||||
nodejs_24
|
||||
(yarn.override { nodejs = nodejs_24; })
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
echo "Docs: docs/tinymist/nix.typ."
|
||||
'';
|
||||
};
|
||||
# Developing neovim integration requires a fresh tinymist binary
|
||||
devShells.neovim = pkgs.mkShell {
|
||||
buildInputs = [
|
||||
tinymist
|
||||
];
|
||||
shellHook = ''
|
||||
echo "Docs: docs/tinymist/nix.typ."
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
23
contrib/nix/unstable/flake.nix
Normal file
23
contrib/nix/unstable/flake.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# https://wiki.nixos.org/wiki/Flakes
|
||||
{
|
||||
description = "A flake configuration to use tinymist CLI from unstable nixpkgs";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs }:
|
||||
let
|
||||
system = "x86_64-linux";
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
in {
|
||||
devShells.x86_64-linux.default = pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
tinymist
|
||||
];
|
||||
shellHook = ''
|
||||
echo "Got tinymist from nixpkgs unstable channel"
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
5
contrib/typst-preview/editors/vscode/.gitignore
vendored
Normal file
5
contrib/typst-preview/editors/vscode/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
out
|
||||
dist
|
||||
node_modules
|
||||
.vscode-test/
|
||||
*.vsix
|
||||
11
contrib/typst-preview/editors/vscode/.vscodeignore
Normal file
11
contrib/typst-preview/editors/vscode/.vscodeignore
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
node_modules
|
||||
.vscode/**
|
||||
.vscode-test/**
|
||||
src/**
|
||||
.gitignore
|
||||
.yarnrc
|
||||
vsc-extension-quickstart.md
|
||||
**/tsconfig.json
|
||||
**/.eslintrc.json
|
||||
**/*.map
|
||||
**/*.ts
|
||||
1
contrib/typst-preview/editors/vscode/.yarnrc
Normal file
1
contrib/typst-preview/editors/vscode/.yarnrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
--ignore-engines true
|
||||
368
contrib/typst-preview/editors/vscode/CHANGELOG.md
Normal file
368
contrib/typst-preview/editors/vscode/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,368 @@
|
|||
# Change Log
|
||||
|
||||
Mirroring from [Tinymist Changelog](https://github.com/Myriad-Dreamin/tinymist/blob/main/editors/vscode/CHANGELOG.md)
|
||||
|
||||
## v0.11.14 - [2024-07-07]
|
||||
|
||||
## Compiler
|
||||
|
||||
This bug is introduced by [Preparing for parallelizing lsp requests](https://github.com/Myriad-Dreamin/tinymist/pull/342).
|
||||
|
||||
* (Fix) Lsp should respond errors at tail in https://github.com/Myriad-Dreamin/tinymist/pull/367
|
||||
|
||||
### Commands/Tools
|
||||
|
||||
* Supported single-task preview commands in https://github.com/Myriad-Dreamin/tinymist/pull/364, https://github.com/Myriad-Dreamin/tinymist/pull/368, https://github.com/Myriad-Dreamin/tinymist/pull/370, and https://github.com/Myriad-Dreamin/tinymist/pull/371
|
||||
* Typst Preview extension is already integrated into Tinymist. It . Please disable Typst Preview extension to avoid conflicts.
|
||||
* Otherwise, you should disable the tinymist's embedded preview feature by `"tinymist.preview": "disable"` in your settings.json.
|
||||
|
||||
### Preview
|
||||
|
||||
* Persisting webview preview through vscode restarts by @Myriad-Dreamin and @noamzaks in https://github.com/Myriad-Dreamin/tinymist/pull/373
|
||||
|
||||
**Full Changelog**: https://github.com/Myriad-Dreamin/tinymist/compare/v0.11.13...v0.11.14
|
||||
|
||||
# Change Log (v0.1.0 - v0.11.7)
|
||||
|
||||
All notable changes to the "typst-preview" extension will be documented in this file.
|
||||
|
||||
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
|
||||
|
||||
## v0.11.7 - [2024-06-09]
|
||||
|
||||
Thanks @7sDream for this release!
|
||||
|
||||
- Add supports for setting `sys.inputs` in configuration
|
||||
- Add support for ignoring system fonts.
|
||||
|
||||
## v0.11.6 - [2024-05-19]
|
||||
|
||||
- Add extension icon designed by Zoknatwrd and QuarticCat🔮
|
||||
|
||||
## v0.11.5 - [2024-05-19]
|
||||
|
||||
- Bump to typst v0.11.1
|
||||
- Show activity bar icon only when current file is a typst file
|
||||
|
||||
## v0.11.4 - [2024-04-09]
|
||||
|
||||
- Fix version in nix build
|
||||
- Fix desync in firefox
|
||||
|
||||
## v0.11.3 - [2024-03-25]
|
||||
|
||||
- Bump to typst.ts 0.5.0-rc1
|
||||
|
||||
## v0.11.2 - [2024-03-21]
|
||||
|
||||
- Fix:
|
||||
- #254 Zoom regression in 0.10.8 is now fixed
|
||||
- #270 Wrong webview panel location when using 2-row layout
|
||||
- Fix preview button being slow when using tinymist
|
||||
|
||||
## v0.11.1 - [2024-03-18]
|
||||
|
||||
- Fix:
|
||||
- remove windows-ia32. It is not supported by vscode anymore.
|
||||
|
||||
## v0.11.0 - [2024-03-18]
|
||||
|
||||
- Features:
|
||||
- Upgrade to typst v0.11.0
|
||||
- typst-preview is available on crate.io now. You can install it by running `cargo install typst-preview`. You can also use it as a library in your project by adding `typst-preview` to your `Cargo.toml`.
|
||||
|
||||
## v0.10.10 - [2024-03-13]
|
||||
|
||||
- Features:
|
||||
- Upgrade to typst v0.11.0-rc1(master, 48820fe69b8061bd949847afc343bf160d05c924)
|
||||
- Bug fixes:
|
||||
- Fix gradient color being rendered incorrectly
|
||||
|
||||
## v0.10.9 - [2024-03-10]
|
||||
|
||||
- Features:
|
||||
- Upgrade to typst v0.11.0-rc1
|
||||
- Bug fixes:
|
||||
- May fix a bug when typst preview cannot launch on some windows machines
|
||||
- Fix jumping view while zooming
|
||||
- Fix cannot use relative path in `typst-preview.fontPaths`
|
||||
|
||||
## ~~v0.11.0-rc1 - [2024-03-10]~~
|
||||
|
||||
- Features:
|
||||
- Upgrade to typst v0.11.0-rc1
|
||||
- Bug fixes:
|
||||
- May fix a bug when typst preview cannot launch on some windows machines
|
||||
- Fix jumping view while zooming
|
||||
- Fix cannot use relative path in `typst-preview.fontPaths`
|
||||
|
||||
## v0.10.8 - [2024-02-19]
|
||||
|
||||
- Features:
|
||||
- Add favicon when opening the preview in browser (#239)
|
||||
- Add drag to scroll. You can now drag the preview panel to scroll.
|
||||
- Bug fixes:
|
||||
- fix sensitive scale on touchpad (#244)
|
||||
- The vscode extension will check the server version before starting.
|
||||
- Misc:
|
||||
- Add async tracing and add a new command `typst-preview.showAwaitTree` to pop a message and copy the async tree to clipboard. This is useful for debugging.
|
||||
- Add split debug symbol for the server.
|
||||
-
|
||||
## v0.10.7 - [2024-01-25]
|
||||
|
||||
- Features:
|
||||
- Jump to source is more accurate now.
|
||||
- Add a config to invert color in preview panel. See `typst-preview.invertColors`.
|
||||
- Allow config scroll sync mode. See `typst-preview.scrollSync`
|
||||
- (Experimental) Improve cursor indicator.
|
||||
|
||||
## v0.10.6 - [2024-01-17]
|
||||
|
||||
- Bug fixes:
|
||||
- fix a bug which cause the preview panel no longer updates as you type
|
||||
|
||||
## v0.10.5 - [2024-01-14]
|
||||
|
||||
- Bug fixes:
|
||||
- fix a bug that fails to incrementally rendering pages with transformed content
|
||||
- fix #141: glyph data desync problem, corrupting state of webview typically after your editor hibernating and coming back.
|
||||
|
||||
- Features:
|
||||
- performance is now improved even further. We now use a more efficient way to render the document.
|
||||
|
||||
## v0.10.4 - [2024-01-05]
|
||||
|
||||
- Bug fixes:
|
||||
- Fix open in browser. It's broken in v0.10.3.
|
||||
|
||||
- Features:
|
||||
- Improve incremental rendering performance.
|
||||
|
||||
## v0.10.3 - [2024-01-01]
|
||||
|
||||
- Bug fixes:
|
||||
- Thanks to new rendering technique, scrolling in no longer laggy on long document.
|
||||
|
||||
- Features:
|
||||
- We now automatically declare the previewing file as entrypoint when `typst-preview.pinPreviewFile` is set to `true`. This is like the eye icon in webapp. This should improve diagnostic messages for typst lsp. You can enable this by setting `typst-preview.pinPreviewFile` to `true`.
|
||||
|
||||
## v0.10.2 - [2023-12-18]
|
||||
|
||||
- Bug fixes:
|
||||
- fix scrollbar hiding
|
||||
|
||||
## v0.10.1 - [2023-12-17]
|
||||
|
||||
- Features:
|
||||
- Improve thumbnail side panel and outline. Now it is clickable and you can jump to the corresponding page.
|
||||
|
||||
- Bug fixes:
|
||||
- Improve performance for outline generation.
|
||||
|
||||
## v0.10.0 - [2023-12-05]
|
||||
|
||||
- Features:
|
||||
- Bump to typst v0.10.0
|
||||
|
||||
## v0.9.2 - [2023-11-23]
|
||||
|
||||
- Features:
|
||||
- You can now enable a preview panel in the sidebar. See `typst-preview.showInActivityBar`.
|
||||
- A new keybinding is added. You can trigger preview by using `Ctrl`/`Cmd` + `k` `v` now.
|
||||
|
||||
- Bug fix:
|
||||
- Scroll to cursor on 2-column documents is now improved.
|
||||
|
||||
## v0.9.1 - [2023-11-17]
|
||||
|
||||
- Features:
|
||||
- #160: Slides mode is available now! You can enable use `typst-preview.preview-slide` command.
|
||||
- Allow adjust the status bar item
|
||||
|
||||
- Bug fixes:
|
||||
- Previously the `Compiling` status is never sent to the status bar item. This is now fixed.
|
||||
- #183 #128 Various rendering fix.
|
||||
|
||||
## v0.9.0 - [2023-10-31]
|
||||
|
||||
- Features:
|
||||
- Update to typst v0.9.0
|
||||
- Add a status indicator in status bar. When compile fails, it becomes red. Clicking on it will show the error message.
|
||||
|
||||
- Bug fixes:
|
||||
- #143 Scrolling is not that laggy now
|
||||
- #159 Fix a clip path bug
|
||||
|
||||
## v0.8.3 - [2023-10-28]
|
||||
|
||||
- Bug fixes:
|
||||
- #152 Do not pop up error message when the preview window is closed
|
||||
- #156 Fix shaking scrollbar/border
|
||||
- #161 #151 Should not panic when the file is not exist
|
||||
|
||||
- Features:
|
||||
- #157 Add a rough indicator for the current cursor position in the preview panel. You may enable this in configuration.
|
||||
|
||||
## v0.8.2 - [2023-10-20]
|
||||
|
||||
- Features:
|
||||
- #142 The scroll position of the preview panel is now preserved when you switch between tabs.
|
||||
- #133 We now provide a button to show log when the server crashes. This should make debugging easier. You may also use the command `typst-preview.showLog` to show the log.
|
||||
- #129 A `--version` flag is now provided in the cli
|
||||
|
||||
- Bug fixes:
|
||||
- #137 Previously preview page might go blank when saving the file
|
||||
- #130 Previously you cannot watch a file in `/tmp`
|
||||
- #118 Previously the preview page might flash when you save the file
|
||||
|
||||
## v0.8.1 - [2023-09-24]
|
||||
|
||||
- Bug fixes:
|
||||
- #121: Disable darkreader for preview panel. This should fix the problem where the preview panel is invisible when darkreader is installed in the browser.
|
||||
- #123: Fix a VDOM bug which may cause color/clip-path desync.
|
||||
- #124: Fix a race condition which may cause the webview process messages out of order, resulting in blank screen.
|
||||
- #125: Resizing the preview panel is not that laggy now.
|
||||
- Features:
|
||||
- #120: We now show page breaks and center pages horizontally. By default we will choose the `vscode-sideBar-background` color as the page break color. If it is not distinguishable from white, we will use rgb(82, 86, 89) instead.
|
||||
|
||||
## v0.8.0 - [2023-09-17]
|
||||
|
||||
- Upgrade to typst v0.8.0
|
||||
- Fix #111: Previously stroke related attributes are not rendered correctly. This is now fixed.
|
||||
- Fix #105: The compiler will panic randomly. This is now fixed.
|
||||
- Upstream bug fixes: <https://github.com/Myriad-Dreamin/typst.ts/releases/tag/v0.4.0-rc3>
|
||||
|
||||
## v0.7.5 - [2023-09-01]
|
||||
|
||||
- Fix #107: now VSCode variables like `${workspaceFolder}` can be used in `typst-preview.fontPaths`.
|
||||
- Fix cannot open multiple preview tabs at the same time.
|
||||
|
||||
## v0.7.4 - [2023-08-29]
|
||||
|
||||
- Typst Preview Book is now available at <https://enter-tainer.github.io/typst-preview/> ! You can find the documentation of Typst Preview there.
|
||||
- Improved standalone usage: Use `typst-preview` without VSCode now becomes easier. All you need is `typst-preview --partial-rendering cool-doc.typ`. Take a look at <https://enter-tainer.github.io/typst-preview/standalone.html>
|
||||
- Upgrade to typst.ts 0.4.0-rc2. This fixes a subtle incremental parsing bug.
|
||||
- Partial rendering is now enabled by default. This should improve performance on long document. You can disable it by setting `typst-preview.partialRendering` to `false`.
|
||||
|
||||
## v0.7.3 - [2023-08-20]
|
||||
|
||||
- Bugfix: fix a subtle rendering issue, [typst.ts#306](https://github.com/Myriad-Dreamin/typst.ts/pull/306).
|
||||
|
||||
## v0.7.2 - [2023-08-20]
|
||||
|
||||
- Bug fixes:
|
||||
- #79: We now put typst compiler and renderer in a dedicate thread. Therefore we should get more stable performance.
|
||||
- #78: Currently only the latest compile/render request is processed. This should fix the problem where the preview request will queue up when you type too fast and the doc takes a lot of time to compile.
|
||||
- #81: We now use a more robust way to detect the whether to kill stale server process. This should fix the problem where the when preview tab will become blank when it becomes inactive for a while.
|
||||
- #87: Add enum description for `typst-preview.scrollSync`. Previously the description is missing.
|
||||
|
||||
## v0.7.1 - [2023-08-16]
|
||||
|
||||
- Bug fixes:
|
||||
- fix #41. It is now possible to use Typst Preview in VSCode Remote.
|
||||
- fix #82. You can have preview button even when typst-lsp is not installed.
|
||||
- Misc: We downgrade the ci image for Linux to Ubuntu 20.04. This should fix the problem where the extension cannot be installed on some old Linux distros.
|
||||
|
||||
## v0.7.0 - [2023-08-09]
|
||||
|
||||
- Upgrade to typst v0.7.0
|
||||
- Bug fixes
|
||||
- #77 #75: Previously arm64 devices will see a blank preview. This is now fixed.
|
||||
- #74: Previously when you open a file without opening in folder, the preview will not work. This is now fixed.
|
||||
|
||||
## v0.6.4 - [2023-08-06]
|
||||
|
||||
- Rename to Typst Preview.
|
||||
- Add page level partial rendering. This should improve performance on long document. This is an experimental feature and is disabled by default. You can enable it by setting `typst-preview.partialRendering` to `true`.
|
||||
- The binary `typst-preview` now can be used as a standalone typst server. You can use it to preview your document in browser. For example: `typst-preview ./assets/demo/main.typ --open-in-browser --partial-rendering`
|
||||
- Fix #70: now you can launch many preview instances at the same time.
|
||||
|
||||
## v0.6.3 - [2023-07-29]
|
||||
|
||||
- Fix #13, #63: Now ctrl+wheel zoom should zoom the content to the cursor position. And when the cursor is not within the document, the zoom sill works.
|
||||
|
||||
## v0.6.2 - [2023-07-25]
|
||||
|
||||
- Fix #60 and #24. Now we watch dirty files in memory therefore no shadow file is needed. Due to the removal of disk read/write, this should also improve performance and latency.
|
||||
- Preview on type is now enabled by default for new users. Existing users will not be affected.
|
||||
|
||||
## v0.6.1 - [2023-07-14]
|
||||
|
||||
- Fix empty file preview. Previously, if you start with an empty file and type something, the preview will not be updated. This is now fixed.
|
||||
|
||||
## v0.6.0 - [2023-07-06]
|
||||
|
||||
- Upgrade to typst v0.6.0
|
||||
- Bug fixes:
|
||||
- #48: Webview cannot load frontend resources when VSCode is installed by scoop
|
||||
- #46: Preview to source jump not working after inserting new text in the source file
|
||||
- #52: Bug fix about VDOM operation
|
||||
- Enhancement
|
||||
- #54: Only scroll the preview panel when the event is triggered by mouse
|
||||
|
||||
## v0.5.1 - [2023-06-30]
|
||||
|
||||
- Performance improvement(#14): We now use typst.ts. We utilize a [virtual DOM](https://en.wikipedia.org/wiki/Virtual_DOM) approach to diff and render the document. This is a **significant enhancement** of previewing document in `onType` mode in terms of resource savings and response time for changes.
|
||||
- Cross jump between code and preview (#36): We implement SyncTeX-like feature for typst-preview. You can now click on the preview panel to jump to the corresponding code location, and vice versa. This feature is still experimental and may not work well in some cases. Please report any issues you encounter.
|
||||
- Sync preview position with cursor: We now automatically scroll the preview panel to the corresponding position of the cursor. This feature is controlled by `typst-preview.scrollSync`
|
||||
- Open preview in separate window(#39): You can type `typst-preview.browser` in command palette to open the preview page in a separate browser.
|
||||
- Links in preview panel: You can now click on links in the preview panel to open them in browser. The cross reference links are also clickable.
|
||||
- Text selection in preview panel: You can now select text in the preview panel.
|
||||
|
||||
## v0.5.0 - [2023-06-10]
|
||||
|
||||
- Upgrade to typst v0.5.0
|
||||
|
||||
## v0.4.1 - [2023-06-07]
|
||||
|
||||
- Makes the WebSocket connection retry itself when it is closed, with a delay of 1 second.
|
||||
|
||||
## v0.4.0 - [2023-06-07]
|
||||
|
||||
- Upgrade to typst v0.4.0
|
||||
|
||||
## v0.3.3 - [2023-05-11]
|
||||
|
||||
- Fix nix-ld compatibility by inheriting env vars(#33)
|
||||
|
||||
## v0.3.1 - [2023-05-04]
|
||||
|
||||
- Publish to OpenVSX
|
||||
- allow configuring font paths
|
||||
|
||||
## v0.3.0 - [2023-04-26]
|
||||
|
||||
- Upgrade typst to v0.3.0
|
||||
- Fix panic when pages are removed
|
||||
|
||||
## v0.2.4 - [2023-04-21]
|
||||
|
||||
- Automatically choose a free port to listen. This should fix the problem where you can't preview multiple files at the same time.
|
||||
- Server will exit right after client disconnects, preventing resource leak.
|
||||
|
||||
## v0.2.3 - [2023-04-20]
|
||||
|
||||
- Performance Improvement: only update pages when they are visible. This should improve performance when you have a lot of pages.
|
||||
|
||||
## v0.2.2 - [2023-04-16]
|
||||
|
||||
- Fix server process not killed on exit(maybe)
|
||||
- Add config for OnSave/OnType
|
||||
- Add output channel for logging
|
||||
|
||||
## v0.2.1 - [2023-04-16]
|
||||
|
||||
- Bundle typst-ws within vsix. You no longer need to install typst-ws
|
||||
|
||||
## v0.1.7 - [2023-04-10]
|
||||
|
||||
- Preview on type
|
||||
- Add config entry for `typst-ws` path
|
||||
|
||||
## v0.1.6 - [2023-04-09]
|
||||
|
||||
Add preview button
|
||||
|
||||
## v0.1.0 - [2023-04-09]
|
||||
|
||||
Initial release
|
||||
21
contrib/typst-preview/editors/vscode/LICENSE
Normal file
21
contrib/typst-preview/editors/vscode/LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 mgt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
55
contrib/typst-preview/editors/vscode/README.md
Normal file
55
contrib/typst-preview/editors/vscode/README.md
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# [DEPRECATION NOTICE] Typst preview extension has been integrated into [tinymist](https://github.com/Myriad-Dreamin/tinymist)
|
||||
|
||||
We recommend all users migrate to tinymist for the following benefits:
|
||||
|
||||
- More centralized resource management
|
||||
- Reduced redundancy and lower resource usage
|
||||
- Easier updates and maintenance
|
||||
|
||||
This repository will no longer be updated in future. All development will move to tinymist. Thank you for your support and understanding!
|
||||
|
||||
- We still maintain the typst-preview extension for a while in a best effort way.
|
||||
- The lazy people can continue using their setting, as all old things are still working.
|
||||
- This respect people who love minimal env, like a treesitter plugin plus preview.
|
||||
- Tinymist will ensure compatibility to typst-preview as much as possible.
|
||||
- for vscode users: uninstall the preview extension and install the tinymist extension.
|
||||
- for standalone cli users: `typst-preview -> tinymist preview`
|
||||
|
||||
# [Typst Preview VSCode](https://github.com/Enter-tainer/typst-preview)
|
||||
|
||||
Preview your Typst files in vscode instantly!
|
||||
|
||||
## Features
|
||||
|
||||
- Low latency preview: preview your document instantly on type. The incremental rendering technique makes the preview latency as low as possible.
|
||||
- Open in browser: open the preview in browser, so you put it in another monitor. https://github.com/typst/typst/issues/1344
|
||||
- Cross jump between code and preview: We implement SyncTeX-like feature for typst-preview. You can now click on the preview panel to jump to the corresponding code location, and vice versa.
|
||||
|
||||
Install this extension from [marketplace](https://marketplace.visualstudio.com/items?itemName=mgt19937.typst-preview), open command palette (Ctrl+Shift+P), and type `>Typst Preview:`.
|
||||
|
||||
You can also use the shortcut (Ctrl+K V).
|
||||
|
||||

|
||||
|
||||
For more information, please visit documentation at [Typst Preview Book](https://enter-tainer.github.io/typst-preview/).
|
||||
|
||||
## Extension Settings
|
||||
|
||||
See https://enter-tainer.github.io/typst-preview/config.html
|
||||
|
||||
## Bug report
|
||||
|
||||
To achieve high performance instant preview, we use a **different rendering backend** from official typst. We are making our best effort to keep the rendering result consistent with official typst. We have set up comprehensive tests to ensure the consistency of the rendering result. But we cannot guarantee that the rendering result is the same in all cases. There can be unknown corner cases that we haven't covered.
|
||||
|
||||
**Therefore, if you encounter any rendering issue, please report it to this repo other than official typst repo.**
|
||||
## Known Issues
|
||||
|
||||
See [issues](https://github.com/Enter-tainer/typst-preview/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) on GitHub.
|
||||
|
||||
## Legal
|
||||
|
||||
This project is not affiliated with, created by, or endorsed by Typst the brand.
|
||||
|
||||
## Change Log
|
||||
|
||||
See [CHANGELOG.md](CHANGELOG.md)
|
||||
BIN
contrib/typst-preview/editors/vscode/demo.png
Normal file
BIN
contrib/typst-preview/editors/vscode/demo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 106 KiB |
282
contrib/typst-preview/editors/vscode/package.json
Normal file
282
contrib/typst-preview/editors/vscode/package.json
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
{
|
||||
"name": "typst-preview",
|
||||
"displayName": "Typst Preview",
|
||||
"description": "preview your typst document in instant",
|
||||
"publisher": "mgt19937",
|
||||
"license": "MIT",
|
||||
"icon": "./preview-logo.png",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Enter-tainer/typst-preview"
|
||||
},
|
||||
"version": "0.11.14",
|
||||
"engines": {
|
||||
"vscode": "^1.97.0"
|
||||
},
|
||||
"categories": [
|
||||
"Other"
|
||||
],
|
||||
"activationEvents": [
|
||||
"onLanguage:typst"
|
||||
],
|
||||
"main": "./out/extension.js",
|
||||
"contributes": {
|
||||
"icons": {
|
||||
"typst-guy": {
|
||||
"description": "typst guy",
|
||||
"default": {
|
||||
"fontPath": "./preview.woff",
|
||||
"fontCharacter": "A"
|
||||
}
|
||||
}
|
||||
},
|
||||
"languages": [
|
||||
{
|
||||
"id": "typst",
|
||||
"extensions": [
|
||||
".typ"
|
||||
]
|
||||
}
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"command": "typst-preview.preview",
|
||||
"title": "Typst Preview: Preview current file",
|
||||
"description": "Launch typst-preview server",
|
||||
"icon": "$(open-preview)",
|
||||
"when": "resourceLangId == typst && editorTextFocus"
|
||||
},
|
||||
{
|
||||
"command": "typst-preview.browser",
|
||||
"title": "Typst Preview: Preview current file in browser",
|
||||
"description": "Launch typst-preview server and open the preview in your browser",
|
||||
"icon": "$(open-preview)",
|
||||
"when": "resourceLangId == typst && editorTextFocus"
|
||||
},
|
||||
{
|
||||
"command": "typst-preview.preview-slide",
|
||||
"title": "Typst Preview: Preview current file in slide mode",
|
||||
"description": "Launch typst-preview server in slide mode",
|
||||
"icon": "$(open-preview)",
|
||||
"when": "resourceLangId == typst && editorTextFocus"
|
||||
},
|
||||
{
|
||||
"command": "typst-preview.browser-slide",
|
||||
"title": "Typst Preview: Preview current file in browser and slide mode",
|
||||
"description": "Launch typst-preview server in slide mode and open the preview in your browser",
|
||||
"icon": "$(open-preview)",
|
||||
"when": "resourceLangId == typst && editorTextFocus"
|
||||
},
|
||||
{
|
||||
"command": "typst-preview.sync",
|
||||
"title": "Typst Preview: Sync preview with current cursor",
|
||||
"description": "Scroll preview to current cursor position",
|
||||
"icon": "$(sync)",
|
||||
"when": "resourceLangId == typst && editorTextFocus"
|
||||
},
|
||||
{
|
||||
"command": "typst-preview.showLog",
|
||||
"title": "Typst Preview: Show Log",
|
||||
"description": "Show typst-preview log",
|
||||
"icon": "$(list-flat)",
|
||||
"when": "resourceLangId == typst"
|
||||
},
|
||||
{
|
||||
"command": "typst-preview.noteOutline",
|
||||
"title": "Note: Jumping to source location of the outline item doesn't work well if its body doesn't have source location, e.g.\n```\n#let my-heading(h) = heading(h) // will jump to here\n#my-heading(\"Title\") // will not jump to here\n```.\nHence, you may want to use `my-heading[Title]` instead to gain better experience of outline jumping.",
|
||||
"description": "...",
|
||||
"icon": "$(extensions-info-message)"
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
"editor/title": [
|
||||
{
|
||||
"command": "typst-preview.preview",
|
||||
"when": "resourceLangId == typst && editorTextFocus",
|
||||
"group": "navigation"
|
||||
}
|
||||
],
|
||||
"view/title": [
|
||||
{
|
||||
"command": "typst-preview.noteOutline",
|
||||
"when": "view == typst-preview.outline",
|
||||
"group": "navigation"
|
||||
}
|
||||
]
|
||||
},
|
||||
"viewsContainers": {
|
||||
"activitybar": [
|
||||
{
|
||||
"id": "typst-preview-activitybar",
|
||||
"title": "Typst Preview",
|
||||
"icon": "./icons/activity-bar.svg"
|
||||
}
|
||||
]
|
||||
},
|
||||
"views": {
|
||||
"typst-preview-activitybar": [
|
||||
{
|
||||
"id": "typst-preview.content-preview",
|
||||
"type": "webview",
|
||||
"name": "Content",
|
||||
"when": "config.typst-preview.showInActivityBar && resourceLangId == typst"
|
||||
},
|
||||
{
|
||||
"id": "typst-preview.outline",
|
||||
"name": "Outline",
|
||||
"when": "config.typst-preview.showInActivityBar && resourceLangId == typst"
|
||||
}
|
||||
]
|
||||
},
|
||||
"configuration": {
|
||||
"title": "Typst Preview",
|
||||
"properties": {
|
||||
"typst-preview.executable": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "Path to typst-preview executable. If not set, the extension will use bundled typst-preview. If bundled binary is not found, it will use typst-preview installed in PATH"
|
||||
},
|
||||
"typst-preview.sysInputs": {
|
||||
"type": "object",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"default": {},
|
||||
"description": "key-value pairs visible through `sys.inputs`, corresponds to `--input` argument of typst cli"
|
||||
},
|
||||
"typst-preview.systemFonts": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Whether to load system fonts. If disabled, only fonts in `typst-preview.fontPaths` is loaded"
|
||||
},
|
||||
"typst-preview.fontPaths": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"title": "Font path",
|
||||
"description": "Absolute path to a directory or file containing font assets."
|
||||
},
|
||||
"default": [],
|
||||
"description": "List of *additional* paths to font assets used by typst-preview."
|
||||
},
|
||||
"typst-preview.refresh": {
|
||||
"title": "Refresh preview",
|
||||
"description": "Refresh preview when the document is saved or when the document is changed",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"onSave",
|
||||
"onType"
|
||||
],
|
||||
"default": "onType",
|
||||
"enumDescriptions": [
|
||||
"Refresh preview on save",
|
||||
"Refresh preview on type"
|
||||
]
|
||||
},
|
||||
"typst-preview.scrollSync": {
|
||||
"description": "Configure scroll sync mode.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"never",
|
||||
"onSelectionChangeByMouse",
|
||||
"onSelectionChange"
|
||||
],
|
||||
"default": "onSelectionChangeByMouse",
|
||||
"enumDescriptions": [
|
||||
"Disable automatic scroll sync",
|
||||
"Scroll preview to current cursor position when selection changes by mouse",
|
||||
"Scroll preview to current cursor position when selection changes by mouse or keyboard (any source)"
|
||||
]
|
||||
},
|
||||
"typst-preview.partialRendering": {
|
||||
"description": "Only render visible part of the document. This can improve performance but still being experimental.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"typst-preview.invertColors": {
|
||||
"description": "Invert colors of the preview (useful for dark themes without cost). Please note you could see the origin colors when you hover elements in the preview.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"never",
|
||||
"auto",
|
||||
"always"
|
||||
],
|
||||
"default": "never",
|
||||
"enumDescriptions": [
|
||||
"Disable color inversion of the preview",
|
||||
"Invert colors smartly by detecting dark/light themes in browser environment or by `typst query` your document",
|
||||
"Always invert colors of the preview"
|
||||
]
|
||||
},
|
||||
"typst-preview.cursorIndicator": {
|
||||
"description": "(Experimental) Show typst cursor indicator in preview.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"typst-preview.showInActivityBar": {
|
||||
"description": "(Experimental) Show a preview panel in activity bar.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"typst-preview.statusBarIndicator": {
|
||||
"description": "Style of status bar indicator for typst-preview.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"full",
|
||||
"compact"
|
||||
],
|
||||
"default": "compact",
|
||||
"enumDescriptions": [
|
||||
"Show full status bar indicator (ICON Compile Success)",
|
||||
"Show compact status bar indicator (ICON)"
|
||||
]
|
||||
},
|
||||
"typst-preview.pinPreviewFile": {
|
||||
"description": "Declare current previewing file as entrypoint for typst-lsp. This will make typst-lsp to use this file as entrypoint instead of the file opened in vscode. This can improve diagnostics messages and auto completion but still being experimental.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"keybindings": [
|
||||
{
|
||||
"command": "typst-preview.preview",
|
||||
"key": "ctrl+k v",
|
||||
"mac": "cmd+k v",
|
||||
"when": "editorLangId == typst"
|
||||
}
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"build:frontend": "cd ../../../../ && yarn build:preview && cd contrib/typst-preview/editors/vscode && yarn install:frontend",
|
||||
"install:frontend": "rimraf ./out/frontend/ && cpr ../../../../tools/typst-preview-frontend/dist/ ./out/frontend/",
|
||||
"build-base": "esbuild ../../../../editors/vscode/src/extension.preview.ts --bundle --outfile=out/extension.js --external:vscode --format=cjs --platform=node --target=node16",
|
||||
"vscode:prepublish": "yarn run build-base -- --minify && yarn run build:frontend",
|
||||
"compile": "yarn run build-base -- --sourcemap && yarn run build:frontend",
|
||||
"build": "yarn run compile",
|
||||
"watch": "yarn run build-base -- --sourcemap --watch",
|
||||
"pretest": "yarn run compile && yarn run lint",
|
||||
"package": "vsce package --yarn",
|
||||
"lint": "eslint src",
|
||||
"test": "node ./out/test/runTest.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/cross-spawn": "^6.0.2",
|
||||
"@types/glob": "^8.1.0",
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@types/node": "^22.13.4",
|
||||
"@types/vscode": "^1.97.0",
|
||||
"@types/ws": "^8.5.5",
|
||||
"@vscode/test-electron": "^2.3.9",
|
||||
"@vscode/vsce": "^2.22.0",
|
||||
"glob": "^8.1.0",
|
||||
"mocha": "^10.2.0",
|
||||
"typescript": "^5.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.3",
|
||||
"node-fetch": "^3.3.2",
|
||||
"vscode-variables": "^0.1.3",
|
||||
"ws": "^8.13.0"
|
||||
}
|
||||
}
|
||||
BIN
contrib/typst-preview/editors/vscode/preview-logo.png
Normal file
BIN
contrib/typst-preview/editors/vscode/preview-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
22
contrib/typst-preview/editors/vscode/preview-logo.svg
Normal file
22
contrib/typst-preview/editors/vscode/preview-logo.svg
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2" viewBox="0 0 600 600">
|
||||
<filter xmlns="http://www.w3.org/2000/svg" id="a" width="100%" height="100%" x="0%" y="0%">
|
||||
<feTurbulence xmlns="http://www.w3.org/2000/svg" baseFrequency=".005" type="fractalNoise"/>
|
||||
</filter>
|
||||
<path d="M0 0h600v600H0z" style="fill:#30a9b3;fill-rule:nonzero"/>
|
||||
<path d="M0 0h600v600H0z" opacity=".5" style="filter:url(#a)"/>
|
||||
<path d="M7.888 18.148c0 1.133.162 1.892.487 2.28.325.387.916.581 1.773.581.886 0 2.024-.447 3.412-1.341l.886 1.475c-2.599 2.175-4.741 3.263-6.425 3.263-1.684 0-3.014-.402-3.988-1.207-.975-.834-1.463-2.294-1.463-4.38V7.107H.355L0 5.453l2.57-.804V2.458L7.888 0v4.917l5.229-.402-.488 2.905-4.741-.179v10.907Z" style="fill:#fff;fill-rule:nonzero" transform="translate(200 122) scale(14.1524)"/>
|
||||
<circle cx="240" cy="247" r="101" style="fill:#30a9b3" transform="translate(-7 9)"/>
|
||||
<g transform="translate(163 144) scale(16.7338)">
|
||||
<clipPath id="b">
|
||||
<circle cx="4.183" cy="6.693" r="6.036"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#b)">
|
||||
<path d="M7.888 18.148c0 1.133.162 1.892.487 2.28.325.387.916.581 1.773.581.886 0 2.024-.447 3.412-1.341l.886 1.475c-2.599 2.175-4.741 3.263-6.425 3.263-1.684 0-3.014-.402-3.988-1.207-.975-.834-1.463-2.294-1.463-4.38V7.107H.355L0 5.453l2.57-.804V2.458L7.888 0v4.917l5.229-.402-.488 2.905-4.741-.179v10.907Z" style="fill:#fff;fill-rule:nonzero"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="M352.734 406.179a8.004 8.004 0 0 1-5.668-2.348l-72.685-72.685a8.019 8.019 0 0 1 0-11.337 8.018 8.018 0 0 1 11.337 0l72.685 72.685a8.018 8.018 0 0 1-5.669 13.685" style="fill:#7b7979;fill-rule:nonzero" transform="translate(30)"/>
|
||||
<path d="m429.598 441.015-59.858-59.858a23.91 23.91 0 0 0-17.006-7.045 23.91 23.91 0 0 0-17.006 7.045c-9.377 9.376-9.377 24.635 0 34.011l59.858 59.858a23.91 23.91 0 0 0 17.006 7.045 23.905 23.905 0 0 0 17.006-7.044c9.377-9.377 9.377-24.636 0-34.012" style="fill:#a7a6a6;fill-rule:nonzero" transform="translate(30)"/>
|
||||
<path d="M330.327 389.472c-3.325 8.611-1.534 18.76 5.402 25.696l59.858 59.858a23.91 23.91 0 0 0 17.006 7.045c3.026 0 5.958-.574 8.696-1.635l-90.962-90.964Z" style="fill:#918f90;fill-rule:nonzero" transform="translate(30)"/>
|
||||
<path d="M203.089 129.336c70.433 0 127.732 57.301 127.732 127.733s-57.3 127.732-127.732 127.732S75.356 327.502 75.356 257.069c0-70.433 57.301-127.733 127.733-127.733Zm0 34.205c-51.572 0-93.528 41.956-93.528 93.528s41.957 93.528 93.528 93.528c51.571 0 93.528-41.956 93.528-93.528s-41.956-93.528-93.528-93.528Z" style="fill:#ff8c78" transform="translate(30)"/>
|
||||
<path d="M203.089 149.645c59.234 0 107.424 48.19 107.424 107.424 0 59.234-48.19 107.424-107.424 107.424-59.234 0-107.424-48.19-107.424-107.424 0-59.234 48.19-107.424 107.424-107.424Zm0 13.896c-51.572 0-93.528 41.956-93.528 93.528s41.957 93.528 93.528 93.528c51.571 0 93.528-41.956 93.528-93.528s-41.956-93.528-93.528-93.528Z" style="fill:#df7a6e" transform="translate(30)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3 KiB |
BIN
contrib/typst-preview/editors/vscode/preview.woff
Normal file
BIN
contrib/typst-preview/editors/vscode/preview.woff
Normal file
Binary file not shown.
2
contrib/typst-preview/editors/vscode/src/global.d.ts
vendored
Normal file
2
contrib/typst-preview/editors/vscode/src/global.d.ts
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
interface Window {}
|
||||
declare const acquireVsCodeApi: any;
|
||||
19
contrib/typst-preview/editors/vscode/tsconfig.json
Normal file
19
contrib/typst-preview/editors/vscode/tsconfig.json
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "ES2020",
|
||||
"outDir": "out",
|
||||
"lib": ["ES2020", "DOM"],
|
||||
"sourceMap": true,
|
||||
"rootDir": "../../../../editors/vscode",
|
||||
"skipLibCheck": true,
|
||||
"types": ["./src/global.d.ts"],
|
||||
"resolveJsonModule": true
|
||||
/* Additional Checks */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
},
|
||||
"files": ["../../../../editors/vscode/src/extension.preview.ts"],
|
||||
"include": ["../../../../editors/vscode/src/**/*.ts"]
|
||||
}
|
||||
19
crates/cmark-writer-macros/Cargo.toml
Normal file
19
crates/cmark-writer-macros/Cargo.toml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "cmark-writer-macros"
|
||||
version = "0.9.0"
|
||||
edition = "2021"
|
||||
authors = ["Hong Jiarong"]
|
||||
description = "Proc-macro implementations for cmark-writer"
|
||||
license = "MIT"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
syn = { version = "2.0", features = ["full", "extra-traits"] }
|
||||
quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
cmark-writer = { path = "../cmark-writer" }
|
||||
ecow = "0.2.6"
|
||||
9
crates/cmark-writer-macros/LICENSE
Normal file
9
crates/cmark-writer-macros/LICENSE
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
MIT License
|
||||
|
||||
Copyright 2025 Hong Jiarong
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
387
crates/cmark-writer-macros/src/lib.rs
Normal file
387
crates/cmark-writer-macros/src/lib.rs
Normal file
|
|
@ -0,0 +1,387 @@
|
|||
extern crate proc_macro;
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::Span;
|
||||
use quote::quote;
|
||||
use syn::{
|
||||
parse::Parse, parse::ParseStream, parse_macro_input, DeriveInput, Ident, LitBool, LitStr, Token,
|
||||
};
|
||||
|
||||
/// Parse custom_node attribute parameters
|
||||
struct CustomNodeArgs {
|
||||
is_block: Option<bool>,
|
||||
html_impl: Option<bool>,
|
||||
}
|
||||
|
||||
impl Parse for CustomNodeArgs {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let mut is_block = None;
|
||||
let mut html_impl = None;
|
||||
|
||||
if input.is_empty() {
|
||||
return Ok(CustomNodeArgs {
|
||||
is_block,
|
||||
html_impl,
|
||||
});
|
||||
}
|
||||
|
||||
loop {
|
||||
if input.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
let ident: Ident = input.parse()?;
|
||||
|
||||
if ident == "block" {
|
||||
let _: Token![=] = input.parse()?;
|
||||
let value: LitBool = input.parse()?;
|
||||
is_block = Some(value.value);
|
||||
} else if ident == "html_impl" {
|
||||
let _: Token![=] = input.parse()?;
|
||||
let value: LitBool = input.parse()?;
|
||||
html_impl = Some(value.value);
|
||||
} else {
|
||||
return Err(syn::Error::new_spanned(
|
||||
ident,
|
||||
"Unknown attribute parameter",
|
||||
));
|
||||
}
|
||||
|
||||
// Handle optional comma separator
|
||||
if input.peek(Token![,]) {
|
||||
let _: Token![,] = input.parse()?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(CustomNodeArgs {
|
||||
is_block,
|
||||
html_impl,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct StructureErrorArgs {
|
||||
format: Option<LitStr>,
|
||||
}
|
||||
|
||||
impl Parse for StructureErrorArgs {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let mut format = None;
|
||||
|
||||
while !input.is_empty() {
|
||||
let ident: Ident = input.parse()?;
|
||||
|
||||
if ident == "format" {
|
||||
let _: Token![=] = input.parse()?;
|
||||
let value: LitStr = input.parse()?;
|
||||
format = Some(value);
|
||||
} else {
|
||||
return Err(syn::Error::new_spanned(
|
||||
ident,
|
||||
"Unknown attribute parameter",
|
||||
));
|
||||
}
|
||||
|
||||
if input.peek(Token![,]) {
|
||||
let _: Token![,] = input.parse()?;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self { format })
|
||||
}
|
||||
}
|
||||
|
||||
/// Custom node attribute macro for implementing the CustomNode trait
|
||||
///
|
||||
/// This macro automatically implements the CustomNode trait. Users can specify
|
||||
/// whether the node is a block element using the `block` parameter and whether
|
||||
/// it implements HTML rendering with the `html_impl` parameter.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use cmark_writer::writer::{BlockWriterProxy, HtmlWriteResult, HtmlWriter, InlineWriterProxy};
|
||||
/// use cmark_writer::{custom_node, WriteResult};
|
||||
/// use ecow::EcoString;
|
||||
///
|
||||
/// // Specified as an inline element with both CommonMark and HTML implementations
|
||||
/// #[derive(Debug, Clone, PartialEq)]
|
||||
/// #[custom_node(block=false, html_impl=true)]
|
||||
/// struct HighlightNode {
|
||||
/// content: EcoString,
|
||||
/// color: EcoString,
|
||||
/// }
|
||||
///
|
||||
/// impl HighlightNode {
|
||||
/// // Required for CommonMark rendering
|
||||
/// fn write_custom(&self, writer: &mut InlineWriterProxy) -> WriteResult<()> {
|
||||
/// writer.write_str("<span style=\"background-color: ")?;
|
||||
/// writer.write_str(&self.color)?;
|
||||
/// writer.write_str("\">")?;
|
||||
/// writer.write_str(&self.content)?;
|
||||
/// writer.write_str("</span>")?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
///
|
||||
/// // Optional HTML rendering implementation
|
||||
/// fn write_html_custom(&self, writer: &mut HtmlWriter) -> HtmlWriteResult<()> {
|
||||
/// writer.start_tag("span")?;
|
||||
/// writer.attribute("style", &format!("background-color: {}", self.color))?;
|
||||
/// writer.finish_tag()?;
|
||||
/// writer.text(&self.content)?;
|
||||
/// writer.end_tag("span")?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // Only CommonMark implementation, default HTML implementation
|
||||
/// #[derive(Debug, Clone, PartialEq)]
|
||||
/// #[custom_node(block=true)]
|
||||
/// struct AlertNode {
|
||||
/// content: EcoString,
|
||||
/// }
|
||||
///
|
||||
/// impl AlertNode {
|
||||
/// fn write_custom(&self, writer: &mut BlockWriterProxy) -> WriteResult<()> {
|
||||
/// writer.write_str("<div class=\"alert\">")?;
|
||||
/// writer.write_str(&self.content)?;
|
||||
/// writer.write_str("</div>")?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[proc_macro_attribute]
|
||||
pub fn custom_node(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let args = syn::parse_macro_input!(attr as CustomNodeArgs);
|
||||
let input = parse_macro_input!(item as DeriveInput);
|
||||
let name = &input.ident;
|
||||
|
||||
// Configure is_block implementation
|
||||
let is_block_impl = if let Some(is_block) = args.is_block {
|
||||
quote! {
|
||||
fn is_block(&self) -> bool {
|
||||
#is_block
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
fn is_block(&self) -> bool {
|
||||
self.is_block_custom()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let is_block = args.is_block.unwrap_or(false);
|
||||
|
||||
// Configure html_write implementation
|
||||
let html_write_impl = if args.html_impl.unwrap_or(false) {
|
||||
// When html_impl=true, expect user to implement write_html_custom method
|
||||
quote! {
|
||||
fn html_write(
|
||||
&self,
|
||||
writer: &mut ::cmark_writer::writer::HtmlWriter,
|
||||
) -> ::cmark_writer::writer::HtmlWriteResult<()> {
|
||||
self.write_html_custom(writer)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// When html_impl is not set or false, use default implementation
|
||||
quote! {
|
||||
fn html_write(
|
||||
&self,
|
||||
writer: &mut ::cmark_writer::writer::HtmlWriter,
|
||||
) -> ::cmark_writer::writer::HtmlWriteResult<()> {
|
||||
writer.write_trusted_html(&format!(
|
||||
"<!-- HTML rendering not implemented for Custom Node: {} -->",
|
||||
self.type_name()
|
||||
))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let write_block_impl = if is_block {
|
||||
quote! {
|
||||
fn write_block(
|
||||
&self,
|
||||
writer: &mut ::cmark_writer::writer::BlockWriterProxy,
|
||||
) -> ::cmark_writer::error::WriteResult<()> {
|
||||
self.write_custom(writer)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {}
|
||||
};
|
||||
|
||||
let write_inline_impl = if !is_block {
|
||||
quote! {
|
||||
fn write_inline(
|
||||
&self,
|
||||
writer: &mut ::cmark_writer::writer::InlineWriterProxy,
|
||||
) -> ::cmark_writer::error::WriteResult<()> {
|
||||
self.write_custom(writer)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {}
|
||||
};
|
||||
|
||||
let expanded = quote! {
|
||||
#input
|
||||
|
||||
impl ::cmark_writer::ast::CustomNode for #name {
|
||||
#write_block_impl
|
||||
|
||||
#write_inline_impl
|
||||
|
||||
#html_write_impl
|
||||
|
||||
fn clone_box(&self) -> Box<dyn ::cmark_writer::ast::CustomNode> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
|
||||
fn eq_box(&self, other: &dyn ::cmark_writer::ast::CustomNode) -> bool {
|
||||
if let Some(other) = other.as_any().downcast_ref::<Self>() {
|
||||
self == other
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#is_block_impl
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl #name {
|
||||
pub fn matches(node: &dyn ::cmark_writer::ast::CustomNode) -> bool {
|
||||
node.type_name() == std::any::type_name::<#name>() ||
|
||||
node.as_any().downcast_ref::<#name>().is_some()
|
||||
}
|
||||
|
||||
pub fn extract(node: Box<dyn ::cmark_writer::ast::CustomNode>) -> Option<#name> {
|
||||
node.as_any().downcast_ref::<#name>().map(|n| n.clone())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
|
||||
/// Custom error attribute macro, replaces the struct form errors in the original define_custom_errors! macro
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use cmark_writer::structure_error;
|
||||
///
|
||||
/// #[structure_error(format = "Table column mismatch: {}")]
|
||||
/// struct TableColumnMismatchError(pub &'static str);
|
||||
/// ```
|
||||
#[proc_macro_attribute]
|
||||
pub fn structure_error(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let args = if attr.is_empty() {
|
||||
StructureErrorArgs::default()
|
||||
} else {
|
||||
parse_macro_input!(attr as StructureErrorArgs)
|
||||
};
|
||||
let input = parse_macro_input!(item as DeriveInput);
|
||||
let name = &input.ident;
|
||||
|
||||
// Parse format attribute
|
||||
let format_lit = args
|
||||
.format
|
||||
.unwrap_or_else(|| LitStr::new("{}", Span::call_site()));
|
||||
|
||||
let expanded = quote! {
|
||||
#input
|
||||
|
||||
impl #name {
|
||||
pub fn new(message: &'static str) -> Self {
|
||||
Self(message)
|
||||
}
|
||||
|
||||
pub fn into_error(self) -> ::cmark_writer::error::WriteError {
|
||||
let mut error_factory = ::cmark_writer::error::StructureError::new(#format_lit);
|
||||
|
||||
let arg = self.0.to_string();
|
||||
error_factory = error_factory.arg(arg);
|
||||
|
||||
<::cmark_writer::error::StructureError as ::cmark_writer::error::CustomErrorFactory>::create_error(&error_factory)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<#name> for ::cmark_writer::error::WriteError {
|
||||
fn from(factory: #name) -> Self {
|
||||
factory.into_error()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::cmark_writer::error::CustomErrorFactory for #name {
|
||||
fn create_error(&self) -> ::cmark_writer::error::WriteError {
|
||||
let mut error_factory = ::cmark_writer::error::StructureError::new(#format_lit);
|
||||
|
||||
let arg = self.0.to_string();
|
||||
error_factory = error_factory.arg(arg);
|
||||
|
||||
<::cmark_writer::error::StructureError as ::cmark_writer::error::CustomErrorFactory>::create_error(&error_factory)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
|
||||
/// Custom coded error attribute macro, replaces the coded form errors in the original define_custom_errors! macro
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use cmark_writer::coded_error;
|
||||
///
|
||||
/// #[coded_error]
|
||||
/// struct MarkdownSyntaxError(pub String, pub String);
|
||||
/// ```
|
||||
#[proc_macro_attribute]
|
||||
pub fn coded_error(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(item as DeriveInput);
|
||||
let name = &input.ident;
|
||||
|
||||
let expanded = quote! {
|
||||
#input
|
||||
|
||||
impl #name {
|
||||
pub fn new(message: &str, code: &str) -> Self {
|
||||
Self(message.to_string(), code.to_string())
|
||||
}
|
||||
|
||||
pub fn into_error(self) -> ::cmark_writer::error::WriteError {
|
||||
let coded_error = ::cmark_writer::error::CodedError::new(self.0, self.1);
|
||||
<::cmark_writer::error::CodedError as ::cmark_writer::error::CustomErrorFactory>::create_error(&coded_error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<#name> for ::cmark_writer::error::WriteError {
|
||||
fn from(factory: #name) -> Self {
|
||||
factory.into_error()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::cmark_writer::error::CustomErrorFactory for #name {
|
||||
fn create_error(&self) -> ::cmark_writer::error::WriteError {
|
||||
let coded_error = ::cmark_writer::error::CodedError::new(self.0.clone(), self.1.clone());
|
||||
<::cmark_writer::error::CodedError as ::cmark_writer::error::CustomErrorFactory>::create_error(&coded_error)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
24
crates/cmark-writer/Cargo.toml
Normal file
24
crates/cmark-writer/Cargo.toml
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[package]
|
||||
name = "cmark-writer"
|
||||
version = "0.9.0"
|
||||
edition = "2021"
|
||||
description = "A CommonMark writer implementation in Rust for serializing AST nodes to CommonMark format"
|
||||
license = "MIT"
|
||||
authors = ["Hong Jiarong"]
|
||||
repository = "https://github.com/hongjr03/cmark-writer"
|
||||
keywords = ["markdown", "commonmark", "writer", "serializer"]
|
||||
categories = ["text-processing"]
|
||||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
cmark-writer-macros = { path = "../cmark-writer-macros", version = "0.9.0" }
|
||||
ecow = "0.2.5"
|
||||
env_logger = "0.11.8"
|
||||
html-escape = "0.2.13"
|
||||
log = "0.4.27"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
# GitHub Flavored Markdown support including tables with alignment, strikethrough,
|
||||
# task lists, and autolinks without angle brackets
|
||||
gfm = []
|
||||
9
crates/cmark-writer/LICENSE
Normal file
9
crates/cmark-writer/LICENSE
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
MIT License
|
||||
|
||||
Copyright 2025 Hong Jiarong
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
164
crates/cmark-writer/README.md
Normal file
164
crates/cmark-writer/README.md
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
# cmark-writer
|
||||
|
||||
[](./LICENSE)
|
||||
|
||||
A CommonMark writer implementation in Rust.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```rust
|
||||
use cmark_writer::ast::{Node, ListItem};
|
||||
use cmark_writer::writer::CommonMarkWriter;
|
||||
|
||||
// Create a document
|
||||
let document = Node::Document(vec![
|
||||
Node::heading(1, vec![Node::Text("Hello CommonMark".into())]),
|
||||
Node::Paragraph(vec![
|
||||
Node::Text("This is a simple ".into()),
|
||||
Node::Strong(vec![Node::Text("example".into())]),
|
||||
Node::Text(".".into()),
|
||||
]),
|
||||
]);
|
||||
|
||||
// Render to CommonMark
|
||||
let mut writer = CommonMarkWriter::new();
|
||||
writer.write(&document).expect("Failed to write document");
|
||||
let markdown = writer.into_string();
|
||||
|
||||
println!("{}", markdown);
|
||||
```
|
||||
|
||||
## Custom Options
|
||||
|
||||
```rust
|
||||
use cmark_writer::options::WriterOptionsBuilder;
|
||||
use cmark_writer::writer::CommonMarkWriter;
|
||||
|
||||
// Use builder pattern for custom options
|
||||
let options = WriterOptionsBuilder::new()
|
||||
.strict(true)
|
||||
.hard_break_spaces(false)
|
||||
.indent_spaces(2)
|
||||
.build();
|
||||
|
||||
let mut writer = CommonMarkWriter::with_options(options);
|
||||
```
|
||||
|
||||
## Table Support
|
||||
|
||||
```rust
|
||||
use cmark_writer::ast::{Node, tables::TableBuilder};
|
||||
|
||||
// Create tables with the builder pattern
|
||||
let table = TableBuilder::new()
|
||||
.headers(vec![
|
||||
Node::Text("Name".into()),
|
||||
Node::Text("Age".into())
|
||||
])
|
||||
.add_row(vec![
|
||||
Node::Text("John".into()),
|
||||
Node::Text("30".into()),
|
||||
])
|
||||
.add_row(vec![
|
||||
Node::Text("Alice".into()),
|
||||
Node::Text("25".into()),
|
||||
])
|
||||
.build();
|
||||
```
|
||||
|
||||
## GitHub Flavored Markdown (GFM)
|
||||
|
||||
Enable GFM features by adding to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
cmark-writer = { version = "0.8.0", features = ["gfm"] }
|
||||
```
|
||||
|
||||
GFM Support:
|
||||
|
||||
- Tables with column alignment
|
||||
- Strikethrough text
|
||||
- Task lists
|
||||
- Extended autolinks
|
||||
- HTML element filtering
|
||||
|
||||
## HTML Writing
|
||||
|
||||
The library provides dedicated HTML writing capabilities through the `HtmlWriter` class:
|
||||
|
||||
```rust
|
||||
use cmark_writer::{HtmlWriter, HtmlWriterOptions, Node};
|
||||
|
||||
// Create HTML writer with custom options
|
||||
let options = HtmlWriterOptions {
|
||||
strict: true,
|
||||
code_block_language_class_prefix: Some("language-".into()),
|
||||
#[cfg(feature = "gfm")]
|
||||
enable_gfm: true,
|
||||
#[cfg(feature = "gfm")]
|
||||
gfm_disallowed_html_tags: vec!["script".into()],
|
||||
};
|
||||
|
||||
let mut writer = HtmlWriter::with_options(options);
|
||||
|
||||
// Write some nodes
|
||||
let paragraph = Node::Paragraph(vec![Node::Text("Hello HTML".into())]);
|
||||
writer.write_node(¶graph).unwrap();
|
||||
|
||||
// Get resulting HTML
|
||||
let html = writer.into_string().unwrap();
|
||||
assert_eq!(html, "<p>Hello HTML</p>\n");
|
||||
```
|
||||
|
||||
## Custom Nodes
|
||||
|
||||
```rust
|
||||
use cmark_writer::{HtmlWriteResult, HtmlWriter, Node, WriteResult};
|
||||
use cmark_writer::writer::InlineWriterProxy;
|
||||
use cmark_writer::custom_node;
|
||||
use ecow::EcoString;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[custom_node(block=false, html_impl=true)]
|
||||
struct HighlightNode {
|
||||
content: EcoString,
|
||||
color: EcoString,
|
||||
}
|
||||
|
||||
impl HighlightNode {
|
||||
// Implementation for CommonMark output
|
||||
fn write_custom(&self, writer: &mut InlineWriterProxy) -> WriteResult<()> {
|
||||
writer.write_str("<span style=\"background-color: ")?;
|
||||
writer.write_str(&self.color)?;
|
||||
writer.write_str("\">")?;
|
||||
writer.write_str(&self.content)?;
|
||||
writer.write_str("</span>")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Optional HTML-specific implementation
|
||||
fn write_html_custom(&self, writer: &mut HtmlWriter) -> HtmlWriteResult<()> {
|
||||
writer.start_tag("span")?;
|
||||
writer.attribute("style", &format!("background-color: {}", self.color))?;
|
||||
writer.finish_tag()?;
|
||||
writer.text(&self.content)?;
|
||||
writer.end_tag("span")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
# Build
|
||||
cargo build
|
||||
|
||||
# Run tests
|
||||
cargo test
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the LICENSE file for details.
|
||||
135
crates/cmark-writer/src/ast/custom.rs
Normal file
135
crates/cmark-writer/src/ast/custom.rs
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
//! Custom node definitions for the CommonMark AST.
|
||||
|
||||
use crate::error::{WriteError, WriteResult};
|
||||
use crate::writer::{BlockWriterProxy, HtmlWriteResult, HtmlWriter, InlineWriterProxy};
|
||||
use std::any::Any;
|
||||
|
||||
/// Trait for implementing custom node behavior for the CommonMark AST.
|
||||
///
|
||||
/// This trait defines methods that all custom node types must implement.
|
||||
/// Users can implement dedicated block or inline rendering methods for CommonMark output and
|
||||
/// optionally override the `html_write` method for HTML output.
|
||||
///
|
||||
/// The recommended way to implement this trait is through the `custom_node` macro,
|
||||
/// which provides a default implementation of most methods and requires users to
|
||||
/// implement only the node-specific logic.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use ecow::EcoString;
|
||||
/// use cmark_writer_macros::custom_node;
|
||||
/// use cmark_writer::error::WriteResult;
|
||||
/// use cmark_writer::writer::{HtmlWriteResult, HtmlWriter, InlineWriterProxy};
|
||||
///
|
||||
/// // Define a custom node with support for both CommonMark and HTML output
|
||||
/// #[derive(Debug, Clone, PartialEq)]
|
||||
/// #[custom_node(block=false, html_impl=true)]
|
||||
/// struct HighlightNode {
|
||||
/// content: EcoString,
|
||||
/// color: EcoString,
|
||||
/// }
|
||||
///
|
||||
/// impl HighlightNode {
|
||||
/// // Required for CommonMark output
|
||||
/// fn write_custom(&self, writer: &mut InlineWriterProxy) -> WriteResult<()> {
|
||||
/// writer.write_str("<span style=\"background-color: ")?;
|
||||
/// writer.write_str(&self.color)?;
|
||||
/// writer.write_str("\">")?;
|
||||
/// writer.write_str(&self.content)?;
|
||||
/// writer.write_str("</span>")?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
///
|
||||
/// // Optional HTML-specific implementation
|
||||
/// fn write_html_custom(&self, writer: &mut HtmlWriter) -> HtmlWriteResult<()> {
|
||||
/// writer.start_tag("span")?;
|
||||
/// writer.attribute("style", &format!("background-color: {}", self.color))?;
|
||||
/// writer.finish_tag()?;
|
||||
/// writer.text(&self.content)?;
|
||||
/// writer.end_tag("span")?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub trait CustomNode: std::fmt::Debug + Send + Sync {
|
||||
/// Write the custom node as a block element using the restricted block writer proxy.
|
||||
///
|
||||
/// Block custom nodes should implement this method to emit valid block-level content.
|
||||
fn write_block(&self, writer: &mut BlockWriterProxy) -> WriteResult<()> {
|
||||
let _ = writer;
|
||||
Err(WriteError::UnsupportedNodeType)
|
||||
}
|
||||
|
||||
/// Write the custom node as an inline element using the restricted inline writer proxy.
|
||||
///
|
||||
/// Inline custom nodes should implement this method to emit valid inline content.
|
||||
fn write_inline(&self, writer: &mut InlineWriterProxy) -> WriteResult<()> {
|
||||
let _ = writer;
|
||||
Err(WriteError::UnsupportedNodeType)
|
||||
}
|
||||
|
||||
/// Writes the HTML representation of the custom node to the provided HTML writer.
|
||||
///
|
||||
/// By default, this writes an HTML comment indicating that HTML rendering is not implemented
|
||||
/// for this custom node type. When using the `custom_node` macro with `html_impl=true`,
|
||||
/// this method delegates to the user-defined `write_html_custom` method.
|
||||
///
|
||||
/// Users should either:
|
||||
/// 1. Override this method directly, or
|
||||
/// 2. Use the `custom_node` macro with `html_impl=true` and implement the `write_html_custom` method.
|
||||
fn html_write(&self, writer: &mut HtmlWriter) -> HtmlWriteResult<()> {
|
||||
writer.write_trusted_html(&format!(
|
||||
"<!-- HTML rendering not implemented for Custom Node: {} -->",
|
||||
self.type_name()
|
||||
))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Clone the custom node
|
||||
fn clone_box(&self) -> Box<dyn CustomNode>;
|
||||
|
||||
/// Check if two custom nodes are equal
|
||||
fn eq_box(&self, other: &dyn CustomNode) -> bool;
|
||||
|
||||
/// Whether the custom node is a block element
|
||||
fn is_block(&self) -> bool;
|
||||
|
||||
/// Convert to Any for type casting
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
|
||||
/// Convert to mutable Any for type casting
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||
|
||||
/// Get the type name of the custom node for pattern matching
|
||||
fn type_name(&self) -> &'static str {
|
||||
std::any::type_name::<Self>()
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: CustomNodeWriter trait is deprecated and will be removed in a future version.
|
||||
// Custom nodes should now directly use the provided writer proxies instead.
|
||||
/*
|
||||
/// Trait for custom node writer implementation
|
||||
pub trait CustomNodeWriter {
|
||||
/// Write a string to the output
|
||||
fn write_str(&mut self, s: &str) -> std::fmt::Result;
|
||||
|
||||
/// Write a character to the output
|
||||
fn write_char(&mut self, c: char) -> std::fmt::Result;
|
||||
}
|
||||
*/
|
||||
|
||||
// Implement Clone for Box<dyn CustomNode>
|
||||
impl Clone for Box<dyn CustomNode> {
|
||||
fn clone(&self) -> Self {
|
||||
self.clone_box()
|
||||
}
|
||||
}
|
||||
|
||||
// Implement PartialEq for Box<dyn CustomNode>
|
||||
impl PartialEq for Box<dyn CustomNode> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.eq_box(&**other)
|
||||
}
|
||||
}
|
||||
78
crates/cmark-writer/src/ast/html.rs
Normal file
78
crates/cmark-writer/src/ast/html.rs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
//! HTML element definitions and utilities for CommonMark AST.
|
||||
//!
|
||||
//! This module contains definitions for HTML elements and attributes in the AST,
|
||||
//! along with utilities for safely handling HTML content.
|
||||
|
||||
use super::Node;
|
||||
use ecow::EcoString;
|
||||
|
||||
/// HTML attribute
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct HtmlAttribute {
|
||||
/// Attribute name
|
||||
pub name: EcoString,
|
||||
/// Attribute value
|
||||
pub value: EcoString,
|
||||
}
|
||||
|
||||
/// HTML element
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct HtmlElement {
|
||||
/// HTML tag name
|
||||
pub tag: EcoString,
|
||||
/// HTML attributes
|
||||
pub attributes: Vec<HtmlAttribute>,
|
||||
/// Child nodes
|
||||
pub children: Vec<Node>,
|
||||
/// Whether this is a self-closing element
|
||||
pub self_closing: bool,
|
||||
}
|
||||
|
||||
impl HtmlElement {
|
||||
/// Create a new HTML element
|
||||
pub fn new(tag: &str) -> Self {
|
||||
Self {
|
||||
tag: tag.into(),
|
||||
attributes: Vec::new(),
|
||||
children: Vec::new(),
|
||||
self_closing: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Add an attribute to the HTML element
|
||||
pub fn with_attribute(mut self, name: &str, value: &str) -> Self {
|
||||
self.attributes.push(HtmlAttribute {
|
||||
name: name.into(),
|
||||
value: value.into(),
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
/// Add multiple attributes to the HTML element
|
||||
pub fn with_attributes(mut self, attrs: Vec<(&str, &str)>) -> Self {
|
||||
for (name, value) in attrs {
|
||||
self.attributes.push(HtmlAttribute {
|
||||
name: name.into(),
|
||||
value: value.into(),
|
||||
});
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Add child nodes to the HTML element
|
||||
pub fn with_children(mut self, children: Vec<Node>) -> Self {
|
||||
self.children = children;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set whether the element is self-closing
|
||||
pub fn self_closing(mut self, is_self_closing: bool) -> Self {
|
||||
self.self_closing = is_self_closing;
|
||||
self
|
||||
}
|
||||
|
||||
/// Check if this element's tag matches any in the provided list (case-insensitive)
|
||||
pub fn tag_matches_any(&self, tags: &[EcoString]) -> bool {
|
||||
tags.iter().any(|tag| tag.eq_ignore_ascii_case(&self.tag))
|
||||
}
|
||||
}
|
||||
17
crates/cmark-writer/src/ast/mod.rs
Normal file
17
crates/cmark-writer/src/ast/mod.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
//! Abstract Syntax Tree for CommonMark document structure.
|
||||
//!
|
||||
//! This module defines various node types for representing CommonMark documents,
|
||||
//! including headings, paragraphs, lists, code blocks, etc.
|
||||
|
||||
mod custom;
|
||||
mod html;
|
||||
mod node;
|
||||
pub mod tables;
|
||||
|
||||
pub use self::custom::CustomNode;
|
||||
pub use self::html::{HtmlAttribute, HtmlElement};
|
||||
pub use self::node::{CodeBlockType, HeadingType, ListItem, Node};
|
||||
|
||||
// Re-export GFM specific types when the GFM feature is enabled
|
||||
#[cfg(feature = "gfm")]
|
||||
pub use self::node::{TableAlignment, TaskListStatus};
|
||||
389
crates/cmark-writer/src/ast/node.rs
Normal file
389
crates/cmark-writer/src/ast/node.rs
Normal file
|
|
@ -0,0 +1,389 @@
|
|||
//! Node definitions for the CommonMark AST.
|
||||
|
||||
use super::custom::CustomNode;
|
||||
use super::html::HtmlElement;
|
||||
use ecow::EcoString;
|
||||
use std::boxed::Box;
|
||||
|
||||
/// Code block type according to CommonMark specification
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub enum CodeBlockType {
|
||||
/// Indented code block - composed of one or more indented chunks, each preceded by four or more spaces
|
||||
Indented,
|
||||
/// Fenced code block - surrounded by backtick or tilde fences
|
||||
#[default]
|
||||
Fenced,
|
||||
}
|
||||
|
||||
/// Heading type according to CommonMark specification
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub enum HeadingType {
|
||||
/// ATX Type - Beginning with #
|
||||
#[default]
|
||||
Atx,
|
||||
/// Setext Type - Underlined or overlined text
|
||||
Setext,
|
||||
}
|
||||
|
||||
/// Table column alignment options for GFM tables
|
||||
#[cfg(feature = "gfm")]
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub enum TableAlignment {
|
||||
/// Left alignment (default)
|
||||
#[default]
|
||||
Left,
|
||||
/// Center alignment
|
||||
Center,
|
||||
/// Right alignment
|
||||
Right,
|
||||
/// No specific alignment specified
|
||||
None,
|
||||
}
|
||||
|
||||
/// Task list item status for GFM task lists
|
||||
#[cfg(feature = "gfm")]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum TaskListStatus {
|
||||
/// Checked/completed task
|
||||
Checked,
|
||||
/// Unchecked/incomplete task
|
||||
Unchecked,
|
||||
}
|
||||
|
||||
/// Main node type, representing an element in a CommonMark document
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Node {
|
||||
/// Root document node, contains child nodes
|
||||
Document(Vec<Node>),
|
||||
|
||||
// Leaf blocks
|
||||
// Thematic breaks
|
||||
/// Thematic break (horizontal rule)
|
||||
ThematicBreak,
|
||||
|
||||
// ATX headings & Setext headings
|
||||
/// Heading, contains level (1-6) and inline content
|
||||
Heading {
|
||||
/// Heading level, 1-6
|
||||
level: u8,
|
||||
/// Heading content, containing inline elements
|
||||
content: Vec<Node>,
|
||||
/// Heading type (ATX or Setext)
|
||||
heading_type: HeadingType,
|
||||
},
|
||||
|
||||
// Indented code blocks & Fenced code blocks
|
||||
/// Code block, containing optional language identifier and content
|
||||
CodeBlock {
|
||||
/// Optional language identifier (None for indented code blocks, Some for fenced code blocks)
|
||||
language: Option<EcoString>,
|
||||
/// Code content
|
||||
content: EcoString,
|
||||
/// The type of code block (Indented or Fenced)
|
||||
block_type: CodeBlockType,
|
||||
},
|
||||
|
||||
// HTML blocks
|
||||
/// HTML block
|
||||
HtmlBlock(EcoString),
|
||||
|
||||
// Link reference definitions
|
||||
/// Link reference definition
|
||||
LinkReferenceDefinition {
|
||||
/// Link label (used for reference)
|
||||
label: EcoString,
|
||||
/// Link destination URL
|
||||
destination: EcoString,
|
||||
/// Optional link title
|
||||
title: Option<EcoString>,
|
||||
},
|
||||
|
||||
// Paragraphs
|
||||
/// Paragraph node, containing inline elements
|
||||
Paragraph(Vec<Node>),
|
||||
|
||||
// Blank lines - typically handled during parsing, not represented in AST
|
||||
|
||||
// Container blocks
|
||||
// Block quotes
|
||||
/// Block quote, containing any block-level elements
|
||||
BlockQuote(Vec<Node>),
|
||||
|
||||
// & List items and Lists
|
||||
/// Ordered list, containing starting number and list items
|
||||
OrderedList {
|
||||
/// List starting number
|
||||
start: u32,
|
||||
/// List items
|
||||
items: Vec<ListItem>,
|
||||
},
|
||||
|
||||
/// Unordered list, containing list items
|
||||
UnorderedList(Vec<ListItem>),
|
||||
|
||||
/// Table (extension to CommonMark)
|
||||
Table {
|
||||
/// Header cells
|
||||
headers: Vec<Node>,
|
||||
/// Column alignments for the table
|
||||
#[cfg(feature = "gfm")]
|
||||
alignments: Vec<TableAlignment>,
|
||||
/// Table rows, each row containing multiple cells
|
||||
rows: Vec<Vec<Node>>,
|
||||
},
|
||||
|
||||
// Inlines
|
||||
// Code spans
|
||||
/// Inline code
|
||||
InlineCode(EcoString),
|
||||
|
||||
// Emphasis and strong emphasis
|
||||
/// Emphasis (italic)
|
||||
Emphasis(Vec<Node>),
|
||||
|
||||
/// Strong emphasis (bold)
|
||||
Strong(Vec<Node>),
|
||||
|
||||
/// Strikethrough (GFM extension)
|
||||
Strikethrough(Vec<Node>),
|
||||
|
||||
// Links
|
||||
/// Link
|
||||
Link {
|
||||
/// Link URL
|
||||
url: EcoString,
|
||||
/// Optional link title
|
||||
title: Option<EcoString>,
|
||||
/// Link text
|
||||
content: Vec<Node>,
|
||||
},
|
||||
|
||||
/// Reference link
|
||||
ReferenceLink {
|
||||
/// Link reference label
|
||||
label: EcoString,
|
||||
/// Link text content (optional, if empty it's a shortcut reference)
|
||||
content: Vec<Node>,
|
||||
},
|
||||
|
||||
// Images
|
||||
/// Image
|
||||
Image {
|
||||
/// Image URL
|
||||
url: EcoString,
|
||||
/// Optional image title
|
||||
title: Option<EcoString>,
|
||||
/// Alternative text, containing inline elements
|
||||
alt: Vec<Node>,
|
||||
},
|
||||
|
||||
// Autolinks
|
||||
/// Autolink (URI or email wrapped in < and >)
|
||||
Autolink {
|
||||
/// Link URL
|
||||
url: EcoString,
|
||||
/// Whether this is an email autolink
|
||||
is_email: bool,
|
||||
},
|
||||
|
||||
/// GFM Extended Autolink (without angle brackets, automatically detected)
|
||||
ExtendedAutolink(EcoString),
|
||||
|
||||
// Raw HTML
|
||||
/// HTML inline element
|
||||
HtmlElement(HtmlElement),
|
||||
|
||||
// Hard line breaks
|
||||
/// Hard break (two spaces followed by a line break, or backslash followed by a line break)
|
||||
HardBreak,
|
||||
|
||||
// Soft line breaks
|
||||
/// Soft break (single line break)
|
||||
SoftBreak,
|
||||
|
||||
// Textual content
|
||||
/// Plain text
|
||||
Text(EcoString),
|
||||
|
||||
/// Custom node that allows users to implement their own writing behavior
|
||||
Custom(Box<dyn CustomNode>),
|
||||
}
|
||||
|
||||
impl Default for Node {
|
||||
fn default() -> Self {
|
||||
Node::Document(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
/// List item type
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum ListItem {
|
||||
/// Unordered list item
|
||||
Unordered {
|
||||
/// List item content, containing one or more block-level elements
|
||||
content: Vec<Node>,
|
||||
},
|
||||
/// Ordered list item
|
||||
Ordered {
|
||||
/// Optional item number for ordered lists, allowing manual numbering
|
||||
number: Option<u32>,
|
||||
/// List item content, containing one or more block-level elements
|
||||
content: Vec<Node>,
|
||||
},
|
||||
/// Task list item (GFM extension)
|
||||
#[cfg(feature = "gfm")]
|
||||
Task {
|
||||
/// Task completion status
|
||||
status: TaskListStatus,
|
||||
/// List item content, containing one or more block-level elements
|
||||
content: Vec<Node>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Node {
|
||||
/// Check if a node is a block-level node
|
||||
pub fn is_block(&self) -> bool {
|
||||
match self {
|
||||
Node::Custom(node) => node.is_block(),
|
||||
_ => matches!(
|
||||
self,
|
||||
Node::Document(_)
|
||||
// Leaf blocks
|
||||
| Node::ThematicBreak
|
||||
| Node::Heading { .. }
|
||||
| Node::CodeBlock { .. }
|
||||
| Node::HtmlBlock(_)
|
||||
| Node::LinkReferenceDefinition { .. }
|
||||
| Node::Paragraph(_)
|
||||
// Container blocks
|
||||
| Node::BlockQuote(_)
|
||||
| Node::OrderedList { .. }
|
||||
| Node::UnorderedList(_)
|
||||
| Node::Table { .. }
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if a node is an inline node
|
||||
pub fn is_inline(&self) -> bool {
|
||||
match self {
|
||||
Node::Custom(node) => !node.is_block(),
|
||||
_ => matches!(
|
||||
self,
|
||||
// Inlines
|
||||
// Code spans
|
||||
Node::InlineCode(_)
|
||||
// Emphasis and strong emphasis
|
||||
| Node::Emphasis(_)
|
||||
| Node::Strong(_)
|
||||
| Node::Strikethrough(_)
|
||||
// Links
|
||||
| Node::Link { .. }
|
||||
| Node::ReferenceLink { .. }
|
||||
// Images
|
||||
| Node::Image { .. }
|
||||
// Autolinks
|
||||
| Node::Autolink { .. }
|
||||
| Node::ExtendedAutolink(_)
|
||||
// Raw HTML
|
||||
| Node::HtmlElement(_)
|
||||
// Hard line breaks
|
||||
| Node::HardBreak
|
||||
// Soft line breaks
|
||||
| Node::SoftBreak
|
||||
// Textual content
|
||||
| Node::Text(_)
|
||||
),
|
||||
}
|
||||
}
|
||||
/// Create a heading node
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `level` - Heading level (1-6)
|
||||
/// * `content` - Heading content
|
||||
///
|
||||
/// # Returns
|
||||
/// A new heading node, default ATX type
|
||||
pub fn heading(level: u8, content: Vec<Node>) -> Self {
|
||||
Node::Heading {
|
||||
level,
|
||||
content,
|
||||
heading_type: HeadingType::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a code block node
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `language` - Optional language identifier
|
||||
/// * `content` - Code content
|
||||
///
|
||||
/// # Returns
|
||||
/// A new code block node, default Fenced type
|
||||
pub fn code_block(language: Option<EcoString>, content: EcoString) -> Self {
|
||||
Node::CodeBlock {
|
||||
language,
|
||||
content,
|
||||
block_type: CodeBlockType::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a strikethrough node
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `content` - Content to be struck through
|
||||
///
|
||||
/// # Returns
|
||||
/// A new strikethrough node
|
||||
pub fn strikethrough(content: Vec<Node>) -> Self {
|
||||
Node::Strikethrough(content)
|
||||
}
|
||||
|
||||
/// Create a task list item
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `status` - Task completion status
|
||||
/// * `content` - Task content
|
||||
///
|
||||
/// # Returns
|
||||
/// A new task list item
|
||||
#[cfg(feature = "gfm")]
|
||||
pub fn task_list_item(status: TaskListStatus, content: Vec<Node>) -> ListItem {
|
||||
ListItem::Task { status, content }
|
||||
}
|
||||
|
||||
/// Create a table with alignment
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `headers` - Table header cells
|
||||
/// * `alignments` - Column alignments
|
||||
/// * `rows` - Table rows
|
||||
///
|
||||
/// # Returns
|
||||
/// A new table node with alignment information
|
||||
#[cfg(feature = "gfm")]
|
||||
pub fn table_with_alignment(
|
||||
headers: Vec<Node>,
|
||||
alignments: Vec<TableAlignment>,
|
||||
rows: Vec<Vec<Node>>,
|
||||
) -> Self {
|
||||
Node::Table {
|
||||
headers,
|
||||
alignments,
|
||||
rows,
|
||||
}
|
||||
}
|
||||
/// Check if a custom node is of a specific type, and return a reference to that type
|
||||
pub fn as_custom_type<T: CustomNode + 'static>(&self) -> Option<&T> {
|
||||
if let Node::Custom(node) = self {
|
||||
node.as_any().downcast_ref::<T>()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if a node is a custom node of a specific type
|
||||
pub fn is_custom_type<T: CustomNode + 'static>(&self) -> bool {
|
||||
self.as_custom_type::<T>().is_some()
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue