mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-23 16:40:28 +00:00
Add --build
command
First pass at the build system described in #356. To test it, move to a new, empty directory and try `tiddlywiki editions/tw5.com --verbose --build`
This commit is contained in:
parent
552657fc58
commit
f7e50e0950
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
.DS_Store
|
||||
tmp/
|
||||
output/
|
||||
|
@ -1612,6 +1612,7 @@ $tw.boot.startup = function(options) {
|
||||
wikiThemesSubDir: "./themes",
|
||||
wikiLanguagesSubDir: "./languages",
|
||||
wikiTiddlersSubDir: "./tiddlers",
|
||||
wikiOutputSubDir: "./output",
|
||||
jsModuleHeaderRegExpString: "^\\/\\*\\\\(?:\\r?\\n)((?:^[^\\r\\n]*(?:\\r?\\n))+?)(^\\\\\\*\\/$(?:\\r?\\n)?)",
|
||||
fileExtensionInfo: Object.create(null), // Map file extension to {type:}
|
||||
contentTypeInfo: Object.create(null) // Map type to {encoding:,extension:}
|
||||
|
11
core/language/en-GB/Help/build.tid
Normal file
11
core/language/en-GB/Help/build.tid
Normal file
@ -0,0 +1,11 @@
|
||||
title: $:/language/Help/build
|
||||
description: Automatically run configured commands
|
||||
|
||||
Build the specified build targets for the current wiki. If no build targets are specified then all available targets will be built.
|
||||
|
||||
```
|
||||
--build <target> [<target> ...]
|
||||
```
|
||||
|
||||
Build targets are defined in the `tiddlywiki.info` file of a wiki folder.
|
||||
|
8
core/language/en-GB/Help/clearpassword.tid
Normal file
8
core/language/en-GB/Help/clearpassword.tid
Normal file
@ -0,0 +1,8 @@
|
||||
title: $:/language/Help/clearpassword
|
||||
description: Set a password for subsequent crypto operations
|
||||
|
||||
Clear the password for subsequent crypto operations
|
||||
|
||||
```
|
||||
--clearpassword
|
||||
```
|
10
core/language/en-GB/Help/output.tid
Normal file
10
core/language/en-GB/Help/output.tid
Normal file
@ -0,0 +1,10 @@
|
||||
title: $:/language/Help/output
|
||||
description: Set the base output directory for subsequent commands
|
||||
|
||||
Sets the base output directory for subsequent commands. The default output directory is the current working directory.
|
||||
|
||||
```
|
||||
--output <pathname>
|
||||
```
|
||||
|
||||
If the specified pathname is relative then it is resolved relative to the current output directory.
|
@ -6,3 +6,5 @@ Render an individual tiddler as a specified ContentType, defaults to `text/html`
|
||||
```
|
||||
--rendertiddler <title> <filename> [<type>]
|
||||
```
|
||||
|
||||
Any missing directories in the path to the filename are automatically created.
|
||||
|
@ -12,3 +12,5 @@ For example:
|
||||
```
|
||||
--rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html ./static text/plain
|
||||
```
|
||||
|
||||
Any files in the target directory are deleted. The target directory is recursively created if it is missing.
|
||||
|
@ -6,3 +6,5 @@ Saves an individual tiddler in its raw text or binary format to the specified fi
|
||||
```
|
||||
--savetiddler <title> <filename>
|
||||
```
|
||||
|
||||
Any missing directories in the path to the filename are automatically created.
|
||||
|
@ -20,11 +20,20 @@ Parse a sequence of commands
|
||||
callback: a callback invoked as callback(err) where err is null if there was no error
|
||||
*/
|
||||
var Commander = function(commandTokens,callback,wiki,streams) {
|
||||
var path = require("path");
|
||||
this.commandTokens = commandTokens;
|
||||
this.nextToken = 0;
|
||||
this.callback = callback;
|
||||
this.wiki = wiki;
|
||||
this.streams = streams;
|
||||
this.outputPath = process.cwd();
|
||||
};
|
||||
|
||||
/*
|
||||
Add a string of tokens to the command queue
|
||||
*/
|
||||
Commander.prototype.addCommandTokens = function(commandTokens) {
|
||||
Array.prototype.push.apply(this.commandTokens,commandTokens);
|
||||
};
|
||||
|
||||
/*
|
||||
|
52
core/modules/commands/build.js
Normal file
52
core/modules/commands/build.js
Normal file
@ -0,0 +1,52 @@
|
||||
/*\
|
||||
title: $:/core/modules/commands/build.js
|
||||
type: application/javascript
|
||||
module-type: command
|
||||
|
||||
Command to build a build target
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.info = {
|
||||
name: "build",
|
||||
synchronous: true
|
||||
};
|
||||
|
||||
var Command = function(params,commander) {
|
||||
this.params = params;
|
||||
this.commander = commander;
|
||||
};
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
// Get the build targets defined in the wiki
|
||||
var buildTargets = $tw.boot.wikiInfo.build;
|
||||
if(!buildTargets) {
|
||||
return "No build targets defined"
|
||||
}
|
||||
// Loop through each of the specified targets
|
||||
var targets;
|
||||
if(this.params.length > 0) {
|
||||
targets = this.params;
|
||||
} else {
|
||||
targets = Object.keys(buildTargets);
|
||||
}
|
||||
for(var targetIndex=0; targetIndex<targets.length; targetIndex++) {
|
||||
var target = targets[targetIndex],
|
||||
commands = buildTargets[target];
|
||||
if(!commands) {
|
||||
return "Build target '" + target + "' not found";
|
||||
}
|
||||
// Add the commands to the queue
|
||||
this.commander.addCommandTokens(commands);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
exports.Command = Command;
|
||||
|
||||
})();
|
33
core/modules/commands/clearpassword.js
Normal file
33
core/modules/commands/clearpassword.js
Normal file
@ -0,0 +1,33 @@
|
||||
/*\
|
||||
title: $:/core/modules/commands/clearpassword.js
|
||||
type: application/javascript
|
||||
module-type: command
|
||||
|
||||
Clear password for crypto operations
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.info = {
|
||||
name: "clearpassword",
|
||||
synchronous: true
|
||||
};
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
this.params = params;
|
||||
this.commander = commander;
|
||||
this.callback = callback;
|
||||
};
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
$tw.crypto.setPassword(null);
|
||||
return null;
|
||||
};
|
||||
|
||||
exports.Command = Command;
|
||||
|
||||
})();
|
38
core/modules/commands/output.js
Normal file
38
core/modules/commands/output.js
Normal file
@ -0,0 +1,38 @@
|
||||
/*\
|
||||
title: $:/core/modules/commands/output.js
|
||||
type: application/javascript
|
||||
module-type: command
|
||||
|
||||
Command to set the default output location (defaults to current working directory)
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.info = {
|
||||
name: "output",
|
||||
synchronous: true
|
||||
};
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
this.params = params;
|
||||
this.commander = commander;
|
||||
this.callback = callback;
|
||||
};
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
var fs = require("fs"),
|
||||
path = require("path");
|
||||
if(this.params.length < 1) {
|
||||
return "Missing output path";
|
||||
}
|
||||
this.commander.outputPath = path.resolve(this.commander.outputPath,this.params[0]);
|
||||
return null;
|
||||
};
|
||||
|
||||
exports.Command = Command;
|
||||
|
||||
})();
|
@ -31,8 +31,9 @@ Command.prototype.execute = function() {
|
||||
fs = require("fs"),
|
||||
path = require("path"),
|
||||
title = this.params[0],
|
||||
filename = this.params[1],
|
||||
filename = path.resolve(this.commander.outputPath,this.params[1]),
|
||||
type = this.params[2] || "text/html";
|
||||
$tw.utils.createFileDirectories(filename);
|
||||
fs.writeFile(filename,this.commander.wiki.renderTiddler(type,title),"utf8",function(err) {
|
||||
self.callback(err);
|
||||
});
|
||||
|
@ -35,10 +35,12 @@ Command.prototype.execute = function() {
|
||||
wiki = this.commander.wiki,
|
||||
filter = this.params[0],
|
||||
template = this.params[1],
|
||||
pathname = this.params[2],
|
||||
pathname = path.resolve(this.commander.outputPath,this.params[2]),
|
||||
type = this.params[3] || "text/html",
|
||||
extension = this.params[4] || ".html",
|
||||
tiddlers = wiki.filterTiddlers(filter);
|
||||
$tw.utils.deleteDirectory(pathname);
|
||||
$tw.utils.createDirectory(pathname);
|
||||
$tw.utils.each(tiddlers,function(title) {
|
||||
var parser = wiki.parseTiddler(template),
|
||||
widgetNode = wiki.makeWidget(parser,{variables: {currentTiddler: title}});
|
||||
|
@ -31,10 +31,11 @@ Command.prototype.execute = function() {
|
||||
fs = require("fs"),
|
||||
path = require("path"),
|
||||
title = this.params[0],
|
||||
filename = this.params[1],
|
||||
filename = path.resolve(this.commander.outputPath,this.params[1]),
|
||||
tiddler = this.commander.wiki.getTiddler(title),
|
||||
type = tiddler.fields.type || "text/vnd.tiddlywiki",
|
||||
contentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: "utf8"};
|
||||
$tw.utils.createFileDirectories(filename);
|
||||
fs.writeFile(filename,tiddler.fields.text,contentTypeInfo.encoding,function(err) {
|
||||
self.callback(err);
|
||||
});
|
||||
|
@ -87,9 +87,13 @@ exports.removeTrailingSeparator = function(dirPath) {
|
||||
Recursively create a directory
|
||||
*/
|
||||
exports.createDirectory = function(dirPath) {
|
||||
var parts = dirPath.split(path.sep);
|
||||
for(var component=0; component<parts.length; component++) {
|
||||
var subDirPath = parts.slice(0,component+1).join(path.sep);
|
||||
if(dirPath.substr(dirPath.length-1,1) !== path.sep) {
|
||||
dirPath = dirPath + path.sep;
|
||||
}
|
||||
var pos = 1;
|
||||
pos = dirPath.indexOf(path.sep,pos);
|
||||
while(pos !== -1) {
|
||||
var subDirPath = dirPath.substr(0,pos);
|
||||
if(!$tw.utils.isDirectory(subDirPath)) {
|
||||
try {
|
||||
fs.mkdirSync(subDirPath);
|
||||
@ -97,6 +101,33 @@ exports.createDirectory = function(dirPath) {
|
||||
return "Error creating directory '" + subDirPath + "'";
|
||||
}
|
||||
}
|
||||
pos = dirPath.indexOf(path.sep,pos + 1);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/*
|
||||
Recursively create directories needed to contain a specified file
|
||||
*/
|
||||
exports.createFileDirectories = function(filePath) {
|
||||
return $tw.utils.createDirectory(path.dirname(filePath));
|
||||
};
|
||||
|
||||
/*
|
||||
Recursively delete a directory
|
||||
*/
|
||||
exports.deleteDirectory = function(dirPath) {
|
||||
if(fs.existsSync(dirPath)) {
|
||||
var entries = fs.readdirSync(dirPath);
|
||||
for(var entryIndex=0; entryIndex<entries.length; entryIndex++) {
|
||||
var currPath = dirPath + path.sep + entries[entryIndex];
|
||||
if(fs.lstatSync(currPath).isDirectory()) {
|
||||
$tw.utils.deleteDirectory(currPath);
|
||||
} else {
|
||||
fs.unlinkSync(currPath);
|
||||
}
|
||||
}
|
||||
fs.rmdirSync(dirPath);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
7
editions/tw5.com/tiddlers/commands/BuildCommand.tid
Normal file
7
editions/tw5.com/tiddlers/commands/BuildCommand.tid
Normal file
@ -0,0 +1,7 @@
|
||||
created: 20140425085548209
|
||||
modified: 20140425085738745
|
||||
tags: command
|
||||
title: BuildCommand
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
{{$:/language/Help/build}}
|
@ -0,0 +1,4 @@
|
||||
title: ClearPasswordCommand
|
||||
tags: command
|
||||
|
||||
{{$:/language/Help/clearpassword}}
|
7
editions/tw5.com/tiddlers/commands/OutputCommand.tid
Normal file
7
editions/tw5.com/tiddlers/commands/OutputCommand.tid
Normal file
@ -0,0 +1,7 @@
|
||||
created: 20140425085548209
|
||||
modified: 20140425085738745
|
||||
tags: command
|
||||
title: OutputCommand
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
{{$:/language/Help/output}}
|
@ -24,6 +24,7 @@ The `tiddlywiki.info` file in a wiki folder contains a JSON object comprising th
|
||||
* ''themes'' - an array of theme names to be included in the wiki
|
||||
* ''languages'' - an array of language names to be included in the wiki
|
||||
* ''includeWikis'' - an array of relative paths to external wiki folders to be included in the wiki
|
||||
* ''build'' - a hashmap of named build targets, each defined by an array of command tokens (see BuildCommand)
|
||||
* ''config'' - an optional hashmap of configuration options (see below)
|
||||
|
||||
Configuration options include:
|
||||
@ -34,16 +35,23 @@ For example:
|
||||
|
||||
```
|
||||
{
|
||||
"plugins": [
|
||||
"tiddlywiki/tiddlyweb",
|
||||
"tiddlywiki/filesystem"
|
||||
],
|
||||
"includeWikis": [
|
||||
"../tw5.com"
|
||||
],
|
||||
"config": {
|
||||
"retain-original-tiddler-path": true
|
||||
}
|
||||
"plugins": [
|
||||
"tiddlywiki/tiddlyweb",
|
||||
"tiddlywiki/filesystem"
|
||||
],
|
||||
"includeWikis": [
|
||||
"../tw5.com"
|
||||
],
|
||||
"build": {
|
||||
"index": [
|
||||
"--rendertiddler","$:/core/save/all","index.html","text/plain"],
|
||||
"favicon": [
|
||||
"--savetiddler","$:/favicon.ico","favicon.ico",
|
||||
"--savetiddler","$:/green_favicon.ico","static/favicon.ico"]
|
||||
},
|
||||
"config": {
|
||||
"retain-original-tiddler-path": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -55,26 +63,26 @@ Sub-folders within the `tiddlers` folder can also be given a `tiddlywiki.files`
|
||||
|
||||
```
|
||||
{
|
||||
"tiddlers": [
|
||||
{
|
||||
"file": "d3.min.js",
|
||||
"fields": {
|
||||
"type": "application/javascript",
|
||||
"title": "$:/plugins/tiddlywiki/d3/d3.js",
|
||||
"module-type": "library"
|
||||
},
|
||||
"prefix": "var d3;if($tw.browser){\n",
|
||||
"suffix": "}\nexports.d3 = d3;\n"
|
||||
},
|
||||
{
|
||||
"file": "cloud/d3.layout.cloud.js",
|
||||
"fields": {
|
||||
"type": "application/javascript",
|
||||
"title": "$:/plugins/tiddlywiki/d3/d3.layout.cloud.js",
|
||||
"module-type": "library"
|
||||
}
|
||||
}
|
||||
]
|
||||
"tiddlers": [
|
||||
{
|
||||
"file": "d3.min.js",
|
||||
"fields": {
|
||||
"type": "application/javascript",
|
||||
"title": "$:/plugins/tiddlywiki/d3/d3.js",
|
||||
"module-type": "library"
|
||||
},
|
||||
"prefix": "var d3;if($tw.browser){\n",
|
||||
"suffix": "}\nexports.d3 = d3;\n"
|
||||
},
|
||||
{
|
||||
"file": "cloud/d3.layout.cloud.js",
|
||||
"fields": {
|
||||
"type": "application/javascript",
|
||||
"title": "$:/plugins/tiddlywiki/d3/d3.layout.cloud.js",
|
||||
"module-type": "library"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -26,8 +26,30 @@
|
||||
"zh-Hant",
|
||||
"it-IT",
|
||||
"ja-JP"
|
||||
]
|
||||
,
|
||||
],
|
||||
"build": {
|
||||
"index": [
|
||||
"--rendertiddler","$:/core/save/all","index.html","text/plain"],
|
||||
"encrypted": [
|
||||
"--password", "password",
|
||||
"--rendertiddler", "$:/core/save/all", "encrypted.html", "text/plain",
|
||||
"--clearpassword"],
|
||||
"favicon": [
|
||||
"--savetiddler","$:/favicon.ico","favicon.ico",
|
||||
"--savetiddler","$:/green_favicon.ico","static/favicon.ico"],
|
||||
"readmes": [
|
||||
"--rendertiddler","ReadMe","readme.md","text/html",
|
||||
"--rendertiddler","ContributingTemplate","contributing.md","text/html",
|
||||
"--rendertiddler","$:/core/copyright.txt","licenses/copyright.md","text/html"],
|
||||
"empty": [
|
||||
"--rendertiddler","$:/editions/tw5.com/download-empty","empty.html","text/plain",
|
||||
"--rendertiddler","$:/editions/tw5.com/download-empty","empty.hta","text/plain"],
|
||||
"static": [
|
||||
"--rendertiddler","$:/core/templates/static.template.html","static.html","text/plain",
|
||||
"--rendertiddler","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain",
|
||||
"--rendertiddler","$:/core/templates/static.template.css","static/static.css","text/plain",
|
||||
"--rendertiddlers","[!is[system]]","$:/core/templates/static.tiddler.html","static","text/plain"]
|
||||
},
|
||||
"config": {
|
||||
"retain-original-tiddler-path": true
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user