Tiddlywiki and VS Code?

I was thinking of doing a VS Code extension and wondered if anyone had done/started anything similar?

Essentially, I want to use Tiddlywiki as a project planning tool and a lightweight issue tracker. I’ve done a couple macros that get the kind of workflow I want, but having things in a separate app apart from my developer tooling, and having the documentation away from my code, definitely slows things down.

I’m thinking of something that adds a Wiki tab to the VS Code sidebar, opening a configured path in a local WebView. The wiki path is configurable via setting. Ideally you’d set it locally per project/workspace and commit those settings, so opening the project opens whatever wiki you’ve configured for that workspace.

I’m also considering writing a saver that uses whatever file API VS Code extensions expose. And if the wiki at the configured path isn’t found, an empty wiki with the saver preloaded is generated and opened.

Has anyone done anything like this? I wouldn’t want to start a project if someone already has/is, or if there’s something that’s abandoned and just needs a bit of updating.

3 Likes

Hi,
I don’t know of any VSCode plugin that you describe but I’d like to beta or even alpha-test if you need some feedback.

I didn’t have time to dig into VSCode plugin programming yet, but I would be interested.

Do you intend to start a TW server like backend to store single tiddlers or do you intend to create a single-file wiki saver?

Ooooh, very interesting idea. I also have wondered if hosting a wiki-view inside VS Code is a actionable thing…

I wrote the VS Code TW5 Syntax plugin. That might help you get started.

1 Like

What I’m imagining is a TiddlyWiki side panel that loads a configurable path, defaulting to wiki.html, from the workspace. I’d also create a saver that passes data back to the extension, which writes the new file out to the old path. If a wiki doesn’t exist, opening the view would create a new one from a copy shipped with the extension and prepopulated with the saver. Otherwise you could install the saver into an existing wiki and run it that way.

Haven’t done a lot with VS Code extensions, but so far I have a WebView panel and am fairly close to loading an existing wiki into that.

My goal is to open a blank project, press ctrl-alt-w/ctrl-shift-w, immediately have an empty wiki configured to save via the extension, and start hacking.

Anyway, was curious if something like that existed, but it doesn’t seem to. Hopefully I’ll have something to post here soon.

OK. I think that’s a good start. TW savers are relatively straight forward. See: TiddlyWiki5/core/modules/savers at master · Jermolene/TiddlyWiki5 · GitHub

Once it works, I think there is a high chance, that it can be included into the TW core, if you use ES5 js code only.

As you can see there are some settings that are needed for TW to know about savers.

They should have a header like this:

/*\
title: $:/core/modules/savers/<new-saver-name>.js
type: application/javascript
module-type: saver

A short description about the saver
\*/

It should export functions similar to:

NewSaver.prototype.save = function(text,method,callback,options) { ...

NewSaver.prototype.info = { ...

NewSaver.prototype.canSave = function(wiki) { ...

The first saver that returns .canSave() as true, will be used to save the wiki.

.info should contain a priority and a capabilities element. So the lower the priority number the higher in the list it will be.

Edit: Quote from https://tiddlywiki.com/dev/#Saver

The syncer module uses the saver with the highest priority capable of the requested method to save the file.

So in your case .canSave() should test, if the wiki runs as a VSCode plugin. … A bit of testing will be needed. Since there are some savers out in the wild, that basically always return true :confused:

some info that may help

I think it should default to the /docs/ directory path. If a docs/ path is part of a GitHub repo, it will be easy to create a gh-page using it.

Since the GitHub-saver is part of the TW core, it would be possible to directly write it back to the gh-page from the web, if an auth-token is provided.

just an idea

Cool, I have a draft saver ready. 2 questions:

  1. I just copied the custom saver and made various tweaks that look like they should get it working in VS Code. I then go to import the tiddler via the import form. But I don’t see JavaScript as a content-type, nor does the tiddler seem to be titled with what I’ve set in the comment tag. Should importing correctly handle JavaScript files, or do I need to build the wiki via nodejs first? For the moment I’m not building a full plugin–I’m just trying to package the tiddler as a single file that can be imported. If it can be included in core once I’ve got it working, that’d probably be best.

  2. Does anything look obviously wrong with this? I still have to actually run it of course, but I want to be sure nothing blatantly stands out.

/*\
title: $:/ndarilek/vscode-integration/saver.js
type: application/javascript
module-type: saver

Saves via the VS Code integration extension
\*/
(function () {

	"use strict";

	let vscode = null;
	if (!!acquireVsCodeApi) {
		vscode = acquireVsCodeApi();
	}

	var VscodeSaver = function (wiki) {
	};

	CustomSaver.prototype.save = function (text, method, callback) {
		vscode.postMessage({ command: "save", text });
		// Errors are surfaced in VS Code.
		callback(null);
		return true;
	};

	/*
	Information about this saver
	*/
	CustomSaver.prototype.info = {
		name: "vs code",
		priority: 4000,
		capabilities: ["save", "autosave"]
	};

	/*
	Static method that returns true if this saver is capable of working
	*/
	exports.canSave = function (wiki) {
		try {
			return !!acquireVsCodeApi;
		} catch (err) {
			console.log({ msg: "vs code saver is disabled", reason: err });
			return false;
		}
	};

	/*
	Create an instance of this saver
	*/
	exports.create = function (wiki) {
		return new VscodeSaver(wiki);
	};
})();

Given that the extension creates the wiki if it isn’t found, I’d like to avoid creating subdirectories that don’t exist, especially for opinionated tools like GH Pages that I don’t intend to use. It’s fairly easy to change the setting globally or per workspace, but having to create missing directories makes things a bit more complicated.

I’m not sure, if the internal core code can handle the space in vs code. None of the other savers use spaces. So may be you should use "VSCode" instead.

Instead of let you can use var to stay with ES5 spec. … It’s also not needed, that you indent the “first” code level by 1 tab even if the (function () { wraps this code.

You can use the following formatting, if you want. … It’s only a view tab characters less, but any bit counts in the end :wink:

(function () {

"use strict";

var vscode = null;
if (!!acquireVsCodeApi) {
	vscode = acquireVsCodeApi();
}

In TW every function fails gracefully, except we can’t guarantee the code integrity anymore. Logging to the console should be avoided, except for testing. So some production code does contain comments: // console.log – but most of the time it’s completely removed.

Since your saver will only work in a VSCode environment it will always “throw” the log-message in the browser, which would make it “noisy” in browsers without the possibility to “silence” it.

Cool, thanks for all this feedback. The one thing I’m still not sure about: should I have been able to just import this .js file and have the fields picked up from the comments? Because that’s the bit I can’t get to work. Do I just import as is, and set the fields manually from the comment?

The core/node.js environment will auto load .js files with the right “front matter” as tiddlers/modules.

In order to import easily to a stand-alone *.html wiki, rename the file from “script.js” to “script.js.tid” and make sure the “front matter” is valid. The drag-drop import mechanism will then recognize the tw5 “title”, “type”, etc, fiields.

Ahh, Now I do understand the question. If you use Joshua’s workflow make sure, that your file header looks as follows. So no special comments.

title: $:/ndarilek/vscode-integration/saver.js
type: application/javascript
module-type: saver

(function () {
	"use strict";

If you create a tiddler named: $:/ndarilek/vscode-integration/saver.js

You can leave the comment section alone, BUT you need to set the type and the module-type fields manually as with any other tiddler.

The startup mechanism will pick it up as code. As I wrote the code seems to throw an exception, which will not work if the wiki is loaded with a browser.

-m

It did run some tests, if there is a chance to be implemented as a standard saver. It needs to look more like this:

title: $:/ndarilek/vscode-integration/saver.js
type: application/javascript
module-type: saver

(function () {
	"use strict";

	var VscodeSaver = function (wiki) {
		this.vscode = acquireVsCodeApi();
		this.wiki = wiki;
	};

	VscodeSaver.prototype.save = function (text, method, callback) {
		this.vscode.postMessage({ command: "save", text });
		// Errors are surfaced in VS Code.
		callback(null);
		return true;
	};

	/*
	Information about this saver
	*/
	VscodeSaver.prototype.info = {
		name: "vscode",
		priority: 4000,
		capabilities: ["save", "autosave"]
	};

	/*
	Static method that returns true if this saver is capable of working
	*/
	exports.canSave = function (wiki) {
		if (typeof acquireVsCodeApi !== "undefined") return true;
		return false;
	};

	/*
	Create an instance of this saver
	*/
	exports.create = function (wiki) {
		return new VscodeSaver(wiki);
	};
})();

In your code you forgot to rename the prototype functions to VscodeSaver so the internal functions are all missing.

The TW core uses export.canSave() to check if a saver is worth to be initialized. If this function returns false absolutely nothing of the code is executed at all.

The TW core uses the export.create() function to instantiate the saver with VscodeSaver(wiki); … When the new is executed it needs to initiate the acquireVsCodeApi() functioin. The API instance need to be saved to a “private” variable available with this … as used in the .save() function.

I think my code could work, if acquireVsCodeApi is globally available in the VSCode web-view. I’ll have to check the docs.

Can you provide some links to the VSCode development docs you are using, to get me started?

Just to be sure. I’m still interested to have TW as a VSCode panel.

But

I did read a bit about the WebView API and found something interesting. It seems WebViews are considered a “heavy” workload in VSCode. From a programmers point of view, I do understand the following info as a plea: “Only use it as a last resort”. … Which makes me think …

TiddlyWiki is a full-blown web-app, so we should expect some “blowbacks” on the way.

Should I use a webview?

Webviews are pretty amazing, but they should also be used sparingly and only when VS Code’s native API is inadequate. Webviews are resource heavy and run in a separate context from normal extensions. A poorly designed webview can also easily feel out of place within VS Code.

Before using a webview, please consider the following:

  • Does this functionality really need to live within VS Code? Would it be better as a separate application or website?

  • Is a webview the only way to implement your feature? Can you use the regular VS Code APIs instead?

  • Will your webview add enough user value to justify its high resource cost?

Remember: Just because you can do something with webviews, doesn’t mean you should. However, if you are confident that you need to use webviews, then this document is here to help. Let’s get started.

Thanks for all this feedback.

Just so we’re on the same page, I’ve read all these docs. I’ve also done this for a couple decades, so wrangling code and fixing whatever errors there certainly are isn’t the problem. I’ve got this, don’t worry, I just didn’t know how to import the JS or if there was some egregious thing I missed.

Now that I know how to import this correctly, I’ll take it from here. Also, I’m not worried about VS Code running TW being resource-heavy, and if it is for someone then this extension may just not be for them. Thus far it’s been perfectly fine to use so it’s probably NBD.

All righty. https://github.com/ndarilek/vscode-tiddlywiki-integration vsix build available in the release.

Right now you can open up a new project and press ctrl-alt-w to create an empty wiki at the configured path in the workspace, wiki.html by default. If wiki.html already exists, ctrl-alt-w opens a webview and focuses it.

If the extension creates the wiki for you then the saver is pre-installed. Otherwise you’ll need to import the tiddler linked in the README.

PRs with icons and other graphical assets welcome. Once I’m fairly confident it works, I’ll publish it to the marketplaces, update the first post in this thread, etc. I just don’t have the wherewithal to deal with Microsoft/Azure crap ATM.

Suggestions welcome. Essentially, I’ve been wanting to use TiddlyWiki as a sort of design document/issue tracker hybrid for game development work, but I didn’t really like any of the separate apps nor did I want something running in the browser that wouldn’t let me keep my documents in git. I want to see if I’m more likely to create and maintain my docs if adding issues/designs is as simple as ctrl-alt-w, work with wiki, ctrl-alt-e, edit code, repeat. I’m happy to add other functionality but I don’t want to stray too far from that initial design goal. Ideally this just lets TW do what it does best, and provides minimally-invasive interventions where helpful.

2 Likes

Which OS do you use?
I’ll post my issues at GitHub, where they can be closed when they have been resolved.