mirror of
https://github.com/foambubble/foam.git
synced 2026-01-09 14:08:13 -05:00
Prettier format and chores (#448)
* fix #442 - link to known-issues replaced * formatted settings + enable format on save + improved jest config * removed editorconfig in foam-cli * formatted foam-vscode * removed author in package.json files * minor changes to readme files * fixed husky pre-commit hook
This commit is contained in:
45
.vscode/settings.json
vendored
45
.vscode/settings.json
vendored
@@ -1,24 +1,25 @@
|
||||
// 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.files.ignore": [
|
||||
"**/.vscode/**/*",
|
||||
"**/_layouts/**/*",
|
||||
"**/_site/**/*",
|
||||
"**/node_modules/**/*"
|
||||
],
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
// "editor.formatOnSave": true,
|
||||
"prettier.requireConfig": true
|
||||
}
|
||||
"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.files.ignore": [
|
||||
"**/.vscode/**/*",
|
||||
"**/_layouts/**/*",
|
||||
"**/_site/**/*",
|
||||
"**/node_modules/**/*"
|
||||
],
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"prettier.requireConfig": true,
|
||||
"editor.formatOnSave": true,
|
||||
"jest.debugCodeLens.showWhenTestStateIn": ["fail", "unknown", "pass"]
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ To learn more about how to use **Foam**, read the [[recipes]].
|
||||
|
||||
Getting stuck in the setup? Read the [[frequently-asked-questions]].
|
||||
|
||||
There are [[known-issues]], and I'm sure, many unknown issues! Please [report them on GitHub](http://github.com/foambubble/foam/issues)!
|
||||
Check our [issues on GitHub](http://github.com/foambubble/foam/issues) if you get stuck on something, and create a new one if something doesn't seem right!
|
||||
|
||||
## Features
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
"version": "0.2.0",
|
||||
"description": "Foam",
|
||||
"repository": "git@github.com:foambubble/foam.git",
|
||||
"author": "Jani Eväkallio <jani.evakallio@gmail.com>",
|
||||
"license": "MIT",
|
||||
"private": "true",
|
||||
"workspaces": [
|
||||
@@ -33,7 +32,7 @@
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "tsdx lint"
|
||||
"pre-commit": "yarn lint"
|
||||
}
|
||||
},
|
||||
"prettier": {
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -2,7 +2,6 @@
|
||||
"name": "foam-cli",
|
||||
"description": "Foam CLI",
|
||||
"version": "0.7.4",
|
||||
"author": "Jani Eväkallio @jevakallio",
|
||||
"bin": {
|
||||
"foam": "./bin/run"
|
||||
},
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
# Foam Core
|
||||
|
||||
Repository for tooling used by the other modules
|
||||
This module contains the core functions, model, and API of Foam.
|
||||
It is used by its clients to integrate Foam in various use cases, from VsCode extension, to CLI, to CI integrations.
|
||||
|
||||
## Local Development
|
||||
|
||||
Below is a list of commands you will probably find useful.
|
||||
|
||||
### `npm start` or `yarn start`
|
||||
### `yarn watch`
|
||||
|
||||
Runs the project in development/watch mode. Your project will be rebuilt upon changes.
|
||||
|
||||
### `npm run build` or `yarn build`
|
||||
### `yarn build`
|
||||
|
||||
Bundles the package to the `dist` folder. The package is optimized and bundled with Rollup into multiple formats (CommonJS, UMD, and ES Module).
|
||||
|
||||
### `npm test` or `yarn test`
|
||||
### `yarn test`
|
||||
|
||||
Runs the test watcher (Jest) in an interactive mode.
|
||||
By default, runs tests related to files changed since the last commit.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"name": "foam-core",
|
||||
"author": "Jani Eväkallio",
|
||||
"repository": "https://github.com/foambubble/foam",
|
||||
"version": "0.7.4",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"name": "foam-vscode",
|
||||
"displayName": "Foam for VSCode (Wikilinks to Markdown)",
|
||||
"description": "Generate markdown reference lists from wikilinks in a workspace",
|
||||
"author": "Jani Eväkallio",
|
||||
"repository": {
|
||||
"url": "https://github.com/foambubble/foam",
|
||||
"type": "git"
|
||||
@@ -180,7 +179,7 @@
|
||||
"build": "tsc -p ./",
|
||||
"pretest": "yarn build",
|
||||
"test": "node ./out/test/run-tests.js",
|
||||
"lint": "eslint src --ext ts",
|
||||
"lint": "tsdx lint",
|
||||
"clean": "rimraf out",
|
||||
"watch": "tsc --build ./tsconfig.json ../foam-core/tsconfig.json --watch",
|
||||
"vscode:start-debugging": "yarn clean && yarn watch",
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import {
|
||||
Selection,
|
||||
Uri,
|
||||
window,
|
||||
workspace,
|
||||
WorkspaceConfiguration
|
||||
} from "vscode";
|
||||
import { dirname, join } from "path";
|
||||
import dateFormat from "dateformat";
|
||||
import * as fs from "fs";
|
||||
import { docConfig, focusNote, pathExists } from "./utils";
|
||||
import { workspace, WorkspaceConfiguration } from 'vscode';
|
||||
import { dirname, join } from 'path';
|
||||
import dateFormat from 'dateformat';
|
||||
import * as fs from 'fs';
|
||||
import { docConfig, focusNote, pathExists } from './utils';
|
||||
|
||||
async function openDailyNoteFor(date?: Date) {
|
||||
const foamConfiguration = workspace.getConfiguration("foam");
|
||||
const foamConfiguration = workspace.getConfiguration('foam');
|
||||
const currentDate = date !== undefined ? date : new Date();
|
||||
|
||||
const dailyNotePath = getDailyNotePath(foamConfiguration, currentDate);
|
||||
@@ -26,7 +20,7 @@ async function openDailyNoteFor(date?: Date) {
|
||||
function getDailyNotePath(configuration: WorkspaceConfiguration, date: Date) {
|
||||
const rootDirectory = workspace.workspaceFolders[0].uri.fsPath;
|
||||
const dailyNoteDirectory: string =
|
||||
configuration.get("openDailyNote.directory") ?? ".";
|
||||
configuration.get('openDailyNote.directory') ?? '.';
|
||||
const dailyNoteFilename = getDailyNoteFileName(configuration, date);
|
||||
|
||||
return join(rootDirectory, dailyNoteDirectory, dailyNoteFilename);
|
||||
@@ -37,10 +31,10 @@ function getDailyNoteFileName(
|
||||
date: Date
|
||||
): string {
|
||||
const filenameFormat: string = configuration.get(
|
||||
"openDailyNote.filenameFormat"
|
||||
'openDailyNote.filenameFormat'
|
||||
);
|
||||
const fileExtension: string = configuration.get(
|
||||
"openDailyNote.fileExtension"
|
||||
'openDailyNote.fileExtension'
|
||||
);
|
||||
|
||||
return `${dateFormat(date, filenameFormat, false)}.${fileExtension}`;
|
||||
@@ -58,8 +52,8 @@ async function createDailyNoteIfNotExists(
|
||||
await createDailyNoteDirectoryIfNotExists(dailyNotePath);
|
||||
|
||||
const titleFormat: string =
|
||||
configuration.get("openDailyNote.titleFormat") ??
|
||||
configuration.get("openDailyNote.filenameFormat");
|
||||
configuration.get('openDailyNote.titleFormat') ??
|
||||
configuration.get('openDailyNote.filenameFormat');
|
||||
|
||||
await fs.promises.writeFile(
|
||||
dailyNotePath,
|
||||
@@ -83,5 +77,5 @@ export {
|
||||
openDailyNoteFor,
|
||||
getDailyNoteFileName,
|
||||
createDailyNoteIfNotExists,
|
||||
getDailyNotePath
|
||||
getDailyNotePath,
|
||||
};
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
"use strict";
|
||||
|
||||
import { workspace, ExtensionContext, window, Uri } from "vscode";
|
||||
import { workspace, ExtensionContext, window } from 'vscode';
|
||||
import {
|
||||
bootstrap,
|
||||
FoamConfig,
|
||||
Foam,
|
||||
Services,
|
||||
Logger,
|
||||
FileDataStore
|
||||
} from "foam-core";
|
||||
FileDataStore,
|
||||
} from 'foam-core';
|
||||
|
||||
import { features } from "./features";
|
||||
import { getConfigFromVscode } from "./services/config";
|
||||
import { VsCodeOutputLogger, exposeLogger } from "./services/logging";
|
||||
import { VsCodeDataStore } from "./services/datastore";
|
||||
import { features } from './features';
|
||||
import { getConfigFromVscode } from './services/config';
|
||||
import { VsCodeOutputLogger, exposeLogger } from './services/logging';
|
||||
|
||||
export async function activate(context: ExtensionContext) {
|
||||
const logger = new VsCodeOutputLogger();
|
||||
@@ -21,14 +18,14 @@ export async function activate(context: ExtensionContext) {
|
||||
exposeLogger(context, logger);
|
||||
|
||||
try {
|
||||
Logger.info("Starting Foam");
|
||||
Logger.info('Starting Foam');
|
||||
|
||||
const config: FoamConfig = getConfigFromVscode();
|
||||
const watcher = workspace.createFileSystemWatcher("**/*");
|
||||
const watcher = workspace.createFileSystemWatcher('**/*');
|
||||
const dataStore = new FileDataStore(config, watcher);
|
||||
|
||||
const services: Services = {
|
||||
dataStore: dataStore
|
||||
dataStore: dataStore,
|
||||
};
|
||||
const foamPromise: Promise<Foam> = bootstrap(config, services);
|
||||
|
||||
@@ -41,7 +38,7 @@ export async function activate(context: ExtensionContext) {
|
||||
|
||||
context.subscriptions.push(dataStore, foam, watcher);
|
||||
} catch (e) {
|
||||
Logger.error("An error occurred while bootstrapping Foam", e);
|
||||
Logger.error('An error occurred while bootstrapping Foam', e);
|
||||
window.showErrorMessage(
|
||||
`An error occurred while bootstrapping Foam. ${e.stack}`
|
||||
);
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
import {
|
||||
env,
|
||||
window,
|
||||
Uri,
|
||||
workspace,
|
||||
Position,
|
||||
Selection,
|
||||
commands,
|
||||
} from 'vscode';
|
||||
import { env, window, Uri, Position, Selection, commands } from 'vscode';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
describe('copyWithoutBrackets', () => {
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
import {
|
||||
window,
|
||||
env,
|
||||
ExtensionContext,
|
||||
commands,
|
||||
} from "vscode";
|
||||
import { FoamFeature } from "../types";
|
||||
import { removeBrackets } from "../utils";
|
||||
import { window, env, ExtensionContext, commands } from 'vscode';
|
||||
import { FoamFeature } from '../types';
|
||||
import { removeBrackets } from '../utils';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: (context: ExtensionContext) => {
|
||||
context.subscriptions.push(
|
||||
commands.registerCommand("foam-vscode.copy-without-brackets", copyWithoutBrackets)
|
||||
commands.registerCommand(
|
||||
'foam-vscode.copy-without-brackets',
|
||||
copyWithoutBrackets
|
||||
)
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
async function copyWithoutBrackets () {
|
||||
async function copyWithoutBrackets() {
|
||||
// Get the active text editor
|
||||
const editor = window.activeTextEditor;
|
||||
|
||||
|
||||
@@ -4,17 +4,17 @@ import {
|
||||
ExtensionContext,
|
||||
workspace,
|
||||
Uri,
|
||||
SnippetString
|
||||
} from "vscode";
|
||||
import * as path from "path";
|
||||
import { FoamFeature } from "../types";
|
||||
import { TextEncoder } from "util";
|
||||
import { focusNote } from "../utils";
|
||||
SnippetString,
|
||||
} from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { FoamFeature } from '../types';
|
||||
import { TextEncoder } from 'util';
|
||||
import { focusNote } from '../utils';
|
||||
|
||||
const templatesDir = `${workspace.workspaceFolders[0].uri.path}/.foam/templates`;
|
||||
|
||||
async function getTemplates(): Promise<string[]> {
|
||||
const templates = await workspace.findFiles(".foam/templates/**.md");
|
||||
const templates = await workspace.findFiles('.foam/templates/**.md');
|
||||
// parse title, not whole file!
|
||||
return templates.map(template => path.basename(template.path));
|
||||
}
|
||||
@@ -23,7 +23,7 @@ const feature: FoamFeature = {
|
||||
activate: (context: ExtensionContext) => {
|
||||
context.subscriptions.push(
|
||||
commands.registerCommand(
|
||||
"foam-vscode.create-note-from-template",
|
||||
'foam-vscode.create-note-from-template',
|
||||
async () => {
|
||||
const templates = await getTemplates();
|
||||
const activeFile = window.activeTextEditor?.document?.fileName;
|
||||
@@ -34,14 +34,14 @@ const feature: FoamFeature = {
|
||||
const selectedTemplate = await window.showQuickPick(templates);
|
||||
const folder = await window.showInputBox({
|
||||
prompt: `Where should the template be created?`,
|
||||
value: currentDir
|
||||
value: currentDir,
|
||||
});
|
||||
|
||||
let filename = await window.showInputBox({
|
||||
prompt: `Enter the filename for the new note`,
|
||||
value: ``,
|
||||
validateInput: value =>
|
||||
value.length ? undefined : "Please enter a value!"
|
||||
value.length ? undefined : 'Please enter a value!',
|
||||
});
|
||||
filename = path.extname(filename).length
|
||||
? filename
|
||||
@@ -54,14 +54,14 @@ const feature: FoamFeature = {
|
||||
const snippet = new SnippetString(templateText.toString());
|
||||
await workspace.fs.writeFile(
|
||||
Uri.file(targetFile),
|
||||
new TextEncoder().encode("")
|
||||
new TextEncoder().encode('')
|
||||
);
|
||||
await focusNote(targetFile, true);
|
||||
await window.activeTextEditor.insertSnippet(snippet);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default feature;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import * as vscode from "vscode";
|
||||
import * as path from "path";
|
||||
import { FoamFeature } from "../types";
|
||||
import { Foam, Logger } from "foam-core";
|
||||
import { TextDecoder } from "util";
|
||||
import { getGraphStyle, getTitleMaxLength } from "../settings";
|
||||
import { isSome } from "../utils";
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { FoamFeature } from '../types';
|
||||
import { Foam, Logger } from 'foam-core';
|
||||
import { TextDecoder } from 'util';
|
||||
import { getGraphStyle, getTitleMaxLength } from '../settings';
|
||||
import { isSome } from '../utils';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: (context: vscode.ExtensionContext, foamPromise: Promise<Foam>) => {
|
||||
@@ -19,11 +19,11 @@ const feature: FoamFeature = {
|
||||
}
|
||||
});
|
||||
|
||||
vscode.commands.registerCommand("foam-vscode.show-graph", async () => {
|
||||
vscode.commands.registerCommand('foam-vscode.show-graph', async () => {
|
||||
if (panel) {
|
||||
const columnToShowIn = vscode.window.activeTextEditor
|
||||
? vscode.window.activeTextEditor.viewColumn
|
||||
: undefined;
|
||||
? vscode.window.activeTextEditor.viewColumn
|
||||
: undefined;
|
||||
panel.reveal(columnToShowIn);
|
||||
} else {
|
||||
const foam = await foamPromise;
|
||||
@@ -43,83 +43,83 @@ const feature: FoamFeature = {
|
||||
});
|
||||
|
||||
vscode.window.onDidChangeActiveTextEditor(e => {
|
||||
if (e.document.uri.scheme === "file") {
|
||||
if (e.document.uri.scheme === 'file') {
|
||||
const note = foam.notes.getNote(e.document.uri);
|
||||
if (isSome(note)) {
|
||||
panel.webview.postMessage({
|
||||
type: "didSelectNote",
|
||||
payload: note.uri.path
|
||||
type: 'didSelectNote',
|
||||
payload: note.uri.path,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function updateGraph(panel: vscode.WebviewPanel, foam: Foam) {
|
||||
const graph = generateGraphData(foam);
|
||||
panel.webview.postMessage({
|
||||
type: "didUpdateGraphData",
|
||||
payload: graph
|
||||
type: 'didUpdateGraphData',
|
||||
payload: graph,
|
||||
});
|
||||
}
|
||||
|
||||
function generateGraphData(foam: Foam) {
|
||||
const graph = {
|
||||
nodes: {},
|
||||
edges: new Set()
|
||||
edges: new Set(),
|
||||
};
|
||||
|
||||
foam.notes.getNotes().forEach(n => {
|
||||
const links = foam.notes.getForwardLinks(n.uri);
|
||||
graph.nodes[n.uri.path] = {
|
||||
id: n.uri.path,
|
||||
type: "note",
|
||||
type: 'note',
|
||||
uri: n.uri,
|
||||
title: cutTitle(n.title)
|
||||
title: cutTitle(n.title),
|
||||
};
|
||||
links.forEach(link => {
|
||||
if (!(link.to.path in graph.nodes)) {
|
||||
graph.nodes[link.to.path] = {
|
||||
id: link.to,
|
||||
type: "placeholder",
|
||||
type: 'placeholder',
|
||||
uri: `virtual:${link.to}`,
|
||||
title:
|
||||
"slug" in link.link
|
||||
'slug' in link.link
|
||||
? cutTitle(link.link.slug)
|
||||
: cutTitle(link.link.label)
|
||||
: cutTitle(link.link.label),
|
||||
};
|
||||
}
|
||||
graph.edges.add({
|
||||
source: link.from.path,
|
||||
target: link.to.path
|
||||
target: link.to.path,
|
||||
});
|
||||
});
|
||||
});
|
||||
return {
|
||||
nodes: graph.nodes,
|
||||
links: Array.from(graph.edges)
|
||||
links: Array.from(graph.edges),
|
||||
};
|
||||
}
|
||||
|
||||
function cutTitle(title: string): string {
|
||||
const maxLen = getTitleMaxLength();
|
||||
if (maxLen > 0 && title.length > maxLen) {
|
||||
return title.substring(0, maxLen).concat("...");
|
||||
return title.substring(0, maxLen).concat('...');
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
async function createGraphPanel(foam: Foam, context: vscode.ExtensionContext) {
|
||||
const panel = vscode.window.createWebviewPanel(
|
||||
"foam-graph",
|
||||
"Foam Graph",
|
||||
'foam-graph',
|
||||
'Foam Graph',
|
||||
vscode.ViewColumn.Two,
|
||||
{
|
||||
enableScripts: true,
|
||||
retainContextWhenHidden: true
|
||||
retainContextWhenHidden: true,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -128,7 +128,7 @@ async function createGraphPanel(foam: Foam, context: vscode.ExtensionContext) {
|
||||
panel.webview.onDidReceiveMessage(
|
||||
async message => {
|
||||
switch (message.type) {
|
||||
case "webviewDidLoad":
|
||||
case 'webviewDidLoad':
|
||||
const styles = getGraphStyle();
|
||||
panel.webview.postMessage({
|
||||
type: 'didUpdateStyle',
|
||||
@@ -137,7 +137,7 @@ async function createGraphPanel(foam: Foam, context: vscode.ExtensionContext) {
|
||||
updateGraph(panel, foam);
|
||||
break;
|
||||
|
||||
case "webviewDidSelectNode":
|
||||
case 'webviewDidSelectNode':
|
||||
const noteUri = vscode.Uri.parse(message.payload);
|
||||
const selectedNote = foam.notes.getNote(noteUri);
|
||||
|
||||
@@ -149,8 +149,8 @@ async function createGraphPanel(foam: Foam, context: vscode.ExtensionContext) {
|
||||
}
|
||||
break;
|
||||
|
||||
case "error":
|
||||
Logger.error("An error occurred in the graph view", message.payload);
|
||||
case 'error':
|
||||
Logger.error('An error occurred in the graph view', message.payload);
|
||||
break;
|
||||
}
|
||||
},
|
||||
@@ -166,27 +166,27 @@ async function getWebviewContent(
|
||||
panel: vscode.WebviewPanel
|
||||
) {
|
||||
const webviewPath = vscode.Uri.file(
|
||||
path.join(context.extensionPath, "static", "dataviz.html")
|
||||
path.join(context.extensionPath, 'static', 'dataviz.html')
|
||||
);
|
||||
const file = await vscode.workspace.fs.readFile(webviewPath);
|
||||
const text = new TextDecoder("utf-8").decode(file);
|
||||
const text = new TextDecoder('utf-8').decode(file);
|
||||
|
||||
const webviewUri = (fileName: string) =>
|
||||
panel.webview
|
||||
.asWebviewUri(
|
||||
vscode.Uri.file(path.join(context.extensionPath, "static", fileName))
|
||||
vscode.Uri.file(path.join(context.extensionPath, 'static', fileName))
|
||||
)
|
||||
.toString();
|
||||
|
||||
const graphDirectory = path.join("graphs", "default");
|
||||
const graphDirectory = path.join('graphs', 'default');
|
||||
const textWithVariables = text
|
||||
.replace(
|
||||
"${graphPath}",
|
||||
"{{" + path.join(graphDirectory, "graph.js") + "}}"
|
||||
'${graphPath}', // eslint-disable-line
|
||||
'{{' + path.join(graphDirectory, 'graph.js') + '}}'
|
||||
)
|
||||
.replace(
|
||||
"${graphStylesPath}",
|
||||
"{{" + path.join(graphDirectory, "graph.css") + "}}"
|
||||
'${graphStylesPath}', // eslint-disable-line
|
||||
'{{' + path.join(graphDirectory, 'graph.css') + '}}'
|
||||
);
|
||||
|
||||
// Basic templating. Will replace the script paths with the
|
||||
|
||||
@@ -4,31 +4,31 @@ import {
|
||||
ExtensionContext,
|
||||
commands,
|
||||
Range,
|
||||
ProgressLocation
|
||||
} from "vscode";
|
||||
import * as fs from "fs";
|
||||
import { FoamFeature } from "../types";
|
||||
ProgressLocation,
|
||||
} from 'vscode';
|
||||
import * as fs from 'fs';
|
||||
import { FoamFeature } from '../types';
|
||||
import {
|
||||
applyTextEdit,
|
||||
generateLinkReferences,
|
||||
generateHeading,
|
||||
Foam
|
||||
} from "foam-core";
|
||||
Foam,
|
||||
} from 'foam-core';
|
||||
|
||||
import {
|
||||
getWikilinkDefinitionSetting,
|
||||
LinkReferenceDefinitionsSetting
|
||||
} from "../settings";
|
||||
import { astPositionToVsCodePosition } from "../utils";
|
||||
LinkReferenceDefinitionsSetting,
|
||||
} from '../settings';
|
||||
import { astPositionToVsCodePosition } from '../utils';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: (context: ExtensionContext, foamPromise: Promise<Foam>) => {
|
||||
context.subscriptions.push(
|
||||
commands.registerCommand("foam-vscode.janitor", async () =>
|
||||
commands.registerCommand('foam-vscode.janitor', async () =>
|
||||
janitor(await foamPromise)
|
||||
)
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
async function janitor(foam: Foam) {
|
||||
@@ -44,7 +44,7 @@ async function janitor(foam: Foam) {
|
||||
const outcome = await window.withProgress(
|
||||
{
|
||||
location: ProgressLocation.Notification,
|
||||
title: `Running Foam Janitor across ${noOfFiles} files!`
|
||||
title: `Running Foam Janitor across ${noOfFiles} files!`,
|
||||
},
|
||||
() => runJanitor(foam)
|
||||
);
|
||||
@@ -75,8 +75,8 @@ async function runJanitor(foam: Foam) {
|
||||
|
||||
const dirtyTextDocuments = workspace.textDocuments.filter(
|
||||
textDocument =>
|
||||
(textDocument.languageId === "markdown" ||
|
||||
textDocument.languageId === "mdx") &&
|
||||
(textDocument.languageId === 'markdown' ||
|
||||
textDocument.languageId === 'mdx') &&
|
||||
textDocument.isDirty
|
||||
);
|
||||
|
||||
@@ -151,6 +151,7 @@ async function runJanitor(foam: Foam) {
|
||||
|
||||
if (heading || definitions) {
|
||||
// Apply Edits
|
||||
/* eslint-disable */
|
||||
await editor.edit(editBuilder => {
|
||||
// Note: The ordering matters. Definitions need to be inserted
|
||||
// before heading, since inserting a heading changes line numbers below
|
||||
@@ -169,13 +170,14 @@ async function runJanitor(foam: Foam) {
|
||||
editBuilder.replace(start, heading.newText);
|
||||
}
|
||||
});
|
||||
/* eslint-enable */
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
updatedHeadingCount,
|
||||
updatedDefinitionListCount,
|
||||
changedAnyFiles: updatedHeadingCount + updatedDefinitionListCount
|
||||
changedAnyFiles: updatedHeadingCount + updatedDefinitionListCount,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { ExtensionContext, commands } from "vscode";
|
||||
import { FoamFeature } from "../types";
|
||||
import { openDailyNoteFor } from "../dated-notes";
|
||||
import { ExtensionContext, commands } from 'vscode';
|
||||
import { FoamFeature } from '../types';
|
||||
import { openDailyNoteFor } from '../dated-notes';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: (context: ExtensionContext) => {
|
||||
context.subscriptions.push(
|
||||
commands.registerCommand("foam-vscode.open-daily-note", openDailyNoteFor)
|
||||
commands.registerCommand('foam-vscode.open-daily-note', openDailyNoteFor)
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default feature;
|
||||
|
||||
@@ -7,15 +7,15 @@ import {
|
||||
CompletionItem,
|
||||
CompletionItemKind,
|
||||
CompletionList,
|
||||
CompletionTriggerKind
|
||||
} from "vscode";
|
||||
CompletionTriggerKind,
|
||||
} from 'vscode';
|
||||
import {
|
||||
createDailyNoteIfNotExists,
|
||||
getDailyNoteFileName,
|
||||
openDailyNoteFor,
|
||||
getDailyNotePath
|
||||
} from "../dated-notes";
|
||||
import { FoamFeature } from "../types";
|
||||
getDailyNotePath,
|
||||
} from '../dated-notes';
|
||||
import { FoamFeature } from '../types';
|
||||
|
||||
interface DateSnippet {
|
||||
snippet: string;
|
||||
@@ -24,18 +24,18 @@ interface DateSnippet {
|
||||
}
|
||||
|
||||
const daysOfWeek = [
|
||||
{ day: "sunday", index: 0 },
|
||||
{ day: "monday", index: 1 },
|
||||
{ day: "tuesday", index: 2 },
|
||||
{ day: "wednesday", index: 3 },
|
||||
{ day: "thursday", index: 4 },
|
||||
{ day: "friday", index: 5 },
|
||||
{ day: "saturday", index: 6 }
|
||||
{ day: 'sunday', index: 0 },
|
||||
{ day: 'monday', index: 1 },
|
||||
{ day: 'tuesday', index: 2 },
|
||||
{ day: 'wednesday', index: 3 },
|
||||
{ day: 'thursday', index: 4 },
|
||||
{ day: 'friday', index: 5 },
|
||||
{ day: 'saturday', index: 6 },
|
||||
];
|
||||
type AfterCompletionOptions = "noop" | "createNote" | "navigateToNote";
|
||||
const foamConfig = workspace.getConfiguration("foam");
|
||||
type AfterCompletionOptions = 'noop' | 'createNote' | 'navigateToNote';
|
||||
const foamConfig = workspace.getConfiguration('foam');
|
||||
const foamNavigateOnSelect: AfterCompletionOptions = foamConfig.get(
|
||||
"dateSnippets.afterCompletion"
|
||||
'dateSnippets.afterCompletion'
|
||||
);
|
||||
|
||||
const generateDayOfWeekSnippets = (): DateSnippet[] => {
|
||||
@@ -51,7 +51,7 @@ const generateDayOfWeekSnippets = (): DateSnippet[] => {
|
||||
return {
|
||||
date: target,
|
||||
detail: `Get a daily note link for ${day}`,
|
||||
snippet: `/${day}`
|
||||
snippet: `/${day}`,
|
||||
};
|
||||
});
|
||||
return snippets;
|
||||
@@ -64,49 +64,57 @@ const createCompletionItem = ({ snippet, date, detail }: DateSnippet) => {
|
||||
);
|
||||
completionItem.insertText = getDailyNoteLink(date);
|
||||
completionItem.detail = `${completionItem.insertText} - ${detail}`;
|
||||
if (foamNavigateOnSelect !== "noop") {
|
||||
if (foamNavigateOnSelect !== 'noop') {
|
||||
completionItem.command = {
|
||||
command: "foam-vscode.open-dated-note",
|
||||
title: "Open a note for the given date",
|
||||
arguments: [date]
|
||||
command: 'foam-vscode.open-dated-note',
|
||||
title: 'Open a note for the given date',
|
||||
arguments: [date],
|
||||
};
|
||||
}
|
||||
return completionItem;
|
||||
};
|
||||
|
||||
const getDailyNoteLink = (date: Date) => {
|
||||
const foamExtension = foamConfig.get("openDailyNote.fileExtension");
|
||||
const foamExtension = foamConfig.get('openDailyNote.fileExtension');
|
||||
const name = getDailyNoteFileName(foamConfig, date);
|
||||
return `[[${name.replace(`.${foamExtension}`, "")}]]`;
|
||||
return `[[${name.replace(`.${foamExtension}`, '')}]]`;
|
||||
};
|
||||
|
||||
const snippets: (() => DateSnippet)[] = [
|
||||
() => ({
|
||||
detail: "Insert a link to today's daily note",
|
||||
snippet: "/day",
|
||||
date: new Date()
|
||||
snippet: '/day',
|
||||
date: new Date(),
|
||||
}),
|
||||
() => ({
|
||||
detail: "Insert a link to today's daily note",
|
||||
snippet: "/today",
|
||||
date: new Date()
|
||||
snippet: '/today',
|
||||
date: new Date(),
|
||||
}),
|
||||
() => {
|
||||
const today = new Date();
|
||||
return {
|
||||
detail: "Insert a link to tomorrow's daily note",
|
||||
snippet: "/tomorrow",
|
||||
date: new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1)
|
||||
snippet: '/tomorrow',
|
||||
date: new Date(
|
||||
today.getFullYear(),
|
||||
today.getMonth(),
|
||||
today.getDate() + 1
|
||||
),
|
||||
};
|
||||
},
|
||||
() => {
|
||||
const today = new Date();
|
||||
return {
|
||||
detail: "Insert a link to yesterday's daily note",
|
||||
snippet: "/yesterday",
|
||||
date: new Date(today.getFullYear(), today.getMonth(), today.getDate() - 1)
|
||||
snippet: '/yesterday',
|
||||
date: new Date(
|
||||
today.getFullYear(),
|
||||
today.getMonth(),
|
||||
today.getDate() - 1
|
||||
),
|
||||
};
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
const computedSnippets: ((number: number) => DateSnippet)[] = [
|
||||
@@ -119,7 +127,7 @@ const computedSnippets: ((number: number) => DateSnippet)[] = [
|
||||
today.getFullYear(),
|
||||
today.getMonth(),
|
||||
today.getDate() + days
|
||||
)
|
||||
),
|
||||
};
|
||||
},
|
||||
(weeks: number) => {
|
||||
@@ -131,7 +139,7 @@ const computedSnippets: ((number: number) => DateSnippet)[] = [
|
||||
today.getFullYear(),
|
||||
today.getMonth(),
|
||||
today.getDate() + 7 * weeks
|
||||
)
|
||||
),
|
||||
};
|
||||
},
|
||||
(months: number) => {
|
||||
@@ -143,7 +151,7 @@ const computedSnippets: ((number: number) => DateSnippet)[] = [
|
||||
today.getFullYear(),
|
||||
today.getMonth() + months,
|
||||
today.getDate()
|
||||
)
|
||||
),
|
||||
};
|
||||
},
|
||||
(years: number) => {
|
||||
@@ -155,9 +163,9 @@ const computedSnippets: ((number: number) => DateSnippet)[] = [
|
||||
today.getFullYear() + years,
|
||||
today.getMonth(),
|
||||
today.getDate()
|
||||
)
|
||||
),
|
||||
};
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
const completions: CompletionItemProvider = {
|
||||
@@ -170,10 +178,10 @@ const completions: CompletionItemProvider = {
|
||||
|
||||
const completionItems = [
|
||||
...snippets.map(item => createCompletionItem(item())),
|
||||
...generateDayOfWeekSnippets().map(item => createCompletionItem(item))
|
||||
...generateDayOfWeekSnippets().map(item => createCompletionItem(item)),
|
||||
];
|
||||
return completionItems;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const computedCompletions: CompletionItemProvider = {
|
||||
@@ -187,7 +195,7 @@ const computedCompletions: CompletionItemProvider = {
|
||||
const range = document.getWordRangeAtPosition(position, /\S+/);
|
||||
const snippetString = document.getText(range);
|
||||
const matches = snippetString.match(/(\d+)/);
|
||||
const number: string = matches ? matches[0] : "1";
|
||||
const number: string = matches ? matches[0] : '1';
|
||||
const completionItems = computedSnippets.map(item => {
|
||||
const completionItem = createCompletionItem(item(parseInt(number)));
|
||||
completionItem.range = range;
|
||||
@@ -195,14 +203,14 @@ const computedCompletions: CompletionItemProvider = {
|
||||
});
|
||||
// We still want the list to be treated as "incomplete", because the user may add another number
|
||||
return new CompletionList(completionItems, true);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const datedNoteCommand = (date: Date) => {
|
||||
if (foamNavigateOnSelect === "navigateToNote") {
|
||||
if (foamNavigateOnSelect === 'navigateToNote') {
|
||||
return openDailyNoteFor(date);
|
||||
}
|
||||
if (foamNavigateOnSelect === "createNote") {
|
||||
if (foamNavigateOnSelect === 'createNote') {
|
||||
return createDailyNoteIfNotExists(
|
||||
foamConfig,
|
||||
getDailyNotePath(foamConfig, date),
|
||||
@@ -214,18 +222,18 @@ const datedNoteCommand = (date: Date) => {
|
||||
const feature: FoamFeature = {
|
||||
activate: (context: ExtensionContext) => {
|
||||
context.subscriptions.push(
|
||||
commands.registerCommand("foam-vscode.open-dated-note", date =>
|
||||
commands.registerCommand('foam-vscode.open-dated-note', date =>
|
||||
datedNoteCommand(date)
|
||||
)
|
||||
);
|
||||
languages.registerCompletionItemProvider("markdown", completions, "/");
|
||||
languages.registerCompletionItemProvider('markdown', completions, '/');
|
||||
languages.registerCompletionItemProvider(
|
||||
"markdown",
|
||||
'markdown',
|
||||
computedCompletions,
|
||||
"/",
|
||||
"+"
|
||||
'/',
|
||||
'+'
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default feature;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as vscode from "vscode";
|
||||
import { FoamFeature } from "../../types";
|
||||
import { Foam, Note } from "foam-core";
|
||||
import * as vscode from 'vscode';
|
||||
import { FoamFeature } from '../../types';
|
||||
import { Foam, Note } from 'foam-core';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: async (
|
||||
@@ -11,12 +11,12 @@ const feature: FoamFeature = {
|
||||
const provider = new TagsProvider(foam);
|
||||
context.subscriptions.push(
|
||||
vscode.window.registerTreeDataProvider(
|
||||
"foam-vscode.tags-explorer",
|
||||
'foam-vscode.tags-explorer',
|
||||
provider
|
||||
)
|
||||
);
|
||||
foam.notes.onDidUpdateNote(() => provider.refresh());
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default feature;
|
||||
@@ -68,7 +68,7 @@ export class TagsProvider implements vscode.TreeDataProvider<TagTreeItem> {
|
||||
});
|
||||
return Promise.resolve([
|
||||
new TagSearch(element.tag),
|
||||
...references.sort((a, b) => a.title.localeCompare(b.title))
|
||||
...references.sort((a, b) => a.title.localeCompare(b.title)),
|
||||
]);
|
||||
}
|
||||
if (!element) {
|
||||
@@ -89,13 +89,13 @@ export class Tag extends vscode.TreeItem {
|
||||
) {
|
||||
super(tag, vscode.TreeItemCollapsibleState.Collapsed);
|
||||
this.description = `${this.noteUris.length} reference${
|
||||
this.noteUris.length !== 1 ? "s" : ""
|
||||
this.noteUris.length !== 1 ? 's' : ''
|
||||
}`;
|
||||
this.tooltip = this.description;
|
||||
}
|
||||
|
||||
iconPath = new vscode.ThemeIcon("symbol-number");
|
||||
contextValue = "tag";
|
||||
iconPath = new vscode.ThemeIcon('symbol-number');
|
||||
contextValue = 'tag';
|
||||
}
|
||||
|
||||
export class TagSearch extends vscode.TreeItem {
|
||||
@@ -104,21 +104,21 @@ export class TagSearch extends vscode.TreeItem {
|
||||
const searchString = `#${tag}`;
|
||||
this.tooltip = `Search ${searchString} in workspace`;
|
||||
this.command = {
|
||||
command: "workbench.action.findInFiles",
|
||||
command: 'workbench.action.findInFiles',
|
||||
arguments: [
|
||||
{
|
||||
query: searchString,
|
||||
triggerSearch: true,
|
||||
matchWholeWord: true,
|
||||
isCaseSensitive: true
|
||||
}
|
||||
isCaseSensitive: true,
|
||||
},
|
||||
],
|
||||
title: "Search"
|
||||
title: 'Search',
|
||||
};
|
||||
}
|
||||
|
||||
iconPath = new vscode.ThemeIcon("search");
|
||||
contextValue = "tag-search";
|
||||
iconPath = new vscode.ThemeIcon('search');
|
||||
contextValue = 'tag-search';
|
||||
}
|
||||
|
||||
export class TagReference extends vscode.TreeItem {
|
||||
@@ -142,18 +142,18 @@ export class TagReference extends vscode.TreeItem {
|
||||
// TODO I like about this showing the git state of the note, but I don't like the md icon
|
||||
this.resourceUri = resourceUri;
|
||||
this.command = {
|
||||
command: "vscode.open",
|
||||
command: 'vscode.open',
|
||||
arguments: [
|
||||
resourceUri,
|
||||
{
|
||||
preview: true,
|
||||
selection: selection
|
||||
}
|
||||
selection: selection,
|
||||
},
|
||||
],
|
||||
title: "Open File"
|
||||
title: 'Open File',
|
||||
};
|
||||
}
|
||||
|
||||
iconPath = new vscode.ThemeIcon("note");
|
||||
contextValue = "reference";
|
||||
iconPath = new vscode.ThemeIcon('note');
|
||||
contextValue = 'reference';
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { uniq } from "lodash";
|
||||
import { uniq } from 'lodash';
|
||||
import {
|
||||
CancellationToken,
|
||||
CodeLens,
|
||||
@@ -10,8 +10,8 @@ import {
|
||||
TextDocument,
|
||||
window,
|
||||
workspace,
|
||||
Position
|
||||
} from "vscode";
|
||||
Position,
|
||||
} from 'vscode';
|
||||
|
||||
import {
|
||||
createMarkdownReferences,
|
||||
@@ -19,33 +19,33 @@ import {
|
||||
NoteGraphAPI,
|
||||
Foam,
|
||||
LINK_REFERENCE_DEFINITION_HEADER,
|
||||
LINK_REFERENCE_DEFINITION_FOOTER
|
||||
} from "foam-core";
|
||||
LINK_REFERENCE_DEFINITION_FOOTER,
|
||||
} from 'foam-core';
|
||||
import {
|
||||
hasEmptyTrailing,
|
||||
docConfig,
|
||||
loadDocConfig,
|
||||
isMdEditor,
|
||||
mdDocSelector,
|
||||
getText
|
||||
} from "../utils";
|
||||
import { FoamFeature } from "../types";
|
||||
getText,
|
||||
} from '../utils';
|
||||
import { FoamFeature } from '../types';
|
||||
import {
|
||||
getWikilinkDefinitionSetting,
|
||||
LinkReferenceDefinitionsSetting
|
||||
} from "../settings";
|
||||
LinkReferenceDefinitionsSetting,
|
||||
} from '../settings';
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: async (context: ExtensionContext, foamPromise: Promise<Foam>) => {
|
||||
const foam = await foamPromise;
|
||||
|
||||
context.subscriptions.push(
|
||||
commands.registerCommand("foam-vscode.update-wikilinks", () =>
|
||||
commands.registerCommand('foam-vscode.update-wikilinks', () =>
|
||||
updateReferenceList(foam.notes)
|
||||
),
|
||||
|
||||
workspace.onWillSaveTextDocument(e => {
|
||||
if (e.document.languageId === "markdown") {
|
||||
if (e.document.languageId === 'markdown') {
|
||||
updateDocumentInNoteGraph(foam, e.document);
|
||||
e.waitUntil(updateReferenceList(foam.notes));
|
||||
}
|
||||
@@ -67,7 +67,7 @@ const feature: FoamFeature = {
|
||||
updateDocumentInNoteGraph(foam, editor.document);
|
||||
updateReferenceList(foam.notes);
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function updateDocumentInNoteGraph(foam: Foam, document: TextDocument) {
|
||||
@@ -119,7 +119,7 @@ async function updateReferenceList(foam: NoteGraphAPI) {
|
||||
|
||||
// references must always be preceded by an empty line
|
||||
const spacing = doc.lineAt(range.start.line - 1).isEmptyOrWhitespace
|
||||
? ""
|
||||
? ''
|
||||
: docConfig.eol;
|
||||
|
||||
await editor.edit(editBuilder => {
|
||||
@@ -161,7 +161,7 @@ function generateReferenceList(
|
||||
return [
|
||||
LINK_REFERENCE_DEFINITION_HEADER,
|
||||
...references,
|
||||
LINK_REFERENCE_DEFINITION_FOOTER
|
||||
LINK_REFERENCE_DEFINITION_FOOTER,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -220,14 +220,14 @@ class WikilinkReferenceCodeLensProvider implements CodeLensProvider {
|
||||
const oldRefs = getText(range).replace(/\r?\n|\r/g, docConfig.eol);
|
||||
const newRefs = refs.join(docConfig.eol);
|
||||
|
||||
let status = oldRefs === newRefs ? "up to date" : "out of date";
|
||||
let status = oldRefs === newRefs ? 'up to date' : 'out of date';
|
||||
|
||||
return [
|
||||
new CodeLens(range, {
|
||||
arguments: [],
|
||||
title: `Link references (${status})`,
|
||||
command: ""
|
||||
})
|
||||
command: '',
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { workspace } from "vscode";
|
||||
import { FoamConfig, createConfigFromFolders } from "foam-core";
|
||||
import { getIgnoredFilesSetting } from "../settings";
|
||||
import { workspace } from 'vscode';
|
||||
import { FoamConfig, createConfigFromFolders } from 'foam-core';
|
||||
import { getIgnoredFilesSetting } from '../settings';
|
||||
|
||||
// TODO this is still to be improved - foam config should
|
||||
// not be dependent on vscode but at the moment it's convenient
|
||||
@@ -10,6 +10,6 @@ export const getConfigFromVscode = (): FoamConfig => {
|
||||
const excludeGlobs = getIgnoredFilesSetting();
|
||||
|
||||
return createConfigFromFolders(workspaceFolders, {
|
||||
ignore: excludeGlobs.map(g => g.toString())
|
||||
ignore: excludeGlobs.map(g => g.toString()),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -4,11 +4,11 @@ import {
|
||||
URI,
|
||||
FoamConfig,
|
||||
IDisposable,
|
||||
Logger
|
||||
} from "foam-core";
|
||||
import { workspace, FileSystemWatcher, EventEmitter } from "vscode";
|
||||
import { TextDecoder } from "util";
|
||||
import { isSome } from "../utils";
|
||||
Logger,
|
||||
} from 'foam-core';
|
||||
import { workspace, FileSystemWatcher, EventEmitter } from 'vscode';
|
||||
import { TextDecoder } from 'util';
|
||||
import { isSome } from '../utils';
|
||||
|
||||
export class VsCodeDataStore implements IDataStore, IDisposable {
|
||||
onDidCreateEmitter = new EventEmitter<URI>();
|
||||
@@ -22,23 +22,23 @@ export class VsCodeDataStore implements IDataStore, IDisposable {
|
||||
files: URI[];
|
||||
|
||||
constructor(private config: FoamConfig) {
|
||||
this.watcher = workspace.createFileSystemWatcher("**/*");
|
||||
this.watcher = workspace.createFileSystemWatcher('**/*');
|
||||
this.watcher.onDidCreate(async uri => {
|
||||
await this.listFiles();
|
||||
if (this.isMatch(uri)) {
|
||||
Logger.info("Created: ", uri);
|
||||
Logger.info('Created: ', uri);
|
||||
this.onDidCreateEmitter.fire(uri);
|
||||
}
|
||||
});
|
||||
this.watcher.onDidChange(uri => {
|
||||
if (this.isMatch(uri)) {
|
||||
Logger.info("Updated: ", uri);
|
||||
Logger.info('Updated: ', uri);
|
||||
this.onDidChangeEmitter.fire(uri);
|
||||
}
|
||||
});
|
||||
this.watcher.onDidDelete(uri => {
|
||||
if (this.isMatch(uri)) {
|
||||
Logger.info("Deleted: ", uri);
|
||||
Logger.info('Deleted: ', uri);
|
||||
this.files = this.files.filter(f => f.path !== uri.path);
|
||||
this.onDidDeleteEmitter.fire(uri);
|
||||
}
|
||||
@@ -47,8 +47,8 @@ export class VsCodeDataStore implements IDataStore, IDisposable {
|
||||
|
||||
async listFiles(): Promise<URI[]> {
|
||||
this.files = await workspace.findFiles(
|
||||
`{${this.config.includeGlobs.join(",")}}`,
|
||||
`{${this.config.ignoreGlobs.join(",")}}`
|
||||
`{${this.config.includeGlobs.join(',')}}`,
|
||||
`{${this.config.ignoreGlobs.join(',')}}`
|
||||
);
|
||||
|
||||
return this.files;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { window, commands, ExtensionContext } from "vscode";
|
||||
import { ILogger, IDisposable, LogLevel, BaseLogger } from "foam-core";
|
||||
import { getFoamLoggerLevel } from "../settings";
|
||||
import { window, commands, ExtensionContext } from 'vscode';
|
||||
import { ILogger, IDisposable, LogLevel, BaseLogger } from 'foam-core';
|
||||
import { getFoamLoggerLevel } from '../settings';
|
||||
|
||||
export interface VsCodeLogger extends ILogger, IDisposable {
|
||||
show();
|
||||
}
|
||||
|
||||
export class VsCodeOutputLogger extends BaseLogger implements VsCodeLogger {
|
||||
private channel = window.createOutputChannel("Foam");
|
||||
private channel = window.createOutputChannel('Foam');
|
||||
|
||||
constructor() {
|
||||
super(getFoamLoggerLevel());
|
||||
this.channel.appendLine("Foam Logging: " + getFoamLoggerLevel());
|
||||
this.channel.appendLine('Foam Logging: ' + getFoamLoggerLevel());
|
||||
}
|
||||
|
||||
log(lvl: LogLevel, msg?: any, ...extra: any[]): void {
|
||||
@@ -42,12 +42,12 @@ export const exposeLogger = (
|
||||
logger: VsCodeLogger
|
||||
): void => {
|
||||
context.subscriptions.push(
|
||||
commands.registerCommand("foam-vscode.set-log-level", async () => {
|
||||
const items: LogLevel[] = ["debug", "info", "warn", "error"];
|
||||
commands.registerCommand('foam-vscode.set-log-level', async () => {
|
||||
const items: LogLevel[] = ['debug', 'info', 'warn', 'error'];
|
||||
const level = await window.showQuickPick(
|
||||
items.map(item => ({
|
||||
label: item,
|
||||
description: item === logger.getLevel() && "Current"
|
||||
description: item === logger.getLevel() && 'Current',
|
||||
}))
|
||||
);
|
||||
logger.setLevel(level.label);
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
import * as path from "path";
|
||||
import fs from "fs";
|
||||
import os from "os";
|
||||
import { runTests } from "vscode-test";
|
||||
import * as path from 'path';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import { runTests } from 'vscode-test';
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
// The folder containing the Extension Manifest package.json
|
||||
// Passed to `--extensionDevelopmentPath`
|
||||
const extensionDevelopmentPath = path.resolve(__dirname, "../../");
|
||||
const extensionDevelopmentPath = path.resolve(__dirname, '../../');
|
||||
|
||||
// The path to the extension test script
|
||||
// Passed to --extensionTestsPath
|
||||
const extensionTestsPath = path.resolve(__dirname, "./suite");
|
||||
const extensionTestsPath = path.resolve(__dirname, './suite');
|
||||
|
||||
const tmpWorkspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), "foam-"));
|
||||
const tmpWorkspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'foam-'));
|
||||
|
||||
// Download VS Code, unzip it and run the integration test
|
||||
await runTests({
|
||||
extensionDevelopmentPath,
|
||||
extensionTestsPath,
|
||||
launchArgs: [tmpWorkspaceDir, "--disable-extensions"],
|
||||
launchArgs: [tmpWorkspaceDir, '--disable-extensions'],
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Failed to run tests");
|
||||
console.error('Failed to run tests');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
* and so on..
|
||||
*/
|
||||
|
||||
import path from "path";
|
||||
import { runCLI } from "@jest/core";
|
||||
import path from 'path';
|
||||
import { runCLI } from '@jest/core';
|
||||
|
||||
const rootDir = path.resolve(__dirname, "../..");
|
||||
const rootDir = path.resolve(__dirname, '../..');
|
||||
|
||||
export function run(): Promise<void> {
|
||||
process.stdout.write = (buffer: string) => {
|
||||
@@ -23,25 +23,25 @@ export function run(): Promise<void> {
|
||||
console.error(buffer);
|
||||
return true;
|
||||
};
|
||||
process.env.FORCE_COLOR = "1";
|
||||
process.env.NODE_ENV = "test";
|
||||
process.env.FORCE_COLOR = '1';
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const { results } = await runCLI(
|
||||
{
|
||||
rootDir,
|
||||
roots: ["<rootDir>/src"],
|
||||
transform: JSON.stringify({ "^.+\\.ts$": "ts-jest" }),
|
||||
roots: ['<rootDir>/src'],
|
||||
transform: JSON.stringify({ '^.+\\.ts$': 'ts-jest' }),
|
||||
runInBand: true,
|
||||
testRegex: "\\.(test|spec)\\.ts$",
|
||||
testRegex: '\\.(test|spec)\\.ts$',
|
||||
testEnvironment:
|
||||
"<rootDir>/src/test/support/extended-vscode-environment.js",
|
||||
setupFiles: ["<rootDir>/src/test/support/jest-setup.ts"],
|
||||
setupFilesAfterEnv: ["jest-extended"],
|
||||
'<rootDir>/src/test/support/extended-vscode-environment.js',
|
||||
setupFiles: ['<rootDir>/src/test/support/jest-setup.ts'],
|
||||
setupFilesAfterEnv: ['jest-extended'],
|
||||
globals: JSON.stringify({
|
||||
"ts-jest": {
|
||||
tsconfig: path.resolve(rootDir, "./tsconfig.json"),
|
||||
'ts-jest': {
|
||||
tsconfig: path.resolve(rootDir, './tsconfig.json'),
|
||||
},
|
||||
}),
|
||||
testTimeout: 20000,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Based on https://github.com/svsool/vscode-memo/blob/master/src/test/env/ExtendedVscodeEnvironment.js
|
||||
const VscodeEnvironment = require("jest-environment-vscode");
|
||||
const VscodeEnvironment = require('jest-environment-vscode');
|
||||
|
||||
class ExtendedVscodeEnvironment extends VscodeEnvironment {
|
||||
async setup() {
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
// Based on https://github.com/svsool/vscode-memo/blob/master/src/test/config/jestSetup.ts
|
||||
jest.mock("vscode", () => (global as any).vscode, { virtual: true });
|
||||
jest.mock('vscode', () => (global as any).vscode, { virtual: true });
|
||||
|
||||
6
packages/foam-vscode/src/types.d.ts
vendored
6
packages/foam-vscode/src/types.d.ts
vendored
@@ -1,6 +1,6 @@
|
||||
import { ExtensionContext } from "vscode";
|
||||
import { Foam } from "foam-core";
|
||||
import { ExtensionContext } from 'vscode';
|
||||
import { Foam } from 'foam-core';
|
||||
|
||||
export interface FoamFeature {
|
||||
activate: (context: ExtensionContext, foamPromise: Promise<Foam>) => void
|
||||
activate: (context: ExtensionContext, foamPromise: Promise<Foam>) => void;
|
||||
}
|
||||
|
||||
@@ -1,61 +1,65 @@
|
||||
import { dropExtension, removeBrackets, toTitleCase } from './utils';
|
||||
|
||||
describe("dropExtension", () => {
|
||||
test("returns file name without extension", () => {
|
||||
describe('dropExtension', () => {
|
||||
test('returns file name without extension', () => {
|
||||
expect(dropExtension('file.md')).toEqual('file');
|
||||
});
|
||||
});
|
||||
|
||||
describe("removeBrackets", () => {
|
||||
it("removes the brackets", () => {
|
||||
const input = "hello world [[this-is-it]]";
|
||||
describe('removeBrackets', () => {
|
||||
it('removes the brackets', () => {
|
||||
const input = 'hello world [[this-is-it]]';
|
||||
const actual = removeBrackets(input);
|
||||
const expected = "hello world This Is It";
|
||||
const expected = 'hello world This Is It';
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it("removes the brackets and the md file extension", () => {
|
||||
const input = "hello world [[this-is-it.md]]";
|
||||
it('removes the brackets and the md file extension', () => {
|
||||
const input = 'hello world [[this-is-it.md]]';
|
||||
const actual = removeBrackets(input);
|
||||
const expected = "hello world This Is It";
|
||||
const expected = 'hello world This Is It';
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it("removes the brackets and the mdx file extension", () => {
|
||||
const input = "hello world [[this-is-it.mdx]]";
|
||||
it('removes the brackets and the mdx file extension', () => {
|
||||
const input = 'hello world [[this-is-it.mdx]]';
|
||||
const actual = removeBrackets(input);
|
||||
const expected = "hello world This Is It";
|
||||
const expected = 'hello world This Is It';
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it("removes the brackets and the markdown file extension", () => {
|
||||
const input = "hello world [[this-is-it.markdown]]";
|
||||
it('removes the brackets and the markdown file extension', () => {
|
||||
const input = 'hello world [[this-is-it.markdown]]';
|
||||
const actual = removeBrackets(input);
|
||||
const expected = "hello world This Is It";
|
||||
const expected = 'hello world This Is It';
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it("removes the brackets even with numbers", () => {
|
||||
const input = "hello world [[2020-07-21.markdown]]";
|
||||
it('removes the brackets even with numbers', () => {
|
||||
const input = 'hello world [[2020-07-21.markdown]]';
|
||||
const actual = removeBrackets(input);
|
||||
const expected = "hello world 2020 07 21";
|
||||
const expected = 'hello world 2020 07 21';
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it("removes brackets for more than one word", () => {
|
||||
const input = "I am reading this as part of the [[book-club]] put on by [[egghead]] folks (Lauro).";
|
||||
it('removes brackets for more than one word', () => {
|
||||
const input =
|
||||
'I am reading this as part of the [[book-club]] put on by [[egghead]] folks (Lauro).';
|
||||
const actual = removeBrackets(input);
|
||||
const expected = "I am reading this as part of the Book Club put on by Egghead folks (Lauro).";
|
||||
const expected =
|
||||
'I am reading this as part of the Book Club put on by Egghead folks (Lauro).';
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("toTitleCase", () => {
|
||||
it("title cases a word", () => {
|
||||
const input = "look at this really long sentence but I am calling it a word";
|
||||
describe('toTitleCase', () => {
|
||||
it('title cases a word', () => {
|
||||
const input =
|
||||
'look at this really long sentence but I am calling it a word';
|
||||
const actual = toTitleCase(input);
|
||||
const expected = "Look At This Really Long Sentence But I Am Calling It A Word";
|
||||
const expected =
|
||||
'Look At This Really Long Sentence But I Am Calling It A Word';
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it("works on one word", () => {
|
||||
const input = "word";
|
||||
it('works on one word', () => {
|
||||
const input = 'word';
|
||||
const actual = toTitleCase(input);
|
||||
const expected = "Word";
|
||||
const expected = 'Word';
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,10 +7,10 @@ import {
|
||||
TextEditor,
|
||||
workspace,
|
||||
Uri,
|
||||
Selection
|
||||
} from "vscode";
|
||||
import * as fs from "fs";
|
||||
import { Logger } from "foam-core";
|
||||
Selection,
|
||||
} from 'vscode';
|
||||
import * as fs from 'fs';
|
||||
import { Logger } from 'foam-core';
|
||||
|
||||
interface Point {
|
||||
line: number;
|
||||
@@ -18,34 +18,34 @@ interface Point {
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
export const docConfig = { tab: " ", eol: "\r\n" };
|
||||
export const docConfig = { tab: ' ', eol: '\r\n' };
|
||||
|
||||
export const mdDocSelector = [
|
||||
{ language: "markdown", scheme: "file" },
|
||||
{ language: "markdown", scheme: "untitled" }
|
||||
{ language: 'markdown', scheme: 'file' },
|
||||
{ language: 'markdown', scheme: 'untitled' },
|
||||
];
|
||||
|
||||
export function loadDocConfig() {
|
||||
// Load workspace config
|
||||
let activeEditor = window.activeTextEditor;
|
||||
if (!activeEditor) {
|
||||
Logger.debug("Failed to load config, no active editor");
|
||||
Logger.debug('Failed to load config, no active editor');
|
||||
return;
|
||||
}
|
||||
|
||||
docConfig.eol = activeEditor.document.eol === EndOfLine.CRLF ? "\r\n" : "\n";
|
||||
docConfig.eol = activeEditor.document.eol === EndOfLine.CRLF ? '\r\n' : '\n';
|
||||
|
||||
let tabSize = Number(activeEditor.options.tabSize);
|
||||
let insertSpaces = activeEditor.options.insertSpaces;
|
||||
if (insertSpaces) {
|
||||
docConfig.tab = " ".repeat(tabSize);
|
||||
docConfig.tab = ' '.repeat(tabSize);
|
||||
} else {
|
||||
docConfig.tab = "\t";
|
||||
docConfig.tab = '\t';
|
||||
}
|
||||
}
|
||||
|
||||
export function isMdEditor(editor: TextEditor) {
|
||||
return editor && editor.document && editor.document.languageId === "markdown";
|
||||
return editor && editor.document && editor.document.languageId === 'markdown';
|
||||
}
|
||||
|
||||
export function detectGeneratedCode(
|
||||
@@ -61,7 +61,7 @@ export function detectGeneratedCode(
|
||||
if (headerLine < 0 || headerLine >= footerLine) {
|
||||
return {
|
||||
range: null,
|
||||
lines: []
|
||||
lines: [],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ export function detectGeneratedCode(
|
||||
new Position(headerLine, 0),
|
||||
new Position(footerLine, lines[footerLine].length + 1)
|
||||
),
|
||||
lines: lines.slice(headerLine + 1, footerLine + 1)
|
||||
lines: lines.slice(headerLine + 1, footerLine + 1),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -83,9 +83,9 @@ export function getText(range: Range): string {
|
||||
}
|
||||
|
||||
export function dropExtension(path: string): string {
|
||||
const parts = path.split(".");
|
||||
const parts = path.split('.');
|
||||
parts.pop();
|
||||
return parts.join(".");
|
||||
return parts.join('.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,17 +103,17 @@ export const astPositionToVsCodePosition = (point: Point): Position => {
|
||||
*/
|
||||
export function removeBrackets(s: string): string {
|
||||
// take in the string, split on space
|
||||
const stringSplitBySpace = s.split(" ");
|
||||
const stringSplitBySpace = s.split(' ');
|
||||
|
||||
// loop through words
|
||||
const modifiedWords = stringSplitBySpace.map(currentWord => {
|
||||
if (currentWord.includes("[[")) {
|
||||
if (currentWord.includes('[[')) {
|
||||
// all of these transformations will turn this "[[you-are-awesome]]"
|
||||
// to this "you are awesome"
|
||||
let word = currentWord.replace(/(\[\[)/g, "");
|
||||
word = word.replace(/(\]\])/g, "");
|
||||
word = word.replace(/(.mdx|.md|.markdown)/g, "");
|
||||
word = word.replace(/[-]/g, " ");
|
||||
let word = currentWord.replace(/(\[\[)/g, '');
|
||||
word = word.replace(/(\]\])/g, '');
|
||||
word = word.replace(/(.mdx|.md|.markdown)/g, '');
|
||||
word = word.replace(/[-]/g, ' ');
|
||||
|
||||
// then we titlecase the word so "you are awesome"
|
||||
// becomes "You Are Awesome"
|
||||
@@ -125,7 +125,7 @@ export function removeBrackets(s: string): string {
|
||||
return currentWord;
|
||||
});
|
||||
|
||||
return modifiedWords.join(" ");
|
||||
return modifiedWords.join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,9 +135,9 @@ export function removeBrackets(s: string): string {
|
||||
*/
|
||||
export function toTitleCase(word: string): string {
|
||||
return word
|
||||
.split(" ")
|
||||
.split(' ')
|
||||
.map(word => word[0].toUpperCase() + word.substring(1))
|
||||
.join(" ");
|
||||
.join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,10 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="graph" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0;"></div>
|
||||
<div
|
||||
id="graph"
|
||||
style="position: absolute; top: 0; left: 0; right: 0; bottom: 0;"
|
||||
></div>
|
||||
<!-- To test the graph locally in a broswer:
|
||||
1. copy the json data object received in the message payload
|
||||
2. paste the content in test-data.js
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
const CONTAINER_ID = "graph";
|
||||
const CONTAINER_ID = 'graph';
|
||||
|
||||
/** The style fallback. This values should only be set when all else failed. */
|
||||
const styleFallback = {
|
||||
background: "#202020",
|
||||
background: '#202020',
|
||||
fontSize: 12,
|
||||
highlightedForeground: "#f9c74f",
|
||||
highlightedForeground: '#f9c74f',
|
||||
node: {
|
||||
note: "#277da1",
|
||||
placeholder: "#545454",
|
||||
unknown: "#f94144"
|
||||
}
|
||||
note: '#277da1',
|
||||
placeholder: '#545454',
|
||||
unknown: '#f94144',
|
||||
},
|
||||
};
|
||||
|
||||
function getStyle(name) {
|
||||
@@ -36,27 +36,29 @@ let model = {
|
||||
nodeInfo: {},
|
||||
data: {
|
||||
nodes: [],
|
||||
links: []
|
||||
links: [],
|
||||
},
|
||||
/** The style property.
|
||||
* It tries to be set using VSCode values,
|
||||
* in the case it fails, use the fallback style values.
|
||||
*/
|
||||
style: {
|
||||
background: getStyle(`--vscode-panel-background`)
|
||||
?? styleFallback.background,
|
||||
fontSize: parseInt(getStyle(`--vscode-font-size`) ?? styleFallback.fontSize) - 2,
|
||||
highlightedForeground: getStyle("--vscode-list-highlightForeground")
|
||||
?? styleFallback.highlightedForeground,
|
||||
background:
|
||||
getStyle(`--vscode-panel-background`) ?? styleFallback.background,
|
||||
fontSize:
|
||||
parseInt(getStyle(`--vscode-font-size`) ?? styleFallback.fontSize) - 2,
|
||||
highlightedForeground:
|
||||
getStyle('--vscode-list-highlightForeground') ??
|
||||
styleFallback.highlightedForeground,
|
||||
node: {
|
||||
note: getStyle("--vscode-editor-foreground")
|
||||
?? styleFallback.node.note,
|
||||
placeholder: getStyle("--vscode-list-deemphasizedForeground")
|
||||
?? styleFallback.node.placeholder,
|
||||
unknown: getStyle("--vscode-editor-foreground")
|
||||
?? styleFallback.node.unknown
|
||||
}
|
||||
}
|
||||
note: getStyle('--vscode-editor-foreground') ?? styleFallback.node.note,
|
||||
placeholder:
|
||||
getStyle('--vscode-list-deemphasizedForeground') ??
|
||||
styleFallback.node.placeholder,
|
||||
unknown:
|
||||
getStyle('--vscode-editor-foreground') ?? styleFallback.node.unknown,
|
||||
},
|
||||
},
|
||||
};
|
||||
const graph = ForceGraph();
|
||||
|
||||
@@ -103,7 +105,7 @@ const Actions = {
|
||||
});
|
||||
remaining.forEach(nodeId => {
|
||||
m.data.nodes.push({
|
||||
id: nodeId
|
||||
id: nodeId,
|
||||
});
|
||||
});
|
||||
m.data.links = links; // links can be swapped out without problem
|
||||
@@ -140,28 +142,34 @@ const Actions = {
|
||||
return;
|
||||
}
|
||||
model.style = {
|
||||
background: newStyle.background
|
||||
?? getStyle(`--vscode-panel-background`)
|
||||
?? styleFallback.background,
|
||||
fontSize: newStyle.fontSize
|
||||
?? parseInt(getStyle(`--vscode-font-size`) ?? styleFallback.fontSize) - 2,
|
||||
highlightedForeground: newStyle.highlightedForeground
|
||||
?? getStyle("--vscode-list-highlightForeground")
|
||||
?? styleFallback.highlightedForeground,
|
||||
background:
|
||||
newStyle.background ??
|
||||
getStyle(`--vscode-panel-background`) ??
|
||||
styleFallback.background,
|
||||
fontSize:
|
||||
newStyle.fontSize ??
|
||||
parseInt(getStyle(`--vscode-font-size`) ?? styleFallback.fontSize) - 2,
|
||||
highlightedForeground:
|
||||
newStyle.highlightedForeground ??
|
||||
getStyle('--vscode-list-highlightForeground') ??
|
||||
styleFallback.highlightedForeground,
|
||||
node: {
|
||||
note: newStyle.node?.note
|
||||
?? getStyle("--vscode-editor-foreground")
|
||||
?? styleFallback.node.note,
|
||||
placeholder: newStyle.node?.placeholder
|
||||
?? getStyle("--vscode-list-deemphasizedForeground")
|
||||
?? styleFallback.node.placeholder,
|
||||
unknown: newStyle.node?.unknown
|
||||
?? getStyle("--vscode-editor-foreground")
|
||||
?? styleFallback.node.unknow,
|
||||
note:
|
||||
newStyle.node?.note ??
|
||||
getStyle('--vscode-editor-foreground') ??
|
||||
styleFallback.node.note,
|
||||
placeholder:
|
||||
newStyle.node?.placeholder ??
|
||||
getStyle('--vscode-list-deemphasizedForeground') ??
|
||||
styleFallback.node.placeholder,
|
||||
unknown:
|
||||
newStyle.node?.unknown ??
|
||||
getStyle('--vscode-editor-foreground') ??
|
||||
styleFallback.node.unknow,
|
||||
},
|
||||
};
|
||||
graph.backgroundColor(model.style.background);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function initDataviz(channel) {
|
||||
@@ -170,13 +178,13 @@ function initDataviz(channel) {
|
||||
.graphData(model.data)
|
||||
.backgroundColor(model.style.background)
|
||||
.linkHoverPrecision(8)
|
||||
.d3Force("x", d3.forceX())
|
||||
.d3Force("y", d3.forceY())
|
||||
.d3Force("collide", d3.forceCollide(graph.nodeRelSize()))
|
||||
.d3Force('x', d3.forceX())
|
||||
.d3Force('y', d3.forceY())
|
||||
.d3Force('collide', d3.forceCollide(graph.nodeRelSize()))
|
||||
.linkWidth(0.2)
|
||||
.linkDirectionalParticles(1)
|
||||
.linkDirectionalParticleWidth(link =>
|
||||
getLinkState(link, model) === "highlighted" ? 1 : 0
|
||||
getLinkState(link, model) === 'highlighted' ? 1 : 0
|
||||
)
|
||||
.nodeCanvasObject((node, ctx, globalScale) => {
|
||||
const info = model.nodeInfo[node.id];
|
||||
@@ -189,7 +197,7 @@ function initDataviz(channel) {
|
||||
const fontSize = model.style.fontSize / globalScale;
|
||||
let textColor = d3.rgb(fill);
|
||||
textColor.opacity =
|
||||
getNodeState(node.id, model) === "highlighted"
|
||||
getNodeState(node.id, model) === 'highlighted'
|
||||
? 1
|
||||
: labelAlpha(globalScale);
|
||||
const label = info.title;
|
||||
@@ -204,16 +212,16 @@ function initDataviz(channel) {
|
||||
Actions.highlightNode(node?.id);
|
||||
})
|
||||
.onNodeClick((node, event) => {
|
||||
if (event.getModifierState("Control") || event.getModifierState("Meta")) {
|
||||
if (event.getModifierState('Control') || event.getModifierState('Meta')) {
|
||||
channel.postMessage({
|
||||
type: "webviewDidSelectNode",
|
||||
payload: node.id
|
||||
type: 'webviewDidSelectNode',
|
||||
payload: node.id,
|
||||
});
|
||||
}
|
||||
Actions.selectNode(node.id, event.getModifierState("Shift"));
|
||||
Actions.selectNode(node.id, event.getModifierState('Shift'));
|
||||
})
|
||||
.onBackgroundClick(event => {
|
||||
Actions.selectNode(null, event.getModifierState("Shift"));
|
||||
Actions.selectNode(null, event.getModifierState('Shift'));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -236,53 +244,53 @@ function augmentGraphInfo(data) {
|
||||
function getNodeColor(nodeId, model) {
|
||||
const info = model.nodeInfo[nodeId];
|
||||
const style = model.style;
|
||||
const typeFill = style.node[info.type || "unknown"];
|
||||
const typeFill = style.node[info.type || 'unknown'];
|
||||
switch (getNodeState(nodeId, model)) {
|
||||
case "regular":
|
||||
case 'regular':
|
||||
return { fill: typeFill, border: typeFill };
|
||||
case "lessened":
|
||||
case 'lessened':
|
||||
const darker = d3.hsl(typeFill).darker(3);
|
||||
return { fill: darker, border: darker };
|
||||
case "highlighted":
|
||||
case 'highlighted':
|
||||
return {
|
||||
fill: typeFill,
|
||||
border: style.highlightedForeground
|
||||
border: style.highlightedForeground,
|
||||
};
|
||||
default:
|
||||
throw new Error("Unknown type for node", nodeId);
|
||||
throw new Error('Unknown type for node', nodeId);
|
||||
}
|
||||
}
|
||||
|
||||
function getLinkColor(link, model) {
|
||||
const style = model.style;
|
||||
switch (getLinkState(link, model)) {
|
||||
case "regular":
|
||||
case 'regular':
|
||||
return d3.hsl(style.node.note).darker(2);
|
||||
case "highlighted":
|
||||
case 'highlighted':
|
||||
return style.highlightedForeground;
|
||||
case "lessened":
|
||||
case 'lessened':
|
||||
return d3.hsl(style.node.note).darker(4);
|
||||
default:
|
||||
throw new Error("Unknown type for link", link);
|
||||
throw new Error('Unknown type for link', link);
|
||||
}
|
||||
}
|
||||
|
||||
function getNodeState(nodeId, model) {
|
||||
return model.selectedNodes.has(nodeId) || model.hoverNode === nodeId
|
||||
? "highlighted"
|
||||
? 'highlighted'
|
||||
: model.focusNodes.size === 0
|
||||
? "regular"
|
||||
? 'regular'
|
||||
: model.focusNodes.has(nodeId)
|
||||
? "regular"
|
||||
: "lessened";
|
||||
? 'regular'
|
||||
: 'lessened';
|
||||
}
|
||||
|
||||
function getLinkState(link, model) {
|
||||
return model.focusNodes.size === 0
|
||||
? "regular"
|
||||
? 'regular'
|
||||
: model.focusLinks.has(link)
|
||||
? "highlighted"
|
||||
: "lessened";
|
||||
? 'highlighted'
|
||||
: 'lessened';
|
||||
}
|
||||
|
||||
const Draw = ctx => ({
|
||||
@@ -296,12 +304,12 @@ const Draw = ctx => ({
|
||||
},
|
||||
text: function(text, x, y, size, color) {
|
||||
ctx.font = `${size}px Sans-Serif`;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "top";
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.fillStyle = color;
|
||||
ctx.fillText(text, x, y);
|
||||
return this;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// init the app
|
||||
@@ -310,34 +318,34 @@ try {
|
||||
|
||||
window.onload = () => {
|
||||
initDataviz(vscode);
|
||||
console.log("ready");
|
||||
console.log('ready');
|
||||
vscode.postMessage({
|
||||
type: "webviewDidLoad"
|
||||
type: 'webviewDidLoad',
|
||||
});
|
||||
};
|
||||
|
||||
window.addEventListener("error", error => {
|
||||
window.addEventListener('error', error => {
|
||||
vscode.postMessage({
|
||||
type: "error",
|
||||
type: 'error',
|
||||
payload: {
|
||||
message: error.message,
|
||||
filename: error.filename,
|
||||
lineno: error.lineno,
|
||||
colno: error.colno,
|
||||
error: error.error
|
||||
}
|
||||
error: error.error,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener("message", event => {
|
||||
window.addEventListener('message', event => {
|
||||
const message = event.data;
|
||||
switch (message.type) {
|
||||
case "didUpdateGraphData":
|
||||
case 'didUpdateGraphData':
|
||||
const graphData = augmentGraphInfo(message.payload);
|
||||
console.log("didUpdateGraphData", graphData);
|
||||
console.log('didUpdateGraphData', graphData);
|
||||
Actions.refresh(graphData);
|
||||
break;
|
||||
case "didSelectNote":
|
||||
case 'didSelectNote':
|
||||
const noteId = message.payload;
|
||||
const node = graph.graphData().nodes.find(node => node.id === noteId);
|
||||
if (node) {
|
||||
@@ -345,28 +353,28 @@ try {
|
||||
Actions.selectNode(noteId);
|
||||
}
|
||||
break;
|
||||
case "didUpdateStyle":
|
||||
case 'didUpdateStyle':
|
||||
const style = message.payload;
|
||||
Actions.updateStyle(style);
|
||||
break;
|
||||
}
|
||||
});
|
||||
} catch {
|
||||
console.log("VsCode not detected");
|
||||
console.log('VsCode not detected');
|
||||
}
|
||||
|
||||
window.addEventListener("resize", () => {
|
||||
window.addEventListener('resize', () => {
|
||||
graph.width(window.innerWidth).height(window.innerHeight);
|
||||
});
|
||||
|
||||
// For testing
|
||||
if (window.data) {
|
||||
console.log("Test mode");
|
||||
console.log('Test mode');
|
||||
window.model = model;
|
||||
window.graph = graph;
|
||||
window.onload = () => {
|
||||
initDataviz({
|
||||
postMessage: message => console.log("message", message)
|
||||
postMessage: message => console.log('message', message),
|
||||
});
|
||||
const graphData = augmentGraphInfo(window.data);
|
||||
Actions.refresh(graphData);
|
||||
|
||||
@@ -38,6 +38,8 @@ Quick links to next documentation sections
|
||||
- [Call To Adventure](https://foambubble.github.io/foam#call-to-adventure)
|
||||
- [Thanks and attribution](https://foambubble.github.io/foam#thanks-and-attribution)
|
||||
|
||||
You can also browse the [docs folder](https://github.com/foambubble/foam/tree/master/docs).
|
||||
|
||||
## License
|
||||
|
||||
Foam is licensed under the [MIT license](LICENSE).
|
||||
|
||||
Reference in New Issue
Block a user