2021-04-07 11:16:12 +00:00
|
|
|
/*\
|
|
|
|
title: $:/core/modules/sitemap.js
|
|
|
|
type: application/javascript
|
|
|
|
module-type: global
|
|
|
|
|
|
|
|
Sitemaps are used for static publishing and web serving
|
|
|
|
|
|
|
|
\*/
|
|
|
|
(function(){
|
|
|
|
|
|
|
|
/*jslint node: true, browser: true */
|
|
|
|
/*global $tw: false */
|
|
|
|
"use strict";
|
|
|
|
|
2021-04-10 16:42:35 +00:00
|
|
|
function Sitemap(sitemapTitle,options) {
|
2021-04-07 11:16:12 +00:00
|
|
|
options = options || {};
|
2021-04-10 16:42:35 +00:00
|
|
|
this.sitemapTitle = sitemapTitle;
|
2021-04-07 11:16:12 +00:00
|
|
|
this.wiki = options.wiki;
|
|
|
|
this.routes = [];
|
|
|
|
this.variables = $tw.utils.extend({},options.variables);
|
|
|
|
}
|
|
|
|
|
|
|
|
Sitemap.prototype.load = function(sitemapTitle) {
|
|
|
|
var self = this;
|
|
|
|
// Get the sitemap
|
2021-04-10 16:42:35 +00:00
|
|
|
var sitemapTiddler = this.wiki.getTiddler(this.sitemapTitle);
|
2021-04-07 11:16:12 +00:00
|
|
|
if(sitemapTiddler) {
|
|
|
|
// Collect each route
|
|
|
|
$tw.utils.each(sitemapTiddler.fields.list,function(routeTitle) {
|
|
|
|
var routeTiddler = self.wiki.getTiddler(routeTitle);
|
|
|
|
if(routeTiddler) {
|
|
|
|
// Convert the path into a regexp and an array of {field:,function:} for each capture group
|
|
|
|
var regexpurgatedParameterisedPath = self.regexpurgateParameterisedPath(routeTiddler.fields["route-path"]);
|
|
|
|
self.routes.push({
|
2021-04-10 16:42:35 +00:00
|
|
|
title: routeTitle,
|
2021-04-07 11:16:12 +00:00
|
|
|
params: routeTiddler.getFieldStrings({prefix: "route-"}),
|
2021-04-10 09:58:26 +00:00
|
|
|
variables: routeTiddler.getFieldStrings({prefix: "var-"}),
|
2021-04-07 11:16:12 +00:00
|
|
|
regexp: regexpurgatedParameterisedPath.regexp,
|
|
|
|
captureGroups: regexpurgatedParameterisedPath.captureGroups
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-04-10 09:58:26 +00:00
|
|
|
Sitemap.prototype.renderRoute = function(title,route) {
|
|
|
|
var tiddler = this.wiki.getTiddler(title);
|
|
|
|
switch(route.params.type) {
|
|
|
|
case "raw":
|
|
|
|
return {
|
|
|
|
path: this.resolveParameterisedPath(route.params.path,title),
|
|
|
|
text: tiddler.fields.text || "",
|
|
|
|
type: tiddler.fields.type || "",
|
|
|
|
isBase64: ($tw.config.contentTypeInfo[tiddler.fields.type] || {}).encoding === "base64"
|
|
|
|
};
|
|
|
|
break;
|
|
|
|
case "render":
|
2021-04-10 16:42:35 +00:00
|
|
|
var parser = {
|
|
|
|
tree: [
|
|
|
|
{
|
|
|
|
"type": "importvariables",
|
|
|
|
"attributes": {
|
|
|
|
"tiddler": {
|
|
|
|
"name": "tiddler",
|
|
|
|
"type": "string",
|
|
|
|
"value": this.sitemapTitle,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"tag": "$importvariables",
|
|
|
|
"isBlock": false,
|
|
|
|
"children": [
|
|
|
|
{
|
|
|
|
"type": "importvariables",
|
|
|
|
"attributes": {
|
|
|
|
"tiddler": {
|
|
|
|
"name": "tiddler",
|
|
|
|
"type": "string",
|
|
|
|
"value": route.title,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"tag": "$importvariables",
|
|
|
|
"isBlock": false,
|
|
|
|
"children": this.wiki.parseTiddler(route.params.template,{parseAsInline: true}).tree
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
widgetNode = this.wiki.makeWidget(parser,{
|
|
|
|
variables: $tw.utils.extend({},this.variables,{currentTiddler: title})
|
|
|
|
}),
|
|
|
|
container = $tw.fakeDocument.createElement("div");
|
|
|
|
widgetNode.render(container,null);
|
2021-04-10 09:58:26 +00:00
|
|
|
return {
|
|
|
|
path: this.resolveParameterisedPath(route.params.path,title),
|
2021-04-10 16:42:35 +00:00
|
|
|
text: container.textContent,
|
2021-04-10 09:58:26 +00:00
|
|
|
type: route.params["output-type"] || "text/html"
|
|
|
|
};
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-04-07 11:16:12 +00:00
|
|
|
/*
|
|
|
|
Returns an array of functions that return {path:,text:,type:,isBase64:} for each path
|
|
|
|
*/
|
|
|
|
Sitemap.prototype.getAllFileDetails = function(exportTiddlers) {
|
|
|
|
var self = this,
|
|
|
|
output = [];
|
|
|
|
$tw.utils.each(this.routes,function(route) {
|
|
|
|
var routeFilter = route.params["tiddler-filter"] || "DUMMY_RESULT", // If no filter is provided, use a dummy filter that returns a single result
|
|
|
|
routeTiddlers = self.wiki.filterTiddlers(routeFilter,null,self.wiki.makeTiddlerIterator(exportTiddlers));
|
2021-04-10 09:58:26 +00:00
|
|
|
$tw.utils.each(routeTiddlers,function(title) {
|
|
|
|
output.push(self.renderRoute.bind(self,title,route));
|
|
|
|
});
|
2021-04-07 11:16:12 +00:00
|
|
|
});
|
|
|
|
return output;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2021-04-10 12:51:07 +00:00
|
|
|
Returns an array of server routes {regexp:, handler:}
|
2021-04-07 11:16:12 +00:00
|
|
|
*/
|
|
|
|
Sitemap.prototype.getServerRoutes = function() {
|
|
|
|
var self = this,
|
|
|
|
output = [];
|
|
|
|
$tw.utils.each(this.routes,function(route) {
|
|
|
|
output.push({
|
2021-04-10 12:51:07 +00:00
|
|
|
regexp: route.regexp,
|
|
|
|
handler: function(params) {
|
2021-04-07 11:16:12 +00:00
|
|
|
// Locate the tiddler identified by the capture groups, if any
|
|
|
|
var title = null,
|
|
|
|
nextParam = 0;
|
|
|
|
$tw.utils.each(route.captureGroups,function(captureGroup) {
|
2021-04-10 12:51:07 +00:00
|
|
|
var param = params[nextParam++];
|
2021-04-07 11:16:12 +00:00
|
|
|
if(captureGroup.field === "title") {
|
|
|
|
switch(captureGroup.function) {
|
|
|
|
case "slugify":
|
|
|
|
var titles = self.wiki.unslugify(param);
|
|
|
|
if(titles && titles.length > 0) {
|
|
|
|
title = titles[0];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2021-04-10 16:42:35 +00:00
|
|
|
// Check that the tiddler passes the route filter
|
|
|
|
if(route.params["tiddler-filter"]) {
|
|
|
|
if(!title) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
var routeTiddlers = self.wiki.filterTiddlers(route.params["tiddler-filter"],null,self.wiki.makeTiddlerIterator([title]));
|
|
|
|
if(routeTiddlers.indexOf(title) === -1) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2021-04-07 11:16:12 +00:00
|
|
|
// Return the rendering or raw tiddler
|
2021-04-10 12:51:07 +00:00
|
|
|
return self.renderRoute(title,route);
|
2021-04-07 11:16:12 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
return output;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
Apply a tiddler to a parameterised path to create a usable path
|
|
|
|
*/
|
|
|
|
Sitemap.prototype.resolveParameterisedPath = function(parameterisedPath,title) {
|
|
|
|
var self = this;
|
|
|
|
// Split the path on $*_*$ markers
|
|
|
|
var tiddler = this.wiki.getTiddler(title),
|
|
|
|
output = [];
|
|
|
|
$tw.utils.each(parameterisedPath.split(/(\$[a-z_]+\$)/),function(part) {
|
|
|
|
var match = part.match(/\$([a-z]+)_([a-z]+)\$/);
|
|
|
|
if(match) {
|
|
|
|
var value;
|
|
|
|
// Get the base value
|
|
|
|
switch(match[1]) {
|
|
|
|
case "uri":
|
|
|
|
case "title":
|
|
|
|
value = title;
|
|
|
|
break;
|
|
|
|
case "type":
|
|
|
|
value = tiddler.fields.type || "text/vnd.tiddlywiki";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Apply the encoding function
|
|
|
|
switch(match[2]) {
|
|
|
|
case "encoded":
|
|
|
|
value = encodeURIComponent(value);
|
|
|
|
break;
|
|
|
|
case "doubleencoded":
|
|
|
|
value = encodeURIComponent(encodeURIComponent(value));
|
|
|
|
break;
|
|
|
|
case "slugify":
|
|
|
|
value = self.wiki.slugify(value);
|
|
|
|
break;
|
|
|
|
case "extension":
|
|
|
|
value = ($tw.config.contentTypeInfo[value] || {extension: "."}).extension.slice(1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
output.push(value);
|
|
|
|
} else {
|
|
|
|
output.push(part);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return output.join("");
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
// Convert the path into a regexp and an array of {field:,function:} for each capture group
|
|
|
|
*/
|
|
|
|
Sitemap.prototype.regexpurgateParameterisedPath = function(parameterisedPath) {
|
|
|
|
var regexpParts = ["\\/"],
|
|
|
|
captureGroups = [];
|
|
|
|
$tw.utils.each(parameterisedPath.split(/(\$[a-z_]+\$)/),function(part) {
|
|
|
|
var match = part.match(/\$([a-z]+)_([a-z]+)\$/);
|
|
|
|
if(match) {
|
|
|
|
regexpParts.push("(.+)");
|
|
|
|
captureGroups.push({
|
|
|
|
field: match[1],
|
|
|
|
function: match[2]
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
regexpParts.push($tw.utils.escapeRegExp(part));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return {
|
|
|
|
regexp: new RegExp("^" + regexpParts.join("") + "$"),
|
|
|
|
captureGroups: captureGroups
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.Sitemap = Sitemap;
|
|
|
|
|
|
|
|
})();
|
|
|
|
|