Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ You may need to run this with `sudo`, or from within an Administrator command sh
## Usage

Usage:
node-red-nodegen <source file or URL> [-o <path to save>] [--prefix <prefix string>] [--name <node name>] [--module <module name>] [--version <version number> [--tgz] [--help]
node-red-nodegen <source file or URL> [-o <path to save>] [--prefix <prefix string>] [--name <node name>] [--module <module name>] [--version <version number>] [--conf <path to conf>] [--tgz] [--help]

Description:
Node generator for Node-RED

Supported source:
- Function node (js file in library, "~/.node-red/lib/function/")
- Template node (HTML file in library, "~/.node-red/lib/uitemplates/")
- Swagger definition

Options:
Expand All @@ -24,6 +25,7 @@ You may need to run this with `sudo`, or from within an Administrator command sh
--name : Node name (default: name defined in source)
--module : Module name (default: "node-red-contrib-<node name>")
--version : Node version (format: "number.number.number" like "4.5.1")
--conf : Path of configulation file
--tgz : Save node as tgz file
--help : Show help

Expand Down Expand Up @@ -51,3 +53,18 @@ You may need to run this with `sudo`, or from within an Administrator command sh
-> You can use swagger-petstore node on Node-RED flow editor.

Note: Currently node generator supports GET and POST methods using JSON format without authentication.

### Example 3. [experimental] Create original dashboard node from template widget definition (HTML code)

- On Node-RED flow editor, save template node to library with file name (hello.js).
- copy saved template to <path>/hello.html (change file extension from .js to .html)
- node-red-nodegen <path>/hello.html
(you can change template variables: template_scope, store_out_msgs, and fwd_in_msgs by specifying configuration file :--conf <conf file>; see samples/hello-conf.json)
- cd node-red-contrib-hello
- sudo npm link
- cd ~/.node-red
- npm link node-red-contrib-hello
- set environment variable `NR_DASHBOARD_DIR` to path of install directory of Node-RED dashboard.
- node-red

-> You can use hello dashboard node on Node-RED flow editor.
6 changes: 5 additions & 1 deletion bin/node-red-nodegen.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ function help() {
' [--prefix <prefix string>]' +
' [--name <node name>]' +
' [--module <module name>]' +
' [--conf <path of conf file>' +
' [--version <version number>' +
//' [--icon <png or gif file>' +
//' [--color <node color>' +
Expand Down Expand Up @@ -95,6 +96,10 @@ if (!argv.h && !argv.help) {
data.src = fs.readFileSync(sourcePath);
var filename = nodegen.function2node(data, options);
console.log('Success: ' + filename);
} else if (sourcePath.endsWith('.html')) {
data.src = fs.readFileSync(sourcePath);
var filename = nodegen.widget2node(data, options);
console.log('Success: ' + filename);
} else {
console.error('error: Unsupported file type');
}
Expand All @@ -104,4 +109,3 @@ if (!argv.h && !argv.help) {
} else {
help();
}

108 changes: 107 additions & 1 deletion lib/nodegen.js
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,114 @@ function swagger2node(data, options) {
}
}

function widget2node(data, options) {
// Read config
var conf = {};
if (options.conf) {
try {
conf = require(options.conf);
}
catch (e) {
console.error(e);
}
}
// Read meta data in html file
var meta = {};
var parts = new String(data.src).split('\n');
var new_src = "";
parts.forEach(function (part) {
var match = /^\/\/ (\w+): (.*)/.exec(part.toString());
if (match) {
if (match[1] === 'name') {
meta.name = match[2].replace(/([A-Z])/g, ' $1').toLowerCase().replace(/[^ a-z0-9]+/g, '').replace(/^ | $/, '').replace(/ +/g, '-');
} else {
meta[match[1]] = match[2];
}
}
else {
new_src = new_src +part +"\n";
}
});

if (!data.name || data.name === '') {
data.name = meta.name;
}

if (data.module) {
if (data.prefix) {
console.error('error: module name and prefix are conflicted.');
}
} else {
if (data.prefix) {
data.module = data.prefix + data.name;
} else {
data.module = 'node-red-contrib-' + data.name;
}
}

if (!data.version || data.version === '') {
data.version = '0.0.1';
}

if (data.name === 'function') {
console.error('\'function\' is duplicated node name. Use another name.');
} else {
var params = {
nodeName: data.name,
projectName: data.module,
projectVersion: data.version,
func: jsStringEscape(new_src),
outputs: meta.outputs,
template_scope: "local",
store_out_msgs: "true",
fwd_in_msgs: "true"
};
if (conf) {
for (var name in conf.vars) {
params[name] = conf.vars[name];
}
}

var basedir = __dirname + '/../templates/widget';

createCommonFiles(basedir, data);

// Create package.json
var packageTemplate = fs.readFileSync(basedir+'/package.json.mustache', 'utf-8');
var packageSourceCode = mustache.render(packageTemplate, params);
fs.writeFileSync(data.dst + '/' + data.module + '/package.json', packageSourceCode);

// Create node.js
var nodeTemplate = fs.readFileSync(basedir+'/node.js.mustache', 'utf-8');
var nodeSourceCode = mustache.render(nodeTemplate, params);
fs.writeFileSync(data.dst + '/' + data.module + '/node.js', nodeSourceCode);

// Create node.html
var htmlTemplate = fs.readFileSync(basedir+'/node.html.mustache', 'utf-8');
var htmlSourceCode = mustache.render(htmlTemplate, params);
fs.writeFileSync(data.dst + '/' + data.module + '/node.html', htmlSourceCode);

// Create README.md
var readmeTemplate = fs.readFileSync(basedir+'/README.md.mustache', 'utf-8');
var readmeSourceCode = mustache.render(readmeTemplate, params);
fs.writeFileSync(data.dst + '/' + data.module + '/README.md', readmeSourceCode);

// Create LICENSE file
var licenseTemplate = fs.readFileSync(basedir+'/LICENSE.mustache', 'utf-8');
var licenseSourceCode = mustache.render(licenseTemplate, params);
fs.writeFileSync(data.dst + '/' + data.module + '/LICENSE', licenseSourceCode);

if (options.tgz) {
runNpmPack(data);
return data.dst + '/' + data.module + '-' + data.version + '.tgz';
} else {
return data.dst + '/' + data.module;
}
}
}

module.exports = {
function2node: function2node,
widget2node: widget2node,
swagger2node: swagger2node
};

7 changes: 7 additions & 0 deletions samples/hello-conf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"vars" : {
"template_scope" : "local",
"store_out_msgs" : "true",
"fwd_in_msgs" : "true"
}
}
4 changes: 4 additions & 0 deletions samples/hello.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// name: hello
<div style="background-color:#84180F; color:#FFFFFF; border-radius:15px; font-size:20px;" align="center">
Hello Node-RED
</div>
Loading