Skip to content

Instantly share code, notes, and snippets.

@danielo515
Last active August 29, 2015 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielo515/44c9e12c76b4ef83dd09 to your computer and use it in GitHub Desktop.
Save danielo515/44c9e12c76b4ef83dd09 to your computer and use it in GitHub Desktop.
A sync module to allow tiddlywiki use tasker as backend storage.
/*\
title: $:/plugins/danielo515/TaskerSyncer/filesystemadaptor.js
type: application/javascript
module-type: syncadaptor
A sync adaptor module for synchronising with the local filesystem via Tasker APIs
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
function FileSystemAdaptor(options) {
var self = this;
this.wiki = options.wiki;
this.logger = new $tw.utils.Logger("TaskerAdaptor");
// Create the <wiki>/tiddlers folder if it doesn't exist
$tw.boot.wikiTiddlersPath = "/sdcard/TiddlyTasker/tiddlers";
createDir($tw.boot.wikiTiddlersPath,true);
}
FileSystemAdaptor.prototype.getTiddlerInfo = function(tiddler) {
return {};
};
$tw.config.typeInfo = {
"text/vnd.tiddlywiki": {
fileType: "application/x-tiddler",
extension: ".tid"
},
"image/jpeg" : {
hasMetaFile: true
}
};
$tw.config.typeTemplates = {
"application/x-tiddler": "$:/core/templates/tid-tiddler"
};
var path = {sep:"/"};
FileSystemAdaptor.prototype.getTiddlerFileInfo = function(tiddler,callback) {
// See if we've already got information about this file
$tw.boot.files = $tw.boot.files || {};
var self = this,
title = tiddler.fields.title,
fileInfo = $tw.boot.files[title];
// Get information about how to save tiddlers of this type
var type = tiddler.fields.type || "text/vnd.tiddlywiki",
typeInfo = $tw.config.typeInfo[type];
if(!typeInfo) {
typeInfo = $tw.config.typeInfo["text/vnd.tiddlywiki"];
}
var extension = typeInfo.extension || "";
if(!fileInfo) {
// If not, we'll need to generate it
// Start by getting a list of the existing files in the directory
var files = listFiles($tw.boot.wikiTiddlersPath);
files = files || [];
// Assemble the new fileInfo
fileInfo = {};
fileInfo.filepath = $tw.boot.wikiTiddlersPath + path.sep + self.generateTiddlerFilename(title,extension,files);
fileInfo.type = typeInfo.fileType || tiddler.fields.type;
fileInfo.hasMetaFile = typeInfo.hasMetaFile;
// Save the newly created fileInfo
$tw.boot.files[title] = fileInfo;
// Pass it to the callback
callback(null,fileInfo);
} else {
// Otherwise just invoke the callback
callback(null,fileInfo);
}
};
/*
Transliterate string from cyrillic russian to latin
*/
var transliterate = function(cyrillyc) {
var a = {"Ё":"YO","Й":"I","Ц":"TS","У":"U","К":"K","Е":"E","Н":"N","Г":"G","Ш":"SH","Щ":"SCH","З":"Z","Х":"H","Ъ":"'","ё":"yo","й":"i","ц":"ts","у":"u","к":"k","е":"e","н":"n","г":"g","ш":"sh","щ":"sch","з":"z","х":"h","ъ":"'","Ф":"F","Ы":"I","В":"V","А":"a","П":"P","Р":"R","О":"O","Л":"L","Д":"D","Ж":"ZH","Э":"E","ф":"f","ы":"i","в":"v","а":"a","п":"p","р":"r","о":"o","л":"l","д":"d","ж":"zh","э":"e","Я":"Ya","Ч":"CH","С":"S","М":"M","И":"I","Т":"T","Ь":"'","Б":"B","Ю":"YU","я":"ya","ч":"ch","с":"s","м":"m","и":"i","т":"t","ь":"'","б":"b","ю":"yu"};
return cyrillyc.split("").map(function (char) {
return a[char] || char;
}).join("");
};
/*
Given a tiddler title and an array of existing filenames, generate a new legal filename for the title, case insensitively avoiding the array of existing filenames
*/
FileSystemAdaptor.prototype.generateTiddlerFilename = function(title,extension,existingFilenames) {
// First remove any of the characters that are illegal in Windows filenames
var baseFilename = transliterate(title.replace(/<|>|\:|\"|\/|\\|\||\?|\*|\^|\s/g,"_"));
// Truncate the filename if it is too long
if(baseFilename.length > 200) {
baseFilename = baseFilename.substr(0,200);
}
// Start with the base filename plus the extension
var filename = baseFilename + extension,
count = 1;
// Add a discriminator if we're clashing with an existing filename while
// handling case-insensitive filesystems (NTFS, FAT/FAT32, etc.)
while(existingFilenames.indexOf(filename) !== -1) {
filename = baseFilename + " " + (count++) + extension;
}
return filename;
};
/*
Save a tiddler and invoke the callback with (err,adaptorInfo,revision)
*/
FileSystemAdaptor.prototype.saveTiddler = function(tiddler,callback) {
var self = this;
this.getTiddlerFileInfo(tiddler,function(err,fileInfo) {
var template, content, encoding,
_finish = function() {
callback(null, {}, 0);
};
if(err) {
return callback(err);
}
// Save the tiddler as a self contained templated file
template = $tw.config.typeTemplates[fileInfo.type];
content = self.wiki.renderTiddler("text/plain",template,{variables: {currentTiddler: tiddler.fields.title}});
var ok = writeFile(fileInfo.filepath,content);
if(!ok) {
return callback("Something went wrong while writting");
}
self.logger.log("Saved file",fileInfo.filepath);
_finish();
});
};
/*
Load a tiddler and invoke the callback with (err,tiddlerFields)
*/
FileSystemAdaptor.prototype.loadTiddler = function(title,callback) {
var self = this, tiddler = {"fields":{"title":title}};
this.getTiddlerFileInfo(tiddler,function(err,fileInfo) {
var data = readFile(fileInfo.filepath);
if(!data) {
return callback("The tiddler was not found");
}
var tiddler=$tw.wiki.deserializeTiddlers(fileInfo.type,data);
callback(null,tiddler);
});
};
FileSystemAdaptor.prototype.getSkinnyTiddlers = function (callback){
};
/*
Delete a tiddler and invoke the callback with (err)
*/
FileSystemAdaptor.prototype.deleteTiddler = function(title,callback,options) {
var self = this,
fileInfo = $tw.boot.files[title];
// Only delete the tiddler if we have writable information for the file
if(fileInfo) {
// Delete the file
var deleted = deleteFile(fileInfo.filepath);
if(!deleted) {
return callback("Not able to delete " + fileInfo.filepath);
}
self.logger.log("Deleted file "+fileInfo.filepath);
// Delete the metafile if present
if(fileInfo.hasMetaFile) {
var deleted=deleteFile(fileInfo.filepath + ".meta")
if(!deleted) {
return callback("Not able to delete "+ fileInfo.filepath + ".meta");
}
callback(null);
} else {
callback(null);
}
}else {
callback(null);
}
};
if($tw.browser) {
exports.adaptorClass = FileSystemAdaptor;
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment