How do I insert a newline in Node.js when using Heroku? - node.js

I'm trying to create a Node.js application on Heroku that will output 10 different ASCII faces (I already have the module needed for that). Using the Node tutorial on Heroku, I've set it up to output 10 faces. However, when I try to actually run the code, it puts all of the faces inline with each other. How should I try to make it so that the faces are outputted (if that's even a word) on their own lines?
My current index.js is as follows:
var express = require('express');
var app = express();
var cool = require('cool-ascii-faces');
app.set('port', (process.env.PORT || 5000));
app.get('/', function(request, response) {
var result = ''
var times = process.env.TIMES || 5
for (i=0; i < times; i++)
result += cool();
response.send(result);
});
app.listen(app.get('port'), function() {
console.log("Node app is running on port: " + app.get('port'))
})
I have a .env file already set up for Foreman to use (when testing locally) that contains the following:
TIMES=9
If you want to have a look at the output, head on over here.
TL;DR: How do I use newlines in Node?

I visited the site in question and did a View -> Source. There's no markup of any kind like HTML, BODY, etc. I assume that the browser then would interpret the output as HTML. This ought to work since we're using an HTML tag and a pair of PRE tags to indicate that if we see a hard return ('\n') then the browser should display it.
app.get('/', function(request, response) {
var result = '<html><pre>';
var times = process.env.TIMES || 5
for (i=0; i < times; i++)
result += cool() + '\n';
result += '</pre></html>';
response.send(result);
});

By default, the browser assumes that web servers send HTML.
HTML ignores newlines.
If you aren't sending HTML, you need to specify that by setting a different type:
response.header("Content-Type", "text/plain");
To actually send a newline, just concatenate '\n' to your string.

Related

JSX not Working in NodeJS

Here is my code i am facing issue in my get function where i write my code in forEach loop it gave an error of quotation(Unterminated String Literal).
var express = require('express');
var app = express();
var dataFile = require('./data/friend.json');
app.set('port', process.env.PORT || 5000);
app.get("/" , function(req , res ){
var data = '';
dataFile.friends.forEach(function(item){
data +='
<div>
<li>
<h1>${item.name}</h1>
<h2>${item.Class}</h2>
</li>
</div>';
});
res.send("Welcome");
});
app.listen(app.get('port') , function (err){
console.log("Server is running at "+ app.get('port'));
});
You can not have line breaks in JavaScript strings without concatenating or "escaping" them, unless using template literals (using the back-tick).
There are three ways to go about doing this.
Concatenation:
dataFile.friends.forEach(function(item){
data +='<div>'+
'<li>' +
'<h1>${item.name}</h1>' +
'<h2>${item.Class}</h2>' +
'</li>' +
'</div>';
});
Escaping Line Breaks:
dataFile.friends.forEach(function(item){
data +='<div>\
<li>\
<h1>${item.name}</h1>\
<h2>${item.Class}</h2>\
</li>\
</div>';
});
Template Literals:
dataFile.friends.forEach(function(item){
data +=`<div>
<li>
<h1>${item.name}</h1>
<h2>${item.Class}</h2>
</li>
</div>`;
});
Reference: SyntaxError: unterminated string literal
** It is also important to note that creating a string of elements may not instantiate them in to the DOM correctly. This will cause JavaScript to be unable to interact with these elements. DigitalOcean has a tutorial on this.
Alternatively, you can make use of template literals as mentioned above and available in the above reference link, this will instantiate elements inside the DOM.

Node Express Server Get not getting the first '?' in a query

I am trying to make a get call to my node server using the following parameters
http://localhost:8080/products/?a=13214?b=awedf
I am getting the error: Cannot GET /products/?a=13214?b=awedf
When I remove the '?' before the letter 'a', I get the following query:
{ b: 'awedf' }
I want to be able to add the '?' and get the following query or something similar that gives me the following array:
{ a:13214, b: 'awedf' }
Here is the code I have:
var express = require('express'),
app = express();
var timeout = 0;
app.use(express.static(__dirname, '/'));
app.get('/products/:siteId', function(req, res) {
console.log(req.query);
res.json(products);
});
app.listen(8080);
console.log('Express listening on http://localhost:8080/');
var products = [
{"Product":"Product A"}
,{"Product":"Product B"}
];
EDIT:
I fixed it by changing the query parameters:
http://localhost:8080/product?a=13214&b=awedf
Instead of second ? add &. Parameters are separated with ampersand. Question mark indicates the beginning of query string
Also you don't need :siteId in the path. If you want to use :siteId, then your url would look like /products/1234?b=abc
req.params.siteId === 1234 and req.query.b === 'abc'
So you should replace the ? before b with & like this: http://localhost:8080/products/?a=13214&b=awedf
EDIT: Since you cannot modify the parameters and you already have /:siteId then you should be able to access the value for a like this: req.params.siteId.

I want to pipe a readable css file to the http response

I have an issue with outputting the readable stream to the http response.
behind the scenes there is a regular request and response streams coming from the generic http createServer. I check to see if the 'req.url' ends in css, and I create a readable stream of this file. I see the css contents in the console.log, with the right css code I expect. Then, I try to pipe the readable css file stream to the response, but in Chrome, the file response is blank when I inspect the response. It is a 200 response though. Any thoughts at first glance? I've tried different variations of where I have code commented out.
router.addRoute("[a-aA-z0-9]{1,50}.css$", function(matches){
var cssFile = matches[0];
var pathToCss = process.cwd() + "/" + cssFile;
// takes care of os diffs regarding path delimiters and such
pathToCss = path.normalize(pathToCss);
console.log(matches);
console.log("PATH TO CSS");
console.log(pathToCss)
var readable = fs.createReadStream(pathToCss);
var write = function(chunk){
this.queue(chunk.toString());
console.log(chunk.toString());
}
var end = function(){
this.queue(null);
}
var thru = through(write,end);
//req.on("end",function(){
res.pipe(readable.pipe(thru)).pipe(res);
//res.end();
//});
});
you need to pipe your readable stream into your through-stream, and then pipe it into the response:
readable.pipe(thru).pipe(res);
edit: for preparing your css path, just use path.join instead of concatenating your path and normalizing it:
var pathToCss = path.join(process.cwd(), cssFile);
I separated out this route (css) from my normal html producing routes, the problem I had was that my normal routes in my router object returned strings, like res.end(compiled_html_str), and the css file readable stream was going through that same routing function. I made it separate by isolating it from my router.
var cssMatch = [];
if(cssMatch = req.url.match(/.+\/(.+\.css$)/)){
res.writeHead({"Content-Type":"text/css"});
var cssFile = cssMatch[1];
var pathToCss = process.cwd() + "/" + cssFile;
// takes care of os diffs regarding path delimiters and such
pathToCss = path.normalize(pathToCss);
console.log(cssMatch);
console.log("PATH TO CSS");
console.log(pathToCss)
var readable = fs.createReadStream(pathToCss);
var cssStr = "";
readable.on("data",function(chunk){
cssStr += chunk.toString();
});
readable.on("end",function(){
res.end(cssStr);
});
}

Nodejs Backbone Templates

I have worked a lot with rails, requirejs and backbone and know how to use haml coffee templates in rails.
App = new Backbone.Marionette.Application()
App.addInitializer (options) ->
Backbone.history.start()
alert "yay"
$ ->
alert "yay"
App.start()
How do i do it in Node.js, I have a Node.js app and i am at a deadend with regards to how do i get a template to compile client side, i am not stuck on haml coffee, any template engine will do, jade is fine too, underscore too. Just a good starting point so that i can get on with building the backbone app in node.js.
Any Help is appreciated!
I don't suggest dragging the templates to the client and compiling them there,the right way would be to use some framework such as www.socketstream.com that offers what you want and much more. If you're against frameworks quick and dirty solution to compiling them on the server and calling them as function on the client will be :
// compile.js
var fs = require("fs")
,jade = require("jade");
exports.build = function(templatesDir) {
var js = "var Templates = {}; \n\n";
var files = fs.readdirSync(templatesDir);
var jadeFiles = files.filter(function(file) {
return file.substr(-5) === ".jade";
});
for(var i = 0; i < jadeFiles.length; ++i){
var filePath, key;
var file = jadeFiles[i];
key = file.substr(0, file.indexOf("."));
filePath = templatesDir + file;
var jadeSource = fs.readFileSync(filePath);
js += "Templates." + key + " = " + jade.compile(jadeSource, {
debug: false,
client: true
}).toString() + "; \n\n";
}
return js;
};
// On the server.js
// Compile views
var viewsPath = path.join(__dirname, 'views/');
var generatedJs = require('./compile').build(viewsPath);
var savePath = path.join(__dirname, 'public/js/lib/templates.js');
fs.writeFile(savePath, generatedJs, function (err) {
if (err) throw err;
});
// Then on the client include js/lib/templates.js and use templates like this
FactSummaryView = Backbone.View.extend({
template: Templates.issueSummary,
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
// Also add templates.js to nodemonignore if you're using nodemon
./public/js/lib/templates.js
/public/js/lib/templates.js
You usually don't compile the templates on the client (expect the templates are edited directly in the browser), instead they are compiled in the backend and rendered in the browser.
Compile the templates
In this step you compile the template source code to a JavaScript file that contains a render function.
You can either use haml-coffee on the command line and make a script in your build process or make use of the projects listed in the integration section of the Haml-Coffee README.
Grunt is a popular solution to run certain tasks and with Grunt-Haml you have certainly a flexible build solution for your project.
Render the templates
To render the templates with Marionette you need to make sure the template render function is available on the client. Just type the configured namespace into the developer tools to see if the template functions are registered:
If this is fine, you need to have a custom template render function:
Backbone.Marionette.Renderer.render = (template, data) ->
if JST[template]
JST[template](data)
else if _.isFunction(template)
template(data)
else
console.error 'Template %s not found', template
Now you can simply define the view template and it'll be rendered properly:
class App.Views.Login extends Backbone.Marionette.ItemView
template: 'shared/_login'

Blank output with mustache template, connect & node.js

I'm just getting into this whole node.js business and like it so far; however I've run into an issue involving connect/mustach.
Here's the code for a simple one page app; at this point I'm really just trying to get the app to use my mustache templates so that I can take it from there.
var connect = require("connect"),
fs = require("fs"),
mustache = require("mustache");
connect(
connect.static(__dirname + '/public'),
connect.bodyParser(),
function(req, res){
var data = {
variable: 'Some text that I'd like to see printed out. Should in the long run come from DB.'
},
htmlFile = fs.createReadStream(
__dirname + "/views/index.html",
{ encoding: "utf8" }
),
template = "",
html;
htmlFile.on("data", function(data){
template += data;
});
htmlFile.on("end", function(){
html = mustache.to_html(template, data);
})
res.end(html);
}
).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
My problem here is that the above code generates a blank webpage.
If I log the html-variable I get two outputs of the html with the variable text attached in it, so the to_html-function seems to do it's job. And if I do res.end('some string'); the string is displayed in the browser as it should.
The template is a plain old .html-file with a <p>{{variable}}</p>-tag in its body.
Any idea what's wrong?
Your problem is that you're not using async code correctly. By the time res.end(html) gets called the file is not yet read. Correct usage:
htmlFile.on("end", function(){
html = mustache.to_html(template, data);
res.end(html);
})
Also you should take care of the syntax error: variable: 'Some text that I'd like to see printed out. Should in the long run come from DB.'
(misuse of ')

Resources