<commit_before>express = require("express")
nconf = require("nconf")
_ = require("underscore")._
validator = require("json-schema")
mime = require("mime")
url = require("url")
request = require("request")
path = require("path")



# Set defaults in nconf
require "./configure"


app = module.exports = express()
runUrl = nconf.get("url:run")

genid = (len = 16, prefix = "", keyspace = "<KEY>") ->
  prefix += keyspace.charAt(Math.floor(Math.random() * keyspace.length)) while len-- > 0
  prefix


app.use require("./middleware/cors").middleware()
app.use express.bodyParser()


LRU = require("lru-cache")
previews = LRU(512)
sourcemaps = LRU(512)

apiUrl = nconf.get("url:api")

coffee = require("coffee-script")
livescript = require("LiveScript")
iced = require("iced-coffee-script")
less = require("less")
sass = require("sass")
scss = require("node-sass")
jade = require("jade")
markdown = require("marked")
stylus = require("stylus")
nib = require("nib")

compilers = 
  scss:
    match: /\.css$/
    ext: ['scss']
    compile: (path, filename, source, str, fn) ->
      try
        scss.render(str, fn)
      catch err
        fn(err)

  sass:
    match: /\.css$/
    ext: ['sass']
    compile: (path, filename, source, str, fn) ->
      try
        fn(null, sass.render(str))
      catch err
        fn(err)

  less: 
    match: /\.css$/
    ext: ['less']
    compile: (path, filename, source, str, fn) ->
      try
        less.render(str, fn)
      catch err
        fn(err)

  stylus: 
    match: /\.css/
    ext: ['styl']
    compile: (path, filename, source, str, fn) ->
      try
        stylus(str)
          .use(nib())
          .import("nib")
          .render(fn)
      catch err
        fn(err)      
  coffeescript: 
    match: /\.js$/
    ext: ['coffee']
    compile: (path, filename, source, str, fn) ->
      try
        answer = coffee.compile str,
          bare: true
          returnObject: true
          sourceMap: true
          filename: "#{path}#{source}"
          
        js = answer.js + "\n//@ sourceMappingURL=#{path}#{filename}.map"
        smap = answer.v3SourceMap
        
        fn null, js, smap
      catch err
        fn(err)
      
  livescript: 
    match: /\.js$/
    ext: ['ls']
    compile: (path, filename, source, str, fn) ->
      try
        fn(null, livescript.compile(str))
      catch err
        fn(err)      
      
  icedcoffee: 
    match: /\.js$/
    ext: ['iced']
    compile: (path, filename, source, str, fn) ->
      try
        fn(null, iced.compile(str, runtime: "inline"))
      catch err
        fn(err)

  jade: 
    match: /\.html$/
    ext: ['jade']
    compile: (path, filename, source, str, fn) ->
      render = jade.compile(str, pretty: true)
      try
        fn(null, render({}))
      catch err
        fn(err)
      
  markdown: 
    match: /\.html$/
    ext: ['md',"markdown"]
    compile: (path, filename, source, str, fn) ->
      try
        fn(null, markdown(str))
      catch err
        fn(err)
  
  typescript: require("./compilers/typescript")

renderPlunkFile = (req, res, next) ->
  plunk = req.plunk
  filename = req.params[0] or "index.html"
  file = plunk.files[filename]
  
  res.set "Cache-Control", "no-cache"
  res.set "Expires", 0
  
  if file
    res.set("Content-Type": if req.accepts(file.mime) then file.mime else "text/plain")
    return res.send(200, file.content)
    
  else if sourcemap = sourcemaps.get("#{req.dir}#{filename}")
    res.set "Content-Type", "application/json"
    res.send 200, sourcemap
    
    console.log "[**] Served sourcemap", "#{req.dir}#{filename}"
    
  else
    render = (filename) ->
      base = path.basename(filename, path.extname(filename))
      type = mime.lookup(filename) or "text/plain"
      
      for name, compiler of compilers when filename.match(compiler.match)
        for ext in compiler.ext
          if found = plunk.files["#{base}.#{ext}"]
            compiler.compile req.dir, filename, found.filename, found.content, (err, compiled, sourcemap) ->
              if err
                console.log "[ERR] Compilation error:", err.message
                return res.send 500, err.message or "Compilation error"
              else
                if sourcemap
                  sourcemap_id = "#{req.dir}#{filename}.map"
                  sourcemaps.set sourcemap_id, sourcemap
                  
                  res.set "SourceMap", sourcemap_id
                  
                res.set "Content-Type", if req.accepts(type) then type else "text/plain"
                res.send 200, compiled
            return true
      
    for filename in ["index.html", "example.html", "demo.html", "readme.html"]
      return if render(filename)
    
    # Control will reach here if no file was found
    console.log "[ERR] No suitable source file for: ", filename
    res.send(404)

app.get "/plunks/:id/*", (req, res, next) ->
  req_url = url.parse(req.url)
  unless req.params[0] or /\/$/.test(req_url.pathname)
    req_url.pathname += "/"
    return res.redirect(301, url.format(req_url))
  
  req.dir = "/plunks/#{req.params.id}/"
  
  request.get "#{apiUrl}/plunks/#{req.params.id}?nv=1", (err, response, body) ->
    return res.send(500) if err
    return res.send(response.statusCode) if response.statusCode >= 400
    
    try
      req.plunk = JSON.parse(body)
    catch e
      return res.send(500)
    
    unless req.plunk then res.send(404) # TODO: Better error page
    else renderPlunkFile(req, res, next)<commit_msg>Fix regression introduced that prevented dynamic compilation for non-index files<commit_after>express = require("express")
nconf = require("nconf")
_ = require("underscore")._
validator = require("json-schema")
mime = require("mime")
url = require("url")
request = require("request")
path = require("path")



# Set defaults in nconf
require "./configure"


app = module.exports = express()
runUrl = nconf.get("url:run")

genid = (len = 16, prefix = "", keyspace = "<KEY>") ->
  prefix += keyspace.charAt(Math.floor(Math.random() * keyspace.length)) while len-- > 0
  prefix


app.use require("./middleware/cors").middleware()
app.use express.bodyParser()


LRU = require("lru-cache")
previews = LRU(512)
sourcemaps = LRU(512)

apiUrl = nconf.get("url:api")

coffee = require("coffee-script")
livescript = require("LiveScript")
iced = require("iced-coffee-script")
less = require("less")
sass = require("sass")
scss = require("node-sass")
jade = require("jade")
markdown = require("marked")
stylus = require("stylus")
nib = require("nib")

compilers = 
  scss:
    match: /\.css$/
    ext: ['scss']
    compile: (path, filename, source, str, fn) ->
      try
        scss.render(str, fn)
      catch err
        fn(err)

  sass:
    match: /\.css$/
    ext: ['sass']
    compile: (path, filename, source, str, fn) ->
      try
        fn(null, sass.render(str))
      catch err
        fn(err)

  less: 
    match: /\.css$/
    ext: ['less']
    compile: (path, filename, source, str, fn) ->
      try
        less.render(str, fn)
      catch err
        fn(err)

  stylus: 
    match: /\.css/
    ext: ['styl']
    compile: (path, filename, source, str, fn) ->
      try
        stylus(str)
          .use(nib())
          .import("nib")
          .render(fn)
      catch err
        fn(err)      
  coffeescript: 
    match: /\.js$/
    ext: ['coffee']
    compile: (path, filename, source, str, fn) ->
      try
        answer = coffee.compile str,
          bare: true
          returnObject: true
          sourceMap: true
          filename: "#{path}#{source}"
          
        js = answer.js + "\n//@ sourceMappingURL=#{path}#{filename}.map"
        smap = answer.v3SourceMap
        
        fn null, js, smap
      catch err
        fn(err)
      
  livescript: 
    match: /\.js$/
    ext: ['ls']
    compile: (path, filename, source, str, fn) ->
      try
        fn(null, livescript.compile(str))
      catch err
        fn(err)      
      
  icedcoffee: 
    match: /\.js$/
    ext: ['iced']
    compile: (path, filename, source, str, fn) ->
      try
        fn(null, iced.compile(str, runtime: "inline"))
      catch err
        fn(err)

  jade: 
    match: /\.html$/
    ext: ['jade']
    compile: (path, filename, source, str, fn) ->
      render = jade.compile(str, pretty: true)
      try
        fn(null, render({}))
      catch err
        fn(err)
      
  markdown: 
    match: /\.html$/
    ext: ['md',"markdown"]
    compile: (path, filename, source, str, fn) ->
      try
        fn(null, markdown(str))
      catch err
        fn(err)
  
  typescript: require("./compilers/typescript")

renderPlunkFile = (req, res, next) ->
  plunk = req.plunk
  filename = req.params[0] or "index.html"
  file = plunk.files[filename]
  
  res.set "Cache-Control", "no-cache"
  res.set "Expires", 0
  
  if file
    res.set("Content-Type": if req.accepts(file.mime) then file.mime else "text/plain")
    return res.send(200, file.content)
    
  else if sourcemap = sourcemaps.get("#{req.dir}#{filename}")
    res.set "Content-Type", "application/json"
    res.send 200, sourcemap
    
    console.log "[**] Served sourcemap", "#{req.dir}#{filename}"
    
  else
    render = (filename) ->
      base = path.basename(filename, path.extname(filename))
      type = mime.lookup(filename) or "text/plain"
      
      for name, compiler of compilers when filename.match(compiler.match)
        for ext in compiler.ext
          if found = plunk.files["#{base}.#{ext}"]
            compiler.compile req.dir, filename, found.filename, found.content, (err, compiled, sourcemap) ->
              if err
                console.log "[ERR] Compilation error:", err.message
                return res.send 500, err.message or "Compilation error"
              else
                if sourcemap
                  sourcemap_id = "#{req.dir}#{filename}.map"
                  sourcemaps.set sourcemap_id, sourcemap
                  
                  res.set "SourceMap", sourcemap_id
                  
                res.set "Content-Type", if req.accepts(type) then type else "text/plain"
                res.send 200, compiled
            return true
            
    test = [filename]
    test.push(file) for file in ["index.html", "example.html", "demo.html", "readme.html"] when 0 > test.indexOf(file)
      
    for filename in test
      return if render(filename)
    
    # Control will reach here if no file was found
    console.log "[ERR] No suitable source file for: ", filename
    res.send(404)

app.get "/plunks/:id/*", (req, res, next) ->
  req_url = url.parse(req.url)
  unless req.params[0] or /\/$/.test(req_url.pathname)
    req_url.pathname += "/"
    return res.redirect(301, url.format(req_url))
  
  req.dir = "/plunks/#{req.params.id}/"
  
  request.get "#{apiUrl}/plunks/#{req.params.id}?nv=1", (err, response, body) ->
    return res.send(500) if err
    return res.send(response.statusCode) if response.statusCode >= 400
    
    try
      req.plunk = JSON.parse(body)
    catch e
      return res.send(500)
    
    unless req.plunk then res.send(404) # TODO: Better error page
    else renderPlunkFile(req, res, next)
{'fraction_non_alphanumeric': 0.14896291640477688, 'fraction_numerical': 0.00799138008440334, 'mean_word_length': 2.220936957779063, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4458213', 'n_tokens_mistral': 3792, 'n_tokens_neox': 3620, 'n_words': 910}