2017-02-04 17:37:31 +00:00
|
|
|
/*\
|
|
|
|
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
|
2017-02-09 15:45:39 +00:00
|
|
|
var ENABLE_TIDDLER_TITLE = "$:/config/SaveTrailPlugin/enable",
|
|
|
|
ENABLE_DRAFTS_TIDDLER_TITLE = "$:/config/SaveTrailPlugin/enable-drafts",
|
|
|
|
SYNC_DRAFTS_FILTER_TIDDLER_TITLE = "$:/config/SaveTrailPlugin/sync-drafts-filter";
|
2017-02-04 17:37:31 +00:00
|
|
|
|
|
|
|
exports.startup = function() {
|
|
|
|
$tw.savetrail = $tw.savetrail || {};
|
2017-02-09 15:45:39 +00:00
|
|
|
// Create a syncer to handle autosaving
|
2017-02-04 17:37:31 +00:00
|
|
|
$tw.savetrail.syncadaptor = new SaveTrailSyncAdaptor();
|
|
|
|
$tw.savetrail.syncer = new $tw.Syncer({
|
|
|
|
wiki: $tw.wiki,
|
|
|
|
syncadaptor: $tw.savetrail.syncadaptor,
|
2017-02-09 15:45:39 +00:00
|
|
|
titleSyncFilter: SYNC_DRAFTS_FILTER_TIDDLER_TITLE,
|
2017-09-20 15:28:11 +00:00
|
|
|
logging: false,
|
|
|
|
disableUI: true
|
2017-02-04 17:37:31 +00:00
|
|
|
});
|
2017-02-09 15:45:39 +00:00
|
|
|
// Add hooks for trapping user actions
|
|
|
|
$tw.hooks.addHook("th-saving-tiddler",function(tiddler) {
|
2017-02-13 09:00:34 +00:00
|
|
|
if($tw.wiki.checkTiddlerText(ENABLE_TIDDLER_TITLE,"yes")) {
|
|
|
|
var oldTiddler = $tw.wiki.getTiddler(tiddler.fields.title);
|
|
|
|
if(oldTiddler) {
|
|
|
|
saveTiddlerFile(oldTiddler,{reason: "overwritten"});
|
|
|
|
}
|
|
|
|
saveTiddlerFile(tiddler,{reason: "saved"});
|
2017-02-09 15:45:39 +00:00
|
|
|
}
|
|
|
|
return tiddler;
|
|
|
|
});
|
|
|
|
$tw.hooks.addHook("th-renaming-tiddler",function(newTiddler,oldTiddler) {
|
2017-02-13 09:00:34 +00:00
|
|
|
if($tw.wiki.checkTiddlerText(ENABLE_TIDDLER_TITLE,"yes")) {
|
|
|
|
if(oldTiddler) {
|
|
|
|
saveTiddlerFile(oldTiddler,{reason: "deleted"});
|
|
|
|
}
|
|
|
|
saveTiddlerFile(newTiddler,{reason: "renamed"});
|
2017-02-09 15:45:39 +00:00
|
|
|
}
|
|
|
|
return newTiddler;
|
|
|
|
});
|
|
|
|
$tw.hooks.addHook("th-relinking-tiddler",function(newTiddler,oldTiddler) {
|
2017-02-13 09:00:34 +00:00
|
|
|
if($tw.wiki.checkTiddlerText(ENABLE_TIDDLER_TITLE,"yes")) {
|
|
|
|
if(oldTiddler) {
|
|
|
|
saveTiddlerFile(oldTiddler,{reason: "overwritten"});
|
|
|
|
}
|
|
|
|
saveTiddlerFile(newTiddler,{reason: "relinked"});
|
2017-02-09 15:45:39 +00:00
|
|
|
}
|
|
|
|
return newTiddler;
|
|
|
|
});
|
|
|
|
$tw.hooks.addHook("th-importing-tiddler",function(tiddler) {
|
2017-02-13 09:00:34 +00:00
|
|
|
if($tw.wiki.checkTiddlerText(ENABLE_TIDDLER_TITLE,"yes")) {
|
|
|
|
var oldTiddler = $tw.wiki.getTiddler(tiddler.fields.title);
|
|
|
|
if(oldTiddler) {
|
|
|
|
saveTiddlerFile(oldTiddler,{reason: "overwritten"});
|
|
|
|
}
|
|
|
|
saveTiddlerFile(tiddler,{reason: "imported"});
|
2017-02-09 15:45:39 +00:00
|
|
|
}
|
|
|
|
return tiddler;
|
|
|
|
});
|
|
|
|
$tw.hooks.addHook("th-deleting-tiddler",function(tiddler) {
|
2017-02-13 09:00:34 +00:00
|
|
|
if($tw.wiki.checkTiddlerText(ENABLE_TIDDLER_TITLE,"yes")) {
|
|
|
|
saveTiddlerFile(tiddler,{reason: "deleted"});
|
|
|
|
}
|
2017-02-09 15:45:39 +00:00
|
|
|
return tiddler;
|
|
|
|
});
|
2017-02-04 17:37:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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) {
|
2017-02-09 15:45:39 +00:00
|
|
|
if($tw.wiki.checkTiddlerText(ENABLE_TIDDLER_TITLE,"yes")) {
|
2017-02-04 17:37:31 +00:00
|
|
|
var isDraft = $tw.utils.hop(tiddler.fields,"draft.of");
|
2017-02-09 15:45:39 +00:00
|
|
|
if(!isDraft || $tw.wiki.checkTiddlerText(ENABLE_DRAFTS_TIDDLER_TITLE,"yes")) {
|
|
|
|
saveTiddlerFile(tiddler,{reason: "modified"});
|
2017-02-04 17:37:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
callback(null);
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
Load a tiddler and invoke the callback with (err,tiddlerFields)
|
|
|
|
*/
|
|
|
|
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);
|
|
|
|
};
|
|
|
|
|
2017-02-09 15:45:39 +00:00
|
|
|
function saveTiddlerFile(tiddler,options) {
|
|
|
|
options = options || {};
|
|
|
|
var reason = options.reason || "changed",
|
|
|
|
illegalFilenameCharacters = /<|>|\:|\"|\/|\\|\||\?|\*|\^|\s/g,
|
2017-09-20 15:28:11 +00:00
|
|
|
fixedTitle = $tw.utils.transliterate(tiddler.fields.title).replace(illegalFilenameCharacters,"_"),
|
2017-02-04 17:37:31 +00:00
|
|
|
formattedDate = $tw.utils.stringifyDate(new Date()),
|
2017-02-09 15:45:39 +00:00
|
|
|
filename = fixedTitle + "." + formattedDate + "." + reason + ".json",
|
2017-02-04 17:37:31 +00:00
|
|
|
fields = new Object();
|
|
|
|
for(var field in tiddler.fields) {
|
|
|
|
fields[field] = tiddler.getFieldString(field);
|
|
|
|
}
|
2017-02-04 18:08:43 +00:00
|
|
|
var text = JSON.stringify([fields],null,$tw.config.preferences.jsonSpaces),
|
2017-02-04 17:37:31 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
})();
|