Alpha G33k Alpha G33k - 4 months ago 14
Node.js Question

How use raw Javascript with Node

I have a code generator that I created, and I would like to have the ability to run it on the server. The generator uses pure native ECMA6 javascript to render HTML markup.

'use strict'
class JSML {

constructor(stdIn) {
this.output = '';
this.parse(stdIn);
return this.output;
}

generateAttributeKeyValueString(key, value) {
return `${key}='${value}'`;
}

camelCaseToDashes(str) {
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}

generateDom(vNode) {
var self = this,
selfClosingTagNames = ['area','base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'],
elmStart = `<${vNode.elm}`,
elmAttrs = '',
elmEnd,
elmContent,
inSelfClosingTagBool = false;

selfClosingTagNames.forEach(function(selfClosingTagName) {
if (vNode.elm === selfClosingTagName) {
inSelfClosingTagBool = true;
}
else elmEnd = `</${vNode.elm}>`;

});

function parseInput(vNode, key) {
if (!vNode.hasOwnProperty(key)) return;
var value = vNode[key],
// custom types conditons depending on the key and value of the nodes contents
isActualInnerValueChildContents = (key === 'inner' && typeof value === 'string'),
isChildrenContentArr = (key === 'inner' && Array.isArray(value)),
isSingleChildContent = (key === 'inner' && !isChildrenContentArr && (typeof value === 'object')),
isAttributeKeyValuePair = (key !== 'elm' && key !== 'inner');
if (isActualInnerValueChildContents) elmContent = value;
else if (isAttributeKeyValuePair) elmAttrs += self.generateAttributeKeyValueString(self.camelCaseToDashes(key), value); // Otherwise its an attribute and value pair and should be added to the node string
else if (isChildrenContentArr) {
//Array of multiple child nodes
elmContent = '';
value.forEach(function(subValue) {
elmContent += JSML.run(subValue).output;
});
}
else if (isSingleChildContent) elmContent = JSML.run(value).output;
}

for (var key in vNode) parseInput(vNode, key);

if (inSelfClosingTagBool) {
elmStart += ` ${elmAttrs}/>`;
inSelfClosingTagBool = false;
elmEnd = '';
}
else elmStart += ` ${elmAttrs}>`; // Close off the html elements start tag now that all possible attributes have been written
if (elmContent) this.output = elmStart + elmContent + elmEnd
else this.output = elmStart + elmEnd
}

parse(input) {
var self = this;
self.generateDom(input);
}

}
JSML.run = function(appCode, target) {
var defaultTarget = 'body',
dom = new JSML(appCode);
document.querySelectorAll(target || defaultTarget)[0].innerHTML = dom.output;
return dom;
}


I wish to leverage this on NodeJS, but without an entire rewrite if possible (I realize some fs code will be needed etc). I would like to use the script just as is with a filesystem wrapper around it, and an interface for sending the output to a browser directly to be rendered.

I have used Node with Express and some other frameworks, however there is always middleware involved. Is what I wish to do possible?

If so how?

I was able to get it a simple version of it running after further research using npm Simple HTTP server which reads the static HTML my script outputs by reading this thread: Using node.js as a simple web server, in conjunction with this thread Writing files in Node.js for writing the output of my script to the HTML file. However the main library wont run.

Here is the code I tried:

var fs = require('fs');



var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === 'function' && obj.constructor === Symbol ? 'symbol' : typeof obj;
};
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError('Cannot call a class as a function');
}
}
var JSML = function () {
'use strict';

function JSML(stdIn) {
_classCallCheck(this, JSML);
this.output = '';
this.parse(stdIn);
return this.output;
}
JSML.prototype.generateAttributeKeyValueString = function generateAttributeKeyValueString(key, value) {
return key + '=\'' + value + '\'';
};
JSML.prototype.camelCaseToDashes = function camelCaseToDashes(str) {
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
};
JSML.prototype.generateDom = function generateDom(vNode) {
var self = this, selfClosingTagNames = [
'area',
'base',
'br',
'col',
'command',
'embed',
'hr',
'img',
'input',
'keygen',
'link',
'meta',
'param',
'source',
'track',
'wbr'
], elmStart = '<' + vNode.elm, elmAttrs = '', elmEnd, elmContent;
selfClosingTagNames.forEach(function (selfClosingTagName) {
if (vNode.elm === selfClosingTagName)
elmEnd = '';
else
elmEnd = '</' + vNode.elm + '>';
});
function parseInput(vNode, key) {
if (!vNode.hasOwnProperty(key))
return;
var value = vNode[key], isActualInnerValueChildContents = key === 'inner' && typeof value === 'string', isChildrenContentArr = key === 'inner' && Array.isArray(value), isSingleChildContent = key === 'inner' && !isChildrenContentArr && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object', isAttributeKeyValuePair = key !== 'elm' && key !== 'inner';
if (isActualInnerValueChildContents)
elmContent = value;
else if (isAttributeKeyValuePair)
elmAttrs += self.generateAttributeKeyValueString(self.camelCaseToDashes(key), value);
else if (isChildrenContentArr) {
elmContent = '';
value.forEach(function (subValue) {
elmContent += JSML.run(subValue).output;
});
} else if (isSingleChildContent)
elmContent = JSML.run(value).output;
}
for (var key in vNode){
if (vNode.hasOwnProperty(key)) parseInput(vNode, key);
}

elmStart += ' ' + elmAttrs + '>';
if (elmContent)
this.output = elmStart + elmContent + elmEnd;
else
this.output = elmStart + elmEnd;
};
JSML.prototype.parse = function parse(input) {
var self = this;
self.generateDom(input);
};
return JSML;
}();
JSML.run = function (appCode, target) {
var defaultTarget = 'body', dom = new JSML(appCode);
document.getElementsByTagName(target || defaultTarget)[0].innerHTML = dom.output;
return dom;
};

fs.writeFile("index2.html", JSML.run({
elm: 'img',
src: 'http://placehold.it/50x50'
}, function(err) {
if(err) {
return console.log(err);
}

console.log("The file was saved!");
});


I keep getting "unexpected token ;" in generateView.js at like 98

The main idea is I need to run the JavaScript on my server, generate the markup needed to serve the content generated from my script to lets just say port 80.

Thank you, I am open to any helpful suggestions.

Answer

If I right understand, just put your code to js file, for example script.js. And run node script.js

Maybe yout have to wrap your class to module, this is good point where start learn https://nodejs.org/api/modules.html


Or if you want server, try Express js:

const express = require('express');
const app = express();

const JSML = express('./JSML'); // <--- your module
let jsml = newJSML();

app.get('/home', function(req, res){
  res.send(jsml.run());
});

app.listen(80);