mirror of
https://github.com/foambubble/foam.git
synced 2026-01-11 06:58:11 -05:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18a2d76139 | ||
|
|
722bef4257 | ||
|
|
8fe869223d | ||
|
|
1a961aac70 | ||
|
|
81dacef2fe | ||
|
|
92932cd004 | ||
|
|
1f6f8fd720 | ||
|
|
507699924f | ||
|
|
5d1fb2593b | ||
|
|
6012cc1b64 | ||
|
|
36f1b8af9e | ||
|
|
6ac9f6d229 | ||
|
|
3ce4529232 | ||
|
|
d3b8e66b78 | ||
|
|
836623257c | ||
|
|
27f2bc4050 | ||
|
|
5a5f3b1ef0 | ||
|
|
d374c51e93 | ||
|
|
f3a242251b | ||
|
|
3d6f98351f | ||
|
|
970c30f08c | ||
|
|
8556982b17 | ||
|
|
1ab9520c5c | ||
|
|
2a72bde111 | ||
|
|
2385bd75b5 | ||
|
|
53d2e7aaed | ||
|
|
48c13ef400 | ||
|
|
3ab30547eb |
@@ -932,6 +932,24 @@
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "dmurph",
|
||||
"name": "Daniel Murphy",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/294026?v=4",
|
||||
"profile": "http://www.dmurph.com",
|
||||
"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"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
||||
266
docs/index.md
266
docs/index.md
@@ -106,137 +106,141 @@ 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>
|
||||
</tr>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
|
||||
45
docs/user/features/commands.md
Normal file
45
docs/user/features/commands.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Foam Commands
|
||||
|
||||
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.
|
||||
|
||||
## 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
|
||||
|
||||
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",
|
||||
"command": "foam-vscode.create-note",
|
||||
"args": {
|
||||
"text": "test note ${FOAM_DATE_YEAR}",
|
||||
"notePath": "test note.md",
|
||||
"onFileExists": "ask"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Create a note following the `weekly-note.md` template. If the note already exists, open it
|
||||
```
|
||||
{
|
||||
"key": "alt+g",
|
||||
"command": "foam-vscode.create-note",
|
||||
"args": {
|
||||
"templatePath": ".foam/templates/weekly-note.md",
|
||||
"onFileExists": "open"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
# Spell Checking
|
||||
|
||||
Foam comes with a spell checker powered by the [Spellright extension](https://marketplace.visualstudio.com/items?itemName=ban.spellright).
|
||||
There are many spell checking extensions for VS Code.
|
||||
|
||||
Misspelled words are highlighted, like hellow.
|
||||
You can place the cursor on top of the word, and press `cmd+.` for suggestions on how to fix the problem.
|
||||
The most popular spell checker for VS Code is [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker).
|
||||
|
||||
You can configure the extension in the settings, for example to:
|
||||
Another one of our favorites is [LTeX](https://marketplace.visualstudio.com/items?itemName=valentjn.vscode-ltex&ssr=false#overview), which is a bit heavier but offers some extra functionality.
|
||||
|
||||
- ignore certain files
|
||||
- change the language(s)
|
||||
- and much more
|
||||
|
||||
You can use any number of alternative spell checking extensions for VS Code.
|
||||
One of our favorites is [LTeX](https://marketplace.visualstudio.com/items?itemName=valentjn.vscode-ltex&ssr=false#overview), which is a bit heavier but offers some extra functionality.
|
||||
Another popular one is [Spellright](https://marketplace.visualstudio.com/items?itemName=ban.spellright), but be mindful that there have been reports of incompatibility with the `vscode-markdown` extension (see https://github.com/foambubble/foam/issues/1068).
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
- 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 New Note` and enter a **Title Case Name** to create `Title Case Name.md`
|
||||
- Add a keyboard binding to make creating new notes easier.
|
||||
- `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"
|
||||
|
||||
@@ -7,7 +7,6 @@ This list is subject to change.
|
||||
- [Foam for VSCode](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode) (alpha)
|
||||
- [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)
|
||||
- [Spell Right](https://marketplace.visualstudio.com/items?itemName=ban.spellright)
|
||||
|
||||
## Extensions For Additional Features
|
||||
|
||||
@@ -17,6 +16,7 @@ These extensions are not (yet?) defined in `.vscode/extensions.json`, but have b
|
||||
- [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)
|
||||
- [Excalidraw whiteboard and sketching tool integration](https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor)
|
||||
- [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)
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
],
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"version": "0.19.4"
|
||||
"version": "0.20.1"
|
||||
}
|
||||
|
||||
@@ -4,6 +4,34 @@ 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.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:
|
||||
- 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)
|
||||
- Added support for opening non-text files via wikilink (#915)
|
||||
- Dataviz: now clicking is enough to open a link from the graph
|
||||
- Dataviz: clicking on images/attachments will open them
|
||||
|
||||
## [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)
|
||||
- Images and attachments are not shown by default in graph view (#1056)
|
||||
|
||||
## [0.19.4] - 2022-08-07
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"type": "git"
|
||||
},
|
||||
"homepage": "https://github.com/foambubble/foam",
|
||||
"version": "0.19.4",
|
||||
"version": "0.20.1",
|
||||
"license": "MIT",
|
||||
"publisher": "foam",
|
||||
"engines": {
|
||||
@@ -29,6 +29,7 @@
|
||||
"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"
|
||||
],
|
||||
@@ -128,6 +129,10 @@
|
||||
}
|
||||
],
|
||||
"commandPalette": [
|
||||
{
|
||||
"command": "foam-vscode.create-note-from-default-template",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.update-graph",
|
||||
"when": "false"
|
||||
@@ -159,6 +164,10 @@
|
||||
]
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"command": "foam-vscode.create-note",
|
||||
"title": "Foam: Create Note"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.clear-cache",
|
||||
"title": "Foam: Clear Cache"
|
||||
@@ -201,7 +210,7 @@
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.create-note-from-template",
|
||||
"title": "Foam: Create New Note From Template"
|
||||
"title": "Foam: Create Note From Template"
|
||||
},
|
||||
{
|
||||
"command": "foam-vscode.create-note-from-default-template",
|
||||
@@ -243,6 +252,34 @@
|
||||
"configuration": {
|
||||
"title": "Foam",
|
||||
"properties": {
|
||||
"foam.completion.label": {
|
||||
"type": "string",
|
||||
"default": "path",
|
||||
"description": "Describes what note property to use as a label for completion items",
|
||||
"enum": [
|
||||
"path",
|
||||
"title",
|
||||
"identifier"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Use the path of the note",
|
||||
"Use the title of the note",
|
||||
"Use the identifier of the note"
|
||||
]
|
||||
},
|
||||
"foam.completion.useAlias": {
|
||||
"type": "string",
|
||||
"default": "never",
|
||||
"description": "Specifies in which cases to use an alias when creating a wikilink",
|
||||
"enum": [
|
||||
"never",
|
||||
"whenPathDiffersFromTitle"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Never use aliases in completion items",
|
||||
"Use alias if resource path is different from title"
|
||||
]
|
||||
},
|
||||
"foam.files.ignore": {
|
||||
"type": [
|
||||
"array"
|
||||
@@ -255,6 +292,11 @@
|
||||
],
|
||||
"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>/**/*`"
|
||||
},
|
||||
"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.logging.level": {
|
||||
"type": "string",
|
||||
"default": "info",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Logger } from '../utils/log';
|
||||
import { URI } from './uri';
|
||||
import { asAbsoluteUri, URI } from './uri';
|
||||
|
||||
Logger.setLevel('error');
|
||||
|
||||
@@ -81,3 +81,47 @@ describe('Foam URI', () => {
|
||||
).toEqual(URI.file('../a/note.md'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('asAbsoluteUri', () => {
|
||||
it('should throw if no workspace folder is found', () => {
|
||||
expect(() => asAbsoluteUri(URI.file('relative/path'), [])).toThrow();
|
||||
});
|
||||
it('should return the given URI if already absolute', () => {
|
||||
const uri = URI.file('/absolute/path');
|
||||
expect(asAbsoluteUri(uri, [URI.file('/base')])).toEqual(uri);
|
||||
});
|
||||
describe('with relative URI', () => {
|
||||
it('should return a URI relative if the given URI is relative and there is only one workspace folder', () => {
|
||||
const uri = URI.file('relative/path');
|
||||
const workspaceFolder = URI.file('/workspace/folder');
|
||||
expect(asAbsoluteUri(uri, [workspaceFolder])).toEqual(
|
||||
workspaceFolder.joinPath(uri.path)
|
||||
);
|
||||
});
|
||||
it('should match the first folder with the same name as the first part of the URI', () => {
|
||||
const uri = URI.file('folder2/file');
|
||||
const workspaceFolder1 = URI.file('/absolute/path/folder1');
|
||||
const workspaceFolder2 = URI.file('/absolute/path/folder2');
|
||||
expect(asAbsoluteUri(uri, [workspaceFolder1, workspaceFolder2])).toEqual(
|
||||
workspaceFolder2.joinPath('file')
|
||||
);
|
||||
});
|
||||
});
|
||||
it('should use the first folder if no matching folder is found', () => {
|
||||
const uri = URI.file('folder3/file');
|
||||
const workspaceFolder1 = URI.file('/absolute/path/folder1');
|
||||
const workspaceFolder2 = URI.file('/absolute/path/folder2');
|
||||
expect(asAbsoluteUri(uri, [workspaceFolder1, workspaceFolder2])).toEqual(
|
||||
workspaceFolder1.joinPath(uri.path)
|
||||
);
|
||||
});
|
||||
it('should use the first matching folder', () => {
|
||||
const uri = URI.file('folder/file');
|
||||
const workspaceFolder1 = URI.file('/absolute/path1');
|
||||
const workspaceFolder2 = URI.file('/absolute/path2/folder');
|
||||
const workspaceFolder3 = URI.file('/absolute/path3/folder');
|
||||
expect(
|
||||
asAbsoluteUri(uri, [workspaceFolder1, workspaceFolder2, workspaceFolder3])
|
||||
).toEqual(workspaceFolder2.joinPath('file'));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -367,3 +367,24 @@ function encodeURIComponentMinimal(path: string): string {
|
||||
}
|
||||
return res !== undefined ? res : path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a relative URI into an absolute URI given a collection of base folders.
|
||||
* In case of multiple matches it returns the first one.
|
||||
*
|
||||
* @see {@link pathUtils.asAbsolutePaths|path.asAbsolutePath}
|
||||
*
|
||||
* @param uri the uri to evaluate
|
||||
* @param baseFolders the base folders to use
|
||||
* @returns an absolute uri
|
||||
*
|
||||
* TODO this probably needs to be moved to the workspace service
|
||||
*/
|
||||
export function asAbsoluteUri(uri: URI, baseFolders: URI[]): URI {
|
||||
return URI.file(
|
||||
pathUtils.asAbsolutePaths(
|
||||
uri.path,
|
||||
baseFolders.map(f => f.path)
|
||||
)[0]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,9 +5,17 @@ import { FoamWorkspace } from '../model/workspace';
|
||||
import { IDataStore, IMatcher, IWatcher } from '../services/datastore';
|
||||
import { IDisposable } from '../common/lifecycle';
|
||||
import { ResourceProvider } from '../model/provider';
|
||||
import { getFoamVsCodeConfig } from '../../services/config';
|
||||
|
||||
const imageExtensions = ['.png', '.jpg', '.gif'];
|
||||
const attachmentExtensions = ['.pdf', ...imageExtensions];
|
||||
const attachmentExtConfig = getFoamVsCodeConfig(
|
||||
'files.attachmentExtensions',
|
||||
''
|
||||
)
|
||||
.split(' ')
|
||||
.map(ext => '.' + ext.trim());
|
||||
|
||||
const imageExtensions = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp'];
|
||||
const attachmentExtensions = [...attachmentExtConfig, ...imageExtensions];
|
||||
|
||||
const asResource = (uri: URI): Resource => {
|
||||
const type = imageExtensions.includes(uri.getExtension())
|
||||
@@ -45,6 +53,11 @@ export class AttachmentResourceProvider implements ResourceProvider {
|
||||
.match(filesByFolder.flat())
|
||||
.filter(this.supports);
|
||||
|
||||
Logger.info(
|
||||
`Found ${
|
||||
files.length
|
||||
} attachments, with extensions: ${attachmentExtensions.join(', ')}`
|
||||
);
|
||||
for (const uri of files) {
|
||||
Logger.debug('Found: ' + uri.toString());
|
||||
workspace.set(asResource(uri));
|
||||
@@ -70,7 +83,9 @@ export class AttachmentResourceProvider implements ResourceProvider {
|
||||
}
|
||||
|
||||
supports(uri: URI) {
|
||||
return attachmentExtensions.includes(uri.getExtension());
|
||||
return attachmentExtensions.includes(
|
||||
uri.getExtension().toLocaleLowerCase()
|
||||
);
|
||||
}
|
||||
|
||||
async readAsMarkdown(uri: URI): Promise<string | null> {
|
||||
|
||||
@@ -62,11 +62,11 @@ describe('Matcher', () => {
|
||||
});
|
||||
|
||||
it('happy path', () => {
|
||||
const matcher = new Matcher([URI.file('/')], ['**/*'], ['**/*.pdf']);
|
||||
expect(matcher.isMatch(URI.file('/file.md'))).toBeTruthy();
|
||||
expect(matcher.isMatch(URI.file('/file.pdf'))).toBeFalsy();
|
||||
expect(matcher.isMatch(URI.file('/dir/file.md'))).toBeTruthy();
|
||||
expect(matcher.isMatch(URI.file('/dir/file.pdf'))).toBeFalsy();
|
||||
const matcher = new Matcher([URI.file('/root/')], ['**/*'], ['**/*.pdf']);
|
||||
expect(matcher.isMatch(URI.file('/root/file.md'))).toBeTruthy();
|
||||
expect(matcher.isMatch(URI.file('/root/file.pdf'))).toBeFalsy();
|
||||
expect(matcher.isMatch(URI.file('/root/dir/file.md'))).toBeTruthy();
|
||||
expect(matcher.isMatch(URI.file('/root/dir/file.pdf'))).toBeFalsy();
|
||||
});
|
||||
|
||||
it('ignores files in the exclude list', () => {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { glob } from 'glob';
|
||||
import { promisify } from 'util';
|
||||
import { isWindows } from '../common/platform';
|
||||
import { Event } from '../common/event';
|
||||
import { asAbsolutePaths } from '../utils/path';
|
||||
|
||||
const findAllFiles = promisify(glob);
|
||||
|
||||
@@ -54,21 +55,19 @@ export class Matcher implements IMatcher {
|
||||
|
||||
constructor(
|
||||
baseFolders: URI[],
|
||||
include: string[] = ['**/*'],
|
||||
exclude: string[] = []
|
||||
includeGlobs: string[] = ['**/*'],
|
||||
excludeGlobs: string[] = []
|
||||
) {
|
||||
this.folders = baseFolders.map(toMatcherPathFormat);
|
||||
Logger.info('Workspace folders: ', this.folders);
|
||||
|
||||
this.folders.forEach(folder => {
|
||||
const withFolder = folderPlusGlob(folder);
|
||||
this.include.push(
|
||||
...include.map(glob => {
|
||||
return withFolder(glob);
|
||||
})
|
||||
);
|
||||
this.exclude.push(...exclude.map(withFolder));
|
||||
});
|
||||
this.include = includeGlobs.flatMap(glob =>
|
||||
asAbsolutePaths(glob, this.folders)
|
||||
);
|
||||
this.exclude = excludeGlobs.flatMap(glob =>
|
||||
asAbsolutePaths(glob, this.folders)
|
||||
);
|
||||
|
||||
Logger.info('Glob patterns', {
|
||||
includeGlobs: this.include,
|
||||
ignoreGlobs: this.exclude,
|
||||
@@ -142,13 +141,3 @@ export class FileDataStore implements IDataStore {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const folderPlusGlob = (folder: string) => (glob: string): string => {
|
||||
if (folder.substr(-1) === '/') {
|
||||
folder = folder.slice(0, -1);
|
||||
}
|
||||
if (glob.startsWith('/')) {
|
||||
glob = glob.slice(1);
|
||||
}
|
||||
return folder.length > 0 ? `${folder}/${glob}` : glob;
|
||||
};
|
||||
|
||||
@@ -301,6 +301,21 @@ describe('Generation of markdown references', () => {
|
||||
expect(references.map(r => r.url)).toEqual(['page-b.md', 'page-c.md']);
|
||||
});
|
||||
|
||||
it('should always add extensions for attachments, even when includeExtension = false', () => {
|
||||
const workspace = createTestWorkspace();
|
||||
const noteA = createNoteFromMarkdown(
|
||||
'Link to [[page-b]] and [[image.png]]',
|
||||
'/dir1/page-a.md'
|
||||
);
|
||||
workspace
|
||||
.set(noteA)
|
||||
.set(createNoteFromMarkdown('Content of note B', '/dir1/page-b.md'))
|
||||
.set(createNoteFromMarkdown('', '/dir1/image.png'));
|
||||
|
||||
const references = createMarkdownReferences(workspace, noteA.uri, false);
|
||||
expect(references.map(r => r.url)).toEqual(['page-b', 'image.png']);
|
||||
});
|
||||
|
||||
it('should use relative paths', () => {
|
||||
const workspace = createTestWorkspace();
|
||||
const noteA = createNoteFromMarkdown(
|
||||
|
||||
@@ -181,7 +181,7 @@ to generate markdown reference list`
|
||||
}
|
||||
|
||||
let relativeUri = target.uri.relativeTo(noteUri.getDirectory());
|
||||
if (!includeExtension) {
|
||||
if (!includeExtension && relativeUri.path.endsWith('.md')) {
|
||||
relativeUri = relativeUri.changeExtension('*', '');
|
||||
}
|
||||
|
||||
|
||||
30
packages/foam-vscode/src/core/utils/path.test.ts
Normal file
30
packages/foam-vscode/src/core/utils/path.test.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { asAbsolutePaths } from './path';
|
||||
|
||||
describe('path utils', () => {
|
||||
describe('asAbsolutePaths', () => {
|
||||
it('returns the path if already absolute', () => {
|
||||
const paths = asAbsolutePaths('/path/to/test', [
|
||||
'/root/Users',
|
||||
'/root/tmp',
|
||||
]);
|
||||
expect(paths).toEqual(['/path/to/test']);
|
||||
});
|
||||
it('returns the matching base if found', () => {
|
||||
const paths = asAbsolutePaths('tmp/to/test', [
|
||||
'/root/Users',
|
||||
'/root/tmp',
|
||||
]);
|
||||
expect(paths).toEqual(['/root/tmp/to/test']);
|
||||
});
|
||||
it('returns all bases if no match is found', () => {
|
||||
const paths = asAbsolutePaths('path/to/test', [
|
||||
'/root/Users',
|
||||
'/root/tmp',
|
||||
]);
|
||||
expect(paths).toEqual([
|
||||
'/root/Users/path/to/test',
|
||||
'/root/tmp/path/to/test',
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
import { CharCode } from '../common/charCode';
|
||||
import { posix } from 'path';
|
||||
import { isNone } from './core';
|
||||
|
||||
/**
|
||||
* Converts filesystem path to POSIX path. Supported inputs are:
|
||||
@@ -174,3 +175,46 @@ function parseUNCShare(uncPath: string): [string, string] {
|
||||
return [uncPath.substring(2, idx), uncPath.substring(idx) || '\\'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a relative path into an absolute path given a collection of base folders.
|
||||
* - if no base folder is provided, it will throw
|
||||
* - if the given path is already absolute, it will return it
|
||||
* - if the given path is relative it will return absolute paths for the ones matching the
|
||||
* first part of the path
|
||||
* - if no matching base folder is found, it will return an absolute path per base folder
|
||||
* @param path the path to evaluate
|
||||
* @param baseFolders the base folders to use
|
||||
* @returns an array of absolute path, guaranteed to have at least 1 element
|
||||
*/
|
||||
export function asAbsolutePaths(path: string, baseFolders: string[]): string[] {
|
||||
if (isNone(baseFolders) || baseFolders.length === 0) {
|
||||
throw new Error('Cannot compute absolute URI without a base');
|
||||
}
|
||||
|
||||
if (isAbsolute(path)) {
|
||||
return [path];
|
||||
}
|
||||
let tokens = path.split('/');
|
||||
const firstDir = tokens[0];
|
||||
const res = [];
|
||||
if (baseFolders.length > 1) {
|
||||
for (const folder of baseFolders) {
|
||||
const lastDir = folder.split('/').pop();
|
||||
if (lastDir === firstDir) {
|
||||
tokens = tokens.slice(1);
|
||||
res.push([folder, ...tokens].join('/'));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res.length === 0) {
|
||||
for (const folder of baseFolders) {
|
||||
const match = folder.endsWith('/')
|
||||
? folder.substring(0, folder.length - 1)
|
||||
: folder;
|
||||
res.push([match, ...tokens].join('/'));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@ import { workspace } from 'vscode';
|
||||
import dateFormat from 'dateformat';
|
||||
import { focusNote } from './utils';
|
||||
import { URI } from './core/model/uri';
|
||||
import { fromVsCodeUri, toVsCodeUri } from './utils/vsc-utils';
|
||||
import { toVsCodeUri } from './utils/vsc-utils';
|
||||
import { NoteFactory } from './services/templates';
|
||||
import { getFoamVsCodeConfig } from './services/config';
|
||||
import { asAbsoluteWorkspaceUri } from './services/editor';
|
||||
|
||||
/**
|
||||
* Open the daily note file.
|
||||
@@ -42,17 +43,9 @@ export async function openDailyNoteFor(date?: Date) {
|
||||
*/
|
||||
export function getDailyNotePath(date: Date): URI {
|
||||
const folder = getFoamVsCodeConfig<string>('openDailyNote.directory') ?? '.';
|
||||
const dailyNoteDirectory = URI.file(folder);
|
||||
const dailyNoteDirectory = asAbsoluteWorkspaceUri(URI.file(folder));
|
||||
const dailyNoteFilename = getDailyNoteFileName(date);
|
||||
|
||||
if (dailyNoteDirectory.isAbsolute()) {
|
||||
return dailyNoteDirectory.joinPath(dailyNoteFilename);
|
||||
} else {
|
||||
return fromVsCodeUri(workspace.workspaceFolders[0].uri).joinPath(
|
||||
dailyNoteDirectory.path,
|
||||
dailyNoteFilename
|
||||
);
|
||||
}
|
||||
return dailyNoteDirectory.joinPath(dailyNoteFilename);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +22,11 @@ export async function activate(context: ExtensionContext) {
|
||||
try {
|
||||
Logger.info('Starting Foam');
|
||||
|
||||
if (workspace.workspaceFolders === undefined) {
|
||||
Logger.info('No workspace open. Foam will not start');
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare Foam
|
||||
const readFile = async (uri: URI) =>
|
||||
(await workspace.fs.readFile(toVsCodeUri(uri))).toString();
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
import { commands, ExtensionContext } from 'vscode';
|
||||
import { commands, window, ExtensionContext } from 'vscode';
|
||||
import { FoamFeature } from '../../types';
|
||||
import { DEFAULT_TEMPLATE_URI, NoteFactory } from '../../services/templates';
|
||||
import { getDefaultTemplateUri, NoteFactory } from '../../services/templates';
|
||||
import { Resolver } from '../../services/variable-resolver';
|
||||
|
||||
/**
|
||||
* Create a new note from the default template.
|
||||
*
|
||||
* @deprecated use 'foam-vscode.create-note' instead
|
||||
*/
|
||||
const feature: FoamFeature = {
|
||||
activate: (context: ExtensionContext) => {
|
||||
context.subscriptions.push(
|
||||
commands.registerCommand(
|
||||
'foam-vscode.create-note-from-default-template',
|
||||
() => {
|
||||
window.showWarningMessage(
|
||||
"This command is deprecated, use 'Foam: Create Note' (foam-vscode.create-note) instead"
|
||||
);
|
||||
const resolver = new Resolver(new Map(), new Date());
|
||||
|
||||
return NoteFactory.createFromTemplate(
|
||||
DEFAULT_TEMPLATE_URI,
|
||||
getDefaultTemplateUri(),
|
||||
resolver,
|
||||
undefined,
|
||||
`---
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import { commands, ExtensionContext, QuickPickItem, window } from 'vscode';
|
||||
import { commands, ExtensionContext } from 'vscode';
|
||||
import { FoamFeature } from '../../types';
|
||||
import {
|
||||
getTemplateMetadata,
|
||||
getTemplates,
|
||||
NoteFactory,
|
||||
TEMPLATES_DIR,
|
||||
} from '../../services/templates';
|
||||
import { askUserForTemplate, NoteFactory } from '../../services/templates';
|
||||
import { Resolver } from '../../services/variable-resolver';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
@@ -14,102 +9,17 @@ const feature: FoamFeature = {
|
||||
commands.registerCommand(
|
||||
'foam-vscode.create-note-from-template',
|
||||
async () => {
|
||||
const selectedTemplate = await askUserForTemplate();
|
||||
if (selectedTemplate === undefined) {
|
||||
return;
|
||||
const templateUri = await askUserForTemplate();
|
||||
|
||||
if (templateUri) {
|
||||
const resolver = new Resolver(new Map(), new Date());
|
||||
|
||||
await NoteFactory.createFromTemplate(templateUri, resolver);
|
||||
}
|
||||
const templateFilename =
|
||||
(selectedTemplate as QuickPickItem).description ||
|
||||
(selectedTemplate as QuickPickItem).label;
|
||||
const templateUri = TEMPLATES_DIR.joinPath(templateFilename);
|
||||
|
||||
const resolver = new Resolver(new Map(), new Date());
|
||||
|
||||
await NoteFactory.createFromTemplate(templateUri, resolver);
|
||||
}
|
||||
)
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
async function offerToCreateTemplate(): Promise<void> {
|
||||
const response = await window.showQuickPick(['Yes', 'No'], {
|
||||
placeHolder:
|
||||
'No templates available. Would you like to create one instead?',
|
||||
});
|
||||
if (response === 'Yes') {
|
||||
commands.executeCommand('foam-vscode.create-new-template');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function sortTemplatesMetadata(
|
||||
t1: Map<string, string>,
|
||||
t2: Map<string, string>
|
||||
) {
|
||||
// Sort by name's existence, then name, then path
|
||||
|
||||
if (t1.get('name') === undefined && t2.get('name') !== undefined) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (t1.get('name') !== undefined && t2.get('name') === undefined) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const pathSortOrder = t1
|
||||
.get('templatePath')
|
||||
.localeCompare(t2.get('templatePath'));
|
||||
|
||||
if (t1.get('name') === undefined && t2.get('name') === undefined) {
|
||||
return pathSortOrder;
|
||||
}
|
||||
|
||||
const nameSortOrder = t1.get('name').localeCompare(t2.get('name'));
|
||||
|
||||
return nameSortOrder || pathSortOrder;
|
||||
}
|
||||
|
||||
async function askUserForTemplate() {
|
||||
const templates = await getTemplates();
|
||||
if (templates.length === 0) {
|
||||
return offerToCreateTemplate();
|
||||
}
|
||||
|
||||
const templatesMetadata = (
|
||||
await Promise.all(
|
||||
templates.map(async templateUri => {
|
||||
const metadata = await getTemplateMetadata(templateUri);
|
||||
metadata.set('templatePath', templateUri.getBasename());
|
||||
return metadata;
|
||||
})
|
||||
)
|
||||
).sort(sortTemplatesMetadata);
|
||||
|
||||
const items: QuickPickItem[] = await Promise.all(
|
||||
templatesMetadata.map(metadata => {
|
||||
const label = metadata.get('name') || metadata.get('templatePath');
|
||||
const description = metadata.get('name')
|
||||
? metadata.get('templatePath')
|
||||
: null;
|
||||
const detail = metadata.get('description');
|
||||
const item = {
|
||||
label: label,
|
||||
description: description,
|
||||
detail: detail,
|
||||
};
|
||||
Object.keys(item).forEach(key => {
|
||||
if (!item[key]) {
|
||||
delete item[key];
|
||||
}
|
||||
});
|
||||
return item;
|
||||
})
|
||||
);
|
||||
|
||||
return await window.showQuickPick(items, {
|
||||
placeHolder: 'Select a template to use.',
|
||||
});
|
||||
}
|
||||
|
||||
export default feature;
|
||||
|
||||
129
packages/foam-vscode/src/features/commands/create-note.spec.ts
Normal file
129
packages/foam-vscode/src/features/commands/create-note.spec.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import { commands, window } from 'vscode';
|
||||
import { URI } from '../../core/model/uri';
|
||||
import { asAbsoluteWorkspaceUri, readFile } from '../../services/editor';
|
||||
import {
|
||||
closeEditors,
|
||||
createFile,
|
||||
deleteFile,
|
||||
expectSameUri,
|
||||
getUriInWorkspace,
|
||||
} from '../../test/test-utils-vscode';
|
||||
|
||||
describe('create-note command', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('uses sensible defaults to work even without params', async () => {
|
||||
const spy = jest
|
||||
.spyOn(window, 'showInputBox')
|
||||
.mockImplementationOnce(jest.fn(() => Promise.resolve('Test note')));
|
||||
|
||||
await commands.executeCommand('foam-vscode.create-note');
|
||||
expect(spy).toBeCalled();
|
||||
const target = asAbsoluteWorkspaceUri(URI.file('Test note.md'));
|
||||
expectSameUri(target, window.activeTextEditor?.document.uri);
|
||||
await deleteFile(target);
|
||||
});
|
||||
|
||||
it('gives precedence to the template over the text', async () => {
|
||||
const templateA = await createFile('Template A', [
|
||||
'.foam',
|
||||
'templates',
|
||||
'template-for-create-note.md',
|
||||
]);
|
||||
const target = getUriInWorkspace();
|
||||
await commands.executeCommand('foam-vscode.create-note', {
|
||||
notePath: target.path,
|
||||
templatePath: templateA.uri.path,
|
||||
text: 'hello',
|
||||
});
|
||||
expect(window.activeTextEditor.document.getText()).toEqual('Template A');
|
||||
expectSameUri(window.activeTextEditor.document.uri, target);
|
||||
await deleteFile(target);
|
||||
await deleteFile(templateA.uri);
|
||||
});
|
||||
|
||||
it('focuses on the newly created note', async () => {
|
||||
const target = getUriInWorkspace();
|
||||
await commands.executeCommand('foam-vscode.create-note', {
|
||||
notePath: target.path,
|
||||
text: 'hello',
|
||||
});
|
||||
expect(window.activeTextEditor.document.getText()).toEqual('hello');
|
||||
expectSameUri(window.activeTextEditor.document.uri, target);
|
||||
await deleteFile(target);
|
||||
});
|
||||
|
||||
it('supports variables', async () => {
|
||||
const target = getUriInWorkspace();
|
||||
await commands.executeCommand('foam-vscode.create-note', {
|
||||
notePath: target.path,
|
||||
text: 'hello ${FOAM_TITLE}', // eslint-disable-line no-template-curly-in-string
|
||||
variables: { FOAM_TITLE: 'world' },
|
||||
});
|
||||
expect(window.activeTextEditor.document.getText()).toEqual('hello world');
|
||||
expectSameUri(window.activeTextEditor.document.uri, target);
|
||||
await deleteFile(target);
|
||||
});
|
||||
|
||||
it('supports date variables', async () => {
|
||||
const target = getUriInWorkspace();
|
||||
await commands.executeCommand('foam-vscode.create-note', {
|
||||
notePath: target.path,
|
||||
text: 'hello ${FOAM_DATE_YEAR}', // eslint-disable-line no-template-curly-in-string
|
||||
date: '2021-10-01',
|
||||
});
|
||||
expect(window.activeTextEditor.document.getText()).toEqual('hello 2021');
|
||||
expectSameUri(window.activeTextEditor.document.uri, target);
|
||||
await deleteFile(target);
|
||||
});
|
||||
|
||||
it('supports various options to deal with existing notes', async () => {
|
||||
const target = await createFile('hello');
|
||||
const content = await readFile(target.uri);
|
||||
expect(content).toEqual('hello');
|
||||
|
||||
await commands.executeCommand('foam-vscode.create-note', {
|
||||
notePath: target.uri.path,
|
||||
text: 'test overwrite',
|
||||
onFileExists: 'overwrite',
|
||||
});
|
||||
expect(window.activeTextEditor.document.getText()).toEqual(
|
||||
'test overwrite'
|
||||
);
|
||||
expectSameUri(window.activeTextEditor.document.uri, target.uri);
|
||||
|
||||
await closeEditors();
|
||||
await commands.executeCommand('foam-vscode.create-note', {
|
||||
notePath: target.uri.path,
|
||||
text: 'test open',
|
||||
onFileExists: 'open',
|
||||
});
|
||||
expect(window.activeTextEditor.document.getText()).toEqual(
|
||||
'test overwrite'
|
||||
);
|
||||
expectSameUri(window.activeTextEditor.document.uri, target.uri);
|
||||
|
||||
await closeEditors();
|
||||
await commands.executeCommand('foam-vscode.create-note', {
|
||||
notePath: target.uri.path,
|
||||
text: 'test cancel',
|
||||
onFileExists: 'cancel',
|
||||
});
|
||||
expect(window.activeTextEditor).toBeUndefined();
|
||||
|
||||
const spy = jest
|
||||
.spyOn(window, 'showInputBox')
|
||||
.mockImplementationOnce(jest.fn(() => Promise.resolve(undefined)));
|
||||
await closeEditors();
|
||||
await commands.executeCommand('foam-vscode.create-note', {
|
||||
notePath: target.uri.path,
|
||||
text: 'test ask',
|
||||
onFileExists: 'ask',
|
||||
});
|
||||
expect(spy).toBeCalled();
|
||||
|
||||
await deleteFile(target);
|
||||
});
|
||||
});
|
||||
110
packages/foam-vscode/src/features/commands/create-note.ts
Normal file
110
packages/foam-vscode/src/features/commands/create-note.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { FoamFeature } from '../../types';
|
||||
import { URI } from '../../core/model/uri';
|
||||
import {
|
||||
askUserForTemplate,
|
||||
getPathFromTitle,
|
||||
NoteFactory,
|
||||
} from '../../services/templates';
|
||||
import { Foam } from '../../core/model/foam';
|
||||
import { Resolver } from '../../services/variable-resolver';
|
||||
import { asAbsoluteWorkspaceUri, fileExists } from '../../services/editor';
|
||||
import { isSome } from '../../core/utils';
|
||||
|
||||
interface CreateNoteArgs {
|
||||
/**
|
||||
* The path of the note to create.
|
||||
* If relative it will be resolved against the workspace root.
|
||||
*/
|
||||
notePath?: string;
|
||||
/**
|
||||
* The path of the template to use.
|
||||
*/
|
||||
templatePath?: string;
|
||||
/**
|
||||
* Whether to ask the user to select a template for the new note. If so, overwrites templatePath.
|
||||
*/
|
||||
askForTemplate?: boolean;
|
||||
/**
|
||||
* The text to use for the note.
|
||||
* If a template is provided, the template has precedence
|
||||
*/
|
||||
text?: string;
|
||||
/**
|
||||
* Variables to use in the text or template
|
||||
*/
|
||||
variables?: Map<string, string>;
|
||||
/**
|
||||
* The date used to resolve the FOAM_DATE_* variables. in YYYY-MM-DD format
|
||||
*/
|
||||
date?: string;
|
||||
/**
|
||||
* What to do in case the target file already exists
|
||||
*/
|
||||
onFileExists?: 'overwrite' | 'open' | 'ask' | 'cancel';
|
||||
}
|
||||
|
||||
const DEFAULT_NEW_NOTE_TEXT = `# \${FOAM_TITLE}
|
||||
|
||||
\${FOAM_SELECTED_TEXT}`;
|
||||
|
||||
async function createNote(args: CreateNoteArgs) {
|
||||
args = args ?? {};
|
||||
const date = isSome(args.date) ? new Date(Date.parse(args.date)) : new Date();
|
||||
const resolver = new Resolver(
|
||||
new Map(Object.entries(args.variables ?? {})),
|
||||
date
|
||||
);
|
||||
const text = args.text ?? DEFAULT_NEW_NOTE_TEXT;
|
||||
const noteUri =
|
||||
args.notePath && asAbsoluteWorkspaceUri(URI.file(args.notePath));
|
||||
let templateUri: URI;
|
||||
if (args.askForTemplate) {
|
||||
const selectedTemplate = await askUserForTemplate();
|
||||
if (selectedTemplate) {
|
||||
templateUri = selectedTemplate;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
templateUri =
|
||||
args.templatePath && asAbsoluteWorkspaceUri(URI.file(args.templatePath));
|
||||
}
|
||||
|
||||
if (await fileExists(templateUri)) {
|
||||
return NoteFactory.createFromTemplate(
|
||||
templateUri,
|
||||
resolver,
|
||||
noteUri,
|
||||
text,
|
||||
args.onFileExists
|
||||
);
|
||||
} else {
|
||||
return NoteFactory.createNote(
|
||||
noteUri ?? (await getPathFromTitle(resolver)),
|
||||
text,
|
||||
resolver,
|
||||
args.onFileExists
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const CREATE_NOTE_COMMAND = {
|
||||
command: 'foam-vscode.create-note',
|
||||
title: 'Foam: Create Note',
|
||||
|
||||
asURI: (args: CreateNoteArgs) =>
|
||||
vscode.Uri.parse(`command:${CREATE_NOTE_COMMAND.command}`).with({
|
||||
query: encodeURIComponent(JSON.stringify(args)),
|
||||
}),
|
||||
};
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: (context: vscode.ExtensionContext, foamPromise: Promise<Foam>) => {
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand(CREATE_NOTE_COMMAND.command, createNote)
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export default feature;
|
||||
@@ -10,3 +10,4 @@ export { default as openRandomNoteCommand } from './open-random-note';
|
||||
export { default as openResource } from './open-resource';
|
||||
export { default as updateGraphCommand } from './update-graph';
|
||||
export { default as updateWikilinksCommand } from './update-wikilinks';
|
||||
export { default as createNote } from './create-note';
|
||||
|
||||
@@ -28,13 +28,12 @@ const feature: FoamFeature = {
|
||||
uri.path === vscode.window.activeTextEditor?.document.uri.path
|
||||
? vscode.window.activeTextEditor?.document.uri
|
||||
: toVsCodeUri(uri.asPlain());
|
||||
// if the doc is already open, reuse the same colunm
|
||||
const targetEditor = vscode.window.visibleTextEditors.find(
|
||||
ed => targetUri.path === ed.document.uri.path
|
||||
);
|
||||
const column = targetEditor?.viewColumn;
|
||||
return vscode.window.showTextDocument(targetUri, {
|
||||
viewColumn: column,
|
||||
});
|
||||
return vscode.commands.executeCommand('vscode.open', targetUri);
|
||||
}
|
||||
case 'placeholder': {
|
||||
const title = uri.getName();
|
||||
|
||||
@@ -206,8 +206,7 @@ const feature: FoamFeature = {
|
||||
languages.registerCompletionItemProvider(
|
||||
'markdown',
|
||||
datesCompletionProvider,
|
||||
'/',
|
||||
'+'
|
||||
'/'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
@@ -179,7 +179,7 @@ describe('Hover provider', () => {
|
||||
const provider = new HoverProvider(hoverEnabled, ws, graph, parser);
|
||||
const result = await provider.provideHover(doc, pos, noCancelToken);
|
||||
|
||||
expect(result.contents).toHaveLength(2);
|
||||
expect(result.contents).toHaveLength(3);
|
||||
expect(getValue(result.contents[0])).toEqual(
|
||||
`This is some content from file B`
|
||||
);
|
||||
@@ -205,7 +205,7 @@ describe('Hover provider', () => {
|
||||
const provider = new HoverProvider(hoverEnabled, ws, graph, parser);
|
||||
const result = await provider.provideHover(doc, pos, noCancelToken);
|
||||
|
||||
expect(result.contents).toHaveLength(2);
|
||||
expect(result.contents).toHaveLength(3);
|
||||
expect(getValue(result.contents[0])).toEqual(
|
||||
`This is some content from file B`
|
||||
);
|
||||
@@ -235,7 +235,7 @@ The content of file B`);
|
||||
const provider = new HoverProvider(hoverEnabled, ws, graph, parser);
|
||||
const result = await provider.provideHover(doc, pos, noCancelToken);
|
||||
|
||||
expect(result.contents).toHaveLength(2);
|
||||
expect(result.contents).toHaveLength(3);
|
||||
expect(getValue(result.contents[0])).toEqual(`The content of file B`);
|
||||
ws.dispose();
|
||||
graph.dispose();
|
||||
@@ -255,9 +255,12 @@ The content of file B`);
|
||||
const provider = new HoverProvider(hoverEnabled, ws, graph, parser);
|
||||
const result = await provider.provideHover(doc, pos, noCancelToken);
|
||||
|
||||
expect(result.contents).toHaveLength(2);
|
||||
expect(result.contents).toHaveLength(3);
|
||||
expect(result.contents[0]).toEqual(null);
|
||||
expect(result.contents[1]).toEqual(null);
|
||||
expect(getValue(result.contents[2])).toMatch(
|
||||
"[Create note from template for 'wikilink'](command:foam-vscode.create-note?"
|
||||
);
|
||||
ws.dispose();
|
||||
graph.dispose();
|
||||
});
|
||||
@@ -281,11 +284,12 @@ The content of file B`);
|
||||
const provider = new HoverProvider(hoverEnabled, ws, graph, parser);
|
||||
const result = await provider.provideHover(doc, pos, noCancelToken);
|
||||
|
||||
expect(result.contents).toHaveLength(2);
|
||||
expect(result.contents).toHaveLength(3);
|
||||
expect(getValue(result.contents[0])).toEqual(`This is some content`);
|
||||
expect(getValue(result.contents[1])).toMatch(
|
||||
/^Also referenced in 1 note:/
|
||||
);
|
||||
expect(result.contents[2]).toEqual(null);
|
||||
ws.dispose();
|
||||
graph.dispose();
|
||||
});
|
||||
@@ -309,7 +313,7 @@ The content of file B`);
|
||||
const provider = new HoverProvider(hoverEnabled, ws, graph, parser);
|
||||
const result = await provider.provideHover(doc, pos, noCancelToken);
|
||||
|
||||
expect(result.contents).toHaveLength(2);
|
||||
expect(result.contents).toHaveLength(3);
|
||||
expect(getValue(result.contents[1])).toMatch(
|
||||
/^Also referenced in 1 note:/
|
||||
);
|
||||
@@ -333,12 +337,14 @@ The content of file B`);
|
||||
const provider = new HoverProvider(hoverEnabled, ws, graph, parser);
|
||||
const result = await provider.provideHover(doc, pos, noCancelToken);
|
||||
|
||||
expect(result.contents).toHaveLength(2);
|
||||
expect(result.contents).toHaveLength(3);
|
||||
expect(result.contents[0]).toEqual(null);
|
||||
expect(getValue(result.contents[1])).toMatch(
|
||||
/^Also referenced in 2 notes:/
|
||||
);
|
||||
|
||||
expect(getValue(result.contents[2])).toMatch(
|
||||
"[Create note from template for 'placeholder'](command:foam-vscode.create-note?"
|
||||
);
|
||||
ws.dispose();
|
||||
graph.dispose();
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@ import { FoamWorkspace } from '../core/model/workspace';
|
||||
import { Range } from '../core/model/range';
|
||||
import { FoamGraph } from '../core/model/graph';
|
||||
import { OPEN_COMMAND } from './commands/open-resource';
|
||||
import { CREATE_NOTE_COMMAND } from './commands/create-note';
|
||||
|
||||
export const CONFIG_KEY = 'links.hover.enable';
|
||||
|
||||
@@ -108,8 +109,36 @@ export class HoverProvider implements vscode.HoverProvider {
|
||||
: this.workspace.get(targetUri).title;
|
||||
}
|
||||
|
||||
// If placeholder, offer to create a new note from template (compared to default link provider - not from template)
|
||||
const basedir =
|
||||
vscode.workspace.workspaceFolders.length > 0
|
||||
? vscode.workspace.workspaceFolders[0].uri
|
||||
: vscode.window.activeTextEditor?.document.uri
|
||||
? vscode.window.activeTextEditor!.document.uri
|
||||
: undefined;
|
||||
if (basedir === undefined) {
|
||||
return;
|
||||
}
|
||||
const target = fromVsCodeUri(basedir)
|
||||
.resolve(targetUri, true)
|
||||
.changeExtension('', '.md');
|
||||
const args = {
|
||||
text: target.getName(),
|
||||
notePath: target.path,
|
||||
askForTemplate: true,
|
||||
};
|
||||
const command = CREATE_NOTE_COMMAND.asURI(args);
|
||||
const newNoteFromTemplate = new vscode.MarkdownString(
|
||||
`[Create note from template for '${targetUri.getName()}'](${command})`
|
||||
);
|
||||
newNoteFromTemplate.isTrusted = true;
|
||||
|
||||
const hover: vscode.Hover = {
|
||||
contents: [mdContent, sources.length > 0 ? references : null],
|
||||
contents: [
|
||||
mdContent,
|
||||
sources.length > 0 ? references : null,
|
||||
targetUri.isPlaceholder() ? newNoteFromTemplate : null,
|
||||
],
|
||||
range: toVsCodeRange(targetLink.range),
|
||||
};
|
||||
return hover;
|
||||
|
||||
@@ -1,34 +1,26 @@
|
||||
import { FoamFeature } from '../types';
|
||||
import * as commands from './commands';
|
||||
import dataviz from './dataviz';
|
||||
import * as panels from './panels';
|
||||
import dateSnippets from './date-snippets';
|
||||
import tagsExplorer from './tags-tree-view';
|
||||
import orphans from './orphans';
|
||||
import placeholders from './placeholders';
|
||||
import backlinks from './backlinks';
|
||||
import hoverProvider from './hover-provider';
|
||||
import previewNavigation from './preview';
|
||||
import preview from './preview';
|
||||
import completionProvider, { completionCursorMove } from './link-completion';
|
||||
import tagCompletionProvider from './tag-completion';
|
||||
import linkDecorations from './document-decorator';
|
||||
import navigationProviders from './navigation-provider';
|
||||
import wikilinkDiagnostics from './wikilink-diagnostics';
|
||||
import refactor from './refactor';
|
||||
import { FoamFeature } from '../types';
|
||||
|
||||
export const features: FoamFeature[] = [
|
||||
...Object.values(commands),
|
||||
...Object.values(panels),
|
||||
refactor,
|
||||
navigationProviders,
|
||||
wikilinkDiagnostics,
|
||||
tagsExplorer,
|
||||
dataviz,
|
||||
dateSnippets,
|
||||
orphans,
|
||||
placeholders,
|
||||
backlinks,
|
||||
hoverProvider,
|
||||
linkDecorations,
|
||||
previewNavigation,
|
||||
preview,
|
||||
completionProvider,
|
||||
tagCompletionProvider,
|
||||
completionCursorMove,
|
||||
|
||||
@@ -7,10 +7,11 @@ import {
|
||||
closeEditors,
|
||||
createFile,
|
||||
showInEditor,
|
||||
withModifiedFoamConfiguration,
|
||||
} from '../test/test-utils-vscode';
|
||||
import { fromVsCodeUri } from '../utils/vsc-utils';
|
||||
import {
|
||||
CompletionProvider,
|
||||
WikilinkCompletionProvider,
|
||||
SectionCompletionProvider,
|
||||
} from './link-completion';
|
||||
|
||||
@@ -63,7 +64,7 @@ describe('Link Completion', () => {
|
||||
it('should not return any link for empty documents', async () => {
|
||||
const { uri } = await createFile('');
|
||||
const { doc } = await showInEditor(uri);
|
||||
const provider = new CompletionProvider(ws, graph);
|
||||
const provider = new WikilinkCompletionProvider(ws, graph);
|
||||
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
@@ -76,7 +77,7 @@ describe('Link Completion', () => {
|
||||
it('should not return link outside the wikilink brackets', async () => {
|
||||
const { uri } = await createFile('[[file]] then');
|
||||
const { doc } = await showInEditor(uri);
|
||||
const provider = new CompletionProvider(ws, graph);
|
||||
const provider = new WikilinkCompletionProvider(ws, graph);
|
||||
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
@@ -90,7 +91,7 @@ describe('Link Completion', () => {
|
||||
for (const text of ['[[', '[[file]] [[', '[[file]] #tag [[']) {
|
||||
const { uri } = await createFile(text);
|
||||
const { doc } = await showInEditor(uri);
|
||||
const provider = new CompletionProvider(ws, graph);
|
||||
const provider = new WikilinkCompletionProvider(ws, graph);
|
||||
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
@@ -110,6 +111,103 @@ describe('Link Completion', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('should support label setting', async () => {
|
||||
const { uri: noteUri, content } = await createFile(`# My Note Title`);
|
||||
const workspace = createTestWorkspace();
|
||||
workspace.set(parser.parse(noteUri, content));
|
||||
const provider = new WikilinkCompletionProvider(
|
||||
workspace,
|
||||
FoamGraph.fromWorkspace(workspace)
|
||||
);
|
||||
|
||||
const { uri } = await createFile('[[');
|
||||
const { doc } = await showInEditor(uri);
|
||||
|
||||
await withModifiedFoamConfiguration(
|
||||
'completion.label',
|
||||
'title',
|
||||
async () => {
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
new vscode.Position(0, 3)
|
||||
);
|
||||
|
||||
expect(links.items.map(i => i.label)).toEqual(['My Note Title']);
|
||||
}
|
||||
);
|
||||
|
||||
await withModifiedFoamConfiguration(
|
||||
'completion.label',
|
||||
'path',
|
||||
async () => {
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
new vscode.Position(0, 3)
|
||||
);
|
||||
|
||||
expect(links.items.map(i => i.label)).toEqual([noteUri.getBasename()]);
|
||||
}
|
||||
);
|
||||
|
||||
await withModifiedFoamConfiguration(
|
||||
'completion.label',
|
||||
'identifier',
|
||||
async () => {
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
new vscode.Position(0, 3)
|
||||
);
|
||||
|
||||
expect(links.items.map(i => i.label)).toEqual([
|
||||
workspace.getIdentifier(noteUri),
|
||||
]);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should support alias setting', async () => {
|
||||
const { uri: noteUri, content } = await createFile(`# My Note Title`);
|
||||
const workspace = createTestWorkspace();
|
||||
workspace.set(parser.parse(noteUri, content));
|
||||
const provider = new WikilinkCompletionProvider(
|
||||
workspace,
|
||||
FoamGraph.fromWorkspace(workspace)
|
||||
);
|
||||
|
||||
const { uri } = await createFile('[[');
|
||||
const { doc } = await showInEditor(uri);
|
||||
|
||||
await withModifiedFoamConfiguration(
|
||||
'completion.useAlias',
|
||||
'never',
|
||||
async () => {
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
new vscode.Position(0, 3)
|
||||
);
|
||||
|
||||
expect(links.items.map(i => i.insertText)).toEqual([
|
||||
workspace.getIdentifier(noteUri),
|
||||
]);
|
||||
}
|
||||
);
|
||||
|
||||
await withModifiedFoamConfiguration(
|
||||
'completion.useAlias',
|
||||
'whenPathDiffersFromTitle',
|
||||
async () => {
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
new vscode.Position(0, 3)
|
||||
);
|
||||
|
||||
expect(links.items.map(i => i.insertText)).toEqual([
|
||||
`${workspace.getIdentifier(noteUri)}|My Note Title`,
|
||||
]);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should return sections for other notes', async () => {
|
||||
for (const text of [
|
||||
'[[file-name#',
|
||||
@@ -171,7 +269,7 @@ alias: alias-a
|
||||
ws.set(parser.parse(uri, content));
|
||||
|
||||
const { doc } = await showInEditor(uri);
|
||||
const provider = new CompletionProvider(ws, graph);
|
||||
const provider = new WikilinkCompletionProvider(ws, graph);
|
||||
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { Foam } from '../core/model/foam';
|
||||
import { FoamGraph } from '../core/model/graph';
|
||||
import { Resource } from '../core/model/note';
|
||||
import { URI } from '../core/model/uri';
|
||||
import { FoamWorkspace } from '../core/model/workspace';
|
||||
import { getFoamVsCodeConfig } from '../services/config';
|
||||
import { FoamFeature } from '../types';
|
||||
import { getNoteTooltip, mdDocSelector } from '../utils';
|
||||
import { fromVsCodeUri, toVsCodeUri } from '../utils/vsc-utils';
|
||||
@@ -28,7 +30,7 @@ const feature: FoamFeature = {
|
||||
context.subscriptions.push(
|
||||
vscode.languages.registerCompletionItemProvider(
|
||||
mdDocSelector,
|
||||
new CompletionProvider(foam.workspace, foam.graph),
|
||||
new WikilinkCompletionProvider(foam.workspace, foam.graph),
|
||||
'['
|
||||
),
|
||||
vscode.languages.registerCompletionItemProvider(
|
||||
@@ -159,7 +161,7 @@ export class SectionCompletionProvider
|
||||
}
|
||||
}
|
||||
|
||||
export class CompletionProvider
|
||||
export class WikilinkCompletionProvider
|
||||
implements vscode.CompletionItemProvider<vscode.CompletionItem> {
|
||||
constructor(private ws: FoamWorkspace, private graph: FoamGraph) {}
|
||||
|
||||
@@ -186,20 +188,45 @@ export class CompletionProvider
|
||||
position.line,
|
||||
position.character
|
||||
);
|
||||
const labelStyle = getCompletionLabelSetting();
|
||||
const aliasSetting = getCompletionAliasSetting();
|
||||
|
||||
const resources = this.ws.list().map(resource => {
|
||||
const label = vscode.workspace.asRelativePath(toVsCodeUri(resource.uri));
|
||||
const resourceIsDocument =
|
||||
['attachment', 'image'].indexOf(resource.type) === -1;
|
||||
|
||||
const identifier = this.ws.getIdentifier(resource.uri);
|
||||
|
||||
const label = !resourceIsDocument
|
||||
? identifier
|
||||
: labelStyle === 'path'
|
||||
? vscode.workspace.asRelativePath(toVsCodeUri(resource.uri))
|
||||
: labelStyle === 'title'
|
||||
? resource.title
|
||||
: identifier;
|
||||
|
||||
const item = new ResourceCompletionItem(
|
||||
label,
|
||||
vscode.CompletionItemKind.File,
|
||||
resource.uri
|
||||
);
|
||||
item.sortText =
|
||||
resource.type === 'attachment' ? `1-${item.label}` : `0-${item.label}`;
|
||||
item.filterText = resource.uri.getName();
|
||||
item.insertText = this.ws.getIdentifier(resource.uri);
|
||||
|
||||
item.detail = vscode.workspace.asRelativePath(toVsCodeUri(resource.uri));
|
||||
item.sortText = resourceIsDocument
|
||||
? `0-${item.label}`
|
||||
: `1-${item.label}`;
|
||||
|
||||
const useAlias =
|
||||
resourceIsDocument &&
|
||||
aliasSetting !== 'never' &&
|
||||
wikilinkRequiresAlias(resource);
|
||||
|
||||
item.insertText = useAlias
|
||||
? `${identifier}|${resource.title}`
|
||||
: identifier;
|
||||
item.commitCharacters = useAlias ? [] : linkCommitCharacters;
|
||||
item.range = replacementRange;
|
||||
item.command = COMPLETION_CURSOR_MOVE;
|
||||
item.commitCharacters = linkCommitCharacters;
|
||||
return item;
|
||||
});
|
||||
const aliases = this.ws.list().flatMap(resource =>
|
||||
@@ -265,4 +292,23 @@ class ResourceCompletionItem extends vscode.CompletionItem {
|
||||
}
|
||||
}
|
||||
|
||||
function getCompletionLabelSetting() {
|
||||
const labelStyle: 'path' | 'title' | 'identifier' = getFoamVsCodeConfig(
|
||||
'completion.label'
|
||||
);
|
||||
return labelStyle;
|
||||
}
|
||||
|
||||
function getCompletionAliasSetting() {
|
||||
const aliasStyle: 'never' | 'whenPathDiffersFromTitle' = getFoamVsCodeConfig(
|
||||
'completion.useAlias'
|
||||
);
|
||||
return aliasStyle;
|
||||
}
|
||||
|
||||
const normalize = (text: string) => text.toLocaleLowerCase().trim();
|
||||
function wikilinkRequiresAlias(resource: Resource) {
|
||||
return normalize(resource.uri.getName()) !== normalize(resource.title);
|
||||
}
|
||||
|
||||
export default feature;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { workspace, window } from 'vscode';
|
||||
import { createTestNote, createTestWorkspace } from '../test/test-utils';
|
||||
import { createTestNote, createTestWorkspace } from '../../test/test-utils';
|
||||
import {
|
||||
cleanWorkspace,
|
||||
closeEditors,
|
||||
createNote,
|
||||
getUriInWorkspace,
|
||||
} from '../test/test-utils-vscode';
|
||||
} from '../../test/test-utils-vscode';
|
||||
import { BacklinksTreeDataProvider, BacklinkTreeItem } from './backlinks';
|
||||
import { ResourceTreeItem } from '../utils/grouped-resources-tree-data-provider';
|
||||
import { OPEN_COMMAND } from './commands/open-resource';
|
||||
import { toVsCodeUri } from '../utils/vsc-utils';
|
||||
import { FoamGraph } from '../core/model/graph';
|
||||
import { URI } from '../core/model/uri';
|
||||
import { ResourceTreeItem } from '../../utils/grouped-resources-tree-data-provider';
|
||||
import { OPEN_COMMAND } from '../commands/open-resource';
|
||||
import { toVsCodeUri } from '../../utils/vsc-utils';
|
||||
import { FoamGraph } from '../../core/model/graph';
|
||||
import { URI } from '../../core/model/uri';
|
||||
|
||||
describe('Backlinks panel', () => {
|
||||
beforeAll(async () => {
|
||||
@@ -1,16 +1,16 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { groupBy } from 'lodash';
|
||||
import { URI } from '../core/model/uri';
|
||||
import { URI } from '../../core/model/uri';
|
||||
|
||||
import { getNoteTooltip, isNone } from '../utils';
|
||||
import { FoamFeature } from '../types';
|
||||
import { ResourceTreeItem } from '../utils/grouped-resources-tree-data-provider';
|
||||
import { Foam } from '../core/model/foam';
|
||||
import { FoamWorkspace } from '../core/model/workspace';
|
||||
import { FoamGraph } from '../core/model/graph';
|
||||
import { Resource, ResourceLink } from '../core/model/note';
|
||||
import { Range } from '../core/model/range';
|
||||
import { fromVsCodeUri, toVsCodeUri } from '../utils/vsc-utils';
|
||||
import { getNoteTooltip, isNone } from '../../utils';
|
||||
import { FoamFeature } from '../../types';
|
||||
import { ResourceTreeItem } from '../../utils/grouped-resources-tree-data-provider';
|
||||
import { Foam } from '../../core/model/foam';
|
||||
import { FoamWorkspace } from '../../core/model/workspace';
|
||||
import { FoamGraph } from '../../core/model/graph';
|
||||
import { Resource, ResourceLink } from '../../core/model/note';
|
||||
import { Range } from '../../core/model/range';
|
||||
import { fromVsCodeUri, toVsCodeUri } from '../../utils/vsc-utils';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: async (
|
||||
@@ -1,11 +1,11 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { FoamFeature } from '../types';
|
||||
import { FoamFeature } from '../../types';
|
||||
import { TextDecoder } from 'util';
|
||||
import { getGraphStyle, getTitleMaxLength } from '../settings';
|
||||
import { isSome } from '../utils';
|
||||
import { Foam } from '../core/model/foam';
|
||||
import { Logger } from '../core/utils/log';
|
||||
import { fromVsCodeUri } from '../utils/vsc-utils';
|
||||
import { getGraphStyle, getTitleMaxLength } from '../../settings';
|
||||
import { isSome } from '../../utils';
|
||||
import { Foam } from '../../core/model/foam';
|
||||
import { Logger } from '../../core/utils/log';
|
||||
import { fromVsCodeUri } from '../../utils/vsc-utils';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: (context: vscode.ExtensionContext, foamPromise: Promise<Foam>) => {
|
||||
@@ -141,10 +141,11 @@ async function createGraphPanel(foam: Foam, context: vscode.ExtensionContext) {
|
||||
const selectedNote = foam.workspace.get(fromVsCodeUri(noteUri));
|
||||
|
||||
if (isSome(selectedNote)) {
|
||||
const doc = await vscode.workspace.openTextDocument(
|
||||
selectedNote.uri.path // vscode doesn't recognize the URI directly
|
||||
vscode.commands.executeCommand(
|
||||
'vscode.open',
|
||||
noteUri,
|
||||
vscode.ViewColumn.One
|
||||
);
|
||||
vscode.window.showTextDocument(doc, vscode.ViewColumn.One);
|
||||
}
|
||||
break;
|
||||
}
|
||||
5
packages/foam-vscode/src/features/panels/index.ts
Normal file
5
packages/foam-vscode/src/features/panels/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export { default as backlinks } from './backlinks';
|
||||
export { default as dataviz } from './dataviz';
|
||||
export { default as orphans } from './orphans';
|
||||
export { default as placeholders } from './placeholders';
|
||||
export { default as tags } from './tags-explorer';
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FoamGraph } from '../core/model/graph';
|
||||
import { createTestNote, createTestWorkspace } from '../test/test-utils';
|
||||
import { FoamGraph } from '../../core/model/graph';
|
||||
import { createTestNote, createTestWorkspace } from '../../test/test-utils';
|
||||
import { isOrphan } from './orphans';
|
||||
|
||||
const orphanA = createTestNote({
|
||||
@@ -1,15 +1,15 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { Foam } from '../core/model/foam';
|
||||
import { FoamGraph } from '../core/model/graph';
|
||||
import { URI } from '../core/model/uri';
|
||||
import { getOrphansConfig } from '../settings';
|
||||
import { FoamFeature } from '../types';
|
||||
import { Foam } from '../../core/model/foam';
|
||||
import { FoamGraph } from '../../core/model/graph';
|
||||
import { URI } from '../../core/model/uri';
|
||||
import { getOrphansConfig } from '../../settings';
|
||||
import { FoamFeature } from '../../types';
|
||||
import {
|
||||
GroupedResourcesTreeDataProvider,
|
||||
ResourceTreeItem,
|
||||
UriTreeItem,
|
||||
} from '../utils/grouped-resources-tree-data-provider';
|
||||
import { fromVsCodeUri } from '../utils/vsc-utils';
|
||||
} from '../../utils/grouped-resources-tree-data-provider';
|
||||
import { fromVsCodeUri } from '../../utils/vsc-utils';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: async (
|
||||
@@ -1,12 +1,12 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { Foam } from '../core/model/foam';
|
||||
import { getPlaceholdersConfig } from '../settings';
|
||||
import { FoamFeature } from '../types';
|
||||
import { Foam } from '../../core/model/foam';
|
||||
import { getPlaceholdersConfig } from '../../settings';
|
||||
import { FoamFeature } from '../../types';
|
||||
import {
|
||||
GroupedResourcesTreeDataProvider,
|
||||
UriTreeItem,
|
||||
} from '../utils/grouped-resources-tree-data-provider';
|
||||
import { fromVsCodeUri } from '../utils/vsc-utils';
|
||||
} from '../../utils/grouped-resources-tree-data-provider';
|
||||
import { fromVsCodeUri } from '../../utils/vsc-utils';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: async (
|
||||
@@ -1,17 +1,18 @@
|
||||
import { createTestNote, readFileFromFs } from '../test/test-utils';
|
||||
import { cleanWorkspace, closeEditors } from '../test/test-utils-vscode';
|
||||
import { TagItem, TagReference, TagsProvider } from './tags-tree-view';
|
||||
import { bootstrap, Foam } from '../core/model/foam';
|
||||
import { MarkdownResourceProvider } from '../core/services/markdown-provider';
|
||||
import { FileDataStore, Matcher } from '../core/services/datastore';
|
||||
import { createMarkdownParser } from '../core/services/markdown-parser';
|
||||
import { createTestNote, readFileFromFs } from '../../test/test-utils';
|
||||
import { cleanWorkspace, closeEditors } from '../../test/test-utils-vscode';
|
||||
import { TagItem, TagReference, TagsProvider } from './tags-explorer';
|
||||
import { bootstrap, Foam } from '../../core/model/foam';
|
||||
import { MarkdownResourceProvider } from '../../core/services/markdown-provider';
|
||||
import { FileDataStore, Matcher } from '../../core/services/datastore';
|
||||
import { createMarkdownParser } from '../../core/services/markdown-parser';
|
||||
import { URI } from '../../core/model/uri';
|
||||
|
||||
describe('Tags tree panel', () => {
|
||||
let _foam: Foam;
|
||||
let provider: TagsProvider;
|
||||
|
||||
const dataStore = new FileDataStore(readFileFromFs);
|
||||
const matcher = new Matcher([]);
|
||||
const matcher = new Matcher([URI.file('/root')]);
|
||||
const parser = createMarkdownParser();
|
||||
const mdProvider = new MarkdownResourceProvider(matcher, dataStore, parser);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { URI } from '../core/model/uri';
|
||||
import { URI } from '../../core/model/uri';
|
||||
import * as vscode from 'vscode';
|
||||
import { FoamFeature } from '../types';
|
||||
import { getNoteTooltip, isSome } from '../utils';
|
||||
import { toVsCodeRange, toVsCodeUri } from '../utils/vsc-utils';
|
||||
import { Foam } from '../core/model/foam';
|
||||
import { FoamWorkspace } from '../core/model/workspace';
|
||||
import { Resource, Tag } from '../core/model/note';
|
||||
import { FoamFeature } from '../../types';
|
||||
import { getNoteTooltip, isSome } from '../../utils';
|
||||
import { toVsCodeRange, toVsCodeUri } from '../../utils/vsc-utils';
|
||||
import { Foam } from '../../core/model/foam';
|
||||
import { FoamWorkspace } from '../../core/model/workspace';
|
||||
import { Resource, Tag } from '../../core/model/note';
|
||||
|
||||
const TAG_SEPARATOR = '/';
|
||||
const feature: FoamFeature = {
|
||||
@@ -1,10 +1,10 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { FoamFeature } from '../../types';
|
||||
import { Foam } from '../../core/model/foam';
|
||||
import markdownItFoamTags from './tag-highlight';
|
||||
import markdownItWikilinkNavigation from './wikilink-navigation';
|
||||
import markdownItRemoveLinkReferences from './remove-wikilink-references';
|
||||
import markdownItWikilinkEmbed from './wikilink-embed';
|
||||
import { default as markdownItFoamTags } from './tag-highlight';
|
||||
import { default as markdownItWikilinkNavigation } from './wikilink-navigation';
|
||||
import { default as markdownItRemoveLinkReferences } from './remove-wikilink-references';
|
||||
import { default as markdownItWikilinkEmbed } from './wikilink-embed';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: async (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import MarkdownIt from 'markdown-it';
|
||||
import { FoamWorkspace } from '../../core/model/workspace';
|
||||
import markdownItFoamTags from './tag-highlight';
|
||||
import { default as markdownItFoamTags } from './tag-highlight';
|
||||
|
||||
describe('Stylable tag generation in preview', () => {
|
||||
const md = markdownItFoamTags(MarkdownIt(), new FoamWorkspace());
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
deleteFile,
|
||||
withModifiedFoamConfiguration,
|
||||
} from '../../test/test-utils-vscode';
|
||||
import markdownItWikilinkEmbed, {
|
||||
import {
|
||||
default as markdownItWikilinkEmbed,
|
||||
CONFIG_EMBED_NOTE_IN_CONTAINER,
|
||||
} from './wikilink-embed';
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import markdownItRegex from 'markdown-it-regex';
|
||||
import * as vscode from 'vscode';
|
||||
import { isSome } from '../../utils';
|
||||
import { FoamWorkspace } from '../../core/model/workspace';
|
||||
import { Logger } from '../../core/utils/log';
|
||||
import { toVsCodeUri } from '../../utils/vsc-utils';
|
||||
import { Resource } from '../../core/model/note';
|
||||
import { getFoamVsCodeConfig } from '../../services/config';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import MarkdownIt from 'markdown-it';
|
||||
import { createMarkdownParser } from '../../core/services/markdown-parser';
|
||||
import { FoamWorkspace } from '../../core/model/workspace';
|
||||
import { createTestNote } from '../../test/test-utils';
|
||||
import { getUriInWorkspace } from '../../test/test-utils-vscode';
|
||||
import markdownItWikilinkNavigation from './wikilink-navigation';
|
||||
import markdownItRemoveLinkReferences from './remove-wikilink-references';
|
||||
|
||||
const parser = createMarkdownParser();
|
||||
import { default as markdownItWikilinkNavigation } from './wikilink-navigation';
|
||||
import { default as markdownItRemoveLinkReferences } from './remove-wikilink-references';
|
||||
|
||||
describe('Link generation in preview', () => {
|
||||
const noteA = createTestNote({
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
import markdownItRegex from 'markdown-it-regex';
|
||||
import * as vscode from 'vscode';
|
||||
import { FoamFeature } from '../../types';
|
||||
import { isNone, isSome } from '../../utils';
|
||||
import { Foam } from '../../core/model/foam';
|
||||
import { isNone } from '../../utils';
|
||||
import { FoamWorkspace } from '../../core/model/workspace';
|
||||
import { Logger } from '../../core/utils/log';
|
||||
import { toVsCodeUri } from '../../utils/vsc-utils';
|
||||
import { Resource } from '../../core/model/note';
|
||||
import { MarkdownLink } from '../../core/services/markdown-link';
|
||||
import { Range } from '../../core/model/range';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { getFoamVsCodeConfig } from '../../services/config';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
export const markdownItWikilinkNavigation = (
|
||||
md: markdownit,
|
||||
|
||||
@@ -5,7 +5,12 @@ import {
|
||||
createFile,
|
||||
showInEditor,
|
||||
} from '../test/test-utils-vscode';
|
||||
import { getCurrentEditorDirectory, replaceSelection } from './editor';
|
||||
import {
|
||||
asAbsoluteWorkspaceUri,
|
||||
getCurrentEditorDirectory,
|
||||
replaceSelection,
|
||||
} from './editor';
|
||||
import { URI } from '../core/model/uri';
|
||||
|
||||
describe('Editor utils', () => {
|
||||
beforeAll(closeEditors);
|
||||
@@ -38,4 +43,14 @@ describe('Editor utils', () => {
|
||||
expect(doc.doc.getText()).toEqual('This was the file A');
|
||||
});
|
||||
});
|
||||
|
||||
describe('asAbsoluteWorkspaceUri', () => {
|
||||
it('should work with the VS Code workspace folders if none are passed', () => {
|
||||
const uri = URI.file('relative/path');
|
||||
const workspaceFolder = workspace.workspaceFolders[0];
|
||||
expect(asAbsoluteWorkspaceUri(uri)).toEqual(
|
||||
fromVsCodeUri(workspaceFolder.uri).joinPath(uri.path)
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { URI } from '../core/model/uri';
|
||||
import { asAbsoluteUri, URI } from '../core/model/uri';
|
||||
import { TextEncoder } from 'util';
|
||||
import {
|
||||
FileType,
|
||||
Selection,
|
||||
SnippetString,
|
||||
TextDocument,
|
||||
@@ -85,3 +86,41 @@ export function getCurrentEditorDirectory(): URI {
|
||||
|
||||
throw new Error('A file must be open in editor, or workspace folder needed');
|
||||
}
|
||||
|
||||
export async function fileExists(uri: URI): Promise<boolean> {
|
||||
try {
|
||||
const stat = await workspace.fs.stat(toVsCodeUri(uri));
|
||||
return stat.type === FileType.File;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function readFile(uri: URI): Promise<string | undefined> {
|
||||
if (await fileExists(uri)) {
|
||||
return workspace.fs
|
||||
.readFile(toVsCodeUri(uri))
|
||||
.then(bytes => bytes.toString());
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export const deleteFile = (uri: URI) => {
|
||||
return workspace.fs.delete(toVsCodeUri(uri), { recursive: true });
|
||||
};
|
||||
|
||||
/**
|
||||
* Turns a relative URI into an absolute URI for the given workspace.
|
||||
* @param uri the uri to evaluate
|
||||
* @returns an absolute uri
|
||||
*/
|
||||
export function asAbsoluteWorkspaceUri(uri: URI): URI {
|
||||
if (workspace.workspaceFolders === undefined) {
|
||||
throw new Error('An open folder or workspace is required');
|
||||
}
|
||||
const folders = workspace.workspaceFolders.map(folder =>
|
||||
fromVsCodeUri(folder.uri)
|
||||
);
|
||||
const res = asAbsoluteUri(uri, folders);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Selection, ViewColumn, window, workspace } from 'vscode';
|
||||
import { isWindows } from '../core/common/platform';
|
||||
import { Selection, ViewColumn, window } from 'vscode';
|
||||
import { fromVsCodeUri } from '../utils/vsc-utils';
|
||||
import { determineNewNoteFilepath, NoteFactory } from '../services/templates';
|
||||
import { NoteFactory } from '../services/templates';
|
||||
import {
|
||||
closeEditors,
|
||||
createFile,
|
||||
@@ -10,6 +9,7 @@ import {
|
||||
showInEditor,
|
||||
} from '../test/test-utils-vscode';
|
||||
import { Resolver } from './variable-resolver';
|
||||
import { fileExists } from './editor';
|
||||
|
||||
describe('Create note from template', () => {
|
||||
beforeEach(async () => {
|
||||
@@ -113,27 +113,6 @@ foam_template: # foam template metadata
|
||||
});
|
||||
|
||||
describe('Creation with active text selection', () => {
|
||||
it('should populate FOAM_SELECTED_TEXT with the current selection', async () => {
|
||||
const templateA = await createFile('Template A', [
|
||||
'.foam',
|
||||
'templates',
|
||||
'template-a.md',
|
||||
]);
|
||||
const file = await createFile('Content of first file');
|
||||
const { editor } = await showInEditor(file.uri);
|
||||
editor.selection = new Selection(0, 11, 1, 0);
|
||||
const target = getUriInWorkspace();
|
||||
const resolver = new Resolver(new Map(), new Date());
|
||||
await NoteFactory.createFromTemplate(templateA.uri, resolver, target);
|
||||
expect(await resolver.resolveFromName('FOAM_SELECTED_TEXT')).toEqual(
|
||||
'first file'
|
||||
);
|
||||
|
||||
await deleteFile(templateA);
|
||||
await deleteFile(target);
|
||||
await deleteFile(file);
|
||||
});
|
||||
|
||||
it('should open created note in a new column if there was a selection', async () => {
|
||||
const templateA = await createFile('Template A', [
|
||||
'.foam',
|
||||
@@ -183,91 +162,69 @@ foam_template: # foam template metadata
|
||||
expect(window.visibleTextEditors[0].document.getText()).toEqual(
|
||||
`This is my first file: [[${target.getName()}]]`
|
||||
);
|
||||
await deleteFile(template.uri);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('determineNewNoteFilepath', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
jest.restoreAllMocks();
|
||||
describe('NoteFactory.createNote', () => {
|
||||
beforeEach(async () => {
|
||||
await closeEditors();
|
||||
});
|
||||
it('should use the template path if absolute', async () => {
|
||||
const winAbsolutePath = 'C:\\absolute_path\\journal\\My Note Title.md';
|
||||
const linuxAbsolutePath = '/absolute_path/journal/My Note Title.md';
|
||||
const winResult = await determineNewNoteFilepath(
|
||||
winAbsolutePath,
|
||||
undefined,
|
||||
it('should create a new note', async () => {
|
||||
const target = getUriInWorkspace();
|
||||
await NoteFactory.createNote(
|
||||
target,
|
||||
'Hello World',
|
||||
new Resolver(new Map(), new Date())
|
||||
);
|
||||
expect(winResult.toFsPath()).toMatch(winAbsolutePath);
|
||||
const linuxResult = await determineNewNoteFilepath(
|
||||
linuxAbsolutePath,
|
||||
undefined,
|
||||
new Resolver(new Map(), new Date())
|
||||
);
|
||||
expect(linuxResult.toFsPath()).toMatch(linuxAbsolutePath);
|
||||
expect(await fileExists(target)).toBeTruthy();
|
||||
expect(window.activeTextEditor.document.getText()).toEqual('Hello World');
|
||||
|
||||
await deleteFile(target);
|
||||
});
|
||||
|
||||
it('should compute the relative template filepath from the current directory', async () => {
|
||||
const relativePath = isWindows
|
||||
? 'journal\\My Note Title.md'
|
||||
: 'journal/My Note Title.md';
|
||||
const resultFilepath = await determineNewNoteFilepath(
|
||||
relativePath,
|
||||
it('should support not replacing the selection with a link to the newly created note', async () => {
|
||||
const file = await createFile('This is my first file: World');
|
||||
const { editor } = await showInEditor(file.uri);
|
||||
editor.selection = new Selection(0, 23, 0, 28);
|
||||
const target = getUriInWorkspace();
|
||||
await NoteFactory.createNote(
|
||||
target,
|
||||
'Hello ${FOAM_SELECTED_TEXT} ${FOAM_SELECTED_TEXT}', // eslint-disable-line no-template-curly-in-string
|
||||
new Resolver(new Map(), new Date()),
|
||||
undefined,
|
||||
new Resolver(new Map(), new Date())
|
||||
false
|
||||
);
|
||||
const expectedPath = fromVsCodeUri(
|
||||
workspace.workspaceFolders[0].uri
|
||||
).joinPath(relativePath);
|
||||
expect(resultFilepath.toFsPath()).toMatch(expectedPath.toFsPath());
|
||||
expect(window.activeTextEditor.document.getText()).toEqual(
|
||||
'Hello World World'
|
||||
);
|
||||
expect(window.visibleTextEditors[0].document.getText()).toEqual(
|
||||
`This is my first file: World`
|
||||
);
|
||||
await deleteFile(file.uri);
|
||||
await deleteFile(target);
|
||||
});
|
||||
|
||||
it('should use the note title if nothing else is available', async () => {
|
||||
const noteTitle = 'My new note';
|
||||
const resultFilepath = await determineNewNoteFilepath(
|
||||
it('should support replacing the selection with a link to the newly created note', async () => {
|
||||
const file = await createFile('This is my first file: World');
|
||||
const { editor } = await showInEditor(file.uri);
|
||||
editor.selection = new Selection(0, 23, 0, 28);
|
||||
const target = getUriInWorkspace();
|
||||
await NoteFactory.createNote(
|
||||
target,
|
||||
'Hello ${FOAM_SELECTED_TEXT} ${FOAM_SELECTED_TEXT}', // eslint-disable-line no-template-curly-in-string
|
||||
new Resolver(new Map(), new Date()),
|
||||
undefined,
|
||||
undefined,
|
||||
new Resolver(new Map().set('FOAM_TITLE', noteTitle), new Date())
|
||||
true
|
||||
);
|
||||
const expectedPath = fromVsCodeUri(
|
||||
workspace.workspaceFolders[0].uri
|
||||
).joinPath(`${noteTitle}.md`);
|
||||
expect(resultFilepath.toFsPath()).toMatch(expectedPath.toFsPath());
|
||||
});
|
||||
|
||||
it('should ask the user for a note title if nothing else is available', async () => {
|
||||
const noteTitle = 'My new note';
|
||||
const spy = jest
|
||||
.spyOn(window, 'showInputBox')
|
||||
.mockImplementationOnce(jest.fn(() => Promise.resolve(noteTitle)));
|
||||
const resultFilepath = await determineNewNoteFilepath(
|
||||
undefined,
|
||||
undefined,
|
||||
new Resolver(new Map(), new Date())
|
||||
expect(window.activeTextEditor.document.getText()).toEqual(
|
||||
'Hello World World'
|
||||
);
|
||||
const expectedPath = fromVsCodeUri(
|
||||
workspace.workspaceFolders[0].uri
|
||||
).joinPath(`${noteTitle}.md`);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
expect(resultFilepath.toFsPath()).toMatch(expectedPath.toFsPath());
|
||||
});
|
||||
|
||||
it('should filter invalid chars from the title #1042', async () => {
|
||||
const noteTitle = 'My new note/';
|
||||
const spy = jest
|
||||
.spyOn(window, 'showInputBox')
|
||||
.mockImplementationOnce(jest.fn(() => Promise.resolve(noteTitle)));
|
||||
const resultFilepath = await determineNewNoteFilepath(
|
||||
undefined,
|
||||
undefined,
|
||||
new Resolver(new Map(), new Date())
|
||||
expect(window.visibleTextEditors[0].document.getText()).toEqual(
|
||||
`This is my first file: [[${target.getName()}]]`
|
||||
);
|
||||
const expectedPath = fromVsCodeUri(
|
||||
workspace.workspaceFolders[0].uri
|
||||
).joinPath(`My new note.md`);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
expect(resultFilepath.toFsPath()).toMatch(expectedPath.toFsPath());
|
||||
await deleteFile(file.uri);
|
||||
await deleteFile(target);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,35 +1,51 @@
|
||||
import { URI } from '../core/model/uri';
|
||||
import { TextEncoder } from 'util';
|
||||
import { FileType, SnippetString, ViewColumn, window, workspace } from 'vscode';
|
||||
import {
|
||||
SnippetString,
|
||||
ViewColumn,
|
||||
QuickPickItem,
|
||||
commands,
|
||||
window,
|
||||
workspace,
|
||||
} from 'vscode';
|
||||
import { focusNote } from '../utils';
|
||||
import { fromVsCodeUri, toVsCodeUri } from '../utils/vsc-utils';
|
||||
import { extractFoamTemplateFrontmatterMetadata } from '../utils/template-frontmatter-parser';
|
||||
import { UserCancelledOperation } from './errors';
|
||||
import {
|
||||
asAbsoluteWorkspaceUri,
|
||||
createDocAndFocus,
|
||||
deleteFile,
|
||||
fileExists,
|
||||
findSelectionContent,
|
||||
getCurrentEditorDirectory,
|
||||
readFile,
|
||||
replaceSelection,
|
||||
} from './editor';
|
||||
import { Resolver } from './variable-resolver';
|
||||
import dateFormat from 'dateformat';
|
||||
import { isSome } from '../core/utils';
|
||||
|
||||
/**
|
||||
* The templates directory
|
||||
*/
|
||||
export const TEMPLATES_DIR = fromVsCodeUri(
|
||||
workspace.workspaceFolders[0].uri
|
||||
).joinPath('.foam', 'templates');
|
||||
export const getTemplatesDir = () =>
|
||||
fromVsCodeUri(workspace.workspaceFolders[0].uri).joinPath(
|
||||
'.foam',
|
||||
'templates'
|
||||
);
|
||||
|
||||
/**
|
||||
* The URI of the default template
|
||||
*/
|
||||
export const DEFAULT_TEMPLATE_URI = TEMPLATES_DIR.joinPath('new-note.md');
|
||||
export const getDefaultTemplateUri = () =>
|
||||
getTemplatesDir().joinPath('new-note.md');
|
||||
|
||||
/**
|
||||
* The URI of the template for daily notes
|
||||
*/
|
||||
export const DAILY_NOTE_TEMPLATE_URI = TEMPLATES_DIR.joinPath('daily-note.md');
|
||||
export const getDailyNoteTemplateUri = () =>
|
||||
getTemplatesDir().joinPath('daily-note.md');
|
||||
|
||||
const WIKILINK_DEFAULT_TEMPLATE_TEXT = `# $\{1:$FOAM_TITLE}\n\n$0`;
|
||||
|
||||
@@ -55,9 +71,7 @@ For a full list of features see [the VS Code snippets page](https://code.visuals
|
||||
export async function getTemplateMetadata(
|
||||
templateUri: URI
|
||||
): Promise<Map<string, string>> {
|
||||
const contents = await workspace.fs
|
||||
.readFile(toVsCodeUri(templateUri))
|
||||
.then(bytes => bytes.toString());
|
||||
const contents = (await readFile(templateUri)) ?? '';
|
||||
const [templateMetadata] = extractFoamTemplateFrontmatterMetadata(contents);
|
||||
return templateMetadata;
|
||||
}
|
||||
@@ -74,11 +88,7 @@ export async function getTemplateInfo(
|
||||
templateFallbackText = '',
|
||||
resolver: Resolver
|
||||
) {
|
||||
const templateText = (await fileExists(templateUri))
|
||||
? await workspace.fs
|
||||
.readFile(toVsCodeUri(templateUri))
|
||||
.then(bytes => bytes.toString())
|
||||
: templateFallbackText;
|
||||
const templateText = (await readFile(templateUri)) ?? templateFallbackText;
|
||||
|
||||
const templateWithResolvedVariables = await resolver.resolveText(
|
||||
templateText
|
||||
@@ -95,7 +105,173 @@ export async function getTemplateInfo(
|
||||
};
|
||||
}
|
||||
|
||||
export type OnFileExistStrategy =
|
||||
| 'open'
|
||||
| 'overwrite'
|
||||
| 'cancel'
|
||||
| 'ask'
|
||||
| ((filePath: URI) => Promise<URI | undefined>);
|
||||
|
||||
export async function askUserForTemplate() {
|
||||
const templates = await getTemplates();
|
||||
if (templates.length === 0) {
|
||||
return offerToCreateTemplate();
|
||||
}
|
||||
|
||||
const templatesMetadata = (
|
||||
await Promise.all(
|
||||
templates.map(async templateUri => {
|
||||
const metadata = await getTemplateMetadata(templateUri);
|
||||
metadata.set('templatePath', templateUri.getBasename());
|
||||
return metadata;
|
||||
})
|
||||
)
|
||||
).sort(sortTemplatesMetadata);
|
||||
|
||||
const items: QuickPickItem[] = await Promise.all(
|
||||
templatesMetadata.map(metadata => {
|
||||
const label = metadata.get('name') || metadata.get('templatePath');
|
||||
const description = metadata.get('name')
|
||||
? metadata.get('templatePath')
|
||||
: null;
|
||||
const detail = metadata.get('description');
|
||||
const item = {
|
||||
label: label,
|
||||
description: description,
|
||||
detail: detail,
|
||||
};
|
||||
Object.keys(item).forEach(key => {
|
||||
if (!item[key]) {
|
||||
delete item[key];
|
||||
}
|
||||
});
|
||||
return item;
|
||||
})
|
||||
);
|
||||
|
||||
const selectedTemplate = await window.showQuickPick(items, {
|
||||
placeHolder: 'Select a template to use.',
|
||||
});
|
||||
|
||||
if (selectedTemplate === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const templateFilename =
|
||||
(selectedTemplate as QuickPickItem).description ||
|
||||
(selectedTemplate as QuickPickItem).label;
|
||||
const templateUri = getTemplatesDir().joinPath(templateFilename);
|
||||
return templateUri;
|
||||
}
|
||||
|
||||
async function offerToCreateTemplate(): Promise<void> {
|
||||
const response = await window.showQuickPick(['Yes', 'No'], {
|
||||
placeHolder:
|
||||
'No templates available. Would you like to create one instead?',
|
||||
});
|
||||
if (response === 'Yes') {
|
||||
commands.executeCommand('foam-vscode.create-new-template');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function sortTemplatesMetadata(
|
||||
t1: Map<string, string>,
|
||||
t2: Map<string, string>
|
||||
) {
|
||||
// Sort by name's existence, then name, then path
|
||||
|
||||
if (t1.get('name') === undefined && t2.get('name') !== undefined) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (t1.get('name') !== undefined && t2.get('name') === undefined) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const pathSortOrder = t1
|
||||
.get('templatePath')
|
||||
.localeCompare(t2.get('templatePath'));
|
||||
|
||||
if (t1.get('name') === undefined && t2.get('name') === undefined) {
|
||||
return pathSortOrder;
|
||||
}
|
||||
|
||||
const nameSortOrder = t1.get('name').localeCompare(t2.get('name'));
|
||||
|
||||
return nameSortOrder || pathSortOrder;
|
||||
}
|
||||
|
||||
export const NoteFactory = {
|
||||
createNote: async (
|
||||
newFilePath: URI,
|
||||
text: string,
|
||||
resolver: Resolver,
|
||||
onFileExists?: OnFileExistStrategy,
|
||||
replaceSelectionWithLink = true
|
||||
): Promise<{ didCreateFile: boolean; uri: URI | undefined }> => {
|
||||
try {
|
||||
const onFileExistsFn = async (existingFile: URI) => {
|
||||
if (typeof onFileExists === 'function') {
|
||||
return onFileExists(existingFile);
|
||||
}
|
||||
switch (onFileExists) {
|
||||
case 'open':
|
||||
await commands.executeCommand(
|
||||
'vscode.open',
|
||||
toVsCodeUri(existingFile)
|
||||
);
|
||||
return;
|
||||
case 'overwrite':
|
||||
await deleteFile(existingFile);
|
||||
return existingFile;
|
||||
case 'cancel':
|
||||
return undefined;
|
||||
case 'ask':
|
||||
default: {
|
||||
const newProposedPath = await askUserForFilepathConfirmation(
|
||||
existingFile
|
||||
);
|
||||
return newProposedPath && URI.file(newProposedPath);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
while (await fileExists(newFilePath)) {
|
||||
const proposedNewFilepath = await onFileExistsFn(newFilePath);
|
||||
|
||||
if (proposedNewFilepath === undefined) {
|
||||
return { didCreateFile: false, uri: newFilePath };
|
||||
}
|
||||
newFilePath = proposedNewFilepath;
|
||||
}
|
||||
|
||||
const expandedText = await resolver.resolveText(text);
|
||||
const selectedContent = findSelectionContent();
|
||||
await createDocAndFocus(
|
||||
new SnippetString(expandedText),
|
||||
newFilePath,
|
||||
selectedContent ? ViewColumn.Beside : ViewColumn.Active
|
||||
);
|
||||
|
||||
if (replaceSelectionWithLink && selectedContent !== undefined) {
|
||||
const newNoteTitle = newFilePath.getName();
|
||||
|
||||
await replaceSelection(
|
||||
selectedContent.document,
|
||||
selectedContent.selection,
|
||||
`[[${newNoteTitle}]]`
|
||||
);
|
||||
}
|
||||
|
||||
return { didCreateFile: true, uri: newFilePath };
|
||||
} catch (err) {
|
||||
if (err instanceof UserCancelledOperation) {
|
||||
return;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a new note using a template.
|
||||
* @param templateUri the URI of the template to use.
|
||||
@@ -108,60 +284,29 @@ export const NoteFactory = {
|
||||
resolver: Resolver,
|
||||
filepathFallbackURI?: URI,
|
||||
templateFallbackText = '',
|
||||
onFileExists?: (filePath: URI) => Promise<string | undefined>
|
||||
onFileExists?: OnFileExistStrategy
|
||||
): Promise<{ didCreateFile: boolean; uri: URI | undefined }> => {
|
||||
try {
|
||||
onFileExists = onFileExists
|
||||
? onFileExists
|
||||
: (existingFile: URI) => {
|
||||
const filename = existingFile.getBasename();
|
||||
return askUserForFilepathConfirmation(existingFile, filename);
|
||||
};
|
||||
|
||||
const template = await getTemplateInfo(
|
||||
templateUri,
|
||||
templateFallbackText,
|
||||
resolver
|
||||
);
|
||||
|
||||
const selectedContent = findSelectionContent();
|
||||
if (selectedContent?.content) {
|
||||
resolver.define('FOAM_SELECTED_TEXT', selectedContent?.content);
|
||||
}
|
||||
|
||||
const templateSnippet = new SnippetString(template.text);
|
||||
|
||||
let newFilePath = await determineNewNoteFilepath(
|
||||
template.metadata.get('filepath'),
|
||||
filepathFallbackURI,
|
||||
resolver
|
||||
const newFilePath = asAbsoluteWorkspaceUri(
|
||||
template.metadata.has('filepath')
|
||||
? URI.file(template.metadata.get('filepath'))
|
||||
: isSome(filepathFallbackURI)
|
||||
? filepathFallbackURI
|
||||
: await getPathFromTitle(resolver)
|
||||
);
|
||||
while (await fileExists(newFilePath)) {
|
||||
const proposedNewFilepath = await onFileExists(newFilePath);
|
||||
|
||||
if (proposedNewFilepath === undefined) {
|
||||
return { didCreateFile: false, uri: newFilePath };
|
||||
}
|
||||
newFilePath = URI.file(proposedNewFilepath);
|
||||
}
|
||||
|
||||
await createDocAndFocus(
|
||||
templateSnippet,
|
||||
return NoteFactory.createNote(
|
||||
newFilePath,
|
||||
selectedContent ? ViewColumn.Beside : ViewColumn.Active
|
||||
template.text,
|
||||
resolver,
|
||||
onFileExists
|
||||
);
|
||||
|
||||
if (selectedContent !== undefined) {
|
||||
const newNoteTitle = newFilePath.getName();
|
||||
|
||||
await replaceSelection(
|
||||
selectedContent.document,
|
||||
selectedContent.selection,
|
||||
`[[${newNoteTitle}]]`
|
||||
);
|
||||
}
|
||||
|
||||
return { didCreateFile: true, uri: newFilePath };
|
||||
} catch (err) {
|
||||
if (err instanceof UserCancelledOperation) {
|
||||
return;
|
||||
@@ -185,7 +330,7 @@ export const NoteFactory = {
|
||||
targetDate
|
||||
);
|
||||
return NoteFactory.createFromTemplate(
|
||||
DAILY_NOTE_TEMPLATE_URI,
|
||||
getDailyNoteTemplateUri(),
|
||||
resolver,
|
||||
filepathFallbackURI,
|
||||
templateFallbackText,
|
||||
@@ -197,17 +342,24 @@ export const NoteFactory = {
|
||||
* Creates a new note when following a placeholder wikilink using the default template.
|
||||
* @param wikilinkPlaceholder the placeholder value from the wikilink. (eg. `[[Hello Joe]]` -> `Hello Joe`)
|
||||
* @param filepathFallbackURI the URI to use if the template does not specify the `filepath` metadata attribute. This is configurable by the caller for backwards compatibility purposes.
|
||||
* @param templateURI URI of the template to use. If undefined, use the default template.
|
||||
*/
|
||||
createForPlaceholderWikilink: (
|
||||
createForPlaceholderWikilink: async (
|
||||
wikilinkPlaceholder: string,
|
||||
filepathFallbackURI: URI
|
||||
filepathFallbackURI: URI,
|
||||
templateURI?: URI
|
||||
): Promise<{ didCreateFile: boolean; uri: URI | undefined }> => {
|
||||
const resolver = new Resolver(
|
||||
new Map().set('FOAM_TITLE', wikilinkPlaceholder),
|
||||
new Date()
|
||||
);
|
||||
|
||||
if (templateURI === undefined) {
|
||||
templateURI = getDefaultTemplateUri();
|
||||
}
|
||||
|
||||
return NoteFactory.createFromTemplate(
|
||||
DEFAULT_TEMPLATE_URI,
|
||||
templateURI,
|
||||
resolver,
|
||||
filepathFallbackURI,
|
||||
WIKILINK_DEFAULT_TEMPLATE_TEXT
|
||||
@@ -217,7 +369,7 @@ export const NoteFactory = {
|
||||
|
||||
export const createTemplate = async (): Promise<void> => {
|
||||
const defaultFilename = 'new-template.md';
|
||||
const defaultTemplate = TEMPLATES_DIR.joinPath(defaultFilename);
|
||||
const defaultTemplate = getTemplatesDir().joinPath(defaultFilename);
|
||||
const fsPath = defaultTemplate.toFsPath();
|
||||
const filename = await window.showInputBox({
|
||||
prompt: `Enter the filename for the new template`,
|
||||
@@ -243,14 +395,18 @@ export const createTemplate = async (): Promise<void> => {
|
||||
};
|
||||
|
||||
async function askUserForFilepathConfirmation(
|
||||
defaultFilepath: URI,
|
||||
defaultFilename: string
|
||||
) {
|
||||
defaultFilepath: URI
|
||||
): Promise<string | undefined> {
|
||||
const fsPath = defaultFilepath.toFsPath();
|
||||
return await window.showInputBox({
|
||||
const defaultFilename = defaultFilepath.getBasename();
|
||||
const defaultExtension = defaultFilepath.getExtension();
|
||||
return window.showInputBox({
|
||||
prompt: `Enter the filename for the new note`,
|
||||
value: fsPath,
|
||||
valueSelection: [fsPath.length - defaultFilename.length, fsPath.length - 3],
|
||||
valueSelection: [
|
||||
fsPath.length - defaultFilename.length,
|
||||
fsPath.length - defaultExtension.length,
|
||||
],
|
||||
validateInput: async value =>
|
||||
value.trim().length === 0
|
||||
? 'Please enter a value'
|
||||
@@ -271,25 +427,14 @@ async function askUserForFilepathConfirmation(
|
||||
*/
|
||||
const UNALLOWED_CHARS = '/\\#%&{}<>?*$!\'":@+`|=';
|
||||
|
||||
export async function determineNewNoteFilepath(
|
||||
templateFilepathAttribute: string | undefined,
|
||||
fallbackURI: URI | undefined,
|
||||
resolver: Resolver
|
||||
): Promise<URI> {
|
||||
if (templateFilepathAttribute) {
|
||||
let defaultFilepath = URI.file(templateFilepathAttribute);
|
||||
if (!defaultFilepath.isAbsolute()) {
|
||||
defaultFilepath = fromVsCodeUri(
|
||||
workspace.workspaceFolders[0].uri
|
||||
).joinPath(templateFilepathAttribute);
|
||||
}
|
||||
return defaultFilepath;
|
||||
}
|
||||
|
||||
if (fallbackURI) {
|
||||
return fallbackURI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the title to generate a file path.
|
||||
* It sanitizes the title to remove special characters and spaces.
|
||||
*
|
||||
* @param resolver the resolver to use
|
||||
* @returns the string path of the new note
|
||||
*/
|
||||
export const getPathFromTitle = async (resolver: Resolver) => {
|
||||
let defaultName = await resolver.resolveFromName('FOAM_TITLE');
|
||||
UNALLOWED_CHARS.split('').forEach(char => {
|
||||
defaultName = defaultName.split(char).join('');
|
||||
@@ -299,13 +444,4 @@ export async function determineNewNoteFilepath(
|
||||
`${defaultName}.md`
|
||||
);
|
||||
return defaultFilepath;
|
||||
}
|
||||
|
||||
async function fileExists(uri: URI): Promise<boolean> {
|
||||
try {
|
||||
const stat = await workspace.fs.stat(toVsCodeUri(uri));
|
||||
return stat.type === FileType.File;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import { window } from 'vscode';
|
||||
import { Selection, window } from 'vscode';
|
||||
import { Resolver } from './variable-resolver';
|
||||
import { Variable } from '../core/common/snippetParser';
|
||||
import {
|
||||
createFile,
|
||||
deleteFile,
|
||||
showInEditor,
|
||||
} from '../test/test-utils-vscode';
|
||||
|
||||
describe('substituteFoamVariables', () => {
|
||||
test('Does nothing if no Foam-specific variables are used', async () => {
|
||||
describe('variable-resolver, text substitution', () => {
|
||||
it('should do nothing if no Foam-specific variables are used', async () => {
|
||||
const input = `
|
||||
# \${AnotherVariable} <-- Unrelated to Foam
|
||||
# \${AnotherVariable:default_value} <-- Unrelated to Foam
|
||||
@@ -31,7 +36,7 @@ describe('substituteFoamVariables', () => {
|
||||
expect(await resolver.resolveText(input)).toEqual(input);
|
||||
});
|
||||
|
||||
test('Correctly substitutes variables that are substrings of one another', async () => {
|
||||
it('should correctly substitute variables that are substrings of one another', async () => {
|
||||
// FOAM_TITLE is a substring of FOAM_TITLE_NON_EXISTENT_VARIABLE
|
||||
// If we're not careful with how we substitute the values
|
||||
// we can end up putting the FOAM_TITLE in place FOAM_TITLE_NON_EXISTENT_VARIABLE should be.
|
||||
@@ -56,8 +61,8 @@ describe('substituteFoamVariables', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveFoamVariables', () => {
|
||||
test('Does nothing for unknown Foam-specific variables', async () => {
|
||||
describe('variable-resolver, variable resolution', () => {
|
||||
it('should do nothing for unknown Foam-specific variables', async () => {
|
||||
const variables = [new Variable('FOAM_FOO')];
|
||||
|
||||
const expected = new Map<string, string>();
|
||||
@@ -67,7 +72,7 @@ describe('resolveFoamVariables', () => {
|
||||
expect(await resolver.resolveAll(variables)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Resolves FOAM_TITLE', async () => {
|
||||
it('should resolve FOAM_TITLE', async () => {
|
||||
const foamTitle = 'My note title';
|
||||
const variables = [new Variable('FOAM_TITLE'), new Variable('FOAM_SLUG')];
|
||||
|
||||
@@ -84,7 +89,7 @@ describe('resolveFoamVariables', () => {
|
||||
expect(await resolver.resolveAll(variables)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Resolves FOAM_TITLE without asking the user when it is provided', async () => {
|
||||
it('should resolve FOAM_TITLE without asking the user when it is provided', async () => {
|
||||
const foamTitle = 'My note title';
|
||||
const variables = [new Variable('FOAM_TITLE')];
|
||||
|
||||
@@ -97,7 +102,7 @@ describe('resolveFoamVariables', () => {
|
||||
expect(await resolver.resolveAll(variables)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Resolves FOAM_DATE_* properties with current day by default', async () => {
|
||||
it('should resolve FOAM_DATE_* properties with current day by default', async () => {
|
||||
const variables = [
|
||||
new Variable('FOAM_DATE_YEAR'),
|
||||
new Variable('FOAM_DATE_YEAR_SHORT'),
|
||||
@@ -134,7 +139,7 @@ describe('resolveFoamVariables', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('Resolves FOAM_DATE_* properties with given date', async () => {
|
||||
it('should resolve FOAM_DATE_* properties with given date', async () => {
|
||||
const targetDate = new Date(2021, 9, 12, 1, 2, 3);
|
||||
const variables = [
|
||||
new Variable('FOAM_DATE_YEAR'),
|
||||
@@ -149,6 +154,7 @@ describe('resolveFoamVariables', () => {
|
||||
new Variable('FOAM_DATE_MINUTE'),
|
||||
new Variable('FOAM_DATE_SECOND'),
|
||||
new Variable('FOAM_DATE_SECONDS_UNIX'),
|
||||
new Variable('FOAM_DATE_WEEK'),
|
||||
];
|
||||
|
||||
const expected = new Map<string, string>();
|
||||
@@ -161,6 +167,7 @@ describe('resolveFoamVariables', () => {
|
||||
expected.set('FOAM_DATE_DAY_NAME', 'Tuesday');
|
||||
expected.set('FOAM_DATE_DAY_NAME_SHORT', 'Tue');
|
||||
expected.set('FOAM_DATE_HOUR', '01');
|
||||
expected.set('FOAM_DATE_WEEK', '41');
|
||||
expected.set('FOAM_DATE_MINUTE', '02');
|
||||
expected.set('FOAM_DATE_SECOND', '03');
|
||||
expected.set(
|
||||
@@ -173,10 +180,35 @@ describe('resolveFoamVariables', () => {
|
||||
|
||||
expect(await resolver.resolveAll(variables)).toEqual(expected);
|
||||
});
|
||||
|
||||
describe('FOAM_DATE_WEEK', () => {
|
||||
it('should start counting weeks from 1', async () => {
|
||||
// week number starts from 1, not 0
|
||||
// the first "partial week" of the year is really the last of the previous
|
||||
const resolver = new Resolver(
|
||||
new Map<string, string>(),
|
||||
new Date(2021, 0, 1, 1, 2, 3)
|
||||
);
|
||||
expect(await resolver.resolve(new Variable('FOAM_DATE_WEEK'))).toEqual(
|
||||
'53'
|
||||
);
|
||||
});
|
||||
|
||||
it('should pad week number to 2 digits', async () => {
|
||||
// week number is 2-digit
|
||||
const resolver = new Resolver(
|
||||
new Map<string, string>(),
|
||||
new Date(2021, 0, 7, 1, 2, 3)
|
||||
);
|
||||
expect(await resolver.resolve(new Variable('FOAM_DATE_WEEK'))).toEqual(
|
||||
'01'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveFoamTemplateVariables', () => {
|
||||
test('Does nothing for template without Foam-specific variables', async () => {
|
||||
describe('variable-resolver, resolveText', () => {
|
||||
it('should do nothing for template without Foam-specific variables', async () => {
|
||||
const input = `
|
||||
# \${AnotherVariable} <-- Unrelated to Foam
|
||||
# \${AnotherVariable:default_value} <-- Unrelated to Foam
|
||||
@@ -191,7 +223,7 @@ describe('resolveFoamTemplateVariables', () => {
|
||||
expect(await resolver.resolveText(input)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Does nothing for unknown Foam-specific variables', async () => {
|
||||
it('should do nothing for unknown Foam-specific variables', async () => {
|
||||
const input = `
|
||||
# $FOAM_FOO
|
||||
# \${FOAM_FOO}
|
||||
@@ -204,7 +236,18 @@ describe('resolveFoamTemplateVariables', () => {
|
||||
expect(await resolver.resolveText(input)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Appends FOAM_SELECTED_TEXT with a newline to the template if there is selected text but FOAM_SELECTED_TEXT is not referenced and the template ends in a newline', async () => {
|
||||
it('should resolve FOAM_SELECTED_TEXT with the editor selection', async () => {
|
||||
const file = await createFile('Content of note file');
|
||||
const { editor } = await showInEditor(file.uri);
|
||||
editor.selection = new Selection(0, 11, 1, 0);
|
||||
const resolver = new Resolver(new Map(), new Date());
|
||||
expect(await resolver.resolveFromName('FOAM_SELECTED_TEXT')).toEqual(
|
||||
'note file'
|
||||
);
|
||||
await deleteFile(file);
|
||||
});
|
||||
|
||||
it('should append FOAM_SELECTED_TEXT with a newline to the template if there is selected text but FOAM_SELECTED_TEXT is not referenced and the template ends in a newline', async () => {
|
||||
const foamTitle = 'My note title';
|
||||
|
||||
jest
|
||||
@@ -221,7 +264,7 @@ describe('resolveFoamTemplateVariables', () => {
|
||||
expect(await resolver.resolveText(input)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Appends FOAM_SELECTED_TEXT with a newline to the template if there is selected text but FOAM_SELECTED_TEXT is not referenced and the template ends in multiple newlines', async () => {
|
||||
it('should append FOAM_SELECTED_TEXT with a newline to the template if there is selected text but FOAM_SELECTED_TEXT is not referenced and the template ends in multiple newlines', async () => {
|
||||
const foamTitle = 'My note title';
|
||||
|
||||
jest
|
||||
@@ -238,7 +281,7 @@ describe('resolveFoamTemplateVariables', () => {
|
||||
expect(await resolver.resolveText(input)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Appends FOAM_SELECTED_TEXT without a newline to the template if there is selected text but FOAM_SELECTED_TEXT is not referenced and the template does not end in a newline', async () => {
|
||||
it('should append FOAM_SELECTED_TEXT without a newline to the template if there is selected text but FOAM_SELECTED_TEXT is not referenced and the template does not end in a newline', async () => {
|
||||
const foamTitle = 'My note title';
|
||||
|
||||
jest
|
||||
@@ -255,7 +298,7 @@ describe('resolveFoamTemplateVariables', () => {
|
||||
expect(await resolver.resolveText(input)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Does not append FOAM_SELECTED_TEXT to a template if there is no selected text and is not referenced', async () => {
|
||||
it('should not append FOAM_SELECTED_TEXT to a template if there is no selected text and is not referenced', async () => {
|
||||
const foamTitle = 'My note title';
|
||||
|
||||
jest
|
||||
|
||||
@@ -18,6 +18,7 @@ const knownFoamVariables = new Set([
|
||||
'FOAM_DATE_MONTH_NAME',
|
||||
'FOAM_DATE_MONTH_NAME_SHORT',
|
||||
'FOAM_DATE_DATE',
|
||||
'FOAM_DATE_WEEK',
|
||||
'FOAM_DATE_DAY_NAME',
|
||||
'FOAM_DATE_DAY_NAME_SHORT',
|
||||
'FOAM_DATE_HOUR',
|
||||
@@ -165,6 +166,25 @@ export class Resolver implements VariableResolver {
|
||||
String(this.foamDate.getDate().valueOf()).padStart(2, '0')
|
||||
);
|
||||
break;
|
||||
case 'FOAM_DATE_WEEK': {
|
||||
// https://en.wikipedia.org/wiki/ISO_8601#Week_dates
|
||||
const date = new Date(this.foamDate);
|
||||
|
||||
// Find Thursday of this week starting on Monday
|
||||
date.setDate(date.getDate() + 4 - (date.getDay() || 7));
|
||||
const thursday = date.getTime();
|
||||
|
||||
// Find January 1st
|
||||
date.setMonth(0); // January
|
||||
date.setDate(1); // 1st
|
||||
const janFirst = date.getTime();
|
||||
|
||||
// Round the amount of days to compensate for daylight saving time
|
||||
const days = Math.round((thursday - janFirst) / 86400000); // 1 day = 86400000 ms
|
||||
const weekDay = Math.floor(days / 7) + 1;
|
||||
value = Promise.resolve(String(weekDay.valueOf()).padStart(2, '0'));
|
||||
break;
|
||||
}
|
||||
case 'FOAM_DATE_DAY_NAME':
|
||||
value = Promise.resolve(
|
||||
this.foamDate.toLocaleString('default', { weekday: 'long' })
|
||||
|
||||
@@ -118,3 +118,21 @@ export const withModifiedConfiguration = async (key, value, fn: () => void) => {
|
||||
*/
|
||||
export const withModifiedFoamConfiguration = (key, value, fn: () => void) =>
|
||||
withModifiedConfiguration(`foam.${key}`, value, fn);
|
||||
|
||||
/**
|
||||
* Utility function to check if two URIs are the same.
|
||||
* It has the goal of supporting Uri and URI, and dealing with
|
||||
* inconsistencies in the way they are represented (especially the
|
||||
* drive letter in Windows)
|
||||
*
|
||||
* @param actual the actual value
|
||||
* @param expected the expected value
|
||||
*/
|
||||
export const expectSameUri = (
|
||||
actual: vscode.Uri | URI,
|
||||
expected: vscode.Uri | URI
|
||||
) => {
|
||||
expect(actual.path.toLocaleLowerCase()).toEqual(
|
||||
expected.path.toLocaleLowerCase()
|
||||
);
|
||||
};
|
||||
|
||||
@@ -85,6 +85,8 @@ let model = {
|
||||
style: defaultStyle,
|
||||
showNodesOfType: {
|
||||
placeholder: true,
|
||||
image: false,
|
||||
attachment: false,
|
||||
note: true,
|
||||
tag: true,
|
||||
},
|
||||
@@ -235,12 +237,10 @@ function initDataviz(channel) {
|
||||
Actions.highlightNode(node?.id);
|
||||
})
|
||||
.onNodeClick((node, event) => {
|
||||
if (event.getModifierState('Control') || event.getModifierState('Meta')) {
|
||||
channel.postMessage({
|
||||
type: 'webviewDidSelectNode',
|
||||
payload: node.id,
|
||||
});
|
||||
}
|
||||
channel.postMessage({
|
||||
type: 'webviewDidSelectNode',
|
||||
payload: node.id,
|
||||
});
|
||||
Actions.selectNode(node.id, event.getModifierState('Shift'));
|
||||
})
|
||||
.onBackgroundClick(event => {
|
||||
|
||||
270
readme.md
270
readme.md
@@ -5,7 +5,7 @@
|
||||
👀*This is an early stage project under rapid development. For updates join the [Foam community Discord](https://foambubble.github.io/join-discord/g)! 💬*
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
[](#contributors-)
|
||||
[](#contributors-)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
[](https://foambubble.github.io/join-discord/g)
|
||||
@@ -91,7 +91,7 @@ See for each occurrence the context in which it lives, as well as a preview of t
|
||||
|
||||
### Tag Explorer Panel
|
||||
|
||||
Tag your notes and navigate them with the [Tag Explorer](https://foambubble.github.io/foam/user/user/features/tags).
|
||||
Tag your notes and navigate them with the [Tag Explorer](https://foambubble.github.io/foam/user/features/tags).
|
||||
Foam also supports hierarchical tags.
|
||||
|
||||

|
||||
@@ -197,137 +197,141 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<!-- 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>
|
||||
</tr>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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"><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>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
|
||||
Reference in New Issue
Block a user