From bc61f7eebf9cf810d9b226c65a7f49744bd0a803 Mon Sep 17 00:00:00 2001 From: Jermolene Date: Sat, 4 Feb 2017 17:37:31 +0000 Subject: [PATCH] Introduce savetrail plugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See the readme: “This plugin causes TiddlyWiki to continuously save the contents of each tiddler that is changed as a JSON file. Configured correctly, the browser will download the files silently in the background, and they can be used as a backup in case of accidental data loss.” Inspired by @telmiger’s comment (3) here: https://github.com/Jermolene/TiddlyWiki5/issues/2741#issuecomment-276128 871 --- .../tiddlers/SaveTrailPlugin-enable.tid | 2 + editions/prerelease/tiddlywiki.info | 3 +- .../savetrail/config/enable-drafts.tid | 3 + .../tiddlywiki/savetrail/config/enable.tid | 3 + .../savetrail/config/save-filter.tid | 3 + plugins/tiddlywiki/savetrail/plugin.info | 7 ++ plugins/tiddlywiki/savetrail/readme.tid | 15 +++ plugins/tiddlywiki/savetrail/savetrail.js | 106 ++++++++++++++++++ plugins/tiddlywiki/savetrail/settings.tid | 11 ++ 9 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 editions/prerelease/tiddlers/SaveTrailPlugin-enable.tid create mode 100644 plugins/tiddlywiki/savetrail/config/enable-drafts.tid create mode 100644 plugins/tiddlywiki/savetrail/config/enable.tid create mode 100644 plugins/tiddlywiki/savetrail/config/save-filter.tid create mode 100644 plugins/tiddlywiki/savetrail/plugin.info create mode 100644 plugins/tiddlywiki/savetrail/readme.tid create mode 100644 plugins/tiddlywiki/savetrail/savetrail.js create mode 100644 plugins/tiddlywiki/savetrail/settings.tid diff --git a/editions/prerelease/tiddlers/SaveTrailPlugin-enable.tid b/editions/prerelease/tiddlers/SaveTrailPlugin-enable.tid new file mode 100644 index 000000000..bc5556415 --- /dev/null +++ b/editions/prerelease/tiddlers/SaveTrailPlugin-enable.tid @@ -0,0 +1,2 @@ +title: $:/config/SaveTrailPlugin/enable +text: no diff --git a/editions/prerelease/tiddlywiki.info b/editions/prerelease/tiddlywiki.info index 040ca13c0..638431943 100644 --- a/editions/prerelease/tiddlywiki.info +++ b/editions/prerelease/tiddlywiki.info @@ -12,7 +12,8 @@ "tiddlywiki/highlight", "tiddlywiki/markdown", "tiddlywiki/qrcode", - "tiddlywiki/bibtex" + "tiddlywiki/bibtex", + "tiddlywiki/savetrail" ], "themes": [ "tiddlywiki/vanilla", diff --git a/plugins/tiddlywiki/savetrail/config/enable-drafts.tid b/plugins/tiddlywiki/savetrail/config/enable-drafts.tid new file mode 100644 index 000000000..5b8e9ed06 --- /dev/null +++ b/plugins/tiddlywiki/savetrail/config/enable-drafts.tid @@ -0,0 +1,3 @@ +title: $:/config/SaveTrailPlugin/enable-drafts + +no \ No newline at end of file diff --git a/plugins/tiddlywiki/savetrail/config/enable.tid b/plugins/tiddlywiki/savetrail/config/enable.tid new file mode 100644 index 000000000..f9231b9ec --- /dev/null +++ b/plugins/tiddlywiki/savetrail/config/enable.tid @@ -0,0 +1,3 @@ +title: $:/config/SaveTrailPlugin/enable + +yes \ No newline at end of file diff --git a/plugins/tiddlywiki/savetrail/config/save-filter.tid b/plugins/tiddlywiki/savetrail/config/save-filter.tid new file mode 100644 index 000000000..796c847de --- /dev/null +++ b/plugins/tiddlywiki/savetrail/config/save-filter.tid @@ -0,0 +1,3 @@ +title: $:/config/SaveTrailPlugin/save-filter + +[is[tiddler]] -[[$:/HistoryList]] -[[$:/StoryList]] -[prefix[$:/config/]] -[prefix[$:/temp/]] -[prefix[$:/state/]] -[prefix[$:/status/]] \ No newline at end of file diff --git a/plugins/tiddlywiki/savetrail/plugin.info b/plugins/tiddlywiki/savetrail/plugin.info new file mode 100644 index 000000000..6e7206434 --- /dev/null +++ b/plugins/tiddlywiki/savetrail/plugin.info @@ -0,0 +1,7 @@ +{ + "title": "$:/plugins/tiddlywiki/savetrail", + "description": "Auto-download modified tiddlers", + "author": "JeremyRuston", + "core-version": ">=5.0.0", + "list": "readme settings" +} diff --git a/plugins/tiddlywiki/savetrail/readme.tid b/plugins/tiddlywiki/savetrail/readme.tid new file mode 100644 index 000000000..eb096e989 --- /dev/null +++ b/plugins/tiddlywiki/savetrail/readme.tid @@ -0,0 +1,15 @@ +title: $:/plugins/tiddlywiki/savetrail/readme + +This plugin causes TiddlyWiki to continuously save the contents of each tiddler that is changed as a JSON file. Configured correctly, the browser will download the files silently in the background, and they can be used as a backup in case of accidental data loss. + +''CAUTION'': Using this plugin will generate a //lot// of files in your downloads folder! Some points to watch: + +* This plugin is pretty much unusable unless your browser is set up to download files automatically, without prompting for the location +* Automatic file downloading doesn't work in all browsers - in particular, Safari and Internet Explorer do not currently support the [[necessary HTML5 feature|http://caniuse.com/download]] +* Be aware of the privacy implications of leaving a plaintext trail of all of your edits. You should only enable this plugin on computers that your trust and with content that is not sensitive +* The plugin uses the tiddler title plus a timestamp to generate a filename for the downloaded file, but some browsers don't respect + +Other points to note: + +* By default, after a tiddler has been modified the plugin waits until at least one second has elapsed since the last modification before it attempts to save the tiddler. This reduces the number of times that rapidly changing tiddlers are saved +* This plugin can be used with both the single file HTML configuration and under Node.js because it is independent of the usual saving and syncing processes diff --git a/plugins/tiddlywiki/savetrail/savetrail.js b/plugins/tiddlywiki/savetrail/savetrail.js new file mode 100644 index 000000000..421321b3a --- /dev/null +++ b/plugins/tiddlywiki/savetrail/savetrail.js @@ -0,0 +1,106 @@ +/*\ +title: $:/plugins/tiddlywiki/savetrail/savetrail.js +type: application/javascript +module-type: startup + +A startup module to download every changed tiddler as a JSON file + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +// Export name and synchronous status +exports.name = "savetrail"; +exports.platforms = ["browser"]; +exports.after = ["startup"]; +exports.synchronous = true; + +// Favicon tiddler +var SAVE_FILTER_TIDDLER_TITLE = "$:/config/SaveTrailPlugin/save-filter", + ENABLE_TIDDLER_TITLE = "$:/config/SaveTrailPlugin/enable", + ENABLE_DRAFTS_TIDDLER_TITLE = "$:/config/SaveTrailPlugin/enable-drafts"; + +exports.startup = function() { + $tw.savetrail = $tw.savetrail || {}; + $tw.savetrail.syncadaptor = new SaveTrailSyncAdaptor(); + $tw.savetrail.syncer = new $tw.Syncer({ + wiki: $tw.wiki, + syncadaptor: $tw.savetrail.syncadaptor, + titleSyncFilter: SAVE_FILTER_TIDDLER_TITLE, + logging: false + }); +}; + +function SaveTrailSyncAdaptor(options) { + this.logger = new $tw.utils.Logger("SaveTrail"); +} + +SaveTrailSyncAdaptor.prototype.name = "savetrail"; + +SaveTrailSyncAdaptor.prototype.isReady = function() { + // The savetrail adaptor is always ready + return true; +}; + +SaveTrailSyncAdaptor.prototype.getTiddlerInfo = function(tiddler) { + return {}; +}; + +/* +Save a tiddler and invoke the callback with (err,adaptorInfo,revision) +*/ +SaveTrailSyncAdaptor.prototype.saveTiddler = function(tiddler,callback) { + if($tw.wiki.getTiddlerText(ENABLE_TIDDLER_TITLE).toLowerCase() === "yes") { + var isDraft = $tw.utils.hop(tiddler.fields,"draft.of"); + if(!isDraft || $tw.wiki.getTiddlerText(ENABLE_DRAFTS_TIDDLER_TITLE).toLowerCase() === "yes") { + saveTiddlerFile(tiddler); + } + } + callback(null); +}; + +/* +Load a tiddler and invoke the callback with (err,tiddlerFields) + +We don't need to implement loading for the file system adaptor, because all the tiddler files will have been loaded during the boot process. +*/ +SaveTrailSyncAdaptor.prototype.loadTiddler = function(title,callback) { + callback(null,null); +}; + +/* +Delete a tiddler and invoke the callback with (err) +*/ +SaveTrailSyncAdaptor.prototype.deleteTiddler = function(title,callback,options) { + callback(null); +}; + +function saveTiddlerFile(tiddler) { + var illegalFilenameCharacters = /<|>|\:|\"|\/|\\|\||\?|\*|\^|\s/g, + fixedTitle = tiddler.fields.title.replace(illegalFilenameCharacters,"_"), + formattedDate = $tw.utils.stringifyDate(new Date()), + filename = fixedTitle + "." + formattedDate + ".json", + fields = new Object(); + for(var field in tiddler.fields) { + fields[field] = tiddler.getFieldString(field); + } + var text = JSON.stringify(fields,null,$tw.config.preferences.jsonSpaces), + link = document.createElement("a"); + link.setAttribute("target","_blank"); + link.setAttribute("rel","noopener noreferrer"); + if(Blob !== undefined) { + var blob = new Blob([text], {type: "text/plain"}); + link.setAttribute("href", URL.createObjectURL(blob)); + } else { + link.setAttribute("href","data:text/plain," + encodeURIComponent(text)); + } + link.setAttribute("download",filename); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); +} + +})(); diff --git a/plugins/tiddlywiki/savetrail/settings.tid b/plugins/tiddlywiki/savetrail/settings.tid new file mode 100644 index 000000000..370799d4c --- /dev/null +++ b/plugins/tiddlywiki/savetrail/settings.tid @@ -0,0 +1,11 @@ +title: $:/plugins/tiddlywiki/savetrail/settings + + +<$checkbox tiddler="$:/config/SaveTrailPlugin/enable" field="text" checked="yes" unchecked="no"> Enable automatic saving of modified tiddlers + +<$checkbox tiddler="$:/config/SaveTrailPlugin/enable-drafts" field="text" checked="yes" unchecked="no"> Include automatic saving of draft tiddlers (warning: generates a lot of download files) + +[[Filter|$:/config/SaveTrailPlugin/save-filter]] used to determine tiddlers that should be autosaved: + +<$edit-text tiddler="$:/config/SaveTrailPlugin/save-filter" tag="textarea" class="tc-edit-texteditor"/> +