mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-07-07 20:42:50 +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
|
title: $:/core/boot.js
|
||||||
type: application/javascript
|
type: application/javascript
|
||||||
|
|
||||||
The main boot kernel for TiddlyWiki. This single file creates a barebones TW environment that is just
|
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.
|
||||||
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
|
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:
|
||||||
into a single HTML file along with other elements:
|
|
||||||
|
|
||||||
# bootprefix.js
|
# bootprefix.js
|
||||||
# <module definitions>
|
# <module definitions>
|
||||||
@ -83,7 +81,7 @@ $tw.plugins = {};
|
|||||||
// Modules store registers all the modules the system has seen
|
// Modules store registers all the modules the system has seen
|
||||||
$tw.modules = $tw.modules || {};
|
$tw.modules = $tw.modules || {};
|
||||||
$tw.modules.titles = $tw.modules.titles || {}; // hashmap by module title of {fn:, exports:, moduleType:}
|
$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
|
// Config object
|
||||||
$tw.config = $tw.config || {};
|
$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) {
|
$tw.modules.registerModuleExports = function(name,moduleType,moduleExports) {
|
||||||
if(!$tw.utils.hop($tw.modules.types,moduleType)) {
|
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) {
|
$tw.modules.getModulesByTypeAsHashmap = function(moduleType,nameField) {
|
||||||
nameField = nameField || "name";
|
nameField = nameField || "name";
|
||||||
var modules = $tw.modules.types[moduleType],
|
var results = {};
|
||||||
results = {};
|
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
|
||||||
if(modules) {
|
results[module[nameField]] = module;
|
||||||
for(var t=0; t<modules.length; t++) {
|
});
|
||||||
results[modules[t][nameField]] = modules[t];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
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
|
Apply the exports of the modules of a particular type to a target object
|
||||||
*/
|
*/
|
||||||
$tw.modules.applyMethods = function(moduleType,object) {
|
$tw.modules.applyMethods = function(moduleType,object) {
|
||||||
var modules = $tw.modules.types[moduleType],
|
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
|
||||||
n,m,f;
|
for(var field in module) {
|
||||||
if(modules) {
|
if($tw.utils.hop(module,field)) {
|
||||||
for(n=0; n<modules.length; n++) {
|
object[field] = module[field];
|
||||||
m = modules[n];
|
|
||||||
for(f in m) {
|
|
||||||
object[f] = m[f];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////// Barebones tiddler object
|
/////////////////////////// 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) {
|
$tw.loadBundleFolder = function(filepath,excludeRegExp) {
|
||||||
excludeRegExp = excludeRegExp || /^\.DS_Store$|.meta$/;
|
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)) {
|
if(fs.existsSync(filepath)) {
|
||||||
stat = fs.statSync(filepath);
|
stat = fs.statSync(filepath);
|
||||||
if(stat.isDirectory()) {
|
if(stat.isDirectory()) {
|
||||||
@ -803,12 +814,12 @@ $tw.loadBundleFolder = function(filepath,excludeRegExp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Save the bundle tiddler
|
// Save the bundle tiddler
|
||||||
return {
|
return bundleInfo ? {
|
||||||
title: bundleInfo.title,
|
title: bundleInfo.title,
|
||||||
type: "application/json",
|
type: "application/json",
|
||||||
bundle: "yes",
|
bundle: "yes",
|
||||||
text: JSON.stringify(bundleInfo)
|
text: JSON.stringify(bundleInfo)
|
||||||
};
|
} : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -879,20 +890,33 @@ if($tw.browser) {
|
|||||||
// On the server, we load tiddlers from specified folders
|
// On the server, we load tiddlers from specified folders
|
||||||
var folders = [
|
var folders = [
|
||||||
$tw.boot.bootPath,
|
$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.wikiShadowsSubDir),
|
||||||
path.resolve($tw.boot.wikiPath,$tw.config.wikiTiddlersSubDir)
|
path.resolve($tw.boot.wikiPath,$tw.config.wikiTiddlersSubDir)
|
||||||
];
|
];
|
||||||
for(t=0; t<folders.length; t++) {
|
for(t=0; t<folders.length; t++) {
|
||||||
$tw.wiki.addTiddlers($tw.loadTiddlersFromPath(folders[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);
|
var wikiInfoPath = path.resolve($tw.boot.wikiPath,$tw.config.wikiInfo);
|
||||||
if(fs.existsSync(wikiInfoPath)) {
|
if(fs.existsSync(wikiInfoPath)) {
|
||||||
var wikiInfo = JSON.parse(fs.readFileSync(wikiInfoPath,"utf8")),
|
var wikiInfo = JSON.parse(fs.readFileSync(wikiInfoPath,"utf8")),
|
||||||
pluginBasePath = path.resolve($tw.boot.bootPath,$tw.config.pluginsPath);
|
pluginBasePath = path.resolve($tw.boot.bootPath,$tw.config.pluginsPath);
|
||||||
for(t=0; t<wikiInfo.plugins.length; t++) {
|
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();
|
$tw.wiki.registerModuleTiddlers();
|
||||||
|
|
||||||
// Run any startup modules
|
// Run any startup modules
|
||||||
var mainModules = $tw.modules.types.startup;
|
$tw.modules.forEachModuleOfType("startup",function(title,module) {
|
||||||
for(var m=0; m<mainModules.length; m++) {
|
if(module.startup) {
|
||||||
mainModules[m].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)
|
fn: function defining the module, called with the arguments (module,require,exports)
|
||||||
*/
|
*/
|
||||||
$tw.modules.define = function(moduleName,moduleType,fn) {
|
$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] = {
|
$tw.modules.titles[moduleName] = {
|
||||||
moduleType: moduleType,
|
moduleType: moduleType,
|
||||||
fn: fn
|
fn: fn
|
||||||
|
@ -93,23 +93,17 @@ Commander.prototype.executeNextCommand = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Commander.initCommands = function(moduleType) {
|
Commander.initCommands = function(moduleType) {
|
||||||
// Install the command modules
|
|
||||||
moduleType = moduleType || "command";
|
moduleType = moduleType || "command";
|
||||||
$tw.commands = {};
|
$tw.commands = {};
|
||||||
var modules = $tw.modules.types[moduleType],
|
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
|
||||||
n,m,f,c;
|
var c = $tw.commands[module.info.name] = {};
|
||||||
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
|
// Add the methods defined by the module
|
||||||
for(f in m) {
|
for(var f in module) {
|
||||||
c[f] = m[f];
|
if($tw.utils.hop(module,f)) {
|
||||||
|
c[f] = module[f];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.Commander = Commander;
|
exports.Commander = Commander;
|
||||||
|
@ -266,17 +266,17 @@ var WikiTextParser = function(options) {
|
|||||||
this.runRules = [];
|
this.runRules = [];
|
||||||
var blockRegExpStrings = [],
|
var blockRegExpStrings = [],
|
||||||
runRegExpStrings = [],
|
runRegExpStrings = [],
|
||||||
rules = ($tw.modules.types.wikitextrule || []).slice(0);
|
self = this;
|
||||||
for(var t=0; t<rules.length; t++) {
|
$tw.modules.forEachModuleOfType("wikitextrule",function(title,module) {
|
||||||
if(rules[t].blockParser) {
|
if(module.blockParser) {
|
||||||
this.blockRules.push(rules[t]);
|
self.blockRules.push(module);
|
||||||
blockRegExpStrings.push("(" + rules[t].regExpString + ")");
|
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.blockRegExp = new RegExp(blockRegExpStrings.join("|"),"mg");
|
||||||
this.runRegExp = new RegExp(runRegExpStrings.join("|"),"mg");
|
this.runRegExp = new RegExp(runRegExpStrings.join("|"),"mg");
|
||||||
};
|
};
|
||||||
|
@ -42,12 +42,11 @@ exports.startup = function() {
|
|||||||
// Host-specific startup
|
// Host-specific startup
|
||||||
if($tw.browser) {
|
if($tw.browser) {
|
||||||
// Call browser startup modules
|
// Call browser startup modules
|
||||||
modules = $tw.modules.types["browser-startup"];
|
$tw.modules.forEachModuleOfType("browser-startup",function(title,module) {
|
||||||
if(modules) {
|
if(module.startup) {
|
||||||
for(m=0; m<modules.length; m++) {
|
module.startup();
|
||||||
modules[m].startup();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
// Install the popup manager
|
// Install the popup manager
|
||||||
$tw.popup = new $tw.utils.Popup({
|
$tw.popup = new $tw.utils.Popup({
|
||||||
wiki: $tw.wiki,
|
wiki: $tw.wiki,
|
||||||
@ -113,7 +112,6 @@ exports.startup = function() {
|
|||||||
{output: process.stdout, error: process.stderr}
|
{output: process.stdout, error: process.stderr}
|
||||||
);
|
);
|
||||||
commander.execute();
|
commander.execute();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -388,20 +388,17 @@ exports.initParsers = function(moduleType) {
|
|||||||
// Install the parser modules
|
// Install the parser modules
|
||||||
moduleType = moduleType || "parser";
|
moduleType = moduleType || "parser";
|
||||||
$tw.wiki.parsers = {};
|
$tw.wiki.parsers = {};
|
||||||
var modules = $tw.modules.types[moduleType],
|
var self = this;
|
||||||
n,m,f;
|
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
|
||||||
if(modules) {
|
for(var f in module) {
|
||||||
for(n=0; n<modules.length; n++) {
|
if($tw.utils.hop(module,f)) {
|
||||||
m = modules[n];
|
$tw.wiki.parsers[f] = new module[f]({wiki: self}); // Store an instance of the parser
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
// Install the rules for the old wikitext parser rules
|
// Install the rules for the old wikitext parser rules
|
||||||
var wikitextparser = this.parsers["text/x-tiddlywiki-old"];
|
var wikitextparser = this.parsers["text/x-tiddlywiki-old"];
|
||||||
if(modules && wikitextparser) {
|
if(wikitextparser) {
|
||||||
wikitextparser.installRules();
|
wikitextparser.installRules();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -503,8 +500,6 @@ exports.initMacros = function(moduleType) {
|
|||||||
moduleType = moduleType || "macro";
|
moduleType = moduleType || "macro";
|
||||||
$tw.wiki.macros = {};
|
$tw.wiki.macros = {};
|
||||||
var MacroClass = require("./treenodes/macro.js").Macro,
|
var MacroClass = require("./treenodes/macro.js").Macro,
|
||||||
modules = $tw.modules.types[moduleType],
|
|
||||||
n,m,f,
|
|
||||||
subclassMacro = function(module) {
|
subclassMacro = function(module) {
|
||||||
// Make a copy of the Macro() constructor function
|
// Make a copy of the Macro() constructor function
|
||||||
var MacroMaker = function Macro() {
|
var MacroMaker = function Macro() {
|
||||||
@ -514,17 +509,16 @@ exports.initMacros = function(moduleType) {
|
|||||||
MacroMaker.prototype = new MacroClass();
|
MacroMaker.prototype = new MacroClass();
|
||||||
// Add the prototype methods for this instance of the macro
|
// Add the prototype methods for this instance of the macro
|
||||||
for(var f in module) {
|
for(var f in module) {
|
||||||
|
if($tw.utils.hop(module,f)) {
|
||||||
MacroMaker.prototype[f] = module[f];
|
MacroMaker.prototype[f] = module[f];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Make a more convenient reference to the macro info
|
// Make a more convenient reference to the macro info
|
||||||
return MacroMaker;
|
return MacroMaker;
|
||||||
};
|
};
|
||||||
if(modules) {
|
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
|
||||||
for(n=0; n<modules.length; n++) {
|
$tw.wiki.macros[module.info.name] = subclassMacro(module);
|
||||||
m = modules[n];
|
});
|
||||||
$tw.wiki.macros[m.info.name] = subclassMacro(m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -582,12 +576,12 @@ exports.initSavers = function(moduleType) {
|
|||||||
moduleType = moduleType || "saver";
|
moduleType = moduleType || "saver";
|
||||||
// Instantiate the available savers
|
// Instantiate the available savers
|
||||||
this.savers = [];
|
this.savers = [];
|
||||||
for(var t=0; t<$tw.modules.types[moduleType].length; t++) {
|
var self = this;
|
||||||
var saver = $tw.modules.types[moduleType][t];
|
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
|
||||||
if(saver.canSave(this)) {
|
if(module.canSave(self)) {
|
||||||
this.savers.push(saver.create(this));
|
self.savers.push(module.create(self));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
// Sort the savers into priority order
|
// Sort the savers into priority order
|
||||||
this.savers.sort(function(a,b) {
|
this.savers.sort(function(a,b) {
|
||||||
if(a.info.priority < b.info.priority) {
|
if(a.info.priority < b.info.priority) {
|
||||||
|
@ -88,10 +88,9 @@ $tw.plugins.dropbox.login = function() {
|
|||||||
Invoke any dropbox-startup modules
|
Invoke any dropbox-startup modules
|
||||||
*/
|
*/
|
||||||
$tw.plugins.dropbox.invokeDropboxStartupModules = function(loggedIn) {
|
$tw.plugins.dropbox.invokeDropboxStartupModules = function(loggedIn) {
|
||||||
var mods = $tw.modules.types["dropbox-startup"];
|
$tw.modules.forEachModuleOfType("dropbox-startup",function(title,module) {
|
||||||
for(var m=0; m<mods.length; m++) {
|
module.startup(loggedIn);
|
||||||
mods[m].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…
x
Reference in New Issue
Block a user