mirror of
https://github.com/foambubble/foam.git
synced 2026-01-11 06:58:11 -05:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d6f98351f | ||
|
|
970c30f08c | ||
|
|
8556982b17 | ||
|
|
1ab9520c5c | ||
|
|
2a72bde111 | ||
|
|
2385bd75b5 | ||
|
|
53d2e7aaed | ||
|
|
48c13ef400 | ||
|
|
3ab30547eb |
@@ -932,6 +932,15 @@
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "dmurph",
|
||||
"name": "Daniel Murphy",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/294026?v=4",
|
||||
"profile": "http://www.dmurph.com",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
||||
@@ -236,6 +236,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/lingyv-li"><img src="https://avatars.githubusercontent.com/u/8937944?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Larry Li</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=lingyv-li" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/infogulch"><img src="https://avatars.githubusercontent.com/u/133882?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Joe Taber</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=infogulch" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.readingsnail.pe.kr"><img src="https://avatars.githubusercontent.com/u/1904967?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Woosuk Park</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=readingsnail" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://www.dmurph.com"><img src="https://avatars.githubusercontent.com/u/294026?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Daniel Murphy</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dmurph" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
],
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"version": "0.19.4"
|
||||
"version": "0.19.5"
|
||||
}
|
||||
|
||||
@@ -4,6 +4,14 @@ 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.19.5] - 2022-09-01
|
||||
|
||||
Fixes and Improvements:
|
||||
- Added `FOAM_DATE_WEEK` variable (#1053 - Thanks @dmurph)
|
||||
- Fixed extension inclusion when generating references for attachments
|
||||
- Link completion label can be note title as well as path (#1059)
|
||||
- Images and attachments are not shown by default in graph view (#1056)
|
||||
|
||||
## [0.19.4] - 2022-08-07
|
||||
|
||||
Fixes and Improvements:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"type": "git"
|
||||
},
|
||||
"homepage": "https://github.com/foambubble/foam",
|
||||
"version": "0.19.4",
|
||||
"version": "0.19.5",
|
||||
"license": "MIT",
|
||||
"publisher": "foam",
|
||||
"engines": {
|
||||
@@ -243,6 +243,34 @@
|
||||
"configuration": {
|
||||
"title": "Foam",
|
||||
"properties": {
|
||||
"foam.completion.label": {
|
||||
"type": "string",
|
||||
"default": "path",
|
||||
"description": "Describes what note property to use as a label for completion items",
|
||||
"enum": [
|
||||
"path",
|
||||
"title",
|
||||
"identifier"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Use the path of the note",
|
||||
"Use the title of the note",
|
||||
"Use the identifier of the note"
|
||||
]
|
||||
},
|
||||
"foam.completion.useAlias": {
|
||||
"type": "string",
|
||||
"default": "never",
|
||||
"description": "Specifies in which cases to use an alias when creating a wikilink",
|
||||
"enum": [
|
||||
"never",
|
||||
"whenPathDiffersFromTitle"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Never use aliases in completion items",
|
||||
"Use alias if resource path is different from title"
|
||||
]
|
||||
},
|
||||
"foam.files.ignore": {
|
||||
"type": [
|
||||
"array"
|
||||
|
||||
@@ -301,6 +301,21 @@ describe('Generation of markdown references', () => {
|
||||
expect(references.map(r => r.url)).toEqual(['page-b.md', 'page-c.md']);
|
||||
});
|
||||
|
||||
it('should always add extensions for attachments, even when includeExtension = false', () => {
|
||||
const workspace = createTestWorkspace();
|
||||
const noteA = createNoteFromMarkdown(
|
||||
'Link to [[page-b]] and [[image.png]]',
|
||||
'/dir1/page-a.md'
|
||||
);
|
||||
workspace
|
||||
.set(noteA)
|
||||
.set(createNoteFromMarkdown('Content of note B', '/dir1/page-b.md'))
|
||||
.set(createNoteFromMarkdown('', '/dir1/image.png'));
|
||||
|
||||
const references = createMarkdownReferences(workspace, noteA.uri, false);
|
||||
expect(references.map(r => r.url)).toEqual(['page-b', 'image.png']);
|
||||
});
|
||||
|
||||
it('should use relative paths', () => {
|
||||
const workspace = createTestWorkspace();
|
||||
const noteA = createNoteFromMarkdown(
|
||||
|
||||
@@ -181,7 +181,7 @@ to generate markdown reference list`
|
||||
}
|
||||
|
||||
let relativeUri = target.uri.relativeTo(noteUri.getDirectory());
|
||||
if (!includeExtension) {
|
||||
if (!includeExtension && relativeUri.path.endsWith('.md')) {
|
||||
relativeUri = relativeUri.changeExtension('*', '');
|
||||
}
|
||||
|
||||
|
||||
@@ -1,34 +1,26 @@
|
||||
import { FoamFeature } from '../types';
|
||||
import * as commands from './commands';
|
||||
import dataviz from './dataviz';
|
||||
import * as panels from './panels';
|
||||
import dateSnippets from './date-snippets';
|
||||
import tagsExplorer from './tags-tree-view';
|
||||
import orphans from './orphans';
|
||||
import placeholders from './placeholders';
|
||||
import backlinks from './backlinks';
|
||||
import hoverProvider from './hover-provider';
|
||||
import previewNavigation from './preview';
|
||||
import preview from './preview';
|
||||
import completionProvider, { completionCursorMove } from './link-completion';
|
||||
import tagCompletionProvider from './tag-completion';
|
||||
import linkDecorations from './document-decorator';
|
||||
import navigationProviders from './navigation-provider';
|
||||
import wikilinkDiagnostics from './wikilink-diagnostics';
|
||||
import refactor from './refactor';
|
||||
import { FoamFeature } from '../types';
|
||||
|
||||
export const features: FoamFeature[] = [
|
||||
...Object.values(commands),
|
||||
...Object.values(panels),
|
||||
refactor,
|
||||
navigationProviders,
|
||||
wikilinkDiagnostics,
|
||||
tagsExplorer,
|
||||
dataviz,
|
||||
dateSnippets,
|
||||
orphans,
|
||||
placeholders,
|
||||
backlinks,
|
||||
hoverProvider,
|
||||
linkDecorations,
|
||||
previewNavigation,
|
||||
preview,
|
||||
completionProvider,
|
||||
tagCompletionProvider,
|
||||
completionCursorMove,
|
||||
|
||||
@@ -7,10 +7,11 @@ import {
|
||||
closeEditors,
|
||||
createFile,
|
||||
showInEditor,
|
||||
withModifiedFoamConfiguration,
|
||||
} from '../test/test-utils-vscode';
|
||||
import { fromVsCodeUri } from '../utils/vsc-utils';
|
||||
import {
|
||||
CompletionProvider,
|
||||
WikilinkCompletionProvider,
|
||||
SectionCompletionProvider,
|
||||
} from './link-completion';
|
||||
|
||||
@@ -63,7 +64,7 @@ describe('Link Completion', () => {
|
||||
it('should not return any link for empty documents', async () => {
|
||||
const { uri } = await createFile('');
|
||||
const { doc } = await showInEditor(uri);
|
||||
const provider = new CompletionProvider(ws, graph);
|
||||
const provider = new WikilinkCompletionProvider(ws, graph);
|
||||
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
@@ -76,7 +77,7 @@ describe('Link Completion', () => {
|
||||
it('should not return link outside the wikilink brackets', async () => {
|
||||
const { uri } = await createFile('[[file]] then');
|
||||
const { doc } = await showInEditor(uri);
|
||||
const provider = new CompletionProvider(ws, graph);
|
||||
const provider = new WikilinkCompletionProvider(ws, graph);
|
||||
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
@@ -90,7 +91,7 @@ describe('Link Completion', () => {
|
||||
for (const text of ['[[', '[[file]] [[', '[[file]] #tag [[']) {
|
||||
const { uri } = await createFile(text);
|
||||
const { doc } = await showInEditor(uri);
|
||||
const provider = new CompletionProvider(ws, graph);
|
||||
const provider = new WikilinkCompletionProvider(ws, graph);
|
||||
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
@@ -110,6 +111,103 @@ describe('Link Completion', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('should support label setting', async () => {
|
||||
const { uri: noteUri, content } = await createFile(`# My Note Title`);
|
||||
const workspace = createTestWorkspace();
|
||||
workspace.set(parser.parse(noteUri, content));
|
||||
const provider = new WikilinkCompletionProvider(
|
||||
workspace,
|
||||
FoamGraph.fromWorkspace(workspace)
|
||||
);
|
||||
|
||||
const { uri } = await createFile('[[');
|
||||
const { doc } = await showInEditor(uri);
|
||||
|
||||
await withModifiedFoamConfiguration(
|
||||
'completion.label',
|
||||
'title',
|
||||
async () => {
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
new vscode.Position(0, 3)
|
||||
);
|
||||
|
||||
expect(links.items.map(i => i.label)).toEqual(['My Note Title']);
|
||||
}
|
||||
);
|
||||
|
||||
await withModifiedFoamConfiguration(
|
||||
'completion.label',
|
||||
'path',
|
||||
async () => {
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
new vscode.Position(0, 3)
|
||||
);
|
||||
|
||||
expect(links.items.map(i => i.label)).toEqual([noteUri.getBasename()]);
|
||||
}
|
||||
);
|
||||
|
||||
await withModifiedFoamConfiguration(
|
||||
'completion.label',
|
||||
'identifier',
|
||||
async () => {
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
new vscode.Position(0, 3)
|
||||
);
|
||||
|
||||
expect(links.items.map(i => i.label)).toEqual([
|
||||
workspace.getIdentifier(noteUri),
|
||||
]);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should support alias setting', async () => {
|
||||
const { uri: noteUri, content } = await createFile(`# My Note Title`);
|
||||
const workspace = createTestWorkspace();
|
||||
workspace.set(parser.parse(noteUri, content));
|
||||
const provider = new WikilinkCompletionProvider(
|
||||
workspace,
|
||||
FoamGraph.fromWorkspace(workspace)
|
||||
);
|
||||
|
||||
const { uri } = await createFile('[[');
|
||||
const { doc } = await showInEditor(uri);
|
||||
|
||||
await withModifiedFoamConfiguration(
|
||||
'completion.useAlias',
|
||||
'never',
|
||||
async () => {
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
new vscode.Position(0, 3)
|
||||
);
|
||||
|
||||
expect(links.items.map(i => i.insertText)).toEqual([
|
||||
workspace.getIdentifier(noteUri),
|
||||
]);
|
||||
}
|
||||
);
|
||||
|
||||
await withModifiedFoamConfiguration(
|
||||
'completion.useAlias',
|
||||
'whenPathDiffersFromTitle',
|
||||
async () => {
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
new vscode.Position(0, 3)
|
||||
);
|
||||
|
||||
expect(links.items.map(i => i.insertText)).toEqual([
|
||||
`${workspace.getIdentifier(noteUri)}|My Note Title`,
|
||||
]);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should return sections for other notes', async () => {
|
||||
for (const text of [
|
||||
'[[file-name#',
|
||||
@@ -171,7 +269,7 @@ alias: alias-a
|
||||
ws.set(parser.parse(uri, content));
|
||||
|
||||
const { doc } = await showInEditor(uri);
|
||||
const provider = new CompletionProvider(ws, graph);
|
||||
const provider = new WikilinkCompletionProvider(ws, graph);
|
||||
|
||||
const links = await provider.provideCompletionItems(
|
||||
doc,
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { Foam } from '../core/model/foam';
|
||||
import { FoamGraph } from '../core/model/graph';
|
||||
import { Resource } from '../core/model/note';
|
||||
import { URI } from '../core/model/uri';
|
||||
import { FoamWorkspace } from '../core/model/workspace';
|
||||
import { getFoamVsCodeConfig } from '../services/config';
|
||||
import { FoamFeature } from '../types';
|
||||
import { getNoteTooltip, mdDocSelector } from '../utils';
|
||||
import { fromVsCodeUri, toVsCodeUri } from '../utils/vsc-utils';
|
||||
@@ -28,7 +30,7 @@ const feature: FoamFeature = {
|
||||
context.subscriptions.push(
|
||||
vscode.languages.registerCompletionItemProvider(
|
||||
mdDocSelector,
|
||||
new CompletionProvider(foam.workspace, foam.graph),
|
||||
new WikilinkCompletionProvider(foam.workspace, foam.graph),
|
||||
'['
|
||||
),
|
||||
vscode.languages.registerCompletionItemProvider(
|
||||
@@ -159,7 +161,7 @@ export class SectionCompletionProvider
|
||||
}
|
||||
}
|
||||
|
||||
export class CompletionProvider
|
||||
export class WikilinkCompletionProvider
|
||||
implements vscode.CompletionItemProvider<vscode.CompletionItem> {
|
||||
constructor(private ws: FoamWorkspace, private graph: FoamGraph) {}
|
||||
|
||||
@@ -186,20 +188,45 @@ export class CompletionProvider
|
||||
position.line,
|
||||
position.character
|
||||
);
|
||||
const labelStyle = getCompletionLabelSetting();
|
||||
const aliasSetting = getCompletionAliasSetting();
|
||||
|
||||
const resources = this.ws.list().map(resource => {
|
||||
const label = vscode.workspace.asRelativePath(toVsCodeUri(resource.uri));
|
||||
const resourceIsDocument =
|
||||
['attachment', 'image'].indexOf(resource.type) === -1;
|
||||
|
||||
const identifier = this.ws.getIdentifier(resource.uri);
|
||||
|
||||
const label = !resourceIsDocument
|
||||
? identifier
|
||||
: labelStyle === 'path'
|
||||
? vscode.workspace.asRelativePath(toVsCodeUri(resource.uri))
|
||||
: labelStyle === 'title'
|
||||
? resource.title
|
||||
: identifier;
|
||||
|
||||
const item = new ResourceCompletionItem(
|
||||
label,
|
||||
vscode.CompletionItemKind.File,
|
||||
resource.uri
|
||||
);
|
||||
item.sortText =
|
||||
resource.type === 'attachment' ? `1-${item.label}` : `0-${item.label}`;
|
||||
item.filterText = resource.uri.getName();
|
||||
item.insertText = this.ws.getIdentifier(resource.uri);
|
||||
|
||||
item.detail = vscode.workspace.asRelativePath(toVsCodeUri(resource.uri));
|
||||
item.sortText = resourceIsDocument
|
||||
? `0-${item.label}`
|
||||
: `1-${item.label}`;
|
||||
|
||||
const useAlias =
|
||||
resourceIsDocument &&
|
||||
aliasSetting !== 'never' &&
|
||||
wikilinkRequiresAlias(resource);
|
||||
|
||||
item.insertText = useAlias
|
||||
? `${identifier}|${resource.title}`
|
||||
: identifier;
|
||||
item.commitCharacters = useAlias ? [] : linkCommitCharacters;
|
||||
item.range = replacementRange;
|
||||
item.command = COMPLETION_CURSOR_MOVE;
|
||||
item.commitCharacters = linkCommitCharacters;
|
||||
return item;
|
||||
});
|
||||
const aliases = this.ws.list().flatMap(resource =>
|
||||
@@ -265,4 +292,23 @@ class ResourceCompletionItem extends vscode.CompletionItem {
|
||||
}
|
||||
}
|
||||
|
||||
function getCompletionLabelSetting() {
|
||||
const labelStyle: 'path' | 'title' | 'identifier' = getFoamVsCodeConfig(
|
||||
'completion.label'
|
||||
);
|
||||
return labelStyle;
|
||||
}
|
||||
|
||||
function getCompletionAliasSetting() {
|
||||
const aliasStyle: 'never' | 'whenPathDiffersFromTitle' = getFoamVsCodeConfig(
|
||||
'completion.useAlias'
|
||||
);
|
||||
return aliasStyle;
|
||||
}
|
||||
|
||||
const normalize = (text: string) => text.toLocaleLowerCase().trim();
|
||||
function wikilinkRequiresAlias(resource: Resource) {
|
||||
return normalize(resource.uri.getName()) !== normalize(resource.title);
|
||||
}
|
||||
|
||||
export default feature;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { workspace, window } from 'vscode';
|
||||
import { createTestNote, createTestWorkspace } from '../test/test-utils';
|
||||
import { createTestNote, createTestWorkspace } from '../../test/test-utils';
|
||||
import {
|
||||
cleanWorkspace,
|
||||
closeEditors,
|
||||
createNote,
|
||||
getUriInWorkspace,
|
||||
} from '../test/test-utils-vscode';
|
||||
} from '../../test/test-utils-vscode';
|
||||
import { BacklinksTreeDataProvider, BacklinkTreeItem } from './backlinks';
|
||||
import { ResourceTreeItem } from '../utils/grouped-resources-tree-data-provider';
|
||||
import { OPEN_COMMAND } from './commands/open-resource';
|
||||
import { toVsCodeUri } from '../utils/vsc-utils';
|
||||
import { FoamGraph } from '../core/model/graph';
|
||||
import { URI } from '../core/model/uri';
|
||||
import { ResourceTreeItem } from '../../utils/grouped-resources-tree-data-provider';
|
||||
import { OPEN_COMMAND } from '../commands/open-resource';
|
||||
import { toVsCodeUri } from '../../utils/vsc-utils';
|
||||
import { FoamGraph } from '../../core/model/graph';
|
||||
import { URI } from '../../core/model/uri';
|
||||
|
||||
describe('Backlinks panel', () => {
|
||||
beforeAll(async () => {
|
||||
@@ -1,16 +1,16 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { groupBy } from 'lodash';
|
||||
import { URI } from '../core/model/uri';
|
||||
import { URI } from '../../core/model/uri';
|
||||
|
||||
import { getNoteTooltip, isNone } from '../utils';
|
||||
import { FoamFeature } from '../types';
|
||||
import { ResourceTreeItem } from '../utils/grouped-resources-tree-data-provider';
|
||||
import { Foam } from '../core/model/foam';
|
||||
import { FoamWorkspace } from '../core/model/workspace';
|
||||
import { FoamGraph } from '../core/model/graph';
|
||||
import { Resource, ResourceLink } from '../core/model/note';
|
||||
import { Range } from '../core/model/range';
|
||||
import { fromVsCodeUri, toVsCodeUri } from '../utils/vsc-utils';
|
||||
import { getNoteTooltip, isNone } from '../../utils';
|
||||
import { FoamFeature } from '../../types';
|
||||
import { ResourceTreeItem } from '../../utils/grouped-resources-tree-data-provider';
|
||||
import { Foam } from '../../core/model/foam';
|
||||
import { FoamWorkspace } from '../../core/model/workspace';
|
||||
import { FoamGraph } from '../../core/model/graph';
|
||||
import { Resource, ResourceLink } from '../../core/model/note';
|
||||
import { Range } from '../../core/model/range';
|
||||
import { fromVsCodeUri, toVsCodeUri } from '../../utils/vsc-utils';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: async (
|
||||
@@ -1,11 +1,11 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { FoamFeature } from '../types';
|
||||
import { FoamFeature } from '../../types';
|
||||
import { TextDecoder } from 'util';
|
||||
import { getGraphStyle, getTitleMaxLength } from '../settings';
|
||||
import { isSome } from '../utils';
|
||||
import { Foam } from '../core/model/foam';
|
||||
import { Logger } from '../core/utils/log';
|
||||
import { fromVsCodeUri } from '../utils/vsc-utils';
|
||||
import { getGraphStyle, getTitleMaxLength } from '../../settings';
|
||||
import { isSome } from '../../utils';
|
||||
import { Foam } from '../../core/model/foam';
|
||||
import { Logger } from '../../core/utils/log';
|
||||
import { fromVsCodeUri } from '../../utils/vsc-utils';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: (context: vscode.ExtensionContext, foamPromise: Promise<Foam>) => {
|
||||
5
packages/foam-vscode/src/features/panels/index.ts
Normal file
5
packages/foam-vscode/src/features/panels/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export { default as backlinks } from './backlinks';
|
||||
export { default as dataviz } from './dataviz';
|
||||
export { default as orphans } from './orphans';
|
||||
export { default as placeholders } from './placeholders';
|
||||
export { default as tags } from './tags-explorer';
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FoamGraph } from '../core/model/graph';
|
||||
import { createTestNote, createTestWorkspace } from '../test/test-utils';
|
||||
import { FoamGraph } from '../../core/model/graph';
|
||||
import { createTestNote, createTestWorkspace } from '../../test/test-utils';
|
||||
import { isOrphan } from './orphans';
|
||||
|
||||
const orphanA = createTestNote({
|
||||
@@ -1,15 +1,15 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { Foam } from '../core/model/foam';
|
||||
import { FoamGraph } from '../core/model/graph';
|
||||
import { URI } from '../core/model/uri';
|
||||
import { getOrphansConfig } from '../settings';
|
||||
import { FoamFeature } from '../types';
|
||||
import { Foam } from '../../core/model/foam';
|
||||
import { FoamGraph } from '../../core/model/graph';
|
||||
import { URI } from '../../core/model/uri';
|
||||
import { getOrphansConfig } from '../../settings';
|
||||
import { FoamFeature } from '../../types';
|
||||
import {
|
||||
GroupedResourcesTreeDataProvider,
|
||||
ResourceTreeItem,
|
||||
UriTreeItem,
|
||||
} from '../utils/grouped-resources-tree-data-provider';
|
||||
import { fromVsCodeUri } from '../utils/vsc-utils';
|
||||
} from '../../utils/grouped-resources-tree-data-provider';
|
||||
import { fromVsCodeUri } from '../../utils/vsc-utils';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: async (
|
||||
@@ -1,12 +1,12 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { Foam } from '../core/model/foam';
|
||||
import { getPlaceholdersConfig } from '../settings';
|
||||
import { FoamFeature } from '../types';
|
||||
import { Foam } from '../../core/model/foam';
|
||||
import { getPlaceholdersConfig } from '../../settings';
|
||||
import { FoamFeature } from '../../types';
|
||||
import {
|
||||
GroupedResourcesTreeDataProvider,
|
||||
UriTreeItem,
|
||||
} from '../utils/grouped-resources-tree-data-provider';
|
||||
import { fromVsCodeUri } from '../utils/vsc-utils';
|
||||
} from '../../utils/grouped-resources-tree-data-provider';
|
||||
import { fromVsCodeUri } from '../../utils/vsc-utils';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: async (
|
||||
@@ -1,10 +1,10 @@
|
||||
import { createTestNote, readFileFromFs } from '../test/test-utils';
|
||||
import { cleanWorkspace, closeEditors } from '../test/test-utils-vscode';
|
||||
import { TagItem, TagReference, TagsProvider } from './tags-tree-view';
|
||||
import { bootstrap, Foam } from '../core/model/foam';
|
||||
import { MarkdownResourceProvider } from '../core/services/markdown-provider';
|
||||
import { FileDataStore, Matcher } from '../core/services/datastore';
|
||||
import { createMarkdownParser } from '../core/services/markdown-parser';
|
||||
import { createTestNote, readFileFromFs } from '../../test/test-utils';
|
||||
import { cleanWorkspace, closeEditors } from '../../test/test-utils-vscode';
|
||||
import { TagItem, TagReference, TagsProvider } from './tags-explorer';
|
||||
import { bootstrap, Foam } from '../../core/model/foam';
|
||||
import { MarkdownResourceProvider } from '../../core/services/markdown-provider';
|
||||
import { FileDataStore, Matcher } from '../../core/services/datastore';
|
||||
import { createMarkdownParser } from '../../core/services/markdown-parser';
|
||||
|
||||
describe('Tags tree panel', () => {
|
||||
let _foam: Foam;
|
||||
@@ -1,11 +1,11 @@
|
||||
import { URI } from '../core/model/uri';
|
||||
import { URI } from '../../core/model/uri';
|
||||
import * as vscode from 'vscode';
|
||||
import { FoamFeature } from '../types';
|
||||
import { getNoteTooltip, isSome } from '../utils';
|
||||
import { toVsCodeRange, toVsCodeUri } from '../utils/vsc-utils';
|
||||
import { Foam } from '../core/model/foam';
|
||||
import { FoamWorkspace } from '../core/model/workspace';
|
||||
import { Resource, Tag } from '../core/model/note';
|
||||
import { FoamFeature } from '../../types';
|
||||
import { getNoteTooltip, isSome } from '../../utils';
|
||||
import { toVsCodeRange, toVsCodeUri } from '../../utils/vsc-utils';
|
||||
import { Foam } from '../../core/model/foam';
|
||||
import { FoamWorkspace } from '../../core/model/workspace';
|
||||
import { Resource, Tag } from '../../core/model/note';
|
||||
|
||||
const TAG_SEPARATOR = '/';
|
||||
const feature: FoamFeature = {
|
||||
@@ -2,8 +2,8 @@ import { window } from 'vscode';
|
||||
import { Resolver } from './variable-resolver';
|
||||
import { Variable } from '../core/common/snippetParser';
|
||||
|
||||
describe('substituteFoamVariables', () => {
|
||||
test('Does nothing if no Foam-specific variables are used', async () => {
|
||||
describe('variable-resolver, text substitution', () => {
|
||||
it('should do nothing if no Foam-specific variables are used', async () => {
|
||||
const input = `
|
||||
# \${AnotherVariable} <-- Unrelated to Foam
|
||||
# \${AnotherVariable:default_value} <-- Unrelated to Foam
|
||||
@@ -31,7 +31,7 @@ describe('substituteFoamVariables', () => {
|
||||
expect(await resolver.resolveText(input)).toEqual(input);
|
||||
});
|
||||
|
||||
test('Correctly substitutes variables that are substrings of one another', async () => {
|
||||
it('should correctly substitute variables that are substrings of one another', async () => {
|
||||
// FOAM_TITLE is a substring of FOAM_TITLE_NON_EXISTENT_VARIABLE
|
||||
// If we're not careful with how we substitute the values
|
||||
// we can end up putting the FOAM_TITLE in place FOAM_TITLE_NON_EXISTENT_VARIABLE should be.
|
||||
@@ -56,8 +56,8 @@ describe('substituteFoamVariables', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveFoamVariables', () => {
|
||||
test('Does nothing for unknown Foam-specific variables', async () => {
|
||||
describe('variable-resolver, variable resolution', () => {
|
||||
it('should do nothing for unknown Foam-specific variables', async () => {
|
||||
const variables = [new Variable('FOAM_FOO')];
|
||||
|
||||
const expected = new Map<string, string>();
|
||||
@@ -67,7 +67,7 @@ describe('resolveFoamVariables', () => {
|
||||
expect(await resolver.resolveAll(variables)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Resolves FOAM_TITLE', async () => {
|
||||
it('should resolve FOAM_TITLE', async () => {
|
||||
const foamTitle = 'My note title';
|
||||
const variables = [new Variable('FOAM_TITLE'), new Variable('FOAM_SLUG')];
|
||||
|
||||
@@ -84,7 +84,7 @@ describe('resolveFoamVariables', () => {
|
||||
expect(await resolver.resolveAll(variables)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Resolves FOAM_TITLE without asking the user when it is provided', async () => {
|
||||
it('should resolve FOAM_TITLE without asking the user when it is provided', async () => {
|
||||
const foamTitle = 'My note title';
|
||||
const variables = [new Variable('FOAM_TITLE')];
|
||||
|
||||
@@ -97,7 +97,7 @@ describe('resolveFoamVariables', () => {
|
||||
expect(await resolver.resolveAll(variables)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Resolves FOAM_DATE_* properties with current day by default', async () => {
|
||||
it('should resolve FOAM_DATE_* properties with current day by default', async () => {
|
||||
const variables = [
|
||||
new Variable('FOAM_DATE_YEAR'),
|
||||
new Variable('FOAM_DATE_YEAR_SHORT'),
|
||||
@@ -134,7 +134,7 @@ describe('resolveFoamVariables', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('Resolves FOAM_DATE_* properties with given date', async () => {
|
||||
it('should resolve FOAM_DATE_* properties with given date', async () => {
|
||||
const targetDate = new Date(2021, 9, 12, 1, 2, 3);
|
||||
const variables = [
|
||||
new Variable('FOAM_DATE_YEAR'),
|
||||
@@ -149,6 +149,7 @@ describe('resolveFoamVariables', () => {
|
||||
new Variable('FOAM_DATE_MINUTE'),
|
||||
new Variable('FOAM_DATE_SECOND'),
|
||||
new Variable('FOAM_DATE_SECONDS_UNIX'),
|
||||
new Variable('FOAM_DATE_WEEK'),
|
||||
];
|
||||
|
||||
const expected = new Map<string, string>();
|
||||
@@ -161,6 +162,7 @@ describe('resolveFoamVariables', () => {
|
||||
expected.set('FOAM_DATE_DAY_NAME', 'Tuesday');
|
||||
expected.set('FOAM_DATE_DAY_NAME_SHORT', 'Tue');
|
||||
expected.set('FOAM_DATE_HOUR', '01');
|
||||
expected.set('FOAM_DATE_WEEK', '41');
|
||||
expected.set('FOAM_DATE_MINUTE', '02');
|
||||
expected.set('FOAM_DATE_SECOND', '03');
|
||||
expected.set(
|
||||
@@ -173,10 +175,35 @@ describe('resolveFoamVariables', () => {
|
||||
|
||||
expect(await resolver.resolveAll(variables)).toEqual(expected);
|
||||
});
|
||||
|
||||
describe('FOAM_DATE_WEEK', () => {
|
||||
it('should start counting weeks from 1', async () => {
|
||||
// week number starts from 1, not 0
|
||||
// the first "partial week" of the year is really the last of the previous
|
||||
const resolver = new Resolver(
|
||||
new Map<string, string>(),
|
||||
new Date(2021, 0, 1, 1, 2, 3)
|
||||
);
|
||||
expect(await resolver.resolve(new Variable('FOAM_DATE_WEEK'))).toEqual(
|
||||
'53'
|
||||
);
|
||||
});
|
||||
|
||||
it('should pad week number to 2 digits', async () => {
|
||||
// week number is 2-digit
|
||||
const resolver = new Resolver(
|
||||
new Map<string, string>(),
|
||||
new Date(2021, 0, 7, 1, 2, 3)
|
||||
);
|
||||
expect(await resolver.resolve(new Variable('FOAM_DATE_WEEK'))).toEqual(
|
||||
'01'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveFoamTemplateVariables', () => {
|
||||
test('Does nothing for template without Foam-specific variables', async () => {
|
||||
describe('variable-resolver, resolveText', () => {
|
||||
it('should do nothing for template without Foam-specific variables', async () => {
|
||||
const input = `
|
||||
# \${AnotherVariable} <-- Unrelated to Foam
|
||||
# \${AnotherVariable:default_value} <-- Unrelated to Foam
|
||||
@@ -191,7 +218,7 @@ describe('resolveFoamTemplateVariables', () => {
|
||||
expect(await resolver.resolveText(input)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Does nothing for unknown Foam-specific variables', async () => {
|
||||
it('should do nothing for unknown Foam-specific variables', async () => {
|
||||
const input = `
|
||||
# $FOAM_FOO
|
||||
# \${FOAM_FOO}
|
||||
@@ -204,7 +231,7 @@ describe('resolveFoamTemplateVariables', () => {
|
||||
expect(await resolver.resolveText(input)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Appends FOAM_SELECTED_TEXT with a newline to the template if there is selected text but FOAM_SELECTED_TEXT is not referenced and the template ends in a newline', async () => {
|
||||
it('should append FOAM_SELECTED_TEXT with a newline to the template if there is selected text but FOAM_SELECTED_TEXT is not referenced and the template ends in a newline', async () => {
|
||||
const foamTitle = 'My note title';
|
||||
|
||||
jest
|
||||
@@ -221,7 +248,7 @@ describe('resolveFoamTemplateVariables', () => {
|
||||
expect(await resolver.resolveText(input)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Appends FOAM_SELECTED_TEXT with a newline to the template if there is selected text but FOAM_SELECTED_TEXT is not referenced and the template ends in multiple newlines', async () => {
|
||||
it('should append FOAM_SELECTED_TEXT with a newline to the template if there is selected text but FOAM_SELECTED_TEXT is not referenced and the template ends in multiple newlines', async () => {
|
||||
const foamTitle = 'My note title';
|
||||
|
||||
jest
|
||||
@@ -238,7 +265,7 @@ describe('resolveFoamTemplateVariables', () => {
|
||||
expect(await resolver.resolveText(input)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Appends FOAM_SELECTED_TEXT without a newline to the template if there is selected text but FOAM_SELECTED_TEXT is not referenced and the template does not end in a newline', async () => {
|
||||
it('should append FOAM_SELECTED_TEXT without a newline to the template if there is selected text but FOAM_SELECTED_TEXT is not referenced and the template does not end in a newline', async () => {
|
||||
const foamTitle = 'My note title';
|
||||
|
||||
jest
|
||||
@@ -255,7 +282,7 @@ describe('resolveFoamTemplateVariables', () => {
|
||||
expect(await resolver.resolveText(input)).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Does not append FOAM_SELECTED_TEXT to a template if there is no selected text and is not referenced', async () => {
|
||||
it('should not append FOAM_SELECTED_TEXT to a template if there is no selected text and is not referenced', async () => {
|
||||
const foamTitle = 'My note title';
|
||||
|
||||
jest
|
||||
|
||||
@@ -18,6 +18,7 @@ const knownFoamVariables = new Set([
|
||||
'FOAM_DATE_MONTH_NAME',
|
||||
'FOAM_DATE_MONTH_NAME_SHORT',
|
||||
'FOAM_DATE_DATE',
|
||||
'FOAM_DATE_WEEK',
|
||||
'FOAM_DATE_DAY_NAME',
|
||||
'FOAM_DATE_DAY_NAME_SHORT',
|
||||
'FOAM_DATE_HOUR',
|
||||
@@ -165,6 +166,25 @@ export class Resolver implements VariableResolver {
|
||||
String(this.foamDate.getDate().valueOf()).padStart(2, '0')
|
||||
);
|
||||
break;
|
||||
case 'FOAM_DATE_WEEK': {
|
||||
// https://en.wikipedia.org/wiki/ISO_8601#Week_dates
|
||||
const date = new Date(this.foamDate);
|
||||
|
||||
// Find Thursday of this week starting on Monday
|
||||
date.setDate(date.getDate() + 4 - (date.getDay() || 7));
|
||||
const thursday = date.getTime();
|
||||
|
||||
// Find January 1st
|
||||
date.setMonth(0); // January
|
||||
date.setDate(1); // 1st
|
||||
const janFirst = date.getTime();
|
||||
|
||||
// Round the amount of days to compensate for daylight saving time
|
||||
const days = Math.round((thursday - janFirst) / 86400000); // 1 day = 86400000 ms
|
||||
const weekDay = Math.floor(days / 7) + 1;
|
||||
value = Promise.resolve(String(weekDay.valueOf()).padStart(2, '0'));
|
||||
break;
|
||||
}
|
||||
case 'FOAM_DATE_DAY_NAME':
|
||||
value = Promise.resolve(
|
||||
this.foamDate.toLocaleString('default', { weekday: 'long' })
|
||||
|
||||
@@ -85,6 +85,8 @@ let model = {
|
||||
style: defaultStyle,
|
||||
showNodesOfType: {
|
||||
placeholder: true,
|
||||
image: false,
|
||||
attachment: false,
|
||||
note: true,
|
||||
tag: true,
|
||||
},
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
👀*This is an early stage project under rapid development. For updates join the [Foam community Discord](https://foambubble.github.io/join-discord/g)! 💬*
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
[](#contributors-)
|
||||
[](#contributors-)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
[](https://foambubble.github.io/join-discord/g)
|
||||
@@ -91,7 +91,7 @@ See for each occurrence the context in which it lives, as well as a preview of t
|
||||
|
||||
### Tag Explorer Panel
|
||||
|
||||
Tag your notes and navigate them with the [Tag Explorer](https://foambubble.github.io/foam/user/user/features/tags).
|
||||
Tag your notes and navigate them with the [Tag Explorer](https://foambubble.github.io/foam/user/features/tags).
|
||||
Foam also supports hierarchical tags.
|
||||
|
||||

|
||||
@@ -327,6 +327,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<td align="center"><a href="https://github.com/lingyv-li"><img src="https://avatars.githubusercontent.com/u/8937944?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Larry Li</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=lingyv-li" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/infogulch"><img src="https://avatars.githubusercontent.com/u/133882?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Joe Taber</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=infogulch" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.readingsnail.pe.kr"><img src="https://avatars.githubusercontent.com/u/1904967?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Woosuk Park</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=readingsnail" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://www.dmurph.com"><img src="https://avatars.githubusercontent.com/u/294026?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Daniel Murphy</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dmurph" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user