Parsing Other File Types

If we wanted to dynamically generate CSS (maybe for use in a theme builder of some sort) or JavaScript (perhaps cherry-picking pieces of a more comprehensive JS library), all we have to do is change the file type we’re reading in. Because we read in the files as strings, it makes no difference if they’re something Node could technically try to execute. Here again, Node’s lack of out-of-the-box handling for common file types works to our advantage. Any file can be an application, a library, a template, or a static resource—it’s entirely up to us and how we treat it.

Let’s say that we do indeed have a site offering some kind of customizable client-side widget library. For example, assume we have a customizable CSS file using Mustache to populate user-defined values:

h1 { color: #{{main}}; }
h2 { color: #{{secondary}}; } 
input { border-style: {{border}}; border-radius: {{corners}}px; }

To provide our end users with CSS and JavaScript matching their site’s needs, we only really need to change our routing. We’ll assume the values we’re receiving are coming from a form post, and that the rest of our application file remains the same:

connect(
  connect.static(__dirname + "/public"),
  connect.bodyParser(),
  connect.router(function(app) {
    app.post("/theme", function(req, res) {
      var theme = {
        main: req.body.mainColor,
        secondary: req.body.secondaryColor,
        border: req.body.borderStyle,
        corners: req.body.borderRadius
      };
      // load and render the CSS template
      requirejs(["text!public/css/theme.css"], function(tmpl) {
        var css = mustache.to_html(tmpl, theme);
        res.writeHead(200, {
          "Content-Type": "text/css",
          "Content-Length": css.length
        });
        res.end(css);
      });
    };
    app.post("/builder", function(req, res) {
      var options = {
        shim: req.body.html5shim,
        flash: req.body.useFlash,
        sockets: req.body.useWebSockets,
        jsonp: req.body.useJsonp
      };
      // load and render the JS template
      requirejs(["text!public/js/builder.js"], function(tmpl) {
        var js = mustache.to_html(tmpl, options);
        res.writeHead(200, {
          "Content-Type": "application/javascript",
          "Content-Length": js.length
        });
        res.end(js);
      });
    };
  })
).listen(8000);

Since we don’t want our CSS or JavaScript composed into our parent template, we can skip the render function and recreate its functionality for both MIME types we’ll want to return. You can probably see how the logic to render and return a response could be abstracted out into a function of its own, but since our example application only handles these two scenarios, the less efficient code above will get the job done.

Get Node for Front-End Developers now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.