-3

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.

Alpha G33k
  • 1,367
  • 1
  • 8
  • 19
  • What exactly is the problem? You want to run a node webserver, there is no end of tutorials out there. Have you looked? Have you tried something? You want to run the above code under node. What happens when you do? What error messages do you get? What have you done to try to resolve them? – Quentin Aug 02 '16 at 23:33
  • I have written several node applications, just as stated using expressjs and other middleware... they all use Jade and EJS. I want to use raw javascript ES6. I am building my own middleware, I need to know how to serve what is generated by it. Here is the link to my repo https://github.com/nicholasmabrams/JSML . It is what generates the code. It works great on the clientside however I need to make it run on node so I can have the choice of rendering on the server or client with it. – Alpha G33k Aug 02 '16 at 23:39
  • your attempted code has more than one error - line 4, col 1, Expected an assignment or function call and instead saw an expression. line 5, col 70, Invalid typeof value 'symbol' line 49, col 28, Expected an assignment or function call and instead saw an expression. line 98, col 3, Expected ')' and instead saw ';'. line 98, col 4, Missing semicolon. – Jaromanda X Aug 03 '16 at 00:18
  • the main issue is a missing `)` before the last semi colon ... the other issues are things like using `===` where it looks like you should use `=`, and some are not errors, just jshint being stupid – Jaromanda X Aug 03 '16 at 00:22
  • Sorry yes I did correct all JS hint errors but it still complaining :( thanks for the help – Alpha G33k Aug 03 '16 at 00:24
  • what is still complaining about what? – Jaromanda X Aug 03 '16 at 00:25
  • I see - you're expecting a DOM - nodejs doesn't have one of those – Jaromanda X Aug 03 '16 at 00:27
  • Where am I expecting DOM? No the variable is meant to say its the final out put and what the DOM will be. Bad naming No real DOM methods should be used in there – Alpha G33k Aug 03 '16 at 00:28
  • you are expecting a DOM at line 84 - `document.getElementByTagName` – Jaromanda X Aug 03 '16 at 00:30
  • 1
    if I were you, I'd return `dom.output` from `JSML.run` – Jaromanda X Aug 03 '16 at 00:31

1 Answers1

0

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);
Stan Kondrat
  • 147
  • 1
  • 7