mirror of
https://github.com/foambubble/foam.git
synced 2026-01-11 06:58:11 -05:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e740fec0f | ||
|
|
beae852c21 | ||
|
|
85e857d973 | ||
|
|
667eee0e10 | ||
|
|
b6e68b3605 | ||
|
|
b9b0f9b515 | ||
|
|
95399977ec | ||
|
|
f759e7cd6e | ||
|
|
5839455535 | ||
|
|
7e4ae82fe1 | ||
|
|
e47155424f | ||
|
|
903a191394 | ||
|
|
5c6212dc96 | ||
|
|
bca9756e2b |
@@ -697,6 +697,15 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "bronson",
|
||||
"name": "Scott Bronson",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1776?v=4",
|
||||
"profile": "https://github.com/bronson",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
||||
@@ -56,16 +56,12 @@ Tests in `foam-vscode` live alongside the code in `src`.
|
||||
|
||||
This guide assumes you read the previous instructions and you're set up to work on Foam.
|
||||
|
||||
1. Now we'll use the launch configuration defined at [`.vscode/launch.json`](https://github.com/foambubble/foam/blob/master/.vscode/launch.json) to start a new extension host of VS Code. From the root, or the `foam-vscode` workspace, press f5.
|
||||
1. Now we'll use the launch configuration defined at [`.vscode/launch.json`](https://github.com/foambubble/foam/blob/master/.vscode/launch.json) to start a new extension host of VS Code. Open the "Run and Debug" Activity (the icon with the bug on the far left) and select "Run VSCode Extension" in the pop-up menu. Now hit F5 or click the green arrow "play" button to fire up a new copy of VS Code with your extension installed.
|
||||
|
||||
2. In the new extension host of VS Code that launched, open a Foam workspace (e.g. your personal one, or a test-specific one created from [foam-template](https://github.com/foambubble/foam-template)). This is strictly not necessary, but the extension won't auto-run unless it's in a workspace with a `.vscode/foam.json` file.
|
||||
|
||||
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!
|
||||
|
||||
For more resources related to the VS Code Extension, check out the links below:
|
||||
|
||||
- [[tutorial-adding-a-new-command-to-the-vs-code-extension]]
|
||||
|
||||
---
|
||||
|
||||
Feel free to modify and submit a PR if this guide is out-of-date or contains errors!
|
||||
|
||||
@@ -202,6 +202,7 @@ If that sounds like something you're interested in, I'd love to have you along o
|
||||
<td align="center"><a href="https://github.com/Barabazs"><img src="https://avatars.githubusercontent.com/u/31799121?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Barabas</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Barabazs" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://enginveske@gmail.com"><img src="https://avatars.githubusercontent.com/u/43685404?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Engincan VESKE</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=EngincanV" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://www.paulderaaij.nl"><img src="https://avatars.githubusercontent.com/u/495374?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Paul de Raaij</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=pderaaij" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/bronson"><img src="https://avatars.githubusercontent.com/u/1776?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Scott Bronson</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=bronson" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
],
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"version": "0.13.7"
|
||||
"version": "0.13.8"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "foam-core",
|
||||
"repository": "https://github.com/foambubble/foam",
|
||||
"version": "0.13.7",
|
||||
"version": "0.13.8",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"dist"
|
||||
|
||||
@@ -31,9 +31,11 @@ import { ResourceProvider } from 'model/provider';
|
||||
import { IDataStore, FileDataStore, IMatcher } from './services/datastore';
|
||||
import { IDisposable } from 'common/lifecycle';
|
||||
|
||||
const ALIAS_DIVIDER_CHAR = '|';
|
||||
|
||||
export interface ParserPlugin {
|
||||
name?: string;
|
||||
visit?: (node: Node, note: Resource) => void;
|
||||
visit?: (node: Node, note: Resource, noteSource: string) => void;
|
||||
onDidInitializeParser?: (parser: unified.Processor) => void;
|
||||
onWillParseMarkdown?: (markdown: string) => string;
|
||||
onWillVisitTree?: (tree: Node, note: Resource) => void;
|
||||
@@ -121,7 +123,7 @@ export class MarkdownResourceProvider implements ResourceProvider {
|
||||
switch (link.type) {
|
||||
case 'wikilink':
|
||||
const definitionUri = resource.definitions.find(
|
||||
def => def.label === link.slug
|
||||
def => def.label === link.target
|
||||
)?.url;
|
||||
if (isSome(definitionUri)) {
|
||||
const definedUri = URI.resolve(definitionUri, resource.uri);
|
||||
@@ -130,8 +132,8 @@ export class MarkdownResourceProvider implements ResourceProvider {
|
||||
URI.placeholder(definedUri.path);
|
||||
} else {
|
||||
targetUri =
|
||||
workspace.find(link.slug, resource.uri)?.uri ??
|
||||
URI.placeholder(link.slug);
|
||||
workspace.find(link.target, resource.uri)?.uri ??
|
||||
URI.placeholder(link.target);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -197,12 +199,28 @@ const titlePlugin: ParserPlugin = {
|
||||
|
||||
const wikilinkPlugin: ParserPlugin = {
|
||||
name: 'wikilink',
|
||||
visit: (node, note) => {
|
||||
visit: (node, note, noteSource) => {
|
||||
if (node.type === 'wikiLink') {
|
||||
const text = node.value as string;
|
||||
const alias = node.data?.alias as string;
|
||||
const literalContent = noteSource.substring(
|
||||
node.position!.start.offset!,
|
||||
node.position!.end.offset!
|
||||
);
|
||||
|
||||
const hasAlias =
|
||||
literalContent !== text && literalContent.includes(ALIAS_DIVIDER_CHAR);
|
||||
note.links.push({
|
||||
type: 'wikilink',
|
||||
slug: node.value as string,
|
||||
target: node.value as string,
|
||||
rawText: literalContent,
|
||||
label: hasAlias
|
||||
? alias.trim()
|
||||
: literalContent.substring(2, literalContent.length - 2),
|
||||
target: hasAlias
|
||||
? literalContent
|
||||
.substring(2, literalContent.indexOf(ALIAS_DIVIDER_CHAR))
|
||||
.trim()
|
||||
: text.trim(),
|
||||
range: astPositionToFoamRange(node.position!),
|
||||
});
|
||||
}
|
||||
@@ -259,7 +277,7 @@ export function createMarkdownParser(
|
||||
const parser = unified()
|
||||
.use(markdownParse, { gfm: true })
|
||||
.use(frontmatterPlugin, ['yaml'])
|
||||
.use(wikiLinkPlugin);
|
||||
.use(wikiLinkPlugin, { aliasDivider: ALIAS_DIVIDER_CHAR });
|
||||
|
||||
const plugins = [
|
||||
titlePlugin,
|
||||
@@ -342,7 +360,7 @@ export function createMarkdownParser(
|
||||
|
||||
for (let i = 0, len = plugins.length; i < len; i++) {
|
||||
try {
|
||||
plugins[i].visit?.(node, note);
|
||||
plugins[i].visit?.(node, note, markdown);
|
||||
} catch (e) {
|
||||
handleError(plugins[i], 'visit', uri, e);
|
||||
}
|
||||
@@ -431,7 +449,14 @@ export function createMarkdownReferences(
|
||||
: dropExtension(relativePath);
|
||||
|
||||
// [wiki-link-text]: path/to/file.md "Page title"
|
||||
return { label: link.slug, url: pathToNote, title: target.title };
|
||||
return {
|
||||
label:
|
||||
link.rawText.indexOf('[[') > -1
|
||||
? link.rawText.substring(2, link.rawText.length - 2)
|
||||
: link.rawText || link.label,
|
||||
url: pathToNote,
|
||||
title: target.title,
|
||||
};
|
||||
})
|
||||
.filter(isSome)
|
||||
.sort();
|
||||
|
||||
@@ -11,8 +11,9 @@ export interface NoteSource {
|
||||
|
||||
export interface WikiLink {
|
||||
type: 'wikilink';
|
||||
slug: string;
|
||||
target: string;
|
||||
label: string;
|
||||
rawText: string;
|
||||
range: Range;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ const pathToResourceId = (pathValue: string) => {
|
||||
};
|
||||
const uriToResourceId = (uri: URI) => pathToResourceId(uri.path);
|
||||
|
||||
const pathToResourceName = (pathValue: string) => path.parse(pathValue).name;
|
||||
const pathToResourceName = (pathValue: string) =>
|
||||
path.parse(pathValue).name.toLowerCase();
|
||||
export const uriToResourceName = (uri: URI) => pathToResourceName(uri.path);
|
||||
|
||||
export class FoamWorkspace implements IDisposable {
|
||||
@@ -110,7 +111,12 @@ export class FoamWorkspace implements IDisposable {
|
||||
|
||||
case 'key':
|
||||
const name = pathToResourceName(resourceId as string);
|
||||
const paths = this.resourcesByName[name];
|
||||
let paths = this.resourcesByName[name];
|
||||
|
||||
if (isNone(paths) || paths.length === 0) {
|
||||
paths = this.resourcesByName[resourceId as string];
|
||||
}
|
||||
|
||||
if (isNone(paths) || paths.length === 0) {
|
||||
return null;
|
||||
}
|
||||
@@ -118,6 +124,7 @@ export class FoamWorkspace implements IDisposable {
|
||||
const sortedPaths = paths.length === 1
|
||||
? paths
|
||||
: paths.sort((a, b) => a.localeCompare(b));
|
||||
|
||||
return this.resources[sortedPaths[0]];
|
||||
|
||||
case 'absolute-path':
|
||||
|
||||
@@ -67,10 +67,10 @@ export const createTestNote = (params: {
|
||||
return 'slug' in link
|
||||
? {
|
||||
type: 'wikilink',
|
||||
slug: link.slug,
|
||||
target: link.slug,
|
||||
label: link.slug,
|
||||
range: range,
|
||||
text: 'link text',
|
||||
rawText: 'link text',
|
||||
}
|
||||
: {
|
||||
type: 'link',
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
createMarkdownReferences,
|
||||
ParserPlugin,
|
||||
} from '../src/markdown-provider';
|
||||
import { DirectLink } from '../src/model/note';
|
||||
import { DirectLink, WikiLink } from '../src/model/note';
|
||||
import { Logger } from '../src/utils/log';
|
||||
import { uriToSlug } from '../src/utils/slug';
|
||||
import { URI } from '../src/model/uri';
|
||||
@@ -130,6 +130,24 @@ this is a [link to intro](#introduction)
|
||||
noteE.uri,
|
||||
]);
|
||||
});
|
||||
|
||||
it('Parses backlinks with an alias', () => {
|
||||
const note = createNoteFromMarkdown(
|
||||
'/path/to/page-a.md',
|
||||
'this is [[link|link alias]]. A link with spaces [[other link | spaced]]'
|
||||
);
|
||||
expect(note.links.length).toEqual(2);
|
||||
let link = note.links[0] as WikiLink;
|
||||
expect(link.type).toEqual('wikilink');
|
||||
expect(link.rawText).toEqual('[[link|link alias]]');
|
||||
expect(link.label).toEqual('link alias');
|
||||
expect(link.target).toEqual('link');
|
||||
link = note.links[1] as WikiLink;
|
||||
expect(link.type).toEqual('wikilink');
|
||||
expect(link.rawText).toEqual('[[other link | spaced]]');
|
||||
expect(link.label).toEqual('spaced');
|
||||
expect(link.target).toEqual('other link');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Note Title', () => {
|
||||
@@ -336,19 +354,6 @@ this is some #text that includes #tags we #care-about.
|
||||
new Set(['text', 'tags', 'care-about', 'hello', 'world', 'this_is_good'])
|
||||
);
|
||||
});
|
||||
|
||||
it('can find nested tags as array in yaml', () => {
|
||||
const noteA = createNoteFromMarkdown(
|
||||
'/dir1/page-a.md',
|
||||
`
|
||||
---
|
||||
tags: [hello, world, parent/child]
|
||||
---
|
||||
# this is a heading
|
||||
`
|
||||
);
|
||||
expect(noteA.tags).toEqual(new Set(['hello', 'world', 'parent/child']));
|
||||
});
|
||||
});
|
||||
|
||||
describe('parser plugins', () => {
|
||||
|
||||
@@ -232,7 +232,7 @@ describe('Wikilinks', () => {
|
||||
expect(graph.getAllConnections()[0]).toEqual({
|
||||
source: noteA.uri,
|
||||
target: noteB.uri,
|
||||
link: expect.objectContaining({ type: 'wikilink', slug: 'page-b' }),
|
||||
link: expect.objectContaining({ type: 'wikilink', label: 'page-b' }),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -354,6 +354,51 @@ describe('Wikilinks', () => {
|
||||
attachmentABis.uri,
|
||||
]);
|
||||
});
|
||||
|
||||
it('Allows for dendron-style wikilinks, including a dot', () => {
|
||||
const noteA = createTestNote({
|
||||
uri: '/path/to/page-a.md',
|
||||
links: [{ slug: 'dendron.style' }],
|
||||
});
|
||||
const noteB1 = createTestNote({ uri: '/path/to/another/dendron.style.md' });
|
||||
|
||||
const ws = createTestWorkspace();
|
||||
ws.set(noteA).set(noteB1);
|
||||
const graph = FoamGraph.fromWorkspace(ws);
|
||||
|
||||
expect(graph.getLinks(noteA.uri).map(l => l.target)).toEqual([noteB1.uri]);
|
||||
});
|
||||
|
||||
it('Handles capatalization of files and wiki links correctly', () => {
|
||||
const noteA = createTestNote({
|
||||
uri: '/path/to/page-a.md',
|
||||
links: [
|
||||
// uppercased filename, lowercased slug
|
||||
{ slug: 'page-b' },
|
||||
// lowercased filename, camelcased wikilink
|
||||
{ slug: 'Page-C' },
|
||||
// lowercased filename, lowercased wikilink
|
||||
{ slug: 'page-d' },
|
||||
],
|
||||
});
|
||||
const ws = createTestWorkspace()
|
||||
.set(noteA)
|
||||
.set(createTestNote({ uri: '/somewhere/PAGE-B.md' }))
|
||||
.set(createTestNote({ uri: '/path/another/page-c.md' }))
|
||||
.set(createTestNote({ uri: '/path/another/page-d.md' }));
|
||||
const graph = FoamGraph.fromWorkspace(ws);
|
||||
|
||||
expect(
|
||||
graph
|
||||
.getLinks(noteA.uri)
|
||||
.map(link => link.target.path)
|
||||
.sort()
|
||||
).toEqual([
|
||||
'/path/another/page-c.md',
|
||||
'/path/another/page-d.md',
|
||||
'/somewhere/PAGE-B.md',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('markdown direct links', () => {
|
||||
|
||||
@@ -3741,9 +3741,9 @@ github-slugger@^1.3.0:
|
||||
emoji-regex ">=6.0.0 <=6.1.1"
|
||||
|
||||
glob-parent@^5.0.0:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
|
||||
integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
@@ -5924,6 +5924,11 @@ replace-ext@1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
|
||||
integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=
|
||||
|
||||
replace-ext@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-2.0.0.tgz#9471c213d22e1bcc26717cd6e50881d88f812b06"
|
||||
integrity sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==
|
||||
|
||||
request-promise-core@1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9"
|
||||
@@ -7220,9 +7225,9 @@ write@1.0.3:
|
||||
mkdirp "^0.5.1"
|
||||
|
||||
ws@^5.2.0:
|
||||
version "5.2.2"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f"
|
||||
integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==
|
||||
version "5.2.3"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d"
|
||||
integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==
|
||||
dependencies:
|
||||
async-limiter "~1.0.0"
|
||||
|
||||
|
||||
@@ -4,6 +4,16 @@ All notable changes to the "foam-vscode" extension will be documented in this fi
|
||||
|
||||
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
|
||||
|
||||
## [0.13.8] - 2021-07-02
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
- Improved handling of capitalization in wikilinks (#688 - thanks @pderaaij)
|
||||
- This update will make wikilinks with different capitalization, such as `[[wikilink]]` and `[[WikiLink]]` point to the same file. Please note that means that files that only differ in capitalization across the workspace would now be treated as having the same name
|
||||
- Allow dots in wikilinks (#689 - thanks @pderaaij)
|
||||
- Fixed a bug in the expansion of date snippets (thanks @syndenham-chorea)
|
||||
- Added support for wikilink alias syntax, like `[[wikilink|label]]` (#689 - thanks @pderaaij)
|
||||
|
||||
## [0.13.7] - 2021-06-05
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"type": "git"
|
||||
},
|
||||
"homepage": "https://github.com/foambubble/foam",
|
||||
"version": "0.13.7",
|
||||
"version": "0.13.8",
|
||||
"license": "MIT",
|
||||
"publisher": "foam",
|
||||
"engines": {
|
||||
@@ -395,7 +395,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"dateformat": "^3.0.3",
|
||||
"foam-core": "^0.13.7",
|
||||
"foam-core": "^0.13.8",
|
||||
"gray-matter": "^4.0.2",
|
||||
"markdown-it-regex": "^0.2.0",
|
||||
"micromatch": "^4.0.2",
|
||||
|
||||
@@ -5,6 +5,14 @@ import { isAbsolute } from 'path';
|
||||
import { docConfig, focusNote, pathExists } from './utils';
|
||||
import { URI } from 'foam-core';
|
||||
|
||||
/**
|
||||
* Open the daily note file.
|
||||
*
|
||||
* In the case that the daily note file does not exist,
|
||||
* it gets created along with any folders in its path.
|
||||
*
|
||||
* @param date A given date to be formatted as filename.
|
||||
*/
|
||||
async function openDailyNoteFor(date?: Date) {
|
||||
const foamConfiguration = workspace.getConfiguration('foam');
|
||||
const currentDate = date !== undefined ? date : new Date();
|
||||
@@ -19,6 +27,19 @@ async function openDailyNoteFor(date?: Date) {
|
||||
await focusNote(dailyNotePath, isNew);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the daily note file path.
|
||||
*
|
||||
* This function first checks the `foam.openDailyNote.directory` configuration string,
|
||||
* defaulting to the current directory.
|
||||
*
|
||||
* In the case that the directory path is not absolute,
|
||||
* the resulting path will start on the current workspace top-level.
|
||||
*
|
||||
* @param configuration The current workspace configuration.
|
||||
* @param date A given date to be formatted as filename.
|
||||
* @returns The path to the daily note file.
|
||||
*/
|
||||
function getDailyNotePath(
|
||||
configuration: WorkspaceConfiguration,
|
||||
date: Date
|
||||
@@ -38,6 +59,17 @@ function getDailyNotePath(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the daily note filename (basename) to use.
|
||||
*
|
||||
* Fetch the filename format and extension from
|
||||
* `foam.openDailyNote.filenameFormat` and
|
||||
* `foam.openDailyNote.fileExtension`, respectively.
|
||||
*
|
||||
* @param configuration The current workspace configuration.
|
||||
* @param date A given date to be formatted as filename.
|
||||
* @returns The daily note's filename.
|
||||
*/
|
||||
function getDailyNoteFileName(
|
||||
configuration: WorkspaceConfiguration,
|
||||
date: Date
|
||||
@@ -52,6 +84,17 @@ function getDailyNoteFileName(
|
||||
return `${dateFormat(date, filenameFormat, false)}.${fileExtension}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a daily note if it does not exist.
|
||||
*
|
||||
* In the case that the folders referenced in the file path also do not exist,
|
||||
* this function will create all folders in the path.
|
||||
*
|
||||
* @param configuration The current workspace configuration.
|
||||
* @param dailyNotePath The path to daily note file.
|
||||
* @param currentDate The current date, to be used as a title.
|
||||
* @returns Wether the file was created.
|
||||
*/
|
||||
async function createDailyNoteIfNotExists(
|
||||
configuration: WorkspaceConfiguration,
|
||||
dailyNotePath: URI,
|
||||
@@ -77,6 +120,17 @@ async function createDailyNoteIfNotExists(
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the directory (or directories) needed for the note to be placed in.
|
||||
*
|
||||
* If the daily note's folder does not exist,
|
||||
* create such directory and all other non-existent directories in the path.
|
||||
*
|
||||
* For example, for the path `/home/user/foam-template/journal/yyyy-mm-dd.md`,
|
||||
* it will create all directories in the path up until the file.
|
||||
*
|
||||
* @param dailyNotePath The path to the daily note file.
|
||||
*/
|
||||
async function createDailyNoteDirectoryIfNotExists(dailyNotePath: URI) {
|
||||
const dailyNoteDirectory = URI.getDir(dailyNotePath);
|
||||
|
||||
|
||||
@@ -125,10 +125,7 @@ export class BacklinkTreeItem extends vscode.TreeItem {
|
||||
public readonly resource: Resource,
|
||||
public readonly link: ResourceLink
|
||||
) {
|
||||
super(
|
||||
link.type === 'wikilink' ? link.slug : link.label,
|
||||
vscode.TreeItemCollapsibleState.None
|
||||
);
|
||||
super(link.label, vscode.TreeItemCollapsibleState.None);
|
||||
this.label = `${link.range.start.line}: ${this.label}`;
|
||||
this.command = {
|
||||
command: 'vscode.open',
|
||||
|
||||
@@ -100,4 +100,24 @@ describe('Document links provider', () => {
|
||||
);
|
||||
expect(links[0].range).toEqual(new vscode.Range(0, 18, 0, 35));
|
||||
});
|
||||
|
||||
it('should support wikilinks that have an alias', async () => {
|
||||
const fileB = await createFile('# File B');
|
||||
const fileA = await createFile(
|
||||
`this is a link to [[${fileB.name}|alias]].`
|
||||
);
|
||||
const noteA = parser.parse(fileA.uri, fileA.content);
|
||||
const noteB = parser.parse(fileB.uri, fileB.content);
|
||||
const ws = createTestWorkspace()
|
||||
.set(noteA)
|
||||
.set(noteB);
|
||||
|
||||
const { doc } = await showInEditor(noteA.uri);
|
||||
const provider = new LinkProvider(ws, parser);
|
||||
const links = provider.provideDocumentLinks(doc);
|
||||
|
||||
expect(links.length).toEqual(1);
|
||||
expect(links[0].target).toEqual(OPEN_COMMAND.asURI(noteB.uri));
|
||||
expect(links[0].range).toEqual(new vscode.Range(0, 18, 0, 33));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -80,7 +80,7 @@ const getDailyNoteLink = (date: Date) => {
|
||||
return `[[${name.replace(`.${foamExtension}`, '')}]]`;
|
||||
};
|
||||
|
||||
const snippets: (() => DateSnippet)[] = [
|
||||
const snippetFactories: (() => DateSnippet)[] = [
|
||||
() => ({
|
||||
detail: "Insert a link to today's daily note",
|
||||
snippet: '/day',
|
||||
@@ -169,24 +169,28 @@ const computedSnippets: ((number: number) => DateSnippet)[] = [
|
||||
];
|
||||
|
||||
const completions: CompletionItemProvider = {
|
||||
provideCompletionItems: (_document, _position, _token, _context) => {
|
||||
provideCompletionItems: (document, position, _token, _context) => {
|
||||
if (_context.triggerKind === CompletionTriggerKind.Invoke) {
|
||||
// if completion was triggered without trigger character then we return [] to fallback
|
||||
// to vscode word-based suggestions (see https://github.com/foambubble/foam/pull/417)
|
||||
return [];
|
||||
}
|
||||
|
||||
const range = document.getWordRangeAtPosition(position, /\S+/);
|
||||
const completionItems = [
|
||||
...snippets.map(item => createCompletionItem(item())),
|
||||
...generateDayOfWeekSnippets().map(item => createCompletionItem(item)),
|
||||
];
|
||||
...snippetFactories.map(snippetFactory => snippetFactory()),
|
||||
...generateDayOfWeekSnippets(),
|
||||
].map(snippet => {
|
||||
const completionItem = createCompletionItem(snippet);
|
||||
completionItem.range = range;
|
||||
return completionItem;
|
||||
});
|
||||
return completionItems;
|
||||
},
|
||||
};
|
||||
|
||||
const computedCompletions: CompletionItemProvider = {
|
||||
provideCompletionItems: (document, position, _token, _context) => {
|
||||
if (_context.triggerKind === CompletionTriggerKind.Invoke) {
|
||||
export const datesCompletionProvider: CompletionItemProvider = {
|
||||
provideCompletionItems: (document, position, _token, context) => {
|
||||
if (context.triggerKind === CompletionTriggerKind.Invoke) {
|
||||
// if completion was triggered without trigger character then we return [] to fallback
|
||||
// to vscode word-based suggestions (see https://github.com/foambubble/foam/pull/417)
|
||||
return [];
|
||||
@@ -229,7 +233,7 @@ const feature: FoamFeature = {
|
||||
languages.registerCompletionItemProvider('markdown', completions, '/');
|
||||
languages.registerCompletionItemProvider(
|
||||
'markdown',
|
||||
computedCompletions,
|
||||
datesCompletionProvider,
|
||||
'/',
|
||||
'+'
|
||||
);
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import * as vscode from 'vscode';
|
||||
import markdownItRegex from 'markdown-it-regex';
|
||||
import { Foam, FoamWorkspace, Logger, URI } from 'foam-core';
|
||||
import markdownItRegex from 'markdown-it-regex';
|
||||
import * as vscode from 'vscode';
|
||||
import { FoamFeature } from '../types';
|
||||
import { isNone } from '../utils';
|
||||
|
||||
const ALIAS_DIVIDER_CHAR = '|';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: async (
|
||||
@@ -11,11 +14,13 @@ const feature: FoamFeature = {
|
||||
const foam = await foamPromise;
|
||||
|
||||
return {
|
||||
extendMarkdownIt: (md: markdownit) =>
|
||||
[markdownItWithFoamTags, markdownItWithFoamLinks].reduce(
|
||||
(acc, extension) => extension(acc, foam.workspace),
|
||||
md
|
||||
),
|
||||
extendMarkdownIt: (md: markdownit) => {
|
||||
return [
|
||||
markdownItWithFoamTags,
|
||||
markdownItWithFoamLinks,
|
||||
markdownItWithRemoveLinkReferences,
|
||||
].reduce((acc, extension) => extension(acc, foam.workspace), md);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -29,13 +34,23 @@ export const markdownItWithFoamLinks = (
|
||||
regex: /\[\[([^[\]]+?)\]\]/,
|
||||
replace: (wikilink: string) => {
|
||||
try {
|
||||
const resource = workspace.find(wikilink);
|
||||
if (resource == null) {
|
||||
return getPlaceholderLink(wikilink);
|
||||
const linkHasAlias = wikilink.includes(ALIAS_DIVIDER_CHAR);
|
||||
const resourceLink = linkHasAlias
|
||||
? wikilink.substring(0, wikilink.indexOf('|'))
|
||||
: wikilink;
|
||||
|
||||
const resource = workspace.find(resourceLink);
|
||||
if (isNone(resource)) {
|
||||
return getPlaceholderLink(resourceLink);
|
||||
}
|
||||
|
||||
const linkLabel = linkHasAlias
|
||||
? wikilink.substr(wikilink.indexOf('|') + 1)
|
||||
: wikilink;
|
||||
|
||||
return `<a class='foam-note-link' title='${
|
||||
resource.title
|
||||
}' href='${URI.toFsPath(resource.uri)}'>${wikilink}</a>`;
|
||||
}' href='${URI.toFsPath(resource.uri)}'>${linkLabel}</a>`;
|
||||
} catch (e) {
|
||||
Logger.error(
|
||||
`Error while creating link for [[${wikilink}]] in Preview panel`,
|
||||
@@ -60,7 +75,7 @@ export const markdownItWithFoamTags = (
|
||||
replace: (tag: string) => {
|
||||
try {
|
||||
const resource = workspace.find(tag);
|
||||
if (resource == null) {
|
||||
if (isNone(resource)) {
|
||||
return getFoamTag(tag);
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -77,4 +92,16 @@ export const markdownItWithFoamTags = (
|
||||
const getFoamTag = (content: string) =>
|
||||
`<span class='foam-tag'>${content}</span>`;
|
||||
|
||||
export const markdownItWithRemoveLinkReferences = (
|
||||
md: markdownit,
|
||||
workspace: FoamWorkspace
|
||||
) => {
|
||||
// Forget about reference blocks before processing links.
|
||||
md.inline.ruler.before('link', 'clear-references', state => {
|
||||
state.env.references = undefined;
|
||||
return false;
|
||||
});
|
||||
return md;
|
||||
};
|
||||
|
||||
export default feature;
|
||||
|
||||
@@ -70,10 +70,10 @@ export const createTestNote = (params: {
|
||||
return 'slug' in link
|
||||
? {
|
||||
type: 'wikilink',
|
||||
slug: link.slug,
|
||||
target: link.slug,
|
||||
label: link.slug,
|
||||
range: range,
|
||||
text: 'link text',
|
||||
rawText: 'link text',
|
||||
}
|
||||
: {
|
||||
type: 'link',
|
||||
@@ -139,7 +139,7 @@ export const createNote = (r: Resource) => {
|
||||
|
||||
some content and ${r.links
|
||||
.map(l =>
|
||||
l.type === 'wikilink' ? `[[${l.slug}]]` : `[${l.label}](${l.target})`
|
||||
l.type === 'wikilink' ? `[[${l.label}]]` : `[${l.label}](${l.target})`
|
||||
)
|
||||
.join(' some content between links.\n')}
|
||||
last line.
|
||||
|
||||
@@ -2506,10 +2506,10 @@
|
||||
"resolved" "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz"
|
||||
"version" "2.0.2"
|
||||
|
||||
"foam-core@^0.13.6":
|
||||
"integrity" "sha512-Yu+ACWQ38EdTnGMuYRIVlqc6FzJfvm1GWM50w3Wnpx7w/AaUTnnlddCccnYzmXYiISZTRfWQgiOdR/0L9i3WJw=="
|
||||
"resolved" "https://registry.npmjs.org/foam-core/-/foam-core-0.13.6.tgz"
|
||||
"version" "0.13.6"
|
||||
"foam-core@^0.13.7":
|
||||
"integrity" "sha512-+A2RUGvkk1ntyrjhQkf0mUo1ytWrqWKYho56R4avCc9W1dQtavJ4+IGv+iR+ettAk8k5hbuF30KOZm4KCplhJA=="
|
||||
"resolved" "https://registry.npmjs.org/foam-core/-/foam-core-0.13.7.tgz"
|
||||
"version" "0.13.7"
|
||||
dependencies:
|
||||
"detect-newline" "^3.1.0"
|
||||
"fast-array-diff" "^1.0.0"
|
||||
@@ -2520,6 +2520,7 @@
|
||||
"remark-frontmatter" "^2.0.0"
|
||||
"remark-parse" "^8.0.2"
|
||||
"remark-wiki-link" "^0.0.4"
|
||||
"replace-ext" "^2.0.0"
|
||||
"title-case" "^3.0.2"
|
||||
"unified" "^9.0.0"
|
||||
"unist-util-visit" "^2.0.2"
|
||||
@@ -4459,6 +4460,11 @@
|
||||
"resolved" "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz"
|
||||
"version" "1.6.1"
|
||||
|
||||
"replace-ext@^2.0.0":
|
||||
"integrity" "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug=="
|
||||
"resolved" "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz"
|
||||
"version" "2.0.0"
|
||||
|
||||
"replace-ext@1.0.0":
|
||||
"integrity" "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs="
|
||||
"resolved" "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
👀*This is an early stage project under rapid development. For updates join the [Foam community Discord](https://foambubble.github.io/join-discord/g)! 💬*
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
[](#contributors-)
|
||||
[](#contributors-)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
[](https://foambubble.github.io/join-discord/g)
|
||||
@@ -158,6 +158,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<td align="center"><a href="https://github.com/Barabazs"><img src="https://avatars.githubusercontent.com/u/31799121?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Barabas</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Barabazs" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://enginveske@gmail.com"><img src="https://avatars.githubusercontent.com/u/43685404?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Engincan VESKE</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=EngincanV" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://www.paulderaaij.nl"><img src="https://avatars.githubusercontent.com/u/495374?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Paul de Raaij</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=pderaaij" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/bronson"><img src="https://avatars.githubusercontent.com/u/1776?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Scott Bronson</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=bronson" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -5422,9 +5422,9 @@ has@^1.0.3:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
hosted-git-info@^2.1.4, hosted-git-info@^2.7.1:
|
||||
version "2.8.8"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
|
||||
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
|
||||
version "2.8.9"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
|
||||
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
|
||||
|
||||
hosted-git-info@^4.0.0:
|
||||
version "4.0.0"
|
||||
|
||||
Reference in New Issue
Block a user