<commit_before>'use strict';

var path = require('path');

var express = require('express');
var router = express.Router();

var Gherkin = require('gherkin');
var Parser = new Gherkin.Parser();
var markdown = require('markdown').markdown;

var arrrayToTree = require('file-tree');
var TreeModel = require('tree-model');

var getProject = require('../lib/specifications/project').get;
var getProjectData = require('../lib/specifications/project').getData;
var getFileContents = require('../lib/specifications/project').getFileContents;

var appConfig = require('../lib/configuration').get();

// Given a file path, generate additional data or promises for data.
function getFilePathToFileData(appConfig, projectData, getFileContents) {
  return function filePathToFileData(filePath) {
    var file = {};

    file.name = path.basename(filePath);
    file.filePath = filePath;

    file.route = path.posix.join(appConfig.projectRoute, projectData.repoName, filePath);

    file.isFeatureFile = /.*\.feature/.test(filePath);
    file.isMarkdownFile = /.*\.md/.test(filePath);

    if (file.isFeatureFile || file.isMarkdownFile) {
      file.contentsPromise = getFileContents(projectData, filePath);
    } else {
      file.contentsPromise = undefined;
    }

    return file;
  };
}

// Given some file content process it into the relevant data structure.
function getProcessFileContent(fileContents) {
  return function processFileContent(file, index) {
    var fileContent = fileContents[index];

    if (!fileContent || !fileContent.length) {
      file.empty = true;
    }

    if (file.isFeatureFile) {
      try {
        file.data = Parser.parse(fileContent);
      } catch (err) {
        file.error = err;
      }
    } else if(file.isMarkdownFile) {
      file.data = markdown.parse(fileContent);
    } else {
      file.data = false;
    }

    return file;
  };
}

// Render the project page and send to client.
function getRender(res, appConfig, renderOptions) {
  return function render(projectData) {
    var renderingData = {};
    var view = {};
    var viewNames = [];

    renderingData.openBurgerMenu = renderOptions.openBurgerMenu;

    // Handle no project data being found.
    if (!projectData) {
      res.render('project', renderingData);
      return;
    }

    renderingData['project'] = projectData;

    // If there are no files in the project then don't
    // try and get file contents.
    if (!projectData.files.length) {
      res.render('project', renderingData);
      return;
    }

    // If the project config contains specified views use them.
    if (projectData.config) {
      viewNames = Object.keys(projectData.config.views);
    }
    if (viewNames.length > 0) {
      renderingData.hasViews = true;
      renderingData.viewNames = viewNames.map(function (viewName) {
        return {
          name: viewName,
          urlEncodedName: encodeURIComponent(viewName),
          isCurrent: viewName === renderOptions.currentView
        };
      });

      // Grab any view config that might have been specified in the project config.
      view = renderingData.view = projectData.config.views[renderOptions.currentView];

      // Filter the file list based on the excludedPaths in project config.
      if (view && view.hasExcludedPaths) {
        projectData.files = projectData.files.filter(view.helpers.isIncludedPath);
      }
    }

    // Configure function for mapping file paths to file data.
    var pathToData = getFilePathToFileData(appConfig, projectData, getFileContents);

    // Make a copy of the simple file list before modifying it.
    var fileList = projectData.files.slice();

    // Map list of file paths to list of file data objects.
    projectData.files = projectData.files.map(pathToData);

    // Wait for content promises to resolve then mix
    // in the resolved file content.
    var promisesForFileContent = projectData.files.map(function(f) {return f.contentsPromise;});
    return Promise.all(promisesForFileContent)
      .then(function(fileContents) {

        // Mix in the file content.
        projectData.files = projectData.files.map(getProcessFileContent(fileContents));

        // Generate a file tree data structure.
        arrrayToTree(fileList, function(filePath, next) {

          // Fix the assumption in file-tree that we are dealing with actual
          // files on disk.
          filePath = path.relative(appConfig.rootPath, filePath);

          // Use a loop to find the file matching this part of the tree.
          var currentFile = projectData.files.filter(function(file) {
            return filePath === file.filePath;
          })[0];

          // Link the file list and the tree structure by reference.
          var leaf = {
            name: filePath,
            file: currentFile,
            isFile: true
          };

          // Continue to generate the tree.
          next(null, leaf);
        }, function(err, fileTree) {

          // Tree generation is complete.
          // Wrap in tree model convenience object.
          var treeRoot = (new TreeModel()).parse({name: 'root', children: fileTree});

          // Use the tree to construct a set of files by directory.
          var filesByDir = {};
          var fileNodes = treeRoot.all(function(node) { return node.model.isFile; });
          fileNodes.forEach(function(fileNode) {
            var pathToNode = fileNode.getPath();

            // Derive a directory path.
            var directoryNames = pathToNode
                                  .map(function(node) {
                                    var model = node.model;
                                    if (!node.isRoot() && !model.isFile) {
                                      return node.model.name;
                                    }
                                    return '';
                                  });
            var directoryPath = path.join.apply(path, directoryNames);

            // Store the file data keyed by containing directory.
            if (!filesByDir[directoryPath]) {
              filesByDir[directoryPath] = [];
            }
            filesByDir[directoryPath].push(fileNode.model.file);
          });

          // Reference the finished file tree on the rendering data object.
          renderingData['project'].filesByDir = filesByDir;

          // Render the page.
          res.render('project', renderingData);
        });
      });
  };
}

// Pass errors to the next Express middleware for handling.
function getPassError(next) {
  return function passError(err) {
    next(err);
  };
}

// List of available features in a project.
router.get(/^\/([^\/]+)$/, function(req, res, next) {

  // Cookie variables.
  var openBurgerMenu = (req.cookies.specsOpenBurgerMenu === 'true');

  // Session variable.
  if(!req.session.branches) req.session.branches = {};
  var sessionBranches = req.session.branches;

  // The repository name from the URL.
  var repoName = req.params[0];

  // Query param indicating a particular ref should
  // be used when retrieving repo data.
  var targetBranchName = req.query.branch || false;

  // Query param causing a Git fetch.
  var projectShouldUpdate = (req.query.update === 'true');

  // Query parameter containing desired named view from project config.
  var currentView = req.query.view || false;

  // Create rendering options.
  var renderOptions = {
    openBurgerMenu: openBurgerMenu,
    currentView: currentView
  };

  // Create the render and passError functions.
  var configuredRender = getRender(res, appConfig, renderOptions);
  var configuredPassError = getPassError(next);

  // TODO: Have one place this object is created.
  var projectData = {
    repoName: repoName,
    projectLink: path.posix.join(appConfig.projectRoute, repoName),
    localPath: path.join(appConfig.projectsPath, repoName)
  };

  // Perform a clone or fetch on the repo then get the data.
  // If this switch is set then the branch will not change.
  if (projectShouldUpdate) {

    // Set the current branch name which will be used in the update.
    // If not supplied the repo default branch will be used.
    projectData.currentBranchName = sessionBranches[repoName] || false;

    // Update the repo and get the repo data.
    getProject(projectData)
      .then(configuredRender)
      .catch(configuredPassError);

  // Change the branch.
  } else if (targetBranchName && targetBranchName !== sessionBranches[repoName]) {
    getProjectData(projectData, targetBranchName)
      .then(function(projectData) {

        // The data for the target branch was retrieved succesfully,
        // Update the branch session variable. Done here rather than
        // earlier to avoid bad requests (nonsense refs) persisting.
        sessionBranches[repoName] = projectData.currentBranchName;
        return projectData;
      })
      .then(configuredRender)
      .catch(configuredPassError);

  // Else, generate the metadata and render the page.
  } else {
    getProjectData(projectData, sessionBranches[repoName])
      .then(configuredRender)
      .catch(configuredPassError);
  }
});

module.exports = router;
<commit_msg>Add support for using default views when no view is specified.<commit_after>'use strict';

var path = require('path');

var express = require('express');
var router = express.Router();

var Gherkin = require('gherkin');
var Parser = new Gherkin.Parser();
var markdown = require('markdown').markdown;

var arrrayToTree = require('file-tree');
var TreeModel = require('tree-model');

var getProject = require('../lib/specifications/project').get;
var getProjectData = require('../lib/specifications/project').getData;
var getFileContents = require('../lib/specifications/project').getFileContents;

var appConfig = require('../lib/configuration').get();

// Given a file path, generate additional data or promises for data.
function getFilePathToFileData(appConfig, projectData, getFileContents) {
  return function filePathToFileData(filePath) {
    var file = {};

    file.name = path.basename(filePath);
    file.filePath = filePath;

    file.route = path.posix.join(appConfig.projectRoute, projectData.repoName, filePath);

    file.isFeatureFile = /.*\.feature/.test(filePath);
    file.isMarkdownFile = /.*\.md/.test(filePath);

    if (file.isFeatureFile || file.isMarkdownFile) {
      file.contentsPromise = getFileContents(projectData, filePath);
    } else {
      file.contentsPromise = undefined;
    }

    return file;
  };
}

// Given some file content process it into the relevant data structure.
function getProcessFileContent(fileContents) {
  return function processFileContent(file, index) {
    var fileContent = fileContents[index];

    if (!fileContent || !fileContent.length) {
      file.empty = true;
    }

    if (file.isFeatureFile) {
      try {
        file.data = Parser.parse(fileContent);
      } catch (err) {
        file.error = err;
      }
    } else if(file.isMarkdownFile) {
      file.data = markdown.parse(fileContent);
    } else {
      file.data = false;
    }

    return file;
  };
}

// Render the project page and send to client.
function getRender(res, appConfig, renderOptions) {
  return function render(projectData) {
    var renderingData = {};
    var view = {};
    var viewNames = [];
    var currentView;
    var defaultName;

    renderingData.openBurgerMenu = renderOptions.openBurgerMenu;

    // Handle no project data being found.
    if (!projectData) {
      res.render('project', renderingData);
      return;
    }

    renderingData['project'] = projectData;

    // If there are no files in the project then don't
    // try and get file contents.
    if (!projectData.files.length) {
      res.render('project', renderingData);
      return;
    }

    // If the project config contains specified views use them.
    currentView = renderOptions.currentView;
    if (projectData.config) {
      viewNames = Object.keys(projectData.config.views);
    }

    if (viewNames.length > 0) {
      renderingData.hasViews = true;

      // No view specified, attempt to use a DEFAULT view.
      if (currentView === false) {
        // The defaultView value may be undefined, that will result in no view logic being applied.
        currentView = viewNames
                        .filter(function(name) {
                          return !!projectData.config.views[name].default;
                        })[0] || false;
      }

      // Generate view name data for the UI.
      renderingData.viewNames = viewNames.map(function (viewName) {
        return {
          name: viewName,
          urlEncodedName: encodeURIComponent(viewName),
          isCurrent: viewName === currentView
        };
      });

      // Explicit request for no view logic to be applied.
      if (currentView === 'none') {
        view = renderingData.view = false;

      // Grab any view config that might have been specified in the project config.
      } else {
        view = renderingData.view = projectData.config.views[currentView];
      }

      // Filter the file list based on the excludedPaths in project config.
      if (view && view.hasExcludedPaths) {
        projectData.files = projectData.files.filter(view.helpers.isIncludedPath);
      }
    }

    // Configure function for mapping file paths to file data.
    var pathToData = getFilePathToFileData(appConfig, projectData, getFileContents);

    // Make a copy of the simple file list before modifying it.
    var fileList = projectData.files.slice();

    // Map list of file paths to list of file data objects.
    projectData.files = projectData.files.map(pathToData);

    // Wait for content promises to resolve then mix
    // in the resolved file content.
    var promisesForFileContent = projectData.files.map(function(f) {return f.contentsPromise;});
    return Promise.all(promisesForFileContent)
      .then(function(fileContents) {

        // Mix in the file content.
        projectData.files = projectData.files.map(getProcessFileContent(fileContents));

        // Generate a file tree data structure.
        arrrayToTree(fileList, function(filePath, next) {

          // Fix the assumption in file-tree that we are dealing with actual
          // files on disk.
          filePath = path.relative(appConfig.rootPath, filePath);

          // Use a loop to find the file matching this part of the tree.
          var currentFile = projectData.files.filter(function(file) {
            return filePath === file.filePath;
          })[0];

          // Link the file list and the tree structure by reference.
          var leaf = {
            name: filePath,
            file: currentFile,
            isFile: true
          };

          // Continue to generate the tree.
          next(null, leaf);
        }, function(err, fileTree) {

          // Tree generation is complete.
          // Wrap in tree model convenience object.
          var treeRoot = (new TreeModel()).parse({name: 'root', children: fileTree});

          // Use the tree to construct a set of files by directory.
          var filesByDir = {};
          var fileNodes = treeRoot.all(function(node) { return node.model.isFile; });
          fileNodes.forEach(function(fileNode) {
            var pathToNode = fileNode.getPath();

            // Derive a directory path.
            var directoryNames = pathToNode
                                  .map(function(node) {
                                    var model = node.model;
                                    if (!node.isRoot() && !model.isFile) {
                                      return node.model.name;
                                    }
                                    return '';
                                  });
            var directoryPath = path.join.apply(path, directoryNames);

            // Store the file data keyed by containing directory.
            if (!filesByDir[directoryPath]) {
              filesByDir[directoryPath] = [];
            }
            filesByDir[directoryPath].push(fileNode.model.file);
          });

          // Reference the finished file tree on the rendering data object.
          renderingData['project'].filesByDir = filesByDir;

          // Render the page.
          res.render('project', renderingData);
        });
      });
  };
}

// Pass errors to the next Express middleware for handling.
function getPassError(next) {
  return function passError(err) {
    next(err);
  };
}

// List of available features in a project.
router.get(/^\/([^\/]+)$/, function(req, res, next) {

  // Cookie variables.
  var openBurgerMenu = (req.cookies.specsOpenBurgerMenu === 'true');

  // Session variable.
  if(!req.session.branches) req.session.branches = {};
  var sessionBranches = req.session.branches;

  // The repository name from the URL.
  var repoName = req.params[0];

  // Query param indicating a particular ref should
  // be used when retrieving repo data.
  var targetBranchName = req.query.branch || false;

  // Query param causing a Git fetch.
  var projectShouldUpdate = (req.query.update === 'true');

  // Query parameter containing desired named view from project config.
  var currentView = req.query.view || false;

  // Create rendering options.
  var renderOptions = {
    openBurgerMenu: openBurgerMenu,
    currentView: currentView
  };

  // Create the render and passError functions.
  var configuredRender = getRender(res, appConfig, renderOptions);
  var configuredPassError = getPassError(next);

  // TODO: Have one place this object is created.
  var projectData = {
    repoName: repoName,
    projectLink: path.posix.join(appConfig.projectRoute, repoName),
    localPath: path.join(appConfig.projectsPath, repoName)
  };

  // Perform a clone or fetch on the repo then get the data.
  // If this switch is set then the branch will not change.
  if (projectShouldUpdate) {

    // Set the current branch name which will be used in the update.
    // If not supplied the repo default branch will be used.
    projectData.currentBranchName = sessionBranches[repoName] || false;

    // Update the repo and get the repo data.
    getProject(projectData)
      .then(configuredRender)
      .catch(configuredPassError);

  // Change the branch.
  } else if (targetBranchName && targetBranchName !== sessionBranches[repoName]) {
    getProjectData(projectData, targetBranchName)
      .then(function(projectData) {

        // The data for the target branch was retrieved succesfully,
        // Update the branch session variable. Done here rather than
        // earlier to avoid bad requests (nonsense refs) persisting.
        sessionBranches[repoName] = projectData.currentBranchName;
        return projectData;
      })
      .then(configuredRender)
      .catch(configuredPassError);

  // Else, generate the metadata and render the page.
  } else {
    getProjectData(projectData, sessionBranches[repoName])
      .then(configuredRender)
      .catch(configuredPassError);
  }
});

module.exports = router;
<|endoftext|>


<commit_before>        $(function () {

                //           $(window).scroll(function () {
                //                if ($(window).scrollTop() >= 100) {
                //                    $('.actGotop').fadeIn(300);
                //                } else {
                //                    $('.actGotop').fadeOut(300);
                //                }
                //                var p_top = 750;
                //                if ($(window).scrollTop() > p_top) {
                //                    $(".visible-md").addClass("person-fix");
                //                } else {
                //                    $(".visible-md").removeClass("person-fix");
                //                }
                //            });
                //            $('.actGotop').click(function () {
                //                $('html,body').animate({
                //                    scrollTop: '0px'
                //                }, 800);
                //            });
                //足球展开交互

                $(".t-img").on("click", function () {
                    $(this).parents(".show-tips").removeClass("ani-delay").addClass("soccer-hide");
                    $(this).siblings(".tools").addClass("tools-show");
                });
                $(".t-close").on("click", function () {
                    $(this).parents(".tools").removeClass("tools-show");
                    $(this).parents(".show-tips").addClass("ani-delay").removeClass("soccer-hide");
                });

                //导航交互
                var MQL = 1170;

                //primary navigation slide-in effect

                if ($(window).width() > MQL) {
                    var headerHeight = $('.navbar-custom').height();
                    $(window).on('scroll', {
                            previousTop: 0
                        },
                        function () {
                            var currentTop = $(window).scrollTop();
                            //check if user is scrolling up
                            if (currentTop < this.previousTop) {
                                //if scrolling up...
                                if (currentTop > 0 && $('.navbar-custom').hasClass('is-fixed')) {
                                    $('.navbar-custom').addClass('is-visible');
                                } else {
                                    $('.navbar-custom').removeClass('is-visible is-fixed');
                                }
                            } else {
                                //if scrolling down...
                                $('.navbar-custom').removeClass('is-visible');
                                if (currentTop > headerHeight && !$('.navbar-custom').hasClass('is-fixed')) $('.navbar-custom').addClass('is-fixed');
                            }
                            this.previousTop = currentTop;
                        });
                }

                //css动画抖动
                var windowH = $(window).height(),
                    bodyH = $("body").height();
                if (bodyH <= windowH) {
                    $("body").addClass("overflow");
                } else {
                    $("body").removeClass("overflow");
                }
                // 首页背景
                fixBg();
                $(window).resize(function () {
                    fixBg();
                })

                function fixBg() {
                    var win = $(window).width(),
                        winH = $(window).height();
                    if (win > 1024) {
                        $('#home-bg').style('height', winH);
                    }
                })
        }<commit_msg>修复bug<commit_after>        $(function () {

                //           $(window).scroll(function () {
                //                if ($(window).scrollTop() >= 100) {
                //                    $('.actGotop').fadeIn(300);
                //                } else {
                //                    $('.actGotop').fadeOut(300);
                //                }
                //                var p_top = 750;
                //                if ($(window).scrollTop() > p_top) {
                //                    $(".visible-md").addClass("person-fix");
                //                } else {
                //                    $(".visible-md").removeClass("person-fix");
                //                }
                //            });
                //            $('.actGotop').click(function () {
                //                $('html,body').animate({
                //                    scrollTop: '0px'
                //                }, 800);
                //            });
                //足球展开交互

                $(".t-img").on("click", function () {
                    $(this).parents(".show-tips").removeClass("ani-delay").addClass("soccer-hide");
                    $(this).siblings(".tools").addClass("tools-show");
                });
                $(".t-close").on("click", function () {
                    $(this).parents(".tools").removeClass("tools-show");
                    $(this).parents(".show-tips").addClass("ani-delay").removeClass("soccer-hide");
                });

                //导航交互
                var MQL = 1170;

                //primary navigation slide-in effect

                if ($(window).width() > MQL) {
                    var headerHeight = $('.navbar-custom').height();
                    $(window).on('scroll', {
                            previousTop: 0
                        },
                        function () {
                            var currentTop = $(window).scrollTop();
                            //check if user is scrolling up
                            if (currentTop < this.previousTop) {
                                //if scrolling up...
                                if (currentTop > 0 && $('.navbar-custom').hasClass('is-fixed')) {
                                    $('.navbar-custom').addClass('is-visible');
                                } else {
                                    $('.navbar-custom').removeClass('is-visible is-fixed');
                                }
                            } else {
                                //if scrolling down...
                                $('.navbar-custom').removeClass('is-visible');
                                if (currentTop > headerHeight && !$('.navbar-custom').hasClass('is-fixed')) $('.navbar-custom').addClass('is-fixed');
                            }
                            this.previousTop = currentTop;
                        });
                }

                //css动画抖动
                var windowH = $(window).height(),
                    bodyH = $("body").height();
                if (bodyH <= windowH) {
                    $("body").addClass("overflow");
                } else {
                    $("body").removeClass("overflow");
                }
                // 首页背景
                fixBg();
                $(window).resize(function () {
                    fixBg();
                })

                function fixBg() {
                    var win = $(window).width(),
                        winH = $(window).height();
                    if (win > 1024) {
                        $('#home-bg').css('height', winH);
                    }
                })
        }<|endoftext|>


<commit_before>module.change_code = 1; // this allows hotswapping of code (ignored in production)

var swig = require("swig");
var request = require("request");
var SnippetDemo = require("biojs-util-snippets").demo;
var snipResponse = require("./snippets/response.js");
var join = require("path").join;
var errors = require("./errors");
var mime = require("mime");

var RequestCaching = require("node-request-caching");
var rc = new RequestCaching();

var snip = {};

function searchErrorWrapper(err, res) {
  if (!err) {
    err = {};
  }
  if (!err.details) {
    err.details = {};
  }
  err.details.res = res;
  errors.searchForError(err.code, err.details);
}

snip.demo = function(req, res) {
  var name = req.params.name;
  var currentSnip = req.params.snip;
  var additionalPath = req.params[0];
  var hasExtension = currentSnip.indexOf(".") >= 0 || additionalPath !== undefined;

  global.db.db().find({
    name: name
  }).exec(function(err, pkgs) {
    if (pkgs.length === 0 || pkgs[0].latest.sniper === undefined) {
      res.send({
        error: "no snips"
      });
      return;
    }
    var pkg = pkgs[0];
    // if there is a file extension - we probably want to load it from github
    // TODO: distinguish between multiple folders
    if (hasExtension) {
      if (pkg.repository !== undefined && pkg.repository.github !== undefined) {
        // TOOD: use default github branch
        var snippetPath = currentSnip;
        if (additionalPath !== undefined) {
          snippetPath = join(currentSnip, additionalPath);
        }
        serveGithubFile(pkg.repository.github, join("master", pkg.latest.sniper.snippets[0], snippetPath), res);
      } else {
        errors.unknownSnippetFile({
          pkg: pkg,
          currentSnip: currentSnip,
          req: req,
          res: res
        });
        return;
      }
    } else {
      var s = new SnippetDemo({
        pkg: pkg,
        snippetName: currentSnip,
        services: services
      }).then(function(item) {
        snipResponse._demoFill(res, item, pkg);
      }).catch(function(err) {
        searchErrorWrapper(err, res);
      });
    }
  });
};

// https://github.com/jsbin/jsbin/blob/v1.0.0/index.php#L77
snip.jsbin = function(req, res) {
  snip.edit(req, res, function(snip) {
    var js = snip.inlineScript;
    var body = swig.renderFile(__dirname + "/../templates/header.html", {
      scripts: snip.js,
      css: snip.css
    });
    body += "\n" + snip.inlineBody;
    res.render("jsbin", {
      html: body,
      js: js,
      redirectURL: "http://jsbin.com?js,output"
    });
  });
};

// http://blog.codepen.io/documentation/api/prefill/
snip.codepen = function(req, res) {
  snip.edit(req, res, function(snip) {
    var js = snip.inlineScript;
    var body = swig.renderFile(__dirname + "/../templates/header.html", {
      scripts: snip.js,
      css: snip.css
    });
    body += "\n" + snip.inlineBody;
    var obj = {
      js: js,
      html: body
    };
    obj = JSON.stringify(obj);
    obj = obj.replace(/"/g, '\"'); // unscrew quotes
    res.render("codepen", {
      obj: obj,
      redirectURL: "http://codepen.io/pen/define"
    });
  });
};

// https://github.com/angular/angular.js/issues/7166
snip.plunker = function(req, res) {
  snip.edit(req, res, function(snp) {
    var js = snp.inlineScript;
    var body = swig.renderFile(__dirname + "/../templates/header.html", {
      scripts: snp.js,
      css: snp.css
    });
    body += "\n" + snp.inlineBody;
    body += "\n<script src='main.js'></script>";
    var files = {
      js: js,
      html: body
    };
    res.render("plunker", {
      files: files,
      description: "A BioJS example",
      tags: ["biojs", snp.name],
      redirectURL: "http://plnkr.co/edit/"
    });
  });
};

snip.edit = function(req, res, callback) {
  var name = req.params.name;
  var currentSnip = req.params.snip;
  global.db.db().find({
    name: name
  }).exec(function(err, pkg) {
    if (pkg.length === 0 || pkg[0].latest.sniper == undefined) {
      res.send({
        error: "no snips"
      });
      return;
    }
    var s = new SnippetDemo({
      pkg: pkg[0],
      snippetName: currentSnip,
      services: services
    }).then(function(snp) {
      snipResponse.removeTags(snp);
      var githubRegex = /\/github\//g;
      for (var i in snp.js) {
        snp.js[i] = snp.js[i].replace(githubRegex, services.ghProxy);
      }
      for (var i in snp.css) {
        snp.css[i] = snp.css[i].replace(githubRegex, services.ghProxy);
      }
      snp.inlineScript = snp.inlineScript.replace(githubRegex, services.ghProxy);
      snp.inlineBody = snp.inlineBody.replace(githubRegex, services.ghProxy);
      callback(snp);
    }).catch(function(err) {
      searchErrorWrapper(err, res);
    });
  });
};

// list available snips
snip.overview = function(req, res) {
  var name = req.params.name;
  var currentSnip = req.params.snip;
  global.db.db().find({
    name: name
  }).exec(function(err, pkg) {
    if (pkg.length === 0 || pkg[0].latest.sniper == undefined) {
      errors.noSnippets({
        pkg: pkg,
        currentSnip: currentSnip,
        req: req,
        res: res
      });
      return;
    }
    pkg = pkg[0];
    var baseURL = req.protocol + '://' + req.get('host') + req.originalUrl;
    // remove path at the end
    if (baseURL.charAt(baseURL.length - 1) !== "/") {
      baseURL += "/";
    }
    if (pkg.latest.sniper.srcs === undefined) {
      errors.unknownSnippetFile({
        pkg: pkg,
        currentSnip: currentSnip,
        req: req,
        res: res
      });
      return;
    }
    var snips = Object.keys(pkg.latest.sniper.srcs);
    res.render("list", {
      snips: snips,
      baseHref: baseURL
    });
  });
};

// simple github proxy
snip.github = function(req, res) {
  serveGithubFile({
    user: req.params.name,
    repo: req.params.repo
  }, req.params[0], res);
};

function serveGithubFile(pkg, path, res) {
  var url = "https://raw.githubusercontent.com/" + pkg.user + "/" + pkg.repo + "/" + path;
  var type = mime.lookup(url);
  res.set('Content-Type', type);
  // proxy the data from github
  var ttl = 180; // in s
  rc.get(url, {}, ttl, function(err, resp, body, cache) {
    if (cache.hit) {
      log.verbose("serving github file (from cache)", pkg, path);
    } else {
      log.verbose("serving github file (new to cache)", pkg, path);
    }
    res.send(body);
  });
  //request(url).pipe(res);
  //request.get(url, function(err, response, body) {
  //res.send(body);
  //});
}

var log;
var services;
module.exports = function(opts) {
  log = opts.log;
  services = opts.services;
  return snip;
};
<commit_msg>ignore errors without messages<commit_after>module.change_code = 1; // this allows hotswapping of code (ignored in production)

var swig = require("swig");
var request = require("request");
var SnippetDemo = require("biojs-util-snippets").demo;
var snipResponse = require("./snippets/response.js");
var join = require("path").join;
var errors = require("./errors");
var mime = require("mime");

var RequestCaching = require("node-request-caching");
var rc = new RequestCaching();

var snip = {};

function searchErrorWrapper(err, res) {
  if (err == undefined) {
    err = {};
  }
  if (err.details == undefined) {
    err.details = {};
  }
  err.details.res = res;
  errors.searchForError(err.code, err.details);
}

snip.demo = function(req, res) {
  var name = req.params.name;
  var currentSnip = req.params.snip;
  var additionalPath = req.params[0];
  var hasExtension = currentSnip.indexOf(".") >= 0 || additionalPath !== undefined;

  global.db.db().find({
    name: name
  }).exec(function(err, pkgs) {
    if (pkgs.length === 0 || pkgs[0].latest.sniper === undefined) {
      res.send({
        error: "no snips"
      });
      return;
    }
    var pkg = pkgs[0];
    // if there is a file extension - we probably want to load it from github
    // TODO: distinguish between multiple folders
    if (hasExtension) {
      if (pkg.repository !== undefined && pkg.repository.github !== undefined) {
        // TOOD: use default github branch
        var snippetPath = currentSnip;
        if (additionalPath !== undefined) {
          snippetPath = join(currentSnip, additionalPath);
        }
        serveGithubFile(pkg.repository.github, join("master", pkg.latest.sniper.snippets[0], snippetPath), res);
      } else {
        errors.unknownSnippetFile({
          pkg: pkg,
          currentSnip: currentSnip,
          req: req,
          res: res
        });
        return;
      }
    } else {
      var s = new SnippetDemo({
        pkg: pkg,
        snippetName: currentSnip,
        services: services
      }).then(function(item) {
        snipResponse._demoFill(res, item, pkg);
      }).catch(function(err) {
        searchErrorWrapper(err, res);
      });
    }
  });
};

// https://github.com/jsbin/jsbin/blob/v1.0.0/index.php#L77
snip.jsbin = function(req, res) {
  snip.edit(req, res, function(snip) {
    var js = snip.inlineScript;
    var body = swig.renderFile(__dirname + "/../templates/header.html", {
      scripts: snip.js,
      css: snip.css
    });
    body += "\n" + snip.inlineBody;
    res.render("jsbin", {
      html: body,
      js: js,
      redirectURL: "http://jsbin.com?js,output"
    });
  });
};

// http://blog.codepen.io/documentation/api/prefill/
snip.codepen = function(req, res) {
  snip.edit(req, res, function(snip) {
    var js = snip.inlineScript;
    var body = swig.renderFile(__dirname + "/../templates/header.html", {
      scripts: snip.js,
      css: snip.css
    });
    body += "\n" + snip.inlineBody;
    var obj = {
      js: js,
      html: body
    };
    obj = JSON.stringify(obj);
    obj = obj.replace(/"/g, '\"'); // unscrew quotes
    res.render("codepen", {
      obj: obj,
      redirectURL: "http://codepen.io/pen/define"
    });
  });
};

// https://github.com/angular/angular.js/issues/7166
snip.plunker = function(req, res) {
  snip.edit(req, res, function(snp) {
    var js = snp.inlineScript;
    var body = swig.renderFile(__dirname + "/../templates/header.html", {
      scripts: snp.js,
      css: snp.css
    });
    body += "\n" + snp.inlineBody;
    body += "\n<script src='main.js'></script>";
    var files = {
      js: js,
      html: body
    };
    res.render("plunker", {
      files: files,
      description: "A BioJS example",
      tags: ["biojs", snp.name],
      redirectURL: "http://plnkr.co/edit/"
    });
  });
};

snip.edit = function(req, res, callback) {
  var name = req.params.name;
  var currentSnip = req.params.snip;
  global.db.db().find({
    name: name
  }).exec(function(err, pkg) {
    if (pkg.length === 0 || pkg[0].latest.sniper == undefined) {
      res.send({
        error: "no snips"
      });
      return;
    }
    var s = new SnippetDemo({
      pkg: pkg[0],
      snippetName: currentSnip,
      services: services
    }).then(function(snp) {
      snipResponse.removeTags(snp);
      var githubRegex = /\/github\//g;
      for (var i in snp.js) {
        snp.js[i] = snp.js[i].replace(githubRegex, services.ghProxy);
      }
      for (var i in snp.css) {
        snp.css[i] = snp.css[i].replace(githubRegex, services.ghProxy);
      }
      snp.inlineScript = snp.inlineScript.replace(githubRegex, services.ghProxy);
      snp.inlineBody = snp.inlineBody.replace(githubRegex, services.ghProxy);
      callback(snp);
    }).catch(function(err) {
      searchErrorWrapper(err, res);
    });
  });
};

// list available snips
snip.overview = function(req, res) {
  var name = req.params.name;
  var currentSnip = req.params.snip;
  global.db.db().find({
    name: name
  }).exec(function(err, pkg) {
    if (pkg.length === 0 || pkg[0].latest.sniper == undefined) {
      errors.noSnippets({
        pkg: pkg,
        currentSnip: currentSnip,
        req: req,
        res: res
      });
      return;
    }
    pkg = pkg[0];
    var baseURL = req.protocol + '://' + req.get('host') + req.originalUrl;
    // remove path at the end
    if (baseURL.charAt(baseURL.length - 1) !== "/") {
      baseURL += "/";
    }
    if (pkg.latest.sniper.srcs === undefined) {
      errors.unknownSnippetFile({
        pkg: pkg,
        currentSnip: currentSnip,
        req: req,
        res: res
      });
      return;
    }
    var snips = Object.keys(pkg.latest.sniper.srcs);
    res.render("list", {
      snips: snips,
      baseHref: baseURL
    });
  });
};

// simple github proxy
snip.github = function(req, res) {
  serveGithubFile({
    user: req.params.name,
    repo: req.params.repo
  }, req.params[0], res);
};

function serveGithubFile(pkg, path, res) {
  var url = "https://raw.githubusercontent.com/" + pkg.user + "/" + pkg.repo + "/" + path;
  var type = mime.lookup(url);
  res.set('Content-Type', type);
  // proxy the data from github
  var ttl = 180; // in s
  rc.get(url, {}, ttl, function(err, resp, body, cache) {
    if (cache.hit) {
      log.verbose("serving github file (from cache)", pkg, path);
    } else {
      log.verbose("serving github file (new to cache)", pkg, path);
    }
    res.send(body);
  });
  //request(url).pipe(res);
  //request.get(url, function(err, response, body) {
  //res.send(body);
  //});
}

var log;
var services;
module.exports = function(opts) {
  log = opts.log;
  services = opts.services;
  return snip;
};
<|endoftext|>


<commit_before>//     ___  _____  _____ ___  _________
//    |_  |/  ___|/  __ \|  \/  ||  _  \
//      | |\ `--. | /  \/| .  . || | | |
//      | | `--. \| |    | |\/| || | | |
//  /\__/ //\__/ /| \__/\| |  | || |/ /
//  \____/ \____/  \____/\_|  |_/|___/
//
/*
 *  Project: jscmd
 *  Description: Command prompt in javascript and jQuery
 *  Author: Dennis Wethmar
 *  License: MIT
 */

// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;
(function($, window, document, undefined) {

    var // plugin name
            pluginName = "jscmd",
            // key using in $.data()
            dataKey = "plugin_" + pluginName;

    function Plugin(element, options) {

        element.append($(document.createElement("div")));
        this.element = element.find("div");

        this.options = {
            version: "1.0.2",
            namespace: "jscmd",
			disk: "J",
            path: "\\"
        };

        this.elements = {
            inputField: "",
            form: "",
            prompt: "",
            inputMirror: ""
        };

        this.commandCollection = new Array();

        $.extend(this.options, options);

        this.init(this.options);
    };

    // initialize options
    Plugin.prototype.init = function(options) {

        this.element.empty();
        /*
         * Update plugin for options
         */
        this.element.parent().addClass(options.namespace + "-container");
        this.element.addClass(options.namespace);

        var logClass = options.namespace + "-log";
        this.elements.log = $(document.createElement("div")).attr({
            class: logClass
        });

        var CommandInputFieldClass = options.namespace + "-inputField";
        this.elements.CommandInputField = $(document.createElement("input")).attr({
            class: CommandInputFieldClass,
            name: options.namespace + "-inputField",
            type: "text",
            autocomplete: "off",
            unselectable : "off",
            onselectstart: "return false;",
            onmousedown: "return false;",
			style: "pointer-events: auto !important"
        }).css({
            "-moz-user-select": "none",
            "-webkit-user-select": "none",
            "-ms-user-select": "none",
            "user-select": "none",
        });

        this.elements.form = $(document.createElement("form")).attr({
            method: "GET"
        }).css({
            position: "relative",
            left: "-9999px",
        }).append(this.elements.CommandInputField);

        var promptClass = options.namespace + "-prompt";
        this.elements.prompt = $(document.createElement("label")).attr({
            class: promptClass,
            for : CommandInputFieldClass
        }).html(this.getPath());

        var inputMirrorClass = options.namespace + "-inputMirror";
        this.elements.inputMirror = $(document.createElement("span")).attr({
            class: inputMirrorClass
        });

        $(this.elements.CommandInputField).bind("keyup keydown init", {plugin: this}, function(event) {
            var plugin = event.data.plugin;

            var input = plugin.elements.CommandInputField;
            var inputValue = input.val();
            var inputPosition = input[0].selectionStart;

            var mirrorInput = "";
            for (var i = 0; i < inputValue.length; i++)
            {
                if (inputValue.charAt(i) === " ") {
                    mirrorInput += " ";
                } else {
                    mirrorInput += "" + inputValue.charAt(i) + "";
                }
            }

            plugin.elements.inputMirror.html(mirrorInput);
            if (inputPosition <= inputValue.length) {
                plugin.elements.inputMirror.append($(" "));
                plugin.elements.inputMirror.find("span:eq(" + inputPosition + ")").addClass("input-position");
            }
        });

        $(this.elements.form).bind("submit", {plugin: this}, function(event) {
            event.preventDefault();
            var plugin = event.data.plugin;
            var input = plugin.elements.CommandInputField.val();
            plugin.elements.CommandInputField.val("");
            plugin.elements.inputMirror.empty();

            var path = $("
").append( //Put the path in a span so we can style it
                $("").addClass("prompt").html(plugin.getPath())
            ).append(">").html();

            plugin.addLogEntry(path + input);
            plugin.execute(input);

            //Auto scroll
            plugin.element[0].scrollTop = plugin.element[0].scrollHeight;
        });

        $(this.element).bind("click", {plugin: this}, function(event) {

            var plugin = event.data.plugin;
            var input = plugin.elements.CommandInputField;
			var selection = window.getSelection().toString();
            if(selection !== ""){ //Prevent focusing when selecting text
                return;
            }

            var y = plugin.element[0].scrollTop; //prevent autoscrolling
            input.focus();
            plugin.element[0].scrollTop = y;
        });

        //To make that thingy blink
        $(this.elements.CommandInputField).trigger("init");
        this.element.append(this.elements.log, this.elements.prompt, this.elements.inputMirror, this.elements.form);

        this.addLogEntry("Jscmd [Version: " + options.version + "]");
        this.addLogEntry("(c) 2014 Dennis Wethmar. ★");
        this.addLogEntry(" ");
    };

    Plugin.prototype.addLogEntry = function(log) {
        this.elements.log.append($(document.createElement("div")).attr({class: "log-entry"}).html(log));
    };

    Plugin.prototype.registerCommand = function(name, description, logic) {
        this.commandCollection.push(new Command(name, description, logic));
    };

    Plugin.prototype.getPath = function(){
        return this.options.disk + ":" + ( this.options.path === "" ? "\\" : this.options.path);
    };

    Plugin.prototype.setPath = function(path){
        var pieces = path.split(':', 2);
        var disk  = pieces[0];
        var path  = pieces[1];
        this.options.disk = disk;
        this.options.path = path;
        this.elements.prompt.html(this.getPath());
    };

    Plugin.prototype.execute = function(command) {

        var params = command.match(/(".*?"|[^"\s]+)+(?=\s*|\s*$)/g);
        if(params === null || params.length === 0){
            params = new Array();
        }
        var commandName = params.shift();

        if(typeof commandName === "undefined"){
            return;
        }

		$.each( params, function( key, value ) { // remove outer qoutes of params
			if (value.charAt(0) === "\"" && value.charAt(value.length -1) === "\"")
			{
				params[key] = value.substr(1,value.length -2);
			}
		});

        var result = $.grep(this.commandCollection, function(e){
            return e.name.toLowerCase() === commandName;
        });

        if(result.length > 0){
            var command = result[0];
            var keepFocus = false;
            try{
                keepFocus = command.logic(this, params);
            }catch(e){
                var stack = e.stack.split("\n");
                for(var i = 0; i < stack.length; i++){
                    this.addLogEntry(stack[i]);
                }
                keepFocus = true;
            }finally{
                if(typeof keepFocus === "undefined" || keepFocus === false){
                    this.executionFinished();
                }
            }

        }else{
            this.addLogEntry("'" + commandName + "' is not recognized as an internal or external command.");
            this.addLogEntry(" ");
        }
    };

    Plugin.prototype.executionFinished = function(){
        this.setPath(this.getPath());
        this.addLogEntry(" ");
    };

    function Command(name, decription, logic){
        this.name = name;
        this.decription = decription;
        this.logic = logic;
    }

    /*
     * Plugin wrapper, preventing against multiple instantiations and
     * return plugin instance.
     */
    $.fn[pluginName] = function(options) {

        var plugin = this.data(dataKey);

        // has plugin instantiated ?
        if (plugin instanceof Plugin) {
            // if have options arguments, call plugin.init() again
            if (typeof options !== "undefined") {
                plugin.init(options);
            }
        } else {
            plugin = new Plugin(this, options);
            this.data(dataKey, plugin);
        }

        return plugin;
    };

}(jQuery, window, document));<commit_msg>removed my name<commit_after>//     ___  _____  _____ ___  _________
//    |_  |/  ___|/  __ \|  \/  ||  _  \
//      | |\ `--. | /  \/| .  . || | | |
//      | | `--. \| |    | |\/| || | | |
//  /\__/ //\__/ /| \__/\| |  | || |/ /
//  \____/ \____/  \____/\_|  |_/|___/
//
/*
 *  Project: jscmd
 *  Description: Command prompt in javascript and jQuery
 *  Author: Dennis Wethmar
 *  License: MIT
 */

// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;
(function($, window, document, undefined) {

    var // plugin name
            pluginName = "jscmd",
            // key using in $.data()
            dataKey = "plugin_" + pluginName;

    function Plugin(element, options) {

        element.append($(document.createElement("div")));
        this.element = element.find("div");

        this.options = {
            version: "1.0.2",
            namespace: "jscmd",
			disk: "J",
            path: "\\"
        };

        this.elements = {
            inputField: "",
            form: "",
            prompt: "",
            inputMirror: ""
        };

        this.commandCollection = new Array();

        $.extend(this.options, options);

        this.init(this.options);
    };

    // initialize options
    Plugin.prototype.init = function(options) {

        this.element.empty();
        /*
         * Update plugin for options
         */
        this.element.parent().addClass(options.namespace + "-container");
        this.element.addClass(options.namespace);

        var logClass = options.namespace + "-log";
        this.elements.log = $(document.createElement("div")).attr({
            class: logClass
        });

        var CommandInputFieldClass = options.namespace + "-inputField";
        this.elements.CommandInputField = $(document.createElement("input")).attr({
            class: CommandInputFieldClass,
            name: options.namespace + "-inputField",
            type: "text",
            autocomplete: "off",
            unselectable : "off",
            onselectstart: "return false;",
            onmousedown: "return false;",
			style: "pointer-events: auto !important"
        }).css({
            "-moz-user-select": "none",
            "-webkit-user-select": "none",
            "-ms-user-select": "none",
            "user-select": "none",
        });

        this.elements.form = $(document.createElement("form")).attr({
            method: "GET"
        }).css({
            position: "relative",
            left: "-9999px",
        }).append(this.elements.CommandInputField);

        var promptClass = options.namespace + "-prompt";
        this.elements.prompt = $(document.createElement("label")).attr({
            class: promptClass,
            for : CommandInputFieldClass
        }).html(this.getPath());

        var inputMirrorClass = options.namespace + "-inputMirror";
        this.elements.inputMirror = $(document.createElement("span")).attr({
            class: inputMirrorClass
        });

        $(this.elements.CommandInputField).bind("keyup keydown init", {plugin: this}, function(event) {
            var plugin = event.data.plugin;

            var input = plugin.elements.CommandInputField;
            var inputValue = input.val();
            var inputPosition = input[0].selectionStart;

            var mirrorInput = "";
            for (var i = 0; i < inputValue.length; i++)
            {
                if (inputValue.charAt(i) === " ") {
                    mirrorInput += " ";
                } else {
                    mirrorInput += "" + inputValue.charAt(i) + "";
                }
            }

            plugin.elements.inputMirror.html(mirrorInput);
            if (inputPosition <= inputValue.length) {
                plugin.elements.inputMirror.append($(" "));
                plugin.elements.inputMirror.find("span:eq(" + inputPosition + ")").addClass("input-position");
            }
        });

        $(this.elements.form).bind("submit", {plugin: this}, function(event) {
            event.preventDefault();
            var plugin = event.data.plugin;
            var input = plugin.elements.CommandInputField.val();
            plugin.elements.CommandInputField.val("");
            plugin.elements.inputMirror.empty();

            var path = $("
").append( //Put the path in a span so we can style it
                $("").addClass("prompt").html(plugin.getPath())
            ).append(">").html();

            plugin.addLogEntry(path + input);
            plugin.execute(input);

            //Auto scroll
            plugin.element[0].scrollTop = plugin.element[0].scrollHeight;
        });

        $(this.element).bind("click", {plugin: this}, function(event) {

            var plugin = event.data.plugin;
            var input = plugin.elements.CommandInputField;
			var selection = window.getSelection().toString();
            if(selection !== ""){ //Prevent focusing when selecting text
                return;
            }

            var y = plugin.element[0].scrollTop; //prevent autoscrolling
            input.focus();
            plugin.element[0].scrollTop = y;
        });

        //To make that thingy blink
        $(this.elements.CommandInputField).trigger("init");
        this.element.append(this.elements.log, this.elements.prompt, this.elements.inputMirror, this.elements.form);

        this.addLogEntry("Jscmd [Version: " + options.version + "]");
        //this.addLogEntry("(c) 2014 Dennis Wethmar. ★");
        this.addLogEntry(" ");
    };

    Plugin.prototype.addLogEntry = function(log) {
        this.elements.log.append($(document.createElement("div")).attr({class: "log-entry"}).html(log));
    };

    Plugin.prototype.registerCommand = function(name, description, logic) {
        this.commandCollection.push(new Command(name, description, logic));
    };

    Plugin.prototype.getPath = function(){
        return this.options.disk + ":" + ( this.options.path === "" ? "\\" : this.options.path);
    };

    Plugin.prototype.setPath = function(path){
        var pieces = path.split(':', 2);
        var disk  = pieces[0];
        var path  = pieces[1];
        this.options.disk = disk;
        this.options.path = path;
        this.elements.prompt.html(this.getPath());
    };

    Plugin.prototype.execute = function(command) {

        var params = command.match(/(".*?"|[^"\s]+)+(?=\s*|\s*$)/g);
        if(params === null || params.length === 0){
            params = new Array();
        }
        var commandName = params.shift();

        if(typeof commandName === "undefined"){
            return;
        }

		$.each( params, function( key, value ) { // remove outer qoutes of params
			if (value.charAt(0) === "\"" && value.charAt(value.length -1) === "\"")
			{
				params[key] = value.substr(1,value.length -2);
			}
		});

        var result = $.grep(this.commandCollection, function(e){
            return e.name.toLowerCase() === commandName;
        });

        if(result.length > 0){
            var command = result[0];
            var keepFocus = false;
            try{
                keepFocus = command.logic(this, params);
            }catch(e){
                var stack = e.stack.split("\n");
                for(var i = 0; i < stack.length; i++){
                    this.addLogEntry(stack[i]);
                }
                keepFocus = true;
            }finally{
                if(typeof keepFocus === "undefined" || keepFocus === false){
                    this.executionFinished();
                }
            }

        }else{
            this.addLogEntry("'" + commandName + "' is not recognized as an internal or external command.");
            this.addLogEntry(" ");
        }
    };

    Plugin.prototype.executionFinished = function(){
        this.setPath(this.getPath());
        this.addLogEntry(" ");
    };

    function Command(name, decription, logic){
        this.name = name;
        this.decription = decription;
        this.logic = logic;
    }

    /*
     * Plugin wrapper, preventing against multiple instantiations and
     * return plugin instance.
     */
    $.fn[pluginName] = function(options) {

        var plugin = this.data(dataKey);

        // has plugin instantiated ?
        if (plugin instanceof Plugin) {
            // if have options arguments, call plugin.init() again
            if (typeof options !== "undefined") {
                plugin.init(options);
            }
        } else {
            plugin = new Plugin(this, options);
            this.data(dataKey, plugin);
        }

        return plugin;
    };

}(jQuery, window, document));<|endoftext|>


<commit_before>// @flow
export default [
  {
    title: 'Front End Engineer',
    unit: 'Appier',
    location: 'Taipei, Taiwan',
    duration: '2017 - Present',
    description: 'Aixon Team',
  },
  {
    title: 'F2E&RGBA Meetup',
    unit: 'Co-organizer',
    location: 'Taipei, Taiwan',
    duration: '2016 - Present',
    description: 'f2e.tw Community',
  },
  {
    title: 'Front End Developer',
    unit: 'iCHEF Co., Ltd.',
    location: 'Taipei, Taiwan',
    duration: '2016 - 2017',
    description: 'Cloud Team',
  },
  {
    title: 'Front End Engineer',
    unit: 'Galaxy Software Services',
    location: 'Taipei, Taiwan',
    duration: '2014 - 2016',
    description: 'Front End Developer & Web Designer',
  },
  {
    title: 'Bachelor of Computer Science',
    unit: 'National Cheng Kung University',
    location: 'Tainan, Taiwan',
    duration: '2010 - 2014',
    description: 'Major in web development',
  },
];
<commit_msg>Update work experiences<commit_after>// @flow
export default [
  {
    title: 'Senior Front End Engineer',
    unit: 'Appier',
    location: 'Taipei, Taiwan',
    duration: '2017 - Present',
    description: 'Enterprise Solution Department',
  },
  {
    title: 'F2E&RGBA Meetup',
    unit: 'Co-organizer',
    location: 'Taipei, Taiwan',
    duration: '2016 - Present',
    description: 'f2e.tw Community',
  },
  {
    title: 'Front End Developer',
    unit: 'iCHEF Co., Ltd.',
    location: 'Taipei, Taiwan',
    duration: '2016 - 2017',
    description: 'Cloud Team',
  },
  {
    title: 'Front End Engineer',
    unit: 'Galaxy Software Services',
    location: 'Taipei, Taiwan',
    duration: '2014 - 2016',
    description: 'Uwillx Team',
  },
];
<|endoftext|>


<commit_before>'use strict'

const Domain = require('../schemas/Domain')

const add = async (data) => {

	return Domain.create(data)

}

const all = async () => {

	return Domain.find({})

}

const get = async (id) => {

	return Domain.findOne({
		id
	})

}

const update = async (id, { title }) => {

	return Domain.findOneAndUpdate({
		id
	}, {
		$set: {
			title,
			updated: Date.now()
		}
	})

}

const del = async (id) => {

	return Domain.findOneAndDelete({
		id
	})

}

module.exports = {
	add,
	all,
	get,
	update,
	del
}<commit_msg>Sort domains by title (insensitive)<commit_after>'use strict'

const Domain = require('../schemas/Domain')

const add = async (data) => {

	return Domain.create(data)

}

const all = async () => {

	return Domain.aggregate([
		{
			$addFields: {
				insensitive: {
					$toLower: '$title'
				}
			}
		},
		{
			$sort: {
				insensitive: 1
			}
		}
	])

}

const get = async (id) => {

	return Domain.findOne({
		id
	})

}

const update = async (id, { title }) => {

	return Domain.findOneAndUpdate({
		id
	}, {
		$set: {
			title,
			updated: Date.now()
		}
	})

}

const del = async (id) => {

	return Domain.findOneAndDelete({
		id
	})

}

module.exports = {
	add,
	all,
	get,
	update,
	del
}<|endoftext|>


<commit_before>/*
 Copyright (c) 2008-2013 Pivotal Labs

 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
 "Software"), to deal in the Software without restriction, including
 without limitation the rights to use, copy, modify, merge, publish,
 distribute, sublicense, and/or sell copies of the Software, and to
 permit persons to whom the Software is furnished to do so, subject to
 the following conditions:

 The above copyright notice and this permission notice shall be
 included in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

jasmineRequire.html = function(j$) {
    j$.ResultsNode = jasmineRequire.ResultsNode();
    j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
    j$.QueryString = jasmineRequire.QueryString();
    j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
};

jasmineRequire.HtmlReporter = function(j$) {

    var noopTimer = {
        start: function() {},
        elapsed: function() { return 0; }
    };

    function HtmlReporter(options) {
        var env = options.env || {},
            getContainer = options.getContainer,
            createElement = options.createElement,
            createTextNode = options.createTextNode,
            onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
            timer = options.timer || noopTimer,
            results = [],
            specsExecuted = 0,
            failureCount = 0,
            pendingSpecCount = 0,
            htmlReporterMain,
            symbols;

        this.initialize = function() {
            htmlReporterMain = createDom("div", {className: "html-reporter"},
                createDom("div", {className: "banner"},
                    createDom("span", {className: "title"}, "Jasmine"),
                    createDom("span", {className: "version"}, j$.version)
                ),
                createDom("ul", {className: "symbol-summary"}),
                createDom("div", {className: "alert"}),
                createDom("div", {className: "results"},
                    createDom("div", {className: "failures"})
                )
            );
            getContainer().appendChild(htmlReporterMain);

            symbols = find(".symbol-summary");
        };

        var totalSpecsDefined;
        this.jasmineStarted = function(options) {
            totalSpecsDefined = options.totalSpecsDefined || 0;
            timer.start();
        };

        var summary = createDom("div", {className: "summary"});

        var topResults = new j$.ResultsNode({}, "", null),
            currentParent = topResults;

        this.suiteStarted = function(result) {
            currentParent.addChild(result, "suite");
            currentParent = currentParent.last();
        };

        this.suiteDone = function(result) {
            if (currentParent == topResults) {
                return;
            }

            currentParent = currentParent.parent;
        };

        this.specStarted = function(result) {
            currentParent.addChild(result, "spec");
        };

        var failures = [];
        this.specDone = function(result) {
            if (result.status != "disabled") {
                specsExecuted++;
            }

            symbols.appendChild(createDom("li", {
                    className: result.status,
                    id: "spec_" + result.id,
                    title: result.fullName
                }
            ));

            if (result.status == "failed") {
                failureCount++;

                var failure =
                    createDom("div", {className: "spec-detail failed"},
                        createDom("div", {className: "description"},
                            createDom("a", {title: result.fullName, href: specHref(result)}, result.fullName)
                        ),
                        createDom("div", {className: "messages"})
                    );
                var messages = failure.childNodes[1];

                for (var i = 0; i < result.failedExpectations.length; i++) {
                    var expectation = result.failedExpectations[i];
                    messages.appendChild(createDom("div", {className: "result-message"}, expectation.message));
                    messages.appendChild(createDom("div", {className: "stack-trace"}, expectation.stack));
                }

                failures.push(failure);
            }

            if (result.status == "pending") {
                pendingSpecCount++;
            }
        };

        this.jasmineDone = function() {
            var specSuiteId = "";
            var banner = find(".banner");
            banner.appendChild(createDom("span", {className: "duration"}, "finished in " + timer.elapsed() / 1000 + "s"));

            var alert = find(".alert");

            alert.appendChild(createDom("span", { className: "exceptions" },
                createDom("label", { className: "label", 'for': "raise-exceptions" }, "raise exceptions"),
                createDom("input", {
                    className: "raise",
                    id: "raise-exceptions",
                    type: "checkbox"
                })
            ));
            var checkbox = find("input");

            checkbox.checked = !env.catchingExceptions();
            checkbox.onclick = onRaiseExceptionsClick;

            if (specsExecuted < totalSpecsDefined) {
                var skippedMessage = "Ran " + specsExecuted + " of " + totalSpecsDefined + " specs - run all";
                alert.appendChild(
                    createDom("span", {className: "bar skipped"},
                        createDom("a", {href: "?", title: "Run all specs"}, skippedMessage)
                    )
                );
            }
            var statusBarMessage = "" + pluralize("spec", specsExecuted) + ", " + pluralize("failure", failureCount);
            if (pendingSpecCount) { statusBarMessage += ", " + pluralize("pending spec", pendingSpecCount); }

            var statusBarClassName = "bar " + ((failureCount > 0) ? "failed" : "passed");
            alert.appendChild(createDom("span", {className: statusBarClassName}, statusBarMessage));

            var results = find(".results");
            results.appendChild(summary);

            summaryList(topResults, summary);

            function summaryList(resultsTree, domParent) {
                var specListNode;
                for (var i = 0; i < resultsTree.children.length; i++) {
                    var resultNode = resultsTree.children[i];
                    if (resultNode.type == "suite") {
                        specSuiteId = resultNode.result.id;

                        var suiteListNode = createDom("ul", {className: "suite", id: "suite-" + specSuiteId},
                            createDom("li", {className: "suite-detail"},
                                createDom("a", {href: specHref(resultNode.result)}, resultNode.result.description)
                            )
                        );

                        summaryList(resultNode, suiteListNode);
                        domParent.appendChild(suiteListNode);
                    }
                    if (resultNode.type == "spec") {
                        if (domParent.getAttribute("class") != "specs") {
                            specListNode = createDom("ul", {className: "specs"});
                            domParent.appendChild(specListNode);
                        }

                        var attributesObj = {
                            className: resultNode.result.status,
                            id: "spec-" + resultNode.result.id
                        };

                        specSuiteId && (attributesObj["spec-suite-id"] = specSuiteId);

                        specListNode.appendChild(
                            createDom("li", attributesObj,
                                createDom("a", {href: specHref(resultNode.result)}, resultNode.result.description)
                            )
                        );
                    }
                }
            }

            if (failures.length) {
                alert.appendChild(
                    createDom('span', {className: "menu bar spec-list"},
                        createDom("span", {}, "Spec List | "),
                        createDom('a', {className: "failures-menu", href: "#"}, "Failures")));
                alert.appendChild(
                    createDom('span', {className: "menu bar failure-list"},
                        createDom('a', {className: "spec-list-menu", href: "#"}, "Spec List"),
                        createDom("span", {}, " | Failures ")));

                find(".failures-menu").onclick = function() {
                    setMenuModeTo('failure-list');
                };
                find(".spec-list-menu").onclick = function() {
                    setMenuModeTo('spec-list');
                };

                setMenuModeTo('failure-list');

                var failureNode = find(".failures");
                for (var i = 0; i < failures.length; i++) {
                    failureNode.appendChild(failures[i]);
                }
            }

            scrollToSpec(document.querySelector(".summary li.passed"));
        };

        return this;

        function find(selector) {
            return getContainer().querySelector(selector);
        }

        function scrollToSpec(specEl){
            var scroll = 0,
                windowInnerHeight = window.innerHeight,
                suiteId = specEl.getAttribute("spec-suite-id");

            var parent = getParentById(specEl, "suite-" + suiteId);

            if(parent && (parent.offsetTop > 0)){
                var parentHeight = parent.offsetHeight;

                scroll = (parent.offsetTop + parentHeight) > windowInnerHeight ?
                    parent.offsetTop - windowInnerHeight/2 : 0;
            }

            document.body.scrollTop = scroll;
        }

        function getParentById(el, id){
            var found = false,
                parent = el;

            while(!found){
                if(parent.parentNode.id === id){
                    found = true;
                }
                parent = parent.parentNode;
            }

            return parent;
        }

        function createDom(type, attrs, childrenVarArgs) {
            var el = createElement(type);

            for (var i = 2; i < arguments.length; i++) {
                var child = arguments[i];

                if (typeof child === 'string') {
                    el.appendChild(createTextNode(child));
                } else {
                    if (child) {
                        el.appendChild(child);
                    }
                }
            }

            for (var attr in attrs) {
                if (attr == "className") {
                    el[attr] = attrs[attr];
                } else {
                    el.setAttribute(attr, attrs[attr]);
                }
            }

            return el;
        }

        function pluralize(singular, count) {
            var word = (count == 1 ? singular : singular + "s");

            return "" + count + " " + word;
        }

        function specHref(result) {
            return "?spec=" + encodeURIComponent(result.fullName);
        }

        function setMenuModeTo(mode) {
            htmlReporterMain.setAttribute("class", "html-reporter " + mode);
        }
    }

    return HtmlReporter;
};

jasmineRequire.HtmlSpecFilter = function() {
    function HtmlSpecFilter(options) {
        var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
        var filterPattern = new RegExp(filterString);

        this.matches = function(specName) {
            return filterPattern.test(specName);
        };
    }

    return HtmlSpecFilter;
};

jasmineRequire.ResultsNode = function() {
    function ResultsNode(result, type, parent) {
        this.result = result;
        this.type = type;
        this.parent = parent;

        this.children = [];

        this.addChild = function(result, type) {
            this.children.push(new ResultsNode(result, type, this));
        };

        this.last = function() {
            return this.children[this.children.length - 1];
        };
    }

    return ResultsNode;
};

jasmineRequire.QueryString = function() {
    function QueryString(options) {

        this.setParam = function(key, value) {
            var paramMap = queryStringToParamMap();
            paramMap[key] = value;
            options.getWindowLocation().search = toQueryString(paramMap);
        };

        this.getParam = function(key) {
            return queryStringToParamMap()[key];
        };

        return this;

        function toQueryString(paramMap) {
            var qStrPairs = [];
            for (var prop in paramMap) {
                qStrPairs.push(encodeURIComponent(prop) + "=" + encodeURIComponent(paramMap[prop]));
            }
            return "?" + qStrPairs.join('&');
        }

        function queryStringToParamMap() {
            var paramStr = options.getWindowLocation().search.substring(1),
                params = [],
                paramMap = {};

            if (paramStr.length > 0) {
                params = paramStr.split('&');
                for (var i = 0; i < params.length; i++) {
                    var p = params[i].split('=');
                    var value = decodeURIComponent(p[1]);
                    if (value === "true" || value === "false") {
                        value = JSON.parse(value);
                    }
                    paramMap[decodeURIComponent(p[0])] = value;
                }
            }

            return paramMap;
        }

    }

    return QueryString;
};<commit_msg>Added guard.<commit_after>/*
 Copyright (c) 2008-2013 Pivotal Labs

 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
 "Software"), to deal in the Software without restriction, including
 without limitation the rights to use, copy, modify, merge, publish,
 distribute, sublicense, and/or sell copies of the Software, and to
 permit persons to whom the Software is furnished to do so, subject to
 the following conditions:

 The above copyright notice and this permission notice shall be
 included in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

jasmineRequire.html = function(j$) {
    j$.ResultsNode = jasmineRequire.ResultsNode();
    j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
    j$.QueryString = jasmineRequire.QueryString();
    j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
};

jasmineRequire.HtmlReporter = function(j$) {

    var noopTimer = {
        start: function() {},
        elapsed: function() { return 0; }
    };

    function HtmlReporter(options) {
        var env = options.env || {},
            getContainer = options.getContainer,
            createElement = options.createElement,
            createTextNode = options.createTextNode,
            onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
            timer = options.timer || noopTimer,
            results = [],
            specsExecuted = 0,
            failureCount = 0,
            pendingSpecCount = 0,
            htmlReporterMain,
            symbols;

        this.initialize = function() {
            htmlReporterMain = createDom("div", {className: "html-reporter"},
                createDom("div", {className: "banner"},
                    createDom("span", {className: "title"}, "Jasmine"),
                    createDom("span", {className: "version"}, j$.version)
                ),
                createDom("ul", {className: "symbol-summary"}),
                createDom("div", {className: "alert"}),
                createDom("div", {className: "results"},
                    createDom("div", {className: "failures"})
                )
            );
            getContainer().appendChild(htmlReporterMain);

            symbols = find(".symbol-summary");
        };

        var totalSpecsDefined;
        this.jasmineStarted = function(options) {
            totalSpecsDefined = options.totalSpecsDefined || 0;
            timer.start();
        };

        var summary = createDom("div", {className: "summary"});

        var topResults = new j$.ResultsNode({}, "", null),
            currentParent = topResults;

        this.suiteStarted = function(result) {
            currentParent.addChild(result, "suite");
            currentParent = currentParent.last();
        };

        this.suiteDone = function(result) {
            if (currentParent == topResults) {
                return;
            }

            currentParent = currentParent.parent;
        };

        this.specStarted = function(result) {
            currentParent.addChild(result, "spec");
        };

        var failures = [];
        this.specDone = function(result) {
            if (result.status != "disabled") {
                specsExecuted++;
            }

            symbols.appendChild(createDom("li", {
                    className: result.status,
                    id: "spec_" + result.id,
                    title: result.fullName
                }
            ));

            if (result.status == "failed") {
                failureCount++;

                var failure =
                    createDom("div", {className: "spec-detail failed"},
                        createDom("div", {className: "description"},
                            createDom("a", {title: result.fullName, href: specHref(result)}, result.fullName)
                        ),
                        createDom("div", {className: "messages"})
                    );
                var messages = failure.childNodes[1];

                for (var i = 0; i < result.failedExpectations.length; i++) {
                    var expectation = result.failedExpectations[i];
                    messages.appendChild(createDom("div", {className: "result-message"}, expectation.message));
                    messages.appendChild(createDom("div", {className: "stack-trace"}, expectation.stack));
                }

                failures.push(failure);
            }

            if (result.status == "pending") {
                pendingSpecCount++;
            }
        };

        this.jasmineDone = function() {
            var specSuiteId = "";
            var banner = find(".banner");
            banner.appendChild(createDom("span", {className: "duration"}, "finished in " + timer.elapsed() / 1000 + "s"));

            var alert = find(".alert");

            alert.appendChild(createDom("span", { className: "exceptions" },
                createDom("label", { className: "label", 'for': "raise-exceptions" }, "raise exceptions"),
                createDom("input", {
                    className: "raise",
                    id: "raise-exceptions",
                    type: "checkbox"
                })
            ));
            var checkbox = find("input");

            checkbox.checked = !env.catchingExceptions();
            checkbox.onclick = onRaiseExceptionsClick;

            if (specsExecuted < totalSpecsDefined) {
                var skippedMessage = "Ran " + specsExecuted + " of " + totalSpecsDefined + " specs - run all";
                alert.appendChild(
                    createDom("span", {className: "bar skipped"},
                        createDom("a", {href: "?", title: "Run all specs"}, skippedMessage)
                    )
                );
            }
            var statusBarMessage = "" + pluralize("spec", specsExecuted) + ", " + pluralize("failure", failureCount);
            if (pendingSpecCount) { statusBarMessage += ", " + pluralize("pending spec", pendingSpecCount); }

            var statusBarClassName = "bar " + ((failureCount > 0) ? "failed" : "passed");
            alert.appendChild(createDom("span", {className: statusBarClassName}, statusBarMessage));

            var results = find(".results");
            results.appendChild(summary);

            summaryList(topResults, summary);

            function summaryList(resultsTree, domParent) {
                var specListNode;
                for (var i = 0; i < resultsTree.children.length; i++) {
                    var resultNode = resultsTree.children[i];
                    if (resultNode.type == "suite") {
                        specSuiteId = resultNode.result.id;

                        var suiteListNode = createDom("ul", {className: "suite", id: "suite-" + specSuiteId},
                            createDom("li", {className: "suite-detail"},
                                createDom("a", {href: specHref(resultNode.result)}, resultNode.result.description)
                            )
                        );

                        summaryList(resultNode, suiteListNode);
                        domParent.appendChild(suiteListNode);
                    }
                    if (resultNode.type == "spec") {
                        if (domParent.getAttribute("class") != "specs") {
                            specListNode = createDom("ul", {className: "specs"});
                            domParent.appendChild(specListNode);
                        }

                        var attributesObj = {
                            className: resultNode.result.status,
                            id: "spec-" + resultNode.result.id
                        };

                        specSuiteId && (attributesObj["spec-suite-id"] = specSuiteId);

                        specListNode.appendChild(
                            createDom("li", attributesObj,
                                createDom("a", {href: specHref(resultNode.result)}, resultNode.result.description)
                            )
                        );
                    }
                }
            }

            if (failures.length) {
                alert.appendChild(
                    createDom('span', {className: "menu bar spec-list"},
                        createDom("span", {}, "Spec List | "),
                        createDom('a', {className: "failures-menu", href: "#"}, "Failures")));
                alert.appendChild(
                    createDom('span', {className: "menu bar failure-list"},
                        createDom('a', {className: "spec-list-menu", href: "#"}, "Spec List"),
                        createDom("span", {}, " | Failures ")));

                find(".failures-menu").onclick = function() {
                    setMenuModeTo('failure-list');
                };
                find(".spec-list-menu").onclick = function() {
                    setMenuModeTo('spec-list');
                };

                setMenuModeTo('failure-list');

                var failureNode = find(".failures");
                for (var i = 0; i < failures.length; i++) {
                    failureNode.appendChild(failures[i]);
                }
            }

            scrollToSpec(document.querySelector(".summary li.passed"));
        };

        return this;

        function find(selector) {
            return getContainer().querySelector(selector);
        }

        function scrollToSpec(specEl){
            var scroll = 0,
                windowInnerHeight = window.innerHeight,
                suiteId = specEl.getAttribute("spec-suite-id");

            var parent = getParentById(specEl, "suite-" + suiteId);

            if(parent && (parent.offsetTop > 0)){
                var parentHeight = parent.offsetHeight;

                scroll = (parent.offsetTop + parentHeight) > windowInnerHeight ?
                    parent.offsetTop - windowInnerHeight/2 : 0;
            }

            document.body.scrollTop = scroll;
        }

        function getParentById(el, id){
            var found = false,
                parent = el;

            while(!found){
                if(parent && parent.parentNode){
                    if(parent.parentNode.id === id){
                        found = true;
                    }

                    parent = parent.parentNode;
                }else{
                    found = true;
                    parent = null;
                }
            }

            return parent;
        }

        function createDom(type, attrs, childrenVarArgs) {
            var el = createElement(type);

            for (var i = 2; i < arguments.length; i++) {
                var child = arguments[i];

                if (typeof child === 'string') {
                    el.appendChild(createTextNode(child));
                } else {
                    if (child) {
                        el.appendChild(child);
                    }
                }
            }

            for (var attr in attrs) {
                if (attr == "className") {
                    el[attr] = attrs[attr];
                } else {
                    el.setAttribute(attr, attrs[attr]);
                }
            }

            return el;
        }

        function pluralize(singular, count) {
            var word = (count == 1 ? singular : singular + "s");

            return "" + count + " " + word;
        }

        function specHref(result) {
            return "?spec=" + encodeURIComponent(result.fullName);
        }

        function setMenuModeTo(mode) {
            htmlReporterMain.setAttribute("class", "html-reporter " + mode);
        }
    }

    return HtmlReporter;
};

jasmineRequire.HtmlSpecFilter = function() {
    function HtmlSpecFilter(options) {
        var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
        var filterPattern = new RegExp(filterString);

        this.matches = function(specName) {
            return filterPattern.test(specName);
        };
    }

    return HtmlSpecFilter;
};

jasmineRequire.ResultsNode = function() {
    function ResultsNode(result, type, parent) {
        this.result = result;
        this.type = type;
        this.parent = parent;

        this.children = [];

        this.addChild = function(result, type) {
            this.children.push(new ResultsNode(result, type, this));
        };

        this.last = function() {
            return this.children[this.children.length - 1];
        };
    }

    return ResultsNode;
};

jasmineRequire.QueryString = function() {
    function QueryString(options) {

        this.setParam = function(key, value) {
            var paramMap = queryStringToParamMap();
            paramMap[key] = value;
            options.getWindowLocation().search = toQueryString(paramMap);
        };

        this.getParam = function(key) {
            return queryStringToParamMap()[key];
        };

        return this;

        function toQueryString(paramMap) {
            var qStrPairs = [];
            for (var prop in paramMap) {
                qStrPairs.push(encodeURIComponent(prop) + "=" + encodeURIComponent(paramMap[prop]));
            }
            return "?" + qStrPairs.join('&');
        }

        function queryStringToParamMap() {
            var paramStr = options.getWindowLocation().search.substring(1),
                params = [],
                paramMap = {};

            if (paramStr.length > 0) {
                params = paramStr.split('&');
                for (var i = 0; i < params.length; i++) {
                    var p = params[i].split('=');
                    var value = decodeURIComponent(p[1]);
                    if (value === "true" || value === "false") {
                        value = JSON.parse(value);
                    }
                    paramMap[decodeURIComponent(p[0])] = value;
                }
            }

            return paramMap;
        }

    }

    return QueryString;
};<|endoftext|>


<commit_before>import value from './formatInputValue.js';
import suggestion from './formatDropdownValue.js';
import algoliaLogo from './icons/algolia.svg';
import osmLogo from './icons/osm.svg';

export default {
  footer: `

  Built by ${algoliaLogo.trim()}
  using ${osmLogo.trim()} data

`,
  value,
  suggestion
};
<commit_msg>fix(footer): powered by link goes to algolia.com/places<commit_after>import value from './formatInputValue.js';
import suggestion from './formatDropdownValue.js';
import algoliaLogo from './icons/algolia.svg';
import osmLogo from './icons/osm.svg';

export default {
  footer: `

  Built by ${algoliaLogo.trim()}
  using ${osmLogo.trim()} data

`,
  value,
  suggestion
};
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright (c) 2017 Google Inc. All rights reserved.
 * This code may only be used under the BSD style license found at
 * http://polymer.github.io/LICENSE.txt
 * Code distributed by Google as part of this project is also
 * subject to an additional IP rights grant found at
 * http://polymer.github.io/PATENTS.txt
 */
import {fs} from '../platform/fs-web.js';
import {vm} from '../platform/vm-web.js';
import {fetch} from './fetch-web.js';

import {assert} from '../platform/assert-web.js';
import {Particle} from './particle.js';
import {DomParticle} from './dom-particle.js';
import {MultiplexerDomParticle} from './multiplexer-dom-particle.js';
import {TransformationDomParticle} from './transformation-dom-particle.js';
import {JsonldToManifest} from './converters/jsonldToManifest.js';
const html = (strings, ...values) => (strings[0] + values.map((v, i) => v + strings[i + 1]).join('')).trim();

function schemaLocationFor(name) {
  return `../entities/${name}.schema`;
}

export class Loader {
  path(fileName) {
    let path = fileName.replace(/[/][^/]+$/, '/');
    return path;
  }

  join(prefix, path) {
    if (/^https?:\/\//.test(path))
      return path;
    // TODO: replace this with something that isn't hacky
    if (path[0] == '/' || path[1] == ':')
      return path;
    prefix = this.path(prefix);
    return prefix + path;
  }

  loadResource(file) {
    if (/^https?:\/\//.test(file))
      return this._loadURL(file);
    return this._loadFile(file);
  }

  _loadFile(file) {
    return new Promise((resolve, reject) => {
      fs.readFile(file, (err, data) => {
        if (err)
          reject(err);
        else
          resolve(data.toString('utf-8'));
      });
    });
  }

  _loadURL(url) {
    if (/\/\/schema.org\//.test(url)) {
      if (url.endsWith('/Thing')) {
        return fetch('https://schema.org/Product.jsonld').then(res => res.text()).then(data => JsonldToManifest.convert(data, {'@id': 'schema:Thing'}));
      }
      return fetch(url + '.jsonld').then(res => res.text()).then(data => JsonldToManifest.convert(data));
    }
    return fetch(url).then(res => res.text());
  }

  async loadParticleClass(spec) {
    let clazz = await this.requireParticle(spec.implFile);
    clazz.spec = spec;
    return clazz;
  }

  async requireParticle(fileName) {
    let src = await this.loadResource(fileName);
    // Note. This is not real isolation.
    let script = new vm.Script(src, {filename: fileName, displayErrors: true});
    let result = [];
    let self = {
      defineParticle(particleWrapper) {
        result.push(particleWrapper);
      },
      console,
      importScripts: s => null //console.log(`(skipping browser-space import for [${s}])`)
    };
    script.runInNewContext(self, {filename: fileName, displayErrors: true});
    assert(result.length > 0 && typeof result[0] == 'function', `Error while instantiating particle implementation from ${fileName}`);
    return this.unwrapParticle(result[0]);
  }

  unwrapParticle(particleWrapper) {
    return particleWrapper({Particle, DomParticle, TransformationDomParticle, MultiplexerDomParticle, html});
  }

}
<commit_msg>Default particle source filename to empty string in loader. (#1487)<commit_after>/**
 * @license
 * Copyright (c) 2017 Google Inc. All rights reserved.
 * This code may only be used under the BSD style license found at
 * http://polymer.github.io/LICENSE.txt
 * Code distributed by Google as part of this project is also
 * subject to an additional IP rights grant found at
 * http://polymer.github.io/PATENTS.txt
 */
import {fs} from '../platform/fs-web.js';
import {vm} from '../platform/vm-web.js';
import {fetch} from './fetch-web.js';

import {assert} from '../platform/assert-web.js';
import {Particle} from './particle.js';
import {DomParticle} from './dom-particle.js';
import {MultiplexerDomParticle} from './multiplexer-dom-particle.js';
import {TransformationDomParticle} from './transformation-dom-particle.js';
import {JsonldToManifest} from './converters/jsonldToManifest.js';
const html = (strings, ...values) => (strings[0] + values.map((v, i) => v + strings[i + 1]).join('')).trim();

function schemaLocationFor(name) {
  return `../entities/${name}.schema`;
}

export class Loader {
  path(fileName) {
    let path = fileName.replace(/[/][^/]+$/, '/');
    return path;
  }

  join(prefix, path) {
    if (/^https?:\/\//.test(path))
      return path;
    // TODO: replace this with something that isn't hacky
    if (path[0] == '/' || path[1] == ':')
      return path;
    prefix = this.path(prefix);
    return prefix + path;
  }

  loadResource(file) {
    if (/^https?:\/\//.test(file))
      return this._loadURL(file);
    return this._loadFile(file);
  }

  _loadFile(file) {
    return new Promise((resolve, reject) => {
      fs.readFile(file, (err, data) => {
        if (err)
          reject(err);
        else
          resolve(data.toString('utf-8'));
      });
    });
  }

  _loadURL(url) {
    if (/\/\/schema.org\//.test(url)) {
      if (url.endsWith('/Thing')) {
        return fetch('https://schema.org/Product.jsonld').then(res => res.text()).then(data => JsonldToManifest.convert(data, {'@id': 'schema:Thing'}));
      }
      return fetch(url + '.jsonld').then(res => res.text()).then(data => JsonldToManifest.convert(data));
    }
    return fetch(url).then(res => res.text());
  }

  async loadParticleClass(spec) {
    let clazz = await this.requireParticle(spec.implFile);
    clazz.spec = spec;
    return clazz;
  }

  async requireParticle(fileName) {
    if (fileName === null) fileName = '';
    let src = await this.loadResource(fileName);
    // Note. This is not real isolation.
    let script = new vm.Script(src, {filename: fileName, displayErrors: true});
    let result = [];
    let self = {
      defineParticle(particleWrapper) {
        result.push(particleWrapper);
      },
      console,
      importScripts: s => null //console.log(`(skipping browser-space import for [${s}])`)
    };
    script.runInNewContext(self, {filename: fileName, displayErrors: true});
    assert(result.length > 0 && typeof result[0] == 'function', `Error while instantiating particle implementation from ${fileName}`);
    return this.unwrapParticle(result[0]);
  }

  unwrapParticle(particleWrapper) {
    return particleWrapper({Particle, DomParticle, TransformationDomParticle, MultiplexerDomParticle, html});
  }

}
<|endoftext|>