Search code examples
node.jsexpressmarkdownjavascript-marked

returning rendered markdown with express and marked


So I am running a small test application to return the contents of a markdown file in html when a route is visited. I am using marked to render the markdown (https://github.com/chjj/marked).

Here us what I have so far -

app.get('/test', function(req, res) {
  var path = __dirname + '/markdown/test.md'
  var file = fs.readFile(path, 'utf8', function(err, data) {
    if(err) {
      console.log(err)
    }
    return data.toString()
  })
  res.send(marked(file))
})

When I navigate to localhost:3000 I'm getting -

TypeError: Cannot call method 'replace' of undefined Please report this to https://github.com/chij/marked.

I'm fairly certain I'm trying to send a string, and it res.send('Hello World!') works just fine. Sorry I'm new to both Node and express so I'm still figuring things out. Any help is much appreciated.


Solution

  • If you want to assign the data of the file to a variable, you should try the fs.readFileSync() method.

    Synchronous Solution

    app.get('/test', function(req, res) {
      var path = __dirname + '/markdown/test.md';
      var file = fs.readFileSync(path, 'utf8');
      res.send(marked(file.toString()));
    });
    

    Asynchronous Solution

    app.get('/test', function(req, res) {
      var path = __dirname + '/markdown/test.md';
      fs.readFile(path, 'utf8', function(err, data) {
        if(err) {
          console.log(err);
        }
        res.send(marked(data.toString()));
      });
    });
    

    Promisified Solution

    var Promise = require('bluebird'); // Require 'bluebird' in your package.json file, and run npm install.
    var fs = require('fs');
    var path = require('path');
    Promise.promisifyAll(fs);
    
    app.get('/test', function (req, res) {
      fs.readFileAsync(path.join(__dirname, '/markdown/test.md')).then(function(val) {
        res.send(marked(val.toString()));
      });
    });
    

    Because asynchronous programming will move on to the next step, running the previous one in a separate thread, accessing data assigned asynchronously outside of the callback function may result in a race condition. If you want to use it asynchronously, you can either handle the response within the asynchronous callback function, or convert it to a promise.

    Information on Promises:

    Asynchronous Programming in JavaScript with Promises

    Promise.js

    Bluebird (Another promise lib)