<commit_before>var _ = require('../util').lodash,
    Property = require('./property').Property,
    PropertyList = require('./property-list').PropertyList,
    EventList = require('./event-list').EventList,
    Request = require('./request').Request,
    RequestAuth = require('./request-auth').RequestAuth,
    Response = require('./response').Response,

    Item,

    /**
     * Whitelisted protocol profile behaviors.
     *
     * @private
     * @type {String}
     *
     * @todo change type to array for supporting multiple behaviors
     */
    PROTOCOL_PROFILE_BEHAVIORS = 'disableBodyPruning',

    /**
     * Extracts `auth` from an entity. Checks if `auth` is present and it is not falsy type.
     *
     * @private
     *
     * @param {Object} [entity]
     */
    extractAuth = function (entity) {
        var auth;

        return (entity && (auth = entity.auth) && RequestAuth.isValidType(auth.type)) ? auth : undefined;
    };

/**
 * The following defines the object (or JSON) structure that one can pass to the Item while creating a new Item
 * instance. This is also the object structure returned when `.toJSON()` is called on an Item instance.
 * @typedef Item~definition
 *
 * @property {Request~definition=} [request] A request represents an HTTP request. If a string, the string is assumed to
 * be the request URL and the method is assumed to be 'GET'.
 * @property {Array<Response~definition>=} [responses] Sample responses for this request can be stored along with the
 * item definition.
 * @property {Array<Event~definition>=} [events] Postman allows you to configure scripts to run when specific events
 * occur. These scripts are stored here, and can be referenced in the collection by their id.
 *
 * @example
 * {
 *     "name": "Get Headers from Echo",
 *     "id": "my-request-1",
 *     "description": "Makes a GET call to echo service and returns the client headers that were sent",
 *
 *     "request": {
 *         "url": "https://postman-echo.com/headers",
 *         "method": "GET"
 *     }
 * }
 *
 * @todo add response and event to example
 */
_.inherit((

    /**
     * A Postman Collection Item that holds your request definition, responses and other stuff. An Item essentially is
     * a HTTP request definition along with the sample responses and test scripts clubbed together. One or more of these
     * items can be grouped together and placed in an {@link ItemGroup} and as such forms a {@link Collection} of
     * requests.
     *
     * @constructor
     * @extends {Property}
     *
     * @param {Item~definition=} [definition] While creating a new instance of Item, one can provide the initial
     * configuration of the item with the the request it sends, the expected sample responses, tests, etc
     *
     * @example
Add a new Item to a folder in a collection instance

     * var Collection = require('postman-collection').Collection,
     *     Item = require('postman-collection').Item,
     *     myCollection;
     *
     * myCollection = new Collection({
     *     "item": [{
     *         "id": "my-folder-1",
     *         "name": "The solo folder in this collection",
     *         "item": [] // blank array indicates this is a folder
     *     }]
     * }); // create a collection with an empty folder
     * // add a request to "my-folder-1" that sends a GET request
     * myCollection.items.one("my-folder-1").items.add(new Item({
     *     "name": "Send a GET request",
     *     "id": "my-get-request",
     *     "request": {
     *         "url": "https://postman-echo.com/get",
     *         "method": "GET"
     *     }
     * }));
     */
    Item = function PostmanItem (definition) {
        // this constructor is intended to inherit and as such the super constructor is required to be executed
        Item.super_.apply(this, arguments);

        _.mergeDefined(this, /** @lends Item.prototype */ {
            /**
             * The instance of the {@link Request} object inside an Item defines the HTTP request that is supposed to be
             * sent. It further contains the request method, url, request body, etc.
             * @type {Request}
             */
            request: definition && (new Request(definition.request)),

            /**
             * An Item also contains a list of sample responses that is expected when the request defined in the item is
             * executed. The sample responses are useful in elaborating API usage and is also useful for other
             * integrations that use the sample responses to do something - say a mock service.
             * @type {PropertyList<Response>}
             */
            responses: new PropertyList(Response, this, definition && definition.response),

            /**
             * Events are a set of of {@link Script}s that are executed when certain activities are triggered on an
             * Item. For example, on defining an event that listens to the "test" event, would cause the associated
             * script of the event to be executed when the test runs.
             * @type {EventList}
             *
             * @example
Add a script to be executed on "prerequest" event

             * var Collection = require('postman-collection').Collection,
             *     Item = require('postman-collection').Item,
             *     myCollection;
             *
             * myCollection = new Collection({
             *     "item": [{
             *         "name": "Send a GET request",
             *         "id": "my-get-request",
             *         "request": {
             *             "url": "https://postman-echo.com/get",
             *             "method": "GET"
             *         }
             *     }]
             * }); // create a collection with one request
             *
             * // add a pre-request script to the event list
             * myCollection.items.one('my-get-request').events.add({
             *     "listen": "prerequest",
             *     "script": {
             *         "type": "text/javascript",
             *         "exec": "console.log(new Date())"
             *     }
             * });
             */
            events: new EventList(this, definition && definition.event),

            /**
             * Set of configurations used to alter the usual behavior of sending the request.
             *
             * @type {Object}
             * @property {Boolean} disableBodyPruning Disable body pruning for request methods like GET, HEAD etc.
             *
             * @todo Inherit this from ItemGroup & Collection
             */
            protocolProfileBehavior: definition && definition.protocolProfileBehavior &&
                _.pick(definition.protocolProfileBehavior, PROTOCOL_PROFILE_BEHAVIORS)
        });
    }), Property);

_.assign(Item.prototype, /** @lends Item.prototype */ {
    /**
     * Defines whether this property instances requires an id
     * @private
     * @readOnly
     * @type {Boolean}
     */
    _postman_propertyRequiresId: true,

    /**
     * Fetches applicable AuthType from the current item.
     *
     * @returns {RequestAuth}
     *
     * @note Since v3.0 release, this returns the entire auth RequestAuth, instead of just the parameters
     */
    getAuth: function () {
        var requestAuth;

        // find auth on request, if not found or empty auth, lookup in the parents
        return (requestAuth = extractAuth(this.request)) ? requestAuth : this.findInParents('auth', extractAuth);
    },

    /**
     * Returns {@link Event}s corresponding to a particular event name. If no name is given, returns all events. This
     * is useful when you want to trigger all associated scripts for an event.
     *
     * @param {String} name - one of the available event types such as `test`, `prerequest`, `postrequest`, etc.
     * @returns {Array<Event>}
     *
     * @example
Get all events for an item and evaluate their scripts

     * var fs = require('fs'), // needed to read JSON file from disk
     *     Collection = require('postman-collection').Collection,
     *     myCollection;
     *
     * // Load a collection to memory from a JSON file on disk (say, sample-collection.json)
     * myCollection = new Collection(JSON.stringify(fs.readFileSync('sample-collection.json').toString()));
     *
     * // assuming the collection has a request called "my-request-1" in root, we get it's test events
     * myCollection.items.one("my-request-1").getEvents("test").forEach(function (event) {
     *     event.script && eval(event.script.toSource());
     * });
     *
     * @todo decide appropriate verb names based on the fact that it gets events for a specific listener name
     * @draft
     */
    getEvents: function (name) {
        if (!name) {
            return this.events.all(); // return all events if name is not provided.
        }
        return this.events.filter(function (ev) {
            return ev.listen === name;
        });
    },

    /**
     * Sets authentication method for the request within this item
     *
     * @param {?String|RequestAuth~definition} type
     * @param {VariableList~definition=} [options]
     *
     * @note This function was previously (in v2 of SDK) used to clone request and populate headers. Now it is used to
     * only set auth information to request
     */
    authorizeRequestUsing: function (type, options) {
        if (!this.request) { this.request = new Request(); } // worst case
        return this.request.authorizeUsing(type, options);
    }
});

_.assign(Item, /** @lends Item */ {
    /**
     * Defines the name of this property for internal use.
     * @private
     * @readOnly
     * @type {String}
     */
    _postman_propertyName: 'Item',

    /**
     * Check whether an object is an instance of PostmanItem.
     *
     * @param {*} obj
     * @returns {Boolean}
     */
    isItem: function (obj) {
        return Boolean(obj) && ((obj instanceof Item) ||
            _.inSuperChain(obj.constructor, '_postman_propertyName', Item._postman_propertyName));
    }
});

module.exports = {
    Item: Item
};
<commit_msg>Update const `PROTOCOL_PROFILE_BEHAVIORS` to array of strings<commit_after>var _ = require('../util').lodash,
    Property = require('./property').Property,
    PropertyList = require('./property-list').PropertyList,
    EventList = require('./event-list').EventList,
    Request = require('./request').Request,
    RequestAuth = require('./request-auth').RequestAuth,
    Response = require('./response').Response,

    Item,

    /**
     * Whitelisted protocol profile behaviors.
     *
     * @private
     * @type {String[]}
     */
    PROTOCOL_PROFILE_BEHAVIORS = ['disableBodyPruning'],

    /**
     * Extracts `auth` from an entity. Checks if `auth` is present and it is not falsy type.
     *
     * @private
     *
     * @param {Object} [entity]
     */
    extractAuth = function (entity) {
        var auth;

        return (entity && (auth = entity.auth) && RequestAuth.isValidType(auth.type)) ? auth : undefined;
    };

/**
 * The following defines the object (or JSON) structure that one can pass to the Item while creating a new Item
 * instance. This is also the object structure returned when `.toJSON()` is called on an Item instance.
 * @typedef Item~definition
 *
 * @property {Request~definition=} [request] A request represents an HTTP request. If a string, the string is assumed to
 * be the request URL and the method is assumed to be 'GET'.
 * @property {Array<Response~definition>=} [responses] Sample responses for this request can be stored along with the
 * item definition.
 * @property {Array<Event~definition>=} [events] Postman allows you to configure scripts to run when specific events
 * occur. These scripts are stored here, and can be referenced in the collection by their id.
 *
 * @example
 * {
 *     "name": "Get Headers from Echo",
 *     "id": "my-request-1",
 *     "description": "Makes a GET call to echo service and returns the client headers that were sent",
 *
 *     "request": {
 *         "url": "https://postman-echo.com/headers",
 *         "method": "GET"
 *     }
 * }
 *
 * @todo add response and event to example
 */
_.inherit((

    /**
     * A Postman Collection Item that holds your request definition, responses and other stuff. An Item essentially is
     * a HTTP request definition along with the sample responses and test scripts clubbed together. One or more of these
     * items can be grouped together and placed in an {@link ItemGroup} and as such forms a {@link Collection} of
     * requests.
     *
     * @constructor
     * @extends {Property}
     *
     * @param {Item~definition=} [definition] While creating a new instance of Item, one can provide the initial
     * configuration of the item with the the request it sends, the expected sample responses, tests, etc
     *
     * @example
Add a new Item to a folder in a collection instance

     * var Collection = require('postman-collection').Collection,
     *     Item = require('postman-collection').Item,
     *     myCollection;
     *
     * myCollection = new Collection({
     *     "item": [{
     *         "id": "my-folder-1",
     *         "name": "The solo folder in this collection",
     *         "item": [] // blank array indicates this is a folder
     *     }]
     * }); // create a collection with an empty folder
     * // add a request to "my-folder-1" that sends a GET request
     * myCollection.items.one("my-folder-1").items.add(new Item({
     *     "name": "Send a GET request",
     *     "id": "my-get-request",
     *     "request": {
     *         "url": "https://postman-echo.com/get",
     *         "method": "GET"
     *     }
     * }));
     */
    Item = function PostmanItem (definition) {
        // this constructor is intended to inherit and as such the super constructor is required to be executed
        Item.super_.apply(this, arguments);

        _.mergeDefined(this, /** @lends Item.prototype */ {
            /**
             * The instance of the {@link Request} object inside an Item defines the HTTP request that is supposed to be
             * sent. It further contains the request method, url, request body, etc.
             * @type {Request}
             */
            request: definition && (new Request(definition.request)),

            /**
             * An Item also contains a list of sample responses that is expected when the request defined in the item is
             * executed. The sample responses are useful in elaborating API usage and is also useful for other
             * integrations that use the sample responses to do something - say a mock service.
             * @type {PropertyList<Response>}
             */
            responses: new PropertyList(Response, this, definition && definition.response),

            /**
             * Events are a set of of {@link Script}s that are executed when certain activities are triggered on an
             * Item. For example, on defining an event that listens to the "test" event, would cause the associated
             * script of the event to be executed when the test runs.
             * @type {EventList}
             *
             * @example
Add a script to be executed on "prerequest" event

             * var Collection = require('postman-collection').Collection,
             *     Item = require('postman-collection').Item,
             *     myCollection;
             *
             * myCollection = new Collection({
             *     "item": [{
             *         "name": "Send a GET request",
             *         "id": "my-get-request",
             *         "request": {
             *             "url": "https://postman-echo.com/get",
             *             "method": "GET"
             *         }
             *     }]
             * }); // create a collection with one request
             *
             * // add a pre-request script to the event list
             * myCollection.items.one('my-get-request').events.add({
             *     "listen": "prerequest",
             *     "script": {
             *         "type": "text/javascript",
             *         "exec": "console.log(new Date())"
             *     }
             * });
             */
            events: new EventList(this, definition && definition.event),

            /**
             * Set of configurations used to alter the usual behavior of sending the request.
             *
             * @type {Object}
             * @property {Boolean} disableBodyPruning Disable body pruning for request methods like GET, HEAD etc.
             *
             * @todo Inherit this from ItemGroup & Collection
             */
            protocolProfileBehavior: definition && definition.protocolProfileBehavior &&
                _.pick(definition.protocolProfileBehavior, PROTOCOL_PROFILE_BEHAVIORS)
        });
    }), Property);

_.assign(Item.prototype, /** @lends Item.prototype */ {
    /**
     * Defines whether this property instances requires an id
     * @private
     * @readOnly
     * @type {Boolean}
     */
    _postman_propertyRequiresId: true,

    /**
     * Fetches applicable AuthType from the current item.
     *
     * @returns {RequestAuth}
     *
     * @note Since v3.0 release, this returns the entire auth RequestAuth, instead of just the parameters
     */
    getAuth: function () {
        var requestAuth;

        // find auth on request, if not found or empty auth, lookup in the parents
        return (requestAuth = extractAuth(this.request)) ? requestAuth : this.findInParents('auth', extractAuth);
    },

    /**
     * Returns {@link Event}s corresponding to a particular event name. If no name is given, returns all events. This
     * is useful when you want to trigger all associated scripts for an event.
     *
     * @param {String} name - one of the available event types such as `test`, `prerequest`, `postrequest`, etc.
     * @returns {Array<Event>}
     *
     * @example
Get all events for an item and evaluate their scripts

     * var fs = require('fs'), // needed to read JSON file from disk
     *     Collection = require('postman-collection').Collection,
     *     myCollection;
     *
     * // Load a collection to memory from a JSON file on disk (say, sample-collection.json)
     * myCollection = new Collection(JSON.stringify(fs.readFileSync('sample-collection.json').toString()));
     *
     * // assuming the collection has a request called "my-request-1" in root, we get it's test events
     * myCollection.items.one("my-request-1").getEvents("test").forEach(function (event) {
     *     event.script && eval(event.script.toSource());
     * });
     *
     * @todo decide appropriate verb names based on the fact that it gets events for a specific listener name
     * @draft
     */
    getEvents: function (name) {
        if (!name) {
            return this.events.all(); // return all events if name is not provided.
        }
        return this.events.filter(function (ev) {
            return ev.listen === name;
        });
    },

    /**
     * Sets authentication method for the request within this item
     *
     * @param {?String|RequestAuth~definition} type
     * @param {VariableList~definition=} [options]
     *
     * @note This function was previously (in v2 of SDK) used to clone request and populate headers. Now it is used to
     * only set auth information to request
     */
    authorizeRequestUsing: function (type, options) {
        if (!this.request) { this.request = new Request(); } // worst case
        return this.request.authorizeUsing(type, options);
    }
});

_.assign(Item, /** @lends Item */ {
    /**
     * Defines the name of this property for internal use.
     * @private
     * @readOnly
     * @type {String}
     */
    _postman_propertyName: 'Item',

    /**
     * Check whether an object is an instance of PostmanItem.
     *
     * @param {*} obj
     * @returns {Boolean}
     */
    isItem: function (obj) {
        return Boolean(obj) && ((obj instanceof Item) ||
            _.inSuperChain(obj.constructor, '_postman_propertyName', Item._postman_propertyName));
    }
});

module.exports = {
    Item: Item
};
<|endoftext|>


<commit_before>import {toArray,exists} from '../../utils/utils'
import {hasEntity, getEntity} from '../../utils/entityUtils'

function extractEntities(data){
  return data.filter(hasEntity).map(getEntity).map(e=>e.iuid)
}

export function reverseSelections(intents, idsMapper$){
  Array.prototype.flatMap = function(lambda) {
    return Array.prototype.concat.apply([], this.map(lambda))
  }

  //what we want is actually typeUid!
  //so typeUidFromInstUid()

  //select bom entries from entities
  let selectBomEntries$ = intents
    .selectEntities$
    .withLatestFrom(idsMapper$,function(entityIds,idsMapper){
      return entityIds.map(id=>idsMapper.typeUidFromInstUid[id])
    })
    /*.withLatestFrom(entities$,function(entityIds,entities){
      return entityIds.map(id=>entities.byId[id].typeUid)
    })*/

  //select entities from bom entries
  //in this case instUidFromTypeUid

  let selectEntities$ = intents
    .selectBomEntries$
    .withLatestFrom(idsMapper$,function(bomIds,idsMapper){
      return bomIds.map(id=>idsMapper.instUidFromTypeUid[id])
    })

    /*.withLatestFrom(entities$,function(bomIds,entities){
      return bomIds.flatMap(function(typeUid){
        return entities.instances.filter( i => i.typeUid === typeUid ).map( i => i.iuid )
      })
    })*/
  //selectEntities$.subscribe(e=>console.log("for these bomEntries, instIds are",e))
  //selectBomEntries$.subscribe(e=>console.log("for these entities, typeUids are",e))

  selectEntities$   = selectEntities$.merge(intents.selectEntities$)
  selectBomEntries$ = selectBomEntries$.merge(intents.selectBomEntries$)

  return{
    selectEntities$
    ,selectBomEntries$
  }
}

export function selectionsIntents(drivers, idsMapper$){
  //console.log("selectionsIntents")
  let selectEntities$ = drivers.events.select("gl")//.events("selectedMeshes$")
    .flatMap(e=>e.selectedMeshes$)
    .filter(exists)
    .map(extractEntities)

  let selectBomEntries$ = drivers.events.select("bom")//.events("entryTaps$")
    .flatMap(e=>e.entryTaps$)
    .filter(exists)
    .map(toArray)

  return reverseSelections({
     selectEntities$
    ,selectBomEntries$
  },idsMapper$)

}<commit_msg>refactor(selections) updated selection intents<commit_after>import {toArray,exists} from '../../utils/utils'
import {hasEntity, getEntity} from '../../utils/entityUtils'

function extractEntities(data){
  return data.filter(hasEntity).map(getEntity).map(e=>e.iuid)
}

export function reverseSelections(intents, idsMapper$){
  Array.prototype.flatMap = function(lambda) {
    return Array.prototype.concat.apply([], this.map(lambda))
  }

  //what we want is actually typeUid!
  //so typeUidFromInstUid()

  //select bom entries from entities
  let selectBomEntries$ = intents
    .selectEntities$
    .withLatestFrom(idsMapper$,function(entityIds,idsMapper){
      return entityIds.map(id=>idsMapper.typeUidFromInstUid[id]).filter(exists)
    })
    //.do(e=>console.log("selectedBomEntries",e))

  //select entities from bom entries
  //in this case instUidFromTypeUid

  let selectEntities$ = intents
    .selectBomEntries$
    .withLatestFrom(idsMapper$,function(bomIds,idsMapper){
      return bomIds.map(id=>idsMapper.instUidFromTypeUid[id]).filter(exists)
    })
    //.do(e=>console.log("selectedEntities",e))

    /*.withLatestFrom(entities$,function(bomIds,entities){
      return bomIds.flatMap(function(typeUid){
        return entities.instances.filter( i => i.typeUid === typeUid ).map( i => i.iuid )
      })
    })*/
  //selectEntities$.subscribe(e=>console.log("for these bomEntries, instIds are",e))
  //selectBomEntries$.subscribe(e=>console.log("for these entities, typeUids are",e))

  selectEntities$   = selectEntities$.merge(intents.selectEntities$)
  selectBomEntries$ = selectBomEntries$.merge(intents.selectBomEntries$)

  return{
    selectEntities$
    ,selectBomEntries$
  }
}

export function selectionsIntents(drivers, idsMapper$){
  //console.log("selectionsIntents")
  let selectEntities$ = drivers.events.select("gl")//.events("selectedMeshes$")
    .flatMap(e=>e.selectedMeshes$)
    .filter(exists)
    .map(extractEntities)
    .distinctUntilChanged()
    .shareReplay(1)

  let selectBomEntries$ = drivers.events.select("bom")//.events("entryTaps$")
    .flatMap(e=>e.entryTapped$)
    .filter(exists)
    .map(toArray)
    .distinctUntilChanged()
    .shareReplay(1)

  return reverseSelections({
     selectEntities$
    ,selectBomEntries$
  },idsMapper$)

}<|endoftext|>


<commit_before>// matter.js
//

'use strict';

var createError  = require('../createError');
var colliderfile = require('../colliderfile');
var logErrorExit = require('../logErrorExit');
var pkg = require('../../package.json');

var fs   = require('fs');
var path = require('path');
var spawn = require('child_process').spawn;
var url  = require('url');

var _ = require('lodash');
var docopt = require('docopt').docopt;
var rimraf = require('rimraf');
var which = require('which');

var doc = `
usage:
  collider matter
  collider matter clone <url> [<locale>]
  collider matter (rm | remove) <locale>

options:
  -h, --help  Show help information.
  --version   Show program version.

commands:
  clone       Clone a Matter library into the current project.
  remove, rm  Remove a Matter library from the current project.

  With no command, 'matter' shows a list of Matter libraries in the current project.
`;

module.exports = function (argv) {

  var args = docopt(doc, {
    argv: argv,
    version: `Collider CLI ${pkg.version}`,
  });

  dispatchOn(['matter'], args, matterList);
  dispatchOn(['matter', 'clone'], args, matterClone);
  dispatchOn(['matter', 'remove'], args, matterRemove);
  dispatchOn(['matter', 'rm'], args, matterRemove);
};

// FUNCTIONS
//

/**
 * Dispatch a callback when the given commands match those given to docopts.
 * @param  {Array}    commands An array of commands to match.
 * @param  {Object}   args     A docopts arguments object.
 * @param  {Function} callback The command handler to call.
 */
function dispatchOn(commands, args, callback) {
  var haystack = [];

  // For each truthy and Boolean-type arg, push its name into 'haystack'.
  _.forEach(args, function (val, key) {
    if (val === true) haystack.push(key);
  });

  // If 'commands' and 'haystack' match, then fire our callback.
  if (_.isEqual(commands.sort(), haystack.sort())) {
    callback(args);
  }
}

function matterList() {
  colliderfile.get('.', printMatterInfo);

  function printMatterInfo(data) {
    var matterLibs = data.matterLibs;
    var librarySingOrPlur = matterLibs.length > 1 ? 'libraries' : 'library';

    if (matterLibs.length > 0) {
      console.log();
      console.log(`'${data.name}' has ${matterLibs.length} Matter ${librarySingOrPlur}:`);

      matterLibs.forEach(function (library, i) {
        console.log();
        console.log(`${i + 1}. ${library.locale}`);
        console.log(`   ${library.url}`);
      });

      console.log();
    } else {
      console.log();
      console.log(`'${data.name}' has 0 Matter libraries. See 'collider help matter'.`);
      console.log();
    }
  }
}

function matterClone(args) {
  var args = {
    url: args['<url>'],
    locale: args['<locale>'],
  };

  // Re-assign the parsed URL to 'args.url'. The original can be found at 'args.url.href'.
  args.url = url.parse(args.url);

  // Verify the clone URL protocol is 'https:' or exit.
  var protocol = args.url.protocol;
  if (protocol !== 'https:') {
    var err = createError(
      `"${protocol}" is an unsupported protocol. URLs should start with "https:".`
    );
    logErrorExit(err, true);
  }

  // Set locale to the repo. name if it wasn't given.
  if (!args.locale) {
    args.locale = getRepoNameFromParsedUrl(args.url);
  }

  // Verify locale has the correct suffix.
  if (!args.locale.endsWith('-matter')) {
    var err = createError(`Unsupported locale. "${args.locale}" should have a "-matter" suffix.`);
    logErrorExit(err, true);
  }

  // Check `git` is installed before continuing.
  which('git', function (err) {
    if (err) throw err;
    spawn('git', ['clone', '--depth', 1, args.url.href, args.locale], { stdio: 'inherit' })
      .on('close', function (code, signal) {

        // If the clone was successful:
        if (code === 0) {
          colliderfile.get('.', function (data) {

            // Push a new Matter lib. object into the colliderfile data.
            data.matterLibs.push({
              url: args.url.href,
              locale: args.locale,
            });

            // Update the colliderfile with the new data.
            colliderfile.update(data, '.', function () {

              // Link the new Matter lib's Sass partial.
              updateMatterSass(data, '.', function () {
                console.log();
                console.log(`"${args.locale}" was cloned successfully! See 'collider matter'.`);
                console.log();
              });
            });
          });
        }
      });
  });

  /**
   * Retrieve a repo. name from a GitHub clone url.
   * @param  {Object} url A URL parsed using 'url.parse()'.
   * @return {String}     The repo's name.
   */
  function getRepoNameFromParsedUrl(url) {
    if (!url.pathname) {
      throw new Error('"pathname" does not exist.');
    }

    var repoName = path.basename(url.pathname, '.git');
    return repoName;
  }
}

function matterRemove(args) {
  var locale = args['<locale>'];

  // Check that 'locale' is a Matter library before attempting to delete it.
  fs.access(`./${locale}/matter/_matter.scss`, fs.F_OK, function (err) {
    if (err) throw err;

    // Get Collider-file data.
    colliderfile.get('.', function (data) {
      var projectName    = data.name;
      var createdTime    = data.createdTime;
      var author         = data.author;
      var currMatterLibs = data.matterLibs;

      // Filter Matter library to remove from Matter array.
      var newMatterLibs = currMatterLibs.filter(function (matter) {
        return matter.locale !== locale;
      });

      // 1. Remove _matter.scss @import entry.
      // 2. Then remove the Matter Collider-file entry.
      // 3. And then remove the Matter library directory.
      updateMatterSass(data, '.', function () {

        colliderfile.update({
          name: projectName,
          createdTime: createdTime,
          author: author,
          matterLibs: newMatterLibs,
        }, '.',
        function () {
          rimraf(`./${locale}`, function (err) {
            if (err) throw err;
            console.log();
            console.log(`"${locale}" was removed successfully. See 'collider matter'.`);
            console.log();
          });
        });
      });

    });

  });
}

/**
 * Write the necessary Sass @imports to collider/_matter.scss.
 * @param  {Object}   colliderfile A .collider file in object-form.
 * @param  {String}   projectPath  The project path.
 * @param  {Function} cb           A callback function to call on success.
 */
function updateMatterSass(colliderfile, projectPath, cb) {
  var matterLibs  = colliderfile.matterLibs;
  var sassImports = ["@import '../project/matter/matter';"];

  // Add any Matter libs. to the 'sassImports' array.
  matterLibs.forEach(function (lib) {
    sassImports.push(`@import '../${lib.locale}/matter/matter';`);
  });

  // Join array members by a newline and terminate the string with a final newline.
  var data = sassImports.join('\n');
  data += '\n';

  fs.writeFile(`${projectPath}/collider/_matter.scss`, data, function (err) {
    if (err) throw err;
    if (typeof cb === 'function') {
      cb();
    }
  });
}
<commit_msg>Require raw 'child_process' to make use of exec<commit_after>// matter.js
//

'use strict';

var createError  = require('../createError');
var colliderfile = require('../colliderfile');
var logErrorExit = require('../logErrorExit');
var pkg = require('../../package.json');

var fs   = require('fs');
var path = require('path');
var cp = require('child_process');
var url  = require('url');

var _ = require('lodash');
var docopt = require('docopt').docopt;
var rimraf = require('rimraf');
var which = require('which');

var doc = `
usage:
  collider matter
  collider matter clone <url> [<locale>]
  collider matter (rm | remove) <locale>

options:
  -h, --help  Show help information.
  --version   Show program version.

commands:
  clone       Clone a Matter library into the current project.
  remove, rm  Remove a Matter library from the current project.

  With no command, 'matter' shows a list of Matter libraries in the current project.
`;

module.exports = function (argv) {

  var args = docopt(doc, {
    argv: argv,
    version: `Collider CLI ${pkg.version}`,
  });

  dispatchOn(['matter'], args, matterList);
  dispatchOn(['matter', 'clone'], args, matterClone);
  dispatchOn(['matter', 'remove'], args, matterRemove);
  dispatchOn(['matter', 'rm'], args, matterRemove);
};

// FUNCTIONS
//

/**
 * Dispatch a callback when the given commands match those given to docopts.
 * @param  {Array}    commands An array of commands to match.
 * @param  {Object}   args     A docopts arguments object.
 * @param  {Function} callback The command handler to call.
 */
function dispatchOn(commands, args, callback) {
  var haystack = [];

  // For each truthy and Boolean-type arg, push its name into 'haystack'.
  _.forEach(args, function (val, key) {
    if (val === true) haystack.push(key);
  });

  // If 'commands' and 'haystack' match, then fire our callback.
  if (_.isEqual(commands.sort(), haystack.sort())) {
    callback(args);
  }
}

function matterList() {
  colliderfile.get('.', printMatterInfo);

  function printMatterInfo(data) {
    var matterLibs = data.matterLibs;
    var librarySingOrPlur = matterLibs.length > 1 ? 'libraries' : 'library';

    if (matterLibs.length > 0) {
      console.log();
      console.log(`'${data.name}' has ${matterLibs.length} Matter ${librarySingOrPlur}:`);

      matterLibs.forEach(function (library, i) {
        console.log();
        console.log(`${i + 1}. ${library.locale}`);
        console.log(`   ${library.url}`);
      });

      console.log();
    } else {
      console.log();
      console.log(`'${data.name}' has 0 Matter libraries. See 'collider help matter'.`);
      console.log();
    }
  }
}

function matterClone(args) {
  var args = {
    url: args['<url>'],
    locale: args['<locale>'],
  };

  // Re-assign the parsed URL to 'args.url'. The original can be found at 'args.url.href'.
  args.url = url.parse(args.url);

  // Verify the clone URL protocol is 'https:' or exit.
  var protocol = args.url.protocol;
  if (protocol !== 'https:') {
    var err = createError(
      `"${protocol}" is an unsupported protocol. URLs should start with "https:".`
    );
    logErrorExit(err, true);
  }

  // Set locale to the repo. name if it wasn't given.
  if (!args.locale) {
    args.locale = getRepoNameFromParsedUrl(args.url);
  }

  // Verify locale has the correct suffix.
  if (!args.locale.endsWith('-matter')) {
    var err = createError(`Unsupported locale. "${args.locale}" should have a "-matter" suffix.`);
    logErrorExit(err, true);
  }

  // Check `git` is installed before continuing.
  which('git', function (err) {
    if (err) throw err;
    spawn('git', ['clone', '--depth', 1, args.url.href, args.locale], { stdio: 'inherit' })
      .on('close', function (code, signal) {

        // If the clone was successful:
        if (code === 0) {
          colliderfile.get('.', function (data) {

            // Push a new Matter lib. object into the colliderfile data.
            data.matterLibs.push({
              url: args.url.href,
              locale: args.locale,
            });

            // Update the colliderfile with the new data.
            colliderfile.update(data, '.', function () {

              // Link the new Matter lib's Sass partial.
              updateMatterSass(data, '.', function () {
                console.log();
                console.log(`"${args.locale}" was cloned successfully! See 'collider matter'.`);
                console.log();
              });
            });
          });
        }
      });
  });

  /**
   * Retrieve a repo. name from a GitHub clone url.
   * @param  {Object} url A URL parsed using 'url.parse()'.
   * @return {String}     The repo's name.
   */
  function getRepoNameFromParsedUrl(url) {
    if (!url.pathname) {
      throw new Error('"pathname" does not exist.');
    }

    var repoName = path.basename(url.pathname, '.git');
    return repoName;
  }
}

function matterRemove(args) {
  var locale = args['<locale>'];

  // Check that 'locale' is a Matter library before attempting to delete it.
  fs.access(`./${locale}/matter/_matter.scss`, fs.F_OK, function (err) {
    if (err) throw err;

    // Get Collider-file data.
    colliderfile.get('.', function (data) {
      var projectName    = data.name;
      var createdTime    = data.createdTime;
      var author         = data.author;
      var currMatterLibs = data.matterLibs;

      // Filter Matter library to remove from Matter array.
      var newMatterLibs = currMatterLibs.filter(function (matter) {
        return matter.locale !== locale;
      });

      // 1. Remove _matter.scss @import entry.
      // 2. Then remove the Matter Collider-file entry.
      // 3. And then remove the Matter library directory.
      updateMatterSass(data, '.', function () {

        colliderfile.update({
          name: projectName,
          createdTime: createdTime,
          author: author,
          matterLibs: newMatterLibs,
        }, '.',
        function () {
          rimraf(`./${locale}`, function (err) {
            if (err) throw err;
            console.log();
            console.log(`"${locale}" was removed successfully. See 'collider matter'.`);
            console.log();
          });
        });
      });

    });

  });
}

/**
 * Write the necessary Sass @imports to collider/_matter.scss.
 * @param  {Object}   colliderfile A .collider file in object-form.
 * @param  {String}   projectPath  The project path.
 * @param  {Function} cb           A callback function to call on success.
 */
function updateMatterSass(colliderfile, projectPath, cb) {
  var matterLibs  = colliderfile.matterLibs;
  var sassImports = ["@import '../project/matter/matter';"];

  // Add any Matter libs. to the 'sassImports' array.
  matterLibs.forEach(function (lib) {
    sassImports.push(`@import '../${lib.locale}/matter/matter';`);
  });

  // Join array members by a newline and terminate the string with a final newline.
  var data = sassImports.join('\n');
  data += '\n';

  fs.writeFile(`${projectPath}/collider/_matter.scss`, data, function (err) {
    if (err) throw err;
    if (typeof cb === 'function') {
      cb();
    }
  });
}
<|endoftext|>


<commit_before>var async            = require('async'),
    args             = require('../util/arguments'),
    create           = require('../actions/create'),
    edit             = require('../actions/edit'),
    end              = require('../actions/end'),
    findById         = require('../actions/findById'),
    findCurrent      = require('../actions/findCurrent'),
    findLast         = require('../actions/findLast'),
    doneOutput       = require('./common/common-output'),
    preHandleOptions = require('./common/prehandleOptions');

module.exports = function rerun(options) {
    var context = preHandleOptions(options);

    var findMethod = findLast;
    if(options.id){
        findMethod = findById;
    }

    async.waterfall([
        args.bind(this, context, false),
        findMethod,
        // update changes from found task
        function (args, done) {
            args.changes.task = args.task.task;
            args.changes.project = args.task.project;
            args.changes.note = args.task.note;
            args.changes.start = options.start;
            done(null, args)
        },
        findCurrent,
        end,
        create,
        edit,
        findCurrent
    ], doneOutput)
};<commit_msg>fixed rerun command<commit_after>var async            = require('async'),
    args             = require('../util/arguments'),
    create           = require('../actions/create'),
    edit             = require('../actions/edit'),
    end              = require('../actions/end'),
    find             = require('../actions/find'),
    findById         = require('../actions/findById'),
    findLast         = require('../actions/findLast'),
    doneOutput       = require('./common/common-output'),
    preHandleOptions = require('./common/prehandleOptions');

module.exports = function rerun(options) {
    var context = preHandleOptions(options);

    var findMethod = findLast;
    if (options.id) {
        findMethod = findById;
    }

    async.waterfall([
        args.bind(this, context, false),
        findMethod,
        // update changes from found task
        function (args, done) {
            args.changes.task = args.task.task;
            args.changes.project = args.task.project;
            args.changes.note = args.task.note;
            args.changes.start = options.start;
            done(null, args)
        },
        end,
        create,
        edit,
        find
    ], doneOutput)
};<|endoftext|>


<commit_before>var mout = require('mout');
var Q = require('q');
var Logger = require('bower-logger');
var RegistryClient = require('bower-registry-client');
var cli = require('../util/cli');
var Tracker = require('../util/analytics').Tracker;
var defaultConfig = require('../config');

function search(name, config) {
    var registryClient;
    var promise;
    var tracker;
    var logger = new Logger();

    config = mout.object.deepFillIn(config || {}, defaultConfig);
    config.cache = config.storage.registry;

    registryClient = new RegistryClient(config, logger);
    tracker = new Tracker(config);

    // If no name was specified, list all packages
    if (!name) {
        promise = Q.nfcall(registryClient.list.bind(registryClient));
    // Otherwise search it
    } else {
        promise = Q.nfcall(registryClient.search.bind(registryClient), name);
    }

    promise
    .done(function (results) {
        tracker.track('searched', name);
        logger.emit('end', results);
    }, function (error) {
        logger.emit('error', error);
    });

    return logger;
}

// -------------------

search.line = function (argv) {
    var options = search.options(argv);
    return search(options.argv.remain.slice(1).join(' '), options);
};

search.options = function (argv) {
    return cli.readOptions(argv);
};

search.completion = function () {
    // TODO:
};

module.exports = search;
<commit_msg>Tweak insight tracking for `search` command<commit_after>var mout = require('mout');
var Q = require('q');
var Logger = require('bower-logger');
var RegistryClient = require('bower-registry-client');
var cli = require('../util/cli');
var Tracker = require('../util/analytics').Tracker;
var defaultConfig = require('../config');

function search(name, config) {
    var registryClient;
    var promise;
    var tracker;
    var logger = new Logger();

    config = mout.object.deepFillIn(config || {}, defaultConfig);
    config.cache = config.storage.registry;

    registryClient = new RegistryClient(config, logger);
    tracker = new Tracker(config);
    tracker.track('search', name);

    // If no name was specified, list all packages
    if (!name) {
        promise = Q.nfcall(registryClient.list.bind(registryClient));
    // Otherwise search it
    } else {
        promise = Q.nfcall(registryClient.search.bind(registryClient), name);
    }

    promise
    .done(function (results) {
        logger.emit('end', results);
    }, function (error) {
        logger.emit('error', error);
    });

    return logger;
}

// -------------------

search.line = function (argv) {
    var options = search.options(argv);
    return search(options.argv.remain.slice(1).join(' '), options);
};

search.options = function (argv) {
    return cli.readOptions(argv);
};

search.completion = function () {
    // TODO:
};

module.exports = search;
<|endoftext|>


<commit_before>var BaseCommand = require('./base');

module.exports = BaseCommand.extend({
    name: 'update',
    description: 'update a Ghost instance',

    arguments: [
        {name: 'version', optional: true}
    ],
    options: [{
        name: 'rollback',
        alias: 'R',
        description: 'Rollback to the previously installed Ghost version',
        flag: true
    }],

    execute: function (version, options) {
        this.checkValidInstall();

        var Promise         = require('bluebird'),
            path            = require('path'),
            Config          = require('../utils/config'),
            resolveVersion  = require('../utils/resolve-version'),
            config          = Config.load('.ghost-cli'),
            self            = this,
            installPath, environment;

        if (options.rollback) {
            if (!config.get('previous-version')) {
                return Promise.reject('No previous version found');
            }

            version = config.get('previous-version');
            installPath = path.join(process.cwd(), 'versions', version);
        }

        environment = config.get('running', null);

        return this.runCommand('doctor', 'update').then(function fetchVersion() {
            if (options.rollback) {
                return Promise.resolve();
            }

            return resolveVersion(version, config.get('active-version'))
                .then(function installGhost(resolvedVersion) {
                    version = resolvedVersion;
                    installPath = path.join(process.cwd(), 'versions', version);

                    return self.runTask('npm-download', {
                        module: 'ghost',
                        version: version,
                        destination: installPath
                    }, 'Downloading the updated version of Ghost');
                });
        }).then(function stopCurrentGhost() {
            if (!environment) {
                // If environment isn't set ghost is not running.
                // Therefore we don't need to stop Ghost, so skip that part
                return Promise.resolve();
            }

            return self.runCommand('stop');
        }).then(function afterStop() {
            var fs = require('fs-extra'),
                symlinkSync = require('symlink-or-copy').sync;

            fs.removeSync(path.join(process.cwd(), 'current'));

            symlinkSync(installPath, path.join(process.cwd(), 'current'));
        }).then(function restartGhost() {
            config.set(
                'previous-version',
                (options.rollback) ? null : config.get('active-version')
            ).set('active-version', version).save();

            var startConfig = [];
            startConfig[environment] = true;

            return self.runCommand('start', startConfig);
        });
    }
});
<commit_msg>:bug: skip fetch of new version on `ghost update` if version already exists<commit_after>var BaseCommand = require('./base');

module.exports = BaseCommand.extend({
    name: 'update',
    description: 'update a Ghost instance',

    arguments: [
        {name: 'version', optional: true}
    ],
    options: [{
        name: 'rollback',
        alias: 'R',
        description: 'Rollback to the previously installed Ghost version',
        flag: true
    }],

    execute: function (version, options) {
        this.checkValidInstall();

        var Promise         = require('bluebird'),
            path            = require('path'),
            fs              = require('fs-extra'),
            Config          = require('../utils/config'),
            resolveVersion  = require('../utils/resolve-version'),
            config          = Config.load('.ghost-cli'),
            self            = this,
            installPath, environment;

        if (options.rollback) {
            if (!config.get('previous-version')) {
                return Promise.reject('No previous version found');
            }

            version = config.get('previous-version');
            installPath = path.join(process.cwd(), 'versions', version);
        }

        environment = config.get('running', null);

        return this.runCommand('doctor', 'update').then(function fetchVersion() {
            if (options.rollback) {
                return Promise.resolve();
            }

            return resolveVersion(version, config.get('active-version'))
                .then(function installGhost(resolvedVersion) {
                    version = resolvedVersion;
                    installPath = path.join(process.cwd(), 'versions', version);

                    if (fs.existsSync(installPath)) {
                        // Version is already installed, skip the install
                        // TODO: when the --force flag is implemented, delete the
                        // existing dir if the option is supplied
                        return Promise.resolve();
                    }

                    return self.runTask('npm-download', {
                        module: 'ghost',
                        version: version,
                        destination: installPath
                    }, 'Downloading the updated version of Ghost');
                });
        }).then(function stopCurrentGhost() {
            if (!environment) {
                // If environment isn't set ghost is not running.
                // Therefore we don't need to stop Ghost, so skip that part
                return Promise.resolve();
            }

            return self.runCommand('stop');
        }).then(function afterStop() {
            var symlinkSync = require('symlink-or-copy').sync;

            fs.removeSync(path.join(process.cwd(), 'current'));

            symlinkSync(installPath, path.join(process.cwd(), 'current'));
        }).then(function restartGhost() {
            config.set(
                'previous-version',
                (options.rollback) ? null : config.get('active-version')
            ).set('active-version', version).save();

            var startConfig = [];
            startConfig[environment] = true;

            return self.runCommand('start', startConfig);
        });
    }
});
<|endoftext|>


<commit_before>var cypher = require('./cypher-utils');
var Concept = require('./concept');
var neo = require('neo4j');
var Class = require('js.class');

var ConceptManager = Class({

	/*
	构造函数
	*/
	create: function(url){
		this.url = url;
		if(url)
			this.db = new neo.GraphDatabase({url:url});
	},

	/*
	创建Concept节点
	参数
		- cb 回调函数function(err, Concept)
	*/
	addNew: function (cb) {
		var self = this;
		console.log('addNew start.');
		// 组合查询语句
		var query = [];
		query.push(cypher.create('p', Concept.LABEL));		// 创建节点
		query.push(cypher.ret('p'));					// 返回刚刚创建的节点

		// 执行查询
		self.db.cypher({
			query: query.join('\n')
		}, function (err, result) {
			if (err) cb(err);
			else cb(null, new Concept(self.url, result[0].p._id, result[0].p.labels, result[0].p.properties));
			console.log('query end');
		});
		console.log('addNew end');
	},
	/*
	删除Concept节点
	参数
		- id 指定删除的节点的id
		- cb 回调函数function(err, result)
	*/
	del: function (id, cb) {

		var query = [];
		query.push(cypher.match('p', Concept.LABEL));		// 匹配Concept标签
		query.push(cypher.idFilter('p', id));			// 根据id进行筛选
		query.push(cypher.matchConnect('p','','r'));	// 找出当前节点相关的所有连接
		query.push(cypher.del('r'));					// 删除这些连接
		query.push(cypher.del('p'));					// 删除节点

		this.db.cypher({
			query: query.join('\n')
		}, cb);
	},

	/*
	获取节点
	参数：
		- id 节点id
		- cb 回调函数function(err, Concept)
	*/
	get: function (id, cb) {
		var self = this;
		var query = [];
		query.push(cypher.match('p', Concept.LABEL));
		query.push(cypher.idFilter('p', id));
		query.push(cypher.ret('p'));
		self.db.cypher({
			query: query.join('\n')
		}, function (err, result) {
			if(err ||  result.length === 0) cb(err || 'could not find concept');
			else {
				var concept = new Concept(self.url, result[0].p._id,  result[0].p.labels, result[0].p.properties);
				cb(err, concept);
			}
		});
	},

	/*
	根据节点name获取节点
	参数
		- name 必须的
		- maxLength 可选的
		- cb 必须的，回调函数
	*/
	findByName: function () {
		var name = arguments[0];
		var maxLength = 100;
		if(arguments.length > 2) maxLength = arguments[1];
		var cb = arguments[arguments.length - 1];
		var self = this;
		var query = [];
		query.push('Match (p:Concept)-[:hasName]->(n:Name{text:{name}})');
		query.push(cypher.ret(cypher.distinct('p')));
		this.db.cypher({
			query: query.join('\n'),
			params: {name: name}
		}, function (err, result) {
			if(err) cb(err);
			else {
				var persons = [], count = 0;
				result.forEach(function (res) {
					if(count++ >= maxLength) return;
					var person = new Concept(self.url, res.p._id, res.p.labels, res.p.properties);
					persons.push(person);
				});
				cb(null, persons);
			}
		});
	}
});
module.exports = ConceptManager;<commit_msg>recover<commit_after>var cypher = require('./cypher-utils');
var Concept = require('./concept');
var neo = require('neo4j');
var Class = require('js.class');

var ConceptManager = Class({

	/*
	构造函数
	*/
	create: function(url){
		this.url = url;
		if(url)
			this.db = new neo.GraphDatabase({url:url});
	},

	/*
	创建Concept节点
	参数
		- cb 回调函数function(err, Concept)
	*/
	addNew: function (cb) {
		var self = this;
		// 组合查询语句
		var query = [];
		query.push(cypher.create('p', Concept.LABEL));		// 创建节点
		query.push(cypher.ret('p'));					// 返回刚刚创建的节点

		// 执行查询
		self.db.cypher({
			query: query.join('\n')
		}, function (err, result) {
			if (err) cb(err);
			else cb(null, new Concept(self.url, result[0].p._id, result[0].p.labels, result[0].p.properties));
		});
	},
	/*
	删除Concept节点
	参数
		- id 指定删除的节点的id
		- cb 回调函数function(err, result)
	*/
	del: function (id, cb) {

		var query = [];
		query.push(cypher.match('p', Concept.LABEL));		// 匹配Concept标签
		query.push(cypher.idFilter('p', id));			// 根据id进行筛选
		query.push(cypher.matchConnect('p','','r'));	// 找出当前节点相关的所有连接
		query.push(cypher.del('r'));					// 删除这些连接
		query.push(cypher.del('p'));					// 删除节点

		this.db.cypher({
			query: query.join('\n')
		}, cb);
	},

	/*
	获取节点
	参数：
		- id 节点id
		- cb 回调函数function(err, Concept)
	*/
	get: function (id, cb) {
		var self = this;
		var query = [];
		query.push(cypher.match('p', Concept.LABEL));
		query.push(cypher.idFilter('p', id));
		query.push(cypher.ret('p'));
		self.db.cypher({
			query: query.join('\n')
		}, function (err, result) {
			if(err ||  result.length === 0) cb(err || 'could not find concept');
			else {
				var concept = new Concept(self.url, result[0].p._id,  result[0].p.labels, result[0].p.properties);
				cb(err, concept);
			}
		});
	},

	/*
	根据节点name获取节点
	参数
		- name 必须的
		- maxLength 可选的
		- cb 必须的，回调函数
	*/
	findByName: function () {
		var name = arguments[0];
		var maxLength = 100;
		if(arguments.length > 2) maxLength = arguments[1];
		var cb = arguments[arguments.length - 1];
		var self = this;
		var query = [];
		query.push('Match (p:Concept)-[:hasName]->(n:Name{text:{name}})');
		query.push(cypher.ret(cypher.distinct('p')));
		this.db.cypher({
			query: query.join('\n'),
			params: {name: name}
		}, function (err, result) {
			if(err) cb(err);
			else {
				var persons = [], count = 0;
				result.forEach(function (res) {
					if(count++ >= maxLength) return;
					var person = new Concept(self.url, res.p._id, res.p.labels, res.p.properties);
					persons.push(person);
				});
				cb(null, persons);
			}
		});
	}
});
module.exports = ConceptManager;<|endoftext|>


<commit_before>'use strict';

var Post = require('../model/post')
  , response = require('../server/response')
  , logger = require('../server/logger')
  , status = require('../server/status')
  ,	UserCtrl = require('./user.js')
  , Comment = require('../model/comment')
  ;

var PostController = function () { };

var regExCheckEmptyText = /(^\s*)(\s*$)/;

PostController.prototype.loadPost = function (req, res, next) {
  Post.findOne({ _id: req.params.pid }).exec().then((post) => {
    req.info = req.info || {};
    req.info.post = post;
    next();
  }, (err) => {
    logger.error(err);
    response.respondError(req, res, status.codes.PostNotFound.code);
  });
};

PostController.prototype.getPosts = function (req, res) {
 	// get/check university .. 아직 로그인 세션 디테일 어딨는지 몰름
	let userUni = req.session.university;

	// 일단 written으로 sort했는대 edited이 우선이 되야지만 if edited을 어덯게 추가할지 몰라서 이렇게
	Post.find({ university: userUni }, { sort: { written: -1} }, function (err, posts) {
	    if (err) {
	    	response.respondError(req, res, status.codes.GetPostsFailed.code);
	    }
    	// fetch posts in array
	    response.respondSuccess(req, res, posts.map(function(p){
		   	return {
		   		title: p.title,
		   		text: p.text,
		   		written: p.written,
		   		edited: p.edited,
		   		votes: p.votes
	    	};
	    }));
	});
};

PostController.prototype.getPost = function (req, res) {
	Post.findOne({_id:req.params.pid}, function (err, post) {
		// if server can't find post
		if (err) {
			response.respondError(req, res, status.codes.CouldNotFindPost.code);
	  	}
	  	if (post) {
	  		// fetch post
	  		let gotPost = {
		    	title: post.title,
		    	text: post.text,
		    	written: post.written,
		    	edited: post.edited,
		    	votes: post.votes,
		    	comments: post.comments
		    };
		    response.respondSuccess(req, res, gotPost);
	   	}
  	});
};

PostController.prototype.deletePost = function (req, res, next) {
	Post.findOne({ _id:req.params.pid}, function (err, post) {
		if (err) {
			response.respondError(req, res, status.codes.CouldNotFindPost.code);
		}
		if (post) {
			// check if owner or admin
			UserCtrl.permitOwnerOrAdmin(req, res, next);

			// delete post
			Post.remove(function (err, post) {
				if (err) {
					response.respondError(req, res, status.codes.PostRemoveFailed.code);
				}
				response.respondSuccess(req, res, post);
			});
		}
	});
};

PostController.prototype.reportPost = function (req, res) {
	Post.findOne({ id: req.params.cid }).exec().then((post) => {
	    if (post === null) {
	      response.respondError(req, res, status.codes.PostNotFound.code);
	    } else if (undefined !== post.reported.find((duplicate) => { return duplicate.toString() === req.info.user._id.toString(); })) {
	      response.respondError(req, res, status.codes.AlreadyReported.code);
	    } else {
	      post.reported.push(req.info.user._id).save(function (err, newReport) {
	        if (err) {
	        	response.respondError(req, res, status.codes.AddReportFailed.code);
	        }
	        response.respondSuccess(req, res, newReport);
	      });
	    }
	});
};

PostController.prototype.getCommentsOnPost = function (req, res) {
  var commentsInfo = []
    , receivedCommentsIdArr = req.info.post.comments
    ;

  var makeCommentInfoObj = function(nickname, writtenDate, likeVoteCount) {
    return {
      'nickname': nickname
    , 'writtenDate': writtenDate
    , 'likeVoteCount': likeVoteCount
    };
  };

  Comment
    .find({ _id: { $in: receivedCommentsIdArr } })
    .populate({ path: 'author' })
    .exec()
      .then(function (err, comments) {
        if (err) {
          response.respondError(req, res, status.codes.CommentsOnPostGottenFailed.code);
        } else {
          commentsInfo = comments.map(function (comment) {
            return makeCommentInfoObj(comment.author.nickname, comment.written, comment.voteScore);
          });
        }
      })
    .then(function () {
      commentsInfo.sort(function (date1, date2) { return date1 - date2; }); // synchronous func
      response.respondSuccess(req, res, commentsInfo);
    });
};

PostController.prototype.addPost = function (req, res) {
  res = res;

  var newPost = new Post({
  //   title: req.body.title
  // , text: req.body.text
  // , author: req.body.author
  // , university: req.body.university
    title: req.info.post.title
  , text: req.info.post.text
  , author: req.info.post.author
  , university: req.info.post.university
  });

  // Test whether the title is continuum of space or newline
  if (regExCheckEmptyText.test(newPost.title)) {
    response.respondError(req, res, status.codes.TitleOfPostIsInvalid.code);
    return;
  }
  // Test whether the text is continuum group of space or newline
  if (regExCheckEmptyText.test(newPost.text)) {
    response.respondError(req, res, status.codes.TextOfPostIsInvalid.code);
    return;
  }

  newPost
    .save()
    .then(function (err, savedPost) {
      if (err) {
        response.respondError(req, res, status.codes.PostAddedFailed.code, null);
      } else {
        response.respondSuccess(req, res, savedPost._id.toString());
      }
    });
};

PostController.prototype.updateVote = function (req, res) {
  var newVote = req.info.vote;

  for(var i=0 ; i<req.info.post.vote.length ; i++) {
    if (req.info.post.vote[i] === req.info.reported) {
      response.respondError(req, res, status.codes.PostVotedAlready.code);
      return;
    }
  }

  Post
    .update({ _id: req.params.pid })
      // req.info.uid: vote한 사람 id
    , { $push: { uid: req.info.uid, voteType: newVote } }
    , function (err, results) {
        results = results;
        if (err) {
          response.respondError(req, res, status.codes.UpdateVoteFailed.code);
        }
      }
    .then(function () {
      if(newVote === 'up') {
        Post
          .update({ _id: req.params.pid })
          , { $inc: { voteScore: 1 } }
          , function (err, result) {
            result = result;
            if (err) {
              response.respondError(req, res, status.codes.UpdateVoteInDBFailed.code);
            } else {
              response.respondSuccess(req, res, null);
            }
          };

      } else if (newVote === 'down') {
        Post
          .update({ _id: req.params.pid })
        , { $inc: { voteScore: -1 } }
        , function (err, result) {
          result = result;
          if (err) {
            response.respondError(req, res, status.codes.UpdateVoteInDBFailed.code);
          } else {
            response.respondSuccess(req, res, null);
          }
        };
      }

    });
};

// // todo : make test code
// PostController.prototype.getVotesOnPost = function (req, res) {
//   Post
//     .find({ _id: req.params.pid })
//     .select('votes')
//     .sort({ written: 1 })
//     .exec(function (err, votes) {
//       if (err) {
//         response.respondError(req, res, status.codes.CommentsOnPostGottenFailed.code);
//       } else {
//         response.respondSuccess(req, res, votes);
//       }
//     });
// };

// // todo : make test code
// PostController.prototype.voteForPost = function (req, res) {
//   var newVotes = [];
//   res = res;

//   Post.find({ _id: req.body.pid })
//     .select('votes')
//     .exec(function (err, votes) {
//       newVotes = votes;
//     });

//   // then
//   newVotes.push(req.body.vote);

// //   Post
// //     .update({ _id: req.body.pid }
// //              , { votes: newVotes }
// //              , function(err, results) {
// //                  // do something
// //                });

// };

module.exports = new PostController();<commit_msg>report in cmt, vot in post, add cmt in cmt model<commit_after>'use strict';

var Post = require('../model/post')
  , response = require('../server/response')
  , logger = require('../server/logger')
  , status = require('../server/status')
  ,	UserCtrl = require('./user.js')
  , Comment = require('../model/comment')
  ;

var PostController = function () { };

var regExCheckEmptyText = /(^\s*)(\s*$)/;

PostController.prototype.loadPost = function (req, res, next) {
  Post.findOne({ _id: req.params.pid }).exec().then((post) => {
    req.info = req.info || {};
    req.info.post = post;
    next();
  }, (err) => {
    logger.error(err);
    response.respondError(req, res, status.codes.PostNotFound.code);
  });
};

PostController.prototype.getPosts = function (req, res) {
 	// get/check university .. 아직 로그인 세션 디테일 어딨는지 몰름
	let userUni = req.session.university;

	// 일단 written으로 sort했는대 edited이 우선이 되야지만 if edited을 어덯게 추가할지 몰라서 이렇게
	Post.find({ university: userUni }, { sort: { written: -1} }, function (err, posts) {
	    if (err) {
	    	response.respondError(req, res, status.codes.GetPostsFailed.code);
	    }
    	// fetch posts in array
	    response.respondSuccess(req, res, posts.map(function(p){
		   	return {
		   		title: p.title,
		   		text: p.text,
		   		written: p.written,
		   		edited: p.edited,
		   		votes: p.votes
	    	};
	    }));
	});
};

PostController.prototype.getPost = function (req, res) {
	Post.findOne({_id:req.params.pid}, function (err, post) {
		// if server can't find post
		if (err) {
			response.respondError(req, res, status.codes.CouldNotFindPost.code);
	  	}
	  	if (post) {
	  		// fetch post
	  		let gotPost = {
		    	title: post.title,
		    	text: post.text,
		    	written: post.written,
		    	edited: post.edited,
		    	votes: post.votes,
		    	comments: post.comments
		    };
		    response.respondSuccess(req, res, gotPost);
	   	}
  	});
};

PostController.prototype.deletePost = function (req, res, next) {
	Post.findOne({ _id:req.params.pid}, function (err, post) {
		if (err) {
			response.respondError(req, res, status.codes.CouldNotFindPost.code);
		}
		if (post) {
			// check if owner or admin
			UserCtrl.permitOwnerOrAdmin(req, res, next);

			// delete post
			Post.remove(function (err, post) {
				if (err) {
					response.respondError(req, res, status.codes.PostRemoveFailed.code);
				}
				response.respondSuccess(req, res, post);
			});
		}
	});
};

PostController.prototype.reportPost = function (req, res) {
	Post.findOne({ id: req.params.cid }).exec().then((post) => {
	    if (post === null) {
	      response.respondError(req, res, status.codes.PostNotFound.code);
	    } else if (undefined !== post.reported.find((duplicate) => { return duplicate.toString() === req.info.user._id.toString(); })) {
	      response.respondError(req, res, status.codes.AlreadyReported.code);
	    } else {
	      post.reported.push(req.info.user._id).save(function (err, newReport) {
	        if (err) {
	        	response.respondError(req, res, status.codes.AddReportFailed.code);
	        }
	        response.respondSuccess(req, res, newReport);
	      });
	    }
	});
};

PostController.prototype.getCommentsOnPost = function (req, res) {
  var commentsInfo = []
    , receivedCommentsIdArr = req.info.post.comments
    ;

  var makeCommentInfoObj = function(nickname, writtenDate, likeVoteCount) {
    return {
      'nickname': nickname
    , 'writtenDate': writtenDate
    , 'likeVoteCount': likeVoteCount
    };
  };

  Comment
    .find({ _id: { $in: receivedCommentsIdArr } })
    .populate({ path: 'author' })
    .exec()
      .then(function (err, comments) {
        if (err) {
          response.respondError(req, res, status.codes.CommentsOnPostGottenFailed.code);
        } else {
          commentsInfo = comments.map(function (comment) {
            return makeCommentInfoObj(comment.author.nickname, comment.written, comment.voteScore);
          });
        }
      })
    .then(function () {
      commentsInfo.sort(function (date1, date2) { return date1 - date2; }); // synchronous func
      response.respondSuccess(req, res, commentsInfo);
    });
};

PostController.prototype.addPost = function (req, res) {
  res = res;

  var newPost = new Post({
  //   title: req.body.title
  // , text: req.body.text
  // , author: req.body.author
  // , university: req.body.university
    title: req.info.post.title
  , text: req.info.post.text
  , author: req.info.post.author
  , university: req.info.post.university
  });

  // Test whether the title is continuum of space or newline
  if (regExCheckEmptyText.test(newPost.title)) {
    response.respondError(req, res, status.codes.TitleOfPostIsInvalid.code);
    return;
  }
  // Test whether the text is continuum group of space or newline
  if (regExCheckEmptyText.test(newPost.text)) {
    response.respondError(req, res, status.codes.TextOfPostIsInvalid.code);
    return;
  }

  newPost
    .save()
    .then(function (err, savedPost) {
      if (err) {
        response.respondError(req, res, status.codes.PostAddedFailed.code, null);
      } else {
        response.respondSuccess(req, res, savedPost._id.toString());
      }
    });
};

PostController.prototype.updateVote = function (req, res) {
  var newVote = req.info.vote;

  for(var i=0 ; i<req.info.post.vote.length ; i++) {
    if (req.info.post.vote[i] === req.info.reported) {
      response.respondError(req, res, status.codes.PostVotedAlready.code);
      return;
    }
  }

  Post
    .update({ _id: req.params.pid })
      // req.info.uid: vote한 사람 id
    , { $push: { votes: { uid: req.info.uid, voteType: newVote } } }
    , function (err, results) {
        results = results;
        if (err) {
          response.respondError(req, res, status.codes.UpdateVoteFailed.code);
        }
      }
    .then(function () {
      if(newVote === 'up') {
        Post
          .update({ _id: req.params.pid })
          , { $inc: { voteScore: 1 } }
          , function (err, result) {
            result = result;
            if (err) {
              response.respondError(req, res, status.codes.UpdateVoteInDBFailed.code);
            } else {
              response.respondSuccess(req, res, null);
            }
          };

      } else if (newVote === 'down') {
        Post
          .update({ _id: req.params.pid })
        , { $inc: { voteScore: -1 } }
        , function (err, result) {
          result = result;
          if (err) {
            response.respondError(req, res, status.codes.UpdateVoteInDBFailed.code);
          } else {
            response.respondSuccess(req, res, null);
          }
        };
      }
    });
};

// // todo : make test code
// PostController.prototype.getVotesOnPost = function (req, res) {
//   Post
//     .find({ _id: req.params.pid })
//     .select('votes')
//     .sort({ written: 1 })
//     .exec(function (err, votes) {
//       if (err) {
//         response.respondError(req, res, status.codes.CommentsOnPostGottenFailed.code);
//       } else {
//         response.respondSuccess(req, res, votes);
//       }
//     });
// };

// // todo : make test code
// PostController.prototype.voteForPost = function (req, res) {
//   var newVotes = [];
//   res = res;

//   Post.find({ _id: req.body.pid })
//     .select('votes')
//     .exec(function (err, votes) {
//       newVotes = votes;
//     });

//   // then
//   newVotes.push(req.body.vote);

// //   Post
// //     .update({ _id: req.body.pid }
// //              , { votes: newVotes }
// //              , function(err, results) {
// //                  // do something
// //                });

// };

module.exports = new PostController();<|endoftext|>


<commit_before>var elasticsearch = require('elasticsearch');

exports.sitemap = function sitemap(req, res) {
    var es_client = req.app.get('es_client');
    var host_base = req.headers.host;
    var catalog = req.params.catalog;
    var offset = req.param('offset');

    var query = {
        index:'assets',
        size:1000,
        from:0,
        body:{}
    };

    if(offset && offset != undefined) {
        query.from = parseInt(offset);
    }

    if(catalog && catalog != undefined) {
      query.body.filter = {
          and: []
      };

      query.body.filter.and.push({
        query: {
            match: {
                catalog: catalog
            }
        }
      });
    }

    es_client.search(query).then(function(search_result) {
        var sitemap = '<?xml version="1.0" encoding="UTF-8"?>\n \
                    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"\n \
                            xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"\n \
                            xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">\n';

        for(var i=0; i < search_result.hits.hits.length; ++i) {
            var source = search_result.hits.hits[i]._source;
            var catalog = source.catalog;
            var title = source.short_title || '';
            var description = source.description || '';
            var id = source.id;
            var url = 'http://' + host_base + '/' + catalog + '/' + id;

            var sitemap_entry = '<url>\n \
                <loc>' + url + '</loc>\n \
                <image:image>\n \
                  <image:loc>http://' + url + '/image/1200</image:loc>\n \
                  <image:title><![CDATA[' + title + ']]></image:title> \n \
                  <image:caption><![CDATA[' + description + ']]></image:caption> \n \
                </image:image>\n \
            </url>\n';

            sitemap += sitemap_entry;
        }

        sitemap += '</urlset>';
        res.header('Content-type', 'text/xml; charset=utf-8');
        res.send(sitemap);
    });
};
<commit_msg>Added offset to 20000<commit_after>var elasticsearch = require('elasticsearch');

exports.sitemap = function sitemap(req, res) {
    var es_client = req.app.get('es_client');
    var host_base = req.headers.host;
    var catalog = req.params.catalog;
    var offset = req.param('offset');

    var query = {
        index:'assets',
        size:20000,
        from:0,
        body:{}
    };

    if(offset && offset != undefined) {
        query.from = parseInt(offset) * 20000;
    }

    if(catalog && catalog != undefined) {
      query.body.filter = {
          and: []
      };

      query.body.filter.and.push({
        query: {
            match: {
                catalog: catalog
            }
        }
      });
    }

    es_client.search(query).then(function(search_result) {
        var sitemap = '<?xml version="1.0" encoding="UTF-8"?>\n \
                    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"\n \
                            xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"\n \
                            xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">\n';

        for(var i=0; i < search_result.hits.hits.length; ++i) {
            var source = search_result.hits.hits[i]._source;
            var catalog = source.catalog;
            var title = source.short_title || '';
            var description = source.description || '';
            var id = source.id;
            var url = 'http://' + host_base + '/' + catalog + '/' + id;

            var sitemap_entry = '<url>\n \
                <loc>' + url + '</loc>\n \
                <image:image>\n \
                  <image:loc>http://' + url + '/image/1200</image:loc>\n \
                  <image:title><![CDATA[' + title + ']]></image:title> \n \
                  <image:caption><![CDATA[' + description + ']]></image:caption> \n \
                </image:image>\n \
            </url>\n';

            sitemap += sitemap_entry;
        }

        sitemap += '</urlset>';
        res.header('Content-type', 'text/xml; charset=utf-8');
        res.send(sitemap);
    });
};
<|endoftext|>


<commit_before>'use strict'

const moment = require('moment-timezone')

const formatTime = (d) => moment(d).tz('Europe/Berlin').format('HH:mm')

const formatDate = (d) => moment(d).tz('Europe/Berlin').format('YYYY-MM-DD')

const formatDuration = (ms) => {
  const d = moment.duration(ms)
  return [
    ('0' + d.asMinutes()).slice(-2),
    ('0' + d.seconds()).slice(-2)
  ].join(':')
}

const convertJourney = (route) => {
  const firstPart = route.parts[0]
  const firstWaypoint = {
    location: firstPart.origin.name,
    arriveTime: null,
    arriveDate: null,
    departTime: formatTime(firstPart.departure),
    departDate: formatDate(firstPart.departure),
    trainId: firstPart.line.name || null
  }

  return {
    departTime: formatTime(route.departure),
    departDate: formatDate(route.departure),
    arriveTime: formatTime(route.arrival),
    arriveDate: formatDate(route.arrival),
    waypoints: [
      firstWaypoint,
      ...route.parts.map((part, i, parts) => {
        const nextPart = parts[i + 1]
        return {
          location: part.destination.name,
          arriveTime: formatTime(part.arrival),
          arriveDate: formatDate(part.arrival),
          departTime: nextPart ? formatTime(nextPart.departure) : null,
          departDate: nextPart ? formatDate(nextPart.departure) : null,
          trainId: part.line.name || null
        }
      })
    ],
    duration: formatDuration(new Date(route.arrival) - new Date(route.departure)),
    priceEUR: route.price.amount,
    platformDep: route.origin.platform || null,
    platformArr: route.destination.platform || null
  }
}

module.exports = convertJourney
<commit_msg>durations as HH:MM<commit_after>'use strict'

const moment = require('moment-timezone')

const formatTime = (d) => moment(d).tz('Europe/Berlin').format('HH:mm')

const formatDate = (d) => moment(d).tz('Europe/Berlin').format('YYYY-MM-DD')

const formatDuration = (ms) => {
  const d = moment.duration(ms)
  return [
    ('0' + Math.floor(d.asHours())).slice(-2),
    ('0' + d.minutes()).slice(-2)
  ].join(':')
}

const convertJourney = (route) => {
  const firstPart = route.parts[0]
  const firstWaypoint = {
    location: firstPart.origin.name,
    arriveTime: null,
    arriveDate: null,
    departTime: formatTime(firstPart.departure),
    departDate: formatDate(firstPart.departure),
    trainId: firstPart.line.name || null
  }

  return {
    departTime: formatTime(route.departure),
    departDate: formatDate(route.departure),
    arriveTime: formatTime(route.arrival),
    arriveDate: formatDate(route.arrival),
    waypoints: [
      firstWaypoint,
      ...route.parts.map((part, i, parts) => {
        const nextPart = parts[i + 1]
        return {
          location: part.destination.name,
          arriveTime: formatTime(part.arrival),
          arriveDate: formatDate(part.arrival),
          departTime: nextPart ? formatTime(nextPart.departure) : null,
          departDate: nextPart ? formatDate(nextPart.departure) : null,
          trainId: part.line.name || null
        }
      })
    ],
    duration: formatDuration(new Date(route.arrival) - new Date(route.departure)),
    priceEUR: route.price.amount,
    platformDep: route.origin.platform || null,
    platformArr: route.destination.platform || null
  }
}

module.exports = convertJourney
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2011 unscriptable.com
 *
 * TODO: documentation
 * TODO: process selector replacements in onSelector so they can be cascaded to other selector processors
 * TODO: allow for nested rules (LESS, SASS, XStyle)
 *
 */

(function (global, doc) {

	var ancestries, id = 0,
		rightTemplate = '${0}{${1}:expression(cssx_child_selector_right(this,"${1}","${2}"));}\n',
		levelTemplate = '${0}{${1}:expression(cssx_child_selector(this,"${1}","${2}"));}\n',
		leftTemplate = '${0}{${1}:${1}}';

	function createKey () {
        return 'cssx-child-selector-' + id++;
    }

	var replaceRx = /\$\{(\d)\}/g;
	function replace (string, values) {
		return string.replace(replaceRx, function (match, pos) {
			return values[pos];
		});
	}

	define({

		onSelector: function (selector) {

			if (selector.indexOf('>') >= 0) {

				// create unique key for this ancestry
				var key = createKey();

				// save ancestry
				ancestries = ancestries || [];
				ancestries.push({ selector: selector, key: key });

				return '.' + key;
			}

		},

		onEndRule: function (selectors) {
			var i, j, ancestry, level, parentKey, childKey, output = '';

			if (ancestries && ancestries.length > 0) {

				for (i = 0; i < ancestries.length; i++) {

					// TODO: bail if any blanks were found in ancestry
					ancestry = ancestries[i].selector.split(/\s*>\s*/g);
					childKey = ancestries[i].key;

					for (j = ancestry.length - 1; j > 0; j--) {

						level = ancestry[j];

						parentKey = createKey();

						if (j == ancestry.length - 1) {
							// create right-most rule
							output += replace(rightTemplate, [level, childKey, parentKey]);
						}
						else {
							output += replace(levelTemplate, [level, childKey, parentKey]);
						}

						childKey = parentKey;

					}

					// create left-most rule
					output += replace(leftTemplate, [ancestry[0], parentKey]);

				}
			}

			// clean up ancestries
			ancestries = null;

			return output;
		}

	});

	// TODO: remove this and replace it with something simpler
	function toggleClass (node, className, add) {
		var replaced, newClassName, replaceRx = new RegExp('\s?' + className + '\s?');
		newClassName = node.className.replace(replaceRx, function (match) {
			replaced = add;
			return add ? match : ' ';
		});
		newClassName += add && !replaced ? ' ' + className : '';
		// IE6 isn't smart enough to check if className actually changed
		if (node.className != newClassName) {
			node.className = newClassName;
		}
	}

	global['cssx_child_selector'] = function (node, childKey, parentKey) {
		var parent = node.parentNode;
		return parent && parent.currentStyle[parentKey] == parentKey ? childKey : '';
	};

	global['cssx_child_selector_right'] = function (node, origKey, parentKey) {
		var parent = node.parentNode;
		toggleClass(node, origKey, parent && parent.currentStyle[parentKey] == parentKey);
	};

}(this, document));
<commit_msg>hoisted the regex<commit_after>/**
 * Copyright (c) 2011 unscriptable.com
 *
 * TODO: documentation
 * TODO: process selector replacements in onSelector so they can be cascaded to other selector processors
 * TODO: allow for nested rules (LESS, SASS, XStyle)
 *
 */

(function (global, doc) {

	var ancestries, id = 0,
		ancestrySplitterRx = /\s*>\s*/g,
		rightTemplate = '${0}{${1}:expression(cssx_child_selector_right(this,"${1}","${2}"));}\n',
		levelTemplate = '${0}{${1}:expression(cssx_child_selector(this,"${1}","${2}"));}\n',
		leftTemplate = '${0}{${1}:${1}}';

	function createKey () {
        return 'cssx-child-selector-' + id++;
    }

	var replaceRx = /\$\{(\d)\}/g;
	function replace (string, values) {
		return string.replace(replaceRx, function (match, pos) {
			return values[pos];
		});
	}

	define({

		onSelector: function (selector) {

			if (selector.indexOf('>') >= 0) {

				// create unique key for this ancestry
				var key = createKey();

				// save ancestry
				ancestries = ancestries || [];
				ancestries.push({ selector: selector, key: key });

				return '.' + key;
			}

		},

		onEndRule: function (selectors) {
			var i, j, ancestry, level, parentKey, childKey, output = '';

			if (ancestries && ancestries.length > 0) {

				for (i = 0; i < ancestries.length; i++) {

					// TODO: bail if any blanks were found in ancestry
					ancestry = ancestries[i].selector.split(ancestrySplitterRx);
					childKey = ancestries[i].key;

					for (j = ancestry.length - 1; j > 0; j--) {

						level = ancestry[j];

						parentKey = createKey();

						if (j == ancestry.length - 1) {
							// create right-most rule
							output += replace(rightTemplate, [level, childKey, parentKey]);
						}
						else {
							output += replace(levelTemplate, [level, childKey, parentKey]);
						}

						childKey = parentKey;

					}

					// create left-most rule
					output += replace(leftTemplate, [ancestry[0], parentKey]);

				}
			}

			// clean up ancestries
			ancestries = null;

			return output;
		}

	});

	// TODO: remove this and replace it with something simpler
	function toggleClass (node, className, add) {
		var replaced, newClassName, replaceRx = new RegExp('\s?' + className + '\s?');
		newClassName = node.className.replace(replaceRx, function (match) {
			replaced = add;
			return add ? match : ' ';
		});
		newClassName += add && !replaced ? ' ' + className : '';
		// IE6 isn't smart enough to check if className actually changed
		if (node.className != newClassName) {
			node.className = newClassName;
		}
	}

	global['cssx_child_selector'] = function (node, childKey, parentKey) {
		var parent = node.parentNode;
		return parent && parent.currentStyle[parentKey] == parentKey ? childKey : '';
	};

	global['cssx_child_selector_right'] = function (node, origKey, parentKey) {
		var parent = node.parentNode;
		toggleClass(node, origKey, parent && parent.currentStyle[parentKey] == parentKey);
	};

}(this, document));
<|endoftext|>


<commit_before>export function TakeResources(gameRef, resources) {
  const params = new FormData();
  params.set('id', gameRef.gameId);
  params.set('playerToken', gameRef.playerToken);
  params.set('action', 'TakeResources');
  params.set('payload', resources);

  return fetch('/game/act', { method: 'POST', body: params });
}

export function TakeFactory(gameRef, factoryRow, factoryIndex) {
  params.set('id', gameRef.gameId);
  params.set('playerToken', gameRef.playerToken);
  params.set('action', 'TakeFactory');
  params.set('payload', `${factoryRow},${factoryIndex}`);

  return fetch('/game/act', { method: 'POST', body: params });
}
<commit_msg>Fixing build failure from the previous commit.<commit_after>export function TakeResources(gameRef, resources) {
  const params = new FormData();
  params.set('id', gameRef.gameId);
  params.set('playerToken', gameRef.playerToken);
  params.set('action', 'TakeResources');
  params.set('payload', resources);

  return fetch('/game/act', { method: 'POST', body: params });
}

export function TakeFactory(gameRef, factoryRow, factoryIndex) {
  const params = new FormData();
  params.set('id', gameRef.gameId);
  params.set('playerToken', gameRef.playerToken);
  params.set('action', 'TakeFactory');
  params.set('payload', `${factoryRow},${factoryIndex}`);

  return fetch('/game/act', { method: 'POST', body: params });
}
<|endoftext|>


<commit_before>import mirror, { actions } from 'mirrorx';
import { GET_LIST, GET_ONE, CREATE, UPDATE } from '../rest';

const addRecords = (newRecords = [], oldRecords) => {

  const newRecordsById = newRecords.reduce((prev, record) => {
    prev[record.id] = {
      record,
      fetchedAt: new Date(),
    };
    return prev;
  }, {});

  return {
    ...oldRecords,
    ...newRecordsById,
  };
};

export default (model, restClient) => {
  mirror.model({
    name: model,
    initialState: {
      list: {},
      ids: [],
      total: 0,
      params: {
        _filter: {},
        _sort: null,
        _order: "asc",
        _page: 1,
        _limit: 10,
      },
    },
    reducers: {
      add(state, { data, total }) {
        return {
          ...state,
          list: addRecords(data, state.list),
          total,
          ids: data.map(record => record.id),
        };
      },
      addOne(state, data) {
        return {
          ...state,
          list: addRecords([data], state.list),
        }
      },
      setListParams(state, data) {
        return {
          ...state,
          params: {
            ...state.params,
            ...data
          },
        }
      },
    },
    effects: {
      async getList(params) {
        actions.loading.set(true);
        const result = await restClient(GET_LIST, model, params);
        actions[model].add(result);
        actions.loading.set(false);
      },
      async getOne(id) {
        actions.loading.set(true);
        const { data } = await restClient(GET_ONE, model, { id });
        actions[model].addOne(data);
        actions.loading.set(false);
      },
      async create(data) {
        actions.loading.set(true);
        await restClient(CREATE, model, { data });
        actions.loading.set(false);
      },
      async update(id, data) {
        actions.loading.set(true);
        await restClient(UPDATE, model, { id, data });
        actions.loading.set(false);
      },
    }

  });
};<commit_msg>删除action<commit_after>import mirror, { actions } from 'mirrorx';
import { GET_LIST, GET_ONE, CREATE, UPDATE, REMOVE } from '../rest';

const addRecords = (newRecords = [], oldRecords) => {

  const newRecordsById = newRecords.reduce((prev, record) => {
    prev[record.id] = {
      record,
      fetchedAt: new Date(),
    };
    return prev;
  }, {});

  return {
    ...oldRecords,
    ...newRecordsById,
  };
};

export default (model, restClient) => {
  mirror.model({
    name: model,
    initialState: {
      list: {},
      ids: [],
      total: 0,
      params: {
        _filter: {},
        _sort: null,
        _order: "asc",
        _page: 1,
        _limit: 10,
      },
    },
    reducers: {
      add(state, { data, total }) {
        return {
          ...state,
          list: addRecords(data, state.list),
          total,
          ids: data.map(record => record.id),
        };
      },
      addOne(state, data) {
        return {
          ...state,
          list: addRecords([data], state.list),
        }
      },
      setListParams(state, data) {
        return {
          ...state,
          params: {
            ...state.params,
            ...data
          },
        }
      },
    },
    effects: {
      async getList(params) {
        actions.loading.set(true);
        const result = await restClient(GET_LIST, model, params);
        actions[model].add(result);
        actions.loading.set(false);
      },
      async getOne(id) {
        actions.loading.set(true);
        const { data } = await restClient(GET_ONE, model, { id });
        actions[model].addOne(data);
        actions.loading.set(false);
      },
      async create(data) {
        actions.loading.set(true);
        await restClient(CREATE, model, { data });
        actions.loading.set(false);
      },
      async update(id, data) {
        actions.loading.set(true);
        await restClient(UPDATE, model, { id, data });
        actions.loading.set(false);
      },
      async remove(id) {
        actions.loading.set(true);
        await restClient(REMOVE, model, { id });
        actions.loading.set(false);
      },
    }

  });
};<|endoftext|>


<commit_before>(function(fn, _, undefined) {
  fn.fromString = function(string) {
    var [year, month, day] = _.map(string.split('-'), function(s) {
      return Number.parseInt(s);
    });
    return new Date(year, month-1, day);
  };
})(Date, window._);

<commit_msg>Add addDays to JS Date<commit_after>(function(clazz, _, undefined) {
  clazz.fromString = function(string) {
    var [year, month, day] = _.map(string.split('-'), function(s) {
      return Number.parseInt(s);
    });
    return new Date(year, month-1, day);
  };

  var fn = clazz.prototype;

  fn.addDays = function(days) {
    var year = this.getFullYear(),
        month = this.getMonth(),
        day = this.getDate() + days;

    return new Date(year, month, day);
  };
})(Date, window._);

<|endoftext|>


<commit_before>//= require introjs

var introJs = introJs().setOption("nextLabel", " Próximo ")
.setOption("prevLabel", "Anterior")
.setOption("skipLabel", "Fechar")
.setOption("doneLabel", "Fechar")
.setOption("showStepNumbers", false);

L.easyButton('fa-question-circle', function(btn, map) {
  introJs.start();
}).addTo(map);

$(".navbar")
  .attr("data-intro",
  "
WELCOME!
 Facilite seu trajeto pela universidade com o Onde é? UnB, através dele você será capaz de traçar rotas entre edifícios, localizar salas, prédios, departamentos e muito mais. Para conhecer mais sobre a aplicação clique em Próximo.")
  .attr("data-step", "1")
  .attr("data-tooltipClass", "tutorialStyle")
  .attr("data-position", "auto");
$("#searchContainer")
  .attr("data-intro",
  "
PESQUISA
 Aqui é possível pesquisar qualquer prédio, sala e departamento da universidade!")
  .attr("data-step", "2")
  .attr("data-tooltipClass", "tutorialStyle")
  .attr("data-position", "auto");
$(".leaflet-control-zoom")
  .attr("data-intro",
  "
ZOOM
 Para interagir melhor com o mapa é possível dar zoom nos lugares do seu interesse. Basta clicar nos sinais de + e -.")
  .attr("data-step", "3")
  .attr("data-tooltipClass", "tutorialStyle")
  .attr("data-position", "auto");
$(".leaflet-bar.easy-button-container.leaflet-control").eq(0)
  .attr("data-intro",
  "
ROTAS
 Clicando nesse botão e inserindo o Local de Partida e o Local de chegada, uma rota será traçada e você vai conseguir navegar pela universidade sem nenhum problema!")
  .attr("data-step", "4")
  .attr("data-tooltipClass", "tutorialStyle")
  .attr("data-position", "auto");
$(".leaflet-control-layers.leaflet-control")
  .attr("data-intro",
  "
PONTOS
 Aqui você será capaz de localizar diversos pontos da universidade, como bicicletários, banheiros, lanchonetes, pontos de acesso e pontos de ônibus!")
  .attr("data-step", "5")
  .attr("data-tooltipClass", "tutorialStyle")
  .attr("data-position", "auto");
$(".leaflet-contextmenu")
  .attr("data-intro",
  "
MENU
 Clicando com o botão direito do mouse um menu irá aparecerá com opções para selecionar rotas e compartilhar sua posição!")
  .attr("data-step", "6")
  .attr("data-tooltipClass", "tutorialStyle")
  .attr("data-position", "auto");
$(".leaflet-bar.easy-button-container.leaflet-control").eq(1)
  .attr("data-intro",
  "
FIM!
 Chegamos ao fim! Caso tenha alguma dúvida ou queira ver o tutorial denovo clique nesse botão")
  .attr("data-step", "7")
  .attr("data-tooltipClass", "tutorialStyle")
  .attr("data-position", "auto");

introJs.oncomplete(function() {
  map.contextmenu.hide();
  localStorage.setItem("hideTutorial", true);
});
introJs.onexit(function(){
  localStorage.setItem("hideTutorial", true);
});

window.addEventListener("load", function() {
  if(!localStorage.hasOwnProperty('hideTutorial')){
    introJs.start();
  }
});

introJs.onchange(function(element){
  var step = $(element).data("step");
  if (step == 6){
    var center = map.getCenter();
    map.contextmenu.showAt(center);
  } else {
    map.contextmenu.hide();
  }
});
<commit_msg>Fixing tutorial position on the map<commit_after>//= require introjs

var introJs = introJs().setOption("nextLabel", " Próximo ")
.setOption("prevLabel", "Anterior")
.setOption("skipLabel", "Fechar")
.setOption("doneLabel", "Fechar")
.setOption("showStepNumbers", false);

L.easyButton('fa-question-circle', function(btn, map) {
  introJs.start();
}).addTo(map);

$(".navbar")
  .attr("data-intro",
  "
WELCOME!
 Facilite seu trajeto pela universidade com o Onde é? UnB, através dele você será capaz de traçar rotas entre edifícios, localizar salas, prédios, departamentos e muito mais. Para conhecer mais sobre a aplicação clique em Próximo.")
  .attr("data-step", "1")
  .attr("data-tooltipClass", "tutorialStyle")
  .attr("data-position", "bottom-middle-aligned");
$("#searchContainer")
  .attr("data-intro",
  "
PESQUISA
 Aqui é possível pesquisar qualquer prédio, sala e departamento da universidade!")
  .attr("data-step", "2")
  .attr("data-tooltipClass", "tutorialStyle")
  .attr("data-position", "bottom-middle-aligne");
$(".leaflet-control-zoom")
  .attr("data-intro",
  "
ZOOM
 Para interagir melhor com o mapa é possível dar zoom nos lugares do seu interesse. Basta clicar nos sinais de + e -.")
  .attr("data-step", "3")
  .attr("data-tooltipClass", "tutorialStyle")
  .attr("data-position", "auto");
$(".leaflet-bar.easy-button-container.leaflet-control").eq(0)
  .attr("data-intro",
  "
ROTAS
 Clicando nesse botão e inserindo o Local de Partida e o Local de chegada, uma rota será traçada e você vai conseguir navegar pela universidade sem nenhum problema!")
  .attr("data-step", "4")
  .attr("data-tooltipClass", "tutorialStyle")
  .attr("data-position", "auto");
$(".leaflet-control-layers.leaflet-control")
  .attr("data-intro",
  "
PONTOS
 Aqui você será capaz de localizar diversos pontos da universidade, como bicicletários, banheiros, lanchonetes, pontos de acesso e pontos de ônibus!")
  .attr("data-step", "5")
  .attr("data-tooltipClass", "tutorialStyle")
  .attr("data-position", "auto");
$(".leaflet-contextmenu")
  .attr("data-intro",
  "
MENU
 Clicando com o botão direito do mouse no mapa um menu irá aparecerá com opções para selecionar rotas e compartilhar sua posição!")
  .attr("data-step", "6")
  .attr("data-tooltipClass", "tutorialStyle")
  .attr("data-position", "bottom-middle-aligne");
$(".leaflet-bar.easy-button-container.leaflet-control").eq(1)
  .attr("data-intro",
  "
FIM!
 Chegamos ao fim! Caso tenha alguma dúvida ou queira ver o tutorial denovo clique nesse botão")
  .attr("data-step", "7")
  .attr("data-tooltipClass", "tutorialStyle")
  .attr("data-position", "auto");

introJs.oncomplete(function() {
  map.contextmenu.hide();
  localStorage.setItem("hideTutorial", true);
});
introJs.onexit(function(){
  localStorage.setItem("hideTutorial", true);
});

window.addEventListener("load", function() {
  if(!localStorage.hasOwnProperty('hideTutorial')){
    introJs.start();
  }
});

introJs.onchange(function(element){
  var step = $(element).data("step");
  if (step == 6){
    // var center = map.getCenter();
    map.contextmenu.showAt(L.latLng(-15.759648154527714, -47.86931991577149));
  } else {
    map.contextmenu.hide();
  }
});
<|endoftext|>