mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-23 10:07:19 +00:00
Refactoring module mechanism
Changed the data structure $tw.modules.types to make it possible to detect repeated registrations
This commit is contained in:
parent
ce47f5e1d4
commit
539b64b626
89
core/boot.js
89
core/boot.js
@ -2,11 +2,9 @@
|
||||
title: $:/core/boot.js
|
||||
type: application/javascript
|
||||
|
||||
The main boot kernel for TiddlyWiki. This single file creates a barebones TW environment that is just
|
||||
sufficient to bootstrap the modules containing the main logic of the application.
|
||||
The main boot kernel for TiddlyWiki. This single file creates a barebones TW environment that is just sufficient to bootstrap the modules containing the main logic of the application.
|
||||
|
||||
On the server this file is executed directly to boot TiddlyWiki. In the browser, this file is packed
|
||||
into a single HTML file along with other elements:
|
||||
On the server this file is executed directly to boot TiddlyWiki. In the browser, this file is packed into a single HTML file along with other elements:
|
||||
|
||||
# bootprefix.js
|
||||
# <module definitions>
|
||||
@ -83,7 +81,7 @@ $tw.plugins = {};
|
||||
// Modules store registers all the modules the system has seen
|
||||
$tw.modules = $tw.modules || {};
|
||||
$tw.modules.titles = $tw.modules.titles || {}; // hashmap by module title of {fn:, exports:, moduleType:}
|
||||
$tw.modules.types = $tw.modules.types || {}; // hashmap by module type of array of exports
|
||||
$tw.modules.types = $tw.modules.types || {}; // hashmap by module type of hashmap of exports
|
||||
|
||||
// Config object
|
||||
$tw.config = $tw.config || {};
|
||||
@ -300,9 +298,28 @@ Register the exports of a single module in the $tw.modules.types hashmap
|
||||
*/
|
||||
$tw.modules.registerModuleExports = function(name,moduleType,moduleExports) {
|
||||
if(!$tw.utils.hop($tw.modules.types,moduleType)) {
|
||||
$tw.modules.types[moduleType] = [];
|
||||
$tw.modules.types[moduleType] = {};
|
||||
}
|
||||
if($tw.utils.hop($tw.modules.types[moduleType],name)) {
|
||||
console.log("Warning: Reregistering module - " + name);
|
||||
}
|
||||
$tw.modules.types[moduleType][name] = moduleExports;
|
||||
};
|
||||
|
||||
/*
|
||||
Apply a callback to each module of a particular type
|
||||
moduleType: type of modules to enumerate
|
||||
callback: function called as callback(title,moduleExports) for each module
|
||||
*/
|
||||
$tw.modules.forEachModuleOfType = function(moduleType,callback) {
|
||||
var modules = $tw.modules.types[moduleType];
|
||||
if(modules) {
|
||||
for(var title in modules) {
|
||||
if($tw.utils.hop(modules,title)) {
|
||||
callback(title,modules[title]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$tw.modules.types[moduleType].push(moduleExports);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -310,13 +327,10 @@ Get all the modules of a particular type in a hashmap by their `name` field
|
||||
*/
|
||||
$tw.modules.getModulesByTypeAsHashmap = function(moduleType,nameField) {
|
||||
nameField = nameField || "name";
|
||||
var modules = $tw.modules.types[moduleType],
|
||||
results = {};
|
||||
if(modules) {
|
||||
for(var t=0; t<modules.length; t++) {
|
||||
results[modules[t][nameField]] = modules[t];
|
||||
}
|
||||
}
|
||||
var results = {};
|
||||
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
|
||||
results[module[nameField]] = module;
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
@ -324,16 +338,13 @@ $tw.modules.getModulesByTypeAsHashmap = function(moduleType,nameField) {
|
||||
Apply the exports of the modules of a particular type to a target object
|
||||
*/
|
||||
$tw.modules.applyMethods = function(moduleType,object) {
|
||||
var modules = $tw.modules.types[moduleType],
|
||||
n,m,f;
|
||||
if(modules) {
|
||||
for(n=0; n<modules.length; n++) {
|
||||
m = modules[n];
|
||||
for(f in m) {
|
||||
object[f] = m[f];
|
||||
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
|
||||
for(var field in module) {
|
||||
if($tw.utils.hop(module,field)) {
|
||||
object[field] = module[field];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/////////////////////////// Barebones tiddler object
|
||||
@ -775,7 +786,7 @@ Load the tiddlers from a bundle folder, and package them up into a proper JSON b
|
||||
*/
|
||||
$tw.loadBundleFolder = function(filepath,excludeRegExp) {
|
||||
excludeRegExp = excludeRegExp || /^\.DS_Store$|.meta$/;
|
||||
var stat, files, bundleInfo = {tiddlers: []}, bundleTiddlers = [], f, file, titlePrefix, t;
|
||||
var stat, files, bundleInfo, bundleTiddlers = [], f, file, titlePrefix, t;
|
||||
if(fs.existsSync(filepath)) {
|
||||
stat = fs.statSync(filepath);
|
||||
if(stat.isDirectory()) {
|
||||
@ -803,12 +814,12 @@ $tw.loadBundleFolder = function(filepath,excludeRegExp) {
|
||||
}
|
||||
}
|
||||
// Save the bundle tiddler
|
||||
return {
|
||||
return bundleInfo ? {
|
||||
title: bundleInfo.title,
|
||||
type: "application/json",
|
||||
bundle: "yes",
|
||||
text: JSON.stringify(bundleInfo)
|
||||
};
|
||||
} : null;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -879,20 +890,33 @@ if($tw.browser) {
|
||||
// On the server, we load tiddlers from specified folders
|
||||
var folders = [
|
||||
$tw.boot.bootPath,
|
||||
path.resolve($tw.boot.wikiPath,$tw.config.wikiPluginsSubDir),
|
||||
path.resolve($tw.boot.wikiPath,$tw.config.wikiShadowsSubDir),
|
||||
path.resolve($tw.boot.wikiPath,$tw.config.wikiTiddlersSubDir)
|
||||
];
|
||||
for(t=0; t<folders.length; t++) {
|
||||
$tw.wiki.addTiddlers($tw.loadTiddlersFromPath(folders[t]));
|
||||
}
|
||||
// Load any plugins specified within the wiki folder
|
||||
// Load any plugins listed in the wiki info file
|
||||
var wikiInfoPath = path.resolve($tw.boot.wikiPath,$tw.config.wikiInfo);
|
||||
if(fs.existsSync(wikiInfoPath)) {
|
||||
var wikiInfo = JSON.parse(fs.readFileSync(wikiInfoPath,"utf8")),
|
||||
pluginBasePath = path.resolve($tw.boot.bootPath,$tw.config.pluginsPath);
|
||||
for(t=0; t<wikiInfo.plugins.length; t++) {
|
||||
$tw.wiki.addTiddler($tw.loadBundleFolder(path.resolve(pluginBasePath,"./" + wikiInfo.plugins[t])));
|
||||
var bundle = $tw.loadBundleFolder(path.resolve(pluginBasePath,"./" + wikiInfo.plugins[t]));
|
||||
if(bundle) {
|
||||
$tw.wiki.addTiddler(bundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Load any plugins within the wiki folder
|
||||
var wikiPluginsPath = path.resolve($tw.boot.wikiPath,$tw.config.wikiPluginsSubDir);
|
||||
if(fs.existsSync(wikiPluginsPath)) {
|
||||
var pluginFolders = fs.readdirSync(wikiPluginsPath);
|
||||
for(t=0; t<pluginFolders.length; t++) {
|
||||
var bundle = $tw.loadBundleFolder(path.resolve(wikiPluginsPath,"./" + pluginFolders[t]));
|
||||
if(bundle) {
|
||||
$tw.wiki.addTiddler(bundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -904,9 +928,10 @@ $tw.wiki.unpackBundleTiddlers();
|
||||
$tw.wiki.registerModuleTiddlers();
|
||||
|
||||
// Run any startup modules
|
||||
var mainModules = $tw.modules.types.startup;
|
||||
for(var m=0; m<mainModules.length; m++) {
|
||||
mainModules[m].startup();
|
||||
}
|
||||
$tw.modules.forEachModuleOfType("startup",function(title,module) {
|
||||
if(module.startup) {
|
||||
module.startup();
|
||||
}
|
||||
});
|
||||
|
||||
})();
|
||||
|
@ -26,6 +26,9 @@ Define a JavaScript tiddler module for later execution
|
||||
fn: function defining the module, called with the arguments (module,require,exports)
|
||||
*/
|
||||
$tw.modules.define = function(moduleName,moduleType,fn) {
|
||||
if(Object.prototype.hasOwnProperty.call($tw.modules.titles,moduleName)) {
|
||||
console.log("Warning: Redefined module - " + moduleName);
|
||||
}
|
||||
$tw.modules.titles[moduleName] = {
|
||||
moduleType: moduleType,
|
||||
fn: fn
|
||||
|
@ -93,23 +93,17 @@ Commander.prototype.executeNextCommand = function() {
|
||||
};
|
||||
|
||||
Commander.initCommands = function(moduleType) {
|
||||
// Install the command modules
|
||||
moduleType = moduleType || "command";
|
||||
$tw.commands = {};
|
||||
var modules = $tw.modules.types[moduleType],
|
||||
n,m,f,c;
|
||||
if(modules) {
|
||||
for(n=0; n<modules.length; n++) {
|
||||
m = modules[n];
|
||||
$tw.commands[m.info.name] = {};
|
||||
c = $tw.commands[m.info.name];
|
||||
// Add the methods defined by the module
|
||||
for(f in m) {
|
||||
c[f] = m[f];
|
||||
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
|
||||
var c = $tw.commands[module.info.name] = {};
|
||||
// Add the methods defined by the module
|
||||
for(var f in module) {
|
||||
if($tw.utils.hop(module,f)) {
|
||||
c[f] = module[f];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
exports.Commander = Commander;
|
||||
|
@ -266,17 +266,17 @@ var WikiTextParser = function(options) {
|
||||
this.runRules = [];
|
||||
var blockRegExpStrings = [],
|
||||
runRegExpStrings = [],
|
||||
rules = ($tw.modules.types.wikitextrule || []).slice(0);
|
||||
for(var t=0; t<rules.length; t++) {
|
||||
if(rules[t].blockParser) {
|
||||
this.blockRules.push(rules[t]);
|
||||
blockRegExpStrings.push("(" + rules[t].regExpString + ")");
|
||||
self = this;
|
||||
$tw.modules.forEachModuleOfType("wikitextrule",function(title,module) {
|
||||
if(module.blockParser) {
|
||||
self.blockRules.push(module);
|
||||
blockRegExpStrings.push("(" + module.regExpString + ")");
|
||||
}
|
||||
if(rules[t].runParser) {
|
||||
this.runRules.push(rules[t]);
|
||||
runRegExpStrings.push("(" + rules[t].regExpString + ")");
|
||||
if(module.runParser) {
|
||||
self.runRules.push(module);
|
||||
runRegExpStrings.push("(" + module.regExpString + ")");
|
||||
}
|
||||
}
|
||||
});
|
||||
this.blockRegExp = new RegExp(blockRegExpStrings.join("|"),"mg");
|
||||
this.runRegExp = new RegExp(runRegExpStrings.join("|"),"mg");
|
||||
};
|
||||
|
@ -42,12 +42,11 @@ exports.startup = function() {
|
||||
// Host-specific startup
|
||||
if($tw.browser) {
|
||||
// Call browser startup modules
|
||||
modules = $tw.modules.types["browser-startup"];
|
||||
if(modules) {
|
||||
for(m=0; m<modules.length; m++) {
|
||||
modules[m].startup();
|
||||
$tw.modules.forEachModuleOfType("browser-startup",function(title,module) {
|
||||
if(module.startup) {
|
||||
module.startup();
|
||||
}
|
||||
}
|
||||
});
|
||||
// Install the popup manager
|
||||
$tw.popup = new $tw.utils.Popup({
|
||||
wiki: $tw.wiki,
|
||||
@ -113,7 +112,6 @@ exports.startup = function() {
|
||||
{output: process.stdout, error: process.stderr}
|
||||
);
|
||||
commander.execute();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -387,21 +387,18 @@ exports.clearCache = function(title) {
|
||||
exports.initParsers = function(moduleType) {
|
||||
// Install the parser modules
|
||||
moduleType = moduleType || "parser";
|
||||
$tw.wiki.parsers = {};
|
||||
var modules = $tw.modules.types[moduleType],
|
||||
n,m,f;
|
||||
if(modules) {
|
||||
for(n=0; n<modules.length; n++) {
|
||||
m = modules[n];
|
||||
// Add the parsers defined by the module
|
||||
for(f in m) {
|
||||
$tw.wiki.parsers[f] = new m[f]({wiki: this}); // Store an instance of the parser
|
||||
$tw.wiki.parsers = {};
|
||||
var self = this;
|
||||
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
|
||||
for(var f in module) {
|
||||
if($tw.utils.hop(module,f)) {
|
||||
$tw.wiki.parsers[f] = new module[f]({wiki: self}); // Store an instance of the parser
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// Install the rules for the old wikitext parser rules
|
||||
var wikitextparser = this.parsers["text/x-tiddlywiki-old"];
|
||||
if(modules && wikitextparser) {
|
||||
if(wikitextparser) {
|
||||
wikitextparser.installRules();
|
||||
}
|
||||
};
|
||||
@ -501,10 +498,8 @@ It's useful to remember what the `new` keyword does. It:
|
||||
*/
|
||||
exports.initMacros = function(moduleType) {
|
||||
moduleType = moduleType || "macro";
|
||||
$tw.wiki.macros = {};
|
||||
$tw.wiki.macros = {};
|
||||
var MacroClass = require("./treenodes/macro.js").Macro,
|
||||
modules = $tw.modules.types[moduleType],
|
||||
n,m,f,
|
||||
subclassMacro = function(module) {
|
||||
// Make a copy of the Macro() constructor function
|
||||
var MacroMaker = function Macro() {
|
||||
@ -514,17 +509,16 @@ exports.initMacros = function(moduleType) {
|
||||
MacroMaker.prototype = new MacroClass();
|
||||
// Add the prototype methods for this instance of the macro
|
||||
for(var f in module) {
|
||||
MacroMaker.prototype[f] = module[f];
|
||||
if($tw.utils.hop(module,f)) {
|
||||
MacroMaker.prototype[f] = module[f];
|
||||
}
|
||||
}
|
||||
// Make a more convenient reference to the macro info
|
||||
return MacroMaker;
|
||||
};
|
||||
if(modules) {
|
||||
for(n=0; n<modules.length; n++) {
|
||||
m = modules[n];
|
||||
$tw.wiki.macros[m.info.name] = subclassMacro(m);
|
||||
}
|
||||
}
|
||||
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
|
||||
$tw.wiki.macros[module.info.name] = subclassMacro(module);
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
@ -582,12 +576,12 @@ exports.initSavers = function(moduleType) {
|
||||
moduleType = moduleType || "saver";
|
||||
// Instantiate the available savers
|
||||
this.savers = [];
|
||||
for(var t=0; t<$tw.modules.types[moduleType].length; t++) {
|
||||
var saver = $tw.modules.types[moduleType][t];
|
||||
if(saver.canSave(this)) {
|
||||
this.savers.push(saver.create(this));
|
||||
var self = this;
|
||||
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
|
||||
if(module.canSave(self)) {
|
||||
self.savers.push(module.create(self));
|
||||
}
|
||||
}
|
||||
});
|
||||
// Sort the savers into priority order
|
||||
this.savers.sort(function(a,b) {
|
||||
if(a.info.priority < b.info.priority) {
|
||||
|
@ -88,10 +88,9 @@ $tw.plugins.dropbox.login = function() {
|
||||
Invoke any dropbox-startup modules
|
||||
*/
|
||||
$tw.plugins.dropbox.invokeDropboxStartupModules = function(loggedIn) {
|
||||
var mods = $tw.modules.types["dropbox-startup"];
|
||||
for(var m=0; m<mods.length; m++) {
|
||||
mods[m].startup(loggedIn);
|
||||
}
|
||||
$tw.modules.forEachModuleOfType("dropbox-startup",function(title,module) {
|
||||
module.startup(loggedIn);
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1,15 +0,0 @@
|
||||
/*\
|
||||
title: $:/tiddlywiki/plugins/demoplugin/demoplugin.js
|
||||
type: application/javascript
|
||||
module-type: demo
|
||||
|
||||
A demo plugin
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
"use strict";
|
||||
|
||||
|
||||
})();
|
Loading…
Reference in New Issue
Block a user