Compare commits
800 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3c535276c | ||
|
|
add22b0bd0 | ||
|
|
48f855144e | ||
|
|
67291f0cbe | ||
|
|
45b302c698 | ||
|
|
f897edab5f | ||
|
|
dffb9f3dd8 | ||
|
|
573e1966ae | ||
|
|
d161aa98a0 | ||
|
|
f10d93c22e | ||
|
|
17a98fba68 | ||
|
|
dee28397cb | ||
|
|
c4055eb37c | ||
|
|
91049bebd9 | ||
|
|
9f6c35b9ec | ||
|
|
f0ed7c0b39 | ||
|
|
e64c4fc0f8 | ||
|
|
cd19cec4f7 | ||
|
|
070fc53685 | ||
|
|
b232c55843 | ||
|
|
55a14b3fbe | ||
|
|
60fde1711e | ||
|
|
31ca9d4e8b | ||
|
|
bd47a09d1e | ||
|
|
744322a398 | ||
|
|
70de0e3ebd | ||
|
|
935ef83c4f | ||
|
|
93370095e9 | ||
|
|
e8e9a5a5d3 | ||
|
|
a5fbf6991c | ||
|
|
a5f8017ab7 | ||
|
|
201fa4d564 | ||
|
|
5e23d4446b | ||
|
|
ef4e3fe28e | ||
|
|
6d6d86692a | ||
|
|
ada9724e54 | ||
|
|
6347b728e4 | ||
|
|
5079812745 | ||
|
|
c2ed9b2577 | ||
|
|
20a5178326 | ||
|
|
81ad61f89d | ||
|
|
5fc030b4dc | ||
|
|
6ef1ba5b57 | ||
|
|
bea6b181db | ||
|
|
e17819f458 | ||
|
|
db52e9c29a | ||
|
|
e06fcb8ced | ||
|
|
51f43e8bfa | ||
|
|
0f66935385 | ||
|
|
29a6b121bb | ||
|
|
6ed37f9ac2 | ||
|
|
f7c53b9afb | ||
|
|
e6e5c5c881 | ||
|
|
f059b89fa5 | ||
|
|
8d5a678bb8 | ||
|
|
8d901105bf | ||
|
|
637394156f | ||
|
|
a79a987f5e | ||
|
|
b22335d38e | ||
|
|
757ccbddcf | ||
|
|
39a30b320d | ||
|
|
912e436ca8 | ||
|
|
1b0853e23d | ||
|
|
07c4e69319 | ||
|
|
4b3808a9ec | ||
|
|
bd09a10fd8 | ||
|
|
9dbdd092f6 | ||
|
|
ce331f12fb | ||
|
|
cb93370f59 | ||
|
|
7c77dca821 | ||
|
|
17ffed418f | ||
|
|
7abb97e681 | ||
|
|
33b1acddd0 | ||
|
|
e73803f927 | ||
|
|
bbd257e650 | ||
|
|
491b32baaa | ||
|
|
70d8bfe273 | ||
|
|
e69c8bbad8 | ||
|
|
12aba4e900 | ||
|
|
9d70521ccf | ||
|
|
1d7ff4fbf7 | ||
|
|
1eaf04d907 | ||
|
|
9839013465 | ||
|
|
65be619d51 | ||
|
|
c4331cb140 | ||
|
|
c09831e832 | ||
|
|
2a48e6adf1 | ||
|
|
8579d29890 | ||
|
|
4fe9794b10 | ||
|
|
9413a6f878 | ||
|
|
e77672dfc7 | ||
|
|
bb9795952d | ||
|
|
36b3efafd4 | ||
|
|
b9ba9768ea | ||
|
|
09c2c44c0a | ||
|
|
99ebbab100 | ||
|
|
6ab6dda1da | ||
|
|
f77dce3566 | ||
|
|
67c4355dff | ||
|
|
1038d51e5d | ||
|
|
eaa61c1ea1 | ||
|
|
50695b6866 | ||
|
|
bf9011e23f | ||
|
|
ac8a429ac2 | ||
|
|
f0cf59a1ac | ||
|
|
145abfb026 | ||
|
|
438160d08f | ||
|
|
b867f72fe2 | ||
|
|
cad6a2d5b4 | ||
|
|
3ea28e673f | ||
|
|
ea11a3646f | ||
|
|
c8e79e75ba | ||
|
|
9340568653 | ||
|
|
0d7b55c52f | ||
|
|
5644c0c381 | ||
|
|
04390b461f | ||
|
|
3ca6f32628 | ||
|
|
9fbf962e9f | ||
|
|
b0d3aceecd | ||
|
|
94d88987ea | ||
|
|
aaf7a40969 | ||
|
|
4065019525 | ||
|
|
eeb1fc9cb4 | ||
|
|
f35d8c8332 | ||
|
|
c8cd435142 | ||
|
|
0e42e1ea00 | ||
|
|
a6bdfc3421 | ||
|
|
47003754f6 | ||
|
|
71072d9520 | ||
|
|
b64dd8f88a | ||
|
|
173c89d86f | ||
|
|
b1013829d8 | ||
|
|
48ac869e40 | ||
|
|
00e590bc67 | ||
|
|
55053acd38 | ||
|
|
576ee9ca9d | ||
|
|
b99c61a0ee | ||
|
|
8d3b5619cd | ||
|
|
fdc7b8e68f | ||
|
|
f5f558d5bc | ||
|
|
c9c38ef10b | ||
|
|
c30f401c4f | ||
|
|
9b92050af8 | ||
|
|
31a41e2a66 | ||
|
|
baa56bc246 | ||
|
|
f53e81e0cb | ||
|
|
f454266846 | ||
|
|
0ba3c22795 | ||
|
|
ff38cf361c | ||
|
|
57e93b91c5 | ||
|
|
c1161b95ed | ||
|
|
32dc63b62a | ||
|
|
0c1198c802 | ||
|
|
ed4b78cfdc | ||
|
|
65f77baf2b | ||
|
|
eabdf00d3d | ||
|
|
c084a15e08 | ||
|
|
e577ba591e | ||
|
|
b17c7f888a | ||
|
|
0ed41b7d7e | ||
|
|
2e1faaa34f | ||
|
|
63f02f4f0e | ||
|
|
489fc5ec9e | ||
|
|
4c8ecdb344 | ||
|
|
8d705ff6c5 | ||
|
|
cfe68e65e8 | ||
|
|
0e179f5fd7 | ||
|
|
6cabd6283b | ||
|
|
6135e38fce | ||
|
|
935b2230af | ||
|
|
6dcd89e9cd | ||
|
|
2775b2051f | ||
|
|
5ebb2d7370 | ||
|
|
c9488e6661 | ||
|
|
442261e655 | ||
|
|
1aa2d41c95 | ||
|
|
e5a2194c23 | ||
|
|
cf6f051ee8 | ||
|
|
bebde4de68 | ||
|
|
174c4b7734 | ||
|
|
1f7519ee60 | ||
|
|
b6482546a5 | ||
|
|
0decd84f7f | ||
|
|
a1dbda0b23 | ||
|
|
427245f211 | ||
|
|
4678189eab | ||
|
|
15d89e34cf | ||
|
|
cbb0d8f72b | ||
|
|
131150f5a6 | ||
|
|
a31bca73e7 | ||
|
|
1d5f940c94 | ||
|
|
70ea6a5a16 | ||
|
|
849af69ce2 | ||
|
|
754570a9ec | ||
|
|
f7f6f26997 | ||
|
|
946d84a7a9 | ||
|
|
781ab6ac40 | ||
|
|
df86d02e8b | ||
|
|
19e468c908 | ||
|
|
5a81ea19b8 | ||
|
|
64a38e56b9 | ||
|
|
fca0528a7e | ||
|
|
936916acf8 | ||
|
|
61e9fc0308 | ||
|
|
2356623d7a | ||
|
|
ee70acebb6 | ||
|
|
09c48db957 | ||
|
|
d7658852b0 | ||
|
|
0a0efba37b | ||
|
|
a16c0c6355 | ||
|
|
8dcbe67152 | ||
|
|
2c20621071 | ||
|
|
48c4c0b8e4 | ||
|
|
2900777ffb | ||
|
|
0ccd428852 | ||
|
|
368ade6b44 | ||
|
|
5f6b6e3b4a | ||
|
|
43554a4303 | ||
|
|
2b0007c21a | ||
|
|
5ab0bdaa69 | ||
|
|
1c74df0266 | ||
|
|
469a1aaaf8 | ||
|
|
c5523f7aaf | ||
|
|
61b46bc5ac | ||
|
|
d7a0f71552 | ||
|
|
7d6d60039e | ||
|
|
42cc53cefc | ||
|
|
e68daa8ac2 | ||
|
|
333cc1f9df | ||
|
|
00bb8c6385 | ||
|
|
1deb969c20 | ||
|
|
928afceca7 | ||
|
|
179b31f67c | ||
|
|
7d4fe9ca0f | ||
|
|
3e33383eb1 | ||
|
|
66324fd292 | ||
|
|
8b1fbcabaa | ||
|
|
90519488c1 | ||
|
|
1012e10ddc | ||
|
|
2dd129d9bd | ||
|
|
6af5458082 | ||
|
|
9744cf0117 | ||
|
|
01921c799c | ||
|
|
b1674b4b84 | ||
|
|
9f7f803e25 | ||
|
|
b83c565e29 | ||
|
|
dee30923ff | ||
|
|
9a91be8025 | ||
|
|
46a9d6e602 | ||
|
|
511fd48081 | ||
|
|
0039fc1555 | ||
|
|
98044187cd | ||
|
|
a6dcc1ea79 | ||
|
|
32a686227e | ||
|
|
faa74132e5 | ||
|
|
3a847f7e42 | ||
|
|
66c978891e | ||
|
|
2f31230e07 | ||
|
|
c4225c0011 | ||
|
|
4edc7a0280 | ||
|
|
a60fe5204b | ||
|
|
bb980b4afe | ||
|
|
504658d87a | ||
|
|
feff69d969 | ||
|
|
a34d77242a | ||
|
|
1b24c1277d | ||
|
|
e6750205be | ||
|
|
1da8bf3f8b | ||
|
|
90c60b6a40 | ||
|
|
ee79f89c7f | ||
|
|
0668d48fd5 | ||
|
|
d046f73d16 | ||
|
|
f144d713d1 | ||
|
|
d31c403bdc | ||
|
|
35a0327387 | ||
|
|
9b39649bde | ||
|
|
3d857463f0 | ||
|
|
0428642a2f | ||
|
|
5182a9ae1a | ||
|
|
ab3686b3b5 | ||
|
|
c5b7b7845d | ||
|
|
2f13c335ed | ||
|
|
f219ac721f | ||
|
|
0149885289 | ||
|
|
cb80a10de2 | ||
|
|
092eb0fd2a | ||
|
|
24f79d9d3f | ||
|
|
d667b19716 | ||
|
|
4d38a0881a | ||
|
|
1478d0bd53 | ||
|
|
00a9e59bc2 | ||
|
|
2b2843234e | ||
|
|
71449aa5cc | ||
|
|
87f293a3f6 | ||
|
|
6da3ddb5dd | ||
|
|
87e80ccfe9 | ||
|
|
af9865d91b | ||
|
|
e576b6e8a4 | ||
|
|
c9f4c8f94e | ||
|
|
6ef63da973 | ||
|
|
2d85b0a554 | ||
|
|
41cbcc4c46 | ||
|
|
6c94880497 | ||
|
|
1d75c6b6b8 | ||
|
|
338bc022f9 | ||
|
|
2451730311 | ||
|
|
22cdaabe28 | ||
|
|
5a69240178 | ||
|
|
b81ef077f6 | ||
|
|
cb72b53653 | ||
|
|
050a513b48 | ||
|
|
481d1f56e4 | ||
|
|
229238703a | ||
|
|
074de212ce | ||
|
|
98e4490318 | ||
|
|
c79dc3c41f | ||
|
|
b45abe88ac | ||
|
|
2bac596e3d | ||
|
|
15a6ea8d8d | ||
|
|
72d6f8263a | ||
|
|
7549b3d989 | ||
|
|
ca628b37de | ||
|
|
db120b5c45 | ||
|
|
2973f5d27b | ||
|
|
075c7ad350 | ||
|
|
23625ed8fa | ||
|
|
9bd06909c8 | ||
|
|
1b45c2af13 | ||
|
|
b4bbf6c6fb | ||
|
|
a5b8d9668d | ||
|
|
490210da00 | ||
|
|
6878d440b1 | ||
|
|
81fa0a7d0f | ||
|
|
b7d4e547a1 | ||
|
|
2b2e256b8f | ||
|
|
7a7b31c2ae | ||
|
|
dea5eb1053 | ||
|
|
df3144ea73 | ||
|
|
a170cc3ad9 | ||
|
|
35b3813022 | ||
|
|
f0472fe89b | ||
|
|
7bdb2fa025 | ||
|
|
5ba7ad449a | ||
|
|
145441d55e | ||
|
|
62ff3419c1 | ||
|
|
34aee134d6 | ||
|
|
5899120d87 | ||
|
|
816a2fefe7 | ||
|
|
1f64e59917 | ||
|
|
5e54334fb9 | ||
|
|
d354af306f | ||
|
|
045cece0ce | ||
|
|
506012200f | ||
|
|
4ad2f0d495 | ||
|
|
b00e3cfd4b | ||
|
|
bb05489872 | ||
|
|
ede4d417bd | ||
|
|
928072fa27 | ||
|
|
6a313fcc8a | ||
|
|
725f7f4915 | ||
|
|
b9cb0ea16d | ||
|
|
61b80795a4 | ||
|
|
8daaa23774 | ||
|
|
8a0d308ceb | ||
|
|
e6a7a9aae7 | ||
|
|
f3943bd846 | ||
|
|
d2ae94df34 | ||
|
|
f799613b1a | ||
|
|
3f057a01d8 | ||
|
|
3ad5136735 | ||
|
|
e201ce6f83 | ||
|
|
383a3a7d4c | ||
|
|
8261f1de1b | ||
|
|
5b38e6fa56 | ||
|
|
717f34bc85 | ||
|
|
47fb2a90a9 | ||
|
|
85a7221895 | ||
|
|
9618a89528 | ||
|
|
14f0af2754 | ||
|
|
ebe248670d | ||
|
|
511960c4a9 | ||
|
|
31fd1f93ce | ||
|
|
6625b69170 | ||
|
|
9e8533fbb8 | ||
|
|
9c9cbb7dcb | ||
|
|
079a13e161 | ||
|
|
69c1e587d0 | ||
|
|
3996252531 | ||
|
|
4fddda65e6 | ||
|
|
5916344092 | ||
|
|
b96722dd69 | ||
|
|
263ccab311 | ||
|
|
3571af82c7 | ||
|
|
c60520c0ff | ||
|
|
b473431eae | ||
|
|
cbf434f741 | ||
|
|
04c401207f | ||
|
|
7291e6aac6 | ||
|
|
a7aab96f0e | ||
|
|
f500749644 | ||
|
|
47e59bc54c | ||
|
|
8902e25021 | ||
|
|
33093e1eb4 | ||
|
|
d36178c44f | ||
|
|
15b09ccc75 | ||
|
|
dffa6c87a0 | ||
|
|
c4a1caee09 | ||
|
|
1d9f07b86d | ||
|
|
a794a95bb8 | ||
|
|
40a56f6057 | ||
|
|
82353f7b64 | ||
|
|
82a22da90a | ||
|
|
380e40ea05 | ||
|
|
2bedb23341 | ||
|
|
1110b76364 | ||
|
|
d19e632f80 | ||
|
|
4e040b5f7a | ||
|
|
7a2a0934c2 | ||
|
|
d3eb7b223c | ||
|
|
f74eec954f | ||
|
|
864c4e7aa6 | ||
|
|
5667906caf | ||
|
|
2fe7c524e7 | ||
|
|
5cc83526ad | ||
|
|
76b5e99a08 | ||
|
|
7d5505d421 | ||
|
|
d97a11f8b5 | ||
|
|
0590cec684 | ||
|
|
b4cdc4feb9 | ||
|
|
986fd95524 | ||
|
|
f51fec5fb9 | ||
|
|
8198ce2af3 | ||
|
|
defffc4c8e | ||
|
|
8f47cbfb0b | ||
|
|
0be91c17d0 | ||
|
|
fae7ab8417 | ||
|
|
df239f2cc0 | ||
|
|
70099dc97f | ||
|
|
c11be0e3ec | ||
|
|
f8b7870180 | ||
|
|
c58a5c62d9 | ||
|
|
ce92444bf2 | ||
|
|
b2709ebffd | ||
|
|
2b20cf9d24 | ||
|
|
f4a499ad0f | ||
|
|
4494b158c0 | ||
|
|
3416e55264 | ||
|
|
9b53e31cd5 | ||
|
|
f49b93b042 | ||
|
|
a005930c14 | ||
|
|
9dea1ee6ed | ||
|
|
1ea0999d17 | ||
|
|
2e6a466ba5 | ||
|
|
fbcd430dc6 | ||
|
|
2bd910db47 | ||
|
|
8158c9a483 | ||
|
|
4622fbe757 | ||
|
|
97a635c2de | ||
|
|
e8c67c75fd | ||
|
|
6151ecb4c1 | ||
|
|
1d8c192c07 | ||
|
|
014911b7a9 | ||
|
|
7b2d7b8aa5 | ||
|
|
caceed2d4c | ||
|
|
476ec6c2fd | ||
|
|
5374edfa01 | ||
|
|
6a0cac9dfb | ||
|
|
b525a6a211 | ||
|
|
c295761560 | ||
|
|
6154164b4b | ||
|
|
05ce2d3537 | ||
|
|
544f24bcba | ||
|
|
1c354ed976 | ||
|
|
9b9bf1bfbe | ||
|
|
29d5f02d10 | ||
|
|
9bc2fbc141 | ||
|
|
cac009b773 | ||
|
|
bf1639cac7 | ||
|
|
5f28e145c4 | ||
|
|
8199ab964e | ||
|
|
14c050e34b | ||
|
|
b96411d1f9 | ||
|
|
87c469a6c7 | ||
|
|
c29aef03f0 | ||
|
|
9eaf94de7a | ||
|
|
f5e7526fae | ||
|
|
579e4925c8 | ||
|
|
4a4c558d9d | ||
|
|
9bb34850e2 | ||
|
|
c6e37532bc | ||
|
|
221f962beb | ||
|
|
17566279e2 | ||
|
|
4e7488414d | ||
|
|
c206817431 | ||
|
|
995c6fff2b | ||
|
|
c216062537 | ||
|
|
80a27a1e5e | ||
|
|
b8f5e10f4b | ||
|
|
d8bffdcf6c | ||
|
|
71c0360523 | ||
|
|
3260c2b3e0 | ||
|
|
a523c4ab63 | ||
|
|
24f69ea819 | ||
|
|
12d816b761 | ||
|
|
0e13a3783f | ||
|
|
09e5f3aa7f | ||
|
|
5991db1a83 | ||
|
|
f46419f800 | ||
|
|
94a89be841 | ||
|
|
00224e99a0 | ||
|
|
cfd6eb6fb3 | ||
|
|
701c5ccb9e | ||
|
|
bf797df982 | ||
|
|
0f710ffefb | ||
|
|
2a87f08287 | ||
|
|
c27c5885b1 | ||
|
|
e5771b0fc9 | ||
|
|
c9a5232d43 | ||
|
|
266faf9081 | ||
|
|
cdf3dc7f2e | ||
|
|
1bcfa9d9f0 | ||
|
|
d2dd4aed37 | ||
|
|
6eea02622a | ||
|
|
395b5da765 | ||
|
|
635f033193 | ||
|
|
14b100ea20 | ||
|
|
693cc3611c | ||
|
|
a9591e1a56 | ||
|
|
7a702f09a0 | ||
|
|
04ccdbb646 | ||
|
|
b2e661d9e3 | ||
|
|
d2161ff46c | ||
|
|
8e699db62d | ||
|
|
25201e6859 | ||
|
|
c1c14b814c | ||
|
|
001a49b34e | ||
|
|
08fcf7cf15 | ||
|
|
78db3d0b96 | ||
|
|
ed460fde4f | ||
|
|
1471203b68 | ||
|
|
53093ba459 | ||
|
|
f873961439 | ||
|
|
5146bd04df | ||
|
|
9247884a5b | ||
|
|
e159a6239c | ||
|
|
626cc773f4 | ||
|
|
1e26329d38 | ||
|
|
58e0b4bde5 | ||
|
|
b072b920fd | ||
|
|
2758c94434 | ||
|
|
83c086879d | ||
|
|
0429eaa9ed | ||
|
|
73c35e3b44 | ||
|
|
089f21ca72 | ||
|
|
0efdb019a0 | ||
|
|
57623378fb | ||
|
|
27566da617 | ||
|
|
c429113394 | ||
|
|
2e12942e22 | ||
|
|
fa5b698571 | ||
|
|
4237569390 | ||
|
|
01b1b3d0ea | ||
|
|
9f2c68fd66 | ||
|
|
9f21042e58 | ||
|
|
840e6fc6fd | ||
|
|
3f237386b2 | ||
|
|
eca6e00bf2 | ||
|
|
afcccd780b | ||
|
|
239c611d3e | ||
|
|
4a2f362ed7 | ||
|
|
b040669bfb | ||
|
|
2c5a35d9b8 | ||
|
|
eade3f4799 | ||
|
|
98d8daaa7c | ||
|
|
1c227c547f | ||
|
|
167c1fafa1 | ||
|
|
edf5fc8401 | ||
|
|
3de0006651 | ||
|
|
f79d382da5 | ||
|
|
11bb0fabcd | ||
|
|
4c43eb5eeb | ||
|
|
364d6ec3f9 | ||
|
|
40646fd1b3 | ||
|
|
2769eb9b71 | ||
|
|
aa97051437 | ||
|
|
496391b048 | ||
|
|
2e743c896f | ||
|
|
3941c33b1d | ||
|
|
cdc49c09f1 | ||
|
|
fc7300ba87 | ||
|
|
d3aa51c9ed | ||
|
|
387c906af2 | ||
|
|
d04c2a96b7 | ||
|
|
797c4cd2b1 | ||
|
|
0ebc874796 | ||
|
|
0b970a73b6 | ||
|
|
065b2fef1b | ||
|
|
b5033f6b45 | ||
|
|
274b341648 | ||
|
|
c51f2a80c3 | ||
|
|
e6415a3ee9 | ||
|
|
134a5aaa0d | ||
|
|
86c609f49f | ||
|
|
bf3dec46bc | ||
|
|
2d7c9cfc05 | ||
|
|
7e705ccfd8 | ||
|
|
1680637235 | ||
|
|
3de56b94c3 | ||
|
|
1b5840b2bf | ||
|
|
b14c4c50cf | ||
|
|
1f8c2f5b1e | ||
|
|
db3a584ab9 | ||
|
|
918f914c91 | ||
|
|
9f5d180447 | ||
|
|
77e2c68810 | ||
|
|
60caf743c6 | ||
|
|
b8dee7a5c9 | ||
|
|
3b6a7e9b71 | ||
|
|
648ee34171 | ||
|
|
4a88e471f6 | ||
|
|
14a2b715e7 | ||
|
|
0c368dbe65 | ||
|
|
f0b7542d94 | ||
|
|
80cd7d3eac | ||
|
|
ef08e0a34b | ||
|
|
62a2c22ba1 | ||
|
|
1417575b98 | ||
|
|
4862810035 | ||
|
|
e1b9bad05b | ||
|
|
47f7521e93 | ||
|
|
771f86710f | ||
|
|
dc55cedb0d | ||
|
|
e93c6832e4 | ||
|
|
0f0c7f9f3d | ||
|
|
d9984ce292 | ||
|
|
c9e813effe | ||
|
|
3fea99ef24 | ||
|
|
06a3841dd3 | ||
|
|
32fb742de5 | ||
|
|
c41b7adcfd | ||
|
|
be55a2237d | ||
|
|
265f788f98 | ||
|
|
c7d3a7dcf6 | ||
|
|
e02a766070 | ||
|
|
c9dd684451 | ||
|
|
5329033b46 | ||
|
|
4bd914fdba | ||
|
|
b7f093d55b | ||
|
|
87273d9eba | ||
|
|
bb1ea17d95 | ||
|
|
a554705cab | ||
|
|
6c9abc572a | ||
|
|
be168b8963 | ||
|
|
d05d6ac95e | ||
|
|
700a546b39 | ||
|
|
0fd6e1c87b | ||
|
|
733e747f58 | ||
|
|
672abbea2d | ||
|
|
b04fdae043 | ||
|
|
e7a124f178 | ||
|
|
4994761fe2 | ||
|
|
ad4cbd748b | ||
|
|
3d85902d2c | ||
|
|
8b558fa2f7 | ||
|
|
94a8610edf | ||
|
|
ad2a30b5f8 | ||
|
|
39d3cf46f3 | ||
|
|
596804ac79 | ||
|
|
6ac15e9252 | ||
|
|
1a8f10e942 | ||
|
|
779c1ef6ae | ||
|
|
600eb150bf | ||
|
|
0ef0fbc3f9 | ||
|
|
95ae50c24e | ||
|
|
3a43c4b5b9 | ||
|
|
0e73c9bec5 | ||
|
|
9479f5d53d | ||
|
|
7716d98868 | ||
|
|
918a33b45e | ||
|
|
2c1fd2890c | ||
|
|
939cf94de6 | ||
|
|
a912a7702d | ||
|
|
b35b0e9515 | ||
|
|
8ad93a6916 | ||
|
|
aac34c96f7 | ||
|
|
975bb10001 | ||
|
|
6cce35de6c | ||
|
|
722c0d6888 | ||
|
|
ce8a343ffd | ||
|
|
5e539a3d14 | ||
|
|
1224316217 | ||
|
|
8d7aeb3edd | ||
|
|
c65500b061 | ||
|
|
8642b8b46a | ||
|
|
ea381eac51 | ||
|
|
6395e471f0 | ||
|
|
59f0351b79 | ||
|
|
1b16fa69d0 | ||
|
|
e8f67590bc | ||
|
|
b34a8feb63 | ||
|
|
fcbca1e48a | ||
|
|
4585790b45 | ||
|
|
445b64a2ec | ||
|
|
5d18d09b72 | ||
|
|
fdfdfda6ce | ||
|
|
f016ae27ec | ||
|
|
c9d3eca431 | ||
|
|
486beaf650 | ||
|
|
6e82cf221e | ||
|
|
46b9591859 | ||
|
|
3e76da58f5 | ||
|
|
9d42bd2f97 | ||
|
|
75890ec6e8 | ||
|
|
fb0429e40f | ||
|
|
8db813a661 | ||
|
|
2655be9aae | ||
|
|
fc99756136 | ||
|
|
9159a98dbe | ||
|
|
310f8e4a5e | ||
|
|
d79f3416a3 | ||
|
|
e194928291 | ||
|
|
32aa8f4223 | ||
|
|
c88d6be1d7 | ||
|
|
1b1dc55da7 | ||
|
|
bfbc81c90f | ||
|
|
cefbf74582 | ||
|
|
0780842365 | ||
|
|
1f94a87993 | ||
|
|
157228edb5 | ||
|
|
10268fc60f | ||
|
|
e51911ed83 | ||
|
|
e1429bc666 | ||
|
|
a2d6d361d6 | ||
|
|
c581ead809 | ||
|
|
3ed5fda4e7 | ||
|
|
33dcfcb09a | ||
|
|
df84c25e01 | ||
|
|
b8dc7990f7 | ||
|
|
a1ee808ed5 | ||
|
|
3a35eeb1d5 | ||
|
|
c6412760fc | ||
|
|
cc21043053 | ||
|
|
b1816a0567 | ||
|
|
29b170a8bd | ||
|
|
3ed144f003 | ||
|
|
613d7f2adb | ||
|
|
82260d7030 | ||
|
|
dbd8b1c0ce | ||
|
|
d2a4a281a3 | ||
|
|
37021e7a0a | ||
|
|
02c171d64c | ||
|
|
a99f20b9f1 | ||
|
|
14d66203d3 | ||
|
|
6e1b28c59e | ||
|
|
53a1b19e07 | ||
|
|
87e735faa9 | ||
|
|
b2f0d51aa2 | ||
|
|
9a6403a6cd | ||
|
|
021b3952ec | ||
|
|
8ddeab7a88 | ||
|
|
bea11bf7df | ||
|
|
323807c0e1 | ||
|
|
d55b122d33 | ||
|
|
a118b461a7 | ||
|
|
c572a821e9 | ||
|
|
a3f18bb143 | ||
|
|
525a289a2c | ||
|
|
d8d058360b | ||
|
|
5ccb528e02 | ||
|
|
d9818f4b2d | ||
|
|
4e905d0334 | ||
|
|
033b08b1bb | ||
|
|
430775649c | ||
|
|
0bd714bb02 | ||
|
|
0d0289cbf7 | ||
|
|
6b21c76332 | ||
|
|
59c962d8fc | ||
|
|
13cb8fcff5 | ||
|
|
4d6317f3bc | ||
|
|
1b4ce2b925 | ||
|
|
8f7f61f2af | ||
|
|
f11b884bed | ||
|
|
3a968a305f | ||
|
|
847cce915b | ||
|
|
704d84454d | ||
|
|
6d46762e30 | ||
|
|
82cf9497ae | ||
|
|
d1563c2c23 | ||
|
|
7744fdc4b2 | ||
|
|
2d82b815fc | ||
|
|
99701e88a0 | ||
|
|
6901ae30f5 | ||
|
|
50e62b2925 | ||
|
|
c41e7cf5fc | ||
|
|
232c3ff111 | ||
|
|
a0a21a093f | ||
|
|
e2042b590a | ||
|
|
d8ed7464a1 | ||
|
|
cc08ac6f53 | ||
|
|
976a473d39 |
11
.all-contributorsrc
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"files": [],
|
||||
"imageSize": 100,
|
||||
"contributorsPerLine": 7,
|
||||
"contributorsSortAlphabetically": false,
|
||||
"badgeTemplate": "",
|
||||
"contributorTemplate": "",
|
||||
"types": {},
|
||||
"skipCi": "true",
|
||||
"contributors": []
|
||||
}
|
||||
1
.frontmatter/content/mediaDb.json
Normal file
@@ -0,0 +1 @@
|
||||
{"assets":{"v7.0.0":{"snippets-dashboard.png":{"caption":"Snippets dashboard","alt":"Snippets dashboard"}}}}
|
||||
0
.frontmatter/templates/.gitkeep
Normal file
1
.github/FUNDING.yml
vendored
@@ -1,4 +1,5 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [estruyf]
|
||||
open_collective: frontmatter
|
||||
custom: ["https://www.buymeacoffee.com/zMeFRy9"]
|
||||
|
||||
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: 'Issue: '
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: 'Enhancement: '
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
7
.github/ISSUE_TEMPLATE/feedback_request.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
name: Feedback
|
||||
about: Tell more on what you think
|
||||
title: 'Feedback: '
|
||||
labels: ''
|
||||
assignees: ''
|
||||
---
|
||||
20
.github/ISSUE_TEMPLATE/showcase.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Showcase
|
||||
about: Let us know that you are using Front Matter and we'll add you on our showcase page
|
||||
title: 'Showcase: '
|
||||
labels: 'showcase'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
**Title you want to give your site**
|
||||
|
||||
Define a clear title that will be used on the showcase page. Example: `Front Matter`.
|
||||
|
||||
**Link to the site**
|
||||
|
||||
A URL to the site to add.
|
||||
|
||||
**A nice and clean description**
|
||||
|
||||
Keep it simple. Just let us know which static-site generator you used, and other frameworks.
|
||||
|
||||
71
.github/workflows/codeql-analysis.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
- cron: '24 14 * * 5'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'javascript' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
# Learn more:
|
||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
31
.github/workflows/release-beta.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
name: BETA Release
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: "Build and release"
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16
|
||||
registry-url: https://registry.npmjs.org/
|
||||
|
||||
- name: Install the dependencies
|
||||
run: npm i
|
||||
|
||||
- name: Prepare BETA
|
||||
run: node scripts/beta-release.js $GITHUB_RUN_ID
|
||||
|
||||
- name: Publish
|
||||
run: npx vsce publish -p ${{ secrets.VSCE_PAT }} --baseImagesUrl https://raw.githubusercontent.com/estruyf/vscode-front-matter/dev
|
||||
|
||||
- name: Publish to open-vsx.org
|
||||
run: npx ovsx publish -p ${{ secrets.OPEN_VSX_PAT }}
|
||||
|
||||
14
.github/workflows/release.yml
vendored
@@ -12,17 +12,19 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14
|
||||
node-version: 16
|
||||
registry-url: https://registry.npmjs.org/
|
||||
|
||||
- name: Install the dependencies
|
||||
run: npm i
|
||||
|
||||
- name: Install vsce
|
||||
run: npm i -g vsce
|
||||
|
||||
- name: Prepare MAIN release
|
||||
run: node scripts/main-release.js
|
||||
|
||||
- name: Publish
|
||||
run: vsce publish -p ${{ secrets.VSCE_PAT }}
|
||||
run: npx vsce publish -p ${{ secrets.VSCE_PAT }}
|
||||
|
||||
- name: Publish to open-vsx.org
|
||||
run: npx ovsx publish -p ${{ secrets.OPEN_VSX_PAT }}
|
||||
9
.templates/documentation.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title:
|
||||
slug:
|
||||
description:
|
||||
date: 2019-08-22T15:20:28.000Z
|
||||
lastmod: 2019-08-22T15:20:28.000Z
|
||||
weight: 1
|
||||
type: documentation
|
||||
---
|
||||
12
.vscode/launch.json
vendored
@@ -18,6 +18,18 @@
|
||||
],
|
||||
"preLaunchTask": "npm: build:ext"
|
||||
},
|
||||
{
|
||||
"name": "Attach Extension",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/dist/**/*.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Extension Tests",
|
||||
"type": "extensionHost",
|
||||
|
||||
66
.vscode/recoil.code-snippets
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"Recoil Atom": {
|
||||
"prefix": "sq-atom",
|
||||
"body": [
|
||||
"import { atom } from 'recoil';",
|
||||
"",
|
||||
"export const ${1:CollectionId}Atom = atom({",
|
||||
" key: '${1:CollectionId}Atom',",
|
||||
" default: 1",
|
||||
"});"
|
||||
],
|
||||
"description": "Creates a new atom",
|
||||
"scope": "typescript"
|
||||
},
|
||||
"Recoil Selector (sync)": {
|
||||
"prefix": "sq-selector-sync",
|
||||
"body": [
|
||||
"import { selector } from 'recoil';",
|
||||
"",
|
||||
"export const ${1:CollectionData}Selector = selector({",
|
||||
" key: '${1:CollectionData}Selector',",
|
||||
" get: ({get}) => {",
|
||||
" return get(${1:CollectionData}Atom);",
|
||||
" }",
|
||||
"});"
|
||||
],
|
||||
"description": "Creates a new synchronous selector",
|
||||
"scope": "typescript"
|
||||
},
|
||||
"Recoil Selector (async)": {
|
||||
"prefix": "sq-selector-async",
|
||||
"body": [
|
||||
"import { selector } from 'recoil';",
|
||||
"",
|
||||
"export const ${1:CollectionData}Selector = selector({",
|
||||
" key: '${1:CollectionData}Selector',",
|
||||
" get: async ({get}) => {",
|
||||
" return await dataFetch(get(${2:CollectionIdState}));",
|
||||
" }",
|
||||
"});"
|
||||
],
|
||||
"description": "Creates a new asynchronous selector",
|
||||
"scope": "typescript"
|
||||
},
|
||||
"Recoil selectorFamily": {
|
||||
"prefix": "sq-selector-fam",
|
||||
"body": [
|
||||
"import { selectorFamily } from 'recoil';",
|
||||
"",
|
||||
"export const ${1:CollectionData}Selector = selectorFamily({",
|
||||
" key: '${1:CollectionData}Selector',",
|
||||
" get: id => async () => {",
|
||||
" return await dataFetch({id});",
|
||||
" }",
|
||||
"});"
|
||||
],
|
||||
"description": "Creates a selectorFamily (same as selector, but used to provide parameters)",
|
||||
"scope": "typescript"
|
||||
},
|
||||
"useTranslation": {
|
||||
"prefix": ["sq-translation", "useTranslation"],
|
||||
"body": "const { t: strings } = useTranslation();",
|
||||
"description": "Include the translations",
|
||||
"scope": "typescriptreact"
|
||||
}
|
||||
}
|
||||
8
.vscode/settings.json
vendored
@@ -7,5 +7,11 @@
|
||||
"out": true // set this to false to include "out" folder in search results
|
||||
},
|
||||
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
|
||||
"typescript.tsc.autoDetect": "off"
|
||||
"typescript.tsc.autoDetect": "off",
|
||||
"eliostruyf.writingstyleguide.terms.isDisabled": true,
|
||||
"eliostruyf.writingstyleguide.biasFree.isDisabled": true,
|
||||
"exportall.config.folderListener": [
|
||||
"/src/pagesView/state/atom",
|
||||
"/src/pagesView/state/selectors"
|
||||
]
|
||||
}
|
||||
@@ -10,3 +10,20 @@ vsc-extension-quickstart.md
|
||||
**/*.ts
|
||||
webpack.config.js
|
||||
node_modules
|
||||
docs
|
||||
tailwind.config.js
|
||||
sample
|
||||
postcss.config.js
|
||||
.templates
|
||||
.github
|
||||
scripts
|
||||
.all-contributorsrc
|
||||
assets/v2.*
|
||||
assets/v3.*
|
||||
assets/v4.*
|
||||
assets/sponsors
|
||||
dist/*.html
|
||||
frontmatter.json
|
||||
.frontmatter
|
||||
webpack
|
||||
README.beta.md
|
||||
462
CHANGELOG.md
@@ -1,5 +1,467 @@
|
||||
# Change Log
|
||||
|
||||
## [7.2.0] - 2022-05-02 - [Release notes](https://beta.frontmatter.codes/updates/v7.2.0)
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- New tag design for the tags, category, and taxonomy fields
|
||||
- [#263](https://github.com/estruyf/vscode-front-matter/issues/263): WYSIWYG string field option
|
||||
- [#308](https://github.com/estruyf/vscode-front-matter/issues/308): New `File` field
|
||||
- [#314](https://github.com/estruyf/vscode-front-matter/issues/314): New preview actions to open the page in the browser and refresh the preview
|
||||
- [#322](https://github.com/estruyf/vscode-front-matter/issues/322): Show parent folder name when file is an index page (`index.md` / `_index.md`)
|
||||
- [#323](https://github.com/estruyf/vscode-front-matter/issues/323): Added 11ty, jekyll, and docusaurus to the framework selection list
|
||||
- [#325](https://github.com/estruyf/vscode-front-matter/issues/325): Better welcome experience that allows you to add content folders straight from the welcome view
|
||||
- [#326](https://github.com/estruyf/vscode-front-matter/issues/326): Content type actions to create, update, or set according to the current file
|
||||
|
||||
### ⚡️ Optimizations
|
||||
|
||||
- [#316](https://github.com/estruyf/vscode-front-matter/issues/316): Suppress file parsing errors when closing the dashboard
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- Updated JSON schema link to supported version by VS Code (draft-07)
|
||||
- Hide the view mode action from the Front Matter panel if no custom modes are defined
|
||||
- Fix in decode base64 uploaded video files
|
||||
- Fix for a lightbox on other types of documents (pdf, etc.)
|
||||
- Fix for hiding the image preview on slide-over for none image documents
|
||||
- [#324](https://github.com/estruyf/vscode-front-matter/issues/324): Fix for the framework selection on the welcome screen
|
||||
|
||||
## [7.1.2] - 2022-04-11
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- [#315](https://github.com/estruyf/vscode-front-matter/issues/315): Fix draft tab navigation
|
||||
|
||||
## [7.1.1] - 2022-04-08
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- Fix in menu item with `stopPropagation` not defined.
|
||||
|
||||
## [7.1.0] - 2022-04-07 - [Release notes](https://beta.frontmatter.codes/updates/v7.1.0)
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- [#240](https://github.com/estruyf/vscode-front-matter/issues/240): Capability added to define display modes
|
||||
- [#246](https://github.com/estruyf/vscode-front-matter/issues/246): Support to add multiple tags/keywords/taxonomy via comma separated values
|
||||
- [#293](https://github.com/estruyf/vscode-front-matter/issues/293): Support added for setting preview images in block fields
|
||||
- [#294](https://github.com/estruyf/vscode-front-matter/issues/294): Full-text search allows you to search through all your page content
|
||||
- [#297](https://github.com/estruyf/vscode-front-matter/issues/297): SEO Keywords input got moved to the SEO section
|
||||
- [#301](https://github.com/estruyf/vscode-front-matter/issues/301): Show tags on the content cards
|
||||
- [#303](https://github.com/estruyf/vscode-front-matter/issues/303): Content card actions to quickly view, delete, or run custom scripts
|
||||
- [#310](https://github.com/estruyf/vscode-front-matter/issues/310): Supported mime types for media dashboard
|
||||
|
||||
### ⚡️ Optimizations
|
||||
|
||||
- [#296](https://github.com/estruyf/vscode-front-matter/issues/296): Loading optimization of the content dashboard
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- [#302](https://github.com/estruyf/vscode-front-matter/issues/302): Fix for spinner when navigating between tabs
|
||||
- [#304](https://github.com/estruyf/vscode-front-matter/issues/304): Fix yaml stringify which caused additional fields to be added
|
||||
- [#305](https://github.com/estruyf/vscode-front-matter/issues/305): Fix for overflow issue in taxonomy picker
|
||||
- [#306](https://github.com/estruyf/vscode-front-matter/issues/306): Fix for default value of content type fields
|
||||
- [#311](https://github.com/estruyf/vscode-front-matter/issues/311): Fix for updating snippets
|
||||
|
||||
## [7.0.0] - 2022-03-21 - [Release notes](https://beta.frontmatter.codes/updates/v7.0.0)
|
||||
|
||||
### ✨ New Features
|
||||
|
||||
- [#175](https://github.com/estruyf/vscode-front-matter/issues/175): New snippet support + dashboard
|
||||
- [#281](https://github.com/estruyf/vscode-front-matter/issues/281): New `isPublishDate` and `isModifiedDate` datetime field properties
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- Light color theme enhancements to media cards
|
||||
- Light color theme enhancements to folder cards
|
||||
- Added collapse and dashboard button to the view title of the FM Panel
|
||||
- Show content commands only when a supported file type is active
|
||||
- Added `{{year}}`, `{{month}}`, and `{{day}}` placeholders for fields
|
||||
- [#272](https://github.com/estruyf/vscode-front-matter/issues/272): New slide over panel for showing details of media files
|
||||
- [#276](https://github.com/estruyf/vscode-front-matter/issues/276): Add a Front Matter walkthrough for VS Code
|
||||
- [#270](https://github.com/estruyf/vscode-front-matter/issues/270): Only show media files from public folder if `pageBundle` is not enabled on any of the content types
|
||||
- [#282](https://github.com/estruyf/vscode-front-matter/issues/282): Insert relative paths for media files located in a page bundle (also sub-folders)
|
||||
- [#283](https://github.com/estruyf/vscode-front-matter/issues/283): Added published date sorting options for the content dashboard
|
||||
- [#286](https://github.com/estruyf/vscode-front-matter/issues/286): Refresh button added for the content page
|
||||
- [#287](https://github.com/estruyf/vscode-front-matter/issues/287): Show folder name on `index.md` files for recently modified files
|
||||
- [#292](https://github.com/estruyf/vscode-front-matter/issues/292): Lower fuzzy search threshold for the content dashboard
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- [#279](https://github.com/estruyf/vscode-front-matter/issues/279): Fix for content dashboard updates for all registered types
|
||||
- [#280](https://github.com/estruyf/vscode-front-matter/issues/280): Fix to not automatically set dates on new files that do not contain front matter
|
||||
- [#284](https://github.com/estruyf/vscode-front-matter/issues/284): Show the WYSIWYG controls on all supported file types
|
||||
- [#290](https://github.com/estruyf/vscode-front-matter/issues/290): Fix for onDidChangeTextEditorSelection listener sending metadata updates
|
||||
|
||||
## [6.1.1] - 2022-03-02
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- [#275](https://github.com/estruyf/vscode-front-matter/issues/275): Fix for rendering the panel when content contains an invalid markdown syntax tree
|
||||
|
||||
## [6.1.0] - 2022-02-28 - [Release notes](https://beta.frontmatter.codes/updates/v6.1.0)
|
||||
|
||||
### ✨ New features
|
||||
|
||||
- [#176](https://github.com/estruyf/vscode-front-matter/issues/176): New `block` field type that allows you to you to define a group of fields which can be used to create a list of data
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- Updated the activity bar icon for better visibility
|
||||
- Storing the panel collapse section states
|
||||
- [#241](https://github.com/estruyf/vscode-front-matter/issues/241): Added taxonomy limit field property which allows you to limit the number of selections
|
||||
- [#242](https://github.com/estruyf/vscode-front-matter/issues/242): Keep comments at the root of the front matter
|
||||
- [#248](https://github.com/estruyf/vscode-front-matter/issues/248): Added support for front matter highlighting to all file types specified in `frontMatter.content.supportedFileTypes`
|
||||
- [#255](https://github.com/estruyf/vscode-front-matter/issues/255): Added support for default values on block fields / data creation
|
||||
- [#257](https://github.com/estruyf/vscode-front-matter/issues/257): Allow preview images to be used in multi-dimensional fields
|
||||
- [#271](https://github.com/estruyf/vscode-front-matter/issues/271): Added image size placeholders for media snippets
|
||||
|
||||
### ⚡️ Optimizations
|
||||
|
||||
- Show the data item its details when clicking on the record
|
||||
- Refactoring of the explorer view panel listeners
|
||||
- Added `{{now}}` placeholder to the publishing date for content creation
|
||||
- [#243](https://github.com/estruyf/vscode-front-matter/issues/243): Refactoring front matter parsing
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- [#247](https://github.com/estruyf/vscode-front-matter/issues/247): Fix the front matter highlighting in markdown documents
|
||||
- [#261](https://github.com/estruyf/vscode-front-matter/issues/261): Fix to allow that tag and category fields can be renamed
|
||||
- [#264](https://github.com/estruyf/vscode-front-matter/issues/264): Fix for Windows paths on content folder registration
|
||||
- [#268](https://github.com/estruyf/vscode-front-matter/issues/268): Fix for panel which only shows loading indicator
|
||||
|
||||
## [6.0.0] - 2022-01-25 - [Release Notes](https://beta.frontmatter.codes/updates/v6.0.0)
|
||||
|
||||
### ✨ New features
|
||||
|
||||
- [#193](https://github.com/estruyf/vscode-front-matter/issues/193): Support added for editing data files.
|
||||
- [#197](https://github.com/estruyf/vscode-front-matter/issues/197): Support for multi-dimensional content type fields on content creation and editing.
|
||||
- [#225](https://github.com/estruyf/vscode-front-matter/issues/225): Placeholder support for front matter field values (template and content type).
|
||||
- [#226](https://github.com/estruyf/vscode-front-matter/issues/226): Ability to specify the local server start command and trigger it from the UI.
|
||||
- [#227](https://github.com/estruyf/vscode-front-matter/issues/227): Specify the file types to support with the new `frontMatter.content.supportedFileTypes` setting.
|
||||
- [#228](https://github.com/estruyf/vscode-front-matter/issues/228): Show bulk button actions in panel and dashboard view.
|
||||
- [#231](https://github.com/estruyf/vscode-front-matter/issues/231): Once you authenticate via GitHub as a supporter, the support links will be hidden from the UI.
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- Added default field value for content type fields
|
||||
- HMR support for panel webview development
|
||||
- Added reveal media file action
|
||||
- [#187](https://github.com/estruyf/vscode-front-matter/issues/187): Svelte support with the [#227](https://github.com/estruyf/vscode-front-matter/issues/227) features has been added.
|
||||
- [#198](https://github.com/estruyf/vscode-front-matter/issues/198): Additional media sort options (alt, caption, and size).
|
||||
- [#230](https://github.com/estruyf/vscode-front-matter/issues/230): JSON front matter support added.
|
||||
- [#233](https://github.com/estruyf/vscode-front-matter/issues/233): Partial update when a page is updated.
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- [#234](https://github.com/estruyf/vscode-front-matter/issues/234): Fix for multi-word keywords
|
||||
- [#235](https://github.com/estruyf/vscode-front-matter/issues/235): Fix for reselecting the previously removed value from a choice field
|
||||
|
||||
## [5.10.0] - 2022-01-10
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- [#218](https://github.com/estruyf/vscode-front-matter/issues/218): Add support for creating `mdx` files from templates and content types. This introduced a new setting: `frontMatter.content.defaultFileType`.
|
||||
- [#220](https://github.com/estruyf/vscode-front-matter/issues/220): Add support DateTime updates in `mdx` files when the `mdx extension` is not installed.
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- [#221](https://github.com/estruyf/vscode-front-matter/issues/221): Automatic DateTime switch from on text change to on save to prevent multiple updates.
|
||||
|
||||
## [5.9.0] - 2022-01-01 - 🎇🎆
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- Fixing the spinner which overlaps the global navigation bar
|
||||
- Quick actions added for media files (edit, delete, insert markdown, insert snippet)
|
||||
- [#199](https://github.com/estruyf/vscode-front-matter/issues/199): Search media files in the currently selected folder
|
||||
- [#211](https://github.com/estruyf/vscode-front-matter/issues/211): Replace text selection on media inserts
|
||||
- [#212](https://github.com/estruyf/vscode-front-matter/issues/212): Create folder watchers for content folders. When new content gets created, the dashboard updates.
|
||||
- [#213](https://github.com/estruyf/vscode-front-matter/issues/213): New media folder overview design
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- [#210](https://github.com/estruyf/vscode-front-matter/issues/210): Fix for adding media files with uppercase file extensions
|
||||
- [#214](https://github.com/estruyf/vscode-front-matter/issues/214): Fix for opening markdown file after creating it for the specified content type
|
||||
|
||||
## [5.8.0] - 2021-12-21 - 🎄
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- Refactoring of the WebView logic to new message handlers
|
||||
- Optimized the `getMedia` call from the webview
|
||||
- Keep the dashboard its context when switching tabs
|
||||
- [#205](https://github.com/estruyf/vscode-front-matter/issues/205): Define a logging level setting
|
||||
- [#206](https://github.com/estruyf/vscode-front-matter/issues/206): Add front matter issues to the diagnostic tab
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- [#207](https://github.com/estruyf/vscode-front-matter/issues/207): Fix the quick picks for content creation
|
||||
- [#208](https://github.com/estruyf/vscode-front-matter/issues/208): Fix for the collapse sections action so that it is not available everywhere, but only on the Front Matter panel
|
||||
|
||||
## [5.7.0] - 2021-12-07 - [Release Notes](https://beta.frontmatter.codes/updates/v5.7.0)
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- [#188](https://github.com/estruyf/vscode-front-matter/issues/188): Support for `.markdown` files added to the dashboard
|
||||
- [#190](https://github.com/estruyf/vscode-front-matter/issues/190): Diagnostic output for the extension
|
||||
- [#194](https://github.com/estruyf/vscode-front-matter/issues/194): WYSIWYG controls added for markdown files + configuration to enable/disable the functionality
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- [#191](https://github.com/estruyf/vscode-front-matter/issues/191): Fix beta settings page
|
||||
- [#200](https://github.com/estruyf/vscode-front-matter/issues/200): Fix last modified date sorting for media files
|
||||
- [#201](https://github.com/estruyf/vscode-front-matter/issues/201): Fix overflow issue with the media filename
|
||||
- [#202](https://github.com/estruyf/vscode-front-matter/issues/202): Fix checkbox label color for light themes
|
||||
|
||||
## [5.6.0] - 2021-11-23
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- Updated camera icon from VS Code to media icon
|
||||
- Updated the media card actions to show it within a menu. This will give a better experience with custom scripts.
|
||||
- [#97](https://github.com/estruyf/vscode-front-matter/issues/97): Custom Script support for media files and folders
|
||||
- [#178](https://github.com/estruyf/vscode-front-matter/issues/178): Sorting added to the media dashboard
|
||||
- [#179](https://github.com/estruyf/vscode-front-matter/issues/179): Updated the `open dashboard` icon to make it easier to spot it
|
||||
- [#180](https://github.com/estruyf/vscode-front-matter/issues/180): Added `{filename}` as placeholder for media snippets
|
||||
- [#181](https://github.com/estruyf/vscode-front-matter/issues/181): Support for custom taxonomy fields added
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- [#183](https://github.com/estruyf/vscode-front-matter/issues/183): Fix type error on the `frontMatter.content.sorting` setting
|
||||
|
||||
## [5.5.0] - 2021-11-15
|
||||
|
||||
As from this version onwards, the extension will be published to [open-vsx.org](https://open-vsx.org/).
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- [#173](https://github.com/estruyf/vscode-front-matter/issues/173): Allow to specify your own sorting for the content dashboard
|
||||
- [#174](https://github.com/estruyf/vscode-front-matter/issues/174): Added option to exclude sub-directories from page/markdown content retrieval
|
||||
|
||||
## [5.4.0] - 2021-11-05
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- [#166](https://github.com/estruyf/vscode-front-matter/issues/166): Added preview button to the panel base view
|
||||
- [#167](https://github.com/estruyf/vscode-front-matter/issues/167): Allow to set the preview path per content type
|
||||
|
||||
## [5.3.1] - 2021-10-29
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- [#163](https://github.com/estruyf/vscode-front-matter/issues/163): Setting workspace state instead of global state for the media view
|
||||
|
||||
## [5.3.0] - 2021-10-28 - [Release Notes](https://beta.frontmatter.codes/updates/v5.3.0)
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- [#158](https://github.com/estruyf/vscode-front-matter/issues/158): Add support for non-boolean draft/publish status fields
|
||||
- [#159](https://github.com/estruyf/vscode-front-matter/issues/159): Enhancements to SEO checks: Slug check, keyword details, more article information
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- Value check when generating slug from title
|
||||
- Fix for date time formatting with `DD` and `YYYY` tokens
|
||||
- Fix in tag space replacing when object is passed
|
||||
|
||||
## [5.2.0] - 2021-10-19
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- [#151](https://github.com/estruyf/vscode-front-matter/issues/151): Detect which site-generator or framework is used
|
||||
- [#152](https://github.com/estruyf/vscode-front-matter/issues/152): Automatically set setting based on the used site-generator or framework
|
||||
- [#154](https://github.com/estruyf/vscode-front-matter/issues/154): Bulk script support added
|
||||
- [#155](https://github.com/estruyf/vscode-front-matter/issues/155): Fallback image added for the images shown in the editor panel
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- [#153](https://github.com/estruyf/vscode-front-matter/issues/153): Support old date formatting for date-fns
|
||||
- [#156](https://github.com/estruyf/vscode-front-matter/issues/156): Fix for uploading media files into a new folder
|
||||
|
||||
## [5.1.1] - 2021-10-14
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- [#149](https://github.com/estruyf/vscode-front-matter/issues/149): Fix panel rendering when incorrect type for keywords is provided
|
||||
|
||||
## [5.1.0] - 2021-10-13
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- [#141](https://github.com/estruyf/vscode-front-matter/issues/141): Allow content creation for page bundles or single files
|
||||
- [#145](https://github.com/estruyf/vscode-front-matter/issues/145): Moved folder registration settings to `frontmatter.json` file
|
||||
- [#147](https://github.com/estruyf/vscode-front-matter/issues/147): Error boundary added for metadata fields
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- Rendered more hooks than during the previous render in `FileList`
|
||||
- [#142](https://github.com/estruyf/vscode-front-matter/issues/142): Fix for unknown tags where it throws an error
|
||||
- [#143](https://github.com/estruyf/vscode-front-matter/issues/143): Fix for duplicate values in the file list
|
||||
- [#144](https://github.com/estruyf/vscode-front-matter/issues/144): Fix for `toISOString` does not exist on object
|
||||
- [#146](https://github.com/estruyf/vscode-front-matter/issues/146): Date parsing logic added with fallbacks
|
||||
|
||||
## [5.0.0] - 2021-10-07 - [Release Notes](https://beta.frontmatter.codes/updates/v5.0.0)
|
||||
|
||||
### ✨ New features
|
||||
|
||||
- [#113](https://github.com/estruyf/vscode-front-matter/issues/113): Integrating a local DB for media metadata (caption, alt)
|
||||
- [#132](https://github.com/estruyf/vscode-front-matter/issues/132): Major changes to the media dashboard which allows you to navigate through all folders
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- [#110](https://github.com/estruyf/vscode-front-matter/issues/110): Add support for workspaces with multiple folders
|
||||
- [#117](https://github.com/estruyf/vscode-front-matter/issues/117): Allow to specify a singleline of text in the metadata fields
|
||||
- [#119](https://github.com/estruyf/vscode-front-matter/issues/119): Multi-select support for choice fields
|
||||
- [#121](https://github.com/estruyf/vscode-front-matter/issues/121): Choice fields support ID/title objects as well as a regular string
|
||||
- [#122](https://github.com/estruyf/vscode-front-matter/issues/122): Update the filenames of your media
|
||||
- [#124](https://github.com/estruyf/vscode-front-matter/issues/124): Add new `isPreviewImage` property to the content type field to specify custom preview images
|
||||
- [#126](https://github.com/estruyf/vscode-front-matter/issues/126): Create new content from the available content types
|
||||
- [#127](https://github.com/estruyf/vscode-front-matter/issues/127): Title bar action added to open the dashboard
|
||||
- [#128](https://github.com/estruyf/vscode-front-matter/issues/128): Support for multi-select on image fields added
|
||||
- [#131](https://github.com/estruyf/vscode-front-matter/issues/131): Folder creation support added on media dashboard
|
||||
- [#134](https://github.com/estruyf/vscode-front-matter/issues/134): On startup, the extension checks if local settings can be promoted
|
||||
- [#135](https://github.com/estruyf/vscode-front-matter/issues/135): `Hidden` property added for field configuration
|
||||
- [#137](https://github.com/estruyf/vscode-front-matter/issues/137): Ask to move the `.templates` folder to the new `.frontmatter` folder
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- [#120](https://github.com/estruyf/vscode-front-matter/issues/120): Choice and number field not updating when set manually in front matter of the file
|
||||
- [#133](https://github.com/estruyf/vscode-front-matter/issues/133): Fix for overriding default content type settings
|
||||
|
||||
## [4.0.1] - 2021-09-24
|
||||
|
||||
- [#114](https://github.com/estruyf/vscode-front-matter/issues/114): Fix for categories/tags provided as string in YAML
|
||||
- [#115](https://github.com/estruyf/vscode-front-matter/issues/115): Fix for updating added categories/tags
|
||||
- [#116](https://github.com/estruyf/vscode-front-matter/issues/116): Fix for not showing the `-1` limit on inputs
|
||||
|
||||
## [4.0.0] - 2021-09-22 - [Release Notes](https://beta.frontmatter.codes/updates/v4_0_0)
|
||||
|
||||
- [#101](https://github.com/estruyf/vscode-front-matter/issues/101): Date picker available on the metadata section
|
||||
- [#102](https://github.com/estruyf/vscode-front-matter/issues/102): Support comma separated arrays in front matter
|
||||
- [#103](https://github.com/estruyf/vscode-front-matter/issues/103): Added title and description field to the metadata section
|
||||
- [#104](https://github.com/estruyf/vscode-front-matter/issues/104): Allow to set images in front matter from the metadata panel section
|
||||
- [#105](https://github.com/estruyf/vscode-front-matter/issues/105): Content Type support with backwards compatibility
|
||||
- [#106](https://github.com/estruyf/vscode-front-matter/issues/106): Introduction of team level settings for Front Matter
|
||||
- [#107](https://github.com/estruyf/vscode-front-matter/issues/107): Number field support added in content type fields
|
||||
- [#108](https://github.com/estruyf/vscode-front-matter/issues/108): Choice field support added in content type fields
|
||||
- [#109](https://github.com/estruyf/vscode-front-matter/issues/109): JSON Config script added to automate the JSON schema
|
||||
- [#111](https://github.com/estruyf/vscode-front-matter/issues/111): Insert media into the markdown contents
|
||||
- [#112](https://github.com/estruyf/vscode-front-matter/issues/112): Add snippet support for media insertion
|
||||
|
||||
## [3.1.0] - 2021-09-10
|
||||
|
||||
- BETA version available at: [beta.frontmatter.codes](https://beta.frontmatter.codes)
|
||||
- [#72](https://github.com/estruyf/vscode-front-matter/issues/72): Media view on the dashboard
|
||||
- [#73](https://github.com/estruyf/vscode-front-matter/issues/73): List view option for the dashboard
|
||||
- [#77](https://github.com/estruyf/vscode-front-matter/issues/77): Dashboard grouping pages functionality integrated
|
||||
- [#81](https://github.com/estruyf/vscode-front-matter/issues/81): Optimizing the content folders to use a new setting to simplify configuration
|
||||
- [#87](https://github.com/estruyf/vscode-front-matter/issues/87): Fix issue with autofocus and command palette
|
||||
- [#88](https://github.com/estruyf/vscode-front-matter/issues/88): Fix issue with search sorting
|
||||
- [#89](https://github.com/estruyf/vscode-front-matter/issues/89): Clear filter, sorting, and grouping button added
|
||||
- [#90](https://github.com/estruyf/vscode-front-matter/issues/90): Refactoring to use Recoil state management
|
||||
- [#91](https://github.com/estruyf/vscode-front-matter/issues/91): Support image previews from content folders
|
||||
- [#98](https://github.com/estruyf/vscode-front-matter/issues/98): Add drag and drop support for media upload in a folder
|
||||
|
||||
## [3.0.2] - 2021-08-31
|
||||
|
||||
- [#82](https://github.com/estruyf/vscode-front-matter/issues/82): Hide the register and unregister commands from the command palette
|
||||
|
||||
## [3.0.1] - 2021-08-30
|
||||
|
||||
- [#79](https://github.com/estruyf/vscode-front-matter/issues/79): Fix scrollbar not visible on the welcome screen
|
||||
|
||||
## [3.0.0] - 2021-08-27
|
||||
|
||||
- [#61](https://github.com/estruyf/vscode-front-matter/issues/61): List of recently modified files
|
||||
- [#64](https://github.com/estruyf/vscode-front-matter/issues/64): Publish toggle for easier publishing an article
|
||||
- [#65](https://github.com/estruyf/vscode-front-matter/issues/65): Aggregate articles in draft
|
||||
- [#66](https://github.com/estruyf/vscode-front-matter/issues/66): New dashboard webview on which you can manage all your content
|
||||
- [#69](https://github.com/estruyf/vscode-front-matter/issues/69): Welcome screen for getting started
|
||||
|
||||
## [2.5.1] - 2020-08-23
|
||||
|
||||
- Fix typo in the `package.json` file for the preview command
|
||||
|
||||
## [2.5.0] - 2020-08-19
|
||||
|
||||
- Moved the center layout button to the other actions section
|
||||
- [#60](https://github.com/estruyf/vscode-front-matter/issues/60): Added the ability to open a site preview in VS Code
|
||||
|
||||
## [2.4.1] - 2020-08-16
|
||||
|
||||
- Better editor highlighting functionality
|
||||
|
||||
## [2.4.0] - 2020-08-16
|
||||
|
||||
- [#21](https://github.com/estruyf/vscode-front-matter/issues/21): Folding provider for Front Matter implemented
|
||||
- [#55](https://github.com/estruyf/vscode-front-matter/issues/55): Highlight Front Matter in Markdown files
|
||||
- [#56](https://github.com/estruyf/vscode-front-matter/issues/56): Action to collapse all Front Matter panel sections at once
|
||||
- [#57](https://github.com/estruyf/vscode-front-matter/issues/57): New action added to provide better writing settings (only for Markdown files)
|
||||
- [#58](https://github.com/estruyf/vscode-front-matter/issues/58): Sections remember their previous state (folded/unfolded)
|
||||
- [#59](https://github.com/estruyf/vscode-front-matter/issues/59): Center layout view toggle action added
|
||||
|
||||
## [2.3.0] - 2020-08-10
|
||||
|
||||
- Refactoring and showing other actions in the base view
|
||||
- Show `BaseView` in Front Matter panel when switching to `welcome` tab
|
||||
- [#31](https://github.com/estruyf/vscode-front-matter/issues/31): Automatically update the last modification date of the file when performing changes
|
||||
- [#53](https://github.com/estruyf/vscode-front-matter/issues/53): Create current Markdown file as template
|
||||
|
||||
## [2.2.0] - 2020-08-06
|
||||
|
||||
- [#28](https://github.com/estruyf/vscode-front-matter/issues/28): Align the file its name with the article slug
|
||||
- [#47](https://github.com/estruyf/vscode-front-matter/issues/47): Fix when table shows only value `0`
|
||||
- [#48](https://github.com/estruyf/vscode-front-matter/issues/48): Added new folder registration message + notification helper
|
||||
- [#49](https://github.com/estruyf/vscode-front-matter/issues/49): New initialize project command
|
||||
- [#50](https://github.com/estruyf/vscode-front-matter/issues/50): Fix in the table rendering of rows
|
||||
- [#51](https://github.com/estruyf/vscode-front-matter/issues/51): Panel actions base view enhanced to show project actions and information
|
||||
|
||||
## [2.1.0] - 2020-08-04
|
||||
|
||||
- [#44](https://github.com/estruyf/vscode-front-matter/issues/45): Added article creation command
|
||||
- [#45](https://github.com/estruyf/vscode-front-matter/issues/45): WSL support added
|
||||
- [#46](https://github.com/estruyf/vscode-front-matter/issues/46): Make the tag pickers render in full width
|
||||
|
||||
## [2.0.1] - 2020-07-27
|
||||
|
||||
- [#42](https://github.com/estruyf/vscode-front-matter/issues/42): Small enhancement to the table layout
|
||||
- [#43](https://github.com/estruyf/vscode-front-matter/issues/43): Fix for collapsible sections and taxonomy picker
|
||||
|
||||
## [2.0.0] - 2020-07-23
|
||||
|
||||
- Redesigned sidebar panel
|
||||
- Sidebar background styling match the VSCode defined sidebar color
|
||||
- Added support for `mdx` files
|
||||
- Added support for `enter` press in the combobox
|
||||
- [#41](https://github.com/estruyf/vscode-front-matter/issues/41): Word count implementation + extra details
|
||||
- [#40](https://github.com/estruyf/vscode-front-matter/issues/40): Added checks for the keyword usage in title, description, slug, and content
|
||||
|
||||
## [1.18.0] - 2020-07-20
|
||||
|
||||
- Updated README
|
||||
|
||||
## [1.17.1] - 2020-06-28
|
||||
|
||||
- [#34](https://github.com/estruyf/vscode-front-matter/issues/34): Fix that last modification date does not update the publication date
|
||||
- [#38](https://github.com/estruyf/vscode-front-matter/issues/38): Update the last modification date on new page creation from the template
|
||||
|
||||
## [1.17.0] - 2020-06-14
|
||||
|
||||
- [#36](https://github.com/estruyf/vscode-front-matter/issues/36): Add the option to change the Front Matter its description field
|
||||
|
||||
## [1.16.1] - 2020-05-27
|
||||
|
||||
- Fix for Node.js v14.16.0
|
||||
|
||||
## [1.16.0] - 2020-05-04
|
||||
|
||||
- Add all front matter properties as an argument for custom scripts
|
||||
|
||||
## [1.15.1] - 2020-05-04
|
||||
|
||||
- Add the ability to specify a custom Node path
|
||||
|
||||
## [1.15.0] - 2020-05-04
|
||||
|
||||
- Added the ability to add your own custom scripts as panel actions.
|
||||
|
||||
190
README.beta.md
Normal file
@@ -0,0 +1,190 @@
|
||||
<h1 align="center">
|
||||
<a href="https://frontmatter.codes">
|
||||
<img alt="Front Matter" src="https://frontmatter.codes/assets/frontmatter-social.png">
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
<h2 align="center">Front Matter a CMS running straight in Visual Studio Code</h2>
|
||||
|
||||
<h2 align="center">This is the BETA version of Front Matter. If you were looking for the main version, check it out at <a href="https://frontmatter.codes">frontmatter.codes</a></h2>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter" title="Check it out on the Visual Studio Marketplace">
|
||||
<img src="https://vsmarketplacebadge.apphb.com/version/eliostruyf.vscode-front-matter.svg" alt="Visual Studio Marketplace" style="display: inline-block" />
|
||||
</a>
|
||||
|
||||
<img src="https://vsmarketplacebadge.apphb.com/installs/eliostruyf.vscode-front-matter.svg" alt="Number of installs" style="display: inline-block;margin-left:10px" />
|
||||
|
||||
<img src="https://vsmarketplacebadge.apphb.com/rating/eliostruyf.vscode-front-matter.svg" alt="Ratings" style="display: inline-block;margin-left:10px" />
|
||||
|
||||
<a href="https://github.com/sponsors/estruyf" title="Become a sponsor" style="margin-left:10px">
|
||||
<img src="https://img.shields.io/github/sponsors/estruyf?color=%23CE2E7C&logo=github&style=flat" alt="Sponsor the project" style="display: inline-block" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h2 align="center">
|
||||
<a href="https://beta.frontmatter.codes" title="Documentation @ beta.frontmatter.codes">
|
||||
Check out the extension documentation at beta.frontmatter.codes
|
||||
</a>
|
||||
</h2>
|
||||
|
||||
## ❓ What is Front Matter?
|
||||
|
||||
Front Matter is a CMS that runs within Visual Studio Code. It gives you the power and control of a full-blown CMS while also providing you the flexibility and speed of the static site generator of your choice. Jump right into editing and creating content with Front Matter and be able to preview it straight in VS Code.
|
||||
|
||||
The extension supports various static-site generators and frameworks like Hugo, Jekyll, Hexo, NextJs, Gatsby, and more.
|
||||
|
||||
A couple of our extension highlights that hopefully get you interested in giving Front Matter a try:
|
||||
|
||||
- Content, data, and media management
|
||||
- Search, filter, sort, etc. all your content
|
||||
- Create new content
|
||||
- Supporting tools to edit content and media
|
||||
- Preview your site/content straight in Visual Studio Code
|
||||
- SEO checks for title, description, and keywords
|
||||
- Extensibility
|
||||
- As we know, we cannot support all use cases. We provide a way to extend the functionality of the extension to your needs
|
||||
- and many more features ...
|
||||
|
||||
> Missing something? Let us know by opening an issue on the [GitHub repository](https://github.com/estruyf/vscode-front-matter/issues/new/choose)
|
||||
|
||||
<p align="center">
|
||||
<img src="https://frontmatter.codes/assets/marketplace/v6.0.0/content-preview.png" alt="Site preview" style="display: inline-block" />
|
||||
</p>
|
||||
|
||||
> If you see something missing in your article creation flow, please feel free to reach out.
|
||||
|
||||
**Version 7**
|
||||
|
||||
Snippets support for Front Matter has been added!
|
||||
|
||||

|
||||
|
||||
**Version 6**
|
||||
|
||||
In this version, we introduced the new data files/folders dashboard. You can find more information about the release in our [v6.0.0 release notes](https://frontmatter.codes/updates/v6.0.0).
|
||||
|
||||
<p align="center">
|
||||
<img src="https://frontmatter.codes/assets/marketplace/v6.0.0/data-dashboard.png" alt="Data dashboard" style="display: inline-block" />
|
||||
</p>
|
||||
|
||||
> Data files/folders are pieces of content that do not belong to any markdown content, but live on their own. Most of the time, these data files are used to store additional information about your project/blog/website that will be used to render the content.
|
||||
|
||||
**Version 5**
|
||||
|
||||
The new media dashboard redesign got introduced + support for setting metadata on media files [v5.0.0 release notes](https://frontmatter.codes/updates/v5.0.0).
|
||||
|
||||
<p align="center">
|
||||
<img src="https://frontmatter.codes/assets/marketplace/v5.9.0/media-dashboard.png" alt="Data dashboard" style="display: inline-block" />
|
||||
</p>
|
||||
|
||||
**Version 4**
|
||||
|
||||
Support for Team level settings, content-types, and image support. Get to know more at: [v4.0.0 release notes](https://frontmatter.codes/updates/v4_0_0).
|
||||
|
||||
**Version 3**
|
||||
|
||||
In version v3 we introduced the welcome and dashboard webview. The welcome view allows to get you started using the extension, and the dashboard allows you to manage all your markdown pages in one place. This makes it easy to search, filter, sort, and more.
|
||||
|
||||
**Version 2**
|
||||
|
||||
In version v2 we released the re-designed sidebar panel with improved SEO support. This extension makes it the only extension to manage your Markdown pages for your static sites in Visual Studio Code.
|
||||
|
||||
<p align="center" style="margin-top: 2rem;">
|
||||
<a href="https://www.producthunt.com/posts/front-matter?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-front-matter" target="_blank">
|
||||
<img src="https://api.producthunt.com/widgets/embed-image/v1/featured.png?post_id=309033&theme=dark" alt="Front Matter BETA - Managing your static sites straight from within VS Code | Product Hunt" style="width: 250px; height: 40px;" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## ⚙️ Installation
|
||||
|
||||
You can get the extension via:
|
||||
|
||||
- The VS Code marketplace: [VS Code Marketplace - Front Matter](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter).
|
||||
- The extension CLI: `ext install eliostruyf.vscode-front-matter`
|
||||
- Or by clicking on the following link: <a href="" title="open extension in VS Code" data-vscode="vscode:extension/eliostruyf.vscode-front-matter">open extension in VS Code</a>
|
||||
|
||||
> **Info**: The docs can be found on [frontmatter.codes](https://frontmatter.codes).
|
||||
|
||||
### 🧪 Beta version
|
||||
|
||||
If you have the courage to test out the beta features, we made available a beta version as well. You can install this via:
|
||||
|
||||
- Uninstall the main Front Matter version
|
||||
- Install the beta version
|
||||
- VS Code marketplace: [VS Code Marketplace - Front Matter BETA](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter-beta).
|
||||
- The extension CLI: `ext install eliostruyf.vscode-front-matter-beta`
|
||||
- Or by clicking on the following link: <a href="" title="open extension in VS Code" data-vscode="vscode:extension/eliostruyf.vscode-front-matter-beta">open extension in VS Code</a>
|
||||
|
||||
> **Info**: The BETA docs can be found on [beta.frontmatter.codes](https://beta.frontmatter.codes).
|
||||
|
||||
## 📖 Documentation
|
||||
|
||||
All documentation can be found on [frontmatter.codes](https://frontmatter.codes).
|
||||
|
||||
Documentation repository: [GitHub - Front Matter DOCs](https://github.com/FrontMatter/web-documentation-nextjs)
|
||||
|
||||
## 💪 Contributing
|
||||
|
||||
Pull requests are welcome. Please open an issue first to discuss what you would like to change, or which problem you would like to fix. This makes it easier for us to follow-up and plan for future releases.
|
||||
|
||||
You can always help us improve the extension in varous ways like:
|
||||
|
||||
- Testing out the extension and providing feedback
|
||||
- Reporting issues and bugs
|
||||
- Suggesting new features
|
||||
- Fixing an issue
|
||||
- Updating documentation
|
||||
- UI improvements
|
||||
- Tutorials
|
||||
- etc.
|
||||
|
||||
Eager to start contributing? Great 🤩, you can contribute to the following projects:
|
||||
|
||||
- [Extension](https://github.com/estruyf/vscode-front-matter)
|
||||
- [Documentation](https://github.com/FrontMatter/web-documentation-nextjs)
|
||||
- [Sample Projects](https://github.com/FrontMatter/project-samples)
|
||||
|
||||
## 👀 Show the work you are using Front Matter
|
||||
|
||||
Are you using Front Matter and are you interested in showing for which websites you use it? You can show your work by opening a [showcase issue](https://github.com/estruyf/vscode-front-matter/issues/new?assignees=&labels=&template=showcase.md&title=Showcase%3A+).
|
||||
|
||||
You can open showcase issues for the following things:
|
||||
|
||||
- Show the website for which you use Front Matter;
|
||||
- Share an article/video/webcast/... that explains how you use Front Matter;
|
||||
- Got something else to share? Open an issue and we can see where it fits on our website.
|
||||
|
||||
## 👉 Contributors 🤘
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/estruyf/vscode-front-matter/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=estruyf/vscode-front-matter" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 🖤 Backers & Sponsors 👇 🤘
|
||||
|
||||
<p align="center">
|
||||
<img src="https://frontmatter.codes/api/img-sponsors" />
|
||||
</p>
|
||||
|
||||
<br />
|
||||
|
||||
<p align="center">
|
||||
<a href="https://vercel.com/?utm_source=vscode-frontmatter&utm_campaign=oss">
|
||||
<img src="https://frontmatter.codes/assets/sponsors/powered-by-vercel.png" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 🔑 License
|
||||
|
||||
[MIT](./LICENSE)
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<p align="center">
|
||||
<a href="https://visitorbadge.io">
|
||||
<img src="https://estruyf-github.azurewebsites.net/api/VisitorHit?user=estruyf&repo=vscode-front-matter&countColor=%23F05450&labelColor=%230E131F" height="25px" />
|
||||
</a>
|
||||
</p>
|
||||
298
README.md
@@ -1,213 +1,189 @@
|
||||
[](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter)
|
||||
|
||||
[](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter)
|
||||
|
||||
[](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter&ssr=false#review-details)
|
||||
<h1 align="center">
|
||||
<a href="https://frontmatter.codes">
|
||||
<img alt="Front Matter" src="https://frontmatter.codes/assets/frontmatter-social.png">
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
This VSCode extension simplifies working with your markdown articles' front matter when using a static site generator like Hugo, Jekyll, Hexo, NextJs, Gatsby, and many more... For example, you can keep a list of used tags, categories and add/remove them from your article with the extension.
|
||||
<h2 align="center">Front Matter a CMS running straight in Visual Studio Code</h2>
|
||||
|
||||
The extension will automatically verify if your title and description are SEO compliant. If this would not be the case, it will give you a warning.
|
||||
<p align="center">
|
||||
<a href="https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter" title="Check it out on the Visual Studio Marketplace">
|
||||
<img src="https://vsmarketplacebadge.apphb.com/version/eliostruyf.vscode-front-matter.svg" alt="Visual Studio Marketplace" style="display: inline-block" />
|
||||
</a>
|
||||
|
||||
<img src="https://vsmarketplacebadge.apphb.com/installs/eliostruyf.vscode-front-matter.svg" alt="Number of installs" style="display: inline-block;margin-left:10px" />
|
||||
|
||||
<img src="https://vsmarketplacebadge.apphb.com/rating/eliostruyf.vscode-front-matter.svg" alt="Ratings" style="display: inline-block;margin-left:10px" />
|
||||
|
||||
<a href="https://github.com/sponsors/estruyf" title="Become a sponsor" style="margin-left:10px">
|
||||
<img src="https://img.shields.io/github/sponsors/estruyf?color=%23CE2E7C&logo=github&style=flat" alt="Sponsor the project" style="display: inline-block" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h2 align="center">
|
||||
<a href="https://frontmatter.codes" title="Documentation @ frontmatter.codes">
|
||||
Check out the extension documentation at frontmatter.codes
|
||||
</a>
|
||||
</h2>
|
||||
|
||||
## ❓ What is Front Matter?
|
||||
|
||||
Front Matter is a CMS that runs within Visual Studio Code. It gives you the power and control of a full-blown CMS while also providing you the flexibility and speed of the static site generator of your choice. Jump right into editing and creating content with Front Matter and be able to preview it straight in VS Code.
|
||||
|
||||
The extension supports various static-site generators and frameworks like Hugo, Jekyll, Hexo, NextJs, Gatsby, and more.
|
||||
|
||||
A couple of our extension highlights that hopefully get you interested in giving Front Matter a try:
|
||||
|
||||
- Content, data, and media management
|
||||
- Search, filter, sort, etc. all your content
|
||||
- Create new content
|
||||
- Supporting tools to edit content and media
|
||||
- Preview your site/content straight in Visual Studio Code
|
||||
- SEO checks for title, description, and keywords
|
||||
- Extensibility
|
||||
- As we know, we cannot support all use cases. We provide a way to extend the functionality of the extension to your needs
|
||||
- and many more features ...
|
||||
|
||||
> Missing something? Let us know by opening an issue on the [GitHub repository](https://github.com/estruyf/vscode-front-matter/issues/new/choose)
|
||||
|
||||
<p align="center">
|
||||
<img src="https://frontmatter.codes/assets/marketplace/v6.0.0/content-preview.png" alt="Site preview" style="display: inline-block" />
|
||||
</p>
|
||||
|
||||
> If you see something missing in your article creation flow, please feel free to reach out.
|
||||
|
||||
## FrontMatter Panel (introduced in 1.10.0)
|
||||
**Version 7**
|
||||
|
||||
In version `1.10.0` of this extension, the FrontMatter panel got introduced. This panel allows you to perform most of the extension actions by just a click on the button.
|
||||
Snippets support for Front Matter has been added!
|
||||
|
||||

|
||||

|
||||
|
||||
Initially, this panel has been created to make it easier to add tags and categories to your articles as the current VSCode multi-select is not optimal to use.
|
||||
**Version 6**
|
||||
|
||||
To leverage most of the capabilities of the extension. SEO information and everyday actions like slug optimization, updating the date, and publish/drafting the article.
|
||||
In this version, we introduced the new data files/folders dashboard. You can find more information about the release in our [v6.0.0 release notes](https://frontmatter.codes/updates/v6.0.0).
|
||||
|
||||
> **Info**: By default, the tags/categories picker allows you to insert existing and none tags/categories. When you enter a none existing tag/category, the panel shows an add `+` icon in front of that button. This functionality allows you to store this tag/category in your settings. If you want to disable this feature, you can do that by setting the `frontMatter.panel.freeform` setting to `false`.
|
||||
<p align="center">
|
||||
<img src="https://frontmatter.codes/assets/marketplace/v6.0.0/data-dashboard.png" alt="Data dashboard" style="display: inline-block" />
|
||||
</p>
|
||||
|
||||
Since version `1.15.0`, the extension allows you to create your own custom actions, by running Node.js scripts from your project. In order to use this functionality, you will need to configure the [`frontMatter.custom.scripts`](#frontMatter.custom.scripts) setting for your project.
|
||||
> Data files/folders are pieces of content that do not belong to any markdown content, but live on their own. Most of the time, these data files are used to store additional information about your project/blog/website that will be used to render the content.
|
||||
|
||||
Once a custom action has been configured, it will appear on the Front Matter panel.
|
||||
**Version 5**
|
||||
|
||||

|
||||
The new media dashboard redesign got introduced + support for setting metadata on media files [v5.0.0 release notes](https://frontmatter.codes/updates/v5.0.0).
|
||||
|
||||
The current workspace- and file-path will be passed as an argument. In your script fetch these arguments as follows:
|
||||
<p align="center">
|
||||
<img src="https://frontmatter.codes/assets/marketplace/v5.9.0/media-dashboard.png" alt="Data dashboard" style="display: inline-block" />
|
||||
</p>
|
||||
|
||||
```javascript
|
||||
const arguments = process.argv;
|
||||
const workspaceArg = arguments[2];
|
||||
const fileArg = arguments[3];
|
||||
```
|
||||
**Version 4**
|
||||
|
||||
The output of the script will be passed as a notification, and it allows you to copy the output.
|
||||
Support for Team level settings, content-types, and image support. Get to know more at: [v4.0.0 release notes](https://frontmatter.codes/updates/v4_0_0).
|
||||
|
||||

|
||||
**Version 3**
|
||||
|
||||
## Creating articles from templates
|
||||
In version v3 we introduced the welcome and dashboard webview. The welcome view allows to get you started using the extension, and the dashboard allows you to manage all your markdown pages in one place. This makes it easy to search, filter, sort, and more.
|
||||
|
||||
By default, the extension looks for files stored in a `.templates` folder that should be located in your website project's root.
|
||||
**Version 2**
|
||||
|
||||
> **Info**: You can overwrite the path by specifying it with the `frontMatter.templates.folder` setting.
|
||||
In version v2 we released the re-designed sidebar panel with improved SEO support. This extension makes it the only extension to manage your Markdown pages for your static sites in Visual Studio Code.
|
||||
|
||||
When adding files in the folder, you'll be able to run the `Front Matter: New article from template` from a command or explorer menu. It will present you with the article template options once you pick one and specify the title. It creates the file and updates its front matter.
|
||||
<p align="center" style="margin-top: 2rem;">
|
||||
<a href="https://www.producthunt.com/posts/front-matter?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-front-matter" target="_blank">
|
||||
<img src="https://api.producthunt.com/widgets/embed-image/v1/featured.png?post_id=309033&theme=dark" alt="Front Matter - Managing your static sites straight from within VS Code | Product Hunt" style="width: 250px; height: 40px;" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
> **Info**: By default, the extension will create articles with a `yyyy-MM-dd` prefix. If you do not want that or change the date format, you can update the `frontMatter.templates.prefix` setting.
|
||||
## ⚙️ Installation
|
||||
|
||||
## Syntax highlighting for Hugo Shortcodes
|
||||
You can get the extension via:
|
||||
|
||||

|
||||
- The VS Code marketplace: [VS Code Marketplace - Front Matter](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter).
|
||||
- The extension CLI: `ext install eliostruyf.vscode-front-matter`
|
||||
- Or by clicking on the following link: <a href="" title="open extension in VS Code" data-vscode="vscode:extension/eliostruyf.vscode-front-matter">open extension in VS Code</a>
|
||||
|
||||
## Available commands:
|
||||
> **Info**: The docs can be found on [frontmatter.codes](https://frontmatter.codes).
|
||||
|
||||
**Front Matter: Create <tag | category>**
|
||||
### 🧪 Beta version
|
||||
|
||||
Creates a new <tag | category> and allows you to include it into your post automatically
|
||||
If you have the courage to test out the beta features, we made available a beta version as well. You can install this via:
|
||||
|
||||

|
||||
|
||||
**Front Matter: Insert <tags | categories>**
|
||||
- Uninstall the main Front Matter version
|
||||
- Install the beta version
|
||||
- VS Code marketplace: [VS Code Marketplace - Front Matter BETA](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter-beta).
|
||||
- The extension CLI: `ext install eliostruyf.vscode-front-matter-beta`
|
||||
- Or by clicking on the following link: <a href="" title="open extension in VS Code" data-vscode="vscode:extension/eliostruyf.vscode-front-matter-beta">open extension in VS Code</a>
|
||||
|
||||
Inserts a selected <tags | categories> into the front matter of your article/post/... - When using this command, the FrontMatter panel opens and focuses on the specified type.
|
||||
> **Info**: The BETA docs can be found on [beta.frontmatter.codes](https://beta.frontmatter.codes).
|
||||
|
||||
> **Info**: This experience changed in version `1.11.0`.
|
||||
## 📖 Documentation
|
||||
|
||||
**Front Matter: Export all tags & categories to your settings**
|
||||
All documentation can be found on [frontmatter.codes](https://frontmatter.codes).
|
||||
|
||||
Export all the already used tags & categories in your articles/posts/... to your user settings.
|
||||
Documentation repository: [GitHub - Front Matter DOCs](https://github.com/FrontMatter/web-documentation-nextjs)
|
||||
|
||||
**Front Matter: Remap or remove tag/category in all articles**
|
||||
## 💪 Contributing
|
||||
|
||||
This command helps you quickly update/remap or delete a tag or category in your markdown files. The extension will ask you to select the taxonomy type (*tag* or *category*), the old taxonomy value, and the new one (leave the input field *blank* to remove the tag/category).
|
||||
Pull requests are welcome. Please open an issue first to discuss what you would like to change, or which problem you would like to fix. This makes it easier for us to follow-up and plan for future releases.
|
||||
|
||||
> **Info**: Once the remapping/deleting process completes. Your VSCode settings update with all new taxonomy tags/categories.
|
||||
You can always help us improve the extension in varous ways like:
|
||||
|
||||
**Front Matter: Set current date**
|
||||
- Testing out the extension and providing feedback
|
||||
- Reporting issues and bugs
|
||||
- Suggesting new features
|
||||
- Fixing an issue
|
||||
- Updating documentation
|
||||
- UI improvements
|
||||
- Tutorials
|
||||
- etc.
|
||||
|
||||
Update the `date` property of the current article/post/... to the current date & time.
|
||||
Eager to start contributing? Great 🤩, you can contribute to the following projects:
|
||||
|
||||
**Optional**: if you want, you can specify the date property format by adding your settings' preference. Settings key: `frontMatter.taxonomy.dateFormat`. Check [date-fns formatting](https://date-fns.org/v2.0.1/docs/format) for more information on which patterns you can use.
|
||||
- [Extension](https://github.com/estruyf/vscode-front-matter)
|
||||
- [Documentation](https://github.com/FrontMatter/web-documentation-nextjs)
|
||||
- [Sample Projects](https://github.com/FrontMatter/project-samples)
|
||||
|
||||
**Front Matter: Set lastmod date**
|
||||
## 👀 Show the work you are using Front Matter
|
||||
|
||||
Update the `lastmod` (last modified) property of the current article/post/... to the current date & time.
|
||||
Are you using Front Matter and are you interested in showing for which websites you use it? You can show your work by opening a [showcase issue](https://github.com/estruyf/vscode-front-matter/issues/new?assignees=&labels=&template=showcase.md&title=Showcase%3A+).
|
||||
|
||||
> **note**: Uses the same date format settings key as current date: `frontMatter.taxonomy.dateFormat`.
|
||||
You can open showcase issues for the following things:
|
||||
|
||||
**Front Matter: Generate slug based on article title**
|
||||
- Show the website for which you use Front Matter;
|
||||
- Share an article/video/webcast/... that explains how you use Front Matter;
|
||||
- Got something else to share? Open an issue and we can see where it fits on our website.
|
||||
|
||||
This command generates a clean slug for your article. It removes known stop words, punctuations, and special characters.
|
||||
## 👉 Contributors 🤘
|
||||
|
||||
Example:
|
||||
```
|
||||
title: Just a sample page with a title
|
||||
slug: sample-page-title
|
||||
```
|
||||
<p align="center">
|
||||
<a href="https://github.com/estruyf/vscode-front-matter/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=estruyf/vscode-front-matter" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
You can also specify a prefix and suffix, which can be added to the slug if you want. Use the following settings to do this: `frontMatter.taxonomy.slugPrefix` and `frontMatter.taxonomy.slugSuffix`. By default, both options are not provided and will not add anything to the slug.
|
||||
## 🖤 Backers & Sponsors 👇 🤘
|
||||
|
||||
> **Info**: At the moment, the extension only supports English stopwords.
|
||||
<p align="center">
|
||||
<img src="https://frontmatter.codes/api/img-sponsors" />
|
||||
</p>
|
||||
|
||||
## Where is the data stored?
|
||||
<br />
|
||||
|
||||
The tags and categories are stored in the project VSCode user settings. You can find them back under: `.vscode/settings.json`.
|
||||
<p align="center">
|
||||
<a href="https://vercel.com/?utm_source=vscode-frontmatter&utm_campaign=oss">
|
||||
<img src="https://frontmatter.codes/assets/sponsors/powered-by-vercel.png" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
```json
|
||||
{
|
||||
"frontMatter.taxonomy.tags": [],
|
||||
"frontMatter.taxonomy.categories": []
|
||||
}
|
||||
```
|
||||
## 🔑 License
|
||||
|
||||
## Additional extension settings
|
||||
[MIT](./LICENSE)
|
||||
|
||||
The extension has more settings that allow you to configure it to your needs further. Here is a list of settings that you can set:
|
||||
<br />
|
||||
<br />
|
||||
|
||||
### `frontMatter.taxonomy.seoTitleLength`
|
||||
|
||||
Specifies the optimal title length for SEO (set to `-1` to turn it off). Default value: `60`.
|
||||
|
||||
```json
|
||||
{
|
||||
"frontMatter.taxonomy.seoTitleLength": 60
|
||||
}
|
||||
```
|
||||
### `frontMatter.taxonomy.seoDescriptionLength`
|
||||
|
||||
Specifies the optimal description length for SEO (set to `-1` to turn it off). Default value: `160`.
|
||||
|
||||
```json
|
||||
{
|
||||
"frontMatter.taxonomy.seoDescriptionLength": 160
|
||||
}
|
||||
```
|
||||
|
||||
### `frontMatter.taxonomy.frontMatterType`
|
||||
|
||||
Specify which Front Matter language you want to use. The extension supports `YAML` (default) and `TOML`.
|
||||
|
||||
```json
|
||||
{
|
||||
"frontMatter.taxonomy.frontMatterType": "YAML"
|
||||
}
|
||||
```
|
||||
|
||||
### `frontMatter.taxonomy.indentArrays`
|
||||
|
||||
Specify if arrays in the front matter are indented. Default: `true`. If you do not want to indent the array values, you can update it with the following setting change:
|
||||
|
||||
```json
|
||||
{
|
||||
"frontMatter.taxonomy.indentArrays": false
|
||||
}
|
||||
```
|
||||
|
||||
### `frontMatter.taxonomy.noPropertyValueQuotes`
|
||||
|
||||
Specify the property names of which you want to remove the quotes in the output value. **Warning**: only use this when you know what you are doing. If you're going to, for instance, remove the quotes from the date property, you can add the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"frontMatter.taxonomy.noPropertyValueQuotes": ["date"]
|
||||
}
|
||||
```
|
||||
|
||||
### `frontMatter.taxonomy.dateField`
|
||||
|
||||
Specifies the date field name to use in your Front Matter. Default value: `date`.
|
||||
|
||||
```json
|
||||
{
|
||||
"frontMatter.taxonomy.dateField": "date"
|
||||
}
|
||||
```
|
||||
|
||||
### `frontMatter.taxonomy.modifiedField`
|
||||
|
||||
Specifies the modified date field name to use in your Front Matter. Default value: `lastmod`.
|
||||
|
||||
```json
|
||||
{
|
||||
"frontMatter.taxonomy.modifiedField": "lastmod"
|
||||
}
|
||||
```
|
||||
|
||||
### `frontMatter.custom.scripts`
|
||||
|
||||
Allows you to specify a title and script path (starting relative from the root of your project). These values will be used to create custom actions on the Front Matter panel. Default value: `[]`.
|
||||
|
||||
```json
|
||||
{
|
||||
"frontMatter.custom.scripts": [{
|
||||
"title": "Generate social image",
|
||||
"script": "./scripts/social-img.js"
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
- Start by opening the command prompt:
|
||||
- Windows: ⇧+ctrl+P
|
||||
- Mac: ⇧+⌘+P
|
||||
- Use one of the commands from above
|
||||
|
||||
## Feedback / issues / ideas
|
||||
|
||||
Please submit them via creating an issue in the project repository: [issue list](https://github.com/estruyf/vscode-front-matter/issues).
|
||||
<p align="center">
|
||||
<a href="https://visitorbadge.io">
|
||||
<img src="https://estruyf-github.azurewebsites.net/api/VisitorHit?user=estruyf&repo=vscode-front-matter&countColor=%23F05450&labelColor=%230E131F" height="25px" />
|
||||
</a>
|
||||
</p>
|
||||
|
Before Width: | Height: | Size: 202 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 70 KiB |
2
assets/empty.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1" height="1">
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 68 B |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 27 KiB |
BIN
assets/frontmatter-beta.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
45
assets/frontmatter-beta.svg
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 28 28" style="enable-background:new 0 0 28 28;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFE45E;}
|
||||
.st1{fill:none;stroke:#FFE45E;stroke-width:2;stroke-miterlimit:10;}
|
||||
.st2{font-family:'MyriadPro-Bold';}
|
||||
.st3{font-size:8px;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M4.1,10.2H2.4V2.1h3.1V4H4.1v1.2h1.2V7H4.1V10.2z"/>
|
||||
<path class="st0" d="M10.7,10.2H8.9L8,7.3c0-0.1,0-0.1,0-0.2C7.9,7.1,7.9,7,7.8,6.8v0.6v2.9H6.1V2.1h1.8c0.8,0,1.3,0.2,1.8,0.6
|
||||
c0.5,0.5,0.8,1.2,0.8,2.1c0,1-0.4,1.6-1.1,2L10.7,10.2z M7.9,5.8L7.9,5.8c0.3,0,0.5-0.1,0.6-0.3S8.7,5,8.7,4.8c0-0.6-0.3-1-0.8-1
|
||||
l0,0V5.8z"/>
|
||||
<path class="st0" d="M16.1,6.2c0,1.2-0.2,2.3-0.7,3.1s-1.1,1.2-1.7,1.2s-1.2-0.3-1.6-0.9c-0.6-0.8-0.9-1.9-0.9-3.4
|
||||
s0.3-2.6,0.9-3.4C12.6,2.3,13,2,13.7,2c0.8,0,1.3,0.4,1.8,1.2C15.8,3.8,16.1,4.8,16.1,6.2z M14.3,6.2c0-1.4-0.2-2.2-0.7-2.2
|
||||
c-0.2,0-0.4,0.2-0.5,0.6c-0.1,0.4-0.2,0.9-0.2,1.6c0,0.7,0.1,1.2,0.2,1.6c0.1,0.4,0.3,0.6,0.5,0.6c0.2,0,0.4-0.2,0.5-0.6
|
||||
C14.2,7.3,14.3,6.9,14.3,6.2z"/>
|
||||
<path class="st0" d="M16.8,10.2V2.1h1.7l0.9,2.9c0.1,0.1,0.1,0.3,0.2,0.6c0.1,0.2,0.1,0.5,0.2,0.8L20,7c-0.1-0.7-0.1-1.3-0.2-1.8
|
||||
s-0.1-1-0.1-1.2V2.1h1.7v8.2h-1.6l-0.9-3c-0.1-0.3-0.2-0.6-0.3-0.9c-0.1-0.3-0.1-0.6-0.2-0.8c0,0.6,0.1,1.1,0.1,1.5
|
||||
c0,0.4,0,0.8,0,1.2v2.1h-1.7V10.2z"/>
|
||||
<path class="st0" d="M24.6,10.2h-1.7V4h-1V2.1h3.7V4h-1.1V10.2z"/>
|
||||
</g>
|
||||
</g>
|
||||
<rect class="st1" width="28" height="28"/>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M3.1,11.6H4l0.6,3c0.1,0.4,0.2,0.8,0.2,1.2C4.9,16.2,4.9,16.6,5,17c0-0.1,0-0.1,0-0.1v-0.1l0.2-0.9l0.1-0.8
|
||||
l0.1-0.5l0.6-3h0.9l0.7,7.5h-1l-0.2-2.6c0-0.1,0-0.2,0-0.3c0-0.1,0-0.2,0-0.2v-1v-0.9l0,0c0,0,0,0,0-0.1v0.2c0,0.2,0,0.3-0.1,0.5
|
||||
c-0.1,0.2,0,0.2-0.1,0.3L6,15.7V16l-0.6,3.3H4.7l-0.6-2.8c-0.1-0.4-0.2-0.8-0.2-1.1c-0.1-0.4-0.1-0.8-0.2-1.2l-0.3,5.2h-1
|
||||
L3.1,11.6z"/>
|
||||
<path class="st0" d="M9.4,11.6h0.8l1.6,7.5h-1l-0.3-1.5H9l-0.3,1.5h-1L9.4,11.6z M10.4,16.8l-0.3-1.2C10,14.8,9.8,13.9,9.7,13
|
||||
c0,0.5-0.1,0.9-0.2,1.4c-0.1,0.5-0.2,1-0.3,1.5l-0.2,1L10.4,16.8L10.4,16.8z"/>
|
||||
<path class="st0" d="M11.6,11.6h3.3v0.9h-1.1v6.7h-1v-6.7h-1.2V11.6z"/>
|
||||
<path class="st0" d="M14.9,11.6h3.3v0.9h-1.1v6.7h-1v-6.7h-1.2V11.6z"/>
|
||||
<path class="st0" d="M18.8,11.6h2.7v0.9h-1.7v2.4h1.5v0.9h-1.5v2.6h1.7v0.9h-2.7V11.6z"/>
|
||||
<path class="st0" d="M22.3,11.6h1.3c0.6,0,1,0.1,1.2,0.4c0.3,0.3,0.5,0.9,0.5,1.6c0,0.5-0.1,1-0.3,1.3c-0.2,0.3-0.4,0.5-0.8,0.6
|
||||
l1.4,3.7h-1l-1.4-3.7v3.7h-1L22.3,11.6L22.3,11.6z M23.3,14.9c0.4,0,0.7-0.1,0.8-0.3c0.2-0.2,0.2-0.5,0.2-0.9c0-0.2,0-0.4-0.1-0.6
|
||||
c-0.1-0.2-0.1-0.3-0.2-0.4c-0.1-0.1-0.2-0.2-0.3-0.2s-0.3-0.1-0.4-0.1h-0.2v2.5H23.3z"/>
|
||||
</g>
|
||||
</g>
|
||||
<text transform="matrix(1 0 0 1 5.4457 25.9479)" class="st0 st2 st3">BETA</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
1
assets/frontmatter-dark.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1249.98 1249.98"><rect x="25" y="25" width="1199.98" height="1199.98" style="fill:none;stroke:#ffffff;stroke-miterlimit:10;stroke-width:50px"/><path d="M171.89,489.56H95.38V127.21H230.6V212.4H171.89v52.8h54.68v81.91H171.89Z" transform="translate(24 24)" style="fill:#ffffff"/><path d="M461.79,489.56H379l-37.8-129.08c-.37-2.18-1-5.08-1.93-8.68s-2.05-7.9-3.39-12.91l.55,23.94V489.56H260.33V127.21h78.34q51.75,0,77.43,26.05,32.65,33.32,32.66,94.81,0,65.71-43.85,90.82ZM336.84,295H342q13.21,0,22-12.91t8.81-32.86q0-40.59-33.21-40.6h-2.75Z" transform="translate(24 24)" style="fill:#ffffff"/><path d="M691.68,309.56q0,82.85-29.54,134.71-29.35,51.63-76.51,51.63-41.82,0-71.74-39.66Q476.29,406,476.28,305.57q0-96.23,39.26-147.15,29.18-37.78,69.18-37.79,49,0,78,51.17T691.68,309.56Zm-79.44.7q0-98.32-27.16-98.33-13.58,0-21.65,25.81-7.89,23.94-7.89,70.41,0,45.77,7.43,71t20.65,25.23q13.57,0,20.91-24.88Q612.24,354.62,612.24,310.26Z" transform="translate(24 24)" style="fill:#ffffff"/><path d="M724.34,489.56V127.21h73l38.35,127.2q3.1,11.27,7.06,25.81t8.72,33.56l7.88,31.92Q855.17,298.52,853,265t-2.2-56.33V127.21h73V489.56h-73l-38.53-133.3q-6.06-21.35-10.92-40t-8.53-35.56q2.38,38.26,3.49,66.65t1.1,49.76v92.46Z" transform="translate(24 24)" style="fill:#ffffff"/><path d="M1062.31,489.56H985.8V214H943.6V127.21h162.56V214h-43.85Z" transform="translate(24 24)" style="fill:#ffffff"/><path d="M122.7,730.59h35.82l27.36,133.72q5,25.05,9.16,50.2t7.55,52.74q.39-3.6.6-5.62a25.33,25.33,0,0,1,.4-2.87l5.84-37.56,5.23-35.66L219.29,862l24.35-131.39h36.22l28.57,327.72h-40l-7-111.22q-.41-8.49-.71-14.64c-.2-4.11-.3-7.5-.3-10.19l-1.81-43.94-1-40.33c0-.28,0-.88-.1-1.8s-.17-2.16-.3-3.72l-1,6.58q-1.61,11.69-2.91,20.38t-2.32,14.65L245.65,904l-2,11.25-26.16,143.06H189.3L164.75,934.78q-5-24.4-8.95-49.56t-7.14-52.75l-12.08,225.84H97.14Z" transform="translate(24 24)" style="fill:#ffffff"/><path d="M395.56,730.59h32.6l66.6,327.72H453.31l-11.67-63.89H380.06l-11.87,63.89H327.94Zm40,229.66L426.35,908q-9.27-53.28-15.1-113.77Q408.43,823.78,404,854t-10.46,64.2l-7.65,42Z" transform="translate(24 24)" style="fill:#ffffff"/><path d="M496.17,730.59H632.4v38.63H585.51v289.09h-41V769.22H496.17Z" transform="translate(24 24)" style="fill:#ffffff"/><path d="M639,730.59H775.26v38.63H728.38v289.09h-41V769.22H639Z" transform="translate(24 24)" style="fill:#ffffff"/><path d="M806.65,730.59H917.93V768H848.5V871.74h61.58V909.1H848.5V1021h69.43v37.35H806.65Z" transform="translate(24 24)" style="fill:#ffffff"/><path d="M964.61,730.59h55.13q34.21,0,50.91,17.19,21.13,22.29,21.13,68.14,0,35.24-11.16,56.56t-31.9,26.43l57.15,159.4h-42.46l-57-160.46v160.46H964.61Zm41.85,145.18q24.35,0,34.41-11.88t10.06-40.12a138.46,138.46,0,0,0-2.11-26.11q-2.11-10.81-6.64-17.61a27.08,27.08,0,0,0-11.67-10,41.58,41.58,0,0,0-17-3.18h-7Z" transform="translate(24 24)" style="fill:#ffffff"/></svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 67 KiB |
17
assets/frontmatter-short-min.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1250 1250" style="enable-background:new 0 0 1250 1250;" xml:space="preserve">
|
||||
<path fill="#C5C5C5" d="M316,1082.3H119.4V151.2h347.5v218.9H316v135.7h140.5v210.5H316V1082.3z"/>
|
||||
<path fill="#C5C5C5" d="M602.2,151.2H704l77.7,379.9c9.5,47.4,18.1,95,26,142.6s15,97.6,21.4,149.8c0.7-6.8,1.3-12.1,1.7-16
|
||||
c0.2-2.7,0.6-5.5,1.1-8.2l16.6-106.7l14.9-101.3l13.2-66.9l69.2-373.3h102.9l81.2,931.1h-113.6l-19.9-316c-0.8-16.1-1.4-29.9-2-41.6
|
||||
c-0.6-11.7-0.9-21.3-0.9-29L988.3,571l-2.8-114.6c0-0.8,0-2.5-0.3-5.1s-0.5-6.1-0.9-10.6l-2.8,18.7c-3,22.1-5.8,41.4-8.3,57.9
|
||||
s-4.7,30.3-6.6,41.6l-15.1,84.9l-5.7,32l-74.3,406.4h-80.1l-69.7-351c-9.5-46.2-17.9-93.1-25.4-140.8s-14.2-97.6-20.3-149.9
|
||||
l-34.3,641.6H529.6L602.2,151.2z"/>
|
||||
<rect x="119.4" y="0.1" fill="#C5C5C5" width="184" height="64.7"/>
|
||||
<rect x="395.7" y="0.1" fill="#C5C5C5" width="184" height="64.7"/>
|
||||
<rect x="675.3" y="0.1" fill="#C5C5C5" width="184" height="64.7"/>
|
||||
<rect x="119.4" y="1184.7" fill="#C5C5C5" width="184" height="64.7"/>
|
||||
<rect x="395.7" y="1184.7" fill="#C5C5C5" width="184" height="64.7"/>
|
||||
<rect x="675.3" y="1184.7" fill="#C5C5C5" width="184" height="64.7"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/frontmatter-teal-128x128.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
@@ -1,39 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 28 28" style="enable-background:new 0 0 28 28;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{enable-background:new ;}
|
||||
.st1{fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:10;}
|
||||
.st2{fill:none;}
|
||||
</style>
|
||||
<g class="st0">
|
||||
<path d="M4,11.4H2.2V2.9h3.2v2H4v1.2h1.3V8H4V11.4z"/>
|
||||
<path d="M10.9,11.4H9l-0.9-3c0-0.1,0-0.1,0-0.2C8,8.1,8,8,7.9,7.8l0,0.6v3H6.1V2.9H8c0.8,0,1.4,0.2,1.9,0.6
|
||||
c0.5,0.5,0.8,1.3,0.8,2.2c0,1-0.4,1.7-1.1,2.1L10.9,11.4z M8,6.8h0.1c0.2,0,0.4-0.1,0.5-0.3C8.7,6.3,8.8,6,8.8,5.7
|
||||
c0-0.6-0.3-1-0.8-1H8V6.8z"/>
|
||||
<path d="M16.5,7.2c0,1.3-0.2,2.4-0.7,3.2c-0.5,0.8-1.1,1.2-1.8,1.2c-0.7,0-1.2-0.3-1.7-0.9c-0.6-0.8-0.9-2-0.9-3.5
|
||||
c0-1.5,0.3-2.7,0.9-3.5c0.5-0.6,1-0.9,1.7-0.9c0.8,0,1.4,0.4,1.9,1.2C16.2,4.7,16.5,5.8,16.5,7.2z M14.6,7.2c0-1.5-0.2-2.3-0.7-2.3
|
||||
c-0.2,0-0.4,0.2-0.5,0.6c-0.1,0.4-0.2,0.9-0.2,1.7c0,0.7,0.1,1.3,0.2,1.7c0.1,0.4,0.3,0.6,0.5,0.6c0.2,0,0.4-0.2,0.5-0.6
|
||||
C14.5,8.4,14.6,7.9,14.6,7.2z"/>
|
||||
<path d="M17.2,11.4V2.9H19l0.9,3C20,6,20,6.2,20.1,6.5c0.1,0.2,0.1,0.5,0.2,0.8L20.5,8c-0.1-0.7-0.1-1.4-0.2-1.9s-0.1-1-0.1-1.3
|
||||
V2.9H22v8.5h-1.7l-0.9-3.1c-0.1-0.3-0.2-0.6-0.3-0.9s-0.1-0.6-0.2-0.8c0,0.6,0.1,1.1,0.1,1.6c0,0.4,0,0.8,0,1.2v2.2H17.2z"/>
|
||||
<path d="M25.3,11.4h-1.8V4.9h-1v-2h3.9v2h-1.1V11.4z"/>
|
||||
</g>
|
||||
<rect class="st1" width="28" height="28"/>
|
||||
<g class="st0">
|
||||
<path d="M2.9,17h0.9L4.4,20c0.1,0.4,0.2,0.8,0.2,1.2c0.1,0.4,0.1,0.8,0.2,1.2c0-0.1,0-0.1,0-0.1c0,0,0-0.1,0-0.1L5,21.3l0.1-0.8
|
||||
L5.2,20l0.6-3h0.9l0.7,7.5h-1l-0.2-2.6c0-0.1,0-0.2,0-0.3s0-0.2,0-0.2l0-1l0-0.9c0,0,0,0,0,0c0,0,0,0,0-0.1l0,0.2
|
||||
c0,0.2,0,0.3-0.1,0.5s0,0.2-0.1,0.3l-0.1,0.7l0,0.3l-0.6,3.3H4.5l-0.6-2.8c-0.1-0.4-0.2-0.8-0.2-1.1c-0.1-0.4-0.1-0.8-0.2-1.2
|
||||
l-0.3,5.2h-1L2.9,17z"/>
|
||||
<path d="M9.3,17h0.8l1.6,7.5h-1L10.4,23H8.9l-0.3,1.5h-1L9.3,17z M10.3,22.2L10,21c-0.1-0.8-0.3-1.7-0.4-2.6c0,0.5-0.1,0.9-0.2,1.4
|
||||
c-0.1,0.5-0.2,1-0.3,1.5l-0.2,1H10.3z"/>
|
||||
<path d="M11.5,17h3.3v0.9h-1.1v6.7h-1v-6.7h-1.2V17z"/>
|
||||
<path d="M14.8,17h3.3v0.9H17v6.7h-1v-6.7h-1.2V17z"/>
|
||||
<path d="M18.7,17h2.7v0.9h-1.7v2.4h1.5v0.9h-1.5v2.6h1.7v0.9h-2.7V17z"/>
|
||||
<path d="M22.3,17h1.3c0.6,0,1,0.1,1.2,0.4c0.3,0.3,0.5,0.9,0.5,1.6c0,0.5-0.1,1-0.3,1.3c-0.2,0.3-0.4,0.5-0.8,0.6l1.4,3.7h-1
|
||||
l-1.4-3.7v3.7h-1V17z M23.3,20.3c0.4,0,0.7-0.1,0.8-0.3c0.2-0.2,0.2-0.5,0.2-0.9c0-0.2,0-0.4-0.1-0.6s-0.1-0.3-0.2-0.4
|
||||
s-0.2-0.2-0.3-0.2c-0.1,0-0.3-0.1-0.4-0.1h-0.2V20.3z"/>
|
||||
</g>
|
||||
<rect x="-33.5" y="14" class="st2" width="8.6" height="14"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
9
assets/icons/blockquote-dark.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M6 15h15" />
|
||||
<path d="M21 19h-15" />
|
||||
<path d="M15 11h6" />
|
||||
<path d="M21 7h-6" />
|
||||
<path d="M9 9h1a1 1 0 1 1 -1 1v-2.5a2 2 0 0 1 2 -2" />
|
||||
<path d="M3 9h1a1 1 0 1 1 -1 1v-2.5a2 2 0 0 1 2 -2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 449 B |
9
assets/icons/blockquote-light.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M6 15h15" />
|
||||
<path d="M21 19h-15" />
|
||||
<path d="M15 11h6" />
|
||||
<path d="M21 7h-6" />
|
||||
<path d="M9 9h1a1 1 0 1 1 -1 1v-2.5a2 2 0 0 1 2 -2" />
|
||||
<path d="M3 9h1a1 1 0 1 1 -1 1v-2.5a2 2 0 0 1 2 -2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 449 B |
5
assets/icons/bold-dark.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M7 5h6a3.5 3.5 0 0 1 0 7h-6z" />
|
||||
<path d="M13 12h1a3.5 3.5 0 0 1 0 7h-7v-7" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 329 B |
5
assets/icons/bold-light.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M7 5h6a3.5 3.5 0 0 1 0 7h-6z" />
|
||||
<path d="M13 12h1a3.5 3.5 0 0 1 0 7h-7v-7" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 329 B |
4
assets/icons/close-dark.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="32px" height="32px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#C5C5C5">
|
||||
<path d="M9 9H4v1h5V9z" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 3l1-1h7l1 1v7l-1 1h-2v2l-1 1H3l-1-1V6l1-1h2V3zm1 2h4l1 1v4h2V3H6v2zm4 1H3v7h7V6z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 277 B |
4
assets/icons/close-light.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="32px" height="32px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#424242">
|
||||
<path d="M9 9H4v1h5V9z" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 3l1-1h7l1 1v7l-1 1h-2v2l-1 1H3l-1-1V6l1-1h2V3zm1 2h4l1 1v4h2V3H6v2zm4 1H3v7h7V6z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 277 B |
6
assets/icons/code-dark.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<polyline points="7 8 3 12 7 16" />
|
||||
<polyline points="17 8 21 12 17 16" />
|
||||
<line x1="14" y1="4" x2="10" y2="20" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 358 B |
6
assets/icons/code-light.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<polyline points="7 8 3 12 7 16" />
|
||||
<polyline points="17 8 21 12 17 16" />
|
||||
<line x1="14" y1="4" x2="10" y2="20" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 358 B |
7
assets/icons/codeblock-dark.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M9 12h6" />
|
||||
<path d="M12 9v6" />
|
||||
<path d="M6 19a2 2 0 0 1 -2 -2v-4l-1 -1l1 -1v-4a2 2 0 0 1 2 -2" />
|
||||
<path d="M18 19a2 2 0 0 0 2 -2v-4l1 -1l-1 -1v-4a2 2 0 0 0 -2 -2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 422 B |
7
assets/icons/codeblock-light.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M9 12h6" />
|
||||
<path d="M12 9v6" />
|
||||
<path d="M6 19a2 2 0 0 1 -2 -2v-4l-1 -1l1 -1v-4a2 2 0 0 1 2 -2" />
|
||||
<path d="M18 19a2 2 0 0 0 2 -2v-4l1 -1l-1 -1v-4a2 2 0 0 0 -2 -2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 422 B |
17
assets/icons/frontmatter-short-dark.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1250 1250" style="enable-background:new 0 0 1250 1250;" xml:space="preserve">
|
||||
<path fill="#C5C5C5" d="M316,1082.3H119.4V151.2h347.5v218.9H316v135.7h140.5v210.5H316V1082.3z"/>
|
||||
<path fill="#C5C5C5" d="M602.2,151.2H704l77.7,379.9c9.5,47.4,18.1,95,26,142.6s15,97.6,21.4,149.8c0.7-6.8,1.3-12.1,1.7-16
|
||||
c0.2-2.7,0.6-5.5,1.1-8.2l16.6-106.7l14.9-101.3l13.2-66.9l69.2-373.3h102.9l81.2,931.1h-113.6l-19.9-316c-0.8-16.1-1.4-29.9-2-41.6
|
||||
c-0.6-11.7-0.9-21.3-0.9-29L988.3,571l-2.8-114.6c0-0.8,0-2.5-0.3-5.1s-0.5-6.1-0.9-10.6l-2.8,18.7c-3,22.1-5.8,41.4-8.3,57.9
|
||||
s-4.7,30.3-6.6,41.6l-15.1,84.9l-5.7,32l-74.3,406.4h-80.1l-69.7-351c-9.5-46.2-17.9-93.1-25.4-140.8s-14.2-97.6-20.3-149.9
|
||||
l-34.3,641.6H529.6L602.2,151.2z"/>
|
||||
<rect x="119.4" y="0.1" fill="#C5C5C5" width="184" height="64.7"/>
|
||||
<rect x="395.7" y="0.1" fill="#C5C5C5" width="184" height="64.7"/>
|
||||
<rect x="675.3" y="0.1" fill="#C5C5C5" width="184" height="64.7"/>
|
||||
<rect x="119.4" y="1184.7" fill="#C5C5C5" width="184" height="64.7"/>
|
||||
<rect x="395.7" y="1184.7" fill="#C5C5C5" width="184" height="64.7"/>
|
||||
<rect x="675.3" y="1184.7" fill="#C5C5C5" width="184" height="64.7"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
17
assets/icons/frontmatter-short-light.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1250 1250" style="enable-background:new 0 0 1250 1250;" xml:space="preserve">
|
||||
<path fill="#424242" d="M316,1082.3H119.4V151.2h347.5v218.9H316v135.7h140.5v210.5H316V1082.3z"/>
|
||||
<path fill="#424242" d="M602.2,151.2H704l77.7,379.9c9.5,47.4,18.1,95,26,142.6s15,97.6,21.4,149.8c0.7-6.8,1.3-12.1,1.7-16
|
||||
c0.2-2.7,0.6-5.5,1.1-8.2l16.6-106.7l14.9-101.3l13.2-66.9l69.2-373.3h102.9l81.2,931.1h-113.6l-19.9-316c-0.8-16.1-1.4-29.9-2-41.6
|
||||
c-0.6-11.7-0.9-21.3-0.9-29L988.3,571l-2.8-114.6c0-0.8,0-2.5-0.3-5.1s-0.5-6.1-0.9-10.6l-2.8,18.7c-3,22.1-5.8,41.4-8.3,57.9
|
||||
s-4.7,30.3-6.6,41.6l-15.1,84.9l-5.7,32l-74.3,406.4h-80.1l-69.7-351c-9.5-46.2-17.9-93.1-25.4-140.8s-14.2-97.6-20.3-149.9
|
||||
l-34.3,641.6H529.6L602.2,151.2z"/>
|
||||
<rect x="119.4" y="0.1" fill="#424242" width="184" height="64.7"/>
|
||||
<rect x="395.7" y="0.1" fill="#424242" width="184" height="64.7"/>
|
||||
<rect x="675.3" y="0.1" fill="#424242" width="184" height="64.7"/>
|
||||
<rect x="119.4" y="1184.7" fill="#424242" width="184" height="64.7"/>
|
||||
<rect x="395.7" y="1184.7" fill="#424242" width="184" height="64.7"/>
|
||||
<rect x="675.3" y="1184.7" fill="#424242" width="184" height="64.7"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
11
assets/icons/frontmatter-small-dark.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1250 1250" style="enable-background:new 0 0 1250 1250;" xml:space="preserve" width="16" height="16">
|
||||
<path fill="#C5C5C5" d="M316,1082.3H119.4V151.2h347.5v218.9H316v135.7h140.5v210.5H316V1082.3z"/>
|
||||
<path fill="#C5C5C5" d="M602.2,151.2H704l77.7,379.9c9.5,47.4,18.1,95,26,142.6c7.9,47.6,15,97.6,21.4,149.8c0.7-6.8,1.3-12.1,1.7-16
|
||||
c0.2-2.7,0.6-5.5,1.1-8.2l16.6-106.7l14.9-101.3l13.2-66.9l69.2-373.3h102.9l81.2,931.1h-113.6l-19.9-316c-0.8-16.1-1.4-29.9-2-41.6
|
||||
c-0.6-11.7-0.9-21.3-0.9-29L988.3,571l-2.8-114.6c0-0.8,0-2.5-0.3-5.1s-0.5-6.1-0.9-10.6l-2.8,18.7c-3,22.1-5.8,41.4-8.3,57.9
|
||||
c-2.5,16.5-4.7,30.3-6.6,41.6l-15.1,84.9l-5.7,32l-74.3,406.4h-80.1l-69.7-351c-9.5-46.2-17.9-93.1-25.4-140.8
|
||||
c-7.5-47.7-14.2-97.6-20.3-149.9l-34.3,641.6H529.6L602.2,151.2z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
11
assets/icons/frontmatter-small-light.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1250 1250" style="enable-background:new 0 0 1250 1250;" xml:space="preserve" width="16" height="16">
|
||||
<path fill="#424242" d="M316,1082.3H119.4V151.2h347.5v218.9H316v135.7h140.5v210.5H316V1082.3z"/>
|
||||
<path fill="#424242" d="M602.2,151.2H704l77.7,379.9c9.5,47.4,18.1,95,26,142.6c7.9,47.6,15,97.6,21.4,149.8c0.7-6.8,1.3-12.1,1.7-16
|
||||
c0.2-2.7,0.6-5.5,1.1-8.2l16.6-106.7l14.9-101.3l13.2-66.9l69.2-373.3h102.9l81.2,931.1h-113.6l-19.9-316c-0.8-16.1-1.4-29.9-2-41.6
|
||||
c-0.6-11.7-0.9-21.3-0.9-29L988.3,571l-2.8-114.6c0-0.8,0-2.5-0.3-5.1s-0.5-6.1-0.9-10.6l-2.8,18.7c-3,22.1-5.8,41.4-8.3,57.9
|
||||
c-2.5,16.5-4.7,30.3-6.6,41.6l-15.1,84.9l-5.7,32l-74.3,406.4h-80.1l-69.7-351c-9.5-46.2-17.9-93.1-25.4-140.8
|
||||
c-7.5-47.7-14.2-97.6-20.3-149.9l-34.3,641.6H529.6L602.2,151.2z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
11
assets/icons/frontmatter-small-teal.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1250 1250" style="enable-background:new 0 0 1250 1250;" xml:space="preserve" width="16" height="16">
|
||||
<path fill="#02aeb7" d="M316,1082.3H119.4V151.2h347.5v218.9H316v135.7h140.5v210.5H316V1082.3z"/>
|
||||
<path fill="#02aeb7" d="M602.2,151.2H704l77.7,379.9c9.5,47.4,18.1,95,26,142.6c7.9,47.6,15,97.6,21.4,149.8c0.7-6.8,1.3-12.1,1.7-16
|
||||
c0.2-2.7,0.6-5.5,1.1-8.2l16.6-106.7l14.9-101.3l13.2-66.9l69.2-373.3h102.9l81.2,931.1h-113.6l-19.9-316c-0.8-16.1-1.4-29.9-2-41.6
|
||||
c-0.6-11.7-0.9-21.3-0.9-29L988.3,571l-2.8-114.6c0-0.8,0-2.5-0.3-5.1s-0.5-6.1-0.9-10.6l-2.8,18.7c-3,22.1-5.8,41.4-8.3,57.9
|
||||
c-2.5,16.5-4.7,30.3-6.6,41.6l-15.1,84.9l-5.7,32l-74.3,406.4h-80.1l-69.7-351c-9.5-46.2-17.9-93.1-25.4-140.8
|
||||
c-7.5-47.7-14.2-97.6-20.3-149.9l-34.3,641.6H529.6L602.2,151.2z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
10
assets/icons/heading-dark.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M7 12h10" />
|
||||
<path d="M7 4v16" />
|
||||
<path d="M17 4v16" />
|
||||
<path d="M15 20h4" />
|
||||
<path d="M15 4h4" />
|
||||
<path d="M5 20h4" />
|
||||
<path d="M5 4h4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 400 B |
10
assets/icons/heading-light.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M7 12h10" />
|
||||
<path d="M7 4v16" />
|
||||
<path d="M17 4v16" />
|
||||
<path d="M15 20h4" />
|
||||
<path d="M15 4h4" />
|
||||
<path d="M5 20h4" />
|
||||
<path d="M5 4h4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 400 B |
6
assets/icons/italic-dark.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<line x1="11" y1="5" x2="17" y2="5" />
|
||||
<line x1="7" y1="19" x2="13" y2="19" />
|
||||
<line x1="14" y1="5" x2="10" y2="19" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 362 B |
6
assets/icons/italic-light.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<line x1="11" y1="5" x2="17" y2="5" />
|
||||
<line x1="7" y1="19" x2="13" y2="19" />
|
||||
<line x1="14" y1="5" x2="10" y2="19" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 362 B |
3
assets/icons/media-dark.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="#C5C5C5" width="24" height="24">
|
||||
<path fillRule="evenodd" d="M4 3a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V5a2 2 0 00-2-2H4zm12 12H4l4-8 3 6 2-4 3 6z" clipRule="evenodd" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 269 B |
3
assets/icons/media-light.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="#424242" width="24" height="24">
|
||||
<path fillRule="evenodd" d="M4 3a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V5a2 2 0 00-2-2H4zm12 12H4l4-8 3 6 2-4 3 6z" clipRule="evenodd" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 269 B |
7
assets/icons/options-dark.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<circle cx="12" cy="12" r="9" />
|
||||
<line x1="8" y1="12" x2="8" y2="12.01" />
|
||||
<line x1="12" y1="12" x2="12" y2="12.01" />
|
||||
<line x1="16" y1="12" x2="16" y2="12.01" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 408 B |
7
assets/icons/options-light.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<circle cx="12" cy="12" r="9" />
|
||||
<line x1="8" y1="12" x2="8" y2="12.01" />
|
||||
<line x1="12" y1="12" x2="12" y2="12.01" />
|
||||
<line x1="16" y1="12" x2="16" y2="12.01" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 408 B |
8
assets/icons/ordered-list-dark.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-list-numbers" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M11 6h9" />
|
||||
<path d="M11 12h9" />
|
||||
<path d="M12 18h8" />
|
||||
<path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4" />
|
||||
<path d="M6 10v-6l-2 2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 451 B |
8
assets/icons/ordered-list-light.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-list-numbers" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M11 6h9" />
|
||||
<path d="M11 12h9" />
|
||||
<path d="M12 18h8" />
|
||||
<path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4" />
|
||||
<path d="M6 10v-6l-2 2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 451 B |
3
assets/icons/scissors-dark.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="#C5C5C5" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M14.121 14.121L19 19m-7-7l7-7m-7 7l-2.879 2.879M12 12L9.121 9.121m0 5.758a3 3 0 10-4.243 4.243 3 3 0 004.243-4.243zm0-5.758a3 3 0 10-4.243-4.243 3 3 0 004.243 4.243z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 357 B |
3
assets/icons/scissors-light.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="#424242" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M14.121 14.121L19 19m-7-7l7-7m-7 7l-2.879 2.879M12 12L9.121 9.121m0 5.758a3 3 0 10-4.243 4.243 3 3 0 004.243-4.243zm0-5.758a3 3 0 10-4.243-4.243 3 3 0 004.243 4.243z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 357 B |
5
assets/icons/strikethrough-dark.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M7 5v9a5 5 0 0 0 10 0v-9" />
|
||||
<path d="M4 12h16" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 301 B |
5
assets/icons/strikethrough-light.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M7 5v9a5 5 0 0 0 10 0v-9" />
|
||||
<path d="M4 12h16" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 301 B |
9
assets/icons/unordered-list-dark.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-list" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<line x1="9" y1="6" x2="20" y2="6" />
|
||||
<line x1="9" y1="12" x2="20" y2="12" />
|
||||
<line x1="9" y1="18" x2="20" y2="18" />
|
||||
<line x1="5" y1="6" x2="5" y2="6.01" />
|
||||
<line x1="5" y1="12" x2="5" y2="12.01" />
|
||||
<line x1="5" y1="18" x2="5" y2="18.01" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 533 B |
9
assets/icons/unordered-list-light.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-list" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<line x1="9" y1="6" x2="20" y2="6" />
|
||||
<line x1="9" y1="12" x2="20" y2="12" />
|
||||
<line x1="9" y1="18" x2="20" y2="18" />
|
||||
<line x1="5" y1="6" x2="5" y2="6.01" />
|
||||
<line x1="5" y1="12" x2="5" y2="12.01" />
|
||||
<line x1="5" y1="18" x2="5" y2="18.01" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 533 B |
|
Before Width: | Height: | Size: 232 KiB |
@@ -21,6 +21,44 @@
|
||||
}
|
||||
}
|
||||
|
||||
.relative {
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.absolute {
|
||||
position: absolute !important;
|
||||
}
|
||||
|
||||
.inherit {
|
||||
position: inherit !important;
|
||||
}
|
||||
|
||||
.z-10 { z-index: 10 !important; }
|
||||
.z-20 { z-index: 10 !important; }
|
||||
|
||||
.w-full {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.collapsible__body,
|
||||
.ext_settings {
|
||||
padding: 1rem 1.25rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#app, .frontmatter {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.frontmatter.media_selection {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
opacity: 0.8;
|
||||
text-align: center;
|
||||
padding: 1rem 1.25rem;
|
||||
}
|
||||
|
||||
.spinner,
|
||||
.spinner:before,
|
||||
.spinner:after {
|
||||
@@ -58,6 +96,13 @@
|
||||
left: 3.5em;
|
||||
}
|
||||
|
||||
.frontmatter {
|
||||
padding-top: 0;
|
||||
padding-bottom: var(--input-margin-vertical);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.frontmatter h3 {
|
||||
margin-bottom: 1rem;
|
||||
@@ -69,28 +114,42 @@
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
.seo__status__details {
|
||||
margin-bottom: 2rem;
|
||||
.article__tags h3,
|
||||
.seo__status h3 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.section {
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.section h3 svg {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.seo__status__details, .seo__status__keywords {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.collapsible__body h4 {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.not-valid {
|
||||
color: var(--vscode-errorForeground);
|
||||
}
|
||||
|
||||
.article__actions {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.article__action {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.article__tags {
|
||||
/* position: relative; */
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.article__tags__dropbox {
|
||||
width: 90%;
|
||||
/* Minus the twice the padding */
|
||||
width: calc(100% - 2.5rem);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
z-index: 1;
|
||||
@@ -108,19 +167,30 @@
|
||||
border: 1px solid var(--vscode-inputValidation-infoBorder);
|
||||
}
|
||||
|
||||
.article__tags__input input:disabled {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.article__tags__input.freeform {
|
||||
position: relative;
|
||||
outline: 1px solid var(--vscode-inputValidation-infoBorder);
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
.article__tags__input.freeform input {
|
||||
padding-right: 35px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.article__tags__input button {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 30px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.article__tags ul {
|
||||
@@ -151,66 +221,530 @@
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.article__tags__items__item {
|
||||
display: inline-block;
|
||||
margin-bottom: .5rem;
|
||||
margin-right: .5rem;
|
||||
.article__actions > * + *,
|
||||
.other_actions > * + *,
|
||||
.base__actions > * + *,
|
||||
.base__information > * + * {
|
||||
--tw-space-y-reverse: 0;
|
||||
margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
|
||||
margin-bottom: calc(1rem * var(--tw-space-y-reverse));
|
||||
}
|
||||
|
||||
.article__tags__items__item_add,
|
||||
.article__tags__items__item_delete {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
.base__action label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.article__tags__items__item svg {
|
||||
display: inline;
|
||||
vertical-align: bottom;
|
||||
.base__action input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.article__tags__items__item_delete span {
|
||||
margin-left: .5rem;
|
||||
}
|
||||
|
||||
.article__tags__items__pill_notexists {
|
||||
color: var(--vscode-inputValidation-errorForeground);
|
||||
background-color: var(--vscode-inputValidation-errorBackground);
|
||||
padding-left: .5rem;
|
||||
}
|
||||
|
||||
.article__tags__items__pill_notexists:hover {
|
||||
color: var(--vscode-inputValidation-errorForeground);
|
||||
background-color: var(--vscode-inputValidation-errorBackground);
|
||||
|
||||
filter: contrast(60%);
|
||||
}
|
||||
|
||||
.article__tags__items__item_add {
|
||||
color: var(--vscode-inputValidation-infoForeground);
|
||||
background-color: var(--vscode-inputValidation-infoBackground);
|
||||
border-right: 1px solid var(--vscode-inputValidation-infoBorder);
|
||||
}
|
||||
|
||||
.article__tags__items__item_add:hover {
|
||||
color: var(--vscode-inputValidation-infoForeground);
|
||||
background-color: var(--vscode-inputValidation-infoBackground);
|
||||
border-right: 1px solid var(--vscode-inputValidation-infoBorder);
|
||||
|
||||
filter: contrast(60%);
|
||||
.seo__status__details ul > * + *,
|
||||
.ext_settings > * + * {
|
||||
--tw-space-y-reverse: 0;
|
||||
margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
|
||||
margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
|
||||
}
|
||||
|
||||
.ext_link_block {
|
||||
margin-bottom: .5rem;
|
||||
text-align: right;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ext_link_block svg {
|
||||
margin-right: .5rem;
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
min-width: 16px;
|
||||
}
|
||||
|
||||
.ext_link_block button span {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ext_link_block button,
|
||||
.ext_link_block a {
|
||||
color: var(--vscode-textLink-foreground);
|
||||
align-items: center;
|
||||
color: var(--vscode-button-secondaryForeground);
|
||||
background-color: var(--vscode-button-secondaryBackground);
|
||||
border: 0px;
|
||||
border-radius: 0px;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
font-size: var(--vscode-font-size);
|
||||
font-weight: var(--vscode-font-weight);
|
||||
line-height: 26px;
|
||||
padding: 0px 14px;
|
||||
user-select: none;
|
||||
text-decoration: none;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ext_link_block button.active {
|
||||
color: var(--vscode-button-foreground);
|
||||
background: var(--vscode-button-background);
|
||||
}
|
||||
.ext_link_block button.active:hover {
|
||||
cursor: pointer;
|
||||
background: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
.ext_link_block a:hover,
|
||||
.ext_link_block a:active,
|
||||
.ext_link_block a:focus,
|
||||
.ext_link_block a:visited {
|
||||
color: var(--vscode-textLink-activeForeground);
|
||||
color: var(--vscode-button-secondaryForeground);
|
||||
}
|
||||
|
||||
.ext_link_block a:hover,
|
||||
.ext_link_block button:hover {
|
||||
background-color: var(--vscode-button-secondaryHoverBackground);
|
||||
}
|
||||
|
||||
.table__cell {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.table__title {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.table__cell__seo_details {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.table__cell__validation {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.table__cell__validation div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
.table__cell__validation .valid {
|
||||
color: #46EC86;
|
||||
}
|
||||
|
||||
.table__cell__validation .warning {
|
||||
color: #E6AF2E;
|
||||
}
|
||||
|
||||
.table__cell__validation div span + span {
|
||||
margin-left: .5rem;
|
||||
}
|
||||
|
||||
.seo__status__note {
|
||||
font-size: 10px;
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
/* Fields */
|
||||
.field__toggle {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.field__toggle input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.field__toggle__slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: var(--vscode-button-secondaryBackground);
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
border-radius: 34px;
|
||||
}
|
||||
|
||||
.field__toggle__slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
background-color: white;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
input:checked + .field__toggle__slider {
|
||||
background-color: var(--vscode-button-background);
|
||||
}
|
||||
|
||||
input:focus + .field__toggle__slider {
|
||||
box-shadow: 0 0 1px var(--vscode-button-background);
|
||||
}
|
||||
|
||||
input:checked + .field__toggle__slider:before {
|
||||
-webkit-transform: translateX(26px);
|
||||
-ms-transform: translateX(26px);
|
||||
transform: translateX(26px);
|
||||
}
|
||||
|
||||
/* Metadata */
|
||||
.metadata_field {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.vscode-dark .metadata_field__box {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border: 1px dashed rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.vscode-light .metadata_field__box {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
border: 1px dashed rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.metadata_field__box {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border: 1px dashed rgba(255, 255, 255, 0.2);
|
||||
margin-bottom: .5rem;
|
||||
padding: .5rem 1rem;
|
||||
}
|
||||
|
||||
.metadata_field__label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
.metadata_field__label.metadata_field__label_parent {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.metadata_field__label svg {
|
||||
margin-right: .5rem;
|
||||
}
|
||||
|
||||
.metadata_field__error {
|
||||
color: var(--vscode-errorForeground);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.metadata_field__error button {
|
||||
color: var(--vscode-button-secondaryForeground);
|
||||
background-color: var(--vscode-button-secondaryBackground);
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.metadata_field__error button:hover {
|
||||
background-color: var(--vscode-button-secondaryHoverBackground);
|
||||
}
|
||||
|
||||
.metadata_field__input, .metadata_field__input:focus,
|
||||
.metadata_field__textarea, .metadata_field__textarea:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.metadata_field__limit {
|
||||
color: var(--vscode-inputValidation-warningBorder);
|
||||
margin-top: .25rem;
|
||||
}
|
||||
|
||||
.metadata_field__number {
|
||||
border: 1px solid var(--vscode-inputValidation-infoBorder) !important;
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.metadata_field__choice__toggle {
|
||||
color: var(--vscode-input-placeholderForeground);
|
||||
border: 1px solid var(--vscode-inputValidation-infoBorder) !important;
|
||||
outline: none !important;
|
||||
width: 100%;
|
||||
padding: var(--input-padding-vertical) var(--input-padding-horizontal);
|
||||
background-color: var(--vscode-input-background);
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.metadata_field__choice__toggle:hover,
|
||||
.metadata_field__choice__toggle:focus,
|
||||
.metadata_field__choice__toggle:active,
|
||||
.metadata_field__choice__toggle:disabled {
|
||||
background-color: var(--vscode-input-background);
|
||||
}
|
||||
|
||||
.metadata_field__choice__toggle span {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.metadata_field__choice__toggle svg.icon {
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
margin-left: .25rem;
|
||||
|
||||
position: absolute;
|
||||
right: .25rem;
|
||||
}
|
||||
|
||||
.metadata_field__choice_list {
|
||||
width: 90%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
list-style: none;
|
||||
overflow: auto;
|
||||
max-height: 200px;
|
||||
|
||||
color: var(--vscode-dropdown-foreground);
|
||||
background-color: var(--vscode-dropdown-background);
|
||||
}
|
||||
|
||||
.metadata_field__choice_list.open {
|
||||
border: 1px solid rgba(0, 0, 0, .9);
|
||||
}
|
||||
|
||||
.metadata_field__choice_list li {
|
||||
padding: var(--input-padding-vertical) var(--input-padding-horizontal);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.metadata_field__choice_list li:active {
|
||||
color: var(--vscode-button-foreground);
|
||||
background-color: var(--vscode-button-background);
|
||||
}
|
||||
|
||||
.metadata_field__choice_list li[aria-selected="true"] {
|
||||
color: var(--vscode-button-foreground);
|
||||
background-color: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
.metadata_field__choice_list li[aria-disabled="true"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.metadata_field__choice_list__item {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.metadata_field__choice__button {
|
||||
margin-top: .5rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
width: auto;
|
||||
margin-right: .5rem;
|
||||
}
|
||||
|
||||
.metadata_field__choice__button_icon {
|
||||
height: 1.25rem;
|
||||
width: 1.25rem;
|
||||
margin-left: .5rem;
|
||||
}
|
||||
|
||||
.metadata_field__datetime {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.metadata_field__datetime > .react-datepicker-wrapper {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.metadata_field__datetime > button {
|
||||
color: var(--vscode-button-secondaryForeground);
|
||||
background-color: var(--vscode-button-secondaryBackground);
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.metadata_field__datetime > button:hover {
|
||||
background-color: var(--vscode-button-secondaryHoverBackground);
|
||||
}
|
||||
|
||||
.metadata_field__multiple_images {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.metadata_field__preview_image img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-height: 16rem;
|
||||
}
|
||||
|
||||
.metadata_field__file__button,
|
||||
.metadata_field__preview_image__button {
|
||||
background-color: transparent;
|
||||
border: 1px dashed var(--vscode-button-background);
|
||||
padding: 1.5rem;
|
||||
filter: brightness(85%);
|
||||
}
|
||||
|
||||
.metadata_field__file__button:hover,
|
||||
.metadata_field__preview_image__button:hover {
|
||||
background-color: rgba(255, 255, 255, .1);
|
||||
filter: brightness(100%);
|
||||
}
|
||||
|
||||
.metadata_field__file__button svg,
|
||||
.metadata_field__preview_image__button svg {
|
||||
color: var(--vscode-foreground);
|
||||
display: block;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.metadata_field__file__button span,
|
||||
.metadata_field__preview_image__button span {
|
||||
color: var(--vscode-foreground);
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
margin-top: .5rem;
|
||||
}
|
||||
|
||||
.vscode-light .metadata_field__preview_image__preview {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.vscode-dark .metadata_field__preview_image__preview {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.metadata_field__preview_image__preview {
|
||||
background-color: var(--vscode-button-secondaryBackground);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.metadata_field__preview_image__remove {
|
||||
background-color: var(--vscode-inputValidation-errorBackground);
|
||||
color: var(--vscode-inputValidation-errorForeground);
|
||||
}
|
||||
|
||||
.metadata_field__preview_image__remove:hover {
|
||||
background-color: var(--vscode-inputValidation-errorBackground);
|
||||
color: var(--vscode-inputValidation-errorForeground);
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
/* File list */
|
||||
.file_list vscode-label {
|
||||
border-bottom: 1px solid var(--vscode-foreground);
|
||||
}
|
||||
|
||||
.file_list__items {
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.file_list__items__item {
|
||||
color: var(--vscode-foreground);
|
||||
font-size: var(--vscode-font-size);
|
||||
font-weight: var(--vscode-font-weight);
|
||||
cursor: pointer;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
margin: 0 -1rem;
|
||||
padding: 0 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.file_list__items__item:hover {
|
||||
background-color: var(--vscode-list-hoverBackground);
|
||||
color: var(--vscode-list-hoverForeground);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.file_list__items__item svg {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-right: .25rem;
|
||||
}
|
||||
|
||||
.file_list__items__item span {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* Sponsor */
|
||||
.sponsor {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.sponsor:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.sponsor:hover svg {
|
||||
fill: currentcolor;
|
||||
}
|
||||
|
||||
.sponsor svg {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-right: .25rem;
|
||||
}
|
||||
|
||||
.sponsor a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--vscode-foreground);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sponsor a:hover {
|
||||
color: var(--vscode-foreground);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sponsor a > span {
|
||||
margin-right: .25rem;
|
||||
}
|
||||
|
||||
/* Timepicker */
|
||||
.react-datepicker button {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.react-datepicker button:hover {
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
.react-datepicker__triangle {
|
||||
transform: translate3d(15px, 0px, 0px) !important;
|
||||
}
|
||||
|
||||
.react-datepicker-time__input {
|
||||
background: transparent !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
|
||||
.react-datepicker-time__input input {
|
||||
border: 1px solid #aeaeae !important;
|
||||
}
|
||||
@@ -1,29 +1,26 @@
|
||||
:root {
|
||||
--container-paddding: 20px;
|
||||
--container-padding: 20px;
|
||||
--input-padding-vertical: 6px;
|
||||
--input-padding-horizontal: 4px;
|
||||
--input-margin-vertical: 4px;
|
||||
--input-margin-horizontal: 0;
|
||||
}
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 0 var(--container-paddding);
|
||||
color: var(--vscode-foreground);
|
||||
font-size: var(--vscode-font-size);
|
||||
font-weight: var(--vscode-font-weight);
|
||||
font-family: var(--vscode-font-family);
|
||||
background-color: var(--vscode-editor-background);
|
||||
background-color: var(--vscode-sideBar-background);
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-left: var(--container-paddding);
|
||||
}
|
||||
|
||||
body > *,
|
||||
form > * {
|
||||
margin-block-start: var(--input-margin-vertical);
|
||||
margin-block-end: var(--input-margin-vertical);
|
||||
padding-left: var(--container-padding);
|
||||
}
|
||||
|
||||
*:focus {
|
||||
@@ -53,6 +50,7 @@ button {
|
||||
outline-offset: 2px !important;
|
||||
color: var(--vscode-button-foreground);
|
||||
background: var(--vscode-button-background);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
|
||||
|
Before Width: | Height: | Size: 56 KiB |
3
assets/walkthrough/documentation.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## Documentation
|
||||
|
||||
Our documentation can be found at: [https://frontmatter.codes/docs](https://frontmatter.codes/docs)
|
||||
11
assets/walkthrough/get-started.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## Getting started
|
||||
|
||||
Thanks for installing Front Matter!
|
||||
|
||||
To get started, open our dashboard which will guide you through the initialization process of your project.
|
||||
|
||||
When you haven't initialized your project yet, you will see the Front Matter's welcome screen on which you will have to perform the following steps:
|
||||
|
||||
- Project initialization
|
||||
- Content folders registration
|
||||
- Framework initialization
|
||||
8
assets/walkthrough/support-the-project.md
Normal file
@@ -0,0 +1,8 @@
|
||||
## Support the project
|
||||
|
||||
Front Matter is an open source project and we are always looking for new contributors, supporters, and partners. If you are interested in backing the project, please consider supporting it by donating. You can donate at via the following links:
|
||||
|
||||
- [GitHub Sponsors](https://github.com/sponsors/estruyf)
|
||||
- [Open Collective](https://opencollective.com/frontmatter)
|
||||
|
||||
> Each sponsor/backer will be mentioned on the [Front Matter](https://frontmatter.codes) website and on the [GitHub repository](https://github.com/estruyf/vscode-front-matter).
|
||||
55
frontmatter.json
Normal file
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"$schema": "https://beta.frontmatter.codes/frontmatter.schema.json",
|
||||
"frontMatter.framework.id": "other",
|
||||
"frontMatter.content.publicFolder": "",
|
||||
"frontMatter.content.pageFolders": [
|
||||
{
|
||||
"title": ".vscode",
|
||||
"path": "[[workspace]]/.vscode"
|
||||
}
|
||||
],
|
||||
"frontMatter.content.snippets": {
|
||||
"New version": {
|
||||
"description": "Insert a new version to the changelog",
|
||||
"body": [
|
||||
"## [{{version}}] - {{year}}-{{month}}-{{day}}",
|
||||
"",
|
||||
"### ✨ New features",
|
||||
"",
|
||||
"### 🎨 Enhancements",
|
||||
"",
|
||||
"### ⚡️ Optimizations",
|
||||
"",
|
||||
"### 🐞 Fixes"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "version",
|
||||
"title": "Version",
|
||||
"single": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "year",
|
||||
"title": "Year",
|
||||
"default": "2022"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "month",
|
||||
"title": "Month",
|
||||
"default": "xx"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "day",
|
||||
"title": "Day",
|
||||
"default": "xx"
|
||||
}
|
||||
],
|
||||
"openingTags": "{{",
|
||||
"closingTags": "}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
20291
package-lock.json
generated
2139
package.json
9
postcss.config.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const tailwindcss = require('tailwindcss');
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('postcss-nested'),
|
||||
tailwindcss('./tailwind.config.js'),
|
||||
require('autoprefixer'),
|
||||
],
|
||||
};
|
||||
10
sample/script-sample.js
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
const arguments = process.argv;
|
||||
|
||||
if (arguments && arguments.length > 0) {
|
||||
const workspaceArg = arguments[2]; // The workspace path
|
||||
const fileArg = arguments[3]; // The file path
|
||||
const frontMatterArg = arguments[4]; // Front matter data
|
||||
|
||||
console.log(`The content returned for your notification.`);
|
||||
}
|
||||
20
scripts/beta-release.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const packageJson = require('../package.json');
|
||||
const version = packageJson.version.split('.');
|
||||
|
||||
packageJson.version = `${version[0]}.${version[1]}.${process.argv[process.argv.length-1].substr(0, 7)}`;
|
||||
packageJson.preview = true;
|
||||
packageJson.name = "vscode-front-matter-beta";
|
||||
packageJson.displayName = `${packageJson.displayName} BETA`;
|
||||
packageJson.description = `BETA Version of Front Matter. ${packageJson.description}`;
|
||||
packageJson.icon = "assets/frontmatter-beta.png";
|
||||
packageJson.homepage = "https://beta.frontmatter.codes";
|
||||
|
||||
console.log(packageJson.version);
|
||||
|
||||
fs.writeFileSync(path.join(path.resolve('.'), 'package.json'), JSON.stringify(packageJson, null, 2));
|
||||
|
||||
let readme = fs.readFileSync(path.join(__dirname, '../README.beta.md'), 'utf8');
|
||||
fs.writeFileSync(path.join(__dirname, '../README.md'), readme);
|
||||
7
scripts/main-release.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const packageJson = require('../package.json');
|
||||
packageJson.name = "vscode-front-matter";
|
||||
|
||||
fs.writeFileSync(path.join(path.resolve('.'), 'package.json'), JSON.stringify(packageJson, null, 2));
|
||||
@@ -1,27 +1,37 @@
|
||||
import { SETTING_MODIFIED_FIELD } from './../constants/settings';
|
||||
import { DEFAULT_CONTENT_TYPE } from './../constants/ContentType';
|
||||
import { isValidFile } from './../helpers/isValidFile';
|
||||
import { SETTING_AUTO_UPDATE_DATE, SETTING_MODIFIED_FIELD, SETTING_SLUG_UPDATE_FILE_NAME, SETTING_TEMPLATES_PREFIX, CONFIG_KEY, SETTING_DATE_FORMAT, SETTING_SLUG_PREFIX, SETTING_SLUG_SUFFIX, SETTING_CONTENT_PLACEHOLDERS, TelemetryEvent } from './../constants';
|
||||
import * as vscode from 'vscode';
|
||||
import { TaxonomyType } from "../models";
|
||||
import { CONFIG_KEY, SETTING_DATE_FORMAT, EXTENSION_NAME, SETTING_SLUG_PREFIX, SETTING_SLUG_SUFFIX, SETTING_DATE_FIELD } from "../constants/settings";
|
||||
import { Field, TaxonomyType } from "../models";
|
||||
import { format } from "date-fns";
|
||||
import { ArticleHelper, SettingsHelper, SlugHelper } from '../helpers';
|
||||
import matter = require('gray-matter');
|
||||
import { ArticleHelper, Settings, SlugHelper } from '../helpers';
|
||||
import { Notifications } from '../helpers/Notifications';
|
||||
import { extname, basename, parse, dirname } from 'path';
|
||||
import { COMMAND_NAME, DefaultFields } from '../constants';
|
||||
import { DashboardData } from '../models/DashboardData';
|
||||
import { DateHelper } from '../helpers/DateHelper';
|
||||
import { parseWinPath } from '../helpers/parseWinPath';
|
||||
import { Telemetry } from '../helpers/Telemetry';
|
||||
import { ParsedFrontMatter } from '../parsers';
|
||||
import { MediaListener } from '../listeners/panel';
|
||||
import { NavigationType } from '../dashboardWebView/models';
|
||||
import { processKnownPlaceholders } from '../helpers/PlaceholderHelper';
|
||||
|
||||
|
||||
export class Article {
|
||||
|
||||
/**
|
||||
* Insert taxonomy
|
||||
*
|
||||
* @param type
|
||||
*/
|
||||
public static async insert(type: TaxonomyType) {
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const article = ArticleHelper.getFrontMatter(editor);
|
||||
const article = ArticleHelper.getCurrent();
|
||||
|
||||
if (!article) {
|
||||
return;
|
||||
}
|
||||
@@ -41,7 +51,7 @@ export class Article {
|
||||
}
|
||||
|
||||
// Add all the known options to the selection list
|
||||
const crntOptions = SettingsHelper.getTaxonomy(type);
|
||||
const crntOptions = Settings.getTaxonomy(type);
|
||||
if (crntOptions && crntOptions.length > 0) {
|
||||
for (const crntOpt of crntOptions) {
|
||||
if (!options.find(o => o.label === crntOpt)) {
|
||||
@@ -53,7 +63,7 @@ export class Article {
|
||||
}
|
||||
|
||||
if (options.length === 0) {
|
||||
vscode.window.showInformationMessage(`${EXTENSION_NAME}: No ${type === TaxonomyType.Tag ? "tags" : "categories"} configured.`);
|
||||
Notifications.info(`No ${type === TaxonomyType.Tag ? "tags" : "categories"} configured.`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -88,8 +98,7 @@ export class Article {
|
||||
try {
|
||||
ArticleHelper.update(editor, article);
|
||||
} catch (e) {
|
||||
vscode.window.showErrorMessage(`${EXTENSION_NAME}: Something failed while parsing the date format. Check your "${CONFIG_KEY}${SETTING_DATE_FORMAT}" setting.`);
|
||||
console.log(e.message);
|
||||
Notifications.error(`Something failed while parsing the date format. Check your "${CONFIG_KEY}${SETTING_DATE_FORMAT}" setting.`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,18 +106,8 @@ export class Article {
|
||||
* Update the date in the front matter
|
||||
* @param article
|
||||
*/
|
||||
public static updateDate(article: matter.GrayMatterFile<string>, forceCreate: boolean = false) {
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
const dateFormat = config.get(SETTING_DATE_FORMAT) as string;
|
||||
const dateField = config.get(SETTING_DATE_FIELD) as string || "date";
|
||||
|
||||
if (typeof article.data[dateField] !== "undefined" || forceCreate) {
|
||||
if (dateFormat && typeof dateFormat === "string") {
|
||||
article.data[dateField] = format(new Date(), dateFormat);
|
||||
} else {
|
||||
article.data[dateField] = new Date();
|
||||
}
|
||||
}
|
||||
public static updateDate(article: ParsedFrontMatter, forceCreate: boolean = false) {
|
||||
article.data = ArticleHelper.updateDates(article.data);
|
||||
return article;
|
||||
}
|
||||
|
||||
@@ -116,41 +115,69 @@ export class Article {
|
||||
* Sets the article lastmod date
|
||||
*/
|
||||
public static async setLastModifiedDate() {
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const article = ArticleHelper.getFrontMatter(editor);
|
||||
if (!article) {
|
||||
const updatedArticle = this.setLastModifiedDateInner(editor.document);
|
||||
|
||||
if (typeof updatedArticle === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
const dateFormat = config.get(SETTING_DATE_FORMAT) as string;
|
||||
const dateField = config.get(SETTING_MODIFIED_FIELD) as string || "lastmod";
|
||||
try {
|
||||
if (dateFormat && typeof dateFormat === "string") {
|
||||
article.data[dateField] = format(new Date(), dateFormat);
|
||||
} else {
|
||||
article.data[dateField] = new Date();
|
||||
}
|
||||
ArticleHelper.update(
|
||||
editor,
|
||||
updatedArticle as ParsedFrontMatter
|
||||
);
|
||||
}
|
||||
|
||||
ArticleHelper.update(editor, article);
|
||||
} catch (e) {
|
||||
vscode.window.showErrorMessage(`${EXTENSION_NAME}: Something failed while parsing the date format. Check your "${CONFIG_KEY}${SETTING_DATE_FORMAT}" setting.`);
|
||||
console.log(e.message);
|
||||
public static async setLastModifiedDateOnSave(
|
||||
document: vscode.TextDocument
|
||||
): Promise<vscode.TextEdit[]> {
|
||||
const updatedArticle = this.setLastModifiedDateInner(document);
|
||||
|
||||
if (typeof updatedArticle === "undefined") {
|
||||
return [];
|
||||
}
|
||||
|
||||
const update = ArticleHelper.generateUpdate(document, updatedArticle);
|
||||
|
||||
return [update];
|
||||
}
|
||||
|
||||
private static setLastModifiedDateInner(
|
||||
document: vscode.TextDocument
|
||||
): ParsedFrontMatter | undefined {
|
||||
const article = ArticleHelper.getFrontMatterFromDocument(document);
|
||||
|
||||
// Only set the date, if there is already front matter set
|
||||
if (!article || !article.data || Object.keys(article.data).length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cloneArticle = Object.assign({}, article);
|
||||
const dateField = ArticleHelper.getModifiedDateField(article) || DefaultFields.LastModified;
|
||||
try {
|
||||
cloneArticle.data[dateField] = Article.formatDate(new Date());
|
||||
return cloneArticle;
|
||||
} catch (e: any) {
|
||||
Notifications.error(`Something failed while parsing the date format. Check your "${CONFIG_KEY}${SETTING_DATE_FORMAT}" setting.`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the slug based on the article title
|
||||
*/
|
||||
public static generateSlug() {
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
const prefix = config.get(SETTING_SLUG_PREFIX) as string;
|
||||
const suffix = config.get(SETTING_SLUG_SUFFIX) as string;
|
||||
public static async generateSlug() {
|
||||
Telemetry.send(TelemetryEvent.generateSlug);
|
||||
|
||||
const prefix = Settings.get(SETTING_SLUG_PREFIX) as string;
|
||||
const suffix = Settings.get(SETTING_SLUG_SUFFIX) as string;
|
||||
const updateFileName = Settings.get(SETTING_SLUG_UPDATE_FILE_NAME) as string;
|
||||
const filePrefix = Settings.get<string>(SETTING_TEMPLATES_PREFIX);
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
@@ -160,14 +187,94 @@ export class Article {
|
||||
return;
|
||||
}
|
||||
|
||||
const articleTitle: string = article.data["title"];
|
||||
const contentType = ArticleHelper.getContentType(article.data);
|
||||
const titleField = "title";
|
||||
const articleTitle: string = article.data[titleField];
|
||||
|
||||
const slug = SlugHelper.createSlug(articleTitle);
|
||||
if (slug) {
|
||||
article.data["slug"] = `${prefix}${slug}${suffix}`;
|
||||
let slugFieldValue = `${prefix}${slug}${suffix}`;
|
||||
article.data["slug"] = slugFieldValue;
|
||||
|
||||
if (contentType) {
|
||||
// Update the fields containing the slug placeholder
|
||||
let fieldsToUpdate: Field[] = contentType.fields.filter(f => f.default === "{{slug}}");
|
||||
for (const field of fieldsToUpdate) {
|
||||
article.data[field.name] = slug;
|
||||
}
|
||||
|
||||
// Update the fields containing a custom placeholder that depends on slug
|
||||
const placeholders = Settings.get<{id: string, value: string}[]>(SETTING_CONTENT_PLACEHOLDERS);
|
||||
const customPlaceholders = placeholders?.filter(p => p.value.includes("{{slug}}"));
|
||||
const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
|
||||
for (const customPlaceholder of (customPlaceholders || [])) {
|
||||
const customPlaceholderFields = contentType.fields.filter(f => f.default === `{{${customPlaceholder.id}}}`);
|
||||
for (const pField of customPlaceholderFields) {
|
||||
article.data[pField.name] = customPlaceholder.value;
|
||||
article.data[pField.name] = processKnownPlaceholders(article.data[pField.name], articleTitle, dateFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ArticleHelper.update(editor, article);
|
||||
|
||||
// Check if the file name should be updated by the slug
|
||||
// This is required for systems like Jekyll
|
||||
if (updateFileName) {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor) {
|
||||
const ext = extname(editor.document.fileName);
|
||||
const fileName = basename(editor.document.fileName);
|
||||
|
||||
let slugName = slug.startsWith("/") ? slug.substring(1) : slug;
|
||||
slugName = slugName.endsWith("/") ? slugName.substring(0, slugName.length - 1) : slugName;
|
||||
|
||||
let newFileName = `${slugName}${ext}`;
|
||||
if (filePrefix && typeof filePrefix === "string") {
|
||||
newFileName = `${format(new Date(), DateHelper.formatUpdate(filePrefix) as string)}-${newFileName}`;
|
||||
}
|
||||
|
||||
const newPath = editor.document.uri.fsPath.replace(fileName, newFileName);
|
||||
|
||||
try {
|
||||
await editor.document.save();
|
||||
|
||||
await vscode.workspace.fs.rename(editor.document.uri, vscode.Uri.file(newPath), {
|
||||
overwrite: false
|
||||
});
|
||||
} catch (e: any) {
|
||||
Notifications.error(`Failed to rename file: ${e?.message || e}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the slug from the front matter
|
||||
*/
|
||||
public static getSlug() {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const file = parseWinPath(editor.document.fileName);
|
||||
|
||||
if (!isValidFile(file)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const parsedFile = parse(file);
|
||||
|
||||
if (parsedFile.name.toLowerCase() !== "index") {
|
||||
return parsedFile.name;
|
||||
}
|
||||
|
||||
const folderName = basename(dirname(file));
|
||||
return folderName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the page its draft mode
|
||||
*/
|
||||
@@ -185,4 +292,100 @@ export class Article {
|
||||
article.data["draft"] = newDraftStatus;
|
||||
ArticleHelper.update(editor, article);
|
||||
}
|
||||
|
||||
/**
|
||||
* Article auto updater
|
||||
* @param event
|
||||
*/
|
||||
public static async autoUpdate(event: vscode.TextDocumentWillSaveEvent) {
|
||||
const document = event.document;
|
||||
if (document && ArticleHelper.isSupportedFile(document)) {
|
||||
const autoUpdate = Settings.get(SETTING_AUTO_UPDATE_DATE);
|
||||
|
||||
if (autoUpdate) {
|
||||
event.waitUntil(Article.setLastModifiedDateOnSave(document));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the date to the defined format
|
||||
*/
|
||||
public static formatDate(dateValue: Date): string {
|
||||
const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
|
||||
|
||||
if (dateFormat && typeof dateFormat === "string") {
|
||||
return format(dateValue, DateHelper.formatUpdate(dateFormat) as string);
|
||||
} else {
|
||||
return typeof dateValue.toISOString === 'function' ? dateValue.toISOString() : dateValue?.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an image from the media dashboard into the article
|
||||
*/
|
||||
public static async insertMedia() {
|
||||
let editor = vscode.window.activeTextEditor;
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const article = ArticleHelper.getFrontMatter(editor);
|
||||
const contentType = article && article.data ? ArticleHelper.getContentType(article.data) : DEFAULT_CONTENT_TYPE;
|
||||
|
||||
const position = editor.selection.active;
|
||||
|
||||
await vscode.commands.executeCommand(COMMAND_NAME.dashboard, {
|
||||
type: "media",
|
||||
data: {
|
||||
pageBundle: !!contentType.pageBundle,
|
||||
filePath: editor.document.uri.fsPath,
|
||||
fieldName: basename(editor.document.uri.fsPath),
|
||||
position
|
||||
}
|
||||
} as DashboardData);
|
||||
|
||||
// Let the editor panel know you are selecting an image
|
||||
MediaListener.getMediaSelection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a snippet into the article
|
||||
*/
|
||||
public static async insertSnippet() {
|
||||
let editor = vscode.window.activeTextEditor;
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const position = editor.selection.active;
|
||||
const selectionText = editor.document.getText(editor.selection);
|
||||
|
||||
const article = ArticleHelper.getFrontMatter(editor);
|
||||
|
||||
await vscode.commands.executeCommand(COMMAND_NAME.dashboard, {
|
||||
type: NavigationType.Snippets,
|
||||
data: {
|
||||
fileTitle: article?.data.title || "",
|
||||
filePath: editor.document.uri.fsPath,
|
||||
fieldName: basename(editor.document.uri.fsPath),
|
||||
position,
|
||||
selection: selectionText
|
||||
}
|
||||
} as DashboardData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the article date and return it
|
||||
* @param article
|
||||
* @param dateFormat
|
||||
* @param field
|
||||
* @param forceCreate
|
||||
*/
|
||||
private static articleDate(article: ParsedFrontMatter, field: string, forceCreate: boolean) {
|
||||
if (typeof article.data[field] !== "undefined" || forceCreate) {
|
||||
article.data[field] = Article.formatDate(new Date());
|
||||
}
|
||||
return article;
|
||||
}
|
||||
}
|
||||
|
||||
75
src/commands/Backers.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { commands, ExtensionContext } from 'vscode';
|
||||
import { CONTEXT } from '../constants';
|
||||
import { Extension } from '../helpers';
|
||||
import { Credentials } from "../services/Credentials";
|
||||
import fetch from "node-fetch";
|
||||
import { ExplorerView } from '../explorerView/ExplorerView';
|
||||
import { Dashboard } from './Dashboard';
|
||||
import { SettingsListener } from '../listeners/panel';
|
||||
|
||||
export class Backers {
|
||||
private static creds: Credentials | null = null;
|
||||
|
||||
public static async init(context: ExtensionContext) {
|
||||
Backers.creds = new Credentials();
|
||||
await Backers.creds.initialize(context, Backers.tryUsernameCheck);
|
||||
|
||||
Backers.tryUsernameCheck();
|
||||
|
||||
context.subscriptions.push(
|
||||
commands.registerCommand('frontMatter.authenticate', async () => {
|
||||
Backers.tryUsernameCheck();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public static async tryUsernameCheck() {
|
||||
try {
|
||||
const username = await Backers.getUsername();
|
||||
Backers.validate(username || "");
|
||||
} catch (e) {
|
||||
Backers.validate("");
|
||||
}
|
||||
}
|
||||
|
||||
public static async getUsername() {
|
||||
const octokit = await Backers.creds?.getOctokit();
|
||||
const user = await octokit?.users.getAuthenticated();
|
||||
|
||||
if (user?.data?.login) {
|
||||
return user?.data?.login;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public static async validate(username: string) {
|
||||
const ext = Extension.getInstance();
|
||||
|
||||
if (!username) {
|
||||
ext.setState(CONTEXT.backer, undefined, 'global');
|
||||
}
|
||||
|
||||
const isBeta = ext.isBetaVersion();
|
||||
|
||||
const response = await fetch(`https://${isBeta ? `beta.` : ``}frontmatter.codes/api/backers?backer=${username}`);
|
||||
|
||||
if (response.ok) {
|
||||
const prevData = await ext.getState<boolean>(CONTEXT.backer, 'global');
|
||||
await ext.setState(CONTEXT.backer, true, 'global');
|
||||
|
||||
if (!prevData) {
|
||||
const explorerView = ExplorerView.getInstance();
|
||||
if (explorerView.visible) {
|
||||
SettingsListener.getSettings();
|
||||
}
|
||||
|
||||
if (Dashboard.isOpen) {
|
||||
Dashboard.reload();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ext.setState(CONTEXT.backer, false, 'global');
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/commands/Content.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { commands, QuickPickItem, window } from 'vscode';
|
||||
import { COMMAND_NAME } from '../constants';
|
||||
|
||||
export class Content {
|
||||
|
||||
public static async create() {
|
||||
|
||||
const options: QuickPickItem[] = [{
|
||||
label: "Create content by content type",
|
||||
description: "Select if you want to create new content by the available content type(s)"
|
||||
}, {
|
||||
label: "Create content by template",
|
||||
description: "Select if you want to create new content by the available template(s)"
|
||||
} as QuickPickItem];
|
||||
|
||||
const selectedOption = await window.showQuickPick(options, {
|
||||
placeHolder: `Select how you want to create your new content`,
|
||||
canPickMany: false
|
||||
});
|
||||
|
||||
if (selectedOption) {
|
||||
if (selectedOption.label === options[0].label) {
|
||||
commands.executeCommand(COMMAND_NAME.createByContentType);
|
||||
} else {
|
||||
commands.executeCommand(COMMAND_NAME.createByTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
225
src/commands/Dashboard.ts
Normal file
@@ -0,0 +1,225 @@
|
||||
import { SETTING_DASHBOARD_OPENONSTART, CONTEXT } from '../constants';
|
||||
import { join } from "path";
|
||||
import { commands, Uri, ViewColumn, Webview, WebviewPanel, window } from "vscode";
|
||||
import { Logger, Settings as SettingsHelper } from '../helpers';
|
||||
import { DashboardCommand } from '../dashboardWebView/DashboardCommand';
|
||||
import { Extension } from '../helpers/Extension';
|
||||
import { WebviewHelper } from '@estruyf/vscode';
|
||||
import { DashboardData } from '../models/DashboardData';
|
||||
import { MediaLibrary } from '../helpers/MediaLibrary';
|
||||
import { DashboardListener, MediaListener, SettingsListener, TelemetryListener, DataListener, PagesListener, ExtensionListener, SnippetListener } from '../listeners/dashboard';
|
||||
import { MediaListener as PanelMediaListener } from '../listeners/panel'
|
||||
import { ModeListener } from '../listeners/general';
|
||||
|
||||
export class Dashboard {
|
||||
private static webview: WebviewPanel | null = null;
|
||||
private static _viewData: DashboardData | undefined;
|
||||
private static isDisposed: boolean = true;
|
||||
|
||||
public static get viewData(): DashboardData | undefined {
|
||||
return Dashboard._viewData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init the dashboard
|
||||
*/
|
||||
public static async init() {
|
||||
const openOnStartup = SettingsHelper.get(SETTING_DASHBOARD_OPENONSTART);
|
||||
if (openOnStartup) {
|
||||
Dashboard.open();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open or reveal the dashboard
|
||||
*/
|
||||
public static async open(data?: DashboardData) {
|
||||
MediaLibrary.getInstance();
|
||||
|
||||
Dashboard._viewData = data;
|
||||
|
||||
if (Dashboard.isOpen) {
|
||||
Dashboard.reveal(!!data);
|
||||
} else {
|
||||
Dashboard.create();
|
||||
}
|
||||
|
||||
await commands.executeCommand('setContext', CONTEXT.isDashboardOpen, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the dashboard is still open
|
||||
*/
|
||||
public static get isOpen(): boolean {
|
||||
return !Dashboard.isDisposed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reveal the dashboard if it is open
|
||||
*/
|
||||
public static reveal(hasData: boolean = false) {
|
||||
if (Dashboard.webview) {
|
||||
Dashboard.webview.reveal();
|
||||
|
||||
if (hasData) {
|
||||
Dashboard.postWebviewMessage({ command: DashboardCommand.viewData, data: Dashboard.viewData });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static close() {
|
||||
Dashboard.webview?.dispose();
|
||||
}
|
||||
|
||||
public static reload() {
|
||||
if (Dashboard.isOpen) {
|
||||
Dashboard.webview?.dispose();
|
||||
|
||||
setTimeout(() => {
|
||||
Dashboard.open();
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
public static resetViewData() {
|
||||
Dashboard._viewData = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the dashboard webview
|
||||
*/
|
||||
public static async create() {
|
||||
const extensionUri = Extension.getInstance().extensionPath;
|
||||
|
||||
// Create the preview webview
|
||||
Dashboard.webview = window.createWebviewPanel(
|
||||
'frontMatterDashboard',
|
||||
'FrontMatter Dashboard',
|
||||
ViewColumn.One,
|
||||
{
|
||||
enableScripts: true,
|
||||
retainContextWhenHidden: true
|
||||
}
|
||||
);
|
||||
|
||||
Dashboard.isDisposed = false;
|
||||
|
||||
Dashboard.webview.iconPath = {
|
||||
dark: Uri.file(join(extensionUri.fsPath, 'assets/icons/frontmatter-short-dark.svg')),
|
||||
light: Uri.file(join(extensionUri.fsPath, 'assets/icons/frontmatter-short-light.svg'))
|
||||
};
|
||||
|
||||
Dashboard.webview.webview.html = Dashboard.getWebviewContent(Dashboard.webview.webview, extensionUri);
|
||||
|
||||
Dashboard.webview.onDidChangeViewState(async () => {
|
||||
if (!this.webview?.visible) {
|
||||
Dashboard._viewData = undefined;
|
||||
PanelMediaListener.getMediaSelection();
|
||||
|
||||
Dashboard.postWebviewMessage({ command: DashboardCommand.viewData, data: null });
|
||||
}
|
||||
|
||||
await commands.executeCommand('setContext', CONTEXT.isDashboardOpen, this.webview?.visible);
|
||||
});
|
||||
|
||||
Dashboard.webview.onDidDispose(async () => {
|
||||
Dashboard.isDisposed = true;
|
||||
Dashboard._viewData = undefined;
|
||||
PanelMediaListener.getMediaSelection();
|
||||
await commands.executeCommand('setContext', CONTEXT.isDashboardOpen, false);
|
||||
});
|
||||
|
||||
SettingsHelper.onConfigChange((global?: any) => {
|
||||
SettingsListener.getSettings();
|
||||
});
|
||||
|
||||
Dashboard.webview.webview.onDidReceiveMessage(async (msg) => {
|
||||
Logger.info(`Receiving message from webview: ${msg.command}`);
|
||||
|
||||
DashboardListener.process(msg);
|
||||
ExtensionListener.process(msg);
|
||||
MediaListener.process(msg);
|
||||
PagesListener.process(msg);
|
||||
SettingsListener.process(msg);
|
||||
DataListener.process(msg);
|
||||
TelemetryListener.process(msg);
|
||||
SnippetListener.process(msg);
|
||||
ModeListener.process(msg);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the webview
|
||||
* @returns The webview
|
||||
*/
|
||||
public static getWebview() {
|
||||
return Dashboard.webview?.webview;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post data to the dashboard
|
||||
* @param msg
|
||||
*/
|
||||
public static postWebviewMessage(msg: { command: DashboardCommand, data?: any }) {
|
||||
if (Dashboard.isDisposed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Dashboard.webview) {
|
||||
Dashboard.webview?.webview.postMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the webview HTML contents
|
||||
* @param webView
|
||||
*/
|
||||
private static getWebviewContent(webView: Webview, extensionPath: Uri): string {
|
||||
const dashboardFile = "dashboardWebView.js";
|
||||
const localPort = `9000`;
|
||||
const localServerUrl = `localhost:${localPort}`;
|
||||
|
||||
let scriptUri = "";
|
||||
const isProd = Extension.getInstance().isProductionMode;
|
||||
if (isProd) {
|
||||
scriptUri = webView.asWebviewUri(Uri.joinPath(extensionPath, 'dist', dashboardFile)).toString();
|
||||
} else {
|
||||
scriptUri = `http://${localServerUrl}/${dashboardFile}`;
|
||||
}
|
||||
|
||||
const nonce = WebviewHelper.getNonce();
|
||||
|
||||
const ext = Extension.getInstance();
|
||||
const version = ext.getVersion();
|
||||
const isBeta = ext.isBetaVersion();
|
||||
|
||||
const csp = [
|
||||
`default-src 'none';`,
|
||||
`img-src ${`vscode-file://vscode-app`} ${webView.cspSource} https://api.visitorbadge.io 'self' 'unsafe-inline'`,
|
||||
`script-src ${isProd ? `'nonce-${nonce}'` : `http://${localServerUrl} http://0.0.0.0:${localPort}`} 'unsafe-eval'`,
|
||||
`style-src ${webView.cspSource} 'self' 'unsafe-inline'`,
|
||||
`font-src ${webView.cspSource}`,
|
||||
`connect-src https://o1022172.ingest.sentry.io ${isProd ? `` : `ws://${localServerUrl} ws://0.0.0.0:${localPort} http://${localServerUrl} http://0.0.0.0:${localPort}`}`
|
||||
];
|
||||
|
||||
return `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" style="width:100%;height:100%;margin:0;padding:0;">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="${csp.join('; ')}">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<title>Front Matter Dashboard</title>
|
||||
</head>
|
||||
<body style="width:100%;height:100%;margin:0;padding:0;overflow:hidden" class="bg-gray-100 text-vulcan-500 dark:bg-vulcan-500 dark:text-whisper-500">
|
||||
<div id="app" data-isProd="${isProd}" data-environment="${isBeta ? "BETA" : "main"}" data-version="${version.usedVersion}" style="width:100%;height:100%;margin:0;padding:0;" ${version.usedVersion ? "" : `data-showWelcome="true"`}></div>
|
||||
|
||||
<img style="display:none" src="https://api.visitorbadge.io/api/combined?user=estruyf&repo=frontmatter-usage&countColor=%23263759&slug=${`dashboard-${version.installedVersion}`}" alt="Daily usage" />
|
||||
|
||||
<script ${isProd ? `nonce="${nonce}"` : ""} src="${scriptUri}"></script>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
}
|
||||
}
|
||||
63
src/commands/Diagnostics.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { Folders } from "./Folders";
|
||||
import { ViewColumn, workspace } from "vscode";
|
||||
import ContentProvider from "../providers/ContentProvider";
|
||||
import { join } from "path";
|
||||
import { ContentFolder } from "../models";
|
||||
|
||||
|
||||
export class Diagnostics {
|
||||
|
||||
public static async show() {
|
||||
const folders = Folders.get();
|
||||
const projectName = Folders.getProjectFolderName();
|
||||
const wsFolder = Folders.getWorkspaceFolder();
|
||||
|
||||
const folderData = [];
|
||||
for (const folder of folders) {
|
||||
folderData.push(await Diagnostics.processFolder(folder, projectName));
|
||||
}
|
||||
|
||||
const all = await Diagnostics.allProjectFiles();
|
||||
|
||||
const logging = `# Project name
|
||||
|
||||
${projectName}
|
||||
|
||||
# Folders
|
||||
|
||||
${folders.map(f => `- ${f.title}: "${f.path}"`).join("\n")}
|
||||
|
||||
# Workspace folder
|
||||
|
||||
${wsFolder ? wsFolder.fsPath : "No workspace folder"}
|
||||
|
||||
# Total files
|
||||
|
||||
${all}
|
||||
|
||||
# Folders to search files
|
||||
|
||||
${folderData.join("\n")}
|
||||
`;
|
||||
|
||||
ContentProvider.show(logging, `${projectName} diagnostics`, "markdown", ViewColumn.One);
|
||||
}
|
||||
|
||||
private static async allProjectFiles() {
|
||||
const allFiles = await workspace.findFiles(`**/*.*`);
|
||||
return `Total files found: ${allFiles.length}`;
|
||||
}
|
||||
|
||||
private static async processFolder(folder: ContentFolder, projectName: string) {
|
||||
let projectStart = folder.path.split(projectName).pop();
|
||||
projectStart = projectStart || "";
|
||||
projectStart = projectStart?.replace(/\\/g, '/');
|
||||
projectStart = projectStart?.startsWith('/') ? projectStart.substr(1) : projectStart;
|
||||
|
||||
const mdFiles = await workspace.findFiles(join(projectStart, folder.excludeSubdir ? '/' : '**/', '*.md'));
|
||||
const mdxFiles = await workspace.findFiles(join(projectStart, folder.excludeSubdir ? '/' : '**/', '*.mdx'));
|
||||
const markdownFiles = await workspace.findFiles(join(projectStart, folder.excludeSubdir ? '/' : '**/', '*.markdown'));
|
||||
|
||||
return `- Project start length: ${projectStart.length} | Search in: "${join(projectStart, folder.excludeSubdir ? '/' : '**/', '*.*')}" | mdFiles: ${mdFiles.length} | mdxFiles: ${mdxFiles.length} | markdownFiles: ${markdownFiles.length}`;
|
||||
}
|
||||
}
|
||||
391
src/commands/Folders.ts
Normal file
@@ -0,0 +1,391 @@
|
||||
import { Questions } from './../helpers/Questions';
|
||||
import { SETTING_CONTENT_PAGE_FOLDERS, SETTING_CONTENT_STATIC_FOLDER, SETTING_CONTENT_SUPPORTED_FILETYPES, TelemetryEvent } from './../constants';
|
||||
import { commands, Uri, workspace, window } from "vscode";
|
||||
import { basename, dirname, join, relative, sep } from "path";
|
||||
import { ContentFolder, FileInfo, FolderInfo } from "../models";
|
||||
import uniqBy = require("lodash.uniqby");
|
||||
import { Template } from "./Template";
|
||||
import { Notifications } from "../helpers/Notifications";
|
||||
import { Settings } from "../helpers";
|
||||
import { existsSync, mkdirSync } from 'fs';
|
||||
import { format } from 'date-fns';
|
||||
import { Dashboard } from './Dashboard';
|
||||
import { parseWinPath } from '../helpers/parseWinPath';
|
||||
import { MediaHelpers } from '../helpers/MediaHelpers';
|
||||
import { MediaListener, PagesListener, SettingsListener } from '../listeners/dashboard';
|
||||
import { DEFAULT_FILE_TYPES } from '../constants/DefaultFileTypes';
|
||||
import { Telemetry } from '../helpers/Telemetry';
|
||||
import { glob } from 'glob';
|
||||
|
||||
export const WORKSPACE_PLACEHOLDER = `[[workspace]]`;
|
||||
|
||||
export class Folders {
|
||||
|
||||
/**
|
||||
* Add a media folder
|
||||
* @returns
|
||||
*/
|
||||
public static async addMediaFolder(data?: {selectedFolder?: string}) {
|
||||
let wsFolder = Folders.getWorkspaceFolder();
|
||||
const staticFolder = Settings.get<string>(SETTING_CONTENT_STATIC_FOLDER);
|
||||
|
||||
let startPath = "";
|
||||
|
||||
if (data?.selectedFolder) {
|
||||
startPath = data.selectedFolder.replace(parseWinPath(wsFolder?.fsPath || ""), "");
|
||||
} else if (staticFolder) {
|
||||
startPath = `/${staticFolder}`;
|
||||
}
|
||||
|
||||
if (startPath && !startPath.endsWith("/")) {
|
||||
startPath += "/";
|
||||
}
|
||||
|
||||
const folderName = await window.showInputBox({
|
||||
prompt: `Which name would you like to give to your folder (use "/" to create multi-level folders)?`,
|
||||
value: startPath,
|
||||
ignoreFocusOut: true,
|
||||
placeHolder: `${format(new Date(), `yyyy/MM`)}`
|
||||
});
|
||||
|
||||
if (!folderName) {
|
||||
Notifications.warning(`No folder name was specified.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const folders = folderName.split("/").filter(f => f);
|
||||
let parentFolders: string[] = [];
|
||||
|
||||
for (const folder of folders) {
|
||||
const folderPath = join(parseWinPath(wsFolder?.fsPath || ""), parentFolders.join("/"), folder);
|
||||
|
||||
parentFolders.push(folder);
|
||||
|
||||
if (!existsSync(folderPath)) {
|
||||
mkdirSync(folderPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (Dashboard.isOpen) {
|
||||
MediaHelpers.resetMedia();
|
||||
MediaListener.sendMediaFiles(0, folderName);
|
||||
}
|
||||
|
||||
Telemetry.send(TelemetryEvent.addMediaFolder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create content in a registered folder
|
||||
* @returns
|
||||
*/
|
||||
public static async create() {
|
||||
const selectedFolder = await Questions.SelectContentFolder();
|
||||
if (!selectedFolder) {
|
||||
return;
|
||||
}
|
||||
|
||||
const folders = Folders.get();
|
||||
const location = folders.find(f => f.title === selectedFolder);
|
||||
if (location) {
|
||||
const folderPath = Folders.getFolderPath(Uri.file(location.path));
|
||||
if (folderPath) {
|
||||
Template.create(folderPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the new folder path
|
||||
* @param folder
|
||||
*/
|
||||
public static async register(folder: Uri) {
|
||||
if (folder && folder.fsPath) {
|
||||
const wslPath = folder.fsPath.replace(/\//g, '\\');
|
||||
|
||||
let folders = Folders.get();
|
||||
|
||||
const exists = folders.find(f => f.path.includes(folder.fsPath) || f.path.includes(wslPath));
|
||||
|
||||
if (exists) {
|
||||
Notifications.warning(`Folder is already registered`);
|
||||
return;
|
||||
}
|
||||
|
||||
const folderName = await window.showInputBox({
|
||||
prompt: `Which name would you like to specify for this folder?`,
|
||||
placeHolder: `Folder name`,
|
||||
value: basename(folder.fsPath)
|
||||
});
|
||||
|
||||
folders.push({
|
||||
title: folderName,
|
||||
path: folder.fsPath
|
||||
} as ContentFolder);
|
||||
|
||||
folders = uniqBy(folders, f => f.path);
|
||||
await Folders.update(folders);
|
||||
|
||||
Notifications.info(`Folder registered`);
|
||||
|
||||
Telemetry.send(TelemetryEvent.registerFolder);
|
||||
|
||||
SettingsListener.getSettings();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a folder path
|
||||
* @param folder
|
||||
*/
|
||||
public static async unregister(folder: Uri) {
|
||||
if (folder && folder.path) {
|
||||
let folders = Folders.get();
|
||||
folders = folders.filter(f => f.path !== folder.fsPath);
|
||||
await Folders.update(folders);
|
||||
|
||||
Telemetry.send(TelemetryEvent.unregisterFolder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the folder path
|
||||
* @param folder
|
||||
* @returns
|
||||
*/
|
||||
public static getFolderPath(folder: Uri) {
|
||||
let folderPath = "";
|
||||
const wsFolder = Folders.getWorkspaceFolder();
|
||||
if (folder && folder.fsPath) {
|
||||
folderPath = folder.fsPath;
|
||||
} else if (wsFolder) {
|
||||
folderPath = wsFolder.fsPath;
|
||||
}
|
||||
return folderPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the workspace folder
|
||||
*/
|
||||
public static getWorkspaceFolder(): Uri | undefined {
|
||||
const folders = workspace.workspaceFolders;
|
||||
|
||||
if (folders && folders.length === 1) {
|
||||
return folders[0].uri;
|
||||
} else if (folders && folders.length > 1) {
|
||||
let projectFolder = undefined;
|
||||
|
||||
for (const folder of folders) {
|
||||
if (!projectFolder && existsSync(join(folder.uri.fsPath, Settings.globalFile))) {
|
||||
projectFolder = folder.uri;
|
||||
}
|
||||
}
|
||||
|
||||
if (!projectFolder) {
|
||||
window.showWorkspaceFolderPick({
|
||||
placeHolder: `Please select the main workspace folder for Front Matter to use.`
|
||||
}).then(selectedFolder => {
|
||||
if (selectedFolder) {
|
||||
Settings.createGlobalFile(selectedFolder.uri);
|
||||
// Full reload to make sure the whole extension is reloaded correctly
|
||||
commands.executeCommand(`workbench.action.reloadWindow`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return projectFolder;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the project
|
||||
*/
|
||||
public static getProjectFolderName(): string {
|
||||
const wsFolder = Folders.getWorkspaceFolder();
|
||||
if (wsFolder) {
|
||||
return basename(wsFolder.fsPath);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the registered folders information
|
||||
*/
|
||||
public static async getInfo(limit?: number): Promise<FolderInfo[] | null> {
|
||||
const supportedFiles = Settings.get<string[]>(SETTING_CONTENT_SUPPORTED_FILETYPES);
|
||||
const folders = Folders.get();
|
||||
if (folders && folders.length > 0) {
|
||||
let folderInfo: FolderInfo[] = [];
|
||||
|
||||
for (const folder of folders) {
|
||||
try {
|
||||
const projectName = Folders.getProjectFolderName();
|
||||
let projectStart = folder.path.split(projectName).pop();
|
||||
|
||||
if (projectStart) {
|
||||
projectStart = projectStart.replace(/\\/g, '/');
|
||||
projectStart = projectStart.startsWith('/') ? projectStart.substr(1) : projectStart;
|
||||
|
||||
let files: Uri[] = [];
|
||||
|
||||
for (const fileType of (supportedFiles || DEFAULT_FILE_TYPES)) {
|
||||
const filePath = join(projectStart, folder.excludeSubdir ? '/' : '**', `*${fileType.startsWith('.') ? '' : '.'}${fileType}`);
|
||||
const foundFiles = await workspace.findFiles(filePath, '**/node_modules/**');
|
||||
files = [...files, ...foundFiles];
|
||||
}
|
||||
|
||||
if (files) {
|
||||
let fileStats: FileInfo[] = [];
|
||||
|
||||
for (const file of files) {
|
||||
try {
|
||||
const fileName = basename(file.fsPath);
|
||||
const folderName = dirname(file.fsPath).split(sep).pop();
|
||||
|
||||
const stats = await workspace.fs.stat(file);
|
||||
|
||||
fileStats.push({
|
||||
filePath: file.fsPath,
|
||||
fileName,
|
||||
folderName,
|
||||
...stats
|
||||
});
|
||||
} catch (error) {
|
||||
// Skip the file
|
||||
}
|
||||
}
|
||||
|
||||
fileStats = fileStats.sort((a, b) => b.mtime - a.mtime);
|
||||
|
||||
if (limit) {
|
||||
fileStats = fileStats.slice(0, limit);
|
||||
}
|
||||
|
||||
folderInfo.push({
|
||||
title: folder.title,
|
||||
files: files.length,
|
||||
lastModified: fileStats
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Skip the current folder
|
||||
}
|
||||
}
|
||||
|
||||
return folderInfo;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the folder settings
|
||||
* @returns
|
||||
*/
|
||||
public static get(): ContentFolder[] {
|
||||
const wsFolder = Folders.getWorkspaceFolder();
|
||||
const folders: ContentFolder[] = Settings.get(SETTING_CONTENT_PAGE_FOLDERS) as ContentFolder[];
|
||||
|
||||
return folders.map(folder => ({
|
||||
...folder,
|
||||
path: Folders.absWsFolder(folder, wsFolder)
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the folder settings
|
||||
* @param folders
|
||||
*/
|
||||
public static async update(folders: ContentFolder[]) {
|
||||
const wsFolder = Folders.getWorkspaceFolder();
|
||||
|
||||
let folderDetails = folders.map(folder => ({
|
||||
...folder,
|
||||
path: Folders.relWsFolder(folder, wsFolder)
|
||||
}));
|
||||
|
||||
await Settings.update(SETTING_CONTENT_PAGE_FOLDERS, folderDetails, true);
|
||||
|
||||
// Reinitialize the folder listeners
|
||||
PagesListener.startWatchers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the absolute file path
|
||||
* @param filePath
|
||||
* @returns
|
||||
*/
|
||||
public static getAbsFilePath(filePath: string): string {
|
||||
const wsFolder = Folders.getWorkspaceFolder();
|
||||
const isWindows = process.platform === 'win32';
|
||||
let absPath = filePath.replace(WORKSPACE_PLACEHOLDER, parseWinPath(wsFolder?.fsPath || ""));
|
||||
absPath = isWindows ? absPath.split('/').join('\\') : absPath;
|
||||
return absPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the absolute URL for the workspace
|
||||
* @param folder
|
||||
* @param wsFolder
|
||||
* @returns
|
||||
*/
|
||||
private static absWsFolder(folder: ContentFolder, wsFolder?: Uri) {
|
||||
const isWindows = process.platform === 'win32';
|
||||
let absPath = folder.path.replace(WORKSPACE_PLACEHOLDER, parseWinPath(wsFolder?.fsPath || ""));
|
||||
absPath = isWindows ? absPath.split('/').join('\\') : absPath;
|
||||
return absPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate relative folder path
|
||||
* @param folder
|
||||
* @param wsFolder
|
||||
* @returns
|
||||
*/
|
||||
public static relWsFolder(folder: ContentFolder, wsFolder?: Uri) {
|
||||
const isWindows = process.platform === 'win32';
|
||||
let absPath = parseWinPath(folder.path).replace(parseWinPath(wsFolder?.fsPath || ""), WORKSPACE_PLACEHOLDER);
|
||||
absPath = isWindows ? absPath.split('\\').join('/') : absPath;
|
||||
return absPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the content folders
|
||||
*/
|
||||
public static async getContentFolders() {
|
||||
// Find folders that contain files
|
||||
const wsFolder = Folders.getWorkspaceFolder();
|
||||
const supportedFiles = Settings.get<string[]>(SETTING_CONTENT_SUPPORTED_FILETYPES) || DEFAULT_FILE_TYPES;
|
||||
const patterns = supportedFiles.map(fileType => `${join(wsFolder?.fsPath || "", "**", `*${fileType.startsWith('.') ? '' : '.'}${fileType}`)}`);
|
||||
let folders: string[] = [];
|
||||
|
||||
for (const pattern of patterns) {
|
||||
folders = [...folders, ...(await this.findFolders(pattern))];
|
||||
}
|
||||
|
||||
// Filter out the workspace folder
|
||||
if (wsFolder) {
|
||||
folders = folders.filter(folder => folder !== wsFolder.fsPath);
|
||||
}
|
||||
|
||||
const uniqueFolders = [...new Set(folders)];
|
||||
return uniqueFolders.map(folder => relative(wsFolder?.path || "", folder));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all content folders
|
||||
* @param pattern
|
||||
* @returns
|
||||
*/
|
||||
private static findFolders(pattern: string): Promise<string[]> {
|
||||
return new Promise(resolve => {
|
||||
glob(pattern, { ignore: "**/node_modules/**" }, (err, files) => {
|
||||
const allFolders = files.map(file => dirname(file));
|
||||
const uniqueFolders = [...new Set(allFolders)];
|
||||
resolve(uniqueFolders);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
157
src/commands/Preview.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
import { Telemetry } from './../helpers/Telemetry';
|
||||
import { SETTING_PREVIEW_HOST, SETTING_PREVIEW_PATHNAME, CONTEXT, TelemetryEvent, PreviewCommands } from './../constants';
|
||||
import { ArticleHelper } from './../helpers/ArticleHelper';
|
||||
import { join } from "path";
|
||||
import { commands, env, Uri, ViewColumn, window } from "vscode";
|
||||
import { Extension, Settings } from '../helpers';
|
||||
import { PreviewSettings } from '../models';
|
||||
import { format } from 'date-fns';
|
||||
import { DateHelper } from '../helpers/DateHelper';
|
||||
import { Article } from '.';
|
||||
import { urlJoin } from 'url-join-ts';
|
||||
import { WebviewHelper } from '@estruyf/vscode';
|
||||
|
||||
|
||||
export class Preview {
|
||||
|
||||
/**
|
||||
* Init the preview
|
||||
*/
|
||||
public static async init() {
|
||||
const settings = Preview.getSettings();
|
||||
await commands.executeCommand('setContext', CONTEXT.canOpenPreview, !!settings.host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the markdown preview in the editor
|
||||
*/
|
||||
public static async open(extensionPath: string) {
|
||||
const settings = Preview.getSettings();
|
||||
|
||||
if (!settings.host) {
|
||||
return;
|
||||
}
|
||||
|
||||
const editor = window.activeTextEditor;
|
||||
const article = editor ? ArticleHelper.getFrontMatter(editor) : null;
|
||||
let slug = article?.data ? article.data.slug : "";
|
||||
|
||||
let pathname = settings.pathname;
|
||||
if (article?.data) {
|
||||
const contentType = ArticleHelper.getContentType(article.data);
|
||||
if (contentType && contentType.previewPath) {
|
||||
pathname = contentType.previewPath;
|
||||
}
|
||||
}
|
||||
|
||||
if (!slug) {
|
||||
slug = Article.getSlug();
|
||||
}
|
||||
|
||||
if (pathname) {
|
||||
const articleDate = ArticleHelper.getDate(article);
|
||||
|
||||
try {
|
||||
slug = join(format(articleDate || new Date(), DateHelper.formatUpdate(pathname) as string), slug);
|
||||
} catch (error) {
|
||||
slug = join(pathname, slug);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the preview webview
|
||||
const webView = window.createWebviewPanel(
|
||||
'frontMatterPreview',
|
||||
'FrontMatter Preview',
|
||||
{
|
||||
viewColumn: ViewColumn.Beside,
|
||||
preserveFocus: true
|
||||
},
|
||||
{
|
||||
enableScripts: true
|
||||
}
|
||||
);
|
||||
|
||||
webView.iconPath = {
|
||||
dark: Uri.file(join(extensionPath, 'assets/icons/frontmatter-short-dark.svg')),
|
||||
light: Uri.file(join(extensionPath, 'assets/icons/frontmatter-short-light.svg'))
|
||||
}
|
||||
|
||||
const localhostUrl = await env.asExternalUri(
|
||||
Uri.parse(settings.host)
|
||||
);
|
||||
|
||||
const cspSource = webView.webview.cspSource;
|
||||
|
||||
webView.webview.onDidReceiveMessage(message => {
|
||||
switch (message.command) {
|
||||
case PreviewCommands.toVSCode.open:
|
||||
if (message.data) {
|
||||
commands.executeCommand('vscode.open', message.data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const dashboardFile = "dashboardWebView.js";
|
||||
const localPort = `9000`;
|
||||
const localServerUrl = `localhost:${localPort}`;
|
||||
|
||||
const nonce = WebviewHelper.getNonce();
|
||||
|
||||
const ext = Extension.getInstance();
|
||||
const isProd = ext.isProductionMode;
|
||||
const version = ext.getVersion();
|
||||
const isBeta = ext.isBetaVersion();
|
||||
const extensionUri = ext.extensionPath;
|
||||
|
||||
const csp = [
|
||||
`default-src 'none';`,
|
||||
`img-src ${localhostUrl} ${cspSource} http: https:;`,
|
||||
`script-src ${isProd ? `'nonce-${nonce}'` : `http://${localServerUrl} http://0.0.0.0:${localPort}`} 'unsafe-eval'`,
|
||||
`style-src ${cspSource} 'self' 'unsafe-inline' http: https:`,
|
||||
`connect-src https://o1022172.ingest.sentry.io ${isProd ? `` : `ws://${localServerUrl} ws://0.0.0.0:${localPort} http://${localServerUrl} http://0.0.0.0:${localPort}`}`,
|
||||
`frame-src ${localhostUrl} ${cspSource} http: https:;`,
|
||||
];
|
||||
|
||||
let scriptUri = "";
|
||||
if (isProd) {
|
||||
scriptUri = webView.webview.asWebviewUri(Uri.joinPath(extensionUri, 'dist', dashboardFile)).toString();
|
||||
} else {
|
||||
scriptUri = `http://${localServerUrl}/${dashboardFile}`;
|
||||
}
|
||||
|
||||
webView.webview.html = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" style="width:100%;height:100%;margin:0;padding:0;">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="${csp.join('; ')}">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<title>Front Matter Preview</title>
|
||||
</head>
|
||||
<body style="width:100%;height:100%;margin:0;padding:0;overflow:hidden">
|
||||
<div id="app" data-type="preview" data-url="${urlJoin(localhostUrl.toString(), slug || '')}" data-isProd="${isProd}" data-environment="${isBeta ? "BETA" : "main"}" data-version="${version.usedVersion}" style="width:100%;height:100%;margin:0;padding:0;"></div>
|
||||
|
||||
<script ${isProd ? `nonce="${nonce}"` : ""} src="${scriptUri}"></script>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
Telemetry.send(TelemetryEvent.openPreview);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all settings related to the preview command
|
||||
*/
|
||||
public static getSettings(): PreviewSettings {
|
||||
const host = Settings.get<string>(SETTING_PREVIEW_HOST);
|
||||
const pathname = Settings.get<string>(SETTING_PREVIEW_PATHNAME);
|
||||
|
||||
return {
|
||||
host,
|
||||
pathname
|
||||
};
|
||||
}
|
||||
}
|
||||
85
src/commands/Project.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { Telemetry } from './../helpers/Telemetry';
|
||||
import { workspace, Uri } from "vscode";
|
||||
import { join } from "path";
|
||||
import * as fs from "fs";
|
||||
import { Notifications } from "../helpers/Notifications";
|
||||
import { Template } from "./Template";
|
||||
import { Folders } from "./Folders";
|
||||
import { FrameworkDetector, Logger, Settings } from "../helpers";
|
||||
import { SETTING_CONTENT_DEFAULT_FILETYPE, TelemetryEvent } from "../constants";
|
||||
import { SettingsListener } from '../listeners/dashboard';
|
||||
|
||||
export class Project {
|
||||
|
||||
private static content = `---
|
||||
title:
|
||||
slug:
|
||||
description:
|
||||
author:
|
||||
date: 2019-08-22T15:20:28.000Z
|
||||
lastmod: 2019-08-22T15:20:28.000Z
|
||||
draft: true
|
||||
tags: []
|
||||
categories: []
|
||||
---
|
||||
`;
|
||||
|
||||
/**
|
||||
* Initialize a new "Project" instance.
|
||||
*/
|
||||
public static async init(sampleTemplate: boolean = true) {
|
||||
try {
|
||||
Settings.createTeamSettings();
|
||||
const fileType = Settings.get<string>(SETTING_CONTENT_DEFAULT_FILETYPE);
|
||||
|
||||
const folder = Template.getSettings();
|
||||
const templatePath = Project.templatePath();
|
||||
|
||||
if (!folder || !templatePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
const article = Uri.file(join(templatePath.fsPath, `article.${fileType}`));
|
||||
|
||||
if (!fs.existsSync(templatePath.fsPath)) {
|
||||
await workspace.fs.createDirectory(templatePath);
|
||||
}
|
||||
|
||||
if (sampleTemplate) {
|
||||
fs.writeFileSync(article.fsPath, Project.content, { encoding: "utf-8" });
|
||||
Notifications.info("Project initialized successfully.");
|
||||
}
|
||||
|
||||
Telemetry.send(TelemetryEvent.initialization);
|
||||
|
||||
|
||||
// Check if you can find the framework
|
||||
const wsFolder = Folders.getWorkspaceFolder();
|
||||
const framework = FrameworkDetector.get(wsFolder?.fsPath || "");
|
||||
|
||||
if (framework) {
|
||||
SettingsListener.setFramework(framework.name);
|
||||
}
|
||||
|
||||
SettingsListener.getSettings();
|
||||
} catch (err: any) {
|
||||
Logger.error(`Project::init: ${err?.message || err}`);
|
||||
Notifications.error(`Sorry, something went wrong - ${err?.message || err}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the template path for the current project
|
||||
*/
|
||||
public static templatePath() {
|
||||
const folder = Template.getSettings();
|
||||
const wsFolder = Folders.getWorkspaceFolder();
|
||||
|
||||
if (!folder || !wsFolder) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const templatePath = Uri.file(join(wsFolder.fsPath, folder));
|
||||
return templatePath;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as matter from 'gray-matter';
|
||||
import * as fs from 'fs';
|
||||
import { TaxonomyType } from "../models";
|
||||
import { CONFIG_KEY, SETTING_TAXONOMY_TAGS, SETTING_TAXONOMY_CATEGORIES, EXTENSION_NAME } from '../constants';
|
||||
import { ArticleHelper, SettingsHelper, FilesHelper } from '../helpers';
|
||||
import { TomlEngine, getFmLanguage, getFormatOpts } from '../helpers/TomlEngine';
|
||||
import { SETTING_TAXONOMY_TAGS, SETTING_TAXONOMY_CATEGORIES, EXTENSION_NAME } from '../constants';
|
||||
import { ArticleHelper, Settings as SettingsHelper, FilesHelper } from '../helpers';
|
||||
import { FrontMatterParser } from '../parsers';
|
||||
import { DumpOptions } from 'js-yaml';
|
||||
import { Notifications } from '../helpers/Notifications';
|
||||
|
||||
export class Settings {
|
||||
|
||||
@@ -21,20 +21,19 @@ export class Settings {
|
||||
});
|
||||
|
||||
if (newOption) {
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
const configSetting = type === TaxonomyType.Tag ? SETTING_TAXONOMY_TAGS : SETTING_TAXONOMY_CATEGORIES;
|
||||
let options = config.get(configSetting) as string[];
|
||||
let options = SettingsHelper.get(configSetting, true) as string[];
|
||||
if (!options) {
|
||||
options = [];
|
||||
}
|
||||
|
||||
if (options.find(o => o === newOption)) {
|
||||
vscode.window.showInformationMessage(`${EXTENSION_NAME}: The provided ${type === TaxonomyType.Tag ? "tag" : "category"} already exists.`);
|
||||
Notifications.info(`The provided ${type === TaxonomyType.Tag ? "tag" : "category"} already exists.`);
|
||||
return;
|
||||
}
|
||||
|
||||
options.push(newOption);
|
||||
await SettingsHelper.update(type, options);
|
||||
await SettingsHelper.updateTaxonomy(type, options);
|
||||
|
||||
// Ask if the new term needs to be added to the page
|
||||
const addToPage = await vscode.window.showQuickPick(["yes", "no"], { canPickMany: false, placeHolder: `Do you want to add the new ${type === TaxonomyType.Tag ? "tag" : "category"} to the page?` });
|
||||
@@ -71,8 +70,6 @@ export class Settings {
|
||||
* Export the tags/categories front matter to the user settings
|
||||
*/
|
||||
public static async export() {
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
|
||||
// Retrieve all the Markdown files
|
||||
const allMdFiles = await FilesHelper.getMdFiles();
|
||||
if (!allMdFiles) {
|
||||
@@ -92,10 +89,6 @@ export class Settings {
|
||||
const progressNr = allMdFiles.length/100;
|
||||
progress.report({ increment: 0});
|
||||
|
||||
// Get language options
|
||||
const language = getFmLanguage();
|
||||
const langOpts = getFormatOpts(language);
|
||||
|
||||
let i = 0;
|
||||
for (const file of allMdFiles) {
|
||||
progress.report({ increment: (++i/progressNr) });
|
||||
@@ -104,10 +97,7 @@ export class Settings {
|
||||
const txtData = mdFile.getText();
|
||||
if (txtData) {
|
||||
try {
|
||||
const article = matter(txtData, {
|
||||
...TomlEngine,
|
||||
...langOpts
|
||||
});
|
||||
const article = FrontMatterParser.fromFile(txtData);
|
||||
if (article && article.data) {
|
||||
const { data } = article;
|
||||
const mdTags = data["tags"];
|
||||
@@ -127,25 +117,25 @@ export class Settings {
|
||||
}
|
||||
|
||||
// Retrieve the currently known tags, and add the new ones
|
||||
let crntTags: string[] = config.get(SETTING_TAXONOMY_TAGS) as string[];
|
||||
let crntTags: string[] = SettingsHelper.get(SETTING_TAXONOMY_TAGS, true) as string[];
|
||||
if (!crntTags) { crntTags = []; }
|
||||
crntTags = [...crntTags, ...tags];
|
||||
// Update the tags and filter out the duplicates
|
||||
crntTags = [...new Set(crntTags)];
|
||||
crntTags = crntTags.sort().filter(t => !!t);
|
||||
await config.update(SETTING_TAXONOMY_TAGS, crntTags);
|
||||
await SettingsHelper.update(SETTING_TAXONOMY_TAGS, crntTags, true);
|
||||
|
||||
// Retrieve the currently known tags, and add the new ones
|
||||
let crntCategories: string[] = config.get(SETTING_TAXONOMY_CATEGORIES) as string[];
|
||||
let crntCategories: string[] = SettingsHelper.get(SETTING_TAXONOMY_CATEGORIES, true) as string[];
|
||||
if (!crntCategories) { crntCategories = []; }
|
||||
crntCategories = [...crntCategories, ...categories];
|
||||
// Update the categories and filter out the duplicates
|
||||
crntCategories = [...new Set(crntCategories)];
|
||||
crntCategories = crntCategories.sort().filter(c => !!c);
|
||||
await config.update(SETTING_TAXONOMY_CATEGORIES, crntCategories);
|
||||
await SettingsHelper.update(SETTING_TAXONOMY_CATEGORIES, crntCategories, true);
|
||||
|
||||
// Done
|
||||
vscode.window.showInformationMessage(`${EXTENSION_NAME}: Export completed. Tags: ${crntTags.length} - Categories: ${crntCategories.length}.`);
|
||||
Notifications.info(`Export completed. Tags: ${crntTags.length} - Categories: ${crntCategories.length}.`);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -154,8 +144,6 @@ export class Settings {
|
||||
* Remap a tag or category to a new one
|
||||
*/
|
||||
public static async remap() {
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
|
||||
const taxType = await vscode.window.showQuickPick([
|
||||
"Tag",
|
||||
"Category"
|
||||
@@ -171,7 +159,7 @@ export class Settings {
|
||||
let options = SettingsHelper.getTaxonomy(type);
|
||||
|
||||
if (!options || options.length === 0) {
|
||||
vscode.window.showInformationMessage(`${EXTENSION_NAME}: No ${type === TaxonomyType.Tag ? "tags" : "categories"} configured.`);
|
||||
Notifications.info(`No ${type === TaxonomyType.Tag ? "tags" : "categories"} configured.`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -222,13 +210,8 @@ export class Settings {
|
||||
progress.report({ increment: (++i/progressNr) });
|
||||
const mdFile = fs.readFileSync(file.path, { encoding: "utf8" });
|
||||
if (mdFile) {
|
||||
const language = getFmLanguage();
|
||||
const langOpts = getFormatOpts(language);
|
||||
try {
|
||||
const article = matter(mdFile, {
|
||||
...TomlEngine,
|
||||
...langOpts
|
||||
});
|
||||
const article = FrontMatterParser.fromFile(mdFile);
|
||||
if (article && article.data) {
|
||||
const { data } = article;
|
||||
let taxonomies: string[] = data[matterProp];
|
||||
@@ -243,16 +226,13 @@ export class Settings {
|
||||
data[matterProp] = [...new Set(taxonomies)].sort();
|
||||
const spaces = vscode.window.activeTextEditor?.options?.tabSize;
|
||||
// Update the file
|
||||
fs.writeFileSync(file.path, matter.stringify(article.content, article.data, {
|
||||
...TomlEngine,
|
||||
...langOpts,
|
||||
fs.writeFileSync(file.path, FrontMatterParser.toFile(article.content, article.data, {
|
||||
indent: spaces || 2
|
||||
} as DumpOptions as any), { encoding: "utf8" });
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(file.path);
|
||||
// Continue with the next file
|
||||
}
|
||||
}
|
||||
@@ -271,9 +251,9 @@ export class Settings {
|
||||
// Remove the selected option
|
||||
options = options.filter(o => o !== selectedOption);
|
||||
}
|
||||
await SettingsHelper.update(type, options);
|
||||
await SettingsHelper.updateTaxonomy(type, options);
|
||||
|
||||
vscode.window.showInformationMessage(`${EXTENSION_NAME}: ${newOptionValue ? "Remapping" : "Deleation"} of the ${selectedOption} ${type === TaxonomyType.Tag ? "tag" : "category"} completed.`);
|
||||
Notifications.info(`${newOptionValue ? "Remapping" : "Deleation"} of the ${selectedOption} ${type === TaxonomyType.Tag ? "tag" : "category"} completed.`);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
import { SETTING_SEO_DESCRIPTION_LENGTH, SETTING_SEO_TITLE_LENGTH } from './../constants/settings';
|
||||
import { CONTEXT, SETTING_SEO_DESCRIPTION_FIELD, SETTING_SEO_DESCRIPTION_LENGTH, SETTING_SEO_TITLE_LENGTH } from './../constants';
|
||||
import * as vscode from 'vscode';
|
||||
import { CONFIG_KEY } from '../constants';
|
||||
import { ArticleHelper, SeoHelper } from '../helpers';
|
||||
import { ExplorerView } from '../webview/ExplorerView';
|
||||
import { ArticleHelper, SeoHelper, Settings } from '../helpers';
|
||||
import { ExplorerView } from '../explorerView/ExplorerView';
|
||||
import { DefaultFields } from '../constants';
|
||||
import { ContentType } from '../helpers/ContentType';
|
||||
import { DataListener } from '../listeners/panel';
|
||||
import { commands } from 'vscode';
|
||||
|
||||
export class StatusListener {
|
||||
|
||||
@@ -15,15 +18,21 @@ export class StatusListener {
|
||||
public static async verify(frontMatterSB: vscode.StatusBarItem, collection: vscode.DiagnosticCollection) {
|
||||
const draftMsg = "in draft";
|
||||
const publishMsg = "to publish";
|
||||
|
||||
const draft = ContentType.getDraftField();
|
||||
if (!draft || draft.type !== "boolean") {
|
||||
frontMatterSB.hide();
|
||||
}
|
||||
|
||||
let editor = vscode.window.activeTextEditor;
|
||||
if (editor && editor.document && editor.document.languageId.toLowerCase() === "markdown") {
|
||||
if (editor && ArticleHelper.isSupportedFile()) {
|
||||
try {
|
||||
commands.executeCommand('setContext', CONTEXT.isValidFile, true);
|
||||
|
||||
const article = ArticleHelper.getFrontMatter(editor);
|
||||
|
||||
// Update the StatusBar based on the article draft state
|
||||
if (article && typeof article.data["draft"] !== "undefined") {
|
||||
// console.log(`Draft status: ${article.data["draft"]}`);
|
||||
if (article.data["draft"] === true) {
|
||||
frontMatterSB.text = `$(book) ${draftMsg}`;
|
||||
frontMatterSB.show();
|
||||
@@ -38,28 +47,35 @@ export class StatusListener {
|
||||
collection.clear();
|
||||
|
||||
// Retrieve the SEO config properties
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
const titleLength = config.get(SETTING_SEO_TITLE_LENGTH) as number || -1;
|
||||
const descLength = config.get(SETTING_SEO_DESCRIPTION_LENGTH) as number || -1;
|
||||
const titleLength = Settings.get(SETTING_SEO_TITLE_LENGTH) as number || -1;
|
||||
const descLength = Settings.get(SETTING_SEO_DESCRIPTION_LENGTH) as number || -1;
|
||||
const fieldName = Settings.get(SETTING_SEO_DESCRIPTION_FIELD) as string || DefaultFields.Description;
|
||||
|
||||
if (article.data.title && titleLength > -1) {
|
||||
SeoHelper.checkLength(editor, collection, article, "title", titleLength);
|
||||
}
|
||||
|
||||
if (article.data.description && descLength > -1) {
|
||||
SeoHelper.checkLength(editor, collection, article, "description", descLength);
|
||||
if (article.data[fieldName] && descLength > -1) {
|
||||
SeoHelper.checkLength(editor, collection, article, fieldName, descLength);
|
||||
}
|
||||
}
|
||||
|
||||
const panel = ExplorerView.getInstance();
|
||||
if (panel && panel.visible) {
|
||||
panel.pushMetadata(article!.data);
|
||||
DataListener.pushMetadata(article!.data);
|
||||
}
|
||||
|
||||
return;
|
||||
} catch (e) {
|
||||
// Nothing to do
|
||||
}
|
||||
} else {
|
||||
commands.executeCommand('setContext', CONTEXT.isValidFile, false);
|
||||
|
||||
const panel = ExplorerView.getInstance();
|
||||
if (panel && panel.visible) {
|
||||
DataListener.pushMetadata(null);
|
||||
}
|
||||
}
|
||||
|
||||
frontMatterSB.hide();
|
||||
|
||||
@@ -1,72 +1,155 @@
|
||||
import { Questions } from './../helpers/Questions';
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { CONFIG_KEY, EXTENSION_NAME, SETTING_TEMPLATES_FOLDER, SETTING_TEMPLATES_PREFIX } from '../constants';
|
||||
import { format } from 'date-fns';
|
||||
import sanitize from '../helpers/Sanitize';
|
||||
import { ArticleHelper } from '../helpers';
|
||||
import { SETTING_CONTENT_DEFAULT_FILETYPE, SETTING_TEMPLATES_FOLDER, TelemetryEvent } from '../constants';
|
||||
import { ArticleHelper, Settings } from '../helpers';
|
||||
import { Article } from '.';
|
||||
import { Notifications } from '../helpers/Notifications';
|
||||
import { CONTEXT } from '../constants';
|
||||
import { Project } from './Project';
|
||||
import { Folders } from './Folders';
|
||||
import { ContentType } from '../helpers/ContentType';
|
||||
import { ContentType as IContentType } from '../models';
|
||||
import { PagesListener } from '../listeners/dashboard';
|
||||
import { extname } from 'path';
|
||||
import { Telemetry } from '../helpers/Telemetry';
|
||||
|
||||
export class Template {
|
||||
|
||||
/**
|
||||
* Check if the template folder is available
|
||||
*/
|
||||
public static async init() {
|
||||
const isInitialized = await Template.isInitialized();
|
||||
await vscode.commands.executeCommand('setContext', CONTEXT.canInit, !isInitialized);
|
||||
|
||||
if (isInitialized) {
|
||||
await vscode.commands.executeCommand('setContext', CONTEXT.initialized, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the project is already initialized
|
||||
*/
|
||||
public static async isInitialized() {
|
||||
const wsFolder = Folders.getWorkspaceFolder();
|
||||
const folder = Template.getSettings();
|
||||
|
||||
if (!folder || !wsFolder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const templatePath = vscode.Uri.file(path.join(wsFolder.fsPath, folder));
|
||||
|
||||
try {
|
||||
await vscode.workspace.fs.stat(templatePath);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a template
|
||||
*/
|
||||
public static async generate() {
|
||||
const folder = Template.getSettings();
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
const fileType = Settings.get<string>(SETTING_CONTENT_DEFAULT_FILETYPE);
|
||||
|
||||
if (folder && editor && ArticleHelper.isSupportedFile()) {
|
||||
const article = ArticleHelper.getFrontMatter(editor);
|
||||
const clonedArticle = Object.assign({}, article);
|
||||
|
||||
const titleValue = await vscode.window.showInputBox({
|
||||
prompt: `What name would you like to give your template?`,
|
||||
placeHolder: `article`
|
||||
});
|
||||
|
||||
if (!titleValue) {
|
||||
Notifications.warning(`You did not specify a template title.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const keepContents = await vscode.window.showQuickPick(
|
||||
["yes", "no"],
|
||||
{
|
||||
canPickMany: false,
|
||||
placeHolder: `Do you want to keep the contents for the template?`,
|
||||
}
|
||||
);
|
||||
|
||||
if (!keepContents) {
|
||||
Notifications.warning(`You did not pick any of the options for keeping the template its content.`);
|
||||
return;
|
||||
}
|
||||
|
||||
await Project.init(false);
|
||||
const templatePath = Project.templatePath();
|
||||
if (templatePath) {
|
||||
let fileContents = ArticleHelper.stringifyFrontMatter(keepContents === "no" ? "" : clonedArticle.content, clonedArticle.data);
|
||||
|
||||
const templateFile = path.join(templatePath.fsPath, `${titleValue}.${fileType}`);
|
||||
fs.writeFileSync(templateFile, fileContents, { encoding: "utf-8" });
|
||||
|
||||
Notifications.info(`Template created and is now available in your ${folder} folder.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create from a template
|
||||
*/
|
||||
public static async create(folderPath: string) {
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
const folder = config.get<string>(SETTING_TEMPLATES_FOLDER);
|
||||
const prefix = config.get<string>(SETTING_TEMPLATES_PREFIX);
|
||||
const folder = Settings.get<string>(SETTING_TEMPLATES_FOLDER);
|
||||
const contentTypes = ContentType.getAll();
|
||||
|
||||
if (!folderPath) {
|
||||
this.showNoTemplates(`Incorrect project folder path retrieved.`);
|
||||
Notifications.warning(`Incorrect project folder path retrieved.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!folder) {
|
||||
this.showNoTemplates(`No templates found.`);
|
||||
Notifications.warning(`No templates found.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const templates = await vscode.workspace.findFiles(`${folder}/**/*`, "**/node_modules/**,**/archetypes/**");
|
||||
if (!templates || templates.length === 0) {
|
||||
this.showNoTemplates(`No templates found.`);
|
||||
Notifications.warning(`No templates found.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedTemplate = await vscode.window.showQuickPick(templates.map(t => path.basename(t.fsPath)), {
|
||||
placeHolder: `Select the article template to use`
|
||||
placeHolder: `Select the content template to use`
|
||||
});
|
||||
if (!selectedTemplate) {
|
||||
this.showNoTemplates(`No template selected.`);
|
||||
Notifications.warning(`No template selected.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const titleValue = await vscode.window.showInputBox({
|
||||
prompt: `What would you like to use as a title for the new article?`,
|
||||
placeHolder: `Article title`
|
||||
});
|
||||
const titleValue = await Questions.ContentTitle();
|
||||
if (!titleValue) {
|
||||
this.showNoTemplates(`You did not specify an article title.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the template read
|
||||
const template = templates.find(t => t.fsPath.endsWith(selectedTemplate));
|
||||
if (!template) {
|
||||
this.showNoTemplates(`Article template could not be found.`);
|
||||
Notifications.warning(`Content template could not be found.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const fileExt = path.parse(selectedTemplate).ext;
|
||||
const sanitizedName = sanitize(titleValue.toLowerCase().replace(/ /g, "-"));
|
||||
let newFileName = `${sanitizedName}${fileExt}`;
|
||||
if (prefix && typeof prefix === "string") {
|
||||
newFileName = `${format(new Date(), prefix)}-${newFileName}`;
|
||||
const templateData = ArticleHelper.getFrontMatterByPath(template.fsPath);
|
||||
let contentType: IContentType | undefined;
|
||||
if (templateData && templateData.data && templateData.data.type) {
|
||||
contentType = contentTypes?.find(t => t.name === templateData.data.type);
|
||||
}
|
||||
|
||||
const newFilePath = path.join(folderPath, newFileName);
|
||||
if (fs.existsSync(newFilePath)) {
|
||||
this.showNoTemplates(`File already exists, please remove it before creating a new one with the same title.`);
|
||||
const fileExtension = extname(template.fsPath).replace(".", "");
|
||||
let newFilePath: string | undefined = ArticleHelper.createContent(contentType, folderPath, titleValue, fileExtension);
|
||||
if (!newFilePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -76,18 +159,12 @@ export class Template {
|
||||
// Update the properties inside the template
|
||||
let frontMatter = ArticleHelper.getFrontMatterByPath(newFilePath);
|
||||
if (!frontMatter) {
|
||||
this.showNoTemplates(`Something failed when retrieving the newly created file.`);
|
||||
Notifications.warning(`Something failed when retrieving the newly created file.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (frontMatter.data) {
|
||||
const fmData = frontMatter.data;
|
||||
if (typeof fmData.title !== "undefined") {
|
||||
fmData.title = titleValue;
|
||||
}
|
||||
if (typeof fmData.slug !== "undefined") {
|
||||
fmData.slug = sanitizedName;
|
||||
}
|
||||
frontMatter.data = ArticleHelper.updatePlaceholders(frontMatter.data, titleValue);
|
||||
|
||||
frontMatter = Article.updateDate(frontMatter);
|
||||
|
||||
@@ -101,13 +178,19 @@ export class Template {
|
||||
vscode.window.showTextDocument(txtDoc);
|
||||
}
|
||||
|
||||
vscode.window.showInformationMessage(`${EXTENSION_NAME}: Your new article has been created.`);
|
||||
Notifications.info(`Your new content has been created.`);
|
||||
|
||||
Telemetry.send(TelemetryEvent.createContentFromTemplate);
|
||||
|
||||
// Trigger a refresh for the dashboard
|
||||
PagesListener.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a warning message when no templates are found
|
||||
* Get the folder settings
|
||||
*/
|
||||
private static showNoTemplates(value: string) {
|
||||
vscode.window.showWarningMessage(`${EXTENSION_NAME}: ${value}`);
|
||||
public static getSettings() {
|
||||
const folder = Settings.get<string>(SETTING_TEMPLATES_FOLDER);
|
||||
return folder;
|
||||
}
|
||||
}
|
||||
233
src/commands/Wysiwyg.ts
Normal file
@@ -0,0 +1,233 @@
|
||||
import { commands, window, Selection, QuickPickItem } from "vscode";
|
||||
import { COMMAND_NAME, CONTEXT, SETTING_CONTENT_WYSIWYG } from "../constants";
|
||||
import { Settings } from "../helpers";
|
||||
|
||||
enum MarkupType {
|
||||
bold = 1,
|
||||
italic,
|
||||
strikethrough,
|
||||
code,
|
||||
codeblock,
|
||||
blockquote,
|
||||
heading,
|
||||
unorderedList,
|
||||
orderedList,
|
||||
taskList
|
||||
}
|
||||
|
||||
export class Wysiwyg {
|
||||
|
||||
/**
|
||||
* Registers the markup commands for the WYSIWYG controls
|
||||
* @param subscriptions
|
||||
* @returns
|
||||
*/
|
||||
public static async registerCommands(subscriptions: any) {
|
||||
|
||||
const wysiwygEnabled = Settings.get(SETTING_CONTENT_WYSIWYG);
|
||||
|
||||
if (!wysiwygEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
await commands.executeCommand('setContext', CONTEXT.wysiwyg, true);
|
||||
|
||||
// Surrounding markup
|
||||
subscriptions.push(commands.registerCommand(COMMAND_NAME.bold, () => this.addMarkup(MarkupType.bold)));
|
||||
subscriptions.push(commands.registerCommand(COMMAND_NAME.italic, () => this.addMarkup(MarkupType.italic)));
|
||||
subscriptions.push(commands.registerCommand(COMMAND_NAME.strikethrough, () => this.addMarkup(MarkupType.strikethrough)));
|
||||
subscriptions.push(commands.registerCommand(COMMAND_NAME.code, () => this.addMarkup(MarkupType.code)));
|
||||
subscriptions.push(commands.registerCommand(COMMAND_NAME.codeblock, () => this.addMarkup(MarkupType.codeblock)));
|
||||
|
||||
// Prefix markup
|
||||
subscriptions.push(commands.registerCommand(COMMAND_NAME.heading, () => this.addMarkup(MarkupType.heading)));
|
||||
subscriptions.push(commands.registerCommand(COMMAND_NAME.blockquote, () => this.addMarkup(MarkupType.blockquote)));
|
||||
subscriptions.push(commands.registerCommand(COMMAND_NAME.unorderedlist, () => this.addMarkup(MarkupType.unorderedList)));
|
||||
subscriptions.push(commands.registerCommand(COMMAND_NAME.orderedlist, () => this.addMarkup(MarkupType.orderedList)));
|
||||
subscriptions.push(commands.registerCommand(COMMAND_NAME.taskList, () => this.addMarkup(MarkupType.taskList)));
|
||||
|
||||
// Options
|
||||
subscriptions.push(commands.registerCommand(COMMAND_NAME.options, async () => {
|
||||
const qpItems: QuickPickItem[] = [
|
||||
{ label: "$(list-unordered) Unordered list", detail: "Add an unordered list", alwaysShow: true, },
|
||||
{ label: "$(list-ordered) Ordered list", detail: "Add an ordered list", alwaysShow: true },
|
||||
{ label: "$(tasklist) Task list", detail: "Add a task list", alwaysShow: true },
|
||||
{ label: "$(code) Code", detail: "Add inline code snippet", alwaysShow: true },
|
||||
{ label: "$(symbol-namespace) Code block", detail: "Add a code block", alwaysShow: true },
|
||||
{ label: "$(quote) Blockquote", detail: "Add a blockquote", alwaysShow: true },
|
||||
]
|
||||
|
||||
const option = await window.showQuickPick([ ...qpItems ], {
|
||||
placeHolder: "Which type of markup would you like to insert?",
|
||||
canPickMany: false,
|
||||
ignoreFocusOut: false,
|
||||
});
|
||||
|
||||
if (option) {
|
||||
if (option.label === qpItems[0].label) {
|
||||
await this.addMarkup(MarkupType.unorderedList);
|
||||
} else if (option.label === qpItems[1].label) {
|
||||
await this.addMarkup(MarkupType.orderedList);
|
||||
} else if (option.label === qpItems[2].label) {
|
||||
await this.addMarkup(MarkupType.taskList);
|
||||
} else if (option.label === qpItems[3].label) {
|
||||
await this.addMarkup(MarkupType.code);
|
||||
} else if (option.label === qpItems[4].label) {
|
||||
await this.addMarkup(MarkupType.codeblock);
|
||||
} else if (option.label === qpItems[5].label) {
|
||||
await this.addMarkup(MarkupType.blockquote);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the markup to the content
|
||||
* @param type
|
||||
* @returns
|
||||
*/
|
||||
private static async addMarkup(type: MarkupType) {
|
||||
const editor = window.activeTextEditor;
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selection = editor.selection;
|
||||
const hasTextSelection = !selection.isEmpty;
|
||||
|
||||
const markers = this.getMarkers(type);
|
||||
if (!markers) {
|
||||
return;
|
||||
}
|
||||
|
||||
const crntSelection = selection.active;
|
||||
|
||||
if (hasTextSelection) {
|
||||
// Replace the selection and surround with the markup
|
||||
const selectionText = editor.document.getText(selection);
|
||||
const txt = await this.insertText(markers, type, selectionText);
|
||||
|
||||
editor.edit(builder => {
|
||||
builder.replace(selection, txt);
|
||||
});
|
||||
} else {
|
||||
const txt = await this.insertText(markers, type);
|
||||
|
||||
// Insert the markers where cursor is located.
|
||||
const markerLength = this.isMarkupWrapping(type) ? txt.length + 1 : markers.length;
|
||||
let newPosition = crntSelection.with(crntSelection.line, crntSelection.character + markerLength);
|
||||
|
||||
await editor.edit(builder => {
|
||||
builder.insert(newPosition, txt);
|
||||
});
|
||||
|
||||
if (type === MarkupType.codeblock) {
|
||||
newPosition = crntSelection.with(crntSelection.line + 1, 0);
|
||||
}
|
||||
|
||||
editor.selection = new Selection(newPosition, newPosition);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the text will be wrapped
|
||||
* @param type
|
||||
* @returns
|
||||
*/
|
||||
private static isMarkupWrapping(type: MarkupType) {
|
||||
return (
|
||||
type === MarkupType.blockquote ||
|
||||
type === MarkupType.heading ||
|
||||
type === MarkupType.unorderedList ||
|
||||
type === MarkupType.orderedList ||
|
||||
type === MarkupType.taskList
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert text at the current cursor position
|
||||
*/
|
||||
private static async insertText(marker: string | undefined, type: MarkupType, text: string | null = null) {
|
||||
const crntText = text || this.lineBreak(type);
|
||||
|
||||
if (this.isMarkupWrapping(type)) {
|
||||
if (type === MarkupType.heading) {
|
||||
const headingLvl = await window.showQuickPick([
|
||||
"Heading 1",
|
||||
"Heading 2",
|
||||
"Heading 3",
|
||||
"Heading 4",
|
||||
"Heading 5",
|
||||
"Heading 6"
|
||||
], {
|
||||
canPickMany: false,
|
||||
placeHolder: "Which heading level do you want to insert?",
|
||||
ignoreFocusOut: false
|
||||
});
|
||||
|
||||
if (headingLvl) {
|
||||
const headingNr = parseInt(headingLvl.replace("Heading ", ""));
|
||||
return `${Array(headingNr + 1).join(marker)} ${crntText}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (type === MarkupType.unorderedList || type === MarkupType.taskList) {
|
||||
const lines = crntText.split("\n").map(line => `${marker} ${line}`);
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
if (type === MarkupType.orderedList) {
|
||||
const lines = crntText.split("\n").map((line, idx) => `${idx+1}. ${line}`);
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
return `${marker} ${crntText}`;
|
||||
} else {
|
||||
return `${marker}${crntText}${marker}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if linebreak needs to be added
|
||||
* @param type
|
||||
* @returns
|
||||
*/
|
||||
private static lineBreak(type: MarkupType) {
|
||||
if (type === MarkupType.codeblock) {
|
||||
return `\n\n`;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the type of markers
|
||||
* @param type
|
||||
* @returns
|
||||
*/
|
||||
private static getMarkers(type: MarkupType) {
|
||||
switch(type) {
|
||||
case MarkupType.bold:
|
||||
return `**`;
|
||||
case MarkupType.italic:
|
||||
return `*`;
|
||||
case MarkupType.strikethrough:
|
||||
return `~~`;
|
||||
case MarkupType.code:
|
||||
return "`";
|
||||
case MarkupType.codeblock:
|
||||
return "```";
|
||||
case MarkupType.blockquote:
|
||||
return ">";
|
||||
case MarkupType.heading:
|
||||
return "#";
|
||||
case MarkupType.unorderedList:
|
||||
return "-";
|
||||
case MarkupType.orderedList:
|
||||
return "1.";
|
||||
case MarkupType.taskList:
|
||||
return "- [ ]";
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/components/features/FeatureFlag.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export interface IFeatureFlagProps {
|
||||
flag: string;
|
||||
features: string[] | null;
|
||||
alternative?: JSX.Element;
|
||||
}
|
||||
|
||||
export const FeatureFlag: React.FunctionComponent<IFeatureFlagProps> = ({ flag, features, alternative, children }: React.PropsWithChildren<IFeatureFlagProps>) => {
|
||||
|
||||
if (!features ||( features.length > 0 && !features.includes(flag))) {
|
||||
if (alternative) {
|
||||
return alternative;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
};
|
||||
13
src/components/icons/CompressIcon.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export interface ICompressIconProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const CompressIcon: React.FunctionComponent<ICompressIconProps> = ({className}: React.PropsWithChildren<ICompressIconProps>) => {
|
||||
return (
|
||||
<svg className={className || ""} aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||
<path fill="currentColor" d="M436 192H312c-13.3 0-24-10.7-24-24V44c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v84h84c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12zm-276-24V44c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v84H12c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h124c13.3 0 24-10.7 24-24zm0 300V344c0-13.3-10.7-24-24-24H12c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h84v84c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm192 0v-84h84c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12H312c-13.3 0-24 10.7-24 24v124c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12z"></path>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
41
src/components/uniforms-frontmatter/AutoField.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import * as invariant from 'invariant';
|
||||
import { createAutoField } from 'uniforms';
|
||||
import { PreviewImageField } from '../../panelWebView/components/Fields/PreviewImageField';
|
||||
export { AutoFieldProps } from 'uniforms';
|
||||
|
||||
import BoolField from './BoolField';
|
||||
import DateField from './DateField';
|
||||
import ListField from './ListField';
|
||||
import NestField from './NestField';
|
||||
import NumField from './NumField';
|
||||
import RadioField from './RadioField';
|
||||
import SelectField from './SelectField';
|
||||
import TextField from './TextField';
|
||||
|
||||
const AutoField = createAutoField(props => {
|
||||
|
||||
if (props.allowedValues) {
|
||||
return props.checkboxes && props.fieldType !== Array
|
||||
? RadioField
|
||||
: SelectField;
|
||||
}
|
||||
|
||||
switch (props.fieldType) {
|
||||
case Array:
|
||||
return ListField;
|
||||
case Boolean:
|
||||
return BoolField;
|
||||
case Date:
|
||||
return DateField;
|
||||
case Number:
|
||||
return NumField;
|
||||
case Object:
|
||||
return NestField;
|
||||
case String:
|
||||
return TextField;
|
||||
}
|
||||
|
||||
return invariant(false, 'Unsupported field type: %s', props.fieldType);
|
||||
});
|
||||
|
||||
export default AutoField;
|
||||
29
src/components/uniforms-frontmatter/AutoFields.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import { ComponentType, createElement, Fragment } from 'react';
|
||||
import { useForm } from 'uniforms';
|
||||
|
||||
import AutoField from './AutoField';
|
||||
|
||||
export type AutoFieldsProps = {
|
||||
autoField?: ComponentType<{ name: string }>;
|
||||
element?: ComponentType | string;
|
||||
fields?: string[];
|
||||
omitFields?: string[];
|
||||
};
|
||||
|
||||
export default function AutoFields({
|
||||
autoField = AutoField,
|
||||
element = Fragment,
|
||||
fields,
|
||||
omitFields = [],
|
||||
...props
|
||||
}: AutoFieldsProps) {
|
||||
const { schema } = useForm();
|
||||
|
||||
return createElement(
|
||||
element,
|
||||
props,
|
||||
(fields ?? schema.getSubfields())
|
||||
.filter(field => !omitFields.includes(field))
|
||||
.map(field => createElement(autoField, { key: field, name: field })),
|
||||
);
|
||||
}
|
||||
13
src/components/uniforms-frontmatter/AutoForm.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { AutoForm } from 'uniforms';
|
||||
|
||||
import ValidatedQuickForm from './ValidatedQuickForm';
|
||||
|
||||
function Auto(parent: any) {
|
||||
class _ extends AutoForm.Auto(parent) {
|
||||
static Auto = Auto;
|
||||
}
|
||||
|
||||
return _ as unknown as AutoForm;
|
||||
}
|
||||
|
||||
export default Auto(ValidatedQuickForm);
|
||||
13
src/components/uniforms-frontmatter/BaseForm.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { BaseForm } from 'uniforms';
|
||||
|
||||
function Unstyled(parent: any) {
|
||||
class _ extends parent {
|
||||
static Unstyled = Unstyled;
|
||||
|
||||
static displayName = `Unstyled${parent.displayName}`;
|
||||
}
|
||||
|
||||
return _ as unknown as typeof BaseForm;
|
||||
}
|
||||
|
||||
export default Unstyled(BaseForm);
|
||||
52
src/components/uniforms-frontmatter/BoolField.css
Normal file
@@ -0,0 +1,52 @@
|
||||
.field__toggle {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.field__toggle input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.field__toggle__slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: var(--frontmatter-toggle-secondaryBackground, var(--vscode-button-secondaryBackground));
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
border-radius: 34px;
|
||||
}
|
||||
|
||||
.field__toggle__slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
background-color: white;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
input:checked + .field__toggle__slider {
|
||||
background-color: var(--frontmatter-toggle-background, var(--vscode-button-background));
|
||||
}
|
||||
|
||||
input:focus + .field__toggle__slider {
|
||||
box-shadow: 0 0 1px var(--frontmatter-toggle-background, var(--vscode-button-background));
|
||||
}
|
||||
|
||||
input:checked + .field__toggle__slider:before {
|
||||
-webkit-transform: translateX(26px);
|
||||
-ms-transform: translateX(26px);
|
||||
transform: translateX(26px);
|
||||
}
|
||||
44
src/components/uniforms-frontmatter/BoolField.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import * as React from 'react';
|
||||
import { Ref } from 'react';
|
||||
import { HTMLFieldProps, connectField, filterDOMProps } from 'uniforms';
|
||||
import './BoolField.css';
|
||||
import { LabelField } from './LabelField';
|
||||
|
||||
export type BoolFieldProps = HTMLFieldProps<
|
||||
boolean,
|
||||
HTMLDivElement,
|
||||
{ inputRef?: Ref<HTMLInputElement> }
|
||||
>;
|
||||
|
||||
function Bool({
|
||||
disabled,
|
||||
id,
|
||||
inputRef,
|
||||
label,
|
||||
name,
|
||||
onChange,
|
||||
readOnly,
|
||||
value,
|
||||
...props
|
||||
}: BoolFieldProps) {
|
||||
return (
|
||||
<div {...filterDOMProps(props)}>
|
||||
<LabelField label={label} id={id} required={props.required} />
|
||||
|
||||
<label className="field__toggle">
|
||||
<input
|
||||
checked={value || false}
|
||||
disabled={disabled}
|
||||
id={id}
|
||||
name={name}
|
||||
onChange={() => !disabled && !readOnly && onChange(!value)}
|
||||
ref={inputRef}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span className="field__toggle__slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default connectField<BoolFieldProps>(Bool, { kind: 'leaf' });
|
||||
57
src/components/uniforms-frontmatter/DateField.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import * as React from 'react';
|
||||
import { Ref } from 'react';
|
||||
import { HTMLFieldProps, connectField, filterDOMProps } from 'uniforms';
|
||||
|
||||
/* istanbul ignore next */
|
||||
const DateConstructor = (typeof global === 'object' ? global : window).Date;
|
||||
const dateFormat = (value?: Date) => value?.toISOString().slice(0, -8);
|
||||
|
||||
export type DateFieldProps = HTMLFieldProps<
|
||||
Date,
|
||||
HTMLDivElement,
|
||||
{ inputRef?: Ref<HTMLInputElement>; max?: Date; min?: Date }
|
||||
>;
|
||||
|
||||
function Date({
|
||||
disabled,
|
||||
id,
|
||||
inputRef,
|
||||
label,
|
||||
max,
|
||||
min,
|
||||
name,
|
||||
onChange,
|
||||
placeholder,
|
||||
readOnly,
|
||||
value,
|
||||
...props
|
||||
}: DateFieldProps) {
|
||||
return (
|
||||
<div {...filterDOMProps(props)}>
|
||||
{label && <label htmlFor={id}>{label}</label>}
|
||||
|
||||
<input
|
||||
disabled={disabled}
|
||||
id={id}
|
||||
max={dateFormat(max)}
|
||||
min={dateFormat(min)}
|
||||
name={name}
|
||||
onChange={event => {
|
||||
const date = new DateConstructor(event.target.valueAsNumber);
|
||||
if (date.getFullYear() < 10000) {
|
||||
onChange(date);
|
||||
} else if (isNaN(event.target.valueAsNumber)) {
|
||||
onChange(undefined);
|
||||
}
|
||||
}}
|
||||
placeholder={placeholder}
|
||||
readOnly={readOnly}
|
||||
ref={inputRef}
|
||||
type="datetime-local"
|
||||
value={dateFormat(value) ?? ''}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default connectField<DateFieldProps>(Date, { kind: 'leaf' });
|
||||
19
src/components/uniforms-frontmatter/ErrorField.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import * as React from 'react';
|
||||
import { HTMLProps } from 'react';
|
||||
import { Override, connectField, filterDOMProps } from 'uniforms';
|
||||
|
||||
export type ErrorFieldProps = Override<
|
||||
Omit<HTMLProps<HTMLDivElement>, 'onChange'>,
|
||||
{ error?: any; errorMessage?: string }
|
||||
>;
|
||||
|
||||
function Error({ children, error, errorMessage, ...props }: ErrorFieldProps) {
|
||||
return !error ? null : (
|
||||
<div {...filterDOMProps(props)}>{children || errorMessage}</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default connectField<ErrorFieldProps>(Error, {
|
||||
initialValue: false,
|
||||
kind: 'leaf',
|
||||
});
|
||||
18
src/components/uniforms-frontmatter/ErrorsField.css
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
|
||||
.autoform-error {
|
||||
background-color: var(--frontmatter-error-background, var(--vscode-inputValidation-errorBackground));
|
||||
border: 1px solid var(--frontmatter-error-border, var(--vscode-inputValidation-errorBorder));
|
||||
border-radius: 2px;
|
||||
margin: 20px 0px;
|
||||
padding: 10px;
|
||||
color: var(--frontmatter-error-foreground, var(--vscode-editor-foreground));
|
||||
|
||||
ul {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
}
|
||||