<commit_before>$(document).ready(function() {
  var updateDag = function(data, cache) {
        var cacheStatus, cacheContents;

        var present = data.present || false;
        var contents = data.dot_content || [];

        if (cache !== undefined) {
            cacheStatus = cache.status || false;
            cacheContents = cache.dot_content || [];
        }

        if ((present === cacheStatus) && (contents.length === cacheContents.length)) {
            return;
        }

        $(".dag").empty();

        if (!present) {
            $(".dag").append("
No graph data.
")
            return;
        }

        var stringContents = contents.map(function(e) {
            return String.fromCharCode(e);
        }).join("");
        $(".dag").append(Viz(stringContents));
  };

  $.get("/api/dag", function(data) {
      updateDag(data, undefined);
      setInterval(function(cache) {
          $.get("/api/dag", function(data) {
              updateDag(data, cache)
          });
        }, 10000, data);
  });

  $("#logo").fadeOut("slow", function() {

    $("#header").fadeIn();
    $("#controls").fadeIn();
    $("#graph").fadeIn();

    var width = 1024,
        height = 768;

    var color = d3.scale.category10();

    var nodes = [],
        links = [];

    var force = d3.layout.force()
        .nodes(nodes)
        .links(links)
        .charge(-400)
        .linkDistance(120)
        .size([width, height])
        .on("tick", tick);

    var svg = d3.select("#topology").append("svg")
        .attr("width", width)
        .attr("height", height);

    var node = svg.selectAll(".node"),
        link = svg.selectAll(".link");

    var update = function(response) {

        // Add any missing nodes.
        $.each(response.nodes, function(key, value) {
            var result = findNode(nodes, value.id);
            if (result == undefined) {
                nodes.push(value);
            }
        });

        // Remove deleted nodes.
        $.each(nodes, function(key, value) {
            // Prevent from splice during iteration by ignoring
            // undefined values.
            if(value != undefined) {
                var result = findNodeIndex(response.nodes, value.id);
                if (result == undefined) {
                    nodes.splice(key, 1);
                }
            }
        });

        // Add any missing links.
        $.each(response.links, function(key, value) {
            var result = findLink(links, value.source, value.target);
            var sourceNode = findNode(nodes, value.source);
            var targetNode = findNode(nodes, value.target);
            if (result == undefined) {
                links.push({source: sourceNode, target: targetNode});
            }
        });

        // Remove deleted links.
        for(var i = links.length; i--;){
            // Prevent from splice during iteration by ignoring
            // undefined values.
            if(links[i] != undefined) {
                if(typeof links[i].source === 'object') {
                    var result = findLinkIndex(response.links, links[i].source.id, links[i].target.id);
                } else {
                    var result = findLinkIndex(response.links, links[i].source, links[i].target);
                }
                if (result == undefined) {
                    links.splice(i, 1);
                }
            }
        }

        start();
    };

    // Invoke immediately and schedule refreshes.
    $.get("/api/status", function(response) {
        update(response);

        setInterval(function() {
            $.get("/api/status", function(response) {
                update(response);
            });
        }, 2000);
    });

    function start() {
      link = link.data(force.links(), function(d) { return d.source.id + "-" + d.target.id; });
      link.enter().insert("line", ".node").attr("class", "link");
      link.exit().remove();

      node = node.data(force.nodes(), function(d) { return d.id;});
      node.enter().append("circle").attr("class", function(d) { return "node " + d.id; }).attr("r", 8).style("fill", function(d) { return color(d.group); })

      node.append("text")
          .attr("dx", 12)
          .attr("dy", ".35em")
          .text(function(d) { return d.name });

      node.exit().remove();

      force.start();
    }

    function tick() {
      node.attr("cx", function(d) { return d.x; })
          .attr("cy", function(d) { return d.y; })

      link.attr("x1", function(d) { return d.source.x; })
          .attr("y1", function(d) { return d.source.y; })
          .attr("x2", function(d) { return d.target.x; })
          .attr("y2", function(d) { return d.target.y; });
    }

    // Taken from: http://stackoverflow.com/questions/9539294/adding-new-nodes-to-force-directed-layout
    var findNode = function (nodes, id) {
        for (var i=0; i < nodes.length; i++) {
            if (nodes[i].id === id)
                return nodes[i]
        };
    }

    var findLink = function (links, source, target) {
        for (var i=0; i < links.length; i++) {
            if (links[i].source.id === source && links[i].target.id === target)
                return links[i]
        };
    }

    // Taken from: http://stackoverflow.com/questions/9539294/adding-new-nodes-to-force-directed-layout
    var findNodeIndex = function (nodes, id) {
        for (var i=0; i < nodes.length; i++) {
            if (nodes[i].id === id)
                return i
        };
    }

    var findLinkIndex = function (links, source, target) {
        for (var i=0; i < links.length; i++) {
            if (links[i].source === source && links[i].target === target)
                return i
        };
    }

  });
});
<commit_msg>Alter d3.<commit_after>$(document).ready(function() {
  var updateDag = function(data, cache) {
        var cacheStatus, cacheContents;

        var present = data.present || false;
        var contents = data.dot_content || [];

        if (cache !== undefined) {
            cacheStatus = cache.status || false;
            cacheContents = cache.dot_content || [];
        }

        if ((present === cacheStatus) && (contents.length === cacheContents.length)) {
            return;
        }

        $(".dag").empty();

        if (!present) {
            $(".dag").append("
No graph data.
")
            return;
        }

        var stringContents = contents.map(function(e) {
            return String.fromCharCode(e);
        }).join("");
        $(".dag").append(Viz(stringContents));
  };

  $.get("/api/dag", function(data) {
      updateDag(data, undefined);
      setInterval(function(cache) {
          $.get("/api/dag", function(data) {
              updateDag(data, cache)
          });
        }, 10000, data);
  });

  $("#logo").fadeOut("slow", function() {

    $("#header").fadeIn();
    $("#controls").fadeIn();
    $("#graph").fadeIn();

    var width = 1024,
        height = 768;

    var color = d3.scale.category10();

    var nodes = [],
        links = [];

    var force = d3.layout.force()
        .nodes(nodes)
        .links(links)
        .charge(-400)
        .linkDistance(120)
        .size([width, height])
        .on("tick", tick);

    var svg = d3.select("#topology").append("svg")
        .attr("width", width)
        .attr("height", height);

    var node = svg.selectAll(".node"),
        link = svg.selectAll(".link");

    var update = function(response) {

        // Add any missing nodes.
        $.each(response.nodes, function(key, value) {
            var result = findNode(nodes, value.id);
            if (result == undefined) {
                nodes.push(value);
            }
        });

        // Remove deleted nodes.
        $.each(nodes, function(key, value) {
            // Prevent from splice during iteration by ignoring
            // undefined values.
            if(value != undefined) {
                var result = findNodeIndex(response.nodes, value.id);
                if (result == undefined) {
                    nodes.splice(key, 1);
                }
            }
        });

        // Add any missing links.
        $.each(response.links, function(key, value) {
            var result = findLink(links, value.source, value.target);
            var sourceNode = findNode(nodes, value.source);
            var targetNode = findNode(nodes, value.target);
            if (result == undefined) {
                links.push({source: sourceNode, target: targetNode});
            }
        });

        // Remove deleted links.
        for(var i = links.length; i--;){
            // Prevent from splice during iteration by ignoring
            // undefined values.
            if(links[i] != undefined) {
                if(typeof links[i].source === 'object') {
                    var result = findLinkIndex(response.links, links[i].source.id, links[i].target.id);
                } else {
                    var result = findLinkIndex(response.links, links[i].source, links[i].target);
                }
                if (result == undefined) {
                    links.splice(i, 1);
                }
            }
        }

        start();
    };

    // Invoke immediately and schedule refreshes.
    $.get("/api/status", function(response) {
        update(response);

        setInterval(function() {
            $.get("/api/status", function(response) {
                update(response);
            });
        }, 2000);
    });

    function start() {
      link = link.data(force.links(), function(d) { return d.source.id + "-" + d.target.id; });
      link.enter().insert("line", ".node").attr("class", "link");
      link.exit().remove();

      node = node.data(force.nodes(), function(d) { return d.id;});
      node.enter().append("circle")
                    .attr("class", function(d) { return "node " + d.id; })
                    .attr("r", 8)
                    .style("fill", function(d) { return color(d.group); })
                  .append("text")
                    .attr("dx", 12)
                    .attr("dy", ".35em")
                    .text(function(d) { return d.name });

      node.exit().remove();

      force.start();
    }

    function tick() {
      node.attr("cx", function(d) { return d.x; })
          .attr("cy", function(d) { return d.y; })

      link.attr("x1", function(d) { return d.source.x; })
          .attr("y1", function(d) { return d.source.y; })
          .attr("x2", function(d) { return d.target.x; })
          .attr("y2", function(d) { return d.target.y; });
    }

    // Taken from: http://stackoverflow.com/questions/9539294/adding-new-nodes-to-force-directed-layout
    var findNode = function (nodes, id) {
        for (var i=0; i < nodes.length; i++) {
            if (nodes[i].id === id)
                return nodes[i]
        };
    }

    var findLink = function (links, source, target) {
        for (var i=0; i < links.length; i++) {
            if (links[i].source.id === source && links[i].target.id === target)
                return links[i]
        };
    }

    // Taken from: http://stackoverflow.com/questions/9539294/adding-new-nodes-to-force-directed-layout
    var findNodeIndex = function (nodes, id) {
        for (var i=0; i < nodes.length; i++) {
            if (nodes[i].id === id)
                return i
        };
    }

    var findLinkIndex = function (links, source, target) {
        for (var i=0; i < links.length; i++) {
            if (links[i].source === source && links[i].target === target)
                return i
        };
    }

  });
});
<|endoftext|>


<commit_before>var fs = require('fs-extra');
var helper = require('helper');
var join = require('path').join;
var blog_dir = join(helper.rootDir, 'blogs');
var load_db = require('../db/load');
var dumps = join(__dirname, 'dumps');
var config = require('config');
var access = require('../access');
var BLOG_ID = "1";
var DROPBOX_FOLDER_PATH = "/Users/David/Dropbox/Apps/Blot test";

if (require.main === module) {

  var identifier = process.argv[2];

  if (!identifier) return print_available();

  main(identifier, function(err){

    if (err) throw err;

    access('dev', function(){

      process.exit();

    });
  });
}

function main (label, callback) {

  fs.emptyDir(blog_dir, function(err){

    if (err) return callback(err);

    load_db(label, function(err){

      if (err) return callback(err);

      fs.copy(join(dumps, label), blog_dir, function(err) {

        if (err) return callback(err);

        fs.emptyDir(config.cache_directory, function(err){

          if (err) return callback(err);

          fs.emptyDir(DROPBOX_FOLDER_PATH, function(err){

            if (err) return callback(err);

            fs.copy(join(blog_dir, BLOG_ID), DROPBOX_FOLDER_PATH, function(err){

              if (err) return callback(err);

              callback();
            });
          });
        });
      });
    });
  });

}

function load_dir (dir) {

  return fs.readdirSync(dir).filter(function(e){

    return fs.statSync(dir + '/' + e).isDirectory();
  });
}

function print_available () {

  var all_dumps = load_dir(dumps);

  console.log('Please choose one of the available folders:');

  console.log();

  for (var i in all_dumps) {
    console.log('',all_dumps[i]);
  }

  console.log('');
}

// save the contents of the blogs folder to /dumps

// save the state of the database

<commit_msg>Reset git directory on folder load<commit_after>var fs = require("fs-extra");
var helper = require("helper");
var join = require("path").join;
var blog_dir = join(helper.rootDir, "blogs");
var git_data_dir = join(helper.rootDir, "app", "clients", "git", "data");
var load_db = require("../db/load");
var dumps = join(__dirname, "dumps");
var config = require("config");
var access = require("../access");
var BLOG_ID = "1";
var DROPBOX_FOLDER_PATH = "/Users/David/Dropbox/Apps/Blot test";

if (require.main === module) {
  var identifier = process.argv[2];

  if (!identifier) return print_available();

  main(identifier, function(err) {
    if (err) throw err;

    access("dev", function() {
      process.exit();
    });
  });
}

function main(label, callback) {
  fs.emptyDir(blog_dir, function(err) {
    if (err) return callback(err);

    load_db(label, function(err) {
      if (err) return callback(err);

      fs.copy(join(dumps, label), blog_dir, function(err) {
        if (err) return callback(err);

        fs.emptyDirSync(git_data_dir);

        fs.emptyDir(config.cache_directory, function(err) {
          if (err) return callback(err);

          fs.emptyDir(DROPBOX_FOLDER_PATH, function(err) {
            if (err) return callback(err);

            fs.copy(join(blog_dir, BLOG_ID), DROPBOX_FOLDER_PATH, function(
              err
            ) {
              if (err) return callback(err);

              callback();
            });
          });
        });
      });
    });
  });
}

function load_dir(dir) {
  return fs.readdirSync(dir).filter(function(e) {
    return fs.statSync(dir + "/" + e).isDirectory();
  });
}

function print_available() {
  var all_dumps = load_dir(dumps);

  console.log("Please choose one of the available folders:");

  console.log();

  for (var i in all_dumps) {
    console.log("", all_dumps[i]);
  }

  console.log("");
}

// save the contents of the blogs folder to /dumps

// save the state of the database
<|endoftext|>


<commit_before>/**
 * @usage
 *
 * gulp.src('app.js', {read: false})
 *     .pipe(rollup(options))
 *     .pipe(gulp.dest('dist'));
 */

import through from 'through2';
import gulpUtils from 'gulp-util';
import fs from 'fs';
import path from 'path';
import rollup from 'rollup';

const PLUGIN_NAME = 'gulp-rollup';

function unixStylePath (filePath) {
  return filePath.split(path.sep).join('/');
}

function gulpRollup (_options_) {
  const options = _options_ || {};

  return through.obj((file, enc, callback) => {
    if (!file.path) { callback(); }

    if (file.isStream()) {
      callback(
        new gulpUtils.PluginError(PLUGIN_NAME, 'Streaming not supported')
      );
    }

    try {
      const stats = fs.lstatSync(file.path);
      if (stats.isFile()) {
        let finalOptions = options;
        if (typeof(options) === 'function') {
          finalOptions = options(file);
        }
        finalOptions.entry = file.path;

        rollup.rollup(finalOptions).then(bundle => {
          const res = bundle.generate(finalOptions);
          file.contents = new Buffer(res.code);
          const map = res.map;
          if (map) {
            // This makes sure the paths in the generated source map (file and
            // sources) are relative to file.base:
            map.file = unixStylePath(file.relative);
            map.sources = map.sources.map(
              fileName => unixStylePath(path.relative(file.base, fileName))
            );
            file.sourceMap = map;
          }
          callback(null, file);
        }, err => {
          setImmediate(() => callback(
            new gulpUtils.PluginError(PLUGIN_NAME, err))
          );
        });
      }
    } catch (err) {
      callback(new gulpUtils.PluginError(PLUGIN_NAME, err));
    }
  }, function () {
    this.emit('end');
  });
}

export default gulpRollup;
<commit_msg>Simplify import.<commit_after>/**
 * @usage
 *
 * gulp.src('app.js', {read: false})
 *     .pipe(rollup(options))
 *     .pipe(gulp.dest('dist'));
 */

import through from 'through2';
import gulpUtils from 'gulp-util';
import fs from 'fs';
import path from 'path';
import { rollup } from 'rollup';

const PLUGIN_NAME = 'gulp-rollup';

function unixStylePath (filePath) {
  return filePath.split(path.sep).join('/');
}

function gulpRollup (_options_) {
  const options = _options_ || {};

  return through.obj((file, enc, callback) => {
    if (!file.path) { callback(); }

    if (file.isStream()) {
      callback(
        new gulpUtils.PluginError(PLUGIN_NAME, 'Streaming not supported')
      );
    }

    try {
      const stats = fs.lstatSync(file.path);
      if (stats.isFile()) {
        let finalOptions = options;
        if (typeof(options) === 'function') {
          finalOptions = options(file);
        }
        finalOptions.entry = file.path;

        rollup(finalOptions).then(bundle => {
          const res = bundle.generate(finalOptions);
          file.contents = new Buffer(res.code);
          const map = res.map;
          if (map) {
            // This makes sure the paths in the generated source map (file and
            // sources) are relative to file.base:
            map.file = unixStylePath(file.relative);
            map.sources = map.sources.map(
              fileName => unixStylePath(path.relative(file.base, fileName))
            );
            file.sourceMap = map;
          }
          callback(null, file);
        }, err => {
          setImmediate(() => callback(
            new gulpUtils.PluginError(PLUGIN_NAME, err))
          );
        });
      }
    } catch (err) {
      callback(new gulpUtils.PluginError(PLUGIN_NAME, err));
    }
  }, function () {
    this.emit('end');
  });
}

export default gulpRollup;
<|endoftext|>


<commit_before>// routes.js
// This is a big clunky file; you're advised to read side by side with the API doc (https://github.com/SeetiTel/Documentation/blob/master/API.md)

// POST /whistle/new/image	Creates a single whistle with the provided text data
// POST /whistle/new/text	Creates a single whistle with the provided text data
router.post('/whistle/new/', function(req, res) {
  var type = parseInt(req.body.type),
    data = req.body.data,
    query = "INSERT INTO whistles VALUES(?, ?, ?)",
    currDate = Date.now(),
    param,
    uploadFilename,
    newFilename;

  switch (type) {
    case 0:
      // text
      param = [currDate, 0, data];
      break;
    case 1:
      //voice; not supported
      res.status(404).json({
        error: 'Voice whistles not supported with this method'
      });
      return;
    case 2:
      //image

      //the upload logic is all handled directly by multer; all we do is get the filename. Horrid security, I know.
      //here, we'll get the filenames, both uploaded and future
      uploadFilename = "data\\" + req.files.data.name;
      newFilename = "data\\" + uuid.v4() + ".jpg";

      //renameSync doesn't have a callback; https://nodejs.org/api/fs.html
      fs.renameSync(uploadFilename, newFilename);

      param = [Date.now(), 2, newFilename];
      break;
    default:
      //invalid type
      res.status(404).json({
        error: 'Type ' + type + ' not found'
      });
      return;
  }

  //run the query
  db.run(query, param, function(err) {
    if (err) {
      res.status(500).json({
        error: err
      });
    } else {
      //ghetto way to get the last whistle and return its id
      db.each('SELECT ROWID as id, * FROM whistles WHERE created = ' + currDate + ' LIMIT 1', function(err, row) {
        res.json({
          id: row.id
        });
      });
    }
  });
});

// GET /whistles/{offset}	Returns an array of teasers starting after the given id (offset)
router.get('/whistles/:offset?', function(req, res) {
  var offset = req.params.offset ? parseInt(req.params.offset) : 0, //offset is either what they gave us, or zero
    query = 'SELECT ROWID as id, * FROM whistles ORDER BY created DESC LIMIT ' + offset + ', 25',
    results = [],
    teaser;

  //push each result into the array
  db.each(query, function(err, row) {
      //deal with differing row types, and make sure our teaser is appropriate for each
      switch (row.type) {
        case 0:
          // text
          teaser = row.value.slice(0, 40);
          break;
        case 1:
          //audio
          teaser = "(audio content)";
          break;
        case 2:
          //image
          teaser = "(image content)";
          break;
      }

      //push the results we got into the array
      results.push({
        "id": row.id,
        "created": row.created,
        "type": row.type,
        "teaser": teaser
      });
    },

    function(err, count) {
      if (!err) {
        //no error, SHIP IT!
        if (results.length > 0) {
          //we have good results; pass it to the user
          res.json(results);
        } else {
          //no results, let em know
          res.status(410).json({
            error: 'No more records.'
          });
        }
      } else {
        res.status(500).json({
          error: err
        });
      }
    });
});

//GET /whistles/search/{phrase}	Returns an array of teasers that contain the given string (phrase)
router.get('/whistles/search/:phrase', function(req, res) {
  //sqlite is being weird about preparing a wildcard LIKE param, so we'll just manually stick the %'s in ourselves
  var phrase = '%' + (req.params.phrase ? req.params.phrase : "searchfornothingbecauseyousuck") + '%',
    query = 'SELECT ROWID as id, * FROM whistles WHERE value LIKE ?',
    results = [];

  db.each(query, [phrase], function(err, row) {
      //deal with differing row types, and make sure our teaser is appropriate for each
      switch (row.type) {
        case 0:
          // text
          teaser = row.value.slice(0, 40);
          break;
        case 1:
          //audio text
          teaser = "(audio content)";
          break;
        case 2:
          //image
          teaser = "(image content)";
          break;
      }

      //push the results into the array
      results.push({
        "id": row.id,
        "created": row.created,
        "type": row.type,
        "teaser": teaser
      });
    },

    function(err, count) {
      if (!err) {
        //no error, SHIP IT!
        if (results.length > 0) {
          //we have good results; pass it to the user
          res.json(results);
        } else {
          //no results, let em know
          res.status(410).json({
            error: 'No records matching.'
          });
        }
      } else {
        res.status(500).json({
          error: err
        });
      }
    });
});

//GET /whistle/{id}	Returns a full whistle with the given id (id)
router.get('/whistle/:id', function(req, res) {
  //sqlite is being weird about preparing a wildcard LIKE paran, so we'll just manually stick them in
  var id = req.params.id ? parseInt(req.params.id) : 0,
    query = 'SELECT ROWID as id, * FROM whistles WHERE id=?',
    result = false;

  //run the query
  db.each(query, [id], function(err, row) {
      result = {
        "id": row.id,
        "created": row.created,
        "type": row.type,
        "content": row.value
      };
    },

    function(err, count) {
      if (!err) {
        //no error, SHIP IT!
        if (result !== false) {
          res.json(result);
        } else {
          //no results, let em know
          res.status(404).json({
            error: 'No such ID.'
          });
        }
      } else {
        res.status(500).json({
          error: err
        });
      }
    });
});
<commit_msg>Adding HTTP code as spec'd<commit_after>// routes.js
// This is a big clunky file; you're advised to read side by side with the API doc (https://github.com/SeetiTel/Documentation/blob/master/API.md)

// POST /whistle/new/image	Creates a single whistle with the provided text data
// POST /whistle/new/text	Creates a single whistle with the provided text data
router.post('/whistle/new/', function(req, res) {
  var type = parseInt(req.body.type),
    data = req.body.data,
    query = "INSERT INTO whistles VALUES(?, ?, ?)",
    currDate = Date.now(),
    param,
    uploadFilename,
    newFilename;

  switch (type) {
    case 0:
      // text
      param = [currDate, 0, data];
      break;
    case 1:
      //voice; not supported
      res.status(404).json({
        error: 'Voice whistles not supported with this method'
      });
      return;
    case 2:
      //image

      //the upload logic is all handled directly by multer; all we do is get the filename. Horrid security, I know.
      //here, we'll get the filenames, both uploaded and future
      uploadFilename = "data\\" + req.files.data.name;
      newFilename = "data\\" + uuid.v4() + ".jpg";

      //renameSync doesn't have a callback; https://nodejs.org/api/fs.html
      fs.renameSync(uploadFilename, newFilename);

      param = [Date.now(), 2, newFilename];
      break;
    default:
      //invalid type
      res.status(404).json({
        error: 'Type ' + type + ' not found'
      });
      return;
  }

  //run the query
  db.run(query, param, function(err) {
    if (err) {
      res.status(500).json({
        error: err
      });
    } else {
      //ghetto way to get the last whistle and return its id
      db.each('SELECT ROWID as id, * FROM whistles WHERE created = ' + currDate + ' LIMIT 1', function(err, row) {
        res.status(201).json({
          id: row.id
        });
      });
    }
  });
});

// GET /whistles/{offset}	Returns an array of teasers starting after the given id (offset)
router.get('/whistles/:offset?', function(req, res) {
  var offset = req.params.offset ? parseInt(req.params.offset) : 0, //offset is either what they gave us, or zero
    query = 'SELECT ROWID as id, * FROM whistles ORDER BY created DESC LIMIT ' + offset + ', 25',
    results = [],
    teaser;

  //push each result into the array
  db.each(query, function(err, row) {
      //deal with differing row types, and make sure our teaser is appropriate for each
      switch (row.type) {
        case 0:
          // text
          teaser = row.value.slice(0, 40);
          break;
        case 1:
          //audio
          teaser = "(audio content)";
          break;
        case 2:
          //image
          teaser = "(image content)";
          break;
      }

      //push the results we got into the array
      results.push({
        "id": row.id,
        "created": row.created,
        "type": row.type,
        "teaser": teaser
      });
    },

    function(err, count) {
      if (!err) {
        //no error, SHIP IT!
        if (results.length > 0) {
          //we have good results; pass it to the user
          res.json(results);
        } else {
          //no results, let em know
          res.status(410).json({
            error: 'No more records.'
          });
        }
      } else {
        res.status(500).json({
          error: err
        });
      }
    });
});

//GET /whistles/search/{phrase}	Returns an array of teasers that contain the given string (phrase)
router.get('/whistles/search/:phrase', function(req, res) {
  //sqlite is being weird about preparing a wildcard LIKE param, so we'll just manually stick the %'s in ourselves
  var phrase = '%' + (req.params.phrase ? req.params.phrase : "searchfornothingbecauseyousuck") + '%',
    query = 'SELECT ROWID as id, * FROM whistles WHERE value LIKE ?',
    results = [];

  db.each(query, [phrase], function(err, row) {
      //deal with differing row types, and make sure our teaser is appropriate for each
      switch (row.type) {
        case 0:
          // text
          teaser = row.value.slice(0, 40);
          break;
        case 1:
          //audio text
          teaser = "(audio content)";
          break;
        case 2:
          //image
          teaser = "(image content)";
          break;
      }

      //push the results into the array
      results.push({
        "id": row.id,
        "created": row.created,
        "type": row.type,
        "teaser": teaser
      });
    },

    function(err, count) {
      if (!err) {
        //no error, SHIP IT!
        if (results.length > 0) {
          //we have good results; pass it to the user
          res.json(results);
        } else {
          //no results, let em know
          res.status(410).json({
            error: 'No records matching.'
          });
        }
      } else {
        res.status(500).json({
          error: err
        });
      }
    });
});

//GET /whistle/{id}	Returns a full whistle with the given id (id)
router.get('/whistle/:id', function(req, res) {
  //sqlite is being weird about preparing a wildcard LIKE paran, so we'll just manually stick them in
  var id = req.params.id ? parseInt(req.params.id) : 0,
    query = 'SELECT ROWID as id, * FROM whistles WHERE id=?',
    result = false;

  //run the query
  db.each(query, [id], function(err, row) {
      result = {
        "id": row.id,
        "created": row.created,
        "type": row.type,
        "content": row.value
      };
    },

    function(err, count) {
      if (!err) {
        //no error, SHIP IT!
        if (result !== false) {
          res.json(result);
        } else {
          //no results, let em know
          res.status(404).json({
            error: 'No such ID.'
          });
        }
      } else {
        res.status(500).json({
          error: err
        });
      }
    });
});
<|endoftext|>


<commit_before>/**
 * @license
 * Visual Blocks Editor
 *
 * Copyright 2012 Google Inc.
 * https://developers.google.com/blockly/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Loading and saving blocks with localStorage and cloud storage.
 * @author q.neutron@gmail.com (Quynh Neutron)
 */
'use strict';

// Create a namespace.
var BlocklyStorage = {};

/**
 * Backup code blocks to localStorage.
 * @param {!Blockly.WorkspaceSvg} workspace Workspace.
 * @private
 */
BlocklyStorage.backupBlocks_ = function(workspace) {
  if ('localStorage' in window) {
    var xml = Blockly.Xml.workspaceToDom(workspace);
    // Gets the current URL, not including the hash.
    var url = window.location.href.split('#')[0];
    window.localStorage.setItem(url, Blockly.Xml.domToText(xml));
  }
};

/**
 * Bind the localStorage backup function to the unload event.
 * @param {Blockly.WorkspaceSvg=} opt_workspace Workspace.
 */
BlocklyStorage.backupOnUnload = function(opt_workspace) {
  var workspace = opt_workspace || Blockly.getMainWorkspace();
  window.addEventListener('unload',
      function() {BlocklyStorage.backupBlocks_(workspace);}, false);
};

/**
 * Restore code blocks from localStorage.
 * @param {Blockly.WorkspaceSvg=} opt_workspace Workspace.
 */
BlocklyStorage.restoreBlocks = function(opt_workspace) {
  var url = window.location.href.split('#')[0];
  if ('localStorage' in window && window.localStorage[url]) {
    var workspace = opt_workspace || Blockly.getMainWorkspace();
    var xml = Blockly.Xml.textToDom(window.localStorage[url]);
    Blockly.Xml.domToWorkspace(xml, workspace);
  }
};

/**
 * Save blocks to database and return a link containing key to XML.
 * @param {Blockly.WorkspaceSvg=} opt_workspace Workspace.
 */
BlocklyStorage.link = function(opt_workspace) {
  var workspace = opt_workspace || Blockly.getMainWorkspace();
  var xml = Blockly.Xml.workspaceToDom(workspace);
  var data = Blockly.Xml.domToText(xml);
  BlocklyStorage.makeRequest_('/storage', 'xml', data, workspace);
};

/**
 * Retrieve XML text from database using given key.
 * @param {string} key Key to XML, obtained from href.
 * @param {Blockly.WorkspaceSvg=} opt_workspace Workspace.
 */
BlocklyStorage.retrieveXml = function(key, opt_workspace) {
  var workspace = opt_workspace || Blockly.getMainWorkspace();
  BlocklyStorage.makeRequest_('/storage', 'key', key, workspace);
};

/**
 * Global reference to current AJAX request.
 * @type {XMLHttpRequest}
 * @private
 */
BlocklyStorage.httpRequest_ = null;

/**
 * Fire a new AJAX request.
 * @param {string} url URL to fetch.
 * @param {string} name Name of parameter.
 * @param {string} content Content of parameter.
 * @param {!Blockly.WorkspaceSvg} workspace Workspace.
 * @private
 */
BlocklyStorage.makeRequest_ = function(url, name, content, workspace) {
  if (BlocklyStorage.httpRequest_) {
    // AJAX call is in-flight.
    BlocklyStorage.httpRequest_.abort();
  }
  BlocklyStorage.httpRequest_ = new XMLHttpRequest();
  BlocklyStorage.httpRequest_.name = name;
  BlocklyStorage.httpRequest_.onreadystatechange =
      BlocklyStorage.handleRequest_;
  BlocklyStorage.httpRequest_.open('POST', url);
  BlocklyStorage.httpRequest_.setRequestHeader('Content-Type',
      'application/x-www-form-urlencoded');
  BlocklyStorage.httpRequest_.send(name + '=' + encodeURIComponent(content));
  BlocklyStorage.httpRequest_.workspace = workspace;
};

/**
 * Callback function for AJAX call.
 * @private
 */
BlocklyStorage.handleRequest_ = function() {
  if (BlocklyStorage.httpRequest_.readyState == 4) {
    if (BlocklyStorage.httpRequest_.status != 200) {
      BlocklyStorage.alert(BlocklyStorage.HTTPREQUEST_ERROR + '\n' +
          'httpRequest_.status: ' + BlocklyStorage.httpRequest_.status);
    } else {
      var data = BlocklyStorage.httpRequest_.responseText.trim();
      if (BlocklyStorage.httpRequest_.name == 'xml') {
        window.location.hash = data;
        BlocklyStorage.alert(BlocklyStorage.LINK_ALERT.replace('%1',
            window.location.href));
      } else if (BlocklyStorage.httpRequest_.name == 'key') {
        if (!data.length) {
          BlocklyStorage.alert(BlocklyStorage.HASH_ERROR.replace('%1',
              window.location.hash));
        } else {
          BlocklyStorage.loadXml_(data, BlocklyStorage.httpRequest_.workspace);
        }
      }
      BlocklyStorage.monitorChanges_(BlocklyStorage.httpRequest_.workspace);
    }
    BlocklyStorage.httpRequest_ = null;
  }
};

/**
 * Start monitoring the workspace.  If a change is made that changes the XML,
 * clear the key from the URL.  Stop monitoring the workspace once such a
 * change is detected.
 * @param {!Blockly.WorkspaceSvg} workspace Workspace.
 * @private
 */
BlocklyStorage.monitorChanges_ = function(workspace) {
  var startXmlDom = Blockly.Xml.workspaceToDom(workspace);
  var startXmlText = Blockly.Xml.domToText(startXmlDom);
  function change() {
    var xmlDom = Blockly.Xml.workspaceToDom(workspace);
    var xmlText = Blockly.Xml.domToText(xmlDom);
    if (startXmlText != xmlText) {
      window.location.hash = '';
      workspace.removeChangeListener(bindData);
    }
  }
  var bindData = workspace.addChangeListener(change);
};

/**
 * Load blocks from XML.
 * @param {string} xml Text representation of XML.
 * @param {!Blockly.WorkspaceSvg} workspace Workspace.
 * @private
 */
BlocklyStorage.loadXml_ = function(xml, workspace) {
  try {
    xml = Blockly.Xml.textToDom(xml);
  } catch (e) {
    BlocklyStorage.alert(BlocklyStorage.XML_ERROR + '\nXML: ' + xml);
    return;
  }
  // Clear the workspace to avoid merge.
  workspace.clear();
  Blockly.Xml.domToWorkspace(xml, workspace);
};

/**
 * Present a text message to the user.
 * Designed to be overridden if an app has custom dialogs, or a butter bar.
 * @param {string} message Text to alert.
 */
BlocklyStorage.alert = function(message) {
  window.alert(message);
};
<commit_msg>Stop storing IDs on every block in our datastore.<commit_after>/**
 * @license
 * Visual Blocks Editor
 *
 * Copyright 2012 Google Inc.
 * https://developers.google.com/blockly/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Loading and saving blocks with localStorage and cloud storage.
 * @author q.neutron@gmail.com (Quynh Neutron)
 */
'use strict';

// Create a namespace.
var BlocklyStorage = {};

/**
 * Backup code blocks to localStorage.
 * @param {!Blockly.WorkspaceSvg} workspace Workspace.
 * @private
 */
BlocklyStorage.backupBlocks_ = function(workspace) {
  if ('localStorage' in window) {
    var xml = Blockly.Xml.workspaceToDom(workspace);
    // Gets the current URL, not including the hash.
    var url = window.location.href.split('#')[0];
    window.localStorage.setItem(url, Blockly.Xml.domToText(xml));
  }
};

/**
 * Bind the localStorage backup function to the unload event.
 * @param {Blockly.WorkspaceSvg=} opt_workspace Workspace.
 */
BlocklyStorage.backupOnUnload = function(opt_workspace) {
  var workspace = opt_workspace || Blockly.getMainWorkspace();
  window.addEventListener('unload',
      function() {BlocklyStorage.backupBlocks_(workspace);}, false);
};

/**
 * Restore code blocks from localStorage.
 * @param {Blockly.WorkspaceSvg=} opt_workspace Workspace.
 */
BlocklyStorage.restoreBlocks = function(opt_workspace) {
  var url = window.location.href.split('#')[0];
  if ('localStorage' in window && window.localStorage[url]) {
    var workspace = opt_workspace || Blockly.getMainWorkspace();
    var xml = Blockly.Xml.textToDom(window.localStorage[url]);
    Blockly.Xml.domToWorkspace(xml, workspace);
  }
};

/**
 * Save blocks to database and return a link containing key to XML.
 * @param {Blockly.WorkspaceSvg=} opt_workspace Workspace.
 */
BlocklyStorage.link = function(opt_workspace) {
  var workspace = opt_workspace || Blockly.getMainWorkspace();
  var xml = Blockly.Xml.workspaceToDom(workspace, true);
  var data = Blockly.Xml.domToText(xml);
  BlocklyStorage.makeRequest_('/storage', 'xml', data, workspace);
};

/**
 * Retrieve XML text from database using given key.
 * @param {string} key Key to XML, obtained from href.
 * @param {Blockly.WorkspaceSvg=} opt_workspace Workspace.
 */
BlocklyStorage.retrieveXml = function(key, opt_workspace) {
  var workspace = opt_workspace || Blockly.getMainWorkspace();
  BlocklyStorage.makeRequest_('/storage', 'key', key, workspace);
};

/**
 * Global reference to current AJAX request.
 * @type {XMLHttpRequest}
 * @private
 */
BlocklyStorage.httpRequest_ = null;

/**
 * Fire a new AJAX request.
 * @param {string} url URL to fetch.
 * @param {string} name Name of parameter.
 * @param {string} content Content of parameter.
 * @param {!Blockly.WorkspaceSvg} workspace Workspace.
 * @private
 */
BlocklyStorage.makeRequest_ = function(url, name, content, workspace) {
  if (BlocklyStorage.httpRequest_) {
    // AJAX call is in-flight.
    BlocklyStorage.httpRequest_.abort();
  }
  BlocklyStorage.httpRequest_ = new XMLHttpRequest();
  BlocklyStorage.httpRequest_.name = name;
  BlocklyStorage.httpRequest_.onreadystatechange =
      BlocklyStorage.handleRequest_;
  BlocklyStorage.httpRequest_.open('POST', url);
  BlocklyStorage.httpRequest_.setRequestHeader('Content-Type',
      'application/x-www-form-urlencoded');
  BlocklyStorage.httpRequest_.send(name + '=' + encodeURIComponent(content));
  BlocklyStorage.httpRequest_.workspace = workspace;
};

/**
 * Callback function for AJAX call.
 * @private
 */
BlocklyStorage.handleRequest_ = function() {
  if (BlocklyStorage.httpRequest_.readyState == 4) {
    if (BlocklyStorage.httpRequest_.status != 200) {
      BlocklyStorage.alert(BlocklyStorage.HTTPREQUEST_ERROR + '\n' +
          'httpRequest_.status: ' + BlocklyStorage.httpRequest_.status);
    } else {
      var data = BlocklyStorage.httpRequest_.responseText.trim();
      if (BlocklyStorage.httpRequest_.name == 'xml') {
        window.location.hash = data;
        BlocklyStorage.alert(BlocklyStorage.LINK_ALERT.replace('%1',
            window.location.href));
      } else if (BlocklyStorage.httpRequest_.name == 'key') {
        if (!data.length) {
          BlocklyStorage.alert(BlocklyStorage.HASH_ERROR.replace('%1',
              window.location.hash));
        } else {
          BlocklyStorage.loadXml_(data, BlocklyStorage.httpRequest_.workspace);
        }
      }
      BlocklyStorage.monitorChanges_(BlocklyStorage.httpRequest_.workspace);
    }
    BlocklyStorage.httpRequest_ = null;
  }
};

/**
 * Start monitoring the workspace.  If a change is made that changes the XML,
 * clear the key from the URL.  Stop monitoring the workspace once such a
 * change is detected.
 * @param {!Blockly.WorkspaceSvg} workspace Workspace.
 * @private
 */
BlocklyStorage.monitorChanges_ = function(workspace) {
  var startXmlDom = Blockly.Xml.workspaceToDom(workspace);
  var startXmlText = Blockly.Xml.domToText(startXmlDom);
  function change() {
    var xmlDom = Blockly.Xml.workspaceToDom(workspace);
    var xmlText = Blockly.Xml.domToText(xmlDom);
    if (startXmlText != xmlText) {
      window.location.hash = '';
      workspace.removeChangeListener(bindData);
    }
  }
  var bindData = workspace.addChangeListener(change);
};

/**
 * Load blocks from XML.
 * @param {string} xml Text representation of XML.
 * @param {!Blockly.WorkspaceSvg} workspace Workspace.
 * @private
 */
BlocklyStorage.loadXml_ = function(xml, workspace) {
  try {
    xml = Blockly.Xml.textToDom(xml);
  } catch (e) {
    BlocklyStorage.alert(BlocklyStorage.XML_ERROR + '\nXML: ' + xml);
    return;
  }
  // Clear the workspace to avoid merge.
  workspace.clear();
  Blockly.Xml.domToWorkspace(xml, workspace);
};

/**
 * Present a text message to the user.
 * Designed to be overridden if an app has custom dialogs, or a butter bar.
 * @param {string} message Text to alert.
 */
BlocklyStorage.alert = function(message) {
  window.alert(message);
};
<|endoftext|>


<commit_before>/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

/*
 * resolveLocalFileSystemURI
 *
 * IN
 *  args
 *   0 - escaped local filesystem URI
 *   1 - options (standard HTML5 file system options)
 *   2 - size
 * OUT
 *  success - Entry object
 *   - isDirectory
 *   - isFile
 *   - name
 *   - fullPath
 *   - nativeURL
 *   - fileSystemName
 *  fail - FileError code
 */

var info = require('org.apache.cordova.file.bb10FileSystemInfo'),
    requestAnimationFrame = cordova.require('org.apache.cordova.file.bb10RequestAnimationFrame'),
    createEntryFromNative = require('org.apache.cordova.file.bb10CreateEntryFromNative'),
    DEFAULT_SIZE = 5*1024*1024,
    SANDBOXED = true,
    UNSANDBOXED = false;

module.exports = function (success, fail, args) {
    var request = args[0],
        options = args[1],
        size = args[2];
    if (request) {
        request = decodeURIComponent(request);
        if (request.indexOf('?') > -1) {
            //bb10 does not support params; strip them off
            request = request.substring(0, request.indexOf('?'));
        }
        if (request.indexOf('file://localhost/') === 0) {
            //remove localhost prefix
            request = request.replace('file://localhost/', 'file:///');
        }
        //requests to sandboxed locations should use cdvfile
        request = request.replace(info.persistentPath, 'cdvfile://localhost/persistent');
        request = request.replace(info.temporaryPath, 'cdvfile://localhost/temporary');
        //pick appropriate handler
        if (request.indexOf('file:///') === 0) {
            resolveFile(success, fail, request, options);
        } else if (request.indexOf('cdvfile://localhost/') === 0) {
            resolveCdvFile(success, fail, request, options, size);
        } else if (request.indexOf('local:///') === 0) {
            resolveLocal(success, fail, request, options);
        } else {
            fail(FileError.ENCODING_ERR);
        }
    } else {
        fail(FileError.NOT_FOUND_ERR);
    }
};

//resolve file:///
function resolveFile(success, fail, request, options) {
    var path = request.substring(7);
    resolve(success, fail, path, window.PERSISTENT, UNSANDBOXED, options);
}

//resolve cdvfile://localhost/filesystemname/
function resolveCdvFile(success, fail, request, options, size) {
    var components = /cdvfile:\/\/localhost\/([^\/]+)\/(.*)/.exec(request),
        fsType = components[1],
        path = components[2];
    if (fsType === 'persistent') {
        resolve(success, fail, path, window.PERSISTENT, SANDBOXED, options, size);
    }
    else if (fsType === 'temporary') {
        resolve(success, fail, path, window.TEMPORARY, SANDBOXED, options, size);
    }
    else if (fsType === 'root') {
        resolve(success, fail, path, window.PERSISTENT, UNSANDBOXED, options);
    }
    else {
        fail(FileError.NOT_FOUND_ERR);
    }
}

//resolve local:///
function resolveLocal(success, fail, request, options) {
    var path = localPath + request.substring(8);
    resolve(success, fail, path, window.PERSISTENT, UNSANDBOXED, options);
}

//validate parameters and set sandbox
function resolve(success, fail, path, fsType, sandbox, options, size) {
    options = options || { create: false };
    size = size || DEFAULT_SIZE;
    if (size > info.MAX_SIZE) {
        //bb10 does not respect quota; fail at unreasonably large size
        fail(FileError.QUOTA_EXCEEDED_ERR);
    } else if (path.indexOf(':') > -1) {
        //files with : character are not valid in Cordova apps
        fail(FileError.ENCODING_ERR);
    } else {
        requestAnimationFrame(function () {
            cordova.exec(function () {
                requestAnimationFrame(function () {
                    resolveNative(success, fail, path, fsType, options, size);
                });
            }, fail, 'File', 'setSandbox', [sandbox], false);
        });
    }
}

//find path using webkit file system
function resolveNative(success, fail, path, fsType, options, size) {
    window.webkitRequestFileSystem(
        fsType,
        size,
        function (fs) {
            if (path === '') {
                //no path provided, call success with root file system
                success(createEntryFromNative(fs.root));
            } else {
                //otherwise attempt to resolve as file
                fs.root.getFile(
                    path,
                    options,
                    function (entry) {
                        success(createEntryFromNative(entry));
                    },
                    function (fileError) {
                        //file not found, attempt to resolve as directory
                        fs.root.getDirectory(
                            path,
                            options,
                            function (entry) {
                                success(createEntryFromNative(entry));
                            },
                            function (dirError) {
                                //path cannot be resolved
                                if (fileError.code === FileError.INVALID_MODIFICATION_ERR &&
                                    options.exclusive) {
                                    //mobile-spec expects this error code
                                    fail(FileError.PATH_EXISTS_ERR);
                                } else {
                                    fail(FileError.NOT_FOUND_ERR);
                                }
                            }
                        );
                    }
                );
            }
        }
    );
}
<commit_msg>CB-7445 [BlackBerry10] resolveLocalFileSystemURI - change DEFAULT_SIZE to MAX_SIZE<commit_after>/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

/*
 * resolveLocalFileSystemURI
 *
 * IN
 *  args
 *   0 - escaped local filesystem URI
 *   1 - options (standard HTML5 file system options)
 *   2 - size
 * OUT
 *  success - Entry object
 *   - isDirectory
 *   - isFile
 *   - name
 *   - fullPath
 *   - nativeURL
 *   - fileSystemName
 *  fail - FileError code
 */

var info = require('org.apache.cordova.file.bb10FileSystemInfo'),
    requestAnimationFrame = cordova.require('org.apache.cordova.file.bb10RequestAnimationFrame'),
    createEntryFromNative = require('org.apache.cordova.file.bb10CreateEntryFromNative'),
    SANDBOXED = true,
    UNSANDBOXED = false;

module.exports = function (success, fail, args) {
    var request = args[0],
        options = args[1],
        size = args[2];
    if (request) {
        request = decodeURIComponent(request);
        if (request.indexOf('?') > -1) {
            //bb10 does not support params; strip them off
            request = request.substring(0, request.indexOf('?'));
        }
        if (request.indexOf('file://localhost/') === 0) {
            //remove localhost prefix
            request = request.replace('file://localhost/', 'file:///');
        }
        //requests to sandboxed locations should use cdvfile
        request = request.replace(info.persistentPath, 'cdvfile://localhost/persistent');
        request = request.replace(info.temporaryPath, 'cdvfile://localhost/temporary');
        //pick appropriate handler
        if (request.indexOf('file:///') === 0) {
            resolveFile(success, fail, request, options);
        } else if (request.indexOf('cdvfile://localhost/') === 0) {
            resolveCdvFile(success, fail, request, options, size);
        } else if (request.indexOf('local:///') === 0) {
            resolveLocal(success, fail, request, options);
        } else {
            fail(FileError.ENCODING_ERR);
        }
    } else {
        fail(FileError.NOT_FOUND_ERR);
    }
};

//resolve file:///
function resolveFile(success, fail, request, options) {
    var path = request.substring(7);
    resolve(success, fail, path, window.PERSISTENT, UNSANDBOXED, options);
}

//resolve cdvfile://localhost/filesystemname/
function resolveCdvFile(success, fail, request, options, size) {
    var components = /cdvfile:\/\/localhost\/([^\/]+)\/(.*)/.exec(request),
        fsType = components[1],
        path = components[2];
    if (fsType === 'persistent') {
        resolve(success, fail, path, window.PERSISTENT, SANDBOXED, options, size);
    }
    else if (fsType === 'temporary') {
        resolve(success, fail, path, window.TEMPORARY, SANDBOXED, options, size);
    }
    else if (fsType === 'root') {
        resolve(success, fail, path, window.PERSISTENT, UNSANDBOXED, options);
    }
    else {
        fail(FileError.NOT_FOUND_ERR);
    }
}

//resolve local:///
function resolveLocal(success, fail, request, options) {
    var path = localPath + request.substring(8);
    resolve(success, fail, path, window.PERSISTENT, UNSANDBOXED, options);
}

//validate parameters and set sandbox
function resolve(success, fail, path, fsType, sandbox, options, size) {
    options = options || { create: false };
    size = size || info.MAX_SIZE;
    if (size > info.MAX_SIZE) {
        //bb10 does not respect quota; fail at unreasonably large size
        fail(FileError.QUOTA_EXCEEDED_ERR);
    } else if (path.indexOf(':') > -1) {
        //files with : character are not valid in Cordova apps
        fail(FileError.ENCODING_ERR);
    } else {
        requestAnimationFrame(function () {
            cordova.exec(function () {
                requestAnimationFrame(function () {
                    resolveNative(success, fail, path, fsType, options, size);
                });
            }, fail, 'File', 'setSandbox', [sandbox], false);
        });
    }
}

//find path using webkit file system
function resolveNative(success, fail, path, fsType, options, size) {
    window.webkitRequestFileSystem(
        fsType,
        size,
        function (fs) {
            if (path === '') {
                //no path provided, call success with root file system
                success(createEntryFromNative(fs.root));
            } else {
                //otherwise attempt to resolve as file
                fs.root.getFile(
                    path,
                    options,
                    function (entry) {
                        success(createEntryFromNative(entry));
                    },
                    function (fileError) {
                        //file not found, attempt to resolve as directory
                        fs.root.getDirectory(
                            path,
                            options,
                            function (entry) {
                                success(createEntryFromNative(entry));
                            },
                            function (dirError) {
                                //path cannot be resolved
                                if (fileError.code === FileError.INVALID_MODIFICATION_ERR &&
                                    options.exclusive) {
                                    //mobile-spec expects this error code
                                    fail(FileError.PATH_EXISTS_ERR);
                                } else {
                                    fail(FileError.NOT_FOUND_ERR);
                                }
                            }
                        );
                    }
                );
            }
        }
    );
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

var csv = require('fast-csv');
var fs = require('fs');
var options = require('commander');
var grouper = require('./lib/grouper');
var geocoder = require('./lib/geocoder');
var streamSplitter = require('./lib/streamSplitter');
var through2 = require('through2');

var package = JSON.parse(fs.readFileSync(__dirname+'/package.json', 'utf8'));

options
  .version(package.version)
  .option('-i, --input [file]', 'Input (csv file) [stdin]', '-')
  .option('-o, --output [file]', 'Output (csv file) [stdout]', '-')
  .option('-s, --street-col [col]', 'Street col [street]', 'street')
  .option('-z, --zipcode-col [col]', 'Zipcode col [zipcode]', 'zipcode')
  .option('-c, --city-col [col]', 'City col [city]', 'city')
  .option('-S, --state-col [col]', 'State col [state]', 'state') // short forms are dumb
  .option('-d, --delimiter [symbol]', 'CSV delimiter in input file', ',')
  .option('-O, --output-split [column]', 'Write to multiple files divided by column', '')
  .option('-a, --auth-id [id]', 'SmartyStreets auth id [environment variable smartystreets_auth_id]', process.env.SMARTYSTREETS_AUTH_ID)
  .option('-A, --auth-token [token]', 'SmartyStreets auth token [environment variable smartystreets_auth_token]', process.env.SMARTYSTREETS_AUTH_TOKEN)
  .option('-j, --concurrency [jobs]', 'Maximum number of concurrent requests [48]', 48)
  .option('-✈, --column-definition [mode]', 'Column definition mode or file [standard]', 'standard')
  .option('-p, --column-prefix [text]', 'Prefix for smartystreets columns in the output file [ss_]', 'ss_')
  .option('-x, --column-suffix [text]', 'Suffix for smartystreets columns in the output file', '')
  .option('-q, --quiet', 'Quiet mode - turn off progress messages')
  .option('-l, --log-interval [num]', 'Show progress after every X number of rows [1000]', 1000)
  .parse(process.argv);

options.concurrency = parseInt(options.concurrency);

if (!options.concurrency) {
  console.error('Invalid concurrency');
  options.help();
}

if (!options.authId) {
  console.error('Please specify a SmartyStreets auth id');
  options.help();
}

if (!options.authToken) {
  console.error('Please specify a SmartyStreets auth token');
  options.help();
}

if (!options.input) {
  console.error('Please specify an input file');
  options.help();
}
if (!options.output) {
  console.error('Please specify an input file');
  options.help();
}

var columnModes = ['mail', 'standard', 'complete', 'basic'];
if (columnModes.indexOf(options.columnDefinition) != -1) {
  //modes are in structure/mode.json
  options.structure = JSON.parse( fs.readFileSync(__dirname+'/structure/'+options.columnDefinition+'.json', 'utf8') );
} else if (options.columnDefinition.substr(0, 1) == '{') {
  //it's a JSON object
  options.structure = JSON.parse(options.columnDefinition);
} else {
  //it's a JSON file
  options.structure = JSON.parse( fs.readFileSync(options.columnDefinition, 'utf8') );
}

var readStream = options.input == '-' ? process.stdin : fs.createReadStream(options.input);

var writeStream;
if (options.outputSplit) {
  try {
    fs.mkdirSync(options.output);
  } catch(e) {
    if ( e.code != 'EEXIST' ) throw e;
  }

  var firstRow = true, rowIndex, headers;

  writeStream = streamSplitter(function(row){
    if (firstRow) {
      firstRow = false;
      rowIndex = row.indexOf(options.outputSplit);
      headers = row;

      if (rowIndex == -1) {
        console.error('couldn\'t find column', options.outputSplit, 'in', row);
        process.exit();
      }

      return false;
    }

    var cell = row[rowIndex];

    while (cell.length < 5) {
      cell = '0'+cell;
    }

    return row[rowIndex].substr(0, 2);
  }, function(streamName){
    var source = csv.createWriteStream();
    source.write(headers);
    source.pipe( fs.createWriteStream(options.output+'/'+streamName+'.csv') );
    return source;
  }, {objectMode: true});
} else if (options.output == '-') {
  writeStream = csv.createWriteStream();
  writeStream.pipe( process.stdout );
} else {
  writeStream = csv.createWriteStream();
  writeStream.pipe( fs.createWriteStream(options.output) );
}

readStream.pipe(csv({headers: true, delimiter: options.delimiter}))
  .pipe(grouper(70))
  .pipe(geocoder(options))
  .pipe(writeStream);<commit_msg>truncate to 3<commit_after>#!/usr/bin/env node

var csv = require('fast-csv');
var fs = require('fs');
var options = require('commander');
var grouper = require('./lib/grouper');
var geocoder = require('./lib/geocoder');
var streamSplitter = require('./lib/streamSplitter');
var through2 = require('through2');

var package = JSON.parse(fs.readFileSync(__dirname+'/package.json', 'utf8'));

options
  .version(package.version)
  .option('-i, --input [file]', 'Input (csv file) [stdin]', '-')
  .option('-o, --output [file]', 'Output (csv file) [stdout]', '-')
  .option('-s, --street-col [col]', 'Street col [street]', 'street')
  .option('-z, --zipcode-col [col]', 'Zipcode col [zipcode]', 'zipcode')
  .option('-c, --city-col [col]', 'City col [city]', 'city')
  .option('-S, --state-col [col]', 'State col [state]', 'state') // short forms are dumb
  .option('-d, --delimiter [symbol]', 'CSV delimiter in input file', ',')
  .option('-O, --output-split [column]', 'Write to multiple files divided by column', '')
  .option('-a, --auth-id [id]', 'SmartyStreets auth id [environment variable smartystreets_auth_id]', process.env.SMARTYSTREETS_AUTH_ID)
  .option('-A, --auth-token [token]', 'SmartyStreets auth token [environment variable smartystreets_auth_token]', process.env.SMARTYSTREETS_AUTH_TOKEN)
  .option('-j, --concurrency [jobs]', 'Maximum number of concurrent requests [48]', 48)
  .option('-✈, --column-definition [mode]', 'Column definition mode or file [standard]', 'standard')
  .option('-p, --column-prefix [text]', 'Prefix for smartystreets columns in the output file [ss_]', 'ss_')
  .option('-x, --column-suffix [text]', 'Suffix for smartystreets columns in the output file', '')
  .option('-q, --quiet', 'Quiet mode - turn off progress messages')
  .option('-l, --log-interval [num]', 'Show progress after every X number of rows [1000]', 1000)
  .parse(process.argv);

options.concurrency = parseInt(options.concurrency);

if (!options.concurrency) {
  console.error('Invalid concurrency');
  options.help();
}

if (!options.authId) {
  console.error('Please specify a SmartyStreets auth id');
  options.help();
}

if (!options.authToken) {
  console.error('Please specify a SmartyStreets auth token');
  options.help();
}

if (!options.input) {
  console.error('Please specify an input file');
  options.help();
}
if (!options.output) {
  console.error('Please specify an input file');
  options.help();
}

var columnModes = ['mail', 'standard', 'complete', 'basic'];
if (columnModes.indexOf(options.columnDefinition) != -1) {
  //modes are in structure/mode.json
  options.structure = JSON.parse( fs.readFileSync(__dirname+'/structure/'+options.columnDefinition+'.json', 'utf8') );
} else if (options.columnDefinition.substr(0, 1) == '{') {
  //it's a JSON object
  options.structure = JSON.parse(options.columnDefinition);
} else {
  //it's a JSON file
  options.structure = JSON.parse( fs.readFileSync(options.columnDefinition, 'utf8') );
}

var readStream = options.input == '-' ? process.stdin : fs.createReadStream(options.input);

var writeStream;
if (options.outputSplit) {
  try {
    fs.mkdirSync(options.output);
  } catch(e) {
    if ( e.code != 'EEXIST' ) throw e;
  }

  var firstRow = true, rowIndex, headers;

  writeStream = streamSplitter(function(row){
    if (firstRow) {
      firstRow = false;
      rowIndex = row.indexOf(options.outputSplit);
      headers = row;

      if (rowIndex == -1) {
        console.error('couldn\'t find column', options.outputSplit, 'in', row);
        process.exit();
      }

      return false;
    }

    var cell = row[rowIndex];

    while (cell.length < 5) {
      cell = '0'+cell;
    }

    return row[rowIndex].substr(0, 3);
  }, function(streamName){
    var source = csv.createWriteStream();
    source.write(headers);
    source.pipe( fs.createWriteStream(options.output+'/'+streamName+'.csv') );
    return source;
  }, {objectMode: true});
} else if (options.output == '-') {
  writeStream = csv.createWriteStream();
  writeStream.pipe( process.stdout );
} else {
  writeStream = csv.createWriteStream();
  writeStream.pipe( fs.createWriteStream(options.output) );
}

readStream.pipe(csv({headers: true, delimiter: options.delimiter}))
  .pipe(grouper(70))
  .pipe(geocoder(options))
  .pipe(writeStream);<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';
const fs = require('fs');
const path = require('path');
const ora = require('ora');
const { argv } = require('yargs');
const { getPackageListMetrics } = require('../src/metrics');
let DEFAULT_INPUT_FILE_PATH = path.join(
  __dirname,
  'fixtures',
  'top-1000-packages.json'
);
const DEFAULT_OUTPUT_FILE_PATH = path.join(
  __dirname,
  'results',
  'results.json'
);

async function writePackageStatsToFile(inputFilePath, outputFilePath) {
  const packageList = require(inputFilePath).map((pkgObj) => pkgObj.package);
  const packageListMetrics = await getPackageListMetrics(packageList);
  fs.writeFileSync(outputFilePath, JSON.stringify(packageListMetrics));
}

async function main(
  inputFile = DEFAULT_INPUT_FILE_PATH,
  outputFile = DEFAULT_OUTPUT_FILE_PATH
) {
  const inputFilePath = path.resolve(inputFile);
  const outputFilePath = path.resolve(outputFile);
  const spinner = ora({ stream: process.stdout });
  spinner.text = `Analyzing Packages..`;
  spinner.start();
  try {
    const start = Date.now();
    await writePackageStatsToFile(inputFilePath, outputFilePath);
    const duration = (Date.now() - start) / 1000;
    spinner.succeed(
      `Analyzed ${inputFile} in ${duration.toFixed(
        2
      )}s.\nResults have been stored in ${outputFile}`
    );
    process.exit(0);
  } catch (e) {
    spinner.fail(`Failed to analyze packages. Error: ${e.message}`);
    process.exit(1);
  }
}

main(argv.input, argv.output);
<commit_msg>Add whitespace in metrics-cli JSON output<commit_after>#!/usr/bin/env node
'use strict';
const fs = require('fs');
const path = require('path');
const ora = require('ora');
const { argv } = require('yargs');
const { getPackageListMetrics } = require('../src/metrics');
let DEFAULT_INPUT_FILE_PATH = path.join(
  __dirname,
  'fixtures',
  'top-1000-packages.json'
);
const DEFAULT_OUTPUT_FILE_PATH = path.join(
  __dirname,
  'results',
  'results.json'
);

async function writePackageStatsToFile(inputFilePath, outputFilePath) {
  const packageList = require(inputFilePath).map((pkgObj) => pkgObj.package);
  const packageListMetrics = await getPackageListMetrics(packageList);
  fs.writeFileSync(outputFilePath, JSON.stringify(packageListMetrics, null, 2));
}

async function main(
  inputFile = DEFAULT_INPUT_FILE_PATH,
  outputFile = DEFAULT_OUTPUT_FILE_PATH
) {
  const inputFilePath = path.resolve(inputFile);
  const outputFilePath = path.resolve(outputFile);
  const spinner = ora({ stream: process.stdout });
  spinner.text = `Analyzing Packages..`;
  spinner.start();
  try {
    const start = Date.now();
    await writePackageStatsToFile(inputFilePath, outputFilePath);
    const duration = (Date.now() - start) / 1000;
    spinner.succeed(
      `Analyzed ${inputFile} in ${duration.toFixed(
        2
      )}s.\nResults have been stored in ${outputFile}`
    );
    process.exit(0);
  } catch (e) {
    spinner.fail(`Failed to analyze packages. Error: ${e.message}`);
    process.exit(1);
  }
}

main(argv.input, argv.output);
<|endoftext|>


<commit_before>// MAIN PROGRAM, start here.

// global libs
var assert = require('assert'),
    fs = require('fs'),
    path = require('path'),
    // ExpressJS and associated middleware
    express = require('express'),
    morgan = require('morgan'),
    bodyParser = require('body-parser'),

    logger = require('./utils/logger'),
    logStream,

    // local libs
    utils = require('./utils/general'),
    githubHookHandler = require('./github-hook'),
    // The configReader reads the given file, and merges it with any existing user
    // configuration file.
    cfg = require('./utils/configReader').read(path.join(__dirname, 'conf/config.json')),

    HOST = cfg.host,
    PORT = cfg.port || 8081,

    baseUrl = 'http://' + HOST + ':' + PORT,
    // This path is registered with Github as a webhook URL.
    githubHookPath = '/github-hook',
    prWebhookUrl = baseUrl + githubHookPath,

    // This directory contains all the additional service
    // handlers that will be loaded dynamically and attached
    // to this web server.
    HANDLER_DIR = 'handlers';

logger = logger.initialize(cfg.logDirectory, cfg.logLevel);
logger.info('nupic.tools server starting...');
logger.info('nupic.tools will use the following configuration:');
logger.debug('nupic.tools configuration', utils.sterilizeConfig(cfg));

// enable web server logging; pipe those log messages through our logger
logStream = {
    write: function(message, encoding){
        logger.info(message);
    }
};

utils.constructRepoClients(prWebhookUrl, cfg, function(repoClients) {
    var dynamicHttpHandlerModules,
        activeValidators,
        app = express(),
        padInt = utils.padInt,
        padDecimal = utils.padDecimal;

    // Print the time of the request to the millisecond.
    app.use(function(req, res, next) {
        var now = new Date(),
            dateString = now.getFullYear() + '/' +
                padInt(now.getMonth() + 1) + '/' +
                padInt(now.getDate()) + ' ' +
                padInt(now.getHours()) + ':' +
                padInt(now.getMinutes()) + ':' +
                padInt(now.getSeconds()) + '.' +
                padDecimal(now.getMilliseconds());
        logger.log('\n' + dateString + ' | Request received');
        next();
    });
    // Enable a log of logging.
    app.use(morgan({
        format: 'dev',
        immediate: true,
        stream: logStream
    }))
    // Auto body parsing is nice.
    app.use(bodyParser.json())
    app.use(bodyParser.urlencoded())
    // This puts the Github webhook handler into place
    app.use(githubHookPath, githubHookHandler.initializer(repoClients, cfg));

    logger.verbose('The following validators are active:');
    activeValidators = githubHookHandler.getValidators();
    activeValidators.forEach(function(v) {
        logger.verbose('\t==> ' + v);
    });

    dynamicHttpHandlerModules = utils.initializeModulesWithin(HANDLER_DIR);

    // Loads all the modules within the handlers directory, and registers the URLs
    // the declared, linked to their request handler functions.
    logger.verbose('The following URL handlers are active:');
    dynamicHttpHandlerModules.forEach(function(handlerConfig) {
        var urls = Object.keys(handlerConfig);
        urls.forEach(function(url) {
            var handler = handlerConfig[url](repoClients, dynamicHttpHandlerModules, cfg, activeValidators),
                name = handler.title,
                msg = '\t==> ' + name + ' listening for url pattern: ' + url;
            if (! handler.disabled) {
                logger.verbose(msg);
                app.use(url, handler);
            }
        });
    });

    app.listen(PORT, function() {
        logger.info('Server running at %s.', baseUrl);
    });

});
<commit_msg>extended urlencoded parser<commit_after>// MAIN PROGRAM, start here.

// global libs
var assert = require('assert'),
    fs = require('fs'),
    path = require('path'),
    // ExpressJS and associated middleware
    express = require('express'),
    morgan = require('morgan'),
    bodyParser = require('body-parser'),

    logger = require('./utils/logger'),
    logStream,

    // local libs
    utils = require('./utils/general'),
    githubHookHandler = require('./github-hook'),
    // The configReader reads the given file, and merges it with any existing user
    // configuration file.
    cfg = require('./utils/configReader').read(path.join(__dirname, 'conf/config.json')),

    HOST = cfg.host,
    PORT = cfg.port || 8081,

    baseUrl = 'http://' + HOST + ':' + PORT,
    // This path is registered with Github as a webhook URL.
    githubHookPath = '/github-hook',
    prWebhookUrl = baseUrl + githubHookPath,

    // This directory contains all the additional service
    // handlers that will be loaded dynamically and attached
    // to this web server.
    HANDLER_DIR = 'handlers';

logger = logger.initialize(cfg.logDirectory, cfg.logLevel);
logger.info('nupic.tools server starting...');
logger.info('nupic.tools will use the following configuration:');
logger.debug('nupic.tools configuration', utils.sterilizeConfig(cfg));

// enable web server logging; pipe those log messages through our logger
logStream = {
    write: function(message, encoding){
        logger.info(message);
    }
};

utils.constructRepoClients(prWebhookUrl, cfg, function(repoClients) {
    var dynamicHttpHandlerModules,
        activeValidators,
        app = express(),
        padInt = utils.padInt,
        padDecimal = utils.padDecimal;

    // Print the time of the request to the millisecond.
    app.use(function(req, res, next) {
        var now = new Date(),
            dateString = now.getFullYear() + '/' +
                padInt(now.getMonth() + 1) + '/' +
                padInt(now.getDate()) + ' ' +
                padInt(now.getHours()) + ':' +
                padInt(now.getMinutes()) + ':' +
                padInt(now.getSeconds()) + '.' +
                padDecimal(now.getMilliseconds());
        logger.log('\n' + dateString + ' | Request received');
        next();
    });
    // Enable a log of logging.
    app.use(morgan({
        format: 'dev',
        immediate: true,
        stream: logStream
    }))
    // Auto body parsing is nice.
    app.use(bodyParser.json())
    app.use(bodyParser.urlencoded({ extended: true }))
    // This puts the Github webhook handler into place
    app.use(githubHookPath, githubHookHandler.initializer(repoClients, cfg));

    logger.verbose('The following validators are active:');
    activeValidators = githubHookHandler.getValidators();
    activeValidators.forEach(function(v) {
        logger.verbose('\t==> ' + v);
    });

    dynamicHttpHandlerModules = utils.initializeModulesWithin(HANDLER_DIR);

    // Loads all the modules within the handlers directory, and registers the URLs
    // the declared, linked to their request handler functions.
    logger.verbose('The following URL handlers are active:');
    dynamicHttpHandlerModules.forEach(function(handlerConfig) {
        var urls = Object.keys(handlerConfig);
        urls.forEach(function(url) {
            var handler = handlerConfig[url](repoClients, dynamicHttpHandlerModules, cfg, activeValidators),
                name = handler.title,
                msg = '\t==> ' + name + ' listening for url pattern: ' + url;
            if (! handler.disabled) {
                logger.verbose(msg);
                app.use(url, handler);
            }
        });
    });

    app.listen(PORT, function() {
        logger.info('Server running at %s.', baseUrl);
    });

});
<|endoftext|>


<commit_before>/*
 * grunt-ristretto
 *
 * Copyright (c) 2013 Viliam Kopecky
 * Licensed under the MIT license.
 */

'use strict';

// show debug info on error
process.on('uncaughtException', function(err) {
    console.log(err.stack);
});

module.exports = function(grunt) {

  var fs = require('fs');
  var path = require('path');

  var metafilename = '.ristretto.json';

  var allow_publish = function(dir, meta) {
    var allow_write = false;

    if(grunt.file.exists(dir)) { // publish dir/file exists
      if(grunt.file.isDir(dir)) { // is directory
        if(grunt.file.exists(meta)) { // contains ristretto metadata
          allow_write = true;
        } else { // does not contain ristretto metadata
          if(grunt.file.expand([dir+'/**.*']).length === 0) { // directory is empty
            allow_write = true;
          } else { // directory is not empty, but doesn't contain ristretto metadata
            allow_write = true; //grunt.warn('Publish direrctory "'+dir+'" is not empty.');
          }
        }
      } else { // publish dir is not a directory
        grunt.warn('File '+dir+' already exists and is not a directory.');
      }
    } else { // publish dir doesn't exist
      allow_write = true;
    }
    return allow_write;
  };

  var build_and_copy = function(options, params, dest, meta, done) {

    var php_script = require('../libs/php_script');

    var latte2html = php_script.latte2html;
    var neon2json = php_script.neon2json;

    var copy_files = grunt.file.expand({ cwd: params.www_dir }, ['**/*.*', '**/.*', '!**/*.latte', '!**/*.neon']);
    var neon_files = grunt.file.expand({ cwd: params.model_dir }, ['**/*.neon']);
    var latte_files = grunt.file.expand({ cwd: params.latte_dir }, ['**/*.latte', '!**/@*.latte']);

    var next_total = 1;
    var next = function() {
      if(next_total === 3) {
          grunt.file.write(meta, JSON.stringify({ 'published_by': 'Ristretto', 'timestamp': (new Date()).getTime() }));
          grunt.log.writeln('');
          grunt.log.ok('Publish finished', meta);
          grunt.log.writeln('  ', dest);
          return done();
      }
      next_total++;
    };

    var published_copy = 0;
    var next_copy = function(){
      if(published_copy === copy_files.length) {
        grunt.log.ok('Finished: Copy static files');
        next();
        return;
      }
      var filepath = copy_files[published_copy];

      if(grunt.file.isFile(params.www_dir + '/' + filepath)) {
        grunt.log.writeln('   Copy file', filepath);

        grunt.file.copy(params.www_dir + '/' + filepath, dest + filepath);
      }
      published_copy++;
      next_copy();
    };
    next_copy();

    var published_latte = 0;
    var next_latte = function(){
      if(published_latte === latte_files.length) {
        grunt.log.ok('Finished: Compile Latte files');
        next();
        return;
      }
      var filepath = latte_files[published_latte];
      grunt.log.writeln('   Compiling Latte file', filepath);

      latte2html(options, filepath, function(body){
        var write = dest + filepath.substr(0, filepath.length - 'latte'.length) + 'html';
        grunt.log.writeln('   Writing Latte file', filepath);
        grunt.file.write(write, body);
        published_latte++;
        next_latte();
      });
    };
    next_latte();

    var published_neon = 0;
    var next_neon = function(){
      if(published_neon === neon_files.length) {
        grunt.log.ok('Finished: Compile NE-ON files');
        next();
        return;
      }
      var filepath = neon_files[published_neon];
      grunt.log.writeln('   Compiling NE-ON file', filepath);

      neon2json(options, filepath, function(body){
        var model_dest = dest;
        if(options.model_dir.indexOf(options.www_dir) === 0) {
          model_dest += options.model_dir.substr(options.www_dir.length+1);
        } else {
          model_dest += options.model_dir;
        }
        grunt.log.writeln('   Writing NE-ON file', filepath);
        var write = model_dest + '/' +filepath;
        grunt.file.write(write, body);
        published_neon++;
        next_neon();
      });
    };
    next_neon();
  };

  var publish = function(options, done) {
    var dest = options.publish_dir + '/';
    dest = dest.replace('//', '/');

    var meta = dest + metafilename;

    var params = {
      www_dir: fs.realpathSync(options.www_dir),
      latte_dir: fs.realpathSync(options.latte_dir),
      temp_dir: fs.realpathSync(options.temp_dir)
    };

    if(options.model_dir && grunt.file.exists(options.model_dir)) {
      params.model_dir = fs.realpathSync(options.model_dir);
    }

    if(!allow_publish(dest, meta)) {
      done();
      return;
    }

    var created = false;
    if(!grunt.file.exists(dest)) {
      created = true;
      grunt.file.mkdir(dest);
    }

    if(grunt.file.isPathInCwd(dest)) {
      grunt.file.delete(dest);
      build_and_copy(options, params, dest, meta, done);
    } else {
      console.log('');
      grunt.log.warn('You are publishing into directory outside of CWD. This action will overwrite its contents.');
      grunt.log.warn(dest);
      require('co-prompt').confirm("\n   Are you sure? [ NO | yes ]: ")(function(wut, ok) {
        if(ok) {
          var time = (new Date).getTime();
          var temp_dest = dest.replace(/\/*$/, '') + '-ristretto-' + time;

          if(grunt.file.exists(dest)) {
            if(created) {
              grunt.file.delete(dest, { force: true });
            } else {
              require('fs').renameSync(dest, temp_dest);
            }
          }

          grunt.log.ok('Original contents moved to:');
          grunt.log.ok(temp_dest);

          build_and_copy(options, params, dest, meta, done);
        } else {
          console.log('');
          grunt.log.ok('Publish aborted');
          done();
        }
      });
    }

  };

  grunt.registerTask('ristretto', 'Ristretto frontend prototyping system', function() {
    var options = this.options();
    var config = options.config;

    var version = config.ristretto_version = grunt.file.readJSON(__dirname + '/../package.json').version;

    if(typeof config.port === 'undefined') {
      config.port = 8000;
    }

    if(typeof config.www_dir === 'undefined') {
      config.www_dir = '.';
    }

    if(typeof config.model_dir === 'undefined') {
      config.model_dir = config.www_dir + '/model';
    }

    if(typeof config.latte_dir === 'undefined') {
      config.latte_dir = config.www_dir;
    }

    if(typeof config.publish_dir === 'undefined') {
      config.publish_dir = 'publish';
    }

    if(typeof config.temp_dir === 'undefined') {
      config.temp_dir = require('os').tmpdir() + '/ristretto-'+version;
    }

    if(grunt.file.exists(config.temp_dir)) {
      if(!grunt.file.isDir(config.temp_dir)) {
        grunt.log.error('Temporary dir path is not a directory: `' + config.temp_dir + '`.');
      }
    } else {
      grunt.file.mkdir(config.temp_dir);
    }

    var flags = this.flags;
    var done = this.async();

    var request = require('request');

    if(flags['reload'] || flags['pages']) {
      request('http://127.0.0.1:'+config.port+'/reload', function(){
        done();
      });
    return;
    } else if(flags['reload-stylesheets'] || flags['styles'] || flags['stylesheets']) {
      request('http://127.0.0.1:'+config.port+'/reload-stylesheets', function(){
        done();
      });
      return;
    } else if(flags['publish']) {
      publish(config, function(){
        done();
      });
    return;
    } else if(flags['startup']) {
      require('../libs/server').startup(config, function() {
        console.log('Ristretto running on 127.0.0.1:'+config.port);
        done();
      });
    return;
    }

  });

};<commit_msg>Fixed publish of NE-ON files (converting to json)<commit_after>/*
 * grunt-ristretto
 *
 * Copyright (c) 2013 Viliam Kopecky
 * Licensed under the MIT license.
 */

'use strict';

// show debug info on error
process.on('uncaughtException', function(err) {
    console.log(err.stack);
});

module.exports = function(grunt) {

  var fs = require('fs');
  var path = require('path');

  var metafilename = '.ristretto.json';

  var allow_publish = function(dir, meta) {
    var allow_write = false;

    if(grunt.file.exists(dir)) { // publish dir/file exists
      if(grunt.file.isDir(dir)) { // is directory
        if(grunt.file.exists(meta)) { // contains ristretto metadata
          allow_write = true;
        } else { // does not contain ristretto metadata
          if(grunt.file.expand([dir+'/**.*']).length === 0) { // directory is empty
            allow_write = true;
          } else { // directory is not empty, but doesn't contain ristretto metadata
            allow_write = true; //grunt.warn('Publish direrctory "'+dir+'" is not empty.');
          }
        }
      } else { // publish dir is not a directory
        grunt.warn('File '+dir+' already exists and is not a directory.');
      }
    } else { // publish dir doesn't exist
      allow_write = true;
    }
    return allow_write;
  };

  var build_and_copy = function(options, params, dest, meta, done) {

    var php_script = require('../libs/php_script');

    var latte2html = php_script.latte2html;
    var neon2json = php_script.neon2json;

    var copy_files = grunt.file.expand({ cwd: params.www_dir }, ['**/*.*', '**/.*', '!**/*.latte', '!**/*.neon']);
    var neon_files = grunt.file.expand({ cwd: params.model_dir }, ['**/*.neon']);
    var latte_files = grunt.file.expand({ cwd: params.latte_dir }, ['**/*.latte', '!**/@*.latte']);

    var next_total = 1;
    var next = function() {
      if(next_total === 3) {
          grunt.file.write(meta, JSON.stringify({ 'published_by': 'Ristretto', 'timestamp': (new Date()).getTime() }));
          grunt.log.writeln('');
          grunt.log.ok('Publish finished', meta);
          grunt.log.writeln('  ', dest);
          return done();
      }
      next_total++;
    };

    var published_copy = 0;
    var next_copy = function(){
      if(published_copy === copy_files.length) {
        grunt.log.ok('Finished: Copy static files');
        next();
        return;
      }
      var filepath = copy_files[published_copy];

      if(grunt.file.isFile(params.www_dir + '/' + filepath)) {
        grunt.log.writeln('   Copy file', filepath);

        grunt.file.copy(params.www_dir + '/' + filepath, dest + filepath);
      }
      published_copy++;
      next_copy();
    };
    next_copy();

    var published_latte = 0;
    var next_latte = function(){
      if(published_latte === latte_files.length) {
        grunt.log.ok('Finished: Compile Latte files');
        next();
        return;
      }
      var filepath = latte_files[published_latte];
      grunt.log.writeln('   Compiling Latte file', filepath);

      latte2html(options, filepath, function(body){
        var write = dest + filepath.substr(0, filepath.length - 'latte'.length) + 'html';
        grunt.log.writeln('   Writing Latte file', filepath);
        grunt.file.write(write, body);
        published_latte++;
        next_latte();
      });
    };
    next_latte();

    var published_neon = 0;
    var next_neon = function(){
      if(published_neon === neon_files.length) {
        grunt.log.ok('Finished: Compile NE-ON files');
        next();
        return;
      }
      var filepath = neon_files[published_neon];
      grunt.log.writeln('   Compiling NE-ON file', filepath);

      var realpath = options.model_dir + '/' + filepath;

      realpath = fs.realpathSync(realpath);

      neon2json(options, realpath, function(body){
        var model_dest = dest;
        if(options.model_dir.indexOf(options.www_dir) === 0) {
          model_dest += options.model_dir.substr(options.www_dir.length+1);
        } else {
          model_dest += options.model_dir;
        }
        grunt.log.writeln('   Writing NE-ON file', filepath);
        var write = model_dest + '/' +filepath;
        grunt.file.write(write, body);
        published_neon++;
        next_neon();
      });
    };
    next_neon();
  };

  var publish = function(options, done) {
    var dest = options.publish_dir + '/';
    dest = dest.replace('//', '/');

    var meta = dest + metafilename;

    var params = {
      www_dir: fs.realpathSync(options.www_dir),
      latte_dir: fs.realpathSync(options.latte_dir),
      temp_dir: fs.realpathSync(options.temp_dir)
    };

    if(options.model_dir && grunt.file.exists(options.model_dir)) {
      params.model_dir = fs.realpathSync(options.model_dir);
    }

    if(!allow_publish(dest, meta)) {
      done();
      return;
    }

    var created = false;
    if(!grunt.file.exists(dest)) {
      created = true;
      grunt.file.mkdir(dest);
    }

    if(grunt.file.isPathInCwd(dest)) {
      grunt.file.delete(dest);
      build_and_copy(options, params, dest, meta, done);
    } else {
      console.log('');
      grunt.log.warn('You are publishing into directory outside of CWD. This action will overwrite its contents.');
      grunt.log.warn(dest);
      require('co-prompt').confirm("\n   Are you sure? [ NO | yes ]: ")(function(wut, ok) {
        if(ok) {
          var time = (new Date).getTime();
          var temp_dest = dest.replace(/\/*$/, '') + '-ristretto-' + time;

          if(grunt.file.exists(dest)) {
            if(created) {
              grunt.file.delete(dest, { force: true });
            } else {
              require('fs').renameSync(dest, temp_dest);
            }
          }

          grunt.log.ok('Original contents moved to:');
          grunt.log.ok(temp_dest);

          build_and_copy(options, params, dest, meta, done);
        } else {
          console.log('');
          grunt.log.ok('Publish aborted');
          done();
        }
      });
    }

  };

  grunt.registerTask('ristretto', 'Ristretto frontend prototyping system', function() {
    var options = this.options();
    var config = options.config;

    var version = config.ristretto_version = grunt.file.readJSON(__dirname + '/../package.json').version;

    if(typeof config.port === 'undefined') {
      config.port = 8000;
    }

    if(typeof config.www_dir === 'undefined') {
      config.www_dir = '.';
    }

    if(typeof config.model_dir === 'undefined') {
      config.model_dir = config.www_dir + '/model';
    }

    if(typeof config.latte_dir === 'undefined') {
      config.latte_dir = config.www_dir;
    }

    if(typeof config.publish_dir === 'undefined') {
      config.publish_dir = 'publish';
    }

    if(typeof config.temp_dir === 'undefined') {
      config.temp_dir = require('os').tmpdir() + '/ristretto-'+version;
    }

    if(grunt.file.exists(config.temp_dir)) {
      if(!grunt.file.isDir(config.temp_dir)) {
        grunt.log.error('Temporary dir path is not a directory: `' + config.temp_dir + '`.');
      }
    } else {
      grunt.file.mkdir(config.temp_dir);
    }

    var flags = this.flags;
    var done = this.async();

    var request = require('request');

    if(flags['reload'] || flags['pages']) {
      request('http://127.0.0.1:'+config.port+'/reload', function(){
        done();
      });
    return;
    } else if(flags['reload-stylesheets'] || flags['styles'] || flags['stylesheets']) {
      request('http://127.0.0.1:'+config.port+'/reload-stylesheets', function(){
        done();
      });
      return;
    } else if(flags['publish']) {
      publish(config, function(){
        done();
      });
    return;
    } else if(flags['startup']) {
      require('../libs/server').startup(config, function() {
        console.log('Ristretto running on 127.0.0.1:'+config.port);
        done();
      });
    return;
    }

  });

};<|endoftext|>