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

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

const inquirer = require("inquirer");
const chalk = require("chalk");
const {
  emptyDirSync,
  ensureDirSync,
  copySync,
  moveSync,
  writeJsonSync,
} = require("fs-extra");
const argv = require("minimist")(process.argv.slice(2), {
  string: ["_"],
  boolean: true,
});
const posthtml = require("posthtml");
const fs = require("fs");
const path = require("path");

// Add Search List as prompt type
inquirer.registerPrompt("search-list", require("inquirer-search-list"));

// Set up frameworks and colors
const frameworks = Object.entries({
  vanilla: "yellow",
  vue: "green",
  react: "cyan",
  preact: "magenta",
  "lit-element": "blue",
  svelte: "red",
}).map(([name, color]) => ({
  name: chalk[color](name),
  value: name,
  color,
}));

// Get default args
let targetDir = argv._[0];
let framework = argv.framework || argv.f;
let typescript = argv.typescript || argv.ts;
let overwrite = argv.overwrite;
const defaultProjectName = !targetDir ? "vite-pwa" : targetDir;

if (targetDir === undefined) {
  overwrite = false;
}

// Start the inquisition!
inquirer
  .prompt([
    {
      type: "input",
      name: "dir",
      message: "Project name:",
      default: defaultProjectName,
      when: () => defaultProjectName === "vite-pwa",
    },
    {
      type: "confirm",
      name: "overwrite",
      default: false,
      message: ({ dir }) =>
        (dir === "."
          ? "Current directory"
          : `Target directory "${dir || targetDir}"`) +
        " is not empty. Remove existing files and continue?",
      when: ({ dir }) => !isEmpty(dir) && overwrite !== true,
    },
    {
      type: "input",
      name: "package",
      message: "Package name:",
      default: ({ dir }) =>
        dir ? toValidPackageName(dir) : toValidPackageName(targetDir),
      validate: (package) =>
        isValidPackageName(package) ? true : "Invalid package name",
      when: (answers) =>
        continuePrompts(answers) &&
        (answers.dir
          ? !isValidPackageName(answers.dir)
          : !isValidPackageName(targetDir)),
    },
    {
      type: "search-list",
      name: "framework",
      message: "Select a framework:",
      default: () =>
        framework
          ? isAvailableFramework(framework)?.value
          : frameworks[0].value,
      choices: frameworks,
      when: (answers) =>
        continuePrompts(answers) &&
        (framework ? !isAvailableFramework(framework) : true),
    },
    {
      type: "confirm",
      name: "typescript",
      default: typescript === undefined ? false : true,
      message: "Use TypeScript?",
      when: continuePrompts && typescript === undefined,
    },
  ])
  .then((answers) => {
    if (continuePrompts(answers) === false) {
      throw new Error(chalk.red("✖") + " Operation cancelled");
    }

    const options = Object.assign(
      {
        dir: targetDir,
        framework: framework ? framework.toLowerCase() : "",
        package: targetDir,
        typescript,
        overwrite,
      },
      Object.assign({ package: answers.dir }, answers)
    );

    // Processing files
    const cwd = process.cwd();
    const createViteDir = path.dirname(require.resolve("create-vite"));
    const renameFiles = {
      _gitignore: ".gitignore",
    };

    const root = path.join(cwd, options.dir);

    if (options.overwrite) {
      emptyDirSync(root);
    } else {
      ensureDirSync(root);
    }

    const {color} = isAvailableFramework(options.framework);

    console.log(`\nScaffolding ${chalk[color](options.framework)} project${options.typescript ? chalk.bold(' with TypeScript') : ''} in:\n${root}`);

    const template = options.framework + (options.typescript ? "-ts" : "");

    // Copy files in
    copySync(path.join(createViteDir, `template-${template}`), root);
    copySync(path.join(__dirname, "templates"), root);
    for (const [oldName, newName] of Object.entries(renameFiles)) {
      moveSync(path.join(root, oldName), path.join(root, newName));
    }

    // Update package file
    const pkg = require(path.join(root, "package.json"));
    pkg.name = options.package;
    writeJsonSync(
      path.join(root, "package.json"),
      require("./lib/update-package")(pkg, options.typescript),
      { spaces: 2 }
    );

    // Update index.html to include PWA stuff
    const indexHTML = fs.readFileSync(path.join(root, "index.html"), "utf-8");
    const updatedHTML = posthtml()
      .use(require("./lib/posthtml-add-pwa.js")())
      .process(indexHTML, { sync: true }).html;
    fs.writeFileSync(path.join(root, "index.html"), updatedHTML);

    // Update Vite Config
    require("./lib/update-vite-config")(root, options.typescript);

    // Close out
    const pkgManager = getPkgManager();
    console.log("\nDone. Now run:\n");
    if (root !== cwd) {
      console.log(`  cd ${path.relative(cwd, root)}`);
    }
    switch (pkgManager) {
      case "yarn":
        console.log(`  yarn`);
        console.log("  yarn dev");
        break;
      default:
        console.log(`  ${pkgManager} install`);
        console.log(`  ${pkgManager} run dev`);
        break;
    }
    console.log();
  })
  .catch((e) => {
    console.error(e.message);
  });

// Prompt Helper Functions
function continuePrompts({ dir, overwrite }) {
  if (
    !(
      fs.existsSync(dir || targetDir) &&
      fs.readdirSync(dir || targetDir).length === 0
    ) &&
    overwrite === false
  ) {
    return false;
  }

  return true;
}

function isEmpty(dir) {
  if (!fs.existsSync(dir || targetDir)) return true;

  return fs.readdirSync(dir || targetDir).length === 0;
}

function isValidPackageName(projectName) {
  return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(
    projectName
  );
}

function toValidPackageName(projectName) {
  return projectName
    .trim()
    .toLowerCase()
    .replace(/\s+/g, "-")
    .replace(/^[._]/, "")
    .replace(/[^a-z0-9-~]+/g, "-");
}

function isAvailableFramework(fr) {
  return frameworks.find((f) => f.value === fr.toLowerCase());
}

/**
 * @param {string | undefined} userAgent process.env.npm_config_user_agent
 * @returns object | undefined
 */
function getPkgManager(userAgent = process.env.npm_config_user_agent) {
  if (!userAgent) return "npm";
  const pkgSpec = userAgent.split(" ")[0];
  const pkgSpecArr = pkgSpec.split("/");
  return pkgSpecArr[0] || "npm";
}
<commit_msg>Add JS flags to allow specifying no TS usage<commit_after>#!/usr/bin/env node

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

const inquirer = require("inquirer");
const chalk = require("chalk");
const {
  emptyDirSync,
  ensureDirSync,
  copySync,
  moveSync,
  writeJsonSync,
} = require("fs-extra");
const argv = require("minimist")(process.argv.slice(2), {
  string: ["_"],
  boolean: true,
});
const posthtml = require("posthtml");
const fs = require("fs");
const path = require("path");

// Add Search List as prompt type
inquirer.registerPrompt("search-list", require("inquirer-search-list"));

// Set up frameworks and colors
const frameworks = Object.entries({
  vanilla: "yellow",
  vue: "green",
  react: "cyan",
  preact: "magenta",
  "lit-element": "blue",
  svelte: "red",
}).map(([name, color]) => ({
  name: chalk[color](name),
  value: name,
  color,
}));

// Get default args
let targetDir = argv._[0];
let framework = argv.framework || argv.f;
let typescript = argv.typescript || argv.ts;
let overwrite = argv.overwrite;
const defaultProjectName = !targetDir ? "vite-pwa" : targetDir;

if (argv.javascript || argv.js) {
  typescript = false;
}

if (targetDir === undefined) {
  overwrite = false;
}

// Start the inquisition!
inquirer
  .prompt([
    {
      type: "input",
      name: "dir",
      message: "Project name:",
      default: defaultProjectName,
      when: () => defaultProjectName === "vite-pwa",
    },
    {
      type: "confirm",
      name: "overwrite",
      default: false,
      message: ({ dir }) =>
        (dir === "."
          ? "Current directory"
          : `Target directory "${dir || targetDir}"`) +
        " is not empty. Remove existing files and continue?",
      when: ({ dir }) => !isEmpty(dir) && overwrite !== true,
    },
    {
      type: "input",
      name: "package",
      message: "Package name:",
      default: ({ dir }) =>
        dir ? toValidPackageName(dir) : toValidPackageName(targetDir),
      validate: (package) =>
        isValidPackageName(package) ? true : "Invalid package name",
      when: (answers) =>
        continuePrompts(answers) &&
        (answers.dir
          ? !isValidPackageName(answers.dir)
          : !isValidPackageName(targetDir)),
    },
    {
      type: "search-list",
      name: "framework",
      message: "Select a framework:",
      default: () =>
        framework
          ? isAvailableFramework(framework)?.value
          : frameworks[0].value,
      choices: frameworks,
      when: (answers) =>
        continuePrompts(answers) &&
        (framework ? !isAvailableFramework(framework) : true),
    },
    {
      type: "confirm",
      name: "typescript",
      default: typescript === undefined ? false : true,
      message: "Use TypeScript?",
      when: continuePrompts && typescript === undefined,
    },
  ])
  .then((answers) => {
    if (continuePrompts(answers) === false) {
      throw new Error(chalk.red("✖") + " Operation cancelled");
    }

    const options = Object.assign(
      {
        dir: targetDir,
        framework: framework ? framework.toLowerCase() : "",
        package: targetDir,
        typescript,
        overwrite,
      },
      Object.assign({ package: answers.dir }, answers)
    );

    // Processing files
    const cwd = process.cwd();
    const createViteDir = path.dirname(require.resolve("create-vite"));
    const renameFiles = {
      _gitignore: ".gitignore",
    };

    const root = path.join(cwd, options.dir);

    if (options.overwrite) {
      emptyDirSync(root);
    } else {
      ensureDirSync(root);
    }

    const { color } = isAvailableFramework(options.framework);

    console.log(
      `\nScaffolding ${chalk[color](options.framework)} project${
        options.typescript ? chalk.bold(" with TypeScript") : ""
      } in:\n${root}`
    );

    const template = options.framework + (options.typescript ? "-ts" : "");

    // Copy files in
    copySync(path.join(createViteDir, `template-${template}`), root);
    copySync(path.join(__dirname, "templates"), root);
    for (const [oldName, newName] of Object.entries(renameFiles)) {
      moveSync(path.join(root, oldName), path.join(root, newName));
    }

    // Update package file
    const pkg = require(path.join(root, "package.json"));
    pkg.name = options.package;
    writeJsonSync(
      path.join(root, "package.json"),
      require("./lib/update-package")(pkg, options.typescript),
      { spaces: 2 }
    );

    // Update index.html to include PWA stuff
    const indexHTML = fs.readFileSync(path.join(root, "index.html"), "utf-8");
    const updatedHTML = posthtml()
      .use(require("./lib/posthtml-add-pwa.js")())
      .process(indexHTML, { sync: true }).html;
    fs.writeFileSync(path.join(root, "index.html"), updatedHTML);

    // Update Vite Config
    require("./lib/update-vite-config")(root, options.typescript);

    // Close out
    const pkgManager = getPkgManager();
    console.log("\nDone. Now run:\n");
    if (root !== cwd) {
      console.log(`  cd ${path.relative(cwd, root)}`);
    }
    switch (pkgManager) {
      case "yarn":
        console.log(`  yarn`);
        console.log("  yarn dev");
        break;
      default:
        console.log(`  ${pkgManager} install`);
        console.log(`  ${pkgManager} run dev`);
        break;
    }
    console.log();
  })
  .catch((e) => {
    console.error(e.message);
  });

// Prompt Helper Functions
function continuePrompts({ dir, overwrite }) {
  if (
    !(
      fs.existsSync(dir || targetDir) &&
      fs.readdirSync(dir || targetDir).length === 0
    ) &&
    overwrite === false
  ) {
    return false;
  }

  return true;
}

function isEmpty(dir) {
  if (!fs.existsSync(dir || targetDir)) return true;

  return fs.readdirSync(dir || targetDir).length === 0;
}

function isValidPackageName(projectName) {
  return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(
    projectName
  );
}

function toValidPackageName(projectName) {
  return projectName
    .trim()
    .toLowerCase()
    .replace(/\s+/g, "-")
    .replace(/^[._]/, "")
    .replace(/[^a-z0-9-~]+/g, "-");
}

function isAvailableFramework(fr) {
  return frameworks.find((f) => f.value === fr.toLowerCase());
}

/**
 * @param {string | undefined} userAgent process.env.npm_config_user_agent
 * @returns object | undefined
 */
function getPkgManager(userAgent = process.env.npm_config_user_agent) {
  if (!userAgent) return "npm";
  const pkgSpec = userAgent.split(" ")[0];
  const pkgSpecArr = pkgSpec.split("/");
  return pkgSpecArr[0] || "npm";
}
<|endoftext|>


<commit_before>/**
 * hive.js
 * Copyright (C) 2013-2015 Marcel Klehr <mklehr@gmx.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
var shoe = require('shoe-bin')
  , dataplex = require('dataplex')
  , co = require('co')
  , gulf = require('gulf')
  , through = require('through2')

module.exports = setup
module.exports.consumes = ['hooks','sync', 'auth']

function setup(plugin, imports, register) {
  var hooks = imports.hooks
    , sync = imports.sync
    , auth = imports.auth

  hooks.on('http:listening', function*(server) {
    sock.install(server, '/socket')
  })

  var sock = shoe(function(stream) {
    var plex = dataplex()
    stream.pipe(plex).pipe(stream)

    plex.add('/document/:id/sync', function(opts) {
      var link = new gulf.Link
      // Set up link authorization
      link.authorizeFn = function(msg, credentials, cb) {
        co(function*() {
          var user = yield auth.authenticate('token', credentials)
            , allowed = false
          switch(msg[0]) {
            case 'edit':
              allowed = yield auth.authorize(user, 'document:change', {document: opts.id})
              break;
            case 'ack':
            case 'requestInit':
              allowed = yield auth.authorize(user, 'document/snapshots:index', {document: opts.id})
              break;
          }
          return allowed
        })
        .then(function(allowed) {
          cb(null, allowed)
        })
        .catch(cb)
      }
      co(function*() {
        if(!(yield auth.authorize(plex.user, 'document/snapshots:index', {document: opts.id}))) return
        // load document and add slave link
        var doc = yield sync.getDocument(opts.id)
        doc.attachSlaveLink(link)
      })
      .then(function() {})
      .catch(function(er) { throw new er})
      return link
    })

    plex.add('/authenticate', function() {
      return through(function(chunk, enc, cb) {
        co(function*() {
          plex.user = yield auth.authenticate('token', chunk.toString(enc))
        })
        .then(cb)
        .catch(cb)
      })
    })

    co(function*() {
      yield hooks.callHook('shoe-interface:connect', plex)
    }).then(function() {})
  })

  register()
}<commit_msg>Wire up /document/:id/broadcast with broadcast provider<commit_after>/**
 * hive.js
 * Copyright (C) 2013-2015 Marcel Klehr <mklehr@gmx.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
var shoe = require('shoe-bin')
  , dataplex = require('dataplex')
  , co = require('co')
  , gulf = require('gulf')
  , through = require('through2')
  , PassThrough = require('duplex-passthrough')

module.exports = setup
module.exports.consumes = ['hooks','sync', 'auth', 'broadcast']

function setup(plugin, imports, register) {
  var hooks = imports.hooks
    , sync = imports.sync
    , auth = imports.auth
    , broadcast = imports.broadcast

  hooks.on('http:listening', function*(server) {
    sock.install(server, '/socket')
  })

  var sock = shoe(function(stream) {
    var plex = dataplex()
    stream.pipe(plex).pipe(stream)

    plex.add('/document/:id/sync', function(opts) {
      var link = new gulf.Link
      // Set up link authorization
      link.authorizeFn = function(msg, credentials, cb) {
        co(function*() {
          var user = yield auth.authenticate('token', credentials)
            , allowed = false
          switch(msg[0]) {
            case 'edit':
              allowed = yield auth.authorize(user, 'document:change', {document: opts.id})
              break;
            case 'ack':
            case 'requestInit':
              allowed = yield auth.authorize(user, 'document/snapshots:index', {document: opts.id})
              break;
          }
          return allowed
        })
        .then(function(allowed) {
          cb(null, allowed)
        })
        .catch(cb)
      }
      co(function*() {
        if(!(yield auth.authorize(plex.user, 'document/snapshots:index', {document: opts.id}))) return
        // load document and add slave link
        var doc = yield sync.getDocument(opts.id)
        doc.attachSlaveLink(link)
      })
      .then(function() {})
      .catch(function(er) { throw new er})
      return link
    })

    plex.add('/document/:id/broadcast', function(opts) {
      co(function*(){
        if(!(yield auth.authorize(plex.user, 'document/snapshots:index', {document: opts.id}))) return
        stream.wrapStream(broadcast.document(opts.id))
      }).then(function(){})
      var stream = PassThrough(null)
      return stream
    })

    plex.add('/authenticate', function() {
      return through(function(chunk, enc, cb) {
        co(function*() {
          plex.user = yield auth.authenticate('token', chunk.toString(enc))
        })
        .then(cb)
        .catch(cb)
      })
    })

    co(function*() {
      yield hooks.callHook('shoe-interface:connect', plex)
    }).then(function() {})
  })

  register()
}<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var PLUGIN_NAME = 'kalabox-plugin-dbenv';

module.exports = function(kbox) {

  kbox.whenApp(function(app) {

    // Events
    kbox.core.events.on('pre-install-component', function(component, done) {

      var settings = {};
      var defaultSettings = {
        databases: {
          default: {
            default: {
              driver: 'mysql',
              prefix: '',
              database: 'kalabox',
              username: 'kalabox',
              password: '',
              host: component.appDomain,
              port: 3306
            }
          }
        }
      };
      if (app.config.pluginConf[PLUGIN_NAME]) {
        if (app.config.pluginConf[PLUGIN_NAME].settings) {
          settings = app.config.pluginConf[PLUGIN_NAME].settings;
        }
      }
      settings = _.merge({}, defaultSettings, settings);
      component.installOptions.Env.push(
        'KB_APP_SETTINGS=' + JSON.stringify(settings)
      );

      done();
    });

  });

};
<commit_msg>Need empty conf<commit_after>'use strict';

var _ = require('lodash');
var PLUGIN_NAME = 'kalabox-plugin-dbenv';

module.exports = function(kbox) {

  kbox.whenApp(function(app) {

    // Events
    kbox.core.events.on('pre-install-component', function(component, done) {

      var settings = {};
      var defaultSettings = {
        databases: {
          default: {
            default: {
              driver: 'mysql',
              prefix: '',
              database: 'kalabox',
              username: 'kalabox',
              password: '',
              host: component.appDomain,
              port: 3306
            }
          }
        },
        conf: {}
      };
      if (app.config.pluginConf[PLUGIN_NAME]) {
        if (app.config.pluginConf[PLUGIN_NAME].settings) {
          settings = app.config.pluginConf[PLUGIN_NAME].settings;
        }
      }
      settings = _.merge({}, defaultSettings, settings);
      component.installOptions.Env.push(
        'KB_APP_SETTINGS=' + JSON.stringify(settings)
      );

      done();
    });

  });

};
<|endoftext|>


<commit_before>"use strict"

const program = require('commander');
const cg = require('./src/crystalgazer');
const pkg = require('./package.json');
const blessed = require('blessed');
const contrib = require('blessed-contrib');
const screen = blessed.screen();
const grid = new contrib.grid({rows: 1, cols: 1, screen: screen});

screen.key(['escape', 'q', 'C-c'], function(ch, key) {
    return process.exit(0);
});

let getConfigFrom = function(configName, options){
    let workingDirectory = '.';

    if ( options.workingDirectory ){
        workingDirectory = options.workingDirectory;
    }

    const cgConfig = {
        workingDirectory: workingDirectory,
        name: configName
    };

    return cgConfig;
};

let init = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    cg.init(cgConfig);
};

let numberOfCommits = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    console.log(cgConfig);
    const numberOfCommits = cg.numberOfCommits(cgConfig);

    console.log('Number of commits: ' + numberOfCommits);
};

let numberOfFilesChanged = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    const numberOfFilesChanged = cg.numberOfFilesChanged(cgConfig);

    console.log('numberOfFilesChanged: ' + numberOfFilesChanged);
};

let filesByType = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    const filesByType = cg.filesByType(cgConfig);

    console.log('filesByType: ' + JSON.stringify(filesByType));
};

let authors = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    const authors = cg.authors(cgConfig);

    console.log('authors: ' + authors);
};

let drawTwoColumnTable = function(headers, data){
    var table = grid.set(0, 0, 1, 1,contrib.table,
        { keys: true
        , fg: 'white'
        , selectedFg: 'white'
        , selectedBg: 'blue'
        , interactive: true
        , label: 'Revisions by file (Press ESC to exit)'
        , width: '50%'
        , height: '50%'
        , border: {type: "line", fg: "cyan"}
        , columnSpacing: 5 //in chars
        , columnWidth: [60, 20] /*in chars*/ });

      //allow control the table with the keyboard
      table.focus()

      table.setData(
      { headers: headers
      , data: data});

  screen.render()
};

let revisionsByFile = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    const revisionsByFile = cg.revisionsByFile(cgConfig);
    const headers = ['File name', '# Revisions'];
    const data = revisionsByFile.map(function(item){
        return [item.file, item.revisions];
    });

    drawTwoColumnTable(headers, data);
};

let linesByFile = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    const linesByFile = cg.linesByFile(cgConfig);

    const headers = ['File name', '# Lines'];
    const data = linesByFile.map(function(item){
        return [item.file, item.lines];
    });

    drawTwoColumnTable(headers, data);
};

let authorsByFile = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    const authorsByFile = cg.authorsByFile(cgConfig);

    console.log('authorsByFile: ' + JSON.stringify(authorsByFile));
};

let complexityOverTime = function(configName, fileName, options){
    const cgConfig = getConfigFrom(configName, options);
    cg.complexityOverTime(cgConfig, fileName).then(function(complexity){
        console.log('complexity trend: ' + JSON.stringify(complexity));
    });
};

program
    .version(pkg.version)
    .command('init <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(init);

program
    .command('numberOfCommits <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(numberOfCommits);

program
    .command('numberOfFilesChanged <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(numberOfFilesChanged);

program
    .command('filesByType <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(filesByType);

program
    .command('authors <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(authors);

program
    .command('revisionsByFile <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(revisionsByFile);

program
    .command('linesByFile <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(linesByFile);

program
    .command('authorsByFile <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(authorsByFile);

program
    .command('complexityOverTime <configName> <fileName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(complexityOverTime);

program.parse(process.argv);

// if program was called with no arguments, show help.
if (program.args.length === 0) program.help();<commit_msg>Add line chart visualization for complexity over time.<commit_after>"use strict"

const program = require('commander');
const cg = require('./src/crystalgazer');
const pkg = require('./package.json');
const dateFns = require('date-fns');
const blessed = require('blessed');
const contrib = require('blessed-contrib');
const screen = blessed.screen();

screen.key(['escape', 'q', 'C-c'], function(ch, key) {
    return process.exit(0);
});

let getConfigFrom = function(configName, options){
    let workingDirectory = '.';

    if ( options.workingDirectory ){
        workingDirectory = options.workingDirectory;
    }

    const cgConfig = {
        workingDirectory: workingDirectory,
        name: configName
    };

    return cgConfig;
};

let drawTwoColumnTable = function(headers, data){
    const grid = new contrib.grid({rows: 1, cols: 1, screen: screen});
    const table = grid.set(0, 0, 1, 1,contrib.table,
        { keys: true
        , fg: 'white'
        , selectedFg: 'white'
        , selectedBg: 'blue'
        , interactive: true
        , label: 'Revisions by file (Press ESC to exit)'
        , width: '50%'
        , height: '50%'
        , border: {type: "line", fg: "cyan"}
        , columnSpacing: 5 //in chars
        , columnWidth: [60, 20] /*in chars*/ });

    //allow control the table with the keyboard
    table.focus();

    table.setData(
      { headers: headers
      , data: data});

    screen.render();
};

let init = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    cg.init(cgConfig);
};

let numberOfCommits = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    console.log(cgConfig);
    const numberOfCommits = cg.numberOfCommits(cgConfig);

    console.log('Number of commits: ' + numberOfCommits);
};

let numberOfFilesChanged = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    const numberOfFilesChanged = cg.numberOfFilesChanged(cgConfig);

    console.log('numberOfFilesChanged: ' + numberOfFilesChanged);
};

let filesByType = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    const filesByType = cg.filesByType(cgConfig);

    console.log('filesByType: ' + JSON.stringify(filesByType));
};

let authors = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    const authors = cg.authors(cgConfig);

    console.log('authors: ' + authors);
};

let revisionsByFile = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    const revisionsByFile = cg.revisionsByFile(cgConfig);
    const headers = ['File name', '# Revisions'];
    const data = revisionsByFile.map(function(item){
        return [item.file, item.revisions];
    });

    drawTwoColumnTable(headers, data);
};

let linesByFile = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    const linesByFile = cg.linesByFile(cgConfig);

    const headers = ['File name', '# Lines'];
    const data = linesByFile.map(function(item){
        return [item.file, item.lines];
    });

    drawTwoColumnTable(headers, data);
};

let authorsByFile = function(configName, options){
    const cgConfig = getConfigFrom(configName, options);
    const authorsByFile = cg.authorsByFile(cgConfig);

    const headers = ['File name', '# Authors'];
    const data = authorsByFile.map(function(item){
        return [item.file, item.authors];
    });

    drawTwoColumnTable(headers, data);
};

let addLineChartTo = function(grid, xpos, ypos, label, series){
    let line = grid.set(xpos, ypos, 1, 1,contrib.line,
        { style:
          { line: "yellow"
          , text: "green"
          , baseline: "black"}
        , xLabelPadding: 3
        , xPadding: 5
        , showLegend: false
        , wholeNumbersOnly: true //true=do not show fraction in y axis
        , label: label});

        screen.append(line);
        line.setData([series]);
}

let complexityOverTime = function(configName, fileName, options){
    const cgConfig = getConfigFrom(configName, options);
    cg.complexityOverTime(cgConfig, fileName).then(function(complexity){
        const grid = new contrib.grid({rows: 2, cols: 1, screen: screen});

        var linesSeries = {
            title: 'Lines',
            x: complexity.map(function(c){return c.date;}),
            y: complexity.map(function(c){return c.numberOfLines;}),
            style: {
                line: 'blue'
               }
         };
        addLineChartTo(grid, 0, 0, 'Complexity (number of lines) over time (Press ESC to exit)',linesSeries);

        var tabsSeries = {
            title: 'Tabs',
            x: complexity.map(function(c){return c.date;}),
            y: complexity.map(function(c){return c.maxNumberOfTabs;}),
            style: {
                line: 'red'
            }
        };
        addLineChartTo(grid, 1, 0, 'Complexity (max # of tabs) over time (Press ESC to exit)',tabsSeries);
        screen.render();
    });
};

program
    .version(pkg.version)
    .command('init <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(init);

program
    .command('numberOfCommits <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(numberOfCommits);

program
    .command('numberOfFilesChanged <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(numberOfFilesChanged);

program
    .command('filesByType <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(filesByType);

program
    .command('authors <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(authors);

program
    .command('revisionsByFile <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(revisionsByFile);

program
    .command('linesByFile <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(linesByFile);

program
    .command('authorsByFile <configName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(authorsByFile);

program
    .command('complexityOverTime <configName> <fileName>')
    .option('-w, --workingDirectory <working_directory>', 'working directory')
    .action(complexityOverTime);

program.parse(process.argv);

// if program was called with no arguments, show help.
if (program.args.length === 0) program.help();<|endoftext|>


<commit_before>

function copy(from, to) {
  (from || []).forEach(function (e) {
    to.forEach(function (to) { to.push(e) })
  })
}

function combine(args) {
  var plugs = {}
  var sockets = {}
  args.forEach(function (mod) {
    for(var k in mod) {
      if(Array.isArray(mod[k]))
        (sockets[k] = sockets[k] || []).push(mod[k])
      else if('function' == typeof mod[k])
        (plugs[k] = plugs[k] || []).push(mod[k])
    }
  })

  for(var k in sockets) copy(plugs[k], sockets[k])

  return {plugs: plugs, sockets: sockets}
}

module.exports = combine

<commit_msg>rewrite<commit_after>
function hasAll(set, keys) {
  return keys.every(function (k) {
    return !!set[k]
  })
}

function isString (s) {
  return 'string' === typeof s
}

function isEmpty (e) {
  for(var k in e) return false
  return true
}

var apply = require('./apply')

function keys (obj) {
  return obj ? Object.keys(obj) : []
}

//perform a single pass over the modules,
//and satisify ever module which can now be resolved
//with the current sockets.

//apply this function repeatedly, until either there are
//no more plugs, or there was a pass which did not satisfy anything.

function eachPlug(gives, plugs, iter) {
  if(isString(gives))
    iter(gives, plugs)
  else
    for(var k in module.gives)
      iter(k, plugs[k], gives[k])

}

function append(obj, key, value) {
  obj[key] = (obj[key] || []).concat(value)
}

function setup(sockets, needs) {
  var _sockets = {}
  if(isString(needs)) {
    var name = parts[0]
    var type = parts[1]
    return apply[type](sockets[name])
  }
  else {

  }
}

function satisfy(sockets, module, add) {
  console.log('SAT?', module)
  var added = false
  if(!module.needs) {
    append(add, module.gives, module.create())
    return true
  }
  else if(hasAll(sockets, keys(module.needs))) {
    var _sockets = {}
    keys(module.needs).forEach(function (name) {
      _sockets[name] = apply[module.needs[name]](sockets[name])
    })
    eachPlug(module.gives, module.create(_sockets), function (name, fn) {
      append(add, name, fn)
    })
    return true
  }
  return false
}

module.exports  = function combine (modules, entry, type) {
  //iterate over array, and collect new plugs which are satisfyable.

  if(entry)
    modules.push({
      needs: entry+':'+(type||'first'),
      create: function (entry) {
        return entry
      }
    })

  var sockets = {}
  while (true) {
    var newSockets = {}
    var _modules = modules
    modules = modules.filter(function (module) {
      return !satisfy(sockets, module, newSockets)
    })

    if(isEmpty(newSockets))
      throw new Error('could not resolve all modules')
    else
      for(var k in newSockets)
        append(sockets, k, newSockets[k])

    if(!modules.length)
      return sockets
  }

}

<|endoftext|>


<commit_before>#!/usr/bin/env node
const Promise = require('bluebird');
const fs = require('fs');
const path = require('path');
const request = require('request-promise');
const moment = require('moment');
const _ = require('lodash');
const errors = require('request-promise/errors');

const args = require('./args.js');
const config = _.assign({
    filteredPokemonIds: null,
    trustedUserId: null,
    minLatitude: 24.783617562869416,
    maxLatitude: 24.82740393838965,
    minLongitude: 120.93629837036131,
    maxLongitude: 121.0129451751709,
    queryInterval: 10000,
    telegramChatId: null,
    telegramBotToken: null,
    telegramBotEnable: false,
    source: 'pokeradar'
}, require(path.resolve(args.config)));
const PokeRadar = require('./providers/pokeradar.js');
const telegramBot = require('./telegram_bot.js')(config);
const pokemonNames = require('./pokemon_names.js');
const pokemonStickers = require('./stickers.js');
const getReverseGeocode = require('./get_reverse_geocode.js');

let sentPokemons = [];

const pushNotifications = function(pokemons) {
    let promise = Promise.resolve();
    sentPokemons = _.filter(sentPokemons, (o) => o.until.isAfter(moment()));
    pokemons.forEach(function(v) {
        if (!_.find(sentPokemons, (o) => o.uniqueId == v.uniqueId) && v.remainingTime.diff(moment.utc(0)) > 0) {
            let message = '';
            promise = promise.then(() => getReverseGeocode(v.latitude, v.longitude)).then(function(reverseGeocode) {
                message = `#${v.pokemonName.zh} (${reverseGeocode.map((x) => '#' + x).join(' ')} #${v.pokemonName.en} #${v.pokemonId})\n`
                    + `導航: ${v.direction}\n`
                    + `剩餘時間: ${v.remainingTime.format('mm:ss')}\n`
                    + `結束於: ${v.until.format('YYYY-MM-DD HH:mm:ss')}`;
                console.log(moment().format(), 'message:', message);
            });
            if (config.telegramBotEnable && telegramBot && config.telegramChatId) {
                promise = promise
                    .then(() => telegramBot.sendSticker(config.telegramChatId, pokemonStickers[v.pokemonId]))
                    .then(() => telegramBot.sendMessage(config.telegramChatId, message))
                    .then(() => telegramBot.sendLocation(config.telegramChatId, v.latitude, v.longitude))
                    .catch(function(err) {
                        console.error(moment().format(), err.message);
                    })
            }
            sentPokemons.push(v);
        }
    });
    return promise;
}

let Provider = require('./providers/' + config.source);
let provider = new Provider(config);

provider
    .init()
    .then(function requestLoop() {
        return provider
            .getPokemons()
            .then(pushNotifications)
            .catch(errors.StatusCodeError, function (reason) {
                console.error(moment().format(), reason.message);
            })
            .catch(errors.RequestError, function (reason) {
                console.error(moment().format(), reason.message);
            })
            .delay(config.queryInterval)
            .then(requestLoop);
    });
<commit_msg>Catch general errors outside requestLoop<commit_after>#!/usr/bin/env node
const Promise = require('bluebird');
const fs = require('fs');
const path = require('path');
const request = require('request-promise');
const moment = require('moment');
const _ = require('lodash');
const errors = require('request-promise/errors');

const args = require('./args.js');
const config = _.assign({
    filteredPokemonIds: null,
    trustedUserId: null,
    minLatitude: 24.783617562869416,
    maxLatitude: 24.82740393838965,
    minLongitude: 120.93629837036131,
    maxLongitude: 121.0129451751709,
    queryInterval: 10000,
    telegramChatId: null,
    telegramBotToken: null,
    telegramBotEnable: false,
    source: 'pokeradar'
}, require(path.resolve(args.config)));
const PokeRadar = require('./providers/pokeradar.js');
const telegramBot = require('./telegram_bot.js')(config);
const pokemonNames = require('./pokemon_names.js');
const pokemonStickers = require('./stickers.js');
const getReverseGeocode = require('./get_reverse_geocode.js');

let sentPokemons = [];

const pushNotifications = function(pokemons) {
    let promise = Promise.resolve();
    sentPokemons = _.filter(sentPokemons, (o) => o.until.isAfter(moment()));
    pokemons.forEach(function(v) {
        if (!_.find(sentPokemons, (o) => o.uniqueId == v.uniqueId) && v.remainingTime.diff(moment.utc(0)) > 0) {
            let message = '';
            promise = promise.then(() => getReverseGeocode(v.latitude, v.longitude)).then(function(reverseGeocode) {
                message = `#${v.pokemonName.zh} (${reverseGeocode.map((x) => '#' + x).join(' ')} #${v.pokemonName.en} #${v.pokemonId})\n`
                    + `導航: ${v.direction}\n`
                    + `剩餘時間: ${v.remainingTime.format('mm:ss')}\n`
                    + `結束於: ${v.until.format('YYYY-MM-DD HH:mm:ss')}`;
                console.log(moment().format(), 'message:', message);
            });
            if (config.telegramBotEnable && telegramBot && config.telegramChatId) {
                promise = promise
                    .then(() => telegramBot.sendSticker(config.telegramChatId, pokemonStickers[v.pokemonId]))
                    .then(() => telegramBot.sendMessage(config.telegramChatId, message))
                    .then(() => telegramBot.sendLocation(config.telegramChatId, v.latitude, v.longitude))
                    .catch(function(err) {
                        console.error(moment().format(), err.message);
                    })
            }
            sentPokemons.push(v);
        }
    });
    return promise;
}

let Provider = require('./providers/' + config.source);
let provider = new Provider(config);

provider
    .init()
    .then(function requestLoop() {
        return provider
            .getPokemons()
            .then(pushNotifications)
            .catch(errors.StatusCodeError, function (reason) {
                console.error(moment().format(), reason.message);
            })
            .catch(errors.RequestError, function (reason) {
                console.error(moment().format(), reason.message);
            })

            .delay(config.queryInterval)
            .then(requestLoop);
    })
    .catch(function(reason) {
        console.error(moment().format(), reason.message);
        console.log('Program Stopped')
        // TODO: use TelegramBot#stopPolling instead
        telegramBot._polling.abort = true;
    });
<|endoftext|>


<commit_before>module.exports = {
    rules: {
        "accessor-pairs": 0,
        "array-callback-return": 2,
        "block-scoped-var": 2,
        "complexity": [
            0, 11
        ],
        "consistent-return": 2,
        "curly": [
            2, "multi-line"
        ],
        "default-case": 0,
        "dot-notation": [
            2, {
                "allowKeywords": true
            }
        ],
        "dot-location": 0,
        "eqeqeq": [
            2, "allow-null"
        ],
        "guard-for-in": 0,
        "id-blacklist": 0,
        "no-alert": 1,
        "no-caller": 2,
        "no-case-declarations": 2,
        "no-div-regex": 0,
        "no-else-return": 2,
        "no-empty-function": [
            2, {
                "allow": ["arrowFunctions", "functions", "methods"]
            }
        ],
        "no-empty-pattern": 2,
        "no-extra-label": 2,
        "no-eq-null": 0,
        "no-eval": 2,
        "no-extend-native": 2,
        "no-extra-bind": 2,
        "no-fallthrough": 0,
        "no-floating-decimal": 2,
        "no-implicit-coercion": 0,
        "no-implied-eval": 2,
        "no-invalid-this": 0,
        "no-iterator": 2,
        "no-labels": 1,
        "no-lone-blocks": 2,
        "no-loop-func": 2,
        "no-magic-numbers": [
            0, {
                "ignore": [],
                "ignoreArrayIndexes": true,
                "enforceConst": true,
                "detectObjects": false
            }
        ],
        "no-multi-spaces": 1,
        "no-multi-str": 2,
        "no-native-reassign": 2,
        "no-new": 2,
        "no-new-func": 2,
        "no-new-wrappers": 2,
        "no-octal": 2,
        "no-octal-escape": 2,
        "no-param-reassign": [
            2, {
                "props": true
            }
        ],
        "no-process-env": 0,
        "no-proto": 2,
        "no-redeclare": 2,
        "no-restricted-syntax": [
            2, "DebuggerStatement", "LabeledStatement", "WithStatement"
        ],
        "no-return-assign": 2,
        "no-script-url": 2,
        "no-self-compare": 2,
        "no-sequences": 2,
        "no-throw-literal": 2,
        "no-unmodified-loop-condition": 0,
        "no-unsafe-finally": 2,
        "no-unused-expressions": 0,
        "no-unused-labels": 2,
        "no-useless-call": 0,
        "no-useless-concat": 2,
        "no-useless-escape": 2,
        "no-void": 0,
        "no-warning-comments": [
            0, {
                "terms": [
                    "todo", "fixme", "xxx"
                ],
                "location": "start"
            }
        ],
        "no-with": 2,
        "radix": 2,
        "vars-on-top": 2,
        "wrap-iife": [
            2, "outside"
        ],
        "yoda": 2,
        "no-cond-assign": [
            2, "always"
        ],
        "no-console": 0,
        "no-constant-condition": 1,
        "no-control-regex": 2,
        "no-debugger": 2,
        "no-dupe-args": 2,
        "no-dupe-keys": 2,
        "no-duplicate-case": 2,
        "no-empty-character-class": 2,
        "no-empty": 2,
        "no-ex-assign": 2,
        "no-extra-boolean-cast": 0,
        "no-extra-parens": [
            0,
            "all", {
                "conditionalAssign": true,
                "nestedBinaryExpressions": false
            }
        ],
        "no-extra-semi": 2,
        "no-func-assign": 2,
        "no-inner-declarations": 2,
        "no-invalid-regexp": 2,
        "no-irregular-whitespace": 2,
        "no-negated-in-lhs": 2,
        "no-obj-calls": 2,
        "no-regex-spaces": 2,
        "no-sparse-arrays": 2,
        "no-unreachable": 2,
        "use-isnan": 2,
        "valid-jsdoc": 0,
        "valid-typeof": 2,
        "no-unexpected-multiline": 0,
        "callback-return": 0,
        "global-require": 0,
        "handle-callback-err": 0,
        "no-mixed-requires": [
            0, false
        ],
        "no-new-require": 0,
        "no-path-concat": 0,
        "no-process-exit": 0,
        "no-restricted-modules": 0,
        "no-sync": 0,
        "import/no-unresolved": 0,
        "array-bracket-spacing": [
            2, "never"
        ],
        "block-spacing": [
            2, "always"
        ],
        "brace-style": [
            2,
            "1tbs", {
                "allowSingleLine": true
            }
        ],
        "camelcase": [
            2, {
                "properties": "never"
            }
        ],
        "comma-spacing": [
            2, {
                "before": false,
                "after": true
            }
        ],
        "comma-style": [
            2, "last"
        ],
        "computed-property-spacing": [
            2, "never"
        ],
        "consistent-this": 0,
        "eol-last": 2,
        "func-names": 1,
        "func-style": 0,
        "id-length": 0,
        "indent": [
            1,
            2, {
                "SwitchCase": 1
            }
        ],
        "jsx-quotes": 1,
        "key-spacing": [
            2, {
                "beforeColon": false,
                "afterColon": true
            }
        ],
        "keyword-spacing": [
            2, {
                "before": true,
                "after": true,
                "overrides": {
                    "return": {
                        "after": true
                    },
                    "throw": {
                        "after": true
                    },
                    "case": {
                        "after": true
                    }
                }
            }
        ],
        "lines-around-comment": 0,
        "linebreak-style": 0,
        "max-len": [
            1, {
                "code": 120,
                "ignoreComments": true,
                "ignoreUrls": true,
                "ignoreTemplateLiterals": true
            }
        ],
        "max-nested-callbacks": 0,
        "max-statements-per-line": [
            0, {
                "max": 1
            }
        ],
        "new-cap": [
            2, {
                "newIsCap": true
            }
        ],
        "new-parens": 0,
        "newline-after-var": 0,
        "newline-before-return": 0,
        "newline-per-chained-call": [
            2, {
                "ignoreChainWithDepth": 3
            }
        ],
        "no-array-constructor": 2,
        "no-continue": 0,
        "no-inline-comments": 0,
        "no-lonely-if": 0,
        "no-mixed-spaces-and-tabs": 2,
        "no-multiple-empty-lines": [
            2, {
                "max": 2,
                "maxEOF": 1
            }
        ],
        "no-negated-condition": 0,
        "no-nested-ternary": 2,
        "no-new-object": 2,
        "no-spaced-func": 2,
        "no-ternary": 0,
        "no-trailing-spaces": 1,
        "no-underscore-dangle": 0,
        "no-unneeded-ternary": [
            2, {
                "defaultAssignment": false
            }
        ],
        "no-whitespace-before-property": 2,
        "object-curly-spacing": [
            1, "always"
        ],
        "one-var": [
            2, "never"
        ],
        "one-var-declaration-per-line": [
            2, "always"
        ],
        "operator-assignment": 0,
        "operator-linebreak": 0,
        "padded-blocks": 0,
        "quote-props": 0,
        "quotes": [
            1, "single", {
                "avoidEscape": true,
                "allowTemplateLiterals": true
            }
        ],
        "id-match": 0,
        "require-jsdoc": 0,
        "semi-spacing": [
            2, {
                "before": false,
                "after": true
            }
        ],
        "semi": 1,
        "sort-vars": 0,
        "space-before-blocks": 2,
        "space-before-function-paren": [
            1, "never"
        ],
        "space-in-parens": [
            2, "never"
        ],
        "space-infix-ops": 2,
        "space-unary-ops": 0,
        "spaced-comment": [
            2,
            "always", {
                "exceptions": [
                    "-", "+"
                ],
                "markers": ["=", "!"]
            }
        ],
        "wrap-regex": 0,
        "init-declarations": 0,
        "no-catch-shadow": 0,
        "no-delete-var": 2,
        "no-implicit-globals": 0,
        "no-label-var": 0,
        "no-self-assign": 2,
        "no-shadow-restricted-names": 2,
        "no-shadow": 2,
        "no-undef-init": 0,
        "no-undef": 2,
        "no-undefined": 0,
        "no-unused-vars": [
            1, {
                "vars": "local",
                "args": "after-used"
            }
        ],
        "no-use-before-define": 0,
        "arrow-body-style": [
            2, "as-needed"
        ],
        "arrow-parens": 0,
        "arrow-spacing": [
            2, {
                "before": true,
                "after": true
            }
        ],
        "comma-dangle": 0,
        "constructor-super": 0,
        "generator-star-spacing": 0,
        "no-class-assign": 2,
        "no-confusing-arrow": [
            2, {
                "allowParens": true
            }
        ],
        "no-const-assign": 2,
        "no-dupe-class-members": 2,
        "no-duplicate-imports": 2,
        "no-new-symbol": 2,
        "no-restricted-globals": 0,
        "no-restricted-imports": 0,
        "no-this-before-super": 0,
        "no-var": 2,
        "no-useless-computed-key": 2,
        "no-useless-constructor": 2,
        "object-shorthand": [
            2, "always"
        ],
        "prefer-arrow-callback": [
            2, {
                "allowNamedFunctions": true,
                "allowUnboundThis": true
            }
        ],
        "prefer-const": 1,
        "prefer-spread": 0,
        "prefer-reflect": 0,
        "prefer-rest-params": 2,
        "prefer-template": 1,
        "require-yield": 0,
        "sort-imports": 0,
        "template-curly-spacing": 2,
        "yield-star-spacing": [
            2, "after"
        ],
        "import/export": 2,
        "import/default": 0,
        "import/extensions": [
            0, "never"
        ],
        "import/named": 0,
        "import/namespace": 0,
        "import/no-extraneous-dependencies": [
            0, {
                "devDependencies": false,
                "optionalDependencies": false
            }
        ],
        "import/no-named-as-default": 0,
        "import/no-commonjs": 0,
        "import/no-amd": 2,
        "import/imports-first": [
            0, "absolute-first"
        ],
        "import/no-duplicates": 0,
        "import/no-deprecated": 0,
        "import/no-namespace": 0,
        "import/no-named-as-default-member": 0,
        "import/no-nodejs-modules": 0,
        "import/order": [
            0, {
                "groups": [
                    "builtin",
                    "external",
                    "internal",
                    "parent",
                    "sibling",
                    "index"
                ],
                "newlines-between": "never"
            }
        ],
        "import/newline-after-import": 0,
        "import/no-mutable-exports": 2,
        "strict": [
            2, "never"
        ],
        "react/display-name": [
            0, {
                "ignoreTranspilerName": false
            }
        ],
        "react/forbid-prop-types": [
            0, {
                "forbid": ["any", "array", "object"]
            }
        ],
        "react/jsx-boolean-value": [
            2, "never"
        ],
        "react/jsx-closing-bracket-location": 0,
        "react/jsx-curly-spacing": [
            2,
            "never", {
                "allowMultiline": true
            }
        ],
        "react/jsx-handler-names": [
            0, {
                "eventHandlerPrefix": "handle",
                "eventHandlerPropPrefix": "on"
            }
        ],
        "react/jsx-indent-props": 0,
        "react/jsx-key": 0,
        "react/jsx-max-props-per-line": [
            0, {
                "maximum": 1
            }
        ],
        "react/jsx-no-bind": [
            2, {
                "ignoreRefs": true,
                "allowArrowFunctions": true,
                "allowBind": false
            }
        ],
        "react/jsx-no-duplicate-props": [
            0, {
                "ignoreCase": false
            }
        ],
        "react/jsx-no-literals": 0,
        "react/jsx-no-undef": 2,
        "react/jsx-pascal-case": 2,
        "react/sort-prop-types": [
            0, {
                "ignoreCase": false,
                "callbacksLast": false
            }
        ],
        "react/jsx-sort-prop-types": 0,
        "react/jsx-sort-props": [
            0, {
                "ignoreCase": false,
                "callbacksLast": false
            }
        ],
        "react/jsx-filename-extension": 0,
        "react/jsx-uses-react": 1,
        "react/jsx-uses-vars": 1,
        "react/no-danger": 0,
        "react/no-deprecated": 1,
        "react/no-did-mount-set-state": 2,
        "react/no-did-update-set-state": 2,
        "react/no-direct-mutation-state": 0,
        "react/no-is-mounted": 2,
        "react/no-multi-comp": [
            2, {
                "ignoreStateless": true
            }
        ],
        "react/no-set-state": 0,
        "react/no-string-refs": 0,
        "react/no-unknown-property": 2,
        "react/prefer-es6-class": [
            2, "always"
        ],
        "react/prefer-stateless-function": 0,
        "react/prop-types": 0,
        "react/react-in-jsx-scope": 1,
        "react/require-extension": [
            0, {
                "extensions": [".jsx"]
            }
        ],
        "react/require-render-return": 2,
        "react/self-closing-comp": 0,
        "react/jsx-space-before-closing": [
            2, "always"
        ],
        "react/sort-comp": 0,
        "react/jsx-first-prop-new-line": 0,
        "react/jsx-equals-spacing": [
            2, "never"
        ],
        "react/jsx-indent": [
            1, 2
        ],
    }
};
<commit_msg>Make spaced-comment warning instead of error<commit_after>module.exports = {
    rules: {
        "accessor-pairs": 0,
        "array-callback-return": 2,
        "block-scoped-var": 2,
        "complexity": [
            0, 11
        ],
        "consistent-return": 2,
        "curly": [
            2, "multi-line"
        ],
        "default-case": 0,
        "dot-notation": [
            2, {
                "allowKeywords": true
            }
        ],
        "dot-location": 0,
        "eqeqeq": [
            2, "allow-null"
        ],
        "guard-for-in": 0,
        "id-blacklist": 0,
        "no-alert": 1,
        "no-caller": 2,
        "no-case-declarations": 2,
        "no-div-regex": 0,
        "no-else-return": 2,
        "no-empty-function": [
            2, {
                "allow": ["arrowFunctions", "functions", "methods"]
            }
        ],
        "no-empty-pattern": 2,
        "no-extra-label": 2,
        "no-eq-null": 0,
        "no-eval": 2,
        "no-extend-native": 2,
        "no-extra-bind": 2,
        "no-fallthrough": 0,
        "no-floating-decimal": 2,
        "no-implicit-coercion": 0,
        "no-implied-eval": 2,
        "no-invalid-this": 0,
        "no-iterator": 2,
        "no-labels": 1,
        "no-lone-blocks": 2,
        "no-loop-func": 2,
        "no-magic-numbers": [
            0, {
                "ignore": [],
                "ignoreArrayIndexes": true,
                "enforceConst": true,
                "detectObjects": false
            }
        ],
        "no-multi-spaces": 1,
        "no-multi-str": 2,
        "no-native-reassign": 2,
        "no-new": 2,
        "no-new-func": 2,
        "no-new-wrappers": 2,
        "no-octal": 2,
        "no-octal-escape": 2,
        "no-param-reassign": [
            2, {
                "props": true
            }
        ],
        "no-process-env": 0,
        "no-proto": 2,
        "no-redeclare": 2,
        "no-restricted-syntax": [
            2, "DebuggerStatement", "LabeledStatement", "WithStatement"
        ],
        "no-return-assign": 2,
        "no-script-url": 2,
        "no-self-compare": 2,
        "no-sequences": 2,
        "no-throw-literal": 2,
        "no-unmodified-loop-condition": 0,
        "no-unsafe-finally": 2,
        "no-unused-expressions": 0,
        "no-unused-labels": 2,
        "no-useless-call": 0,
        "no-useless-concat": 2,
        "no-useless-escape": 2,
        "no-void": 0,
        "no-warning-comments": [
            0, {
                "terms": [
                    "todo", "fixme", "xxx"
                ],
                "location": "start"
            }
        ],
        "no-with": 2,
        "radix": 2,
        "vars-on-top": 2,
        "wrap-iife": [
            2, "outside"
        ],
        "yoda": 2,
        "no-cond-assign": [
            2, "always"
        ],
        "no-console": 0,
        "no-constant-condition": 1,
        "no-control-regex": 2,
        "no-debugger": 2,
        "no-dupe-args": 2,
        "no-dupe-keys": 2,
        "no-duplicate-case": 2,
        "no-empty-character-class": 2,
        "no-empty": 2,
        "no-ex-assign": 2,
        "no-extra-boolean-cast": 0,
        "no-extra-parens": [
            0,
            "all", {
                "conditionalAssign": true,
                "nestedBinaryExpressions": false
            }
        ],
        "no-extra-semi": 2,
        "no-func-assign": 2,
        "no-inner-declarations": 2,
        "no-invalid-regexp": 2,
        "no-irregular-whitespace": 2,
        "no-negated-in-lhs": 2,
        "no-obj-calls": 2,
        "no-regex-spaces": 2,
        "no-sparse-arrays": 2,
        "no-unreachable": 2,
        "use-isnan": 2,
        "valid-jsdoc": 0,
        "valid-typeof": 2,
        "no-unexpected-multiline": 0,
        "callback-return": 0,
        "global-require": 0,
        "handle-callback-err": 0,
        "no-mixed-requires": [
            0, false
        ],
        "no-new-require": 0,
        "no-path-concat": 0,
        "no-process-exit": 0,
        "no-restricted-modules": 0,
        "no-sync": 0,
        "import/no-unresolved": 0,
        "array-bracket-spacing": [
            2, "never"
        ],
        "block-spacing": [
            2, "always"
        ],
        "brace-style": [
            2,
            "1tbs", {
                "allowSingleLine": true
            }
        ],
        "camelcase": [
            2, {
                "properties": "never"
            }
        ],
        "comma-spacing": [
            2, {
                "before": false,
                "after": true
            }
        ],
        "comma-style": [
            2, "last"
        ],
        "computed-property-spacing": [
            2, "never"
        ],
        "consistent-this": 0,
        "eol-last": 2,
        "func-names": 1,
        "func-style": 0,
        "id-length": 0,
        "indent": [
            1,
            2, {
                "SwitchCase": 1
            }
        ],
        "jsx-quotes": 1,
        "key-spacing": [
            2, {
                "beforeColon": false,
                "afterColon": true
            }
        ],
        "keyword-spacing": [
            2, {
                "before": true,
                "after": true,
                "overrides": {
                    "return": {
                        "after": true
                    },
                    "throw": {
                        "after": true
                    },
                    "case": {
                        "after": true
                    }
                }
            }
        ],
        "lines-around-comment": 0,
        "linebreak-style": 0,
        "max-len": [
            1, {
                "code": 120,
                "ignoreComments": true,
                "ignoreUrls": true,
                "ignoreTemplateLiterals": true
            }
        ],
        "max-nested-callbacks": 0,
        "max-statements-per-line": [
            0, {
                "max": 1
            }
        ],
        "new-cap": [
            2, {
                "newIsCap": true
            }
        ],
        "new-parens": 0,
        "newline-after-var": 0,
        "newline-before-return": 0,
        "newline-per-chained-call": [
            2, {
                "ignoreChainWithDepth": 3
            }
        ],
        "no-array-constructor": 2,
        "no-continue": 0,
        "no-inline-comments": 0,
        "no-lonely-if": 0,
        "no-mixed-spaces-and-tabs": 2,
        "no-multiple-empty-lines": [
            2, {
                "max": 2,
                "maxEOF": 1
            }
        ],
        "no-negated-condition": 0,
        "no-nested-ternary": 2,
        "no-new-object": 2,
        "no-spaced-func": 2,
        "no-ternary": 0,
        "no-trailing-spaces": 1,
        "no-underscore-dangle": 0,
        "no-unneeded-ternary": [
            2, {
                "defaultAssignment": false
            }
        ],
        "no-whitespace-before-property": 2,
        "object-curly-spacing": [
            1, "always"
        ],
        "one-var": [
            2, "never"
        ],
        "one-var-declaration-per-line": [
            2, "always"
        ],
        "operator-assignment": 0,
        "operator-linebreak": 0,
        "padded-blocks": 0,
        "quote-props": 0,
        "quotes": [
            1, "single", {
                "avoidEscape": true,
                "allowTemplateLiterals": true
            }
        ],
        "id-match": 0,
        "require-jsdoc": 0,
        "semi-spacing": [
            2, {
                "before": false,
                "after": true
            }
        ],
        "semi": 1,
        "sort-vars": 0,
        "space-before-blocks": 2,
        "space-before-function-paren": [
            1, "never"
        ],
        "space-in-parens": [
            2, "never"
        ],
        "space-infix-ops": 2,
        "space-unary-ops": 0,
        "spaced-comment": [
            1,
            "always", {
                "exceptions": [
                    "-", "+"
                ],
                "markers": ["=", "!"]
            }
        ],
        "wrap-regex": 0,
        "init-declarations": 0,
        "no-catch-shadow": 0,
        "no-delete-var": 2,
        "no-implicit-globals": 0,
        "no-label-var": 0,
        "no-self-assign": 2,
        "no-shadow-restricted-names": 2,
        "no-shadow": 2,
        "no-undef-init": 0,
        "no-undef": 2,
        "no-undefined": 0,
        "no-unused-vars": [
            1, {
                "vars": "local",
                "args": "after-used"
            }
        ],
        "no-use-before-define": 0,
        "arrow-body-style": [
            2, "as-needed"
        ],
        "arrow-parens": 0,
        "arrow-spacing": [
            2, {
                "before": true,
                "after": true
            }
        ],
        "comma-dangle": 0,
        "constructor-super": 0,
        "generator-star-spacing": 0,
        "no-class-assign": 2,
        "no-confusing-arrow": [
            2, {
                "allowParens": true
            }
        ],
        "no-const-assign": 2,
        "no-dupe-class-members": 2,
        "no-duplicate-imports": 2,
        "no-new-symbol": 2,
        "no-restricted-globals": 0,
        "no-restricted-imports": 0,
        "no-this-before-super": 0,
        "no-var": 2,
        "no-useless-computed-key": 2,
        "no-useless-constructor": 2,
        "object-shorthand": [
            2, "always"
        ],
        "prefer-arrow-callback": [
            2, {
                "allowNamedFunctions": true,
                "allowUnboundThis": true
            }
        ],
        "prefer-const": 1,
        "prefer-spread": 0,
        "prefer-reflect": 0,
        "prefer-rest-params": 2,
        "prefer-template": 1,
        "require-yield": 0,
        "sort-imports": 0,
        "template-curly-spacing": 2,
        "yield-star-spacing": [
            2, "after"
        ],
        "import/export": 2,
        "import/default": 0,
        "import/extensions": [
            0, "never"
        ],
        "import/named": 0,
        "import/namespace": 0,
        "import/no-extraneous-dependencies": [
            0, {
                "devDependencies": false,
                "optionalDependencies": false
            }
        ],
        "import/no-named-as-default": 0,
        "import/no-commonjs": 0,
        "import/no-amd": 2,
        "import/imports-first": [
            0, "absolute-first"
        ],
        "import/no-duplicates": 0,
        "import/no-deprecated": 0,
        "import/no-namespace": 0,
        "import/no-named-as-default-member": 0,
        "import/no-nodejs-modules": 0,
        "import/order": [
            0, {
                "groups": [
                    "builtin",
                    "external",
                    "internal",
                    "parent",
                    "sibling",
                    "index"
                ],
                "newlines-between": "never"
            }
        ],
        "import/newline-after-import": 0,
        "import/no-mutable-exports": 2,
        "strict": [
            2, "never"
        ],
        "react/display-name": [
            0, {
                "ignoreTranspilerName": false
            }
        ],
        "react/forbid-prop-types": [
            0, {
                "forbid": ["any", "array", "object"]
            }
        ],
        "react/jsx-boolean-value": [
            2, "never"
        ],
        "react/jsx-closing-bracket-location": 0,
        "react/jsx-curly-spacing": [
            2,
            "never", {
                "allowMultiline": true
            }
        ],
        "react/jsx-handler-names": [
            0, {
                "eventHandlerPrefix": "handle",
                "eventHandlerPropPrefix": "on"
            }
        ],
        "react/jsx-indent-props": 0,
        "react/jsx-key": 0,
        "react/jsx-max-props-per-line": [
            0, {
                "maximum": 1
            }
        ],
        "react/jsx-no-bind": [
            2, {
                "ignoreRefs": true,
                "allowArrowFunctions": true,
                "allowBind": false
            }
        ],
        "react/jsx-no-duplicate-props": [
            0, {
                "ignoreCase": false
            }
        ],
        "react/jsx-no-literals": 0,
        "react/jsx-no-undef": 2,
        "react/jsx-pascal-case": 2,
        "react/sort-prop-types": [
            0, {
                "ignoreCase": false,
                "callbacksLast": false
            }
        ],
        "react/jsx-sort-prop-types": 0,
        "react/jsx-sort-props": [
            0, {
                "ignoreCase": false,
                "callbacksLast": false
            }
        ],
        "react/jsx-filename-extension": 0,
        "react/jsx-uses-react": 1,
        "react/jsx-uses-vars": 1,
        "react/no-danger": 0,
        "react/no-deprecated": 1,
        "react/no-did-mount-set-state": 2,
        "react/no-did-update-set-state": 2,
        "react/no-direct-mutation-state": 0,
        "react/no-is-mounted": 2,
        "react/no-multi-comp": [
            2, {
                "ignoreStateless": true
            }
        ],
        "react/no-set-state": 0,
        "react/no-string-refs": 0,
        "react/no-unknown-property": 2,
        "react/prefer-es6-class": [
            2, "always"
        ],
        "react/prefer-stateless-function": 0,
        "react/prop-types": 0,
        "react/react-in-jsx-scope": 1,
        "react/require-extension": [
            0, {
                "extensions": [".jsx"]
            }
        ],
        "react/require-render-return": 2,
        "react/self-closing-comp": 0,
        "react/jsx-space-before-closing": [
            1, "always"
        ],
        "react/sort-comp": 0,
        "react/jsx-first-prop-new-line": 0,
        "react/jsx-equals-spacing": [
            2, "never"
        ],
        "react/jsx-indent": [
            1, 2
        ],
    }
};
<|endoftext|>


<commit_before>'use strict';

var yeoman = require('yeoman-generator');
var _ = require('lodash');

var PageChisel = yeoman.Base.extend({
  /**
   * Extends base Yeoman constructor
   * @public
   */
  constructor: function () {
    yeoman.Base.apply(this, arguments);
    this.sourceRoot(this.destinationRoot());

    this.option('skip-build', {
      desc: 'Do not run `gulp build` after pages are created',
      type: Boolean,
      defaults: false
    });
  },

  /**
   * Reads current generator config and list of pages
   * @public
   */
  initializing: function () {
    try {
      this.configuration = this.config.get('config');
    } catch (ex) {
      this.log('You need to run this generator in a project directory.');
      process.exit();
    }

    if(this.configuration.features && this.configuration.features.has_wp) {
      this.log('You can\'t add pages to WordPress projects.');
      process.exit();
    }

    this.pages = this.config.get('pages');
  },

  /**
   * Gets generator arguments
   * @public
   */
  prompting: {
    /**
     * Gets new pages listed in arguments and checks if there're any pages to render
     * @public
     */
    checkNames: function () {
      this.argument('newPages', {
        desc: 'List of names',
        type: Array,
        required: false
      });

      this.pages = _.union(this.newPages, this.pages);

      if (_.isEmpty(this.pages)) {
        this.log('Page names list cannot be empty.');
        process.exit();
      }
    },

    /**
     * Checks if there are any reserved names in pages array
     * @public
     */
    checkReservedNames: function () {
      var reservedNames = ['_template'];
      var isReserved = function (page) {
        return _.includes(reservedNames, _.kebabCase(page));
      };

      if (_.some(this.pages, isReserved, this)) {
        this.log('You cannot use those reserved words: ' + reservedNames.join(', ') + '.');
        process.exit();
      }
    }
  },

  /**
   * Updated the generator config file with new pages
   * @public
   */
  configuring: function () {
    this.config.set('pages', this.pages);
  },

  /**
   * Generates template files based on provided list or stored in config file
   * @public
   */
  writing: {
    /**
     * Generates template files based on provided list or stored in config file
     * @public
     */
    generatePages: function () {
      this.pages.forEach(function(pageName) {
        var fileName = _.kebabCase(pageName) + '.twig';

        // Write file if not exists
        if (!this.fs.exists(this.destinationPath('src/templates/' + fileName))) {
          this.fs.copyTpl(this.templatePath('src/templates/_template.twig'), this.destinationPath('src/templates/' + fileName), {
            pageName: pageName
          });
        }
      }, this);
    },

    /**
     * Updates main project page listing with generated page list
     * @public
     */
    updateIndex: function () {
      var pagesObject = [];

      this.pages.forEach(function(page) {
        pagesObject.push({ name: page, slug: _.kebabCase(page) });
      });

      this.fs.copyTpl(this.templatePath('index/project-index.html'), this.destinationPath('index.html'), { pages: pagesObject });
    }

  },

  /**
   * Runs build helpers if they're not skipped by generator
   * @public
   */
  install: function () {
    if (!this.options['skip-build']) {
      this.spawnCommand('gulp', ['build']);
    }

    this.log('All done!');
  }
});

module.exports = PageChisel;
<commit_msg>Add new pages at the end of the list Fixes #83<commit_after>'use strict';

var yeoman = require('yeoman-generator');
var _ = require('lodash');

var PageChisel = yeoman.Base.extend({
  /**
   * Extends base Yeoman constructor
   * @public
   */
  constructor: function () {
    yeoman.Base.apply(this, arguments);
    this.sourceRoot(this.destinationRoot());

    this.option('skip-build', {
      desc: 'Do not run `gulp build` after pages are created',
      type: Boolean,
      defaults: false
    });
  },

  /**
   * Reads current generator config and list of pages
   * @public
   */
  initializing: function () {
    try {
      this.configuration = this.config.get('config');
    } catch (ex) {
      this.log('You need to run this generator in a project directory.');
      process.exit();
    }

    if(this.configuration.features && this.configuration.features.has_wp) {
      this.log('You can\'t add pages to WordPress projects.');
      process.exit();
    }

    this.pages = this.config.get('pages');
  },

  /**
   * Gets generator arguments
   * @public
   */
  prompting: {
    /**
     * Gets new pages listed in arguments and checks if there're any pages to render
     * @public
     */
    checkNames: function () {
      this.argument('newPages', {
        desc: 'List of names',
        type: Array,
        required: false
      });

      this.pages = _.union(this.pages, this.newPages);

      if (_.isEmpty(this.pages)) {
        this.log('Page names list cannot be empty.');
        process.exit();
      }
    },

    /**
     * Checks if there are any reserved names in pages array
     * @public
     */
    checkReservedNames: function () {
      var reservedNames = ['_template'];
      var isReserved = function (page) {
        return _.includes(reservedNames, _.kebabCase(page));
      };

      if (_.some(this.pages, isReserved, this)) {
        this.log('You cannot use those reserved words: ' + reservedNames.join(', ') + '.');
        process.exit();
      }
    }
  },

  /**
   * Updated the generator config file with new pages
   * @public
   */
  configuring: function () {
    this.config.set('pages', this.pages);
  },

  /**
   * Generates template files based on provided list or stored in config file
   * @public
   */
  writing: {
    /**
     * Generates template files based on provided list or stored in config file
     * @public
     */
    generatePages: function () {
      this.pages.forEach(function(pageName) {
        var fileName = _.kebabCase(pageName) + '.twig';

        // Write file if not exists
        if (!this.fs.exists(this.destinationPath('src/templates/' + fileName))) {
          this.fs.copyTpl(this.templatePath('src/templates/_template.twig'), this.destinationPath('src/templates/' + fileName), {
            pageName: pageName
          });
        }
      }, this);
    },

    /**
     * Updates main project page listing with generated page list
     * @public
     */
    updateIndex: function () {
      var pagesObject = [];

      this.pages.forEach(function(page) {
        pagesObject.push({ name: page, slug: _.kebabCase(page) });
      });

      this.fs.copyTpl(this.templatePath('index/project-index.html'), this.destinationPath('index.html'), { pages: pagesObject });
    }

  },

  /**
   * Runs build helpers if they're not skipped by generator
   * @public
   */
  install: function () {
    if (!this.options['skip-build']) {
      this.spawnCommand('gulp', ['build']);
    }

    this.log('All done!');
  }
});

module.exports = PageChisel;
<|endoftext|>