mirror of
https://github.com/foambubble/foam.git
synced 2026-01-10 22:48:09 -05:00
Compare commits
377 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf70c97fd7 | ||
|
|
5d8b9756a9 | ||
|
|
f63b7b2c9b | ||
|
|
875fde8a45 | ||
|
|
5ef292382e | ||
|
|
0fa0176e1b | ||
|
|
d312eca3d1 | ||
|
|
bff39be923 | ||
|
|
52c16b15df | ||
|
|
f2a5c6c45a | ||
|
|
6c354a13d8 | ||
|
|
8826a2b358 | ||
|
|
761eeb7336 | ||
|
|
6d9a8305ce | ||
|
|
4ee065ff9a | ||
|
|
df3cd90ce7 | ||
|
|
0af6c4de15 | ||
|
|
3d49146087 | ||
|
|
8cb2246278 | ||
|
|
72890d33cb | ||
|
|
70b11a921a | ||
|
|
f457b14ec0 | ||
|
|
bbb4801486 | ||
|
|
80b1537324 | ||
|
|
007315c3a1 | ||
|
|
ec1750d5a6 | ||
|
|
5480c65a48 | ||
|
|
7afa286ea5 | ||
|
|
4a7c2d9de2 | ||
|
|
1f6b2abce2 | ||
|
|
5f017ee4ea | ||
|
|
61032668be | ||
|
|
9192cefc7c | ||
|
|
2f966276b5 | ||
|
|
145970a6cb | ||
|
|
54a6ffdf01 | ||
|
|
40740db416 | ||
|
|
145653ec85 | ||
|
|
503b486179 | ||
|
|
a36d39acf8 | ||
|
|
fb92790a0a | ||
|
|
dcb951004a | ||
|
|
3b5906a1cf | ||
|
|
dc541dea2a | ||
|
|
eb908cb689 | ||
|
|
967ff18d8d | ||
|
|
89298b9652 | ||
|
|
e1694f298b | ||
|
|
61961f0c1d | ||
|
|
2822bfaa9e | ||
|
|
9af4e814ac | ||
|
|
f8f2ecbec8 | ||
|
|
6d4db373bf | ||
|
|
9149546445 | ||
|
|
4893d55ed3 | ||
|
|
53caa94013 | ||
|
|
eda46ac006 | ||
|
|
37837a314d | ||
|
|
fc084c736e | ||
|
|
ca5229f557 | ||
|
|
f96282828c | ||
|
|
c863586cd0 | ||
|
|
a6c0cc603f | ||
|
|
8ed2d17793 | ||
|
|
08aae069fe | ||
|
|
09c1426926 | ||
|
|
4694cfae8d | ||
|
|
9ca36c9d81 | ||
|
|
65367b53b4 | ||
|
|
43a2984047 | ||
|
|
b0800fd30e | ||
|
|
5cbc722929 | ||
|
|
f57b8ec9b6 | ||
|
|
0c7b1458f5 | ||
|
|
8c31b563cc | ||
|
|
ca7bfdff1d | ||
|
|
1fe786c5c2 | ||
|
|
649bd6440a | ||
|
|
7a562aa0aa | ||
|
|
0bab17c130 | ||
|
|
8121223e30 | ||
|
|
793664ac59 | ||
|
|
4c5430d2b1 | ||
|
|
ebef851f5a | ||
|
|
253ee94b1c | ||
|
|
9ffd465a32 | ||
|
|
ff3dacdbbf | ||
|
|
0a6350464b | ||
|
|
fe0228bdcc | ||
|
|
471260bdd3 | ||
|
|
a22f1b46dc | ||
|
|
318641ae04 | ||
|
|
12a4fd98c3 | ||
|
|
a93360eb1b | ||
|
|
0938de2694 | ||
|
|
a120f368c3 | ||
|
|
c028689012 | ||
|
|
27665154db | ||
|
|
659621e75d | ||
|
|
3ed6c5306c | ||
|
|
ffe7a32886 | ||
|
|
7b99804022 | ||
|
|
d24d4b1e83 | ||
|
|
d1a145545e | ||
|
|
46f3753425 | ||
|
|
4e0f6a5eeb | ||
|
|
6b79a5cad0 | ||
|
|
6756c43ab0 | ||
|
|
bcecb5d9c7 | ||
|
|
71ddc3c4bc | ||
|
|
7a10c45ed8 | ||
|
|
c669e5436b | ||
|
|
afbb40fe9b | ||
|
|
c7cdb509ce | ||
|
|
7b96936926 | ||
|
|
1d223683f1 | ||
|
|
94bf3ea469 | ||
|
|
de9224b5c7 | ||
|
|
6c0064390a | ||
|
|
2903acb34e | ||
|
|
d55b592264 | ||
|
|
e525051617 | ||
|
|
9a49c9ff66 | ||
|
|
b0727307b0 | ||
|
|
a004e61b2a | ||
|
|
1a7e633edc | ||
|
|
fb78e2baff | ||
|
|
9d143394dc | ||
|
|
249e3dd924 | ||
|
|
3398ab08ac | ||
|
|
2a197cfee5 | ||
|
|
e95aa05059 | ||
|
|
dc8df6fd1e | ||
|
|
babcbb1ec1 | ||
|
|
82e46b22ff | ||
|
|
1999b04ea2 | ||
|
|
ebc9c5761e | ||
|
|
f37f2e20a2 | ||
|
|
f11a779132 | ||
|
|
20694278a6 | ||
|
|
6a849d220b | ||
|
|
6001dc0214 | ||
|
|
93cedcc490 | ||
|
|
cad0c38965 | ||
|
|
bdb95a0832 | ||
|
|
e0580d39bf | ||
|
|
279b3b48f1 | ||
|
|
e3c63fca89 | ||
|
|
948b7db5ef | ||
|
|
503a8f5f18 | ||
|
|
8ab4f13543 | ||
|
|
894bf12899 | ||
|
|
a3b375e248 | ||
|
|
c840070a3a | ||
|
|
8a6551f281 | ||
|
|
88ae96cf25 | ||
|
|
acfd2e1fc1 | ||
|
|
6b02a87538 | ||
|
|
1a99e693df | ||
|
|
dd467ce86f | ||
|
|
7d7446ef7e | ||
|
|
6be4f002b8 | ||
|
|
bb6faee06d | ||
|
|
31cfeb3034 | ||
|
|
5d11818ffc | ||
|
|
e7ee143544 | ||
|
|
aa311b2688 | ||
|
|
0fca141a7b | ||
|
|
6a4bd341ab | ||
|
|
764750f591 | ||
|
|
2686b9a365 | ||
|
|
5a6ef644bd | ||
|
|
d7c92f8284 | ||
|
|
c2e5e4bf2a | ||
|
|
9d0ba879d2 | ||
|
|
9606dcc64c | ||
|
|
d70e441790 | ||
|
|
dde11f8c6f | ||
|
|
cd9ee4d556 | ||
|
|
a8296c2c88 | ||
|
|
13a340eb1d | ||
|
|
d2dd979e70 | ||
|
|
4989796cb0 | ||
|
|
d24814d065 | ||
|
|
4a410d1f5c | ||
|
|
ccb92ad5ee | ||
|
|
e6512cffa8 | ||
|
|
1fa4f37d96 | ||
|
|
27b9b451ad | ||
|
|
362d6f8e09 | ||
|
|
cef8d2a532 | ||
|
|
22b837f252 | ||
|
|
07e02c2d69 | ||
|
|
931ad7a5b6 | ||
|
|
db7eb9775f | ||
|
|
b25152d115 | ||
|
|
1545079c62 | ||
|
|
4835164902 | ||
|
|
06efdc2865 | ||
|
|
b68fd7e138 | ||
|
|
d8baa2fd36 | ||
|
|
7f587095e8 | ||
|
|
77ad245319 | ||
|
|
b892c783da | ||
|
|
e4f6259104 | ||
|
|
aa197239fc | ||
|
|
8f3c23dd60 | ||
|
|
9a027c08ba | ||
|
|
959d0f1ea1 | ||
|
|
57e32c4349 | ||
|
|
f168f66368 | ||
|
|
103ff12b2d | ||
|
|
96a3afa132 | ||
|
|
d586e63104 | ||
|
|
2fba6e9008 | ||
|
|
cdbb965661 | ||
|
|
0c958e31f6 | ||
|
|
fd84fcfd74 | ||
|
|
becf495edc | ||
|
|
4d99883c03 | ||
|
|
8bd679c751 | ||
|
|
8986ee286c | ||
|
|
51b1af1981 | ||
|
|
4276e8043f | ||
|
|
8d1e9b15ce | ||
|
|
bfcfad32e8 | ||
|
|
abe18cc961 | ||
|
|
9490aa2dad | ||
|
|
6c3f4588b3 | ||
|
|
21b8c5b827 | ||
|
|
c66ed74aea | ||
|
|
3876811fb6 | ||
|
|
d9299ee9d4 | ||
|
|
23e21a62f3 | ||
|
|
e7c8d5a4eb | ||
|
|
3ef1b69b2e | ||
|
|
5859b2a9c6 | ||
|
|
54086fdd7e | ||
|
|
a308dfd109 | ||
|
|
e327115673 | ||
|
|
c019767476 | ||
|
|
5e8b817a82 | ||
|
|
e0acc0ba8c | ||
|
|
df4efc5138 | ||
|
|
1e2b3b1bc3 | ||
|
|
eee364de50 | ||
|
|
3ed2bcd37b | ||
|
|
797aa9f29a | ||
|
|
30ab58485c | ||
|
|
ba98f1990c | ||
|
|
6c1d6868f7 | ||
|
|
e773e1ff68 | ||
|
|
86e2bb1ba0 | ||
|
|
fc2fb6a0ab | ||
|
|
956d0119be | ||
|
|
8ddb6a2d12 | ||
|
|
fb9447630f | ||
|
|
06a5988a52 | ||
|
|
fac2247382 | ||
|
|
b089b997bb | ||
|
|
a504054504 | ||
|
|
a00d18cfbb | ||
|
|
5ca7c3eb52 | ||
|
|
571b6a3528 | ||
|
|
b6c9eac86c | ||
|
|
557330413c | ||
|
|
20894a1166 | ||
|
|
d0b3d5ff11 | ||
|
|
34fb62bb0b | ||
|
|
f297139e0c | ||
|
|
09e13f77b0 | ||
|
|
56d8c4c7a0 | ||
|
|
626a323193 | ||
|
|
25d9b5e459 | ||
|
|
c2241f16de | ||
|
|
5dee7cb2c0 | ||
|
|
154ded382b | ||
|
|
5de69ff3c3 | ||
|
|
8aefcfd515 | ||
|
|
e0e08a2a0f | ||
|
|
93c5d2f80c | ||
|
|
1c294d84c5 | ||
|
|
f1b15eceed | ||
|
|
96f410a453 | ||
|
|
95a14d5dd6 | ||
|
|
10905fd703 | ||
|
|
f4eaf5c5ff | ||
|
|
b4830eaf30 | ||
|
|
0cda6aed50 | ||
|
|
89c9bb5a7f | ||
|
|
941e870a65 | ||
|
|
c6655c33ff | ||
|
|
c94fb18f8a | ||
|
|
cbd55bac74 | ||
|
|
83a90177b9 | ||
|
|
37aec28af6 | ||
|
|
447f7fc068 | ||
|
|
ad1243665a | ||
|
|
f07de73bc4 | ||
|
|
c431ccfb62 | ||
|
|
f31ef897cc | ||
|
|
7a5f45c0ce | ||
|
|
df32d9e708 | ||
|
|
b3d4691bfa | ||
|
|
f5260f7d3f | ||
|
|
9b4b7ec84d | ||
|
|
52b7f86a9f | ||
|
|
2db7060124 | ||
|
|
a4f04b3b6b | ||
|
|
b5a8a5d7c7 | ||
|
|
f5a29e431c | ||
|
|
5a7a1ba89f | ||
|
|
b054bafc78 | ||
|
|
8acb60253a | ||
|
|
3c69508dcb | ||
|
|
a368be9b47 | ||
|
|
b1f76bb653 | ||
|
|
d4bc16b9bd | ||
|
|
882b0b6012 | ||
|
|
048623d910 | ||
|
|
f2fbe927ae | ||
|
|
d0ee71be1b | ||
|
|
2a14dc0c57 | ||
|
|
745acbabd3 | ||
|
|
c226cddcd8 | ||
|
|
1b0d3239b5 | ||
|
|
cddf3bc769 | ||
|
|
bd158e9b8e | ||
|
|
5e648ca9c6 | ||
|
|
cc53f995f0 | ||
|
|
44fea21bc7 | ||
|
|
2b70e49e95 | ||
|
|
f5c4cba799 | ||
|
|
e06f46e393 | ||
|
|
4ce51673cc | ||
|
|
4db9409679 | ||
|
|
0e6b9f8c83 | ||
|
|
7b4a56fe69 | ||
|
|
aa734e9b9b | ||
|
|
3f7d235b9f | ||
|
|
0b879c0714 | ||
|
|
8b7400c20f | ||
|
|
d2feee8c75 | ||
|
|
2113705fb6 | ||
|
|
4758923188 | ||
|
|
275028ffa5 | ||
|
|
8b425ff420 | ||
|
|
64638868c0 | ||
|
|
7a2756eb1d | ||
|
|
540371bf96 | ||
|
|
42b32103f5 | ||
|
|
1d264dcb22 | ||
|
|
7f8c58084b | ||
|
|
6b2dda4a71 | ||
|
|
a6cb50f3d6 | ||
|
|
09c2198928 | ||
|
|
431da1b385 | ||
|
|
57e0621c24 | ||
|
|
ebd1008215 | ||
|
|
0df958c3a4 | ||
|
|
14709313ae | ||
|
|
ff2dd23918 | ||
|
|
66e74966ee | ||
|
|
9b022d0c61 | ||
|
|
e1b301814e | ||
|
|
2010d8d51e | ||
|
|
22fa977c9b | ||
|
|
285293ec23 | ||
|
|
6497f527ca | ||
|
|
689c167384 | ||
|
|
18a2d76139 | ||
|
|
722bef4257 | ||
|
|
8fe869223d | ||
|
|
1a961aac70 | ||
|
|
81dacef2fe | ||
|
|
92932cd004 | ||
|
|
1f6f8fd720 |
@@ -941,8 +941,261 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Dominic-DallOsto",
|
||||
"name": "Dominic D",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/26859884?v=4",
|
||||
"profile": "https://github.com/Dominic-DallOsto",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "elgirafo",
|
||||
"name": "luca",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/80516439?v=4",
|
||||
"profile": "http://elgirafo.xyz",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Lloyd-Jackman-UKPL",
|
||||
"name": "Lloyd Jackman",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/55206370?v=4",
|
||||
"profile": "https://github.com/Lloyd-Jackman-UKPL",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "sn3akiwhizper",
|
||||
"name": "sn3akiwhizper",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/102705294?v=4",
|
||||
"profile": "http://sn3akiwhizper.github.io",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jonathanpberger",
|
||||
"name": "jonathan berger",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/41085?v=4",
|
||||
"profile": "http://jonathanpberger.com/",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "badsketch",
|
||||
"name": "Daniel Wang",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/8953212?v=4",
|
||||
"profile": "https://github.com/badsketch",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "tlylt",
|
||||
"name": "Liu YongLiang",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/41845017?v=4",
|
||||
"profile": "http://yongliangliu.com",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Skakerman",
|
||||
"name": "Scott Akerman",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/15224439?v=4",
|
||||
"profile": "http://scottakerman.com",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jimgraham",
|
||||
"name": "Jim Graham",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/430293?v=4",
|
||||
"profile": "http://www.jim-graham.net/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "hezhizhen",
|
||||
"name": "Zhizhen He",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/7611700?v=4",
|
||||
"profile": "https://t.me/littlepoint",
|
||||
"contributions": [
|
||||
"tool"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "tcheneau",
|
||||
"name": "Tony Cheneau",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/952059?v=4",
|
||||
"profile": "https://amnesiak.org/me",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "nicholas-l",
|
||||
"name": "Nicholas Latham",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/12977174?v=4",
|
||||
"profile": "https://github.com/nicholas-l",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "thara",
|
||||
"name": "Tomochika Hara",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1532891?v=4",
|
||||
"profile": "https://thara.dev",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "dcarosone",
|
||||
"name": "Daniel Carosone",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/11495017?v=4",
|
||||
"profile": "https://github.com/dcarosone",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "MABruni",
|
||||
"name": "Miguel Angel Bruni Montero",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/100445384?v=4",
|
||||
"profile": "https://github.com/MABruni",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Walshkev",
|
||||
"name": "Kevin Walsh ",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/77123083?v=4",
|
||||
"profile": "https://github.com/Walshkev",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "hereistheusername",
|
||||
"name": "Xinglan Liu",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/33437051?v=4",
|
||||
"profile": "http://hereistheusername.github.io/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Hegghammer",
|
||||
"name": "Thomas Hegghammer",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/64712218?v=4",
|
||||
"profile": "http://www.hegghammer.com",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "PiotrAleksander",
|
||||
"name": "Piotr Mrzygłosz",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/6314591?v=4",
|
||||
"profile": "https://github.com/PiotrAleksander",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "markschaver",
|
||||
"name": "Mark Schaver",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/7584?v=4",
|
||||
"profile": "http://schaver.com/",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "n8layman",
|
||||
"name": "Nathan Layman",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/25353944?v=4",
|
||||
"profile": "https://github.com/n8layman",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "emmanuel-ferdman",
|
||||
"name": "Emmanuel Ferdman",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/35470921?v=4",
|
||||
"profile": "https://github.com/emmanuel-ferdman",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Tenormis",
|
||||
"name": "Tenormis",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/61572102?v=4",
|
||||
"profile": "https://github.com/Tenormis",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "djplaner",
|
||||
"name": "David Jones",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/225052?v=4",
|
||||
"profile": "http://djon.es/blog",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "s-jacob-powell",
|
||||
"name": "S. Jacob Powell",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/109111499?v=4",
|
||||
"profile": "https://github.com/s-jacob-powell",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "figdavi",
|
||||
"name": "Davi Figueiredo",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/99026991?v=4",
|
||||
"profile": "https://github.com/figdavi",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ChThH",
|
||||
"name": "CT Hall",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/9499483?v=4",
|
||||
"profile": "https://github.com/ChThH",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "meestahp",
|
||||
"name": "meestahp",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/177708514?v=4",
|
||||
"profile": "https://github.com/meestahp",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
"skipCi": true
|
||||
"skipCi": true,
|
||||
"commitType": "docs"
|
||||
}
|
||||
|
||||
59
.claude/commands/prepare-pr.md
Normal file
59
.claude/commands/prepare-pr.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Prepare PR Command
|
||||
|
||||
Analyze the current branch changes and generate:
|
||||
|
||||
- a PR title
|
||||
- a PR description
|
||||
- considerations for the developer before pushing the PR
|
||||
|
||||
Output the title and description ready to paste into GitHub.
|
||||
|
||||
## PR TITLE
|
||||
|
||||
Use format: `type(scope): description`
|
||||
|
||||
- type: feat/fix/refactor/perf/docs/chore
|
||||
- Keep under 72 characters
|
||||
- Be specific but brief
|
||||
|
||||
## PR DESCRIPTION
|
||||
|
||||
It should have these sections (use a paragraph per section, no need to title them).
|
||||
CONSTRAINTS:
|
||||
|
||||
- 100-200 words total
|
||||
- No file names or "updated X file" statements
|
||||
- Active voice
|
||||
- No filler or pleasantries
|
||||
- Focus on WHAT and WHY, not HOW
|
||||
|
||||
### What Changed
|
||||
|
||||
List 2-4 changes grouped by DOMAIN, not files. Focus on:
|
||||
|
||||
- User-facing changes
|
||||
- Architectural shifts
|
||||
- API changes
|
||||
Skip trivial updates (formatting, minor refactors).
|
||||
|
||||
### Why
|
||||
|
||||
One sentence explaining motivation (skip if obvious from title).
|
||||
|
||||
### Critical Notes
|
||||
|
||||
ONLY include if relevant:
|
||||
|
||||
- Breaking changes
|
||||
- Performance impact
|
||||
- Security implications
|
||||
- New dependencies
|
||||
- Required config/env changes
|
||||
- Database migrations
|
||||
|
||||
If no critical notes exist, omit this section.
|
||||
|
||||
## Considerations
|
||||
|
||||
Run the `yarn lint` command and report any failures.
|
||||
Also analize the changeset, and act as a PR reviewer to provide comments about the changes.
|
||||
61
.claude/commands/research-issue.md
Normal file
61
.claude/commands/research-issue.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Research Issue Command
|
||||
|
||||
Research a GitHub issue by analyzing the issue details and codebase to generate a comprehensive task analysis file.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/research-issue <issue-number>
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
- `issue-number` (required): The GitHub issue number to research
|
||||
|
||||
## Description
|
||||
|
||||
This command performs comprehensive research on a GitHub issue by:
|
||||
|
||||
1. **Fetching Issue Details**: Uses `gh issue view` to get issue title, description, labels, comments, and related information
|
||||
2. **Codebase Analysis**: Searches the codebase for relevant files, patterns, and components mentioned in the issue
|
||||
3. **Root Cause Analysis**: Identifies possible technical causes based on the issue description and codebase findings
|
||||
4. **Solution Planning**: Proposes two solution approaches ranked by preference
|
||||
5. **Documentation**: Creates a structured task file in `.agent/tasks/<issue-id>-<sanitized-title>.md`
|
||||
|
||||
If there is already a `.agent/tasks/<issue-id>-<sanitized-title>.md` file, use it for context and update it accordingly.
|
||||
If at any time during these steps you need clarifying information from me, please ask.
|
||||
|
||||
## Output Format
|
||||
|
||||
Creates a markdown file with:
|
||||
|
||||
- Issue summary and key details
|
||||
- Research findings from codebase analysis
|
||||
- Identified possible root causes
|
||||
- Two ranked solution approaches with pros/cons
|
||||
- Technical considerations and dependencies
|
||||
|
||||
## Examples
|
||||
|
||||
```
|
||||
/research-issue 1234
|
||||
/research-issue 567
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
The command will:
|
||||
|
||||
1. Validate the issue number and check if it exists
|
||||
2. Fetch issue details using GitHub CLI
|
||||
3. Search codebase for relevant patterns, files, and components
|
||||
4. Analyze findings to identify root causes
|
||||
5. Generate structured markdown file with research results
|
||||
6. Save to `.agent/tasks/` directory with standardized naming
|
||||
|
||||
## Error Handling
|
||||
|
||||
- Invalid issue numbers
|
||||
- GitHub CLI authentication issues
|
||||
- Network connectivity problems
|
||||
- File system write permissions
|
||||
10
.devcontainer/devcontainer.json
Normal file
10
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Foam Dev Container",
|
||||
"image": "mcr.microsoft.com/devcontainers/typescript-node:0-18",
|
||||
"postCreateCommand": "yarn install",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,21 +6,22 @@
|
||||
"sourceType": "module"
|
||||
},
|
||||
"env": { "node": true, "es6": true },
|
||||
"plugins": ["@typescript-eslint", "import", "jest"],
|
||||
"plugins": ["jest"],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:import/recommended",
|
||||
"plugin:import/typescript",
|
||||
"plugin:jest/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"no-redeclare": "off",
|
||||
"no-unused-vars": "off",
|
||||
"no-use-before-define": "off",
|
||||
"@typescript-eslint/no-use-before-define": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/interface-name-prefix": "off",
|
||||
"@typescript-eslint/no-unused-vars": "warn",
|
||||
"import/no-extraneous-dependencies": [
|
||||
"error",
|
||||
{
|
||||
|
||||
8
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
8
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -74,13 +74,13 @@ body:
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating System Version
|
||||
description: What opearting system are you using?
|
||||
description: What operating system are you using?
|
||||
placeholder: |
|
||||
- OS: [e.g. macOS, Windows, Linux]
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: vscode_version
|
||||
id: vscode_version
|
||||
attributes:
|
||||
label: Visual Studio Code Version
|
||||
description: |
|
||||
@@ -92,6 +92,6 @@ body:
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: |
|
||||
description: |
|
||||
Add any other context about the problem here.
|
||||
The Foam log output for VSCode can be found here: https://github.com/foambubble/foam/blob/master/docs/features/foam-logging-in-vscode.md
|
||||
The Foam log output for VSCode can be found here: https://github.com/foambubble/foam/blob/main/docs/user/tools/foam-logging-in-vscode.md
|
||||
|
||||
43
.github/workflows/ci.yml
vendored
43
.github/workflows/ci.yml
vendored
@@ -3,24 +3,34 @@ name: CI
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
|
||||
jobs:
|
||||
typos-check:
|
||||
name: Spell Check with Typos
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Actions Repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Check spelling with custom config file
|
||||
uses: crate-ci/typos@v1.14.8
|
||||
with:
|
||||
config: ./typos.toml
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '12'
|
||||
node-version: '18'
|
||||
- name: Restore Dependencies and VS Code test instance
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
node_modules
|
||||
@@ -34,21 +44,22 @@ jobs:
|
||||
|
||||
test:
|
||||
name: Build and Test
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-10.15, ubuntu-18.04, windows-2019]
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
OS: ${{ matrix.os }}
|
||||
# strategy:
|
||||
# matrix:
|
||||
# os: [macos-12, ubuntu-22.04, windows-2022]
|
||||
# runs-on: ${{ matrix.os }}
|
||||
runs-on: ubuntu-22.04
|
||||
# env:
|
||||
# OS: ${{ matrix.os }}
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '12'
|
||||
node-version: '18'
|
||||
- name: Restore Dependencies and VS Code test instance
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
node_modules
|
||||
@@ -62,4 +73,4 @@ jobs:
|
||||
- name: Run Tests
|
||||
uses: GabrielBB/xvfb-action@v1.4
|
||||
with:
|
||||
run: yarn test --stream
|
||||
run: yarn test
|
||||
|
||||
49
.github/workflows/update-docs.yml
vendored
Normal file
49
.github/workflows/update-docs.yml
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
name: Update Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- docs/user/**/*
|
||||
- docs/.vscode/**/*
|
||||
- docs/assets/**/*
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update-docs:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: foambubble/foam-template
|
||||
path: foam-template
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
path: foam
|
||||
- name: Copy and fixup user docs files
|
||||
id: copy
|
||||
run: |
|
||||
rm -r foam-template/docs
|
||||
rm -r foam-template/assets
|
||||
rm -r foam-template/.vscode
|
||||
cp -r foam/docs/user foam-template/docs
|
||||
cp -r foam/docs/assets foam-template/assets
|
||||
cp -r foam/docs/.vscode foam-template/.vscode
|
||||
|
||||
# Strip autogenerated wikileaks references because
|
||||
# they are not an appropriate default user experience.
|
||||
(cd foam-template/docs; find . -type f -name '*.md' -exec sed -i '/\[\/\/begin\]/,/\[\/\/end\]/d' {} +)
|
||||
|
||||
# Set the commit message format
|
||||
echo "message=Docs sync @ $(cd foam; git log --pretty='format:%h %s')" >> $GITHUB_OUTPUT
|
||||
- uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
token: ${{ secrets.FOAM_DOCS_SYNC_TOKEN }}
|
||||
path: foam-template
|
||||
commit-message: ${{ steps.copy.outputs.message }}
|
||||
branch: bot/foam-docs-sync
|
||||
delete-branch: true
|
||||
title: Sync docs from foam
|
||||
body: Copy docs from main foam repo
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,7 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
.vscode-test/
|
||||
.vscode-test-web/
|
||||
*.tsbuildinfo
|
||||
*.vsix
|
||||
*.log
|
||||
@@ -10,3 +11,4 @@ docs/_site
|
||||
docs/.sass-cache
|
||||
docs/.jekyll-metadata
|
||||
.test-workspace
|
||||
.agent/tasks
|
||||
|
||||
8
.vscode/settings.json
vendored
8
.vscode/settings.json
vendored
@@ -24,9 +24,11 @@
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnSaveMode": "file",
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"jest.autoRun": "off",
|
||||
"jest.rootPath": "packages/foam-vscode",
|
||||
"jest.jestCommandLine": "yarn jest",
|
||||
"jest.jestCommandLine": "yarn test:unit",
|
||||
"gitdoc.enabled": false,
|
||||
"search.mode": "reuseEditor"
|
||||
"search.mode": "reuseEditor",
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
}
|
||||
|
||||
23
.vscode/tasks.json
vendored
23
.vscode/tasks.json
vendored
@@ -7,7 +7,28 @@
|
||||
"label": "watch: foam-vscode",
|
||||
"type": "npm",
|
||||
"script": "watch",
|
||||
"problemMatcher": "$tsc-watch",
|
||||
"problemMatcher": {
|
||||
"owner": "typescript",
|
||||
"fileLocation": ["relative", "${workspaceFolder}"],
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.*?)\\((\\d+),(\\d+)\\):\\s+(.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"message": 4
|
||||
}
|
||||
],
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": {
|
||||
"regexp": ".*"
|
||||
},
|
||||
"endsPattern": {
|
||||
"regexp": ".*"
|
||||
}
|
||||
}
|
||||
},
|
||||
"isBackground": true,
|
||||
"presentation": {
|
||||
"reveal": "always"
|
||||
|
||||
263
CLAUDE.md
Normal file
263
CLAUDE.md
Normal file
@@ -0,0 +1,263 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Collaboration Principles
|
||||
|
||||
**Be honest and objective**: Evaluate all suggestions, ideas, and feedback on their technical merits. Don't be overly complimentary or sycophantic. If something doesn't make sense, doesn't align with best practices, or could be improved, say so directly and constructively. Technical accuracy and project quality take precedence over being agreeable.
|
||||
|
||||
## Project overview
|
||||
|
||||
Foam is a personal knowledge management and sharing system, built on Visual Studio Code and GitHub. It allows users to organize research, keep re-discoverable notes, write long-form content, and optionally publish it to the web. The main goals are to help users create relationships between thoughts and information, supporting practices like building a "Second Brain" or a "Zettelkasten". Foam is free, open-source, and extensible, giving users ownership and control over their information. The target audience includes individuals interested in personal knowledge management, note-taking, and content creation, particularly those familiar with VS Code and GitHub.
|
||||
|
||||
## Quick Commands
|
||||
|
||||
All the following commands are to be executed from the `packages/foam-vscode` directory
|
||||
|
||||
### Development
|
||||
|
||||
- `yarn install` - Install dependencies
|
||||
- `yarn build` - Build all packages
|
||||
- `yarn watch` - Watch mode for development
|
||||
- `yarn clean` - Clean build outputs
|
||||
- `yarn reset` - Full clean, install, and build
|
||||
|
||||
### Testing
|
||||
|
||||
- `yarn test` - Run all tests (unit + integration)
|
||||
- `yarn test:unit` - Run unit tests (\*.test.ts files and the .spec.ts files marked a vscode-mock friendly)
|
||||
- `yarn test:e2e` - Run only integration tests (\*.spec.ts files)
|
||||
- `yarn lint` - Run linting
|
||||
- `yarn test-reset-workspace` to clean test workspace
|
||||
|
||||
Unit tests run in Node.js environment using Jest
|
||||
Integration tests require VS Code extension host
|
||||
When running tests, do not provide additional parameters, they are ignored by the custom runner script. You cannot run just a test, you have to run the whole suite.
|
||||
|
||||
Unit tests are named `*.test.ts` and integration tests are `*.spec.ts`. These test files live alongside the code in the `src` directory. An integration test is one that has a direct or indirect dependency on `vscode` module.
|
||||
There is a mock `vscode` module that can be used to run most integration tests without starting VS Code. Tests that can use this mock are start with the line `/* @unit-ready */`.
|
||||
|
||||
- If you are interested in a test inside a `*.test.ts` file, run `yarn test:unit` or inside a `*.spec.ts` file that starts with `/* @unit-ready */` run `yarn test:unit`
|
||||
- If you are interested in a test inside a `*.spec.ts` file that does not include `/* @unit-ready */` run `yarn test`
|
||||
|
||||
While in development we mostly want to use `yarn test:unit`.
|
||||
When multiple tests are failing, look at all of them, but only focus on fixing the first one. Once that is fixed, run the test suite again and repeat the process.
|
||||
|
||||
When writing tests keep mocking to a bare minimum. Code should be written in a way that is easily testable and if I/O is necessary, it should be done in appropriate temporary directories.
|
||||
Never mock anything that is inside `packages/foam-vscode/src/core/`.
|
||||
|
||||
Use the utility functions from `test-utils.ts` and `test-utils-vscode.ts` and `test-datastore.ts`.
|
||||
|
||||
To improve readability of the tests, set up the test and tear it down within the test case (as opposed to use other functions like `beforeEach` unless it's much better to do it that way)
|
||||
|
||||
Never fix a test by adjusting the expectation if the expectation is correct, test must be fixed by addressing the issue with the code.
|
||||
|
||||
## Repository Structure
|
||||
|
||||
This is a monorepo using Yarn workspaces with the main VS Code extension in `packages/foam-vscode/`.
|
||||
|
||||
### Key Directories
|
||||
|
||||
- `packages/foam-vscode/src/core/` - Platform-agnostic business logic (NO vscode dependencies)
|
||||
- `packages/foam-vscode/src/features/` - VS Code-specific features and UI
|
||||
- `packages/foam-vscode/src/services/` - service implementations, might have VS Code dependency, but we try keep that to a minimum
|
||||
- `packages/foam-vscode/src/test/` - Test utilities and mocks
|
||||
- `docs/` - Documentation and user guides
|
||||
|
||||
### File Naming Patterns
|
||||
|
||||
Test files follow `*.test.ts` for unit tests and `*.spec.ts` for integration tests, living alongside the code in `src`. An integration test is one that has a direct or indirect dependency on `vscode` package.
|
||||
|
||||
### Important Constraint
|
||||
|
||||
Code in `packages/foam-vscode/src/core/` MUST NOT depend on the `vscode` library or any files outside the core directory. This maintains platform independence.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
### Core Abstractions
|
||||
|
||||
**FoamWorkspace** - Central repository managing all resources (notes, attachments)
|
||||
|
||||
- Uses reversed trie for efficient resource lookup
|
||||
- Event-driven updates (onDidAdd, onDidUpdate, onDidDelete)
|
||||
- Handles identifier resolution for short-form linking
|
||||
|
||||
**FoamGraph** - Manages relationship graph between resources
|
||||
|
||||
- Tracks links and backlinks between resources
|
||||
- Real-time updates when workspace changes
|
||||
- Handles placeholder resources for broken links
|
||||
|
||||
**ResourceProvider Pattern** - Pluggable architecture for different file types
|
||||
|
||||
- `MarkdownProvider` for .md files
|
||||
- `AttachmentProvider` for other file types
|
||||
- Extensible for future resource types
|
||||
|
||||
**DataStore Interface** - Abstract file system operations
|
||||
|
||||
- Platform-agnostic file access with configurable filtering
|
||||
- Supports both local and remote file systems
|
||||
|
||||
### Feature Integration Pattern
|
||||
|
||||
Features are registered as functions receiving:
|
||||
|
||||
```typescript
|
||||
(context: ExtensionContext, foamPromise: Promise<Foam>) => void
|
||||
```
|
||||
|
||||
This allows features to:
|
||||
|
||||
- Register VS Code commands, providers, and event handlers
|
||||
- Access the Foam workspace when ready
|
||||
- Extend markdown-it for preview rendering
|
||||
|
||||
### Testing Conventions
|
||||
|
||||
- `*.test.ts` - Unit tests using Jest
|
||||
- `*.spec.ts` - Integration tests requiring VS Code extension host
|
||||
- Tests live alongside source code in `src/`
|
||||
- Test cases should be phrased in terms of aspects of the feature being tested (expected behaviors), as they serve both as validation of the code as well as documentation of what the expected behavior for the code is in different situations. They should include the happy paths and edge cases.
|
||||
|
||||
## Development Workflow
|
||||
|
||||
We build production code together. I handle implementation details while you guide architecture and catch complexity early.
|
||||
When working on an issue, check if a `.agent/tasks/<issue-id>-<sanitized-title>.md` exists. If not, suggest whether we should start by doing a research on it (using the `/research-issue <issue-id>`) command.
|
||||
Whenever we work together on a task, feel free to challenge my assumptions and ideas and be critical if useful.
|
||||
|
||||
## Core Workflow: Research → Plan → Implement → Validate
|
||||
|
||||
**Start every feature with:** "Let me research the codebase and create a plan before implementing."
|
||||
|
||||
1. **Research** - Understand existing patterns and architecture
|
||||
2. **Plan** - Propose approach and verify with you
|
||||
3. **Implement** - Build with tests and error handling
|
||||
4. **Validate** - ALWAYS run formatters, linters, and tests after implementation
|
||||
|
||||
- Whenever working on a feature or issue, let's always come up with a plan first, then save it to a file called `/.agent/current-plan.md`, before getting started with code changes. Update this file as the work progresses.
|
||||
- Let's use pure functions where possible to improve readability and testing.
|
||||
|
||||
### Adding New Features
|
||||
|
||||
1. Create feature in `src/features/` directory
|
||||
2. Register feature in `src/features/index.ts`
|
||||
3. Add tests (both unit and integration as needed)
|
||||
4. Update configuration in `package.json` if needed
|
||||
|
||||
### Working on an issue
|
||||
|
||||
1. Get the issue information from github
|
||||
2. Define a step by step plan for addressing the issue
|
||||
3. Create tests for the feature
|
||||
4. Starting from the first test case, implement the feature so the test passes
|
||||
|
||||
### Core Logic Changes
|
||||
|
||||
1. Modify code in `src/core/` (ensure no vscode dependencies)
|
||||
2. Add comprehensive unit tests
|
||||
3. Update integration tests in features that use the core logic
|
||||
|
||||
## Configuration
|
||||
|
||||
The extension uses VS Code's configuration system with the `foam.*` namespace.
|
||||
You can find all the settings in `/packages/foam-vscode/package.json`
|
||||
|
||||
## Common Development Tasks
|
||||
|
||||
### Extending Core Functionality
|
||||
|
||||
When adding to `src/core/`:
|
||||
|
||||
- Keep platform-agnostic (no vscode imports)
|
||||
- Add comprehensive unit tests
|
||||
- Consider impact on graph and workspace state
|
||||
- Update relevant providers if needed
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **Runtime**: VS Code API, markdown parsing, file watching
|
||||
- **Development**: TypeScript, Jest, ESLint, esbuild
|
||||
- **Key Libraries**: remark (markdown parsing), lru-cache, lodash
|
||||
|
||||
The extension supports both Node.js and browser environments via separate build targets.
|
||||
|
||||
## Documentation Guidelines
|
||||
|
||||
### User Documentation (`docs/user/`)
|
||||
|
||||
Documentation in `docs/user/` must be written for non-technical users. The goal is to help novice users quickly start using features, not to explain technical implementation details.
|
||||
|
||||
**Writing Guidelines:**
|
||||
|
||||
- **Target audience**: Assume users are new to Foam and may not be technical
|
||||
- **Be concise**: Keep it short and to the point - every sentence must convey useful information
|
||||
- **Avoid repetition**: Don't repeat the same concept in different words
|
||||
- **Focus on "how to use"**: Show users what they can do and how to do it, not how it works internally
|
||||
- **Balance brevity with clarity**: Users won't read verbose documentation, but they need enough information to succeed
|
||||
- **Use examples**: Show practical use cases rather than abstract descriptions
|
||||
- **Start with the most common use case**: Lead with what most users will want to do first
|
||||
|
||||
# GitHub CLI Integration
|
||||
|
||||
To interact with the github repo we will be using the `gh` command.
|
||||
ALWAYS ask before performing a write operation on Github.
|
||||
|
||||
## Common Commands for Claude Code Integration
|
||||
|
||||
### Issues
|
||||
|
||||
```bash
|
||||
# List all issues
|
||||
gh issue list
|
||||
|
||||
# Filter issues by milestone
|
||||
gh issue list --milestone "v1.0.0"
|
||||
|
||||
# Filter issues by assignee
|
||||
gh issue list --assignee @me
|
||||
gh issue list --assignee username
|
||||
|
||||
# Filter issues by label
|
||||
gh issue list --label "bug"
|
||||
gh issue list --label "enhancement,priority-high"
|
||||
|
||||
# Filter issues by state
|
||||
gh issue list --state open
|
||||
gh issue list --state closed
|
||||
gh issue list --state all
|
||||
|
||||
# Combine filters
|
||||
gh issue list --milestone "v1.0.0" --label "bug" --assignee @me
|
||||
|
||||
# View specific issue
|
||||
gh issue view 123
|
||||
|
||||
# Create issue
|
||||
gh issue create --title "Bug fix" --body "Description"
|
||||
|
||||
# Add comment to issue
|
||||
gh issue comment 123 --body "Update comment"
|
||||
```
|
||||
|
||||
### Pull Requests
|
||||
|
||||
```bash
|
||||
# List all PRs
|
||||
gh pr list
|
||||
|
||||
# Filter PRs the same way as for filters (for example, here is by milestone)
|
||||
gh pr list --milestone "v1.0.0"
|
||||
|
||||
# View PR details
|
||||
gh pr view 456
|
||||
|
||||
# Create PR
|
||||
gh pr create --title "Feature" --body "Description"
|
||||
|
||||
# Check out PR locally
|
||||
gh pr checkout 456
|
||||
|
||||
# Add review comment
|
||||
gh pr comment 456 --body "LGTM"
|
||||
```
|
||||
4
docs/.vscode/custom-tag-style.css
vendored
Normal file
4
docs/.vscode/custom-tag-style.css
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.foam-tag{
|
||||
color:#ffffff;
|
||||
background-color: #000000;
|
||||
}
|
||||
10
docs/.vscode/extensions.json
vendored
10
docs/.vscode/extensions.json
vendored
@@ -5,17 +5,11 @@
|
||||
// Foam's own extension
|
||||
"foam.foam-vscode",
|
||||
|
||||
// Prettier for auto formatting code
|
||||
"esbenp.prettier-vscode",
|
||||
|
||||
// GitLens for seeing version history inline
|
||||
"eamodio.gitlens",
|
||||
|
||||
// Tons of markdown goodies (lists, tables of content, so much more)
|
||||
"yzhang.markdown-all-in-one",
|
||||
|
||||
// Graph visualizer
|
||||
"tchayen.markdown-links",
|
||||
// Prettier for auto formatting code
|
||||
"esbenp.prettier-vscode",
|
||||
|
||||
// Understated grayscale theme (light and dark variants)
|
||||
"philipbe.theme-gray-matter"
|
||||
|
||||
4
docs/.vscode/foam.json
vendored
4
docs/.vscode/foam.json
vendored
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"purpose": "this file exists to tell the foam-vscode plugin that it's currently in a foam workspace",
|
||||
"future": "we may use this for custom configuration"
|
||||
}
|
||||
2
docs/.vscode/keybindings.json
vendored
2
docs/.vscode/keybindings.json
vendored
@@ -3,6 +3,6 @@
|
||||
[
|
||||
{
|
||||
"key": "cmd+shift+n",
|
||||
"command": "vscodeMarkdownNotes.newNote"
|
||||
"command": "foam-vscode.create-note"
|
||||
}
|
||||
]
|
||||
|
||||
12
docs/.vscode/settings.json
vendored
12
docs/.vscode/settings.json
vendored
@@ -5,7 +5,6 @@
|
||||
"editor.overviewRulerBorder": false,
|
||||
"editor.lineHeight": 24,
|
||||
"foam.edit.linkReferenceDefinitions": "withExtensions",
|
||||
"vscodeMarkdownNotes.noteCompletionConvention": "noExtension",
|
||||
"[markdown]": {
|
||||
"editor.quickSuggestions": {
|
||||
"other": true,
|
||||
@@ -13,18 +12,11 @@
|
||||
"strings": false
|
||||
}
|
||||
},
|
||||
"cSpell.language": "en-GB",
|
||||
"git.enableSmartCommit": true,
|
||||
"git.postCommitCommand": "sync",
|
||||
"spellright.language": [
|
||||
"en"
|
||||
],
|
||||
"spellright.documentTypes": [
|
||||
"markdown",
|
||||
"plaintext"
|
||||
],
|
||||
"files.exclude": {
|
||||
"_site/**": true
|
||||
},
|
||||
"files.insertFinalNewline": true
|
||||
"files.insertFinalNewline": true,
|
||||
"markdown.styles": [".vscode/custom-tag-style.css"]
|
||||
}
|
||||
|
||||
1
docs/.vscode/spellright.dict
vendored
1
docs/.vscode/spellright.dict
vendored
@@ -1 +0,0 @@
|
||||
Backlinking
|
||||
1
docs/CNAME
Normal file
1
docs/CNAME
Normal file
@@ -0,0 +1 @@
|
||||
foamnotes.com
|
||||
BIN
docs/assets/images/custom-tag-style.png
Normal file
BIN
docs/assets/images/custom-tag-style.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
docs/assets/images/graph-filter.gif
Executable file
BIN
docs/assets/images/graph-filter.gif
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 7.1 MiB |
BIN
docs/assets/images/note-embed-type-demo.gif
Normal file
BIN
docs/assets/images/note-embed-type-demo.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 568 KiB |
BIN
docs/assets/images/pdf_output.png
Normal file
BIN
docs/assets/images/pdf_output.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
@@ -1,17 +0,0 @@
|
||||
# Big Vision
|
||||
|
||||
[[todo]]
|
||||
|
||||
- What methodologies do we want to support?
|
||||
- Zettelkasten?
|
||||
- GTD? (Get Things Done)
|
||||
- Digital gardening?
|
||||
- Blogging/publishing
|
||||
- Others?
|
||||
- Be an educational tool as much as a tool to implement these methodologies
|
||||
- What use cases are we working towards?
|
||||
-[[todo]] User round table
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[todo]: dev/todo.md "Todo"
|
||||
[//end]: # "Autogenerated link references"
|
||||
@@ -1,7 +1,7 @@
|
||||
# Developing documentation
|
||||
|
||||
The best way to develop docs for the Foam repo is to directly open the `$foam-repo/docs/` as the root folder in a new vscode window.
|
||||
This automatically configures vscode with the necessary settings enabled (like [[link-reference-definitions]]) to effiniently write this documentation.
|
||||
This automatically configures vscode with the necessary settings enabled (like [[link-reference-definitions]]) to efficiently write this documentation.
|
||||
|
||||
## Organization
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
The Foam prototype is built by assembling third-party extensions, which seems like a good strategy because
|
||||
|
||||
- It supports picking and mixing of tools and workflows
|
||||
- Less code to write an maintain
|
||||
- Less code to write and maintain
|
||||
|
||||
But there's also a bunch of roadmap items that are hard to implement this way, as the third party plugins don't do exactly what we want them to do (e.g. Markdown All In One is not compatible with [[referencing-notes-by-title]].
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
---
|
||||
redirect_from:
|
||||
- /code-of-conduct
|
||||
---
|
||||
|
||||
# Code of Conduct
|
||||
|
||||
We follow the [Contributor Covenant](https://www.contributor-covenant.org/) code of conduct.
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
---
|
||||
tags: todo, good-first-task
|
||||
---
|
||||
|
||||
# Contribution Guide
|
||||
|
||||
Foam is open to contributions of any kind, including but not limited to code, documentation, ideas, and feedback.
|
||||
This guide aims to help guide new and seasoned contributors getting around the Foam codebase.
|
||||
This guide aims to help guide new and seasoned contributors getting around the Foam codebase. For a comprehensive guide about contributing to open-source projects in general, [see here](https://blog.robsewell.com/blog/how-to-fork-a-github-repository-and-contribute-to-an-open-source-project/).
|
||||
|
||||
## Getting Up To Speed
|
||||
|
||||
@@ -13,6 +14,8 @@ Before you start contributing we recommend that you read the following links:
|
||||
- [[principles]] - This document describes the guiding principles behind Foam.
|
||||
- [[code-of-conduct]] - Rules we hope every contributor aims to follow, allowing everyone to participate in our community!
|
||||
|
||||
To get yourself familiar with the codebase you can also browse [this repo](https://app.komment.ai/wiki/github/foambubble/foam)
|
||||
|
||||
## Diving In
|
||||
|
||||
We understand that diving in an unfamiliar codebase may seem scary,
|
||||
@@ -23,17 +26,19 @@ Finally, the easiest way to help, is to use it and provide feedback by [submitti
|
||||
|
||||
## Contributing
|
||||
|
||||
If you're interested in contributing, this short guide will help you get things set up locally.
|
||||
If you're interested in contributing, this short guide will help you get things set up locally (assuming [node.js >= v18](https://nodejs.org/) and [yarn](https://yarnpkg.com/) are already installed on your system).
|
||||
You can also use the provided [[devcontainers]] to avoid installing dependencies locally. With the Dev Containers extension installed, open the repository in VS Code and run **Dev Containers: Reopen in Container**.
|
||||
|
||||
1. Clone the repo locally:
|
||||
1. Fork the project to your Github account by clicking the "Fork" button on the top right hand corner of the project's [home repository page](https://github.com/foambubble/foam).
|
||||
2. Clone your newly forked repo locally:
|
||||
|
||||
`git clone https://github.com/foambubble/foam.git`
|
||||
`git clone https://github.com/your_username/foam.git`
|
||||
|
||||
2. Install the necessary dependencies by running this command from the root:
|
||||
3. Install the necessary dependencies by running this command from the root of the cloned repository:
|
||||
|
||||
`yarn install`
|
||||
|
||||
3. From the root, run the command:
|
||||
4. From the repository root, run the command:
|
||||
|
||||
`yarn build`
|
||||
|
||||
@@ -43,19 +48,19 @@ You should now be ready to start working!
|
||||
|
||||
Foam code and documentation live in the monorepo at [foambubble/foam](https://github.com/foambubble/foam/).
|
||||
|
||||
- [/docs](https://github.com/foambubble/foam/tree/master/docs): documentation and [[recipes]].
|
||||
- [/docs](https://github.com/foambubble/foam/tree/main/docs): documentation and [[recipes]].
|
||||
|
||||
Exceptions to the monorepo are:
|
||||
|
||||
- The starter template at [foambubble/foam-template](https://github.com/foambubble/)
|
||||
- All other [[recommended-extensions]] live in their respective GitHub repos
|
||||
|
||||
This project uses [Yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces/).
|
||||
This project uses [Yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces/).
|
||||
|
||||
Originally Foam had:
|
||||
|
||||
- [/packages/foam-core](https://github.com/foambubble/foam/tree/master/packages/foam-core) - Powers the core functionality in Foam across all platforms.
|
||||
- [/packages/foam-vscode](https://github.com/foambubble/foam/tree/master/packages/foam-vscode) - The core VS Code plugin.
|
||||
- [/packages/foam-core](https://github.com/foambubble/foam/tree/ee7a8919761f168d3931079adf21c5ad4d63db59/packages/foam-core) - Powers the core functionality in Foam across all platforms.
|
||||
- [/packages/foam-vscode](https://github.com/foambubble/foam/tree/main/packages/foam-vscode) - The core VS Code plugin.
|
||||
|
||||
To improve DX we have moved the `foam-core` module into `packages/foam-vscode/src/core`, but from a development point of view it's useful to think of the `foam-vscode/src/core` "submodule" as something that might be extracted in the future.
|
||||
|
||||
@@ -80,12 +85,24 @@ Tests live alongside the code in `src`.
|
||||
|
||||
This guide assumes you read the previous instructions and you're set up to work on Foam.
|
||||
|
||||
1. Now we'll use the launch configuration defined at [`.vscode/launch.json`](https://github.com/foambubble/foam/blob/master/.vscode/launch.json) to start a new extension host of VS Code. Open the "Run and Debug" Activity (the icon with the bug on the far left) and select "Run VSCode Extension" in the pop-up menu. Now hit F5 or click the green arrow "play" button to fire up a new copy of VS Code with your extension installed.
|
||||
1. Now we'll use the launch configuration defined at [`.vscode/launch.json`](https://github.com/foambubble/foam/blob/main/.vscode/launch.json) to start a new extension host of VS Code. Open the "Run and Debug" Activity (the icon with the bug on the far left) and select "Run VSCode Extension" in the pop-up menu. Now hit F5 or click the green arrow "play" button to fire up a new copy of VS Code with your extension installed.
|
||||
|
||||
2. In the new extension host of VS Code that launched, open a Foam workspace (e.g. your personal one, or a test-specific one created from [foam-template](https://github.com/foambubble/foam-template)). This is strictly not necessary, but the extension won't auto-run unless it's in a workspace with a `.vscode/foam.json` file.
|
||||
2. In the new extension host of VS Code that launched, open a Foam workspace (e.g. your personal one, or a test-specific one created from [foam-template](https://github.com/foambubble/foam-template)).
|
||||
|
||||
3. Test a command to make sure it's working as expected. Open the Command Palette (Ctrl/Cmd + Shift + P) and select "Foam: Update Markdown Reference List". If you see no errors, it's good to go!
|
||||
|
||||
### Submitting a Pull Request (PR)
|
||||
|
||||
After you have made your changes to your copy of the project, it is time to try and merge those changes into the public community project.
|
||||
|
||||
1. Return to the project's [home repository page](https://github.com/foambubble/foam).
|
||||
2. Github should show you an button called "Compare & pull request" linking your forked repository to the community repository.
|
||||
3. Click that button and confirm that your repository is going to be merged into the community repository. See [this guide](https://blog.robsewell.com/blog/how-to-fork-a-github-repository-and-contribute-to-an-open-source-project/) for more specifics.
|
||||
4. Add as many relevant details to the PR message to make it clear to the project maintainers and other members of the community what you have accomplished with your new changes. Link to any issues the changes are related to.
|
||||
5. Your PR will then need to be reviewed and accepted by the other members of the community. Any discussion about the changes will occur in your PR thread.
|
||||
6. Once reviewed and accept you can complete the merge request!
|
||||
7. Finally rest and watch the sun rise on a grateful universe... Or start tackling the other open issues ;)
|
||||
|
||||
---
|
||||
|
||||
Feel free to modify and submit a PR if this guide is out-of-date or contains errors!
|
||||
@@ -95,6 +112,7 @@ Feel free to modify and submit a PR if this guide is out-of-date or contains err
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[principles]: ../principles.md "Principles"
|
||||
[code-of-conduct]: code-of-conduct.md "Code of Conduct"
|
||||
[devcontainers]: devcontainers.md "Using Dev Containers"
|
||||
[recipes]: ../user/recipes/recipes.md "Recipes"
|
||||
[recommended-extensions]: ../user/getting-started/recommended-extensions.md "Recommended Extensions"
|
||||
[//end]: # "Autogenerated link references"
|
||||
|
||||
13
docs/dev/devcontainers.md
Normal file
13
docs/dev/devcontainers.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Using Dev Containers
|
||||
|
||||
Foam provides a [devcontainer](https://devcontainer.ai/) configuration to make it easy to contribute without installing Node and Yarn locally.
|
||||
|
||||
## Quick start
|
||||
|
||||
1. Install [VS Code](https://code.visualstudio.com/) and the [Dev Containers](https://aka.ms/vscode-remote/download/extension) extension.
|
||||
2. Open the Foam repository in VS Code.
|
||||
3. Run **Dev Containers: Reopen in Container** from the command palette.
|
||||
|
||||
This will build a Docker image with Node 18 and install dependencies using `yarn install`. Once ready you can run the usual build and test commands from the integrated terminal.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Foam File Format
|
||||
|
||||
This file is an example of a valid Foam file. Essentially it's just a markdown file with a bit of additional support for MediaWiki-style `[[wikilinks]]`.
|
||||
This file is an example of a valid Foam file. Essentially it's just a markdown file with a bit of additional support for MediaWiki-style `[[wikilinks]]` and note embeds.
|
||||
|
||||
Here are a few specific constraints, mainly because our tooling is a bit fragmented. Most of these should be eventually lifted, and our requirement should just be "Markdown with `[[wikilinks]]`:
|
||||
|
||||
@@ -10,7 +10,6 @@ Here are a few specific constraints, mainly because our tooling is a bit fragmen
|
||||
- This is a temporary limitation and will be lifted in future versions.
|
||||
- At least `.mdx` will be supported, but ideally we'll support any file that you can map to `Markdown` language mode in VS Code
|
||||
- **In addition to normal Markdown Links syntax you can use `[[MediaWiki]]` links.** See [[wikilinks]] for more details.
|
||||
- **You can embed other notes using `![[note]]` syntax.** This supports various modifiers like `content![[note]]` or `full-card![[note]]` to control how content is displayed.
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[wikilinks]: ../user/features/wikilinks.md "Wikilinks"
|
||||
[//end]: # "Autogenerated link references"
|
||||
[wikilinks]: ../user/features/wikilinks.md 'Wikilinks'
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
# Foam Core 2020-07-11
|
||||
|
||||
Present: @jevakallio, @riccardoferretti
|
||||
|
||||
### Tests
|
||||
|
||||
- How do we know this approach works?
|
||||
- Supports renaming
|
||||
- Supports searching with (attribute-x)
|
||||
- Find dead links
|
||||
|
||||
### Getting started
|
||||
|
||||
- Land work to master
|
||||
- Create a foam-core package
|
||||
|
||||
-
|
||||
|
||||
### Open questions
|
||||
|
||||
- How should writing to files work
|
||||
- What if affected notes have unsaved changes
|
||||
|
||||
### Graph methods
|
||||
|
||||
- get all
|
||||
- search by
|
||||
- tag
|
||||
- free text
|
||||
- [[todo]]: how do vs code search editors work? are they pluggable? what do they need?
|
||||
- find dead links
|
||||
- for linters
|
||||
- serialize/toJSON (for visualizers)
|
||||
- subscribe to changes
|
||||
- find if a link exists (and which link) in a given row / column position + return it's start and end position - this would probably be needed e.g. to CTRL-hovering to work properly
|
||||
|
||||
### Node methods
|
||||
|
||||
- rename node and all links to that node
|
||||
- get links
|
||||
- forward links (for link lists)
|
||||
- backlinks (with surrounding context)
|
||||
|
||||
### Node definition
|
||||
|
||||
What do we need the node (and edge metadata) to contain:
|
||||
|
||||
- `id`: tbd
|
||||
- should be unique, needs some kind of unique gen function
|
||||
- should be reconstructable even if links are not updated every time
|
||||
- what happens during rename? is reparenting the graph going to be hard?
|
||||
- do id's need to be persistent, or can we create them per in-memory session, keep them stable despite renames, and then next session generate a new id?
|
||||
- Ideally should be a path to file, so it's easy to look up from the graph by id for renaming
|
||||
- `type`: Note | Image | etc
|
||||
- `title`: can be read from markdown title or frontmatter metadata
|
||||
- `path`: full path to file, relative to workspace (graph) root
|
||||
- `links`:
|
||||
- `id`: File to link to
|
||||
- `text`: The link label
|
||||
- `type` markdown | mediawiki | image | http
|
||||
- `section`: : Anchor link to a heading in target note, if we want to add support for linking to sections
|
||||
- `block` (ref)
|
||||
- Positional data from AST?
|
||||
- `tags`
|
||||
|
||||
### Markdown layer
|
||||
|
||||
- `source`: raw markdown (rename?)
|
||||
- `ast`: raw markdown ast
|
||||
- `checksum`: if we do caching
|
||||
|
||||
### Link text
|
||||
|
||||
// some-file.md
|
||||
// # Some File
|
||||
|
||||
Write -> Store on disk
|
||||
[[Some File]] -> [Some File](some-file.md)
|
||||
|
||||
Editing
|
||||
[Some File](some-file.md)
|
||||
|
||||
On disk (could be solved by migration)
|
||||
[[some-file]]
|
||||
[[Some File]]
|
||||
|
||||
- docs/index.md -> Index
|
||||
- notes/index.md -> Index
|
||||
|
||||
[[Index]]
|
||||
[[Index | notes/index.md]]
|
||||
|
||||
[Index] docs/index.md
|
||||
[Index | notes/index.md]: notes/index.md
|
||||
|
||||
[[Some File | path/to/some-file.md]]
|
||||
|
||||
Do we apply any constraints:
|
||||
|
||||
- `[[file-name-without-extension]]`
|
||||
- `[[file-name-with-extension.md]]`
|
||||
- `[[Title Cased File Name]]`
|
||||
|
||||
Not supported by Markdown Notes:
|
||||
|
||||
- `[[path/to/file-name.md]]` - Just use markdown links
|
||||
- `[[Target Note Title]]`
|
||||
|
||||
Issues:
|
||||
|
||||
- Name clashes in directories
|
||||
- Name clashes between extensions
|
||||
- Renaming
|
||||
- Change filename/title needs to reflect everywhere
|
||||
- Orphaning
|
||||
|
||||
- If we can't rely on in-memory process to rename things correctly while changes happen (e.g. file is renamed, moved, deleted, or titled) <ref id="1" />
|
||||
|
||||
Solving this issue is necessarily heuristic. We could try to write smart solutions, plus a linter for orphans
|
||||
|
||||
How others solve this:
|
||||
|
||||
- Unique ids -- could support optionally as part of file name or front matter metadata. Should not be required.
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[todo]: ../todo.md "Todo"
|
||||
[Index]: ../../index.md "Foam"
|
||||
[//end]: # "Autogenerated link references"
|
||||
@@ -14,7 +14,7 @@ Currently it is not possible within Foam to include other notes into a note. Nex
|
||||
|
||||
Initial work and thought on including a note was ignited by issue [#652](https://github.com/foambubble/foam/issues/652). Requested by a user was a likewise functionality as offered in Obsidian. This was simply the ability to include a note.
|
||||
|
||||
Whilst researching digital gardening for my own setup, I came across an in-depth overview by [Maggie Appleton](https://maggieappleton.com/roam-garden). Showing examples of her personal Roam Research I see valuable possibilites to connect more information, if we would add additional functionalities to the possibility of including a note. This proposal displays these possible functionalities and markup.
|
||||
Whilst researching digital gardening for my own setup, I came across an in-depth overview by [Maggie Appleton](https://maggieappleton.com/roam-garden). Showing examples of her personal Roam Research I see valuable possibilities to connect more information, if we would add additional functionalities to the possibility of including a note. This proposal displays these possible functionalities and markup.
|
||||
|
||||
## New features
|
||||
|
||||
@@ -29,7 +29,7 @@ The minimal functionality is the ability to fully include a note. Markup used in
|
||||
|
||||
### Include a section of a note
|
||||
|
||||
It could be interesting to only include a section of a note instead of the entire note. In order to do so thse user should be able to use the following syntax:
|
||||
It could be interesting to only include a section of a note instead of the entire note. In order to do so the user should be able to use the following syntax:
|
||||
|
||||
`![[wikilink#section-b]]`
|
||||
|
||||
@@ -37,11 +37,11 @@ As a result it will include the section title + section content until the next s
|
||||
|
||||
### Include an attribute of a file (note property or frontmatter)
|
||||
|
||||
As a user I could be interested in collecting the value of any given proeprty for a note. For example, I might want to include the tags as defined in the frontmatter of note A. This should be possible via the syntax:
|
||||
As a user I could be interested in collecting the value of any given property for a note. For example, I might want to include the tags as defined in the frontmatter of note A. This should be possible via the syntax:
|
||||
|
||||
`![[wikilink:<property>]]`
|
||||
|
||||
The property value should be lookedup by foam defined properties, e.g. title, **or** any property defined in the frontmatter of a note.
|
||||
The property value should be looked up by foam defined properties, e.g. title, **or** any property defined in the frontmatter of a note.
|
||||
|
||||
So, the example of including the tags of a note should be:
|
||||
|
||||
|
||||
@@ -66,8 +66,9 @@ The potential solution:
|
||||
- For edit-time
|
||||
- Make edit-time link reference definition generation optional via user settings. They should be on by default, and generating valid markdown links with a relative path to a `.md` file.
|
||||
- Make format of the link reference definition configurable (whether to include '.md' or not)
|
||||
- Out of recommended extensions, currently only "markdown links" doesn't support them (?). However even its [code](https://github.com/tchayen/markdown-links/blob/master/src/parsing.ts#L25) seems to include wikilink parser, so it might just be a bug?
|
||||
- Out of recommended extensions, currently only "markdown links" doesn't support them (?). However even its [code](https://github.com/tchayen/markdown-links/blob/main/src/parsing.ts#L25) seems to include wikilink parser, so it might just be a bug?
|
||||
- For build-time
|
||||
|
||||
- To satisfy mutually incompatible constraints between GitHub UI, VSCode UI, and GitHub Pages, we should add a pre-processing/build step for pushing to GitHub Pages.
|
||||
- This would be a GitHub action (or a local script, ran via foam-cli) that outputs publish-friendly markdown format for static site generators and other publishing tools
|
||||
- This build step should be pluggable, so that other transformations could be ran during it
|
||||
@@ -117,7 +118,7 @@ The potential solution:
|
||||
enum LinkReferenceDefinitions {
|
||||
Off, // link reference definitions are not generated
|
||||
WithExtensions, // link reference definitions contain .md (or similar) file extensions
|
||||
WithoutExtensions // link reference definitions do not contain file extenions
|
||||
WithoutExtensions // link reference definitions do not contain file extensions
|
||||
}
|
||||
|
||||
```
|
||||
@@ -125,6 +126,7 @@ The potential solution:
|
||||
- With Foam repo, just use edit-time link reference definitions with '.md' extension - this makes the links work in the GitHub UI
|
||||
- Have publish target defined for GitHub pages, that doesn't use '.md' extension, but still has the link reference definitions. Generate the output into gh-pages branch (or separate repo) with automation.
|
||||
- This naturally requires first removing the existing link reference definitions during the build
|
||||
|
||||
- Other
|
||||
- To clean up the search results, remove link reference definition section guards (assuming that these are not defined by the markdown spec). Use unifiedjs parse trees to identify if there's missing (or surplus) definitions (check if they are identified properly by the library), and just add the needed definitions to the bottom of the file (without guards) AND remove them if they are not needed (anywhere from the file).
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ If you want to pick up work in this category, you should have a plan on how long
|
||||
|
||||
Everything else, categorised into themes. Just because something is on this list doesn't mean it'll get done. If you're interested in working on items in this category, check the [[contribution-guide]] for how to get started.
|
||||
|
||||
If a roadmap item is a stub, **consider** opening a [GitHub issue](https://github.com/foambubble/foam/issues) to start a conversation to avoid situations where the implementation does not fit long term vision and roadmap. _Note that this is optional. The only centralised governance in Foam is to decide what ends up in the official [template](https://github.com/foambubble/foam-template), [documentation](https://github.com/foambubble/foam) and [extension](https://github.com/foambubble/foam/tree/master/packages/foam-vscode). You are free to build whatever you want for yourself, and we'd love if you shared it with us, but you are by no means obligated to do so!_
|
||||
If a roadmap item is a stub, **consider** opening a [GitHub issue](https://github.com/foambubble/foam/issues) to start a conversation to avoid situations where the implementation does not fit long term vision and roadmap. _Note that this is optional. The only centralised governance in Foam is to decide what ends up in the official [template](https://github.com/foambubble/foam-template), [documentation](https://github.com/foambubble/foam) and [extension](https://github.com/foambubble/foam/tree/main/packages/foam-vscode). You are free to build whatever you want for yourself, and we'd love if you shared it with us, but you are by no means obligated to do so!_
|
||||
|
||||
**When creating GitHub issues to discuss roadmap items, link them here.**
|
||||
|
||||
|
||||
@@ -1,329 +0,0 @@
|
||||
# Templates v2 Proposal <!-- omit in TOC -->
|
||||
|
||||
The current capabilities of templates is limited in some important ways. This document aims to propose a design that addresses these shortcomings.
|
||||
|
||||
**IMPORTANT: This design is merely a proposal of a design that could be implemented. It DOES NOT represent a commitment by `Foam` developers to implement the features outlined in this document. This document is merely a mechanism to facilitate discussion of a possible future direction for `Foam`.**
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Limitations of current templating](#limitations-of-current-templating)
|
||||
- [Too much friction to create a new note](#too-much-friction-to-create-a-new-note)
|
||||
- [Manual note creation (Mouse + Keyboard)](#manual-note-creation-mouse--keyboard)
|
||||
- [Manual note creation (Keyboard)](#manual-note-creation-keyboard)
|
||||
- [Foam missing note creation](#foam-missing-note-creation)
|
||||
- [`Markdown Notes: New Note` (Keyboard)](#markdown-notes-new-note-keyboard)
|
||||
- [Foam template note creation (Keyboard)](#foam-template-note-creation-keyboard)
|
||||
- [Templating of daily notes](#templating-of-daily-notes)
|
||||
- [Templating of filepaths](#templating-of-filepaths)
|
||||
- [Goal / Philosophy](#goal--philosophy)
|
||||
- [Proposal](#proposal)
|
||||
- [Summary](#summary)
|
||||
- [Add a `${title}` and `${titleSlug}` template variables](#add-a-title-and-titleslug-template-variables)
|
||||
- [Add a `Foam: Create New Note` command and hotkey](#add-a-foam-create-new-note-command-and-hotkey)
|
||||
- [Case 1: `.foam/templates/new-note.md` doesn't exist](#case-1-foamtemplatesnew-notemd-doesnt-exist)
|
||||
- [Case 2: `.foam/templates/new-note.md` exists](#case-2-foamtemplatesnew-notemd-exists)
|
||||
- [Change missing wikilinks to use the default template](#change-missing-wikilinks-to-use-the-default-template)
|
||||
- [Add a metadata section to templates](#add-a-metadata-section-to-templates)
|
||||
- [Example](#example)
|
||||
- [Add a replacement for `dateFormat`](#add-a-replacement-for-dateformat)
|
||||
- [Add support for daily note templates](#add-support-for-daily-note-templates)
|
||||
- [Eliminate all `foam.openDailyNote` settings](#eliminate-all-foamopendailynote-settings)
|
||||
- [Summary: resulting behaviour](#summary-resulting-behaviour)
|
||||
- [`Foam: Create New Note`](#foam-create-new-note)
|
||||
- [`Foam: Open Daily Note`](#foam-open-daily-note)
|
||||
- [Navigating to missing wikilinks](#navigating-to-missing-wikilinks)
|
||||
- [`Foam: Create Note From Template`](#foam-create-note-from-template)
|
||||
- [Extensions](#extensions)
|
||||
- [More variables in templates](#more-variables-in-templates)
|
||||
- [`defaultFilepath`](#defaultfilepath)
|
||||
- [Arbitrary hotkey -> template mappings?](#arbitrary-hotkey---template-mappings)
|
||||
|
||||
## Introduction
|
||||
|
||||
Creating of new notes in Foam is too cumbersome and slow. Despite their power, Foam templates can currently only be used in very limited scenarios.
|
||||
|
||||
This proposal aims to address these issues by streamlining note creation and by allowing templates to be used everywhere.
|
||||
|
||||
## Limitations of current templating
|
||||
|
||||
### Too much friction to create a new note
|
||||
|
||||
Creating new notes should an incredibly streamlined operation. There should be no friction to creating new notes.
|
||||
|
||||
Unfortunately, all of the current methods for creating notes are cumbersome.
|
||||
|
||||
#### Manual note creation (Mouse + Keyboard)
|
||||
|
||||
1. Navigate to the directory where you want the note
|
||||
2. Click the new file button
|
||||
3. Provide a filename
|
||||
4. Manually enter the template contents you want
|
||||
|
||||
#### Manual note creation (Keyboard)
|
||||
|
||||
1. Navigate to the directory where you want the note
|
||||
2. `⌘N` to create a new file
|
||||
3. `⌘S` to save the file and give it a filename
|
||||
4. Manually enter the template contents you want
|
||||
|
||||
#### Foam missing note creation
|
||||
|
||||
1. Open an existing note in the directory where you want the note
|
||||
2. Use the wikilinks syntax to create a link to the title of the note you want to have
|
||||
3. Use `Ctrl+Click`/`F12` to create the new file
|
||||
4. Manually enter the template contents you want
|
||||
|
||||
#### `Markdown Notes: New Note` (Keyboard)
|
||||
|
||||
1. Navigate to the directory where you want the note
|
||||
2. `Shift+⌘P` to open the command pallette
|
||||
3. Type `New Note` until it appears in the list. Press `Enter/Return` to select it.
|
||||
4. Enter a title for the note
|
||||
5. Manually enter the template contents you want
|
||||
|
||||
#### Foam template note creation (Keyboard)
|
||||
|
||||
1. `Shift+⌘P` to open the command pallette
|
||||
2. Type `Create New Note From Template` until it appears in the list. Press `Enter/Return` to select it.
|
||||
3. Use the arrow keys (or type the template name) to select the template. Press `Enter/Return` to select it.
|
||||
4. Modify the filepath to match the desired directory + filename. Press `Enter/Return` to select it.
|
||||
|
||||
All of these steps are far too cumbersome. And only the last one allows the use of templates.
|
||||
|
||||
### Templating of daily notes
|
||||
|
||||
Currently `Open Daily Note` opens an otherwise empty note, with a title defined by the `foam.openDailyNote.titleFormat` setting.
|
||||
Daily notes should be able to be fully templated as well.
|
||||
|
||||
### Templating of filepaths
|
||||
|
||||
As discussed in ["Template the filepath in `openDailyNote`"](https://github.com/foambubble/foam/issues/523), it would be useful to be able to specify the default filepaths of templates. For example, many people include timestamps in their filepaths.
|
||||
|
||||
## Goal / Philosophy
|
||||
|
||||
In a sentence: **Creating a new note should be a single button press and should use templates.**
|
||||
|
||||
## Proposal
|
||||
|
||||
1. Add a new `Foam: Create New Note` that is the streamlined counterpart to the more flexible `Foam: Create New Note From Template`
|
||||
2. Use templates everywhere
|
||||
3. Add metadata into the actual templates themselves in order to template the filepaths themselves.
|
||||
|
||||
### Summary
|
||||
|
||||
This can be done through a series of changes to the way that templates are implemented:
|
||||
|
||||
1. Add a `${title}` and `${titleSlug}` template variables
|
||||
2. Add a `Foam: Create New Note` command and hotkey
|
||||
3. Change missing wikilinks to use the default template
|
||||
4. Add a metadata section to templates
|
||||
5. Add a replacement for `dateFormat`
|
||||
6. Add support for daily note templates
|
||||
7. Eliminate all `foam.openDailyNote` settings
|
||||
|
||||
I've broken it out into these steps to show that the overall proposal can be implemented piecemeal in independent PRs that build on one another.
|
||||
|
||||
### Add a `${title}` and `${titleSlug}` template variables
|
||||
|
||||
When you use `Markdown Notes: New Note`, and give it a title, the title is formatted as a filename and also used as the title in the resulting note.
|
||||
|
||||
**Example:**
|
||||
|
||||
Given the title `Living in a dream world` to `Markdown Notes: New Note`, the filename is `living-in-a-dream-world.md` and the file contents are:
|
||||
|
||||
```markdown
|
||||
# Living in a dream world
|
||||
```
|
||||
|
||||
When creating a note from a template in Foam, you should be able to use a `${title}` variable. If the template uses the `${title}` variable, the user will be prompted for a title when they create a note from a template.
|
||||
|
||||
Example:
|
||||
|
||||
Given this `.foam/templates/my_template.md` template that uses the `${title}` variable:
|
||||
|
||||
```markdown
|
||||
# ${title}
|
||||
```
|
||||
|
||||
When a user asks for a new note using this template (eg. `Foam: Create New Note From Template`), VSCode will first ask the user for a title then provide it to the template, producing:
|
||||
|
||||
```markdown
|
||||
# Living in a dream world
|
||||
```
|
||||
|
||||
There will also be a `${titleSlug}` variable made available, which will be the "slugified" version of the title (eg. `living-in-a-dream-world`). This will be useful in later steps where we want to template the filepath of a template.
|
||||
|
||||
### Add a `Foam: Create New Note` command and hotkey
|
||||
|
||||
Instead of using `Markdown Notes: New Note`, Foam itself will have a `Create New Note` command that creates notes using templates.
|
||||
|
||||
This would open use the template found at `.foam/templates/new-note.md` to create the new note.
|
||||
|
||||
`Foam: Create New Note` will offer the fastest workflow for creating a note when you don't need customization, while `Foam: Create New Note From Template` will remain to serve a fully customizable (but slower) workflow.
|
||||
|
||||
#### Case 1: `.foam/templates/new-note.md` doesn't exist
|
||||
|
||||
If `.foam/templates/new-note.md` doesn't exist, it behaves the same as `Markdown Notes: New Note`:
|
||||
|
||||
* it would ask for a title and create the note in the current directory. It would open a note with the note containing the title.
|
||||
|
||||
**Note:** this would use an implicit default template, making use of the `${title}` variable.
|
||||
|
||||
#### Case 2: `.foam/templates/new-note.md` exists
|
||||
|
||||
If `.foam/templates/new-note.md` exists:
|
||||
|
||||
* it asks for the note title and creates the note in the current directory
|
||||
|
||||
**Progress:** At this point, we have a faster way to create new notes from templates.
|
||||
|
||||
### Change missing wikilinks to use the default template
|
||||
|
||||
Clicking on a dangling/missing wikilink should be equivalent to calling `Foam: Create New Note` with the contents of the link as the title.
|
||||
That way, creating a note by navigating to a missing note uses the default template.
|
||||
|
||||
### Add a metadata section to templates
|
||||
|
||||
* The `Foam: New Note` command creates a new note in the current directory. This is a sensible default that makes it quick, but lacks flexibility.
|
||||
* The `Foam: Create New Note From Template` asks the user to confirm/customize the filepath. This is more flexible but slower since there are more steps involved.
|
||||
|
||||
Both commands use templates. It would be nice if we could template the filepaths as well as the template contents (See ["Template the filepath in `openDailyNote`"](https://github.com/foambubble/foam/issues/523) for a more in-depth discussion the benefits of filepath templating).
|
||||
|
||||
In order to template the filepath, there needs to be a place where metadata like this can be specified.
|
||||
I think this metadata should be stored alongside the templates themselves. That way, it can make use of all the same template variable available to the templates themselves.
|
||||
|
||||
Conceptually, adding metadata to the templates is similar to Markdown frontmatter, though the choice of exact syntax for adding this metadata will have to be done with care since the templates can contain arbitrary contents including frontmatter.
|
||||
|
||||
#### Example
|
||||
|
||||
A workable syntax is still to be determined.
|
||||
While this syntax probably doesn't work as a solution, for this example I will demonstrate the concept using a second frontmatter block:
|
||||
|
||||
```markdown
|
||||
<!-- The below front-matter block is for foam-specific template settings -->
|
||||
<!-- It is removed when the user creates a new note using this template -->
|
||||
---
|
||||
<!-- The default filepath to use when using this template -->
|
||||
<!-- Relative paths are relative to the workspace, absolute paths are absolute -->
|
||||
<!-- Note that you can include VSCode snippet variables to template the path -->
|
||||
filepath: `journal/${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}_${titleSlug}.md`
|
||||
---
|
||||
|
||||
<!-- The actual contents of the template begin after the `---` thematic break immediately below this line-->
|
||||
---
|
||||
---
|
||||
created: ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}T${CURRENT_HOUR}:${CURRENT_MINUTE}:${CURRENT_SECOND}
|
||||
tags: []
|
||||
---
|
||||
|
||||
# ${title}
|
||||
```
|
||||
|
||||
In this example, using this template improves the UX:
|
||||
|
||||
In `Foam: Create New Note` workflow, having `filepath` metadata within `.foam/templates/new-note.md` allows for control over the filepath without having to introduce any more UX steps to create a new note. It's still just a hotkey away and a title.
|
||||
|
||||
As we'll see, when it comes to allowing daily notes to be templated, we don't even need to use `${title}` in our template, in which case we don't we don't even need to prompt for a title.
|
||||
|
||||
In the `Create New Note From Template` workflow, during the step where we allow the user to customize the filepath, it will already templated according to the `filepath` in the template's metadata. This means that the user has to make fewer changes to the path, especially in cases where they want to include things like datetimes in the filenames. This makes it faster (eg. don't have to remember what day it is, and don't have to type it) and less error-prone (eg. when they accidentally type the wrong date).
|
||||
|
||||
### Add a replacement for `dateFormat`
|
||||
|
||||
`foam.openDailyNote.filenameFormat` uses `dateFormat()` to put the current timestamp into the daily notes filename. This is much more flexible than what is available in VSCode Snippet variables. Before daily notes are switched over to use templates, we will have to come up with another mechanism/syntax to allow for calls to `dateFormat()` within template files.
|
||||
|
||||
This would be especially useful in the migration of users to the new daily notes templates. For example, if `.foam/templates/daily-note.md` is unset, then we could generate an implicit template for use by `Foam: Open Daily Note`. Very roughly something like:
|
||||
|
||||
```markdown
|
||||
<!-- The below front-matter block is for foam-specific template settings -->
|
||||
<!-- It is removed when the user creates a new note using this template -->
|
||||
---
|
||||
<!-- The default filepath to use when using this template -->
|
||||
<!-- Relative paths are relative to the workspace, absolute paths are absolute -->
|
||||
<!-- Note that you can include VSCode snippet variables to template the path -->
|
||||
filepath: `${foam.openDailyNote.directory}/${foam.openDailyNote.filenameFormat}.${foam.openDailyNote.fileExtension}`
|
||||
---
|
||||
|
||||
<!-- The actual contents of the template begin after the `---` thematic break immediately below this line-->
|
||||
---
|
||||
# ${foam.openDailyNote.titleFormat}
|
||||
```
|
||||
|
||||
### Add support for daily note templates
|
||||
|
||||
With the above features implemented, making daily notes use templates is simple.
|
||||
|
||||
We define a `.foam/templates/daily-note.md` filepath that the `Foam: Open Daily Note` command will always use to find its daily note template.
|
||||
If `.foam/templates/daily-note.md` does not exist, it falls back to a default, implicitly defined daily notes template (which follows the default behaviour of the current `foam.openDailyNote` settings).
|
||||
|
||||
Both `Foam: Open Daily Note` and `Foam: Create New Note` can share all of the implementation code, with the only differences being the hotkeys used and the template filepath used.
|
||||
|
||||
Example daily note template (again using the example syntax of the foam-specific frontmatter block):
|
||||
|
||||
```markdown
|
||||
<!-- The below front-matter block is for foam-specific template settings -->
|
||||
<!-- It is removed when the user creates a new note using this template -->
|
||||
---
|
||||
<!-- The default filepath to use when using this template -->
|
||||
<!-- Relative paths are relative to the workspace, absolute paths are absolute -->
|
||||
<!-- Note that you can include VSCode snippet variables to template the path -->
|
||||
filepath: `journal/${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}.md`
|
||||
---
|
||||
|
||||
<!-- The actual contents of the template begin after the `---` thematic break immediately below this line-->
|
||||
---
|
||||
# ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}
|
||||
```
|
||||
|
||||
Since there is no use of the `${title}` variable, opening the daily note behaves exactly as it does today and automatically opens the note with no further user interaction.
|
||||
|
||||
### Eliminate all `foam.openDailyNote` settings
|
||||
|
||||
Now that all of the functionality of the `foam.openDailyNote` settings have been obviated, these settings can be removed:
|
||||
|
||||
* `foam.openDailyNote.directory`, `foam.openDailyNote.filenameFormat`, and `foam.openDailyNote.fileExtension` can be specified in the `filepath` metadata of the daily note template.
|
||||
* `foam.openDailyNote.titleFormat` has been replaced by the ability to fully template the daily note, including the title.
|
||||
|
||||
## Summary: resulting behaviour
|
||||
|
||||
### `Foam: Create New Note`
|
||||
|
||||
A new command optimized for speedy creation of new notes. This will become the default way to create new notes. In its fastest form, it simply opens the new note with no further user interaction.
|
||||
|
||||
### `Foam: Open Daily Note`
|
||||
|
||||
Simplified since it no longer has its custom settings, and re-uses all the same implementation code as `Foam: Create New Note`.
|
||||
Templates can now be used with daily notes.
|
||||
|
||||
### Navigating to missing wikilinks
|
||||
|
||||
Now creates the new notes using the default template. Re-uses all the same implementation code as `Foam: Create New Note`
|
||||
Now uses the contents of the wikilink as the `${title}` parameter for the template.
|
||||
|
||||
### `Foam: Create Note From Template`
|
||||
|
||||
Almost the exact same as it is today. However, with `${title}` and `filepath` templating, users will have less changes to make in the filepath confirmation step.
|
||||
It's the slower but more powerful version of `Foam: Create New Note`, allowing you to pick any template, as well as customize the filepath.
|
||||
|
||||
## Extensions
|
||||
|
||||
In addition to the ideas of this proposal, there are ways we could imagine extending it. These are all "out of scope" for this design, but thinking about them could be useful to guide our thinking about this design.
|
||||
|
||||
### More variables in templates
|
||||
|
||||
`${title}` is necessary in this case to replace the functionality of `Markdown Notes: New Note`.
|
||||
However, one could imagine that this pattern of "Ask the user for a value for missing variable values" could be useful in other situations too.
|
||||
Perhaps users could even define their own (namespaced) template variables, and Foam would ask them for values to use for each when creating a note using a template that used those variables.
|
||||
|
||||
### `defaultFilepath`
|
||||
|
||||
By using `defaultFilepath` instead of `filepath` in the metadata section, you could have more control over the note creation without having to fall back to the full `Create New Note From Template` workflow.
|
||||
|
||||
* `filepath` will not ask the user for the file path, simply use the value provided (as described above)
|
||||
* `defaultFilepath` will ask the user for the file path, pre-populating the file path using `defaultFilepath`
|
||||
|
||||
The first allows "one-click" note creation, the second more customization.
|
||||
This might not be necessary, or this might not be the right way to solve the problem. We'll see.
|
||||
|
||||
### Arbitrary hotkey -> template mappings?
|
||||
|
||||
`Foam: Open Daily Note` and `Foam: Create New Note` only differ by their hotkey and their default template setting.
|
||||
Is there a reason/opportunity to abstract this further and allow for users to define custom `hotkey -> template` mappings?
|
||||
@@ -1,16 +1,16 @@
|
||||
# Releasing Foam
|
||||
|
||||
1. Get to the latest code
|
||||
- `git checkout master && git fetch && git rebase`
|
||||
- `git checkout main && git fetch && git rebase`
|
||||
2. Sanity checks
|
||||
- `yarn reset`
|
||||
- `yarn test`
|
||||
3. Update change log
|
||||
3. Update change log
|
||||
- `./packages/foam-vscode/CHANGELOG.md`
|
||||
- `git add *`
|
||||
- `git commit -m"Preparation for next release"`
|
||||
4. Update version
|
||||
- `$ yarn version-extension <version>` (where `version` is `patch/minor/major`)
|
||||
- `$ yarn version-extension <version>` (where `version` is `patch/minor/major`)
|
||||
5. Package extension
|
||||
- `$ yarn package-extension`
|
||||
6. Publish extension
|
||||
@@ -20,6 +20,6 @@
|
||||
- select "tags" in top left
|
||||
- select the tag that was just released, click "edit" and copy release information from changelog
|
||||
- publish (no need to attach artifacts)
|
||||
8. Annouce on Discord
|
||||
8. Announce on Discord
|
||||
|
||||
Steps 1 to 6 should really be replaced by a GitHub action...
|
||||
Steps 1 to 6 should really be replaced by a GitHub action...
|
||||
|
||||
130
docs/dev/testing.md
Normal file
130
docs/dev/testing.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# Testing in Foam VS Code Extension
|
||||
|
||||
This document explains the testing strategy and conventions used in the Foam VS Code extension.
|
||||
|
||||
## Test File Types
|
||||
|
||||
We use two distinct types of test files, each serving different purposes:
|
||||
|
||||
### `.test.ts` Files - Pure Unit Tests
|
||||
|
||||
- **Purpose**: Test business logic and algorithms in complete isolation
|
||||
- **Dependencies**: No VS Code APIs dependencies
|
||||
- **Environment**: Pure Jest with Node.js
|
||||
- **Speed**: Very fast execution
|
||||
- **Location**: Throughout the codebase alongside source files
|
||||
|
||||
### `.spec.ts` Files - Integration Tests with VS Code APIs
|
||||
|
||||
- **Purpose**: Test features that integrate with VS Code APIs and user workflows
|
||||
- **Dependencies**: Will likely depend on VS Code APIs (`vscode` module), otherwise avoid incurring the performance hit
|
||||
- **Environment**: Can run in TWO environments:
|
||||
- **Mock Environment**: Jest with VS Code API mocks (fast)
|
||||
- **Real VS Code**: Full VS Code extension host (slow but comprehensive)
|
||||
- **Speed**: Depends on environment (see performance section below)
|
||||
- **Location**: Primarily in `src/features/` and service layers
|
||||
|
||||
## Key Principle: Environment Flexibility for `.spec.ts` Files
|
||||
|
||||
**`.spec.ts` files use VS Code APIs**, but they can run in different environments:
|
||||
|
||||
- **Mock Environment**: Uses our VS Code API mocks for speed
|
||||
- **Real VS Code**: Uses actual VS Code extension host for full integration testing
|
||||
|
||||
This dual-environment capability allows us to:
|
||||
|
||||
- Run specs quickly during development (mock environment)
|
||||
- Verify full integration during CI/CD (real VS Code environment)
|
||||
- Gradually migrate specs to mock-compatible implementations
|
||||
|
||||
## Performance Comparison
|
||||
|
||||
| Test Type | Environment | Typical Duration | VS Code APIs |
|
||||
| --------------------- | ---------------------- | ---------------- | ---------------- |
|
||||
| **`.test.ts`** | Pure Jest | fastest | **No** |
|
||||
| **`.spec.ts` (mock)** | Jest + VS Code Mocks | fast | **Yes** (mocked) |
|
||||
| **`.spec.ts` (real)** | VS Code Extension Host | sloooooow. | **Yes** (real) |
|
||||
|
||||
## Running Tests
|
||||
|
||||
### Available Commands
|
||||
|
||||
- **`yarn test:unit`**: Runs `.test.ts` files (no VS Code dependencies) + `@unit-ready` marked `.spec.ts` files using mocks
|
||||
- **`yarn test:unit-without-specs`**: Runs only `.test.ts` files
|
||||
- **`yarn test:e2e`**: Runs all `.spec.ts` files in full VS Code extension host
|
||||
- **`yarn test`**: Runs both unit and e2e test suites sequentially
|
||||
|
||||
## Mock Environment Migration
|
||||
|
||||
We're gradually enabling `.spec.ts` files to run in our fast mock environment while maintaining their ability to run in real VS Code.
|
||||
|
||||
### The `@unit-ready` Annotation
|
||||
|
||||
Spec files marked with `/* @unit-ready */` can run in both environments:
|
||||
|
||||
```typescript
|
||||
/* @unit-ready */
|
||||
import * as vscode from 'vscode';
|
||||
// ... test uses VS Code APIs but works with our mocks
|
||||
```
|
||||
|
||||
### Common Migration Fixes
|
||||
|
||||
**Configuration defaults**: Our mocks don't load package.json defaults
|
||||
|
||||
```typescript
|
||||
// Before
|
||||
const format = getFoamVsCodeConfig('openDailyNote.filenameFormat');
|
||||
|
||||
// After (defensive)
|
||||
const format = getFoamVsCodeConfig(
|
||||
'openDailyNote.filenameFormat',
|
||||
'yyyy-mm-dd'
|
||||
);
|
||||
```
|
||||
|
||||
**File system operations**: Ensure proper async handling
|
||||
|
||||
```typescript
|
||||
// Mock file operations are immediate but still async
|
||||
await vscode.workspace.fs.writeFile(uri, content);
|
||||
```
|
||||
|
||||
### When NOT to Migrate
|
||||
|
||||
Some specs should remain real-VS-Code-only:
|
||||
|
||||
- Tests verifying complex VS Code UI interactions
|
||||
- Tests requiring real file system watching with timing
|
||||
- Tests validating extension packaging or activation
|
||||
- Tests that depend on VS Code's complex internal state management
|
||||
|
||||
## Mock System Capabilities
|
||||
|
||||
Our `vscode-mock.ts` provides comprehensive VS Code API mocking:
|
||||
|
||||
## Contributing Guidelines
|
||||
|
||||
When adding new tests:
|
||||
|
||||
1. **Choose the right type**:
|
||||
|
||||
- Use `.test.ts` for pure business logic with no VS Code dependencies
|
||||
- Use `.spec.ts` for anything that needs VS Code APIs
|
||||
|
||||
2. **Consider mock compatibility**:
|
||||
|
||||
- When writing `.spec.ts` files, consider if they could run in mock environment
|
||||
- Add `/* @unit-ready */` if the test works with our mocks
|
||||
|
||||
3. **Follow naming conventions**:
|
||||
|
||||
- Test files should be co-located with source files when possible
|
||||
- Use descriptive test names that explain the expected behavior
|
||||
|
||||
4. **Performance awareness**:
|
||||
- Prefer unit tests for business logic (fastest)
|
||||
- Use mock-compatible specs for VS Code integration (fast)
|
||||
- Reserve real VS Code specs for complex integration scenarios (comprehensive)
|
||||
|
||||
This testing strategy gives us the best of both worlds: fast feedback during development and comprehensive integration verification when needed.
|
||||
@@ -10,7 +10,6 @@ Uncategorised thoughts, to be added
|
||||
- Investigate other similar extensions:
|
||||
- [Unotes](https://marketplace.visualstudio.com/items?itemName=ryanmcalister.Unotes)
|
||||
- [vscode-memo](https://github.com/svsool/vscode-memo)
|
||||
- [gistpad wiki](https://github.com/jevakallio/gistpad/tree/master/src/repos/wiki)
|
||||
- Open in Foam
|
||||
- When you want to open a Foam published website in your own VS Code, we could have a "Open in Foam" link that opens the link in VS Code via a url binding (if possible), downloads the github repo locally, and opens it as a Foam workspace.
|
||||
- Every Foam could have a different theme even in the editor, so you'll see it like they see it
|
||||
|
||||
428
docs/index.md
428
docs/index.md
@@ -1,10 +1,25 @@
|
||||
# Foam
|
||||
# What is Foam?
|
||||
|
||||
**Foam** is a personal knowledge management and sharing system inspired by [Roam Research](https://roamresearch.com/), built on [Visual Studio Code](https://code.visualstudio.com/) and [GitHub](https://github.com/).
|
||||
Foam is a personal knowledge management system built on [Visual Studio Code](https://code.visualstudio.com/) and [GitHub](https://github.com/). It helps you organize research, create discoverable notes, and publish your knowledge.
|
||||
|
||||
You can use **Foam** for organising your research, keeping re-discoverable notes, writing long-form content and, optionally, publishing it to the web.
|
||||
## Key Features
|
||||
|
||||
**Foam** is free, open source, and extremely extensible to suit your personal workflow. You own the information you create with Foam, and you're free to share it, and collaborate on it with anyone you want.
|
||||
- **Wikilinks** - Connect thoughts with `[[double bracket]]` syntax
|
||||
- **Embeds** - Include content from other notes with `![[note]]` syntax
|
||||
- **Backlinks** - Automatically discover connections between notes
|
||||
- **Graph visualization** - See your knowledge network visually
|
||||
- **Daily notes** - Capture timestamped thoughts
|
||||
- **Templates** - Standardize note creation
|
||||
- **Tags** - Organize and filter content
|
||||
|
||||
## Why Choose Foam?
|
||||
|
||||
- **Free and open source** - No subscriptions or vendor lock-in
|
||||
- **Own your data** - Notes stored as standard Markdown files
|
||||
- **VS Code integration** - Leverage powerful editing and extensions
|
||||
- **Git-based** - Version control and collaboration built-in
|
||||
|
||||
Foam is like a bathtub: _What you get out of it depends on what you put into it._
|
||||
|
||||
<p class="announcement">
|
||||
<b>New!</b> Join <a href="https://foambubble.github.io/join-discord/w" target="_blank">Foam community Discord</a> for users and contributors!
|
||||
@@ -17,88 +32,79 @@ You can use **Foam** for organising your research, keeping re-discoverable notes
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Foam](#foam)
|
||||
- [What is Foam?](#what-is-foam)
|
||||
- [Key Features](#key-features)
|
||||
- [Why Choose Foam?](#why-choose-foam)
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [How do I use Foam?](#how-do-i-use-foam)
|
||||
- [What's in a Foam?](#whats-in-a-foam)
|
||||
- [Getting started](#getting-started)
|
||||
- [Features](#features)
|
||||
- [Call To Adventure](#call-to-adventure)
|
||||
- [Contributing](#contributing)
|
||||
- [Thanks and attribution](#thanks-and-attribution)
|
||||
- [License](#license)
|
||||
|
||||
## How do I use Foam?
|
||||
|
||||
**Foam** is a tool that supports creating relationships between thoughts and information to help you think better.
|
||||
Foam helps you create relationships between thoughts and information through:
|
||||
|
||||
Whether you want to build a [Second Brain](https://www.buildingasecondbrain.com/) or a [Zettelkasten](https://zettelkasten.de/posts/overview/), write a book, or just get better at long-term learning, **Foam** can help you organise your thoughts if you follow these simple rules:
|
||||
1. **Atomic notes** - Write focused markdown documents on single topics
|
||||
2. **Wikilinks** - Connect ideas with `[[double bracket]]` syntax
|
||||
3. **Backlinks** - Discover unexpected connections between notes
|
||||
4. **Graph visualization** - See your knowledge network visually
|
||||
|
||||
1. Create a single **Foam** workspace for all your knowledge and research following the [Getting started](#getting-started) guide.
|
||||
2. Write your thoughts in markdown documents (I like to call them **Bubbles**, but that might be more than a little twee). These documents should be atomic: Put things that belong together into a single document, and limit its content to that single topic. ([source](https://zettelkasten.de/posts/overview/#principles))
|
||||
3. Use Foam's shortcuts and autocompletions to link your thoughts together with `[[wikilinks]]`, and navigate between them to explore your knowledge graph.
|
||||
4. Get an overview of your **Foam** workspace using a [[graph-visualization]] (⚠️ WIP), and discover relationships between your thoughts with the use of [[backlinking]].
|
||||
|
||||
Foam is a like a bathtub: _What you get out of it depends on what you put into it._
|
||||
Success with Foam depends on consistent note-taking and linking habits.
|
||||
|
||||
## What's in a Foam?
|
||||
|
||||
Like the soapy suds it's named after, **Foam** is mostly air.
|
||||
Foam combines existing tools:
|
||||
|
||||
1. The editing experience of **Foam** is powered by VS Code, enhanced by workspace settings that glue together [[recommended-extensions]] and preferences optimised for writing and navigating information.
|
||||
2. To back up, collaborate on and share your content between devices, Foam pairs well with [GitHub](http://github.com/).
|
||||
3. To publish your content, you can set it up to publish to [GitHub Pages](https://pages.github.com/), or to any website hosting platform like [Netlify](http://netlify.com/) or [Vercel](https://vercel.com).
|
||||
1. **VS Code** - Enhanced with [[recommended-extensions]] optimized for knowledge management
|
||||
2. **GitHub** - Version control, backup, and collaboration
|
||||
3. **Static site generators** - Publish to GitHub Pages, Netlify, or Vercel
|
||||
|
||||
> **Fun fact**: This documentation was researched, written and published using **Foam**.
|
||||
> This documentation was created using Foam.
|
||||
|
||||
## Getting started
|
||||
|
||||
> ⚠️ Foam is still in preview. Expect the experience to be a little rough.
|
||||
**Requirements:** GitHub account and Visual Studio Code
|
||||
|
||||
These instructions assume you have a GitHub account, and you have Visual Studio Code installed.
|
||||
|
||||
1. Use the [foam-template project](https://github.com/foambubble/foam-template) to generate a new repository. If you're logged into GitHub, you can just hit this button:
|
||||
1. **Create repository** - Use the [foam-template](https://github.com/foambubble/foam-template) to generate a new repository
|
||||
|
||||
<a class="github-button" href="https://github.com/foambubble/foam-template/generate" data-icon="octicon-repo-template" data-size="large" aria-label="Use this template foambubble/foam-template on GitHub">Use this template</a>
|
||||
|
||||
*If you want to keep your thoughts to yourself, remember to set the repository private, or if you don't want to use GitHub to host your workspace at all, choose [**Download as ZIP**](https://github.com/foambubble/foam-template/archive/master.zip) instead of **Use this template**.*
|
||||
2. **Clone and open** - Clone locally and open the folder in VS Code
|
||||
3. **Install extensions** - Click "Install all" when prompted for recommended extensions
|
||||
4. **Configure** - Edit `.vscode/settings.json` for your preferences
|
||||
|
||||
2. [Clone the repository locally](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository) and open it in VS Code.
|
||||
**Next steps:**
|
||||
|
||||
*Open the repository as a folder using the `File > Open...` menu item. In VS Code, "open workspace" refers to [multi-root workspaces](https://code.visualstudio.com/docs/editor/multi-root-workspaces).*
|
||||
|
||||
3. When prompted to install recommended extensions, click **Install all** (or **Show Recommendations** if you want to review and install them one by one)
|
||||
|
||||
After setting up the repository, open `.vscode/settings.json` and edit, add or remove any settings you'd like for your Foam workspace.
|
||||
|
||||
* *If using a [multi-root workspace](https://code.visualstudio.com/docs/editor/multi-root-workspaces) as noted above, make sure that your **Foam** directory is first in the list. There are some settings that will need to be migrated from `.vscode/settings.json` to your `.code-workspace` file.*
|
||||
|
||||
To learn more about how to use **Foam**, read the [[recipes]].
|
||||
|
||||
Getting stuck in the setup? Read the [[frequently-asked-questions]].
|
||||
|
||||
Check our [issues on GitHub](http://github.com/foambubble/foam/issues) if you get stuck on something, and create a new one if something doesn't seem right!
|
||||
- Explore the [[recipes]] for usage patterns
|
||||
- Check [[frequently-asked-questions]] if you need help
|
||||
- Report issues on [GitHub](http://github.com/foambubble/foam/issues)
|
||||
|
||||
## Features
|
||||
|
||||
**Foam** doesn't have features in the traditional sense. Out of the box, you have access to all features of VS Code and all the [[recommended-extensions]] you choose to install, but it's up to you to discover what you can do with it!
|
||||
Foam leverages VS Code and [[recommended-extensions]] to provide:
|
||||
|
||||
- **Wikilinks** with autocomplete and navigation
|
||||
- **Backlinks** panel showing connections
|
||||
- **Graph visualization** of your knowledge network
|
||||
- **Daily notes** with templates and snippets
|
||||
- **Tag system** for organization
|
||||
- **Publishing** to static sites
|
||||
|
||||

|
||||
|
||||
Head over to [[recipes]] for some useful patterns and ideas!
|
||||
Explore [[recipes]] for usage patterns and workflows.
|
||||
|
||||
## Call To Adventure
|
||||
## Contributing
|
||||
|
||||
The goal of **Foam** is to be your personal companion on your quest for knowledge.
|
||||
Foam is an evolving project and we welcome contributions:
|
||||
|
||||
It's currently about "10% ready" relative to all the features I've thought of, but I've only thought of ~1% of the features it could have, and I'm excited to learn from others.
|
||||
|
||||
I am using it as my personal thinking tool. By making it public, I hope to learn from others not only how to improve Foam, but also to improve how I learn and manage information.
|
||||
|
||||
If that sounds like something you're interested in, I'd love to have you along on the journey.
|
||||
|
||||
- Read about our [[principles]] to understand Foam's philosophy and direction
|
||||
- Read the [[contribution-guide]] guide to learn how to participate.
|
||||
- Feel free to open [GitHub issues](https://github.com/foambubble/foam/issues) to give me feedback and ideas for new features.
|
||||
- Read our [[principles]] to understand Foam's philosophy
|
||||
- Follow the [[contribution-guide]] to get involved
|
||||
- Share feedback via [GitHub issues](https://github.com/foambubble/foam/issues)
|
||||
|
||||
## Thanks and attribution
|
||||
|
||||
@@ -106,138 +112,176 @@ If that sounds like something you're interested in, I'd love to have you along o
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://jevakallio.dev/"><img src="https://avatars1.githubusercontent.com/u/1203949?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Jani Eväkallio</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jevakallio" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jevakallio" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://joeprevite.com/"><img src="https://avatars3.githubusercontent.com/u/3806031?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Joe Previte</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jsjoeio" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jsjoeio" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/riccardoferretti"><img src="https://avatars3.githubusercontent.com/u/457005?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Riccardo</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=riccardoferretti" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=riccardoferretti" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://ojanaho.com/"><img src="https://avatars0.githubusercontent.com/u/2180090?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Janne Ojanaho</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jojanaho" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jojanaho" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://bypaulshen.com/"><img src="https://avatars3.githubusercontent.com/u/2266187?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Paul Shen</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=paulshen" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/coffenbacher"><img src="https://avatars0.githubusercontent.com/u/245867?v=4?s=60" width="60px;" alt=""/><br /><sub><b>coffenbacher</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=coffenbacher" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://mathieu.dutour.me/"><img src="https://avatars2.githubusercontent.com/u/3254314?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Mathieu Dutour</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=mathieudutour" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/presidentelect"><img src="https://avatars2.githubusercontent.com/u/1242300?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Michael Hansen</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=presidentelect" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://klickverbot.at/"><img src="https://avatars1.githubusercontent.com/u/19335?v=4?s=60" width="60px;" alt=""/><br /><sub><b>David Nadlinger</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dnadlinger" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://pluckd.co/"><img src="https://avatars2.githubusercontent.com/u/20598571?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Fernando</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MrCordeiro" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/jfgonzalez7"><img src="https://avatars3.githubusercontent.com/u/58857736?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Juan Gonzalez</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jfgonzalez7" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://www.louiechristie.com/"><img src="https://avatars1.githubusercontent.com/u/6807448?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Louie Christie</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=louiechristie" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://supersandro.de/"><img src="https://avatars2.githubusercontent.com/u/7258858?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Sandro</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=SuperSandro2000" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Skn0tt"><img src="https://avatars1.githubusercontent.com/u/14912729?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Simon Knott</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Skn0tt" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://styfle.dev/"><img src="https://avatars1.githubusercontent.com/u/229881?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Steven</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=styfle" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Georift"><img src="https://avatars2.githubusercontent.com/u/859430?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Tim</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Georift" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/sauravkhdoolia"><img src="https://avatars1.githubusercontent.com/u/34188267?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Saurav Khdoolia</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=sauravkhdoolia" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://anku.netlify.com/"><img src="https://avatars1.githubusercontent.com/u/22813027?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Ankit Tiwari</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=anku255" title="Documentation">📖</a> <a href="https://github.com/foambubble/foam/commits?author=anku255" title="Tests">⚠️</a> <a href="https://github.com/foambubble/foam/commits?author=anku255" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ayushbaweja"><img src="https://avatars1.githubusercontent.com/u/44344063?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Ayush Baweja</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ayushbaweja" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/TaiChi-IO"><img src="https://avatars3.githubusercontent.com/u/65092992?v=4?s=60" width="60px;" alt=""/><br /><sub><b>TaiChi-IO</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=TaiChi-IO" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/juanfrank77"><img src="https://avatars1.githubusercontent.com/u/12146882?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Juan F Gonzalez </b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=juanfrank77" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://sanketdg.github.io"><img src="https://avatars3.githubusercontent.com/u/8980971?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Sanket Dasgupta</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=SanketDG" title="Documentation">📖</a> <a href="https://github.com/foambubble/foam/commits?author=SanketDG" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/nstafie"><img src="https://avatars1.githubusercontent.com/u/10801854?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Nicholas Stafie</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=nstafie" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/francishamel"><img src="https://avatars3.githubusercontent.com/u/36383308?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Francis Hamel</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=francishamel" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://digiguru.co.uk"><img src="https://avatars1.githubusercontent.com/u/619436?v=4?s=60" width="60px;" alt=""/><br /><sub><b>digiguru</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=digiguru" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=digiguru" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/chirag-singhal"><img src="https://avatars3.githubusercontent.com/u/42653703?v=4?s=60" width="60px;" alt=""/><br /><sub><b>CHIRAG SINGHAL</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=chirag-singhal" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/lostintangent"><img src="https://avatars3.githubusercontent.com/u/116461?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Jonathan Carter</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=lostintangent" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.synesthesia.co.uk"><img src="https://avatars3.githubusercontent.com/u/181399?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Julian Elve</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=synesthesia" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/thomaskoppelaar"><img src="https://avatars3.githubusercontent.com/u/36331365?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Thomas Koppelaar</b></sub></a><br /><a href="#question-thomaskoppelaar" title="Answering Questions">💬</a> <a href="https://github.com/foambubble/foam/commits?author=thomaskoppelaar" title="Code">💻</a> <a href="#userTesting-thomaskoppelaar" title="User Testing">📓</a></td>
|
||||
<td align="center"><a href="http://www.akshaymehra.com"><img src="https://avatars1.githubusercontent.com/u/8671497?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Akshay</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MehraAkshay" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://johnlindquist.com"><img src="https://avatars0.githubusercontent.com/u/36073?v=4?s=60" width="60px;" alt=""/><br /><sub><b>John Lindquist</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=johnlindquist" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://ashwin.run/"><img src="https://avatars2.githubusercontent.com/u/1689183?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Ashwin Ramaswami</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=epicfaace" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Klaudioz"><img src="https://avatars1.githubusercontent.com/u/632625?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Claudio Canales</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Klaudioz" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/vitaly-pevgonen"><img src="https://avatars0.githubusercontent.com/u/6272738?v=4?s=60" width="60px;" alt=""/><br /><sub><b>vitaly-pevgonen</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=vitaly-pevgonen" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://dshemetov.github.io"><img src="https://avatars0.githubusercontent.com/u/1810426?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Dmitry Shemetov</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dshemetov" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/hooncp"><img src="https://avatars1.githubusercontent.com/u/48883554?v=4?s=60" width="60px;" alt=""/><br /><sub><b>hooncp</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=hooncp" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://rt-canada.ca"><img src="https://avatars1.githubusercontent.com/u/13721239?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Martin Laws</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=martinlaws" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://seanksmith.me"><img src="https://avatars3.githubusercontent.com/u/2085441?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Sean K Smith</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=sksmith" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/kevin-neely/"><img src="https://avatars1.githubusercontent.com/u/37545028?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Kevin Neely</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=kneely" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://ariefrahmansyah.dev"><img src="https://avatars3.githubusercontent.com/u/8122852?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Arief Rahmansyah</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ariefrahmansyah" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://vhanda.in"><img src="https://avatars2.githubusercontent.com/u/426467?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Vishesh Handa</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=vHanda" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://www.linkedin.com/in/heroichitesh"><img src="https://avatars3.githubusercontent.com/u/37622734?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Hitesh Kumar</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=HeroicHitesh" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://spencerwoo.com"><img src="https://avatars2.githubusercontent.com/u/32114380?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Spencer Woo</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=spencerwooo" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://ingalless.com"><img src="https://avatars3.githubusercontent.com/u/22981941?v=4?s=60" width="60px;" alt=""/><br /><sub><b>ingalless</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ingalless" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=ingalless" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://jmg-duarte.github.io"><img src="https://avatars2.githubusercontent.com/u/15343819?v=4?s=60" width="60px;" alt=""/><br /><sub><b>José Duarte</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jmg-duarte" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jmg-duarte" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.yenly.wtf"><img src="https://avatars1.githubusercontent.com/u/6759658?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Yenly</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=yenly" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.hikerpig.cn"><img src="https://avatars1.githubusercontent.com/u/2259688?v=4?s=60" width="60px;" alt=""/><br /><sub><b>hikerpig</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=hikerpig" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://sigfried.org"><img src="https://avatars1.githubusercontent.com/u/1586931?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Sigfried Gold</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Sigfried" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://www.tristansokol.com"><img src="https://avatars3.githubusercontent.com/u/867661?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Tristan Sokol</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=tristansokol" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://umbrellait.com"><img src="https://avatars0.githubusercontent.com/u/49779373?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Danil Rodin</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=umbrellait-danil-rodin" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/scottjoewilliams/"><img src="https://avatars1.githubusercontent.com/u/2026866?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Scott Williams</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=scott-joe" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://jackiexiao.github.io/blog"><img src="https://avatars2.githubusercontent.com/u/18050469?v=4?s=60" width="60px;" alt=""/><br /><sub><b>jackiexiao</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Jackiexiao" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://generativist.substack.com/"><img src="https://avatars3.githubusercontent.com/u/78835?v=4?s=60" width="60px;" alt=""/><br /><sub><b>John B Nelson</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jbn" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/asifm"><img src="https://avatars2.githubusercontent.com/u/3958387?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Asif Mehedi</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=asifm" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/litanlitudan"><img src="https://avatars2.githubusercontent.com/u/4970420?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Tan Li</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=litanlitudan" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://shaunagordon.com"><img src="https://avatars1.githubusercontent.com/u/579361?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Shauna Gordon</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ShaunaGordon" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://mcluck.tech"><img src="https://avatars1.githubusercontent.com/u/1753801?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Mike Cluck</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MCluck90" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://brandonpugh.com"><img src="https://avatars1.githubusercontent.com/u/684781?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Brandon Pugh</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=bpugh" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://max.davitt.me"><img src="https://avatars1.githubusercontent.com/u/27709025?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Max Davitt</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=themaxdavitt" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://briananglin.me"><img src="https://avatars3.githubusercontent.com/u/2637602?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Brian Anglin</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=anglinb" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://deft.work"><img src="https://avatars1.githubusercontent.com/u/1455507?v=4?s=60" width="60px;" alt=""/><br /><sub><b>elswork</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=elswork" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://leonh.fr/"><img src="https://avatars.githubusercontent.com/u/19996318?v=4?s=60" width="60px;" alt=""/><br /><sub><b>léon h</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=leonhfr" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://nygaard.site"><img src="https://avatars.githubusercontent.com/u/4606342?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Nikhil Nygaard</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=njnygaard" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://www.nitwit.se"><img src="https://avatars.githubusercontent.com/u/1382124?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Mark Dixon</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=nitwit-se" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/joeltjames"><img src="https://avatars.githubusercontent.com/u/3732400?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Joel James</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=joeltjames" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.ryo33.com"><img src="https://avatars.githubusercontent.com/u/8780513?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Hashiguchi Ryo</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ryo33" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://movermeyer.com"><img src="https://avatars.githubusercontent.com/u/1459385?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Michael Overmeyer</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=movermeyer" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/derrickqin"><img src="https://avatars.githubusercontent.com/u/3038111?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Derrick Qin</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=derrickqin" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/zomars/"><img src="https://avatars.githubusercontent.com/u/3504472?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Omar López</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=zomars" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://robincn.com"><img src="https://avatars.githubusercontent.com/u/1583193?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Robin King</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=RobinKing" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://twitter.com/deegovee"><img src="https://avatars.githubusercontent.com/u/4730170?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Dheepak </b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dheepakg" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/daniel-vera-g"><img src="https://avatars.githubusercontent.com/u/28257108?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Daniel VG</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=daniel-vera-g" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Barabazs"><img src="https://avatars.githubusercontent.com/u/31799121?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Barabas</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Barabazs" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://enginveske@gmail.com"><img src="https://avatars.githubusercontent.com/u/43685404?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Engincan VESKE</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=EngincanV" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://www.paulderaaij.nl"><img src="https://avatars.githubusercontent.com/u/495374?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Paul de Raaij</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=pderaaij" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/bronson"><img src="https://avatars.githubusercontent.com/u/1776?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Scott Bronson</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=bronson" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://rafaelriedel.de"><img src="https://avatars.githubusercontent.com/u/41793?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Rafael Riedel</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=rafo" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/Pearcekieser"><img src="https://avatars.githubusercontent.com/u/5055971?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Pearcekieser</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Pearcekieser" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/theowenyoung"><img src="https://avatars.githubusercontent.com/u/62473795?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Owen Young</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=theowenyoung" title="Documentation">📖</a> <a href="#content-theowenyoung" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="http://www.prashu.com"><img src="https://avatars.githubusercontent.com/u/476729?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Prashanth Subrahmanyam</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ksprashu" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/JonasSprenger"><img src="https://avatars.githubusercontent.com/u/25108895?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Jonas SPRENGER</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=JonasSprenger" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Laptop765"><img src="https://avatars.githubusercontent.com/u/1468359?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Paul</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Laptop765" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=eltociear" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/memeplex"><img src="https://avatars.githubusercontent.com/u/2845433?v=4?s=60" width="60px;" alt=""/><br /><sub><b>memeplex</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=memeplex" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/AndreiD049"><img src="https://avatars.githubusercontent.com/u/52671223?v=4?s=60" width="60px;" alt=""/><br /><sub><b>AndreiD049</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=AndreiD049" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/iam-yan"><img src="https://avatars.githubusercontent.com/u/48427014?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Yan</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=iam-yan" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://WikiEducator.org/User:JimTittsler"><img src="https://avatars.githubusercontent.com/u/180326?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Jim Tittsler</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jimt" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://malcolmmielle.wordpress.com/"><img src="https://avatars.githubusercontent.com/u/4457840?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Malcolm Mielle</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MalcolmMielle" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://snippets.page/"><img src="https://avatars.githubusercontent.com/u/74916913?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Veesar</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=veesar" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/bentongxyz"><img src="https://avatars.githubusercontent.com/u/60358804?v=4?s=60" width="60px;" alt=""/><br /><sub><b>bentongxyz</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=bentongxyz" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://brianjdevries.com"><img src="https://avatars.githubusercontent.com/u/42778030?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Brian DeVries</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=techCarpenter" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://Cliffordfajardo.com"><img src="https://avatars.githubusercontent.com/u/6743796?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Clifford Fajardo </b></sub></a><br /><a href="#tool-cliffordfajardo" title="Tools">🔧</a></td>
|
||||
<td align="center"><a href="http://cu-dev.ca"><img src="https://avatars.githubusercontent.com/u/6589365?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Chris Usick</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=chrisUsick" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/josephdecock"><img src="https://avatars.githubusercontent.com/u/1145533?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Joe DeCock</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=josephdecock" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.drewtyler.com"><img src="https://avatars.githubusercontent.com/u/5640816?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Drew Tyler</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=drewtyler" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Lauviah0622"><img src="https://avatars.githubusercontent.com/u/43416399?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Lauviah0622</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Lauviah0622" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.elastic.co/elastic-agent"><img src="https://avatars.githubusercontent.com/u/1813008?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Josh Dover</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=joshdover" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://phelm.co.uk"><img src="https://avatars.githubusercontent.com/u/4057948?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Phil Helm</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=phelma" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/lingyv-li"><img src="https://avatars.githubusercontent.com/u/8937944?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Larry Li</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=lingyv-li" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/infogulch"><img src="https://avatars.githubusercontent.com/u/133882?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Joe Taber</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=infogulch" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.readingsnail.pe.kr"><img src="https://avatars.githubusercontent.com/u/1904967?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Woosuk Park</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=readingsnail" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://www.dmurph.com"><img src="https://avatars.githubusercontent.com/u/294026?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Daniel Murphy</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dmurph" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://jevakallio.dev/"><img src="https://avatars1.githubusercontent.com/u/1203949?v=4?s=60" width="60px;" alt="Jani Eväkallio"/><br /><sub><b>Jani Eväkallio</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jevakallio" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jevakallio" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://joeprevite.com/"><img src="https://avatars3.githubusercontent.com/u/3806031?v=4?s=60" width="60px;" alt="Joe Previte"/><br /><sub><b>Joe Previte</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jsjoeio" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jsjoeio" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/riccardoferretti"><img src="https://avatars3.githubusercontent.com/u/457005?v=4?s=60" width="60px;" alt="Riccardo"/><br /><sub><b>Riccardo</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=riccardoferretti" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=riccardoferretti" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://ojanaho.com/"><img src="https://avatars0.githubusercontent.com/u/2180090?v=4?s=60" width="60px;" alt="Janne Ojanaho"/><br /><sub><b>Janne Ojanaho</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jojanaho" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jojanaho" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://bypaulshen.com/"><img src="https://avatars3.githubusercontent.com/u/2266187?v=4?s=60" width="60px;" alt="Paul Shen"/><br /><sub><b>Paul Shen</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=paulshen" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/coffenbacher"><img src="https://avatars0.githubusercontent.com/u/245867?v=4?s=60" width="60px;" alt="coffenbacher"/><br /><sub><b>coffenbacher</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=coffenbacher" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://mathieu.dutour.me/"><img src="https://avatars2.githubusercontent.com/u/3254314?v=4?s=60" width="60px;" alt="Mathieu Dutour"/><br /><sub><b>Mathieu Dutour</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=mathieudutour" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/presidentelect"><img src="https://avatars2.githubusercontent.com/u/1242300?v=4?s=60" width="60px;" alt="Michael Hansen"/><br /><sub><b>Michael Hansen</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=presidentelect" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://klickverbot.at/"><img src="https://avatars1.githubusercontent.com/u/19335?v=4?s=60" width="60px;" alt="David Nadlinger"/><br /><sub><b>David Nadlinger</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dnadlinger" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://pluckd.co/"><img src="https://avatars2.githubusercontent.com/u/20598571?v=4?s=60" width="60px;" alt="Fernando"/><br /><sub><b>Fernando</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MrCordeiro" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jfgonzalez7"><img src="https://avatars3.githubusercontent.com/u/58857736?v=4?s=60" width="60px;" alt="Juan Gonzalez"/><br /><sub><b>Juan Gonzalez</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jfgonzalez7" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.louiechristie.com/"><img src="https://avatars1.githubusercontent.com/u/6807448?v=4?s=60" width="60px;" alt="Louie Christie"/><br /><sub><b>Louie Christie</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=louiechristie" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://supersandro.de/"><img src="https://avatars2.githubusercontent.com/u/7258858?v=4?s=60" width="60px;" alt="Sandro"/><br /><sub><b>Sandro</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=SuperSandro2000" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Skn0tt"><img src="https://avatars1.githubusercontent.com/u/14912729?v=4?s=60" width="60px;" alt="Simon Knott"/><br /><sub><b>Simon Knott</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Skn0tt" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://styfle.dev/"><img src="https://avatars1.githubusercontent.com/u/229881?v=4?s=60" width="60px;" alt="Steven"/><br /><sub><b>Steven</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=styfle" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Georift"><img src="https://avatars2.githubusercontent.com/u/859430?v=4?s=60" width="60px;" alt="Tim"/><br /><sub><b>Tim</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Georift" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sauravkhdoolia"><img src="https://avatars1.githubusercontent.com/u/34188267?v=4?s=60" width="60px;" alt="Saurav Khdoolia"/><br /><sub><b>Saurav Khdoolia</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=sauravkhdoolia" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://anku.netlify.com/"><img src="https://avatars1.githubusercontent.com/u/22813027?v=4?s=60" width="60px;" alt="Ankit Tiwari"/><br /><sub><b>Ankit Tiwari</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=anku255" title="Documentation">📖</a> <a href="https://github.com/foambubble/foam/commits?author=anku255" title="Tests">⚠️</a> <a href="https://github.com/foambubble/foam/commits?author=anku255" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ayushbaweja"><img src="https://avatars1.githubusercontent.com/u/44344063?v=4?s=60" width="60px;" alt="Ayush Baweja"/><br /><sub><b>Ayush Baweja</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ayushbaweja" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TaiChi-IO"><img src="https://avatars3.githubusercontent.com/u/65092992?v=4?s=60" width="60px;" alt="TaiChi-IO"/><br /><sub><b>TaiChi-IO</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=TaiChi-IO" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/juanfrank77"><img src="https://avatars1.githubusercontent.com/u/12146882?v=4?s=60" width="60px;" alt="Juan F Gonzalez "/><br /><sub><b>Juan F Gonzalez </b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=juanfrank77" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://sanketdg.github.io"><img src="https://avatars3.githubusercontent.com/u/8980971?v=4?s=60" width="60px;" alt="Sanket Dasgupta"/><br /><sub><b>Sanket Dasgupta</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=SanketDG" title="Documentation">📖</a> <a href="https://github.com/foambubble/foam/commits?author=SanketDG" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nstafie"><img src="https://avatars1.githubusercontent.com/u/10801854?v=4?s=60" width="60px;" alt="Nicholas Stafie"/><br /><sub><b>Nicholas Stafie</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=nstafie" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/francishamel"><img src="https://avatars3.githubusercontent.com/u/36383308?v=4?s=60" width="60px;" alt="Francis Hamel"/><br /><sub><b>Francis Hamel</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=francishamel" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://digiguru.co.uk"><img src="https://avatars1.githubusercontent.com/u/619436?v=4?s=60" width="60px;" alt="digiguru"/><br /><sub><b>digiguru</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=digiguru" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=digiguru" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/chirag-singhal"><img src="https://avatars3.githubusercontent.com/u/42653703?v=4?s=60" width="60px;" alt="CHIRAG SINGHAL"/><br /><sub><b>CHIRAG SINGHAL</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=chirag-singhal" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lostintangent"><img src="https://avatars3.githubusercontent.com/u/116461?v=4?s=60" width="60px;" alt="Jonathan Carter"/><br /><sub><b>Jonathan Carter</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=lostintangent" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.synesthesia.co.uk"><img src="https://avatars3.githubusercontent.com/u/181399?v=4?s=60" width="60px;" alt="Julian Elve"/><br /><sub><b>Julian Elve</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=synesthesia" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/thomaskoppelaar"><img src="https://avatars3.githubusercontent.com/u/36331365?v=4?s=60" width="60px;" alt="Thomas Koppelaar"/><br /><sub><b>Thomas Koppelaar</b></sub></a><br /><a href="#question-thomaskoppelaar" title="Answering Questions">💬</a> <a href="https://github.com/foambubble/foam/commits?author=thomaskoppelaar" title="Code">💻</a> <a href="#userTesting-thomaskoppelaar" title="User Testing">📓</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.akshaymehra.com"><img src="https://avatars1.githubusercontent.com/u/8671497?v=4?s=60" width="60px;" alt="Akshay"/><br /><sub><b>Akshay</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MehraAkshay" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://johnlindquist.com"><img src="https://avatars0.githubusercontent.com/u/36073?v=4?s=60" width="60px;" alt="John Lindquist"/><br /><sub><b>John Lindquist</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=johnlindquist" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://ashwin.run/"><img src="https://avatars2.githubusercontent.com/u/1689183?v=4?s=60" width="60px;" alt="Ashwin Ramaswami"/><br /><sub><b>Ashwin Ramaswami</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=epicfaace" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Klaudioz"><img src="https://avatars1.githubusercontent.com/u/632625?v=4?s=60" width="60px;" alt="Claudio Canales"/><br /><sub><b>Claudio Canales</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Klaudioz" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vitaly-pevgonen"><img src="https://avatars0.githubusercontent.com/u/6272738?v=4?s=60" width="60px;" alt="vitaly-pevgonen"/><br /><sub><b>vitaly-pevgonen</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=vitaly-pevgonen" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://dshemetov.github.io"><img src="https://avatars0.githubusercontent.com/u/1810426?v=4?s=60" width="60px;" alt="Dmitry Shemetov"/><br /><sub><b>Dmitry Shemetov</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dshemetov" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hooncp"><img src="https://avatars1.githubusercontent.com/u/48883554?v=4?s=60" width="60px;" alt="hooncp"/><br /><sub><b>hooncp</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=hooncp" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://rt-canada.ca"><img src="https://avatars1.githubusercontent.com/u/13721239?v=4?s=60" width="60px;" alt="Martin Laws"/><br /><sub><b>Martin Laws</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=martinlaws" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://seanksmith.me"><img src="https://avatars3.githubusercontent.com/u/2085441?v=4?s=60" width="60px;" alt="Sean K Smith"/><br /><sub><b>Sean K Smith</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=sksmith" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/kevin-neely/"><img src="https://avatars1.githubusercontent.com/u/37545028?v=4?s=60" width="60px;" alt="Kevin Neely"/><br /><sub><b>Kevin Neely</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=kneely" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://ariefrahmansyah.dev"><img src="https://avatars3.githubusercontent.com/u/8122852?v=4?s=60" width="60px;" alt="Arief Rahmansyah"/><br /><sub><b>Arief Rahmansyah</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ariefrahmansyah" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://vhanda.in"><img src="https://avatars2.githubusercontent.com/u/426467?v=4?s=60" width="60px;" alt="Vishesh Handa"/><br /><sub><b>Vishesh Handa</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=vHanda" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.linkedin.com/in/heroichitesh"><img src="https://avatars3.githubusercontent.com/u/37622734?v=4?s=60" width="60px;" alt="Hitesh Kumar"/><br /><sub><b>Hitesh Kumar</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=HeroicHitesh" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://spencerwoo.com"><img src="https://avatars2.githubusercontent.com/u/32114380?v=4?s=60" width="60px;" alt="Spencer Woo"/><br /><sub><b>Spencer Woo</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=spencerwooo" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://ingalless.com"><img src="https://avatars3.githubusercontent.com/u/22981941?v=4?s=60" width="60px;" alt="ingalless"/><br /><sub><b>ingalless</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ingalless" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=ingalless" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://jmg-duarte.github.io"><img src="https://avatars2.githubusercontent.com/u/15343819?v=4?s=60" width="60px;" alt="José Duarte"/><br /><sub><b>José Duarte</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jmg-duarte" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jmg-duarte" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.yenly.wtf"><img src="https://avatars1.githubusercontent.com/u/6759658?v=4?s=60" width="60px;" alt="Yenly"/><br /><sub><b>Yenly</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=yenly" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.hikerpig.cn"><img src="https://avatars1.githubusercontent.com/u/2259688?v=4?s=60" width="60px;" alt="hikerpig"/><br /><sub><b>hikerpig</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=hikerpig" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://sigfried.org"><img src="https://avatars1.githubusercontent.com/u/1586931?v=4?s=60" width="60px;" alt="Sigfried Gold"/><br /><sub><b>Sigfried Gold</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Sigfried" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.tristansokol.com"><img src="https://avatars3.githubusercontent.com/u/867661?v=4?s=60" width="60px;" alt="Tristan Sokol"/><br /><sub><b>Tristan Sokol</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=tristansokol" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://umbrellait.com"><img src="https://avatars0.githubusercontent.com/u/49779373?v=4?s=60" width="60px;" alt="Danil Rodin"/><br /><sub><b>Danil Rodin</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=umbrellait-danil-rodin" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/scottjoewilliams/"><img src="https://avatars1.githubusercontent.com/u/2026866?v=4?s=60" width="60px;" alt="Scott Williams"/><br /><sub><b>Scott Williams</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=scott-joe" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://jackiexiao.github.io/blog"><img src="https://avatars2.githubusercontent.com/u/18050469?v=4?s=60" width="60px;" alt="jackiexiao"/><br /><sub><b>jackiexiao</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Jackiexiao" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://generativist.substack.com/"><img src="https://avatars3.githubusercontent.com/u/78835?v=4?s=60" width="60px;" alt="John B Nelson"/><br /><sub><b>John B Nelson</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jbn" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/asifm"><img src="https://avatars2.githubusercontent.com/u/3958387?v=4?s=60" width="60px;" alt="Asif Mehedi"/><br /><sub><b>Asif Mehedi</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=asifm" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/litanlitudan"><img src="https://avatars2.githubusercontent.com/u/4970420?v=4?s=60" width="60px;" alt="Tan Li"/><br /><sub><b>Tan Li</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=litanlitudan" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://shaunagordon.com"><img src="https://avatars1.githubusercontent.com/u/579361?v=4?s=60" width="60px;" alt="Shauna Gordon"/><br /><sub><b>Shauna Gordon</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ShaunaGordon" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://mcluck.tech"><img src="https://avatars1.githubusercontent.com/u/1753801?v=4?s=60" width="60px;" alt="Mike Cluck"/><br /><sub><b>Mike Cluck</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MCluck90" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://brandonpugh.com"><img src="https://avatars1.githubusercontent.com/u/684781?v=4?s=60" width="60px;" alt="Brandon Pugh"/><br /><sub><b>Brandon Pugh</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=bpugh" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://max.davitt.me"><img src="https://avatars1.githubusercontent.com/u/27709025?v=4?s=60" width="60px;" alt="Max Davitt"/><br /><sub><b>Max Davitt</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=themaxdavitt" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://briananglin.me"><img src="https://avatars3.githubusercontent.com/u/2637602?v=4?s=60" width="60px;" alt="Brian Anglin"/><br /><sub><b>Brian Anglin</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=anglinb" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://deft.work"><img src="https://avatars1.githubusercontent.com/u/1455507?v=4?s=60" width="60px;" alt="elswork"/><br /><sub><b>elswork</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=elswork" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://leonh.fr/"><img src="https://avatars.githubusercontent.com/u/19996318?v=4?s=60" width="60px;" alt="léon h"/><br /><sub><b>léon h</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=leonhfr" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://nygaard.site"><img src="https://avatars.githubusercontent.com/u/4606342?v=4?s=60" width="60px;" alt="Nikhil Nygaard"/><br /><sub><b>Nikhil Nygaard</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=njnygaard" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.nitwit.se"><img src="https://avatars.githubusercontent.com/u/1382124?v=4?s=60" width="60px;" alt="Mark Dixon"/><br /><sub><b>Mark Dixon</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=nitwit-se" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/joeltjames"><img src="https://avatars.githubusercontent.com/u/3732400?v=4?s=60" width="60px;" alt="Joel James"/><br /><sub><b>Joel James</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=joeltjames" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.ryo33.com"><img src="https://avatars.githubusercontent.com/u/8780513?v=4?s=60" width="60px;" alt="Hashiguchi Ryo"/><br /><sub><b>Hashiguchi Ryo</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ryo33" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://movermeyer.com"><img src="https://avatars.githubusercontent.com/u/1459385?v=4?s=60" width="60px;" alt="Michael Overmeyer"/><br /><sub><b>Michael Overmeyer</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=movermeyer" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/derrickqin"><img src="https://avatars.githubusercontent.com/u/3038111?v=4?s=60" width="60px;" alt="Derrick Qin"/><br /><sub><b>Derrick Qin</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=derrickqin" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/zomars/"><img src="https://avatars.githubusercontent.com/u/3504472?v=4?s=60" width="60px;" alt="Omar López"/><br /><sub><b>Omar López</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=zomars" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://robincn.com"><img src="https://avatars.githubusercontent.com/u/1583193?v=4?s=60" width="60px;" alt="Robin King"/><br /><sub><b>Robin King</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=RobinKing" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://twitter.com/deegovee"><img src="https://avatars.githubusercontent.com/u/4730170?v=4?s=60" width="60px;" alt="Dheepak "/><br /><sub><b>Dheepak </b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dheepakg" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/daniel-vera-g"><img src="https://avatars.githubusercontent.com/u/28257108?v=4?s=60" width="60px;" alt="Daniel VG"/><br /><sub><b>Daniel VG</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=daniel-vera-g" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Barabazs"><img src="https://avatars.githubusercontent.com/u/31799121?v=4?s=60" width="60px;" alt="Barabas"/><br /><sub><b>Barabas</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Barabazs" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://enginveske@gmail.com"><img src="https://avatars.githubusercontent.com/u/43685404?v=4?s=60" width="60px;" alt="Engincan VESKE"/><br /><sub><b>Engincan VESKE</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=EngincanV" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.paulderaaij.nl"><img src="https://avatars.githubusercontent.com/u/495374?v=4?s=60" width="60px;" alt="Paul de Raaij"/><br /><sub><b>Paul de Raaij</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=pderaaij" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bronson"><img src="https://avatars.githubusercontent.com/u/1776?v=4?s=60" width="60px;" alt="Scott Bronson"/><br /><sub><b>Scott Bronson</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=bronson" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://rafaelriedel.de"><img src="https://avatars.githubusercontent.com/u/41793?v=4?s=60" width="60px;" alt="Rafael Riedel"/><br /><sub><b>Rafael Riedel</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=rafo" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Pearcekieser"><img src="https://avatars.githubusercontent.com/u/5055971?v=4?s=60" width="60px;" alt="Pearcekieser"/><br /><sub><b>Pearcekieser</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Pearcekieser" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/theowenyoung"><img src="https://avatars.githubusercontent.com/u/62473795?v=4?s=60" width="60px;" alt="Owen Young"/><br /><sub><b>Owen Young</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=theowenyoung" title="Documentation">📖</a> <a href="#content-theowenyoung" title="Content">🖋</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.prashu.com"><img src="https://avatars.githubusercontent.com/u/476729?v=4?s=60" width="60px;" alt="Prashanth Subrahmanyam"/><br /><sub><b>Prashanth Subrahmanyam</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ksprashu" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/JonasSprenger"><img src="https://avatars.githubusercontent.com/u/25108895?v=4?s=60" width="60px;" alt="Jonas SPRENGER"/><br /><sub><b>Jonas SPRENGER</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=JonasSprenger" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Laptop765"><img src="https://avatars.githubusercontent.com/u/1468359?v=4?s=60" width="60px;" alt="Paul"/><br /><sub><b>Paul</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Laptop765" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=60" width="60px;" alt="Ikko Ashimine"/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=eltociear" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/memeplex"><img src="https://avatars.githubusercontent.com/u/2845433?v=4?s=60" width="60px;" alt="memeplex"/><br /><sub><b>memeplex</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=memeplex" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/AndreiD049"><img src="https://avatars.githubusercontent.com/u/52671223?v=4?s=60" width="60px;" alt="AndreiD049"/><br /><sub><b>AndreiD049</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=AndreiD049" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/iam-yan"><img src="https://avatars.githubusercontent.com/u/48427014?v=4?s=60" width="60px;" alt="Yan"/><br /><sub><b>Yan</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=iam-yan" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://WikiEducator.org/User:JimTittsler"><img src="https://avatars.githubusercontent.com/u/180326?v=4?s=60" width="60px;" alt="Jim Tittsler"/><br /><sub><b>Jim Tittsler</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jimt" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://malcolmmielle.wordpress.com/"><img src="https://avatars.githubusercontent.com/u/4457840?v=4?s=60" width="60px;" alt="Malcolm Mielle"/><br /><sub><b>Malcolm Mielle</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MalcolmMielle" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://snippets.page/"><img src="https://avatars.githubusercontent.com/u/74916913?v=4?s=60" width="60px;" alt="Veesar"/><br /><sub><b>Veesar</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=veesar" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bentongxyz"><img src="https://avatars.githubusercontent.com/u/60358804?v=4?s=60" width="60px;" alt="bentongxyz"/><br /><sub><b>bentongxyz</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=bentongxyz" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://brianjdevries.com"><img src="https://avatars.githubusercontent.com/u/42778030?v=4?s=60" width="60px;" alt="Brian DeVries"/><br /><sub><b>Brian DeVries</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=techCarpenter" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://Cliffordfajardo.com"><img src="https://avatars.githubusercontent.com/u/6743796?v=4?s=60" width="60px;" alt="Clifford Fajardo "/><br /><sub><b>Clifford Fajardo </b></sub></a><br /><a href="#tool-cliffordfajardo" title="Tools">🔧</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://cu-dev.ca"><img src="https://avatars.githubusercontent.com/u/6589365?v=4?s=60" width="60px;" alt="Chris Usick"/><br /><sub><b>Chris Usick</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=chrisUsick" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/josephdecock"><img src="https://avatars.githubusercontent.com/u/1145533?v=4?s=60" width="60px;" alt="Joe DeCock"/><br /><sub><b>Joe DeCock</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=josephdecock" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.drewtyler.com"><img src="https://avatars.githubusercontent.com/u/5640816?v=4?s=60" width="60px;" alt="Drew Tyler"/><br /><sub><b>Drew Tyler</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=drewtyler" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Lauviah0622"><img src="https://avatars.githubusercontent.com/u/43416399?v=4?s=60" width="60px;" alt="Lauviah0622"/><br /><sub><b>Lauviah0622</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Lauviah0622" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.elastic.co/elastic-agent"><img src="https://avatars.githubusercontent.com/u/1813008?v=4?s=60" width="60px;" alt="Josh Dover"/><br /><sub><b>Josh Dover</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=joshdover" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://phelm.co.uk"><img src="https://avatars.githubusercontent.com/u/4057948?v=4?s=60" width="60px;" alt="Phil Helm"/><br /><sub><b>Phil Helm</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=phelma" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lingyv-li"><img src="https://avatars.githubusercontent.com/u/8937944?v=4?s=60" width="60px;" alt="Larry Li"/><br /><sub><b>Larry Li</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=lingyv-li" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/infogulch"><img src="https://avatars.githubusercontent.com/u/133882?v=4?s=60" width="60px;" alt="Joe Taber"/><br /><sub><b>Joe Taber</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=infogulch" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.readingsnail.pe.kr"><img src="https://avatars.githubusercontent.com/u/1904967?v=4?s=60" width="60px;" alt="Woosuk Park"/><br /><sub><b>Woosuk Park</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=readingsnail" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.dmurph.com"><img src="https://avatars.githubusercontent.com/u/294026?v=4?s=60" width="60px;" alt="Daniel Murphy"/><br /><sub><b>Daniel Murphy</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dmurph" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Dominic-DallOsto"><img src="https://avatars.githubusercontent.com/u/26859884?v=4?s=60" width="60px;" alt="Dominic D"/><br /><sub><b>Dominic D</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Dominic-DallOsto" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://elgirafo.xyz"><img src="https://avatars.githubusercontent.com/u/80516439?v=4?s=60" width="60px;" alt="luca"/><br /><sub><b>luca</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=elgirafo" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Lloyd-Jackman-UKPL"><img src="https://avatars.githubusercontent.com/u/55206370?v=4?s=60" width="60px;" alt="Lloyd Jackman"/><br /><sub><b>Lloyd Jackman</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Lloyd-Jackman-UKPL" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://sn3akiwhizper.github.io"><img src="https://avatars.githubusercontent.com/u/102705294?v=4?s=60" width="60px;" alt="sn3akiwhizper"/><br /><sub><b>sn3akiwhizper</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=sn3akiwhizper" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://jonathanpberger.com/"><img src="https://avatars.githubusercontent.com/u/41085?v=4?s=60" width="60px;" alt="jonathan berger"/><br /><sub><b>jonathan berger</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jonathanpberger" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/badsketch"><img src="https://avatars.githubusercontent.com/u/8953212?v=4?s=60" width="60px;" alt="Daniel Wang"/><br /><sub><b>Daniel Wang</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=badsketch" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://yongliangliu.com"><img src="https://avatars.githubusercontent.com/u/41845017?v=4?s=60" width="60px;" alt="Liu YongLiang"/><br /><sub><b>Liu YongLiang</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=tlylt" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://scottakerman.com"><img src="https://avatars.githubusercontent.com/u/15224439?v=4?s=60" width="60px;" alt="Scott Akerman"/><br /><sub><b>Scott Akerman</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Skakerman" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.jim-graham.net/"><img src="https://avatars.githubusercontent.com/u/430293?v=4?s=60" width="60px;" alt="Jim Graham"/><br /><sub><b>Jim Graham</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jimgraham" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://t.me/littlepoint"><img src="https://avatars.githubusercontent.com/u/7611700?v=4?s=60" width="60px;" alt="Zhizhen He"/><br /><sub><b>Zhizhen He</b></sub></a><br /><a href="#tool-hezhizhen" title="Tools">🔧</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://amnesiak.org/me"><img src="https://avatars.githubusercontent.com/u/952059?v=4?s=60" width="60px;" alt="Tony Cheneau"/><br /><sub><b>Tony Cheneau</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=tcheneau" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nicholas-l"><img src="https://avatars.githubusercontent.com/u/12977174?v=4?s=60" width="60px;" alt="Nicholas Latham"/><br /><sub><b>Nicholas Latham</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=nicholas-l" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://thara.dev"><img src="https://avatars.githubusercontent.com/u/1532891?v=4?s=60" width="60px;" alt="Tomochika Hara"/><br /><sub><b>Tomochika Hara</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=thara" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dcarosone"><img src="https://avatars.githubusercontent.com/u/11495017?v=4?s=60" width="60px;" alt="Daniel Carosone"/><br /><sub><b>Daniel Carosone</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dcarosone" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MABruni"><img src="https://avatars.githubusercontent.com/u/100445384?v=4?s=60" width="60px;" alt="Miguel Angel Bruni Montero"/><br /><sub><b>Miguel Angel Bruni Montero</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MABruni" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Walshkev"><img src="https://avatars.githubusercontent.com/u/77123083?v=4?s=60" width="60px;" alt="Kevin Walsh "/><br /><sub><b>Kevin Walsh </b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Walshkev" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://hereistheusername.github.io/"><img src="https://avatars.githubusercontent.com/u/33437051?v=4?s=60" width="60px;" alt="Xinglan Liu"/><br /><sub><b>Xinglan Liu</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=hereistheusername" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.hegghammer.com"><img src="https://avatars.githubusercontent.com/u/64712218?v=4?s=60" width="60px;" alt="Thomas Hegghammer"/><br /><sub><b>Thomas Hegghammer</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Hegghammer" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PiotrAleksander"><img src="https://avatars.githubusercontent.com/u/6314591?v=4?s=60" width="60px;" alt="Piotr Mrzygłosz"/><br /><sub><b>Piotr Mrzygłosz</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=PiotrAleksander" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://schaver.com/"><img src="https://avatars.githubusercontent.com/u/7584?v=4?s=60" width="60px;" alt="Mark Schaver"/><br /><sub><b>Mark Schaver</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=markschaver" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/n8layman"><img src="https://avatars.githubusercontent.com/u/25353944?v=4?s=60" width="60px;" alt="Nathan Layman"/><br /><sub><b>Nathan Layman</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=n8layman" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/emmanuel-ferdman"><img src="https://avatars.githubusercontent.com/u/35470921?v=4?s=60" width="60px;" alt="Emmanuel Ferdman"/><br /><sub><b>Emmanuel Ferdman</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=emmanuel-ferdman" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Tenormis"><img src="https://avatars.githubusercontent.com/u/61572102?v=4?s=60" width="60px;" alt="Tenormis"/><br /><sub><b>Tenormis</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Tenormis" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://djon.es/blog"><img src="https://avatars.githubusercontent.com/u/225052?v=4?s=60" width="60px;" alt="David Jones"/><br /><sub><b>David Jones</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=djplaner" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/s-jacob-powell"><img src="https://avatars.githubusercontent.com/u/109111499?v=4?s=60" width="60px;" alt="S. Jacob Powell"/><br /><sub><b>S. Jacob Powell</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=s-jacob-powell" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/figdavi"><img src="https://avatars.githubusercontent.com/u/99026991?v=4?s=60" width="60px;" alt="Davi Figueiredo"/><br /><sub><b>Davi Figueiredo</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=figdavi" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ChThH"><img src="https://avatars.githubusercontent.com/u/9499483?v=4?s=60" width="60px;" alt="CT Hall"/><br /><sub><b>CT Hall</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ChThH" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/meestahp"><img src="https://avatars.githubusercontent.com/u/177708514?v=4?s=60" width="60px;" alt="meestahp"/><br /><sub><b>meestahp</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=meestahp" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
@@ -245,20 +289,16 @@ If that sounds like something you're interested in, I'd love to have you along o
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
**Foam** was inspired by [Roam Research](https://roamresearch.com/) and the [Zettelkasten methodology](https://zettelkasten.de/posts/overview)
|
||||
Foam was inspired by [Roam Research](https://roamresearch.com/) and [Zettelkasten methodology](https://zettelkasten.de/posts/overview).
|
||||
|
||||
**Foam** wouldn't be possible without [Visual Studio Code](https://code.visualstudio.com/) and [GitHub](https://github.com/), and relies heavily on our fantastic open source [[recommended-extensions]] and all their contributors!
|
||||
Foam builds on [Visual Studio Code](https://code.visualstudio.com/), [GitHub](https://github.com/), and our [[recommended-extensions]].
|
||||
|
||||
## License
|
||||
|
||||
Foam is licensed under the [MIT license](LICENSE.txt).
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[graph-visualization]: user/features/graph-visualization.md "Graph Visualization"
|
||||
[backlinking]: user/features/backlinking.md "Backlinking"
|
||||
[recommended-extensions]: user/getting-started/recommended-extensions.md "Recommended Extensions"
|
||||
[recipes]: user/recipes/recipes.md "Recipes"
|
||||
[frequently-asked-questions]: user/frequently-asked-questions.md "Frequently Asked Questions"
|
||||
[principles]: principles.md "Principles"
|
||||
[contribution-guide]: dev/contribution-guide.md "Contribution Guide"
|
||||
[//end]: # "Autogenerated link references"
|
||||
[recommended-extensions]: user/getting-started/recommended-extensions.md 'Recommended Extensions'
|
||||
[recipes]: user/recipes/recipes.md 'Recipes'
|
||||
[frequently-asked-questions]: user/frequently-asked-questions.md 'Frequently Asked Questions'
|
||||
[principles]: principles.md 'Principles'
|
||||
[contribution-guide]: dev/contribution-guide.md 'Contribution Guide'
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
# Reading list
|
||||
|
||||
- [Zettelkasten article, recommended by tchayen](https://github.com/alefore/weblog/blob/master/zettelkasten.md)
|
||||
- [Suping up VS Code as a Markdown editor](https://kortina.nyc/essays/suping-up-vs-code-as-a-markdown-notebook/)
|
||||
- [VSCode Extensions Packs](https://code.visualstudio.com/blogs/2017/03/07/extension-pack-roundup) [[todo]] Evaluate for deployment
|
||||
- [Dark mode](https://css-tricks.com/dark-modes-with-css/)
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[todo]: dev/todo.md "Todo"
|
||||
[//end]: # "Autogenerated link references"
|
||||
@@ -1,19 +0,0 @@
|
||||
# Terminology
|
||||
|
||||
It would be good to have some shared terminology to talk about Foam concepts. Some in-group terminology is acceptable, but we shouldn't be obtuse just to be exclusive.
|
||||
|
||||
Here's some ideas, these are open for discussion.
|
||||
|
||||
## Foam, the software project
|
||||
|
||||
The set of tools and ideas collected in this organisation.
|
||||
|
||||
## (Your) Foam
|
||||
|
||||
The directory/repository where you keep all your notes.
|
||||
|
||||
Also happens to sound quite a lot like Home. Funny, that.
|
||||
|
||||
## Bubble
|
||||
|
||||
Individual Foam note, written in Markdown.
|
||||
@@ -1,15 +1,66 @@
|
||||
# Backlinking
|
||||
# Backlinks
|
||||
|
||||
When using [[wikilinks]], you can find all notes that link to a specific note in the **Backlinks Explorer**
|
||||
Backlinks are one of Foam's most powerful features for knowledge discovery. They automatically show you which notes reference your current note, creating a web of interconnected knowledge that reveals surprising relationships between your ideas.
|
||||
|
||||
- Run `Cmd` + `Shift` + `P` (`Ctrl` + `Shift` + `P` for Windows), type "backlinks" and run the **Explorer: Focus on Backlinks** view.
|
||||
- Keep this pane always visible to discover relationships between your thoughts
|
||||
- You can drag the backlinks pane to a different section in VS Code if you prefer. See: [[make-backlinks-more-prominent]]
|
||||
- Finding backlinks in published Foam workspaces via [[materialized-backlinks]] is on the [[roadmap]] but not yet implemented.
|
||||
_[📹 Watch: Understanding and using backlinks in Foam]_
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[wikilinks]: wikilinks.md "Wikilinks"
|
||||
[make-backlinks-more-prominent]: ../recipes/make-backlinks-more-prominent.md "Make Backlinks More Prominent"
|
||||
[materialized-backlinks]: ../../dev/proposals/materialized-backlinks.md "Materialized Backlinks (stub)"
|
||||
[roadmap]: ../../dev/proposals/roadmap.md "Roadmap"
|
||||
[//end]: # "Autogenerated link references"
|
||||
## What Are Backlinks?
|
||||
|
||||
A backlink is a connection from another note that points to the note you're currently viewing. While you create forward links intentionally with `[[wikilinks]]`, backlinks are discovered automatically by Foam.
|
||||
|
||||
### Forward Links vs. Backlinks
|
||||
|
||||
**Forward Links** (what you create):
|
||||
|
||||
```markdown
|
||||
# Machine Learning Note
|
||||
|
||||
I'm studying [[Neural Networks]] and [[Deep Learning]] concepts.
|
||||
```
|
||||
|
||||
**Backlinks** (what Foam discovers):
|
||||
If you're viewing the "Neural Networks" note, Foam shows you that "Machine Learning Note" links to it, even though you didn't explicitly create that reverse connection.
|
||||
|
||||
This bidirectional linking creates a richer knowledge network than traditional hierarchical folders.
|
||||
|
||||
## Accessing Backlinks - Connections Panel
|
||||
|
||||
The Connections panel shows both forward links and backlinks:
|
||||
|
||||
1. **Open Command Palette** (`Ctrl+Shift+P` / `Cmd+Shift+P`)
|
||||
2. **Type "connections"** and select "Explorer: Focus on Connections"
|
||||
3. **Use the filter buttons** to show only backlinks, forward links, or all connections
|
||||
|
||||
_[📹 Watch: Finding and opening the backlinks panel]_
|
||||
|
||||
## Using Backlinks for Knowledge Discovery
|
||||
|
||||
### 1. Finding Unexpected Connections
|
||||
|
||||
Backlinks often reveal relationships you didn't consciously create:
|
||||
|
||||
**Example:** While reviewing a "Productivity" note, backlinks might show connections from:
|
||||
|
||||
- A cooking recipe (time management for meal prep)
|
||||
- A fitness routine (efficient workout planning)
|
||||
- A work project (team productivity strategies)
|
||||
|
||||
These diverse connections can spark new insights and cross-domain learning.
|
||||
|
||||
### 2. Identifying Important Concepts
|
||||
|
||||
Notes with many backlinks are often central to your thinking:
|
||||
|
||||
- **Hub concepts** that connect many ideas
|
||||
- **Frequently referenced** resources or definitions
|
||||
- **Bridge topics** that span multiple domains
|
||||
|
||||
### 3. Building Context Around Ideas
|
||||
|
||||
Backlinks provide context for how you use concepts across different areas:
|
||||
|
||||
- How you apply the same principle in various projects
|
||||
- Evolution of your thinking about a topic over time
|
||||
- Different perspectives you've encountered on the same idea
|
||||
|
||||
_[📹 Watch: Using backlinks for knowledge discovery and research]_
|
||||
|
||||
@@ -2,23 +2,26 @@
|
||||
|
||||
Foam has various commands that you can explore by calling the command palette and typing "Foam".
|
||||
|
||||
In particular, some commands can be very customizible and can help with custom workflows and use cases.
|
||||
In particular, some commands can be very customizable and can help with custom workflows and use cases.
|
||||
|
||||
## foam-vscode.create-note command
|
||||
|
||||
This command creates a note.
|
||||
Although it works fine on its own, it can be customized to achieve various use cases.
|
||||
Here are the settings available for the command:
|
||||
- notePath: The path of the note to create. If relative it will be resolved against the workspace root.
|
||||
- templatePath: The path of the template to use. If relative it will be resolved against the workspace root.
|
||||
- text: The text to use for the note. If also a template is provided, the template has precedence
|
||||
- variables: Variables to use in the text or template (e.g. `FOAM_TITLE`)
|
||||
- date: The date used to resolve the FOAM_DATE_* variables. in `YYYY-MM-DD` format
|
||||
- onFileExists?: 'overwrite' | 'open' | 'ask' | 'cancel': What to do in case the target file already exists
|
||||
|
||||
- `notePath`: The path of the note to create. If relative it will be resolved against the workspace root.
|
||||
- `templatePath`: The path of the template to use. If relative it will be resolved against the workspace root.
|
||||
- `title`: The title of the note (that is, the `FOAM_TITLE` variable)
|
||||
- `text`: The text to use for the note. If also a template is provided, the template has precedence
|
||||
- `variables`: Variables to use in the text or template
|
||||
- `date`: The date used to resolve the FOAM*DATE*\* variables. in `YYYY-MM-DD` format
|
||||
- `onFileExists?: 'overwrite' | 'open' | 'ask' | 'cancel'`: What to do in case the target file already exists
|
||||
|
||||
To customize a command and associate a key binding to it, open the key binding settings and add the appropriate configuration, here are some examples:
|
||||
|
||||
- Create a note called `test note.md` with some text. If the note already exists, ask for a new name
|
||||
|
||||
```
|
||||
{
|
||||
"key": "alt+f",
|
||||
@@ -32,6 +35,7 @@ To customize a command and associate a key binding to it, open the key binding s
|
||||
```
|
||||
|
||||
- Create a note following the `weekly-note.md` template. If the note already exists, open it
|
||||
|
||||
```
|
||||
{
|
||||
"key": "alt+g",
|
||||
@@ -43,3 +47,49 @@ To customize a command and associate a key binding to it, open the key binding s
|
||||
}
|
||||
```
|
||||
|
||||
## foam-vscode.open-resource command
|
||||
|
||||
This command opens a resource.
|
||||
|
||||
Normally it receives a `URI`, which identifies the resource to open.
|
||||
|
||||
It is also possible to pass in a filter, which will be run against the workspace resources to find one or more matches.
|
||||
|
||||
- If there is one match, it will be opened
|
||||
- If there is more than one match, a quick pick will show up allowing the user to select the desired resource
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
{
|
||||
"key": "alt+f",
|
||||
"command": "foam-vscode.open-resource",
|
||||
"args": {
|
||||
"filter": {
|
||||
"title": "Weekly Note*"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Link Conversion Commands
|
||||
|
||||
Foam provides commands to convert between wikilink and markdown link formats.
|
||||
|
||||
### foam-vscode.convert-wikilink-to-mdlink
|
||||
|
||||
Converts a wikilink at the cursor position to markdown link format with a relative path.
|
||||
|
||||
Example: `[[my-note]]` → `[My Note](../path/to/my-note.md)`
|
||||
|
||||
### foam-vscode.convert-mdlink-to-wikilink
|
||||
|
||||
Converts a markdown link at the cursor position to wikilink format.
|
||||
|
||||
Example: `[My Note](../path/to/my-note.md)` → `[[my-note]]`
|
||||
|
||||
**Usage:**
|
||||
|
||||
1. Place your cursor inside a wikilink or markdown link
|
||||
2. Open the command palette (`Ctrl+Shift+P` / `Cmd+Shift+P`)
|
||||
3. Type "Foam: Convert" and select the desired conversion command
|
||||
|
||||
@@ -1,23 +1,48 @@
|
||||
# Daily Notes
|
||||
|
||||
Daily notes allow you to quickly create and access a new notes file for each day. This is a surpisingly effective and increasingly common strategy to organize notes and manage events.
|
||||
Daily notes allow you to quickly create and access a note file for each day.
|
||||
|
||||
View today's note file by running the `Foam: Open Daily Note` command, by using the shortcut `alt+d` (note: shortcuts can be [overridden](https://code.visualstudio.com/docs/getstarted/keybindings)), or by using [#snippets](#Snippets). The name, location, and title of daily notes files is [#configurable](#Configuration).
|
||||
## Creating Daily Notes
|
||||
|
||||
## Roam-style Automatic Daily Notes
|
||||
- **Command:** `Ctrl+Shift+P` → "Foam: Open Daily Note"
|
||||
- **Shortcut:** `Alt+D`
|
||||
- **Snippets:** Type `/today`, `/yesterday`, `/tomorrow` in any note
|
||||
|
||||
You can automatically open today's note on startup by setting the `Foam › Open Daily Note: On Startup` setting to `true`.
|
||||
## Automatic Daily Notes
|
||||
|
||||
Open daily note automatically on VS Code startup:
|
||||
|
||||
```json
|
||||
{
|
||||
"foam.openDailyNote.onStartup": true
|
||||
}
|
||||
```
|
||||
|
||||
## Daily Note Templates
|
||||
|
||||
Daily notes can also make use of [[Note Templates]], by defining a special `.foam/templates/daily-note.md` template.
|
||||
Create `.foam/templates/daily-note.md` to customize the structure:
|
||||
|
||||
## Snippets
|
||||
```markdown
|
||||
---
|
||||
type: daily-note
|
||||
---
|
||||
|
||||
Create a link to a recent daily note using [snippets](https://code.visualstudio.com/docs/editor/userdefinedsnippets). Type `/today` and press `enter` to link to today's note. You can also write:
|
||||
# Daily Note - $FOAM_DATE_YEAR-$FOAM_DATE_MONTH-$FOAM_DATE_DATE
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ]
|
||||
|
||||
## Notes
|
||||
```
|
||||
|
||||
## Date Snippets
|
||||
|
||||
Create links to recent daily notes using snippets:
|
||||
|
||||
| Snippet | Date |
|
||||
| ------------ | ------------- |
|
||||
| `/today` | today |
|
||||
| `/tomorrow` | tomorrow |
|
||||
| `/yesterday` | yesterday |
|
||||
| `/monday` | next Monday |
|
||||
@@ -29,27 +54,13 @@ Create a link to a recent daily note using [snippets](https://code.visualstudio.
|
||||
|
||||
## Configuration
|
||||
|
||||
By default, Daily Notes will be created in a file called `yyyy-mm-dd.md` in the workspace's `journals` folder, with a heading `yyyy-mm-dd`.
|
||||
By default, daily notes are created as `yyyy-mm-dd.md` in the workspace's `journals` folder.
|
||||
|
||||
These settings can be overridden in your workspace or global `.vscode/settings.json` file, using the [**dateformat** date masking syntax](https://github.com/felixge/node-dateformat#mask-options):
|
||||
To customize your daily note location and format you can create a `.foam/templates/daily-note.md` template. See [[templates]] for more information.
|
||||
|
||||
It's possible to customize path and heading of your daily notes, by following the [dateformat masking syntax](https://github.com/felixge/node-dateformat#mask-options).
|
||||
The following properties can be used:
|
||||
There are also some settings to customize the behavior of daily notes, but they are deprecated and will be removed. Please use the `daily-note.md` template.
|
||||
|
||||
```json
|
||||
"foam.openDailyNote.directory": "journal",
|
||||
"foam.openDailyNote.filenameFormat": "'daily-note'-yyyy-mm-dd",
|
||||
"foam.openDailyNote.fileExtension": "mdx",
|
||||
"foam.openDailyNote.titleFormat": "'Journal Entry, ' dddd, mmmm d",
|
||||
```
|
||||
|
||||
The above configuration would create a file `journal/daily-note-2020-07-25.mdx`, with the heading `Journal Entry, Sunday, July 25`.
|
||||
|
||||
## Extend Functionality (Weekly, Monthly, Quarterly Notes)
|
||||
|
||||
Please see [[note-macros]]
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[Note Templates]: note-templates.md "Note Templates"
|
||||
[note-macros]: ../recipes/note-macros.md "Custom Note Macros"
|
||||
[note-templates]: note-templates.md "Note Templates"
|
||||
[//end]: # "Autogenerated link references"
|
||||
|
||||
134
docs/user/features/embeds.md
Normal file
134
docs/user/features/embeds.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# Note Embeds
|
||||
|
||||
Embeds allow you to include content from other notes directly into your current note. This is powerful for creating dynamic content that updates automatically when the source note changes.
|
||||
|
||||
## Basic Syntax
|
||||
|
||||
Use the embed syntax with an exclamation mark before the wikilink:
|
||||
|
||||
```markdown
|
||||
![[note-name]]
|
||||
```
|
||||
|
||||
This will embed the entire content of `note-name` into your current note.
|
||||
|
||||
## Embedding Sections
|
||||
|
||||
You can embed specific sections of a note by referencing the heading:
|
||||
|
||||
```markdown
|
||||
![[note-name#Section Title]]
|
||||
```
|
||||
|
||||
## Embed Types
|
||||
|
||||
Foam supports different embedding scopes and styles that can be configured globally or overridden per embed.
|
||||
|
||||
### Scope Modifiers
|
||||
|
||||
- **`full`** - Include the entire note or section, including the title/heading
|
||||
- **`content`** - Include everything except the title/heading
|
||||
|
||||
Examples:
|
||||
|
||||
```markdown
|
||||
full![[my-note]] # Include title + content
|
||||
content![[my-note]] # Content only, no title
|
||||
```
|
||||
|
||||
### Style Modifiers
|
||||
|
||||
- **`card`** - Display the embedded content in a bordered container
|
||||
- **`inline`** - Display the content seamlessly as part of the current note
|
||||
|
||||
Examples:
|
||||
|
||||
```markdown
|
||||
card![[my-note]] # Bordered container
|
||||
inline![[my-note]] # Seamless integration
|
||||
```
|
||||
|
||||
### Combined Modifiers
|
||||
|
||||
You can combine scope and style modifiers:
|
||||
|
||||
```markdown
|
||||
full-card![[my-note]] # Title + content in bordered container
|
||||
content-inline![[my-note]] # Content only, seamlessly integrated
|
||||
full-inline![[my-note]] # Title + content, seamlessly integrated
|
||||
content-card![[my-note]] # Content only in bordered container
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Set your default embed behavior in VS Code settings:
|
||||
|
||||
```json
|
||||
{
|
||||
"foam.preview.embedNoteType": "full-card"
|
||||
}
|
||||
```
|
||||
|
||||
Available options:
|
||||
|
||||
- `full-card` (default)
|
||||
- `full-inline`
|
||||
- `content-card`
|
||||
- `content-inline`
|
||||
|
||||
## Image Sizing
|
||||
|
||||
Resize images to make your documents more readable:
|
||||
|
||||
```markdown
|
||||
![[image.png|300]] # 300 pixels wide
|
||||
![[image.png|50%]] # Half the container width
|
||||
```
|
||||
|
||||
### Common Use Cases
|
||||
|
||||
**Make large screenshots readable:**
|
||||
```markdown
|
||||
![[screenshot.png|600]]
|
||||
```
|
||||
|
||||
**Create responsive images:**
|
||||
```markdown
|
||||
![[diagram.png|70%]]
|
||||
```
|
||||
|
||||
**Size by width and height:**
|
||||
```markdown
|
||||
![[image.png|300x200]]
|
||||
```
|
||||
|
||||
### Alignment
|
||||
|
||||
Center, left, or right align images:
|
||||
|
||||
```markdown
|
||||
![[image.png|300|center]]
|
||||
![[image.png|300|left]]
|
||||
![[image.png|300|right]]
|
||||
```
|
||||
|
||||
### Alt Text
|
||||
|
||||
Add descriptions for accessibility:
|
||||
|
||||
```markdown
|
||||
![[chart.png|400|Monthly sales chart]]
|
||||
```
|
||||
|
||||
### Units
|
||||
|
||||
- `300` or `300px` - pixels (default)
|
||||
- `50%` - percentage of container
|
||||
- `20em` - relative to font size
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
- Check image path: `![[path/to/image.png|300]]`
|
||||
- No spaces around pipes: `|300|` not `| 300 |`
|
||||
- Images only resize in preview mode, not edit mode
|
||||
- Use lowercase alignment: `center` not `Center`
|
||||
132
docs/user/features/graph-view.md
Normal file
132
docs/user/features/graph-view.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# Graph Visualization
|
||||
|
||||
The graph view is one of Foam's most powerful features. It transforms your collection of notes into a visual network, revealing connections between ideas that might not be obvious when reading individual notes. This guide will teach you how to use the graph view to explore, understand, and expand your knowledge base.
|
||||
|
||||
To see the graph execute the `Foam: Show Graph` command.
|
||||
|
||||
Your files, such as notes and documents, are shown as the nodes of the graph along with the tags defined in your notes. The edges of the graph represent either a link between two files or a file that contains a certain tag. A node in the graph will grow in size with the number of connections it has, representing stronger or more defined concepts and topics.
|
||||
|
||||
### The `Show Graph` command
|
||||
|
||||
1. **Press `Ctrl+Shift+P` / `Cmd+Shift+P`**
|
||||
2. **Type "Foam: Show Graph"**
|
||||
3. **Press Enter**
|
||||
|
||||
You can set up a custom keyboard shortcut:
|
||||
|
||||
1. **Go to File > Preferences > Keyboard Shortcuts**
|
||||
2. **Search for "Foam: Show Graph"**
|
||||
3. **Assign your preferred shortcut**
|
||||
|
||||
## Graph Navigation
|
||||
|
||||
With the Foam graph visualization you can:
|
||||
|
||||
- highlight a node by hovering on it, to quickly see how it's connected to the rest of your notes
|
||||
- select one or more (by keeping `shift` pressed while selecting) nodes by clicking on them, to better understand the structure of your notes
|
||||
- navigate to a note by clicking on it's node while pressing `ctrl` or `cmd`
|
||||
- automatically center the graph on the currently edited note, to immediately see its connections
|
||||
|
||||
## Filter View
|
||||
|
||||
If you only wish to view certain types of notes or tags, or want to hide linked attachment nodes then you can apply filters to the graph.
|
||||
|
||||
- Open the graph view using the `Foam: Show Graph` command
|
||||
- Click the button in the top right corner of the graph view that says "Open Controls"
|
||||
- Expand the "Filter By Type" dropdown to view the selection of types that you can filter by
|
||||
- Uncheck the checkbox for any type you want to hide
|
||||
- The types displayed in this dropdown are defined by [[note-properties]] which includes Foam-standard types as well as custom types defined by you!
|
||||
|
||||

|
||||
|
||||
## Custom Graph Styles
|
||||
|
||||
The Foam graph will use the current VS Code theme by default, but it's possible to customize it with the `foam.graph.style` setting.
|
||||
|
||||

|
||||
|
||||
A sample configuration object is provided below, you can provide as many or as little configuration as you wish:
|
||||
|
||||
```json
|
||||
"foam.graph.style": {
|
||||
"background": "#202020",
|
||||
"fontSize": 12,
|
||||
"fontFamily": "Sans-Serif",
|
||||
"lineColor": "#277da1",
|
||||
"lineWidth": 0.2,
|
||||
"particleWidth": 1.0,
|
||||
"highlightedForeground": "#f9c74f",
|
||||
"node": {
|
||||
"note": "#277da1",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `background` background color of the graph, adjust to increase contrast
|
||||
- `fontSize` size of the title font for each node
|
||||
- `fontFamily` font of the title font for each node
|
||||
- `lineColor` color of the edges between nodes in the graph
|
||||
- `lineWidth` thickness of the edges between nodes
|
||||
- `particleWidth` size of the particle animation showing link direction when highlighting a node
|
||||
- `highlightedForeground` color of highlighted nodes and edges when hovering over a node
|
||||
- to style individual types of nodes jump to the next section: [Style Nodes By Type](#style-nodes-by-type)
|
||||
|
||||
### Style Nodes by Type
|
||||
|
||||
It is possible to customize the style of a node based on the `type` property in the YAML frontmatter of the corresponding document.
|
||||
|
||||
There are a few default node types defined by Foam that are displayed in the graph:
|
||||
|
||||
- `note` defines the color for regular nodes whose documents have not overridden the `type` property.
|
||||
- `placeholder` defines the color for links that don't match any existing note. This is a [[placeholder]] because no file with such name exists.
|
||||
- see [[wikilinks]] for more info <!--NOTE: this placeholder link should NOT have an associated file. This is to demonstrate the custom coloring-->
|
||||
- `tag` defines the color for nodes representing #tags, allowing tags to be used as graph nodes similar to backlinks.
|
||||
- see [[tags]] for more info
|
||||
- `feature` shows an example of how you can use note types to customize the graph. It defines the color for the notes of type `feature`
|
||||
- see [[note-properties]] for details
|
||||
|
||||
For example the following `backlinking.md` note:
|
||||
|
||||
```markdown
|
||||
---
|
||||
type: feature
|
||||
---
|
||||
# Backlinking
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
And the following `settings.json`:
|
||||
|
||||
```json
|
||||
"foam.graph.style": {
|
||||
"background": "#202020",
|
||||
"node": {
|
||||
"note": "#277da1",
|
||||
"placeholder": "#545454",
|
||||
"tag": "#f9c74f",
|
||||
"feature": "red",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Will result in the following graph:
|
||||
|
||||

|
||||
|
||||
## What's Next?
|
||||
|
||||
With graph view mastery, you're ready to explore advanced Foam features:
|
||||
|
||||
1. **[[wikilinks]]** - Understand bidirectional connections
|
||||
2. **[[templates]]** - Use templates effectively to standardize your note creation
|
||||
3. **[[tags]]** - Organize your notes with tags
|
||||
4. **[[daily-notes]]** - Set up daily notes to establish capture routines
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[note-properties]: note-properties.md "Note Properties"
|
||||
[wikilinks]: wikilinks.md "Wikilinks"
|
||||
[tags]: tags.md "Tags"
|
||||
[templates]: templates.md "Note Templates"
|
||||
[daily-notes]: daily-notes.md "Daily Notes"
|
||||
[//end]: # "Autogenerated link references"
|
||||
@@ -1,74 +0,0 @@
|
||||
# Graph Visualization
|
||||
|
||||
Foam comes with a graph visualization of your notes.
|
||||
To see the graph execute the `Foam: Show Graph` command.
|
||||
|
||||
## Graph Navigation
|
||||
|
||||
With the graph you can:
|
||||
|
||||
- highlight a node by hovering on it, to quickly see how it's connected to the rest of your notes
|
||||
- select one or more (by keeping `shift` pressed while selecting) nodes by clicking on them, to better understand the structure of your notes
|
||||
- navigate to a note by clicking on it while pressing `ctrl` or `cmd`
|
||||
- automatically center the graph on the currently edited note, to immediately see its connections
|
||||
|
||||
## Custom Graph Styles
|
||||
|
||||
The Foam graph will use the current VS Code theme by default, but it's possible to customize it with the `foam.graph.style` setting.
|
||||
|
||||

|
||||
|
||||
A sample configuration object is provided below, you can provide as many or as little configuration as you wish:
|
||||
|
||||
```json
|
||||
"foam.graph.style": {
|
||||
"background": "#202020",
|
||||
"fontSize": 12,
|
||||
"highlightedForeground": "#f9c74f",
|
||||
"node": {
|
||||
"note": "#277da1",
|
||||
"placeholder": "#545454",
|
||||
"feature": "green",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `note` defines the color for regular nodes
|
||||
- `placeholder` defines the color for links that don't match any existing note. This is a [[placeholder]] because no file with such name exists (see [[wikilinks]] for more info).
|
||||
- `feature` shows an example of how you can use note types to customize the graph. It defines the color for the notes of type `feature`
|
||||
- see [[note-properties]] for details
|
||||
- you can have as many types as you want
|
||||
|
||||
### Style nodes by type
|
||||
|
||||
It is possible to customize the style of a node based on the `type` property in the YAML frontmatter of the corresponding document.
|
||||
|
||||
For example the following `backlinking.md` note:
|
||||
|
||||
```
|
||||
---
|
||||
type: feature
|
||||
---
|
||||
# Backlinking
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
And the following `settings.json`:
|
||||
|
||||
```json
|
||||
"foam.graph.style": {
|
||||
"node": {
|
||||
"feature": "red",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Will result in the following graph:
|
||||
|
||||

|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[wikilinks]: wikilinks.md "Wikilinks"
|
||||
[note-properties]: note-properties.md "Note Properties"
|
||||
[//end]: # "Autogenerated link references"
|
||||
@@ -1,20 +0,0 @@
|
||||
# Including notes in a note
|
||||
|
||||
In some situations it might be useful to include the content of another note in your current note. Foam supports this displaying within the vscode environment. Note, this does not work out-of-the-box for your publishing solutions.
|
||||
|
||||
## Including a note
|
||||
|
||||
Including a note can be done by adding an `!` before a wikilink defintion. For example `![[wikilink]]`.
|
||||
|
||||
## Custom styling
|
||||
|
||||
Displaying the inclusion of notes allows for some custom styling, see [[custom-markdown-preview-styles]]
|
||||
|
||||
## Future possibilities
|
||||
|
||||
Work on this feature is evolving and progressing. See the [[inclusion-of-notes]] proposal for the current discussion.
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[custom-markdown-preview-styles]: custom-markdown-preview-styles.md "Custom Markdown Preview Styles"
|
||||
[inclusion-of-notes]: ../../dev/proposals/inclusion-of-notes.md "Inclusion of notes Proposal "
|
||||
[//end]: # "Autogenerated link references"
|
||||
@@ -1,76 +1,60 @@
|
||||
# Link Reference Definitions
|
||||
|
||||
When you use `[[wikilinks]]`, the [foam-vscode](https://github.com/foambubble/foam/tree/master/packages/foam-vscode) extension can automatically generate [Markdown Link Reference Definitions](https://spec.commonmark.org/0.29/#link-reference-definitions) at the bottom of the file. This is not needed to navigate your workspace with foam-vscode, but is useful for files to remain compatible with various Markdown tools (e.g. parsers, static site generators, VS code plugins etc), which don't support `[[wikilinks]]`.
|
||||
Link reference definitions make your notes compatible with standard Markdown processors by converting wikilinks to standard Markdown references.
|
||||
|
||||
## Example
|
||||
Foam doesn't need references in order to work, but this feature is aimed at supporting other tools you might want to integrate with.
|
||||
|
||||
The following example:
|
||||
## What Are Link Reference Definitions?
|
||||
|
||||
```md
|
||||
- [[wikilinks]]
|
||||
- [[github-pages]]
|
||||
```
|
||||
Foam can automatically add reference definitions to the bottom of your notes:
|
||||
|
||||
...generates the following link reference definitions to the bottom of the file:
|
||||
**Your note:**
|
||||
|
||||
```md
|
||||
[wikilinks]: wikilinks "Wikilinks"
|
||||
[github-pages]: github-pages "GitHub Pages"
|
||||
```
|
||||
```markdown
|
||||
# Machine Learning
|
||||
|
||||
You can open the [raw markdown](https://foambubble.github.io/foam/features/link-reference-definitions.md) to see them at the bottom of this file
|
||||
|
||||
## Specification
|
||||
|
||||
The three components of a link reference definition are `[link-label]: link-target "Link Title"`
|
||||
|
||||
- **link label:** The link text to match in the surrounding markdown document. This matches the inner bracket of the double-bracketed `[[wikilink]]` notation
|
||||
- **link destination** The target of the matched link
|
||||
- By default we generate links without extension. This can be overridden, see [Configuration](#configuration) below
|
||||
- **"Link Title"** Optional title for link (The Foam template has a snippet of JavaScript to replace this on the website at runtime)
|
||||
|
||||
## Configuration
|
||||
|
||||
You can choose to generate link reference definitions with or without file extensions, depending on the target, or to disable the generation altogether. As a rule of thumb:
|
||||
|
||||
- Links with file extensions work better with standard markdown-based tools, such as GitHub web UI.
|
||||
- Links without file extensions work better with certain web publishing tools that treat links as literal urls and don't transform them automatically, such as the standard GitHub pages installation.
|
||||
|
||||
By default, Foam generates links without file extensions for legacy reasons, but this may change in future versions.
|
||||
|
||||
You can override this setting in your Foam workspace's `settings.json`:
|
||||
|
||||
- `"foam.edit.linkReferenceDefinitions": "withoutExtensions"` (default)
|
||||
- `"foam.edit.linkReferenceDefinitions": "withExtensions"`
|
||||
- `"foam.edit.linkReferenceDefinitions": "off"`
|
||||
|
||||
### Ignoring files
|
||||
|
||||
Sometimes, you may want to ignore certain files or folders, so that Foam doesn't generate link reference definitions to them.
|
||||
|
||||
For instance, if you're using a local instance of [Jekyll](https://jekyllrb.com/), you may find that it writes copies of each `.md` file into a `_site` directory, which may lead to Foam generating references to them instead of the original source notes.
|
||||
|
||||
You can ignore the `_site` directory by adding the following to your `.vscode/settings.json`:
|
||||
|
||||
```json
|
||||
"files.exclude": {
|
||||
"**/_site": true
|
||||
},
|
||||
"files.watcherExclude": {
|
||||
"**/_site": true
|
||||
},
|
||||
Related to [[Data Science]] and [[Statistics]].
|
||||
```
|
||||
|
||||
After changing the setting in your workspace, you can run the [[workspace-janitor]] command to convert all existing definitions.
|
||||
**With reference definitions:**
|
||||
|
||||
## Future improvements
|
||||
```markdown
|
||||
# Machine Learning
|
||||
|
||||
Implement `foam.exclude`. [[todo]]
|
||||
Related to [[Data Science]] and [[Statistics]].
|
||||
|
||||
See [[link-reference-definition-improvements]] for further discussion on current problems and potential solutions.
|
||||
[Data Science]: data-science.md 'Data Science'
|
||||
[Statistics]: statistics.md 'Statistics'
|
||||
```
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[workspace-janitor]: ../tools/workspace-janitor.md "Janitor"
|
||||
[todo]: ../../dev/todo.md "Todo"
|
||||
[link-reference-definition-improvements]: ../../dev/proposals/link-reference-definition-improvements.md "Link Reference Definition Improvements"
|
||||
[//end]: # "Autogenerated link references"
|
||||
## Enabling Reference Definitions
|
||||
|
||||
Configure in your settings:
|
||||
|
||||
```json
|
||||
{
|
||||
"foam.edit.linkReferenceDefinitions": "withExtensions"
|
||||
}
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `"off"` - Disabled (default)
|
||||
- `"withoutExtensions"` - References without extension
|
||||
- `"withExtensions"` - References with extension
|
||||
|
||||
If you are using your notes only within Foam, you can keep definitions `off` (also to reduce clutter), otherwise pick your setting based on what is required by your use case.
|
||||
|
||||
## How It Works
|
||||
|
||||
1. Scans your note for wikilinks
|
||||
2. Generates reference definitions when you save
|
||||
3. Updates definitions when links change
|
||||
4. Maintains the auto-generated section
|
||||
|
||||
## Benefits
|
||||
|
||||
- **Standard Markdown compatibility** - Works with any Markdown processor
|
||||
- **Publishing platforms** - Compatible with GitHub Pages, Jekyll, etc.
|
||||
- **Future-proofing** - Not locked into Foam-specific format
|
||||
- **Team collaboration** - Others can read notes without Foam
|
||||
|
||||
@@ -1,35 +1,58 @@
|
||||
---
|
||||
type: feature
|
||||
keywords: hello world
|
||||
keywords: hello world, bonjour
|
||||
tags: [hello, bonjour]
|
||||
---
|
||||
|
||||
# Note Properties
|
||||
|
||||
At the top of the file you can have a section where you define your properties.
|
||||
At the top of the file you can have a section where you define your properties. This section is known as the [Front-Matter](https://learn.cloudcannon.com/jekyll/introduction-to-jekyll-front-matter/) of the document and uses [YAML formatting](https://www.codeproject.com/Articles/1214409/Learn-YAML-in-five-minutes).
|
||||
|
||||
> Be aware that this section needs to be at the very top of the file to be valid
|
||||
> Be aware that this YAML section needs to be at the very top of the file to be valid.
|
||||
|
||||
For example, for this file, we have:
|
||||
|
||||
```text
|
||||
```markdown
|
||||
---
|
||||
type: feature
|
||||
keywords: hello world
|
||||
keywords: hello world, bonjour
|
||||
---
|
||||
```
|
||||
|
||||
Those are properties.
|
||||
Properties can be used to organize your notes.
|
||||
This sets the `type` of this document to `feature` and sets **three** keywords for the document: `hello`, `world`, and `bonjour`. The YAML parser will treat both spaces and commas as the separators for these YAML properties. If you want to use multi-word values for these properties, you will need to combine the words with dashes or underscores (i.e. instead of `hello world`, use `hello_world` or `hello-world`).
|
||||
|
||||
> You can set as many custom properties for a document as you like, but there are a few [special properties](#special-properties) defined by Foam.
|
||||
|
||||
## Special Properties
|
||||
|
||||
Some properties have special meaning for Foam:
|
||||
|
||||
- the `title` property will assign the name to the note that you will see in the graph, regardless of the filename or the first heading (also see how to [[write-notes-in-foam]])
|
||||
- the `type` property can be used to style notes differently in the graph (also see [[graph-visualization]])
|
||||
- the `tags` property can be used to add tags to a note (see [[tags-and-tag-explorer]])
|
||||
| Name | Description |
|
||||
| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `title` | will assign the name to the note that you will see in the graph, regardless of the filename or the first heading (also see how to [[note-taking-in-foam]]) |
|
||||
| `type` | can be used to style notes differently in the graph (also see [[graph-view]]). The default type for a document is `note` unless otherwise specified with this property. |
|
||||
| `tags` | can be used to add tags to a note (see [[tags]]) |
|
||||
| `alias` | can be used to add aliases to the note. an alias will show up in the link autocompletion |
|
||||
|
||||
For example:
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: "Note Title"
|
||||
type: "daily-note"
|
||||
tags: daily, funny, planning
|
||||
alias: alias1, alias2
|
||||
---
|
||||
```
|
||||
|
||||
## Foam Template Properties
|
||||
|
||||
There also exists properties that are even more specific to Foam templates, see [[templates#Metadata]] for more info.
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[write-notes-in-foam]: ../getting-started/write-notes-in-foam.md "Writing Notes"
|
||||
[graph-visualization]: graph-visualization.md "Graph Visualization"
|
||||
[tags]: tags.md "Tags"
|
||||
[graph-view]: ../features/graph-view.md "Graph Visualization"
|
||||
[note-taking-in-foam]: ../getting-started/note-taking-in-foam.md "Note-Taking in Foam"
|
||||
[note-templates#Metadata]: note-templates.md "Note Templates"
|
||||
[//end]: # "Autogenerated link references"
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
# Note Templates
|
||||
|
||||
Foam supports note templates which let you customize the starting content of your notes instead of always starting from an empty note.
|
||||
|
||||
Note templates are `.md` files located in the special `.foam/templates` directory of your workspace.
|
||||
|
||||
## Quickstart
|
||||
|
||||
Create a template:
|
||||
|
||||
* Run the `Foam: Create New Template` command from the command palette
|
||||
* OR manually create a regular `.md` file in the `.foam/templates` directory
|
||||
|
||||

|
||||
|
||||
_Theme: Ayu Light_
|
||||
|
||||
To create a note from a template:
|
||||
|
||||
* Run the `Foam: Create New Note From Template` command and follow the instructions. Don't worry if you've not created a template yet! You'll be prompted to create a new template if none exist.
|
||||
* OR run the `Foam: Create New Note` command, which uses the special default template (`.foam/templates/new-note.md`, if it exists)
|
||||
|
||||

|
||||
|
||||
_Theme: Ayu Light_
|
||||
|
||||
## Special templates
|
||||
### Default template
|
||||
|
||||
The `.foam/templates/new-note.md` template is special in that it is the template that will be used by the `Foam: Create New Note` command.
|
||||
Customize this template to contain content that you want included every time you create a note.
|
||||
|
||||
### Default daily note template
|
||||
|
||||
The `.foam/templates/daily-note.md` template is special in that it is the template that will be used when creating daily notes (e.g. by using `Foam: Open Daily Note`).
|
||||
Customize this template to contain content that you want included every time you create a daily note.
|
||||
|
||||
## Variables
|
||||
|
||||
Templates can use all the variables available in [VS Code Snippets](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_variables).
|
||||
|
||||
In addition, you can also use variables provided by Foam:
|
||||
|
||||
| Name | Description |
|
||||
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `FOAM_SELECTED_TEXT` | Foam will fill it with selected text when creating a new note, if any text is selected. Selected text will be replaced with a wikilink to the new note. |
|
||||
| `FOAM_TITLE` | The title of the note. If used, Foam will prompt you to enter a title for the note. |
|
||||
| `FOAM_SLUG` | The sluggified title of the note (using the default github slug method). If used, Foam will prompt you to enter a title for the note unless `FOAM_TITLE` has already caused the prompt. |
|
||||
| `FOAM_DATE_*` | `FOAM_DATE_YEAR`, `FOAM_DATE_MONTH`, etc. Foam-specific versions of [VS Code's datetime snippet variables](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_variables). Prefer these versions over VS Code's. |
|
||||
|
||||
### `FOAM_DATE_*` variables
|
||||
|
||||
Foam defines its own set of datetime variables that have a similar behaviour as [VS Code's datetime snippet variables](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_variables).
|
||||
|
||||
For example, `FOAM_DATE_YEAR` has the same behaviour as VS Code's `CURRENT_YEAR`, `FOAM_DATE_SECONDS_UNIX` has the same behaviour as `CURRENT_SECONDS_UNIX`, etc.
|
||||
|
||||
By default, prefer using the `FOAM_DATE_` versions. The datetime used to compute the values will be the same for both `FOAM_DATE_` and VS Code's variables, with the exception of the creation notes using the daily note template.
|
||||
|
||||
#### Relative daily notes
|
||||
|
||||
When referring to daily notes, you can use the relative snippets (`/+1d`, `/tomorrow`, etc.). In these cases, the new notes will be created with the daily note template, but the datetime used should be the relative datetime, not the current datetime.
|
||||
By using the `FOAM_DATE_` versions of the variables, the correct relative date will populate the variables, instead of the current datetime.
|
||||
|
||||
For example, given this daily note template (`.foam/templates/daily-note.md`):
|
||||
|
||||
```markdown
|
||||
# $FOAM_DATE_YEAR-$FOAM_DATE_MONTH-$FOAM_DATE_DATE
|
||||
|
||||
## Here's what I'm going to do today
|
||||
|
||||
* Thing 1
|
||||
* Thing 2
|
||||
```
|
||||
|
||||
When the `/tomorrow` snippet is used, `FOAM_DATE_` variables will be populated with tomorrow's date, as expected.
|
||||
If instead you were to use the VS Code versions of these variables, they would be populated with today's date, not tomorrow's, causing unexpected behaviour.
|
||||
|
||||
When creating notes in any other scenario, the `FOAM_DATE_` values are computed using the same datetime as the VS Code ones, so the `FOAM_DATE_` versions can be used in all scenarios by default.
|
||||
|
||||
## Metadata
|
||||
|
||||
Templates can also contain metadata about the templates themselves. The metadata is defined in YAML "Frontmatter" blocks within the templates.
|
||||
|
||||
| Name | Description |
|
||||
| ------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `filepath` | The filepath to use when creating the new note. If the filepath is a relative filepath, it is relative to the current workspace. |
|
||||
| `name` | A human readable name to show in the template picker. |
|
||||
| `description` | A human readable description to show in the template picker. |
|
||||
|
||||
Foam-specific variables (e.g. `$FOAM_TITLE`) can be used within template metadata. However, VS Code snippet variables are ([currently](https://github.com/foambubble/foam/pull/655)) not supported.
|
||||
|
||||
### `filepath` attribute
|
||||
|
||||
The `filepath` metadata attribute allows you to define a relative or absolute filepath to use when creating a note using the template.
|
||||
If the filepath is a relative filepath, it is relative to the current workspace.
|
||||
|
||||
**Note:** While you can make use of the `filepath` attribute in [daily note](daily-notes.md) templates (`.foam/templates/daily-note.md`), there is currently no way to have `filepath` vary based on the date. This will be improved in the future. For now, you can customize the location of daily notes using the [`foam.openDailyNote` settings](daily-notes.md).
|
||||
|
||||
#### Example of relative `filepath`
|
||||
|
||||
For example, `filepath` can be used to customize `.foam/templates/new-note.md`, overriding the default `Foam: Create New Note` behaviour of opening the file in the same directory as the active file:
|
||||
|
||||
```yaml
|
||||
---
|
||||
# This will create the note in the "journal" subdirectory of the current workspace,
|
||||
# regardless of which file is the active file.
|
||||
foam_template:
|
||||
filepath: 'journal/$FOAM_TITLE.md'
|
||||
---
|
||||
```
|
||||
|
||||
#### Example of absolute `filepath`
|
||||
|
||||
`filepath` can be an absolute filepath, so that the notes get created in the same location, regardless of which file or workspace the editor currently has open.
|
||||
The format of an absolute filepath may vary depending on the filesystem used.
|
||||
|
||||
```yaml
|
||||
---
|
||||
foam_template:
|
||||
# Unix / MacOS filesystems
|
||||
filepath: '/Users/john.smith/foam/journal/$FOAM_TITLE.md'
|
||||
|
||||
# Windows filesystems
|
||||
filepath: 'C:\Users\john.smith\Documents\foam\journal\$FOAM_TITLE.md'
|
||||
---
|
||||
```
|
||||
|
||||
### `name` and `description` attributes
|
||||
|
||||
These attributes provide a human readable name and description to be shown in the template picker (e.g. When a user uses the `Foam: Create New Note From Template` command):
|
||||
|
||||

|
||||
|
||||
### Adding template metadata to an existing YAML Frontmatter block
|
||||
|
||||
If your template already has a YAML Frontmatter block, you can add the Foam template metadata to it.
|
||||
|
||||
#### Limitations
|
||||
|
||||
Foam only supports adding the template metadata to *YAML* Frontmatter blocks. If the existing Frontmatter block uses some other format (e.g. JSON), you will have to add the template metadata to its own YAML Frontmatter block.
|
||||
|
||||
Further, the template metadata must be provided as a [YAML block mapping](https://yaml.org/spec/1.2/spec.html#id2798057), with the attributes placed on the lines immediately following the `foam_template` line:
|
||||
|
||||
```yaml
|
||||
---
|
||||
existing_frontmatter: "Existing Frontmatter block"
|
||||
foam_template: # this is a YAML "Block" mapping ("Flow" mappings aren't supported)
|
||||
name: My Note Template # Attributes must be on the lines immediately following `foam_template`
|
||||
description: This is my note template
|
||||
filepath: `journal/$FOAM_TITLE.md`
|
||||
---
|
||||
This is the rest of the template
|
||||
```
|
||||
|
||||
Due to the technical limitations of parsing the complex YAML format, unless the metadata is provided this specific form, Foam is unable to correctly remove the template metadata before creating the resulting note.
|
||||
|
||||
If this limitation proves inconvenient to you, please let us know. We may be able to extend our parsing capabilities to cover your use case. In the meantime, you can add the template metadata without this limitation by providing it in its own YAML Frontmatter block.
|
||||
|
||||
### Adding template metadata to its own YAML Frontmatter block
|
||||
|
||||
You can add the template metadata to its own YAML Frontmatter block at the start of the template:
|
||||
|
||||
```yaml
|
||||
---
|
||||
foam_template:
|
||||
name: My Note Template
|
||||
description: This is my note template
|
||||
filepath: `journal/$FOAM_TITLE.md`
|
||||
---
|
||||
This is the rest of the template
|
||||
```
|
||||
|
||||
If the note already has a Frontmatter block, a Foam-specific Frontmatter block can be added to the start of the template. The Foam-specific Frontmatter block must always be placed at the very beginning of the file, and only whitespace can separate the two Frontmatter blocks.
|
||||
|
||||
```yaml
|
||||
---
|
||||
foam_template:
|
||||
name: My Note Template
|
||||
description: This is my note template
|
||||
filepath: `journal/$FOAM_TITLE.md`
|
||||
---
|
||||
|
||||
---
|
||||
existing_frontmatter: "Existing Frontmatter block"
|
||||
---
|
||||
This is the rest of the template
|
||||
```
|
||||
42
docs/user/features/resource-filters.md
Normal file
42
docs/user/features/resource-filters.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Resource Filters
|
||||
|
||||
Resource filters can be passed to some Foam commands to limit their scope.
|
||||
|
||||
A filter supports the following parameters:
|
||||
|
||||
- `tag`: include a resource if it has the given tag (e.g. `{"tag": "#research"}`)
|
||||
- `type`: include a resource if it is of the given type (e.g. `{"type": "daily-note"}`)
|
||||
- `path`: include a resource if its path matches the given regex (e.g. `{"path": "/projects/*"}`). **Note that this parameter supports regex and not globs.**
|
||||
- `expression`: include a resource if it makes the given expression `true`, where `resource` represents the resource being evaluated (e.g. `{"expression": "resource.type ==='weekly-note'"}`)
|
||||
- `title`: include a resource if the title matches the given regex (e.g. `{"title": "Team meeting:*"}`)
|
||||
|
||||
A filter also supports some logical operators:
|
||||
|
||||
- `and`: include a resource if it matches all the sub-parameters (e.g `{"and": [{"tag": "#research"}, {"title": "Paper *"}]}`)
|
||||
- `or`: include a resource if it matches any of the sub-parameters (e.g `{"or": [{"tag": "#research"}, {"title": "Paper *"}]}`)
|
||||
- `not`: invert the result of the nested filter (e.g. `{"not": {"type": "daily-note"}}`)
|
||||
|
||||
Here is an example of a complex filter, for example to show the Foam graph only of a subset of the workspace:
|
||||
|
||||
```
|
||||
{
|
||||
"key": "alt+f",
|
||||
"command": "foam-vscode.show-graph",
|
||||
"args": {
|
||||
"filter": {
|
||||
"and": [
|
||||
{
|
||||
"or": [
|
||||
{ "type": 'daily-note' },
|
||||
{ "type": 'weekly-note' },
|
||||
{ "path": '/projects/*' },
|
||||
],
|
||||
"not": {
|
||||
{ "tag": '#b' },
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1,30 +1,90 @@
|
||||
---
|
||||
tags: my-tag1 my-tag2
|
||||
---
|
||||
|
||||
# Tags
|
||||
|
||||
You can add tags to your notes to categorize or link notes together.
|
||||
Tags provide flexible categorization and organization for your notes beyond wikilinks and folders.
|
||||
|
||||
## Creating a tag
|
||||
## Creating Tags
|
||||
|
||||
There are two ways of creating a tag:
|
||||
### Inline Tags
|
||||
|
||||
- Adding a `#tag` anywhere in the text of the note, for example: #my-tag1
|
||||
- Using the `tags: tag1, tag2` yaml frontmatter [[note property|note-properties]]. Notice `my-tag1` and `my-tag2` tags which are added to this document this way.
|
||||
Add tags directly in note content:
|
||||
|
||||
Tags can also be hierarchical, so you can have `#parent/child`.
|
||||
```markdown
|
||||
# Machine Learning Fundamentals
|
||||
|
||||
## Using *Tag Explorer*
|
||||
This covers basic algorithms and applications.
|
||||
|
||||
It's possible to navigate tags via the Tag Explorer panel.
|
||||
In the future it will be possible to explore tags via the graph as well.
|
||||
#machine-learning #data-science #algorithms #beginner
|
||||
```
|
||||
|
||||
## Styling tags
|
||||
### Front Matter Tags
|
||||
|
||||
Inline tags can be styled using custom CSS with the selector `.foam-tag`.
|
||||
Add tags in YAML front matter:
|
||||
|
||||
## Using backlinks in place of tags
|
||||
```markdown
|
||||
---
|
||||
tags: [machine-learning, data-science, algorithms, beginner]
|
||||
---
|
||||
```
|
||||
|
||||
Given the power of backlinks, some people prefer to use them as tags.
|
||||
For example you can tag your notes about books with [[book]].
|
||||
### Hierarchical Tags
|
||||
|
||||
Create tag hierarchies using forward slashes:
|
||||
|
||||
```markdown
|
||||
#programming/languages/python
|
||||
#programming/frameworks/react
|
||||
#work/projects/website-redesign
|
||||
#personal/health/exercise
|
||||
```
|
||||
|
||||
## Autocompletion
|
||||
|
||||
Typing `#` shows existing tags. In front matter, use `Ctrl+Space` for tag suggestions.
|
||||
|
||||
## Tag Explorer
|
||||
|
||||
Use the Tag Explorer panel in VS Code's sidebar to:
|
||||
|
||||
- Browse hierarchical tag structure
|
||||
- Filter by tag names
|
||||
- Click tags to see all associated notes
|
||||
- View tag usage counts
|
||||
- Search for tags (click the search icon or use "Foam: Search Tag" command)
|
||||
|
||||
Tags also appear in the [[graph-view]] with customizable colors.
|
||||
|
||||
## Tag Search
|
||||
|
||||
Search for all occurrences of a tag across your workspace:
|
||||
|
||||
1. Use the command palette: "Foam: Search Tag"
|
||||
2. Or click the search icon next to a tag in the Tag Explorer panel
|
||||
|
||||
Results appear in VS Code's search panel where you can navigate between matches.
|
||||
|
||||
> Known limitation: this command leverages VS Code's search capability, so it's constrained by its use of regular expressions. The search is best-effort and some false search results might show up.
|
||||
|
||||
## Custom Tag Styling
|
||||
|
||||
Customize tag appearance in markdown preview by adding CSS:
|
||||
|
||||
1. Create `.foam/css/custom-tag-style.css`
|
||||
2. Add CSS targeting `.foam-tag` class:
|
||||
```css
|
||||
.foam-tag {
|
||||
color: #ffffff;
|
||||
background-color: #000000;
|
||||
}
|
||||
```
|
||||
3. Update `.vscode/settings.json`:
|
||||
```json
|
||||
{
|
||||
"markdown.styles": [".foam/css/custom-tag-style.css"]
|
||||
}
|
||||
```
|
||||
|
||||
## Tags vs Backlinks
|
||||
|
||||
Some users prefer [[book]] backlinks instead of #book tags for categorization. Both approaches work - choose what fits your workflow.
|
||||
|
||||
[graph-view]: graph-view.md 'Graph Visualization'
|
||||
|
||||
401
docs/user/features/templates.md
Normal file
401
docs/user/features/templates.md
Normal file
@@ -0,0 +1,401 @@
|
||||
# Note Templates
|
||||
|
||||
Foam supports note templates which let you customize the starting content of your notes instead of always starting from an empty note.
|
||||
|
||||
Foam supports two types of templates:
|
||||
|
||||
- **Markdown templates** (`.md` files) - Simple templates with predefined content and variables
|
||||
- **JavaScript templates** (`.js` files) - Smart templates that can adapt based on context and make intelligent decisions
|
||||
|
||||
Both types of templates are located in the special `.foam/templates` directory of your workspace.
|
||||
|
||||
## Quickstart
|
||||
|
||||
### Creating templates
|
||||
|
||||
**For simple templates:**
|
||||
|
||||
- Run the `Foam: Create New Template` command from the command palette
|
||||
- OR manually create a regular `.md` file in the `.foam/templates` directory
|
||||
|
||||
**For smart templates:**
|
||||
|
||||
- Create a `.js` file in the `.foam/templates` directory (see [JavaScript Templates](#javascript-templates) section below)
|
||||
|
||||

|
||||
|
||||
### Using templates
|
||||
|
||||
To create a note from a template:
|
||||
|
||||
- Run the `Foam: Create New Note From Template` command and follow the instructions. Don't worry if you've not created a template yet! You'll be prompted to create a new simple template if none exist.
|
||||
- OR run the `Foam: Create New Note` command, which uses the special default template (`.foam/templates/new-note.md` or `.foam/templates/new-note.js`, if it exists)
|
||||
|
||||

|
||||
|
||||
## Special templates
|
||||
|
||||
### Default template
|
||||
|
||||
The default template is used by the `Foam: Create New Note` command. Foam will look for these templates in order:
|
||||
|
||||
1. `.foam/templates/new-note.js` (JavaScript template)
|
||||
2. `.foam/templates/new-note.md` (Markdown template)
|
||||
|
||||
Customize this template to contain content that you want included every time you create a note.
|
||||
|
||||
### Default daily note template
|
||||
|
||||
The daily note template is used when creating daily notes (e.g. by using `Foam: Open Daily Note`). Foam will look for these templates in order:
|
||||
|
||||
1. `.foam/templates/daily-note.js` (JavaScript template)
|
||||
2. `.foam/templates/daily-note.md` (Markdown template)
|
||||
|
||||
For a simple markdown template, it is _recommended_ to define the YAML Front-Matter similar to the following:
|
||||
|
||||
```markdown
|
||||
---
|
||||
type: daily-note
|
||||
---
|
||||
```
|
||||
|
||||
## JavaScript Templates
|
||||
|
||||
JavaScript templates are a powerful way to create smart, context-aware note templates that can adapt based on the situation. Unlike static Markdown templates, JavaScript templates can make intelligent decisions about what content to include.
|
||||
|
||||
**Use JavaScript templates when you want to:**
|
||||
|
||||
- Create different note structures based on the day of the week, time, or date
|
||||
- Adapt templates based on where the note is being created from
|
||||
- Automatically find and link related notes in your workspace
|
||||
- Generate content based on existing notes or workspace structure
|
||||
- Implement complex logic that static templates cannot handle
|
||||
|
||||
### Basic JavaScript template structure
|
||||
|
||||
A JavaScript template is a `.js` file that exports a function returning note content, and optionally location:
|
||||
|
||||
```javascript
|
||||
// .foam/templates/daily-note.js
|
||||
async function createNote({ trigger, foam, resolver, foamDate }) {
|
||||
const today = dayjs();
|
||||
// or you could use foamDate for day specific notes, see FOAM_DATE_* variables
|
||||
// const day = dayjs(foamDate)
|
||||
const formattedDay = today.format('YYYY-MM-DD');
|
||||
|
||||
// if you need a variable you can use the resolver
|
||||
// const title = await resolver.resolveFromName('FOAM_TITLE');
|
||||
|
||||
console.log(
|
||||
'Creating note for today: ' + formattedDay,
|
||||
JSON.stringify(trigger)
|
||||
);
|
||||
|
||||
let content = `# Daily Note - ${formattedDay}
|
||||
|
||||
## Today's focus
|
||||
-
|
||||
|
||||
## Notes
|
||||
-
|
||||
`;
|
||||
|
||||
switch (today.day()) {
|
||||
case 1: // Monday
|
||||
content = `# Week Planning - ${formattedDay}
|
||||
|
||||
## This week's goals
|
||||
- [ ] Goal 1
|
||||
- [ ] Goal 2
|
||||
|
||||
## Focus areas
|
||||
-
|
||||
`;
|
||||
break;
|
||||
case 5: // Friday
|
||||
content = `# Week Review - ${formattedDay}
|
||||
|
||||
## What went well
|
||||
-
|
||||
|
||||
## What could be improved
|
||||
-
|
||||
|
||||
## Next week's priorities
|
||||
-
|
||||
`;
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
content,
|
||||
filepath: `/weekly-planning/${formattedDay}.md`,
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
**Smart meeting notes:**
|
||||
|
||||
```javascript
|
||||
async function createNote({ trigger, foam, resolver }) {
|
||||
const title = (await resolver.resolveFromName('FOAM_TITLE')) || 'Meeting';
|
||||
const today = dayjs();
|
||||
// Detect meeting type from title
|
||||
const isStandup = title.toLowerCase().includes('standup');
|
||||
const isReview = title.toLowerCase().includes('review');
|
||||
|
||||
let template = `# ${title} - ${today.format('YYYY-MM-DD')}
|
||||
|
||||
`;
|
||||
|
||||
if (isStandup) {
|
||||
template += `## What I did yesterday
|
||||
-
|
||||
|
||||
## What I'm doing today
|
||||
-
|
||||
|
||||
## Blockers
|
||||
-
|
||||
`;
|
||||
} else if (isReview) {
|
||||
template += `## What went well
|
||||
-
|
||||
|
||||
## What could be improved
|
||||
-
|
||||
|
||||
## Action items
|
||||
- [ ]
|
||||
`;
|
||||
} else {
|
||||
template += `## Agenda
|
||||
-
|
||||
|
||||
## Notes
|
||||
-
|
||||
|
||||
## Action items
|
||||
- [ ]
|
||||
`;
|
||||
}
|
||||
|
||||
return {
|
||||
content: template,
|
||||
filepath: `/meetings/${title}.md`,
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Template result format
|
||||
|
||||
JavaScript templates must return an object with:
|
||||
|
||||
- `content` (required): The note content as a string
|
||||
- `filepath` (required): Custom file path for the note
|
||||
- NOTE: the path must be within the workspace.
|
||||
- A relative path will be resolved based on the `onRelativePath` command configuration.
|
||||
- An absolute path will be taken as is, if it falls within the workspace. Otherwise it will be considered to be from the workspace root
|
||||
|
||||
```javascript
|
||||
return {
|
||||
content: '# My Note\n\nContent here...',
|
||||
filepath: 'custom-folder/my-note.md',
|
||||
};
|
||||
```
|
||||
|
||||
### Security and limitations
|
||||
|
||||
JavaScript templates run in a best-effort secured environment:
|
||||
|
||||
- ✅ Can only run from trusted VS Code workspaces
|
||||
- ✅ Can access Foam workspace and utilities
|
||||
- ✅ Can use standard JavaScript features
|
||||
- ✅ Have a 30-second execution timeout
|
||||
- ❌ Cannot access the file system directly
|
||||
- ❌ Cannot make network requests
|
||||
- ❌ Cannot access Node.js modules
|
||||
|
||||
This increases the chances that templates stay safe while still being powerful enough for complex logic.
|
||||
|
||||
STILL - PLEASE BE AWARE YOU ARE EXECUTING CODE ON YOUR MACHINE. THIS SANDBOX IS NOT MEANT TO BE THE ULTIMATE SECURITY SOLUTION.
|
||||
|
||||
**YOU MUST TRUST THE REPO CONTRIBUTORS**
|
||||
|
||||
## Markdown templates
|
||||
|
||||
Markdown templates are a simple way to create notes
|
||||
|
||||
**Use Markdown templates when you want to:**
|
||||
|
||||
- Create simple, consistent note structures
|
||||
- Use basic variables and placeholders
|
||||
- Keep templates easy to read and modify
|
||||
|
||||
### Variables
|
||||
|
||||
Markdown templates can use all the variables available in [VS Code Snippets](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_variables).
|
||||
|
||||
In addition, you can also use variables provided by Foam:
|
||||
|
||||
| Name | Description |
|
||||
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `FOAM_SELECTED_TEXT` | Foam will fill it with selected text when creating a new note, if any text is selected. Selected text will be replaced with a wikilink to the new |
|
||||
| `FOAM_TITLE` | The title of the note. If used, Foam will prompt you to enter a title for the note. |
|
||||
| `FOAM_TITLE_SAFE` | The title of the note in a file system safe format. If used, Foam will prompt you to enter a title for the note unless `FOAM_TITLE` has already caused the prompt. |
|
||||
| `FOAM_SLUG` | The sluggified title of the note (using the default github slug method). If used, Foam will prompt you to enter a title for the note unless `FOAM_TITLE` has already caused the prompt. |
|
||||
| `FOAM_CURRENT_DIR` | The current editor's directory path. Resolves to the directory of the currently active file, or falls back to workspace root if no editor is active. Useful for creating notes in the current directory context. |
|
||||
| `FOAM_DATE_*` | `FOAM_DATE_YEAR`, `FOAM_DATE_MONTH`, `FOAM_DATE_WEEK`, `FOAM_DATE_DAY_ISO` etc. Foam-specific versions of [VS Code's datetime snippet variables](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_variables). Prefer these versions over VS Code's. |
|
||||
|
||||
### `FOAM_DATE_*` variables
|
||||
|
||||
Foam defines its own set of datetime variables that have a similar behaviour as [VS Code's datetime snippet variables](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_variables).
|
||||
|
||||
Supported variables include:
|
||||
|
||||
- `FOAM_DATE_YEAR`: 4-digit year (e.g. 2025)
|
||||
- `FOAM_DATE_MONTH`: 2-digit month (e.g. 09)
|
||||
- `FOAM_DATE_WEEK`: ISO 8601 week number (e.g. 37)
|
||||
- `FOAM_DATE_WEEK_YEAR`: the year of the ISO 8601 week number. The year that contains the Thursday of the current week, may vary from calendar year near Jan 1. Often used with `FOAM_DATE_WEEK`.
|
||||
- `FOAM_DATE_DAY_ISO`: ISO 8601 weekday number (1-7, where Monday=1, Sunday=7)
|
||||
- `FOAM_DATE_DATE`: 2-digit day of month (e.g. 15)
|
||||
- `FOAM_DATE_DAY_NAME`: Full weekday name (e.g. Monday)
|
||||
- `FOAM_DATE_DAY_NAME_SHORT`: Short weekday name (e.g. Mon)
|
||||
- `FOAM_DATE_HOUR`, `FOAM_DATE_MINUTE`, `FOAM_DATE_SECOND`, `FOAM_DATE_SECONDS_UNIX`, etc.
|
||||
|
||||
For example, `FOAM_DATE_YEAR` has the same behaviour as VS Code's `CURRENT_YEAR`, `FOAM_DATE_SECONDS_UNIX` has the same behaviour as `CURRENT_SECONDS_UNIX`, etc. `FOAM_DATE_DAY_ISO` returns the ISO weekday number (Monday=1, Sunday=7), which is useful for ISO week date formats like `2025-W37-5`.
|
||||
|
||||
By default, prefer using the `FOAM_DATE_` versions. The datetime used to compute the values will be the same for both `FOAM_DATE_` and VS Code's variables, with the exception of the creation notes using the daily note template.
|
||||
|
||||
For more nitty-gritty details about the supported date formats, [see here](https://github.com/foambubble/foam/blob/main/packages/foam-vscode/src/services/variable-resolver.ts).
|
||||
|
||||
#### Relative daily notes
|
||||
|
||||
When referring to daily notes, you can use the relative snippets (`/+1d`, `/tomorrow`, etc.). In these cases, the new notes will be created with the daily note template, but the datetime used should be the relative datetime, not the current datetime.
|
||||
By using the `FOAM_DATE_` versions of the variables, the correct relative date will populate the variables, instead of the current datetime.
|
||||
|
||||
For example, given this daily note template (`.foam/templates/daily-note.md`):
|
||||
|
||||
```markdown
|
||||
# $FOAM_DATE_YEAR-$FOAM_DATE_MONTH-$FOAM_DATE_DATE
|
||||
|
||||
## Here's what I'm going to do today
|
||||
|
||||
- Thing 1
|
||||
- Thing 2
|
||||
```
|
||||
|
||||
When the `/tomorrow` snippet is used, `FOAM_DATE_` variables will be populated with tomorrow's date, as expected.
|
||||
If instead you were to use the VS Code versions of these variables, they would be populated with today's date, not tomorrow's, causing unexpected behaviour.
|
||||
|
||||
When creating notes in any other scenario, the `FOAM_DATE_` values are computed using the same datetime as the VS Code ones, so the `FOAM_DATE_` versions can be used in all scenarios by default.
|
||||
|
||||
### Metadata
|
||||
|
||||
**Markdown templates** can also contain metadata about the templates themselves. The metadata is defined in YAML "Frontmatter" blocks within the templates.
|
||||
|
||||
| Name | Description |
|
||||
| ------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `filepath` | The filepath to use when creating the new note. If the filepath is a relative filepath, it is relative to the current workspace. |
|
||||
| `name` | A human readable name to show in the template picker. |
|
||||
| `description` | A human readable description to show in the template picker. |
|
||||
|
||||
Foam-specific variables (e.g. `$FOAM_TITLE`) can be used within template metadata. However, VS Code snippet variables are ([currently](https://github.com/foambubble/foam/pull/655)) not supported.
|
||||
|
||||
#### `filepath` attribute
|
||||
|
||||
It is possible to vary the `filepath` value based on the current date using the `FOAM_DATE_*` variables. This is especially useful for the [[daily-notes]] template if you wish to organize by years, months, etc. Below is an example of a daily-note template metadata section that will create new daily notes under the `journal/YEAR/MONTH-MONTH_NAME/` filepath. For example, when a note is created on November 15, 2022, a new file will be created at `C:\Users\foam_user\foam_notes\journal\2022\11-Nov\2022-11-15-daily-note.md`. This method also respects the creation of daily notes relative to the current date (i.e. `/+1d`).
|
||||
|
||||
```markdown
|
||||
---
|
||||
type: daily-note
|
||||
foam_template:
|
||||
description: Daily Note
|
||||
filepath: '/journal/$FOAM_DATE_YEAR/$FOAM_DATE_MONTH-$FOAM_DATE_MONTH_NAME_SHORT/$FOAM_DATE_YEAR-$FOAM_DATE_MONTH-$FOAM_DATE_DATE-daily-note.md'
|
||||
---
|
||||
|
||||
# $FOAM_DATE_YEAR-$FOAM_DATE_MONTH-$FOAM_DATE_DATE Daily Notes
|
||||
```
|
||||
|
||||
##### Creating notes in the current directory
|
||||
|
||||
To create notes in the same directory as your currently active file, use the `FOAM_CURRENT_DIR` variable in your template's `filepath`:
|
||||
|
||||
```markdown
|
||||
---
|
||||
foam_template:
|
||||
name: Current Directory Note
|
||||
filepath: '$FOAM_CURRENT_DIR/$FOAM_SLUG.md'
|
||||
---
|
||||
|
||||
# $FOAM_TITLE
|
||||
|
||||
$FOAM_SELECTED_TEXT
|
||||
```
|
||||
|
||||
**Best practices for filepath patterns:**
|
||||
|
||||
- **Explicit current directory:** `$FOAM_CURRENT_DIR/$FOAM_SLUG.md` - Creates notes in the current editor's directory
|
||||
- **Workspace root:** `/$FOAM_SLUG.md` - Always creates notes in workspace root
|
||||
- **Subdirectories:** `$FOAM_CURRENT_DIR/meetings/$FOAM_SLUG.md` - Creates notes in subdirectories relative to current location
|
||||
|
||||
The `FOAM_CURRENT_DIR` approach is recommended over relative paths (like `./file.md`) because it makes the template's behavior explicit and doesn't depend on configuration settings.
|
||||
|
||||
#### `name` and `description` attributes
|
||||
|
||||
These attributes provide a human readable name and description to be shown in the template picker (e.g. When a user uses the `Foam: Create New Note From Template` command):
|
||||
|
||||

|
||||
|
||||
#### Adding template metadata to an existing YAML Frontmatter block
|
||||
|
||||
If your template already has a YAML Frontmatter block, you can add the Foam template metadata to it.
|
||||
|
||||
Foam only supports adding the template metadata to _YAML_ Frontmatter blocks. If the existing Frontmatter block uses some other format (e.g. JSON), you will have to add the template metadata to its own YAML Frontmatter block.
|
||||
|
||||
Further, the template metadata must be provided as a [YAML block mapping](https://yaml.org/spec/1.2/spec.html#id2798057), with the attributes placed on the lines immediately following the `foam_template` line:
|
||||
|
||||
```yaml
|
||||
---
|
||||
existing_frontmatter: "Existing Frontmatter block"
|
||||
foam_template: # this is a YAML "Block" mapping ("Flow" mappings aren't supported)
|
||||
name: My Note Template # Attributes must be on the lines immediately following `foam_template`
|
||||
description: This is my note template
|
||||
filepath: `journal/$FOAM_TITLE.md`
|
||||
---
|
||||
This is the rest of the template
|
||||
```
|
||||
|
||||
#### Adding template metadata to its own YAML Frontmatter block
|
||||
|
||||
You can add the template metadata to its own YAML Frontmatter block at the start of the template:
|
||||
|
||||
```yaml
|
||||
---
|
||||
foam_template:
|
||||
name: My Note Template
|
||||
description: This is my note template
|
||||
filepath: 'journal/$FOAM_TITLE.md'
|
||||
---
|
||||
This is the rest of the template
|
||||
```
|
||||
|
||||
If the note already has a Frontmatter block, a Foam-specific Frontmatter block can be added to the start of the template. The Foam-specific Frontmatter block must always be placed at the very beginning of the file, and only whitespace can separate the two Frontmatter blocks.
|
||||
|
||||
```yaml
|
||||
---
|
||||
foam_template:
|
||||
name: My Note Template
|
||||
description: This is my note template
|
||||
filepath: 'journal/$FOAM_TITLE.md'
|
||||
---
|
||||
|
||||
---
|
||||
existing_frontmatter: 'Existing Frontmatter block'
|
||||
---
|
||||
This is the rest of the template
|
||||
```
|
||||
|
||||
[daily-notes]: daily-notes.md 'Daily Notes'
|
||||
@@ -1,41 +1,43 @@
|
||||
# Wikilinks
|
||||
|
||||
Wikilinks are the internal links that connect the files in your knowledge base. (Also called `[[MediaWiki]]` links).
|
||||
Wikilinks are internal links that connect files in your knowledge base using `[[double bracket]]` syntax.
|
||||
|
||||
## Creating and navigating wikilinks
|
||||
## Creating Wikilinks
|
||||
|
||||
To create a wikilink, type `[[` and then start typing the name of another note in your repo. Once the desired note is selected press the `tab` key to autocomplete it. For example: [[graph-visualization]].
|
||||
1. **Type `[[`** and start typing a note name
|
||||
2. **Select from autocomplete** and press `Tab`
|
||||
3. **Navigate** with `Ctrl+Click` (`Cmd+Click` on Mac) or `F12`
|
||||
4. **Create new notes** by clicking on non-existent wikilinks
|
||||
|
||||
`Cmd` + `Click` ( `Ctrl` + `Click` on Windows ) on wikilink to navigate to that note (`F12` also works while your cursor is on the wikilink). If the file doesn't exist it will be created in your workspace based on your default [[note-template]] settings.
|
||||
Example: [[graph-view]]
|
||||
|
||||
## Placeholders
|
||||
|
||||
You can also create a [[placeholder]].
|
||||
A placeholder is a wikilink that doesn't have a target file and a link to a placeholder is styled differently so you can easily tell them apart.
|
||||
They can still be helpful to highlight connections.
|
||||
Wikilinks to non-existent files create [[placeholder]] links, styled differently to show they need files created. They're useful for planning your knowledge structure.
|
||||
|
||||
Open the graph with `Foam: Show Graph` command, and look at the placeholder node.
|
||||
View placeholders in the graph with `Foam: Show Graph` command or in the `Placeholders` panel.
|
||||
|
||||
Remember, with `CTRL/CMD+click` on a wikilink you can navigate to the note, or create it (if the link is a placeholder).
|
||||
## Section Links
|
||||
|
||||
## Support for sections
|
||||
Link to specific sections using `[[note-name#Section Title]]` syntax. Foam provides autocomplete for section titles.
|
||||
|
||||
Foam supports autocompletion, navigation, embedding and diagnostics for note sections. Just use the standard wiki syntax of `[[resource#Section Title]]`.
|
||||
Examples:
|
||||
|
||||
## Markdown compatibility
|
||||
- External file: `[link text](other-file.md#section-name)`
|
||||
- Same document: `[link text](#section-name)`
|
||||
|
||||
The [Foam for VSCode](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode) extension automatically generates [[link-reference-definitions]] at the bottom of the file to make wikilinks compatible with other Markdown tools and parsers.
|
||||
## Markdown Compatibility
|
||||
|
||||
## Read more
|
||||
Foam can automatically generate [[link-reference-definitions]] at the bottom of files to make wikilinks compatible with standard Markdown processors.
|
||||
|
||||
- [[foam-file-format]]
|
||||
- [[note-templates]]
|
||||
- See [[link-reference-definition-improvements]] for further discussion on current problems and potential solutions.
|
||||
## Related
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[graph-visualization]: graph-visualization.md "Graph Visualization"
|
||||
[link-reference-definitions]: link-reference-definitions.md "Link Reference Definitions"
|
||||
[foam-file-format]: ../../dev/foam-file-format.md "Foam File Format"
|
||||
[note-templates]: note-templates.md "Note Templates"
|
||||
[link-reference-definition-improvements]: ../../dev/proposals/link-reference-definition-improvements.md "Link Reference Definition Improvements"
|
||||
[//end]: # "Autogenerated link references"
|
||||
- [[foam-file-format]] - Technical details
|
||||
- [[templates]] - Creating new notes
|
||||
- [[link-reference-definition-improvements]] - Current limitations
|
||||
|
||||
[graph-visualization]: graph-visualization.md 'Graph Visualization'
|
||||
[link-reference-definitions]: link-reference-definitions.md 'Link Reference Definitions'
|
||||
[foam-file-format]: ../../dev/foam-file-format.md 'Foam File Format'
|
||||
[note-templates]: note-templates.md 'Note Templates'
|
||||
[link-reference-definition-improvements]: ../../dev/proposals/link-reference-definition-improvements.md 'Link Reference Definition Improvements'
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
- [Frequently Asked Questions](#frequently-asked-questions)
|
||||
- [Links/Graphs/BackLinks don't work. How do I enable them?](#linksgraphsbacklinks-dont-work-how-do-i-enable-them)
|
||||
- [I don't want Foam enabled for all my workspaces](#i-dont-want-foam-enabled-for-all-my-workspaces)
|
||||
- [I want to publish the graph view to GitHub pages or Vercel](#i-want-to-publish-the-graph-view-to-github-pages-or-vercel)
|
||||
|
||||
## Links/Graphs/BackLinks don't work. How do I enable them?
|
||||
|
||||
@@ -13,10 +14,16 @@
|
||||
- Check the formatting rules for links on [[foam-file-format]] and [[wikilinks]]
|
||||
|
||||
## I don't want Foam enabled for all my workspaces
|
||||
Any extension you install in Visual Studio Code is enabled by default. Give the philosophy of Foam it works out of the box without doing any configuration upfront. In case you want to disable Foam for a specific workspace, or disable Foam by default and enable it for specific workspaces, it is advised to follow the best practices as [documented by Visual Studio Code](https://code.visualstudio.com/docs/editor/extension-marketplace#_manage-extensions)
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[recommended-extensions]: getting-started/recommended-extensions.md "Recommended Extensions"
|
||||
[foam-file-format]: ../dev/foam-file-format.md "Foam File Format"
|
||||
[wikilinks]: features/wikilinks.md "Wikilinks"
|
||||
[//end]: # "Autogenerated link references"
|
||||
Any extension you install in Visual Studio Code is enabled by default. Given the philosophy of Foam, it works out of the box without doing any configuration upfront. In case you want to disable Foam for a specific workspace, or disable Foam by default and enable it for specific workspaces, it is advised to follow the best practices as [documented by Visual Studio Code](https://code.visualstudio.com/docs/editor/extension-marketplace#_manage-extensions)
|
||||
|
||||
## I want to publish the graph view to GitHub pages or Vercel
|
||||
|
||||
If you want a different front-end look to your published foam and a way to see your graph view, we'd recommend checking out these templates:
|
||||
|
||||
- [foam-gatsby](https://github.com/mathieudutour/foam-gatsby-template) by [Mathieu Dutour](https://github.com/mathieudutour)
|
||||
- [foam-gatsby-kb](https://github.com/hikerpig/foam-template-gatsby-kb) by [hikerpig](https://github.com/hikerpig)
|
||||
|
||||
[recommended-extensions]: getting-started/recommended-extensions.md 'Recommended Extensions'
|
||||
[foam-file-format]: ../dev/foam-file-format.md 'Foam File Format'
|
||||
[wikilinks]: features/wikilinks.md 'Wikilinks'
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
# Creating New Notes
|
||||
|
||||
- Write out a new `[[wikilink]]` and `Cmd` + `Click` to create a new file and enter it.
|
||||
- For keyboard navigation, use the 'Follow Definition' key `F12` (or [remap the 'editor.action.revealDefinition' key binding](https://code.visualstudio.com/docs/getstarted/keybindings) to something more ergonomic)
|
||||
- `Cmd` + `Shift` + `P` (`Ctrl` + `Shift` + `P` for Windows), execute `Foam: Create Note` and enter a **Title Case Name** to create `Title Case Name.md`
|
||||
- Add a keyboard binding to make creating new notes easier. See [[commands]] for more info on this.
|
||||
- The [[note-templates]] used by this command can be customized.
|
||||
- You shouldn't worry too much about categorizing your notes. You can always [[search-for-notes]], and explore them using the [[graph-visualization]].
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[commands]: ../features/commands.md "Foam Commands"
|
||||
[note-templates]: ../features/note-templates.md "Note Templates"
|
||||
[search-for-notes]: ../recipes/search-for-notes.md "Search for Notes"
|
||||
[graph-visualization]: ../features/graph-visualization.md "Graph Visualization"
|
||||
[//end]: # "Autogenerated link references"
|
||||
209
docs/user/getting-started/first-workspace.md
Normal file
209
docs/user/getting-started/first-workspace.md
Normal file
@@ -0,0 +1,209 @@
|
||||
# Creating Your First Workspace
|
||||
|
||||
A Foam workspace is where all your notes, ideas, and knowledge live. Think of it as your digital garden where thoughts can grow and connect. This guide will help you set up a workspace that's organized, scalable, and tailored to your thinking style.
|
||||
|
||||
## Understanding Workspaces
|
||||
|
||||
A Foam workspace is simply a folder containing **Markdown files** (`.md`) - your actual notes.
|
||||
|
||||
Optionally it can contain:
|
||||
|
||||
- **Configuration files** - VS Code settings and Foam preferences
|
||||
- **Assets** - images, attachments, and other media
|
||||
- **Templates** - reusable note structures
|
||||
|
||||
### Single vs. Multiple Workspaces
|
||||
|
||||
**Recommended: Single Workspace**
|
||||
|
||||
- Keep all your knowledge in one place
|
||||
- Better link discovery and graph visualization
|
||||
- Easier to maintain and backup
|
||||
- Follows the "unified knowledge base" principle
|
||||
|
||||
**Deprecated: Multiple Workspaces** (deprecated - advanced users only)
|
||||
|
||||
- Separate professional and personal knowledge
|
||||
- Isolate sensitive information
|
||||
- Different workflows for different projects
|
||||
|
||||
Multiple workspaces are to be considered deprecated at this point, and might become unsupported in the future.
|
||||
You can simulate a complex workspace by using file/folder links.
|
||||
|
||||
## Method 1: Using the Foam Template (Recommended)
|
||||
|
||||
The easiest way to start is with our pre-configured template:
|
||||
|
||||
### Step 1: Create from Template
|
||||
|
||||
1. **Visit** [github.com/foambubble/foam-template](https://github.com/foambubble/foam-template)
|
||||
2. **Click "Use this template"** (you'll need a GitHub account)
|
||||
3. **Name your repository** (e.g., "john-knowledge-base", "my-second-brain")
|
||||
4. **Choose visibility:**
|
||||
- **Private** - for personal notes (recommended)
|
||||
- **Public** - if you want to share your knowledge openly
|
||||
|
||||
### Step 2: Clone Locally
|
||||
|
||||
```bash
|
||||
git clone https://github.com/yourusername/your-repo-name.git
|
||||
cd your-repo-name
|
||||
```
|
||||
|
||||
### Step 3: Open in VS Code
|
||||
|
||||
1. **Launch VS Code**
|
||||
2. **File > Open Folder**
|
||||
3. **Select your cloned repository folder**
|
||||
|
||||
## Method 2: Start from Scratch
|
||||
|
||||
For a minimal setup:
|
||||
|
||||
1. **Create a new folder** on your computer
|
||||
2. **Open the folder** in VS Code (`File > Open Folder`)
|
||||
|
||||
That's all, you can start working with your markdown files and Foam will take care of the rest.
|
||||
|
||||
## Ideas for your knowledge base
|
||||
|
||||
### 1. Customize Your Settings
|
||||
|
||||
Review and adjust `.vscode/settings.json` based on your preferences:
|
||||
|
||||
- **Daily notes location** - where your daily notes are stored
|
||||
- **Image handling** - how pasted images are organized
|
||||
- **Link format** - with or without file extensions
|
||||
|
||||
### 2. Set Up Your Inbox
|
||||
|
||||
Create `inbox.md` as your default capture location:
|
||||
|
||||
```markdown
|
||||
# Inbox
|
||||
|
||||
Quick notes and ideas go here before being organized.
|
||||
|
||||
## Today's Captures
|
||||
|
||||
-
|
||||
|
||||
## To Process
|
||||
|
||||
-
|
||||
|
||||
## Ideas
|
||||
|
||||
-
|
||||
```
|
||||
|
||||
### 3. Create Core Structure Notes
|
||||
|
||||
## Workspace Organization Strategies
|
||||
|
||||
Establish your main organizational notes.
|
||||
You can use any methodology, Foam is not opinionated.
|
||||
|
||||
The only recommendation is to get started, you can improve later.
|
||||
|
||||
The two main methods adopted by users are [PARA](https://fortelabs.com/blog/para/) and [Zettelkasten](https://zettelkasten.de/overview/).
|
||||
|
||||
### The PARA Method
|
||||
|
||||
Organize around four categories:
|
||||
|
||||
- **Projects** - Things with deadlines
|
||||
- **Areas** - Ongoing responsibilities
|
||||
- **Resources** - Future reference materials
|
||||
- **Archive** - Inactive items
|
||||
|
||||
### Zettelkasten Approach
|
||||
|
||||
Number-based system for atomic ideas:
|
||||
|
||||
- **Permanent notes** - `202501251030-idea-title.md`
|
||||
- **Literature notes** - `book-author-year.md`
|
||||
- **Index notes** - `index-topic.md`
|
||||
|
||||
### 4. Configure Daily Notes
|
||||
|
||||
Daily notes are perfect for:
|
||||
|
||||
- Daily planning and reflection
|
||||
- Meeting notes
|
||||
- Journal entries
|
||||
- Quick captures
|
||||
|
||||
Test your daily notes setup:
|
||||
|
||||
1. **Press `Ctrl+Shift+P` / `Cmd+Shift+P`**
|
||||
2. **Type "Foam: Open Daily Note"**
|
||||
3. **Verify the note is created in the right location**
|
||||
|
||||
Alternatively you can press `Alt+D` to open today's daily note, or `Alt+H` to open another day's daily note.
|
||||
Use the `.foam/templates/daily-note.md` to customize your daily note.
|
||||
|
||||
## Best Practices for New Workspaces
|
||||
|
||||
### 1. Start Small
|
||||
|
||||
- Begin with just a few notes
|
||||
- Don't over-organize initially
|
||||
- Let structure emerge naturally
|
||||
|
||||
### 2. Use Templates
|
||||
|
||||
- Create templates for common note types
|
||||
- Maintain consistency across similar notes
|
||||
- Save time on repetitive formatting
|
||||
|
||||
### 3. Link Early and Often
|
||||
|
||||
- Use `[[wikilinks]]` liberally
|
||||
- Don't worry about creating "perfect" links
|
||||
- Foam handles broken links gracefully
|
||||
|
||||
### 4. Regular Reviews
|
||||
|
||||
- Weekly workspace cleanup
|
||||
- Archive completed projects
|
||||
- Identify missing connections
|
||||
|
||||
## Syncing and Backup
|
||||
|
||||
Foam works on simple files, you can add whatever backup method you prefer on top of it.
|
||||
|
||||
### Git
|
||||
|
||||
Your workspace is a Git repository:
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Add new notes and ideas"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
You can also use other VS Code extensions to manage the git synching if that's helpful.
|
||||
|
||||
### Alternative Sync Methods
|
||||
|
||||
- **Cloud storage** - Dropbox, OneDrive, Google Drive
|
||||
- **Local backup** - Time Machine, File History
|
||||
- **Manual export** - Regular ZIP backups
|
||||
|
||||
## What's Next?
|
||||
|
||||
With your workspace set up, you're ready to:
|
||||
|
||||
1. **[Learn note-taking fundamentals](note-taking-in-foam.md)** - Master Markdown and writing effective notes
|
||||
2. **[Explore navigation](navigation.md)** - Connect your thoughts with wikilinks
|
||||
3. **[Discover the graph view](../features/graph-view.md)** - Visualize your knowledge network
|
||||
4. **[Set up templates](../features/templates.md)** - Standardize your note creation process
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you encounter setup issues:
|
||||
|
||||
- Check the [Installation Guide](installation.md) for prerequisites
|
||||
- Visit the [FAQ](../faq.md) for common workspace problems
|
||||
- Join the [Foam Community Discord](https://foambubble.github.io/join-discord/w)
|
||||
@@ -1,43 +1,256 @@
|
||||
# Getting started with VS Code
|
||||
# Using Foam with VS Code Features
|
||||
|
||||
VS Code is a powerful text editor, hidden behind a simple interface.
|
||||
Foam builds on Visual Studio Code's powerful editing capabilities, integrating seamlessly with VS Code's native features to create a comprehensive knowledge management experience. This guide explores how to leverage VS Code's built-in functionality alongside Foam.
|
||||
|
||||
### Keyboard shortcuts
|
||||
|
||||
VS Code supports various **keyboard shortcuts**, the most important for us are:
|
||||
|
||||
| Shortcut | Action |
|
||||
| ------------- | ---------------------------- |
|
||||
| `cmd+N` | create a new file |
|
||||
| `cmd+S` | save the current file |
|
||||
| `cmd+O` | open a file |
|
||||
| `cmd+P` | use quickpick to open a file |
|
||||
| `cmd+shift+P` | invoke a command (see below) |
|
||||
| Shortcut | Action |
|
||||
| ------------- | ----------------------------- |
|
||||
| `cmd+N` | create a new file |
|
||||
| `cmd+S` | save the current file |
|
||||
| `cmd+O` | open a file |
|
||||
| `cmd+P` | use quickpick to open a file |
|
||||
| `alt+D` | open the daily note for today |
|
||||
| `alt+H` | open the daily note for a day |
|
||||
| `cmd+shift+P` | invoke a command (see below) |
|
||||
|
||||
For more information, see the [VS Code keyboard cheat sheets](https://code.visualstudio.com/docs/getstarted/keybindings#_keyboard-shortcuts-reference), where you can also see how to customize your keybindings.
|
||||
|
||||
## Commands
|
||||
### Commands
|
||||
|
||||
Commands make VS Code extremely powerful.
|
||||
|
||||
To invoke a command, press `cmd+shift+P` and select the command you want to execute.
|
||||
For example, to see the Foam graph:
|
||||
|
||||
- press `cmd+shift+P`
|
||||
- press `cmd+shift+P` to open the command bar
|
||||
- start typing `show graph`
|
||||
- select the `Foam: Show Graph` command
|
||||
|
||||
And watch the magic unfold.
|
||||
|
||||
To see all foam commands, type "foam" in the command bar.
|
||||
For more information on commands, see [commands on the VS Code site](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).
|
||||
|
||||
If you want to learn more about VS Code, check out their [website](https://code.visualstudio.com/docs#first-steps).
|
||||
|
||||
## Panels
|
||||
### Panels
|
||||
|
||||
You can see a few panels on the left, including:
|
||||
Foam integrates with VS Code panels to provide insights into individual notes and the whole knowledge base.
|
||||
|
||||
- `Outline`: this panel shows you the structure of the file based on the headings
|
||||
- `Tag Explorer`: This shows you the tags in your workspace, see [[tags-and-tag-explorer]] for more information on tags
|
||||
- **`Foam: links`**: Shows all notes that link to and from the currently active note, helping you understand connections and navigate your knowledge graph
|
||||
- **`Foam: Orphaned Notes`**: Displays notes that have no incoming or outgoing links, helping you identify isolated content that might need better integration
|
||||
- **`Tag Explorer`**: Shows all tags used across your workspace in a hierarchical view, see [[tags]] for more information on tags
|
||||
- **`Foam: Graph`**: Visual representation of your note connections (also available as a separate graph view)
|
||||
|
||||
## Settings
|
||||
### Styling and Themes
|
||||
|
||||
To view or change the settings in VS Code, press `cmd+,`
|
||||
VS Code is very configurable when it comes to themes and style. Find your ideal set up by running the command `Color Theme`.
|
||||
For more information see the [VS Code documentation](https://code.visualstudio.com/docs/configure/themes).
|
||||
|
||||
### Multi-Cursor Editing
|
||||
|
||||
Edit multiple locations simultaneously for efficient note management:
|
||||
|
||||
**Basic Multi-Cursor:**
|
||||
|
||||
- `Alt+Click` / `Option+Click` - Add cursor at click location
|
||||
- `Ctrl+Alt+Down` / `Cmd+Option+Down` - Add cursor below
|
||||
- `Ctrl+Alt+Up` / `Cmd+Option+Up` - Add cursor above
|
||||
- `Ctrl+D` / `Cmd+D` - Select next occurrence of word
|
||||
- `Ctrl+Shift+L` / `Cmd+Shift+L` - Select all occurrences
|
||||
|
||||
**Bulk wikilink creation:**
|
||||
|
||||
1. **Select a word** (e.g., "Python")
|
||||
2. **Press `Ctrl+Shift+L`** to select all occurrences
|
||||
3. **Type `[[]]`** to wrap all instances
|
||||
4. **Arrow key** to position cursor inside brackets
|
||||
|
||||
### Find and Replace
|
||||
|
||||
Powerful search and replace for note maintenance:
|
||||
|
||||
**Basic Find/Replace:**
|
||||
|
||||
- `Ctrl+F` / `Cmd+F` - Find in current file
|
||||
- `Ctrl+H` / `Cmd+H` - Replace in current file
|
||||
- `Ctrl+Shift+F` / `Cmd+Shift+F` - Find across workspace
|
||||
- `Ctrl+Shift+H` / `Cmd+Shift+H` - Replace across workspace
|
||||
|
||||
### Text Folding
|
||||
|
||||
Organize long notes with collapsible sections:
|
||||
|
||||
**Folding Controls:**
|
||||
|
||||
- **Click fold icons** in the gutter next to headings
|
||||
- `Ctrl+Shift+[` / `Cmd+Option+[` - Fold current section
|
||||
- `Ctrl+Shift+]` / `Cmd+Option+]` - Unfold current section
|
||||
- `Ctrl+K Ctrl+0` / `Cmd+K Cmd+0` - Fold all
|
||||
- `Ctrl+K Ctrl+J` / `Cmd+K Cmd+J` - Unfold all
|
||||
|
||||
## File Management
|
||||
|
||||
### Explorer Integration
|
||||
|
||||
Leverage VS Code's file explorer for note organization:
|
||||
|
||||
**File Operations:**
|
||||
|
||||
- **Drag and drop** files to reorganize
|
||||
- **Right-click context menus** for quick actions
|
||||
- **New file/folder** creation with shortcuts
|
||||
- **Bulk selection** with Ctrl+Click / Cmd+Click
|
||||
|
||||
**Quick File Actions:**
|
||||
|
||||
- `F2` - Rename file (Foam updates links automatically)
|
||||
- `Delete` - Move to trash
|
||||
- `Ctrl+C` / `Cmd+C` then `Ctrl+V` / `Cmd+V` - Copy/paste files
|
||||
- **Right-click → Reveal in Explorer/Finder** - Open in file system
|
||||
|
||||
### Quick Open
|
||||
|
||||
Rapid file navigation for large knowledge bases:
|
||||
|
||||
**Quick Open Commands:**
|
||||
|
||||
- `Ctrl+P` / `Cmd+P` - Go to file
|
||||
- `Ctrl+Shift+O` / `Cmd+Shift+O` - Go to symbol (headings in Markdown)
|
||||
- `Ctrl+T` / `Cmd+T` - Go to symbol in workspace
|
||||
- `Ctrl+G` / `Cmd+G` - Go to line number
|
||||
|
||||
**Search Patterns:**
|
||||
|
||||
```
|
||||
# Go to File (Ctrl+P)
|
||||
machine # Finds "machine-learning.md"
|
||||
proj alpha # Finds "project-alpha.md"
|
||||
daily/2025 # Finds files in daily/2025 folder
|
||||
|
||||
# Go to Symbol (Ctrl+Shift+O)
|
||||
@introduction # Jump to "Introduction" heading
|
||||
@#setup # Jump to "Setup" heading
|
||||
:50 # Go to line 50
|
||||
```
|
||||
|
||||
## Search and Discovery
|
||||
|
||||
### Global Search
|
||||
|
||||
Find content across your entire knowledge base:
|
||||
|
||||
**Search Interface (`Ctrl+Shift+F` / `Cmd+Shift+F`):**
|
||||
|
||||
- **Search box** - Enter your query
|
||||
- **Replace box** - Toggle with replace arrow
|
||||
- **Include/Exclude patterns** - Filter by file types or folders
|
||||
- **Match case** - Case-sensitive search
|
||||
- **Match whole word** - Exact word matching
|
||||
- **Use regular expression** - Advanced pattern matching
|
||||
|
||||
### Timeline View
|
||||
|
||||
Track changes to your notes over time:
|
||||
|
||||
**Accessing Timeline:**
|
||||
|
||||
1. **Open Explorer panel**
|
||||
2. **Expand "Timeline" section** at bottom
|
||||
3. **Select a file** to see its change history
|
||||
4. **Click timeline entries** to see diff views
|
||||
|
||||
**Timeline Features:**
|
||||
|
||||
- **Git commits** show when notes were changed
|
||||
- **File saves** track editing sessions
|
||||
- **Diff views** highlight what changed
|
||||
- **Restore points** for recovering previous versions
|
||||
|
||||
### Outline View
|
||||
|
||||
Navigate long notes with hierarchical structure:
|
||||
|
||||
**Outline Panel:**
|
||||
|
||||
1. **Enable in Explorer** (expand "Outline" section)
|
||||
2. **Shows heading hierarchy** for current note
|
||||
3. **Click headings** to jump to sections
|
||||
4. **Collapse/expand** sections in outline
|
||||
|
||||
## Version Control Integration
|
||||
|
||||
### Git Integration
|
||||
|
||||
Track changes to your knowledge base:
|
||||
|
||||
**Source Control Panel:**
|
||||
|
||||
- **View changes** - See modified files
|
||||
- **Stage changes** - Click `+` to stage files
|
||||
- **Commit changes** - Enter message and commit
|
||||
- **Sync changes** - Push/pull from remote
|
||||
|
||||
**Git Workflow for Notes:**
|
||||
|
||||
1. **Write and edit** your notes
|
||||
2. **Review changes** in Source Control panel
|
||||
3. **Stage relevant files** for commit
|
||||
4. **Write meaningful commit message**
|
||||
5. **Commit and push** to backup/share
|
||||
|
||||
**Useful Git Features:**
|
||||
|
||||
- **Diff view** - See exactly what changed
|
||||
- **File history** - Track note evolution over time
|
||||
- **Branch management** - Experiment with different organization approaches
|
||||
- **Merge conflicts** - Resolve when collaborating
|
||||
|
||||
## Markdown Features
|
||||
|
||||
### Preview Integration
|
||||
|
||||
View formatted notes alongside editing:
|
||||
|
||||
**Preview Commands:**
|
||||
|
||||
- `Ctrl+Shift+V` / `Cmd+Shift+V` - Open preview
|
||||
- `Ctrl+K V` / `Cmd+K V` - Open preview to side
|
||||
- **Preview lock** - Pin preview to specific file
|
||||
|
||||
**Diagrams (with Mermaid extension):**
|
||||
|
||||
````markdown
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Foam Workspace] --> B[Notes]
|
||||
A --> C[Templates]
|
||||
A --> D[Assets]
|
||||
B --> E[Wikilinks]
|
||||
B --> F[Tags]
|
||||
E --> G[Graph View]
|
||||
```
|
||||
````
|
||||
|
||||
## Extension Ecosystem
|
||||
|
||||
Extend Foam's capabilities with complementary extensions.
|
||||
Look for them in the [VS Code Marketplace](https://marketplace.visualstudio.com/).
|
||||
|
||||
## What's Next?
|
||||
|
||||
With VS Code mastery, explore advanced Foam topics:
|
||||
|
||||
1. **[[recommended-extensions]]** - See complementary extensions to improve your note taking experience
|
||||
2. **[[publishing]]** - Share your knowledge base
|
||||
|
||||
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[tags]: ../features/tags.md "Tags"
|
||||
[recommended-extensions]: recommended-extensions.md "Recommended Extensions"
|
||||
[publishing]: ../publishing/publishing.md "Publishing pages"
|
||||
[//end]: # "Autogenerated link references"
|
||||
|
||||
79
docs/user/getting-started/installation.md
Normal file
79
docs/user/getting-started/installation.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Installation
|
||||
|
||||
Getting started with Foam is straightforward. This guide will walk you through installing everything you need to begin your knowledge management journey.
|
||||
|
||||
## Step 1: Install Visual Studio Code
|
||||
|
||||
Foam is built on VS Code, Microsoft's free, open-source code editor. You can download it at https://code.visualstudio.com/
|
||||
|
||||
### Why VS Code?
|
||||
|
||||
VS Code provides:
|
||||
|
||||
- Excellent Markdown editing capabilities
|
||||
- Rich extension ecosystem
|
||||
- Cross-platform compatibility
|
||||
- Integrated terminal and Git support
|
||||
- Customizable interface and shortcuts
|
||||
|
||||
To learn more about using VS Code with Foam, check [[get-started-with-vscode]]
|
||||
|
||||
## Step 2: Install the Foam Extension
|
||||
|
||||
The Foam extension adds knowledge management superpowers to VS Code.
|
||||
|
||||
1. **Open VS Code**
|
||||
2. **Click the Extensions icon** in the sidebar (or press `Ctrl+Shift+X` / `Cmd+Shift+X`)
|
||||
3. **Search for "Foam"** in the extensions marketplace
|
||||
4. **Click "Install"** on the official Foam extension by Foam Team
|
||||
5. **Reload VS Code** when prompted
|
||||
|
||||
### What the Foam Extension Provides
|
||||
|
||||
- Wikilink auto-completion and navigation
|
||||
- Backlink discovery and panel
|
||||
- Graph visualization
|
||||
- Powerful note template engine
|
||||
- Daily notes functionality
|
||||
|
||||
## Step 3: Install Recommended Extensions
|
||||
|
||||
While Foam works on its own, it is focused on the networking aspect of your notes. You might want to install additional extensions to improve the editing experience or the functionality of your notes.
|
||||
|
||||
### Useful Extensions
|
||||
|
||||
- **Markdown All in One** - Rich Markdown editing features. Highly recommended.
|
||||
|
||||
Other extensions:
|
||||
|
||||
- **Spell Right** - Spell checking for your notes
|
||||
- **Paste Image** - Easily insert images from clipboard
|
||||
- **Todo Tree** - Track TODO items across your workspace
|
||||
|
||||
## What's Next?
|
||||
|
||||
Now that Foam is installed, you're ready to:
|
||||
|
||||
1. **[[first-workspace]]** - Set up your knowledge base structure
|
||||
2. **[[get-started-with-vscode]]** - Learn how to use VS Code for note taking
|
||||
3. **[[note-taking-in-foam]]** - Write your first Markdown notes
|
||||
4. **[[navigation]]** - Connect your thoughts with wikilinks
|
||||
5. **[[graph-view]]** - Visualize your knowledge network
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you encounter issues:
|
||||
|
||||
- Check the [[frequently-asked-questions]] for common problems
|
||||
- Visit the [Foam Community Discord](https://foambubble.github.io/join-discord/w)
|
||||
- Browse [GitHub Issues](https://github.com/foambubble/foam/issues) for known problems
|
||||
- Ask questions in [GitHub Discussions](https://github.com/foambubble/foam/discussions)
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[get-started-with-vscode]: get-started-with-vscode.md "Using Foam with VS Code Features"
|
||||
[first-workspace]: first-workspace.md "Creating Your First Workspace"
|
||||
[note-taking-in-foam]: note-taking-in-foam.md "Note-Taking in Foam"
|
||||
[navigation]: navigation.md "Navigation in Foam"
|
||||
[graph-view]: ../features/graph-view.md "Graph Visualization"
|
||||
[frequently-asked-questions]: ../frequently-asked-questions.md "Frequently Asked Questions"
|
||||
[//end]: # "Autogenerated link references"
|
||||
139
docs/user/getting-started/navigation.md
Normal file
139
docs/user/getting-started/navigation.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# Navigation in Foam
|
||||
|
||||
Navigation is where Foam truly shines. Unlike traditional file systems or notebooks, Foam lets you move through your knowledge by following connections between ideas. This guide will teach you how to navigate efficiently using wikilinks, backlinks, and other powerful features.
|
||||
|
||||
_[📹 Watch: Mastering navigation in Foam]_
|
||||
|
||||
## Understanding Wikilinks
|
||||
|
||||
Wikilinks are the backbone of Foam navigation. They connect your thoughts and let you jump between related concepts instantly.
|
||||
|
||||
### Basic Wikilink Syntax
|
||||
|
||||
```markdown
|
||||
I'm learning about [[Machine Learning]] and its applications in [[Data Science]].
|
||||
|
||||
This reminds me of my notes on [[Python Programming]] from yesterday.
|
||||
```
|
||||
|
||||
When you type `[[`, Foam shows you a list of existing notes to link to. If the note doesn't exist, Foam creates a placeholder that you can click to create the note later.
|
||||
|
||||
### Wikilink Variations
|
||||
|
||||
**Link to a specific heading:**
|
||||
|
||||
```markdown
|
||||
See the [[Project Management#Risk Assessment]] section for details.
|
||||
```
|
||||
|
||||
**Link to a specific block:**
|
||||
|
||||
```markdown
|
||||
See the [[Project Management#^block-id]] paragraph for details.
|
||||
```
|
||||
|
||||
**Link with alias:**
|
||||
|
||||
```markdown
|
||||
According to [[Einstein, Albert|Einstein]], imagination is more important than knowledge.
|
||||
```
|
||||
|
||||
### Autocomplete and Link Assistance
|
||||
|
||||
Foam provides intelligent autocomplete when creating links:
|
||||
|
||||
1. **Type `[[`** - Foam shows a dropdown of existing notes
|
||||
2. **Start typing** - The list filters to matching notes
|
||||
3. **Use arrow keys** to navigate suggestions
|
||||
4. **Press Enter** to insert the selected link
|
||||
|
||||
## The Foam Graph
|
||||
|
||||
For a visual overview of your knowledge base, Foam offers a [[graph-view]]. This feature renders your notes as nodes and the links between them as connections, creating an interactive map of your thoughts.
|
||||
|
||||
_[📹 Watch: Navigation with the Foam Graph]_
|
||||
|
||||
### Using the Graph
|
||||
|
||||
1. **Open the Command Palette** (`Ctrl+Shift+P` / `Cmd+Shift+P`)
|
||||
2. **Run the "Foam: Show Graph" command**
|
||||
3. The graph will open in a new panel. You can:
|
||||
|
||||
- **Click on a node** to navigate to that note.
|
||||
- **Pan and zoom** to explore different areas of your knowledge base.
|
||||
- **See how ideas cluster** and identify central concepts.
|
||||
|
||||
## Backlinks: The Power of Reverse Navigation
|
||||
|
||||
Backlinks show you which notes reference the current note. This creates a web of knowledge where ideas naturally connect.
|
||||
|
||||
### Viewing Backlinks
|
||||
|
||||
1. **Open any note**
|
||||
2. **Look for the "Connections" panel** in the sidebar
|
||||
3. **See all notes that link to your current note**
|
||||
4. **Click any backlink** to jump to that note
|
||||
|
||||
## Quick Navigation Features
|
||||
|
||||
### Command Palette Navigation
|
||||
|
||||
Press `Ctrl+Shift+P` / `Cmd+Shift+P` and try these commands:
|
||||
|
||||
- **"Foam: Open Random Note"** - Discover forgotten knowledge
|
||||
- **"Foam: Open Daily Note"** - Quick access to today's notes
|
||||
- **"Go to File"** (`Ctrl+P` / `Cmd+P`) - Fast file opening
|
||||
- **"Go to Symbol"** (`Ctrl+Shift+O` / `Cmd+Shift+O`) - Jump to headings within a note
|
||||
|
||||
### File Explorer Integration
|
||||
|
||||
The VS Code file explorer shows your note structure:
|
||||
|
||||
- **Click any `.md` file** to open it
|
||||
- **Use the search box** to filter files
|
||||
- **Right-click** for context menus (rename, delete, etc.)
|
||||
|
||||
Foam also supports the Note Explorer, which is like the file explorer, but centered around the Foam metadata.
|
||||
|
||||
### Quick Open
|
||||
|
||||
Press `Ctrl+P` / `Cmd+P` and start typing:
|
||||
|
||||
- **File names** - `machine` finds "machine-learning.md"
|
||||
- **Partial paths** - `daily/2025` finds daily notes from 2025
|
||||
- **Recent files** - Empty search shows recently opened files
|
||||
|
||||
## Link Management and Maintenance
|
||||
|
||||
### Finding Broken Links - Placeholders
|
||||
|
||||
In Foam broken links are considered placeholders for future notes.
|
||||
Placeholders (references to non-existent notes) appear differently:
|
||||
|
||||
- In editor: `[[missing-note]]` will be highlighted a different color
|
||||
- In preview: Shows as regular text or with special styling
|
||||
|
||||
Clicking on a placeholder in the editor will create the corresponding note.
|
||||
|
||||
**To find all placeholders:**
|
||||
|
||||
You can find placeholders by looking at the `Placeholders` treeview.
|
||||
|
||||
### Renaming and Moving Notes
|
||||
|
||||
When you rename a note file:
|
||||
|
||||
1. **Use VS Code's rename function** (`F2` key)
|
||||
2. **Foam automatically updates** all links to that note
|
||||
3. **Check the "Problems" panel** for any issues
|
||||
|
||||
Currently you cannot rename whole folders.
|
||||
|
||||
## What's Next?
|
||||
|
||||
With navigation mastered, you're ready to:
|
||||
|
||||
1. **[Explore the graph view](../features/graph-view.md)** - Visualize your knowledge network
|
||||
2. **[Learn about backlinks](../features/backlinking.md)** - Master bidirectional linking
|
||||
3. **[Set up templates](../features/templates.md)** - Standardize your note creation
|
||||
4. **[Use tags effectively](../features/tags.md)** - Add another layer of organization
|
||||
238
docs/user/getting-started/note-taking-in-foam.md
Normal file
238
docs/user/getting-started/note-taking-in-foam.md
Normal file
@@ -0,0 +1,238 @@
|
||||
# Note-Taking in Foam
|
||||
|
||||
Effective note-taking is the foundation of any knowledge management system. In Foam, you'll write notes in Markdown, a simple and powerful format that's both human-readable and widely supported. This guide will teach you everything you need to know about writing great notes in Foam.
|
||||
|
||||
## Markdown Basics
|
||||
|
||||
Markdown is a lightweight markup language that uses simple syntax to format text. Here are the essentials:
|
||||
|
||||
### Headings
|
||||
|
||||
```markdown
|
||||
# Heading 1 (Main Title)
|
||||
|
||||
## Heading 2 (Major Section)
|
||||
|
||||
### Heading 3 (Subsection)
|
||||
|
||||
#### Heading 4 (Minor Section)
|
||||
```
|
||||
|
||||
### Text Formatting
|
||||
|
||||
```markdown
|
||||
**Bold text**
|
||||
_Italic text_
|
||||
**_Bold and italic_**
|
||||
~~Strikethrough~~
|
||||
`Inline code`
|
||||
```
|
||||
|
||||
### Lists
|
||||
|
||||
```markdown
|
||||
## Unordered Lists
|
||||
|
||||
- First item
|
||||
- Second item
|
||||
- Nested item
|
||||
- Another nested item
|
||||
|
||||
## Ordered Lists
|
||||
|
||||
1. First step
|
||||
2. Second step
|
||||
1. Sub-step
|
||||
2. Another sub-step
|
||||
```
|
||||
|
||||
### Links and Images
|
||||
|
||||
```markdown
|
||||
[External link](https://example.com)
|
||||

|
||||
```
|
||||
|
||||
### Code Blocks
|
||||
|
||||
````markdown
|
||||
```javascript
|
||||
function greet(name) {
|
||||
return `Hello, ${name}!`;
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
### Tables
|
||||
|
||||
```markdown
|
||||
| Column 1 | Column 2 | Column 3 |
|
||||
| -------- | -------- | -------- |
|
||||
| Data 1 | Data 2 | Data 3 |
|
||||
| Data 4 | Data 5 | Data 6 |
|
||||
```
|
||||
|
||||
### Quotes and Dividers
|
||||
|
||||
```markdown
|
||||
> This is a quote or important note
|
||||
> It can span multiple lines
|
||||
|
||||
---
|
||||
|
||||
Use three dashes for horizontal dividers
|
||||
```
|
||||
|
||||
_[📹 Watch: Markdown syntax essentials for note-taking]_
|
||||
|
||||
## Foam-Specific Features
|
||||
|
||||
Beyond standard Markdown, Foam adds several powerful features:
|
||||
|
||||
### Wikilinks
|
||||
|
||||
Connect your notes with double brackets:
|
||||
|
||||
```markdown
|
||||
I'm reading about [[Project Management]] and its relationship to [[Personal Productivity]].
|
||||
|
||||
This connects to [[2025-01-25-daily-note]] where I first had this insight.
|
||||
```
|
||||
|
||||
### Note Embedding
|
||||
|
||||
Include content from other notes via [[embeds]]:
|
||||
|
||||
```markdown
|
||||
![[Project Management#Key Principles]]
|
||||
|
||||
This embeds the "Key Principles" section from the Project Management note.
|
||||
```
|
||||
|
||||
### Tags
|
||||
|
||||
Organize your content with [[tags]]:
|
||||
|
||||
```markdown
|
||||
#productivity #learning #foam
|
||||
|
||||
Tags can be anywhere in your note and help with organization and filtering.
|
||||
```
|
||||
|
||||
Use nested tags for better organization:
|
||||
|
||||
```markdown
|
||||
#work/projects/website
|
||||
#learning/programming/javascript
|
||||
#personal/health/exercise
|
||||
```
|
||||
|
||||
Those tags will show as a tree structure in the [Tag Explorer](../features/tags.md)
|
||||
|
||||
### Note Properties (YAML Front Matter)
|
||||
|
||||
Add metadata to your notes:
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: 'Advanced Note-Taking Strategies'
|
||||
tags: [productivity, learning, methods]
|
||||
created: 2025-01-25
|
||||
modified: 2025-01-25
|
||||
status: draft
|
||||
---
|
||||
|
||||
# Advanced Note-Taking Strategies
|
||||
|
||||
Your note content goes here...
|
||||
```
|
||||
|
||||
## Writing Effective Notes
|
||||
|
||||
### The Atomic Principle
|
||||
|
||||
Each note should focus on one concept or idea:
|
||||
|
||||
**Good Example:**
|
||||
|
||||
```markdown
|
||||
# The Feynman Technique
|
||||
|
||||
A learning method where you explain a concept in simple terms as if teaching it to someone else.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Choose a topic to learn
|
||||
2. Explain it in simple terms
|
||||
3. Identify gaps in understanding
|
||||
4. Simplify and use analogies
|
||||
|
||||
## Why It Works
|
||||
|
||||
- Forces active engagement with material
|
||||
- Reveals knowledge gaps quickly
|
||||
- Improves retention through teaching
|
||||
|
||||
Related: [[Active Learning]] [[Study Methods]]
|
||||
```
|
||||
|
||||
**Avoid:**
|
||||
Mixing multiple unrelated concepts in one note.
|
||||
|
||||
### Use Descriptive Titles
|
||||
|
||||
Your note titles should clearly indicate the content:
|
||||
|
||||
**Good:** `REST API Design Principles`
|
||||
**Good:** `Meeting Notes - Product Roadmap Review 2025-01-25`
|
||||
**Avoid:** `Stuff I Learned Today`
|
||||
**Avoid:** `Notes`
|
||||
|
||||
### Link Generously
|
||||
|
||||
Don't hesitate to create links, even to notes that don't exist yet:
|
||||
|
||||
```markdown
|
||||
# Machine Learning Fundamentals
|
||||
|
||||
Machine learning is a subset of [[Artificial Intelligence]] that focuses on creating algorithms that can learn from [[Data]].
|
||||
|
||||
Key concepts include:
|
||||
|
||||
- [[Supervised Learning]]
|
||||
- [[Unsupervised Learning]]
|
||||
- [[Neural Networks]]
|
||||
- [[Feature Engineering]]
|
||||
|
||||
This connects to my work on [[Customer Behavior Analysis]] and [[Predictive Analytics]].
|
||||
```
|
||||
|
||||
Foam will create placeholder pages for missing notes, making it easy to fill in knowledge gaps later.
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
||||
Essential VS Code shortcuts for note-taking:
|
||||
|
||||
| Shortcut | Action |
|
||||
| ------------------------------ | --------------------- |
|
||||
| `Ctrl+N` / `Cmd+N` | New file |
|
||||
| `Ctrl+S` / `Cmd+S` | Save file |
|
||||
| `Ctrl+P` / `Cmd+P` | Quick file open |
|
||||
| `Ctrl+Shift+P` / `Cmd+Shift+P` | Command palette |
|
||||
| `Ctrl+K V` / `Cmd+K V` | Open Markdown preview |
|
||||
| `Ctrl+[` / `Cmd+[` | Decrease indent |
|
||||
| `Ctrl+]` / `Cmd+]` | Increase indent |
|
||||
| `Alt+Z` / `Option+Z` | Toggle word wrap |
|
||||
|
||||
## What's Next?
|
||||
|
||||
Now that you understand note-taking basics:
|
||||
|
||||
1. **[[navigation]]** - Learn to move efficiently between notes with wikilinks
|
||||
2. **[Explore the graph view](../features/graph-view.md)** - Visualize the connections in your knowledge base
|
||||
3. **[Set up templates](../features/templates.md)** - Create reusable note structures
|
||||
4. **[Use daily notes](../features/daily-notes.md)** - Establish a daily capture routine
|
||||
|
||||
[navigation]: navigation.md 'Navigation in Foam'
|
||||
[tags]: ../features/tags.md 'Tags'
|
||||
|
||||
@@ -4,21 +4,21 @@ These extensions defined in `.vscode/extensions.json` are automatically installe
|
||||
|
||||
This list is subject to change.
|
||||
|
||||
- [Foam for VSCode](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode) (alpha)
|
||||
- [Foam for VSCode](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode)
|
||||
- [Markdown All In One](https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one)
|
||||
- [Paste Image](https://marketplace.visualstudio.com/items?itemName=mushan.vscode-paste-image)
|
||||
- [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
|
||||
|
||||
## Extensions For Additional Features
|
||||
|
||||
These extensions are not (yet?) defined in `.vscode/extensions.json`, but have been used by others and shown to play nice with Foam.
|
||||
These extensions are not defined in `.vscode/extensions.json`, but have been used by others and shown to play nice with Foam.
|
||||
|
||||
- [Emojisense](https://marketplace.visualstudio.com/items?itemName=bierner.emojisense)
|
||||
- [Markdown Emoji](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-emoji) (adds `:smile:` syntax, works with emojisense to provide autocomplete for this syntax)
|
||||
- [Markdown Preview Mermaid Support](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid)
|
||||
- [Mermaid Markdown Syntax Highlighting](https://marketplace.visualstudio.com/items?itemName=bpruitt-goddard.mermaid-markdown-syntax-highlighting)
|
||||
- [VSCode PDF Viewing](https://marketplace.visualstudio.com/items?itemName=tomoki1207.pdf)
|
||||
- [Project Manager](https://marketplace.visualstudio.com/items?itemName=alefragnani.project-manager) (to quickly switch between projects)
|
||||
- [Markdown Extended](https://marketplace.visualstudio.com/items?itemName=jebbs.markdown-extended) (with `kbd` option disabled, `kbd` turns wikilinks into non-clickable buttons)
|
||||
- [GitDoc](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.gitdoc) (easy version management via git auto commits)
|
||||
- [Markdown Footnotes](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-footnotes) (Adds [^footnote] syntax support to VS Code's built-in markdown preview)
|
||||
- [Todo Tree](https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree) (Searches workspace for TODO and related comments and summarizes those lines in vs-code gutter)
|
||||
- [Emojisense](https://marketplace.visualstudio.com/items?itemName=bierner.emojisense) (provides emoji autocomplete and suggestions in markdown files)
|
||||
- [Markdown Emoji](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-emoji) (adds `:smile:` syntax support, works with emojisense to provide autocomplete for this syntax)
|
||||
- [Mermaid diagrams Support](https://marketplace.visualstudio.com/items?itemName=MermaidChart.vscode-mermaid-chart) (adds syntax highlighting for Mermaid code blocks in markdown and renders Mermaid diagrams in markdown preview)
|
||||
- [Excalidraw whiteboard and sketching tool integration](https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor) (create and edit hand-drawn style diagrams and sketches directly in VS Code)
|
||||
- [VSCode PDF Viewing](https://marketplace.visualstudio.com/items?itemName=tomoki1207.pdf) (view PDF files directly within VS Code without external applications)
|
||||
- [Project Manager](https://marketplace.visualstudio.com/items?itemName=alefragnani.project-manager) (easily switch between multiple projects and workspaces)
|
||||
- [Markdown Extended](https://marketplace.visualstudio.com/items?itemName=jebbs.markdown-extended) (extended markdown syntax support with additional formatting options - use with `kbd` option disabled as it conflicts with wikilinks)
|
||||
- [GitDoc](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.gitdoc) (automatic git commits for easy version management and backup of your notes)
|
||||
- [Markdown Footnotes](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-footnotes) (adds footnote syntax support `[^footnote]` to VS Code's built-in markdown preview)
|
||||
- [Todo Tree](https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree) (scans workspace for TODO, FIXME, and other comment tags, displaying them in a tree view and editor gutter)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Sync notes with source control
|
||||
|
||||
Source control is a way to precicely manage the history and content of a directory of files.
|
||||
Source control is a way to precisely manage the history and content of a directory of files.
|
||||
Often used for program code, this feature is very useful for note taking as well.
|
||||
|
||||
There are (too) many ways to commit your changes to source control:
|
||||
@@ -1,74 +0,0 @@
|
||||
# Writing Notes
|
||||
|
||||
Notes are simple text files with some extra flavor, in the shape of Markdown syntax and support for extra properties (see [[note-properties]]).
|
||||
|
||||
## Foam Syntax
|
||||
|
||||
Foam uses standard Markdown, with a few added twists:
|
||||
|
||||
- the title of a note (e.g. in the [[graph-visualization]]) is given by precedence based on:
|
||||
- the `title` property (see [[note-properties]])
|
||||
- the first `# heading 1` of the file
|
||||
- the file name
|
||||
|
||||
## Markdown Syntax
|
||||
|
||||
With Markdown, we can style our notes in a simple way, while keeping the document a simple text file (the best way to future-proof your writings!).
|
||||
|
||||
You can see the formatted output by running the `Markdown: Open Preview to the Side` command.
|
||||
|
||||
Here is a high level overview of Markdown, for more information on the Markdown syntax [see here](https://commonmark.org/help/).
|
||||
|
||||
# Heading 1
|
||||
|
||||
## Heading 2
|
||||
|
||||
### Heading 3
|
||||
|
||||
#### Heading 4
|
||||
|
||||
##### Heading 5
|
||||
|
||||
###### Heading 6
|
||||
|
||||
This is a [link to google](https://www.google.com).
|
||||
|
||||
This is a wikilink (aka internal link) to [[note-properties]].
|
||||
|
||||
Here is an image:
|
||||

|
||||
|
||||
> this is a blockquote
|
||||
> it can span multiple lines
|
||||
|
||||
- list item
|
||||
- list item
|
||||
- list item
|
||||
|
||||
1. One
|
||||
2. Two
|
||||
3. Three
|
||||
|
||||
This text is **in bold** and this is *italic*.
|
||||
|
||||
The following is a horizontal rule
|
||||
|
||||
---
|
||||
|
||||
This is a table:
|
||||
| Column 1 | Column 2 |
|
||||
| -------- | -------- |
|
||||
| R1C1 | R1C2 |
|
||||
| R2C1 | R2C2 |
|
||||
|
||||
You can `inline code` or
|
||||
|
||||
```text
|
||||
you can create
|
||||
code blocks
|
||||
```
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[note-properties]: ../features/note-properties.md "Note Properties"
|
||||
[graph-visualization]: ../features/graph-visualization.md "Graph Visualization"
|
||||
[//end]: # "Autogenerated link references"
|
||||
@@ -1,31 +1,49 @@
|
||||
# Using Foam
|
||||
|
||||
Foam is a collection VS Code extensions and recipes that power up the editor into a full-blown note taking system.
|
||||
This folder contains user documentation describing how to get started using Foam, what its main features are, and strategies for getting the most out of Foam.
|
||||
The full docs are included in the `foam-template` repo that most users start from.
|
||||
Foam is a personal knowledge management system built on [Visual Studio Code](https://code.visualstudio.com/) and [GitHub](https://github.com/). It helps you organize research, create discoverable notes, and publish your knowledge.
|
||||
|
||||
> See also [[frequently-asked-questions]].
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Wikilinks** - Connect thoughts with `[[double bracket]]` syntax
|
||||
- **Embeds** - Include content from other notes with `![[note]]` syntax
|
||||
- **Backlinks** - Automatically discover connections between notes
|
||||
- **Graph visualization** - See your knowledge network visually
|
||||
- **Daily notes** - Capture timestamped thoughts
|
||||
- **Templates** - Standardize note creation
|
||||
- **Tags** - Organize and filter content
|
||||
|
||||
## Why Choose Foam?
|
||||
|
||||
- **Free and open source** - No subscriptions or vendor lock-in
|
||||
- **Own your data** - Notes stored as standard Markdown files
|
||||
- **VS Code integration** - Leverage powerful editing and extensions
|
||||
- **Git-based** - Version control and collaboration built-in
|
||||
|
||||
Foam is like a bathtub: _What you get out of it depends on what you put into it._
|
||||
|
||||
## Getting Started
|
||||
|
||||
- [[installation]]
|
||||
- [[get-started-with-vscode]]
|
||||
- [[recommended-extensions]]
|
||||
- [[creating-new-notes]]
|
||||
- [[write-notes-in-foam]]
|
||||
- [[sync-notes-with-soruce-control]]
|
||||
- [[first-workspace]]
|
||||
- [[note-taking-in-foam]]
|
||||
- [[sync-notes]]
|
||||
- [[keyboard-shortcuts]]
|
||||
|
||||
## Features
|
||||
|
||||
- [[wikilinks]]
|
||||
- [[embeds]]
|
||||
- [[tags]]
|
||||
- [[backlinking]]
|
||||
- [[daily-notes]]
|
||||
- [[including-notes]]
|
||||
- [[spell-checking]]
|
||||
- [[graph-visualization]]
|
||||
- [[graph-view]]
|
||||
- [[note-properties]]
|
||||
- [[note-templates]]
|
||||
- [[templates]]
|
||||
- [[paste-images-from-clipboard]]
|
||||
- [[custom-markdown-preview-styles]]
|
||||
- [[link-reference-definitions]]
|
||||
@@ -51,21 +69,22 @@ See [[publishing]] for more details.
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[frequently-asked-questions]: frequently-asked-questions.md "Frequently Asked Questions"
|
||||
[get-started-with-vscode]: getting-started/get-started-with-vscode.md "Getting started with VS Code"
|
||||
[installation]: getting-started/installation.md "Installation"
|
||||
[get-started-with-vscode]: getting-started/get-started-with-vscode.md "Using Foam with VS Code Features"
|
||||
[recommended-extensions]: getting-started/recommended-extensions.md "Recommended Extensions"
|
||||
[creating-new-notes]: getting-started/creating-new-notes.md "Creating New Notes"
|
||||
[write-notes-in-foam]: getting-started/write-notes-in-foam.md "Writing Notes"
|
||||
[sync-notes-with-soruce-control]: getting-started/sync-notes-with-soruce-control.md "Sync notes with source control"
|
||||
[first-workspace]: getting-started/first-workspace.md "Creating Your First Workspace"
|
||||
[note-taking-in-foam]: getting-started/note-taking-in-foam.md "Note-Taking in Foam"
|
||||
[sync-notes]: getting-started/sync-notes.md "Sync notes with source control"
|
||||
[keyboard-shortcuts]: getting-started/keyboard-shortcuts.md "Keyboard Shortcuts"
|
||||
[wikilinks]: features/wikilinks.md "Wikilinks"
|
||||
[embeds]: features/embeds.md "Note Embeds"
|
||||
[tags]: features/tags.md "Tags"
|
||||
[backlinking]: features/backlinking.md "Backlinking"
|
||||
[backlinking]: features/backlinking.md "Backlinks"
|
||||
[daily-notes]: features/daily-notes.md "Daily Notes"
|
||||
[including-notes]: features/including-notes.md "Including notes in a note"
|
||||
[spell-checking]: features/spell-checking.md "Spell Checking"
|
||||
[graph-visualization]: features/graph-visualization.md "Graph Visualization"
|
||||
[graph-view]: features/graph-view.md "Graph Visualization"
|
||||
[note-properties]: features/note-properties.md "Note Properties"
|
||||
[note-templates]: features/note-templates.md "Note Templates"
|
||||
[templates]: features/templates.md "Note Templates"
|
||||
[paste-images-from-clipboard]: features/paste-images-from-clipboard.md "Paste Images from Clipboard"
|
||||
[custom-markdown-preview-styles]: features/custom-markdown-preview-styles.md "Custom Markdown Preview Styles"
|
||||
[link-reference-definitions]: features/link-reference-definitions.md "Link Reference Definitions"
|
||||
|
||||
@@ -50,7 +50,7 @@ In our case, we'll be using the latter tag to wrap our {% raw %}`{{ content }}`{
|
||||
|
||||
You may have noticed that we only made modifications to the template `_layouts/page.html`, which means that `_layouts/home.html` won't have KaTeX support. If you wan't to render math in Foam's home page, you'll need to make the same modifications to `_layouts/home.html` as well.
|
||||
|
||||
Finally, if all goes well, then our site hosted on Vercel will support rendering math equations with KaTeX after commiting these changes to GitHub. Here's a demo of the default template with KaTeX support: [Foam Template with KaTeX support](https://foam-template.vercel.app/).
|
||||
Finally, if all goes well, then our site hosted on Vercel will support rendering math equations with KaTeX after committing these changes to GitHub. Here's a demo of the default template with KaTeX support: [Foam Template with KaTeX support](https://foam-template.vercel.app/).
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[math-support-with-mathjax]: math-support-with-mathjax.md "Math Support"
|
||||
|
||||
@@ -36,31 +36,31 @@ _Note that first entry in `.order` file defines wiki's home page._
|
||||
|
||||
While you are pushing changes to GitHub, you won't see the wiki updated if you don't add Azure as a remote. You can push to multiple repositories simultaneously.
|
||||
|
||||
1. First open a terminal and check if Azure is added running: `git remote show origin`. If you don't see Azure add it in the output then follow these steps.
|
||||
2. Rename your current remote (most likely named origin) to a different name by running: `git remote rename origin main`
|
||||
3. You can then add the remote for your second remote repository, in this case, Azure. e.g `git remote add azure https://<YOUR_ID>@dev.azure.com/<YOUR_ID>/foam-notes/_git/foam-notes`. You can get it from: Repos->Files->Clone and copy the URL.
|
||||
4. Now, you need to set up your origin remote to push to both of these. So run: `git config -e` and edit it.
|
||||
5. Add the `remote origin` section to the bottom of the file with the URLs from each remote repository you'd like to push to. You'll see something like that:
|
||||
1. First open a terminal and check if Azure is added running: `git remote show origin`. If you don't see Azure add it in the output then follow these steps.
|
||||
2. Rename your current remote (most likely named origin) to a different name by running: `git remote rename origin main`
|
||||
3. You can then add the remote for your second remote repository, in this case, Azure. e.g `git remote add azure https://<YOUR_ID>@dev.azure.com/<YOUR_ID>/foam-notes/_git/foam-notes`. You can get it from: Repos->Files->Clone and copy the URL.
|
||||
4. Now, you need to set up your origin remote to push to both of these. So run: `git config -e` and edit it.
|
||||
5. Add the `remote origin` section to the bottom of the file with the URLs from each remote repository you'd like to push to. You'll see something like that:
|
||||
|
||||
```bash
|
||||
[core]
|
||||
```bash
|
||||
[core]
|
||||
...
|
||||
(ignore this part)
|
||||
...
|
||||
(ignore this part)
|
||||
...
|
||||
[branch "master"]
|
||||
remote = github
|
||||
merge = refs/heads/master
|
||||
[branch "main"]
|
||||
remote = github
|
||||
merge = refs/heads/main
|
||||
[remote "github"]
|
||||
url = git@github.com:username/repo.git
|
||||
fetch = +refs/heads/*:refs/remotes/github/*
|
||||
url = git@github.com:username/repo.git
|
||||
fetch = +refs/heads/*:refs/remotes/github/*
|
||||
[remote "azure"]
|
||||
url = https://<YOUR_ID>@dev.azure.com/<YOUR_ID>/foam-notes/_git/foam-notes
|
||||
fetch = +refs/heads/*:refs/remotes/azure/*
|
||||
url = https://<YOUR_ID>@dev.azure.com/<YOUR_ID>/foam-notes/_git/foam-notes
|
||||
fetch = +refs/heads/*:refs/remotes/azure/*
|
||||
[remote "origin"]
|
||||
url = git@github.com:username/repo.git
|
||||
url = https://<YOUR_ID>@dev.azure.com/<YOUR_ID>/foam-notes/_git/foam-notes
|
||||
```
|
||||
url = git@github.com:username/repo.git
|
||||
url = https://<YOUR_ID>@dev.azure.com/<YOUR_ID>/foam-notes/_git/foam-notes
|
||||
```
|
||||
|
||||
6. You can then push to both repositories by: `git push origin master` or a single one using: `git push github master` or `git push azure master`
|
||||
6. You can then push to both repositories by: `git push origin main` or a single one using: `git push github main` or `git push azure main`
|
||||
|
||||
For more information, read the [Azure DevOps documentation](https://docs.microsoft.com/en-us/azure/devops/project/wiki/publish-repo-to-wiki).
|
||||
|
||||
@@ -218,7 +218,7 @@ Commit the file and push it to gitlab.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
- *Could not locate Gemfile* - You didn't follow the steps above to [#Add a Gemlock file]
|
||||
- *Could not locate Gemfile* - You didn't follow the steps above to [Add a Gemlock file](#add-a-gemlock-file)
|
||||
- *Conversion error: Jekyll::Converters::Scss encountered an error while converting* You need to reference a theme.
|
||||
- *Pages are running in CI/CD, but I only ever see `test`, and never deploy* - Perhaps you've renamed the main branch (from master) - check the settings in `.gitlab-ci.yml` and ensure the deploy command is running to the branch you expect it to.
|
||||
- *I deployed, but my .msd files don't seem to be being converted into .html files* - You need a gem that GitHub installs by default - check `gem "jekyll-optional-front-matter"` appears in the `Gemfile`
|
||||
|
||||
@@ -65,7 +65,7 @@ gem "jekyll-katex" # Optional, the package that enables KaTeX math rendering
|
||||
|
||||
Besides adding the plugin `jekyll-katex` in `_config.yml` and `Gemfile`, we'll also have to follow the guides in [[math-support-with-katex]] to let our site fully support using KaTeX to render math equations.
|
||||
|
||||
### Commiting changes to GitHub repo
|
||||
### Committing changes to GitHub repo
|
||||
|
||||
Finally, commit the newly created files to GitHub.
|
||||
|
||||
|
||||
@@ -2,8 +2,12 @@
|
||||
|
||||
This #recipe allows you to paste images on to your notes.
|
||||
|
||||
You can directly link and paste images that are copied to the clipboard using either the [Paste
|
||||
Image](https://marketplace.visualstudio.com/items?itemName=mushan.vscode-paste-image)
|
||||
extension, or the [Markdown Image](https://marketplace.visualstudio.com/items?itemName=hancel.markdown-image) extension.
|
||||
VScode (since
|
||||
[1.79](https://code.visualstudio.com/updates/v1_79#_copy-external-media-files-into-workspace-on-drop-or-paste-for-markdown))
|
||||
now has the ability to paste images from the clipboard, or drag-and-drop image
|
||||
files, directly into markdown documents. The file will be created in the
|
||||
workspace, and a link generated in Markdown format.
|
||||
|
||||
The former does not have MDX support (yet), the latter does.
|
||||
VSCode settings under `Markdown > Copy Files` and `Markdown > Editor > Drop` can
|
||||
be used to configure where the files get placed in your workspace, how they're
|
||||
named, how conflicts with existing files are handled, and more.
|
||||
|
||||
@@ -6,7 +6,7 @@ With this #recipe you can create notes on your iOS device, which will automatica
|
||||
|
||||
* You use [Foam for VSCode](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode) to manage your notes
|
||||
* You wish to adopt a practice such as [A writing inbox for transient and incomplete notes](https://notes.andymatuschak.org/A%20writing%20inbox%20for%20transient%20and%20incomplete%20notes)
|
||||
* You wish to use [Shorcuts](https://support.apple.com/guide/shortcuts/welcome/ios) to capture quick notes into your Foam notes from your iOS device
|
||||
* You wish to use [Shortcuts](https://support.apple.com/guide/shortcuts/welcome/ios) to capture quick notes into your Foam notes from your iOS device
|
||||
|
||||
## Other tools
|
||||
|
||||
@@ -29,6 +29,9 @@ on:
|
||||
jobs:
|
||||
store_data:
|
||||
runs-on: ubuntu-latest
|
||||
# If you encounter a 403 error from a workflow run, try uncommenting the following 2 lines (taken from: https://stackoverflow.com/questions/75880266/cant-make-push-on-a-repo-with-github-actions accepted answer)
|
||||
# permissions:
|
||||
# contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: anglinb/foam-capture-action@main
|
||||
|
||||
53
docs/user/recipes/export-to-pdf.md
Normal file
53
docs/user/recipes/export-to-pdf.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Export to PDF
|
||||
|
||||
This #recipe shows how to export a note to PDF.
|
||||
|
||||
## Required extensions
|
||||
|
||||
- **[vscode-pandoc](https://marketplace.visualstudio.com/items?itemName=chrischinchilla.vscode-pandoc)**
|
||||
|
||||
## Required third-party tools
|
||||
|
||||
- [Pandoc](https://pandoc.org/installing.html)
|
||||
- A [LaTeX distribution](https://www.latex-project.org/get/) such as TeXLive (Linux), MacTeX (MacOS), or MikTeX (Windows)
|
||||
|
||||
Check that Pandoc is installed by opening a terminal and running `pandoc --version`.
|
||||
|
||||
Check that Pandoc can produce PDFs with LaTeX by running the following in the terminal.
|
||||
|
||||
```
|
||||
echo It is working > test.md
|
||||
pandoc test.md -o test.pdf
|
||||
```
|
||||
|
||||
## Instructions
|
||||
|
||||
1. Create a folder in your workspace named `.pandoc`. Take note of the full path to this directory. The rest of this recipe will refer to this path as `$WORKSPACE/.pandoc`.
|
||||
|
||||
2. Download the template file [`foam.latex`](https://raw.githubusercontent.com/Hegghammer/foam-templates/main/foam.latex) from [Hegghammer/foam-templates](https://github.com/Hegghammer/foam-templates) and place it in `$WORKSPACE/.pandoc`.
|
||||
|
||||
3. In VSCode, open `settings.json` for your user (or just for your workspace if you prefer), and add the following line:
|
||||
|
||||
```
|
||||
"pandoc.pdfOptString": "--from=markdown+wikilinks_title_after_pipe --resource-path $WORKSPACE/.pandoc --template foam --listings",
|
||||
```
|
||||
|
||||
Make sure to replace `$WORKSPACE/.pandoc` with the real full path to the `.pandoc` directory you created earlier.
|
||||
|
||||
4. Open a Foam note in VSCode.
|
||||
|
||||
5. Press `Ctrl` + `k`, `p`. Choose "pdf", and press `Enter`.
|
||||
|
||||
The PDF should look something like this:
|
||||
|
||||

|
||||
|
||||
## Options
|
||||
|
||||
If you include a name in the `author` parameter in the YAML of the Foam note, that name will feature in the PDF header on the top left.
|
||||
|
||||
If you don't want syntax highlighting and frames around the codeblocks, remove `--listings` from the `pandoc.pdfOptString` parameter in `settings.json`.
|
||||
|
||||
## Further customization
|
||||
|
||||
If you know some LaTeX, you can [tweak](https://bookdown.org/yihui/rmarkdown-cookbook/latex-template.html) the `foam.latex` template to your needs. Alternatively, you can supply another ready-made template such as [Eisvogel](https://github.com/Wandmalfarbe/pandoc-latex-template); just place the `TEMPLATE_NAME.latex` file in `$WORKSPACE/.pandoc`. You can also use all of Pandoc's [other functionalities](https://learnbyexample.github.io/customizing-pandoc/) by tweaking the `pandoc.pdfOptString` parameter in `settings.json`.
|
||||
173
docs/user/recipes/generate-material-for-mkdocs-site.md
Normal file
173
docs/user/recipes/generate-material-for-mkdocs-site.md
Normal file
@@ -0,0 +1,173 @@
|
||||
# Generate a site using the Material for MkDocs theme
|
||||
|
||||
Configuring a static-site generator (SSG) to publish your Foam provides access to functionality not available through Foam's default publishing mechanism. For example, compare the [original Foam documentation site](https://foambubble.github.io/foam/) with a [Material for MkDocs version](https://djplaner.github.io/foam-with-material-for-mkdocs/) created using the simple configuration detailed below. Try out the search functionality on the Material for MkDocs version. This [digital garden](https://djon.es/memex) and this [blog](https://djon.es/blog/) provide more advanced examples of Foam content published using Material for MkDocs.
|
||||
|
||||
The following explains how to configure the [Material for MkDocs theme](https://squidfunk.github.io/mkdocs-material/) for the [MkDocs SSG](https://www.mkdocs.org) to publish your Foam.
|
||||
|
||||
Like most SSGs (e.g. [Gatsby](https://www.gatsbyjs.com/) is another SSG that can be [used to publish your Foam](https://foambubble.github.io/foam/user/publishing/generate-gatsby-site)) site content is accepted in the form of Markdown files. Like those produced by Foam. SSGs differ in the languages they are written in (MkDocs is Python, Gatsby is Javascript and React) and the features they provide. MkDocs and Material for MkDocs are designed to support project documentation. Gatsby is more general purpose and provides a nice feature set.
|
||||
|
||||
You choose your poison.
|
||||
|
||||
## Requirements
|
||||
|
||||
To use Material for MkDocs to publish your Foam you need:
|
||||
|
||||
- An existing Foam workspace with content.
|
||||
- [Python installed on your computer](https://realpython.com/installing-python/).
|
||||
- Some familiarity and comfort with using the command line on your computer.
|
||||
|
||||
## Instructions
|
||||
|
||||
Configuring Material for MkDocs to publish your Foam involves the following steps:
|
||||
|
||||
1. [Install Material for MkDocs and other requirements](#install-material-for-mkdocs-and-other-requirements).
|
||||
|
||||
Install the Material for MkDocs theme, MkDocs, and other required Python modules.
|
||||
|
||||
2. [Configure Material for MkDocs for your Foam](#configure-material-for-mkdocs-for-your-foam).
|
||||
|
||||
Create a `mkdocs.yml` file in the root of your Foam workspace directory. This file configures Material for MkDocs to work with your Foam.
|
||||
|
||||
2. [Preview and test your site locally](#preview-and-test-your-site-locally).
|
||||
|
||||
Run MkDocs to preview and test your Material for MkDocs Foam site locally. Good for testing and local use.
|
||||
|
||||
3. [Further customise Material for MkDocs](#further-customise-material-for-mkdocs).
|
||||
|
||||
Explore and leverage the additional configuration settings, possible customisations, and additional themes and plugins to customise your site to your needs.
|
||||
|
||||
4. [Publish your site](#publish-your-site).
|
||||
|
||||
Publish your Material for MkDocs Foam site to the web for others to enjoy. There are many options for publishing your site, including GitHub, GitLab, Netlify, and others.
|
||||
|
||||
### Install Material for MkDocs and other requirements
|
||||
|
||||
Material for MkDocs provides [detailed installation instructions](https://squidfunk.github.io/mkdocs-material/getting-started/) which cover the full range of options for installing and configuring Material for MkDocs. The following is a summary of the recommended process.
|
||||
|
||||
1. Within your Foam workspace directory, create a [Python virtual environment](https://realpython.com/what-is-pip/#using-pip-in-a-python-virtual-environment)
|
||||
|
||||
- `python -m venv .venv`
|
||||
- `source .venv/bin/activate` (Linux/Mac) or `.venv\Scripts\activate` (Windows)
|
||||
|
||||
2. Install Material for MkDocs
|
||||
|
||||
- `pip install mkdocs-material`
|
||||
|
||||
3. Install additional Python modules
|
||||
|
||||
- `pip install mkdocs-roamlinks-plugin`
|
||||
- `pip install mkdocs-exclude`
|
||||
|
||||
### Configure Material for MkDocs for your Foam
|
||||
|
||||
To configure Material for MkDocs for your Foam workspace, create a `mkdocs.yml` file in the root of your Foam workspace directory. Below you will find a sample `mkdocs.yml` file (adapted from the [foam-mkdocs-template repository](https://github.com/Jackiexiao/foam-mkdocs-template/tree/master)). Copy and paste it into your `mkdocs.yml` file, then edit it to suit your needs. In particular, don't forget to change the `site_name` and `site_url` to match your Foam workspace. Though this can be left a little later.
|
||||
|
||||
Material for MkDocs provides documentation on both [minimal](https://squidfunk.github.io/mkdocs-material/creating-your-site/#minimal-configuration) and [advanced](https://squidfunk.github.io/mkdocs-material/creating-your-site/#advanced-configuration) configuration of `mkdocs.yml`. Which are revisited in the [customise section below](#further-customise-your-site)
|
||||
|
||||
```yaml
|
||||
site_name: My site # Change this to your site name
|
||||
site_url: https://mydomain.org/mysite # change this
|
||||
theme:
|
||||
name: material
|
||||
features:
|
||||
- navigation.expand
|
||||
- tabs
|
||||
markdown_extensions:
|
||||
- attr_list
|
||||
- pymdownx.tabbed
|
||||
- nl2br
|
||||
- toc:
|
||||
permalink: '#'
|
||||
slugify: !!python/name:pymdownx.slugs.uslugify
|
||||
- admonition
|
||||
- codehilite:
|
||||
guess_lang: false
|
||||
linenums: false
|
||||
- footnotes
|
||||
- meta
|
||||
- def_list
|
||||
- pymdownx.arithmatex
|
||||
- pymdownx.betterem:
|
||||
smart_enable: all
|
||||
- pymdownx.caret
|
||||
- pymdownx.critic
|
||||
- pymdownx.details
|
||||
- pymdownx.inlinehilite
|
||||
- pymdownx.magiclink
|
||||
- pymdownx.mark
|
||||
- pymdownx.smartsymbols
|
||||
- pymdownx.superfences
|
||||
- pymdownx.tasklist
|
||||
- pymdownx.tilde
|
||||
plugins:
|
||||
- search
|
||||
- roamlinks
|
||||
- exclude:
|
||||
glob:
|
||||
- "*.tmp"
|
||||
- "*.pdf"
|
||||
- "*.gz"
|
||||
regex:
|
||||
- '.*\.(tmp|bin|tar)$'
|
||||
```
|
||||
|
||||
### Preview and test your site locally
|
||||
|
||||
MkDocs provides a live preview server allowing you to preview and test your Material for MkDocs Foam site. The server will continue to rebuid your site as you write.
|
||||
|
||||
The simplest method to use the preview service is to run the following command whilst in the rood directory of your Foam workspace:
|
||||
|
||||
```bash
|
||||
mkdocs serve
|
||||
```
|
||||
|
||||
See the Material for MkDocs site for more, including [how to run the preview server via docker](https://squidfunk.github.io/mkdocs-material/creating-your-site/#previewing-as-you-write)
|
||||
|
||||
### Further customise your site
|
||||
|
||||
Further customisation is available through expanding the configuration of Material for MkDocs, using additional MkDocs plugins, customising HTML/CSS, using Markdown extensions, writing your own Python scripts, and more.
|
||||
|
||||
For more on the available customisation paths, see the following:
|
||||
|
||||
- Material for MkDocs [Advanced configuration](https://squidfunk.github.io/mkdocs-material/creating-your-site/#advanced-configuration) or the [Set up section](https://squidfunk.github.io/mkdocs-material/setup/)
|
||||
|
||||
For more configuration options to be included in your `mkdocs.yml` file, including customising: colours, fonts, language, icons, navigation, header, footer etc.
|
||||
|
||||
- Material for MkDocs [Customisation](https://squidfunk.github.io/mkdocs-material/customization/)
|
||||
|
||||
For advice on enhancing the visual design of your site by customising and replacing provided HTML, CSS, and Javascript.
|
||||
|
||||
- Material for MkDocs [Reference](https://squidfunk.github.io/mkdocs-material/reference/)
|
||||
|
||||
An overview of customisation methods that can be used directly within your Markdown files, including: admonitions, annotations, buttons, code blocks, content tabs, data tables, diagrams, grids, Mathematics, etc.
|
||||
|
||||
- a [catalog of 300 MkDocs projects and plugins](https://github.com/mkdocs/catalog#readme)
|
||||
|
||||
For functionality and ideas not included in Material for MkDocs, including: additional themes, plugins, and extensions.
|
||||
|
||||
### Building and publishing your site
|
||||
|
||||
As a Static Site Generator (SSG), MkDocs generates a collection of static HTML and other types of files. Publishing your site involves building those HTML files and placing them onto your web server. The method will vary depending on your web server and hosting provider.
|
||||
|
||||
The MkDocs documentation site provides an explanation of the [simplest method to publish your site to any provider](https://www.mkdocs.org/user-guide/deploying-your-docs/#other-providers) using `mkdocs build` and `scp`.
|
||||
|
||||
The Material for MkDocs [publish page](https://squidfunk.github.io/mkdocs-material/publishing-your-site/) lists options for publishing to
|
||||
|
||||
- GitHub using [mkdocs](https://squidfunk.github.io/mkdocs-material/publishing-your-site/#with-mkdocs)
|
||||
|
||||
Perhaps the simplest method, if you are already using GitHub to host your Foam workspace.
|
||||
|
||||
- GitHub using [GitHub actions](https://squidfunk.github.io/mkdocs-material/publishing-your-site/github-actions/)
|
||||
|
||||
A more automated method of publishing your site to GitHub, using GitHub actions.
|
||||
|
||||
- [GitLab](https://squidfunk.github.io/mkdocs-material/publishing-your-site/#with-mkdocs)
|
||||
|
||||
- [Cloudflage pages](https://deborahwrites.com/guides/deploy-host-mkdocs/deploy-mkdocs-material-cloudflare/)
|
||||
|
||||
- [Netlify](https://deborahwrites.com/guides/deploy-host-mkdocs/deploy-mkdocs-material-netlify/)
|
||||
|
||||
- [Fly.io](https://documentation.breadnet.co.uk/cloud/fly/mkdocs-on-fly/#prerequisites)
|
||||
|
||||
- [Scaleway](https://www.scaleway.com/en/docs/tutorials/using-bucket-website-with-mkdocs/)
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# Make Backlinks More Prominent
|
||||
|
||||
One of the most most common early feature requests in Foam is to make the Markdown Notes Backlinks Explorer more prominent.
|
||||
|
||||
This #recipe shows you how to do that.
|
||||
|
||||
At the moment, you can drag the explorer pane to your bottom pane, and either show it side by side with another pane, or have take the full width of the editor:
|
||||
|
||||

|
||||
|
||||
In the future we'll want to improve this feature by
|
||||
|
||||
- [[materialized-backlinks]]
|
||||
- Providing more context around back link reference
|
||||
- Could be done by tweaking Markdown Notes slightly. Maybe a user setting?
|
||||
- Make back links editable using [VS Code Search Editors](https://code.visualstudio.com/updates/v1_43#_search-editors)
|
||||
- [Suggested by @Jash on Discord](https://discordapp.com/channels/729975036148056075/729978910363746315/730999992419876956)
|
||||
|
||||
[//begin]: # "Autogenerated link references for markdown compatibility"
|
||||
[materialized-backlinks]: ../../dev/proposals/materialized-backlinks.md "Materialized Backlinks (stub)"
|
||||
[//end]: # "Autogenerated link references"
|
||||
43
docs/user/recipes/markup-converter.md
Normal file
43
docs/user/recipes/markup-converter.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Markup Converter
|
||||
|
||||
This #recipe allows you to convert any document into Markdown for storing them in your notes.
|
||||
|
||||
We will be using [Pandoc](https://pandoc.org/), a popular universal document converter. It can convert documents in Microsoft Word, HTML, LaTeX, and many other formats to various formats including markdown and many others.
|
||||
|
||||
## Instructions
|
||||
|
||||
We will go through the example of converting Microsoft Word documents to Markdown. For detailed instructions on how to use Pandoc, please refer to the [Pandoc documentation](https://pandoc.org/MANUAL.html).
|
||||
|
||||
1. [Install Pandoc](https://pandoc.org/installing.html)
|
||||
1. Open the terminal of your choice and verify that Pandoc is installed by running `pandoc --version`
|
||||
1. Copy the Microsoft Word documents that you want to convert into a new folder
|
||||
1. Change the current directory to the folder containing the Microsoft Word documents
|
||||
1. Copy one of the following commands (based on your operating system) into your terminal and press `Enter` to run
|
||||
|
||||
### Linux and macOS (Bash)
|
||||
|
||||
```bash
|
||||
find -name "*.docx" -type f -exec sh -c '
|
||||
for f; do
|
||||
pandoc --extract-media=./ -f docx -t markdown -o "${f%.*}.md" "$f"
|
||||
done
|
||||
' find-sh {} +
|
||||
```
|
||||
|
||||
### Windows (PowerShell)
|
||||
|
||||
```powershell
|
||||
Get-ChildItem . -Filter *.docx |
|
||||
Foreach-Object {
|
||||
pandoc --extract-media=./ --from docx --to markdown $_ -o $_.Name.Replace('.docx', '.md')
|
||||
}
|
||||
```
|
||||
|
||||
### Relevant Configurations
|
||||
|
||||
[Pandoc](https://pandoc.org/) accepts a range of command line arguments to control the conversion process. Here, we'll mention a few that are relevant to the example above.
|
||||
|
||||
- `--extract-media=./` is used to extract the images from the Microsoft Word documents and store them in a subfolder named `media`
|
||||
- `-t markdown` converts the Microsoft Word documents to [Pandoc’s Markdown](https://pandoc.org/MANUAL.html#pandocs-markdown). You can also use `-t gfm` to convert to [GitHub Flavored Markdown](https://docs.github.com/en/get-started/writing-on-github)
|
||||
|
||||
Note that you may want to review the converted Markdown files to ensure that the conversion was successful. Then, You may want to delete the original Microsoft Word documents.
|
||||
@@ -1,58 +0,0 @@
|
||||
# Custom Note Macros
|
||||
|
||||
This #recipe allows you to create custom note macros.
|
||||
|
||||
## Installation
|
||||
|
||||
**This extension is not included in the template**
|
||||
|
||||
To install search note-macros in vscode or head to [note-macros - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=NeelyInnovations.note-macros)
|
||||
|
||||
## Instructions
|
||||
|
||||
### Run macro From command pallette
|
||||
|
||||
Simply use `Ctrl+P` or `Alt+P` depend on your os, and type `Note Macros: Run A Macro` then chose the macro you want to execute.
|
||||
|
||||
### Create Custom Note Macros
|
||||
|
||||
Create your own custom macros by adding them to your `settings.json` (Code|File > Preferences > User Settings). A full example can be found at [settings.json](https://github.com/kneely/note-macros/blob/master/settings.json)
|
||||
|
||||
For example:
|
||||
|
||||
This macro creates a Weekly note in the Weekly note Directory.
|
||||
|
||||
```json
|
||||
{
|
||||
"note-macros": {
|
||||
"Weekly": [
|
||||
{
|
||||
"type": "note",
|
||||
"directory": "Weekly",
|
||||
"extension": ".md",
|
||||
"name": "weekly-note",
|
||||
"date": "yyyy-W"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For an explanation of the fields please go to [note-macros - Explanation of Fields](https://github.com/kneely/note-macros#explanation-of-fields)
|
||||
|
||||
### Add Keybindings to Run your Macros
|
||||
|
||||
in `keybindings.json` (Code|File > Preferences > Keyboard Shortcuts) add bindings to your macros:
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "ctrl+cmd+/",
|
||||
"command": "note-macros.Weekly"
|
||||
}
|
||||
```
|
||||
|
||||
## Issues and Feedback
|
||||
|
||||
If you have any issues or questions please look at the [README.md](https://github.com/kneely/note-macros#note-macros) on the [note-macros](https://github.com/kneely/note-macros) GitHub.
|
||||
|
||||
If you run into any issues that are not fixed by referring to the README or feature requests please open an [issue](https://github.com/kneely/note-macros/issues).
|
||||
@@ -1,19 +1,21 @@
|
||||
<!-- omit in toc -->
|
||||
|
||||
# Recipes
|
||||
|
||||
A #recipe is a guide, tip or strategy for getting the most out of your Foam workspace!
|
||||
|
||||
- [Contribute](#contribute)
|
||||
- [Take smart notes](#take-smart-notes)
|
||||
- [Discover](#discover)
|
||||
- [Organise](#organise)
|
||||
- [Write](#write)
|
||||
- [Version control](#version-control)
|
||||
- [Publish](#publish)
|
||||
- [Collaborate](#collaborate)
|
||||
- [Workflow](#workflow)
|
||||
- [Creative ideas](#creative-ideas)
|
||||
- [Other](#other)
|
||||
- [Recipes](#recipes)
|
||||
- [Contribute](#contribute)
|
||||
- [Take smart notes](#take-smart-notes)
|
||||
- [Discover](#discover)
|
||||
- [Organise](#organise)
|
||||
- [Write](#write)
|
||||
- [Version control](#version-control)
|
||||
- [Publish](#publish)
|
||||
- [Collaborate](#collaborate)
|
||||
- [Workflow](#workflow)
|
||||
- [Creative ideas](#creative-ideas)
|
||||
- [Other](#other)
|
||||
|
||||
## Contribute
|
||||
|
||||
@@ -24,10 +26,11 @@ A #recipe is a guide, tip or strategy for getting the most out of your Foam work
|
||||
|
||||
- Introduction to Zettelkasten [[todo]]
|
||||
- Clip webpages with [[web-clipper]]
|
||||
- Convert Microsoft Word files into Markdown with [[markup-converter]]
|
||||
|
||||
## Discover
|
||||
|
||||
- Explore your notes using [[graph-visualization]]
|
||||
- Explore your notes using [[graph-view]]
|
||||
- Discover relationships with [[backlinking]]
|
||||
- Simulating [[unlinked-references]]
|
||||
|
||||
@@ -41,9 +44,8 @@ A #recipe is a guide, tip or strategy for getting the most out of your Foam work
|
||||
- Use shortcuts for [[creating-new-notes]]
|
||||
- Instantly create and access your [[daily-notes]]
|
||||
- Add and explore [[tags]]
|
||||
- Create [[note-templates]]
|
||||
- Create [[templates]]
|
||||
- Find [[orphans]]
|
||||
- Use custom [[note-macros]] to create weekly, monthly etc. notes
|
||||
- Draw [[diagrams-in-markdown]]
|
||||
- Prettify your links, [[automatically-expand-urls-to-well-titled-links]]
|
||||
- Style your environment with [[custom-markdown-preview-styles]]
|
||||
@@ -56,13 +58,13 @@ A #recipe is a guide, tip or strategy for getting the most out of your Foam work
|
||||
- _More..._
|
||||
- VS Code Advanced Features [[todo]] [[good-first-task]]
|
||||
- Focus with Zen Mode
|
||||
- Display content of other notes in the preview tab by [[including-notes]]
|
||||
- Display content of other notes in the preview tab by [[embeds]]
|
||||
|
||||
## Version control
|
||||
|
||||
- Quick commits with VS Code's built in [[git-integration]]
|
||||
- Store your workspace in an auto-synced GitHub repo with [[write-your-notes-in-github-gist]]
|
||||
- Sync your GitHub repo automatically using the [GitDoc VSCode Plugin](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.gitdoc).
|
||||
- Sync your GitHub repo automatically using the [GitDoc VSCode Plugin](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.gitdoc) [[automatic-git-syncing]].
|
||||
|
||||
## Publish
|
||||
|
||||
@@ -74,16 +76,17 @@ A #recipe is a guide, tip or strategy for getting the most out of your Foam work
|
||||
- Publish using community templates
|
||||
- [[publish-to-netlify-with-eleventy]] by [@juanfrank77](https://github.com/juanfrank77)
|
||||
- [[generate-gatsby-site]] by [@mathieudutour](https://github.com/mathieudutour) and [@hikerpig](https://github.com/hikerpig)
|
||||
- [foamy-nextjs](https://github.com/yenly/foamy-nextjs) by [@yenly](https://github.com/yenly)
|
||||
- [[generate-material-for-mkdocs-site]] by [@djplaner](https://github.com/djplaner)
|
||||
- Make the site your own by [[publish-to-github]].
|
||||
- Render math symbols, by either
|
||||
- adding client-side [[math-support-with-mathjax]] to the default [[publish-to-github-pages]] site
|
||||
- adding a custom Jekyll plugin to support [[math-support-with-katex]]
|
||||
- Export note to PDF [[export-to-pdf]]
|
||||
|
||||
## Collaborate
|
||||
|
||||
- Give your team push access to your GitHub repo [[todo]]
|
||||
- Real-time collaboration via VS Code Live Share [[todo]]
|
||||
- Give your team push access to your [GitHub repo](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-access-to-your-personal-repositories/inviting-collaborators-to-a-personal-repository)
|
||||
- Real-time collaboration via VS Code Live Share [[real-time-collaboration]]
|
||||
- Accept patches via GitHub PRs [[todo]]
|
||||
|
||||
## Workflow
|
||||
@@ -110,6 +113,7 @@ _See [[contribution-guide]] and [[how-to-write-recipes]]._
|
||||
[how-to-write-recipes]: how-to-write-recipes.md "How to Write Recipes"
|
||||
[todo]: ../../dev/todo.md "Todo"
|
||||
[web-clipper]: web-clipper.md "Web Clipper"
|
||||
[markup-converter]: markup-converter.md "Markup Converter"
|
||||
[graph-visualization]: ../features/graph-visualization.md "Graph Visualization"
|
||||
[backlinking]: ../features/backlinking.md "Backlinking"
|
||||
[unlinked-references]: ../../dev/unlinked-references.md "Unlinked references (stub)"
|
||||
@@ -119,7 +123,6 @@ _See [[contribution-guide]] and [[how-to-write-recipes]]._
|
||||
[tags]: ../features/tags.md "Tags"
|
||||
[note-templates]: ../features/note-templates.md "Note Templates"
|
||||
[orphans]: ../tools/orphans.md "Orphaned Notes"
|
||||
[note-macros]: note-macros.md "Custom Note Macros"
|
||||
[diagrams-in-markdown]: diagrams-in-markdown.md "Diagrams in Markdown"
|
||||
[automatically-expand-urls-to-well-titled-links]: automatically-expand-urls-to-well-titled-links.md "Automatically Expand URLs to Well-Titled Links"
|
||||
[custom-markdown-preview-styles]: ../features/custom-markdown-preview-styles.md "Custom Markdown Preview Styles"
|
||||
@@ -128,15 +131,19 @@ _See [[contribution-guide]] and [[how-to-write-recipes]]._
|
||||
[good-first-task]: ../../dev/good-first-task.md "Good First Task"
|
||||
[including-notes]: ../features/including-notes.md "Including notes in a note"
|
||||
[write-your-notes-in-github-gist]: write-your-notes-in-github-gist.md "Write your notes in GitHub Gist"
|
||||
[automatic-git-syncing]: automatic-git-syncing.md "Automatically Sync with Git"
|
||||
[publish-to-github-pages]: ../publishing/publish-to-github-pages.md "GitHub Pages"
|
||||
[publish-to-gitlab-pages]: ../publishing/publish-to-gitlab-pages.md "GitLab Pages"
|
||||
[publish-to-azure-devops-wiki]: ../publishing/publish-to-azure-devops-wiki.md "Publish to Azure DevOps Wiki"
|
||||
[publish-to-vercel]: ../publishing/publish-to-vercel.md "Publish to Vercel"
|
||||
[publish-to-netlify-with-eleventy]: ../publishing/publish-to-netlify-with-eleventy.md "Publish to Netlify with Eleventy"
|
||||
[generate-gatsby-site]: ../publishing/generate-gatsby-site.md "Generate a site using Gatsby"
|
||||
[generate-material-for-mkdocs-site]: generate-material-for-mkdocs-site.md "Generate a site using the Material for MkDocs theme"
|
||||
[publish-to-github]: ../publishing/publish-to-github.md "Publish to GitHub"
|
||||
[math-support-with-mathjax]: ../publishing/math-support-with-mathjax.md "Math Support"
|
||||
[math-support-with-katex]: ../publishing/math-support-with-katex.md "Katex Math Rendering"
|
||||
[export-to-pdf]: export-to-pdf.md "Export to PDF"
|
||||
[real-time-collaboration]: real-time-collaboration.md "Real-time Collaboration"
|
||||
[capture-notes-with-drafts-pro]: capture-notes-with-drafts-pro.md "Capture Notes With Drafts Pro"
|
||||
[capture-notes-with-shortcuts-and-github-actions]: capture-notes-with-shortcuts-and-github-actions.md "Capture Notes With Shortcuts and GitHub Actions"
|
||||
[//end]: # "Autogenerated link references"
|
||||
|
||||
@@ -53,7 +53,7 @@ If such an app was worth building, it would have to have the following features:
|
||||
|
||||
- Instant loading and syncing for quick notes
|
||||
- Sleek, simple, beautifully designed user experience.
|
||||
- Ability to search and navigate forward links and back links (onlly in paid GitJournal version)
|
||||
- Ability to search and navigate forward links and back links (only in paid GitJournal version)
|
||||
- Killer feature that makes it the best note taking tool for Foam (?)
|
||||
|
||||
Given the effort vs reward ratio, it's a low priority for core team, but if someone wants to work on this, we can provide support! Talk to us on the #mobile-apps channel on [Foam Discord](https://foambubble.github.io/join-discord/w).
|
||||
|
||||
@@ -44,7 +44,7 @@ When editing a file, you can easily navigate `[[links]]` by hovering over them t
|
||||
|
||||
You can view a page's backlinks using either of the following techniques:
|
||||
|
||||
1. Expanding the file's node in the `Repositories` tree, since it's child nodes will represent backlinks. This makes it easy to browse your pages and their backlinks in a single hierachical view.
|
||||
1. Expanding the file's node in the `Repositories` tree, since it's child nodes will represent backlinks. This makes it easy to browse your pages and their backlinks in a single hierarchical view.
|
||||
|
||||
1. Opening a file, and then viewing it's backlinks list at the bottom of the editor view. This makes it easy to read a page and then see its backlinks in a contextually rich way.
|
||||
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
],
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"version": "0.20.0"
|
||||
"version": "0.29.1"
|
||||
}
|
||||
|
||||
10
package.json
10
package.json
@@ -17,15 +17,16 @@
|
||||
"clean": "lerna run clean",
|
||||
"build": "lerna run build",
|
||||
"test": "yarn workspace foam-vscode test",
|
||||
"test:unit": "yarn workspace foam-vscode test:unit",
|
||||
"lint": "lerna run lint",
|
||||
"watch": "lerna run watch --concurrency 20 --stream"
|
||||
"watch": "lerna run watch --concurrency 20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"all-contributors-cli": "^6.16.1",
|
||||
"lerna": "^3.22.1"
|
||||
"lerna": "^6.4.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
"node": ">=18"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
@@ -33,10 +34,11 @@
|
||||
}
|
||||
},
|
||||
"prettier": {
|
||||
"arrowParens": "avoid",
|
||||
"printWidth": 80,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
.vscode/**
|
||||
.vscode-test/**
|
||||
out/test/**
|
||||
out/**/*.test.*
|
||||
out/**/*.spec.*
|
||||
test-data/**
|
||||
src/**
|
||||
jest.config.js
|
||||
esbuild.js
|
||||
.test-workspace
|
||||
.gitignore
|
||||
vsc-extension-quickstart.md
|
||||
**/tsconfig.json
|
||||
|
||||
@@ -4,12 +4,458 @@ All notable changes to the "foam-vscode" extension will be documented in this fi
|
||||
|
||||
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
|
||||
|
||||
## 0.29.1
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Load graph in code server (#1400)
|
||||
- Don't treat text in single brackets as links/placeholders if missing a ref (#1545, #1546)
|
||||
- Added option to show graph on startup (#1542)
|
||||
- Added include patterns for Foam notes (#1550, #1422)
|
||||
- Added support for emoji variants in tags (#1536, #1549)
|
||||
- Added support for wikilink with aliases within tables (#1544, #1552)
|
||||
|
||||
## 0.29.0
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Improved support for wikilink references (#1531, #1116, #1504)
|
||||
- Improved tag search to include YAML tags (#1530, #1516)
|
||||
- Improved template filepath sanitization (#1533)
|
||||
- Added FOAM_DATE_WEEK_YEAR (#1532 - thanks @ChThH)
|
||||
- Fixed graph panel moving when revealed - graph now stays in its current location (#1540)
|
||||
|
||||
## [0.28.3] - 2025-10-03
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed sanitation of filepath for templates (#1529 #1526)
|
||||
|
||||
## [0.28.2] - 2025-10-01
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed build for web extension (#1523)
|
||||
|
||||
## [0.28.1] - 2025-09-25
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Removed duplicate links in dataviz graph (#1511 - thanks @Tenormis)
|
||||
- Use letter case to further disambiguate note identifiers (#1519, #1303)
|
||||
- Sanitize `filepath` before creating note from template (#1520, #1216)
|
||||
|
||||
## [0.28.0] - 2025-09-24
|
||||
|
||||
Features:
|
||||
|
||||
- Added workspace symbols for note aliases (#1461)
|
||||
- Added tag navigation and peek (#1510)
|
||||
- Added support for tag refactoring (#1513)
|
||||
- Added support for wikilink images styling (#1514)
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Added support for image link title attribute (#1514)
|
||||
- Exposing FOAM_DATE_DAY_ISO variable (#1512 - thanks @ChThH)
|
||||
|
||||
## [0.27.7] - 2025-09-13
|
||||
|
||||
Features:
|
||||
|
||||
- Added `FOAM_DATE_DAY_ISO` template variable for ISO weekday number (1-7, Monday=1)
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed root-path relative links opening new notes instead of existing files (#1505)
|
||||
|
||||
## [0.27.6] - 2025-09-13
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed URI handling across scheme/authority (fixes #1404)
|
||||
|
||||
## [0.27.5] - 2025-09-06
|
||||
|
||||
Features:
|
||||
|
||||
- Added `FOAM_CURRENT_DIR` template variable for explicit current directory context (#1507)
|
||||
|
||||
## [0.27.4] - 2025-09-05
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed double template application when using absolute `filepath` properties (#1499)
|
||||
|
||||
## [0.27.3] - 2025-09-05
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Improved timezone handling for create-note when passing string date
|
||||
- Added debugging for daily note issue (#1505, #1502, #1494)
|
||||
- Deprecated daily note settings (use daily-note template instead)
|
||||
|
||||
## [0.27.2] - 2025-07-25
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Ensure absolute paths used in create-note command are relative to workspace
|
||||
- Improved Windows path handling in URIs
|
||||
|
||||
## [0.27.1] - 2025-07-24
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed handling of daily note template on Windows machines (#1492)
|
||||
|
||||
## [0.27.0] - 2025-07-23
|
||||
|
||||
Features:
|
||||
|
||||
- Introduced a unified note creation engine supporting both Markdown and JavaScript templates
|
||||
|
||||
Internal:
|
||||
|
||||
- Improved testing framework by creating a mocked VS Code environment
|
||||
|
||||
## [0.26.12] - 2025-06-18
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fix YAML parsing (#1467)
|
||||
- Improved regex parsing (#1479 - thanks @s-jacob-powell)
|
||||
|
||||
## [0.26.11] - 2025-04-19
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Support for custom fonts in graph view (#1457 - thanks @Tenormis)
|
||||
|
||||
## [0.26.10] - 2025-03-29
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- General improvment of wiki embeds (#1443)
|
||||
|
||||
## [0.26.9] - 2025-03-29
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Defensive get of link object ID in graph (#1438)
|
||||
|
||||
Internal:
|
||||
|
||||
- Updated `force-graph` library
|
||||
|
||||
## [0.26.8] - 2025-03-14
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Tag hierarchy now visible in graph (#1436)
|
||||
- Improved Notes Explorer layout
|
||||
|
||||
## [0.26.7] - 2025-03-09
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Improved parsing of tags (fixes #1434)
|
||||
|
||||
## [0.26.6] - 2025-03-08
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Improved graph based navigation when running in virtual workspace
|
||||
- Improved wikilink embeds and fixed cycle detection issue (#1430)
|
||||
- Added links in tags to navigate to corresponding tag explorer item (#1432)
|
||||
|
||||
Internal:
|
||||
|
||||
- Renamed branch from `master` to `main`
|
||||
|
||||
## [0.26.5] - 2025-02-21
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Improved handling of virtual FS URIs (#1426)
|
||||
|
||||
## [0.26.4] - 2024-11-12
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Improved handling of virtual FS URIs (#1409)
|
||||
|
||||
## [0.26.3] - 2024-11-12
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Finetuned use of triemap (#1411 - thanks @pderaaij)
|
||||
|
||||
## [0.26.2] - 2024-11-06
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Performance improvements (#1406 - thanks @pderaaij)
|
||||
|
||||
## [0.26.1] - 2024-10-09
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed issue with Buffer in web extension (#1401 - thanks @pderaaij)
|
||||
|
||||
## [0.26.0] - 2024-10-01
|
||||
|
||||
Features:
|
||||
|
||||
- Foam is now a web extension! (#1395 - many thanks @pderaaij)
|
||||
|
||||
## [0.25.12] - 2024-07-13
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Improved YAML support (#1367)
|
||||
- Added convesion of wikilinks to markdown links (#1365 - thanks @hereistheusername)
|
||||
- Refactored util and settings code
|
||||
|
||||
## [0.25.11] - 2024-03-18
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Actually fixed bug in graph computation (#1345)
|
||||
|
||||
## [0.25.10] - 2024-03-18
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed bug in graph computation (#1345)
|
||||
|
||||
## [0.25.9] - 2024-03-17
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Improved note creation from placeholder (#1344)
|
||||
|
||||
## [0.25.8] - 2024-02-21
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Upgraded dataformat to improve support for daily note naming (#1326 - thanks @rcyeh)
|
||||
|
||||
## [0.25.7] - 2024-01-16
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Modifies url encoding to target only the filename and skip spaces (#1322 - thanks @MABruni)
|
||||
- Minor tweak to quick action menu with suggestions for section name
|
||||
|
||||
## [0.25.6] - 2023-12-13
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed wikilink definition encoding (#1311 - thanks @MABruni)
|
||||
|
||||
## [0.25.5] - 2023-11-30
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Using note title in preview (#1309)
|
||||
|
||||
## [0.25.4] - 2023-09-19
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Added support for linking sections within same document (#1289)
|
||||
- Fixed note embedding bug (#1286 - thanks @badsketch)
|
||||
|
||||
## [0.25.3] - 2023-09-07
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed incorrect handling of embedding of non-existing notes (#1283 - thanks @badsketch)
|
||||
- Introduced Note Embedding Sytanx (#1281 - thanks @badsketch)
|
||||
- Attachments are not considered when computing orphan notes (#1242)
|
||||
|
||||
## [0.25.2] - 2023-09-02
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Added content-only embed styles (#1279 - thanks @badsketch)
|
||||
- Added expand-all button to tree views (#1276)
|
||||
|
||||
## [0.25.1] - 2023-08-23
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Added support for path parameter in filter (#1250)
|
||||
- Added grouping and filtering to tag explorer (#1275)
|
||||
- Added new setting to control note embedding (#1273 - thanks @badsketch)
|
||||
- Added last week's days to snippets (#1248 - thanks @jimgraham)
|
||||
|
||||
Internal:
|
||||
|
||||
- Updated jest to v29 (#1271 - thanks @nicholas-l)
|
||||
- Improved test cleanup and management (#1274)
|
||||
|
||||
## [0.25.0] - 2023-06-30
|
||||
|
||||
Features:
|
||||
|
||||
- Support for multiple extensions and custom default extension (#1235)
|
||||
- Added `FOAM_TITLE_SAFE` template variable (#1232)
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Connections panel tweaks (#1233)
|
||||
|
||||
## [0.24.0] - 2023-05-19
|
||||
|
||||
Features:
|
||||
|
||||
- Converted backlinks panel into more general connections panel (#1230)
|
||||
|
||||
Internal:
|
||||
|
||||
- Improved janitor code (#1228)
|
||||
- Refactored code related to tree view panels (#1226)
|
||||
- Lint and cleanup (#1224)
|
||||
|
||||
## [0.23.0] - 2023-05-06
|
||||
|
||||
Features:
|
||||
|
||||
- Added notes explorer (#1223)
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Enabled tag completion in front matter (#1191 - thanks @jimgraham)
|
||||
- Various improvements to tree views (#1220)
|
||||
|
||||
## [0.22.2] - 2023-04-20
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Support to show placeholders only for open file in panel (#1201, #988)
|
||||
- Show note block in panels on hover preview (#1201, #800)
|
||||
- Show tag references within tag explorer (#1201)
|
||||
- Improved structure of view related commands (#1201)
|
||||
- Ignore `.foam` directory
|
||||
|
||||
## [0.22.1] - 2023-04-15
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Allow the `#` char to trigger tag autocompletion (#1192, #1189 - thanks @jimgraham)
|
||||
|
||||
## [0.22.0] - 2023-04-15
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Added support for deep tag hierarchy in Tag Explorer panel (#1134, #1194)
|
||||
- Consolidated and improved Backlinks, Placeholders and Orphans panels (#1196)
|
||||
- Fixed note resolution when using template without defined path (#1197)
|
||||
|
||||
## [0.21.4] - 2023-04-14
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed issue with generated daily note template due to path escape (#1188, #1190)
|
||||
|
||||
## [0.21.3] - 2023-04-12
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed relative path from workspace root in templates (#1188)
|
||||
|
||||
## [0.21.2] - 2023-04-11
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed embed with relative paths (#1168, #1170)
|
||||
- Improved multi-root folder support for daily notes (#1126, #1175)
|
||||
- Improved use of tag completion (#1183 - thanks @jimgraham)
|
||||
- Fixed relative path use in note creation when using templates (#1170)
|
||||
|
||||
Internal:
|
||||
|
||||
- Sync user docs with foam-template docs (#1180 - thanks @infogulch)
|
||||
|
||||
## [0.21.1] - 2023-02-24
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed note creation from placeholder (#1172)
|
||||
|
||||
## [0.21.0] - 2023-02-16
|
||||
|
||||
Features:
|
||||
|
||||
- Added support for filters for the `foam-vscode.open-resource` command (#1161)
|
||||
|
||||
## [0.20.8] - 2023-02-10
|
||||
|
||||
Internal:
|
||||
|
||||
- Updated most dependencies (#1160)
|
||||
|
||||
## [0.20.7] - 2023-01-31
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Inform the user that directory renaming is not supported (#1143)
|
||||
- Fixed extra `web` directory in published extension (#1152 - thanks @piousdeer)
|
||||
|
||||
## [0.20.6] - 2023-01-21
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Updated minimum VS Code version to 1.70.0 (#1140)
|
||||
- Fixed preview links with sections (#1135 - thanks @badsketch)
|
||||
- Added setting for creating new notes in root or current dir (#1142)
|
||||
|
||||
## [0.20.5] - 2023-01-04
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed entry count in orphan, placeholder, tags-explorer panels (#1131 - thanks @badsketch)
|
||||
|
||||
## [0.20.4] - 2023-01-04
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Added support for emoji tags (#1125 - thanks @badsketch)
|
||||
|
||||
## [0.20.3] - 2022-12-19
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Show number of entries in title for orphan, placeholder, tag treeviews
|
||||
|
||||
## [0.20.2] - 2022-10-26
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Creating new note uses default template when none is provided (#1094)
|
||||
|
||||
Internal:
|
||||
|
||||
- Changed matcher implementation to remove dependency on micromatch/glob
|
||||
- Removed unnecessary dependencies and assets from extension
|
||||
|
||||
## [0.20.1] - 2022-10-13
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Improved support for daily notes in multi root workspace (#1073)
|
||||
- Create note from placeholder using template (#1061 - thanks @Dominic-DallOsto)
|
||||
- Improved support for globs in multi root workspace (#1083)
|
||||
|
||||
## [0.20.0] - 2022-09-30
|
||||
|
||||
New Features:
|
||||
Features:
|
||||
|
||||
- Added `foam-vscode.create-note` command, which can be very customized for several use cases (#1076)
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Removed `+` as a trigger char for date snippets
|
||||
- Improved attachment support (#915)
|
||||
- Improved error handling when starting Foam without an open workspace (#908)
|
||||
@@ -20,6 +466,7 @@ Fixes and Improvements:
|
||||
## [0.19.5] - 2022-09-01
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Added `FOAM_DATE_WEEK` variable (#1053 - Thanks @dmurph)
|
||||
- Fixed extension inclusion when generating references for attachments
|
||||
- Link completion label can be note title as well as path (#1059)
|
||||
@@ -28,20 +475,24 @@ Fixes and Improvements:
|
||||
## [0.19.4] - 2022-08-07
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed note embed in preview (#1052)
|
||||
|
||||
## [0.19.3] - 2022-08-04
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Image embeds fixed in preview (#1036)
|
||||
|
||||
## [0.19.2] - 2022-08-04
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Added support for angle markdown links (#1044)
|
||||
- Filter out invalid file name chars when creating note (#1042)
|
||||
|
||||
Internal:
|
||||
|
||||
- Reorganized docs (#1031, thanks @infogulch)
|
||||
- Fixed documentation links (#1046)
|
||||
- Preview code refactoring
|
||||
@@ -49,39 +500,46 @@ Internal:
|
||||
## [0.19.1] - 2022-07-11
|
||||
|
||||
Internal:
|
||||
|
||||
- Introduced cache for markdown parser (#1030)
|
||||
- Various code refactorings
|
||||
|
||||
## [0.19.0] - 2022-07-07
|
||||
|
||||
New Features:
|
||||
Features:
|
||||
|
||||
- Support for attachments (PDF) and images (#1027)
|
||||
- Support for opening day notes for other days as well (#1026, thanks @alper)
|
||||
|
||||
## [0.18.5] - 2022-06-29
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Support for `alias` YAML property to define note alias (#1014 - thanks @lingyv-li)
|
||||
|
||||
Internal:
|
||||
|
||||
- Improved extension bundling (#1015 - thanks @lingyv-li)
|
||||
- Use `vscode.workspace.fs` instead of `fs` (#1005 - thanks @joshdover)
|
||||
|
||||
## [0.18.4] - 2022-06-03
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- move past `]]` when writing wikilinks (#998 - thanks @Lauviah0622)
|
||||
- highlight improvements (#890 - thanks @memeplex)
|
||||
|
||||
## [0.18.3] - 2022-04-17
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Better reporting when links fail to resolve
|
||||
- Failing link resolution during graph computation no longer fatal
|
||||
|
||||
## [0.18.2] - 2022-04-14
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed parsing error on empty direct links (#980 - thanks @chrisUsick)
|
||||
- Improved rendering in preview of wikilinks that have link definitions (#979 - thanks @josephdecock)
|
||||
- Restored handling of section-only wikilinks (#981)
|
||||
@@ -89,6 +547,7 @@ Fixes and Improvements:
|
||||
## [0.18.1] - 2022-04-13
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed parsing error for direct links with square brackets in them (#977)
|
||||
- Improved markdown direct link resolution (#972)
|
||||
- Improved templates support for custom paths (#970)
|
||||
@@ -96,14 +555,17 @@ Fixes and Improvements:
|
||||
## [0.18.0] - 2022-04-11
|
||||
|
||||
Features:
|
||||
|
||||
- Link synchronization on file rename
|
||||
|
||||
Internal:
|
||||
|
||||
- Changed graph computation on workspace change to simplify code
|
||||
|
||||
## [0.17.8] - 2022-04-01
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Do not add ignored files to Foam upon change (#480)
|
||||
- Restore full use of editor.action.openLink (#693)
|
||||
- Minor performance improvements
|
||||
@@ -111,49 +573,58 @@ Fixes and Improvements:
|
||||
## [0.17.7] - 2022-03-29
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Include links with sections in backlinks (#895)
|
||||
- Improved navigation when document editor is already open
|
||||
|
||||
## [0.17.6] - 2022-03-03
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Don't fail on error when scannig workspace (#943 - thanks @develmusa)
|
||||
|
||||
## [0.17.5] - 2022-02-22
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Added FOAM_SLUG template variable (#865 - Thanks @techCarpenter)
|
||||
|
||||
## [0.17.4] - 2022-02-13
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Improvements to Foam variables in templates (#882 - thanks @movermeyer)
|
||||
- Foam variables can now be used just any other VS Code variables, including in combination with placeholders and transformers
|
||||
|
||||
## [0.17.3] - 2022-01-14
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Fixed autocompletion with tags (#885 - thanks @memeplex)
|
||||
- Improved "Open Daily Note" to be usabled in tasks (#897 - thanks @MCluck90)
|
||||
|
||||
## [0.17.2] - 2021-12-22
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Improved support for wikilinks in titles (#878)
|
||||
- Use syntax injection for wikilinks (#876 - thanks @memeplex)
|
||||
- Fix when applying text edits in last line
|
||||
- Fix when applying text edits in last line
|
||||
|
||||
Internal:
|
||||
|
||||
- DX: Clean up of testing setup (#881 - thanks @memeplex)
|
||||
|
||||
## [0.17.1] - 2021-12-16
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Decorate markdown files only (#857)
|
||||
- Fix template placeholders issue (#859)
|
||||
- Improved replacement range for link completion
|
||||
|
||||
Internal:
|
||||
|
||||
- Major URI/path handling refactoring (#858 - thanks @memeplex)
|
||||
|
||||
## [0.17.0] - 2021-12-08
|
||||
@@ -209,7 +680,6 @@ Fixes and Improvements:
|
||||
- Link Reference Generation is now OFF by default
|
||||
- Fixed preview navigation (#830)
|
||||
|
||||
|
||||
## [0.15.5] - 2021-11-15
|
||||
|
||||
Fixes and Improvements:
|
||||
@@ -516,7 +986,7 @@ Fixes and Improvements:
|
||||
|
||||
## [0.7.1] - 2020-11-27
|
||||
|
||||
New Feature:
|
||||
Features:
|
||||
|
||||
- Foam logging can now be inspected in VsCode Output panel (#377)
|
||||
|
||||
@@ -528,7 +998,7 @@ Fixes and Improvements:
|
||||
|
||||
## [0.7.0] - 2020-11-25
|
||||
|
||||
New Features:
|
||||
Features:
|
||||
|
||||
- Foam stays in sync with changes in notes
|
||||
- Dataviz: Added multiple selection in graph (shift+click on node)
|
||||
@@ -540,7 +1010,7 @@ Fixes and Improvements:
|
||||
|
||||
## [0.6.0] - 2020-11-19
|
||||
|
||||
New features:
|
||||
Features:
|
||||
|
||||
- Added command to create notes from templates (#115 - Thanks @ingalless)
|
||||
|
||||
@@ -555,7 +1025,7 @@ Fixes and Improvements:
|
||||
|
||||
## [0.5.0] - 2020-11-09
|
||||
|
||||
New features:
|
||||
Features:
|
||||
|
||||
- Added tags panel (#311)
|
||||
|
||||
@@ -569,7 +1039,7 @@ Fixes and Improvements:
|
||||
|
||||
## [0.4.0] - 2020-10-28
|
||||
|
||||
New features:
|
||||
Features:
|
||||
|
||||
- Added `Foam: Show Graph` command
|
||||
- Added date snippets (/+1d, ...) to create wikilinks to dates in daily note format
|
||||
@@ -597,7 +1067,7 @@ Fixes and improvements:
|
||||
|
||||
## [0.3.0] - 2020-07-25
|
||||
|
||||
New features:
|
||||
Features:
|
||||
|
||||
- [Daily Notes](https://foambubble.github.io/foam/daily-notes)
|
||||
- [Janitor](https://foambubble.github.io/foam/workspace-janitor) for updating headings and link references across your workspace
|
||||
|
||||
33
packages/foam-vscode/LICENSE
Normal file
33
packages/foam-vscode/LICENSE
Normal file
@@ -0,0 +1,33 @@
|
||||
The MIT Licence (MIT)
|
||||
|
||||
Copyright 2020 - present Jani Eväkallio <jani.evakallio@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Where noted, some code uses the following license:
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2015 - present Microsoft Corporation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
@@ -1,9 +1,10 @@
|
||||
# Foam for VSCode
|
||||
|
||||
[](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode)
|
||||
[](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode)
|
||||
[](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode)
|
||||
[](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode)
|
||||
[](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode)
|
||||
[](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode)
|
||||
[](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode)
|
||||
[](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode)
|
||||
[](https://foambubble.github.io/join-discord/g)
|
||||
|
||||
> You can join the Foam Community on the [Foam Discord](https://foambubble.github.io/join-discord/e)
|
||||
|
||||
@@ -95,7 +96,7 @@ Foam also supports hierarchical tags.
|
||||
|
||||
### Orphans and Placeholder Panels
|
||||
|
||||
Orphans are note that have no inbound nor outbound links.
|
||||
Orphans are note that have no inbound nor outbound links.
|
||||
Placeholders are dangling links, or notes without content.
|
||||
Keep them under control, and your knowledge base in better state, by using this panel.
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 604 KiB |
114
packages/foam-vscode/esbuild.js
Normal file
114
packages/foam-vscode/esbuild.js
Normal file
@@ -0,0 +1,114 @@
|
||||
// also see https://code.visualstudio.com/api/working-with-extensions/bundling-extension
|
||||
const assert = require('assert');
|
||||
const esbuild = require('esbuild');
|
||||
const polyfillPlugin = require('esbuild-plugin-polyfill-node');
|
||||
|
||||
// pass the platform to esbuild as an argument
|
||||
|
||||
function getPlatform() {
|
||||
const args = process.argv.slice(2);
|
||||
const pArg = args.find(arg => arg.startsWith('--platform='));
|
||||
if (pArg) {
|
||||
return pArg.split('=')[1];
|
||||
}
|
||||
throw new Error('No platform specified. Pass --platform <web|node>.');
|
||||
}
|
||||
|
||||
const platform = getPlatform();
|
||||
assert(['web', 'node'].includes(platform), 'Platform must be "web" or "node".');
|
||||
|
||||
const production = process.argv.includes('--production');
|
||||
const watch = process.argv.includes('--watch');
|
||||
|
||||
const config = {
|
||||
web: {
|
||||
platform: 'browser',
|
||||
format: 'cjs',
|
||||
outfile: `out/bundles/extension-web.js`,
|
||||
define: {
|
||||
global: 'globalThis',
|
||||
},
|
||||
plugins: [
|
||||
polyfillPlugin.polyfillNode({
|
||||
// Options (optional)
|
||||
}),
|
||||
{
|
||||
name: 'path-browserify',
|
||||
setup(build) {
|
||||
build.onResolve({ filter: /^path$/ }, args => {
|
||||
return { path: require.resolve('path-browserify') };
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'wikilink-embed',
|
||||
setup(build) {
|
||||
build.onResolve({ filter: /wikilink-embed/ }, args => {
|
||||
return {
|
||||
path: require.resolve(
|
||||
args.resolveDir + '/wikilink-embed-web-extension.ts'
|
||||
),
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
node: {
|
||||
platform: 'node',
|
||||
format: 'cjs',
|
||||
outfile: `out/bundles/extension-node.js`,
|
||||
plugins: [],
|
||||
},
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const ctx = await esbuild.context({
|
||||
...config[platform],
|
||||
entryPoints: ['src/extension.ts'],
|
||||
bundle: true,
|
||||
minify: production,
|
||||
sourcemap: !production,
|
||||
sourcesContent: false,
|
||||
external: ['vscode'],
|
||||
logLevel: 'silent',
|
||||
plugins: [
|
||||
...config[platform].plugins,
|
||||
/* add to the end of plugins array */
|
||||
esbuildProblemMatcherPlugin,
|
||||
],
|
||||
});
|
||||
if (watch) {
|
||||
await ctx.watch();
|
||||
} else {
|
||||
await ctx.rebuild();
|
||||
await ctx.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {import('esbuild').Plugin}
|
||||
*/
|
||||
const esbuildProblemMatcherPlugin = {
|
||||
name: 'esbuild-problem-matcher',
|
||||
|
||||
setup(build) {
|
||||
build.onStart(() => {
|
||||
console.log('[watch] build started');
|
||||
});
|
||||
build.onEnd(result => {
|
||||
result.errors.forEach(({ text, location }) => {
|
||||
console.error(`✘ [ERROR] ${text}`);
|
||||
console.error(
|
||||
` ${location.file}:${location.line}:${location.column}:`
|
||||
);
|
||||
});
|
||||
console.log('[watch] build finished');
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
main().catch(e => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -123,7 +123,7 @@ module.exports = {
|
||||
// runner: "jest-runner",
|
||||
|
||||
// The paths to modules that run some code to configure or set up the testing environment before each test
|
||||
// setupFiles: [],
|
||||
setupFiles: ['<rootDir>/src/test/support/jest-setup.ts'],
|
||||
|
||||
// A list of paths to modules that run some code to configure or set up the testing framework before each test
|
||||
setupFilesAfterEnv: ['jest-extended'],
|
||||
@@ -153,9 +153,8 @@ module.exports = {
|
||||
|
||||
// The regexp pattern or array of patterns that Jest uses to detect test files
|
||||
// This is overridden in every runCLI invocation but it's here as the default
|
||||
// for vscode-jest. We only want unit tests in the test explorer (sidebar),
|
||||
// since spec tests require the entire extension host to be launched before.
|
||||
testRegex: ['\\.test\\.ts$'],
|
||||
// for vscode-jest. Both .test.ts and .spec.ts files use the vscode-mock.
|
||||
testRegex: ['\\.(test|spec)\\.ts$'],
|
||||
|
||||
// This option allows the use of a custom results processor
|
||||
// testResultsProcessor: undefined,
|
||||
|
||||
@@ -8,32 +8,24 @@
|
||||
"type": "git"
|
||||
},
|
||||
"homepage": "https://github.com/foambubble/foam",
|
||||
"version": "0.20.0",
|
||||
"version": "0.29.1",
|
||||
"license": "MIT",
|
||||
"publisher": "foam",
|
||||
"engines": {
|
||||
"vscode": "^1.47.1"
|
||||
"vscode": "^1.96.0"
|
||||
},
|
||||
"icon": "assets/icon/FOAM_ICON_256.png",
|
||||
"categories": [
|
||||
"Other"
|
||||
],
|
||||
"activationEvents": [
|
||||
"workspaceContains:.vscode/foam.json",
|
||||
"onView:foam-vscode.tags-explorer",
|
||||
"onCommand:foam-vscode.update-wikilinks",
|
||||
"onCommand:foam-vscode.open-daily-note",
|
||||
"onCommand:foam-vscode.update-graph",
|
||||
"onCommand:foam-vscode.open-random-note",
|
||||
"onCommand:foam-vscode.janitor",
|
||||
"onCommand:foam-vscode.copy-without-brackets",
|
||||
"onCommand:foam-vscode.show-graph",
|
||||
"onCommand:foam-vscode.create-new-template",
|
||||
"onCommand:foam-vscode.create-note",
|
||||
"onCommand:foam-vscode.create-note-from-template",
|
||||
"onCommand:foam-vscode.create-note-from-default-template"
|
||||
],
|
||||
"main": "./out/extension.js",
|
||||
"main": "./out/bundles/extension-node.js",
|
||||
"browser": "./out/bundles/extension-web.js",
|
||||
"capabilities": {
|
||||
"untrustedWorkspaces": {
|
||||
"supported": "limited",
|
||||
"description": "No expressions are allowed in filters."
|
||||
}
|
||||
},
|
||||
"contributes": {
|
||||
"markdown.markdownItPlugins": true,
|
||||
"markdown.previewStyles": [
|
||||
@@ -62,28 +54,41 @@
|
||||
"views": {
|
||||
"explorer": [
|
||||
{
|
||||
"id": "foam-vscode.backlinks",
|
||||
"name": "Backlinks",
|
||||
"id": "foam-vscode.connections",
|
||||
"name": "Connections",
|
||||
"icon": "$(references)",
|
||||
"contextualTitle": "Backlinks"
|
||||
"contextualTitle": "Foam"
|
||||
},
|
||||
{
|
||||
"id": "foam-vscode.tags-explorer",
|
||||
"name": "Tag Explorer",
|
||||
"icon": "$(tag)",
|
||||
"contextualTitle": "Tags Explorer"
|
||||
"contextualTitle": "Foam"
|
||||
},
|
||||
{
|
||||
"id": "foam-vscode.notes-explorer",
|
||||
"name": "Notes",
|
||||
"icon": "$(notebook)",
|
||||
"contextualTitle": "Foam"
|
||||
},
|
||||
{
|
||||
"id": "foam-vscode.orphans",
|
||||
"name": "Orphans",
|
||||
"icon": "$(debug-gripper)",
|
||||
"contextualTitle": "Orphans"
|
||||
"contextualTitle": "Foam"
|
||||
},
|
||||
{
|
||||
"id": "foam-vscode.placeholders",
|
||||
"name": "Placeholders",
|
||||
"icon": "$(debug-disconnect)",
|
||||
"contextualTitle": "Placeholders"
|
||||
"contextualTitle": "Foam"
|
||||
},
|
||||
{
|
||||
"when": "config.foam.experimental.ai",
|
||||
"id": "foam-vscode.related-notes",
|
||||
"name": "Related Notes (AI)",
|
||||
"icon": "$(sparkle)",
|
||||
"contextualTitle": "Foam"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -93,8 +98,8 @@
|
||||
"contents": "No tags found. Notes that contain tags will show up here. You may add tags to a note with a hashtag (#tag) or by adding a tag list to the front matter (tags: tag1, tag2)."
|
||||
},
|
||||
{
|
||||
"view": "foam-vscode.backlinks",
|
||||
"contents": "No backlinks found for selected resource."
|
||||
"view": "foam-vscode.connections",
|
||||
"contents": "Nothing found for the selected resource and the current filter."
|
||||
},
|
||||
{
|
||||
"view": "foam-vscode.orphans",
|
||||
@@ -102,29 +107,136 @@
|
||||
},
|
||||
{
|
||||
"view": "foam-vscode.placeholders",
|
||||
"contents": "No placeholders found. Pending links and notes without content will show up here."
|
||||
"contents": "No placeholders found for selected resource or workspace."
|
||||
},
|
||||
{
|
||||
"view": "foam-vscode.related-notes",
|
||||
"contents": "Open a note to see related notes.",
|
||||
"when": "config.foam.experimental.ai && foam.relatedNotes.state == 'no-note'"
|
||||
},
|
||||
{
|
||||
"view": "foam-vscode.related-notes",
|
||||
"contents": "Notes haven't been analyzed yet.\n[Analyze Notes](command:foam-vscode.build-embeddings)\nAnalyze your notes to discover similar content.",
|
||||
"when": "config.foam.experimental.ai && foam.relatedNotes.state == 'no-embedding'"
|
||||
},
|
||||
{
|
||||
"view": "foam-vscode.related-notes",
|
||||
"contents": "No similar notes found for the current note.",
|
||||
"when": "config.foam.experimental.ai && foam.relatedNotes.state == 'ready'"
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
"view/item/context": [
|
||||
{
|
||||
"command": "foam-vscode.search-tag",
|
||||
"when": "view == foam-vscode.tags-explorer && viewItem == tag",
|
||||
"group": "inline",
|
||||
"icon": "$(search)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.rename-tag",
|
||||
"when": "view == foam-vscode.tags-explorer && viewItem == tag",
|
||||
"group": "inline",
|
||||
"icon": "$(edit)"
|
||||
}
|
||||
],
|
||||
"editor/context": [
|
||||
{
|
||||
"command": "foam-vscode.rename-tag",
|
||||
"when": "editorTextFocus && resourceExtname == '.md'",
|
||||
"group": "foam",
|
||||
"title": "Rename Tag"
|
||||
}
|
||||
],
|
||||
"view/title": [
|
||||
{
|
||||
"command": "foam-vscode.group-orphans-by-folder",
|
||||
"when": "view == foam-vscode.orphans && foam-vscode.orphans-grouped-by-folder == false",
|
||||
"command": "foam-vscode.views.connections.show:backlinks",
|
||||
"when": "view == foam-vscode.connections && foam-vscode.views.connections.show == 'all links'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.group-orphans-off",
|
||||
"when": "view == foam-vscode.orphans && foam-vscode.orphans-grouped-by-folder == true",
|
||||
"command": "foam-vscode.views.connections.show:forward-links",
|
||||
"when": "view == foam-vscode.connections && foam-vscode.views.connections.show == 'backlinks'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.group-placeholders-by-folder",
|
||||
"when": "view == foam-vscode.placeholders && foam-vscode.placeholders-grouped-by-folder == false",
|
||||
"command": "foam-vscode.views.connections.show:all-links",
|
||||
"when": "view == foam-vscode.connections && foam-vscode.views.connections.show == 'forward links'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.group-placeholders-off",
|
||||
"when": "view == foam-vscode.placeholders && foam-vscode.placeholders-grouped-by-folder == true",
|
||||
"command": "foam-vscode.views.orphans.group-by:folder",
|
||||
"when": "view == foam-vscode.orphans && foam-vscode.views.orphans.group-by == 'off'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.orphans.group-by:off",
|
||||
"when": "view == foam-vscode.orphans && foam-vscode.views.orphans.group-by == 'folder'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.tags-explorer.show:for-current-file",
|
||||
"when": "view == foam-vscode.tags-explorer && foam-vscode.views.tags-explorer.show == 'all'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.tags-explorer.show:all",
|
||||
"when": "view == foam-vscode.tags-explorer && foam-vscode.views.tags-explorer.show == 'for-current-file'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.tags-explorer.group-by:folder",
|
||||
"when": "view == foam-vscode.tags-explorer && foam-vscode.views.tags-explorer.group-by == 'off'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.tags-explorer.group-by:off",
|
||||
"when": "view == foam-vscode.tags-explorer && foam-vscode.views.tags-explorer.group-by == 'folder'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.tags-explorer.expand-all",
|
||||
"when": "view == foam-vscode.tags-explorer",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.placeholders.show:for-current-file",
|
||||
"when": "view == foam-vscode.placeholders && foam-vscode.views.placeholders.show == 'all'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.placeholders.show:all",
|
||||
"when": "view == foam-vscode.placeholders && foam-vscode.views.placeholders.show == 'for-current-file'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.placeholders.group-by:folder",
|
||||
"when": "view == foam-vscode.placeholders && foam-vscode.views.placeholders.group-by == 'off'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.placeholders.group-by:off",
|
||||
"when": "view == foam-vscode.placeholders && foam-vscode.views.placeholders.group-by == 'folder'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.placeholders.expand-all",
|
||||
"when": "view == foam-vscode.placeholders",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.notes-explorer.show:notes",
|
||||
"when": "view == foam-vscode.notes-explorer && foam-vscode.views.notes-explorer.show == 'all'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.notes-explorer.show:all",
|
||||
"when": "view == foam-vscode.notes-explorer && foam-vscode.views.notes-explorer.show == 'notes-only'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.notes-explorer.expand-all",
|
||||
"when": "view == foam-vscode.notes-explorer",
|
||||
"group": "navigation"
|
||||
}
|
||||
],
|
||||
@@ -138,19 +250,75 @@
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.group-orphans-by-folder",
|
||||
"command": "foam-vscode.views.connections.show:all-links",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.group-orphans-off",
|
||||
"command": "foam-vscode.views.connections.show:backlinks",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.group-placeholders-by-folder",
|
||||
"command": "foam-vscode.views.connections.show:forward-links",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.group-placeholders-off",
|
||||
"command": "foam-vscode.views.orphans.group-by:folder",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.orphans.group-by:off",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.tags-explorer.show:for-current-file",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.tags-explorer.show:all",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.tags-explorer.group-by:folder",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.tags-explorer.group-by:off",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.tags-explorer.expand-all",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.placeholders.show:for-current-file",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.placeholders.show:all",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.placeholders.group-by:folder",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.placeholders.group-by:off",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.placeholders.expand-all",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.notes-explorer.show:all",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.notes-explorer.show:notes",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.notes-explorer.expand-all",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
@@ -166,7 +334,7 @@
|
||||
"commands": [
|
||||
{
|
||||
"command": "foam-vscode.create-note",
|
||||
"title": "Foam: Create Note"
|
||||
"title": "Foam: Create New Note"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.clear-cache",
|
||||
@@ -174,19 +342,19 @@
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.update-graph",
|
||||
"title": "Foam: Update graph"
|
||||
"title": "Foam: Update Graph"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.set-log-level",
|
||||
"title": "Foam: Set log level"
|
||||
"title": "Foam: Set Log Level"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.show-graph",
|
||||
"title": "Foam: Show graph"
|
||||
"title": "Foam: Show Graph"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.update-wikilinks",
|
||||
"title": "Foam: Update Markdown Reference List"
|
||||
"command": "foam-vscode.update-wikilink-definitions",
|
||||
"title": "Foam: Update Wikilink Definitions"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.open-daily-note",
|
||||
@@ -210,7 +378,7 @@
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.create-note-from-template",
|
||||
"title": "Foam: Create Note From Template"
|
||||
"title": "Foam: Create New Note From Template"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.create-note-from-default-template",
|
||||
@@ -221,25 +389,128 @@
|
||||
"title": "Foam: Open Resource"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.group-orphans-by-folder",
|
||||
"title": "Foam: Group Orphans By Folder",
|
||||
"command": "foam-vscode.convert-wikilink-to-mdlink",
|
||||
"title": "Foam: Convert Wikilink to Markdown Link"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.convert-mdlink-to-wikilink",
|
||||
"title": "Foam: Convert Markdown Link to Wikilink"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.search-tag",
|
||||
"title": "Foam: Search Tag",
|
||||
"icon": "$(search)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.rename-tag",
|
||||
"title": "Foam: Rename Tag",
|
||||
"icon": "$(edit)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.show-similar-notes",
|
||||
"title": "Foam: Show Similar Notes",
|
||||
"when": "config.foam.experimental.ai"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.build-embeddings",
|
||||
"title": "Foam: Build Embeddings Index",
|
||||
"when": "config.foam.experimental.ai"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.orphans.group-by:folder",
|
||||
"title": "Group By Folder",
|
||||
"icon": "$(list-tree)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.group-orphans-off",
|
||||
"title": "Foam: Don't Group Orphans",
|
||||
"command": "foam-vscode.views.connections.show:backlinks",
|
||||
"title": "Show Backlinks",
|
||||
"icon": "$(arrow-left)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.connections.show:forward-links",
|
||||
"title": "Show Links",
|
||||
"icon": "$(arrow-right)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.connections.show:all-links",
|
||||
"title": "Show All",
|
||||
"icon": "$(arrow-swap)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.orphans.group-by:off",
|
||||
"title": "Flat list",
|
||||
"icon": "$(list-flat)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.group-placeholders-by-folder",
|
||||
"title": "Foam: Group Placeholders By Folder",
|
||||
"command": "foam-vscode.views.tags-explorer.show:for-current-file",
|
||||
"title": "Show tags in current file",
|
||||
"icon": "$(file)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.tags-explorer.show:all",
|
||||
"title": "Show tags in workspace",
|
||||
"icon": "$(files)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.tags-explorer.group-by:folder",
|
||||
"title": "Group By Folder",
|
||||
"icon": "$(list-tree)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.group-placeholders-off",
|
||||
"title": "Foam: Don't Group Placeholders",
|
||||
"command": "foam-vscode.views.tags-explorer.group-by:off",
|
||||
"title": "Flat list",
|
||||
"icon": "$(list-flat)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.tags-explorer.expand-all",
|
||||
"title": "Expand all",
|
||||
"icon": "$(expand-all)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.tags-explorer.focus",
|
||||
"title": "Focus on tag",
|
||||
"icon": "$(symbol-number)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.placeholders.show:for-current-file",
|
||||
"title": "Show placeholders in current file",
|
||||
"icon": "$(file)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.placeholders.show:all",
|
||||
"title": "Show placeholders in workspace",
|
||||
"icon": "$(files)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.placeholders.group-by:folder",
|
||||
"title": "Group By Folder",
|
||||
"icon": "$(list-tree)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.placeholders.group-by:off",
|
||||
"title": "Flat list",
|
||||
"icon": "$(list-flat)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.placeholders.expand-all",
|
||||
"title": "Expand all",
|
||||
"icon": "$(expand-all)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.notes-explorer.show:all",
|
||||
"title": "Show all resources",
|
||||
"icon": "$(files)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.notes-explorer.expand-all",
|
||||
"title": "Expand all",
|
||||
"icon": "$(expand-all)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.views.notes-explorer.show:notes",
|
||||
"title": "Show only notes",
|
||||
"icon": "$(file)"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.create-new-template",
|
||||
"title": "Foam: Create New Template"
|
||||
@@ -252,6 +523,13 @@
|
||||
"configuration": {
|
||||
"title": "Foam",
|
||||
"properties": {
|
||||
"foam.supportedLanguages": {
|
||||
"type": "array",
|
||||
"default": [
|
||||
"markdown"
|
||||
],
|
||||
"description": "List of languages to treat as Markdown-like documents."
|
||||
},
|
||||
"foam.completion.label": {
|
||||
"type": "string",
|
||||
"default": "path",
|
||||
@@ -280,6 +558,19 @@
|
||||
"Use alias if resource path is different from title"
|
||||
]
|
||||
},
|
||||
"foam.completion.linkFormat": {
|
||||
"type": "string",
|
||||
"default": "wikilink",
|
||||
"description": "Controls the format of completed links",
|
||||
"enum": [
|
||||
"wikilink",
|
||||
"link"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Complete as wikilinks (e.g., [[note-name]])",
|
||||
"Complete as markdown links (e.g., [Note Name](note-name.md))"
|
||||
]
|
||||
},
|
||||
"foam.files.ignore": {
|
||||
"type": [
|
||||
"array"
|
||||
@@ -290,13 +581,53 @@
|
||||
"**/_site/**/*",
|
||||
"**/node_modules/**/*"
|
||||
],
|
||||
"description": "Specifies the list of globs that will be ignored by Foam (e.g. they will not be considered when creating the graph). To ignore the all the content of a given folder, use `<folderName>/**/*`"
|
||||
"description": "Specifies the list of globs that will be ignored by Foam (e.g. they will not be considered when creating the graph). To ignore all the content of a given folder, use `<folderName>/**/*`",
|
||||
"deprecationMessage": "Use 'foam.files.exclude' instead. This setting will be removed in a future version."
|
||||
},
|
||||
"foam.files.exclude": {
|
||||
"type": [
|
||||
"array"
|
||||
],
|
||||
"default": [],
|
||||
"description": "Specifies the list of globs that will be excluded by Foam (e.g. they will not be considered when creating the graph). To exclude all the content of a given folder, use `<folderName>/**/*`. This setting is combined with 'foam.files.ignore' (deprecated) and 'files.exclude'."
|
||||
},
|
||||
"foam.files.include": {
|
||||
"type": [
|
||||
"array"
|
||||
],
|
||||
"default": [
|
||||
"**/*"
|
||||
],
|
||||
"description": "Specifies the list of glob patterns for files to include in Foam. Files must match at least one include pattern and not match any exclude patterns. Use this to limit Foam to specific directories (e.g., [\"notes/**\"]) or file types (e.g., [\"**/*.md\"]). Defaults to all files."
|
||||
},
|
||||
"foam.files.attachmentExtensions": {
|
||||
"type": "string",
|
||||
"default": "pdf mp3 webm wav m4a mp4 avi mov rtf txt doc docx pages xls xlsx numbers ppt pptm pptx",
|
||||
"description": "Space separated list of file extensions that will be considered attachments"
|
||||
},
|
||||
"foam.files.notesExtensions": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "Space separated list of extra file extensions that will be considered text notes (e.g. 'mdx txt markdown')"
|
||||
},
|
||||
"foam.files.defaultNoteExtension": {
|
||||
"type": "string",
|
||||
"default": "md",
|
||||
"description": "The default extension for new notes"
|
||||
},
|
||||
"foam.files.newNotePath": {
|
||||
"type": "string",
|
||||
"default": "root",
|
||||
"description": "Specifies where to create a new note. It is overruled by the template or command arguments",
|
||||
"enum": [
|
||||
"root",
|
||||
"currentDir"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Use the root of the workspace",
|
||||
"Use the directory of the file in the current editor"
|
||||
]
|
||||
},
|
||||
"foam.logging.level": {
|
||||
"type": "string",
|
||||
"default": "info",
|
||||
@@ -337,15 +668,18 @@
|
||||
"default": false
|
||||
},
|
||||
"foam.openDailyNote.fileExtension": {
|
||||
"deprecationMessage": "This setting is deprecated and will be removed in future versions. Please use the daily-note template: https://github.com/foambubble/foam/blob/fe0228bdcc647e85682670656b5f09203b1c2518/docs/user/features/daily-notes.md",
|
||||
"type": "string",
|
||||
"default": "md"
|
||||
},
|
||||
"foam.openDailyNote.filenameFormat": {
|
||||
"deprecationMessage": "This setting is deprecated and will be removed in future versions. Please use the daily-note template: https://github.com/foambubble/foam/blob/fe0228bdcc647e85682670656b5f09203b1c2518/docs/user/features/daily-notes.md",
|
||||
"type": "string",
|
||||
"default": "isoDate",
|
||||
"markdownDescription": "Specifies how the daily note filename is formatted. See the [dateformat docs](https://www.npmjs.com/package/dateformat) for valid formats"
|
||||
},
|
||||
"foam.openDailyNote.titleFormat": {
|
||||
"deprecationMessage": "This setting is deprecated and will be removed in future versions. Please use the daily-note template: https://github.com/foambubble/foam/blob/fe0228bdcc647e85682670656b5f09203b1c2518/docs/user/features/daily-notes.md",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
@@ -354,6 +688,7 @@
|
||||
"markdownDescription": "Specifies how the daily note title is formatted. Will default to the filename format if set to null. See the [dateformat docs](https://www.npmjs.com/package/dateformat) for valid formats"
|
||||
},
|
||||
"foam.openDailyNote.directory": {
|
||||
"deprecationMessage": "This setting is deprecated and will be removed in future versions. Please use the daily-note template: https://github.com/foambubble/foam/blob/fe0228bdcc647e85682670656b5f09203b1c2518/docs/user/features/daily-notes.md",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
@@ -368,21 +703,6 @@
|
||||
"default": [],
|
||||
"markdownDescription": "Specifies the list of glob patterns that will be excluded from the orphans report. To ignore the all the content of a given folder, use `**<folderName>/**/*`"
|
||||
},
|
||||
"foam.orphans.groupBy": {
|
||||
"type": [
|
||||
"string"
|
||||
],
|
||||
"enum": [
|
||||
"off",
|
||||
"folder"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Disable grouping",
|
||||
"Group by folder"
|
||||
],
|
||||
"default": "folder",
|
||||
"markdownDescription": "Group orphans report entries by."
|
||||
},
|
||||
"foam.placeholders.exclude": {
|
||||
"type": [
|
||||
"array"
|
||||
@@ -390,21 +710,6 @@
|
||||
"default": [],
|
||||
"markdownDescription": "Specifies the list of glob patterns that will be excluded from the placeholders report. To ignore the all the content of a given folder, use `**<folderName>/**/*`"
|
||||
},
|
||||
"foam.placeholders.groupBy": {
|
||||
"type": [
|
||||
"string"
|
||||
],
|
||||
"enum": [
|
||||
"off",
|
||||
"folder"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Disable grouping",
|
||||
"Group by folder"
|
||||
],
|
||||
"default": "folder",
|
||||
"markdownDescription": "Group blank note report entries by."
|
||||
},
|
||||
"foam.dateSnippets.afterCompletion": {
|
||||
"type": "string",
|
||||
"default": "createNote",
|
||||
@@ -420,10 +725,22 @@
|
||||
],
|
||||
"description": "Whether or not to navigate to the target daily note when a daily note snippet is selected."
|
||||
},
|
||||
"foam.preview.embedNoteInContainer": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Wrap embedded notes in a container when displayed in preview panel"
|
||||
"foam.preview.embedNoteType": {
|
||||
"when": "config.foam.experimental.ai",
|
||||
"type": "string",
|
||||
"default": "full-card",
|
||||
"enum": [
|
||||
"full-inline",
|
||||
"full-card",
|
||||
"content-inline",
|
||||
"content-card"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Include the section with title and style inline",
|
||||
"Include the section with title and style it within a container",
|
||||
"Include the section without title and style inline",
|
||||
"Include the section without title and style it within a container"
|
||||
]
|
||||
},
|
||||
"foam.graph.titleMaxLength": {
|
||||
"type": "number",
|
||||
@@ -434,6 +751,11 @@
|
||||
"type": "object",
|
||||
"description": "Custom graph styling settings. An example is present in the documentation.",
|
||||
"default": {}
|
||||
},
|
||||
"foam.graph.onStartup": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Whether to open the graph on startup."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -449,73 +771,85 @@
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc -p ./",
|
||||
"pretest": "yarn build",
|
||||
"test": "node ./out/test/run-tests.js",
|
||||
"pretest:unit": "yarn build",
|
||||
"test:unit": "node ./out/test/run-tests.js --unit",
|
||||
"pretest:e2e": "yarn build",
|
||||
"test:e2e": "node ./out/test/run-tests.js --e2e",
|
||||
"lint": "tsdx lint src",
|
||||
"build:node": "node esbuild.js --platform=node",
|
||||
"build:web": "node esbuild.js --platform=web",
|
||||
"build": "yarn build:node && yarn build:web",
|
||||
"vscode:prepublish": "yarn clean && yarn build:node --production && yarn build:web --production",
|
||||
"compile": "tsc -p ./",
|
||||
"test-reset-workspace": "rm -rf .test-workspace && mkdir .test-workspace && touch .test-workspace/.keep",
|
||||
"test-setup": "yarn compile && yarn build && yarn test-reset-workspace",
|
||||
"test": "yarn test-setup && node ./out/test/run-tests.js",
|
||||
"test:unit": "yarn test-setup && node ./out/test/run-tests.js --unit",
|
||||
"test:unit-without-specs": "yarn test-setup && node ./out/test/run-tests.js --unit --exclude-specs",
|
||||
"test:e2e": "yarn test-setup && node ./out/test/run-tests.js --e2e",
|
||||
"lint": "dts lint src",
|
||||
"clean": "rimraf out",
|
||||
"watch": "tsc --build ./tsconfig.json --watch",
|
||||
"watch": "nodemon --watch 'src/**/*.ts' --exec 'yarn build' --ext ts",
|
||||
"vscode:start-debugging": "yarn clean && yarn watch",
|
||||
"esbuild-base": "esbuild ./src/extension.ts --bundle --outfile=out/extension.js --external:vscode --format=cjs --platform=node",
|
||||
"vscode:prepublish": "yarn run esbuild-base -- --minify",
|
||||
"package-extension": "npx vsce package --yarn",
|
||||
"package-extension": "npx @vscode/vsce@3.6.0 package --yarn",
|
||||
"install-extension": "code --install-extension ./foam-vscode-$npm_package_version.vsix",
|
||||
"open-in-browser": "vscode-test-web --quality=stable --browser=chromium --extensionDevelopmentPath=. ",
|
||||
"publish-extension-openvsx": "npx ovsx publish foam-vscode-$npm_package_version.vsix -p $OPENVSX_TOKEN",
|
||||
"publish-extension-vscode": "npx vsce publish --packagePath foam-vscode-$npm_package_version.vsix",
|
||||
"publish-extension": "yarn publish-extension-vscode && yarn publish-extension-openvsx"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/dateformat": "^3.0.1",
|
||||
"@types/glob": "^7.1.1",
|
||||
"@types/jest": "^29.5.3",
|
||||
"@types/lodash": "^4.14.157",
|
||||
"@types/markdown-it": "^12.0.1",
|
||||
"@types/micromatch": "^4.0.1",
|
||||
"@types/node": "^13.11.0",
|
||||
"@types/node": "^18.0.0",
|
||||
"@types/picomatch": "^2.2.1",
|
||||
"@types/remove-markdown": "^0.1.1",
|
||||
"@types/vscode": "^1.47.1",
|
||||
"@typescript-eslint/eslint-plugin": "^2.30.0",
|
||||
"@typescript-eslint/parser": "^2.30.0",
|
||||
"esbuild": "^0.14.45",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-import-resolver-typescript": "^2.5.0",
|
||||
"eslint-plugin-import": "^2.24.2",
|
||||
"eslint-plugin-jest": "^25.3.0",
|
||||
"@types/vscode": "^1.70.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.51.0",
|
||||
"@typescript-eslint/parser": "^5.51.0",
|
||||
"@vscode/test-web": "^0.0.62",
|
||||
"dts-cli": "^1.6.3",
|
||||
"esbuild": "^0.17.7",
|
||||
"esbuild-plugin-polyfill-node": "^0.3.0",
|
||||
"eslint": "^8.33.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.3",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-jest": "^27.2.1",
|
||||
"husky": "^4.2.5",
|
||||
"jest": "^26.2.2",
|
||||
"jest-extended": "^0.11.5",
|
||||
"jest": "^29.6.2",
|
||||
"jest-extended": "^3.2.3",
|
||||
"markdown-it": "^12.0.4",
|
||||
"micromatch": "^4.0.2",
|
||||
"nodemon": "^3.1.7",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^26.4.4",
|
||||
"tsdx": "^0.13.2",
|
||||
"ts-jest": "^29.1.1",
|
||||
"tslib": "^2.0.0",
|
||||
"typescript": "^3.9.5",
|
||||
"typescript": "^4.9.5",
|
||||
"vscode-test": "^1.3.0",
|
||||
"wait-for-expect": "^3.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"dateformat": "^3.0.3",
|
||||
"dateformat": "4.5.1",
|
||||
"dayjs": "^1.11.13",
|
||||
"detect-newline": "^3.1.0",
|
||||
"fast-array-diff": "^1.0.1",
|
||||
"github-slugger": "^1.4.0",
|
||||
"glob": "^7.1.6",
|
||||
"gray-matter": "^4.0.2",
|
||||
"js-sha1": "^0.7.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lru-cache": "^7.12.0",
|
||||
"lru-cache": "^7.14.1",
|
||||
"markdown-it-regex": "^0.2.0",
|
||||
"micromatch": "^4.0.2",
|
||||
"mnemonist": "^0.39.8",
|
||||
"path-browserify": "^1.0.1",
|
||||
"remark-frontmatter": "^2.0.0",
|
||||
"remark-parse": "^8.0.2",
|
||||
"remark-wiki-link": "^0.0.4",
|
||||
"remove-markdown": "^0.3.0",
|
||||
"replace-ext": "^2.0.0",
|
||||
"title-case": "^3.0.2",
|
||||
"unified": "^9.0.0",
|
||||
"unist-util-visit": "^2.0.2",
|
||||
"yaml": "^1.10.0"
|
||||
"yaml": "^2.2.2"
|
||||
},
|
||||
"__metadata": {
|
||||
"id": "b85c6625-454b-4b61-8a22-c42f3d0f2e1e",
|
||||
"publisherDisplayName": "Foam",
|
||||
"publisherId": "34339645-24f0-4619-9917-12157fd92446",
|
||||
"isPreReleaseVersion": false
|
||||
}
|
||||
}
|
||||
|
||||
17
packages/foam-vscode/src/ai/model/embedding-cache.ts
Normal file
17
packages/foam-vscode/src/ai/model/embedding-cache.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { URI } from '../../core/model/uri';
|
||||
import { ICache } from '../../core/utils/cache';
|
||||
|
||||
type Checksum = string;
|
||||
|
||||
/**
|
||||
* Cache entry for embeddings
|
||||
*/
|
||||
export interface EmbeddingCacheEntry {
|
||||
checksum: Checksum;
|
||||
embedding: number[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache for embeddings, keyed by URI
|
||||
*/
|
||||
export type EmbeddingCache = ICache<URI, EmbeddingCacheEntry>;
|
||||
365
packages/foam-vscode/src/ai/model/embeddings.test.ts
Normal file
365
packages/foam-vscode/src/ai/model/embeddings.test.ts
Normal file
@@ -0,0 +1,365 @@
|
||||
import { FoamEmbeddings } from './embeddings';
|
||||
import {
|
||||
EmbeddingProvider,
|
||||
EmbeddingProviderInfo,
|
||||
} from '../services/embedding-provider';
|
||||
import {
|
||||
createTestWorkspace,
|
||||
InMemoryDataStore,
|
||||
waitForExpect,
|
||||
} from '../../test/test-utils';
|
||||
import { URI } from '../../core/model/uri';
|
||||
|
||||
// Helper to create a simple mock provider
|
||||
class MockProvider implements EmbeddingProvider {
|
||||
async embed(text: string): Promise<number[]> {
|
||||
const vector = new Array(384).fill(0);
|
||||
vector[0] = text.length / 100; // Deterministic based on text length
|
||||
return vector;
|
||||
}
|
||||
async isAvailable(): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
getProviderInfo(): EmbeddingProviderInfo {
|
||||
return {
|
||||
name: 'Test Provider',
|
||||
type: 'local',
|
||||
model: { name: 'test-model', dimensions: 384 },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const ROOT = [URI.parse('/', 'file')];
|
||||
|
||||
describe('FoamEmbeddings', () => {
|
||||
describe('cosineSimilarity', () => {
|
||||
it('should return 1 for identical vectors', () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const embeddings = new FoamEmbeddings(workspace, new MockProvider());
|
||||
const vector = [1, 2, 3, 4, 5];
|
||||
const similarity = embeddings.cosineSimilarity(vector, vector);
|
||||
expect(similarity).toBeCloseTo(1.0, 5);
|
||||
workspace.dispose();
|
||||
});
|
||||
|
||||
it('should return 0 for orthogonal vectors', () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const embeddings = new FoamEmbeddings(workspace, new MockProvider());
|
||||
const vec1 = [1, 0, 0];
|
||||
const vec2 = [0, 1, 0];
|
||||
const similarity = embeddings.cosineSimilarity(vec1, vec2);
|
||||
expect(similarity).toBeCloseTo(0.0, 5);
|
||||
workspace.dispose();
|
||||
});
|
||||
|
||||
it('should return -1 for opposite vectors', () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const embeddings = new FoamEmbeddings(workspace, new MockProvider());
|
||||
const vec1 = [1, 0, 0];
|
||||
const vec2 = [-1, 0, 0];
|
||||
const similarity = embeddings.cosineSimilarity(vec1, vec2);
|
||||
expect(similarity).toBeCloseTo(-1.0, 5);
|
||||
workspace.dispose();
|
||||
});
|
||||
|
||||
it('should return 0 for zero vectors', () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const embeddings = new FoamEmbeddings(workspace, new MockProvider());
|
||||
const vec1 = [0, 0, 0];
|
||||
const vec2 = [1, 2, 3];
|
||||
const similarity = embeddings.cosineSimilarity(vec1, vec2);
|
||||
expect(similarity).toBe(0);
|
||||
workspace.dispose();
|
||||
});
|
||||
|
||||
it('should throw error for vectors of different lengths', () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const embeddings = new FoamEmbeddings(workspace, new MockProvider());
|
||||
const vec1 = [1, 2, 3];
|
||||
const vec2 = [1, 2];
|
||||
expect(() => embeddings.cosineSimilarity(vec1, vec2)).toThrow();
|
||||
workspace.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateResource', () => {
|
||||
it('should create embedding for a resource', async () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const embeddings = new FoamEmbeddings(workspace, new MockProvider());
|
||||
|
||||
const noteUri = URI.parse('/path/to/note.md', 'file');
|
||||
datastore.set(noteUri, '# Test Note\n\nThis is test content');
|
||||
await workspace.fetchAndSet(noteUri);
|
||||
|
||||
await embeddings.updateResource(noteUri);
|
||||
|
||||
const embedding = embeddings.getEmbedding(noteUri);
|
||||
expect(embedding).not.toBeNull();
|
||||
expect(embedding?.length).toBe(384);
|
||||
|
||||
workspace.dispose();
|
||||
});
|
||||
|
||||
it('should remove embedding when resource is deleted', async () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const embeddings = new FoamEmbeddings(workspace, new MockProvider());
|
||||
|
||||
const noteUri = URI.parse('/path/to/note.md', 'file');
|
||||
datastore.set(noteUri, '# Test Note\n\nContent');
|
||||
await workspace.fetchAndSet(noteUri);
|
||||
|
||||
await embeddings.updateResource(noteUri);
|
||||
expect(embeddings.getEmbedding(noteUri)).not.toBeNull();
|
||||
|
||||
workspace.delete(noteUri);
|
||||
await embeddings.updateResource(noteUri);
|
||||
|
||||
expect(embeddings.getEmbedding(noteUri)).toBeNull();
|
||||
|
||||
workspace.dispose();
|
||||
});
|
||||
|
||||
it('should create different embeddings for different content', async () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const embeddings = new FoamEmbeddings(workspace, new MockProvider());
|
||||
|
||||
const note1Uri = URI.parse('/note1.md', 'file');
|
||||
const note2Uri = URI.parse('/note2.md', 'file');
|
||||
|
||||
// Same title, different content
|
||||
datastore.set(note1Uri, '# Same Title\n\nShort content');
|
||||
datastore.set(
|
||||
note2Uri,
|
||||
'# Same Title\n\nThis is much longer content that should produce a different embedding vector'
|
||||
);
|
||||
|
||||
await workspace.fetchAndSet(note1Uri);
|
||||
await workspace.fetchAndSet(note2Uri);
|
||||
|
||||
await embeddings.updateResource(note1Uri);
|
||||
await embeddings.updateResource(note2Uri);
|
||||
|
||||
const embedding1 = embeddings.getEmbedding(note1Uri);
|
||||
const embedding2 = embeddings.getEmbedding(note2Uri);
|
||||
|
||||
expect(embedding1).not.toBeNull();
|
||||
expect(embedding2).not.toBeNull();
|
||||
|
||||
// Embeddings should be different because content is different
|
||||
// Our mock provider uses text.length for the first vector component
|
||||
expect(embedding1![0]).not.toBe(embedding2![0]);
|
||||
|
||||
workspace.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasEmbeddings', () => {
|
||||
it('should return false when no embeddings exist', () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const embeddings = new FoamEmbeddings(workspace, new MockProvider());
|
||||
expect(embeddings.hasEmbeddings()).toBe(false);
|
||||
workspace.dispose();
|
||||
});
|
||||
|
||||
it('should return true when embeddings exist', async () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const embeddings = new FoamEmbeddings(workspace, new MockProvider());
|
||||
|
||||
const noteUri = URI.parse('/path/to/note.md', 'file');
|
||||
datastore.set(noteUri, '# Note\n\nContent');
|
||||
await workspace.fetchAndSet(noteUri);
|
||||
|
||||
await embeddings.updateResource(noteUri);
|
||||
|
||||
expect(embeddings.hasEmbeddings()).toBe(true);
|
||||
|
||||
workspace.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSimilar', () => {
|
||||
it('should return empty array when no embedding exists for target', () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const embeddings = new FoamEmbeddings(workspace, new MockProvider());
|
||||
const uri = URI.parse('/path/to/note.md', 'file');
|
||||
|
||||
const similar = embeddings.getSimilar(uri, 5);
|
||||
|
||||
expect(similar).toEqual([]);
|
||||
workspace.dispose();
|
||||
});
|
||||
|
||||
it('should return similar notes sorted by similarity', async () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const embeddings = new FoamEmbeddings(workspace, new MockProvider());
|
||||
|
||||
// Create notes with different content lengths
|
||||
const note1Uri = URI.parse('/note1.md', 'file');
|
||||
const note2Uri = URI.parse('/note2.md', 'file');
|
||||
const note3Uri = URI.parse('/note3.md', 'file');
|
||||
|
||||
datastore.set(note1Uri, '# Note 1\n\nShort');
|
||||
datastore.set(note2Uri, '# Note 2\n\nMedium length text');
|
||||
datastore.set(note3Uri, '# Note 3\n\nVery long text content here');
|
||||
|
||||
await workspace.fetchAndSet(note1Uri);
|
||||
await workspace.fetchAndSet(note2Uri);
|
||||
await workspace.fetchAndSet(note3Uri);
|
||||
|
||||
await embeddings.updateResource(note1Uri);
|
||||
await embeddings.updateResource(note2Uri);
|
||||
await embeddings.updateResource(note3Uri);
|
||||
|
||||
// Get similar to note2
|
||||
const similar = embeddings.getSimilar(note2Uri, 10);
|
||||
|
||||
expect(similar.length).toBe(2); // Excludes self
|
||||
expect(similar[0].uri.path).toBeTruthy();
|
||||
expect(similar[0].similarity).toBeGreaterThanOrEqual(
|
||||
similar[1].similarity
|
||||
);
|
||||
|
||||
workspace.dispose();
|
||||
});
|
||||
|
||||
it('should respect topK parameter', async () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const embeddings = new FoamEmbeddings(workspace, new MockProvider());
|
||||
|
||||
// Create multiple notes
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const noteUri = URI.parse(`/note${i}.md`, 'file');
|
||||
datastore.set(noteUri, `# Note ${i}\n\nContent ${i}`);
|
||||
await workspace.fetchAndSet(noteUri);
|
||||
await embeddings.updateResource(noteUri);
|
||||
}
|
||||
|
||||
const target = URI.parse('/note0.md', 'file');
|
||||
const similar = embeddings.getSimilar(target, 3);
|
||||
|
||||
expect(similar.length).toBe(3);
|
||||
|
||||
workspace.dispose();
|
||||
});
|
||||
|
||||
it('should not include self in similar results', async () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const embeddings = new FoamEmbeddings(workspace, new MockProvider());
|
||||
|
||||
const noteUri = URI.parse('/note.md', 'file');
|
||||
datastore.set(noteUri, '# Note\n\nContent');
|
||||
await workspace.fetchAndSet(noteUri);
|
||||
await embeddings.updateResource(noteUri);
|
||||
|
||||
const similar = embeddings.getSimilar(noteUri, 10);
|
||||
|
||||
expect(similar.find(s => s.uri.path === noteUri.path)).toBeUndefined();
|
||||
|
||||
workspace.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
describe('fromWorkspace with monitoring', () => {
|
||||
it('should automatically update when resource is added', async () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const embeddings = FoamEmbeddings.fromWorkspace(
|
||||
workspace,
|
||||
new MockProvider(),
|
||||
true
|
||||
);
|
||||
|
||||
const noteUri = URI.parse('/new-note.md', 'file');
|
||||
datastore.set(noteUri, '# New Note\n\nContent');
|
||||
await workspace.fetchAndSet(noteUri);
|
||||
|
||||
// Give it a moment to process
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
|
||||
const embedding = embeddings.getEmbedding(noteUri);
|
||||
expect(embedding).not.toBeNull();
|
||||
|
||||
embeddings.dispose();
|
||||
workspace.dispose();
|
||||
});
|
||||
|
||||
it('should automatically update when resource is modified', async () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const noteUri = URI.parse('/note.md', 'file');
|
||||
|
||||
datastore.set(noteUri, '# Note\n\nOriginal content');
|
||||
await workspace.fetchAndSet(noteUri);
|
||||
|
||||
const embeddings = FoamEmbeddings.fromWorkspace(
|
||||
workspace,
|
||||
new MockProvider(),
|
||||
true
|
||||
);
|
||||
|
||||
await embeddings.updateResource(noteUri);
|
||||
const originalEmbedding = embeddings.getEmbedding(noteUri);
|
||||
|
||||
// Update the content of the note to simulate a change
|
||||
datastore.set(noteUri, '# Note\n\nDifferent content that is much longer');
|
||||
|
||||
// Trigger workspace update event
|
||||
await workspace.fetchAndSet(noteUri);
|
||||
|
||||
// Wait for automatic update
|
||||
await waitForExpect(
|
||||
() => {
|
||||
const newEmbedding = embeddings.getEmbedding(noteUri);
|
||||
expect(newEmbedding).not.toEqual(originalEmbedding);
|
||||
},
|
||||
1000,
|
||||
50
|
||||
);
|
||||
|
||||
embeddings.dispose();
|
||||
workspace.dispose();
|
||||
});
|
||||
|
||||
it('should automatically remove embedding when resource is deleted', async () => {
|
||||
const datastore = new InMemoryDataStore();
|
||||
const workspace = createTestWorkspace(ROOT, datastore);
|
||||
const noteUri = URI.parse('/note.md', 'file');
|
||||
|
||||
datastore.set(noteUri, '# Note\n\nContent');
|
||||
await workspace.fetchAndSet(noteUri);
|
||||
|
||||
const embeddings = FoamEmbeddings.fromWorkspace(
|
||||
workspace,
|
||||
new MockProvider(),
|
||||
true
|
||||
);
|
||||
|
||||
await embeddings.updateResource(noteUri);
|
||||
expect(embeddings.getEmbedding(noteUri)).not.toBeNull();
|
||||
|
||||
workspace.delete(noteUri);
|
||||
|
||||
// Give it a moment to process
|
||||
await new Promise(resolve => setTimeout(resolve, 50));
|
||||
|
||||
expect(embeddings.getEmbedding(noteUri)).toBeNull();
|
||||
|
||||
embeddings.dispose();
|
||||
workspace.dispose();
|
||||
});
|
||||
});
|
||||
});
|
||||
382
packages/foam-vscode/src/ai/model/embeddings.ts
Normal file
382
packages/foam-vscode/src/ai/model/embeddings.ts
Normal file
@@ -0,0 +1,382 @@
|
||||
import { Emitter } from '../../core/common/event';
|
||||
import { IDisposable } from '../../core/common/lifecycle';
|
||||
import { Logger } from '../../core/utils/log';
|
||||
import { hash } from '../../core/utils';
|
||||
import { EmbeddingProvider, Embedding } from '../services/embedding-provider';
|
||||
import { EmbeddingCache } from './embedding-cache';
|
||||
import {
|
||||
ProgressCallback,
|
||||
CancellationToken,
|
||||
CancellationError,
|
||||
} from '../../core/services/progress';
|
||||
import { FoamWorkspace } from '../../core/model/workspace';
|
||||
import { URI } from '../../core/model/uri';
|
||||
|
||||
/**
|
||||
* Represents a similar resource with its similarity score
|
||||
*/
|
||||
export interface SimilarResource {
|
||||
uri: URI;
|
||||
similarity: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Context information for embedding progress
|
||||
*/
|
||||
export interface EmbeddingProgressContext {
|
||||
/** URI of the current resource */
|
||||
uri: URI;
|
||||
/** Title of the current resource */
|
||||
title: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages embeddings for all resources in the workspace
|
||||
*/
|
||||
export class FoamEmbeddings implements IDisposable {
|
||||
/**
|
||||
* Maps resource URIs to their embeddings
|
||||
*/
|
||||
private embeddings: Map<string, Embedding> = new Map();
|
||||
|
||||
private onDidUpdateEmitter = new Emitter<void>();
|
||||
onDidUpdate = this.onDidUpdateEmitter.event;
|
||||
|
||||
/**
|
||||
* List of disposables to destroy with the embeddings
|
||||
*/
|
||||
private disposables: IDisposable[] = [];
|
||||
|
||||
constructor(
|
||||
private readonly workspace: FoamWorkspace,
|
||||
private readonly provider: EmbeddingProvider,
|
||||
private readonly cache?: EmbeddingCache
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Get the embedding for a resource
|
||||
* @param uri The URI of the resource
|
||||
* @returns The embedding vector, or null if not found
|
||||
*/
|
||||
public getEmbedding(uri: URI): number[] | null {
|
||||
const embedding = this.embeddings.get(uri.path);
|
||||
return embedding ? embedding.vector : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if embeddings are available
|
||||
* @returns true if at least one embedding exists
|
||||
*/
|
||||
public hasEmbeddings(): boolean {
|
||||
return this.embeddings.size > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of embeddings
|
||||
* @returns The count of embeddings
|
||||
*/
|
||||
public size(): number {
|
||||
return this.embeddings.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find similar resources to a given resource
|
||||
* @param uri The URI of the target resource
|
||||
* @param topK The number of similar resources to return
|
||||
* @returns Array of similar resources sorted by similarity (highest first)
|
||||
*/
|
||||
public getSimilar(uri: URI, topK: number = 10): SimilarResource[] {
|
||||
const targetEmbedding = this.getEmbedding(uri);
|
||||
if (!targetEmbedding) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const similarities: SimilarResource[] = [];
|
||||
|
||||
for (const [path, embedding] of this.embeddings.entries()) {
|
||||
// Skip self
|
||||
if (path === uri.path) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const similarity = this.cosineSimilarity(
|
||||
targetEmbedding,
|
||||
embedding.vector
|
||||
);
|
||||
similarities.push({
|
||||
uri: URI.file(path),
|
||||
similarity,
|
||||
});
|
||||
}
|
||||
|
||||
// Sort by similarity (highest first) and take top K
|
||||
similarities.sort((a, b) => b.similarity - a.similarity);
|
||||
return similarities.slice(0, topK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate cosine similarity between two vectors
|
||||
* @param a First vector
|
||||
* @param b Second vector
|
||||
* @returns Similarity score between -1 and 1 (higher is more similar)
|
||||
*/
|
||||
public cosineSimilarity(a: number[], b: number[]): number {
|
||||
if (a.length !== b.length) {
|
||||
throw new Error('Vectors must have the same length');
|
||||
}
|
||||
|
||||
let dotProduct = 0;
|
||||
let normA = 0;
|
||||
let normB = 0;
|
||||
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
dotProduct += a[i] * b[i];
|
||||
normA += a[i] * a[i];
|
||||
normB += b[i] * b[i];
|
||||
}
|
||||
|
||||
const denominator = Math.sqrt(normA) * Math.sqrt(normB);
|
||||
if (denominator === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return dotProduct / denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update embeddings for a single resource
|
||||
* @param uri The URI of the resource to update
|
||||
* @returns The embedding vector, or null if not found/not processed
|
||||
*/
|
||||
public async updateResource(uri: URI): Promise<Embedding | null> {
|
||||
const resource = this.workspace.find(uri);
|
||||
if (!resource) {
|
||||
// Resource deleted, remove embedding
|
||||
this.embeddings.delete(uri.path);
|
||||
if (this.cache) {
|
||||
this.cache.del(uri);
|
||||
}
|
||||
this.onDidUpdateEmitter.fire();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Skip non-note resources (attachments)
|
||||
if (resource.type !== 'note') {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const content = await this.workspace.readAsMarkdown(resource.uri);
|
||||
const text = this.prepareTextForEmbedding(resource.title, content);
|
||||
const textChecksum = hash(text);
|
||||
|
||||
// Check cache if available
|
||||
if (this.cache && this.cache.has(uri)) {
|
||||
const cached = this.cache.get(uri);
|
||||
if (cached.checksum === textChecksum) {
|
||||
Logger.debug(
|
||||
`Skipping embedding for ${uri.toFsPath()} - content unchanged`
|
||||
);
|
||||
// Use cached embedding
|
||||
const embedding: Embedding = {
|
||||
vector: cached.embedding,
|
||||
createdAt: Date.now(),
|
||||
};
|
||||
this.embeddings.set(uri.path, embedding);
|
||||
return embedding;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate new embedding
|
||||
const vector = await this.provider.embed(text);
|
||||
|
||||
const embedding: Embedding = {
|
||||
vector,
|
||||
createdAt: Date.now(),
|
||||
};
|
||||
this.embeddings.set(uri.path, embedding);
|
||||
|
||||
// Update cache
|
||||
if (this.cache) {
|
||||
this.cache.set(uri, {
|
||||
checksum: textChecksum,
|
||||
embedding: vector,
|
||||
});
|
||||
}
|
||||
|
||||
this.onDidUpdateEmitter.fire();
|
||||
return embedding;
|
||||
} catch (error) {
|
||||
Logger.error(`Failed to update embedding for ${uri.toFsPath()}`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update embeddings for all notes, processing only missing or stale ones
|
||||
* @param onProgress Optional callback to report progress
|
||||
* @param cancellationToken Optional token to cancel the operation
|
||||
* @returns Promise that resolves when all embeddings are updated
|
||||
* @throws CancellationError if the operation is cancelled
|
||||
*/
|
||||
public async update(
|
||||
onProgress?: ProgressCallback<EmbeddingProgressContext>,
|
||||
cancellationToken?: CancellationToken
|
||||
): Promise<void> {
|
||||
const start = Date.now();
|
||||
|
||||
// Filter to only process notes (not attachments)
|
||||
const allResources = Array.from(this.workspace.resources());
|
||||
const resources = allResources.filter(r => r.type === 'note');
|
||||
|
||||
Logger.info(
|
||||
`Building embeddings for ${resources.length} notes (${allResources.length} total resources)...`
|
||||
);
|
||||
|
||||
let skipped = 0;
|
||||
let generated = 0;
|
||||
let reused = 0;
|
||||
|
||||
// Process embeddings sequentially to avoid overwhelming the service
|
||||
for (let i = 0; i < resources.length; i++) {
|
||||
// Check for cancellation
|
||||
if (cancellationToken?.isCancellationRequested) {
|
||||
Logger.info(
|
||||
`Embedding build cancelled. Processed ${i}/${resources.length} notes.`
|
||||
);
|
||||
throw new CancellationError('Embedding build cancelled');
|
||||
}
|
||||
|
||||
const resource = resources[i];
|
||||
|
||||
onProgress?.({
|
||||
current: i + 1,
|
||||
total: resources.length,
|
||||
context: {
|
||||
uri: resource.uri,
|
||||
title: resource.title,
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
const content = await this.workspace.readAsMarkdown(resource.uri);
|
||||
const text = this.prepareTextForEmbedding(resource.title, content);
|
||||
const textChecksum = hash(text);
|
||||
|
||||
// Check cache if available
|
||||
if (this.cache && this.cache.has(resource.uri)) {
|
||||
const cached = this.cache.get(resource.uri);
|
||||
if (cached.checksum === textChecksum) {
|
||||
// Check if we already have this embedding in memory
|
||||
const existing = this.embeddings.get(resource.uri.path);
|
||||
if (existing) {
|
||||
// Already have current embedding, skip
|
||||
reused++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Restore from cache
|
||||
this.embeddings.set(resource.uri.path, {
|
||||
vector: cached.embedding,
|
||||
createdAt: Date.now(),
|
||||
});
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate new embedding
|
||||
const vector = await this.provider.embed(text);
|
||||
this.embeddings.set(resource.uri.path, {
|
||||
vector,
|
||||
createdAt: Date.now(),
|
||||
});
|
||||
|
||||
// Update cache
|
||||
if (this.cache) {
|
||||
this.cache.set(resource.uri, {
|
||||
checksum: textChecksum,
|
||||
embedding: vector,
|
||||
});
|
||||
}
|
||||
|
||||
generated++;
|
||||
} catch (error) {
|
||||
Logger.error(
|
||||
`Failed to generate embedding for ${resource.uri.toFsPath()}`,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const end = Date.now();
|
||||
Logger.info(
|
||||
`Embeddings update complete: ${generated} generated, ${skipped} from cache, ${reused} already current (${
|
||||
this.embeddings.size
|
||||
}/${resources.length} total) in ${end - start}ms`
|
||||
);
|
||||
this.onDidUpdateEmitter.fire();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare text for embedding by combining title and content
|
||||
* @param title The title of the note
|
||||
* @param content The markdown content of the note
|
||||
* @returns The combined text to embed
|
||||
*/
|
||||
private prepareTextForEmbedding(title: string, content: string): string {
|
||||
const parts: string[] = [];
|
||||
|
||||
if (title) {
|
||||
parts.push(title);
|
||||
}
|
||||
|
||||
if (content) {
|
||||
parts.push(content);
|
||||
}
|
||||
|
||||
return parts.join('\n\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create FoamEmbeddings from a workspace
|
||||
* @param workspace The workspace to generate embeddings for
|
||||
* @param provider The embedding provider to use
|
||||
* @param keepMonitoring Whether to automatically update embeddings when workspace changes
|
||||
* @param cache Optional cache for storing embeddings
|
||||
* @returns The FoamEmbeddings instance
|
||||
*/
|
||||
public static fromWorkspace(
|
||||
workspace: FoamWorkspace,
|
||||
provider: EmbeddingProvider,
|
||||
keepMonitoring: boolean = false,
|
||||
cache?: EmbeddingCache
|
||||
): FoamEmbeddings {
|
||||
const embeddings = new FoamEmbeddings(workspace, provider, cache);
|
||||
|
||||
if (keepMonitoring) {
|
||||
// Update embeddings when resources change
|
||||
embeddings.disposables.push(
|
||||
workspace.onDidAdd(resource => {
|
||||
embeddings.updateResource(resource.uri);
|
||||
}),
|
||||
workspace.onDidUpdate(({ new: resource }) => {
|
||||
embeddings.updateResource(resource.uri);
|
||||
}),
|
||||
workspace.onDidDelete(resource => {
|
||||
embeddings.embeddings.delete(resource.uri.path);
|
||||
embeddings.onDidUpdateEmitter.fire();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return embeddings;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.onDidUpdateEmitter.dispose();
|
||||
this.disposables.forEach(d => d.dispose());
|
||||
this.disposables = [];
|
||||
this.embeddings.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { URI } from '../../core/model/uri';
|
||||
import { EmbeddingCache, EmbeddingCacheEntry } from './embedding-cache';
|
||||
|
||||
/**
|
||||
* Simple in-memory implementation of embedding cache
|
||||
*/
|
||||
export class InMemoryEmbeddingCache implements EmbeddingCache {
|
||||
private cache: Map<string, EmbeddingCacheEntry> = new Map();
|
||||
|
||||
get(uri: URI): EmbeddingCacheEntry {
|
||||
return this.cache.get(uri.toString());
|
||||
}
|
||||
|
||||
has(uri: URI): boolean {
|
||||
return this.cache.has(uri.toString());
|
||||
}
|
||||
|
||||
set(uri: URI, entry: EmbeddingCacheEntry): void {
|
||||
this.cache.set(uri.toString(), entry);
|
||||
}
|
||||
|
||||
del(uri: URI): void {
|
||||
this.cache.delete(uri.toString());
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.cache.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
import { Logger } from '../../../core/utils/log';
|
||||
import {
|
||||
OllamaEmbeddingProvider,
|
||||
DEFAULT_OLLAMA_CONFIG,
|
||||
} from './ollama-provider';
|
||||
|
||||
Logger.setLevel('error');
|
||||
|
||||
describe('OllamaEmbeddingProvider', () => {
|
||||
const originalFetch = global.fetch;
|
||||
beforeEach(() => {
|
||||
global.fetch = jest.fn();
|
||||
jest.clearAllMocks();
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
global.fetch = originalFetch;
|
||||
});
|
||||
|
||||
describe('constructor', () => {
|
||||
it('should use default config when no config provided', () => {
|
||||
const provider = new OllamaEmbeddingProvider();
|
||||
const config = provider.getConfig();
|
||||
|
||||
expect(config.url).toBe(DEFAULT_OLLAMA_CONFIG.url);
|
||||
expect(config.model).toBe(DEFAULT_OLLAMA_CONFIG.model);
|
||||
expect(config.timeout).toBe(DEFAULT_OLLAMA_CONFIG.timeout);
|
||||
});
|
||||
|
||||
it('should merge custom config with defaults', () => {
|
||||
const provider = new OllamaEmbeddingProvider({
|
||||
url: 'http://custom:11434',
|
||||
});
|
||||
const config = provider.getConfig();
|
||||
|
||||
expect(config.url).toBe('http://custom:11434');
|
||||
expect(config.model).toBe(DEFAULT_OLLAMA_CONFIG.model);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getProviderInfo', () => {
|
||||
it('should return provider information', () => {
|
||||
const provider = new OllamaEmbeddingProvider();
|
||||
const info = provider.getProviderInfo();
|
||||
|
||||
expect(info.name).toBe('Ollama');
|
||||
expect(info.type).toBe('local');
|
||||
expect(info.model.name).toBe('nomic-embed-text');
|
||||
expect(info.model.dimensions).toBe(768);
|
||||
expect(info.endpoint).toBe('http://localhost:11434');
|
||||
expect(info.description).toBe('Local embedding provider using Ollama');
|
||||
expect(info.metadata).toEqual({ timeout: 30000 });
|
||||
});
|
||||
|
||||
it('should return custom model name when configured', () => {
|
||||
const provider = new OllamaEmbeddingProvider({
|
||||
model: 'custom-model',
|
||||
});
|
||||
const info = provider.getProviderInfo();
|
||||
|
||||
expect(info.model.name).toBe('custom-model');
|
||||
});
|
||||
|
||||
it('should return custom endpoint when configured', () => {
|
||||
const provider = new OllamaEmbeddingProvider({
|
||||
url: 'http://custom:8080',
|
||||
});
|
||||
const info = provider.getProviderInfo();
|
||||
|
||||
expect(info.endpoint).toBe('http://custom:8080');
|
||||
});
|
||||
});
|
||||
|
||||
describe('embed', () => {
|
||||
it('should successfully generate embeddings', async () => {
|
||||
const mockEmbedding = new Array(768).fill(0.1);
|
||||
(global.fetch as jest.Mock).mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: async () => ({ embeddings: [mockEmbedding] }),
|
||||
});
|
||||
|
||||
const provider = new OllamaEmbeddingProvider();
|
||||
const result = await provider.embed('test text');
|
||||
|
||||
expect(result).toEqual(mockEmbedding);
|
||||
expect(global.fetch).toHaveBeenCalledWith(
|
||||
'http://localhost:11434/api/embed',
|
||||
expect.objectContaining({
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
model: 'nomic-embed-text',
|
||||
input: ['test text'],
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error on non-ok response', async () => {
|
||||
(global.fetch as jest.Mock).mockResolvedValueOnce({
|
||||
ok: false,
|
||||
status: 500,
|
||||
text: async () => 'Internal server error',
|
||||
});
|
||||
|
||||
const provider = new OllamaEmbeddingProvider();
|
||||
|
||||
await expect(provider.embed('test')).rejects.toThrow(
|
||||
'AI service error (500)'
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error on connection refused', async () => {
|
||||
(global.fetch as jest.Mock).mockRejectedValueOnce(
|
||||
new Error('fetch failed')
|
||||
);
|
||||
|
||||
const provider = new OllamaEmbeddingProvider();
|
||||
|
||||
await expect(provider.embed('test')).rejects.toThrow(
|
||||
'Cannot connect to Ollama'
|
||||
);
|
||||
});
|
||||
|
||||
it('should timeout after configured duration', async () => {
|
||||
(global.fetch as jest.Mock).mockImplementationOnce(
|
||||
(_url, options) =>
|
||||
new Promise((_resolve, reject) => {
|
||||
// Simulate abort signal being triggered
|
||||
options.signal.addEventListener('abort', () => {
|
||||
const error = new Error('The operation was aborted');
|
||||
error.name = 'AbortError';
|
||||
reject(error);
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const provider = new OllamaEmbeddingProvider({ timeout: 1000 });
|
||||
const embedPromise = provider.embed('test');
|
||||
|
||||
// Fast-forward time to trigger timeout
|
||||
jest.advanceTimersByTime(1001);
|
||||
|
||||
await expect(embedPromise).rejects.toThrow('AI service took too long');
|
||||
});
|
||||
});
|
||||
|
||||
describe('isAvailable', () => {
|
||||
it('should return true when Ollama is available', async () => {
|
||||
(global.fetch as jest.Mock).mockResolvedValueOnce({
|
||||
ok: true,
|
||||
});
|
||||
|
||||
const provider = new OllamaEmbeddingProvider();
|
||||
const result = await provider.isAvailable();
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(global.fetch).toHaveBeenCalledWith(
|
||||
'http://localhost:11434/api/tags',
|
||||
expect.objectContaining({
|
||||
method: 'GET',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should return false when Ollama is not available', async () => {
|
||||
(global.fetch as jest.Mock).mockRejectedValueOnce(
|
||||
new Error('Connection refused')
|
||||
);
|
||||
|
||||
const provider = new OllamaEmbeddingProvider();
|
||||
const result = await provider.isAvailable();
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when Ollama returns non-ok status', async () => {
|
||||
(global.fetch as jest.Mock).mockResolvedValueOnce({
|
||||
ok: false,
|
||||
status: 404,
|
||||
});
|
||||
|
||||
const provider = new OllamaEmbeddingProvider();
|
||||
const result = await provider.isAvailable();
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should timeout quickly (5s) when checking availability', async () => {
|
||||
(global.fetch as jest.Mock).mockImplementationOnce(
|
||||
(_url, options) =>
|
||||
new Promise((_resolve, reject) => {
|
||||
// Simulate abort signal being triggered
|
||||
options.signal.addEventListener('abort', () => {
|
||||
const error = new Error('The operation was aborted');
|
||||
error.name = 'AbortError';
|
||||
reject(error);
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const provider = new OllamaEmbeddingProvider();
|
||||
const availabilityPromise = provider.isAvailable();
|
||||
|
||||
// Fast-forward time to trigger timeout (5s for availability check)
|
||||
jest.advanceTimersByTime(5001);
|
||||
|
||||
const result = await availabilityPromise;
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('OllamaEmbeddingProvider - Integration', () => {
|
||||
const provider = new OllamaEmbeddingProvider();
|
||||
|
||||
it('should handle text with unicode characters and emojis', async () => {
|
||||
if (!(await provider.isAvailable())) {
|
||||
console.warn('Ollama is not available, skipping test');
|
||||
return;
|
||||
}
|
||||
const text = 'Task completed ✔ 🚀: All systems go! 🌟';
|
||||
const embedding = await provider.embed(text);
|
||||
|
||||
expect(embedding).toBeDefined();
|
||||
expect(Array.isArray(embedding)).toBe(true);
|
||||
expect(embedding.length).toBe(768); // nomic-embed-text dimension
|
||||
expect(embedding.every(n => typeof n === 'number')).toBe(true);
|
||||
});
|
||||
|
||||
it('should handle text with various unicode characters', async () => {
|
||||
if (!(await provider.isAvailable())) {
|
||||
console.warn('Ollama is not available, skipping test');
|
||||
return;
|
||||
}
|
||||
const text = 'Hello 🌍 with émojis and spëcial çharacters • bullet ✓ check';
|
||||
const embedding = await provider.embed(text);
|
||||
|
||||
expect(embedding).toBeDefined();
|
||||
expect(Array.isArray(embedding)).toBe(true);
|
||||
expect(embedding.length).toBe(768);
|
||||
});
|
||||
|
||||
it('should handle text with combining unicode characters', async () => {
|
||||
if (!(await provider.isAvailable())) {
|
||||
console.warn('Ollama is not available, skipping test');
|
||||
return;
|
||||
}
|
||||
// Test with combining diacriticals that could be represented differently
|
||||
const text = 'café vs cafe\u0301'; // Two ways to represent é
|
||||
const embedding = await provider.embed(text);
|
||||
|
||||
expect(embedding).toBeDefined();
|
||||
expect(Array.isArray(embedding)).toBe(true);
|
||||
expect(embedding.length).toBe(768);
|
||||
});
|
||||
|
||||
it('should handle empty text', async () => {
|
||||
if (!(await provider.isAvailable())) {
|
||||
console.warn('Ollama is not available, skipping test');
|
||||
return;
|
||||
}
|
||||
const text = '';
|
||||
const embedding = await provider.embed(text);
|
||||
|
||||
expect(embedding).toBeDefined();
|
||||
expect(Array.isArray(embedding)).toBe(true);
|
||||
// Note: Ollama returns empty array for empty text
|
||||
expect(embedding.length).toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
|
||||
it.each([10, 50, 60, 100, 300])(
|
||||
'should handle text of various lengths',
|
||||
async length => {
|
||||
if (!(await provider.isAvailable())) {
|
||||
console.warn('Ollama is not available, skipping test');
|
||||
return;
|
||||
}
|
||||
const text = 'Lorem ipsum dolor sit amet. '.repeat(length);
|
||||
try {
|
||||
const embedding = await provider.embed(text);
|
||||
expect(embedding).toBeDefined();
|
||||
expect(Array.isArray(embedding)).toBe(true);
|
||||
expect(embedding.length).toBe(768);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Embedding failed for text of length ${text.length}: ${error}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
166
packages/foam-vscode/src/ai/providers/ollama/ollama-provider.ts
Normal file
166
packages/foam-vscode/src/ai/providers/ollama/ollama-provider.ts
Normal file
@@ -0,0 +1,166 @@
|
||||
import {
|
||||
EmbeddingProvider,
|
||||
EmbeddingProviderInfo,
|
||||
} from '../../services/embedding-provider';
|
||||
import { Logger } from '../../../core/utils/log';
|
||||
|
||||
/**
|
||||
* Configuration for Ollama embedding provider
|
||||
*/
|
||||
export interface OllamaConfig {
|
||||
/** Base URL for Ollama API (default: http://localhost:11434) */
|
||||
url: string;
|
||||
/** Model name to use for embeddings (default: nomic-embed-text) */
|
||||
model: string;
|
||||
/** Request timeout in milliseconds (default: 30000) */
|
||||
timeout: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default configuration for Ollama
|
||||
*/
|
||||
export const DEFAULT_OLLAMA_CONFIG: OllamaConfig = {
|
||||
url: 'http://localhost:11434',
|
||||
model: 'nomic-embed-text',
|
||||
timeout: 30000,
|
||||
};
|
||||
|
||||
/**
|
||||
* Ollama API response for embeddings
|
||||
*/
|
||||
interface OllamaEmbeddingResponse {
|
||||
embeddings: number[][];
|
||||
}
|
||||
|
||||
/**
|
||||
* Embedding provider that uses Ollama for generating embeddings
|
||||
*/
|
||||
export class OllamaEmbeddingProvider implements EmbeddingProvider {
|
||||
private config: OllamaConfig;
|
||||
|
||||
constructor(config: Partial<OllamaConfig> = {}) {
|
||||
this.config = { ...DEFAULT_OLLAMA_CONFIG, ...config };
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an embedding for the given text
|
||||
*/
|
||||
async embed(text: string): Promise<number[]> {
|
||||
// normalize text to suitable input (format and size)
|
||||
// TODO we should better handle long texts by chunking them and averaging embeddings
|
||||
const input = text.substring(0, 6000).normalize();
|
||||
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(
|
||||
() => controller.abort(),
|
||||
this.config.timeout
|
||||
);
|
||||
|
||||
const response = await fetch(`${this.config.url}/api/embed`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: this.config.model,
|
||||
input: [input],
|
||||
}),
|
||||
signal: controller.signal,
|
||||
});
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`AI service error (${response.status}): ${errorText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
if (data.embeddings == null) {
|
||||
throw new Error(
|
||||
`Invalid response from AI service: ${JSON.stringify(data)}`
|
||||
);
|
||||
}
|
||||
return data.embeddings[0];
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
if (error.name === 'AbortError') {
|
||||
throw new Error(
|
||||
'AI service took too long to respond. It may be busy processing another request.'
|
||||
);
|
||||
}
|
||||
if (
|
||||
error.message.includes('fetch') ||
|
||||
error.message.includes('ECONNREFUSED')
|
||||
) {
|
||||
throw new Error(
|
||||
`Cannot connect to Ollama at ${this.config.url}. Make sure Ollama is installed and running.`
|
||||
);
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if Ollama is available and the model is accessible
|
||||
*/
|
||||
async isAvailable(): Promise<boolean> {
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
||||
|
||||
// Try to reach the Ollama API
|
||||
const response = await fetch(`${this.config.url}/api/tags`, {
|
||||
method: 'GET',
|
||||
signal: controller.signal,
|
||||
});
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (!response.ok) {
|
||||
Logger.warn(
|
||||
`Ollama API returned status ${response.status} when checking availability`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
Logger.debug(
|
||||
`Ollama not available at ${this.config.url}: ${
|
||||
error instanceof Error ? error.message : 'Unknown error'
|
||||
}`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get provider information including model details
|
||||
*/
|
||||
getProviderInfo(): EmbeddingProviderInfo {
|
||||
return {
|
||||
name: 'Ollama',
|
||||
type: 'local',
|
||||
model: {
|
||||
name: this.config.model,
|
||||
// nomic-embed-text produces 768-dimensional embeddings
|
||||
dimensions: 768,
|
||||
},
|
||||
description: 'Local embedding provider using Ollama',
|
||||
endpoint: this.config.url,
|
||||
metadata: {
|
||||
timeout: this.config.timeout,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current configuration
|
||||
*/
|
||||
getConfig(): OllamaConfig {
|
||||
return { ...this.config };
|
||||
}
|
||||
}
|
||||
61
packages/foam-vscode/src/ai/services/embedding-provider.ts
Normal file
61
packages/foam-vscode/src/ai/services/embedding-provider.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Information about an embedding provider and its model
|
||||
*/
|
||||
export interface EmbeddingProviderInfo {
|
||||
/** Human-readable name of the provider (e.g., "Ollama", "OpenAI") */
|
||||
name: string;
|
||||
|
||||
/** Type of provider */
|
||||
type: 'local' | 'remote';
|
||||
|
||||
/** Model information */
|
||||
model: {
|
||||
/** Model name (e.g., "nomic-embed-text", "text-embedding-3-small") */
|
||||
name: string;
|
||||
/** Vector dimensions */
|
||||
dimensions: number;
|
||||
};
|
||||
|
||||
/** Optional description of the provider */
|
||||
description?: string;
|
||||
|
||||
/** Backend endpoint/URL if applicable */
|
||||
endpoint?: string;
|
||||
|
||||
/** Additional provider-specific metadata */
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider interface for generating text embeddings
|
||||
*/
|
||||
export interface EmbeddingProvider {
|
||||
/**
|
||||
* Generate an embedding vector for the given text
|
||||
* @param text The text to embed
|
||||
* @returns A promise that resolves to the embedding vector
|
||||
*/
|
||||
embed(text: string): Promise<number[]>;
|
||||
|
||||
/**
|
||||
* Check if the embedding service is available and ready to use
|
||||
* @returns A promise that resolves to true if available, false otherwise
|
||||
*/
|
||||
isAvailable(): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Get information about the provider and its model
|
||||
* @returns Provider metadata including name, type, model info, and configuration
|
||||
*/
|
||||
getProviderInfo(): EmbeddingProviderInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a text embedding with metadata
|
||||
*/
|
||||
export interface Embedding {
|
||||
/** The embedding vector */
|
||||
vector: number[];
|
||||
/** Timestamp when the embedding was created */
|
||||
createdAt: number;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { EmbeddingProvider, EmbeddingProviderInfo } from './embedding-provider';
|
||||
|
||||
/**
|
||||
* A no-op embedding provider that does nothing.
|
||||
* Used when no real embedding provider is available.
|
||||
*/
|
||||
export class NoOpEmbeddingProvider implements EmbeddingProvider {
|
||||
async embed(_text: string): Promise<number[]> {
|
||||
return [];
|
||||
}
|
||||
|
||||
async isAvailable(): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
|
||||
getProviderInfo(): EmbeddingProviderInfo {
|
||||
return {
|
||||
name: 'None',
|
||||
type: 'local',
|
||||
model: {
|
||||
name: 'none',
|
||||
dimensions: 0,
|
||||
},
|
||||
description: 'No embedding provider configured',
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/* @unit-ready */
|
||||
import * as vscode from 'vscode';
|
||||
import {
|
||||
cleanWorkspace,
|
||||
createFile,
|
||||
deleteFile,
|
||||
waitForNoteInFoamWorkspace,
|
||||
} from '../../../test/test-utils-vscode';
|
||||
import { BUILD_EMBEDDINGS_COMMAND } from './build-embeddings';
|
||||
|
||||
describe('build-embeddings command', () => {
|
||||
it('should complete successfully with no notes to analyze', async () => {
|
||||
await cleanWorkspace();
|
||||
|
||||
const showInfoSpy = jest
|
||||
.spyOn(vscode.window, 'showInformationMessage')
|
||||
.mockResolvedValue(undefined);
|
||||
|
||||
const result = await vscode.commands.executeCommand<
|
||||
'complete' | 'cancelled' | 'error'
|
||||
>(BUILD_EMBEDDINGS_COMMAND.command);
|
||||
|
||||
expect(result).toBe('complete');
|
||||
expect(showInfoSpy).toHaveBeenCalledWith(
|
||||
expect.stringContaining('No notes found')
|
||||
);
|
||||
|
||||
showInfoSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('should analyze notes and report completion', async () => {
|
||||
const note1 = await createFile('# Note 1\nContent here', ['note1.md']);
|
||||
const note2 = await createFile('# Note 2\nMore content', ['note2.md']);
|
||||
|
||||
await waitForNoteInFoamWorkspace(note1.uri);
|
||||
await waitForNoteInFoamWorkspace(note2.uri);
|
||||
|
||||
const showInfoSpy = jest
|
||||
.spyOn(vscode.window, 'showInformationMessage')
|
||||
.mockResolvedValue(undefined);
|
||||
|
||||
const result = await vscode.commands.executeCommand<
|
||||
'complete' | 'cancelled' | 'error'
|
||||
>(BUILD_EMBEDDINGS_COMMAND.command);
|
||||
|
||||
expect(result).toBe('complete');
|
||||
expect(showInfoSpy).toHaveBeenCalledWith(
|
||||
expect.stringMatching(/Analyzed.*2/)
|
||||
);
|
||||
|
||||
showInfoSpy.mockRestore();
|
||||
await deleteFile(note1.uri);
|
||||
await deleteFile(note2.uri);
|
||||
});
|
||||
|
||||
it('should return cancelled status when operation is cancelled', async () => {
|
||||
const note1 = await createFile('# Note 1\nContent', ['note1.md']);
|
||||
await waitForNoteInFoamWorkspace(note1.uri);
|
||||
|
||||
const tokenSource = new vscode.CancellationTokenSource();
|
||||
|
||||
const withProgressSpy = jest
|
||||
.spyOn(vscode.window, 'withProgress')
|
||||
.mockImplementation(async (options, task) => {
|
||||
const progress = { report: () => {} };
|
||||
// Cancel immediately
|
||||
tokenSource.cancel();
|
||||
return await task(progress, tokenSource.token);
|
||||
});
|
||||
|
||||
const showInfoSpy = jest
|
||||
.spyOn(vscode.window, 'showInformationMessage')
|
||||
.mockResolvedValue(undefined);
|
||||
|
||||
const result = await vscode.commands.executeCommand<
|
||||
'complete' | 'cancelled' | 'error'
|
||||
>(BUILD_EMBEDDINGS_COMMAND.command);
|
||||
|
||||
expect(result).toBe('cancelled');
|
||||
expect(showInfoSpy).toHaveBeenCalledWith(
|
||||
expect.stringContaining('cancelled')
|
||||
);
|
||||
|
||||
withProgressSpy.mockRestore();
|
||||
showInfoSpy.mockRestore();
|
||||
await deleteFile(note1.uri);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,91 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { Foam } from '../../../core/model/foam';
|
||||
import { CancellationError } from '../../../core/services/progress';
|
||||
import { TaskDeduplicator } from '../../../core/utils/task-deduplicator';
|
||||
import { FoamWorkspace } from '../../../core/model/workspace';
|
||||
import { FoamEmbeddings } from '../../../ai/model/embeddings';
|
||||
|
||||
export const BUILD_EMBEDDINGS_COMMAND = {
|
||||
command: 'foam-vscode.build-embeddings',
|
||||
title: 'Foam: Analyze Notes with AI',
|
||||
};
|
||||
|
||||
export default async function activate(
|
||||
context: vscode.ExtensionContext,
|
||||
foamPromise: Promise<Foam>
|
||||
) {
|
||||
const foam = await foamPromise;
|
||||
// Deduplicate concurrent executions
|
||||
const deduplicator = new TaskDeduplicator<
|
||||
'complete' | 'cancelled' | 'error'
|
||||
>();
|
||||
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand(
|
||||
BUILD_EMBEDDINGS_COMMAND.command,
|
||||
async () => {
|
||||
return await deduplicator.run(
|
||||
() => buildEmbeddings(foam.workspace, foam.embeddings),
|
||||
() => {
|
||||
vscode.window.showInformationMessage(
|
||||
'Note analysis is already in progress - waiting for it to complete'
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
async function buildEmbeddings(
|
||||
workspace: FoamWorkspace,
|
||||
embeddings: FoamEmbeddings
|
||||
): Promise<'complete' | 'cancelled' | 'error'> {
|
||||
const notesCount = workspace.list().filter(r => r.type === 'note').length;
|
||||
|
||||
if (notesCount === 0) {
|
||||
vscode.window.showInformationMessage('No notes found in workspace');
|
||||
return 'complete';
|
||||
}
|
||||
|
||||
// Show progress notification
|
||||
return await vscode.window.withProgress(
|
||||
{
|
||||
location: vscode.ProgressLocation.Window,
|
||||
title: 'Analyzing notes',
|
||||
cancellable: true,
|
||||
},
|
||||
async (progress, token) => {
|
||||
try {
|
||||
await embeddings.update(progressInfo => {
|
||||
const title = progressInfo.context?.title || 'Processing...';
|
||||
const increment = (1 / progressInfo.total) * 100;
|
||||
progress.report({
|
||||
message: `${progressInfo.current}/${progressInfo.total} - ${title}`,
|
||||
increment: increment,
|
||||
});
|
||||
}, token);
|
||||
|
||||
vscode.window.showInformationMessage(
|
||||
`✓ Analyzed ${embeddings.size()} of ${notesCount} notes`
|
||||
);
|
||||
return 'complete';
|
||||
} catch (error) {
|
||||
if (error instanceof CancellationError) {
|
||||
vscode.window.showInformationMessage(
|
||||
'Analysis cancelled. Run the command again to continue where you left off.'
|
||||
);
|
||||
return 'cancelled';
|
||||
}
|
||||
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : 'Unknown error';
|
||||
|
||||
vscode.window.showErrorMessage(
|
||||
`Failed to analyze notes: ${errorMessage}`
|
||||
);
|
||||
return 'error';
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user