Code Monkey home page Code Monkey logo

tw5-bob's Introduction

TW5-Bob

BIG DISCLAMER OF DOOM - Back up your data. Do it. This has been tested but there may be bugs that I don't know about. Also see notes below.

What does it do?

  • Multi-User support for using/editing the same wiki(s) simultaneously
  • Multi-Wiki support - run it once and serve multiple wikis
  • Create and configure new wikis from inside the root wiki
  • Export single file wikis in a variety of ways
  • Two-way real-time syncing between the browser and file system
  • All configuration can be done from inside the wiki
  • Serve external files (like images) so you can include them in your wikis
  • Allows you to run shell scripts and commands from inside the wiki
  • Can be used as a plugin library to make plugins available to other wikis (requires the TWederBob plugin on the other wikis to connect)
  • Inter-server federation. Different Bob servers can communicate to share tiddlers and as chat servers/relays
  • HTTP API for interacting with the server

A lot of the documentation is in the tiddler files in the Documentation folder of the plugin, or in the wiki in the plugin information on the control panel.

How do I set it up?

Easiest Version (Bundled Application)

To make this more accessible to people I made it so you can download a single file and then run it and everything should work. When you run it it should even open the wiki in your default browser.

To do use this go here (https://github.com/OokTech/TW5-BobEXE) and download the file for your system (BobLinux for linux, BobWin.exe for windows and BobOSX for mac). Then run the file.

  • On windows it may ask if you want to allow node through your firewall. Say yes. If you have anti-virus software it will probably say that it is from an untrusted developer and suggest that you don't use it.

It will create an index wiki in the same folder where you run the file, so if you want you can copy the file somewhere else. If you want to move it after you have run it the first time just be sure to copy the IndexWiki folder to the same location or it will create a new one without any changes you have made.

Manual Version

If you are familiar with using tiddlywiki on node than you just need to put the plugin into your plugins folder and include it in your tiddlywiki.info file. For the moment this plugin must be located in the OokTech/Bob subfolder of your plugins folder and listed as OokTech/Bob in the tiddlywiki.info file. You start the server using the wsserver command instead of the server command.

Also see Configuration.md.

Step by step instructions (using Node)

If you want to use a fresh local install of tiddlywiki here are command line instructions:

Clone the tiddlywiki repo and get the plugin (Only do this the first time to install everything):

git clone --depth=1 --branch v5.1.22 https://github.com/Jermolene/TiddlyWiki5.git
git clone --depth=1 https://github.com/OokTech/TW5-Bob.git TiddlyWiki5/plugins/OokTech/Bob
mkdir TiddlyWiki5/Wikis
cp -r TiddlyWiki5/plugins/OokTech/Bob/MultiUserWiki TiddlyWiki5/Wikis/BobWiki/

After that is finished, and to start up tiddlywiki later type:

cd TiddlyWiki5
node ./tiddlywiki.js Wikis/BobWiki  --wsserver

In a browser go to 127.0.0.1:8080 and the wiki should load. From here any tiddlers you create should have .tid files created in the Wikis/BobWiki/tiddlers folder, any edits you do to those files should be immediately reflected in the browser. Open the tiddler called $:/ServerIP, if you go to the ip address listed there on port 8080 (on mine right now the tiddler says 192.168.0.15, so I put 192.168.0.15:8080 in the browser of another computer on the same network to access the wiki). Now any changes you make to tiddlers on one computer will be reflected almost immediately on the other, and any changes you make to tiddlers or the file system will be almost immediately reflected in all connected wikis.

If you want to use the global tiddlywiki install you have to set the environment variable TIDDLYWIKI_PLUGIN_PATH and TIDDLYWIKI_EDITION_PATH to the folder where you have your plugins. On OSX or Linux you open a terminal and type these commands:

export TIDDLYWIKI_PLUGIN_PATH="/path/to/your/plugins"
export TIDDLYWIKI_EDITION_PATH="/path/to/your/editions"
tiddlywiki editions/BobWiki  --wsserver

If you want to change settings see Configuration.md for information.

Updating Bob on a manual install

When a new version of Bob is released you can update your plugin like this. If you followed the instructions above exactly than you use this. If you cloned the repo elsewhere than you need to cd into the folder where you cloned the plugin.

You can do this to make sure you have the most recent version, running this command when you already have the newest version does nothing and won't break anything so you can try it if you are not sure without worrying.

In a terminal type these commands:

cd TiddlyWiki5
cd plugins/OokTech/Bob
git pull

Updating TiddlyWiki on a manual install

This is to update your version of tiddlywiki, not Bob.

When TiddlyWiki release a new version you need to update your TiddlyWiki version also. This assumes that you followed the above instructions exactly. If you cloned the TiddlyWiki repo somewhere else than you have to cd into that folder instead.

In a terminal type these commands:

cd TiddlyWiki5
git fetch --all --tags --prune
git checkout tags/v5.1.22

To use future or previous versions you would change the 5.1.22 in the last command to match the version number you want to use.

Notes

NOTE 1 - .meta files: there isn't full support for .meta files. The only currently known limitation is that when you rename either the .meta file or the file it describes the changes aren't correctly reflected in the browsers. Renaming in the browser works as expected. Also empty .tid files are created for any tiddler with a _canonical_uri field in addition to the .meta file. This has no effect on the wiki.

NOTE 2 - command line arguments and configuration: I am terrible with command line arguments. To prevent the need to have 10 or 15 command line arguments in order to fully configure a wiki I instead added a settings folder in the same folder that holds the tiddlers folder and the tiddlywiki.info file. Inside this folder there is a settings.json file that you can use the configure the wiki. This also lets you change the wiki's settings from within the wiki. Most of the settings wouldn't take effect until the wiki server is reset, so I made a way to reset the wiki server from inside the wiki. You can also shutdown the wiki server from inside the wiki.


More Details

Here is a more detailed list of things added or changed by this plugin

  • Create new wikis from an interface inside the wiki
    • Create wikis using editions
    • Create wikis from existing single html file wikis
    • Create wikis using tiddlers drawn from other existing wikis
    • Add existing node wikis so that they are served by Bob
  • Serve normal node wikis with all the features of Bob
  • Two-way real-time syncing between the browser and file system
    • Updates the wiki in the browser immediately when any changes are made to the file system
    • Immediately save changes to tiddlers made in the browser to the file system
    • Syncing can ignore tiddlers based on an editable exclude filter
    • If the browser is disconnected from the server it can reconnect when the server is accessible again and sync the changes that happened. The syncing is two-way so the browser gets any changes from the server and the server gets changes from the browser.
      • Conflicts are displayed for you to handle.
  • Multi-User support
    • Allows any number of people/computers/browser tabs to connect to the wiki server and use or edit the same wiki(s) simultaneously.
    • Prevents multiple people from editing the same tiddler at the same time by disabling the edit button for tiddlers currently being edited
  • Multi-Wiki support, the plugin can serve multiple wikis at once, each served wiki has all the features listed here.
  • Websockets!! (used on the back-end, can be used by other plugins in the future)
    • Adds a websocket interface to tiddlywiki (currently only used by this plugin, a git plugin is currently being developed)
    • Adds an action widget that allows you to send arbitrary websocket messages to the server. This can be used to do things like trigger shell scripts from inside the wiki.
  • Adds a new command wsserver that starts up a minimal http and websocket server used for the real-time communication between the browser and server.
  • Adds a new command externalserver which starts up the wiki without a server so that you can use an external server, like an expressjs server.
  • Allows you to shutdown the tiddlywiki server from the browser using a websocket message.
  • Lets you run shell scripts from inside the wiki
  • Everything is configurable from inside the wiki
  • Your connection to the server is monitored and you are warned if there is a problem
    • If the browser disconnects from the server you can reconnect.
    • If the server was shutdown/restarted than you need to reload the page to reconnect.
  • Serve files from the local file system (like images) so that they can be used in the wiki.
  • Build a single file version of any served wikis from within the wiki.
  • Share tiddlers between the wikis using the internalFetch mechanism
  • Build single file wikis that take tiddlers from different wikis
  • Inter-server federation
    • Chat (see below)
    • Wiki syncing
      • optionally using a filter to limit which tiddlers are synced
    • fetch/push tiddlers from/to other servers
  • Chat
    • Local chat works between different wikis/connections to the same Bob server
    • Federated chat works between different Bob servers.
  • Plugin library
    • The server can act as a plugin library for other wikis
    • The library can be updated by plugin authors without having to have access to the server
    • The library can be updated directly from github/gitlab/other git server
  • coming soon Exclude lists on a per-wiki and per-user basis
  • under consideration Security and authentication to limit access and editing

tw5-bob's People

Contributors

ibnishak avatar inmysocks avatar joshuafontany avatar linonetwo avatar markusq avatar mklauber avatar paulreiber avatar tejasvi avatar zimiarh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tw5-bob's Issues

README.md need update.

This line in README.md needs to be corrected.
cp -r TiddlyWiki5/plugins/OokTech/Bob/BobWiki TiddlyWiki5/Wikis/BobWiki/

The directory TiddlyWiki5/Wikis/BobWiki not exist. Seems replaced by TiddlyWiki5/Wikis/MultiUserWiki

Correct way to update without wipping out all my sub-wikis

When I perform: git pull origin master in the MultiUser folder, then copy to "TiddlyWiki5/editions" it erases all wikis located in the Node JSON settings. Suggestions for how to properly update MultiUser without erasing all my wiki JSON references?

When renaming a tiddler on the file system the old version is sometimes left in the browser

Make sure you read contributing.md and check the correct boxes below and then
add your issue text here.
If you don't than the issue will be tagged as spam and closed or deleted.


I am running (check any that apply, put an x inside the [ ] to check a box, like this: [x]):

  • Windows
  • OSX
  • Linux
  • Other

and using

  • The nodejs version
  • The single file executable

Before posting I read issue guidelines and:

  • I am using the newest version
  • The answer to my question isn't listed in the documentation or this isn't
    a question
  • This is not a duplicate issue
  • I have not done anything that required me to set acceptance to
    I Will Not Get Tech Support For This

Switching themes doesn't always work

I think it is something to do with how the changes are propagated to different wikis, but when you change the theme it often reverts back to the default theme as though there hasn't been a theme picked.
This is sometimes fixed by reloading but not always.

Newly created folders in the tiddlers folder aren't watched while the server is running

If you create a folder in the tiddlers folder and create a .tid file inside that folder it won't appear in the wiki until after the server is restarted.


I am running (check any that apply, put an x inside the [ ] to check a box, like this: [x]):

  • Windows
  • OSX
  • Linux
  • Other

and using

  • The nodejs version
  • The single file executable

Before posting I read issue guidelines and:

  • I am using the newest version
  • The answer to my question isn't listed in the documentation or this isn't
    a question
  • This is not a duplicate issue
  • I have not done anything that required me to set acceptance to
    I Will Not Get Tech Support For This

Few bugs

Been testing your work for a few days now. Very useful. I hope you continue its development. Here are a few bugs I encountered.

  • Changes made in file-system lost after refresh. Changes persist in the file, but in browser, they are not shown.
  • Title changes are not transmitted from the file-system.
  • Dirty indicator stays on, despite the fact that almost always changes are transmitted

These are the one's I hope you will be able to solve in time for your release candidate. Also a minor inconvenience, rather than a bug, is the fact that if we change the location of a tiddler to a subfolder while keeping the server on, the tiddler is shown as missing. Nothing huge.

Make New Wiki Button from within TW5 fails

This is great Jedediah! Very cool stuff. This makes me increasingly more optimistic about using TW5 with my team. Thank you very much for the very clear and helpful response.

I have a follow-up question regarding my e-mail to you earlier. As I began playing with the "starting other wiki" tid. I tried to test making a "make new wiki button" and even though there is a:

"scripts": {
    "NewWiki":  "tiddlywiki #wikiName --init #editionName" 
}

script already in my Node Settings, it's seems to crash when I click it.

I observed your note:

Note: This does not create the wiki. If the wiki doesn't exist this won't do anything. To create a new wiki from within the wiki see the example for the runScript message.

when I attempt the runScript example:

<$button>
  Make Wiki!
  <$action-websocketmessage $type='runScript' name='NewWiki' #wikiName='Wikis/SomeName' #editionName='MultiUser'/>
</$button>

it fails with the following error:

For Test Make Wiki Button, type is application/x-tiddler hasMetaFile is false filepath is /home/sean/TiddlyWiki5/editions/MultiUserWiki/tiddlers/Test Make Wiki Button.tid
saved file /home/sean/TiddlyWiki5/editions/MultiUserWiki/tiddlers/Test Make Wiki Button.tid
events.js:112
      throw er; // Unhandled 'error' event
      ^

Error: spawn tiddlywiki ENOENT
    at Process.ChildProcess._handle.onexit (internal/child_process.js:201:19)
    at onErrorNT (internal/child_process.js:379:16)
    at process._tickCallback (internal/process/next_tick.js:114:19)

The last character of some inputs is lost

If you type in a field that will cause a saveTiddler message with each key stroke than often the last keystroke isn't saved. There are probably multiple ways to fix this.


I am running (check any that apply, put an x inside the [ ] to check a box, like this: [x]):

  • Windows
  • OSX
  • Linux
  • Other

and using

  • The nodejs version
  • The single file executable

Before posting I read issue guidelines and:

  • I am using the newest version
  • The answer to my question isn't listed in the documentation or this isn't
    a question
  • This is not a duplicate issue
  • I have not done anything that required me to set acceptance to
    I Will Not Get Tech Support For This

Request: Successful internalFetch are appended to a "Fetched List"?

When an internal fetch (an overwrite with the imported) succeeds could the Tiddler address be appended to a perennial (plain text) "Fetched List" for that Wiki?

Why could this be useful?

-- To be able to see what you added, maybe some time ago.

-- In my specific use case it would also allow me to copy parts of the listing to PMarios Bundler that allows me to make sets of Jsonised Tiddlers that I want in sets for normal single-file wiki.

Its not super important. But could be a useful to aid management.


I am running (check any that apply, put an x inside the [ ] to check a box, like this: [x]):

  • Windows
  • OSX
  • Linux
  • Other

and using

  • The nodejs version
  • The single file executable

Before posting I read issue guidelines and:

  • I am using the newest version
  • The answer to my question isn't listed in the documentation or this isn't
    a question
  • This is not a duplicate issue
  • I have not done anything that required me to set acceptance to
    I Will Not Get Tech Support For This

HTTPS support

Does not work with https (behind haproxy with SSL termination in my case) because web socket URL is hardcoded (ws://).
Following patch should fix it:

--- a/WebSockets/BrowserWebSocketsSetup.js
+++ b/WebSockets/BrowserWebSocketsSetup.js
@@ -32,7 +37,8 @@ socket server, but it can be extended for use with other web socket servers.
       var IPTiddler = $tw.wiki.getTiddler("$:/ServerIP");
       var IPAddress = window.location.hostname;
       var WSSPort = IPTiddler.fields.wss_port;
-      $tw.socket = new WebSocket(`ws://${IPAddress}:${WSSPort}`);
+      var WSScheme = window.location.protocol=="https:"?"wss://":"ws://"
+      $tw.socket = new WebSocket(WSScheme + IPAddress +":" + WSSPort);
       $tw.socket.onopen = openSocket;
       $tw.socket.onmessage = parseMessage;
       $tw.socket.binaryType = "arraybuffer";

Possible fix for the .meta tiddler handling problem

I have been working on making external image to work in the last couple days. The problem I tried to solve is this: when saving and uploading changes of a tiddler that is recognized to have metadata, the content of the tiddler in the clients will not get updated properly. I am not sure if this is the problem mentioned in the note of the README.

After bumping my head against the wall for a few times, I finally found the cause and a workaround to it. The cause is something to do with how the tiddlers on client side got updated. When a tiddler got changed in a client, the change is submitted to the server and then broadcasted to all the clients. However, the tiddler got broadcasted is not the one submitted in the first place. When the server receives a tiddler from a client, it saves the tiddler to its filesystem. After that, a filesystem monitor got triggered and reads (supposedly) the latest version of the tiddler back into wiki and broadcasts this tiddler to all the clients.

When a tiddler submitted to the server does not have any metadata, this pipeline runs smoothly. However, if the tiddler has metadata, this pipeline does not work out as expected because its metadata are not read back into wiki correctly when the filesystem monitor tries to broadcast the changes of the tiddler.

Here is how the bug happens in detail. When a tiddler with metadata is submitted to the server, its main body (without metadata) got saved to filesystem first (before its metadata), and such an action triggers the filesystem monitor to broadcast the changes. So the filesystem monitor loads the tiddler from file, in addition with its metadata. However, at this point, the metadata of the tiddler is most likely not being saved to the filesystem yet, because the metadata are saved in the callback of the action of saving the tiddler. Thus, the tiddler loaded from the filesystem is actually outdated and so the one got broadcasted to and shown in the clients.

The proposed workaround is pretty simple: just reverse the order of saving the tiddler data. Saving metadata first then the tiddler itself seems to solve the problem. However, I am not quite sure if this is a proper and solid way to solve it as I am not familiar with node.js and asynchronous stuffs.

I do have a commit with this on my own fork, but I am afraid that it cannot get merged because my fork is way too different from the origin.

TL; DR

In the WebsocketAdaptor.saveTiddler, saving metadata first then the tiddler itself seems to solve the problem mentioned in the first note of the README

The tiddler editing list isn't sent out to new wikis as they are opened.

When you open or reload a wiki your browser doesn't get the list of tiddlers being edited, it only gets tiddlers that someone starts to edit after the wiki is loaded.


I am running:

  • Windows
  • OSX
  • Linux
  • Other

and using

  • The nodejs version
  • The single file executable

Before posting I read issue guidelines and:

  • I am using the newest version
  • The answer to my question isn't listed in the documentation or this isn't
    a question
  • This is not a duplicate issue
  • I have not done anything that required me to set acceptance to
    I Will Not Get Tech Support For This

Make an interface that exposes more settings

Things that need to be configurable:

  • - The url prefix used for serving files
  • - The allowed file mime types for served files
  • - The source of external editions that can be used for new wikis

Comment on here if there is anything I am forgetting.

READ ME BEFORE POSTING AN ISSUE

Hello! Thank you for thinking about posting an issue.

There are some guidelines to help create and support a functioning and respectful environment.

To help with tech support type issues here are a few things to check before you post an issue:

  • Are you using the newest version? If not update to the newest version and see if the issue persists. If not than don't worry about creating a new issue for a resolved problem.
  • Is your question already answered in the documentation? Check the readme, configuration documentation and general documentation
  • Are you asking a question that is already part of another issue? If so add to the conversation in that issue instead of creating a new one to make it easier for people in the future to see progress being made.
  • Is the question you are asking about this plugin or would it be better to ask it on the TiddyWiki issues board? This may not always be obvious so don't worry too much about this one, but take a moment to consider it before posting an issue.

Some other guidelines

  • Are you asking for free engineering work? The people who work on this project do so for their own reasons, please show them enough respect to not consider them your unpaid engineering department.
    • If you are part of a company with a team and are requesting some enterprise grade additions to help than we suggest you consider emailing [email protected] and request a quote if you want a custom implementation.
    • One possible exception to this is education. We have a soft spot for education and often help where we can.

fails on navigating to localhost:8080/otherwiki

Here is the error message:
$:/core/modules/commands/wsserver.js:592 $tw.loadPlugins(wikiInfo.plugins,$tw.config.pluginsPath,$tw.config.pluginsEnvVar); ^ TypeError: Cannot read property 'plugins' of null at Object.handler ($:/core/modules/commands/wsserver.js:592:42) at SimpleServer.requestHandler ($:/core/modules/commands/wsserver.js:321:15) at Server.emit (events.js:127:13) at parserOnIncoming (_http_server.js:642:12) at HTTPParser.parserOnHeadersComplete (_http_common.js:117:17)

Here are the Node Settings I am using:

{
"heartbeat": {
"interval": "1000"
} ,
"scripts": {
"NewWiki": "node ./tiddlywiki.js #wikiName --init #editionName"
} ,
"wikis": {
"otherwiki": "~/TiddlyWiki5/Wikis/SomeName"
} ,
"ws-server": {
"autoIncrementPort": "" ,
"host": "0.0.0.0" ,
"password": "" ,
"pathprefix": "" ,
"port": "8080" ,
"renderType": "text/plain" ,
"rootTiddler": "$:/core/save/all" ,
"serveType": "text/html" ,
"username": ""
}
}

My new MultiUserWiki folder location is ~/TiddlyWiki5/Wikis/SomeName

Why server pads tiddler text with the line feed character (\n) when saving them

First of all, thanks again for making this plugin. I have been using it in my own project for a while and it does satisfy my needs. However, some glitches still might happen occasionally and make me bumping my head to the wall several times.

One of the thing that bites my most frequently is that this plugin pads tiddler text with the line feed character and substantially making the tiddler text differs from what a user inputs. For most of the time, this behaviour harms no one as it only adds a newline to the tiddler. Not a big deal. However, sometimes we do not allow any single character of the tiddler text being changed. For example, some other plugins (and TiddlyWiki itself) saves configurations of their program in the text of config tiddlers. When a user (that is, me) changes the text of these tiddlers, the extra line feed character breaks things up unexpectedly.

Although I could have quietly changed such behaviour in my own codebase, I am curious about what is the reason to wrap the texts with line feed character. My guess is that *nix tools requires text files having a trailing line feed character to work properly. Is this the main reason? If so, will it be safe to stop padding line feed character as TiddlyWiki seems not depending on *nix tools.

By the way, currently this plugin adds a pair of endline character to the beginning and the end of the text whenever a tiddler is being saved. Which means that if I save a tiddler three times, there will be three line feeds added to the text.

IE support

The code does not work in Internet Explorer, because IE does not support template literals and String.prototype.startsWith.
Following patch fixes it:

diff --git a/FileSystemMonitor.js b/FileSystemMonitor.js
index 0be1ea3..ea8fc59 100644
--- a/FileSystemMonitor.js
+++ b/FileSystemMonitor.js
@@ -180,7 +180,7 @@ if (fs) {
                 // So internalTitle is the title used by everything in the $tw
                 // object.
                 // The normal title is tiddlerObject.tiddlers[0].title
-                var internalTitle = (prefix === '' && !tiddlerObject.tiddlers[0].title.startsWith(`{${prefix}}`))?tiddlerObject.tiddlers[0].title:`{${prefix}}${tiddlerObject.tiddlers[0].title}`;
+                var internalTitle = (prefix === '' && !tiddlerObject.tiddlers[0].title.startsWith("{" + prefix + "}"))?tiddlerObject.tiddlers[0].title:"{" + prefix + "}" + tiddlerObject.tiddlers[0].title;
 
                 var tiddler = $tw.wiki.getTiddler(internalTitle);
 
@@ -305,7 +305,7 @@ if (fs) {
       tempTidObject[field] = tiddlerObject.tiddlers[0][field];
     })
     // Everything here should use the internal title
-    tempTidObject.title = `{${prefix}}` === '{}'?title:`{${prefix}}${title}`;
+    tempTidObject.title = "{" + prefix + "}" === '{}'?title:"{" + prefix+ "}" + title ;
     var itemPath = path.join(folder, filename);
     // If the tiddler doesn't exits yet, create it.
     var tiddler = new $tw.Tiddler({fields:tempTidObject});
@@ -334,7 +334,7 @@ if (fs) {
     $tw.wiki.addTiddlers(tempTidObject);
     $tw.wiki.addTiddler(tempTidObject);
     if (prefix && prefix !== '') {
-      var tidTitle = title.startsWith(`{${prefix}}`)?title:`{${prefix}}${title}`;
+      var tidTitle = title.startsWith("{"+prefix+"}")?title:"{"+prefix+"}"+title;
       $tw.MultiUser.Wikis[prefix].tiddlers.push(tidTitle);
     } else {
       if (!title.startsWith('{')) {
@@ -348,7 +348,7 @@ if (fs) {
   }
 
   $tw.MultiUser.DeleteTiddler = function (folder, filename, prefix) {
-    console.log(`Deleted tiddler file ${filename}`)
+    console.log("Deleted tiddler file " + filename)
     var itemPath = path.join(folder, filename);
     // Get the file name because it isn't always the same as the tiddler
     // title.
@@ -362,12 +362,12 @@ if (fs) {
     Object.keys($tw.boot.files).forEach(function(tiddlerName) {
       if ($tw.boot.files[tiddlerName].filepath === itemPath) {
         // Remove the tiddler info from $tw.boot.files
-        console.log(`Deleting Tiddler "${tiddlerName}"`);
+        console.log("Deleting Tiddler "+ tiddlerName);
         delete $tw.boot.files[tiddlerName]
         $tw.wiki.deleteTiddler(tiddlerName);
         // Create a message saying to remove the tiddler
         // Remove the prefix from the tiddler
-        tiddlerName = tiddlerName.replace(new RegExp(`^\{${prefix}\}`),'');
+        tiddlerName = tiddlerName.replace(new RegExp("^\{"+prefix+"\}"),'');
         var message = JSON.stringify({type: 'removeTiddler', title: tiddlerName, wiki: prefix});
         // Send the message to each connected browser
         $tw.MultiUser.SendToBrowsers(message);
diff --git a/NodeSettings.js b/NodeSettings.js
index bb54d25..6e80cad 100644
--- a/NodeSettings.js
+++ b/NodeSettings.js
@@ -59,17 +59,17 @@ $tw.loadSettings = function(settings, newSettingsPath) {
 	try {
 		rawSettings = fs.readFileSync(newSettingsPath);
 	} catch (err) {
-		console.log(`NodeSettings - Failed to load settings file.`);
+		console.log("NodeSettings - Failed to load settings file.");
     rawSettings = '{}';
 	}
 
 	// Try to parse the JSON after loading the file.
 	try {
 		newSettings = JSON.parse(rawSettings);
-		console.log(`NodeSettings - Parsed raw settings.`);
+		console.log("NodeSettings - Parsed raw settings.");
 	} catch (err) {
-		console.log(`NodeSettings - Malformed settings. Using empty default.`);
-		console.log(`NodeSettings - Check settings. Maybe comma error?`);
+		console.log("NodeSettings - Malformed settings. Using empty default.");
+		console.log("NodeSettings - Check settings. Maybe comma error?");
 		// Create an empty default settings.
 		newSettings = {};
 	}
diff --git a/WebSockets/BrowserMessageHandlers.js b/WebSockets/BrowserMessageHandlers.js
index 5d86940..aaa62b4 100644
--- a/WebSockets/BrowserMessageHandlers.js
+++ b/WebSockets/BrowserMessageHandlers.js
@@ -58,7 +58,7 @@ it will overwrite this file.
     if (data.wiki === $tw.wikiName) {
       // The title must exist and must be a string, everything else is optional
       if (data.fields) {
-        if (typeof data.fields.title === 'string' && !data.fields.title.startsWith(`{${$tw.wikiName}}`)) {
+        if (typeof data.fields.title === 'string' && !data.fields.title.startsWith("{" + $tw.wikiName + "}")) {
           // if the tiddler exists already only update it if the update is
           // different than the existing one.
           var changed = TiddlerHasChanged(data, $tw.wiki.getTiddler(data.fields.title));
@@ -89,7 +89,7 @@ it will overwrite this file.
         // remove the prefix for the current wiki from anything listed with
         // that prefix.
         for (var i = 0; i < data.list.length; i++) {
-          data.list[i] = data.list[i].replace(new RegExp(`^\{${$tw.wikiName}\}`),'');
+          data.list[i] = data.list[i].replace(new RegExp("^\{"+$tw.wikiName+"\}"),'');
         }
         var listField = $tw.utils.stringifyList(data.list);
         // Make the tiddler fields
diff --git a/WebSockets/BrowserWebSocketsSetup.js b/WebSockets/BrowserWebSocketsSetup.js
index 73c5202..cdc4c7d 100644
--- a/WebSockets/BrowserWebSocketsSetup.js
+++ b/WebSockets/BrowserWebSocketsSetup.js
@@ -12,7 +12,12 @@ socket server, but it can be extended for use with other web socket servers.
   /*jslint node: true, browser: true */
   /*global $tw: false */
   "use strict";
-
+  if (!String.prototype.startsWith) {
+  String.prototype.startsWith = function(searchString, position) {
+    position = position || 0;
+    return this.indexOf(searchString, position) === position;
+  };
+  }
   // Export name and synchronous status
   exports.name = "web-sockets-setup";
   exports.platforms = ["browser"];
@@ -32,7 +37,7 @@ socket server, but it can be extended for use with other web socket servers.
       var IPTiddler = $tw.wiki.getTiddler("$:/ServerIP");
       var IPAddress = window.location.hostname;
       var WSSPort = IPTiddler.fields.wss_port;
-      $tw.socket = new WebSocket(`ws://${IPAddress}:${WSSPort}`);
+      $tw.socket = new WebSocket("ws://"+ IPAddress +":" + WSSPort);
       $tw.socket.onopen = openSocket;
       $tw.socket.onmessage = parseMessage;
       $tw.socket.binaryType = "arraybuffer";
diff --git a/WebSockets/NodeMessageHandlers.js b/WebSockets/NodeMessageHandlers.js
index a6013d8..d8fbc2f 100644
--- a/WebSockets/NodeMessageHandlers.js
+++ b/WebSockets/NodeMessageHandlers.js
@@ -74,7 +74,7 @@ $tw.nodeMessageHandlers.saveTiddler = function(data) {
       // Ignore draft tiddlers
       if (!data.tiddler.fields['draft.of']) {
         var prefix = data.wiki || '';
-        var internalTitle = prefix === ''?data.tiddler.fields.title:`{${prefix}}${data.tiddler.fields.title}`;
+        var internalTitle = prefix === ''?data.tiddler.fields.title:"{" + prefix +"}" + data.tiddler.fields.title;
         // Set the saved tiddler as no longer being edited. It isn't always
         // being edited but checking eacd time is more complex than just always
         // setting it this way and doesn't benifit us.
@@ -143,7 +143,7 @@ $tw.nodeMessageHandlers.deleteTiddler = function(data) {
   // Make the internal name
   data.wiki = data.wiki || '';
 
-  data.tiddler = data.wiki === ''?data.tiddler:`{${data.wiki}}${data.tiddler}`;
+  data.tiddler = data.wiki === ''?data.tiddler:"{"+data.wiki+"}"+data.tiddler;
   // Delete the tiddler file from the file system
   $tw.syncadaptor.deleteTiddler(data.tiddler);
   // Remove the tiddler from the list of tiddlers being edited.
@@ -158,7 +158,7 @@ $tw.nodeMessageHandlers.deleteTiddler = function(data) {
 */
 $tw.nodeMessageHandlers.editingTiddler = function(data) {
   data.wiki = data.wiki || '';
-  var internalName = data.wiki === ''?data.tiddler:`{${data.wiki}}${data.tiddler}`;
+  var internalName = data.wiki === ''?data.tiddler:"{"+data.wiki+"}"+data.tiddler;
   // Add the tiddler to the list of tiddlers being edited to prevent multiple
   // people from editing it at the same time.
   $tw.MultiUser.UpdateEditingTiddlers(internalName);
@@ -184,7 +184,7 @@ $tw.nodeMessageHandlers.cancelEditingTiddler = function(data) {
     }
   }
   data.wiki = data.wiki || '';
-  var internalName = data.wiki === ''?title:`{${data.wiki}}${title}`;
+  var internalName = data.wiki === ''?title:"{"+data.wiki+"}"+title;
   // Remove the current tiddler from the list of tiddlers being edited.
   if ($tw.MultiUser.EditingTiddlers[internalName]) {
     delete $tw.MultiUser.EditingTiddlers[internalName];
@@ -289,7 +289,7 @@ $tw.nodeMessageHandlers.startWiki = function(data) {
             $tw.MultiUser.WikiState[wikiName] = 'closed';
             var route = {
               method: "GET",
-              path: new RegExp(`^\/${wikiName}\/?$`),
+              path: new RegExp("^\/"+wikiName+"\/?$"),
               handler: function(request, response, state) {
                 // Make sure we aren't already trying to start a wiki before trying
                 // to restart it.
@@ -298,22 +298,22 @@ $tw.nodeMessageHandlers.startWiki = function(data) {
                 if ($tw.MultiUser.WikiState[wikiName] !== 'booting' && $tw.MultiUser.WikiState[wikiName] !== 'running') {
                   console.log('start ', wikiName);
                   $tw.MultiUser.WikiState[wikiName] = 'booting';
-                  $tw.nodeMessageHandlers.startWiki({wikiName: wikiName.split('/').join('##'), wikiPath: `${wikiName}`});
+                  $tw.nodeMessageHandlers.startWiki({wikiName: wikiName.split('/').join('##'), wikiPath: wikiName});
                 }
                 // While waiting for the wiki to boot send a page saying that the
                 // wiki is booting. The page automatically reloads after a few
                 // seconds. If the wiki has booted it loads the wiki if not it
                 // reloads the same page.
                 response.writeHead(200, {"Content-Type": state.server.get("serveType")});
-                var text = `<html><script>setTimeout(function(){location.reload();}, 5000);</script>Booting up the wiki. The page will reload in a few seconds.<br> Click <a href='./${wikiName}'>here</a> to try refreshing manually.</html>`;
+                var text = "<html><script>setTimeout(function(){location.reload();}, 5000);</script>Booting up the wiki. The page will reload in a few seconds.<br> Click <a href='./"+wikiName+"'>here</a> to try refreshing manually.</html>";
                 response.end(text,"utf8");
               }
             }
           } else {
-            console.log('Receive ', String(new RegExp(`^\/${data.wikiPath}\/?$`)), ' ', message.route.text.length);
+            console.log('Receive ', String(new RegExp("^\/"+data.wikiPath+"\/?$")), ' ', message.route.text.length);
             var route = {
           		method: "GET",
-              path: new RegExp(`^\/${data.wikiPath}\/?$`),
+              path: new RegExp("^\/"+data.wikiPath+"\/?$"),
           		handler: function(request,response,state) {
           			response.writeHead(200, {"Content-Type": state.server.get("serveType")});
           			var text = message.route.text;
diff --git a/WebSockets/WebsocketAdaptor.js b/WebSockets/WebsocketAdaptor.js
index 94ddddc..2edde3a 100644
--- a/WebSockets/WebsocketAdaptor.js
+++ b/WebSockets/WebsocketAdaptor.js
@@ -59,10 +59,10 @@ WebsocketAdaptor.prototype.getTiddlerFileInfo = function(tiddler, prefix, callba
   // See if we've already got information about this file
   var self = this,
     title = tiddler.fields.title;
-  if (title.startsWith(`{${prefix}}`)) {
-    title = title.replace(`{${prefix}}`, '');
+  if (title.startsWith("{"+prefix+"}")) {
+    title = title.replace("{"+prefix+"}", '');
   }
-  var internalTitle = `{${prefix}}` ==='{}'?title:`{${prefix}}${title}`;
+  var internalTitle = "{"+prefix+"}" ==='{}'?title:"{"+prefix+"}"+title;
   var fileInfo = $tw.boot.files[internalTitle];
   if(fileInfo) {
     // If so, just invoke the callback
@@ -179,7 +179,7 @@ WebsocketAdaptor.prototype.saveTiddler = function(tiddler, prefix, callback) {
     }
   }
   prefix = prefix || '';
-  var internalName = (prefix === '' || tiddler.fields.title.startsWith(`{${prefix}}`)) ? tiddler.fields.title:`{${prefix}}${tiddler.fields.title}`;
+  var internalName = (prefix === '' || tiddler.fields.title.startsWith("{"+prefix+"}")) ? tiddler.fields.title:"{"+prefix+"}"+tiddler.fields.title;
   if (tiddler && $tw.MultiUser.ExcludeList.indexOf(tiddler.fields.title) === -1 && !tiddler.fields.title.startsWith('$:/state/') && !tiddler.fields.title.startsWith('$:/temp/')) {
     var self = this;
     self.getTiddlerFileInfo(tiddler, prefix,
@@ -255,15 +255,15 @@ function makeTiddlerFile(tiddler) {
   var output = "";
   Object.keys(tiddler.fields).forEach(function(fieldName, index) {
     if (fieldName === 'created' || fieldName === 'modified') {
-      output += `${fieldName}: ${$tw.utils.stringifyDate(new Date(tiddler.fields[fieldName]))}\n`;
+      output += fieldName+": "+$tw.utils.stringifyDate(new Date(tiddler.fields[fieldName]))+"\n";
     } else if (fieldName === 'list' || fieldName === 'tags'){
-      output += `${fieldName}: ${$tw.utils.stringifyList(tiddler.fields[fieldName])}\n`;
+      output += fieldName+": "+$tw.utils.stringifyList(tiddler.fields[fieldName])+"\n";
     } else if (fieldName !== 'text') {
-      output += `${fieldName}: ${tiddler.fields[fieldName]}\n`;
+      output += fieldName+": "+tiddler.fields[fieldName]+"\n";
     }
   })
   if (tiddler.fields.text) {
-    output += `\n${tiddler.fields.text}\n`;
+    output += "\n"+tiddler.fields.text+"\n";
   }
   return output.trim();
 }
diff --git a/ws-server.js b/ws-server.js
index eb5c4a8..1642342 100644
--- a/ws-server.js
+++ b/ws-server.js
@@ -54,7 +54,7 @@ $tw.loadSettings = function(settings, newSettingsPath) {
   try {
     rawSettings = fs.readFileSync(newSettingsPath);
   } catch (err) {
-    console.log(`ws-server - Failed to load settings file.`);
+    console.log("ws-server - Failed to load settings file.");
     rawSettings = '{}';
   }
 
@@ -62,8 +62,8 @@ $tw.loadSettings = function(settings, newSettingsPath) {
   try {
     newSettings = JSON.parse(rawSettings);
   } catch (err) {
-    console.log(`ws-server - Malformed Settings. Using empty default.`);
-    console.log(`ws-server - Check Settings. Maybe comma error?`);
+    console.log("ws-server - Malformed Settings. Using empty default.");
+    console.log("ws-server - Check Settings. Maybe comma error?");
     // Create an empty default Settings.
     newSettings = {};
   }
@@ -122,7 +122,7 @@ if($tw.node) {
   	$tw.utils.each($tw.loadTiddlersFromPath(resolvedWikiPath), function(tiddlerFile) {
       if (!options.prefix || options.prefix !== '') {
         for (var i = 0; i < tiddlerFile.tiddlers.length; i++) {
-          tiddlerFile.tiddlers[i].title = `{${options.prefix}}` === '{}'?tiddlerFile.tiddlers[i].title:`{${options.prefix}}${tiddlerFile.tiddlers[i].title}`
+          tiddlerFile.tiddlers[i].title = "{" + options.prefix +"}" === '{}'?tiddlerFile.tiddlers[i].title:"{"+options.prefix+"}"+tiddlerFile.tiddlers[i].title
         }
       }
   		if(!options.readOnly && tiddlerFile.filepath) {
@@ -162,7 +162,7 @@ if($tw.node) {
   		for(var t=0; t<pluginFolders.length; t++) {
   			pluginFields = $tw.loadPluginFolder(path.resolve(wikiPluginsPath,"./" + pluginFolders[t]));
   			if(pluginFields) {
-          pluginFields.title = `{${options.prefix}}`!=='{}'? `{${options.prefix}}${pluginFields.title}`:pluginFields.title;
+          pluginFields.title = "{"+options.prefix+"}"!=='{}'? "{"+options.prefix+"}"+pluginFields.title:pluginFields.title;
   				$tw.wikis.addTiddler(pluginFields);
   			}
   		}
@@ -174,7 +174,7 @@ if($tw.node) {
   		for(var t=0; t<themeFolders.length; t++) {
   			pluginFields = $tw.loadPluginFolder(path.resolve(wikiThemesPath,"./" + themeFolders[t]));
   			if(pluginFields) {
-          pluginFields.title = `{${options.prefix}}`!=='{}'? `{${options.prefix}}${pluginFields.title}`:pluginFields.title;
+          pluginFields.title = "{"+options.prefix+"}"!=='{}'? "{"+options.prefix+"}"+pluginFields.title:pluginFields.title;
   				$tw.wikis.addTiddler(pluginFields);
   			}
   		}
@@ -186,7 +186,7 @@ if($tw.node) {
   		for(var t=0; t<languageFolders.length; t++) {
   			pluginFields = $tw.loadPluginFolder(path.resolve(wikiLanguagesPath,"./" + languageFolders[t]));
   			if(pluginFields) {
-          pluginFields.title = `{${options.prefix}}`!=='{}'? `{${options.prefix}}${pluginFields.title}`:pluginFields.title;
+          pluginFields.title = "{"+options.prefix+"}"!=='{}'? "{"+options.prefix+"}"+pluginFields.title:pluginFields.title;
   				$tw.wikis.addTiddler(pluginFields);
   			}
   		}
@@ -388,10 +388,10 @@ var Command = function(params,commander,callback) {
         // Add tiddlers to the node process
         var wikiInfo = $tw.MultiUser.loadWikiTiddlers($tw.boot.wikiPath);
         $tw.MultiUser.Wikis.RootWiki.plugins = wikiInfo.plugins.map(function(name) {
-          return `$:/plugins/${name}`;
+          return "$:/plugins/"+name;
         });
         $tw.MultiUser.Wikis.RootWiki.themes = wikiInfo.themes.map(function(name) {
-          return `$:/themes/${name}`;
+          return "$:/themes/"+name;
         });
       }
       // This makes the wikiTiddlers variable a filter that lists all the
@@ -400,7 +400,7 @@ var Command = function(params,commander,callback) {
         variables: {
           wikiTiddlers:
             $tw.MultiUser.Wikis.RootWiki.tiddlers.concat($tw.MultiUser.Wikis.RootWiki.plugins.concat($tw.MultiUser.Wikis.RootWiki.themes)).map(function(tidInfo) {
-              return `[[${tidInfo}]]`;
+              return "[["+tidInfo+"]]";
             }).join(' '),
           wikiName: ''
         }
@@ -534,7 +534,7 @@ function addRoutesThing(inputObject, prefix) {
         if (prefix === '') {
           var fullName = wikiName;
         } else {
-          fullName = `${prefix}/${wikiName}`;
+          fullName = prefix+"/"+wikiName;
         }
         $tw.MultiUser = $tw.MultiUser || {};
         $tw.MultiUser.Wikis = $tw.MultiUser.Wikis || {};
@@ -544,7 +544,7 @@ function addRoutesThing(inputObject, prefix) {
         // Make route handler
         $tw.httpServer.addRoute({
           method: "GET",
-          path: new RegExp(`^\/${fullName}\/?$`),
+          path: new RegExp("^\/"+fullName+"\/?$"),
           handler: function(request, response, state) {
             // Make sure we haven't already loaded the wiki.
 
@@ -558,10 +558,10 @@ function addRoutesThing(inputObject, prefix) {
               // Add tiddlers to the node process
               var wikiInfo = $tw.MultiUser.loadWikiTiddlers($tw.boot.wikiPath);
               $tw.MultiUser.Wikis.RootWiki.plugins = wikiInfo.plugins.map(function(name) {
-                return `$:/plugins/${name}`;
+                return "$:/plugins/"+name;
               });
               $tw.MultiUser.Wikis.RootWiki.themes = wikiInfo.themes.map(function(name) {
-                return `$:/themes/${name}`;
+                return "$:/themes/"+name;
               });
             }
             if ($tw.MultiUser.Wikis[fullName].State !== 'loaded') {
@@ -583,13 +583,13 @@ function addRoutesThing(inputObject, prefix) {
             	$tw.loadPlugins(wikiInfo.languages,$tw.config.languagesPath,$tw.config.languagesEnvVar);
               // Get the list of tiddlers for this wiki
               $tw.MultiUser.Wikis[fullName].tiddlers = $tw.wiki.allTitles().filter(function(title) {
-                return title.startsWith(`{${fullName}}`);
+                return title.startsWith("{"+fullName+"}");
               });
               $tw.MultiUser.Wikis[fullName].plugins = wikiInfo.plugins.map(function(name) {
-                return `$:/plugins/${name}`;
+                return "$:/plugins/"+name;
               });
               $tw.MultiUser.Wikis[fullName].themes = wikiInfo.themes.map(function(name) {
-                return `$:/themes/${name}`;
+                return "$:/themes/"+name;
               });
             }
             // By default the normal file system plugins removed and the
@@ -610,7 +610,7 @@ function addRoutesThing(inputObject, prefix) {
               variables: {
                 wikiTiddlers:
                   $tw.MultiUser.Wikis[fullName].tiddlers.concat($tw.MultiUser.Wikis[fullName].plugins.concat($tw.MultiUser.Wikis[fullName].themes)).map(function(tidInfo) {
-                    return `[[${tidInfo}]]`;
+                    return "[["+tidInfo+"]]";
                   }).join(' '),
                 wikiName: fullName
               }
@@ -620,7 +620,7 @@ function addRoutesThing(inputObject, prefix) {
             response.end(text,"utf8");
           }
         });
-        console.log(`Added route ${String(new RegExp(`^\/${fullName}\/?$`))}`)
+        console.log("Added route "+String(new RegExp("^\/"+fullName+"\/?$")));
       } else {
         // recurse!
         prefix = prefix===''?wikiName:prefix + '/' + wikiName;

Search all child wikis from root wiki

If I have root-wiki and subwiki1 and subwiki2, I can search only subwiki1 from subwiki1 and only subwiki2 from subwiki2.

I'd like to be able to search ALL subwikis from the root wiki. Or, as an alternative, give me a checkbox in $:/AdvancedSearch which allows me to specify search-all-wikis.

I believe you have the wrong copy for line 3 under new TW setup

cp -r TiddlyWiki5/plugins/OokTech/**TW5-**MultiUser/MultiUserWiki TiddlyWiki5/editions/

SHOULD BE:
cp -r TiddlyWiki5/plugins/OokTech/MultiUser/MultiUserWiki TiddlyWiki5/editions/

Am I wrong in this? If I copy and run the first two lines, I'm only left with "MultiUser" folder under OokTech.

Cannot launch TiddlyWiki with MultiUser plugin on Windows 10

Thanks a lot for keep updating this plugin. This plugin is really great and it is good to see that it gets new features frequently.

However, lately I found that I cannot launch TiddlyWiki with this plugin on Windows. To be more specifically, when I try to launch the latest version (b770c46) with command node.exe .\tiddlywiki.js .\path\to\wiki --wsserver, I get an message Error: Unknown command: wsserver. For your information, I was able to use it to launch the version with git commit 0e3c563.

Environment specs:

  • OS: Windows 10
  • Shell: PowerShell
  • TiddlyWiki: v5.1.16-prerelease
  • node: v8.9.3

TiddlyWiki 5.1.16 has a hook on server startup

I was looking through your code, and I noticed that you start a separate server for the websockets. A pull request was merged recently which adds a hook to the server command that passes both the SimpleServer instance and the Node HTTP server instance, allowing you to attach handlers to them without modifying core code. You just need to make sure you attach the hook before the startup task is called that starts the server command (I forget which one it is). You can use it to attach the websockets listener to the server. You can also use it to add route handlers to the SimpleServer instance so you can serve other requests for the data folder (uploads stored in the data folder, for example).

The pull request was merged in time for 5.1.16. Just thought you might like to know that as it seems it would be quite useful to you in several ways.

The PR is here: Jermolene/TiddlyWiki5#3024

Add an auto backup option

This may be better as a separate plugin.

The buildHTMLWiki message would make this relatively simple. I think that we could have it save a single file wiki version after some length of time as long as there are edits newer than the previous backup version.

Things to include:

  • Rolling backups, keep only the newest x versions
  • Configurable backup location(s) (all wikis in one place, each wikis gets its own folder, etc)

Alternately we could set it up so that it saves an archive of the tiddlers folder. That may introduce more external dependencies.

Add automatic pruning of disconnected wikis

See notes in #31 for more.

The general idea is use an LRU algorithm to automatically prune wikis loaded into memory. Have the number of wikis that can be held in memory be configurable and then remove the least recently used one once there are more unused wikis in memory than that.

Configure port number listened by the websocket in setting file

First of all, many thanks to you for developing this super awesome plug-in. I have been searching for how to co-work on TiddlyWiki for quite some time and this plug-in totally solves my problem. Not to mention that the auto-saving functionality comes with it is also very handy.
Now I am trying to host a TiddlyWiki server with this plug-in in a docker container. I have to determine which ports to expose from the container for the server to work correctly. However I find that although I can configure the serving port in the settings.json, but I cannot find a place to configure the listening port. Is it possible to configure it or currently is it safe to assume that it will always be the serving port + 1?

Wiki folder Lost to Bob

I am running (check any that apply, put an x inside the [ ] to check a box, like this: [x]):

  • Windows
  • OSX
  • Linux
  • Other

and using

  • The nodejs version
  • The single file executable

Before posting I read issue guidelines and:

  • I am using the newest version (I think so, not sure how to check)
  • The answer to my question isn't listed in the documentation or this isn't
    a question
  • This is not a duplicate issue
  • I have not done anything that required me to set acceptance to
    I Will Not Get Tech Support For This

Running the Single File Executable on Windows 10 has being working well. I recently installed the plugin for revisions http://j.d.revisions.tiddlyspot.com/ as discussed here but not tested https://groups.google.com/forum/?hl=en#!topic/tiddlywiki/EZhMkt0BDn0

Unfortunately the Wiki would not reload in Bob, I deleted the new plugin tiddler

I had backups and tried a few things. But can no longer get it to open in Bob, Although I have managed to load it via TiddlyServer/NodeJS

The Folder wiki no longer has the Bob Settings and the link from the wiki listing in bob remains.

Is it simply a matter of installing the bob plugin or something else to make the folder wiki accessible in Bob again, as it was originally made from Bob?

Or could/should I create a new wiki and import tiddlers from a single file backup version?

Thanks in Advance
Tony

Duplicating Tiddlers?

This plugin seems to duplicate all of my tiddlers on server restart. For example, if I create a tiddler called "Contents" and restart the node server, the wiki will now have another duplicate tiddler called "{}Contents" that I have to then manually delete. I tested this with a TW with dozens of tids and it duplicated all of them.

Add support for single-file wikis

The goal is to be able to list a single file wiki in the wikis list and it will be converted into a temporary node wiki which you can then edit the same as any other wiki and it will be exported as the single file wiki when you are done editing.

Add a flag to make scripts run in sequence

The example application is using text to speech synthesis for multiple tiddlers by sending the tiddler text to command-line tts software. The way it is you can't queue up multiple tiddlers.

Terminal commands that give non-0 return values crash the wiki instead of just outputting the error

When using the runScript message to run a terminal command the server crashes if the command returns an error. It should just output the error.

One question is if it should proceed to the next queued command if it is part of a queue or if it should clear the command queue it is part of.

For now I think clear the command queue.


I am running (check any that apply, put an x inside the [ ] to check a box, like this: [x]):

  • Windows
  • OSX
  • Linux
  • Other

and using

  • The nodejs version
  • The single file executable

Before posting I read issue guidelines and:

  • I am using the newest version
  • The answer to my question isn't listed in the documentation or this isn't
    a question
  • This is not a duplicate issue
  • I have not done anything that required me to set acceptance to
    I Will Not Get Tech Support For This

Add a way to unload a wiki from memory.

This could be important for long running servers with lots of child wikis. I think that either a button to explicitly unload the wiki on the root wiki or perhaps something that unloads it automatically after some amount of time with no connections to that wiki.

Image/File Management

I know this is not exactly an issue with MultiUser per se, but it's become evident that TiddlyWiki nodejs version is limited in file/image management. If I can't fix this problem with the use of the MultiUser edition of TW, then we will have to start looking for other Wiki platform options (and I'd much prefer to use TW, if possible)

My issue is we do not have the ability to load images or files more generally to the wiki. I have tried:

  1. dragging images into the wiki --> Did not upload to node server
  2. creating external links to network shared images using _canonical_uri --> does not load the image even when I add a browser plug-in to enable local-file links

Do you have any suggestions on how you manage files and images to Tiddlywiki be it directly loading them onto your server or using canonical links? I think you mentioned using TW MultiUser for your own teams. Do ya'll simply not use the wiki for files/images? Or, do you have a special process in place for uploading them?

Unclear reference to address on 'Hello!' tiddler

On the 'Hello!' tiddler, it says "After setting the host and restarting you can connect to this wiki from another computer on the same network by entering the above into the address bar of a browser." However, there the address is not "above". I assume it's referring to the ip address and port that is at the top of the 'Readme' tiddler. It's a little confusing for a new user. Thanks!


I am running (check any that apply, put an x inside the [ ] to check a box, like this: [x]):

  • Windows
  • OSX
  • Linux
  • Other

and using

  • The nodejs version
  • The single file executable

Before posting I read issue guidelines and:

  • I am using the newest version
  • The answer to my question isn't listed in the documentation or this isn't
    a question
  • This is not a duplicate issue
  • I have not done anything that required me to set acceptance to
    I Will Not Get Tech Support For This

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.