mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-02-23 06:20:01 +00:00
Deal with dynamic loading and unloading of plugins
More enhancements needed for the test framework too in order to allow events to be processed manually, without relying on the nexttick handler which is awkward in Jasmine
This commit is contained in:
parent
7e2a8238b5
commit
55c634692b
156
boot/boot.js
156
boot/boot.js
@ -1174,8 +1174,8 @@ $tw.Wiki = function(options) {
|
||||
}
|
||||
return tiddlerTitles;
|
||||
},
|
||||
pluginTiddlersInfo = [], // Array of {tiddler:<tiddler object>,parentPluginTitle:<title>} for all plugins and sub-plugins, ordered by priority
|
||||
pluginContents = Object.create(null), // Hashmap of parsed plugin content
|
||||
pluginTiddlersInfo = [], // Array of tiddler fields for all plugins and sub-plugins, ordered by priority
|
||||
pluginContents = Object.create(null), // Hashmap by title of {contents:<parsed plugin contents>,fields:<fields>,subPluginTitles:<list>}
|
||||
shadowTiddlerInfo = Object.create(null), // Hashmap by title of {source:, tiddler:}
|
||||
shadowTiddlerTitles = null, // Array of tiddler titles, calculated and cached when needed
|
||||
getShadowTiddlerTitles = function() {
|
||||
@ -1393,8 +1393,8 @@ $tw.Wiki = function(options) {
|
||||
// Get an array of all the currently recognised plugin types
|
||||
this.getPluginTypes = function() {
|
||||
var types = [];
|
||||
$tw.utils.each(pluginTiddlersInfo,function(pluginTiddlerInfo) {
|
||||
var pluginType = pluginTiddlerInfo.tiddler.fields["plugin-type"];
|
||||
$tw.utils.each(pluginTiddlersInfo,function(pluginTiddlerFields) {
|
||||
var pluginType = pluginTiddlerFields["plugin-type"];
|
||||
if(pluginType && types.indexOf(pluginType) === -1) {
|
||||
types.push(pluginType);
|
||||
}
|
||||
@ -1402,23 +1402,44 @@ $tw.Wiki = function(options) {
|
||||
return types;
|
||||
};
|
||||
|
||||
// Read plugin contents for all plugins, or just an array of titles. Returns the list of updated plugin titles and the list of deleted plugin titles.
|
||||
// Clears the pluginContents cache for any plugins that have been deleted
|
||||
// Read plugin contents for all plugins, or just an array of titles. Returns the list of updated plugin titles, the list of deleted plugin titles and
|
||||
// a hashmap of the deleted plugin contents. Clears the pluginContents cache for any plugins that have been deleted
|
||||
this.readPluginInfo = function(titles) {
|
||||
var results = {
|
||||
var self = this,
|
||||
results = {
|
||||
modifiedPlugins: [],
|
||||
deletedPlugins: []
|
||||
deletedPlugins: [],
|
||||
deletedPluginContents: {}
|
||||
};
|
||||
$tw.utils.each(titles || getTiddlerTitles(),function(title) {
|
||||
var tiddler = tiddlerStore[title];
|
||||
var tiddler = self.getTiddler(title);
|
||||
if(!tiddler) {
|
||||
for(var t=0; t<pluginContents.length; t++) {
|
||||
if(pluginContents[t].subPluginTitles.indexOf(title) !== -1) {
|
||||
tiddler = new $tw.Tiddler(pluginContents[t].fields);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(tiddler) {
|
||||
if(tiddler.isPlugin() && tiddler.fields.text) {
|
||||
var contents = $tw.utils.parseJSONSafe(tiddler.fields.text);
|
||||
pluginContents[tiddler.fields.title] = contents;
|
||||
results.modifiedPlugins.push(tiddler.fields.title);
|
||||
var contents = $tw.utils.parseJSONSafe(tiddler.fields.text).tiddlers;
|
||||
var subPluginTitles = [];
|
||||
// Read any sub-plugins
|
||||
$tw.utils.each(contents,function(subPluginFields,subPluginTitle) {
|
||||
if(subPluginFields["plugin-type"] && subPluginFields["type"] === "application/json") {
|
||||
var contents = $tw.utils.parseJSONSafe(subPluginFields.text).tiddlers
|
||||
pluginContents[subPluginTitle] = {contents: contents,fields: subPluginFields};
|
||||
results.modifiedPlugins.push(subPluginTitle);
|
||||
subPluginTitles.push(subPluginTitle)
|
||||
}
|
||||
});
|
||||
pluginContents[title] = {contents: contents,fields: tiddler.fields,subPluginTitles: subPluginTitles};
|
||||
results.modifiedPlugins.push(title);
|
||||
}
|
||||
} else {
|
||||
if(pluginContents[title]) {
|
||||
results.deletedPluginContents[title] = {tiddlers: pluginContents[title].contents};
|
||||
delete pluginContents[title];
|
||||
results.deletedPlugins.push(title);
|
||||
}
|
||||
@ -1427,57 +1448,43 @@ $tw.Wiki = function(options) {
|
||||
return results;
|
||||
};
|
||||
|
||||
this.isSubPlugin = function(title) {
|
||||
for(var t=0; t<pluginContents.length; t++) {
|
||||
if(pluginContents[t].subPluginTitles.indexOf(title) !== -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Get plugin info for a plugin
|
||||
this.getPluginInfo = function(title) {
|
||||
return pluginContents[title];
|
||||
var pluginContent = pluginContents[title];
|
||||
if(pluginContent) {
|
||||
return {tiddlers: pluginContent.contents, subPluginTitles: pluginContent.subPluginTitles, fields: pluginContent.fields};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Register the plugin tiddlers of a particular type, or null/undefined for any type, optionally restricting registration to an array of tiddler titles. Return the array of titles affected
|
||||
this.registerPluginTiddlers = function(pluginType,titles) {
|
||||
var self = this,
|
||||
registeredTitles = [];
|
||||
if(titles) {
|
||||
$tw.utils.each(titles,function(title) {
|
||||
checkTiddler(null,title);
|
||||
});
|
||||
} else {
|
||||
this.each(function(tiddler,title) {
|
||||
checkTiddler(tiddler,title);
|
||||
});
|
||||
}
|
||||
return registeredTitles;
|
||||
function checkTiddler(tiddler,title) {
|
||||
if(!tiddler) {
|
||||
tiddler = self.getTiddler(title);
|
||||
}
|
||||
if(tiddler && tiddler.isPlugin() && (!pluginType || tiddler.fields["plugin-type"] === pluginType)) {
|
||||
var disablingTiddler = self.getTiddler("$:/config/Plugins/Disabled/" + title);
|
||||
if(title === "$:/core" || !disablingTiddler || (disablingTiddler.fields.text || "").trim() !== "yes") {
|
||||
self.unregisterPluginTiddlers(null,[title]); // Unregister the plugin if it's already registered
|
||||
pluginTiddlersInfo.push({tiddler: tiddler});
|
||||
registeredTitles.push(tiddler.fields.title);
|
||||
// Register any sub-plugins
|
||||
var contents = pluginContents[tiddler.fields.title];
|
||||
if(contents) {
|
||||
$tw.utils.each(contents.tiddlers,function(subPluginFields,subPluginTitle) {
|
||||
checkSubTiddler(title,subPluginTitle);
|
||||
});
|
||||
$tw.utils.each(pluginContents,function(pluginContent,pluginTitle) {
|
||||
var pluginFields = pluginContent.fields;
|
||||
if(!titles || titles.indexOf(pluginTitle) !== -1) {
|
||||
if(!pluginType || pluginFields["plugin-type"] === pluginType) {
|
||||
var disablingTiddler = self.getTiddler("$:/config/Plugins/Disabled/" + pluginTitle);
|
||||
if(pluginTitle === "$:/core" || !disablingTiddler || (disablingTiddler.fields.text || "").trim() !== "yes") {
|
||||
self.unregisterPluginTiddlers(null,[pluginTitle]); // Unregister the plugin if it's already registered
|
||||
pluginTiddlersInfo.push(pluginFields);
|
||||
registeredTitles.push(pluginTitle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function checkSubTiddler(parentPluginTitle,title) {
|
||||
var tiddlerFields = pluginContents[parentPluginTitle].tiddlers[title];
|
||||
if(tiddlerFields.type === "application/json" && tiddlerFields["plugin-type"] && !tiddlerFields["draft.of"] && (!pluginType || tiddlerFields["plugin-type"] === pluginType)) {
|
||||
var tiddler = new $tw.Tiddler(tiddlerFields,{title: title}),
|
||||
disablingTiddler = self.getTiddler("$:/config/Plugins/Disabled/" + title);
|
||||
if(title === "$:/core" || !disablingTiddler || (disablingTiddler.fields.text || "").trim() !== "yes") {
|
||||
self.unregisterPluginTiddlers(null,[title]); // Unregister the plugin if it's already registered
|
||||
pluginTiddlersInfo.push({tiddler: tiddler,parentPluginTitle: parentPluginTitle});
|
||||
registeredTitles.push(tiddler.fields.title);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return registeredTitles;
|
||||
};
|
||||
|
||||
// Unregister the plugin tiddlers of a particular type, or null/undefined for any type, optionally restricting unregistering to an array of tiddler titles. Returns an array of the titles affected
|
||||
@ -1486,10 +1493,9 @@ $tw.Wiki = function(options) {
|
||||
unregisteredTitles = [];
|
||||
// Remove any previous registered plugins of this type
|
||||
for(var t=pluginTiddlersInfo.length-1; t>=0; t--) {
|
||||
var pluginInfo = pluginTiddlersInfo[t],
|
||||
tiddler = pluginInfo.tiddler;
|
||||
if(tiddler.fields["plugin-type"] && (!pluginType || tiddler.fields["plugin-type"] === pluginType) && (!titles || titles.indexOf(tiddler.fields.title) !== -1)) {
|
||||
unregisteredTitles.push(tiddler.fields.title);
|
||||
var pluginFields = pluginTiddlersInfo[t];
|
||||
if(pluginFields["plugin-type"] && (!pluginType || pluginFields["plugin-type"] === pluginType) && (!titles || titles.indexOf(pluginFields.title) !== -1)) {
|
||||
unregisteredTitles.push(pluginFields.title);
|
||||
pluginTiddlersInfo.splice(t,1);
|
||||
}
|
||||
}
|
||||
@ -1501,15 +1507,13 @@ $tw.Wiki = function(options) {
|
||||
var self = this;
|
||||
// Sort the plugin titles by the `plugin-priority` field, if this field is missing, default to 1
|
||||
pluginTiddlersInfo.sort(function(a, b) {
|
||||
var fieldsA = a.tiddler.fields,
|
||||
fieldsB = b.tiddler.fields,
|
||||
priorityA = "plugin-priority" in fieldsA ? fieldsA["plugin-priority"] : 1,
|
||||
priorityB = "plugin-priority" in fieldsB ? fieldsB["plugin-priority"] : 1;
|
||||
var priorityA = "plugin-priority" in a ? a["plugin-priority"] : 1,
|
||||
priorityB = "plugin-priority" in b ? b["plugin-priority"] : 1;
|
||||
if (priorityA !== priorityB) {
|
||||
return priorityA - priorityB;
|
||||
} else if (fieldsA.title < fieldsB.title) {
|
||||
} else if (a.title < b.title) {
|
||||
return -1;
|
||||
} else if (fieldsA.title === fieldsB.title) {
|
||||
} else if (a.title === b.title) {
|
||||
return 0;
|
||||
} else {
|
||||
return +1;
|
||||
@ -1517,26 +1521,16 @@ $tw.Wiki = function(options) {
|
||||
});
|
||||
// Now go through the plugins in ascending order and assign the shadows
|
||||
shadowTiddlerInfo = Object.create(null);
|
||||
$tw.utils.each(pluginTiddlersInfo,function(tiddlerInfo) {
|
||||
var tiddler = tiddlerInfo.tiddler,
|
||||
contents;
|
||||
if(tiddlerInfo.parentPluginTitle) {
|
||||
contents = $tw.utils.parseJSONSafe(pluginContents[tiddlerInfo.parentPluginTitle].tiddlers[tiddler.fields.title].text || "null");
|
||||
} else {
|
||||
contents = pluginContents[tiddler.fields.title];
|
||||
}
|
||||
$tw.utils.each(pluginTiddlersInfo,function(tiddlerFields) {
|
||||
var contents = pluginContents[tiddlerFields.title].contents;
|
||||
// Extract the constituent tiddlers
|
||||
if(contents) {
|
||||
$tw.utils.each(contents.tiddlers,function(constituentTiddler,constituentTitle) {
|
||||
// Save the tiddler object
|
||||
if(constituentTitle) {
|
||||
shadowTiddlerInfo[constituentTitle] = {
|
||||
source: tiddler.fields.title,
|
||||
tiddler: new $tw.Tiddler(constituentTiddler,{title: constituentTitle})
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
$tw.utils.each(contents,function(constituentTiddler,constituentTitle) {
|
||||
// Save the tiddler object
|
||||
shadowTiddlerInfo[constituentTitle] = {
|
||||
source: tiddlerFields.title,
|
||||
tiddler: new $tw.Tiddler(constituentTiddler,{title: constituentTitle})
|
||||
};
|
||||
});
|
||||
});
|
||||
shadowTiddlerTitles = null; // Force regeneration of the shadow tiddler titles list
|
||||
this.clearCache(null);
|
||||
|
@ -18,68 +18,8 @@ exports.after = ["load-modules"];
|
||||
exports.before = ["startup"];
|
||||
exports.synchronous = true;
|
||||
|
||||
var TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE = "$:/status/RequireReloadDueToPluginChange";
|
||||
|
||||
var PREFIX_CONFIG_REGISTER_PLUGIN_TYPE = "$:/config/RegisterPluginType/";
|
||||
|
||||
exports.startup = function() {
|
||||
$tw.wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: "no"});
|
||||
$tw.wiki.addEventListener("change",function(changes) {
|
||||
// Work out which of the changed tiddlers are plugins that we need to reregister
|
||||
var changesToProcess = [],
|
||||
requireReloadDueToPluginChange = false;
|
||||
$tw.utils.each(Object.keys(changes),function(title) {
|
||||
var tiddler = $tw.wiki.getTiddler(title),
|
||||
requiresReload = $tw.wiki.doesPluginRequireReload(title);
|
||||
if(requiresReload) {
|
||||
requireReloadDueToPluginChange = true;
|
||||
} else if(tiddler) {
|
||||
var pluginType = tiddler.fields["plugin-type"];
|
||||
if($tw.wiki.getTiddlerText(PREFIX_CONFIG_REGISTER_PLUGIN_TYPE + (tiddler.fields["plugin-type"] || ""),"no") === "yes") {
|
||||
changesToProcess.push(title);
|
||||
}
|
||||
}
|
||||
});
|
||||
// Issue warning if any of the tiddlers require a reload
|
||||
if(requireReloadDueToPluginChange) {
|
||||
$tw.wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: "yes"});
|
||||
}
|
||||
// Read or delete the plugin info of the changed tiddlers
|
||||
if(changesToProcess.length > 0) {
|
||||
var changes = $tw.wiki.readPluginInfo(changesToProcess);
|
||||
if(changes.modifiedPlugins.length > 0 || changes.deletedPlugins.length > 0) {
|
||||
var changedShadowTiddlers = {};
|
||||
// Collect the shadow tiddlers of any deleted plugins
|
||||
$tw.utils.each(changes.deletedPlugins,function(pluginTitle) {
|
||||
var pluginInfo = $tw.wiki.getPluginInfo(pluginTitle);
|
||||
if(pluginInfo) {
|
||||
$tw.utils.each(Object.keys(pluginInfo.tiddlers),function(title) {
|
||||
changedShadowTiddlers[title] = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
// Collect the shadow tiddlers of any modified plugins
|
||||
$tw.utils.each(changes.modifiedPlugins,function(pluginTitle) {
|
||||
var pluginInfo = $tw.wiki.getPluginInfo(pluginTitle);
|
||||
if(pluginInfo && pluginInfo.tiddlers) {
|
||||
$tw.utils.each(Object.keys(pluginInfo.tiddlers),function(title) {
|
||||
changedShadowTiddlers[title] = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
// (Re-)register any modified plugins
|
||||
$tw.wiki.registerPluginTiddlers(null,changes.modifiedPlugins);
|
||||
// Unregister any deleted plugins
|
||||
$tw.wiki.unregisterPluginTiddlers(null,changes.deletedPlugins);
|
||||
// Unpack the shadow tiddlers
|
||||
$tw.wiki.unpackPluginTiddlers();
|
||||
// Queue change events for the changed shadow tiddlers
|
||||
$tw.utils.each(Object.keys(changedShadowTiddlers),function(title) {
|
||||
$tw.wiki.enqueueTiddlerEvent(title,changedShadowTiddlers[title], true);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
$tw.utils.installPluginChangeHandler($tw.wiki);
|
||||
};
|
||||
|
||||
})();
|
||||
|
95
core/modules/utils/plugins.js
Normal file
95
core/modules/utils/plugins.js
Normal file
@ -0,0 +1,95 @@
|
||||
/*\
|
||||
title: $:/core/modules/utils/plugins.js
|
||||
type: application/javascript
|
||||
module-type: utils
|
||||
|
||||
Plugin utilities
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE = "$:/status/RequireReloadDueToPluginChange";
|
||||
|
||||
var PREFIX_CONFIG_REGISTER_PLUGIN_TYPE = "$:/config/RegisterPluginType/";
|
||||
|
||||
exports.installPluginChangeHandler = function(wiki) {
|
||||
wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: "no"});
|
||||
wiki.addEventListener("change",function(changes) {
|
||||
// Work out which of the changed tiddlers are plugins that we need to (re)register
|
||||
var changesToProcess = [];
|
||||
$tw.utils.each(Object.keys(changes),function(title) {
|
||||
var tiddler = wiki.getTiddler(title);
|
||||
if(tiddler) {
|
||||
// It is a plugin that has been added or modified and is of a type that we need to register
|
||||
if(tiddler.isPlugin() && $tw.wiki.getTiddlerText(PREFIX_CONFIG_REGISTER_PLUGIN_TYPE + (tiddler.fields["plugin-type"] || ""),"no") === "yes") {
|
||||
changesToProcess.push(title);
|
||||
}
|
||||
} else {
|
||||
if(wiki.isSubPlugin(title)) {
|
||||
// It is a sub-plugin
|
||||
changesToProcess.push(title);
|
||||
} else {
|
||||
// It is a plugin that has been deleted
|
||||
var pluginInfo = wiki.getPluginInfo(title)
|
||||
if(pluginInfo) {
|
||||
changesToProcess.push(title);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if(changesToProcess.length > 0) {
|
||||
// Read the plugin info of the changed tiddlers
|
||||
var changedPluginInfo = wiki.readPluginInfo(changesToProcess);
|
||||
if(changedPluginInfo.modifiedPlugins.length > 0 || changedPluginInfo.deletedPlugins.length > 0) {
|
||||
var changedShadowTiddlers = {},
|
||||
requireReloadDueToPluginChange = false;
|
||||
// Collect the shadow tiddlers of any deleted plugins
|
||||
$tw.utils.each(changedPluginInfo.deletedPlugins,function(pluginTitle) {
|
||||
var contents = changedPluginInfo.deletedPluginContents[pluginTitle];
|
||||
if(contents && contents.tiddlers) {
|
||||
$tw.utils.each(Object.keys(contents.tiddlers),function(title) {
|
||||
changedShadowTiddlers[title] = true;
|
||||
if(contents.tiddlers[title].type === "application/javascript") {
|
||||
requireReloadDueToPluginChange = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// Collect the shadow tiddlers of any modified plugins
|
||||
$tw.utils.each(changedPluginInfo.modifiedPlugins,function(pluginTitle) {
|
||||
var pluginInfo = wiki.getPluginInfo(pluginTitle);
|
||||
if(pluginInfo && pluginInfo.tiddlers) {
|
||||
$tw.utils.each(Object.keys(pluginInfo.tiddlers),function(title) {
|
||||
changedShadowTiddlers[title] = false;
|
||||
if(pluginInfo.tiddlers[title].type === "application/javascript") {
|
||||
requireReloadDueToPluginChange = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// (Re-)register any modified plugins
|
||||
wiki.registerPluginTiddlers(null,changedPluginInfo.modifiedPlugins);
|
||||
// Unregister any deleted plugins
|
||||
wiki.unregisterPluginTiddlers(null,changedPluginInfo.deletedPlugins);
|
||||
// Unpack the shadow tiddlers
|
||||
wiki.unpackPluginTiddlers();
|
||||
// Queue change events for the changed shadow tiddlers
|
||||
$tw.utils.each(changedShadowTiddlers,function(status,title) {
|
||||
wiki.enqueueTiddlerEvent(title,changedShadowTiddlers[title], true);
|
||||
});
|
||||
// Issue warning if any of the tiddlers require a reload
|
||||
if(requireReloadDueToPluginChange) {
|
||||
wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: "yes"});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
})();
|
@ -135,6 +135,14 @@ exports.dispatchEvent = function(type /*, args */) {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
false (default) to dispatch event tick as usual
|
||||
true to suppress dispatching the event tick and allow outstanding events to be processed manually
|
||||
*/
|
||||
exports.setDispatchMode = function(mode) {
|
||||
this.dispatchMode = mode;
|
||||
}
|
||||
|
||||
/*
|
||||
Causes a tiddler to be marked as changed, incrementing the change count, and triggers event handlers.
|
||||
This method should be called after the changes it describes have been made to the wiki.tiddlers[] array.
|
||||
@ -159,17 +167,18 @@ exports.enqueueTiddlerEvent = function(title,isDeleted,isShadow) {
|
||||
}
|
||||
// Trigger events
|
||||
this.eventListeners = this.eventListeners || {};
|
||||
if(!this.eventsTriggered) {
|
||||
var self = this;
|
||||
$tw.utils.nextTick(function() {
|
||||
var changes = self.changedTiddlers;
|
||||
self.changedTiddlers = Object.create(null);
|
||||
self.eventsTriggered = false;
|
||||
if($tw.utils.count(changes) > 0) {
|
||||
self.dispatchEvent("change",changes);
|
||||
}
|
||||
});
|
||||
this.eventsTriggered = true;
|
||||
if(!this.eventsTriggered && !this.dispatchMode) {
|
||||
$tw.utils.nextTick(this.processOutstandingTiddlerEvents.bind(this));
|
||||
}
|
||||
this.eventsTriggered = true;
|
||||
};
|
||||
|
||||
exports.processOutstandingTiddlerEvents = function() {
|
||||
var changes = this.changedTiddlers;
|
||||
this.changedTiddlers = Object.create(null);
|
||||
this.eventsTriggered = false;
|
||||
if($tw.utils.count(changes) > 0) {
|
||||
this.dispatchEvent("change",changes);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1743,7 +1752,7 @@ exports.invokeUpgraders = function(titles,tiddlers) {
|
||||
// Determine whether a plugin by title is dynamically loadable
|
||||
exports.doesPluginRequireReload = function(title) {
|
||||
var tiddler = this.getTiddler(title);
|
||||
if(tiddler && tiddler.fields.type === "application/json" && tiddler.fields["plugin-type"]) {
|
||||
if(tiddler && tiddler.isPlugin()) {
|
||||
if(tiddler.fields["plugin-type"] === "import") {
|
||||
// The import plugin never requires reloading
|
||||
return false;
|
||||
|
@ -0,0 +1,36 @@
|
||||
title: Plugins/DynamicJSPluginLoad
|
||||
description: Dynamic JS plugin loading
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
{{$:/status/RequireReloadDueToPluginChange}}
|
||||
+
|
||||
title: Actions
|
||||
|
||||
<$action-createtiddler $basetitle="$:/plugins/tiddlywiki/test-js-plugin" $template="$:/plugins/tiddlywiki/test-js-plugin/raw" type="application/json"/>
|
||||
+
|
||||
title: $:/plugins/tiddlywiki/test-js-plugin/raw
|
||||
list: readme
|
||||
name: bundled-subplugin-tests
|
||||
plugin-type: plugin
|
||||
type: text/plain
|
||||
|
||||
{
|
||||
"tiddlers": {
|
||||
"$:/plugins/tiddlywiki/test-js-plugin/readme": {
|
||||
"title": "$:/plugins/tiddlywiki/test-js-plugin/readme",
|
||||
"text": "Readme from $:/plugins/tiddlywiki/test-js-plugin\n\n"
|
||||
},
|
||||
"$:/plugins/tiddlywiki/test-js-plugin/js": {
|
||||
"title": "$:/plugins/tiddlywiki/test-js-plugin/js",
|
||||
"text": "2+2",
|
||||
"type": "application/javascript"
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>yes</p>
|
@ -0,0 +1,43 @@
|
||||
title: Plugins/DynamicSubPluginLoad
|
||||
description: Dynamic sub-plugin loading
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
{{$:/plugins/tiddlywiki/test-subplugin/readme}}
|
||||
+
|
||||
title: Actions
|
||||
|
||||
<$action-createtiddler $basetitle="$:/plugins/tiddlywiki/bundled-subplugin-tests" $template="$:/plugins/tiddlywiki/bundled-subplugin-tests/raw" type="application/json"/>
|
||||
+
|
||||
title: $:/plugins/tiddlywiki/bundled-subplugin-tests/raw
|
||||
list: readme
|
||||
name: bundled-subplugin-tests
|
||||
plugin-type: plugin
|
||||
type: text/plain
|
||||
|
||||
{
|
||||
"tiddlers": {
|
||||
"$:/plugins/tiddlywiki/bundled-subplugin-tests/readme": {
|
||||
"title": "$:/plugins/tiddlywiki/bundled-subplugin-tests/readme",
|
||||
"text": "Readme from $:/plugins/tiddlywiki/bundled-subplugin-tests\n\n"
|
||||
},
|
||||
"$:/plugins/tiddlywiki/test-subplugin": {
|
||||
"title": "$:/plugins/tiddlywiki/test-subplugin",
|
||||
"name": "test-subplugin",
|
||||
"description": "Test subplugin",
|
||||
"list": "readme",
|
||||
"stability": "STABILITY_1_EXPERIMENTAL",
|
||||
"version": "5.3.7-prerelease",
|
||||
"plugin-type": "plugin",
|
||||
"dependents": "",
|
||||
"type": "application/json",
|
||||
"text": "{\"tiddlers\":{\"$:/plugins/tiddlywiki/test-subplugin/readme\":{\"title\":\"$:/plugins/tiddlywiki/test-subplugin/readme\",\"text\":\"Readme from $:/plugins/tiddlywiki/test-subplugin\"},\"$:/plugins/tiddlywiki/test-subsubplugin\":{\"title\":\"$:/plugins/tiddlywiki/test-subsubplugin\",\"name\":\"test-subsubplugin\",\"description\":\"Test subsubplugin\",\"list\":\"readme readme2\",\"stability\":\"STABILITY_1_EXPERIMENTAL\",\"version\":\"5.3.7-prerelease\",\"plugin-type\":\"plugin\",\"dependents\":\"\",\"type\":\"application/json\",\"text\":\"{\\\"tiddlers\\\":{\\\"$:/plugins/tiddlywiki/test-subsubplugin/readme\\\":{\\\"title\\\":\\\"$:/plugins/tiddlywiki/test-subsubplugin/readme\\\",\\\"text\\\":\\\"Readme from $:/plugins/tiddlywiki/test-subsubplugin\\\"}}}\"}}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>Readme from <a class="tc-tiddlylink tc-tiddlylink-shadow" href="#%24%3A%2Fplugins%2Ftiddlywiki%2Ftest-subplugin">$:/plugins/tiddlywiki/test-subplugin</a></p>
|
@ -0,0 +1,43 @@
|
||||
title: Plugins/DynamicSubPluginUnload
|
||||
description: Dynamic sub-plugin unloading
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-specx]]
|
||||
|
||||
title: Output
|
||||
|
||||
{{$:/plugins/tiddlywiki/bundled-subplugin-tests/readme}}
|
||||
+
|
||||
title: Actions
|
||||
|
||||
<$action-deletetiddler $tiddler="$:/plugins/tiddlywiki/bundled-subplugin-tests"/>
|
||||
+
|
||||
title: $:/plugins/tiddlywiki/bundled-subplugin-tests
|
||||
list: readme
|
||||
name: bundled-subplugin-tests
|
||||
plugin-type: plugin
|
||||
type: application/json
|
||||
|
||||
{
|
||||
"tiddlers": {
|
||||
"$:/plugins/tiddlywiki/bundled-subplugin-tests/readme": {
|
||||
"title": "$:/plugins/tiddlywiki/bundled-subplugin-tests/readme",
|
||||
"text": "Readme from $:/plugins/tiddlywiki/bundled-subplugin-tests\n\n"
|
||||
},
|
||||
"$:/plugins/tiddlywiki/test-subplugin": {
|
||||
"title": "$:/plugins/tiddlywiki/test-subplugin",
|
||||
"name": "test-subplugin",
|
||||
"description": "Test subplugin",
|
||||
"list": "readme",
|
||||
"stability": "STABILITY_1_EXPERIMENTAL",
|
||||
"version": "5.3.7-prerelease",
|
||||
"plugin-type": "plugin",
|
||||
"dependents": "",
|
||||
"type": "application/json",
|
||||
"text": "{\"tiddlers\":{\"$:/plugins/tiddlywiki/test-subplugin/readme\":{\"title\":\"$:/plugins/tiddlywiki/test-subplugin/readme\",\"text\":\"Readme from $:/plugins/tiddlywiki/test-subplugin\"},\"$:/plugins/tiddlywiki/test-subsubplugin\":{\"title\":\"$:/plugins/tiddlywiki/test-subsubplugin\",\"name\":\"test-subsubplugin\",\"description\":\"Test subsubplugin\",\"list\":\"readme readme2\",\"stability\":\"STABILITY_1_EXPERIMENTAL\",\"version\":\"5.3.7-prerelease\",\"plugin-type\":\"plugin\",\"dependents\":\"\",\"type\":\"application/json\",\"text\":\"{\\\"tiddlers\\\":{\\\"$:/plugins/tiddlywiki/test-subsubplugin/readme\\\":{\\\"title\\\":\\\"$:/plugins/tiddlywiki/test-subsubplugin/readme\\\",\\\"text\\\":\\\"Readme from $:/plugins/tiddlywiki/test-subsubplugin\\\"}}}\"}}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
.
|
@ -0,0 +1,21 @@
|
||||
title: Plugins/SimpleSubPlugin
|
||||
description: Simple sub-plugin
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
{{$:/plugins/tiddlywiki/test-subplugin/readme}}
|
||||
|
||||
+
|
||||
title: $:/plugins/tiddlywiki/bundled-subplugin-tests
|
||||
list: readme
|
||||
name: bundled-subplugin-tests
|
||||
plugin-type: plugin
|
||||
type: application/json
|
||||
|
||||
{"tiddlers":{"$:/plugins/tiddlywiki/bundled-subplugin-tests/readme":{"title":"$:/plugins/tiddlywiki/bundled-subplugin-tests/readme","text":"Readme from $:/plugins/tiddlywiki/bundled-subplugin-tests\n\n"},"$:/plugins/tiddlywiki/test-subplugin":{"title":"$:/plugins/tiddlywiki/test-subplugin","name":"test-subplugin","description":"Test subplugin","list":"readme","stability":"STABILITY_1_EXPERIMENTAL","version":"5.3.7-prerelease","plugin-type":"plugin","dependents":"","type":"application/json","text":"{\"tiddlers\":{\"$:/plugins/tiddlywiki/test-subplugin/readme\":{\"title\":\"$:/plugins/tiddlywiki/test-subplugin/readme\",\"text\":\"Readme from $:/plugins/tiddlywiki/test-subplugin\"},\"$:/plugins/tiddlywiki/test-subsubplugin\":{\"title\":\"$:/plugins/tiddlywiki/test-subsubplugin\",\"name\":\"test-subsubplugin\",\"description\":\"Test subsubplugin\",\"list\":\"readme readme2\",\"stability\":\"STABILITY_1_EXPERIMENTAL\",\"version\":\"5.3.7-prerelease\",\"plugin-type\":\"plugin\",\"dependents\":\"\",\"type\":\"application/json\",\"text\":\"{\\\"tiddlers\\\":{\\\"$:/plugins/tiddlywiki/test-subsubplugin/readme\\\":{\\\"title\\\":\\\"$:/plugins/tiddlywiki/test-subsubplugin/readme\\\",\\\"text\\\":\\\"Readme from $:/plugins/tiddlywiki/test-subsubplugin\\\"}}}\"}}}"}}}
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>Readme from <a class="tc-tiddlylink tc-tiddlylink-shadow" href="#%24%3A%2Fplugins%2Ftiddlywiki%2Ftest-subplugin">$:/plugins/tiddlywiki/test-subplugin</a></p>
|
@ -24,11 +24,15 @@ describe("Wiki-based tests", function() {
|
||||
var tiddler = $tw.wiki.getTiddler(title);
|
||||
it(tiddler.fields.title + ": " + tiddler.fields.description, function() {
|
||||
// Add our tiddlers
|
||||
var wiki = new $tw.Wiki(),
|
||||
coreTiddler = $tw.wiki.getTiddler("$:/core");
|
||||
var wiki = new $tw.Wiki();
|
||||
// Suppress next tick dispatch for wiki change events
|
||||
wiki.setDispatchMode(true);
|
||||
// Add the core plugin
|
||||
var coreTiddler = $tw.wiki.getTiddler("$:/core")
|
||||
if(coreTiddler) {
|
||||
wiki.addTiddler(coreTiddler);
|
||||
}
|
||||
// Add other tiddlers
|
||||
wiki.addTiddlers(readMultipleTiddlersTiddler(title));
|
||||
// Unpack plugin tiddlers
|
||||
wiki.readPluginInfo();
|
||||
@ -37,6 +41,8 @@ describe("Wiki-based tests", function() {
|
||||
wiki.addIndexersToWiki();
|
||||
// Clear changes queue
|
||||
wiki.clearTiddlerEventQueue();
|
||||
// Install the plugin change event handler
|
||||
$tw.utils.installPluginChangeHandler(wiki);
|
||||
// Complain if we don't have the ouput and expected results
|
||||
if(!wiki.tiddlerExists("Output")) {
|
||||
throw "Missing 'Output' tiddler";
|
||||
@ -54,7 +60,14 @@ describe("Wiki-based tests", function() {
|
||||
widgetNode.invokeActionString(wiki.getTiddlerText("Actions"));
|
||||
refreshWidgetNode(widgetNode,wrapper);
|
||||
}
|
||||
// Make sure all wiki events have been cleared
|
||||
while(wiki.eventsTriggered) {
|
||||
wiki.processOutstandingTiddlerEvents();
|
||||
refreshWidgetNode(widgetNode,wrapper);
|
||||
}
|
||||
wiki.processOutstandingTiddlerEvents();
|
||||
// Test the rendering
|
||||
refreshWidgetNode(widgetNode,wrapper);
|
||||
expect(wrapper.innerHTML).toBe(wiki.getTiddlerText("ExpectedResult"));
|
||||
}
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user