Implement APIs for client wikis to sync with the server
It is now possible to create and edit tiddlers, using the existing tiddlywebadaptor syncing mechanism. There are a lot of hacks and lumpiness to make things compatible, so I think I will end up with an independent implementation
This commit is contained in:
parent
299781bdba
commit
a980390870
|
@ -14,8 +14,7 @@
|
||||||
"tiddlywiki/dynannotate",
|
"tiddlywiki/dynannotate",
|
||||||
"tiddlywiki/codemirror",
|
"tiddlywiki/codemirror",
|
||||||
"tiddlywiki/menubar",
|
"tiddlywiki/menubar",
|
||||||
"tiddlywiki/jszip",
|
"tiddlywiki/jszip"
|
||||||
"tiddlywiki/multiwikiserver"
|
|
||||||
],
|
],
|
||||||
"themes": [
|
"themes": [
|
||||||
"tiddlywiki/vanilla",
|
"tiddlywiki/vanilla",
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
"tiddlywiki/evernote",
|
"tiddlywiki/evernote",
|
||||||
"tiddlywiki/internals",
|
"tiddlywiki/internals",
|
||||||
"tiddlywiki/menubar",
|
"tiddlywiki/menubar",
|
||||||
"tiddlywiki/qrcode"
|
"tiddlywiki/qrcode",
|
||||||
|
"tiddlywiki/tiddlyweb",
|
||||||
|
"tiddlywiki/filesystem",
|
||||||
|
"tiddlywiki/multiwikiserver"
|
||||||
],
|
],
|
||||||
"themes": [
|
"themes": [
|
||||||
"tiddlywiki/vanilla",
|
"tiddlywiki/vanilla",
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*\
|
||||||
|
title: $:/plugins/tiddlywiki/multiwikiserver/route-delete-tiddler.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: route
|
||||||
|
|
||||||
|
DELETE /wikis/:recipe_name/recipes/:bag_name/tiddler/:title
|
||||||
|
|
||||||
|
NOTE: Urls currently include the recipe name twice. This is temporary to minimise the changes to the TiddlyWeb plugin
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
exports.method = "DELETE";
|
||||||
|
|
||||||
|
exports.path = /^\/wiki\/([^\/]+)\/bags\/([^\/]+)\/tiddlers\/([^\/]+)$/;
|
||||||
|
|
||||||
|
exports.handler = function(request,response,state) {
|
||||||
|
// Get the parameters
|
||||||
|
var recipe_name = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||||
|
bag_name = $tw.utils.decodeURIComponentSafe(state.params[1]),
|
||||||
|
title = $tw.utils.decodeURIComponentSafe(state.params[2]);
|
||||||
|
var recipeBags = $tw.sqlTiddlerStore.getRecipeBags(recipe_name);
|
||||||
|
if(recipeBags.indexOf(bag_name) !== -1) {
|
||||||
|
$tw.sqlTiddlerStore.deleteTiddler(title,bag_name);
|
||||||
|
response.writeHead(204, "OK", {
|
||||||
|
"Content-Type": "text/plain"
|
||||||
|
});
|
||||||
|
response.end();
|
||||||
|
} else {
|
||||||
|
response.writeHead(404);
|
||||||
|
response.end();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}());
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*\
|
||||||
|
title: $:/plugins/tiddlywiki/multiwikiserver/route-get-status.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: route
|
||||||
|
|
||||||
|
GET /wikis/:recipe_name/status
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
exports.method = "GET";
|
||||||
|
|
||||||
|
exports.path = /^\/wiki\/([^\/]+)\/status$/;
|
||||||
|
|
||||||
|
exports.handler = function(request,response,state) {
|
||||||
|
// Get the recipe name from the parameters
|
||||||
|
var recipe_name = $tw.utils.decodeURIComponentSafe(state.params[0]);
|
||||||
|
// Compose the response
|
||||||
|
var text = JSON.stringify({
|
||||||
|
username: "Joe Bloggs",
|
||||||
|
anonymous: false,
|
||||||
|
read_only: false,
|
||||||
|
logout_is_available: false,
|
||||||
|
space: {
|
||||||
|
recipe: recipe_name
|
||||||
|
},
|
||||||
|
tiddlywiki_version: $tw.version
|
||||||
|
});
|
||||||
|
// Send response
|
||||||
|
if(text) {
|
||||||
|
state.sendResponse(200,{"Content-Type": "application/json"},text,"utf8");
|
||||||
|
} else {
|
||||||
|
response.writeHead(404);
|
||||||
|
response.end();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}());
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*\
|
||||||
|
title: $:/plugins/tiddlywiki/multiwikiserver/route-get-tiddler.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: route
|
||||||
|
|
||||||
|
GET /wikis/:recipe_name/recipes/:recipe_name/tiddler/:title
|
||||||
|
|
||||||
|
NOTE: Urls currently include the recipe name twice. This is temporary to minimise the changes to the TiddlyWeb plugin
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
exports.method = "GET";
|
||||||
|
|
||||||
|
exports.path = /^\/wiki\/([^\/]+)\/recipes\/([^\/]+)\/tiddlers\/([^\/]+)$/;
|
||||||
|
|
||||||
|
exports.handler = function(request,response,state) {
|
||||||
|
// Get the parameters
|
||||||
|
var recipe_name = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||||
|
recipe_name_2 = $tw.utils.decodeURIComponentSafe(state.params[1]),
|
||||||
|
title = $tw.utils.decodeURIComponentSafe(state.params[2]);
|
||||||
|
if(recipe_name === recipe_name_2) {
|
||||||
|
var tiddler = $tw.sqlTiddlerStore.getTiddler(title,recipe_name),
|
||||||
|
tiddlerFields = {},
|
||||||
|
knownFields = [
|
||||||
|
"bag", "created", "creator", "modified", "modifier", "permissions", "recipe", "revision", "tags", "text", "title", "type", "uri"
|
||||||
|
];
|
||||||
|
$tw.utils.each(tiddler,function(value,name) {
|
||||||
|
if(knownFields.indexOf(name) !== -1) {
|
||||||
|
tiddlerFields[name] = value;
|
||||||
|
} else {
|
||||||
|
tiddlerFields.fields = tiddlerFields.fields || {};
|
||||||
|
tiddlerFields.fields[name] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tiddlerFields.revision = "0";
|
||||||
|
tiddlerFields.bag = "bag-gamma";
|
||||||
|
tiddlerFields.type = tiddlerFields.type || "text/vnd.tiddlywiki";
|
||||||
|
state.sendResponse(200,{"Content-Type": "application/json"},JSON.stringify(tiddlerFields),"utf8");
|
||||||
|
} else {
|
||||||
|
response.writeHead(404);
|
||||||
|
response.end();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}());
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*\
|
||||||
|
title: $:/plugins/tiddlywiki/multiwikiserver/route-get-tiddlers-json.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: route
|
||||||
|
|
||||||
|
PUT /wikis/:recipe_name/recipes/:recipe_name/tiddlers.json?filter=:filter
|
||||||
|
|
||||||
|
NOTE: Urls currently include the recipe name twice. This is temporary to minimise the changes to the TiddlyWeb plugin
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
exports.method = "GET";
|
||||||
|
|
||||||
|
exports.path = /^\/wiki\/([^\/]+)\/recipes\/([^\/]+)\/tiddlers.json$/;
|
||||||
|
|
||||||
|
exports.handler = function(request,response,state) {
|
||||||
|
// Get the parameters
|
||||||
|
var recipe_name = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||||
|
recipe_name_2 = $tw.utils.decodeURIComponentSafe(state.params[1]);
|
||||||
|
if(recipe_name === recipe_name_2) {
|
||||||
|
// Get the tiddlers in the recipe
|
||||||
|
var titles = $tw.sqlTiddlerStore.getRecipeTiddlers(recipe_name);
|
||||||
|
// Get a skinny version of each tiddler
|
||||||
|
var tiddlers = [];
|
||||||
|
$tw.utils.each(titles,function(title) {
|
||||||
|
var tiddler = $tw.sqlTiddlerStore.getTiddler(title,recipe_name);
|
||||||
|
tiddlers.push(Object.assign({},tiddler,{text: undefined, revision: "0", bag: "bag-gamma"}));
|
||||||
|
});
|
||||||
|
var text = JSON.stringify(tiddlers);
|
||||||
|
state.sendResponse(200,{"Content-Type": "application/json"},text,"utf8");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Fail if something went wrong
|
||||||
|
response.writeHead(404);
|
||||||
|
response.end();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}());
|
|
@ -1,5 +1,5 @@
|
||||||
/*\
|
/*\
|
||||||
title: $:/plugins/tiddlywiki/multiwikiserver/route-wiki.js
|
title: $:/plugins/tiddlywiki/multiwikiserver/route-get-wiki.js
|
||||||
type: application/javascript
|
type: application/javascript
|
||||||
module-type: route
|
module-type: route
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ GET /wikis/:recipe_name
|
||||||
|
|
||||||
exports.method = "GET";
|
exports.method = "GET";
|
||||||
|
|
||||||
exports.path = /^\/wiki\/(.+)$/;
|
exports.path = /^\/wiki\/([^\/]+)$/;
|
||||||
|
|
||||||
exports.handler = function(request,response,state) {
|
exports.handler = function(request,response,state) {
|
||||||
// Get the recipe name from the parameters
|
// Get the recipe name from the parameters
|
||||||
|
@ -30,6 +30,7 @@ exports.handler = function(request,response,state) {
|
||||||
$:/boot/bootprefix.js
|
$:/boot/bootprefix.js
|
||||||
$:/core
|
$:/core
|
||||||
$:/library/sjcl.js
|
$:/library/sjcl.js
|
||||||
|
$:/plugins/tiddlywiki/tiddlyweb
|
||||||
$:/themes/tiddlywiki/snowwhite
|
$:/themes/tiddlywiki/snowwhite
|
||||||
$:/themes/tiddlywiki/vanilla
|
$:/themes/tiddlywiki/vanilla
|
||||||
`
|
`
|
||||||
|
@ -44,9 +45,12 @@ exports.handler = function(request,response,state) {
|
||||||
var htmlParts = [];
|
var htmlParts = [];
|
||||||
htmlParts.push(template.substring(0,markerPos + marker.length));
|
htmlParts.push(template.substring(0,markerPos + marker.length));
|
||||||
$tw.utils.each(titles,function(title) {
|
$tw.utils.each(titles,function(title) {
|
||||||
htmlParts.push(JSON.stringify($tw.sqlTiddlerStore.getTiddler(title,recipe_name)));
|
var tiddler = $tw.sqlTiddlerStore.getTiddler(title,recipe_name);
|
||||||
|
htmlParts.push(JSON.stringify(Object.assign({},tiddler,{revision: "0", bag: "bag-gamma"})));
|
||||||
htmlParts.push(",")
|
htmlParts.push(",")
|
||||||
});
|
});
|
||||||
|
htmlParts.push(JSON.stringify({title: "$:/config/tiddlyweb/host",text: "$protocol$//$host$$pathname$/"}));
|
||||||
|
htmlParts.push(",")
|
||||||
htmlParts.push(template.substring(markerPos + marker.length))
|
htmlParts.push(template.substring(markerPos + marker.length))
|
||||||
// Send response
|
// Send response
|
||||||
if(htmlParts) {
|
if(htmlParts) {
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*\
|
||||||
|
title: $:/plugins/tiddlywiki/multiwikiserver/route-put-tiddler.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: route
|
||||||
|
|
||||||
|
PUT /wikis/:recipe_name/recipes/:recipe_name/tiddlers/:title
|
||||||
|
|
||||||
|
NOTE: Urls currently include the recipe name twice. This is temporary to minimise the changes to the TiddlyWeb plugin
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
exports.method = "PUT";
|
||||||
|
|
||||||
|
exports.path = /^\/wiki\/([^\/]+)\/recipes\/([^\/]+)\/tiddlers\/([^\/]+)$/;
|
||||||
|
|
||||||
|
exports.handler = function(request,response,state) {
|
||||||
|
// Get the parameters
|
||||||
|
var recipe_name = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||||
|
recipe_name_2 = $tw.utils.decodeURIComponentSafe(state.params[1]),
|
||||||
|
title = $tw.utils.decodeURIComponentSafe(state.params[2]),
|
||||||
|
fields = $tw.utils.parseJSONSafe(state.data);
|
||||||
|
// Pull up any subfields in the `fields` object
|
||||||
|
if(typeof fields.fields === "object") {
|
||||||
|
$tw.utils.each(fields.fields,function(field,name) {
|
||||||
|
fields[name] = field;
|
||||||
|
});
|
||||||
|
delete fields.fields;
|
||||||
|
}
|
||||||
|
// Stringify any array fields
|
||||||
|
$tw.utils.each(fields,function(value,name) {
|
||||||
|
if($tw.utils.isArray(value)) {
|
||||||
|
fields[name] = $tw.utils.stringifyList(value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Require the recipe names to match
|
||||||
|
if(recipe_name === recipe_name_2) {
|
||||||
|
$tw.sqlTiddlerStore.saveRecipeTiddler(fields,recipe_name);
|
||||||
|
var recipe_bags = $tw.sqlTiddlerStore.getRecipeBags(recipe_name),
|
||||||
|
top_bag = recipe_bags[recipe_bags.length - 1];
|
||||||
|
response.writeHead(204, "OK",{
|
||||||
|
Etag: "\"" + top_bag + "/" + encodeURIComponent(title) + "/" + 2222 + ":\"",
|
||||||
|
"Content-Type": "text/plain"
|
||||||
|
});
|
||||||
|
response.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Fail if something went wrong
|
||||||
|
response.writeHead(404);
|
||||||
|
response.end();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}());
|
|
@ -63,8 +63,8 @@ SqlTiddlerStore.prototype.createTables = function() {
|
||||||
recipe_id INTEGER,
|
recipe_id INTEGER,
|
||||||
bag_id INTEGER,
|
bag_id INTEGER,
|
||||||
position INTEGER,
|
position INTEGER,
|
||||||
FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id),
|
FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
FOREIGN KEY (bag_id) REFERENCES bags(bag_id),
|
FOREIGN KEY (bag_id) REFERENCES bags(bag_id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
UNIQUE (recipe_id, bag_id)
|
UNIQUE (recipe_id, bag_id)
|
||||||
)
|
)
|
||||||
`,`
|
`,`
|
||||||
|
@ -73,7 +73,7 @@ SqlTiddlerStore.prototype.createTables = function() {
|
||||||
tiddler_id INTEGER PRIMARY KEY,
|
tiddler_id INTEGER PRIMARY KEY,
|
||||||
bag_id INTEGER,
|
bag_id INTEGER,
|
||||||
title TEXT,
|
title TEXT,
|
||||||
FOREIGN KEY (bag_id) REFERENCES bags(bag_id),
|
FOREIGN KEY (bag_id) REFERENCES bags(bag_id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
UNIQUE (bag_id, title)
|
UNIQUE (bag_id, title)
|
||||||
)
|
)
|
||||||
`,`
|
`,`
|
||||||
|
@ -82,7 +82,7 @@ SqlTiddlerStore.prototype.createTables = function() {
|
||||||
tiddler_id INTEGER,
|
tiddler_id INTEGER,
|
||||||
field_name TEXT,
|
field_name TEXT,
|
||||||
field_value TEXT,
|
field_value TEXT,
|
||||||
FOREIGN KEY (tiddler_id) REFERENCES tiddlers(tiddler_id),
|
FOREIGN KEY (tiddler_id) REFERENCES tiddlers(tiddler_id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
UNIQUE (tiddler_id, field_name)
|
UNIQUE (tiddler_id, field_name)
|
||||||
)
|
)
|
||||||
`]);
|
`]);
|
||||||
|
@ -138,7 +138,7 @@ SqlTiddlerStore.prototype.saveRecipe = function(recipename,bagnames) {
|
||||||
};
|
};
|
||||||
|
|
||||||
SqlTiddlerStore.prototype.saveTiddler = function(tiddlerFields,bagname) {
|
SqlTiddlerStore.prototype.saveTiddler = function(tiddlerFields,bagname) {
|
||||||
// Run the queries
|
// Update the tiddlers table
|
||||||
this.runStatement(`
|
this.runStatement(`
|
||||||
INSERT OR REPLACE INTO tiddlers (bag_id, title)
|
INSERT OR REPLACE INTO tiddlers (bag_id, title)
|
||||||
VALUES (
|
VALUES (
|
||||||
|
@ -149,6 +149,7 @@ SqlTiddlerStore.prototype.saveTiddler = function(tiddlerFields,bagname) {
|
||||||
title: tiddlerFields.title,
|
title: tiddlerFields.title,
|
||||||
bag_name: bagname
|
bag_name: bagname
|
||||||
});
|
});
|
||||||
|
// Update the fields table
|
||||||
this.runStatement(`
|
this.runStatement(`
|
||||||
INSERT OR REPLACE INTO fields (tiddler_id, field_name, field_value)
|
INSERT OR REPLACE INTO fields (tiddler_id, field_name, field_value)
|
||||||
SELECT
|
SELECT
|
||||||
|
@ -172,6 +173,30 @@ SqlTiddlerStore.prototype.saveTiddler = function(tiddlerFields,bagname) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SqlTiddlerStore.prototype.saveRecipeTiddler = function(tiddlerFields,recipename) {
|
||||||
|
// Find the topmost bag in the recipe
|
||||||
|
var row = this.runStatementGet(`
|
||||||
|
SELECT b.bag_name
|
||||||
|
FROM bags AS b
|
||||||
|
JOIN (
|
||||||
|
SELECT rb.bag_id
|
||||||
|
FROM recipe_bags AS rb
|
||||||
|
WHERE rb.recipe_id = (
|
||||||
|
SELECT recipe_id
|
||||||
|
FROM recipes
|
||||||
|
WHERE recipe_name = $recipe_name
|
||||||
|
)
|
||||||
|
ORDER BY rb.position DESC
|
||||||
|
LIMIT 1
|
||||||
|
) AS selected_bag
|
||||||
|
ON b.bag_id = selected_bag.bag_id
|
||||||
|
`,{
|
||||||
|
recipe_name: recipename
|
||||||
|
});
|
||||||
|
// Save the tiddler to the topmost bag
|
||||||
|
this.saveTiddler(tiddlerFields,row.bag_name);
|
||||||
|
};
|
||||||
|
|
||||||
SqlTiddlerStore.prototype.deleteTiddler = function(title,bagname) {
|
SqlTiddlerStore.prototype.deleteTiddler = function(title,bagname) {
|
||||||
// Run the queries
|
// Run the queries
|
||||||
this.runStatement(`
|
this.runStatement(`
|
||||||
|
@ -258,6 +283,26 @@ SqlTiddlerStore.prototype.getRecipeTiddlers = function(recipename) {
|
||||||
return rows.map(value => value.title);
|
return rows.map(value => value.title);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get the names of the bags in a recipe. Returns an empty array for recipes that do not exist
|
||||||
|
*/
|
||||||
|
SqlTiddlerStore.prototype.getRecipeBags = function(recipename) {
|
||||||
|
const rows = this.runStatementGetAll(`
|
||||||
|
SELECT bags.bag_name
|
||||||
|
FROM bags
|
||||||
|
JOIN (
|
||||||
|
SELECT rb.bag_id
|
||||||
|
FROM recipe_bags AS rb
|
||||||
|
JOIN recipes AS r ON rb.recipe_id = r.recipe_id
|
||||||
|
WHERE r.recipe_name = $recipe_name
|
||||||
|
ORDER BY rb.position
|
||||||
|
) AS bag_priority ON bags.bag_id = bag_priority.bag_id
|
||||||
|
`,{
|
||||||
|
recipe_name: recipename
|
||||||
|
});
|
||||||
|
return rows.map(value => value.bag_name);
|
||||||
|
};
|
||||||
|
|
||||||
exports.SqlTiddlerStore = SqlTiddlerStore;
|
exports.SqlTiddlerStore = SqlTiddlerStore;
|
||||||
|
|
||||||
})();
|
})();
|
|
@ -45,7 +45,7 @@ describe("SQL tiddler store", function() {
|
||||||
expect(sqlTiddlerStore.getTiddler("Another Tiddler","recipe-rho")).toEqual({ title: "Another Tiddler", text: "I'm in alpha", tags: "one two three" });
|
expect(sqlTiddlerStore.getTiddler("Another Tiddler","recipe-rho")).toEqual({ title: "Another Tiddler", text: "I'm in alpha", tags: "one two three" });
|
||||||
expect(sqlTiddlerStore.getTiddler("Hello There","recipe-sigma")).toEqual({ title: "Hello There", text: "I'm in gamma", tags: "seven eight nine" });
|
expect(sqlTiddlerStore.getTiddler("Hello There","recipe-sigma")).toEqual({ title: "Hello There", text: "I'm in gamma", tags: "seven eight nine" });
|
||||||
expect(sqlTiddlerStore.getTiddler("Another Tiddler","recipe-sigma")).toEqual({ title: "Another Tiddler", text: "I'm in alpha", tags: "one two three" });
|
expect(sqlTiddlerStore.getTiddler("Another Tiddler","recipe-sigma")).toEqual({ title: "Another Tiddler", text: "I'm in alpha", tags: "one two three" });
|
||||||
// Delete a tiddler to ensure the underlying tiddler in the recipe shows through
|
// Delete a tiddlers to ensure the underlying tiddler in the recipe shows through
|
||||||
sqlTiddlerStore.deleteTiddler("Hello There","bag-beta");
|
sqlTiddlerStore.deleteTiddler("Hello There","bag-beta");
|
||||||
expect(sqlTiddlerStore.getRecipeTiddlers("recipe-rho")).toEqual([ "Another Tiddler", "Hello There"]);
|
expect(sqlTiddlerStore.getRecipeTiddlers("recipe-rho")).toEqual([ "Another Tiddler", "Hello There"]);
|
||||||
expect(sqlTiddlerStore.getRecipeTiddlers("recipe-sigma")).toEqual([ "Another Tiddler", "Hello There"]);
|
expect(sqlTiddlerStore.getRecipeTiddlers("recipe-sigma")).toEqual([ "Another Tiddler", "Hello There"]);
|
||||||
|
@ -53,6 +53,10 @@ describe("SQL tiddler store", function() {
|
||||||
sqlTiddlerStore.deleteTiddler("Another Tiddler","bag-alpha");
|
sqlTiddlerStore.deleteTiddler("Another Tiddler","bag-alpha");
|
||||||
expect(sqlTiddlerStore.getRecipeTiddlers("recipe-rho")).toEqual([ "Hello There"]);
|
expect(sqlTiddlerStore.getRecipeTiddlers("recipe-rho")).toEqual([ "Hello There"]);
|
||||||
expect(sqlTiddlerStore.getRecipeTiddlers("recipe-sigma")).toEqual([ "Hello There"]);
|
expect(sqlTiddlerStore.getRecipeTiddlers("recipe-sigma")).toEqual([ "Hello There"]);
|
||||||
|
// Save a recipe tiddler
|
||||||
|
sqlTiddlerStore.saveRecipeTiddler({title: "More", text: "None"},"recipe-rho");
|
||||||
|
expect(sqlTiddlerStore.getTiddler("More","recipe-rho")).toEqual({title: "More", text: "None"});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,8 @@ TiddlyWebAdaptor.prototype.getHost = function() {
|
||||||
var text = this.wiki.getTiddlerText(CONFIG_HOST_TIDDLER,DEFAULT_HOST_TIDDLER),
|
var text = this.wiki.getTiddlerText(CONFIG_HOST_TIDDLER,DEFAULT_HOST_TIDDLER),
|
||||||
substitutions = [
|
substitutions = [
|
||||||
{name: "protocol", value: document.location.protocol},
|
{name: "protocol", value: document.location.protocol},
|
||||||
{name: "host", value: document.location.host}
|
{name: "host", value: document.location.host},
|
||||||
|
{name: "pathname", value: document.location.pathname}
|
||||||
];
|
];
|
||||||
for(var t=0; t<substitutions.length; t++) {
|
for(var t=0; t<substitutions.length; t++) {
|
||||||
var s = substitutions[t];
|
var s = substitutions[t];
|
||||||
|
|
Loading…
Reference in New Issue