Showing preview only (1,986K chars total). Download the full file or copy to clipboard to get everything.
Repository: foambubble/foam
Branch: main
Commit: 6e3ac4ecda0a
Files: 379
Total size: 1.8 MB
Directory structure:
gitextract_3csvcwq2/
├── .all-contributorsrc
├── .claude/
│ └── commands/
│ ├── prepare-pr.md
│ └── research-issue.md
├── .devcontainer/
│ └── devcontainer.json
├── .editorconfig
├── .eslintrc.json
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.yml
│ │ ├── config.yml
│ │ └── feature_request.yml
│ └── workflows/
│ ├── ci.yml
│ └── update-docs.yml
├── .gitignore
├── .husky/
│ └── pre-push
├── .vscode/
│ ├── launch.json
│ ├── settings.json
│ └── tasks.json
├── .yarnrc
├── CLAUDE.md
├── LICENSE
├── docs/
│ ├── .vscode/
│ │ ├── custom-tag-style.css
│ │ ├── extensions.json
│ │ ├── keybindings.json
│ │ └── settings.json
│ ├── 404.md
│ ├── CNAME
│ ├── Gemfile
│ ├── LICENSE.txt
│ ├── _config.yml
│ ├── _layouts/
│ │ ├── foam.html
│ │ ├── home.html
│ │ ├── mathjax.html
│ │ └── page.html
│ ├── assets/
│ │ └── css/
│ │ └── style.scss
│ ├── dev/
│ │ ├── about-docs.md
│ │ ├── build-vs-assemble.md
│ │ ├── code-of-conduct.md
│ │ ├── contribution-guide.md
│ │ ├── devcontainers.md
│ │ ├── foam-file-format.md
│ │ ├── good-first-task.md
│ │ ├── mdx-by-default.md
│ │ ├── proposals/
│ │ │ ├── foam-core.md
│ │ │ ├── inclusion-of-notes.md
│ │ │ ├── link-reference-definition-improvements.md
│ │ │ ├── materialized-backlinks.md
│ │ │ ├── roadmap.md
│ │ │ └── wikilinks-in-foam.md
│ │ ├── publishing-permissions.md
│ │ ├── releasing-foam.md
│ │ ├── testing.md
│ │ ├── todo.md
│ │ └── unlinked-references.md
│ ├── inbox.md
│ ├── index.md
│ ├── principles.md
│ └── user/
│ ├── features/
│ │ ├── backlinking.md
│ │ ├── block-anchors.md
│ │ ├── commands.md
│ │ ├── custom-markdown-preview-styles.md
│ │ ├── custom-snippets.md
│ │ ├── daily-notes.md
│ │ ├── embeds.md
│ │ ├── foam-queries.md
│ │ ├── graph-view.md
│ │ ├── link-reference-definitions.md
│ │ ├── note-properties.md
│ │ ├── paste-images-from-clipboard.md
│ │ ├── resource-filters.md
│ │ ├── spell-checking.md
│ │ ├── tags.md
│ │ ├── templates.md
│ │ └── wikilinks.md
│ ├── frequently-asked-questions.md
│ ├── getting-started/
│ │ ├── first-workspace.md
│ │ ├── get-started-with-vscode.md
│ │ ├── installation.md
│ │ ├── keyboard-shortcuts.md
│ │ ├── navigation.md
│ │ ├── note-taking-in-foam.md
│ │ ├── recommended-extensions.md
│ │ └── sync-notes.md
│ ├── index.md
│ ├── publishing/
│ │ ├── generate-gatsby-site.md
│ │ ├── math-support-with-katex.md
│ │ ├── math-support-with-mathjax.md
│ │ ├── publish-to-azure-devops-wiki.md
│ │ ├── publish-to-github-pages.md
│ │ ├── publish-to-github.md
│ │ ├── publish-to-gitlab-pages.md
│ │ ├── publish-to-netlify-with-eleventy.md
│ │ ├── publish-to-vercel.md
│ │ └── publishing.md
│ ├── recipes/
│ │ ├── add-images-to-notes.md
│ │ ├── automatic-git-syncing.md
│ │ ├── automatically-expand-urls-to-well-titled-links.md
│ │ ├── capture-notes-with-drafts-pro.md
│ │ ├── capture-notes-with-shortcuts-and-github-actions.md
│ │ ├── diagrams-in-markdown.md
│ │ ├── export-to-pdf.md
│ │ ├── generate-material-for-mkdocs-site.md
│ │ ├── how-to-write-recipes.md
│ │ ├── markup-converter.md
│ │ ├── migrating-from-obsidian.md
│ │ ├── migrating-from-onenote.md
│ │ ├── migrating-from-roam.md
│ │ ├── predefined-user-snippets.md
│ │ ├── real-time-collaboration.md
│ │ ├── recipes.md
│ │ ├── search-for-notes.md
│ │ ├── shows-image-preview-on-hover.md
│ │ ├── take-notes-from-mobile-phone.md
│ │ ├── web-clipper.md
│ │ └── write-your-notes-in-github-gist.md
│ └── tools/
│ ├── cli.md
│ ├── foam-logging-in-vscode.md
│ ├── orphans.md
│ └── workspace-janitor.md
├── lerna.json
├── package.json
├── packages/
│ └── foam-vscode/
│ ├── .vscodeignore
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── __mocks__/
│ │ └── vscode.ts
│ ├── esbuild.js
│ ├── jest.config.js
│ ├── package.json
│ ├── src/
│ │ ├── ai/
│ │ │ ├── model/
│ │ │ │ ├── embedding-cache.ts
│ │ │ │ ├── embeddings.test.ts
│ │ │ │ ├── embeddings.ts
│ │ │ │ └── in-memory-embedding-cache.ts
│ │ │ ├── providers/
│ │ │ │ └── ollama/
│ │ │ │ ├── ollama-provider.test.ts
│ │ │ │ └── ollama-provider.ts
│ │ │ ├── services/
│ │ │ │ ├── embedding-provider.ts
│ │ │ │ └── noop-embedding-provider.ts
│ │ │ └── vscode/
│ │ │ ├── commands/
│ │ │ │ ├── build-embeddings.spec.ts
│ │ │ │ ├── build-embeddings.ts
│ │ │ │ └── show-similar-notes.ts
│ │ │ └── panels/
│ │ │ └── related-notes.ts
│ │ ├── core/
│ │ │ ├── .eslintrc.json
│ │ │ ├── common/
│ │ │ │ ├── cancellation.ts
│ │ │ │ ├── charCode.ts
│ │ │ │ ├── errors.ts
│ │ │ │ ├── event.ts
│ │ │ │ ├── functional.ts
│ │ │ │ ├── iterator.ts
│ │ │ │ ├── lifecycle.ts
│ │ │ │ ├── linkedList.ts
│ │ │ │ ├── platform.ts
│ │ │ │ ├── snippetParser.test.ts
│ │ │ │ └── snippetParser.ts
│ │ │ ├── janitor/
│ │ │ │ ├── convert-links-format.test.ts
│ │ │ │ ├── convert-links-format.ts
│ │ │ │ ├── generate-headings.test.ts
│ │ │ │ ├── generate-headings.ts
│ │ │ │ ├── generate-link-references.test.ts
│ │ │ │ ├── generate-link-references.ts
│ │ │ │ └── index.ts
│ │ │ ├── model/
│ │ │ │ ├── foam.ts
│ │ │ │ ├── graph.test.ts
│ │ │ │ ├── graph.ts
│ │ │ │ ├── location.ts
│ │ │ │ ├── note.test.ts
│ │ │ │ ├── note.ts
│ │ │ │ ├── position.ts
│ │ │ │ ├── provider.ts
│ │ │ │ ├── range.ts
│ │ │ │ ├── tags.test.ts
│ │ │ │ ├── tags.ts
│ │ │ │ ├── uri.test.ts
│ │ │ │ ├── uri.ts
│ │ │ │ ├── workspace.test.ts
│ │ │ │ └── workspace.ts
│ │ │ ├── query/
│ │ │ │ ├── dql.ts
│ │ │ │ ├── html.ts
│ │ │ │ ├── index.test.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── js.ts
│ │ │ ├── services/
│ │ │ │ ├── attachment-provider.ts
│ │ │ │ ├── datastore.test.ts
│ │ │ │ ├── datastore.ts
│ │ │ │ ├── heading-edit.test.ts
│ │ │ │ ├── heading-edit.ts
│ │ │ │ ├── markdown-link.test.ts
│ │ │ │ ├── markdown-link.ts
│ │ │ │ ├── markdown-parser.test.ts
│ │ │ │ ├── markdown-parser.ts
│ │ │ │ ├── markdown-provider.test.ts
│ │ │ │ ├── markdown-provider.ts
│ │ │ │ ├── progress.ts
│ │ │ │ ├── tag-edit.test.ts
│ │ │ │ ├── tag-edit.ts
│ │ │ │ ├── text-edit.test.ts
│ │ │ │ └── text-edit.ts
│ │ │ └── utils/
│ │ │ ├── cache.ts
│ │ │ ├── core.ts
│ │ │ ├── hashtags.ts
│ │ │ ├── index.ts
│ │ │ ├── log.ts
│ │ │ ├── md.test.ts
│ │ │ ├── md.ts
│ │ │ ├── path.test.ts
│ │ │ ├── path.ts
│ │ │ ├── slug.ts
│ │ │ ├── task-deduplicator.test.ts
│ │ │ ├── task-deduplicator.ts
│ │ │ └── utils.test.ts
│ │ ├── dated-notes.spec.ts
│ │ ├── dated-notes.ts
│ │ ├── extension.ts
│ │ ├── features/
│ │ │ ├── block-rename-provider.spec.ts
│ │ │ ├── block-rename-provider.ts
│ │ │ ├── commands/
│ │ │ │ ├── convert-links.spec.ts
│ │ │ │ ├── convert-links.test.ts
│ │ │ │ ├── convert-links.ts
│ │ │ │ ├── copy-without-brackets.spec.ts
│ │ │ │ ├── copy-without-brackets.ts
│ │ │ │ ├── create-new-template.ts
│ │ │ │ ├── create-note-from-template.spec.ts
│ │ │ │ ├── create-note-from-template.ts
│ │ │ │ ├── create-note.spec.ts
│ │ │ │ ├── create-note.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── janitor.ts
│ │ │ │ ├── open-daily-note-for-date.spec.ts
│ │ │ │ ├── open-daily-note-for-date.ts
│ │ │ │ ├── open-daily-note.ts
│ │ │ │ ├── open-dated-note.ts
│ │ │ │ ├── open-random-note.ts
│ │ │ │ ├── open-resource.spec.ts
│ │ │ │ ├── open-resource.ts
│ │ │ │ ├── rename-tag.ts
│ │ │ │ ├── search-tag.spec.ts
│ │ │ │ ├── search-tag.ts
│ │ │ │ ├── update-graph.ts
│ │ │ │ └── update-wikilinks.ts
│ │ │ ├── date-snippets.ts
│ │ │ ├── document-decorator.spec.ts
│ │ │ ├── document-decorator.ts
│ │ │ ├── heading-rename-provider.spec.ts
│ │ │ ├── heading-rename-provider.ts
│ │ │ ├── hover-provider.spec.ts
│ │ │ ├── hover-provider.ts
│ │ │ ├── index.ts
│ │ │ ├── link-completion.spec.ts
│ │ │ ├── link-completion.ts
│ │ │ ├── navigation-provider.spec.ts
│ │ │ ├── navigation-provider.ts
│ │ │ ├── panels/
│ │ │ │ ├── connections.spec.ts
│ │ │ │ ├── connections.ts
│ │ │ │ ├── dataviz/
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dataviz.spec.ts
│ │ │ │ ├── dataviz.test.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── notes-explorer.ts
│ │ │ │ ├── orphans.ts
│ │ │ │ ├── placeholders.ts
│ │ │ │ ├── tags-explorer.spec.ts
│ │ │ │ ├── tags-explorer.ts
│ │ │ │ └── utils/
│ │ │ │ ├── base-tree-provider.ts
│ │ │ │ ├── folder-tree-provider.ts
│ │ │ │ ├── grouped-resources-tree-data-provider.spec.ts
│ │ │ │ ├── grouped-resources-tree-data-provider.ts
│ │ │ │ └── tree-view-utils.ts
│ │ │ ├── preview/
│ │ │ │ ├── block-anchor-ids.test.ts
│ │ │ │ ├── block-anchor-ids.ts
│ │ │ │ ├── escape-wikilink-pipes.test.ts
│ │ │ │ ├── escape-wikilink-pipes.ts
│ │ │ │ ├── foam-query-renderer.test.ts
│ │ │ │ ├── foam-query-renderer.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── remove-wikilink-references.ts
│ │ │ │ ├── tag-highlight.spec.ts
│ │ │ │ ├── tag-highlight.ts
│ │ │ │ ├── wikilink-embed-web-extension.ts
│ │ │ │ ├── wikilink-embed.spec.ts
│ │ │ │ ├── wikilink-embed.test.ts
│ │ │ │ ├── wikilink-embed.ts
│ │ │ │ ├── wikilink-navigation.spec.ts
│ │ │ │ └── wikilink-navigation.ts
│ │ │ ├── refactor.spec.ts
│ │ │ ├── refactor.test.ts
│ │ │ ├── refactor.ts
│ │ │ ├── tag-completion.spec.ts
│ │ │ ├── tag-completion.ts
│ │ │ ├── tag-rename-provider.ts
│ │ │ ├── wikilink-diagnostics.spec.ts
│ │ │ ├── wikilink-diagnostics.ts
│ │ │ ├── workspace-symbol-provider.spec.ts
│ │ │ ├── workspace-symbol-provider.test.ts
│ │ │ └── workspace-symbol-provider.ts
│ │ ├── services/
│ │ │ ├── cache.ts
│ │ │ ├── config.ts
│ │ │ ├── editor.spec.ts
│ │ │ ├── editor.ts
│ │ │ ├── errors.ts
│ │ │ ├── js-template-loader.ts
│ │ │ ├── js-template-sandbox.ts
│ │ │ ├── logging.ts
│ │ │ ├── note-creation-engine.test.ts
│ │ │ ├── note-creation-engine.ts
│ │ │ ├── note-creation-triggers.ts
│ │ │ ├── note-creation-types.ts
│ │ │ ├── template-loader.spec.ts
│ │ │ ├── template-loader.ts
│ │ │ ├── templates.spec.ts
│ │ │ ├── templates.ts
│ │ │ ├── variable-resolver.spec.ts
│ │ │ ├── variable-resolver.ts
│ │ │ └── watcher.ts
│ │ ├── settings.spec.ts
│ │ ├── settings.ts
│ │ ├── test/
│ │ │ ├── run-tests.ts
│ │ │ ├── suite-unit.ts
│ │ │ ├── suite.ts
│ │ │ ├── support/
│ │ │ │ ├── jest-setup-after-env.ts
│ │ │ │ ├── jest-setup-e2e.ts
│ │ │ │ ├── jest-setup.ts
│ │ │ │ └── vscode-environment.js
│ │ │ ├── test-datastore.test.ts
│ │ │ ├── test-datastore.ts
│ │ │ ├── test-utils-vscode.ts
│ │ │ ├── test-utils.ts
│ │ │ ├── vscode-mock-extensions.test.ts
│ │ │ └── vscode-mock.ts
│ │ ├── types.d.ts
│ │ └── utils/
│ │ ├── commands.ts
│ │ ├── globExpand.test.ts
│ │ ├── globExpand.ts
│ │ ├── template-frontmatter-parser.test.ts
│ │ ├── template-frontmatter-parser.ts
│ │ ├── vsc-utils.spec.ts
│ │ └── vsc-utils.ts
│ ├── static/
│ │ └── preview/
│ │ ├── block-anchor-scroll.js
│ │ └── style.css
│ ├── syntaxes/
│ │ └── injection.json
│ ├── test-data/
│ │ ├── __migration__/
│ │ │ ├── Roam Document.md
│ │ │ └── Second Roam Document.md
│ │ ├── __scaffold__/
│ │ │ ├── Note being referred as angel.md
│ │ │ ├── angel-reference.md
│ │ │ ├── file-with-different-link-formats.md
│ │ │ ├── file-with-explicit-and-implicit-link-references.md
│ │ │ ├── file-with-explicit-link-references.md
│ │ │ ├── file-with-only-frontmatter.md
│ │ │ ├── file-without-title.md
│ │ │ ├── first-document.md
│ │ │ ├── index.md
│ │ │ ├── second-document.md
│ │ │ └── third-document.md
│ │ ├── test-config/
│ │ │ ├── enable-plugins/
│ │ │ │ └── config.json
│ │ │ ├── folder1/
│ │ │ │ └── config.json
│ │ │ └── folder2/
│ │ │ └── config.json
│ │ └── test-datastore/
│ │ ├── docs/
│ │ │ └── file-in-nm.md
│ │ ├── file-a.md
│ │ └── info/
│ │ ├── docs/
│ │ │ └── file-in-sub-nm.md
│ │ └── file-b.md
│ ├── tsconfig.json
│ ├── types/
│ │ └── utils.d.ts
│ └── webview-ui/
│ └── graph/
│ ├── build.cjs
│ ├── index.html
│ ├── package.json
│ ├── src/
│ │ ├── components/
│ │ │ ├── control-panel.ts
│ │ │ └── graph-canvas.ts
│ │ ├── foam-graph.ts
│ │ ├── lib/
│ │ │ ├── colors.ts
│ │ │ ├── defaults.ts
│ │ │ ├── graph-utils.test.ts
│ │ │ ├── graph-utils.ts
│ │ │ ├── painter.ts
│ │ │ └── types.ts
│ │ ├── main.css
│ │ ├── main.ts
│ │ └── protocol.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── readme.md
├── tsconfig.base.json
└── typos.toml
================================================
FILE CONTENTS
================================================
================================================
FILE: .all-contributorsrc
================================================
{
"projectName": "foam",
"projectOwner": "foambubble",
"repoType": "github",
"repoHost": "https://github.com",
"files": [
"docs/index.md",
"readme.md"
],
"imageSize": 60,
"commit": false,
"commitConvention": "none",
"contributors": [
{
"login": "jevakallio",
"name": "Jani Eväkallio",
"avatar_url": "https://avatars1.githubusercontent.com/u/1203949?v=4",
"profile": "https://jevakallio.dev/",
"contributions": [
"code",
"doc"
]
},
{
"login": "jsjoeio",
"name": "Joe Previte",
"avatar_url": "https://avatars3.githubusercontent.com/u/3806031?v=4",
"profile": "https://joeprevite.com/",
"contributions": [
"code",
"doc"
]
},
{
"login": "riccardoferretti",
"name": "Riccardo",
"avatar_url": "https://avatars3.githubusercontent.com/u/457005?v=4",
"profile": "https://github.com/riccardoferretti",
"contributions": [
"code",
"doc"
]
},
{
"login": "jojanaho",
"name": "Janne Ojanaho",
"avatar_url": "https://avatars0.githubusercontent.com/u/2180090?v=4",
"profile": "http://ojanaho.com/",
"contributions": [
"code",
"doc"
]
},
{
"login": "paulshen",
"name": "Paul Shen",
"avatar_url": "https://avatars3.githubusercontent.com/u/2266187?v=4",
"profile": "http://bypaulshen.com/",
"contributions": [
"doc"
]
},
{
"login": "coffenbacher",
"name": "coffenbacher",
"avatar_url": "https://avatars0.githubusercontent.com/u/245867?v=4",
"profile": "https://github.com/coffenbacher",
"contributions": [
"doc"
]
},
{
"login": "mathieudutour",
"name": "Mathieu Dutour",
"avatar_url": "https://avatars2.githubusercontent.com/u/3254314?v=4",
"profile": "https://mathieu.dutour.me/",
"contributions": [
"doc"
]
},
{
"login": "presidentelect",
"name": "Michael Hansen",
"avatar_url": "https://avatars2.githubusercontent.com/u/1242300?v=4",
"profile": "https://github.com/presidentelect",
"contributions": [
"doc"
]
},
{
"login": "dnadlinger",
"name": "David Nadlinger",
"avatar_url": "https://avatars1.githubusercontent.com/u/19335?v=4",
"profile": "http://klickverbot.at/",
"contributions": [
"doc"
]
},
{
"login": "MrCordeiro",
"name": "Fernando",
"avatar_url": "https://avatars2.githubusercontent.com/u/20598571?v=4",
"profile": "https://pluckd.co/",
"contributions": [
"doc"
]
},
{
"login": "jfgonzalez7",
"name": "Juan Gonzalez",
"avatar_url": "https://avatars3.githubusercontent.com/u/58857736?v=4",
"profile": "https://github.com/jfgonzalez7",
"contributions": [
"doc"
]
},
{
"login": "louiechristie",
"name": "Louie Christie",
"avatar_url": "https://avatars1.githubusercontent.com/u/6807448?v=4",
"profile": "http://www.louiechristie.com/",
"contributions": [
"doc"
]
},
{
"login": "SuperSandro2000",
"name": "Sandro",
"avatar_url": "https://avatars2.githubusercontent.com/u/7258858?v=4",
"profile": "https://supersandro.de/",
"contributions": [
"doc"
]
},
{
"login": "Skn0tt",
"name": "Simon Knott",
"avatar_url": "https://avatars1.githubusercontent.com/u/14912729?v=4",
"profile": "https://github.com/Skn0tt",
"contributions": [
"doc"
]
},
{
"login": "styfle",
"name": "Steven",
"avatar_url": "https://avatars1.githubusercontent.com/u/229881?v=4",
"profile": "https://styfle.dev/",
"contributions": [
"doc"
]
},
{
"login": "Georift",
"name": "Tim",
"avatar_url": "https://avatars2.githubusercontent.com/u/859430?v=4",
"profile": "https://github.com/Georift",
"contributions": [
"doc"
]
},
{
"login": "sauravkhdoolia",
"name": "Saurav Khdoolia",
"avatar_url": "https://avatars1.githubusercontent.com/u/34188267?v=4",
"profile": "https://github.com/sauravkhdoolia",
"contributions": [
"doc"
]
},
{
"login": "anku255",
"name": "Ankit Tiwari",
"avatar_url": "https://avatars1.githubusercontent.com/u/22813027?v=4",
"profile": "https://anku.netlify.com/",
"contributions": [
"doc",
"test",
"code"
]
},
{
"login": "ayushbaweja",
"name": "Ayush Baweja",
"avatar_url": "https://avatars1.githubusercontent.com/u/44344063?v=4",
"profile": "https://github.com/ayushbaweja",
"contributions": [
"doc"
]
},
{
"login": "TaiChi-IO",
"name": "TaiChi-IO",
"avatar_url": "https://avatars3.githubusercontent.com/u/65092992?v=4",
"profile": "https://github.com/TaiChi-IO",
"contributions": [
"doc"
]
},
{
"login": "juanfrank77",
"name": "Juan F Gonzalez ",
"avatar_url": "https://avatars1.githubusercontent.com/u/12146882?v=4",
"profile": "https://github.com/juanfrank77",
"contributions": [
"doc"
]
},
{
"login": "SanketDG",
"name": "Sanket Dasgupta",
"avatar_url": "https://avatars3.githubusercontent.com/u/8980971?v=4",
"profile": "https://sanketdg.github.io",
"contributions": [
"doc",
"code"
]
},
{
"login": "nstafie",
"name": "Nicholas Stafie",
"avatar_url": "https://avatars1.githubusercontent.com/u/10801854?v=4",
"profile": "https://github.com/nstafie",
"contributions": [
"doc"
]
},
{
"login": "francishamel",
"name": "Francis Hamel",
"avatar_url": "https://avatars3.githubusercontent.com/u/36383308?v=4",
"profile": "https://github.com/francishamel",
"contributions": [
"code"
]
},
{
"login": "digiguru",
"name": "digiguru",
"avatar_url": "https://avatars1.githubusercontent.com/u/619436?v=4",
"profile": "http://digiguru.co.uk",
"contributions": [
"code",
"doc"
]
},
{
"login": "chirag-singhal",
"name": "CHIRAG SINGHAL",
"avatar_url": "https://avatars3.githubusercontent.com/u/42653703?v=4",
"profile": "https://github.com/chirag-singhal",
"contributions": [
"code"
]
},
{
"login": "lostintangent",
"name": "Jonathan Carter",
"avatar_url": "https://avatars3.githubusercontent.com/u/116461?v=4",
"profile": "https://github.com/lostintangent",
"contributions": [
"doc"
]
},
{
"login": "synesthesia",
"name": "Julian Elve",
"avatar_url": "https://avatars3.githubusercontent.com/u/181399?v=4",
"profile": "https://www.synesthesia.co.uk",
"contributions": [
"doc"
]
},
{
"login": "thomaskoppelaar",
"name": "Thomas Koppelaar",
"avatar_url": "https://avatars3.githubusercontent.com/u/36331365?v=4",
"profile": "https://github.com/thomaskoppelaar",
"contributions": [
"question",
"code",
"userTesting"
]
},
{
"login": "MehraAkshay",
"name": "Akshay",
"avatar_url": "https://avatars1.githubusercontent.com/u/8671497?v=4",
"profile": "http://www.akshaymehra.com",
"contributions": [
"code"
]
},
{
"login": "johnlindquist",
"name": "John Lindquist",
"avatar_url": "https://avatars0.githubusercontent.com/u/36073?v=4",
"profile": "http://johnlindquist.com",
"contributions": [
"doc"
]
},
{
"login": "epicfaace",
"name": "Ashwin Ramaswami",
"avatar_url": "https://avatars2.githubusercontent.com/u/1689183?v=4",
"profile": "https://ashwin.run/",
"contributions": [
"doc"
]
},
{
"login": "Klaudioz",
"name": "Claudio Canales",
"avatar_url": "https://avatars1.githubusercontent.com/u/632625?v=4",
"profile": "https://github.com/Klaudioz",
"contributions": [
"doc"
]
},
{
"login": "vitaly-pevgonen",
"name": "vitaly-pevgonen",
"avatar_url": "https://avatars0.githubusercontent.com/u/6272738?v=4",
"profile": "https://github.com/vitaly-pevgonen",
"contributions": [
"doc"
]
},
{
"login": "dshemetov",
"name": "Dmitry Shemetov",
"avatar_url": "https://avatars0.githubusercontent.com/u/1810426?v=4",
"profile": "https://dshemetov.github.io",
"contributions": [
"doc"
]
},
{
"login": "hooncp",
"name": "hooncp",
"avatar_url": "https://avatars1.githubusercontent.com/u/48883554?v=4",
"profile": "https://github.com/hooncp",
"contributions": [
"doc"
]
},
{
"login": "martinlaws",
"name": "Martin Laws",
"avatar_url": "https://avatars1.githubusercontent.com/u/13721239?v=4",
"profile": "http://rt-canada.ca",
"contributions": [
"doc"
]
},
{
"login": "sksmith",
"name": "Sean K Smith",
"avatar_url": "https://avatars3.githubusercontent.com/u/2085441?v=4",
"profile": "http://seanksmith.me",
"contributions": [
"code"
]
},
{
"login": "kneely",
"name": "Kevin Neely",
"avatar_url": "https://avatars1.githubusercontent.com/u/37545028?v=4",
"profile": "https://www.linkedin.com/in/kevin-neely/",
"contributions": [
"doc"
]
},
{
"login": "ariefrahmansyah",
"name": "Arief Rahmansyah",
"avatar_url": "https://avatars3.githubusercontent.com/u/8122852?v=4",
"profile": "https://ariefrahmansyah.dev",
"contributions": [
"doc"
]
},
{
"login": "vHanda",
"name": "Vishesh Handa",
"avatar_url": "https://avatars2.githubusercontent.com/u/426467?v=4",
"profile": "http://vhanda.in",
"contributions": [
"doc"
]
},
{
"login": "HeroicHitesh",
"name": "Hitesh Kumar",
"avatar_url": "https://avatars3.githubusercontent.com/u/37622734?v=4",
"profile": "http://www.linkedin.com/in/heroichitesh",
"contributions": [
"doc"
]
},
{
"login": "spencerwooo",
"name": "Spencer Woo",
"avatar_url": "https://avatars2.githubusercontent.com/u/32114380?v=4",
"profile": "https://spencerwoo.com",
"contributions": [
"doc"
]
},
{
"login": "ingalless",
"name": "ingalless",
"avatar_url": "https://avatars3.githubusercontent.com/u/22981941?v=4",
"profile": "https://ingalless.com",
"contributions": [
"code",
"doc"
]
},
{
"login": "jmg-duarte",
"name": "José Duarte",
"avatar_url": "https://avatars2.githubusercontent.com/u/15343819?v=4",
"profile": "http://jmg-duarte.github.io",
"contributions": [
"code",
"doc"
]
},
{
"login": "yenly",
"name": "Yenly",
"avatar_url": "https://avatars1.githubusercontent.com/u/6759658?v=4",
"profile": "https://www.yenly.wtf",
"contributions": [
"doc"
]
},
{
"login": "hikerpig",
"name": "hikerpig",
"avatar_url": "https://avatars1.githubusercontent.com/u/2259688?v=4",
"profile": "https://www.hikerpig.cn",
"contributions": [
"code"
]
},
{
"login": "Sigfried",
"name": "Sigfried Gold",
"avatar_url": "https://avatars1.githubusercontent.com/u/1586931?v=4",
"profile": "http://sigfried.org",
"contributions": [
"doc"
]
},
{
"login": "tristansokol",
"name": "Tristan Sokol",
"avatar_url": "https://avatars3.githubusercontent.com/u/867661?v=4",
"profile": "http://www.tristansokol.com",
"contributions": [
"code"
]
},
{
"login": "umbrellait-danil-rodin",
"name": "Danil Rodin",
"avatar_url": "https://avatars0.githubusercontent.com/u/49779373?v=4",
"profile": "https://umbrellait.com",
"contributions": [
"doc"
]
},
{
"login": "scott-joe",
"name": "Scott Williams",
"avatar_url": "https://avatars1.githubusercontent.com/u/2026866?v=4",
"profile": "https://www.linkedin.com/in/scottjoewilliams/",
"contributions": [
"doc"
]
},
{
"login": "Jackiexiao",
"name": "jackiexiao",
"avatar_url": "https://avatars2.githubusercontent.com/u/18050469?v=4",
"profile": "https://jackiexiao.github.io/blog",
"contributions": [
"doc"
]
},
{
"login": "jbn",
"name": "John B Nelson",
"avatar_url": "https://avatars3.githubusercontent.com/u/78835?v=4",
"profile": "https://generativist.substack.com/",
"contributions": [
"doc"
]
},
{
"login": "asifm",
"name": "Asif Mehedi",
"avatar_url": "https://avatars2.githubusercontent.com/u/3958387?v=4",
"profile": "https://github.com/asifm",
"contributions": [
"doc"
]
},
{
"login": "litanlitudan",
"name": "Tan Li",
"avatar_url": "https://avatars2.githubusercontent.com/u/4970420?v=4",
"profile": "https://github.com/litanlitudan",
"contributions": [
"code"
]
},
{
"login": "ShaunaGordon",
"name": "Shauna Gordon",
"avatar_url": "https://avatars1.githubusercontent.com/u/579361?v=4",
"profile": "http://shaunagordon.com",
"contributions": [
"doc"
]
},
{
"login": "MCluck90",
"name": "Mike Cluck",
"avatar_url": "https://avatars1.githubusercontent.com/u/1753801?v=4",
"profile": "https://mcluck.tech",
"contributions": [
"code"
]
},
{
"login": "bpugh",
"name": "Brandon Pugh",
"avatar_url": "https://avatars1.githubusercontent.com/u/684781?v=4",
"profile": "http://brandonpugh.com",
"contributions": [
"code"
]
},
{
"login": "themaxdavitt",
"name": "Max Davitt",
"avatar_url": "https://avatars1.githubusercontent.com/u/27709025?v=4",
"profile": "https://max.davitt.me",
"contributions": [
"doc"
]
},
{
"login": "anglinb",
"name": "Brian Anglin",
"avatar_url": "https://avatars3.githubusercontent.com/u/2637602?v=4",
"profile": "http://briananglin.me",
"contributions": [
"doc"
]
},
{
"login": "elswork",
"name": "elswork",
"avatar_url": "https://avatars1.githubusercontent.com/u/1455507?v=4",
"profile": "http://deft.work",
"contributions": [
"doc"
]
},
{
"login": "leonhfr",
"name": "léon h",
"avatar_url": "https://avatars.githubusercontent.com/u/19996318?v=4",
"profile": "http://leonh.fr/",
"contributions": [
"code"
]
},
{
"login": "njnygaard",
"name": "Nikhil Nygaard",
"avatar_url": "https://avatars.githubusercontent.com/u/4606342?v=4",
"profile": "https://nygaard.site",
"contributions": [
"doc"
]
},
{
"login": "nitwit-se",
"name": "Mark Dixon",
"avatar_url": "https://avatars.githubusercontent.com/u/1382124?v=4",
"profile": "http://www.nitwit.se",
"contributions": [
"code"
]
},
{
"login": "joeltjames",
"name": "Joel James",
"avatar_url": "https://avatars.githubusercontent.com/u/3732400?v=4",
"profile": "https://github.com/joeltjames",
"contributions": [
"code"
]
},
{
"login": "ryo33",
"name": "Hashiguchi Ryo",
"avatar_url": "https://avatars.githubusercontent.com/u/8780513?v=4",
"profile": "https://www.ryo33.com",
"contributions": [
"doc"
]
},
{
"login": "movermeyer",
"name": "Michael Overmeyer",
"avatar_url": "https://avatars.githubusercontent.com/u/1459385?v=4",
"profile": "https://movermeyer.com",
"contributions": [
"code"
]
},
{
"login": "derrickqin",
"name": "Derrick Qin",
"avatar_url": "https://avatars.githubusercontent.com/u/3038111?v=4",
"profile": "https://github.com/derrickqin",
"contributions": [
"doc"
]
},
{
"login": "zomars",
"name": "Omar López",
"avatar_url": "https://avatars.githubusercontent.com/u/3504472?v=4",
"profile": "https://www.linkedin.com/in/zomars/",
"contributions": [
"doc"
]
},
{
"login": "RobinKing",
"name": "Robin King",
"avatar_url": "https://avatars.githubusercontent.com/u/1583193?v=4",
"profile": "http://robincn.com",
"contributions": [
"code"
]
},
{
"login": "dheepakg",
"name": "Dheepak ",
"avatar_url": "https://avatars.githubusercontent.com/u/4730170?v=4",
"profile": "http://twitter.com/deegovee",
"contributions": [
"doc"
]
},
{
"login": "daniel-vera-g",
"name": "Daniel VG",
"avatar_url": "https://avatars.githubusercontent.com/u/28257108?v=4",
"profile": "https://github.com/daniel-vera-g",
"contributions": [
"doc"
]
},
{
"login": "Barabazs",
"name": "Barabas",
"avatar_url": "https://avatars.githubusercontent.com/u/31799121?v=4",
"profile": "https://github.com/Barabazs",
"contributions": [
"code"
]
},
{
"login": "EngincanV",
"name": "Engincan VESKE",
"avatar_url": "https://avatars.githubusercontent.com/u/43685404?v=4",
"profile": "http://enginveske@gmail.com",
"contributions": [
"doc"
]
},
{
"login": "pderaaij",
"name": "Paul de Raaij",
"avatar_url": "https://avatars.githubusercontent.com/u/495374?v=4",
"profile": "http://www.paulderaaij.nl",
"contributions": [
"code"
]
},
{
"login": "bronson",
"name": "Scott Bronson",
"avatar_url": "https://avatars.githubusercontent.com/u/1776?v=4",
"profile": "https://github.com/bronson",
"contributions": [
"doc"
]
},
{
"login": "rafo",
"name": "Rafael Riedel",
"avatar_url": "https://avatars.githubusercontent.com/u/41793?v=4",
"profile": "http://rafaelriedel.de",
"contributions": [
"doc"
]
},
{
"login": "Pearcekieser",
"name": "Pearcekieser",
"avatar_url": "https://avatars.githubusercontent.com/u/5055971?v=4",
"profile": "https://github.com/Pearcekieser",
"contributions": [
"doc"
]
},
{
"login": "theowenyoung",
"name": "Owen Young",
"avatar_url": "https://avatars.githubusercontent.com/u/62473795?v=4",
"profile": "https://github.com/theowenyoung",
"contributions": [
"doc",
"content"
]
},
{
"login": "ksprashu",
"name": "Prashanth Subrahmanyam",
"avatar_url": "https://avatars.githubusercontent.com/u/476729?v=4",
"profile": "http://www.prashu.com",
"contributions": [
"doc"
]
},
{
"login": "JonasSprenger",
"name": "Jonas SPRENGER",
"avatar_url": "https://avatars.githubusercontent.com/u/25108895?v=4",
"profile": "https://github.com/JonasSprenger",
"contributions": [
"code"
]
},
{
"login": "Laptop765",
"name": "Paul",
"avatar_url": "https://avatars.githubusercontent.com/u/1468359?v=4",
"profile": "https://github.com/Laptop765",
"contributions": [
"doc"
]
},
{
"login": "eltociear",
"name": "Ikko Ashimine",
"avatar_url": "https://avatars.githubusercontent.com/u/22633385?v=4",
"profile": "https://bandism.net/",
"contributions": [
"doc"
]
},
{
"login": "memeplex",
"name": "memeplex",
"avatar_url": "https://avatars.githubusercontent.com/u/2845433?v=4",
"profile": "https://github.com/memeplex",
"contributions": [
"code"
]
},
{
"login": "AndreiD049",
"name": "AndreiD049",
"avatar_url": "https://avatars.githubusercontent.com/u/52671223?v=4",
"profile": "https://github.com/AndreiD049",
"contributions": [
"code"
]
},
{
"login": "iam-yan",
"name": "Yan",
"avatar_url": "https://avatars.githubusercontent.com/u/48427014?v=4",
"profile": "https://github.com/iam-yan",
"contributions": [
"doc"
]
},
{
"login": "jimt",
"name": "Jim Tittsler",
"avatar_url": "https://avatars.githubusercontent.com/u/180326?v=4",
"profile": "https://WikiEducator.org/User:JimTittsler",
"contributions": [
"doc"
]
},
{
"login": "MalcolmMielle",
"name": "Malcolm Mielle",
"avatar_url": "https://avatars.githubusercontent.com/u/4457840?v=4",
"profile": "http://malcolmmielle.wordpress.com/",
"contributions": [
"doc"
]
},
{
"login": "veesar",
"name": "Veesar",
"avatar_url": "https://avatars.githubusercontent.com/u/74916913?v=4",
"profile": "https://snippets.page/",
"contributions": [
"doc"
]
},
{
"login": "bentongxyz",
"name": "bentongxyz",
"avatar_url": "https://avatars.githubusercontent.com/u/60358804?v=4",
"profile": "https://github.com/bentongxyz",
"contributions": [
"code"
]
},
{
"login": "techCarpenter",
"name": "Brian DeVries",
"avatar_url": "https://avatars.githubusercontent.com/u/42778030?v=4",
"profile": "https://brianjdevries.com",
"contributions": [
"code"
]
},
{
"login": "cliffordfajardo",
"name": "Clifford Fajardo ",
"avatar_url": "https://avatars.githubusercontent.com/u/6743796?v=4",
"profile": "http://Cliffordfajardo.com",
"contributions": [
"tool"
]
},
{
"login": "chrisUsick",
"name": "Chris Usick",
"avatar_url": "https://avatars.githubusercontent.com/u/6589365?v=4",
"profile": "http://cu-dev.ca",
"contributions": [
"code"
]
},
{
"login": "josephdecock",
"name": "Joe DeCock",
"avatar_url": "https://avatars.githubusercontent.com/u/1145533?v=4",
"profile": "https://github.com/josephdecock",
"contributions": [
"code"
]
},
{
"login": "drewtyler",
"name": "Drew Tyler",
"avatar_url": "https://avatars.githubusercontent.com/u/5640816?v=4",
"profile": "http://www.drewtyler.com",
"contributions": [
"doc"
]
},
{
"login": "Lauviah0622",
"name": "Lauviah0622",
"avatar_url": "https://avatars.githubusercontent.com/u/43416399?v=4",
"profile": "https://github.com/Lauviah0622",
"contributions": [
"code"
]
},
{
"login": "joshdover",
"name": "Josh Dover",
"avatar_url": "https://avatars.githubusercontent.com/u/1813008?v=4",
"profile": "https://www.elastic.co/elastic-agent",
"contributions": [
"code"
]
},
{
"login": "phelma",
"name": "Phil Helm",
"avatar_url": "https://avatars.githubusercontent.com/u/4057948?v=4",
"profile": "http://phelm.co.uk",
"contributions": [
"doc"
]
},
{
"login": "lingyv-li",
"name": "Larry Li",
"avatar_url": "https://avatars.githubusercontent.com/u/8937944?v=4",
"profile": "https://github.com/lingyv-li",
"contributions": [
"code"
]
},
{
"login": "infogulch",
"name": "Joe Taber",
"avatar_url": "https://avatars.githubusercontent.com/u/133882?v=4",
"profile": "https://github.com/infogulch",
"contributions": [
"doc"
]
},
{
"login": "readingsnail",
"name": "Woosuk Park",
"avatar_url": "https://avatars.githubusercontent.com/u/1904967?v=4",
"profile": "https://www.readingsnail.pe.kr",
"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"
]
},
{
"login": "elgirafo",
"name": "luca",
"avatar_url": "https://avatars.githubusercontent.com/u/80516439?v=4",
"profile": "http://elgirafo.xyz",
"contributions": [
"doc"
]
},
{
"login": "Lloyd-Jackman-UKPL",
"name": "Lloyd Jackman",
"avatar_url": "https://avatars.githubusercontent.com/u/55206370?v=4",
"profile": "https://github.com/Lloyd-Jackman-UKPL",
"contributions": [
"doc"
]
},
{
"login": "sn3akiwhizper",
"name": "sn3akiwhizper",
"avatar_url": "https://avatars.githubusercontent.com/u/102705294?v=4",
"profile": "http://sn3akiwhizper.github.io",
"contributions": [
"doc"
]
},
{
"login": "jonathanpberger",
"name": "jonathan berger",
"avatar_url": "https://avatars.githubusercontent.com/u/41085?v=4",
"profile": "http://jonathanpberger.com/",
"contributions": [
"doc"
]
},
{
"login": "badsketch",
"name": "Daniel Wang",
"avatar_url": "https://avatars.githubusercontent.com/u/8953212?v=4",
"profile": "https://github.com/badsketch",
"contributions": [
"code"
]
},
{
"login": "tlylt",
"name": "Liu YongLiang",
"avatar_url": "https://avatars.githubusercontent.com/u/41845017?v=4",
"profile": "http://yongliangliu.com",
"contributions": [
"doc"
]
},
{
"login": "Skakerman",
"name": "Scott Akerman",
"avatar_url": "https://avatars.githubusercontent.com/u/15224439?v=4",
"profile": "http://scottakerman.com",
"contributions": [
"code"
]
},
{
"login": "jimgraham",
"name": "Jim Graham",
"avatar_url": "https://avatars.githubusercontent.com/u/430293?v=4",
"profile": "http://www.jim-graham.net/",
"contributions": [
"code"
]
},
{
"login": "hezhizhen",
"name": "Zhizhen He",
"avatar_url": "https://avatars.githubusercontent.com/u/7611700?v=4",
"profile": "https://t.me/littlepoint",
"contributions": [
"tool"
]
},
{
"login": "tcheneau",
"name": "Tony Cheneau",
"avatar_url": "https://avatars.githubusercontent.com/u/952059?v=4",
"profile": "https://amnesiak.org/me",
"contributions": [
"doc"
]
},
{
"login": "nicholas-l",
"name": "Nicholas Latham",
"avatar_url": "https://avatars.githubusercontent.com/u/12977174?v=4",
"profile": "https://github.com/nicholas-l",
"contributions": [
"code"
]
},
{
"login": "thara",
"name": "Tomochika Hara",
"avatar_url": "https://avatars.githubusercontent.com/u/1532891?v=4",
"profile": "https://thara.dev",
"contributions": [
"doc"
]
},
{
"login": "dcarosone",
"name": "Daniel Carosone",
"avatar_url": "https://avatars.githubusercontent.com/u/11495017?v=4",
"profile": "https://github.com/dcarosone",
"contributions": [
"doc"
]
},
{
"login": "MABruni",
"name": "Miguel Angel Bruni Montero",
"avatar_url": "https://avatars.githubusercontent.com/u/100445384?v=4",
"profile": "https://github.com/MABruni",
"contributions": [
"code"
]
},
{
"login": "Walshkev",
"name": "Kevin Walsh ",
"avatar_url": "https://avatars.githubusercontent.com/u/77123083?v=4",
"profile": "https://github.com/Walshkev",
"contributions": [
"doc"
]
},
{
"login": "hereistheusername",
"name": "Xinglan Liu",
"avatar_url": "https://avatars.githubusercontent.com/u/33437051?v=4",
"profile": "http://hereistheusername.github.io/",
"contributions": [
"code"
]
},
{
"login": "Hegghammer",
"name": "Thomas Hegghammer",
"avatar_url": "https://avatars.githubusercontent.com/u/64712218?v=4",
"profile": "http://www.hegghammer.com",
"contributions": [
"doc"
]
},
{
"login": "PiotrAleksander",
"name": "Piotr Mrzygłosz",
"avatar_url": "https://avatars.githubusercontent.com/u/6314591?v=4",
"profile": "https://github.com/PiotrAleksander",
"contributions": [
"doc"
]
},
{
"login": "markschaver",
"name": "Mark Schaver",
"avatar_url": "https://avatars.githubusercontent.com/u/7584?v=4",
"profile": "http://schaver.com/",
"contributions": [
"doc"
]
},
{
"login": "n8layman",
"name": "Nathan Layman",
"avatar_url": "https://avatars.githubusercontent.com/u/25353944?v=4",
"profile": "https://github.com/n8layman",
"contributions": [
"code"
]
},
{
"login": "emmanuel-ferdman",
"name": "Emmanuel Ferdman",
"avatar_url": "https://avatars.githubusercontent.com/u/35470921?v=4",
"profile": "https://github.com/emmanuel-ferdman",
"contributions": [
"doc"
]
},
{
"login": "Tenormis",
"name": "Tenormis",
"avatar_url": "https://avatars.githubusercontent.com/u/61572102?v=4",
"profile": "https://github.com/Tenormis",
"contributions": [
"code"
]
},
{
"login": "djplaner",
"name": "David Jones",
"avatar_url": "https://avatars.githubusercontent.com/u/225052?v=4",
"profile": "http://djon.es/blog",
"contributions": [
"doc"
]
},
{
"login": "s-jacob-powell",
"name": "S. Jacob Powell",
"avatar_url": "https://avatars.githubusercontent.com/u/109111499?v=4",
"profile": "https://github.com/s-jacob-powell",
"contributions": [
"code"
]
},
{
"login": "figdavi",
"name": "Davi Figueiredo",
"avatar_url": "https://avatars.githubusercontent.com/u/99026991?v=4",
"profile": "https://github.com/figdavi",
"contributions": [
"doc"
]
},
{
"login": "ChThH",
"name": "CT Hall",
"avatar_url": "https://avatars.githubusercontent.com/u/9499483?v=4",
"profile": "https://github.com/ChThH",
"contributions": [
"code"
]
},
{
"login": "meestahp",
"name": "meestahp",
"avatar_url": "https://avatars.githubusercontent.com/u/177708514?v=4",
"profile": "https://github.com/meestahp",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,
"skipCi": true,
"commitType": "docs"
}
================================================
FILE: .claude/commands/prepare-pr.md
================================================
# Prepare PR Command
Analyze the current branch changes and generate:
- a PR title
- a PR description
- considerations for the developer before pushing the PR
Output the title and description ready to paste into GitHub.
## PR TITLE
Use format: `type(scope): description`
- type: feat/fix/refactor/perf/docs/chore
- Keep under 72 characters
- Be specific but brief
## PR DESCRIPTION
It should have these sections (use a paragraph per section, no need to title them).
CONSTRAINTS:
- 100-200 words total
- No file names or "updated X file" statements
- Active voice
- No filler or pleasantries
- Focus on WHAT and WHY, not HOW
### What Changed
List 2-4 changes grouped by DOMAIN, not files. Focus on:
- User-facing changes
- Architectural shifts
- API changes
Skip trivial updates (formatting, minor refactors).
### Why
One sentence explaining motivation (skip if obvious from title).
### Critical Notes
ONLY include if relevant:
- Breaking changes
- Performance impact
- Security implications
- New dependencies
- Required config/env changes
- Database migrations
If no critical notes exist, omit this section.
## Considerations
Run the `yarn lint` command and report any failures.
Also analize the changeset, and act as a PR reviewer to provide comments about the changes.
================================================
FILE: .claude/commands/research-issue.md
================================================
# Research Issue Command
Research a GitHub issue by analyzing the issue details and codebase to generate a comprehensive task analysis file.
## Usage
```
/research-issue <issue-number>
```
## Parameters
- `issue-number` (required): The GitHub issue number to research
## Description
This command performs comprehensive research on a GitHub issue by:
1. **Fetching Issue Details**: Uses `gh issue view` to get issue title, description, labels, comments, and related information
2. **Codebase Analysis**: Searches the codebase for relevant files, patterns, and components mentioned in the issue
3. **Root Cause Analysis**: Identifies possible technical causes based on the issue description and codebase findings
4. **Solution Planning**: Proposes two solution approaches ranked by preference
5. **Documentation**: Creates a structured task file in `.agent/tasks/<issue-id>-<sanitized-title>.md`
If there is already a `.agent/tasks/<issue-id>-<sanitized-title>.md` file, use it for context and update it accordingly.
If at any time during these steps you need clarifying information from me, please ask.
## Output Format
Creates a markdown file with:
- Issue summary with link and key details
- Research findings from codebase analysis
- Identified possible root causes
- Two ranked solution approaches with pros/cons
- Technical considerations and dependencies
## Examples
```
/research-issue 1234
/research-issue 567
```
## Implementation
The command will:
1. Validate the issue number and check if it exists
2. Fetch issue details using GitHub CLI
3. Search codebase for relevant patterns, files, and components
4. Analyze findings to identify root causes
5. Generate structured markdown file with research results
6. Save to `.agent/tasks/` directory with standardized naming
## Error Handling
- Invalid issue numbers
- GitHub CLI authentication issues
- Network connectivity problems
- File system write permissions
================================================
FILE: .devcontainer/devcontainer.json
================================================
{
"name": "Foam Dev Container",
"image": "mcr.microsoft.com/devcontainers/typescript-node:0-18",
"postCreateCommand": "yarn install",
"customizations": {
"vscode": {
"extensions": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
}
}
}
================================================
FILE: .editorconfig
================================================
indent_style = space
indent_size = 2
================================================
FILE: .eslintrc.json
================================================
{
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"env": { "node": true, "es6": true },
"plugins": ["jest"],
"extends": [
"eslint:recommended",
"plugin:import/typescript",
"plugin:jest/recommended"
],
"rules": {
"no-redeclare": "off",
"no-unused-vars": "off",
"no-use-before-define": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/interface-name-prefix": "off",
"@typescript-eslint/no-unused-vars": "warn",
"import/no-extraneous-dependencies": [
"error",
{
"devDependencies": ["**/src/test/**", "**/src/**/*{test,spec}.ts"]
}
]
},
"overrides": [
{
// Restrict usage of fs module outside tests to keep foam compatible with the browser
"files": ["**/src/**"],
"excludedFiles": ["**/src/test/**", "**/src/**/*{test,spec}.ts"],
"rules": {
"no-restricted-imports": [
"error",
{
"name": "fs",
"message": "Extension code must not rely Node.js filesystem, use vscode.workspace.fs instead."
}
]
}
}
],
"settings": {
"import/core-modules": ["vscode"],
"import/parsers": {
"@typescript-eslint/parser": [".ts", ".tsx"]
},
"import/resolver": {
"typescript": {
"alwaysTryTypes": true
}
}
},
"ignorePatterns": ["**/core/common/**", "*.js"],
"reportUnusedDisableDirectives": true
}
================================================
FILE: .gitattributes
================================================
*.md linguist-detectable=true
*.css linguist-detectable=false
*.html linguist-detectable=true
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: 'Bug report'
description: Create a report to help us improve
body:
- type: markdown
attributes:
value: |
Thank you for reporting an issue :pray:.
This issue tracker is for reporting bugs found in `foam` (https://github.com/foambubble).
If you have a question about how to achieve something and are struggling, please post a question
inside of either of the following places:
- Foam's Discussion's tab: https://github.com/foambubble/foam/discussions
- Foam's Discord channel: https://foambubble.github.io/join-discord/g
Before submitting a new bug/issue, please check the links below to see if there is a solution or question posted there already:
- Foam's Issue's tab: https://github.com/foambubble/foam/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc
- Foam's closed issues tab: https://github.com/foambubble/foam/issues?q=is%3Aissue+sort%3Aupdated-desc+is%3Aclosed
- Foam's Discussions tab: https://github.com/foambubble/foam/discussions
The more information you fill in, the better the community can help you.
- type: textarea
id: description
attributes:
label: Describe the bug
description: Provide a clear and concise description of the challenge you are running into.
validations:
required: true
- type: input
id: reproducible_example
attributes:
label: Small Reproducible Example
description: |
Note:
- Your bug will may get fixed much faster if there is a way we can somehow run your example or code.
- To create a shareable example, consider cloning the following Foam Github template: https://github.com/foambubble/foam-template
- Please read these tips for providing a minimal example: https://stackoverflow.com/help/mcve.
placeholder: |
e.g. Link to your github repository containing a small reproducible example that the team can run.
validations:
required: false
- type: textarea
id: steps
attributes:
label: Steps to Reproduce the Bug or Issue
description: Describe the steps we have to take to reproduce the behavior.
placeholder: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behavior
description: Provide a clear and concise description of what you expected to happen.
placeholder: |
As a user, I expected ___ behavior but i am seeing ___
validations:
required: true
- type: textarea
id: screenshots_or_videos
attributes:
label: Screenshots or Videos
description: |
If applicable, add screenshots or a video to help explain your problem.
For more information on the supported file image/file types and the file size limits, please refer
to the following link: https://docs.github.com/en/github/writing-on-github/working-with-advanced-formatting/attaching-files
placeholder: |
You can drag your video or image files inside of this editor ↓
- type: input
id: os
attributes:
label: Operating System Version
description: What operating system are you using?
placeholder: |
- OS: [e.g. macOS, Windows, Linux]
validations:
required: true
- type: input
id: vscode_version
attributes:
label: Visual Studio Code Version
description: |
What version of Visual Studio Code are you using?
How to find Visual Studio Code Version: https://code.visualstudio.com/docs/supporting/FAQ#_how-do-i-find-the-version
validations:
required: true
- type: textarea
id: additional
attributes:
label: Additional context
description: |
Add any other context about the problem here.
The Foam log output for VSCode can be found here: https://github.com/foambubble/foam/blob/main/docs/user/tools/foam-logging-in-vscode.md
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: true
contact_links:
- name: Question
url: https://foambubble.github.io/join-discord/g
about: Please ask and answer questions here.
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
name: Feature request
description: Suggest an idea for the `Foam` project
body:
- type: markdown
attributes:
value: |
This issue form is for requesting features only!
If you want to report a bug, please use the [bug report](https://github.com/foambubble/foam/issues/new?assignees=&labels=&template=bug_report.yml) form.
- type: textarea
validations:
required: true
attributes:
label: Is your feature request related to a problem? Please describe.
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
- type: textarea
validations:
required: true
attributes:
label: Describe the solution you'd like
description: A clear and concise description of what you want to happen.
placeholder: |
As a user, I expected ___ behavior but ___ ...
Ideal Steps I would like to see:
1. Go to '...'
2. Click on '....'
3. ....
- type: textarea
validations:
required: true
attributes:
label: Describe alternatives you've considered
description: A clear and concise description of any alternative solutions or features you've considered.
- type: textarea
attributes:
label: Screenshots or Videos
description: |
If applicable, add screenshots or a video to help explain your problem.
For more information on the supported file image/file types and the file size limits, please refer
to the following link: https://docs.github.com/en/github/writing-on-github/working-with-advanced-formatting/attaching-files
placeholder: |
You can drag your video or image files inside of this editor ↓
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
typos-check:
name: Spell Check with Typos
runs-on: ubuntu-latest
steps:
- name: Checkout Actions Repository
uses: actions/checkout@v3
- name: Check spelling with custom config file
uses: crate-ci/typos@v1.14.8
with:
config: ./typos.toml
lint:
name: Lint
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v1
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Restore Dependencies and VS Code test instance
uses: actions/cache@v3
with:
path: |
node_modules
*/*/node_modules
packages/foam-vscode/.vscode-test
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock', 'packages/foam-vscode/src/test/run-tests.ts') }}-${{ secrets.CACHE_VERSION }}
- name: Install Dependencies
run: yarn
- name: Check Lint Rules
run: yarn lint
test:
name: Build and Test
# strategy:
# matrix:
# os: [macos-12, ubuntu-22.04, windows-2022]
# runs-on: ${{ matrix.os }}
runs-on: ubuntu-22.04
# env:
# OS: ${{ matrix.os }}
timeout-minutes: 15
steps:
- uses: actions/checkout@v1
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Restore Dependencies and VS Code test instance
uses: actions/cache@v3
with:
path: |
node_modules
*/*/node_modules
packages/foam-vscode/.vscode-test
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock', 'packages/foam-vscode/src/test/run-tests.ts') }}-${{ secrets.CACHE_VERSION }}
- name: Install Dependencies
run: yarn
- name: Build Packages
run: yarn build
- name: Run Tests
uses: GabrielBB/xvfb-action@v1.4
with:
run: yarn test
================================================
FILE: .github/workflows/update-docs.yml
================================================
name: Update Docs
on:
push:
branches:
- main
paths:
- docs/user/**/*
- docs/.vscode/**/*
- docs/assets/**/*
workflow_dispatch:
jobs:
update-docs:
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v3
with:
repository: foambubble/foam-template
path: foam-template
- uses: actions/checkout@v3
with:
path: foam
- name: Copy and fixup user docs files
id: copy
run: |
rm -r foam-template/docs
rm -r foam-template/assets
rm -r foam-template/.vscode
cp -r foam/docs/user foam-template/docs
cp -r foam/docs/assets foam-template/assets
cp -r foam/docs/.vscode foam-template/.vscode
# Strip autogenerated wikileaks references because
# they are not an appropriate default user experience.
(cd foam-template/docs; find . -type f -name '*.md' -exec sed -i '/\[\/\/begin\]/,/\[\/\/end\]/d' {} +)
# Set the commit message format
echo "message=Docs sync @ $(cd foam; git log --pretty='format:%h %s')" >> $GITHUB_OUTPUT
- uses: peter-evans/create-pull-request@v4
with:
token: ${{ secrets.FOAM_DOCS_SYNC_TOKEN }}
path: foam-template
commit-message: ${{ steps.copy.outputs.message }}
branch: bot/foam-docs-sync
delete-branch: true
title: Sync docs from foam
body: Copy docs from main foam repo
================================================
FILE: .gitignore
================================================
node_modules
.DS_Store
.vscode-test/
.vscode-test-web/
*.tsbuildinfo
*.vsix
*.log
out
dist
packages/foam-vscode/static/dataviz/
packages/foam-vscode/src/features/panels/dataviz/graph-protocol.ts
docs/_site
docs/.sass-cache
docs/.jekyll-metadata
.test-workspace
.agent/tasks
================================================
FILE: .husky/pre-push
================================================
npx yarn lint
================================================
FILE: .vscode/launch.json
================================================
// A launch configuration that compiles the extension and then opens it inside a new window
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Jest Tests",
"type": "extensionHost",
"request": "launch",
"args": [
"${workspaceFolder}/packages/foam-vscode/.test-workspace",
"--disable-extensions",
"--disable-workspace-trust",
"--extensionDevelopmentPath=${workspaceFolder}/packages/foam-vscode",
"--extensionTestsPath=${workspaceFolder}/packages/foam-vscode/out/test/suite"
],
"outFiles": [
"${workspaceFolder}/packages/foam-vscode/out/**/*.js"
],
"preLaunchTask": "${defaultBuildTask}"
},
{
"name": "Run VSCode Extension",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}/packages/foam-vscode"
],
"outFiles": [
"${workspaceFolder}/packages/foam-vscode/out/**/*.js"
],
"preLaunchTask": "${defaultBuildTask}"
},
{
"type": "node",
"name": "vscode-jest-tests",
"request": "launch",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
"cwd": "${workspaceFolder}/packages/foam-vscode",
"runtimeExecutable": "yarn",
"args": [
"jest",
"--runInBand",
"--watchAll=false"
]
}
]
}
================================================
FILE: .vscode/settings.json
================================================
// Place your settings in this file to overwrite default and user settings.
{
"files.exclude": {
// set these to true to hide folders with the compiled JS files,
"packages/**/out": false,
"packages/**/dist": false
},
"search.exclude": {
// set this to false to include compiled JS folders in search results
"packages/**/out": true,
"packages/**/dist": true
},
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
"typescript.tsc.autoDetect": "off",
"foam.edit.linkReferenceDefinitions": "withExtensions",
"foam.files.ignore": [
"**/.vscode/**/*",
"**/_layouts/**/*",
"**/_site/**/*",
"**/node_modules/**/*",
"packages/**/*"
],
"editor.tabSize": 2,
"editor.formatOnSave": true,
"editor.formatOnSaveMode": "file",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"jest.rootPath": "packages/foam-vscode",
"jest.jestCommandLine": "yarn test:unit",
"gitdoc.enabled": false,
"search.mode": "reuseEditor",
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
================================================
FILE: .vscode/tasks.json
================================================
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
{
"version": "2.0.0",
"tasks": [
{
"label": "watch: foam-vscode",
"type": "npm",
"script": "watch",
"problemMatcher": {
"owner": "typescript",
"fileLocation": ["relative", "${workspaceFolder}"],
"pattern": [
{
"regexp": "^(.*?)\\((\\d+),(\\d+)\\):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"message": 4
}
],
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": ".*"
},
"endsPattern": {
"regexp": ".*"
}
}
},
"isBackground": true,
"presentation": {
"reveal": "always"
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "test: all packages",
"type": "npm",
"script": "test",
"problemMatcher": [],
"group": {
"kind": "test",
"isDefault": true
}
}
]
}
================================================
FILE: .yarnrc
================================================
--ignore-engines true
================================================
FILE: CLAUDE.md
================================================
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Collaboration Principles
**Be honest and objective**: Evaluate all suggestions, ideas, and feedback on their technical merits. Don't be overly complimentary or sycophantic. If something doesn't make sense, doesn't align with best practices, or could be improved, say so directly and constructively. Technical accuracy and project quality take precedence over being agreeable.
## Project overview
Foam is a personal knowledge management and sharing system, built on Visual Studio Code and GitHub. It allows users to organize research, keep re-discoverable notes, write long-form content, and optionally publish it to the web. The main goals are to help users create relationships between thoughts and information, supporting practices like building a "Second Brain" or a "Zettelkasten". Foam is free, open-source, and extensible, giving users ownership and control over their information. The target audience includes individuals interested in personal knowledge management, note-taking, and content creation, particularly those familiar with VS Code and GitHub.
## Quick Commands
All the following commands are to be executed from the `packages/foam-vscode` directory
### Development
- `yarn install` - Install dependencies
- `yarn build` - Build all packages
- `yarn watch` - Watch mode for development
- `yarn clean` - Clean build outputs
- `yarn reset` - Full clean, install, and build
### Testing
- `yarn test` - Run all tests (unit + integration)
- `yarn test:unit` - Run unit tests (\*.test.ts files and the .spec.ts files marked a vscode-mock friendly)
- `yarn test:e2e` - Run only integration tests (\*.spec.ts files)
- `yarn lint` - Run linting
- `yarn test-reset-workspace` to clean test workspace
Unit tests run in Node.js environment using Jest
Integration tests require VS Code extension host
When running tests, do not provide additional parameters, they are ignored by the custom runner script. You cannot run just a test, you have to run the whole suite.
Unit tests are named `*.test.ts` and integration tests are `*.spec.ts`. These test files live alongside the code in the `src` directory. An integration test is one that has a direct or indirect dependency on `vscode` module.
There is a mock `vscode` module that can be used to run most integration tests without starting VS Code. Tests that can use this mock are start with the line `/* @unit-ready */`.
- If you are interested in a test inside a `*.test.ts` file, run `yarn test:unit` or inside a `*.spec.ts` file that starts with `/* @unit-ready */` run `yarn test:unit`
- If you are interested in a test inside a `*.spec.ts` file that does not include `/* @unit-ready */` run `yarn test`
While in development we mostly want to use `yarn test:unit`.
When multiple tests are failing, look at all of them, but only focus on fixing the first one. Once that is fixed, run the test suite again and repeat the process.
When writing tests keep mocking to a bare minimum. Code should be written in a way that is easily testable and if I/O is necessary, it should be done in appropriate temporary directories.
Never mock anything that is inside `packages/foam-vscode/src/core/`.
Use the utility functions from `test-utils.ts` and `test-utils-vscode.ts` and `test-datastore.ts`.
To improve readability of the tests, set up the test and tear it down within the test case (as opposed to use other functions like `beforeEach` unless it's much better to do it that way)
Never fix a test by adjusting the expectation if the expectation is correct, test must be fixed by addressing the issue with the code.
## Repository Structure
This is a monorepo using Yarn workspaces with the main VS Code extension in `packages/foam-vscode/`.
### Key Directories
- `packages/foam-vscode/src/core/` - Platform-agnostic business logic (NO vscode dependencies)
- `packages/foam-vscode/src/features/` - VS Code-specific features and UI
- `packages/foam-vscode/src/services/` - service implementations, might have VS Code dependency, but we try keep that to a minimum
- `packages/foam-vscode/src/test/` - Test utilities and mocks
- `packages/foam-vscode/webview-ui/graph/` - Graph visualization web component (`@foam/graph`)
- `docs/` - Documentation and user guides
### Graph Webview (`@foam/graph`)
The graph webview is a standalone Yarn workspace and publishable web component built with Lit.
- Source lives in `webview-ui/graph/src/`; `static/dataviz/` is **build output** (gitignored), not source
- `src/protocol.ts` owns the message contract between extension host and webview — the extension imports from `@foam/graph/protocol`
- The extension's `tsconfig.json` uses `paths` to resolve `@foam/graph/*` to TypeScript source for type checking; esbuild resolves via package exports at bundle time
Commands (run from repo root or `packages/foam-vscode`):
- `yarn workspace @foam/graph build` - Build lib (ESM) and VS Code bundle
- `yarn workspace @foam/graph build:vscode` - Build VS Code bundle only
- `yarn workspace @foam/graph build:lib` - Build publishable ESM bundle only
- `yarn workspace @foam/graph watch` - Watch mode for webview development
- `yarn workspace @foam/graph test` - Run webview tests (Vitest, not Jest)
### File Naming Patterns
Test files follow `*.test.ts` for unit tests and `*.spec.ts` for integration tests, living alongside the code in `src`. An integration test is one that has a direct or indirect dependency on `vscode` package.
### Important Constraint
Code in `packages/foam-vscode/src/core/` MUST NOT depend on the `vscode` library or any files outside the core directory. This maintains platform independence.
## Architecture Overview
### Core Abstractions
**FoamWorkspace** - Central repository managing all resources (notes, attachments)
- Uses reversed trie for efficient resource lookup
- Event-driven updates (onDidAdd, onDidUpdate, onDidDelete)
- Handles identifier resolution for short-form linking
**FoamGraph** - Manages relationship graph between resources
- Tracks links and backlinks between resources
- Real-time updates when workspace changes
- Handles placeholder resources for broken links
**ResourceProvider Pattern** - Pluggable architecture for different file types
- `MarkdownProvider` for .md files
- `AttachmentProvider` for other file types
- Extensible for future resource types
**DataStore Interface** - Abstract file system operations
- Platform-agnostic file access with configurable filtering
- Supports both local and remote file systems
### Feature Integration Pattern
Features are registered as functions receiving:
```typescript
(context: ExtensionContext, foamPromise: Promise<Foam>) => void
```
This allows features to:
- Register VS Code commands, providers, and event handlers
- Access the Foam workspace when ready
- Extend markdown-it for preview rendering
### Testing Conventions
- `*.test.ts` - Unit tests using Jest
- `*.spec.ts` - Integration tests requiring VS Code extension host
- Tests live alongside source code in `src/`
- Test cases should be phrased in terms of aspects of the feature being tested (expected behaviors), as they serve both as validation of the code as well as documentation of what the expected behavior for the code is in different situations. They should include the happy paths and edge cases.
## Development Workflow
We build production code together. I handle implementation details while you guide architecture and catch complexity early.
When working on an issue, check if a `.agent/tasks/<issue-id>-<sanitized-title>.md` exists. If not, suggest whether we should start by doing a research on it (using the `/research-issue <issue-id>`) command.
Whenever we work together on a task, feel free to challenge my assumptions and ideas and be critical if useful.
## Core Workflow: Research → Plan → Implement → Validate
**Start every feature with:** "Let me research the codebase and create a plan before implementing."
1. **Research** - Understand existing patterns and architecture
2. **Plan** - Propose approach and verify with you
3. **Implement** - Build with tests and error handling
4. **Validate** - ALWAYS run formatters, linters, and tests after implementation
- Whenever working on a feature or issue, let's always come up with a plan first, then save it to a file called `/.agent/current-plan.md`, before getting started with code changes. Update this file as the work progresses.
- Let's use pure functions where possible to improve readability and testing.
### Adding New Features
1. Create feature in `src/features/` directory
2. Register feature in `src/features/index.ts`
3. Add tests (both unit and integration as needed)
4. Update configuration in `package.json` if needed
### Working on an issue
1. Get the issue information from github
2. Define a step by step plan for addressing the issue
3. Create tests for the feature
4. **IMPORTANT**: Run the tests to ensure they FAIL before implementing the fix (this validates the test is actually testing what we think it is)
5. Implement the fix to make the test pass
6. Run the tests again to verify the fix works
### Core Logic Changes
1. Modify code in `src/core/` (ensure no vscode dependencies)
2. Add comprehensive unit tests
3. Update integration tests in features that use the core logic
## Configuration
The extension uses VS Code's configuration system with the `foam.*` namespace.
You can find all the settings in `/packages/foam-vscode/package.json`
## Common Development Tasks
### Extending Core Functionality
When adding to `src/core/`:
- Keep platform-agnostic (no vscode imports)
- Add comprehensive unit tests
- Consider impact on graph and workspace state
- Update relevant providers if needed
## Dependencies
- **Runtime**: VS Code API, markdown parsing, file watching
- **Development**: TypeScript, Jest, ESLint, esbuild
- **Key Libraries**: remark (markdown parsing), lru-cache, lodash
- **Graph webview**: Lit (web components), force-graph, d3-force/scale/color, Vitest, happy-dom
The extension supports both Node.js and browser environments via separate build targets.
## Documentation Guidelines
### User Documentation (`docs/user/`)
Documentation in `docs/user/` must be written for non-technical users. The goal is to help novice users quickly start using features, not to explain technical implementation details.
**Writing Guidelines:**
- **Target audience**: Assume users are new to Foam and may not be technical
- **Be concise**: Keep it short and to the point - every sentence must convey useful information
- **Avoid repetition**: Don't repeat the same concept in different words
- **Focus on "how to use"**: Show users what they can do and how to do it, not how it works internally
- **Balance brevity with clarity**: Users won't read verbose documentation, but they need enough information to succeed
- **Use examples**: Show practical use cases rather than abstract descriptions
- **Start with the most common use case**: Lead with what most users will want to do first
# GitHub CLI Integration
To interact with the github repo we will be using the `gh` command.
ALWAYS ask before performing a write operation on Github.
## Common Commands for Claude Code Integration
### Issues
```bash
# List all issues
gh issue list
# Filter issues by milestone
gh issue list --milestone "v1.0.0"
# Filter issues by assignee
gh issue list --assignee @me
gh issue list --assignee username
# Filter issues by label
gh issue list --label "bug"
gh issue list --label "enhancement,priority-high"
# Filter issues by state
gh issue list --state open
gh issue list --state closed
gh issue list --state all
# Combine filters
gh issue list --milestone "v1.0.0" --label "bug" --assignee @me
# View specific issue
gh issue view 123
# Create issue
gh issue create --title "Bug fix" --body "Description"
# Add comment to issue
gh issue comment 123 --body "Update comment"
```
### Pull Requests
```bash
# List all PRs
gh pr list
# Filter PRs the same way as for filters (for example, here is by milestone)
gh pr list --milestone "v1.0.0"
# View PR details
gh pr view 456
# Create PR
gh pr create --title "Feature" --body "Description"
# Check out PR locally
gh pr checkout 456
# Add review comment
gh pr comment 456 --body "LGTM"
```
================================================
FILE: LICENSE
================================================
The MIT Licence (MIT)
Copyright 2020 - present Jani Eväkallio <jani.evakallio@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Where noted, some code uses the following license:
MIT License
Copyright (c) 2015 - present Microsoft Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
================================================
FILE: docs/.vscode/custom-tag-style.css
================================================
.foam-tag{
color:#ffffff;
background-color: #000000;
}
================================================
FILE: docs/.vscode/extensions.json
================================================
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
// Foam's own extension
"foam.foam-vscode",
// Tons of markdown goodies (lists, tables of content, so much more)
"yzhang.markdown-all-in-one",
// Prettier for auto formatting code
"esbenp.prettier-vscode",
// Understated grayscale theme (light and dark variants)
"philipbe.theme-gray-matter"
]
}
================================================
FILE: docs/.vscode/keybindings.json
================================================
// This file does not get automatically applied
// @TODO: Make it work or document how to copy to user keybindings
[
{
"key": "cmd+shift+n",
"command": "foam-vscode.create-note"
}
]
================================================
FILE: docs/.vscode/settings.json
================================================
{
"files.autoSave": "onFocusChange",
"editor.minimap.enabled": false,
"editor.wrappingIndent": "indent",
"editor.overviewRulerBorder": false,
"editor.lineHeight": 24,
"foam.edit.linkReferenceDefinitions": "withExtensions",
"[markdown]": {
"editor.quickSuggestions": {
"other": true,
"comments": false,
"strings": false
}
},
"git.enableSmartCommit": true,
"git.postCommitCommand": "sync",
"files.exclude": {
"_site/**": true
},
"files.insertFinalNewline": true,
"markdown.styles": [".vscode/custom-tag-style.css"]
}
================================================
FILE: docs/404.md
================================================
# Page not found!
Well, that shouldn't have happened!
If you got here via a link from another document, please file an [issue](https://github.com/foambubble/foam/issues) on our GitHub repo including:
- the page you came from
- the link you followed
Thanks!
-The Foam Team
================================================
FILE: docs/CNAME
================================================
foamnotes.com
================================================
FILE: docs/Gemfile
================================================
source "https://rubygems.org"
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
# gem "jekyll", "~> 3.9.0"
# This is the default theme for new Jekyll sites. You may change this to anything you like.
gem "minima", "~> 2.0"
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
gem "github-pages", "~> 209", group: :jekyll_plugins
# If you have any plugins, put them here!
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.6"
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
# and associated library.
install_if -> { RUBY_PLATFORM =~ %r!mingw|mswin|java! } do
gem "tzinfo", "~> 1.2"
gem "tzinfo-data"
end
# Performance-booster for watching directories on Windows
gem "wdm", "~> 0.1.0", :install_if => Gem.win_platform?
# kramdown v2 ships without the gfm parser by default. If you're using
# kramdown v1, comment out this line.
gem "kramdown-parser-gfm"
================================================
FILE: docs/LICENSE.txt
================================================
The MIT Licence (MIT)
Copyright 2020 - present Jani Eväkallio <jani.evakallio@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Where noted, some code uses the following license:
MIT License
Copyright (c) 2015 - present Microsoft Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
================================================
FILE: docs/_config.yml
================================================
title: Foam
google_analytics: "UA-171027939-1"
================================================
FILE: docs/_layouts/foam.html
================================================
---
layout: default
---
<script type="text/javascript">
// NOTE: this should be in sync with the settings/usage in the vscode extension
// atm it's just a wide superset of md extensions to cover a wide range of cases
var MD_EXT = ['.md', '.markdown', '.mdx', '.mdown', '.mkdn', '.mkd', '.mdwn', '.mdtxt', '.mdtext', '.text', '.Rmd'];
function normalizeMdLink(link) {
var url = new URL(link);
var mdFileExt = MD_EXT.find(ext => url.pathname.endsWith(ext));
if (mdFileExt) {
url.pathname = url.pathname.slice(0, mdFileExt.length * -1);
}
return url.toString();
}
window.addEventListener('DOMContentLoaded', (event) => {
document
.querySelectorAll(".markdown-body a[title]:not([href^=http])")
.forEach((a) => {
// filter to only wikilinks
var prev = a.previousSibling;
var next = a.nextSibling;
if (
prev instanceof Text && prev.textContent.endsWith('[') &&
next instanceof Text && next.textContent.startsWith(']')
) {
// remove surrounding brackets
prev.textContent = prev.textContent.slice(0, -1);
next.textContent = next.textContent.slice(1);
// add CSS list for styling
a.classList.add('wikilink');
// replace page-link with "Page Title"...
a.innerText = a.title;
// ...and normalize the links to allow html pages navigation
a.href = normalizeMdLink(a.href);
}
});
document.querySelectorAll(".github-only").forEach((el) => {
el.remove();
});
});
</script>
{{ content }}
================================================
FILE: docs/_layouts/home.html
================================================
---
layout: foam
---
<script async defer src="https://buttons.github.io/buttons.js"></script>
{{ content }}
<script>
window.addEventListener('DOMContentLoaded', (event) => {
var duplicateHeading = document.querySelector("h1:not(#foam)");
if (duplicateHeading && duplicateHeading.remove) {
duplicateHeading.remove();
}
});
</script>
================================================
FILE: docs/_layouts/mathjax.html
================================================
---
layout: foam
---
{{ content }}
<script src="https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
skipTags: ['script', 'noscript', 'style', 'textarea', 'pre'],
inlineMath: [['$','$']]
}
});
</script>
================================================
FILE: docs/_layouts/page.html
================================================
---
layout: foam
---
{{ content }}
================================================
FILE: docs/assets/css/style.scss
================================================
---
---
@import "{{ site.theme }}";
a {
color: #3300ff;
}
.markdown-body {
max-width: 800px;
font-size: 16px;
}
.markdown-body p {
font-size: 16px;
line-height: 1.9em;
margin-bottom: 1.2em;
}
.markdown-body li {
line-height: 1.9em;
}
input.task-list-item-checkbox {
margin-right: 4px;
}
img[src*="demo"] {
border: 1px #eee solid;
-webkit-box-shadow: 4px 4px 16px 0px rgba(50, 50, 50, 0.1);
-moz-box-shadow: 4px 4px 16px 0px rgba(50, 50, 50, 0.1);
box-shadow: 4px 4px 16px 0px rgba(50, 50, 50, 0.1);
}
@media only screen and (min-width: 1170px) {
img[src*="demo"] {
max-width: 130%;
margin-left: -15%;
margin-top: 20px;
margin-bottom: 20px;
}
}
h1,
h2,
h3,
h4,
h5,
blockquote {
font-family: Constantia, "Lucida Bright", Lucidabright, "Lucida Serif", Lucida,
"DejaVu Serif", "Bitstream Vera Serif", "Liberation Serif", Georgia, serif;
}
.wikilink:before {
content: "[[";
opacity: 0.5;
}
.wikilink:after {
content: "]]";
opacity: 0.5;
}
.github-only {
display: none;
}
.announcement {
background: #ede7ff;
padding: 4px 16px;
color: black;
border-radius: 4px;
}
================================================
FILE: docs/dev/about-docs.md
================================================
# Developing documentation
The best way to develop docs for the Foam repo is to directly open the `$foam-repo/docs/` as the root folder in a new vscode window.
This automatically configures vscode with the necessary settings enabled (like [[link-reference-definitions]]) to efficiently write this documentation.
## Organization
The Foam documentation is organized into two areas:
* User docs, located at `$foam-repo/docs/user/*`, which are copied in their entirety into `$foam-template-repo/docs`.
* Developer docs, located at `$foam-repo/docs/dev/*`
New user docs should be added to the User docs folder in the main Foam repo, then copied over to the Foam Template repo.
> [[todo]]: Automate this process. Idea: github action to open a PR on any change to `/docs/user`
[//begin]: # "Autogenerated link references for markdown compatibility"
[link-reference-definitions]: ../user/features/link-reference-definitions.md "Link Reference Definitions"
[todo]: todo.md "Todo"
[//end]: # "Autogenerated link references"
================================================
FILE: docs/dev/build-vs-assemble.md
================================================
# Build vs Assemble
The Foam prototype is built by assembling third-party extensions, which seems like a good strategy because
- It supports picking and mixing of tools and workflows
- Less code to write and maintain
But there's also a bunch of roadmap items that are hard to implement this way, as the third party plugins don't do exactly what we want them to do (e.g. Markdown All In One is not compatible with [[referencing-notes-by-title]].
Overall, we should strive to build big things from small things. Focused, interoperable modules are better, because they allow users to pick and mix which features work for them. A good example of why this matters is the Markdown All In One extension we rely on: While it provides many of the things we need, a few of its features are incompatible with how I would like to work, and therefore it becomes a limiter of how well I can improve my own workflow.
However, there becomes a point where we may benefit from implementing a centralised solution, e.g. a syntax, an extension or perhaps a VSCode language server. As much as possible, we should allow users to operate in a decentralised manner.
================================================
FILE: docs/dev/code-of-conduct.md
================================================
---
redirect_from:
- /code-of-conduct
---
# Code of Conduct
We follow the [Contributor Covenant](https://www.contributor-covenant.org/) code of conduct.
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or
advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at `riki.code+foam@gmail.com`.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
<https://www.contributor-covenant.org/version/2/0/code_of_conduct.html>.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
<https://www.contributor-covenant.org/faq>. Translations are available at
<https://www.contributor-covenant.org/translations>.
================================================
FILE: docs/dev/contribution-guide.md
================================================
---
tags: todo, good-first-task
---
# Contribution Guide
Foam is open to contributions of any kind, including but not limited to code, documentation, ideas, and feedback.
This guide aims to help guide new and seasoned contributors getting around the Foam codebase. For a comprehensive guide about contributing to open-source projects in general, [see here](https://blog.robsewell.com/blog/how-to-fork-a-github-repository-and-contribute-to-an-open-source-project/).
## Getting Up To Speed
Before you start contributing we recommend that you read the following links:
- [[principles]] - This document describes the guiding principles behind Foam.
- [[code-of-conduct]] - Rules we hope every contributor aims to follow, allowing everyone to participate in our community!
To get yourself familiar with the codebase you can also browse [this repo](https://app.komment.ai/wiki/github/foambubble/foam)
## Diving In
We understand that diving in an unfamiliar codebase may seem scary,
to make it easier for new contributors we provide some resources:
You can also see [existing issues](https://github.com/foambubble/foam/issues) and help out!
Finally, the easiest way to help, is to use it and provide feedback by [submitting issues](https://github.com/foambubble/foam/issues/new/choose) or participating in the [Foam Community Discord](https://foambubble.github.io/join-discord/g)!
## Contributing
If you're interested in contributing, this short guide will help you get things set up locally (assuming [node.js >= v18](https://nodejs.org/) and [yarn](https://yarnpkg.com/) are already installed on your system).
You can also use the provided [[devcontainers]] to avoid installing dependencies locally. With the Dev Containers extension installed, open the repository in VS Code and run **Dev Containers: Reopen in Container**.
1. Fork the project to your Github account by clicking the "Fork" button on the top right hand corner of the project's [home repository page](https://github.com/foambubble/foam).
2. Clone your newly forked repo locally:
`git clone https://github.com/your_username/foam.git`
3. Install the necessary dependencies by running this command from the root of the cloned repository:
`yarn install`
4. From the repository root, run the command:
`yarn build`
You should now be ready to start working!
### Structure of the project
Foam code and documentation live in the monorepo at [foambubble/foam](https://github.com/foambubble/foam/).
- [/docs](https://github.com/foambubble/foam/tree/main/docs): documentation and [[recipes]].
Exceptions to the monorepo are:
- The starter template at [foambubble/foam-template](https://github.com/foambubble/)
- All other [[recommended-extensions]] live in their respective GitHub repos
This project uses [Yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces/).
The monorepo contains two Yarn workspace packages:
- [/packages/foam-vscode](https://github.com/foambubble/foam/tree/main/packages/foam-vscode) - The VS Code extension.
- [/packages/foam-vscode/webview-ui/graph](https://github.com/foambubble/foam/tree/main/packages/foam-vscode/webview-ui/graph) - The graph visualization web component (`@foam/graph`), published independently.
#### foam-vscode
The extension's core business logic lives in `src/core/` and must remain platform-agnostic:
1. Nothing in `foam-vscode/src/core` should depend on files outside of this directory.
2. Code in `foam-vscode/src/core` must NOT depend on the `vscode` library.
#### @foam/graph
The graph webview is a standalone Lit web component that can be embedded outside of VS Code. Key points:
- `src/protocol.ts` owns the message contract between the extension host and the webview. The extension imports from `@foam/graph/protocol`.
- `static/dataviz/` is build output (gitignored) — the source lives in `webview-ui/graph/src/`.
- Build and test commands: `yarn workspace @foam/graph build` / `yarn workspace @foam/graph test`.
### Testing
Code needs to come with tests.
We use the following convention in Foam:
- `*.test.ts` are unit tests
- `*.spec.ts` are integration tests
Tests live alongside the code in `src`.
### The VS Code Extension
This guide assumes you read the previous instructions and you're set up to work on Foam.
1. Now we'll use the launch configuration defined at [`.vscode/launch.json`](https://github.com/foambubble/foam/blob/main/.vscode/launch.json) to start a new extension host of VS Code. Open the "Run and Debug" Activity (the icon with the bug on the far left) and select "Run VSCode Extension" in the pop-up menu. Now hit F5 or click the green arrow "play" button to fire up a new copy of VS Code with your extension installed.
2. In the new extension host of VS Code that launched, open a Foam workspace (e.g. your personal one, or a test-specific one created from [foam-template](https://github.com/foambubble/foam-template)).
3. Test a command to make sure it's working as expected. Open the Command Palette (Ctrl/Cmd + Shift + P) and select "Foam: Update Markdown Reference List". If you see no errors, it's good to go!
### Submitting a Pull Request (PR)
After you have made your changes to your copy of the project, it is time to try and merge those changes into the public community project.
1. Return to the project's [home repository page](https://github.com/foambubble/foam).
2. Github should show you an button called "Compare & pull request" linking your forked repository to the community repository.
3. Click that button and confirm that your repository is going to be merged into the community repository. See [this guide](https://blog.robsewell.com/blog/how-to-fork-a-github-repository-and-contribute-to-an-open-source-project/) for more specifics.
4. Add as many relevant details to the PR message to make it clear to the project maintainers and other members of the community what you have accomplished with your new changes. Link to any issues the changes are related to.
5. Your PR will then need to be reviewed and accepted by the other members of the community. Any discussion about the changes will occur in your PR thread.
6. Once reviewed and accept you can complete the merge request!
7. Finally rest and watch the sun rise on a grateful universe... Or start tackling the other open issues ;)
---
Feel free to modify and submit a PR if this guide is out-of-date or contains errors!
---
[//begin]: # "Autogenerated link references for markdown compatibility"
[principles]: ../principles.md "Principles"
[code-of-conduct]: code-of-conduct.md "Code of Conduct"
[devcontainers]: devcontainers.md "Using Dev Containers"
[recipes]: ../user/recipes/recipes.md "Recipes"
[recommended-extensions]: ../user/getting-started/recommended-extensions.md "Recommended Extensions"
[//end]: # "Autogenerated link references"
================================================
FILE: docs/dev/devcontainers.md
================================================
# Using Dev Containers
Foam provides a [devcontainer](https://devcontainer.ai/) configuration to make it easy to contribute without installing Node and Yarn locally.
## Quick start
1. Install [VS Code](https://code.visualstudio.com/) and the [Dev Containers](https://aka.ms/vscode-remote/download/extension) extension.
2. Open the Foam repository in VS Code.
3. Run **Dev Containers: Reopen in Container** from the command palette.
This will build a Docker image with Node 18 and install dependencies using `yarn install`. Once ready you can run the usual build and test commands from the integrated terminal.
================================================
FILE: docs/dev/foam-file-format.md
================================================
# Foam File Format
This file is an example of a valid Foam file. Essentially it's just a markdown file with a bit of additional support for MediaWiki-style `[[wikilinks]]` and note embeds.
Here are a few specific constraints, mainly because our tooling is a bit fragmented. Most of these should be eventually lifted, and our requirement should just be "Markdown with `[[wikilinks]]`:
- **The first top level `# Heading` will be used as title for the note.**
- If not available, we will use the file name
- **File name should have extension `.md`**
- This is a temporary limitation and will be lifted in future versions.
- At least `.mdx` will be supported, but ideally we'll support any file that you can map to `Markdown` language mode in VS Code
- **In addition to normal Markdown Links syntax you can use `[[MediaWiki]]` links.** See [[wikilinks]] for more details.
- **You can embed other notes using `![[note]]` syntax.** This supports various modifiers like `content![[note]]` or `full-card![[note]]` to control how content is displayed.
[wikilinks]: ../user/features/wikilinks.md 'Wikilinks'
================================================
FILE: docs/dev/good-first-task.md
================================================
# Good First Task
See the backlinks of this page for good first contribution opportunities.
[[materialized-backlinks]] would help here.
[//begin]: # "Autogenerated link references for markdown compatibility"
[materialized-backlinks]: proposals/materialized-backlinks.md "Materialized Backlinks (stub)"
[//end]: # "Autogenerated link references"
================================================
FILE: docs/dev/mdx-by-default.md
================================================
# MDX by Default(stub)
**[[todo]] This [[roadmap]] item needs more specification work.**
If you're interested in working on it, please start a conversation in [GitHub issues](https://github.com/foambubble/foam/issues).
[//begin]: # "Autogenerated link references for markdown compatibility"
[todo]: todo.md "Todo"
[roadmap]: proposals/roadmap.md "Roadmap"
[//end]: # "Autogenerated link references"
================================================
FILE: docs/dev/proposals/foam-core.md
================================================
# Foam Core
`foam-core` is a (future) package that powers the core functionality in Foam across all platforms:
- VS Code Extension
- [[workspace-janitor]]
- [[cli]]
- Future initiatives
- Visualizations
- Tag clouds
- Graph
- Should we have a package for visualization?
- [[build-vs-assemble]]
- Not everything needs to live in the Foam repo
- Web based UI (Monaco)
`foam-core`'s primary responsibility is to build an API on top of a workspace of markdown files, which allows us to:
- Treat files as a graph, based on links
- Can be either [[wikilinks]] or relative `[markdown](links.md)` style
- We need to know about the edges (connections) as well as nodes
- What link points to what other file, etc.
- Needs to have the exact link text, e.g. even if `[[some-page]]` or `[[some-page.md]]` or `[[Some Page]]` point to the same document (`./some-page.md`), we need to know which format was used, so [[link-reference-definitions]] can be generated correctly
- Treat each file as semi-structured data
- Title, headings, lists, paragraphs, images, links, data, code
- Also, possible Foam-specific meta stuff, like "backlinks" or "block references".
- This can power advanced search features (e.g. showing entire context of paragraph in back links, find all documents)
Ideally, `foam-core` will be generic enough that in can be used by third parties to build their own tools that operate on markdown directories.
## Technical requirements
- The graph should be relatively inexpensive to compute (for running in CI, mobile etc)
- If necessary, we can implement caching inside a dot folder, but ideally not
- In memory cache already exist, can prime from disk if needed
- The graph should be mutable (or immutable but easy to deep clone) so that persistent processes (VS Code) can cheaply update it when
- Document content changes
- Links update -> Graph change
- Heading changes -> Metadata change
- Anything in the document changes, update AST for individual note
- Files are added
- Files are removed
- Files are renamed
- Aliasing, call the same thing by multiple names
- Doesn't exist yet, should we support?
- The graph should be observable (EventEmitter?) so changes can be applied
- EventEmitter w/ cross platform dependency
- Wonka (staltz's callbag)
- Can be a long term goal
- Short term fix: Just run the build fully on every change
- Ideally, the it should accept file/structure changes from the outside from some sort of event source, so we can decouple source of updates (VS Code Workspace events, file system events...)
- If this gets complicated, we can delay this for now
- We should not take on platform-specific dependencies
- Should work in any JS environment
- Written in TypeScript (preferably tsdx)
- Published to NPM
## Use cases
Here are some example use cases that the core should support. They don't need to be built into the core, but may help us design correct solutions:
- Adding and editing page content
- [[materialized-backlinks]]
- [[link-reference-definitions]] for [[wikilinks]]
- [Frontmatter](https://jekyllrb.com/docs/front-matter/)
- Finding all documents with `#tag`
- Finding all documents with instances of `[[link]]`
- Visualizations
- Full text search
- Or, if search is too expensive/complex, when given a list of file names and line/column positions from VS Code search API, can return the document context (e.g. full paragraph, preceding/following line etc)
## Collaboration
- This week
- List of things to work in order
- Provide more vision on future state
- Write about working and collaboration philosophy
- [[todo]] Prioritise roadmap
- Week of July 13
- Jani is available full time to work on this
- Janne: Write proposals, maybe more
- Riccardo: Available
## Configuration management
- Other tools may not be able to use vscode
- [[todo]] Discuss with Janne and Riccardo
## Feature comparison
Useful for knowing what needs to be supported. See [[feature-comparison]].
## Meeting notes
- [[foam-core-2020-07-11]]
[//begin]: # "Autogenerated link references for markdown compatibility"
[workspace-janitor]: ../../user/tools/workspace-janitor.md "Janitor"
[cli]: ../../user/tools/cli.md "Command Line Interface"
[build-vs-assemble]: ../build-vs-assemble.md "Build vs Assemble"
[wikilinks]: ../../user/features/wikilinks.md "Wikilinks"
[link-reference-definitions]: ../../user/features/link-reference-definitions.md "Link Reference Definitions"
[materialized-backlinks]: materialized-backlinks.md "Materialized Backlinks (stub)"
[todo]: ../todo.md "Todo"
[foam-core-2020-07-11]: ../meeting-notes/foam-core-2020-07-11.md "Foam Core 2020-07-11"
[//end]: # "Autogenerated link references"
================================================
FILE: docs/dev/proposals/inclusion-of-notes.md
================================================
# Inclusion of notes Proposal <!-- omit in TOC -->
Currently it is not possible within Foam to include other notes into a note. Next to including a full note it could be interesting to add functionalities that allow for greater flexibility. This proposal discusses some functionalities around inclusion of notes.
**IMPORTANT: This design is merely a proposal of a design that could be implemented. It DOES NOT represent a commitment by `Foam` developers to implement the features outlined in this document. This document is merely a mechanism to facilitate discussion of a possible future direction for `Foam`.**
- [Introduction](#introduction)
- [New features](#new-features)
- [Including a note](#including-a-note)
- [Include a section of a note](#include-a-section-of-a-note)
- [Include an attribute of a file (note property or frontmatter)](#include-an-attribute-of-a-file-note-property-or-frontmatter)
## Introduction
Initial work and thought on including a note was ignited by issue [#652](https://github.com/foambubble/foam/issues/652). Requested by a user was a likewise functionality as offered in Obsidian. This was simply the ability to include a note.
Whilst researching digital gardening for my own setup, I came across an in-depth overview by [Maggie Appleton](https://maggieappleton.com/roam-garden). Showing examples of her personal Roam Research I see valuable possibilities to connect more information, if we would add additional functionalities to the possibility of including a note. This proposal displays these possible functionalities and markup.
## New features
### Including a note
The minimal functionality is the ability to fully include a note. Markup used in Obsidian for this is `![[wikilink]]`. For Foam I would suggest to follow this syntax. Benefits being:
- Adds minimal amount of knowledge required as syntax is based on the syntax of creating a wikilink.
- Makes the auto-complete work ouf-of-the-box, without any additional code and listeners required.
**Important**. A risk exists that a loop of including the same notes arises. E.g. Note A includes note B which includes note A. This needs to be prevented by the implementation and made visible to the user.
### Include a section of a note
It could be interesting to only include a section of a note instead of the entire note. In order to do so the user should be able to use the following syntax:
`![[wikilink#section-b]]`
As a result it will include the section title + section content until the next section *or* end of file.
### Include an attribute of a file (note property or frontmatter)
As a user I could be interested in collecting the value of any given property for a note. For example, I might want to include the tags as defined in the frontmatter of note A. This should be possible via the syntax:
`![[wikilink:<property>]]`
The property value should be looked up by foam defined properties, e.g. title, **or** any property defined in the frontmatter of a note.
So, the example of including the tags of a note should be:
`![[wikilink:tags]]`
================================================
FILE: docs/dev/proposals/link-reference-definition-improvements.md
================================================
# Link Reference Definition Improvements
## Current Problems
### File-by-file Insertion
For the time being, if you want to get [[wikilinks]] into all files within the workspace, you'll need to generate the link reference definitions yourself file-by-file (with the assistance of Foam).
### Wikilinks don't work on GitHub
> **TL;DR;** [workaround](#workaround) in the end of the chapter.
If you click any of the wikilinks on GitHub web UI (such as the `README.md` of a project), you'll notice that the links break with a 404 error.
At the time of writing (June 28 2020) this is a known, but unsolved error. To understand why this is the case, we need to understand what we are trading off.
So, why don't they work on GitHub?
The three components of [[link-reference-definitions]] are link label, link destination and Link Title.
The issue is the middle **link destination** component. It's configured to point to the file name **without file extension**, i.e. "file-name" instead of "file-name.md". This is to make the GitHub Pages rendering work, because if we generated the links to `file-name.md`, the links would point to the raw markdown files instead of their generated HTML versions.
| Environment | `file-name` | `file-name.md` |
| ---------------- | ----------- | -------------- |
| **VS Code** | Works | Works |
| **GitHub pages** | Works | Breaks |
| **GitHub UI** | Breaks | Works |
So as you can see, we've prioritised GitHub Pages over GitHub Web UI for the time being.
Ideally, we'd like a solution that works with both, but it's not defined yet (see [[link-reference-definitions]] for more details)
#### Workaround
For the time being, you can use relative `[markdown links](markdown-link.md)` syntax.
**Pros:**
- This will work on all platforms.
**Cons:**
- It will break the Markdown Notes [[backlinking]] support
- Less convenient to write
### Finding certain words clutter the VS Code search results
Since link reference definitions have `[//begin]` and `[//end]` guards with explanatory text that use certain words, these words (like "generate") appear in VS Code search results if you happen to search matching strings from the workspace.
## Improvement Proposal
Problem space in essence:
- During edit-time (when modifying the markdown files in an editor)
- link reference definitions are needed if user uses editor extensions that don't understand wikilinks
- link reference definitions may be annoying since they
- add content to files that the user hasn't typed in by themselves
- get out of date if user uses a tool that doesn't autogenerate them
- may clutter the search results
- During build-time (when converting markdown to html for publishing purposes)
- link reference definitions are needed, if the files are published via such tools (or to such platforms) that don't understand wikilinks
- link reference definitions might have to be in different formats depending on the publish target (e.g. GitHub pages vs GitHub UI)
The potential solution:
- For edit-time
- Make edit-time link reference definition generation optional via user settings. They should be on by default, and generating valid markdown links with a relative path to a `.md` file.
- Make format of the link reference definition configurable (whether to include '.md' or not)
- Out of recommended extensions, currently only "markdown links" doesn't support them (?). However even its [code](https://github.com/tchayen/markdown-links/blob/main/src/parsing.ts#L25) seems to include wikilink parser, so it might just be a bug?
- For build-time
- To satisfy mutually incompatible constraints between GitHub UI, VSCode UI, and GitHub Pages, we should add a pre-processing/build step for pushing to GitHub Pages.
- This would be a GitHub action (or a local script, ran via foam-cli) that outputs publish-friendly markdown format for static site generators and other publishing tools
- This build step should be pluggable, so that other transformations could be ran during it
- Have publish targets defined in settings, that support both turning the link reference definitions on/off and defining their format (.md or not). Example draft (including also edit-time aspect):
```typescript
// settings json
// see enumerations below for explanations on values
{
"foam": {
"publish": [
{
"name": "Gitlab Mirror", // name of the publish target
"linkTranspilation": "Off",
"linkReferenceDefinitions": "withExtensions"
},
{
"name": "GitHub Pages",
"linkTranspilation": "Off",
"linkReferenceDefinitions": "withoutExtensions"
},
{
"name": "Blog",
"linkTranspilation": "Off",
"linkReferenceDefinitions": "Off"
},
{
"name": "My Amazing PDF book",
"linkTranspilation": "WikiLinksToMarkdown"
}
],
"edit": {
"linkReferenceDefinitions": "Off"
}
}
}
// Defines if and how links in markdown files are somehow converted (in-place) during build time
// Note that this enumeration is not valid edit-time, since we (probably) don't want to change text like this while user is editing it
enum LinkTranspilation {
Off, // links are not transpiled
WikiLinksToMarkdown, // links using wiki-format [[link]] are converted to normal md links: [link](./some/file.md)
// if this is set, not link reference definitions are generated (not needed)
}
// Defines if and how link reference definition section is generated
enum LinkReferenceDefinitions {
Off, // link reference definitions are not generated
WithExtensions, // link reference definitions contain .md (or similar) file extensions
WithoutExtensions // link reference definitions do not contain file extensions
}
```
- With Foam repo, just use edit-time link reference definitions with '.md' extension - this makes the links work in the GitHub UI
- Have publish target defined for GitHub pages, that doesn't use '.md' extension, but still has the link reference definitions. Generate the output into gh-pages branch (or separate repo) with automation.
- This naturally requires first removing the existing link reference definitions during the build
- Other
- To clean up the search results, remove link reference definition section guards (assuming that these are not defined by the markdown spec). Use unifiedjs parse trees to identify if there's missing (or surplus) definitions (check if they are identified properly by the library), and just add the needed definitions to the bottom of the file (without guards) AND remove them if they are not needed (anywhere from the file).
Note that the proposal above supports both (build-time) inline transpilation of wikilinks as well as creation reference definitions. Depending on the direction of Foam, also only one of them could be selected. In that case the other could be implemented at later point of time.
UI-wise, the publish targets could be picked in some similar fashion as the run/debug targets in vscode by implementing a separate panel, or maybe through command execution (CTRL+SHIFT+P) - not yet defined at this point.
## Links
- [tracking issue on GitHub](https://github.com/foambubble/foam/issues/16)
[//begin]: # "Autogenerated link references for markdown compatibility"
[wikilinks]: ../../user/features/wikilinks.md "Wikilinks"
[link-reference-definitions]: ../../user/features/link-reference-definitions.md "Link Reference Definitions"
[backlinking]: ../../user/features/backlinking.md "Backlinking"
[//end]: # "Autogenerated link references"
================================================
FILE: docs/dev/proposals/materialized-backlinks.md
================================================
# Materialized Backlinks (stub)
**[[todo]] This [[roadmap]] item needs more specification work.**
If you're interested in working on it, please start a conversation in [GitHub issues](https://github.com/foambubble/foam/issues).
## Notes
The idea would be to automatically generate lists of backlinks (and optionally, also forward links) into the bottom of every markdown document to
- Make every link two-way navigable in published sites
- Make Foam notes more portable to different apps and long-term storage
[//begin]: # "Autogenerated link references for markdown compatibility"
[todo]: ../todo.md "Todo"
[roadmap]: roadmap.md "Roadmap"
[//end]: # "Autogenerated link references"
================================================
FILE: docs/dev/proposals/roadmap.md
================================================
# Roadmap
Some of these items can be achieved by combining existing tools, but others may require us to build bespoke software solutions. See [[build-vs-assemble]] to understand trade-offs between these approaches. If a feature can be implemented by contributing to [[recipes]], it should.
## In progress
Items that are already being worked on. Roadmap items in this stage should have an owner.
## High priority
Items we plan on working next. Items in this stage don't need to have an owner, but before we start working on them should have enough specification that they can be picked up and worked on without having to seek consensus.
If you want to pick up work in this category, you should have a plan on how long the implementation will approximately take so we don't block progress by sitting on high priority issues.
## Backlog
Everything else, categorised into themes. Just because something is on this list doesn't mean it'll get done. If you're interested in working on items in this category, check the [[contribution-guide]] for how to get started.
If a roadmap item is a stub, **consider** opening a [GitHub issue](https://github.com/foambubble/foam/issues) to start a conversation to avoid situations where the implementation does not fit long term vision and roadmap. _Note that this is optional. The only centralised governance in Foam is to decide what ends up in the official [template](https://github.com/foambubble/foam-template), [documentation](https://github.com/foambubble/foam) and [extension](https://github.com/foambubble/foam/tree/main/packages/foam-vscode). You are free to build whatever you want for yourself, and we'd love if you shared it with us, but you are by no means obligated to do so!_
**When creating GitHub issues to discuss roadmap items, link them here.**
### Known issues
- [[improve-default-workspace-settings]]
- Discussion: [foam#270](https://github.com/foambubble/foam/issues/270)
- Improve [[git-integration]]
- Fix [[wikilinks]] compatibility issues
- Simplify [[foam-file-format]]
### Core features
- [[renaming-files]]
- [[unlinked-references]]
- [[block-references]]
- [[improved-backlinking]]
- UX: [[make-backlinks-more-prominent]]
- [[materialized-backlinks]]
- [[automatic-git-syncing]]
- [[git-flows-for-teams]]
- [[user-settings]]
- [[link-reference-definitions]]
- [[predefined-user-snippets]]
### Publishing
- [[officially-support-alternative-templates]]
- [[improved-static-site-generation]]
- [[mdx-by-default]]
- [[search-in-published-workspace]]
- [[graph-in-published-workspace]]
- Discussion: [foam#58](https://github.com/foambubble/foam/issues/58)
- [[linking-between-published-workspaces]]
- Discussion: [foam#59](https://github.com/foambubble/foam/issues/59)
- [[publishing-permissions]]
### Platforms
- [[cli]]
- [[mobile-apps]]
- [[packaged-desktop-app]]
- [[web-editor]]
### Migration
The community is working on a number of automated scripts to help you migrate to Foam. The main work of developing such a method involves exporting your notes, converting them to the Markdown format, and then making sure that the links between notes (if you had those) still work.
- [[migrating-from-roam]]
- Discussion: [foam#55](https://github.com/foambubble/foam/issues/55)
- [[migrating-from-obsidian]]
- Discussion: [foam#46](https://github.com/foambubble/foam/issues/46)
- [[migrating-from-onenote]]
- Discussion: [foam#151](https://github.com/foambubble/foam/issues/151)
- _Migration from other tools..._
### Integration
- _Integrations to third party tools_...
### Wild ideas
- [[foam-linter]]
- [[refactoring-via-language-server-protocol]]
[//begin]: # "Autogenerated link references for markdown compatibility"
[build-vs-assemble]: ../build-vs-assemble.md "Build vs Assemble"
[recipes]: ../../user/recipes/recipes.md "Recipes"
[contribution-guide]: ../contribution-guide.md "Contribution Guide"
[wikilinks]: ../../user/features/wikilinks.md "Wikilinks"
[foam-file-format]: ../foam-file-format.md "Foam File Format"
[unlinked-references]: ../unlinked-references.md "Unlinked references (stub)"
[make-backlinks-more-prominent]: ../../user/recipes/make-backlinks-more-prominent.md "Make Backlinks More Prominent"
[materialized-backlinks]: materialized-backlinks.md "Materialized Backlinks (stub)"
[automatic-git-syncing]: ../../user/recipes/automatic-git-syncing.md "Automatically Sync with Git"
[link-reference-definitions]: ../../user/features/link-reference-definitions.md "Link Reference Definitions"
[predefined-user-snippets]: ../../user/recipes/predefined-user-snippets.md "Pre-defined User Snippets"
[mdx-by-default]: ../mdx-by-default.md "MDX by Default(stub)"
[publishing-permissions]: ../publishing-permissions.md "Publishing Permissions(stub)"
[cli]: ../../user/tools/cli.md "Command Line Interface"
[migrating-from-roam]: ../../user/recipes/migrating-from-roam.md "Migrating from Roam (stub)"
[migrating-from-obsidian]: ../../user/recipes/migrating-from-obsidian.md "Migrating from Obsidian (stub)"
[migrating-from-onenote]: ../../user/recipes/migrating-from-onenote.md "Migrating from OneNote"
[//end]: # "Autogenerated link references"
================================================
FILE: docs/dev/proposals/wikilinks-in-foam.md
================================================
# Wikilinks in Foam
Foam supports standard wikilinks in the format `[[wikilink]]`.
Wikilinks can refer to any note or attachment in the repo: `[[note.md]]`, `[[doc.pdf]]`, `[[image.jpg]]`.
The usual wikilink syntax without extension refers to notes: `[[wikilink]]` and `[[wikilink.md]]` are equivalent.
The goal of wikilinks is to uniquely identify a file in a repo, no matter in which directory it lives.
Sometimes in a repo you can have files with the same name in different directories.
Foam allows you to identify those files using the minimum effort needed to disambiguate them.
This is achieved by adding as many directories above the file needed to uniquely identify the link, e.g. `[[house/todo]]`.
See below for more details.
## Goals for wikilinks in Foam
Wikilinks in Foam are meant to satisfy the following:
- make it easy for users to identify a resource
- make it interoperable with other similar note taking systems (Obsidian, Dendron, ...)
- be easy to get started with, but satisfy growing needs
## Types of wikilinks supported in Foam
Foam supports two types of keys inside a wikilink: a **path** reference and an **identifier** reference:
- `[[./file]]` and `[[../to/another/file]]` are **path** links to a resource, relative _from the source_
- `[[/path/to/file]]` is a **path** link to a resource, relative _from the repo root_
- `[[file]]` is an **identifier** of a resource (based on the filename)
- `[[path/to/file]]` is an **identifier** of a resource (based on the path), the same is true for `[[to/file]]`
It's important to note that sometimes identifier keys can't uniquely locale a resource.
A more concrete example will help:
```
/
projects/
house/
todo.md
buy-car/
todo.md
cars.md
work/
todo.md
notes.md
```
In the above repo:
- `[[cars]]` is a unique identifier of a resource - it can be used anywhere in the repo
- `[[todo]]` is an non-unique identifier as it can refer to multiple resources
- `[[house/todo]]` is a unique identifier of a resource - it can be used anywhere in the repo
- `[[projects/house/todo]]` is a unique identifier of a resource - it can be used anywhere in the repo
- `[[/projects/house/todo]]` is a path reference to a resource
- `[[./todo]]` is a path reference to a resource (e.g. from `/projects/buy-car/cars.md`)
Basically we could say as a rule:
- if the link starts with `/` or `.` we consider it a **path** reference, in the first case from the repo root, otherwise from the source note
- if a link doesn't start with `/` or `.` it is an **identifier**
- generally speaking we use the shortest identifier available to identify a resource, **but all are valid**
- `[[projects/buy-car/cars]]`, `[[buy-car/cars]]`, `[[cars]]` are all unique identifier to the same resource, and are all valid in a document
- the same can be said for `[[projects/house/todo]]` and `[[house/todo]]` - but not for `[[todo]]`, because it can refer to more than one resource
## Compatibility with other apps
| Scenario | Obsidian | Foam |
| --------------------------- | ------------------------------- | ------------------------------- |
| 1 `[[notes]]` | ✔ unique identifier in repo | ✔ unique identifier in repo |
| 2 `[[/work/notes]]` | ✔ valid path from repo root | ✔ valid path from repo root |
| 3 `[[work/notes]]` | ✔ valid path from repo root | ✔ valid identifier in repo |
| 4 `[[project/house/todo]]` | ✔ valid path from repo root | ✔ valid unique identifier |
| 5 `[[/project/house/todo]]` | ✔ valid path from repo root | ✔ valid path from repo root |
| 6 `[[house/todo]]` | ✔ valid unique identifier | ✔ valid unique identifier |
| 7 `[[todo]]` | ✘ ambiguous identifier | ✘ ambiguous identifier |
| 8 `[[/house/todo]]` | ✘ incorrect path from repo root | ✘ incorrect path from repo root |
## Non-unique identifiers
We can't prevent non-unique identifiers from occurring in Foam (first and foremost because a file could be edited with another editor) but we can flag them.
Therefore Foam follows the following strategy instead:
1. there is a clear resolution mechanism (alphabetic) so that if nothing changes a non-unique identifier will always return the same note. Resolution has to be deterministic
2. a diagnostic entry (warning or error) is showed to the user for non-unique identifiers, so she knows that she's using a "risky" identifier
1. The quick resolution for this item will show the available unique identifiers matching the non-unique one
## Thanks
Thanks to [@memplex](https://github.com/memeplex) for helping with the thinking around this proposal.
================================================
FILE: docs/dev/publishing-permissions.md
================================================
# Publishing Permissions(stub)
**[[todo]] This [[roadmap]] item needs more specification work.**
If you're interested in working on it, please start a conversation in [GitHub issues](https://github.com/foambubble/foam/issues).
## Notes
- Public and private pages
- Share specific page (with private hash)
[//begin]: # "Autogenerated link references for markdown compatibility"
[todo]: todo.md "Todo"
[roadmap]: proposals/roadmap.md "Roadmap"
[//end]: # "Autogenerated link references"
================================================
FILE: docs/dev/releasing-foam.md
================================================
# Releasing Foam
1. Get to the latest code
- `git checkout main && git fetch && git rebase`
2. Sanity checks
- `yarn reset`
- `yarn test`
3. Update change log
- `./packages/foam-vscode/CHANGELOG.md`
- `git add *`
- `git commit -m"Preparation for next release"`
4. Update version
- `$ yarn version-extension <version>` (where `version` is `patch/minor/major`)
5. Package extension
- `$ yarn package-extension`
6. Publish extension
- `$ yarn publish-extension`
7. Update the release notes in GitHub
- in GitHub, top right, click on "releases"
- select "tags" in top left
- select the tag that was just released, click "edit" and copy release information from changelog
- publish (no need to attach artifacts)
8. Announce on Discord
Steps 1 to 6 should really be replaced by a GitHub action...
================================================
FILE: docs/dev/testing.md
================================================
# Testing in Foam VS Code Extension
This document explains the testing strategy and conventions used in the Foam VS Code extension.
## Test File Types
We use two distinct types of test files, each serving different purposes:
### `.test.ts` Files - Pure Unit Tests
- **Purpose**: Test business logic and algorithms in complete isolation
- **Dependencies**: No VS Code APIs dependencies
- **Environment**: Pure Jest with Node.js
- **Speed**: Very fast execution
- **Location**: Throughout the codebase alongside source files
### `.spec.ts` Files - Integration Tests with VS Code APIs
- **Purpose**: Test features that integrate with VS Code APIs and user workflows
- **Dependencies**: Will likely depend on VS Code APIs (`vscode` module), otherwise avoid incurring the performance hit
- **Environment**: Can run in TWO environments:
- **Mock Environment**: Jest with VS Code API mocks (fast)
- **Real VS Code**: Full VS Code extension host (slow but comprehensive)
- **Speed**: Depends on environment (see performance section below)
- **Location**: Primarily in `src/features/` and service layers
## Key Principle: Environment Flexibility for `.spec.ts` Files
**`.spec.ts` files use VS Code APIs**, but they can run in different environments:
- **Mock Environment**: Uses our VS Code API mocks for speed
- **Real VS Code**: Uses actual VS Code extension host for full integration testing
This dual-environment capability allows us to:
- Run specs quickly during development (mock environment)
- Verify full integration during CI/CD (real VS Code environment)
- Gradually migrate specs to mock-compatible implementations
## Performance Comparison
| Test Type | Environment | Typical Duration | VS Code APIs |
| --------------------- | ---------------------- | ---------------- | ---------------- |
| **`.test.ts`** | Pure Jest | fastest | **No** |
| **`.spec.ts` (mock)** | Jest + VS Code Mocks | fast | **Yes** (mocked) |
| **`.spec.ts` (real)** | VS Code Extension Host | sloooooow. | **Yes** (real) |
## Running Tests
### Available Commands
- **`yarn test:unit`**: Runs `.test.ts` files (no VS Code dependencies) + `@unit-ready` marked `.spec.ts` files using mocks
- **`yarn test:unit-without-specs`**: Runs only `.test.ts` files
- **`yarn test:e2e`**: Runs all `.spec.ts` files in full VS Code extension host
- **`yarn test`**: Runs both unit and e2e test suites sequentially
## Mock Environment Migration
We're gradually enabling `.spec.ts` files to run in our fast mock environment while maintaining their ability to run in real VS Code.
### The `@unit-ready` Annotation
Spec files marked with `/* @unit-ready */` can run in both environments:
```typescript
/* @unit-ready */
import * as vscode from 'vscode';
// ... test uses VS Code APIs but works with our mocks
```
### Common Migration Fixes
**Configuration defaults**: Our mocks don't load package.json defaults
```typescript
// Before
const format = getFoamVsCodeConfig('openDailyNote.filenameFormat');
// After (defensive)
const format = getFoamVsCodeConfig(
'openDailyNote.filenameFormat',
'yyyy-mm-dd'
);
```
**File system operations**: Ensure proper async handling
```typescript
// Mock file operations are immediate but still async
await vscode.workspace.fs.writeFile(uri, content);
```
### When NOT to Migrate
Some specs should remain real-VS-Code-only:
- Tests verifying complex VS Code UI interactions
- Tests requiring real file system watching with timing
- Tests validating extension packaging or activation
- Tests that depend on VS Code's complex internal state management
## Mock System Capabilities
Our `vscode-mock.ts` provides comprehensive VS Code API mocking:
## Contributing Guidelines
When adding new tests:
1. **Choose the right type**:
- Use `.test.ts` for pure business logic with no VS Code dependencies
- Use `.spec.ts` for anything that needs VS Code APIs
2. **Consider mock compatibility**:
- When writing `.spec.ts` files, consider if they could run in mock environment
- Add `/* @unit-ready */` if the test works with our mocks
3. **Follow naming conventions**:
- Test files should be co-located with source files when possible
- Use descriptive test names that explain the expected behavior
4. **Performance awareness**:
- Prefer unit tests for business logic (fastest)
- Use mock-compatible specs for VS Code integration (fast)
- Reserve real VS Code specs for complex integration scenarios (comprehensive)
This testing strategy gives us the best of both worlds: fast feedback during development and comprehensive integration verification when needed.
## Graph Webview (`@foam/graph`)
The webview component has its own test stack, separate from the extension's Jest setup.
- **Framework**: [Vitest](https://vitest.dev/) with [happy-dom](https://github.com/capricorn86/happy-dom) for a browser-like environment
- **Location**: Test files live in `packages/foam-vscode/webview-ui/graph/src/`
- **Command**: `yarn workspace @foam/graph test`
The webview tests focus on the framework-agnostic library code in `src/lib/` (graph utilities, color logic, painter). Lit component rendering tests can be added as the component grows.
================================================
FILE: docs/dev/todo.md
================================================
# Todo
Features belong on the [[roadmap]].
- [ ] Write out Roadmap
- [ ] Isolate tasks for MLH fellows
- [ ] Create better structure for Recipes
- [ ] Connect to folks at GitHub
- [ ] Learn more about VS Code Extension APIs
- [ ] Workspace fs/events
- [ ] Reloading changes from outside vscode
- [ ] Expanding, editable snippets
For more things to do, check backlinks for Pages that annotate [[todo]].
[//begin]: # "Autogenerated link references for markdown compatibility"
[roadmap]: proposals/roadmap.md "Roadmap"
[todo]: todo.md "Todo"
[//end]: # "Autogenerated link references"
================================================
FILE: docs/dev/unlinked-references.md
================================================
# Unlinked references (stub)
**[[todo]] This [[roadmap]] item needs more specification work.**
If you're interested in working on it, please start a conversation in [GitHub issues](https://github.com/foambubble/foam/issues).
## Notes
One of Foam's big features is the ability to find all instances of a reference, create a page for it and update all the references to link to the new page.
Implementing this is on the [[roadmap]], but for the time being you can achieve similar things by:
- `Cmd` + `Shift` + `F` ( `Ctrl` + `Shift` + `F` on Windows ) to find all the references, e.g. "Cat food"
- `Cmd` + `Shift` + `H` ( `Ctrl` + `Shift` + `H` on Windows ) to replace them with [[cat-food]].
- Click any of the references to create a new note.
[//begin]: # "Autogenerated link references for markdown compatibility"
[todo]: todo.md "Todo"
[roadmap]: proposals/roadmap.md "Roadmap"
[//end]: # "Autogenerated link references"
================================================
FILE: docs/inbox.md
================================================
# Inbox
Uncategorised thoughts, to be added
- Release notes
- Markdown Preview
- It's possible to customise the markdown preview styling. **Maybe make it use local foam workspace styles for live preview of the site??**
- See: <https://marketplace.visualstudio.com/items?itemName=bierner.markdown-preview-github-styles>
- Use VS Code [CodeTour](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour) for onboarding
- Investigate other similar extensions:
- [Unotes](https://marketplace.visualstudio.com/items?itemName=ryanmcalister.Unotes)
- [vscode-memo](https://github.com/svsool/vscode-memo)
- Open in Foam
- When you want to open a Foam published website in your own VS Code, we could have a "Open in Foam" link that opens the link in VS Code via a url binding (if possible), downloads the github repo locally, and opens it as a Foam workspace.
- Every Foam could have a different theme even in the editor, so you'll see it like they see it
- UI and layout design of your workspace can become a thing
- VS Code Notebooks API
- <https://code.visualstudio.com/api/extension-guides/notebook>
- Future architecture
- Could we do publish-related settings as a pre-push git hook, e.g. generating footnote labels
- Running them on GitHub Actions to edit stuff as it comes in
- Ideally, we shouldn't have to touch files, should be just markdown
- Looking at the errors/warnings/output panes makes me think, what kind of automated quality tools could we write.
- Deduplication, finding similarities...
- Thought Debugger?
- Knowledge Debugger?
- Janitor? Gardener?
- Foam Compiler?
- Should support Netlify deploys out of the box
- Foam should tick at the same frequency as your brain, and the Foam graph you build should match the mental model you have in your head, making navigation effortless.
- Maps have persistent topologies. As the graph grows, you should be able to visualise where an idea belongs. Maybe a literal map? And island? A DeckGL visualization?
Testing: This file is served from the /docs directory.
================================================
FILE: docs/index.md
================================================
# What is Foam?
Foam is a personal knowledge management system built on [Visual Studio Code](https://code.visualstudio.com/) and [GitHub](https://github.com/). It helps you organize research, create discoverable notes, and publish your knowledge.
## Key Features
- **Wikilinks** - Connect thoughts with `[[double bracket]]` syntax
- **Embeds** - Include content from other notes with `![[note]]` syntax
- **Backlinks** - Automatically discover connections between notes
- **Graph visualization** - See your knowledge network visually
- **Daily notes** - Capture timestamped thoughts
- **Templates** - Standardize note creation
- **Tags** - Organize and filter content
## Why Choose Foam?
- **Free and open source** - No subscriptions or vendor lock-in
- **Own your data** - Notes stored as standard Markdown files
- **VS Code integration** - Leverage powerful editing and extensions
- **Git-based** - Version control and collaboration built-in
Foam is like a bathtub: _What you get out of it depends on what you put into it._
<p class="announcement">
<b>New!</b> Join <a href="https://foambubble.github.io/join-discord/w" target="_blank">Foam community Discord</a> for users and contributors!
</p>
<div class="website-only">
<a class="github-button" href="https://github.com/foambubble/foam" data-icon="octicon-star" data-size="large" data-show-count="true" aria-label="Star foambubble/foam on GitHub">Star</a>
<a class="github-button" href="https://github.com/foambubble/foam-template" data-icon="octicon-repo-template" data-size="large" aria-label="Use this template foambubble/foam-template on GitHub">Use this template</a>
</div>
## Table of Contents
- [What is Foam?](#what-is-foam)
- [Key Features](#key-features)
- [Why Choose Foam?](#why-choose-foam)
- [Table of Contents](#table-of-contents)
- [How do I use Foam?](#how-do-i-use-foam)
- [What's in a Foam?](#whats-in-a-foam)
- [Getting started](#getting-started)
- [Features](#features)
- [Contributing](#contributing)
- [Thanks and attribution](#thanks-and-attribution)
- [License](#license)
## How do I use Foam?
Foam helps you create relationships between thoughts and information through:
1. **Atomic notes** - Write focused markdown documents on single topics
2. **Wikilinks** - Connect ideas with `[[double bracket]]` syntax
3. **Backlinks** - Discover unexpected connections between notes
4. **Graph visualization** - See your knowledge network visually
Success with Foam depends on consistent note-taking and linking habits.
## What's in a Foam?
Foam combines existing tools:
1. **VS Code** - Enhanced with [[recommended-extensions]] optimized for knowledge management
2. **GitHub** - Version control, backup, and collaboration
3. **Static site generators** - Publish to GitHub Pages, Netlify, or Vercel
> This documentation was created using Foam.
## Getting started
**Requirements:** GitHub account and Visual Studio Code
1. **Create repository** - Use the [foam-template](https://github.com/foambubble/foam-template) to generate a new repository
<a class="github-button" href="https://github.com/foambubble/foam-template/generate" data-icon="octicon-repo-template" data-size="large" aria-label="Use this template foambubble/foam-template on GitHub">Use this template</a>
2. **Clone and open** - Clone locally and open the folder in VS Code
3. **Install extensions** - Click "Install all" when prompted for recommended extensions
4. **Configure** - Edit `.vscode/settings.json` for your preferences
**Next steps:**
- Explore the [[recipes]] for usage patterns
- Check [[frequently-asked-questions]] if you need help
- Report issues on [GitHub](http://github.com/foambubble/foam/issues)
## Features
Foam leverages VS Code and [[recommended-extensions]] to provide:
- **Wikilinks** with autocomplete and navigation
- **Backlinks** panel showing connections
- **Graph visualization** of your knowledge network
- **Daily notes** with templates and snippets
- **Tag system** for organization
- **Publishing** to static sites

Explore [[recipes]] for usage patterns and workflows.
## Contributing
Foam is an evolving project and we welcome contributions:
- Read our [[principles]] to understand Foam's philosophy
- Follow the [[contribution-guide]] to get involved
- Share feedback via [GitHub issues](https://github.com/foambubble/foam/issues)
## Thanks and attribution
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://jevakallio.dev/"><img src="https://avatars1.githubusercontent.com/u/1203949?v=4?s=60" width="60px;" alt="Jani Eväkallio"/><br /><sub><b>Jani Eväkallio</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jevakallio" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jevakallio" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://joeprevite.com/"><img src="https://avatars3.githubusercontent.com/u/3806031?v=4?s=60" width="60px;" alt="Joe Previte"/><br /><sub><b>Joe Previte</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jsjoeio" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jsjoeio" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/riccardoferretti"><img src="https://avatars3.githubusercontent.com/u/457005?v=4?s=60" width="60px;" alt="Riccardo"/><br /><sub><b>Riccardo</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=riccardoferretti" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=riccardoferretti" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://ojanaho.com/"><img src="https://avatars0.githubusercontent.com/u/2180090?v=4?s=60" width="60px;" alt="Janne Ojanaho"/><br /><sub><b>Janne Ojanaho</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jojanaho" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jojanaho" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://bypaulshen.com/"><img src="https://avatars3.githubusercontent.com/u/2266187?v=4?s=60" width="60px;" alt="Paul Shen"/><br /><sub><b>Paul Shen</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=paulshen" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/coffenbacher"><img src="https://avatars0.githubusercontent.com/u/245867?v=4?s=60" width="60px;" alt="coffenbacher"/><br /><sub><b>coffenbacher</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=coffenbacher" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://mathieu.dutour.me/"><img src="https://avatars2.githubusercontent.com/u/3254314?v=4?s=60" width="60px;" alt="Mathieu Dutour"/><br /><sub><b>Mathieu Dutour</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=mathieudutour" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/presidentelect"><img src="https://avatars2.githubusercontent.com/u/1242300?v=4?s=60" width="60px;" alt="Michael Hansen"/><br /><sub><b>Michael Hansen</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=presidentelect" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://klickverbot.at/"><img src="https://avatars1.githubusercontent.com/u/19335?v=4?s=60" width="60px;" alt="David Nadlinger"/><br /><sub><b>David Nadlinger</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dnadlinger" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://pluckd.co/"><img src="https://avatars2.githubusercontent.com/u/20598571?v=4?s=60" width="60px;" alt="Fernando"/><br /><sub><b>Fernando</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MrCordeiro" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jfgonzalez7"><img src="https://avatars3.githubusercontent.com/u/58857736?v=4?s=60" width="60px;" alt="Juan Gonzalez"/><br /><sub><b>Juan Gonzalez</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jfgonzalez7" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.louiechristie.com/"><img src="https://avatars1.githubusercontent.com/u/6807448?v=4?s=60" width="60px;" alt="Louie Christie"/><br /><sub><b>Louie Christie</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=louiechristie" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://supersandro.de/"><img src="https://avatars2.githubusercontent.com/u/7258858?v=4?s=60" width="60px;" alt="Sandro"/><br /><sub><b>Sandro</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=SuperSandro2000" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Skn0tt"><img src="https://avatars1.githubusercontent.com/u/14912729?v=4?s=60" width="60px;" alt="Simon Knott"/><br /><sub><b>Simon Knott</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Skn0tt" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://styfle.dev/"><img src="https://avatars1.githubusercontent.com/u/229881?v=4?s=60" width="60px;" alt="Steven"/><br /><sub><b>Steven</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=styfle" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Georift"><img src="https://avatars2.githubusercontent.com/u/859430?v=4?s=60" width="60px;" alt="Tim"/><br /><sub><b>Tim</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Georift" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sauravkhdoolia"><img src="https://avatars1.githubusercontent.com/u/34188267?v=4?s=60" width="60px;" alt="Saurav Khdoolia"/><br /><sub><b>Saurav Khdoolia</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=sauravkhdoolia" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://anku.netlify.com/"><img src="https://avatars1.githubusercontent.com/u/22813027?v=4?s=60" width="60px;" alt="Ankit Tiwari"/><br /><sub><b>Ankit Tiwari</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=anku255" title="Documentation">📖</a> <a href="https://github.com/foambubble/foam/commits?author=anku255" title="Tests">⚠️</a> <a href="https://github.com/foambubble/foam/commits?author=anku255" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ayushbaweja"><img src="https://avatars1.githubusercontent.com/u/44344063?v=4?s=60" width="60px;" alt="Ayush Baweja"/><br /><sub><b>Ayush Baweja</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ayushbaweja" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TaiChi-IO"><img src="https://avatars3.githubusercontent.com/u/65092992?v=4?s=60" width="60px;" alt="TaiChi-IO"/><br /><sub><b>TaiChi-IO</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=TaiChi-IO" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/juanfrank77"><img src="https://avatars1.githubusercontent.com/u/12146882?v=4?s=60" width="60px;" alt="Juan F Gonzalez "/><br /><sub><b>Juan F Gonzalez </b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=juanfrank77" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://sanketdg.github.io"><img src="https://avatars3.githubusercontent.com/u/8980971?v=4?s=60" width="60px;" alt="Sanket Dasgupta"/><br /><sub><b>Sanket Dasgupta</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=SanketDG" title="Documentation">📖</a> <a href="https://github.com/foambubble/foam/commits?author=SanketDG" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nstafie"><img src="https://avatars1.githubusercontent.com/u/10801854?v=4?s=60" width="60px;" alt="Nicholas Stafie"/><br /><sub><b>Nicholas Stafie</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=nstafie" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/francishamel"><img src="https://avatars3.githubusercontent.com/u/36383308?v=4?s=60" width="60px;" alt="Francis Hamel"/><br /><sub><b>Francis Hamel</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=francishamel" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://digiguru.co.uk"><img src="https://avatars1.githubusercontent.com/u/619436?v=4?s=60" width="60px;" alt="digiguru"/><br /><sub><b>digiguru</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=digiguru" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=digiguru" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/chirag-singhal"><img src="https://avatars3.githubusercontent.com/u/42653703?v=4?s=60" width="60px;" alt="CHIRAG SINGHAL"/><br /><sub><b>CHIRAG SINGHAL</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=chirag-singhal" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lostintangent"><img src="https://avatars3.githubusercontent.com/u/116461?v=4?s=60" width="60px;" alt="Jonathan Carter"/><br /><sub><b>Jonathan Carter</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=lostintangent" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.synesthesia.co.uk"><img src="https://avatars3.githubusercontent.com/u/181399?v=4?s=60" width="60px;" alt="Julian Elve"/><br /><sub><b>Julian Elve</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=synesthesia" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/thomaskoppelaar"><img src="https://avatars3.githubusercontent.com/u/36331365?v=4?s=60" width="60px;" alt="Thomas Koppelaar"/><br /><sub><b>Thomas Koppelaar</b></sub></a><br /><a href="#question-thomaskoppelaar" title="Answering Questions">💬</a> <a href="https://github.com/foambubble/foam/commits?author=thomaskoppelaar" title="Code">💻</a> <a href="#userTesting-thomaskoppelaar" title="User Testing">📓</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.akshaymehra.com"><img src="https://avatars1.githubusercontent.com/u/8671497?v=4?s=60" width="60px;" alt="Akshay"/><br /><sub><b>Akshay</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MehraAkshay" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://johnlindquist.com"><img src="https://avatars0.githubusercontent.com/u/36073?v=4?s=60" width="60px;" alt="John Lindquist"/><br /><sub><b>John Lindquist</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=johnlindquist" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://ashwin.run/"><img src="https://avatars2.githubusercontent.com/u/1689183?v=4?s=60" width="60px;" alt="Ashwin Ramaswami"/><br /><sub><b>Ashwin Ramaswami</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=epicfaace" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Klaudioz"><img src="https://avatars1.githubusercontent.com/u/632625?v=4?s=60" width="60px;" alt="Claudio Canales"/><br /><sub><b>Claudio Canales</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Klaudioz" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vitaly-pevgonen"><img src="https://avatars0.githubusercontent.com/u/6272738?v=4?s=60" width="60px;" alt="vitaly-pevgonen"/><br /><sub><b>vitaly-pevgonen</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=vitaly-pevgonen" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dshemetov.github.io"><img src="https://avatars0.githubusercontent.com/u/1810426?v=4?s=60" width="60px;" alt="Dmitry Shemetov"/><br /><sub><b>Dmitry Shemetov</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dshemetov" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hooncp"><img src="https://avatars1.githubusercontent.com/u/48883554?v=4?s=60" width="60px;" alt="hooncp"/><br /><sub><b>hooncp</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=hooncp" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://rt-canada.ca"><img src="https://avatars1.githubusercontent.com/u/13721239?v=4?s=60" width="60px;" alt="Martin Laws"/><br /><sub><b>Martin Laws</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=martinlaws" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://seanksmith.me"><img src="https://avatars3.githubusercontent.com/u/2085441?v=4?s=60" width="60px;" alt="Sean K Smith"/><br /><sub><b>Sean K Smith</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=sksmith" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/kevin-neely/"><img src="https://avatars1.githubusercontent.com/u/37545028?v=4?s=60" width="60px;" alt="Kevin Neely"/><br /><sub><b>Kevin Neely</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=kneely" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://ariefrahmansyah.dev"><img src="https://avatars3.githubusercontent.com/u/8122852?v=4?s=60" width="60px;" alt="Arief Rahmansyah"/><br /><sub><b>Arief Rahmansyah</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ariefrahmansyah" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://vhanda.in"><img src="https://avatars2.githubusercontent.com/u/426467?v=4?s=60" width="60px;" alt="Vishesh Handa"/><br /><sub><b>Vishesh Handa</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=vHanda" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.linkedin.com/in/heroichitesh"><img src="https://avatars3.githubusercontent.com/u/37622734?v=4?s=60" width="60px;" alt="Hitesh Kumar"/><br /><sub><b>Hitesh Kumar</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=HeroicHitesh" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://spencerwoo.com"><img src="https://avatars2.githubusercontent.com/u/32114380?v=4?s=60" width="60px;" alt="Spencer Woo"/><br /><sub><b>Spencer Woo</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=spencerwooo" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://ingalless.com"><img src="https://avatars3.githubusercontent.com/u/22981941?v=4?s=60" width="60px;" alt="ingalless"/><br /><sub><b>ingalless</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ingalless" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=ingalless" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://jmg-duarte.github.io"><img src="https://avatars2.githubusercontent.com/u/15343819?v=4?s=60" width="60px;" alt="José Duarte"/><br /><sub><b>José Duarte</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jmg-duarte" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jmg-duarte" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.yenly.wtf"><img src="https://avatars1.githubusercontent.com/u/6759658?v=4?s=60" width="60px;" alt="Yenly"/><br /><sub><b>Yenly</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=yenly" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.hikerpig.cn"><img src="https://avatars1.githubusercontent.com/u/2259688?v=4?s=60" width="60px;" alt="hikerpig"/><br /><sub><b>hikerpig</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=hikerpig" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://sigfried.org"><img src="https://avatars1.githubusercontent.com/u/1586931?v=4?s=60" width="60px;" alt="Sigfried Gold"/><br /><sub><b>Sigfried Gold</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Sigfried" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.tristansokol.com"><img src="https://avatars3.githubusercontent.com/u/867661?v=4?s=60" width="60px;" alt="Tristan Sokol"/><br /><sub><b>Tristan Sokol</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=tristansokol" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://umbrellait.com"><img src="https://avatars0.githubusercontent.com/u/49779373?v=4?s=60" width="60px;" alt="Danil Rodin"/><br /><sub><b>Danil Rodin</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=umbrellait-danil-rodin" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/scottjoewilliams/"><img src="https://avatars1.githubusercontent.com/u/2026866?v=4?s=60" width="60px;" alt="Scott Williams"/><br /><sub><b>Scott Williams</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=scott-joe" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://jackiexiao.github.io/blog"><img src="https://avatars2.githubusercontent.com/u/18050469?v=4?s=60" width="60px;" alt="jackiexiao"/><br /><sub><b>jackiexiao</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Jackiexiao" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://generativist.substack.com/"><img src="https://avatars3.githubusercontent.com/u/78835?v=4?s=60" width="60px;" alt="John B Nelson"/><br /><sub><b>John B Nelson</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jbn" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/asifm"><img src="https://avatars2.githubusercontent.com/u/3958387?v=4?s=60" width="60px;" alt="Asif Mehedi"/><br /><sub><b>Asif Mehedi</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=asifm" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/litanlitudan"><img src="https://avatars2.githubusercontent.com/u/4970420?v=4?s=60" width="60px;" alt="Tan Li"/><br /><sub><b>Tan Li</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=litanlitudan" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://shaunagordon.com"><img src="https://avatars1.githubusercontent.com/u/579361?v=4?s=60" width="60px;" alt="Shauna Gordon"/><br /><sub><b>Shauna Gordon</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ShaunaGordon" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://mcluck.tech"><img src="https://avatars1.githubusercontent.com/u/1753801?v=4?s=60" width="60px;" alt="Mike Cluck"/><br /><sub><b>Mike Cluck</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MCluck90" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://brandonpugh.com"><img src="https://avatars1.githubusercontent.com/u/684781?v=4?s=60" width="60px;" alt="Brandon Pugh"/><br /><sub><b>Brandon Pugh</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=bpugh" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://max.davitt.me"><img src="https://avatars1.githubusercontent.com/u/27709025?v=4?s=60" width="60px;" alt="Max Davitt"/><br /><sub><b>Max Davitt</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=themaxdavitt" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://briananglin.me"><img src="https://avatars3.githubusercontent.com/u/2637602?v=4?s=60" width="60px;" alt="Brian Anglin"/><br /><sub><b>Brian Anglin</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=anglinb" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://deft.work"><img src="https://avatars1.githubusercontent.com/u/1455507?v=4?s=60" width="60px;" alt="elswork"/><br /><sub><b>elswork</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=elswork" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://leonh.fr/"><img src="https://avatars.githubusercontent.com/u/19996318?v=4?s=60" width="60px;" alt="léon h"/><br /><sub><b>léon h</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=leonhfr" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://nygaard.site"><img src="https://avatars.githubusercontent.com/u/4606342?v=4?s=60" width="60px;" alt="Nikhil Nygaard"/><br /><sub><b>Nikhil Nygaard</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=njnygaard" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://www.nitwit.se"><img src="https://avatars.githubusercontent.com/u/1382124?v=4?s=60" width="60px;" alt="Mark Dixon"/><br /><sub><b>Mark Dixon</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=nitwit-se" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/joeltjames"><img src="https://avatars.githubusercontent.com/u/3732400?v=4?s=60" width="60px;" alt="Joel James"/><br /><sub><b>Joel James</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=joeltjames" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.ryo33.com"><img src="https://avatars.githubusercontent.com/u/8780513?v=4?s=60" width="60px;" alt="Hashiguchi Ryo"/><br /><sub><b>Hashiguchi Ryo</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ryo33" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://movermeyer.com"><img src="https://avatars.githubusercontent.com/u/1459385?v=4?s=60" width="60px;" alt="Michael Overmeyer"/><br /><sub><b>Michael Overmeyer</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=movermeyer" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/derrickqin"><img src="https://avatars.githubusercontent.com/u/3038111?v=4?s=60" width="60px;" alt="Derrick Qin"/><br /><sub><b>Derrick Qin</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=derrickqin" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/zomars/"><img src="https://avatars.githubusercontent.com/u/3504472?v=4?s=60" width="60px;" alt="Omar López"/><br /><sub><b>Omar López</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=zomars" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://robincn.com"><img src="https://avatars.githubusercontent.com/u/1583193?v=4?s=60" width="60px;" alt="Robin King"/><br /><sub><b>Robin King</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=RobinKing" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://twitter.com/deegovee"><img src="https://avatars.githubusercontent.com/u/4730170?v=4?s=60" width="60px;" alt="Dheepak "/><br /><sub><b>Dheepak </b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dheepakg" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/daniel-vera-g"><img src="https://avatars.githubusercontent.com/u/28257108?v=4?s=60" width="60px;" alt="Daniel VG"/><br /><sub><b>Daniel VG</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=daniel-vera-g" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Barabazs"><img src="https://avatars.githubusercontent.com/u/31799121?v=4?s=60" width="60px;" alt="Barabas"/><br /><sub><b>Barabas</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Barabazs" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://enginveske@gmail.com"><img src="https://avatars.githubusercontent.com/u/43685404?v=4?s=60" width="60px;" alt="Engincan VESKE"/><br /><sub><b>Engincan VESKE</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=EngincanV" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.paulderaaij.nl"><img src="https://avatars.githubusercontent.com/u/495374?v=4?s=60" width="60px;" alt="Paul de Raaij"/><br /><sub><b>Paul de Raaij</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=pderaaij" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bronson"><img src="https://avatars.githubusercontent.com/u/1776?v=4?s=60" width="60px;" alt="Scott Bronson"/><br /><sub><b>Scott Bronson</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=bronson" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://rafaelriedel.de"><img src="https://avatars.githubusercontent.com/u/41793?v=4?s=60" width="60px;" alt="Rafael Riedel"/><br /><sub><b>Rafael Riedel</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=rafo" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Pearcekieser"><img src="https://avatars.githubusercontent.com/u/5055971?v=4?s=60" width="60px;" alt="Pearcekieser"/><br /><sub><b>Pearcekieser</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Pearcekieser" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/theowenyoung"><img src="https://avatars.githubusercontent.com/u/62473795?v=4?s=60" width="60px;" alt="Owen Young"/><br /><sub><b>Owen Young</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=theowenyoung" title="Documentation">📖</a> <a href="#content-theowenyoung" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.prashu.com"><img src="https://avatars.githubusercontent.com/u/476729?v=4?s=60" width="60px;" alt="Prashanth Subrahmanyam"/><br /><sub><b>Prashanth Subrahmanyam</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ksprashu" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/JonasSprenger"><img src="https://avatars.githubusercontent.com/u/25108895?v=4?s=60" width="60px;" alt="Jonas SPRENGER"/><br /><sub><b>Jonas SPRENGER</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=JonasSprenger" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Laptop765"><img src="https://avatars.githubusercontent.com/u/1468359?v=4?s=60" width="60px;" alt="Paul"/><br /><sub><b>Paul</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Laptop765" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=60" width="60px;" alt="Ikko Ashimine"/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=eltociear" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/memeplex"><img src="https://avatars.githubusercontent.com/u/2845433?v=4?s=60" width="60px;" alt="memeplex"/><br /><sub><b>memeplex</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=memeplex" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/AndreiD049"><img src="https://avatars.githubusercontent.com/u/52671223?v=4?s=60" width="60px;" alt="AndreiD049"/><br /><sub><b>AndreiD049</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=AndreiD049" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/iam-yan"><img src="https://avatars.githubusercontent.com/u/48427014?v=4?s=60" width="60px;" alt="Yan"/><br /><sub><b>Yan</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=iam-yan" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://WikiEducator.org/User:JimTittsler"><img src="https://avatars.githubusercontent.com/u/180326?v=4?s=60" width="60px;" alt="Jim Tittsler"/><br /><sub><b>Jim Tittsler</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jimt" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://malcolmmielle.wordpress.com/"><img src="https://avatars.githubusercontent.com/u/4457840?v=4?s=60" width="60px;" alt="Malcolm Mielle"/><br /><sub><b>Malcolm Mielle</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MalcolmMielle" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://snippets.page/"><img src="https://avatars.githubusercontent.com/u/74916913?v=4?s=60" width="60px;" alt="Veesar"/><br /><sub><b>Veesar</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=veesar" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bentongxyz"><img src="https://avatars.githubusercontent.com/u/60358804?v=4?s=60" width="60px;" alt="bentongxyz"/><br /><sub><b>bentongxyz</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=bentongxyz" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://brianjdevries.com"><img src="https://avatars.githubusercontent.com/u/42778030?v=4?s=60" width="60px;" alt="Brian DeVries"/><br /><sub><b>Brian DeVries</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=techCarpenter" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://Cliffordfajardo.com"><img src="https://avatars.githubusercontent.com/u/6743796?v=4?s=60" width="60px;" alt="Clifford Fajardo "/><br /><sub><b>Clifford Fajardo </b></sub></a><br /><a href="#tool-cliffordfajardo" title="Tools">🔧</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://cu-dev.ca"><img src="https://avatars.githubusercontent.com/u/6589365?v=4?s=60" width="60px;" alt="Chris Usick"/><br /><sub><b>Chris Usick</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=chrisUsick" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/josephdecock"><img src="https://avatars.githubusercontent.com/u/1145533?v=4?s=60" width="60px;" alt="Joe DeCock"/><br /><sub><b>Joe DeCock</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=josephdecock" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.drewtyler.com"><img src="https://avatars.githubusercontent.com/u/5640816?v=4?s=60" width="60px;" alt="Drew Tyler"/><br /><sub><b>Drew Tyler</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=drewtyler" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Lauviah0622"><img src="https://avatars.githubusercontent.com/u/43416399?v=4?s=60" width="60px;" alt="Lauviah0622"/><br /><sub><b>Lauviah0622</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Lauviah0622" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.elastic.co/elastic-agent"><img src="https://avatars.githubusercontent.com/u/1813008?v=4?s=60" width="60px;" alt="Josh Dover"/><br /><sub><b>Josh Dover</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=joshdover" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://phelm.co.uk"><img src="https://avatars.githubusercontent.com/u/4057948?v=4?s=60" width="60px;" alt="Phil Helm"/><br /><sub><b>Phil Helm</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=phelma" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lingyv-li"><img src="https://avatars.githubusercontent.com/u/8937944?v=4?s=60" width="60px;" alt="Larry Li"/><br /><sub><b>Larry Li</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=lingyv-li" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/infogulch"><img src="https://avatars.githubusercontent.com/u/133882?v=4?s=60" width="60px;" alt="Joe Taber"/><br /><sub><b>Joe Taber</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=infogulch" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.readingsnail.pe.kr"><img src="https://avatars.githubusercontent.com/u/1904967?v=4?s=60" width="60px;" alt="Woosuk Park"/><br /><sub><b>Woosuk Park</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=readingsnail" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.dmurph.com"><img src="https://avatars.githubusercontent.com/u/294026?v=4?s=60" width="60px;" alt="Daniel Murphy"/><br /><sub><b>Daniel Murphy</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dmurph" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Dominic-DallOsto"><img src="https://avatars.githubusercontent.com/u/26859884?v=4?s=60" width="60px;" alt="Dominic D"/><br /><sub><b>Dominic D</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Dominic-DallOsto" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://elgirafo.xyz"><img src="https://avatars.githubusercontent.com/u/80516439?v=4?s=60" width="60px;" alt="luca"/><br /><sub><b>luca</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=elgirafo" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Lloyd-Jackman-UKPL"><img src="https://avatars.githubusercontent.com/u/55206370?v=4?s=60" width="60px;" alt="Lloyd Jackman"/><br /><sub><b>Lloyd Jackman</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Lloyd-Jackman-UKPL" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://sn3akiwhizper.github.io"><img src="https://avatars.githubusercontent.com/u/102705294?v=4?s=60" width="60px;" alt="sn3akiwhizper"/><br /><sub><b>sn3akiwhizper</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=sn3akiwhizper" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://jonathanpberger.com/"><img src="https://avatars.githubusercontent.com/u/41085?v=4?s=60" width="60px;" alt="jonathan berger"/><br /><sub><b>jonathan berger</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jonathanpberger" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/badsketch"><img src="https://avatars.githubusercontent.com/u/8953212?v=4?s=60" width="60px;" alt="Daniel Wang"/><br /><sub><b>Daniel Wang</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=badsketch" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://yongliangliu.com"><img src="https://avatars.githubusercontent.com/u/41845017?v=4?s=60" width="60px;" alt="Liu YongLiang"/><br /><sub><b>Liu YongLiang</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=tlylt" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://scottakerman.com"><img src="https://avatars.githubusercontent.com/u/15224439?v=4?s=60" width="60px;" alt="Scott Akerman"/><br /><sub><b>Scott Akerman</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Skakerman" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.jim-graham.net/"><img src="https://avatars.githubusercontent.com/u/430293?v=4?s=60" width="60px;" alt="Jim Graham"/><br /><sub><b>Jim Graham</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jimgraham" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://t.me/littlepoint"><img src="https://avatars.githubusercontent.com/u/7611700?v=4?s=60" width="60px;" alt="Zhizhen He"/><br /><sub><b>Zhizhen He</b></sub></a><br /><a href="#tool-hezhizhen" title="Tools">🔧</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://amnesiak.org/me"><img src="https://avatars.githubusercontent.com/u/952059?v=4?s=60" width="60px;" alt="Tony Cheneau"/><br /><sub><b>Tony Cheneau</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=tcheneau" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nicholas-l"><img src="https://avatars.githubusercontent.com/u/12977174?v=4?s=60" width="60px;" alt="Nicholas Latham"/><br /><sub><b>Nicholas Latham</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=nicholas-l" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://thara.dev"><img src="https://avatars.githubusercontent.com/u/1532891?v=4?s=60" width="60px;" alt="Tomochika Hara"/><br /><sub><b>Tomochika Hara</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=thara" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dcarosone"><img src="https://avatars.githubusercontent.com/u/11495017?v=4?s=60" width="60px;" alt="Daniel Carosone"/><br /><sub><b>Daniel Carosone</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dcarosone" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MABruni"><img src="https://avatars.githubusercontent.com/u/100445384?v=4?s=60" width="60px;" alt="Miguel Angel Bruni Montero"/><br /><sub><b>Miguel Angel Bruni Montero</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MABruni" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Walshkev"><img src="https://avatars.githubusercontent.com/u/77123083?v=4?s=60" width="60px;" alt="Kevin Walsh "/><br /><sub><b>Kevin Walsh </b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Walshkev" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://hereistheusername.github.io/"><img src="https://avatars.githubusercontent.com/u/33437051?v=4?s=60" width="60px;" alt="Xinglan Liu"/><br /><sub><b>Xinglan Liu</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=hereistheusername" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://www.hegghammer.com"><img src="https://avatars.githubusercontent.com/u/64712218?v=4?s=60" width="60px;" alt="Thomas Hegghammer"/><br /><sub><b>Thomas Hegghammer</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Hegghammer" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PiotrAleksander"><img src="https://avatars.githubusercontent.com/u/6314591?v=4?s=60" width="60px;" alt="Piotr Mrzygłosz"/><br /><sub><b>Piotr Mrzygłosz</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=PiotrAleksander" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://schaver.com/"><img src="https://avatars.githubusercontent.com/u/7584?v=4?s=60" width="60px;" alt="Mark Schaver"/><br /><sub><b>Mark Schaver</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=markschaver" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/n8layman"><img src="https://avatars.githubusercontent.com/u/25353944?v=4?s=60" width="60px;" alt="Nathan Layman"/><br /><sub><b>Nathan Layman</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=n8layman" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/emmanuel-ferdman"><img src="https://avatars.githubusercontent.com/u/35470921?v=4?s=60" width="60px;" alt="Emmanuel Ferdman"/><br /><sub><b>Emmanuel Ferdman</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=emmanuel-ferdman" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Tenormis"><img src="https://avatars.githubusercontent.com/u/61572102?v=4?s=60" width="60px;" alt="Tenormis"/><br /><sub><b>Tenormis</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Tenormis" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://djon.es/blog"><img src="https://avatars.githubusercontent.com/u/225052?v=4?s=60" width="60px;" alt="David Jones"/><br /><sub><b>David Jones</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=djplaner" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/s-jacob-powell"><img src="https://avatars.githubusercontent.com/u/109111499?v=4?s=60" width="60px;" alt="S. Jacob Powell"/><br /><sub><b>S. Jacob Powell</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=s-jacob-powell" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/figdavi"><img src="https://avatars.githubusercontent.com/u/99026991?v=4?s=60" width="60px;" alt="Davi Figueiredo"/><br /><sub><b>Davi Figueiredo</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=figdavi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ChThH"><img src="https://avatars.githubusercontent.com/u/9499483?v=4?s=60" width="60px;" alt="CT Hall"/><br /><sub><b>CT Hall</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ChThH" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/meestahp"><img src="https://avatars.githubusercontent.com/u/177708514?v=4?s=60" width="60px;" alt="meestahp"/><br /><sub><b>meestahp</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=meestahp" title="Code">💻</a></td>
</tr>
</tbody>
</table>
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
Foam was inspired by [Roam Research](https://roamresearch.com/) and [Zettelkasten methodology](https://zettelkasten.de/posts/overview).
Foam builds on [Visual Studio Code](https://code.visualstudio.com/), [GitHub](https://github.com/), and our [[recommended-extensions]].
## License
Foam is licensed under the [MIT license](LICENSE.txt).
[recommended-extensions]: user/getting-started/recommended-extensions.md 'Recommended Extensions'
[recipes]: user/recipes/recipes.md 'Recipes'
[frequently-asked-questions]: user/frequently-asked-questions.md 'Frequently Asked Questions'
[principles]: principles.md 'Principles'
[contribution-guide]: dev/contribution-guide.md 'Contribution Guide'
================================================
FILE: docs/principles.md
================================================
# Principles
## Table of Contents
- [Principles](#principles)
- [Table of Contents](#table-of-contents)
- [Foam enables you to do your best thinking](#foam-enables-you-to-do-your-best-thinking)
- [Foam wants you to own your thoughts](#foam-wants-you-to-own-your-thoughts)
- [Foam helps you share your thoughts with the world.](#foam-helps-you-share-your-thoughts-with-the-world)
- [Foam allows people to collaborate in discovering better ways to work, together.](#foam-allows-people-to-collaborate-in-discovering-better-ways-to-work-together)
- [Foam is for hackers, not only for programmers](#foam-is-for-hackers-not-only-for-programmers)
## Foam enables you to do your best thinking
- **Foam works for you, you don't work for Foam.** You should be able to focus on your work and not fight against Foam, or having to perform fiddly operations or maintenance jobs to keep Foam happy.
- **Foam is not a package deal.** You must be able to adopt only the parts of Foam that you want. There must be no tight coupling between Foam's features.
- **Foam is a starting point** You must be able to customise how foam looks and feels, and combine it with other tools you find helpful in your personal workflow.
- **Foam is not a philosophy.** Whether you use a methodology like Zettelkasten is up to you. **You should be able to use Foam without joining a cult.**
## Foam wants you to own your thoughts
- **Foam doesn't want your data.** You can store your documents wherever you want. Some of Foam's suggested workflows include GitHub, if you don't want to use it to store your data, or you want to stop using it in the future, you should be able to migrate to alternative storage options. If you choose to not upload your notes to any cloud service or remote repository, remember to keep frequent local and occasional offsite backups of your data!
- **Foam should not lock you in.** Foam's content files, structure and metadata should be in interoperable format that supports migrating it to another tool if you prefer to. Users of Foam should be able to develop and share such tools freely.
- **Foam should not leak your secrets.** Nobody, including the developers of Foam, should have access to your personal knowledge graph unless you choose to give it to them. Foams should always be private by default, but [easy to share](#foam-helps-you-share-your-thoughts-with-the-world) if you choose to.
## Foam helps you share your thoughts with the world.
This principle may seem like it contradicts [Foam wants you to own your thoughts](#foam-wants-you-to-own-your-thoughts), but it's actually a compatible corollary. You should be able to do both, because:
> [...] environments that build walls around good ideas tend to be less innovative in the long run than more open-ended environments. Good ideas may not want to be free, but they do want to connect, fuse, recombine. —_Steven Johnson, Where Good Ideas Come From_
- **Foam should make it easy to publish your knowledge graph.** With zero code, you should be able to make your graph public to the world. You should have full control over how it looks, feels, and where it's hosted.
- **Foam should make it easy to collaborate on ideas.** Foam should allow you to work closely together with your collaborators, and accept feedback, input and improvements from others.
- **Foam should make it easy to publish what you choose.** Foam should double as a low-barrier blog/publishing platform, so you can share content to an audience without inviting them to intrude on your entire workspace.
## Foam allows people to collaborate in discovering better ways to work, together.
- **Foam is a collection of ideas.** Foam was released to the public not to share the few good ideas in it, but to learn many good ideas from others. As you improve your own workflow, share your work on your own Foam blog.
- **Foam is open for contributions.** If you use a tool or workflow that you like that fits these principles, please contribute them back to the Foam template as [[recipes]], [[recommended-extensions]] or documentation in [this workspace](https://github.com/foambubble/foam). See also: [[contribution-guide]].
- **Foam is open source.** Feel free to fork it, improve it and remix it. Just don't sell it, as per our [license](LICENSE.txt).
- **Foam is not Roam.** This project was inspired by Roam Research, but we're not limited by what Roam does. No idea is too big (though if it doesn't fit with Foam's core workflow, we might make it a [[recipes]] page instead).
## Foam is for hackers, not only for programmers
While Foam uses tools popular among computer programmers, Foam should be inclusive of everyone who wants to improve their own workflow to improve themselves.
- **Foam embraces the hacker mindset.** The target audience for Foam are people who look for creative ways to improve their ability to collect and organise information.
- **Foam is not just for programmers.** If you're a programmer, feel free to write scripts and extensions to support your own workflow, and publish them for others to use, but the out of the box Foam experience should not require you to know how to do so. You should, however, be curious and open to adopting new tools that are unfamiliar to you, and evaluate whether they could work for you.
- **Foam is for everyone** As a foam user, you support everyone's quest for knowledge and self-improvement, not only your own, or folks' who look like you. All participants in Foam repositories, discussion forums, physical and virtual meeting spaces etc are expected to respect each other as described in our [[code-of-conduct]]. **Foam is not for toxic tech bros.**
[//begin]: # "Autogenerated link references for markdown compatibility"
[recipes]: user/recipes/recipes.md "Recipes"
[recommended-extensions]: user/getting-started/recommended-extensions.md "Recommended Extensions"
[contribution-guide]: dev/contribution-guide.md "Contribution Guide"
[code-of-conduct]: dev/code-of-conduct.md "Code of Conduct"
[//end]: # "Autogenerated link references"
================================================
FILE: docs/user/features/backlinking.md
================================================
# Backlinks
Backlinks are one of Foam's most powerful features for knowledge discovery. They automatically show you which notes reference your current note, creating a web of interconnected knowledge that reveals surprising relationships between your ideas.
_[📹 Watch: Understanding and using backlinks in Foam]_
## What Are Backlinks?
A backlink is a connection from another note that points to the note you're currently viewing. While you create forward links intentionally with `[[wikilinks]]`, backlinks are discovered automatically by Foam.
### Forward Links vs. Backlinks
**Forward Links** (what you create):
```markdown
# Machine Learning Note
I'm studying [[Neural Networks]] and [[Deep Learning]] concepts.
```
**Backlinks** (what Foam discovers):
If you're viewing the "Neural Networks" note, Foam shows you that "Machine Learning Note" links to it, even though you didn't explicitly create that reverse connection.
This bidirectional linking creates a richer knowledge network than traditional hierarchical folders.
## Accessing Backlinks - Connections Panel
The Connections panel shows both forward links and backlinks:
1. **Open Command Palette** (`Ctrl+Shift+P` / `Cmd+Shift+P`)
2. **Type "connections"** and select "Explorer: Focus on Connections"
3. **Use the filter buttons** to show only backlinks, forward links, or all connections
_[📹 Watch: Finding and opening the backlinks panel]_
## Using Backlinks for Knowledge Discovery
### 1. Finding Unexpected Connections
Backlinks often reveal relationships you didn't consciously create:
**Example:** While reviewing a "Productivity" note, backlinks might show connections from:
- A cooking recipe (time management for meal prep)
- A fitness routine (efficient workout planning)
- A work project (team productivity strategies)
These diverse connections can spark new insights and cross-domain learning.
### 2. Identifying Important Concepts
Notes with many backlinks are often central to your thinking:
- **Hub concepts** that connect many ideas
- **Frequently referenced** resources or definitions
- **Bridge topics** that span multiple domains
### 3. Building Context Around Ideas
Backlinks provide context for how you use concepts across different areas:
- How you apply the same principle in various projects
- Evolution of your thinking about a topic over time
- Different perspectives you've encountered on the same idea
_[📹 Watch: Using backlinks for knowledge discovery and research]_
================================================
FILE: docs/user/features/block-anchors.md
================================================
# Block Anchors
Block anchors let you link to a specific paragraph, list item, heading, or blockquote within a note — not just to the note as a whole or to a section heading.
## Adding a Block Anchor
Place `^your-id` at the end of any block element. The ID can contain letters, numbers, and hyphens.
The `^id` marker is hidden in the preview — it's metadata, not visible text.
### Paragraph
```markdown
This is an important finding from the experiment. ^key-finding
```
Multi-line paragraphs work too — put the anchor at the end of the last line:
```markdown
The first measurements were inconclusive.
After repeating the experiment, results became clear. ^experiment-result
```
### List item
Place the anchor at the end of the item text. Foam anchors the entire item, including any sub-items:
```markdown
- Mix dry ingredients thoroughly ^dry-step
- 2 cups flour
- 1 tsp salt
- Add wet ingredients ^wet-step
```
To anchor an entire list, place `^id` on its own line immediately after the last item (no blank line):
```markdown
- First item
- Second item
- Third item
^shopping-list
```
### Heading
```markdown
## Methodology ^methodology
```
The anchor applies to the heading line itself, not the entire section below it.
### Blockquote
Three placements are supported:
**As the last line inside the blockquote:**
```markdown
> The only way to do great work is to love what you do.
> ^jobs-quote
```
**On its own line immediately after the blockquote:**
```markdown
> We shall fight on the beaches,
> we shall fight on the landing grounds.
^churchill-beaches
```
**After the blockquote with a blank line** (useful if your markdown formatter inserts one):
```markdown
> We shall fight on the beaches,
> we shall fight on the landing grounds.
^churchill-beaches
```
### Code block
Place `^id` on its own line after the closing fence. One blank line between the fence and `^id` is also accepted (useful if your markdown formatter adds one automatically):
````markdown
```python
def greet(name):
return f"Hello, {name}"
```
^greet-function
````
### Table
Place `^id` on its own line after the table. One blank line is also accepted:
```markdown
| Name | Score |
| ----- | ----- |
| Alice | 95 |
| Bob | 87 |
^results-table
```
## Linking to a Block
Use `[[note-name#^blockid]]` to link directly to a block:
```markdown
[[research-notes#^key-insight]]
[[research-notes#^list-ref]]
```
Foam provides autocomplete for block IDs when you type `#^` inside a wikilink.
You can also add display text:
```markdown
[[research-notes#^key-insight|See the key insight]]
```
## Embedding a Block
Use `![[note-name#^blockid]]` to embed just that block inline:
```markdown
![[research-notes#^key-insight]]
```
Only the referenced block's content is shown — not the entire note.
## Renaming a Block ID
Place your cursor on a `^blockid` anchor and press `F2` to rename it. Foam updates the anchor and all wikilinks that reference it across your workspace.
## Diagnostics
Foam warns you when a block link points to a `^id` that doesn't exist in the target note. A quick-fix lets you pick from the available block IDs.
If you accidentally use the same `^id` twice in one file, Foam flags the duplicate with a warning. A quick-fix replaces it with a freshly generated unique ID.
## Related
- [[wikilinks]] - General linking
- [[embeds]] - Embedding notes and blocks
================================================
FILE: docs/user/features/commands.md
================================================
# 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 customizable and can help with custom workflows and use cases.
## foam-vscode.create-note command
This command creates a note.
Although it works fine on its own, it can be customized to achieve various use cases.
Here are the settings available for the command:
- `notePath`: The path of the note to create. If relative it will be resolved against the workspace root.
- `templatePath`: The path of the template to use. If relative it will be resolved against the workspace root.
- `title`: The title of the note (that is, the `FOAM_TITLE` variable)
- `text`: The text to use for the note. If also a template is provided, the template has precedence
- `variables`: Variables to use in the text or template
- `date`: The date used to resolve the FOAM*DATE*\* variables. in `YYYY-MM-DD` format
- `onFileExists?: 'overwrite' | 'open' | 'ask' | 'cancel'`: What to do in case the target file already exists
To customize a command and associate a key binding to it, open the key binding settings and add the appropriate configuration, here are some examples:
- Create a note called `test note.md` with some text. If the note already exists, ask for a new name
```
{
"key": "alt+f",
"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"
}
}
```
## foam-vscode.open-resource command
This command opens a resource.
Normally it receives a `URI`, which identifies the resource to open.
It is also possible to pass in a filter, which will be run against the workspace resources to find one or more matches.
- If there is one match, it will be opened
- If there is more than one match, a quick pick will show up allowing the user to select the desired resource
Examples:
```
{
"key": "alt+f",
"command": "foam-vscode.open-resource",
"args": {
"filter": {
"title": "Weekly Note*"
}
}
}
```
## Link Conversion Commands
Foam provides commands to convert between wikilink and markdown link formats.
### foam-vscode.convert-wikilink-to-mdlink
Converts a wikilink at the cursor position to markdown link format with a relative path.
Example: `[[my-note]]` → `[My Note](../path/to/my-note.md)`
### foam-vscode.convert-mdlink-to-wikilink
Converts a markdown link at the cursor position to wikilink format.
Example: `[My Note](../path/to/my-note.md)` → `[[my-note]]`
**Usage:**
1. Place your cursor inside a wikilink or markdown link
2. Open the command palette (`Ctrl+S
gitextract_3csvcwq2/ ├── .all-contributorsrc ├── .claude/ │ └── commands/ │ ├── prepare-pr.md │ └── research-issue.md ├── .devcontainer/ │ └── devcontainer.json ├── .editorconfig ├── .eslintrc.json ├── .gitattributes ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.yml │ │ ├── config.yml │ │ └── feature_request.yml │ └── workflows/ │ ├── ci.yml │ └── update-docs.yml ├── .gitignore ├── .husky/ │ └── pre-push ├── .vscode/ │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── .yarnrc ├── CLAUDE.md ├── LICENSE ├── docs/ │ ├── .vscode/ │ │ ├── custom-tag-style.css │ │ ├── extensions.json │ │ ├── keybindings.json │ │ └── settings.json │ ├── 404.md │ ├── CNAME │ ├── Gemfile │ ├── LICENSE.txt │ ├── _config.yml │ ├── _layouts/ │ │ ├── foam.html │ │ ├── home.html │ │ ├── mathjax.html │ │ └── page.html │ ├── assets/ │ │ └── css/ │ │ └── style.scss │ ├── dev/ │ │ ├── about-docs.md │ │ ├── build-vs-assemble.md │ │ ├── code-of-conduct.md │ │ ├── contribution-guide.md │ │ ├── devcontainers.md │ │ ├── foam-file-format.md │ │ ├── good-first-task.md │ │ ├── mdx-by-default.md │ │ ├── proposals/ │ │ │ ├── foam-core.md │ │ │ ├── inclusion-of-notes.md │ │ │ ├── link-reference-definition-improvements.md │ │ │ ├── materialized-backlinks.md │ │ │ ├── roadmap.md │ │ │ └── wikilinks-in-foam.md │ │ ├── publishing-permissions.md │ │ ├── releasing-foam.md │ │ ├── testing.md │ │ ├── todo.md │ │ └── unlinked-references.md │ ├── inbox.md │ ├── index.md │ ├── principles.md │ └── user/ │ ├── features/ │ │ ├── backlinking.md │ │ ├── block-anchors.md │ │ ├── commands.md │ │ ├── custom-markdown-preview-styles.md │ │ ├── custom-snippets.md │ │ ├── daily-notes.md │ │ ├── embeds.md │ │ ├── foam-queries.md │ │ ├── graph-view.md │ │ ├── link-reference-definitions.md │ │ ├── note-properties.md │ │ ├── paste-images-from-clipboard.md │ │ ├── resource-filters.md │ │ ├── spell-checking.md │ │ ├── tags.md │ │ ├── templates.md │ │ └── wikilinks.md │ ├── frequently-asked-questions.md │ ├── getting-started/ │ │ ├── first-workspace.md │ │ ├── get-started-with-vscode.md │ │ ├── installation.md │ │ ├── keyboard-shortcuts.md │ │ ├── navigation.md │ │ ├── note-taking-in-foam.md │ │ ├── recommended-extensions.md │ │ └── sync-notes.md │ ├── index.md │ ├── publishing/ │ │ ├── generate-gatsby-site.md │ │ ├── math-support-with-katex.md │ │ ├── math-support-with-mathjax.md │ │ ├── publish-to-azure-devops-wiki.md │ │ ├── publish-to-github-pages.md │ │ ├── publish-to-github.md │ │ ├── publish-to-gitlab-pages.md │ │ ├── publish-to-netlify-with-eleventy.md │ │ ├── publish-to-vercel.md │ │ └── publishing.md │ ├── recipes/ │ │ ├── add-images-to-notes.md │ │ ├── automatic-git-syncing.md │ │ ├── automatically-expand-urls-to-well-titled-links.md │ │ ├── capture-notes-with-drafts-pro.md │ │ ├── capture-notes-with-shortcuts-and-github-actions.md │ │ ├── diagrams-in-markdown.md │ │ ├── export-to-pdf.md │ │ ├── generate-material-for-mkdocs-site.md │ │ ├── how-to-write-recipes.md │ │ ├── markup-converter.md │ │ ├── migrating-from-obsidian.md │ │ ├── migrating-from-onenote.md │ │ ├── migrating-from-roam.md │ │ ├── predefined-user-snippets.md │ │ ├── real-time-collaboration.md │ │ ├── recipes.md │ │ ├── search-for-notes.md │ │ ├── shows-image-preview-on-hover.md │ │ ├── take-notes-from-mobile-phone.md │ │ ├── web-clipper.md │ │ └── write-your-notes-in-github-gist.md │ └── tools/ │ ├── cli.md │ ├── foam-logging-in-vscode.md │ ├── orphans.md │ └── workspace-janitor.md ├── lerna.json ├── package.json ├── packages/ │ └── foam-vscode/ │ ├── .vscodeignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── __mocks__/ │ │ └── vscode.ts │ ├── esbuild.js │ ├── jest.config.js │ ├── package.json │ ├── src/ │ │ ├── ai/ │ │ │ ├── model/ │ │ │ │ ├── embedding-cache.ts │ │ │ │ ├── embeddings.test.ts │ │ │ │ ├── embeddings.ts │ │ │ │ └── in-memory-embedding-cache.ts │ │ │ ├── providers/ │ │ │ │ └── ollama/ │ │ │ │ ├── ollama-provider.test.ts │ │ │ │ └── ollama-provider.ts │ │ │ ├── services/ │ │ │ │ ├── embedding-provider.ts │ │ │ │ └── noop-embedding-provider.ts │ │ │ └── vscode/ │ │ │ ├── commands/ │ │ │ │ ├── build-embeddings.spec.ts │ │ │ │ ├── build-embeddings.ts │ │ │ │ └── show-similar-notes.ts │ │ │ └── panels/ │ │ │ └── related-notes.ts │ │ ├── core/ │ │ │ ├── .eslintrc.json │ │ │ ├── common/ │ │ │ │ ├── cancellation.ts │ │ │ │ ├── charCode.ts │ │ │ │ ├── errors.ts │ │ │ │ ├── event.ts │ │ │ │ ├── functional.ts │ │ │ │ ├── iterator.ts │ │ │ │ ├── lifecycle.ts │ │ │ │ ├── linkedList.ts │ │ │ │ ├── platform.ts │ │ │ │ ├── snippetParser.test.ts │ │ │ │ └── snippetParser.ts │ │ │ ├── janitor/ │ │ │ │ ├── convert-links-format.test.ts │ │ │ │ ├── convert-links-format.ts │ │ │ │ ├── generate-headings.test.ts │ │ │ │ ├── generate-headings.ts │ │ │ │ ├── generate-link-references.test.ts │ │ │ │ ├── generate-link-references.ts │ │ │ │ └── index.ts │ │ │ ├── model/ │ │ │ │ ├── foam.ts │ │ │ │ ├── graph.test.ts │ │ │ │ ├── graph.ts │ │ │ │ ├── location.ts │ │ │ │ ├── note.test.ts │ │ │ │ ├── note.ts │ │ │ │ ├── position.ts │ │ │ │ ├── provider.ts │ │ │ │ ├── range.ts │ │ │ │ ├── tags.test.ts │ │ │ │ ├── tags.ts │ │ │ │ ├── uri.test.ts │ │ │ │ ├── uri.ts │ │ │ │ ├── workspace.test.ts │ │ │ │ └── workspace.ts │ │ │ ├── query/ │ │ │ │ ├── dql.ts │ │ │ │ ├── html.ts │ │ │ │ ├── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ └── js.ts │ │ │ ├── services/ │ │ │ │ ├── attachment-provider.ts │ │ │ │ ├── datastore.test.ts │ │ │ │ ├── datastore.ts │ │ │ │ ├── heading-edit.test.ts │ │ │ │ ├── heading-edit.ts │ │ │ │ ├── markdown-link.test.ts │ │ │ │ ├── markdown-link.ts │ │ │ │ ├── markdown-parser.test.ts │ │ │ │ ├── markdown-parser.ts │ │ │ │ ├── markdown-provider.test.ts │ │ │ │ ├── markdown-provider.ts │ │ │ │ ├── progress.ts │ │ │ │ ├── tag-edit.test.ts │ │ │ │ ├── tag-edit.ts │ │ │ │ ├── text-edit.test.ts │ │ │ │ └── text-edit.ts │ │ │ └── utils/ │ │ │ ├── cache.ts │ │ │ ├── core.ts │ │ │ ├── hashtags.ts │ │ │ ├── index.ts │ │ │ ├── log.ts │ │ │ ├── md.test.ts │ │ │ ├── md.ts │ │ │ ├── path.test.ts │ │ │ ├── path.ts │ │ │ ├── slug.ts │ │ │ ├── task-deduplicator.test.ts │ │ │ ├── task-deduplicator.ts │ │ │ └── utils.test.ts │ │ ├── dated-notes.spec.ts │ │ ├── dated-notes.ts │ │ ├── extension.ts │ │ ├── features/ │ │ │ ├── block-rename-provider.spec.ts │ │ │ ├── block-rename-provider.ts │ │ │ ├── commands/ │ │ │ │ ├── convert-links.spec.ts │ │ │ │ ├── convert-links.test.ts │ │ │ │ ├── convert-links.ts │ │ │ │ ├── copy-without-brackets.spec.ts │ │ │ │ ├── copy-without-brackets.ts │ │ │ │ ├── create-new-template.ts │ │ │ │ ├── create-note-from-template.spec.ts │ │ │ │ ├── create-note-from-template.ts │ │ │ │ ├── create-note.spec.ts │ │ │ │ ├── create-note.ts │ │ │ │ ├── index.ts │ │ │ │ ├── janitor.ts │ │ │ │ ├── open-daily-note-for-date.spec.ts │ │ │ │ ├── open-daily-note-for-date.ts │ │ │ │ ├── open-daily-note.ts │ │ │ │ ├── open-dated-note.ts │ │ │ │ ├── open-random-note.ts │ │ │ │ ├── open-resource.spec.ts │ │ │ │ ├── open-resource.ts │ │ │ │ ├── rename-tag.ts │ │ │ │ ├── search-tag.spec.ts │ │ │ │ ├── search-tag.ts │ │ │ │ ├── update-graph.ts │ │ │ │ └── update-wikilinks.ts │ │ │ ├── date-snippets.ts │ │ │ ├── document-decorator.spec.ts │ │ │ ├── document-decorator.ts │ │ │ ├── heading-rename-provider.spec.ts │ │ │ ├── heading-rename-provider.ts │ │ │ ├── hover-provider.spec.ts │ │ │ ├── hover-provider.ts │ │ │ ├── index.ts │ │ │ ├── link-completion.spec.ts │ │ │ ├── link-completion.ts │ │ │ ├── navigation-provider.spec.ts │ │ │ ├── navigation-provider.ts │ │ │ ├── panels/ │ │ │ │ ├── connections.spec.ts │ │ │ │ ├── connections.ts │ │ │ │ ├── dataviz/ │ │ │ │ │ └── index.ts │ │ │ │ ├── dataviz.spec.ts │ │ │ │ ├── dataviz.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── notes-explorer.ts │ │ │ │ ├── orphans.ts │ │ │ │ ├── placeholders.ts │ │ │ │ ├── tags-explorer.spec.ts │ │ │ │ ├── tags-explorer.ts │ │ │ │ └── utils/ │ │ │ │ ├── base-tree-provider.ts │ │ │ │ ├── folder-tree-provider.ts │ │ │ │ ├── grouped-resources-tree-data-provider.spec.ts │ │ │ │ ├── grouped-resources-tree-data-provider.ts │ │ │ │ └── tree-view-utils.ts │ │ │ ├── preview/ │ │ │ │ ├── block-anchor-ids.test.ts │ │ │ │ ├── block-anchor-ids.ts │ │ │ │ ├── escape-wikilink-pipes.test.ts │ │ │ │ ├── escape-wikilink-pipes.ts │ │ │ │ ├── foam-query-renderer.test.ts │ │ │ │ ├── foam-query-renderer.ts │ │ │ │ ├── index.ts │ │ │ │ ├── remove-wikilink-references.ts │ │ │ │ ├── tag-highlight.spec.ts │ │ │ │ ├── tag-highlight.ts │ │ │ │ ├── wikilink-embed-web-extension.ts │ │ │ │ ├── wikilink-embed.spec.ts │ │ │ │ ├── wikilink-embed.test.ts │ │ │ │ ├── wikilink-embed.ts │ │ │ │ ├── wikilink-navigation.spec.ts │ │ │ │ └── wikilink-navigation.ts │ │ │ ├── refactor.spec.ts │ │ │ ├── refactor.test.ts │ │ │ ├── refactor.ts │ │ │ ├── tag-completion.spec.ts │ │ │ ├── tag-completion.ts │ │ │ ├── tag-rename-provider.ts │ │ │ ├── wikilink-diagnostics.spec.ts │ │ │ ├── wikilink-diagnostics.ts │ │ │ ├── workspace-symbol-provider.spec.ts │ │ │ ├── workspace-symbol-provider.test.ts │ │ │ └── workspace-symbol-provider.ts │ │ ├── services/ │ │ │ ├── cache.ts │ │ │ ├── config.ts │ │ │ ├── editor.spec.ts │ │ │ ├── editor.ts │ │ │ ├── errors.ts │ │ │ ├── js-template-loader.ts │ │ │ ├── js-template-sandbox.ts │ │ │ ├── logging.ts │ │ │ ├── note-creation-engine.test.ts │ │ │ ├── note-creation-engine.ts │ │ │ ├── note-creation-triggers.ts │ │ │ ├── note-creation-types.ts │ │ │ ├── template-loader.spec.ts │ │ │ ├── template-loader.ts │ │ │ ├── templates.spec.ts │ │ │ ├── templates.ts │ │ │ ├── variable-resolver.spec.ts │ │ │ ├── variable-resolver.ts │ │ │ └── watcher.ts │ │ ├── settings.spec.ts │ │ ├── settings.ts │ │ ├── test/ │ │ │ ├── run-tests.ts │ │ │ ├── suite-unit.ts │ │ │ ├── suite.ts │ │ │ ├── support/ │ │ │ │ ├── jest-setup-after-env.ts │ │ │ │ ├── jest-setup-e2e.ts │ │ │ │ ├── jest-setup.ts │ │ │ │ └── vscode-environment.js │ │ │ ├── test-datastore.test.ts │ │ │ ├── test-datastore.ts │ │ │ ├── test-utils-vscode.ts │ │ │ ├── test-utils.ts │ │ │ ├── vscode-mock-extensions.test.ts │ │ │ └── vscode-mock.ts │ │ ├── types.d.ts │ │ └── utils/ │ │ ├── commands.ts │ │ ├── globExpand.test.ts │ │ ├── globExpand.ts │ │ ├── template-frontmatter-parser.test.ts │ │ ├── template-frontmatter-parser.ts │ │ ├── vsc-utils.spec.ts │ │ └── vsc-utils.ts │ ├── static/ │ │ └── preview/ │ │ ├── block-anchor-scroll.js │ │ └── style.css │ ├── syntaxes/ │ │ └── injection.json │ ├── test-data/ │ │ ├── __migration__/ │ │ │ ├── Roam Document.md │ │ │ └── Second Roam Document.md │ │ ├── __scaffold__/ │ │ │ ├── Note being referred as angel.md │ │ │ ├── angel-reference.md │ │ │ ├── file-with-different-link-formats.md │ │ │ ├── file-with-explicit-and-implicit-link-references.md │ │ │ ├── file-with-explicit-link-references.md │ │ │ ├── file-with-only-frontmatter.md │ │ │ ├── file-without-title.md │ │ │ ├── first-document.md │ │ │ ├── index.md │ │ │ ├── second-document.md │ │ │ └── third-document.md │ │ ├── test-config/ │ │ │ ├── enable-plugins/ │ │ │ │ └── config.json │ │ │ ├── folder1/ │ │ │ │ └── config.json │ │ │ └── folder2/ │ │ │ └── config.json │ │ └── test-datastore/ │ │ ├── docs/ │ │ │ └── file-in-nm.md │ │ ├── file-a.md │ │ └── info/ │ │ ├── docs/ │ │ │ └── file-in-sub-nm.md │ │ └── file-b.md │ ├── tsconfig.json │ ├── types/ │ │ └── utils.d.ts │ └── webview-ui/ │ └── graph/ │ ├── build.cjs │ ├── index.html │ ├── package.json │ ├── src/ │ │ ├── components/ │ │ │ ├── control-panel.ts │ │ │ └── graph-canvas.ts │ │ ├── foam-graph.ts │ │ ├── lib/ │ │ │ ├── colors.ts │ │ │ ├── defaults.ts │ │ │ ├── graph-utils.test.ts │ │ │ ├── graph-utils.ts │ │ │ ├── painter.ts │ │ │ └── types.ts │ │ ├── main.css │ │ ├── main.ts │ │ └── protocol.ts │ ├── tsconfig.json │ └── vitest.config.ts ├── readme.md ├── tsconfig.base.json └── typos.toml
SYMBOL INDEX (1309 symbols across 145 files)
FILE: packages/foam-vscode/esbuild.js
function getPlatform (line 8) | function getPlatform() {
method setup (line 40) | setup(build) {
method setup (line 48) | setup(build) {
method setup (line 60) | setup(build) {
function buildExtension (line 87) | async function buildExtension() {
function main (line 111) | async function main() {
method setup (line 121) | setup(build) {
FILE: packages/foam-vscode/src/ai/model/embedding-cache.ts
type Checksum (line 4) | type Checksum = string;
type EmbeddingCacheEntry (line 9) | interface EmbeddingCacheEntry {
type EmbeddingCache (line 17) | type EmbeddingCache = ICache<URI, EmbeddingCacheEntry>;
FILE: packages/foam-vscode/src/ai/model/embeddings.test.ts
class MockProvider (line 14) | class MockProvider implements EmbeddingProvider {
method embed (line 15) | async embed(text: string): Promise<number[]> {
method isAvailable (line 20) | async isAvailable(): Promise<boolean> {
method getProviderInfo (line 23) | getProviderInfo(): EmbeddingProviderInfo {
constant ROOT (line 32) | const ROOT = [URI.parse('/', 'file')];
FILE: packages/foam-vscode/src/ai/model/embeddings.ts
type SimilarResource (line 18) | interface SimilarResource {
type EmbeddingProgressContext (line 26) | interface EmbeddingProgressContext {
class FoamEmbeddings (line 36) | class FoamEmbeddings implements IDisposable {
method constructor (line 50) | constructor(
method getEmbedding (line 61) | public getEmbedding(uri: URI): number[] | null {
method hasEmbeddings (line 70) | public hasEmbeddings(): boolean {
method size (line 78) | public size(): number {
method getSimilar (line 88) | public getSimilar(uri: URI, topK: number = 10): SimilarResource[] {
method cosineSimilarity (line 123) | public cosineSimilarity(a: number[], b: number[]): number {
method updateResource (line 151) | public async updateResource(uri: URI): Promise<Embedding | null> {
method update (line 222) | public async update(
method prepareTextForEmbedding (line 327) | private prepareTextForEmbedding(title: string, content: string): string {
method fromWorkspace (line 349) | public static fromWorkspace(
method dispose (line 376) | public dispose(): void {
FILE: packages/foam-vscode/src/ai/model/in-memory-embedding-cache.ts
class InMemoryEmbeddingCache (line 7) | class InMemoryEmbeddingCache implements EmbeddingCache {
method get (line 10) | get(uri: URI): EmbeddingCacheEntry {
method has (line 14) | has(uri: URI): boolean {
method set (line 18) | set(uri: URI, entry: EmbeddingCacheEntry): void {
method del (line 22) | del(uri: URI): void {
method clear (line 26) | clear(): void {
FILE: packages/foam-vscode/src/ai/providers/ollama/ollama-provider.ts
type OllamaConfig (line 10) | interface OllamaConfig {
constant DEFAULT_OLLAMA_CONFIG (line 22) | const DEFAULT_OLLAMA_CONFIG: OllamaConfig = {
class OllamaEmbeddingProvider (line 31) | class OllamaEmbeddingProvider implements EmbeddingProvider {
method constructor (line 34) | constructor(config: Partial<OllamaConfig> = {}) {
method embed (line 41) | async embed(text: string): Promise<number[]> {
method isAvailable (line 102) | async isAvailable(): Promise<boolean> {
method getProviderInfo (line 136) | getProviderInfo(): EmbeddingProviderInfo {
method getConfig (line 156) | getConfig(): OllamaConfig {
FILE: packages/foam-vscode/src/ai/services/embedding-provider.ts
type EmbeddingProviderInfo (line 4) | interface EmbeddingProviderInfo {
type EmbeddingProvider (line 32) | interface EmbeddingProvider {
type Embedding (line 56) | interface Embedding {
FILE: packages/foam-vscode/src/ai/services/noop-embedding-provider.ts
class NoOpEmbeddingProvider (line 7) | class NoOpEmbeddingProvider implements EmbeddingProvider {
method embed (line 8) | async embed(_text: string): Promise<number[]> {
method isAvailable (line 12) | async isAvailable(): Promise<boolean> {
method getProviderInfo (line 16) | getProviderInfo(): EmbeddingProviderInfo {
FILE: packages/foam-vscode/src/ai/vscode/commands/build-embeddings.ts
constant BUILD_EMBEDDINGS_COMMAND (line 8) | const BUILD_EMBEDDINGS_COMMAND = {
function activate (line 13) | async function activate(
function buildEmbeddings (line 40) | async function buildEmbeddings(
FILE: packages/foam-vscode/src/ai/vscode/commands/show-similar-notes.ts
constant SHOW_SIMILAR_NOTES_COMMAND (line 7) | const SHOW_SIMILAR_NOTES_COMMAND = {
function activate (line 12) | async function activate(
function showSimilarNotes (line 28) | async function showSimilarNotes(foam: Foam): Promise<void> {
FILE: packages/foam-vscode/src/ai/vscode/panels/related-notes.ts
function activate (line 10) | async function activate(
class RelatedNotesTreeDataProvider (line 55) | class RelatedNotesTreeDataProvider extends BaseTreeProvider<vscode.TreeI...
method constructor (line 61) | constructor(
method refresh (line 69) | async refresh(): Promise<void> {
method getChildren (line 100) | async getChildren(item?: vscode.TreeItem): Promise<vscode.TreeItem[]> {
method getState (line 129) | public getState(): 'no-note' | 'no-embedding' | 'ready' {
FILE: packages/foam-vscode/src/core/common/cancellation.ts
type CancellationToken (line 11) | interface CancellationToken {
method dispose (line 38) | dispose() {
function isCancellationToken (line 45) | function isCancellationToken(
class MutableToken (line 78) | class MutableToken implements CancellationToken {
method cancel (line 82) | public cancel() {
method isCancellationRequested (line 92) | get isCancellationRequested(): boolean {
method onCancellationRequested (line 96) | get onCancellationRequested(): Event<any> {
method dispose (line 106) | public dispose(): void {
class CancellationTokenSource (line 114) | class CancellationTokenSource {
method constructor (line 118) | constructor(parent?: CancellationToken) {
method token (line 123) | get token(): CancellationToken {
method cancel (line 132) | cancel(): void {
method dispose (line 144) | dispose(cancel: boolean = false): void {
FILE: packages/foam-vscode/src/core/common/charCode.ts
type CharCode (line 14) | const enum CharCode {
FILE: packages/foam-vscode/src/core/common/errors.ts
type ErrorListenerCallback (line 8) | interface ErrorListenerCallback {
type ErrorListenerUnbind (line 12) | interface ErrorListenerUnbind {
class ErrorHandler (line 17) | class ErrorHandler {
method constructor (line 21) | constructor() {
method addListener (line 35) | addListener(listener: ErrorListenerCallback): ErrorListenerUnbind {
method emit (line 43) | private emit(e: any): void {
method _removeListener (line 49) | private _removeListener(listener: ErrorListenerCallback): void {
method setUnexpectedErrorHandler (line 53) | setUnexpectedErrorHandler(newUnexpectedErrorHandler: (e: any) => void)...
method getUnexpectedErrorHandler (line 57) | getUnexpectedErrorHandler(): (e: any) => void {
method onUnexpectedError (line 61) | onUnexpectedError(e: any): void {
method onUnexpectedExternalError (line 67) | onUnexpectedExternalError(e: any): void {
function setUnexpectedErrorHandler (line 74) | function setUnexpectedErrorHandler(
function onUnexpectedError (line 80) | function onUnexpectedError(e: any): undefined {
function onUnexpectedExternalError (line 88) | function onUnexpectedExternalError(e: any): undefined {
type SerializedError (line 96) | interface SerializedError {
function transformErrorForSerialization (line 105) | function transformErrorForSerialization(error: any): any {
type V8CallSite (line 122) | interface V8CallSite {
function isPromiseCanceledError (line 144) | function isPromiseCanceledError(error: any): boolean {
function canceled (line 155) | function canceled(): Error {
function illegalArgument (line 161) | function illegalArgument(name?: string): Error {
function illegalState (line 169) | function illegalState(name?: string): Error {
function readonly (line 177) | function readonly(name?: string): Error {
function disposed (line 183) | function disposed(what: string): Error {
function getErrorMessage (line 189) | function getErrorMessage(err: any): string {
class NotImplementedError (line 205) | class NotImplementedError extends Error {
method constructor (line 206) | constructor(message?: string) {
class NotSupportedError (line 214) | class NotSupportedError extends Error {
method constructor (line 215) | constructor(message?: string) {
FILE: packages/foam-vscode/src/core/common/event.ts
type Event (line 23) | interface Event<T> {
function once (line 37) | function once<T>(event: Event<T>): Event<T> {
function map (line 70) | function map<I, O>(event: Event<I>, map: (i: I) => O): Event<O> {
function forEach (line 80) | function forEach<I>(event: Event<I>, each: (i: I) => void): Event<I> {
function filter (line 105) | function filter<T>(
function signal (line 117) | function signal<T>(event: Event<T>): Event<void> {
function any (line 127) | function any<T>(...events: Event<T>[]): Event<T> {
function reduce (line 140) | function reduce<I, O>(
function snapshot (line 158) | function snapshot<T>(event: Event<T>): Event<T> {
function debounce (line 195) | function debounce<I, O>(
function stopwatch (line 245) | function stopwatch<T>(event: Event<T>): Event<number> {
function latch (line 254) | function latch<T>(event: Event<T>): Event<T> {
function buffer (line 288) | function buffer<T>(
type IChainableEvent (line 338) | interface IChainableEvent<T> {
class ChainableEvent (line 373) | class ChainableEvent<T> implements IChainableEvent<T> {
method constructor (line 374) | constructor(readonly event: Event<T>) {}
method map (line 376) | map<O>(fn: (i: T) => O): IChainableEvent<O> {
method forEach (line 380) | forEach(fn: (i: T) => void): IChainableEvent<T> {
method filter (line 386) | filter(fn: (e: T) => boolean): IChainableEvent<T> {
method reduce (line 390) | reduce<R>(
method latch (line 397) | latch(): IChainableEvent<T> {
method debounce (line 413) | debounce<R>(
method on (line 424) | on(
method once (line 432) | once(listener: (e: T) => any, thisArgs: any, disposables: IDisposable[...
function chain (line 437) | function chain<T>(event: Event<T>): IChainableEvent<T> {
type NodeEventEmitter (line 441) | interface NodeEventEmitter {
function fromNodeEventEmitter (line 446) | function fromNodeEventEmitter<T>(
type DOMEventEmitter (line 459) | interface DOMEventEmitter {
function fromDOMEventEmitter (line 464) | function fromDOMEventEmitter<T>(
function fromPromise (line 478) | function fromPromise<T = any>(promise: Promise<T>): Event<undefined> {
function toPromise (line 496) | function toPromise<T>(event: Event<T>): Promise<T> {
type Listener (line 501) | type Listener<T> = [(e: T) => void, any] | ((e: T) => void);
type EmitterOptions (line 503) | interface EmitterOptions {
function setGlobalLeakWarningThreshold (line 512) | function setGlobalLeakWarningThreshold(n: number): IDisposable {
class LeakageMonitor (line 522) | class LeakageMonitor {
method constructor (line 526) | constructor(
method dispose (line 531) | dispose(): void {
method check (line 537) | check(listenerCount: number): undefined | (() => void) {
class Emitter (line 604) | class Emitter<T> {
method constructor (line 614) | constructor(options?: EmitterOptions) {
method event (line 628) | get event(): Event<T> {
method fire (line 706) | fire(event: T): void {
method dispose (line 735) | dispose() {
class PauseableEmitter (line 749) | class PauseableEmitter<T> extends Emitter<T> {
method constructor (line 754) | constructor(options?: EmitterOptions & { merge?: (input: T[]) => T }) {
method pause (line 759) | pause(): void {
method resume (line 763) | resume(): void {
method fire (line 781) | fire(event: T): void {
type IWaitUntil (line 792) | interface IWaitUntil {
class EventMultiplexer (line 796) | class EventMultiplexer<T> implements IDisposable {
method constructor (line 801) | constructor() {
method event (line 808) | get event(): Event<T> {
method add (line 812) | add(event: Event<T>): IDisposable {
method onFirstListenerAdd (line 832) | private onFirstListenerAdd(): void {
method onLastListenerRemove (line 837) | private onLastListenerRemove(): void {
method hook (line 842) | private hook(e: { event: Event<T>; listener: IDisposable | null }): vo...
method unhook (line 846) | private unhook(e: { event: Event<T>; listener: IDisposable | null }): ...
method dispose (line 853) | dispose(): void {
class EventBufferer (line 878) | class EventBufferer {
method wrapEvent (line 881) | wrapEvent<T>(event: Event<T>): Event<T> {
method bufferEvents (line 899) | bufferEvents<R = void>(fn: () => R): R {
class Relay (line 915) | class Relay<T> implements IDisposable {
method input (line 936) | set input(event: Event<T>) {
method dispose (line 945) | dispose() {
FILE: packages/foam-vscode/src/core/common/functional.ts
function once (line 8) | function once<T extends Function>(this: unknown, fn: T): T {
FILE: packages/foam-vscode/src/core/common/iterator.ts
function is (line 9) | function is<T = any>(thing: any): thing is IterableIterator<T> {
function empty (line 18) | function empty<T = any>(): Iterable<T> {
function from (line 26) | function from<T>(
function first (line 32) | function first<T>(iterable: Iterable<T>): T | undefined {
function some (line 36) | function some<T>(
function consume (line 80) | function consume<T>(
FILE: packages/foam-vscode/src/core/common/lifecycle.ts
constant TRACK_DISPOSABLES (line 18) | const TRACK_DISPOSABLES = false;
function markTracked (line 22) | function markTracked<T extends IDisposable>(x: T): void {
function trackDisposable (line 36) | function trackDisposable<T extends IDisposable>(x: T): T {
class MultiDisposeError (line 50) | class MultiDisposeError extends Error {
method constructor (line 51) | constructor(public readonly errors: any[]) {
type IDisposable (line 60) | interface IDisposable {
function isDisposable (line 64) | function isDisposable<E extends object>(
function dispose (line 85) | function dispose<T extends IDisposable>(
function combinedDisposable (line 116) | function combinedDisposable(...disposables: IDisposable[]): IDisposable {
function toDisposable (line 121) | function toDisposable(fn: () => void): IDisposable {
class DisposableStore (line 131) | class DisposableStore implements IDisposable {
method dispose (line 142) | public dispose(): void {
method clear (line 155) | public clear(): void {
method add (line 163) | public add<T extends IDisposable>(t: T): T {
method dispose (line 189) | dispose() {}
method constructor (line 193) | constructor() {
method dispose (line 197) | public dispose(): void {
method _register (line 203) | protected _register<T extends IDisposable>(t: T): T {
class MutableDisposable (line 217) | class MutableDisposable<T extends IDisposable> implements IDisposable {
method constructor (line 221) | constructor() {
method value (line 225) | get value(): T | undefined {
method value (line 229) | set value(value: T | undefined) {
method clear (line 243) | clear() {
method dispose (line 247) | dispose(): void {
type IReference (line 257) | interface IReference<T> extends IDisposable {
method acquire (line 267) | acquire(key: string, ...args: any[]): IReference<T> {
class ImmortalReference (line 295) | class ImmortalReference<T> implements IReference<T> {
method constructor (line 296) | constructor(public object: T) {}
method dispose (line 297) | dispose(): void {
FILE: packages/foam-vscode/src/core/common/linkedList.ts
class Node (line 8) | class Node<E> {
method constructor (line 15) | constructor(element: E) {
class LinkedList (line 22) | class LinkedList<E> {
method size (line 27) | get size(): number {
method isEmpty (line 31) | isEmpty(): boolean {
method clear (line 35) | clear(): void {
method unshift (line 41) | unshift(element: E): () => void {
method push (line 45) | push(element: E): () => void {
method _insert (line 49) | private _insert(element: E, atTheEnd: boolean): () => void {
method shift (line 78) | shift(): E | undefined {
method pop (line 88) | pop(): E | undefined {
method _remove (line 98) | private _remove(node: Node<E>): void {
method [Symbol.iterator] (line 122) | *[Symbol.iterator](): Iterator<E> {
FILE: packages/foam-vscode/src/core/common/platform.ts
constant LANGUAGE_DEFAULT (line 8) | const LANGUAGE_DEFAULT = 'en';
type NLSConfig (line 21) | interface NLSConfig {
type IProcessEnvironment (line 27) | interface IProcessEnvironment {
type INodeProcess (line 31) | interface INodeProcess {
type INavigator (line 45) | interface INavigator {
type Platform (line 118) | const enum Platform {
function PlatformToString (line 124) | function PlatformToString(platform: Platform) {
function value (line 163) | function value(): string {
function isDefaultVariant (line 167) | function isDefaultVariant(): boolean {
function isDefault (line 177) | function isDefault(): boolean {
type ISetImmediate (line 196) | interface ISetImmediate {
FILE: packages/foam-vscode/src/core/common/snippetParser.test.ts
function assertText (line 115) | function assertText(value: string, expected: string) {
function assertMarker (line 121) | function assertMarker(input: TextmateSnippet | Marker[] | string, ...cto...
function assertTextAndMarker (line 140) | function assertTextAndMarker(value: string, escaped: string, ...ctors: F...
function assertEscaped (line 145) | function assertEscaped(value: string, expected: string) {
function assertTextsnippetString (line 316) | function assertTextsnippetString(input: string, expected: string): void {
function assertIdent (line 333) | function assertIdent(input: string): void {
function assertLen (line 517) | function assertLen(template: string, ...lengths: number[]): void {
function assertParent (line 761) | function assertParent(marker: Marker) {
FILE: packages/foam-vscode/src/core/common/snippetParser.ts
type TokenType (line 31) | const enum TokenType {
type Token (line 49) | interface Token {
class Scanner (line 56) | class Scanner {
method isDigitCharacter (line 72) | static isDigitCharacter(ch: number): boolean {
method isVariableCharacter (line 76) | static isVariableCharacter(ch: number): boolean {
method text (line 85) | text(value: string) {
method tokenText (line 90) | tokenText(token: Token): string {
method next (line 94) | next(): Token {
method appendChild (line 160) | appendChild(child: Marker): this {
method replace (line 172) | replace(child: Marker, others: Marker[]): void {
method children (line 187) | get children(): Marker[] {
method snippet (line 191) | get snippet(): TextmateSnippet | undefined {
method toString (line 204) | toString(): string {
method len (line 210) | len(): number {
class Text (line 217) | class Text extends Marker {
method escape (line 219) | static escape(value: string): string {
method constructor (line 223) | constructor(public value: string) {
method toString (line 226) | toString() {
method toTextmateString (line 229) | toTextmateString(): string {
method len (line 232) | len(): number {
method clone (line 235) | clone(): Text {
class Placeholder (line 244) | class Placeholder extends TransformableMarker {
method compareByIndex (line 245) | static compareByIndex(a: Placeholder, b: Placeholder): number {
method constructor (line 261) | constructor(public index: number) {
method isFinalTabstop (line 265) | get isFinalTabstop() {
method choice (line 269) | get choice(): Choice | undefined {
method toTextmateString (line 275) | toTextmateString(): string {
method clone (line 291) | clone(): Placeholder {
class Choice (line 301) | class Choice extends Marker {
method appendChild (line 305) | appendChild(marker: Marker): this {
method toString (line 313) | toString() {
method toTextmateString (line 317) | toTextmateString(): string {
method len (line 323) | len(): number {
method clone (line 327) | clone(): Choice {
class Transform (line 334) | class Transform extends Marker {
method resolve (line 338) | resolve(value: string): string {
method _replace (line 353) | private _replace(groups: string[]): string {
method toString (line 367) | toString(): string {
method toTextmateString (line 371) | toTextmateString(): string {
method clone (line 375) | clone(): Transform {
class FormatString (line 384) | class FormatString extends Marker {
method constructor (line 386) | constructor(
method resolve (line 395) | resolve(value?: string): string {
method _toPascalCase (line 415) | private _toPascalCase(value: string): string {
method _toCamelCase (line 427) | private _toCamelCase(value: string): string {
method toTextmateString (line 443) | toTextmateString(): string {
method clone (line 460) | clone(): FormatString {
class Variable (line 466) | class Variable extends TransformableMarker {
method constructor (line 470) | constructor(public name: string, pos?: number, endPos?: number) {
method resolve (line 476) | async resolve(resolver: VariableResolver): Promise<boolean> {
method toTextmateString (line 488) | toTextmateString(): string {
method clone (line 500) | clone(): Variable {
type VariableResolver (line 510) | interface VariableResolver {
function asyncWalk (line 514) | async function asyncWalk(marker: Marker[], visitor: (marker: Marker) => ...
function walk (line 526) | function walk(marker: Marker[], visitor: (marker: Marker) => boolean): v...
class TextmateSnippet (line 538) | class TextmateSnippet extends Marker {
method constructor (line 543) | constructor(value: string) {
method variables (line 548) | variables(): Variable[] {
method snippetTextWithVariablesSubstituted (line 559) | snippetTextWithVariablesSubstituted(variableNames?: Set<string>): stri...
method placeholderInfo (line 581) | get placeholderInfo() {
method placeholders (line 598) | get placeholders(): Placeholder[] {
method offset (line 603) | offset(marker: Marker): number {
method fullLen (line 621) | fullLen(marker: Marker): number {
method enclosingPlaceholders (line 630) | enclosingPlaceholders(placeholder: Placeholder): Placeholder[] {
method resolveVariables (line 642) | async resolveVariables(resolver: VariableResolver, variableNames?: Set...
method appendChild (line 654) | appendChild(child: Marker) {
method replace (line 659) | replace(child: Marker, others: Marker[]): void {
method toTextmateString (line 664) | toTextmateString(): string {
method clone (line 668) | clone(): TextmateSnippet {
method asyncWalk (line 674) | async asyncWalk(visitor: (marker: Marker) => Promise<boolean>): Promis...
method walk (line 678) | walk(visitor: (marker: Marker) => boolean): void {
class SnippetParser (line 683) | class SnippetParser {
method escape (line 685) | static escape(value: string): string {
method guessNeedsClipboard (line 689) | static guessNeedsClipboard(template: string): boolean {
method text (line 696) | text(value: string): string {
method parse (line 700) | parse(value: string, insertFinalTabstop?: boolean, enforceFinalTabstop...
method _accept (line 755) | private _accept(type: TokenType, value?: boolean): boolean | string {
method _backTo (line 764) | private _backTo(token: Token): false {
method _until (line 770) | private _until(type: TokenType): false | string {
method _parse (line 790) | private _parse(marker: Marker): boolean {
method _parseEscaped (line 799) | private _parseEscaped(marker: Marker): boolean {
method _parseTabstopOrVariableName (line 815) | private _parseTabstopOrVariableName(parent: Marker): boolean {
method _parseComplexPlaceholder (line 833) | private _parseComplexPlaceholder(parent: Marker): boolean {
method _parseChoiceElement (line 912) | private _parseChoiceElement(parent: Choice): boolean {
method _parseComplexVariable (line 948) | private _parseComplexVariable(parent: Marker): boolean {
method _parseTransform (line 1005) | private _parseTransform(parent: TransformableMarker): boolean {
method _parseFormatString (line 1074) | private _parseFormatString(parent: Transform): boolean {
method _parseAnything (line 1158) | private _parseAnything(marker: Marker): boolean {
FILE: packages/foam-vscode/src/core/janitor/convert-links-format.ts
function convertLinkFormat (line 20) | function convertLinkFormat(
FILE: packages/foam-vscode/src/core/janitor/generate-link-references.test.ts
function textForNote (line 19) | function textForNote(text: string): string {
type TestCase (line 27) | interface TestCase {
FILE: packages/foam-vscode/src/core/janitor/generate-link-references.ts
constant LINK_REFERENCE_DEFINITION_HEADER (line 8) | const LINK_REFERENCE_DEFINITION_HEADER = `[//begin]: # "Autogenerated li...
constant LINK_REFERENCE_DEFINITION_FOOTER (line 9) | const LINK_REFERENCE_DEFINITION_FOOTER = `[//end]: # "Autogenerated link...
FILE: packages/foam-vscode/src/core/model/foam.ts
type Services (line 15) | interface Services {
type Foam (line 21) | interface Foam extends IDisposable {
FILE: packages/foam-vscode/src/core/model/graph.ts
type Connection (line 9) | type Connection = {
class FoamGraph (line 18) | class FoamGraph implements IDisposable {
method constructor (line 40) | constructor(private readonly workspace: FoamWorkspace) {}
method contains (line 42) | public contains(uri: URI): boolean {
method getAllNodes (line 46) | public getAllNodes(): URI[] {
method getAllConnections (line 53) | public getAllConnections(): Connection[] {
method getConnections (line 57) | public getConnections(uri: URI): Connection[] {
method getLinks (line 64) | public getLinks(uri: URI): Connection[] {
method getBacklinks (line 68) | public getBacklinks(uri: URI): Connection[] {
method fromWorkspace (line 81) | public static fromWorkspace(
method update (line 102) | public update() {
method connect (line 130) | private connect(source: URI, target: URI, link: ResourceLink) {
method dispose (line 149) | public dispose(): void {
FILE: packages/foam-vscode/src/core/model/location.ts
type Location (line 8) | interface Location<T> {
method create (line 24) | static create<T>(uri: URI, range: Range, data: T): Location<T> {
method forObjectWithRange (line 28) | static forObjectWithRange<T extends { range: Range }>(
FILE: packages/foam-vscode/src/core/model/note.ts
type ResourceLink (line 5) | interface ResourceLink {
method isReferenceStyleLink (line 17) | static isReferenceStyleLink(link: ResourceLink): boolean {
method isUnresolvedReference (line 24) | static isUnresolvedReference(
method isResolvedReference (line 33) | static isResolvedReference(
method isRegularLink (line 42) | static isRegularLink(link: ResourceLink): boolean {
type NoteLinkDefinition (line 47) | interface NoteLinkDefinition {
method format (line 55) | static format(definition: NoteLinkDefinition) {
method isEqual (line 66) | static isEqual(def1: NoteLinkDefinition, def2: NoteLinkDefinition): bool...
type Tag (line 75) | interface Tag {
type Alias (line 80) | interface Alias {
type Section (line 85) | interface Section {
type BlockType (line 90) | type BlockType =
type Block (line 99) | interface Block {
method generateId (line 113) | static generateId(): string {
type Resource (line 118) | interface Resource {
type ResourceParser (line 130) | interface ResourceParser {
method sortByTitle (line 135) | public static sortByTitle(a: Resource, b: Resource) {
method sortByPath (line 139) | public static sortByPath(a: Resource, b: Resource) {
method isResource (line 143) | public static isResource(thing: any): thing is Resource {
method findSection (line 158) | public static findSection(resource: Resource, label: string): Section | ...
method findBlock (line 165) | public static findBlock(resource: Resource, id: string): Block | null {
method getSectionAtPosition (line 181) | public static getSectionAtPosition(
FILE: packages/foam-vscode/src/core/model/position.ts
type Position (line 4) | interface Position {
method create (line 10) | static create(line: number, character: number): Position {
method Min (line 14) | static Min(...positions: Position[]): Position {
method Max (line 28) | static Max(...positions: Position[]): Position {
method isBefore (line 42) | static isBefore(p1: Position, p2: Position): boolean {
method isBeforeOrEqual (line 52) | static isBeforeOrEqual(p1: Position, p2: Position): boolean {
method isAfter (line 62) | static isAfter(p1: Position, p2: Position): boolean {
method isAfterOrEqual (line 66) | static isAfterOrEqual(p1: Position, p2: Position): boolean {
method isEqual (line 70) | static isEqual(p1: Position, p2: Position): boolean {
method compareTo (line 74) | static compareTo(p1: Position, p2: Position): number {
FILE: packages/foam-vscode/src/core/model/provider.ts
type ResourceProvider (line 6) | interface ResourceProvider extends IDisposable {
FILE: packages/foam-vscode/src/core/model/range.ts
type Range (line 6) | interface Range {
method create (line 12) | static create(
method createFromPosition (line 29) | static createFromPosition(start: Position, end?: Position) {
method containsRange (line 49) | static containsRange(range: Range, contained: Range): boolean {
method containsPosition (line 56) | static containsPosition(range: Range, position: Position): boolean {
method isEqual (line 63) | static isEqual(r1: Range, r2: Range): boolean {
method isBefore (line 69) | static isBefore(a: Range, b: Range): number {
method toString (line 73) | static toString(range: Range): string {
FILE: packages/foam-vscode/src/core/model/tags.ts
class FoamTags (line 8) | class FoamTags implements IDisposable {
method constructor (line 19) | constructor(private readonly workspace: FoamWorkspace) {}
method fromWorkspace (line 29) | public static fromWorkspace(
method update (line 51) | update(): void {
method dispose (line 63) | dispose(): void {
FILE: packages/foam-vscode/src/core/model/uri.ts
class URI (line 33) | class URI {
method constructor (line 40) | constructor(from: Partial<URI> = {}) {
method parse (line 58) | static parse(value: string, defaultScheme: URI | string | null): URI {
method file (line 85) | static file(value: string): URI {
method placeholder (line 90) | static placeholder(path: string): URI {
method resolve (line 94) | resolve(value: string | URI, isDirectory = false): URI {
method isAbsolute (line 110) | isAbsolute(): boolean {
method getDirectory (line 114) | getDirectory(): URI {
method getBasename (line 119) | getBasename(): string {
method getName (line 123) | getName(): string {
method getExtension (line 127) | getExtension(): string {
method changeExtension (line 131) | changeExtension(from: string, to: string): URI {
method joinPath (line 136) | joinPath(...paths: string[]) {
method relativeTo (line 141) | relativeTo(uri: URI) {
method with (line 155) | with(change: {
method forPath (line 180) | forPath(path: string): URI {
method asPlain (line 188) | asPlain(): URI {
method isPlaceholder (line 192) | isPlaceholder(): boolean {
method toFsPath (line 196) | toFsPath() {
method toString (line 203) | toString(): string {
method isMarkdown (line 207) | isMarkdown(): boolean {
method isEqual (line 212) | isEqual(uri: URI): boolean {
function decodeURIComponentGraceful (line 225) | function decodeURIComponentGraceful(str: string): string {
function percentDecode (line 239) | function percentDecode(str: string): string {
function encode (line 251) | function encode(uri: URI, skipEncoding: boolean): string {
function encodeURIComponentFast (line 349) | function encodeURIComponentFast(
function encodeURIComponentMinimal (line 412) | function encodeURIComponentMinimal(path: string): string {
function asAbsoluteUri (line 440) | function asAbsoluteUri(
FILE: packages/foam-vscode/src/core/model/workspace.ts
class FoamWorkspace (line 11) | class FoamWorkspace implements IDisposable {
method constructor (line 47) | constructor(roots: URI[] = [], public defaultExtension: string = '.md') {
method registerProvider (line 51) | registerProvider(provider: ResourceProvider) {
method resolveUri (line 67) | resolveUri(filepath: string, relativeTo?: URI): URI {
method set (line 110) | set(resource: Resource) {
method delete (line 123) | delete(uri: URI) {
method clear (line 132) | clear() {
method _directoryIndexPriority (line 147) | private _directoryIndexPriority(uri: URI): number {
method _registerDirectoryIndex (line 154) | private _registerDirectoryIndex(resource: Resource): void {
method _unregisterDirectoryIndex (line 168) | private _unregisterDirectoryIndex(uri: URI): void {
method findByDirectory (line 201) | public findByDirectory(dirPath: string): Resource | null {
method listByDirectoryIdentifier (line 212) | public listByDirectoryIdentifier(identifier: string): Resource[] {
method exists (line 224) | public exists(uri: URI): boolean {
method list (line 228) | public list(): Resource[] {
method resources (line 232) | public resources(): IterableIterator<Resource> {
method get (line 240) | public get(uri: URI): Resource {
method listByIdentifier (line 249) | public listByIdentifier(identifier: string): Resource[] {
method getIdentifier (line 281) | public getIdentifier(forResource: URI, exclude?: URI[]): string {
method getDirectoryIdentifier (line 315) | public getDirectoryIdentifier(forResource: URI): string | null {
method getTrieIdentifier (line 333) | private getTrieIdentifier(reference: URI | string): string {
method find (line 350) | public find(reference: URI | string, baseUri?: URI): Resource | null {
method resolveLink (line 400) | public resolveLink(resource: Resource, link: ResourceLink): URI {
method fetch (line 411) | public fetch(uri: URI): Promise<Resource | null> {
method fetchAndSet (line 428) | public async fetchAndSet(uri: URI): Promise<Resource | null> {
method readAsMarkdown (line 434) | public readAsMarkdown(uri: URI): Promise<string | null> {
method dispose (line 443) | public dispose(): void {
method isIdentifier (line 449) | static isIdentifier(path: string): boolean {
method getShortestIdentifier (line 463) | static getShortestIdentifier(forPath: string, amongst: string[]): stri...
method fromProviders (line 494) | static async fromProviders(
FILE: packages/foam-vscode/src/core/query/dql.ts
constant DQL_PLACEHOLDER (line 7) | const DQL_PLACEHOLDER = `<div class="foam-query-placeholder">
constant KNOWN_FIELDS (line 43) | const KNOWN_FIELDS = new Set<string>([
constant VALID_FORMATS (line 52) | const VALID_FORMATS = new Set(['list', 'table', 'count']);
function validateFieldValue (line 58) | function validateFieldValue(key: string, value: unknown): string | null {
function renderWarnings (line 104) | function renderWarnings(warnings: string[]): string {
function renderDqlQuery (line 110) | function renderDqlQuery(
FILE: packages/foam-vscode/src/core/query/html.ts
function escapeHtml (line 3) | function escapeHtml(text: string): string {
function noteLink (line 11) | function noteLink(
function cellValue (line 27) | function cellValue(
function renderList (line 41) | function renderList(
function renderTable (line 76) | function renderTable(
function renderCount (line 101) | function renderCount(results: ResourceView[]): string {
function renderResults (line 111) | function renderResults(
FILE: packages/foam-vscode/src/core/query/index.test.ts
function makeWorkspaceAndGraph (line 10) | function makeWorkspaceAndGraph(notes: ReturnType<typeof createTestNote>[...
FILE: packages/foam-vscode/src/core/query/index.ts
type QueryFilter (line 6) | type QueryFilter =
type QueryDescriptor (line 21) | interface QueryDescriptor {
type ResourceView (line 30) | type ResourceView = Record<string, unknown>;
constant DEFAULT_SELECT (line 32) | const DEFAULT_SELECT = ['title', 'path'];
type Predicate (line 36) | type Predicate = (r: Resource) => boolean;
function makeExpressionContext (line 43) | function makeExpressionContext(r: Resource, graph: FoamGraph) {
function parseFilter (line 53) | function parseFilter(
function parseShorthand (line 157) | function parseShorthand(
function buildFullView (line 196) | function buildFullView(r: Resource, graph: FoamGraph): Record<string, un...
function resolveField (line 212) | function resolveField(full: Record<string, unknown>, field: string): unk...
function projectResource (line 220) | function projectResource(
function compareValues (line 231) | function compareValues(a: unknown, b: unknown): number {
function parseSortDescriptor (line 240) | function parseSortDescriptor(sort: string): {
constant ALL_QUERY_FIELDS (line 253) | const ALL_QUERY_FIELDS = [
class QueryResult (line 272) | class QueryResult {
method constructor (line 276) | constructor(
method descriptor (line 285) | get descriptor(): QueryDescriptor {
method clone (line 289) | private clone(): QueryResult {
method where (line 302) | where(predicate: (r: ResourceView) => boolean): QueryResult {
method sortBy (line 308) | sortBy(field: string, direction: 'asc' | 'desc' = 'asc'): QueryResult {
method limit (line 317) | limit(n: number): QueryResult {
method offset (line 323) | offset(n: number): QueryResult {
method select (line 329) | select(fields: string[]): QueryResult {
method format (line 335) | format(f: 'table' | 'list' | 'count'): QueryResult {
method toArray (line 346) | toArray(): ResourceView[] {
function executeQuery (line 383) | function executeQuery(
FILE: packages/foam-vscode/src/core/query/js.ts
constant EXECUTION_TIMEOUT (line 11) | const EXECUTION_TIMEOUT = 10_000;
constant BLOCKED_GLOBALS (line 14) | const BLOCKED_GLOBALS = [
constant JS_PLACEHOLDER (line 33) | const JS_PLACEHOLDER = `<div class="foam-query-placeholder">
function renderJsQuery (line 41) | function renderJsQuery(
FILE: packages/foam-vscode/src/core/services/attachment-provider.ts
class AttachmentResourceProvider (line 33) | class AttachmentResourceProvider implements ResourceProvider {
method constructor (line 37) | constructor(attachmentExtensions: string[] = []) {
method supports (line 41) | supports(uri: URI) {
method readAsMarkdown (line 47) | async readAsMarkdown(uri: URI): Promise<string | null> {
method fetch (line 54) | async fetch(uri: URI) {
method resolveLink (line 58) | resolveLink(w: FoamWorkspace, resource: Resource, l: ResourceLink) {
method dispose (line 65) | dispose() {
FILE: packages/foam-vscode/src/core/services/datastore.ts
type IDataStore (line 8) | interface IDataStore {
type IWatcher (line 23) | interface IWatcher {
type IMatcher (line 29) | interface IMatcher {
class GenericDataStore (line 64) | class GenericDataStore implements IDataStore {
method constructor (line 65) | constructor(
method list (line 70) | async list(): Promise<URI[]> {
method read (line 74) | async read(uri: URI) {
class FileListBasedMatcher (line 92) | class FileListBasedMatcher implements IMatcher {
method constructor (line 97) | constructor(
method match (line 108) | match(files: URI[]): URI[] {
method isMatch (line 112) | isMatch(uri: URI): boolean {
method refresh (line 116) | async refresh() {
method createFromListFn (line 120) | static async createFromListFn(
class AlwaysIncludeMatcher (line 133) | class AlwaysIncludeMatcher implements IMatcher {
method match (line 136) | match(files: URI[]): URI[] {
method isMatch (line 140) | isMatch(uri: URI): boolean {
method refresh (line 144) | refresh(): Promise<void> {
class SubstringExcludeMatcher (line 149) | class SubstringExcludeMatcher implements IMatcher {
method constructor (line 152) | constructor(exclude: string) {
method match (line 156) | match(files: URI[]): URI[] {
method isMatch (line 160) | isMatch(uri: URI): boolean {
method refresh (line 164) | refresh(): Promise<void> {
FILE: packages/foam-vscode/src/core/services/heading-edit.ts
type HeadingEditResult (line 8) | interface HeadingEditResult {
method createRenameBlockEdits (line 26) | static createRenameBlockEdits(
method createRenameSectionEdits (line 149) | static createRenameSectionEdits(
FILE: packages/foam-vscode/src/core/services/markdown-link.ts
method analyzeLink (line 13) | public static analyzeLink(link: ResourceLink) {
method createUpdateLinkEdit (line 78) | public static createUpdateLinkEdit(
FILE: packages/foam-vscode/src/core/services/markdown-parser.ts
type ParserPlugin (line 23) | interface ParserPlugin {
type Checksum (line 33) | type Checksum = string;
type ParserCacheEntry (line 35) | interface ParserCacheEntry {
type ParserCache (line 48) | type ParserCache = ICache<URI, ParserCacheEntry>;
function getLinkDefinitions (line 55) | function getLinkDefinitions(markdown: string): NoteLinkDefinition[] {
function createMarkdownParser (line 71) | function createMarkdownParser(
function getPropertiesInfoFromYAML (line 232) | function getPropertiesInfoFromYAML(yamlText: string): {
constant BLOCK_ANCHOR_REGEX (line 354) | const BLOCK_ANCHOR_REGEX = /(\s)\^([a-zA-Z0-9-]+)$/;
constant STANDALONE_BLOCK_ANCHOR_RE (line 356) | const STANDALONE_BLOCK_ANCHOR_RE = /^\^([a-zA-Z0-9-]+)$/;
constant BLOCK_NODE_TYPES (line 374) | const BLOCK_NODE_TYPES: Record<string, BlockType> = {
constant FULL_LINE_SIBLING_TYPES (line 383) | const FULL_LINE_SIBLING_TYPES: Record<string, BlockType> = {
FILE: packages/foam-vscode/src/core/services/markdown-provider.ts
class MarkdownResourceProvider (line 17) | class MarkdownResourceProvider implements ResourceProvider {
method constructor (line 20) | constructor(
method supports (line 27) | supports(uri: URI) {
method readAsMarkdown (line 31) | async readAsMarkdown(uri: URI): Promise<string | null> {
method fetch (line 83) | async fetch(uri: URI) {
method resolveLink (line 88) | resolveLink(
method _resolveAsDirectory (line 170) | private _resolveAsDirectory(
method _resolveDirectoryByIdentifier (line 178) | private _resolveDirectoryByIdentifier(
method dispose (line 186) | dispose() {
function createMarkdownReferences (line 191) | function createMarkdownReferences(
FILE: packages/foam-vscode/src/core/services/progress.ts
type Progress (line 4) | interface Progress<T = unknown> {
type ProgressCallback (line 16) | type ProgressCallback<T = unknown> = (progress: Progress<T>) => void;
type CancellationToken (line 21) | interface CancellationToken {
class CancellationError (line 29) | class CancellationError extends Error {
method constructor (line 30) | constructor(message: string = 'Operation cancelled') {
FILE: packages/foam-vscode/src/core/services/tag-edit.ts
type TagEditResult (line 13) | interface TagEditResult {
method createRenameTagEdits (line 39) | public static createRenameTagEdits(
method createSingleTagEdit (line 73) | private static createSingleTagEdit(
method validateTagRename (line 101) | public static validateTagRename(
method findChildTags (line 192) | public static findChildTags(foamTags: FoamTags, parentTag: string): stri...
method createHierarchicalRenameEdits (line 217) | public static createHierarchicalRenameEdits(
method getTagAtPosition (line 265) | public static getTagAtPosition(
FILE: packages/foam-vscode/src/core/services/text-edit.ts
type TextEdit (line 6) | interface TextEdit {
method apply (line 22) | public static apply(
type WorkspaceTextEdit (line 74) | interface WorkspaceTextEdit {
FILE: packages/foam-vscode/src/core/utils/cache.ts
type ICache (line 1) | interface ICache<K, V> {
FILE: packages/foam-vscode/src/core/utils/core.ts
function isNotNull (line 9) | function isNotNull<T>(value: T | null): value is T {
function isSome (line 19) | function isSome<T>(
function isNone (line 31) | function isNone<T>(
function isNumeric (line 43) | function isNumeric(value: string): boolean {
function firstFrom (line 62) | async function firstFrom<T>(
FILE: packages/foam-vscode/src/core/utils/hashtags.ts
constant HASHTAG_REGEX (line 2) | const HASHTAG_REGEX =
constant WORD_REGEX (line 4) | const WORD_REGEX =
FILE: packages/foam-vscode/src/core/utils/log.ts
type ILogger (line 1) | interface ILogger {
type LogLevel (line 10) | type LogLevel = 'debug' | 'info' | 'warn' | 'error';
type LogLevelThreshold (line 11) | type LogLevelThreshold = LogLevel | 'off';
method constructor (line 21) | constructor(private level: LogLevelThreshold = 'info') {}
method doLog (line 25) | doLog(msgLevel: LogLevel, message?: any, ...params: any[]): void {
method debug (line 34) | debug(message?: any, ...params: any[]): void {
method info (line 37) | info(message?: any, ...params: any[]): void {
method warn (line 40) | warn(message?: any, ...params: any[]): void {
method error (line 43) | error(message?: any, ...params: any[]): void {
method getLevel (line 46) | getLevel(): LogLevelThreshold {
method setLevel (line 49) | setLevel(level: LogLevelThreshold): void {
class ConsoleLogger (line 54) | class ConsoleLogger extends BaseLogger {
method log (line 55) | log(level: LogLevel, msg?: string, ...params: any[]): void {
class NoOpLogger (line 60) | class NoOpLogger extends BaseLogger {
method log (line 61) | log(_l: LogLevel, _m?: string, ..._p: any[]): void {
class Logger (line 66) | class Logger {
method debug (line 67) | static debug(message?: any, ...params: any[]): void {
method info (line 70) | static info(message?: any, ...params: any[]): void {
method warn (line 73) | static warn(message?: any, ...params: any[]): void {
method error (line 76) | static error(message?: any, ...params: any[]): void {
method getLevel (line 79) | static getLevel(): LogLevelThreshold {
method setLevel (line 82) | static setLevel(level: LogLevelThreshold): void {
method setDefaultLogger (line 88) | static setDefaultLogger(logger: ILogger) {
FILE: packages/foam-vscode/src/core/utils/md.ts
function getExcerpt (line 3) | function getExcerpt(
function stripFrontMatter (line 22) | function stripFrontMatter(markdown: string): string {
function stripImages (line 26) | function stripImages(markdown: string): string {
function isInFrontMatter (line 39) | function isInFrontMatter(content: string, lineNumber: number): boolean {
function isOnYAMLKeywordLine (line 60) | function isOnYAMLKeywordLine(content: string, keyword: string): boolean {
FILE: packages/foam-vscode/src/core/utils/path.ts
function fromFsPath (line 15) | function fromFsPath(path: string): [string, string] {
function toFsPath (line 40) | function toFsPath(path: string, authority?: string): string {
function isAbsolute (line 58) | function isAbsolute(path: string): boolean {
function getDirectory (line 70) | function getDirectory(path: string): string {
function getBasename (line 80) | function getBasename(path: string): string {
function getName (line 90) | function getName(path: string): string {
function getExtension (line 103) | function getExtension(path: string): string {
function changeExtension (line 115) | function changeExtension(
function joinPath (line 136) | function joinPath(...paths: string[]): string {
function relativeTo (line 149) | function relativeTo(path: string, basePath: string): string {
function hasDrive (line 153) | function hasDrive(path: string, idx = 0): boolean {
function isUNCShare (line 165) | function isUNCShare(fsPath: string): boolean {
function parseUNCShare (line 173) | function parseUNCShare(uncPath: string): [string, string] {
function asAbsolutePaths (line 193) | function asAbsolutePaths(path: string, baseFolders: string[]): string[] {
FILE: packages/foam-vscode/src/core/utils/task-deduplicator.test.ts
type Status (line 150) | type Status = 'complete' | 'cancelled' | 'error';
FILE: packages/foam-vscode/src/core/utils/task-deduplicator.ts
class TaskDeduplicator (line 24) | class TaskDeduplicator<T> {
method run (line 36) | async run(task: () => Promise<T>, onDuplicate?: () => void): Promise<T> {
method isRunning (line 57) | isRunning(): boolean {
method clear (line 64) | clear(): void {
FILE: packages/foam-vscode/src/dated-notes.ts
function openDailyNoteFor (line 22) | async function openDailyNoteFor(date?: Date, foam?: Foam) {
function getDailyNoteUri (line 45) | function getDailyNoteUri(date: Date): URI {
function getDailyNoteFileName (line 61) | function getDailyNoteFileName(date: Date): string {
constant DEFAULT_DAILY_NOTE_TEMPLATE (line 74) | const DEFAULT_DAILY_NOTE_TEMPLATE = `---
constant CREATE_DAILY_NOTE_WARNING_RESPONSE (line 96) | const CREATE_DAILY_NOTE_WARNING_RESPONSE = 'Create daily note template';
function createDailyNoteIfNotExists (line 105) | async function createDailyNoteIfNotExists(targetDate: Date, foam: Foam) {
FILE: packages/foam-vscode/src/extension.ts
function activate (line 25) | async function activate(context: ExtensionContext) {
FILE: packages/foam-vscode/src/features/block-rename-provider.ts
function activate (line 14) | async function activate(
class BlockRenameProvider (line 27) | class BlockRenameProvider implements vscode.RenameProvider {
method constructor (line 28) | constructor(private foam: Foam) {}
method prepareRename (line 30) | async prepareRename(
method provideRenameEdits (line 45) | provideRenameEdits(
method getBlockAnchorAtCursor (line 97) | private getBlockAnchorAtCursor(
FILE: packages/foam-vscode/src/features/commands/convert-links.ts
constant CONVERT_WIKILINK_TO_MDLINK (line 12) | const CONVERT_WIKILINK_TO_MDLINK = {
constant CONVERT_MDLINK_TO_WIKILINK (line 17) | const CONVERT_MDLINK_TO_WIKILINK = {
function convertWikilinkToMarkdownAtPosition (line 26) | function convertWikilinkToMarkdownAtPosition(
function convertMarkdownToWikilinkAtPosition (line 72) | function convertMarkdownToWikilinkAtPosition(
function activate (line 120) | async function activate(
function convertWikilinkToMarkdown (line 140) | async function convertWikilinkToMarkdown(foam: Foam): Promise<void> {
function convertMarkdownToWikilink (line 196) | async function convertMarkdownToWikilink(foam: Foam): Promise<void> {
FILE: packages/foam-vscode/src/features/commands/copy-without-brackets.ts
function activate (line 3) | async function activate(context: ExtensionContext) {
function copyWithoutBrackets (line 12) | async function copyWithoutBrackets() {
function removeBrackets (line 38) | function removeBrackets(s: string): string {
function toTitleCase (line 70) | function toTitleCase(word: string): string {
FILE: packages/foam-vscode/src/features/commands/create-new-template.ts
function activate (line 4) | async function activate(context: ExtensionContext) {
FILE: packages/foam-vscode/src/features/commands/create-note-from-template.ts
function activate (line 3) | async function activate(context: ExtensionContext) {
FILE: packages/foam-vscode/src/features/commands/create-note.ts
function activate (line 22) | async function activate(
type CreateNoteArgs (line 34) | interface CreateNoteArgs {
constant DEFAULT_NEW_NOTE_TEXT (line 84) | const DEFAULT_NEW_NOTE_TEXT = `# \${FOAM_TITLE}
function forceLocalDate (line 95) | function forceLocalDate(dateString: string): Date {
function createNote (line 102) | async function createNote(args: CreateNoteArgs, foam: Foam) {
constant CREATE_NOTE_COMMAND (line 217) | const CREATE_NOTE_COMMAND = {
FILE: packages/foam-vscode/src/features/commands/janitor.ts
function activate (line 21) | async function activate(
function janitor (line 32) | async function janitor(foam: Foam) {
function runJanitor (line 68) | async function runJanitor(foam: Foam) {
FILE: packages/foam-vscode/src/features/commands/open-daily-note-for-date.ts
function activate (line 8) | async function activate(
class DateItem (line 32) | class DateItem implements QuickPickItem {
method constructor (line 37) | constructor(public date: Date, offset: number, public exists: boolean) {
function generateDateItems (line 55) | function generateDateItems(ws: FoamWorkspace): DateItem[] {
FILE: packages/foam-vscode/src/features/commands/open-daily-note.ts
function activate (line 6) | async function activate(
FILE: packages/foam-vscode/src/features/commands/open-dated-note.ts
function activate (line 9) | async function activate(
FILE: packages/foam-vscode/src/features/commands/open-random-note.ts
function activate (line 5) | async function activate(
FILE: packages/foam-vscode/src/features/commands/open-resource.ts
function activate (line 12) | async function activate(
type OpenResourceArgs (line 24) | interface OpenResourceArgs {
constant OPEN_COMMAND (line 38) | const OPEN_COMMAND = {
function openResource (line 52) | async function openResource(
type ResourceItem (line 104) | interface ResourceItem extends vscode.QuickPickItem {
FILE: packages/foam-vscode/src/features/commands/rename-tag.ts
constant RENAME_TAG_COMMAND (line 15) | const RENAME_TAG_COMMAND = {
function activate (line 31) | async function activate(
function executeRenameTag (line 79) | async function executeRenameTag(
function performTagRename (line 278) | async function performTagRename(
FILE: packages/foam-vscode/src/features/commands/search-tag.ts
constant SEARCH_TAG_COMMAND (line 5) | const SEARCH_TAG_COMMAND = {
function generateTagSearchPattern (line 16) | function generateTagSearchPattern(tagLabel: string): string {
function activate (line 27) | async function activate(
FILE: packages/foam-vscode/src/features/commands/update-graph.ts
constant UPDATE_GRAPH_COMMAND_NAME (line 4) | const UPDATE_GRAPH_COMMAND_NAME = 'foam-vscode.update-graph';
function activate (line 6) | async function activate(
FILE: packages/foam-vscode/src/features/commands/update-wikilinks.ts
function activate (line 27) | async function activate(
function getWikilinkDefinitionSetting (line 60) | function getWikilinkDefinitionSetting():
function updateWikilinkDefinitions (line 69) | async function updateWikilinkDefinitions(
function detectDocumentWikilinkDefinitions (line 119) | function detectDocumentWikilinkDefinitions(text: string, eol: string) {
class WikilinkReferenceCodeLensProvider (line 145) | class WikilinkReferenceCodeLensProvider implements CodeLensProvider {
method constructor (line 146) | constructor(
method provideCodeLenses (line 151) | public async provideCodeLenses(
FILE: packages/foam-vscode/src/features/date-snippets.ts
function activate (line 13) | async function activate(context: ExtensionContext) {
type DateSnippet (line 24) | interface DateSnippet {
FILE: packages/foam-vscode/src/features/document-decorator.ts
function activate (line 61) | async function activate(
FILE: packages/foam-vscode/src/features/heading-rename-provider.ts
function activate (line 14) | async function activate(
class HeadingRenameProvider (line 26) | class HeadingRenameProvider implements vscode.RenameProvider {
method constructor (line 27) | constructor(private foam: Foam) {}
method prepareRename (line 29) | async prepareRename(
method provideRenameEdits (line 47) | provideRenameEdits(
method getSectionOnHeadingLine (line 103) | private getSectionOnHeadingLine(
function getHeadingLabelRange (line 124) | function getHeadingLabelRange(
FILE: packages/foam-vscode/src/features/hover-provider.ts
constant CONFIG_KEY (line 20) | const CONFIG_KEY = 'links.hover.enable';
function activate (line 22) | async function activate(
class HoverProvider (line 45) | class HoverProvider implements vscode.HoverProvider {
method constructor (line 46) | constructor(
method provideHover (line 53) | async provideHover(
FILE: packages/foam-vscode/src/features/link-completion.ts
constant COMPLETION_CURSOR_MOVE (line 17) | const COMPLETION_CURSOR_MOVE = {
constant WIKILINK_REGEX (line 22) | const WIKILINK_REGEX = /\[\[[^[\]]*(?!.*\]\])/;
constant SECTION_REGEX (line 23) | const SECTION_REGEX = /\[\[([^[\]]*#(?!.*\]\]))/;
function activate (line 25) | async function activate(
class SectionCompletionProvider (line 93) | class SectionCompletionProvider
method constructor (line 96) | constructor(private ws: FoamWorkspace) {}
method provideCompletionItems (line 98) | provideCompletionItems(
method resolveCompletionItem (line 163) | resolveCompletionItem(
class WikilinkCompletionProvider (line 176) | class WikilinkCompletionProvider
method constructor (line 179) | constructor(private ws: FoamWorkspace, private graph: FoamGraph) {}
method provideCompletionItems (line 181) | provideCompletionItems(
method resolveCompletionItem (line 317) | resolveCompletionItem(
class ResourceCompletionItem (line 333) | class ResourceCompletionItem extends vscode.CompletionItem {
method constructor (line 334) | constructor(
function getCompletionLabelSetting (line 343) | function getCompletionLabelSetting() {
function getCompletionAliasSetting (line 349) | function getCompletionAliasSetting() {
function getCompletionLinkFormatSetting (line 356) | function getCompletionLinkFormatSetting() {
function wikilinkRequiresAlias (line 364) | function wikilinkRequiresAlias(resource: Resource, defaultExtension: str...
FILE: packages/foam-vscode/src/features/navigation-provider.ts
function activate (line 22) | async function activate(
class NavigationProvider (line 63) | class NavigationProvider
method constructor (line 69) | constructor(
method provideReferences (line 79) | public provideReferences(
method getTagReferences (line 119) | private getTagReferences(tagLabel: string): vscode.Location[] {
method provideDefinition (line 136) | public async provideDefinition(
method provideDocumentLinks (line 206) | public async provideDocumentLinks(
function resolveFragmentRange (line 285) | function resolveFragmentRange(
FILE: packages/foam-vscode/src/features/panels/connections.ts
function activate (line 19) | async function activate(
class ConnectionsTreeDataProvider (line 55) | class ConnectionsTreeDataProvider extends BaseTreeProvider<vscode.TreeIt...
method constructor (line 61) | constructor(
method refresh (line 102) | async refresh(): Promise<void> {
method getChildren (line 129) | async getChildren(item?: BacklinkPanelTreeItem): Promise<vscode.TreeIt...
type BacklinkPanelTreeItem (line 172) | type BacklinkPanelTreeItem = ResourceTreeItem | ResourceRangeTreeItem;
FILE: packages/foam-vscode/src/features/panels/dataviz/index.ts
function activate (line 9) | async function activate(
function updateGraph (line 61) | function updateGraph(panel: vscode.WebviewPanel, foam: Foam) {
function generateGraphData (line 69) | function generateGraphData(foam: Foam) {
function cutTitle (line 109) | function cutTitle(title: string): string {
function createGraphPanel (line 119) | async function createGraphPanel(
function getWebviewContent (line 187) | async function getWebviewContent(
function getGraphStyle (line 219) | function getGraphStyle(): StylePayload {
function getNodeNavigationCommand (line 223) | function getNodeNavigationCommand(
FILE: packages/foam-vscode/src/features/panels/notes-explorer.ts
function activate (line 18) | async function activate(
function findTreeItemByUri (line 74) | function findTreeItemByUri<I, T>(
type NotesTreeItems (line 85) | type NotesTreeItems =
class NotesProvider (line 90) | class NotesProvider extends FolderTreeProvider<
method constructor (line 96) | constructor(
method getValues (line 126) | getValues() {
method getFilterFn (line 130) | getFilterFn() {
method valueToPath (line 136) | valueToPath(value: Resource) {
method createValueTreeItem (line 145) | createValueTreeItem(
FILE: packages/foam-vscode/src/features/panels/orphans.ts
constant EXCLUDE_TYPES (line 19) | const EXCLUDE_TYPES = ['image', 'attachment'];
function activate (line 20) | async function activate(
function getOrphansConfig (line 57) | function getOrphansConfig(): GroupedResourcesConfig {
class OrphanTreeView (line 63) | class OrphanTreeView extends GroupedResourcesTreeDataProvider {
method constructor (line 64) | constructor(
function isAttachment (line 91) | function isAttachment(uri: URI) {
FILE: packages/foam-vscode/src/features/panels/placeholders.ts
function getPlaceholdersConfig (line 23) | function getPlaceholdersConfig(): GroupedResourcesConfig {
function activate (line 29) | async function activate(
class PlaceholderTreeView (line 81) | class PlaceholderTreeView extends GroupedResourcesTreeDataProvider {
method constructor (line 88) | public constructor(
method createValueTreeItem (line 113) | createValueTreeItem(uri: URI, parent: FolderTreeItem<URI>): UriTreeItem {
method getUris (line 134) | getUris(): URI[] {
FILE: packages/foam-vscode/src/features/panels/tags-explorer.ts
constant TAG_SEPARATOR (line 24) | const TAG_SEPARATOR = '/';
function activate (line 25) | async function activate(
class TagsProvider (line 106) | class TagsProvider extends FolderTreeProvider<TagTreeItem, string> {
method constructor (line 124) | constructor(
method refresh (line 165) | refresh(): void {
method getValues (line 172) | getValues(): string[] {
method valueToPath (line 181) | valueToPath(value: string) {
method countResourcesInSubtree (line 185) | private countResourcesInSubtree(node: Folder<string>) {
method createFolderTreeItem (line 195) | createFolderTreeItem(
method createValueTreeItem (line 204) | createValueTreeItem(
method getChildren (line 215) | async getChildren(element?: TagItem): Promise<TagTreeItem[]> {
type TagTreeItem (line 250) | type TagTreeItem = TagItem | ResourceTreeItem | ResourceRangeTreeItem;
class TagItem (line 252) | class TagItem extends FolderTreeItem<string> {
method constructor (line 255) | constructor(
FILE: packages/foam-vscode/src/features/panels/utils/base-tree-provider.ts
method getTreeItem (line 26) | getTreeItem(element: T) {
method resolveTreeItem (line 30) | async resolveTreeItem(item: T): Promise<T> {
method refresh (line 37) | refresh(): void {
method dispose (line 41) | dispose(): void {
FILE: packages/foam-vscode/src/features/panels/utils/folder-tree-provider.ts
type Folder (line 8) | interface Folder<T> {
class FolderTreeItem (line 19) | class FolderTreeItem<T> extends vscode.TreeItem {
method constructor (line 23) | constructor(
method refresh (line 41) | refresh(): void {
method getParent (line 48) | getParent(element: I | FolderTreeItem<T>): vscode.ProviderResult<I> {
method createFolderTreeItem (line 57) | createFolderTreeItem(
method getChildren (line 65) | async getChildren(item?: I): Promise<I[]> {
method createTree (line 90) | createTree(values: T[], filterFn: (value: T) => boolean): Folder<T> {
method getTreeItemsHierarchy (line 123) | getTreeItemsHierarchy(path: string[]): vscode.TreeItem[] {
method findTreeItemByPath (line 160) | findTreeItemByPath(path: string[]): Promise<I> {
method getFilterFn (line 175) | getFilterFn(): (value: T) => boolean {
function walk (line 203) | function walk<T, R>(node: Folder<T>, fn: (value: T) => R): R[] {
function sortFolderTreeItems (line 221) | function sortFolderTreeItems(a: vscode.TreeItem, b: vscode.TreeItem): nu...
FILE: packages/foam-vscode/src/features/panels/utils/grouped-resources-tree-data-provider.spec.ts
class TestProvider (line 17) | class TestProvider extends GroupedResourcesTreeDataProvider {
method constructor (line 18) | constructor(
method getUris (line 25) | getUris(): URI[] {
method createValueTreeItem (line 28) | createValueTreeItem(value: URI) {
FILE: packages/foam-vscode/src/features/panels/utils/grouped-resources-tree-data-provider.ts
type GroupedResourcesConfig (line 13) | interface GroupedResourcesConfig {
type GroupedResourceTreeItem (line 17) | type GroupedResourceTreeItem = UriTreeItem | FolderTreeItem<URI>;
method constructor (line 54) | constructor(
method valueToPath (line 84) | valueToPath(value: URI) {
method getValues (line 96) | getValues(): URI[] {
method createFolderTreeItem (line 101) | createFolderTreeItem(
FILE: packages/foam-vscode/src/features/panels/utils/tree-view-utils.ts
class BaseTreeItem (line 14) | class BaseTreeItem extends vscode.TreeItem {
method resolveTreeItem (line 15) | resolveTreeItem(): Promise<vscode.TreeItem> {
method getChildren (line 19) | getChildren(): Promise<vscode.TreeItem[]> {
class UriTreeItem (line 24) | class UriTreeItem extends BaseTreeItem {
method constructor (line 27) | constructor(
class ResourceTreeItem (line 45) | class ResourceTreeItem extends UriTreeItem {
method constructor (line 49) | constructor(
method resolveTreeItem (line 70) | async resolveTreeItem(): Promise<ResourceTreeItem> {
class ResourceRangeTreeItem (line 81) | class ResourceRangeTreeItem extends BaseTreeItem {
method constructor (line 83) | constructor(
method resolveTreeItem (line 98) | async resolveTreeItem(): Promise<ResourceRangeTreeItem> {
method createStandardItem (line 128) | static async createStandardItem(
function createBacklinkItemsForResource (line 191) | function createBacklinkItemsForResource(
function createConnectionItemsForResource (line 212) | function createConnectionItemsForResource(
function expandNode (line 241) | async function expandNode<T>(
function expandAll (line 276) | async function expandAll<T>(
FILE: packages/foam-vscode/src/features/preview/block-anchor-ids.ts
constant INLINE_ANCHOR_RE (line 44) | const INLINE_ANCHOR_RE = /\s\^([a-zA-Z0-9-]+)$/;
constant FULL_LINE_ANCHOR_RE (line 46) | const FULL_LINE_ANCHOR_RE = /^\^([a-zA-Z0-9-]+)$/;
constant TRAILING_OWN_LINE_ANCHOR_RE (line 48) | const TRAILING_OWN_LINE_ANCHOR_RE = /\n\^([a-zA-Z0-9-]+)$/;
function insertAnchor (line 51) | function insertAnchor(
function findMatchingOpen (line 66) | function findMatchingOpen(
FILE: packages/foam-vscode/src/features/preview/escape-wikilink-pipes.ts
constant PIPE_PLACEHOLDER (line 29) | const PIPE_PLACEHOLDER = '\uF8FF';
constant WIKILINK_WITH_PIPE_REGEX (line 38) | const WIKILINK_WITH_PIPE_REGEX = /!?\[\[([^\]]*?\|[^\]]*?)\]\]/g;
function encodePipesInWikilinks (line 43) | function encodePipesInWikilinks(text: string): string {
function decodePipesInWikilinks (line 52) | function decodePipesInWikilinks(text: string): string {
FILE: packages/foam-vscode/src/features/preview/foam-query-renderer.ts
function markdownItFoamQuery (line 10) | function markdownItFoamQuery(
FILE: packages/foam-vscode/src/features/preview/index.ts
function activate (line 15) | async function activate(
FILE: packages/foam-vscode/src/features/preview/wikilink-embed-web-extension.ts
constant WIKILINK_EMBED_REGEX (line 7) | const WIKILINK_EMBED_REGEX =
FILE: packages/foam-vscode/src/features/preview/wikilink-embed.ts
constant WIKILINK_EMBED_REGEX (line 22) | const WIKILINK_EMBED_REGEX =
constant WIKILINK_EMBED_REGEX_GROUPS (line 27) | const WIKILINK_EMBED_REGEX_GROUPS =
constant CONFIG_EMBED_NOTE_TYPE (line 29) | const CONFIG_EMBED_NOTE_TYPE = 'preview.embedNoteType';
function getNoteContent (line 129) | function getNoteContent(
function withLinksRelativeToWorkspaceRoot (line 187) | function withLinksRelativeToWorkspaceRoot(
function retrieveNoteConfig (line 220) | function retrieveNoteConfig(explicitModifier: string | undefined): {
type EmbedNoteExtractor (line 243) | type EmbedNoteExtractor = (
function fullExtractor (line 249) | function fullExtractor(
function contentExtractor (line 279) | function contentExtractor(
function extractBlockContent (line 323) | function extractBlockContent(
type EmbedNoteFormatter (line 354) | type EmbedNoteFormatter = (content: string, md: markdownit) => string;
function cardFormatter (line 356) | function cardFormatter(content: string, md: markdownit): string {
function inlineFormatter (line 360) | function inlineFormatter(content: string, md: markdownit): string {
type ImageParameters (line 364) | interface ImageParameters {
function parseImageParameters (line 372) | function parseImageParameters(
function generateImageStyles (line 426) | function generateImageStyles(params: ImageParameters, md: markdownit): s...
function addDefaultUnit (line 461) | function addDefaultUnit(value: string): string {
function escapeHtml (line 469) | function escapeHtml(text: string): string {
FILE: packages/foam-vscode/src/features/refactor.test.ts
function createFoam (line 16) | function createFoam(...notes: Resource[]): Foam {
FILE: packages/foam-vscode/src/features/refactor.ts
constant MARKDOWN_LINK_NOTIFICATION_KEY (line 12) | const MARKDOWN_LINK_NOTIFICATION_KEY =
function buildFutureWorkspace (line 20) | function buildFutureWorkspace(
function toCorrectCase (line 44) | function toCorrectCase(lowerId: string, dirUri: URI): string {
function computeRenameEditsForPairs (line 60) | function computeRenameEditsForPairs(
function computeWikilinkRenameEdits (line 109) | function computeWikilinkRenameEdits(
function computeDirectoryWikilinkRenameEdits (line 121) | function computeDirectoryWikilinkRenameEdits(
function activate (line 137) | async function activate(
FILE: packages/foam-vscode/src/features/tag-completion.ts
constant HASH_REGEX (line 9) | const HASH_REGEX =
constant MAX_LINES_FOR_FRONT_MATTER (line 11) | const MAX_LINES_FOR_FRONT_MATTER = 50;
function activate (line 13) | async function activate(
class TagCompletionProvider (line 27) | class TagCompletionProvider
method constructor (line 30) | constructor(private foamTags: FoamTags) {}
method provideCompletionItems (line 32) | provideCompletionItems(
method createTagsForFrontMatter (line 64) | private createTagsForFrontMatter(
method createTagsForContent (line 117) | private createTagsForContent(
method createCompletionTagItems (line 129) | private createCompletionTagItems(): vscode.CompletionItem[] {
method tagMatchIndices (line 145) | private tagMatchIndices(content: string, match: RegExp): number[] {
FILE: packages/foam-vscode/src/features/tag-rename-provider.ts
function activate (line 22) | async function activate(
class TagRenameProvider (line 41) | class TagRenameProvider implements vscode.RenameProvider {
method constructor (line 42) | constructor(private foam: Foam) {}
method prepareRename (line 57) | prepareRename(
method provideRenameEdits (line 117) | provideRenameEdits(
FILE: packages/foam-vscode/src/features/wikilink-diagnostics.ts
constant AMBIGUOUS_IDENTIFIER_CODE (line 21) | const AMBIGUOUS_IDENTIFIER_CODE = 'ambiguous-identifier';
constant UNKNOWN_SECTION_CODE (line 22) | const UNKNOWN_SECTION_CODE = 'unknown-section';
constant UNKNOWN_BLOCK_CODE (line 23) | const UNKNOWN_BLOCK_CODE = 'unknown-block';
constant DUPLICATE_BLOCK_ID_CODE (line 24) | const DUPLICATE_BLOCK_ID_CODE = 'duplicate-block-id';
type FoamCommand (line 26) | interface FoamCommand<T> {
type FindIdentifierCommandArgs (line 31) | interface FindIdentifierCommandArgs {
constant FIND_IDENTIFIER_COMMAND (line 38) | const FIND_IDENTIFIER_COMMAND: FoamCommand<FindIdentifierCommandArgs> = {
type ReplaceTextCommandArgs (line 58) | interface ReplaceTextCommandArgs {
constant REPLACE_TEXT_COMMAND (line 63) | const REPLACE_TEXT_COMMAND: FoamCommand<ReplaceTextCommandArgs> = {
function activate (line 72) | async function activate(
function updateDiagnostics (line 124) | function updateDiagnostics(
class IdentifierResolver (line 253) | class IdentifierResolver implements vscode.CodeActionProvider {
method constructor (line 258) | constructor(private defaultExtension: string) {}
method provideCodeActions (line 260) | provideCodeActions(
FILE: packages/foam-vscode/src/features/workspace-symbol-provider.ts
function activate (line 6) | async function activate(
class FoamWorkspaceSymbolProvider (line 25) | class FoamWorkspaceSymbolProvider
method constructor (line 28) | constructor(private workspace: FoamWorkspace) {}
method provideWorkspaceSymbols (line 34) | provideWorkspaceSymbols(query: string): vscode.SymbolInformation[] {
method matchesQuery (line 67) | matchesQuery(query: string, candidate: string): boolean {
FILE: packages/foam-vscode/src/services/cache.ts
class VsCodeBasedParserCache (line 21) | class VsCodeBasedParserCache implements ParserCache {
method constructor (line 27) | constructor(private context: ExtensionContext, size = 10000) {
method clear (line 62) | clear(): void {
method get (line 67) | get(uri: URI): ParserCacheEntry {
method has (line 86) | has(uri: URI): boolean {
method set (line 90) | set(uri: URI, entry: ParserCacheEntry): void {
method del (line 95) | del(uri: URI): void {
FILE: packages/foam-vscode/src/services/config.ts
type ConfigurationMonitor (line 3) | interface ConfigurationMonitor<T> extends Disposable {
FILE: packages/foam-vscode/src/services/editor.ts
type SelectionInfo (line 30) | interface SelectionInfo {
function getNoteTooltip (line 40) | function getNoteTooltip(content: string): string {
function formatMarkdownTooltip (line 45) | function formatMarkdownTooltip(content: string): MarkdownString {
function isMdEditor (line 67) | function isMdEditor(editor: TextEditor): boolean {
function isVirtualWorkspace (line 83) | function isVirtualWorkspace(): boolean {
function getWorkspaceDefaultScheme (line 90) | function getWorkspaceDefaultScheme(): string {
function findSelectionContent (line 97) | function findSelectionContent(): SelectionInfo | undefined {
function focusNote (line 117) | async function focusNote(
function createDocAndFocus (line 135) | async function createDocAndFocus(
function replaceSelection (line 149) | async function replaceSelection(
function getEditorEOL (line 162) | function getEditorEOL(): string {
function getCurrentEditorDirectory (line 175) | function getCurrentEditorDirectory(): URI {
function fileExists (line 185) | async function fileExists(uri: URI): Promise<boolean> {
function readFile (line 194) | async function readFile(uri: URI): Promise<string | undefined> {
function deleteFile (line 203) | function deleteFile(uri: URI) {
function asAbsoluteWorkspaceUri (line 212) | function asAbsoluteWorkspaceUri(uriOrPath: URI | string): URI {
function createMatcherAndDataStore (line 222) | async function createMatcherAndDataStore(
FILE: packages/foam-vscode/src/services/errors.ts
class UserCancelledOperation (line 1) | class UserCancelledOperation extends Error {
method constructor (line 2) | constructor(message?: string) {
FILE: packages/foam-vscode/src/services/js-template-loader.ts
class JSTemplateError (line 11) | class JSTemplateError extends Error {
method constructor (line 12) | constructor(message: string, public readonly templatePath: string) {
class JSTemplateLoader (line 21) | class JSTemplateLoader {
method loadFunction (line 34) | async loadFunction(template: URI): Promise<CreateNoteFunction> {
method createFunctionFromCode (line 66) | private createFunctionFromCode(
method createVMSandbox (line 134) | private createVMSandbox() {
method validateTemplateCode (line 148) | private validateTemplateCode(code: string, template: URI): void {
method validateResult (line 184) | private validateResult(result: any, template: URI): void {
FILE: packages/foam-vscode/src/services/js-template-sandbox.ts
function createTemplateSandbox (line 11) | function createTemplateSandbox(context: TemplateContext) {
constant BLOCKED_GLOBALS (line 46) | const BLOCKED_GLOBALS = [
FILE: packages/foam-vscode/src/services/logging.ts
function getFoamLoggerLevel (line 5) | function getFoamLoggerLevel(): LogLevel {
type VsCodeLogger (line 9) | interface VsCodeLogger extends ILogger, IDisposable {
class VsCodeOutputLogger (line 13) | class VsCodeOutputLogger extends BaseLogger implements VsCodeLogger {
method constructor (line 16) | constructor() {
method log (line 21) | log(lvl: LogLevel, msg?: any, ...extra: any[]): void {
method show (line 36) | show() {
method dispose (line 39) | dispose(): void {
FILE: packages/foam-vscode/src/services/note-creation-engine.test.ts
function setupFoamEngine (line 21) | async function setupFoamEngine() {
FILE: packages/foam-vscode/src/services/note-creation-engine.ts
constant FILEPATH_UNALLOWED_CHARS (line 19) | const FILEPATH_UNALLOWED_CHARS = '<>?*"|';
function sanitizeFilepath (line 26) | function sanitizeFilepath(filepath: string): string {
class NoteCreationEngine (line 36) | class NoteCreationEngine {
method constructor (line 37) | constructor(private foam: Foam) {}
method processTemplate (line 48) | async processTemplate(
method executeJSTemplate (line 78) | private async executeJSTemplate(
method executeMarkdownTemplate (line 115) | private async executeMarkdownTemplate(
method generateDefaultFilepath (line 157) | private async generateDefaultFilepath(resolver: Resolver): Promise<str...
method validateNoteCreationResult (line 166) | private validateNoteCreationResult(
method logTriggerInfo (line 203) | private logTriggerInfo(trigger: NoteCreationTrigger): void {
FILE: packages/foam-vscode/src/services/note-creation-triggers.ts
class TriggerFactory (line 9) | class TriggerFactory {
method createCommandTrigger (line 17) | static createCommandTrigger(
method createPlaceholderTrigger (line 32) | static createPlaceholderTrigger(
FILE: packages/foam-vscode/src/services/note-creation-types.ts
type NoteCreationTrigger (line 10) | type NoteCreationTrigger =
type Template (line 28) | type Template =
type TemplateContext (line 38) | interface TemplateContext {
type NoteCreationResult (line 56) | interface NoteCreationResult {
type CreateNoteFunction (line 64) | type CreateNoteFunction = (
function isCommandTrigger (line 71) | function isCommandTrigger(
function isPlaceholderTrigger (line 80) | function isPlaceholderTrigger(
FILE: packages/foam-vscode/src/services/template-loader.ts
class TemplateLoader (line 15) | class TemplateLoader {
method constructor (line 18) | constructor() {
method loadTemplate (line 27) | async loadTemplate(template: URI): Promise<Template> {
method loadJavaScriptTemplate (line 43) | private async loadJavaScriptTemplate(template: URI): Promise<Template> {
method loadMarkdownTemplate (line 65) | private async loadMarkdownTemplate(template: URI): Promise<Template> {
FILE: packages/foam-vscode/src/services/templates.ts
constant DEFAULT_NEW_NOTE_TEMPLATE (line 82) | const DEFAULT_NEW_NOTE_TEMPLATE = `# \${1:$TM_FILENAME_BASE}
function getTemplateMetadata (line 101) | async function getTemplateMetadata(
function getTemplates (line 109) | async function getTemplates(): Promise<URI[]> {
function getTemplateInfo (line 117) | async function getTemplateInfo(
type OnFileExistStrategy (line 137) | type OnFileExistStrategy =
type OnRelativePathStrategy (line 144) | type OnRelativePathStrategy =
function askUserForTemplate (line 151) | async function askUserForTemplate() {
function offerToCreateTemplate (line 202) | async function offerToCreateTemplate(): Promise<void> {
function sortTemplatesMetadata (line 213) | function sortTemplatesMetadata(
function askUserForFilepathConfirmation (line 402) | async function askUserForFilepathConfirmation(
FILE: packages/foam-vscode/src/services/variable-resolver.spec.ts
function getISOWeekYear (line 160) | function getISOWeekYear(date: Date): number {
FILE: packages/foam-vscode/src/services/variable-resolver.ts
class Resolver (line 37) | class Resolver implements VariableResolver {
method constructor (line 45) | constructor(
method define (line 61) | define(name: string, value: string) {
method getVariables (line 71) | getVariables(): Record<string, string> {
method resolveText (line 82) | async resolveText(text: string): Promise<string> {
method resolveAll (line 122) | async resolveAll(variables: Variable[]): Promise<Map<string, string>> {
method resolveFromName (line 140) | async resolveFromName(name: string): Promise<string> {
method resolve (line 147) | async resolve(variable: Variable): Promise<string | undefined> {
function resolveFoamTitle (line 290) | async function resolveFoamTitle() {
function resolveFoamSelectedText (line 303) | function resolveFoamSelectedText() {
function resolveFoamCurrentDir (line 307) | function resolveFoamCurrentDir() {
constant UNALLOWED_CHARS (line 331) | const UNALLOWED_CHARS = '/\\#%&{}<>?*$!\'":@+`|=';
FILE: packages/foam-vscode/src/services/watcher.ts
class VsCodeWatcher (line 8) | class VsCodeWatcher implements IWatcher, IDisposable {
method constructor (line 16) | constructor(private readonly vsCodeWatcher: FileSystemWatcher) {
method dispose (line 27) | dispose(): void {
FILE: packages/foam-vscode/src/settings.ts
function getNotesExtensions (line 11) | function getNotesExtensions() {
function getAttachmentsExtensions (line 36) | function getAttachmentsExtensions() {
function getExcludedFilesSetting (line 43) | function getExcludedFilesSetting(): GlobPattern[] {
function getDirectoryModeSetting (line 53) | function getDirectoryModeSetting(): 'resolve' | 'disabled' {
function getIncludeFilesSetting (line 58) | function getIncludeFilesSetting(): GlobPattern[] {
FILE: packages/foam-vscode/src/test/run-tests.ts
function parseArgs (line 5) | function parseArgs(): {
function getVSCodePlatform (line 26) | function getVSCodePlatform(): string {
function main (line 39) | async function main() {
FILE: packages/foam-vscode/src/test/suite-unit.ts
function parseJestArgs (line 27) | function parseJestArgs(args: string[]): any {
function getUnitReadySpecFiles (line 64) | function getUnitReadySpecFiles(rootDir: string): string[] {
function runUnit (line 91) | function runUnit(
FILE: packages/foam-vscode/src/test/suite.ts
function run (line 27) | function run(): Promise<void> {
FILE: packages/foam-vscode/src/test/support/vscode-environment.js
class VscodeEnvironment (line 4) | class VscodeEnvironment extends TestEnvironment {
method setup (line 5) | async setup() {
method teardown (line 21) | async teardown() {
FILE: packages/foam-vscode/src/test/test-datastore.ts
function getFiles (line 10) | function getFiles(directory: string) {
function getFilesFromDir (line 15) | function getFilesFromDir(files: string[], directory: string) {
class FileDataStore (line 28) | class FileDataStore implements IDataStore {
method constructor (line 29) | constructor(
method list (line 34) | async list(): Promise<URI[]> {
method read (line 39) | async read(uri: URI) {
class Matcher (line 63) | class Matcher implements IMatcher {
method constructor (line 68) | constructor(
method match (line 89) | match(files: URI[]) {
method isMatch (line 102) | isMatch(uri: URI) {
method refresh (line 106) | refresh(): Promise<void> {
FILE: packages/foam-vscode/src/test/test-utils-vscode.ts
function makeFoamMock (line 21) | function makeFoamMock() {
FILE: packages/foam-vscode/src/test/test-utils.ts
class InMemoryDataStore (line 22) | class InMemoryDataStore implements IDataStore {
method set (line 28) | set(uri: URI, content: string): void {
method delete (line 35) | delete(uri: URI): void {
method clear (line 42) | clear(): void {
method list (line 46) | async list(): Promise<URI[]> {
method read (line 50) | async read(uri: URI): Promise<string | null> {
constant TEST_DATA_DIR (line 55) | const TEST_DATA_DIR = URI.file(__dirname).joinPath(
FILE: packages/foam-vscode/src/test/vscode-mock.ts
type Thenable (line 28) | interface Thenable<T> {
class Position (line 41) | class Position implements FoamPosition {
method constructor (line 44) | constructor(line: number, character: number) {
method create (line 48) | static create(line: number, character: number): Position {
method compareTo (line 53) | compareTo(other: Position): number {
method isAfter (line 61) | isAfter(other: Position): boolean {
method isAfterOrEqual (line 65) | isAfterOrEqual(other: Position): boolean {
method isBefore (line 69) | isBefore(other: Position): boolean {
method isBeforeOrEqual (line 73) | isBeforeOrEqual(other: Position): boolean {
method isEqual (line 77) | isEqual(other: Position): boolean {
method translate (line 85) | translate(
method with (line 109) | with(
method isAfter (line 128) | static isAfter(a: Position, b: Position): boolean {
method isAfterOrEqual (line 132) | static isAfterOrEqual(a: Position, b: Position): boolean {
method isBefore (line 136) | static isBefore(a: Position, b: Position): boolean {
method isBeforeOrEqual (line 140) | static isBeforeOrEqual(a: Position, b: Position): boolean {
method isEqual (line 144) | static isEqual(a: Position, b: Position): boolean {
method compareTo (line 148) | static compareTo(a: Position, b: Position): number {
class Range (line 154) | class Range implements FoamRange {
method constructor (line 165) | constructor(
method create (line 181) | static create(
method createFromPosition (line 195) | static createFromPosition(start: Position, end?: Position): Range {
type Uri (line 201) | interface Uri {
function createVSCodeUri (line 222) | function createVSCodeUri(foamUri: URI): Uri {
function fromVsCodeUri (line 266) | function fromVsCodeUri(vsCodeUri: Uri): URI {
method file (line 273) | file(path: string): Uri {
method parse (line 277) | parse(value: string): Uri {
method from (line 281) | from(components: {
method joinPath (line 297) | joinPath(base: Uri, ...pathSegments: string[]): Uri {
class Location (line 304) | class Location {
method constructor (line 305) | constructor(public uri: Uri, public range: Range) {}
type SymbolKind (line 309) | enum SymbolKind {
class SymbolInformation (line 339) | class SymbolInformation {
method constructor (line 340) | constructor(
class Selection (line 349) | class Selection extends Range {
method constructor (line 360) | constructor(
method isReversed (line 381) | get isReversed(): boolean {
method isEmpty (line 385) | get isEmpty(): boolean {
type EndOfLine (line 391) | enum EndOfLine {
type ViewColumn (line 396) | enum ViewColumn {
type FileType (line 404) | enum FileType {
type CompletionItemKind (line 411) | enum CompletionItemKind {
type DiagnosticSeverity (line 439) | enum DiagnosticSeverity {
type ProgressLocation (line 446) | enum ProgressLocation {
class CodeActionKind (line 454) | class CodeActionKind {
method constructor (line 471) | constructor(public readonly value: string) {}
class CodeAction (line 474) | class CodeAction {
method constructor (line 483) | constructor(title: string, kind?: CodeActionKind) {
class CompletionItem (line 491) | class CompletionItem {
method constructor (line 504) | constructor(label: string, kind?: CompletionItemKind) {
class CompletionList (line 510) | class CompletionList {
method constructor (line 514) | constructor(items: CompletionItem[] = [], isIncomplete = false) {
class MarkdownString (line 522) | class MarkdownString {
method constructor (line 526) | constructor(value?: string) {
method appendText (line 530) | appendText(value: string): MarkdownString {
method appendMarkdown (line 535) | appendMarkdown(value: string): MarkdownString {
method appendCodeblock (line 540) | appendCodeblock(value: string, language?: string): MarkdownString {
class Hover (line 546) | class Hover {
method constructor (line 550) | constructor(
class TreeItem (line 565) | class TreeItem {
method constructor (line 576) | constructor(label: string, collapsibleState?: number) {
type TreeItemCollapsibleState (line 582) | enum TreeItemCollapsibleState {
class ThemeColor (line 590) | class ThemeColor {
method constructor (line 591) | constructor(public readonly id: string) {}
class ThemeIcon (line 594) | class ThemeIcon {
method constructor (line 598) | constructor(id: string, color?: ThemeColor) {
type Event (line 609) | interface Event<T> {
type Disposable (line 613) | interface Disposable {
type CancellationToken (line 619) | interface CancellationToken {
class CancellationTokenSource (line 624) | class CancellationTokenSource {
method token (line 629) | get token(): CancellationToken {
method cancel (line 640) | cancel(): void {
method dispose (line 653) | dispose(): void {
type Progress (line 664) | interface Progress<T> {
class EventEmitter (line 668) | class EventEmitter<T> {
method event (line 671) | get event(): Event<T> {
method fire (line 686) | fire(data: T): void {
method dispose (line 696) | dispose(): void {
class Diagnostic (line 703) | class Diagnostic {
method constructor (line 711) | constructor(range: Range, message: string, severity?: DiagnosticSeveri...
class SnippetString (line 720) | class SnippetString {
method constructor (line 723) | constructor(value?: string) {
method appendText (line 727) | appendText(string: string): SnippetString {
method appendTabstop (line 731) | appendTabstop(number?: number): SnippetString {
method appendPlaceholder (line 735) | appendPlaceholder(
method appendChoice (line 743) | appendChoice(values: string[], number?: number): SnippetString {
method appendVariable (line 749) | appendVariable(
type WorkspaceConfiguration (line 760) | interface WorkspaceConfiguration {
class MockWorkspaceConfiguration (line 781) | class MockWorkspaceConfiguration implements WorkspaceConfiguration {
method get (line 784) | get<T>(section: string, defaultValue?: T): T {
method has (line 788) | has(section: string): boolean {
method inspect (line 792) | inspect<T>(section: string):
method update (line 807) | update(
type TextLine (line 819) | interface TextLine {
type TextDocument (line 828) | interface TextDocument {
class MockTextDocument (line 850) | class MockTextDocument implements TextDocument {
method constructor (line 863) | constructor(uri: Uri, content?: string) {
method lineCount (line 901) | get lineCount(): number {
method save (line 905) | async save(): Promise<boolean> {
method getText (line 914) | getText(range?: Range): string {
method lineAt (line 924) | lineAt(lineOrPosition: number | Position): TextLine {
method offsetAt (line 946) | offsetAt(position: Position): number {
method positionAt (line 957) | positionAt(offset: number): Position {
method validatePosition (line 972) | validatePosition(position: Position): Position {
method validateRange (line 981) | validateRange(range: Range): Range {
method getWordRangeAtPosition (line 987) | getWordRangeAtPosition(position: Position): Range | undefined {
method _updateContent (line 1007) | _updateContent(content: string): void {
type TextEditor (line 1024) | interface TextEditor {
class MockTextEditor (line 1039) | class MockTextEditor implements TextEditor {
method constructor (line 1046) | constructor(document: TextDocument, viewColumn?: ViewColumn) {
method edit (line 1053) | async edit(callback: (editBuilder: any) => void): Promise<boolean> {
method insertSnippet (line 1084) | async insertSnippet(snippet: any): Promise<boolean> {
method setDecorations (line 1107) | setDecorations(decorationType: any, ranges: Range[]): void {
method revealRange (line 1111) | revealRange(range: Range): void {
method show (line 1115) | show(column?: ViewColumn): void {
method hide (line 1119) | hide(): void {
class TextEdit (line 1126) | class TextEdit {
method constructor (line 1127) | constructor(public range: Range, public newText: string) {}
method replace (line 1129) | static replace(range: Range, newText: string): TextEdit {
method insert (line 1133) | static insert(position: Position, newText: string): TextEdit {
method delete (line 1137) | static delete(range: Range): TextEdit {
class WorkspaceEdit (line 1144) | class WorkspaceEdit {
method replace (line 1147) | replace(uri: Uri, range: Range, newText: string): void {
method insert (line 1155) | insert(uri: Uri, position: Position, newText: string): void {
method delete (line 1165) | delete(uri: Uri, range: Range): void {
method renameFile (line 1173) | renameFile(
method set (line 1185) | set(uri: Uri, edits: TextEdit[]): void {
method get (line 1193) | get(uri: Uri): TextEdit[] | undefined {
method entries (line 1198) | entries(): [Uri, TextEdit[]][] {
method _getEdits (line 1211) | _getEdits(): Map<string, any[]> {
method size (line 1215) | get size(): number {
type FileSystem (line 1222) | interface FileSystem {
class MockFileSystem (line 1243) | class MockFileSystem implements FileSystem {
method readFile (line 1244) | async readFile(uri: Uri): Promise<Uint8Array> {
method writeFile (line 1249) | async writeFile(uri: Uri, content: Uint8Array): Promise<void> {
method exists (line 1268) | private async exists(uri: Uri): Promise<boolean> {
method delete (line 1277) | async delete(uri: Uri, options?: { recursive?: boolean }): Promise<voi...
method stat (line 1308) | async stat(
method readDirectory (line 1320) | async readDirectory(uri: Uri): Promise<[string, number][]> {
method createDirectory (line 1330) | async createDirectory(uri: Uri): Promise<void> {
method copy (line 1334) | async copy(
method rename (line 1342) | async rename(
type FileSystemWatcher (line 1359) | interface FileSystemWatcher extends Disposable {
class MockFileSystemWatcher (line 1368) | class MockFileSystemWatcher implements FileSystemWatcher {
method constructor (line 1381) | constructor(private pattern: string) {
method _fireCreate (line 1389) | _fireCreate(uri: Uri) {
method _fireChange (line 1395) | _fireChange(uri: Uri) {
method _fireDelete (line 1401) | _fireDelete(uri: Uri) {
method matches (line 1407) | private matches(uri: Uri): boolean {
method dispose (line 1416) | dispose() {
type WorkspaceFolder (line 1431) | interface WorkspaceFolder {
type ExtensionContext (line 1439) | interface ExtensionContext {
function createMockExtensionContext (line 1459) | function createMockExtensionContext(): ExtensionContext {
type Extension (line 1509) | interface Extension<T> {
class MockExtension (line 1518) | class MockExtension<T> implements Extension<T> {
method constructor (line 1519) | constructor(
method activate (line 1528) | activate(): Thenable<T> {
function collectFilesRecursively (line 1536) | async function collectFilesRecursively(dir: string): Promise<string[]> {
class TestFoam (line 1557) | class TestFoam {
method getInstance (line 1560) | static async getInstance(): Promise<Foam> {
method bootstrap (line 1567) | static async bootstrap(): Promise<Foam> {
method reloadFoamWorkspace (line 1659) | static async reloadFoamWorkspace(): Promise<void> {
method dispose (line 1675) | static dispose() {
function initializeFoamCommands (line 1689) | async function initializeFoamCommands(foam: Foam): Promise<void> {
method activeTextEditor (line 1742) | get activeTextEditor(): TextEditor | undefined {
method activeTextEditor (line 1746) | set activeTextEditor(editor: TextEditor | undefined) {
method visibleTextEditors (line 1750) | get visibleTextEditors(): TextEditor[] {
method showInputBox (line 1754) | async showInputBox(options?: {
method showQuickPick (line 1765) | async showQuickPick(items: any[], options?: any): Promise<any> {
method showTextDocument (line 1771) | async showTextDocument(
method showInformationMessage (line 1807) | async showInformationMessage(
method showWarningMessage (line 1815) | async showWarningMessage(
method showErrorMessage (line 1823) | async showErrorMessage(
method withProgress (line 1833) | async withProgress<R>(
method workspaceFolders (line 1861) | get workspaceFolders(): WorkspaceFolder[] | undefined {
method fs (line 1867) | get fs(): FileSystem {
method createFileSystemWatcher (line 1871) | createFileSystemWatcher(globPattern: string): FileSystemWatcher {
method getConfiguration (line 1875) | getConfiguration(section?: string): WorkspaceConfiguration {
method findFiles (line 1891) | async findFiles(
method getWorkspaceFolder (line 1950) | getWorkspaceFolder(uri: Uri): WorkspaceFolder | undefined {
method onWillSaveTextDocument (line 1957) | onWillSaveTextDocument(listener: (e: any) => void): Disposable {
method onWillRenameFiles (line 1966) | onWillRenameFiles(listener: (e: any) => any): Disposable {
method onDidRenameFiles (line 1978) | onDidRenameFiles(listener: (e: any) => any): Disposable {
method onWillDeleteFiles (line 1990) | onWillDeleteFiles(listener: (e: any) => any): Disposable {
method onDidChangeConfiguration (line 2002) | onDidChangeConfiguration(listener: (e: any) => void): Disposable {
method openTextDocument (line 2006) | async openTextDocument(
method applyEdit (line 2039) | async applyEdit(edit: WorkspaceEdit): Promise<boolean> {
method asRelativePath (line 2149) | asRelativePath(
method isTrusted (line 2168) | get isTrusted(): boolean {
method registerCommand (line 2176) | registerCommand(
method executeCommand (line 2188) | async executeCommand<T = unknown>(
method registerCodeLensProvider (line 2208) | registerCodeLensProvider(selector: any, provider: any): Disposable {
method registerWorkspaceSymbolProvider (line 2217) | registerWorkspaceSymbolProvider(provider: any): Disposable {
method getExtension (line 2229) | getExtension<T = any>(extensionId: string): Extension<T> | undefined {
method all (line 2244) | get all(): Extension<any>[] {
method writeText (line 2262) | async writeText(value: string): Promise<void> {
method readText (line 2266) | async readText(): Promise<string> {
function initializeWorkspace (line 2281) | function initializeWorkspace(workspaceRoot: string): void {
function resetMockState (line 2295) | function resetMockState(): void {
function forceCleanup (line 2342) | async function forceCleanup(): Promise<void> {
FILE: packages/foam-vscode/src/types.d.ts
type FoamFeature (line 4) | type FoamFeature = (
FILE: packages/foam-vscode/src/utils/commands.ts
type CommandDescriptor (line 4) | interface CommandDescriptor<T> {
function describeCommand (line 9) | function describeCommand<T>(
function commandAsURI (line 16) | function commandAsURI<T>(command: CommandDescriptor<T>) {
FILE: packages/foam-vscode/src/utils/globExpand.ts
function expandAlternateGroups (line 6) | function expandAlternateGroups(pattern: string): GlobPattern[] {
FILE: packages/foam-vscode/src/utils/template-frontmatter-parser.ts
function extractFoamTemplateFrontmatterMetadata (line 3) | function extractFoamTemplateFrontmatterMetadata(
function removeFoamMetadata (line 52) | function removeFoamMetadata(contents: string) {
FILE: packages/foam-vscode/src/utils/vsc-utils.ts
class ContextMemento (line 86) | class ContextMemento<T> {
method constructor (line 87) | constructor(
method get (line 97) | public get(): T {
method update (line 100) | public async update(value: T): Promise<void> {
class MapBasedMemento (line 109) | class MapBasedMemento implements Memento {
method get (line 110) | get<T>(key: unknown, defaultValue?: unknown | T): T | T {
method keys (line 114) | keys(): readonly string[] {
method update (line 117) | update(key: string, value: any): Promise<void> {
FILE: packages/foam-vscode/static/preview/block-anchor-scroll.js
constant BLOCK_ANCHOR_PREFIX (line 21) | const BLOCK_ANCHOR_PREFIX = '__';
constant FRAGMENT_STORAGE_KEY (line 22) | const FRAGMENT_STORAGE_KEY = 'foam-block-anchor-fragment';
function scrollToBlockAnchor (line 24) | function scrollToBlockAnchor(fragment) {
function getFragmentFromSettings (line 36) | function getFragmentFromSettings() {
function getPendingFragment (line 50) | function getPendingFragment() {
function tryScrollFromContext (line 62) | function tryScrollFromContext() {
FILE: packages/foam-vscode/webview-ui/graph/build.cjs
method setup (line 15) | setup(build) {
function buildLibTarget (line 27) | async function buildLibTarget() {
function buildVscodeTarget (line 45) | async function buildVscodeTarget() {
function main (line 89) | async function main() {
FILE: packages/foam-vscode/webview-ui/graph/src/components/control-panel.ts
class ControlPanel (line 7) | class ControlPanel extends LitElement {
method _nodeTypes (line 114) | private get _nodeTypes() {
method render (line 118) | render() {
method _emit (line 252) | private _emit(eventName: string, detail: unknown) {
method _emitShowNodesOfTypeChange (line 256) | private _emitShowNodesOfTypeChange(type: string, checked: boolean) {
method _emitForcesChange (line 260) | private _emitForcesChange(patch: Partial<Forces>) {
method _emitSelectionChange (line 264) | private _emitSelectionChange(patch: Partial<Selection>) {
type HTMLElementTagNameMap (line 270) | interface HTMLElementTagNameMap {
FILE: packages/foam-vscode/webview-ui/graph/src/components/graph-canvas.ts
class GraphCanvas (line 23) | class GraphCanvas extends LitElement {
method createRenderRoot (line 63) | protected createRenderRoot() {
method render (line 68) | render() {
method firstUpdated (line 72) | firstUpdated() {
method disconnectedCallback (line 170) | disconnectedCallback() {
method updated (line 175) | updated(changed: Map<string, unknown>) {
method selectNote (line 233) | selectNote(noteId: string) {
method _updateFocusSets (line 248) | private _updateFocusSets() {
method _selectNode (line 261) | private _selectNode(nodeId: string | null, isAppend: boolean) {
method _updateGraphData (line 267) | private _updateGraphData() {
type HTMLElementTagNameMap (line 319) | interface HTMLElementTagNameMap {
FILE: packages/foam-vscode/webview-ui/graph/src/foam-graph.ts
class FoamGraph (line 11) | class FoamGraph extends LitElement {
method resolvedStyle (line 40) | private get resolvedStyle(): ResolvedStyle {
method _mergedStylePayload (line 44) | private get _mergedStylePayload(): StylePayload {
method _resolveStyle (line 53) | private _resolveStyle(payload: StylePayload | null): ResolvedStyle {
method updated (line 71) | updated(changed: Map<string, unknown>) {
method _syncNodeTypes (line 78) | private _syncNodeTypes(graph: AugmentedGraph) {
method render (line 99) | render() {
method selectNote (line 129) | selectNote(noteId: string) {
method _onNodeClick (line 134) | private _onNodeClick(nodeId: string) {
method _onStyleChange (line 138) | private _onStyleChange(patch: Partial<ResolvedStyle>) {
type HTMLElementTagNameMap (line 149) | interface HTMLElementTagNameMap {
FILE: packages/foam-vscode/webview-ui/graph/src/lib/colors.ts
function getNodeTypeColor (line 5) | function getNodeTypeColor(type: string, style: ResolvedStyle): string {
function hashString (line 9) | function hashString(str: string): number {
function hashToHSL (line 18) | function hashToHSL(hash: number): string {
function getDirectoryColor (line 25) | function getDirectoryColor(nodeId: string): string {
function getNodeFillAndBorder (line 37) | function getNodeFillAndBorder(
function getLinkColor (line 67) | function getLinkColor(
FILE: packages/foam-vscode/webview-ui/graph/src/lib/defaults.ts
function getCSSVar (line 3) | function getCSSVar(name: string): string {
function getDefaultStyle (line 7) | function getDefaultStyle(): ResolvedStyle {
FILE: packages/foam-vscode/webview-ui/graph/src/lib/graph-utils.ts
function getLinkNodeId (line 4) | function getLinkNodeId(endpoint: string | AugmentedNode): string {
function augmentGraphInfo (line 8) | function augmentGraphInfo(graph: GraphData): AugmentedGraph {
function getNeighbors (line 70) | function getNeighbors(
function computeFocusSets (line 91) | function computeFocusSets(
function getNodeState (line 121) | function getNodeState(
function getLinkState (line 132) | function getLinkState(
FILE: packages/foam-vscode/webview-ui/graph/src/lib/painter.ts
type Circle (line 3) | interface Circle {
type Label (line 9) | interface Label {
class Painter (line 18) | class Painter {
method _addCircle (line 23) | private _addCircle(
method _areSameColor (line 36) | private _areSameColor(a: RGBColor, b: RGBColor): boolean {
method circle (line 40) | circle(x: number, y: number, radius: number, fill: RGBColor, border: R...
method text (line 48) | text(
method paint (line 62) | paint(ctx: CanvasRenderingContext2D): this {
FILE: packages/foam-vscode/webview-ui/graph/src/lib/types.ts
type AugmentedNode (line 3) | interface AugmentedNode extends NodeInfo {
type AugmentedLink (line 8) | interface AugmentedLink {
type AugmentedGraph (line 13) | interface AugmentedGraph {
type ResolvedStyle (line 18) | interface ResolvedStyle {
type NodeState (line 35) | type NodeState = 'regular' | 'highlighted' | 'lessened';
type LinkState (line 36) | type LinkState = 'regular' | 'highlighted' | 'lessened';
type Forces (line 38) | interface Forces {
type Selection (line 45) | interface Selection {
FILE: packages/foam-vscode/webview-ui/graph/src/protocol.ts
type NodeType (line 6) | type NodeType =
type NodeInfo (line 14) | interface NodeInfo {
type GraphData (line 22) | interface GraphData {
type StyleConfig (line 27) | interface StyleConfig {
type StylePayload (line 47) | interface StylePayload {
type ExtensionMessage (line 53) | type ExtensionMessage =
type WebviewMessage (line 59) | type WebviewMessage =
Condensed preview — 379 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,016K chars).
[
{
"path": ".all-contributorsrc",
"chars": 31975,
"preview": "{\n \"projectName\": \"foam\",\n \"projectOwner\": \"foambubble\",\n \"repoType\": \"github\",\n \"repoHost\": \"https://github.com\",\n "
},
{
"path": ".claude/commands/prepare-pr.md",
"chars": 1294,
"preview": "# Prepare PR Command\n\nAnalyze the current branch changes and generate:\n\n- a PR title\n- a PR description\n- considerations"
},
{
"path": ".claude/commands/research-issue.md",
"chars": 1938,
"preview": "# Research Issue Command\n\nResearch a GitHub issue by analyzing the issue details and codebase to generate a comprehensiv"
},
{
"path": ".devcontainer/devcontainer.json",
"chars": 263,
"preview": "{\n \"name\": \"Foam Dev Container\",\n \"image\": \"mcr.microsoft.com/devcontainers/typescript-node:0-18\",\n \"postCreateComman"
},
{
"path": ".editorconfig",
"chars": 36,
"preview": "indent_style = space\nindent_size = 2"
},
{
"path": ".eslintrc.json",
"chars": 1695,
"preview": "{\n \"root\": true,\n \"parser\": \"@typescript-eslint/parser\",\n \"parserOptions\": {\n \"ecmaVersion\": 6,\n \"sourceType\": "
},
{
"path": ".gitattributes",
"chars": 93,
"preview": "*.md linguist-detectable=true\n*.css linguist-detectable=false\n*.html linguist-detectable=true"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.yml",
"chars": 4064,
"preview": "name: 'Bug report'\ndescription: Create a report to help us improve\nbody:\n - type: markdown\n attributes:\n value:"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 163,
"preview": "blank_issues_enabled: true\ncontact_links:\n - name: Question\n url: https://foambubble.github.io/join-discord/g\n ab"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.yml",
"chars": 1737,
"preview": "name: Feature request\ndescription: Suggest an idea for the `Foam` project\nbody:\n - type: markdown\n attributes:\n "
},
{
"path": ".github/workflows/ci.yml",
"chars": 2053,
"preview": "name: CI\n\non:\n push:\n branches:\n - main\n pull_request:\n branches:\n - main\n\njobs:\n typos-check:\n na"
},
{
"path": ".github/workflows/update-docs.yml",
"chars": 1527,
"preview": "name: Update Docs\n\non:\n push:\n branches:\n - main\n paths:\n - docs/user/**/*\n - docs/.vscode/**/*\n "
},
{
"path": ".gitignore",
"chars": 274,
"preview": "node_modules\n.DS_Store\n.vscode-test/\n.vscode-test-web/\n*.tsbuildinfo\n*.vsix\n*.log\nout\ndist\npackages/foam-vscode/static/d"
},
{
"path": ".husky/pre-push",
"chars": 14,
"preview": "npx yarn lint\n"
},
{
"path": ".vscode/launch.json",
"chars": 1685,
"preview": "// A launch configuration that compiles the extension and then opens it inside a new window\n// Use IntelliSense to learn"
},
{
"path": ".vscode/settings.json",
"chars": 1095,
"preview": "// Place your settings in this file to overwrite default and user settings.\n{\n \"files.exclude\": {\n // set these to t"
},
{
"path": ".vscode/tasks.json",
"chars": 1148,
"preview": "// See https://go.microsoft.com/fwlink/?LinkId=733558\n// for the documentation about the tasks.json format\n{\n \"version\""
},
{
"path": ".yarnrc",
"chars": 22,
"preview": "--ignore-engines true\n"
},
{
"path": "CLAUDE.md",
"chars": 12366,
"preview": "# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## "
},
{
"path": "LICENSE",
"chars": 1665,
"preview": "The MIT Licence (MIT)\n\nCopyright 2020 - present Jani Eväkallio <jani.evakallio@gmail.com>\n\nPermission is hereby granted,"
},
{
"path": "docs/.vscode/custom-tag-style.css",
"chars": 59,
"preview": ".foam-tag{\n color:#ffffff;\n background-color: #000000;\n}\n"
},
{
"path": "docs/.vscode/extensions.json",
"chars": 473,
"preview": "{\n // See http://go.microsoft.com/fwlink/?LinkId=827846\n // for the documentation about the extensions.json format\n \""
},
{
"path": "docs/.vscode/keybindings.json",
"chars": 194,
"preview": "// This file does not get automatically applied\n// @TODO: Make it work or document how to copy to user keybindings\n[\n {"
},
{
"path": "docs/.vscode/settings.json",
"chars": 573,
"preview": "{\n \"files.autoSave\": \"onFocusChange\",\n \"editor.minimap.enabled\": false,\n \"editor.wrappingIndent\": \"indent\",\n \"editor"
},
{
"path": "docs/404.md",
"chars": 277,
"preview": "# Page not found!\n\nWell, that shouldn't have happened!\n\nIf you got here via a link from another document, please file an"
},
{
"path": "docs/CNAME",
"chars": 13,
"preview": "foamnotes.com"
},
{
"path": "docs/Gemfile",
"chars": 1264,
"preview": "source \"https://rubygems.org\"\n\n# Hello! This is where you manage which Jekyll version is used to run.\n# When you want to"
},
{
"path": "docs/LICENSE.txt",
"chars": 1665,
"preview": "The MIT Licence (MIT)\n\nCopyright 2020 - present Jani Eväkallio <jani.evakallio@gmail.com>\n\nPermission is hereby granted,"
},
{
"path": "docs/_config.yml",
"chars": 47,
"preview": "title: Foam\ngoogle_analytics: \"UA-171027939-1\"\n"
},
{
"path": "docs/_layouts/foam.html",
"chars": 1540,
"preview": "---\nlayout: default\n---\n\n<script type=\"text/javascript\">\n// NOTE: this should be in sync with the settings/usage in the "
},
{
"path": "docs/_layouts/home.html",
"chars": 345,
"preview": "---\nlayout: foam\n---\n\n<script async defer src=\"https://buttons.github.io/buttons.js\"></script>\n\n{{ content }}\n\n<script>\n"
},
{
"path": "docs/_layouts/mathjax.html",
"chars": 383,
"preview": "---\nlayout: foam\n---\n\n{{ content }}\n\n<script src=\"https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS-MML_H"
},
{
"path": "docs/_layouts/page.html",
"chars": 36,
"preview": "---\nlayout: foam\n---\n\n{{ content }}\n"
},
{
"path": "docs/assets/css/style.scss",
"chars": 1139,
"preview": "---\n---\n\n@import \"{{ site.theme }}\";\n\na {\n color: #3300ff;\n}\n\n.markdown-body {\n max-width: 800px;\n font-size: 16px;\n}"
},
{
"path": "docs/dev/about-docs.md",
"chars": 1021,
"preview": "# Developing documentation\n\nThe best way to develop docs for the Foam repo is to directly open the `$foam-repo/docs/` as"
},
{
"path": "docs/dev/build-vs-assemble.md",
"chars": 1147,
"preview": "# Build vs Assemble\n\nThe Foam prototype is built by assembling third-party extensions, which seems like a good strategy "
},
{
"path": "docs/dev/code-of-conduct.md",
"chars": 5352,
"preview": "---\nredirect_from:\n - /code-of-conduct\n---\n\n# Code of Conduct\n\nWe follow the [Contributor Covenant](https://www.contrib"
},
{
"path": "docs/dev/contribution-guide.md",
"chars": 6821,
"preview": "---\ntags: todo, good-first-task\n---\n\n# Contribution Guide\n\nFoam is open to contributions of any kind, including but not "
},
{
"path": "docs/dev/devcontainers.md",
"chars": 616,
"preview": "# Using Dev Containers\n\nFoam provides a [devcontainer](https://devcontainer.ai/) configuration to make it easy to contri"
},
{
"path": "docs/dev/foam-file-format.md",
"chars": 1109,
"preview": "# Foam File Format\n\nThis file is an example of a valid Foam file. Essentially it's just a markdown file with a bit of ad"
},
{
"path": "docs/dev/good-first-task.md",
"chars": 348,
"preview": "# Good First Task\n\nSee the backlinks of this page for good first contribution opportunities.\n\n[[materialized-backlinks]]"
},
{
"path": "docs/dev/mdx-by-default.md",
"chars": 402,
"preview": "# MDX by Default(stub)\n\n**[[todo]] This [[roadmap]] item needs more specification work.**\n\nIf you're interested in worki"
},
{
"path": "docs/dev/proposals/foam-core.md",
"chars": 4765,
"preview": "# Foam Core\n\n`foam-core` is a (future) package that powers the core functionality in Foam across all platforms:\n\n- VS Co"
},
{
"path": "docs/dev/proposals/inclusion-of-notes.md",
"chars": 3073,
"preview": "# Inclusion of notes Proposal <!-- omit in TOC -->\n\nCurrently it is not possible within Foam to include other notes into"
},
{
"path": "docs/dev/proposals/link-reference-definition-improvements.md",
"chars": 7889,
"preview": "# Link Reference Definition Improvements\n\n## Current Problems\n\n### File-by-file Insertion\n\nFor the time being, if you wa"
},
{
"path": "docs/dev/proposals/materialized-backlinks.md",
"chars": 689,
"preview": "# Materialized Backlinks (stub)\n\n**[[todo]] This [[roadmap]] item needs more specification work.**\n\nIf you're interested"
},
{
"path": "docs/dev/proposals/roadmap.md",
"chars": 5156,
"preview": "# Roadmap\n\nSome of these items can be achieved by combining existing tools, but others may require us to build bespoke s"
},
{
"path": "docs/dev/proposals/wikilinks-in-foam.md",
"chars": 4801,
"preview": "# Wikilinks in Foam\n\nFoam supports standard wikilinks in the format `[[wikilink]]`.\n\nWikilinks can refer to any note or "
},
{
"path": "docs/dev/publishing-permissions.md",
"chars": 490,
"preview": "# Publishing Permissions(stub)\n\n**[[todo]] This [[roadmap]] item needs more specification work.**\n\nIf you're interested "
},
{
"path": "docs/dev/releasing-foam.md",
"chars": 832,
"preview": "# Releasing Foam\n\n1. Get to the latest code\n - `git checkout main && git fetch && git rebase`\n2. Sanity checks\n - `y"
},
{
"path": "docs/dev/testing.md",
"chars": 5285,
"preview": "# Testing in Foam VS Code Extension\n\nThis document explains the testing strategy and conventions used in the Foam VS Cod"
},
{
"path": "docs/dev/todo.md",
"chars": 594,
"preview": "# Todo\n\nFeatures belong on the [[roadmap]].\n\n- [ ] Write out Roadmap\n - [ ] Isolate tasks for MLH fellows\n- [ ] Create "
},
{
"path": "docs/dev/unlinked-references.md",
"chars": 931,
"preview": "# Unlinked references (stub)\n\n**[[todo]] This [[roadmap]] item needs more specification work.**\n\nIf you're interested in"
},
{
"path": "docs/inbox.md",
"chars": 2077,
"preview": "# Inbox\n\nUncategorised thoughts, to be added\n\n- Release notes\n- Markdown Preview\n - It's possible to customise the mark"
},
{
"path": "docs/index.md",
"chars": 50860,
"preview": "# What is Foam?\n\nFoam is a personal knowledge management system built on [Visual Studio Code](https://code.visualstudio."
},
{
"path": "docs/principles.md",
"chars": 6055,
"preview": "# Principles\n\n## Table of Contents\n\n- [Principles](#principles)\n - [Table of Contents](#table-of-contents)\n - [Foam en"
},
{
"path": "docs/user/features/backlinking.md",
"chars": 2485,
"preview": "# Backlinks\n\nBacklinks are one of Foam's most powerful features for knowledge discovery. They automatically show you whi"
},
{
"path": "docs/user/features/block-anchors.md",
"chars": 3406,
"preview": "# Block Anchors\n\nBlock anchors let you link to a specific paragraph, list item, heading, or blockquote within a note — n"
},
{
"path": "docs/user/features/commands.md",
"chars": 3004,
"preview": "# Foam Commands\n\nFoam has various commands that you can explore by calling the command palette and typing \"Foam\".\n\nIn pa"
},
{
"path": "docs/user/features/custom-markdown-preview-styles.md",
"chars": 1179,
"preview": "# Custom Markdown Preview Styles\n\nVisual Studio Code allows you to use your own CSS in the Markdown preview tab.\n\n## Ins"
},
{
"path": "docs/user/features/custom-snippets.md",
"chars": 1002,
"preview": "# Adding Custom Snippets\n\nYou can add custom snippets whilst the default set of snippets are decided by following the be"
},
{
"path": "docs/user/features/daily-notes.md",
"chars": 1645,
"preview": "# Daily Notes\n\nDaily notes allow you to quickly create and access a note file for each day.\n\n## Creating Daily Notes\n\n- "
},
{
"path": "docs/user/features/embeds.md",
"chars": 3224,
"preview": "# Note Embeds\n\nEmbeds allow you to include content from other notes directly into your current note. This is powerful fo"
},
{
"path": "docs/user/features/foam-queries.md",
"chars": 4117,
"preview": "# Foam Queries\n\nFoam Queries let you show dynamic lists, tables, and counts of notes inside the Markdown preview.\n\nUse t"
},
{
"path": "docs/user/features/graph-view.md",
"chars": 5930,
"preview": "# Graph Visualization\n\nThe graph view is one of Foam's most powerful features. It transforms your collection of notes in"
},
{
"path": "docs/user/features/link-reference-definitions.md",
"chars": 1665,
"preview": "# Link Reference Definitions\n\nLink reference definitions make your notes compatible with standard Markdown processors by"
},
{
"path": "docs/user/features/note-properties.md",
"chars": 3039,
"preview": "---\ntype: feature\nkeywords: hello world, bonjour\ntags: [hello, bonjour]\n---\n\n# Note Properties\n\nAt the top of the file y"
},
{
"path": "docs/user/features/paste-images-from-clipboard.md",
"chars": 716,
"preview": "# Paste Images from Clipboard\n\nBy installing the [vscode-paste-image](https://github.com/mushanshitiancai/vscode-paste-i"
},
{
"path": "docs/user/features/resource-filters.md",
"chars": 1629,
"preview": "# Resource Filters\n\nResource filters can be passed to some Foam commands to limit their scope.\n\nA filter supports the fo"
},
{
"path": "docs/user/features/spell-checking.md",
"chars": 686,
"preview": "# Spell Checking\n\nThere are many spell checking extensions for VS Code.\n\nThe most popular spell checker for VS Code is ["
},
{
"path": "docs/user/features/tags.md",
"chars": 2179,
"preview": "# Tags\n\nTags provide flexible categorization and organization for your notes beyond wikilinks and folders.\n\n## Creating "
},
{
"path": "docs/user/features/templates.md",
"chars": 17887,
"preview": "# Note Templates\n\nFoam supports note templates which let you customize the starting content of your notes instead of alw"
},
{
"path": "docs/user/features/wikilinks.md",
"chars": 3006,
"preview": "# Wikilinks\n\nWikilinks are internal links that connect files in your knowledge base using `[[double bracket]]` syntax.\n\n"
},
{
"path": "docs/user/frequently-asked-questions.md",
"chars": 2035,
"preview": "# Frequently Asked Questions\n\n- [Frequently Asked Questions](#frequently-asked-questions)\n - [Links/Graphs/BackLinks do"
},
{
"path": "docs/user/getting-started/first-workspace.md",
"chars": 5801,
"preview": "# Creating Your First Workspace\n\nA Foam workspace is where all your notes, ideas, and knowledge live. Think of it as you"
},
{
"path": "docs/user/getting-started/get-started-with-vscode.md",
"chars": 8214,
"preview": "# Using Foam with VS Code Features\n\nFoam builds on Visual Studio Code's powerful editing capabilities, integrating seaml"
},
{
"path": "docs/user/getting-started/installation.md",
"chars": 3033,
"preview": "# Installation\n\nGetting started with Foam is straightforward. This guide will walk you through installing everything you"
},
{
"path": "docs/user/getting-started/keyboard-shortcuts.md",
"chars": 1670,
"preview": "# Keyboard Shortcuts\n\nHere are some keyboard shortcuts you'll love when editing your notes.\n\nThis works best if you can "
},
{
"path": "docs/user/getting-started/navigation.md",
"chars": 4733,
"preview": "# Navigation in Foam\n\nNavigation is where Foam truly shines. Unlike traditional file systems or notebooks, Foam lets you"
},
{
"path": "docs/user/getting-started/note-taking-in-foam.md",
"chars": 5376,
"preview": "# Note-Taking in Foam\n\nEffective note-taking is the foundation of any knowledge management system. In Foam, you'll write"
},
{
"path": "docs/user/getting-started/recommended-extensions.md",
"chars": 2527,
"preview": "# Recommended Extensions\n\nThese extensions defined in `.vscode/extensions.json` are automatically installed when you acc"
},
{
"path": "docs/user/getting-started/sync-notes.md",
"chars": 786,
"preview": "# Sync notes with source control\n\nSource control is a way to precisely manage the history and content of a directory of "
},
{
"path": "docs/user/index.md",
"chars": 4476,
"preview": "# Using Foam\n\nFoam is a personal knowledge management system built on [Visual Studio Code](https://code.visualstudio.com"
},
{
"path": "docs/user/publishing/generate-gatsby-site.md",
"chars": 1420,
"preview": "# Generate a site using Gatsby\n\n## Using foam-gatsby-template\n\nYou can use [foam-gatsby-template](https://github.com/mat"
},
{
"path": "docs/user/publishing/math-support-with-katex.md",
"chars": 3644,
"preview": "# Katex Math Rendering\n\nApart from using the method mentioned in [[math-support-with-mathjax]], we can also use KaTeX to"
},
{
"path": "docs/user/publishing/math-support-with-mathjax.md",
"chars": 2219,
"preview": "---\nlayout: mathjax\n---\n\n# Math Support\n\nPublished Foam pages don't support math formulas by default. To enable this fea"
},
{
"path": "docs/user/publishing/publish-to-azure-devops-wiki.md",
"chars": 3950,
"preview": "# Publish to Azure DevOps Wiki\n\nPublish your Foam workspace as an Azure DevOps wiki.\n\n[Azure DevOps](https://azure.micro"
},
{
"path": "docs/user/publishing/publish-to-github-pages.md",
"chars": 2389,
"preview": "# GitHub Pages\n\n1. In VSCode workspace settings set `\"foam.edit.linkReferenceDefinitions\": \"withoutExtensions\"`\n2. Execu"
},
{
"path": "docs/user/publishing/publish-to-github.md",
"chars": 725,
"preview": "# Publish to GitHub\n\nThe standard [foam-template](https://github.com/foambubble/foam-template) is ready to be published "
},
{
"path": "docs/user/publishing/publish-to-gitlab-pages.md",
"chars": 6265,
"preview": "# GitLab Pages\n\nYou don't have to use GitHub to serve Foam pages. You can also use GitLab.\n\nGitlab pages can be kept pri"
},
{
"path": "docs/user/publishing/publish-to-netlify-with-eleventy.md",
"chars": 953,
"preview": "# Publish to Netlify with Eleventy\n\nYou can use [foam-eleventy-template](https://github.com/juanfrank77/foam-eleventy-te"
},
{
"path": "docs/user/publishing/publish-to-vercel.md",
"chars": 4433,
"preview": "# Publish to Vercel\n\nThis #recipe shows you how to deploy the default Foam website template to Vercel.\n\n[Vercel](https:/"
},
{
"path": "docs/user/publishing/publishing.md",
"chars": 1366,
"preview": "# Publishing pages\n\nFoam pages can be published.\n\nTODO add publishing TOC\n\n## Foam site generator?\n\nAnother case of the "
},
{
"path": "docs/user/recipes/add-images-to-notes.md",
"chars": 656,
"preview": "# Add images to your notes\n\nThis #recipe allows you to paste images on to your notes.\n\nVScode (since\n[1.79](https://code"
},
{
"path": "docs/user/recipes/automatic-git-syncing.md",
"chars": 926,
"preview": "# Automatically Sync with Git\n\nWith this #recipe you can regularly commit and push to git, to keep your repo in always s"
},
{
"path": "docs/user/recipes/automatically-expand-urls-to-well-titled-links.md",
"chars": 910,
"preview": "# Automatically Expand URLs to Well-Titled Links\n\nWith this #recipe you can convert a link to a fully-formed Markdown li"
},
{
"path": "docs/user/recipes/capture-notes-with-drafts-pro.md",
"chars": 4961,
"preview": "# Capture Notes With Drafts Pro\n\nWith this #recipe you can create notes on your iOS device, which will automatically be "
},
{
"path": "docs/user/recipes/capture-notes-with-shortcuts-and-github-actions.md",
"chars": 2769,
"preview": "# Capture Notes With Shortcuts and GitHub Actions\n\nWith this #recipe you can create notes on your iOS device, which will"
},
{
"path": "docs/user/recipes/diagrams-in-markdown.md",
"chars": 1276,
"preview": "# Diagrams in Markdown\n\nWe have two alternative #recipe for displaying diagrams in markdown:\n\n- [Diagrams in Markdown](#"
},
{
"path": "docs/user/recipes/export-to-pdf.md",
"chars": 2495,
"preview": "# Export to PDF\n\nThis #recipe shows how to export a note to PDF.\n\n## Required extensions\n\n- **[vscode-pandoc](https://ma"
},
{
"path": "docs/user/recipes/generate-material-for-mkdocs-site.md",
"chars": 9110,
"preview": "# Generate a site using the Material for MkDocs theme\n\nConfiguring a static-site generator (SSG) to publish your Foam pr"
},
{
"path": "docs/user/recipes/how-to-write-recipes.md",
"chars": 2025,
"preview": "# How to Write Recipes\n\nThis is an example of how to structure a Recipe. The first paragraph or two should explain the p"
},
{
"path": "docs/user/recipes/markup-converter.md",
"chars": 2163,
"preview": "# Markup Converter\n\nThis #recipe allows you to convert any document into Markdown for storing them in your notes.\n\nWe wi"
},
{
"path": "docs/user/recipes/migrating-from-obsidian.md",
"chars": 432,
"preview": "# Migrating from Obsidian (stub)\n\n**[[todo]] This [[roadmap]] item needs more specification work.**\n\nIf you're intereste"
},
{
"path": "docs/user/recipes/migrating-from-onenote.md",
"chars": 3567,
"preview": "# Migrating from OneNote\n\nThis guide mostly duplicates the instructions at the repo for the PowerShell [script](https://"
},
{
"path": "docs/user/recipes/migrating-from-roam.md",
"chars": 428,
"preview": "# Migrating from Roam (stub)\n\n**[[todo]] This [[roadmap]] item needs more specification work.**\n\nIf you're interested in"
},
{
"path": "docs/user/recipes/predefined-user-snippets.md",
"chars": 2206,
"preview": "# Pre-defined User Snippets\n\nThis #recipe allows us to introduce Roam style commands to Foam, by using [VS Code Snippets"
},
{
"path": "docs/user/recipes/real-time-collaboration.md",
"chars": 139,
"preview": "# Real-time Collaboration\n\nThis #recipe is here to just tell you that VS Code Live Share will allow you to collaborate l"
},
{
"path": "docs/user/recipes/recipes.md",
"chars": 6971,
"preview": "<!-- omit in toc -->\n\n# Recipes\n\nA #recipe is a guide, tip or strategy for getting the most out of your Foam workspace!\n"
},
{
"path": "docs/user/recipes/search-for-notes.md",
"chars": 582,
"preview": "# Search for Notes\n\nThis #recipe contains tips on how to leverage VS Code search features.\n\n[[todo]] Add more VS Code se"
},
{
"path": "docs/user/recipes/shows-image-preview-on-hover.md",
"chars": 411,
"preview": "# Shows Image Preview on Hover\n\nThis #recipe allows you to see a preview of an image on hover.\n\nUse extension: [Image pr"
},
{
"path": "docs/user/recipes/take-notes-from-mobile-phone.md",
"chars": 2756,
"preview": "# Take notes on mobile phones\n\nThis #recipe offers solutions to taking Foam notes on the go.\n\nFor the time being we have"
},
{
"path": "docs/user/recipes/web-clipper.md",
"chars": 774,
"preview": "# Web Clipper\n\nThis #recipe allows you to convert any web content into Markdown for storing them in your notes.\n\nThere a"
},
{
"path": "docs/user/recipes/write-your-notes-in-github-gist.md",
"chars": 4629,
"preview": "# Write your notes in GitHub Gist\n\nThis #recipe will allow you to persist your notes in a GitHub repository, and automat"
},
{
"path": "docs/user/tools/cli.md",
"chars": 491,
"preview": "# Command Line Interface\n\nCreate a CLI tool to allow running common Foam commands. These may include:\n\n- `foam init` - c"
},
{
"path": "docs/user/tools/foam-logging-in-vscode.md",
"chars": 674,
"preview": "# Foam logging in VsCode\n\nThe Foam extension logs details about what its doing in vscode's `Output` tab.\nGenerally this "
},
{
"path": "docs/user/tools/orphans.md",
"chars": 607,
"preview": "# Orphaned Notes\n\nFoam helps you to find orphans: notes that have neither forward links nor backlinks.\n\nOrphans can be f"
},
{
"path": "docs/user/tools/workspace-janitor.md",
"chars": 2103,
"preview": "# Janitor\n\nTo store your personal knowledge graph in markdown files instead of a database, we need some additional tooli"
},
{
"path": "lerna.json",
"chars": 112,
"preview": "{\n \"packages\": [\n \"packages/*\"\n ],\n \"npmClient\": \"yarn\",\n \"useWorkspaces\": true,\n \"version\": \"0.33.0\"\n}\n"
},
{
"path": "package.json",
"chars": 1179,
"preview": "{\n \"name\": \"foam\",\n \"version\": \"0.2.0\",\n \"description\": \"Foam\",\n \"repository\": \"git@github.com:foambubble/foam.git\","
},
{
"path": "packages/foam-vscode/.vscodeignore",
"chars": 281,
"preview": ".vscode/**\n.vscode-test/**\nout/test/**\nout/**/*.test.*\nout/**/*.spec.*\ntest-data/**\nsrc/**\nwebview-ui/**\njest.config.js\n"
},
{
"path": "packages/foam-vscode/CHANGELOG.md",
"chars": 31111,
"preview": "# Change Log\n\nAll notable changes to the \"foam-vscode\" extension will be documented in this file.\n\nCheck [Keep a Changel"
},
{
"path": "packages/foam-vscode/LICENSE",
"chars": 1665,
"preview": "The MIT Licence (MIT)\n\nCopyright 2020 - present Jani Eväkallio <jani.evakallio@gmail.com>\n\nPermission is hereby granted,"
},
{
"path": "packages/foam-vscode/README.md",
"chars": 7403,
"preview": "<div align=\"center\">\n<img src=\"assets/icon/FOAM_ICON_256.png\" width=\"100\"/>\n\n# Foam for VSCode\n\n[ Micros"
},
{
"path": "packages/foam-vscode/src/core/common/charCode.ts",
"chars": 17832,
"preview": "/*---------------------------------------------------------------------------------------------\n * Copyright (c) Micros"
},
{
"path": "packages/foam-vscode/src/core/common/errors.ts",
"chars": 5375,
"preview": "/*---------------------------------------------------------------------------------------------\n * Copyright (c) Micros"
},
{
"path": "packages/foam-vscode/src/core/common/event.ts",
"chars": 25507,
"preview": "/*---------------------------------------------------------------------------------------------\n * Copyright (c) Micros"
},
{
"path": "packages/foam-vscode/src/core/common/functional.ts",
"chars": 744,
"preview": "/*---------------------------------------------------------------------------------------------\n * Copyright (c) Micros"
},
{
"path": "packages/foam-vscode/src/core/common/iterator.ts",
"chars": 2675,
"preview": "/*---------------------------------------------------------------------------------------------\n * Copyright (c) Micros"
},
{
"path": "packages/foam-vscode/src/core/common/lifecycle.ts",
"chars": 7409,
"preview": "/*---------------------------------------------------------------------------------------------\n * Copyright (c) Micros"
},
{
"path": "packages/foam-vscode/src/core/common/linkedList.ts",
"chars": 3211,
"preview": "/*---------------------------------------------------------------------------------------------\n * Copyright (c) Micros"
},
{
"path": "packages/foam-vscode/src/core/common/platform.ts",
"chars": 5386,
"preview": "/*---------------------------------------------------------------------------------------------\n * Copyright (c) Micros"
},
{
"path": "packages/foam-vscode/src/core/common/snippetParser.test.ts",
"chars": 33514,
"preview": "/*---------------------------------------------------------------------------------------------\n * Originally taken fro"
},
{
"path": "packages/foam-vscode/src/core/common/snippetParser.ts",
"chars": 29006,
"preview": "/*---------------------------------------------------------------------------------------------\n * Originally taken fro"
},
{
"path": "packages/foam-vscode/src/core/janitor/convert-links-format.test.ts",
"chars": 2788,
"preview": "import { convertLinkFormat } from '.';\nimport { TEST_DATA_DIR } from '../../test/test-utils';\nimport { MarkdownResourceP"
},
{
"path": "packages/foam-vscode/src/core/janitor/convert-links-format.ts",
"chars": 2662,
"preview": "import { Resource, ResourceLink } from '../model/note';\nimport { URI } from '../model/uri';\nimport { FoamWorkspace } fro"
},
{
"path": "packages/foam-vscode/src/core/janitor/generate-headings.test.ts",
"chars": 2706,
"preview": "import { generateHeading } from '.';\nimport { readFileFromFs, TEST_DATA_DIR } from '../../test/test-utils';\nimport { Mar"
},
{
"path": "packages/foam-vscode/src/core/janitor/generate-headings.ts",
"chars": 1542,
"preview": "import matter from 'gray-matter';\nimport { Resource } from '../model/note';\nimport { Range } from '../model/range';\nimpo"
},
{
"path": "packages/foam-vscode/src/core/janitor/generate-link-references.test.ts",
"chars": 7124,
"preview": "import { generateLinkReferences } from '.';\nimport { createTestNote, createTestWorkspace } from '../../test/test-utils';"
},
{
"path": "packages/foam-vscode/src/core/janitor/generate-link-references.ts",
"chars": 2341,
"preview": "import { NoteLinkDefinition, Resource } from '../model/note';\nimport { Range } from '../model/range';\nimport { createMar"
},
{
"path": "packages/foam-vscode/src/core/janitor/index.ts",
"chars": 184,
"preview": "export { generateLinkReferences } from './generate-link-references';\nexport { generateHeading } from './generate-heading"
},
{
"path": "packages/foam-vscode/src/core/model/foam.ts",
"chars": 2818,
"preview": "import { IDisposable } from '../common/lifecycle';\nimport { IDataStore, IMatcher, IWatcher } from '../services/datastore"
},
{
"path": "packages/foam-vscode/src/core/model/graph.test.ts",
"chars": 20274,
"preview": "import { createTestNote, createTestWorkspace } from '../../test/test-utils';\nimport { FoamGraph } from './graph';\nimport"
},
{
"path": "packages/foam-vscode/src/core/model/graph.ts",
"chars": 4197,
"preview": "import { debounce } from 'lodash';\nimport { ResourceLink } from './note';\nimport { URI } from './uri';\nimport { FoamWork"
},
{
"path": "packages/foam-vscode/src/core/model/location.ts",
"chars": 692,
"preview": "import { Range } from './range';\nimport { URI } from './uri';\n\n/**\n * Represents a location inside a resource, such as a"
},
{
"path": "packages/foam-vscode/src/core/model/note.test.ts",
"chars": 3488,
"preview": "import { createNoteFromMarkdown } from '../../test/test-utils';\nimport { Position } from './position';\nimport { URI } fr"
},
{
"path": "packages/foam-vscode/src/core/model/note.ts",
"chars": 4900,
"preview": "import { URI } from './uri';\nimport { Range } from './range';\nimport { Position } from './position';\n\nexport interface R"
},
{
"path": "packages/foam-vscode/src/core/model/position.ts",
"chars": 2136,
"preview": "// Some code in this file coming from https://github.com/microsoft/vscode/\n// See LICENSE for details\n\nexport interface "
},
{
"path": "packages/foam-vscode/src/core/model/provider.ts",
"chars": 479,
"preview": "import { IDisposable } from '../common/lifecycle';\nimport { Resource, ResourceLink } from './note';\nimport { URI } from "
},
{
"path": "packages/foam-vscode/src/core/model/range.ts",
"chars": 1862,
"preview": "// Some code in this file coming from https://github.com/microsoft/vscode/\n// See LICENSE for details\n\nimport { Position"
},
{
"path": "packages/foam-vscode/src/core/model/tags.test.ts",
"chars": 4519,
"preview": "import { createTestNote, createTestWorkspace } from '../../test/test-utils';\nimport { FoamTags } from './tags';\nimport {"
},
{
"path": "packages/foam-vscode/src/core/model/tags.ts",
"chars": 1963,
"preview": "import { FoamWorkspace } from './workspace';\nimport { IDisposable } from '../common/lifecycle';\nimport { debounce } from"
},
{
"path": "packages/foam-vscode/src/core/model/uri.test.ts",
"chars": 5475,
"preview": "import { Logger } from '../utils/log';\nimport { asAbsoluteUri, URI } from './uri';\n\nLogger.setLevel('error');\n\ndescribe("
},
{
"path": "packages/foam-vscode/src/core/model/uri.ts",
"chars": 13841,
"preview": "// `URI` is mostly compatible with VSCode's `Uri`.\n// Having a Foam-specific URI object allows for easier maintenance of"
},
{
"path": "packages/foam-vscode/src/core/model/workspace.test.ts",
"chars": 18723,
"preview": "import { FoamWorkspace } from './workspace';\nimport { Logger } from '../utils/log';\nimport { URI } from './uri';\nimport "
},
{
"path": "packages/foam-vscode/src/core/model/workspace.ts",
"chars": 17014,
"preview": "import { Resource, ResourceLink } from './note';\nimport { URI } from './uri';\nimport { isAbsolute, getExtension, changeE"
},
{
"path": "packages/foam-vscode/src/core/query/dql.ts",
"chars": 7286,
"preview": "import { parse as parseYaml } from 'yaml';\nimport { FoamWorkspace } from '../model/workspace';\nimport { FoamGraph } from"
},
{
"path": "packages/foam-vscode/src/core/query/html.ts",
"chars": 3752,
"preview": "import { QueryDescriptor, ResourceView } from '.';\n\nexport function escapeHtml(text: string): string {\n return String(t"
},
{
"path": "packages/foam-vscode/src/core/query/index.test.ts",
"chars": 19263,
"preview": "import { Logger } from '../utils/log';\nimport { FoamGraph } from '../model/graph';\nimport { createTestNote, createTestWo"
},
{
"path": "packages/foam-vscode/src/core/query/index.ts",
"chars": 11491,
"preview": "import { Resource } from '../model/note';\nimport { FoamWorkspace } from '../model/workspace';\nimport { FoamGraph } from "
},
{
"path": "packages/foam-vscode/src/core/query/js.ts",
"chars": 4075,
"preview": "import * as vm from 'vm';\nimport { FoamWorkspace } from '../model/workspace';\nimport { FoamGraph } from '../model/graph'"
},
{
"path": "packages/foam-vscode/src/core/services/attachment-provider.ts",
"chars": 1684,
"preview": "import { Resource, ResourceLink } from '../model/note';\nimport { URI } from '../model/uri';\nimport { FoamWorkspace } fro"
},
{
"path": "packages/foam-vscode/src/core/services/datastore.test.ts",
"chars": 3122,
"preview": "import { Matcher, toMatcherPathFormat } from '../../test/test-datastore';\nimport { TEST_DATA_DIR } from '../../test/test"
},
{
"path": "packages/foam-vscode/src/core/services/datastore.ts",
"chars": 3636,
"preview": "import { URI } from '../model/uri';\nimport { Logger } from '../utils/log';\nimport { Event } from '../common/event';\n\n/**"
},
{
"path": "packages/foam-vscode/src/core/services/heading-edit.test.ts",
"chars": 14521,
"preview": "import {\n createNoteFromMarkdown,\n createTestWorkspace,\n} from '../../test/test-utils';\nimport { FoamGraph } from '../"
},
{
"path": "packages/foam-vscode/src/core/services/heading-edit.ts",
"chars": 8775,
"preview": "import { FoamGraph } from '../model/graph';\nimport { FoamWorkspace } from '../model/workspace';\nimport { URI } from '../"
},
{
"path": "packages/foam-vscode/src/core/services/markdown-link.test.ts",
"chars": 26089,
"preview": "import { getRandomURI } from '../../test/test-utils';\nimport { ResourceLink } from '../model/note';\nimport { Range } fro"
},
{
"path": "packages/foam-vscode/src/core/services/markdown-link.ts",
"chars": 4633,
"preview": "import { ResourceLink } from '../model/note';\nimport { URI } from '../model/uri';\nimport { TextEdit } from './text-edit'"
},
{
"path": "packages/foam-vscode/src/core/services/markdown-parser.test.ts",
"chars": 32395,
"preview": "import {\n createMarkdownParser,\n getBlockFor,\n ParserPlugin,\n} from './markdown-parser';\nimport { NoteLinkDefinition,"
},
{
"path": "packages/foam-vscode/src/core/services/markdown-parser.ts",
"chars": 23667,
"preview": "// eslint-disable-next-line import/no-extraneous-dependencies\nimport { Point, Node, Position as AstPosition } from 'unis"
},
{
"path": "packages/foam-vscode/src/core/services/markdown-provider.test.ts",
"chars": 37492,
"preview": "import { createMarkdownParser } from './markdown-parser';\nimport {\n createMarkdownReferences,\n MarkdownResourceProvide"
},
{
"path": "packages/foam-vscode/src/core/services/markdown-provider.ts",
"chars": 9151,
"preview": "import {\n NoteLinkDefinition,\n Resource,\n ResourceLink,\n ResourceParser,\n} from '../model/note';\nimport { isNone, is"
},
{
"path": "packages/foam-vscode/src/core/services/progress.ts",
"chars": 875,
"preview": "/**\n * Generic progress information for long-running operations\n */\nexport interface Progress<T = unknown> {\n /** Curre"
},
{
"path": "packages/foam-vscode/src/core/services/tag-edit.test.ts",
"chars": 17391,
"preview": "import { createTestNote, createTestWorkspace } from '../../test/test-utils';\nimport { FoamTags } from '../model/tags';\ni"
},
{
"path": "packages/foam-vscode/src/core/services/tag-edit.ts",
"chars": 8744,
"preview": "import { FoamTags } from '../model/tags';\nimport { TextEdit, WorkspaceTextEdit } from './text-edit';\nimport { Location }"
},
{
"path": "packages/foam-vscode/src/core/services/text-edit.test.ts",
"chars": 2481,
"preview": "import { Range } from '../model/range';\nimport { Logger } from '../utils/log';\nimport { TextEdit } from './text-edit';\n\n"
},
{
"path": "packages/foam-vscode/src/core/services/text-edit.ts",
"chars": 2482,
"preview": "import detectNewline from 'detect-newline';\nimport { Position } from '../model/position';\nimport { Range } from '../mode"
},
{
"path": "packages/foam-vscode/src/core/utils/cache.ts",
"chars": 156,
"preview": "export interface ICache<K, V> {\n get(key: K): V | undefined;\n has(key: K): boolean;\n set(key: K, data: V): void;\n de"
},
{
"path": "packages/foam-vscode/src/core/utils/core.ts",
"chars": 2302,
"preview": "import sha1 from 'js-sha1';\n\n/**\n * Checks if a value is not null.\n *\n * @param value - The value to check.\n * @returns "
},
{
"path": "packages/foam-vscode/src/core/utils/hashtags.ts",
"chars": 833,
"preview": "import { isSome } from './core';\nexport const HASHTAG_REGEX =\n /(?<=^|\\s)#([0-9]*[\\p{L}\\p{Extended_Pictographic}/_-](?:"
},
{
"path": "packages/foam-vscode/src/core/utils/index.ts",
"chars": 357,
"preview": "import { titleCase } from 'title-case';\nexport { extractHashtags, extractTagsFromProp } from './hashtags';\nexport * from"
},
{
"path": "packages/foam-vscode/src/core/utils/log.ts",
"chars": 3050,
"preview": "export interface ILogger {\n debug(message?: any, ...params: any[]): void;\n info(message?: any, ...params: any[]): void"
}
]
// ... and 179 more files (download for full content)
About this extraction
This page contains the full source code of the foambubble/foam GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 379 files (1.8 MB), approximately 488.7k tokens, and a symbol index with 1309 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.