2011-12-13 12:30:09 +00:00
|
|
|
/*\
|
|
|
|
title: js/WikiStore.js
|
|
|
|
|
|
|
|
\*/
|
2011-12-12 10:52:04 +00:00
|
|
|
(function(){
|
|
|
|
|
2011-12-09 16:34:02 +00:00
|
|
|
/*jslint node: true */
|
2011-11-30 17:27:00 +00:00
|
|
|
"use strict";
|
|
|
|
|
2011-12-05 16:50:25 +00:00
|
|
|
var Tiddler = require("./Tiddler.js").Tiddler,
|
2012-01-06 17:53:37 +00:00
|
|
|
utils = require("./Utils.js");
|
2011-11-22 14:29:29 +00:00
|
|
|
|
2011-12-28 17:16:56 +00:00
|
|
|
/* Creates a new WikiStore object
|
|
|
|
|
|
|
|
Available options are:
|
|
|
|
shadowStore: An existing WikiStore to use for shadow tiddler storage. Pass null to prevent a default shadow store from being created
|
|
|
|
*/
|
2011-12-11 18:28:09 +00:00
|
|
|
var WikiStore = function WikiStore(options) {
|
2011-12-28 17:16:56 +00:00
|
|
|
options = options || {};
|
2011-11-22 14:29:29 +00:00
|
|
|
this.tiddlers = {};
|
2012-01-05 11:08:05 +00:00
|
|
|
this.parsers = {};
|
2012-01-07 17:33:42 +00:00
|
|
|
this.macros = {};
|
2011-12-28 17:16:56 +00:00
|
|
|
this.tiddlerSerializers = {};
|
|
|
|
this.tiddlerDeserializers = {};
|
2011-12-28 22:07:17 +00:00
|
|
|
this.sandbox = options.sandbox;
|
2011-12-11 18:28:09 +00:00
|
|
|
this.shadows = options.shadowStore !== undefined ? options.shadowStore : new WikiStore({
|
2011-12-28 17:16:56 +00:00
|
|
|
shadowStore: null
|
2011-12-11 18:28:09 +00:00
|
|
|
});
|
2011-11-22 14:29:29 +00:00
|
|
|
};
|
|
|
|
|
2012-01-05 11:08:05 +00:00
|
|
|
WikiStore.prototype.registerParser = function(type,parser) {
|
|
|
|
this.parsers[type] = parser;
|
2011-12-28 17:16:56 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
WikiStore.prototype.registerTiddlerSerializer = function(extension,mimeType,serializer) {
|
|
|
|
this.tiddlerSerializers[extension] = serializer;
|
|
|
|
this.tiddlerSerializers[mimeType] = serializer;
|
|
|
|
};
|
|
|
|
|
|
|
|
WikiStore.prototype.registerTiddlerDeserializer = function(extension,mimeType,deserializer) {
|
|
|
|
this.tiddlerDeserializers[extension] = deserializer;
|
|
|
|
this.tiddlerDeserializers[mimeType] = deserializer;
|
2011-12-01 10:19:21 +00:00
|
|
|
};
|
2011-11-22 14:29:29 +00:00
|
|
|
|
2011-12-06 18:29:53 +00:00
|
|
|
WikiStore.prototype.getTiddler = function(title) {
|
2011-11-22 14:29:29 +00:00
|
|
|
var t = this.tiddlers[title];
|
2011-12-03 17:02:34 +00:00
|
|
|
if(t instanceof Tiddler) {
|
|
|
|
return t;
|
|
|
|
} else if(this.shadows) {
|
|
|
|
return this.shadows.getTiddler(title);
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
2011-12-01 10:19:21 +00:00
|
|
|
};
|
2011-11-22 14:29:29 +00:00
|
|
|
|
2011-12-06 18:29:53 +00:00
|
|
|
WikiStore.prototype.getTiddlerText = function(title) {
|
2011-12-03 17:02:34 +00:00
|
|
|
var t = this.getTiddler(title);
|
2011-12-01 15:07:10 +00:00
|
|
|
return t instanceof Tiddler ? t.fields.text : null;
|
|
|
|
};
|
|
|
|
|
2011-12-06 18:29:53 +00:00
|
|
|
WikiStore.prototype.deleteTiddler = function(title) {
|
2011-11-22 14:29:29 +00:00
|
|
|
delete this.tiddlers[title];
|
2011-12-01 10:19:21 +00:00
|
|
|
};
|
2011-11-22 14:29:29 +00:00
|
|
|
|
2011-12-06 18:29:53 +00:00
|
|
|
WikiStore.prototype.tiddlerExists = function(title) {
|
2011-12-16 10:48:36 +00:00
|
|
|
var exists = this.tiddlers[title] instanceof Tiddler;
|
|
|
|
if(exists) {
|
|
|
|
return true;
|
|
|
|
} else if (this.shadows) {
|
|
|
|
return this.shadows.tiddlerExists(title);
|
|
|
|
}
|
|
|
|
return ;
|
2011-12-02 14:40:18 +00:00
|
|
|
};
|
2011-12-01 15:07:10 +00:00
|
|
|
|
2011-12-06 18:29:53 +00:00
|
|
|
WikiStore.prototype.addTiddler = function(tiddler) {
|
2011-12-01 15:07:10 +00:00
|
|
|
this.tiddlers[tiddler.fields.title] = tiddler;
|
2011-12-01 10:19:21 +00:00
|
|
|
};
|
2011-11-22 14:29:29 +00:00
|
|
|
|
2011-12-12 08:59:28 +00:00
|
|
|
WikiStore.prototype.forEachTiddler = function(/* [sortField,[excludeTag,]]callback */) {
|
|
|
|
var a = 0,
|
|
|
|
sortField = arguments.length > 1 ? arguments[a++] : null,
|
|
|
|
excludeTag = arguments.length > 2 ? arguments[a++] : null,
|
|
|
|
callback = arguments[a++],
|
2012-01-05 21:31:47 +00:00
|
|
|
t,
|
|
|
|
tiddlers = [],
|
|
|
|
tiddler;
|
2011-12-12 08:59:28 +00:00
|
|
|
if(sortField) {
|
|
|
|
for(t in this.tiddlers) {
|
|
|
|
tiddlers.push(this.tiddlers[t]);
|
|
|
|
}
|
|
|
|
tiddlers.sort(function (a,b) {
|
|
|
|
var aa = a.fields[sortField] || 0,
|
|
|
|
bb = b.fields[sortField] || 0;
|
|
|
|
if(aa < bb) {
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
if(aa > bb) {
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
for(t=0; t<tiddlers.length; t++) {
|
|
|
|
if(!tiddlers[t].hasTag(excludeTag)) {
|
|
|
|
callback.call(this,tiddlers[t].fields.title,tiddlers[t]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for(t in this.tiddlers) {
|
|
|
|
tiddler = this.tiddlers[t];
|
|
|
|
if(tiddler instanceof Tiddler && !tiddler.hasTag(excludeTag))
|
|
|
|
callback.call(this,t,tiddler);
|
|
|
|
}
|
2011-11-22 14:29:29 +00:00
|
|
|
}
|
2011-12-01 10:19:21 +00:00
|
|
|
};
|
2011-11-22 14:29:29 +00:00
|
|
|
|
2011-12-14 18:25:40 +00:00
|
|
|
WikiStore.prototype.getTitles = function(sortField,excludeTag) {
|
2011-12-28 16:10:30 +00:00
|
|
|
sortField = sortField || "title";
|
2011-12-14 18:25:40 +00:00
|
|
|
var tiddlers = [];
|
|
|
|
this.forEachTiddler(sortField,excludeTag,function(title,tiddler) {
|
|
|
|
tiddlers.push(title);
|
|
|
|
});
|
|
|
|
return tiddlers;
|
|
|
|
};
|
|
|
|
|
2011-12-28 16:10:30 +00:00
|
|
|
WikiStore.prototype.getMissingTitles = function() {
|
|
|
|
return [];
|
|
|
|
};
|
|
|
|
|
|
|
|
WikiStore.prototype.getOrphanTitles = function() {
|
|
|
|
return [];
|
|
|
|
};
|
|
|
|
|
|
|
|
WikiStore.prototype.getShadowTitles = function() {
|
|
|
|
return this.shadows ? this.shadows.getTitles() : [];
|
|
|
|
};
|
|
|
|
|
2011-12-28 17:16:56 +00:00
|
|
|
WikiStore.prototype.serializeTiddler = function(type,tiddler) {
|
|
|
|
var serializer = this.tiddlerSerializers[type];
|
|
|
|
if(serializer) {
|
|
|
|
return serializer(tiddler);
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
WikiStore.prototype.deserializeTiddlers = function(type,text,srcFields) {
|
|
|
|
var fields = {},
|
|
|
|
deserializer = this.tiddlerDeserializers[type],
|
|
|
|
t;
|
|
|
|
if(srcFields) {
|
|
|
|
for(t in srcFields) {
|
|
|
|
fields[t] = srcFields[t];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(deserializer) {
|
|
|
|
return deserializer(text,fields);
|
|
|
|
} else {
|
|
|
|
// Return a raw tiddler for unknown types
|
|
|
|
fields.text = text;
|
|
|
|
return [fields];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-01-03 11:09:59 +00:00
|
|
|
WikiStore.prototype.classesForLink = function(target) {
|
2012-01-05 20:10:25 +00:00
|
|
|
var className = "",
|
|
|
|
externalRegExp = /(?:file|http|https|mailto|ftp|irc|news|data):[^\s'"]+(?:\/|\b)/i;
|
2012-01-07 10:35:02 +00:00
|
|
|
if (this.tiddlerExists(target)) {
|
2012-01-05 20:10:25 +00:00
|
|
|
className = "linkInternalResolves";
|
2012-01-07 10:35:02 +00:00
|
|
|
} else if(externalRegExp.test(target)) {
|
|
|
|
className = "linkExternal";
|
2012-01-05 20:10:25 +00:00
|
|
|
} else {
|
|
|
|
className = "linkInternalMissing";
|
|
|
|
}
|
2012-01-05 21:31:47 +00:00
|
|
|
return className !== "" ? " class=\"" + className + "\"" : "";
|
2012-01-03 11:09:59 +00:00
|
|
|
};
|
|
|
|
|
2011-12-28 17:16:56 +00:00
|
|
|
WikiStore.prototype.parseText = function(type,text) {
|
2012-01-05 11:08:05 +00:00
|
|
|
var parser = this.parsers[type];
|
|
|
|
if(!parser) {
|
|
|
|
parser = this.parsers["text/x-tiddlywiki"];
|
2011-12-28 17:16:56 +00:00
|
|
|
}
|
2012-01-05 11:08:05 +00:00
|
|
|
if(parser) {
|
|
|
|
return parser.parse(text);
|
2011-12-28 17:16:56 +00:00
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-12-11 18:28:09 +00:00
|
|
|
WikiStore.prototype.parseTiddler = function(title) {
|
|
|
|
var tiddler = this.getTiddler(title);
|
|
|
|
if(tiddler) {
|
2012-01-06 17:40:22 +00:00
|
|
|
// Check the cache
|
|
|
|
if(!tiddler.parseTree) {
|
|
|
|
tiddler.parseTree = this.parseText(tiddler.fields.type,tiddler.fields.text);
|
|
|
|
}
|
|
|
|
return tiddler.parseTree;
|
2011-12-11 18:28:09 +00:00
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
2011-12-12 10:52:04 +00:00
|
|
|
};
|
2011-12-11 18:28:09 +00:00
|
|
|
|
2012-01-06 17:40:22 +00:00
|
|
|
/*
|
|
|
|
Compiles a JavaScript function that renders a tiddler in a particular MIME type
|
|
|
|
*/
|
|
|
|
WikiStore.prototype.compileTiddler = function(title,type) {
|
|
|
|
/*jslint evil: true */
|
|
|
|
var tiddler = this.getTiddler(title);
|
|
|
|
if(tiddler) {
|
|
|
|
if(!tiddler.renderers[type]) {
|
|
|
|
var tree = this.parseTiddler(title);
|
|
|
|
tiddler.renderers[type] = eval(tree.compile(type));
|
|
|
|
}
|
|
|
|
return tiddler.renderers[type];
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-12-14 14:11:11 +00:00
|
|
|
/*
|
2012-01-04 19:44:38 +00:00
|
|
|
Render a tiddler to a particular MIME type. Optionally render it with a different tiddler
|
2012-01-06 17:40:22 +00:00
|
|
|
as the context. This option is used to render a tiddler through a template eg
|
2012-01-04 19:44:38 +00:00
|
|
|
store.renderTiddler("text/html",templateTitle,tiddlerTitle)
|
2011-12-14 14:11:11 +00:00
|
|
|
*/
|
|
|
|
WikiStore.prototype.renderTiddler = function(type,title,asTitle) {
|
2012-01-06 17:40:22 +00:00
|
|
|
var tiddler = this.getTiddler(title),
|
|
|
|
fn = this.compileTiddler(title,type);
|
2012-01-06 18:43:36 +00:00
|
|
|
if(tiddler) {
|
|
|
|
if(asTitle) {
|
|
|
|
var asTiddler = this.getTiddler(asTitle);
|
|
|
|
return fn(asTiddler,this,utils);
|
|
|
|
} else {
|
|
|
|
if(!tiddler.renditions[type]) {
|
|
|
|
tiddler.renditions[type] = fn(tiddler,this,utils);
|
|
|
|
}
|
|
|
|
return tiddler.renditions[type];
|
2012-01-06 17:40:22 +00:00
|
|
|
}
|
2011-12-11 18:28:09 +00:00
|
|
|
}
|
2012-01-06 18:43:36 +00:00
|
|
|
return null;
|
2011-12-12 10:52:04 +00:00
|
|
|
};
|
2011-12-11 18:28:09 +00:00
|
|
|
|
2012-01-07 17:33:42 +00:00
|
|
|
WikiStore.prototype.installMacro = function(macro) {
|
|
|
|
this.macros[macro.name] = macro;
|
2012-01-03 11:09:59 +00:00
|
|
|
};
|
|
|
|
|
2011-12-06 18:29:53 +00:00
|
|
|
exports.WikiStore = WikiStore;
|
2011-12-12 10:52:04 +00:00
|
|
|
|
|
|
|
})();
|