<commit_before>'use strict';
// Reference: https://projectpokemon.org/wiki/Pokemon_X/Y_3DS_Structure
function stripNullChars (str) {
  return str.replace(/\0.*/, '');
}

function parseMap (data, map) {
  const parsedData = [];
  for (let i = 0; i < map.length; i++, data = Math.floor(data / 2)) {
    if (map[i] && data % 2) {
      parsedData.push(map[i]);
    }
  }
  return parsedData;
}

function checksumIsValid (buf) {
  let sum = 0;
  for (let i = 8; i < 232; i += 2) {
    sum += buf.readUInt16LE(i);
  }
  return (sum & 0xffff) === buf.readUInt16LE(0x06);
}

function getDateFromInt (dateStorage) {
  if (!dateStorage) {
    return null;
  }
  return Date.UTC((dateStorage & 0xff) + 2000, (dateStorage >>> 8 & 0xff) - 1, (dateStorage >>> 16 & 0xff));
}

exports.parseBuffer = buf => {
  const data = {};
  if (buf.readUInt16LE(0x04)) {
    throw new Error('The provided buffer is not valid pk6 data');
  }
  data.checksumIsValid = checksumIsValid(buf);
  data.encryptionConstant = buf.readUInt32LE(0x00);
  data.dexNo = buf.readUInt16LE(0x08);
  data.heldItemId = buf.readUInt16LE(0x0a);
  data.tid = buf.readUInt16LE(0x0c);
  data.sid = buf.readUInt16LE(0x0e);
  data.exp = buf.readUInt32LE(0x10);
  data.abilityId = buf.readUInt8(0x14);
  data.abilityNum = buf.readUInt8(0x15);
  data.superTrainingHitsRemaining = buf.readUInt8(0x16);
  data.superTrainingBag = buf.readUInt8(0x17);
  data.pid = buf.readUInt32LE(0x18);
  data.natureId = buf.readUInt8(0x1c); // TODO: Parse

  const genderByte = buf.readUInt8(0x1d);
  data.isFatefulEncounter = !!(genderByte & 0x01);
  const isFemale = genderByte & 0x02;
  const isGenderless = genderByte & 0x04;
  data.gender = isFemale ? 'F' : isGenderless ? '' : 'M';
  data.formId = genderByte >>> 3;

  data.evHp = buf.readUInt8(0x1e);
  data.evAtk = buf.readUInt8(0x1f);
  data.evDef = buf.readUInt8(0x20);
  data.evSpe = buf.readUInt8(0x21);
  data.evSpAtk = buf.readUInt8(0x22);
  data.evSpDef = buf.readUInt8(0x23);

  data.contestStatCool = buf.readUInt8(0x24);
  data.contestStatBeauty = buf.readUInt8(0x25);
  data.contestStatCute = buf.readUInt8(0x26);
  data.contestStatSmart = buf.readUInt8(0x27);
  data.contestStatTough = buf.readUInt8(0x28);
  data.contestStatSheen = buf.readUInt8(0x29);

  const markingByte = buf.readUInt8(0x2a);
  data.hasCircleMarking = !!(markingByte & 0x01);
  data.hasTriangleMarking = !!(markingByte & 0x02);
  data.hasSquareMarking = !!(markingByte & 0x04);
  data.hasHeartMarking = !!(markingByte & 0x08);
  data.hasStarMarking = !!(markingByte & 0x10);
  data.hasDiamondMarking = !!(markingByte & 0x20);

  const pokerusByte = buf.readUInt8(0x2b);
  data.pokerusDuration = pokerusByte & 16;
  data.pokerusStrain = pokerusByte >>> 4;

  data.medalData = buf.readUInt32LE(0x2c);
  data.ribbonData = buf.readUIntLE(0x30, 6);
  data.distributionSuperTrainingFlags = buf.readUInt8(0x3a); // Not sure what these are
  data.nickname = stripNullChars(buf.toString('utf16le', 0x40, 0x58));

  data.move1Id = buf.readUInt16LE(0x5a);
  data.move2Id = buf.readUInt16LE(0x5c);
  data.move3Id = buf.readUInt16LE(0x5e);
  data.move4Id = buf.readUInt16LE(0x60);
  data.move1Pp = buf.readUInt8(0x62);
  data.move2Pp = buf.readUInt8(0x63);
  data.move3Pp = buf.readUInt8(0x64);
  data.move4Pp = buf.readUInt8(0x65);
  data.move1Ppu = buf.readUInt8(0x66);
  data.move2Ppu = buf.readUInt8(0x67);
  data.move3Ppu = buf.readUInt8(0x68);
  data.move4Ppu = buf.readUInt8(0x69);
  data.eggMove1Id = buf.readUInt16LE(0x6a);
  data.eggMove2Id = buf.readUInt16LE(0x6c);
  data.eggMove3Id = buf.readUInt16LE(0x6e);
  data.eggMove4Id = buf.readUInt16LE(0x70);

  data.canDoSecretSuperTraining = !!(buf.readUInt8(0x72));

  const ivBytes = buf.readUInt32LE(0x74);
  data.ivHp = ivBytes & 0x1f;
  data.ivAtk = ivBytes >>> 5 & 0x1f;
  data.ivDef = ivBytes >>> 10 & 0x1f;
  data.ivSpe = ivBytes >>> 15 & 0x1f;
  data.ivSpAtk = ivBytes >>> 20 & 0x1f;
  data.ivSpDef = ivBytes >>> 25 & 0x1f;
  data.isEgg = (ivBytes >>> 30) % 2 !== 0;
  data.isNicknamed = (ivBytes >>> 31) % 2 !== 0;

  data.notOt = stripNullChars(buf.toString('utf16le', 0x78, 0x90));
  data.notOtGender = buf.readUInt8(0x92) ? 'F' : 'M';

  data.currentHandlerIsOt = !buf.readUInt8(0x93);

  data.geoLocation1 = buf.readUInt16LE(0x94); // TODO: Figure out how to parse these
  data.geoLocation2 = buf.readUInt16LE(0x96);
  data.geoLocation3 = buf.readUInt16LE(0x98);
  data.geoLocation4 = buf.readUInt16LE(0x9a);
  data.geoLocation5 = buf.readUInt16LE(0x9c);

  data.notOtFriendship = buf.readUInt8(0xa2);
  data.notOtAffection = buf.readUInt8(0xa3);
  data.notOtMemoryIntensity = buf.readUInt8(0xa4); // TODO: Parse
  data.notOtMemoryLine = buf.readUInt8(0xa5);
  data.notOtMemoryFeeling = buf.readUInt8(0xa6);
  data.notOtMemoryTextVar = buf.readUInt16LE(0xa8);

  data.fullness = buf.readUInt8(0xae);
  data.enjoyment = buf.readUInt8(0xaf);

  data.ot = stripNullChars(buf.toString('utf16le', 0xb0, 0xc8));
  data.otFriendship = buf.readUInt8(0xca);
  data.otAffection = buf.readUInt8(0xcb);
  data.otMemoryIntensity = buf.readUInt8(0xcc); // TODO: Parse
  data.otMemoryLine = buf.readUInt8(0xcd);
  data.otMemoryTextVar = buf.readUInt16LE(0xce);
  data.otMemoryFeeling = buf.readUInt8(0xd0);

  data.eggDate = getDateFromInt(buf.readUIntLE(0xd1, 3));
  data.metDate = getDateFromInt(buf.readUIntLE(0xd4, 3));

  data.eggLocationId = buf.readUInt16LE(0xd8); // TODO: Parse
  data.metLocationId = buf.readUInt32LE(0xda);
  data.ballId = buf.readUInt8(0xdc);

  const encounterLevelByte = buf.readUInt8(0xdd);
  data.levelMet = encounterLevelByte & 0x7f;
  data.otGender = encounterLevelByte >>> 7 ? 'F' : 'M';

  data.encounterTypeId = buf.readUInt8(0xde); // TODO: Parse
  data.otGameId = buf.readUInt8(0xdf); // TODO: Parse
  data.countryId = buf.readUInt8(0xe0); // TODO: Parse
  data.regionId = buf.readUInt8(0xe1); // TODO: Parse
  data.consoleRegion = ['J', 'U', 'E', 'K'][buf.readUInt8(0xe2)]; // Japan, Americas, PAL, Korea
  data.language = ['JPN', 'ENG', 'FRE', 'ITA', 'GER', 'SPA', 'KOR'][buf.readUInt8(0xe3) - 1];
  data.rawPk6 = buf.toString('base64');

  return data;
};

exports.parseFile = path => {
  return exports.parseBuffer(require('fs').readFileSync(path));
};

exports.getPokemonData = dexNo => {
  try {
    return require(`./pokemon_data/${dexNo}.json`);
  } catch (e) {
    throw new Error(`Invalid dex number: ${dexNo}`);
  }
};

exports.getItemData = itemId => {
  if (itemId === 0) {
    return null;
  }
  try {
    return require(`./item_data_gen6/${itemId}.json`);
  } catch (e) {
    throw new Error(`Invalid item ID: ${itemId}`);
  }
};

exports.getMoveData = moveId => {
  if (moveId === 0) {
    return null;
  }
  try {
    return require(`./move_data/${moveId}.json`);
  } catch (e) {
    throw new Error(`Invalid move ID: ${moveId}`);
  }
};

exports.getAbilityData = abilityId => {
  if (abilityId === 0) {
    return null;
  }
  try {
    return require(`./ability_data/${abilityId}.json`);
  } catch (e) {
    throw `Invalid ability ID: ${abilityId}`;
  }
};

exports.getRibbonData = ribbonData => {
  return parseMap(ribbonData, require('./ribbonsByOrder'));
};

exports.getMedalData = medalData => {
  return parseMap(medalData, require('./medalsByOrder'));
};
<commit_msg>Added the missing console regions<commit_after>'use strict';
// Reference: https://projectpokemon.org/wiki/Pokemon_X/Y_3DS_Structure
function stripNullChars (str) {
  return str.replace(/\0.*/, '');
}

function parseMap (data, map) {
  const parsedData = [];
  for (let i = 0; i < map.length; i++, data = Math.floor(data / 2)) {
    if (map[i] && data % 2) {
      parsedData.push(map[i]);
    }
  }
  return parsedData;
}

function checksumIsValid (buf) {
  let sum = 0;
  for (let i = 8; i < 232; i += 2) {
    sum += buf.readUInt16LE(i);
  }
  return (sum & 0xffff) === buf.readUInt16LE(0x06);
}

function getDateFromInt (dateStorage) {
  if (!dateStorage) {
    return null;
  }
  return Date.UTC((dateStorage & 0xff) + 2000, (dateStorage >>> 8 & 0xff) - 1, (dateStorage >>> 16 & 0xff));
}

exports.parseBuffer = buf => {
  const data = {};
  if (buf.readUInt16LE(0x04)) {
    throw new Error('The provided buffer is not valid pk6 data');
  }
  data.checksumIsValid = checksumIsValid(buf);
  data.encryptionConstant = buf.readUInt32LE(0x00);
  data.dexNo = buf.readUInt16LE(0x08);
  data.heldItemId = buf.readUInt16LE(0x0a);
  data.tid = buf.readUInt16LE(0x0c);
  data.sid = buf.readUInt16LE(0x0e);
  data.exp = buf.readUInt32LE(0x10);
  data.abilityId = buf.readUInt8(0x14);
  data.abilityNum = buf.readUInt8(0x15);
  data.superTrainingHitsRemaining = buf.readUInt8(0x16);
  data.superTrainingBag = buf.readUInt8(0x17);
  data.pid = buf.readUInt32LE(0x18);
  data.natureId = buf.readUInt8(0x1c); // TODO: Parse

  const genderByte = buf.readUInt8(0x1d);
  data.isFatefulEncounter = !!(genderByte & 0x01);
  const isFemale = genderByte & 0x02;
  const isGenderless = genderByte & 0x04;
  data.gender = isFemale ? 'F' : isGenderless ? '' : 'M';
  data.formId = genderByte >>> 3;

  data.evHp = buf.readUInt8(0x1e);
  data.evAtk = buf.readUInt8(0x1f);
  data.evDef = buf.readUInt8(0x20);
  data.evSpe = buf.readUInt8(0x21);
  data.evSpAtk = buf.readUInt8(0x22);
  data.evSpDef = buf.readUInt8(0x23);

  data.contestStatCool = buf.readUInt8(0x24);
  data.contestStatBeauty = buf.readUInt8(0x25);
  data.contestStatCute = buf.readUInt8(0x26);
  data.contestStatSmart = buf.readUInt8(0x27);
  data.contestStatTough = buf.readUInt8(0x28);
  data.contestStatSheen = buf.readUInt8(0x29);

  const markingByte = buf.readUInt8(0x2a);
  data.hasCircleMarking = !!(markingByte & 0x01);
  data.hasTriangleMarking = !!(markingByte & 0x02);
  data.hasSquareMarking = !!(markingByte & 0x04);
  data.hasHeartMarking = !!(markingByte & 0x08);
  data.hasStarMarking = !!(markingByte & 0x10);
  data.hasDiamondMarking = !!(markingByte & 0x20);

  const pokerusByte = buf.readUInt8(0x2b);
  data.pokerusDuration = pokerusByte & 16;
  data.pokerusStrain = pokerusByte >>> 4;

  data.medalData = buf.readUInt32LE(0x2c);
  data.ribbonData = buf.readUIntLE(0x30, 6);
  data.distributionSuperTrainingFlags = buf.readUInt8(0x3a); // Not sure what these are
  data.nickname = stripNullChars(buf.toString('utf16le', 0x40, 0x58));

  data.move1Id = buf.readUInt16LE(0x5a);
  data.move2Id = buf.readUInt16LE(0x5c);
  data.move3Id = buf.readUInt16LE(0x5e);
  data.move4Id = buf.readUInt16LE(0x60);
  data.move1Pp = buf.readUInt8(0x62);
  data.move2Pp = buf.readUInt8(0x63);
  data.move3Pp = buf.readUInt8(0x64);
  data.move4Pp = buf.readUInt8(0x65);
  data.move1Ppu = buf.readUInt8(0x66);
  data.move2Ppu = buf.readUInt8(0x67);
  data.move3Ppu = buf.readUInt8(0x68);
  data.move4Ppu = buf.readUInt8(0x69);
  data.eggMove1Id = buf.readUInt16LE(0x6a);
  data.eggMove2Id = buf.readUInt16LE(0x6c);
  data.eggMove3Id = buf.readUInt16LE(0x6e);
  data.eggMove4Id = buf.readUInt16LE(0x70);

  data.canDoSecretSuperTraining = !!(buf.readUInt8(0x72));

  const ivBytes = buf.readUInt32LE(0x74);
  data.ivHp = ivBytes & 0x1f;
  data.ivAtk = ivBytes >>> 5 & 0x1f;
  data.ivDef = ivBytes >>> 10 & 0x1f;
  data.ivSpe = ivBytes >>> 15 & 0x1f;
  data.ivSpAtk = ivBytes >>> 20 & 0x1f;
  data.ivSpDef = ivBytes >>> 25 & 0x1f;
  data.isEgg = (ivBytes >>> 30) % 2 !== 0;
  data.isNicknamed = (ivBytes >>> 31) % 2 !== 0;

  data.notOt = stripNullChars(buf.toString('utf16le', 0x78, 0x90));
  data.notOtGender = buf.readUInt8(0x92) ? 'F' : 'M';

  data.currentHandlerIsOt = !buf.readUInt8(0x93);

  data.geoLocation1 = buf.readUInt16LE(0x94); // TODO: Figure out how to parse these
  data.geoLocation2 = buf.readUInt16LE(0x96);
  data.geoLocation3 = buf.readUInt16LE(0x98);
  data.geoLocation4 = buf.readUInt16LE(0x9a);
  data.geoLocation5 = buf.readUInt16LE(0x9c);

  data.notOtFriendship = buf.readUInt8(0xa2);
  data.notOtAffection = buf.readUInt8(0xa3);
  data.notOtMemoryIntensity = buf.readUInt8(0xa4); // TODO: Parse
  data.notOtMemoryLine = buf.readUInt8(0xa5);
  data.notOtMemoryFeeling = buf.readUInt8(0xa6);
  data.notOtMemoryTextVar = buf.readUInt16LE(0xa8);

  data.fullness = buf.readUInt8(0xae);
  data.enjoyment = buf.readUInt8(0xaf);

  data.ot = stripNullChars(buf.toString('utf16le', 0xb0, 0xc8));
  data.otFriendship = buf.readUInt8(0xca);
  data.otAffection = buf.readUInt8(0xcb);
  data.otMemoryIntensity = buf.readUInt8(0xcc); // TODO: Parse
  data.otMemoryLine = buf.readUInt8(0xcd);
  data.otMemoryTextVar = buf.readUInt16LE(0xce);
  data.otMemoryFeeling = buf.readUInt8(0xd0);

  data.eggDate = getDateFromInt(buf.readUIntLE(0xd1, 3));
  data.metDate = getDateFromInt(buf.readUIntLE(0xd4, 3));

  data.eggLocationId = buf.readUInt16LE(0xd8); // TODO: Parse
  data.metLocationId = buf.readUInt32LE(0xda);
  data.ballId = buf.readUInt8(0xdc);

  const encounterLevelByte = buf.readUInt8(0xdd);
  data.levelMet = encounterLevelByte & 0x7f;
  data.otGender = encounterLevelByte >>> 7 ? 'F' : 'M';

  data.encounterTypeId = buf.readUInt8(0xde); // TODO: Parse
  data.otGameId = buf.readUInt8(0xdf); // TODO: Parse
  data.countryId = buf.readUInt8(0xe0); // TODO: Parse
  data.regionId = buf.readUInt8(0xe1); // TODO: Parse
  data.consoleRegion = ['J', 'U', 'E', 'K', 'T', 'C'][buf.readUInt8(0xe2)]; // Japan, Americas, PAL, Korea, Taiwan, China
  data.language = ['JPN', 'ENG', 'FRE', 'ITA', 'GER', 'SPA', 'KOR'][buf.readUInt8(0xe3) - 1];
  data.rawPk6 = buf.toString('base64');

  return data;
};

exports.parseFile = path => {
  return exports.parseBuffer(require('fs').readFileSync(path));
};

exports.getPokemonData = dexNo => {
  try {
    return require(`./pokemon_data/${dexNo}.json`);
  } catch (e) {
    throw new Error(`Invalid dex number: ${dexNo}`);
  }
};

exports.getItemData = itemId => {
  if (itemId === 0) {
    return null;
  }
  try {
    return require(`./item_data_gen6/${itemId}.json`);
  } catch (e) {
    throw new Error(`Invalid item ID: ${itemId}`);
  }
};

exports.getMoveData = moveId => {
  if (moveId === 0) {
    return null;
  }
  try {
    return require(`./move_data/${moveId}.json`);
  } catch (e) {
    throw new Error(`Invalid move ID: ${moveId}`);
  }
};

exports.getAbilityData = abilityId => {
  if (abilityId === 0) {
    return null;
  }
  try {
    return require(`./ability_data/${abilityId}.json`);
  } catch (e) {
    throw `Invalid ability ID: ${abilityId}`;
  }
};

exports.getRibbonData = ribbonData => {
  return parseMap(ribbonData, require('./ribbonsByOrder'));
};

exports.getMedalData = medalData => {
  return parseMap(medalData, require('./medalsByOrder'));
};
<|endoftext|>


<commit_before>var cssSelectorParser = require('css-selector-parser').CssSelectorParser;
var selectorParser = new cssSelectorParser();
var inspect = require('obj-inspector')

module.exports = function plugin (options) {
    options = options || {}

    var preConnection = options.prefix || "-"
    var sufConnection = options.suffix || "-"

    return function (css) {
        var newRules = []

        css.eachAtRule(function (atRule, i) {
            if (atRule.name === 'prefix') {
                atRule.eachRule(function (rule) {
                    if (isClassSelector(rule.selector)) {
                        rule.selector = "." + atRule.params + preConnection + selectorParser.parse(rule.selector).rule.classNames[0]
                    }
                    if (isIdSelector(rule.selector)) {
                        rule.selector = "#" + atRule.params + sufConnection + selectorParser.parse(rule.selector).rule.id
                    }
//                    inspect(rule)
                    rule.eachDecl(function (decl) {
                        decl.before = rule.before
                        decl.after = rule.after
                    })
                    newRules.push(rule)
                })

            }

            if (atRule.name === 'suffix') {
                atRule.eachRule(function (rule) {
                    if (isClassSelector(rule.selector)) {
                        rule.selector = "." + selectorParser.parse(rule.selector).rule.classNames[0] + preConnection + atRule.params;
                    }
                    if (isIdSelector(rule.selector)) {
                        rule.selector = "#" + selectorParser.parse(rule.selector).rule.id + sufConnection + atRule.params;
                    }
                    rule.eachDecl(function (decl) {
                        decl.before = "\n  "
                        decl.after = "\n  "
                    })
                    rule.after = "\n  "
                    newRules.push(rule)
                })

            }
            atRule.removeSelf()
        })
        css.append(newRules)
    }
}

function isClassSelector (selector) {
    if (selectorParser.parse(selector).rule.classNames) return true
}

function isIdSelector (selector) {
    if (selectorParser.parse(selector).rule.id) return true
}
<commit_msg>:put_litter_in_its_place:<commit_after>var cssSelectorParser = require('css-selector-parser').CssSelectorParser;
var selectorParser = new cssSelectorParser();

module.exports = function plugin (options) {
    options = options || {}

    var preConnection = options.prefix || "-"
    var sufConnection = options.suffix || "-"

    return function (css) {
        var newRules = []

        css.eachAtRule(function (atRule, i) {
            if (atRule.name === 'prefix') {
                atRule.eachRule(function (rule) {
                    if (isClassSelector(rule.selector)) {
                        rule.selector = "." + atRule.params + preConnection + selectorParser.parse(rule.selector).rule.classNames[0]
                    }
                    if (isIdSelector(rule.selector)) {
                        rule.selector = "#" + atRule.params + sufConnection + selectorParser.parse(rule.selector).rule.id
                    }
                    rule.eachDecl(function (decl) {
                        decl.before = rule.before
                        decl.after = rule.after
                    })
                    newRules.push(rule)
                })

            }

            if (atRule.name === 'suffix') {
                atRule.eachRule(function (rule) {
                    if (isClassSelector(rule.selector)) {
                        rule.selector = "." + selectorParser.parse(rule.selector).rule.classNames[0] + preConnection + atRule.params;
                    }
                    if (isIdSelector(rule.selector)) {
                        rule.selector = "#" + selectorParser.parse(rule.selector).rule.id + sufConnection + atRule.params;
                    }
                    rule.eachDecl(function (decl) {
                        decl.before = "\n  "
                        decl.after = "\n  "
                    })
                    rule.after = "\n  "
                    newRules.push(rule)
                })

            }
            atRule.removeSelf()
        })
        css.append(newRules)
    }
}

function isClassSelector (selector) {
    if (selectorParser.parse(selector).rule.classNames) return true
}

function isIdSelector (selector) {
    if (selectorParser.parse(selector).rule.id) return true
}
<|endoftext|>


<commit_before>'use strict';

/**
 * Assigns transport to the client pipeline
*/
function Trooba() {
    this._handlers = [];
}

Trooba.prototype = {
    transport: function transport(transport, config) {
        if (typeof transport === 'string') {
            transport = require(transport);
        }
        this._transport = {
            handler: transport,
            config: config
        };
        if (transport.api) {
            this._api = transport.api;
        }
        return this;
    },

    use: function use(handler, config) {
        if (typeof handler === 'string') {
            handler = require(handler);
        }
        this._handlers.unshift({
            handler: handler,
            config: config
        });
        this._pipe = undefined;
        return this;
    },

    /**
    * If config parameters is provided, then we assume api to be an API wrapper factory,
    * otherwise it is considered as an instance of API wrapper
    */
    interface: function interface$(api, config) {
        this._api = {
            handler: api,
            config: config
        };
        return this;
    },

    create: function create(context) {
        var self = this;

        var pipe = this._pipe = this._pipe || buildPipe(
            this._handlers,
            // allow lazy transport binding via request context
            createPipePoint(function injectTransport(pipe) {
                var tr = pipe.context.transport || self._transport;
                if (!tr) {
                    throw new Error('Transport is not provided');
                }
                tr.handler ?
                    tr.handler(pipe, tr.config) :
                    tr(pipe);
            }
        ));

        if (this._api) {
            pipe = context ? pipe.create(context) : pipe;
            var pipeApi = {
                create: function create(context) {
                    return pipe.create(context);
                }
            };
            return this._api.handler ? this._api.handler(pipeApi, this._api.config) :
                this._api(pipeApi);
        }

        return pipe.create(context || {});
    }
};

module.exports.transport = function createWithTransport(transport, config) {
    var trooba = new Trooba();
    return trooba.transport(transport, config);
};

module.exports.use = function createWithHandler(handler, config) {
    var trooba = new Trooba();
    return trooba.use(handler, config);
};

module.exports.interface = function createWithInterface(api, config) {
    var trooba = new Trooba();
    return trooba.interface(api, config);
};

/**
   The pipe API signature is
    pipe.on()
        .context()
        .request()
        .end()

*/
function buildPipe(handlers, target) {
    var pipe = handlers.reduce(function reduce(next, handlerMeta) {
        return createPipePoint(handlerMeta, next);
    }, target);

    return createPipePoint(function startPipe(pipe) {}, pipe);
}
module.exports.buildPipe = buildPipe;

function createPipePoint(handler, next) {
    var point = new PipePoint(handler);
    point.next = next;
    if (next) {
        next.prev = point;
    }
    return point;
}

module.exports.createPipePoint = createPipePoint;

var Types = {
    REQUEST: 1,
    RESPONSE: 2
};
module.exports.Type = Types;

/*
* Channel point forms a linked list node
*/
function PipePoint(handler) {
    this._messageHandlers = {};
    this.handler = handler;
    if (typeof handler !== 'function') {
        this.handler = handler.handler;
        this.config = handler.config;
    }
    // build a unique identifer for every new instance of point
    // we do not anticipate creates of so many within one pipe to create conflicts
    PipePoint.instanceCounter = PipePoint.instanceCounter ? PipePoint.instanceCounter : 0;
    this._id = PipePoint.instanceCounter++;
}

PipePoint.prototype = {
    send: function send(message) {
        // pick the direction
        var nextPoint = message.flow === Types.REQUEST ?
            this.next : this.prev;

        if (nextPoint) {
            if (!this.context) {
                throw new Error('Context is missing, make sure context() is used first');
            }
            // attach context to the message to keep context flow
            // check processing step to see where context goes
            message.context = this.context;
            // forward message down the pipe
            nextPoint.process(message);
        }
        else if (message.type === 'error') {
            throw message.ref;
        }

        return this;
    },

    process: function process(message) {
        // IMPORTANT: This should always be the first to propagate context
        // create point bound to current message and assign the context
        var point = Object.create(this);
        point.context = message.context;

        // context propagation is sync and
        // init all points in the pipeline
        if (message.type === 'context') {
            // allow hooks to happen
            point.handler(point, point.config);
        }
        else {
            // handle the hooks
            var messageHandlers = point.handlers();
            var processMessage = messageHandlers[message.type];
            if (processMessage) {
                // if sync delivery, than no callback needed before propagation further
                processMessage(message.ref, message.sync ? undefined : onComplete);
                if (!message.sync) {
                    // on complete has continued the flow
                    return;
                }
            }
            else if (processEndEvent()) {
                return;
            }
        }

        point.send(message);

        function onComplete(ref) {
            if (arguments.length) {
                message.ref = ref;
            }
            // special case for stream
            if (processEndEvent()) {
                return;
            }
            point.send(message);
        }

        function processEndEvent() {
            if ((message.type === 'response:data' ||
                message.type === 'request:data') && message.ref === undefined) {

                var endHandler = messageHandlers[
                    message.flow === Types.REQUEST ? 'request:end' : 'response:end'];
                if (endHandler) {
                    endHandler(function onComplete() {
                        point.send(message);
                    });
                    return true;
                }
            }
        }
    },

    /*
    * context method is sync methods that runs through all handlers
    * to allow them to hook to events they are interested in
    * The context will be attached to every message and bound to pipe (Object.create is pretty fast) at the time of
    * processing by different points to preserve the context
    */
    create: function create$(context) {
        context = context || {};

        if (this.context) {
            // inherit from existing context if any
            var self = this;
            Object.keys(this.context).forEach(function forEach(name) {
                if (name.charAt(0) !== '$' && !context[name]) {
                    context[name] = self.context[name];
                }
            });
        }

        // do not inherit message handles from previous context
        context.$points = undefined;

        // bind context to the point and return it
        var contextualPoint = Object.create(this);
        contextualPoint.context = context;
        contextualPoint.send({
            type: 'context',
            flow: Types.REQUEST,
            ref: context
        });
        return contextualPoint;
    },

    throw: function throw$(err) {
        this.send({
            type: 'error',
            flow: Types.RESPONSE,
            ref: err
        });
    },

    streamRequest: function streamRequest$(request) {
        this.context.$requestStream = true;
        var point = this.request(request);
        return createWriteStream({
            channel: point,
            flow: Types.REQUEST
        });
    },

    request: function request$(request, callback) {
        var point = this;
        if (!point.context) {
            // create default context
            point = point.create({});
        }

        function sendRequest() {
            point.send({
                type: 'request',
                flow: Types.REQUEST,
                ref: request
            });
        }

        if (callback) {
            point
            .on('error', callback)
            .on('response', function (res) { callback(null, res); });

            sendRequest();
            return point;
        }

        this.context.$requestStream ? sendRequest() : setTimeout(sendRequest, 0);

        return point;
    },

    respond: function respond$(response) {
        this.send({
            type: 'response',
            flow: Types.RESPONSE,
            ref: response
        });

        return this;
    },

    streamResponse: function streamResponse$(response) {
        this.context.$responseStream = true;
        var point = this.respond(response);

        return createWriteStream({
            channel: point,
            flow: Types.RESPONSE
        });
    },

    /*
    * Message handlers will be attached to specific context and mapped to a specific point by its _id
    * This is need to avoid re-creating pipe for every new context
    */
    on: function onEvent$(type, handler) {
        var handlers = this.handlers();
        if (handlers[type]) {
            throw new Error('The hook has already been registered, you can use only one hook for specific event type: ' + type);
        }
        handlers[type] = handler;
        return this;
    },

    once: function onceEvent$(type, handler) {
        var self = this;
        this.on(type, function onceFn() {
            delete self.handlers()[type];
            handler.apply(null, arguments);
        });
        return this;
    },

    handlers: function handlers() {
        var ctx = this.context;
        if (!ctx) {
            throw new Error('Context is missing, please make sure context() is used first');
        }
        ctx = ctx.$points = ctx.$points || {};
        ctx = ctx[this._id] = ctx[this._id] || {};
        ctx._messageHandlers = ctx._messageHandlers || {};
        return ctx._messageHandlers;
    }
};

function createWriteStream(ctx) {
    var type = ctx.flow === Types.REQUEST ? 'request:data' : 'response:data';
    var channel = ctx.channel;

    function _write(data) {
        if (channel._streamClosed) {
            throw new Error('The stream has been closed already');
        }

        if (data === undefined) {
            ctx.channel._streamClosed = true;
        }

        channel.send({
            type: type,
            flow: ctx.flow,
            ref: data
        });
    }

    return {
        write: function write$(data) {
            _write(data);
            return this;
        },

        end: function end$() {
            _write();
            return channel;
        }
    };
}
<commit_msg>replaced Object.create with native clone<commit_after>'use strict';

/**
 * Assigns transport to the client pipeline
*/
function Trooba() {
    this._handlers = [];
}

Trooba.prototype = {
    transport: function transport(transport, config) {
        if (typeof transport === 'string') {
            transport = require(transport);
        }
        this._transport = {
            handler: transport,
            config: config
        };
        if (transport.api) {
            this._api = transport.api;
        }
        return this;
    },

    use: function use(handler, config) {
        if (typeof handler === 'string') {
            handler = require(handler);
        }
        this._handlers.unshift({
            handler: handler,
            config: config
        });
        this._pipe = undefined;
        return this;
    },

    /**
    * If config parameters is provided, then we assume api to be an API wrapper factory,
    * otherwise it is considered as an instance of API wrapper
    */
    interface: function interface$(api, config) {
        this._api = {
            handler: api,
            config: config
        };
        return this;
    },

    create: function create(context) {
        var self = this;

        var pipe = this._pipe = this._pipe || buildPipe(
            this._handlers,
            // allow lazy transport binding via request context
            createPipePoint(function injectTransport(pipe) {
                var tr = pipe.context.transport || self._transport;
                if (!tr) {
                    throw new Error('Transport is not provided');
                }
                tr.handler ?
                    tr.handler(pipe, tr.config) :
                    tr(pipe);
            }
        ));

        if (this._api) {
            pipe = context ? pipe.create(context) : pipe;
            var pipeApi = {
                create: function create(context) {
                    return pipe.create(context);
                }
            };
            return this._api.handler ? this._api.handler(pipeApi, this._api.config) :
                this._api(pipeApi);
        }

        return pipe.create(context || {});
    }
};

module.exports.transport = function createWithTransport(transport, config) {
    var trooba = new Trooba();
    return trooba.transport(transport, config);
};

module.exports.use = function createWithHandler(handler, config) {
    var trooba = new Trooba();
    return trooba.use(handler, config);
};

module.exports.interface = function createWithInterface(api, config) {
    var trooba = new Trooba();
    return trooba.interface(api, config);
};

/**
   The pipe API signature is
    pipe.on()
        .context()
        .request()
        .end()

*/
function buildPipe(handlers, target) {
    var pipe = handlers.reduce(function reduce(next, handlerMeta) {
        return createPipePoint(handlerMeta, next);
    }, target);

    return createPipePoint(function startPipe(pipe) {}, pipe);
}
module.exports.buildPipe = buildPipe;

function createPipePoint(handler, next) {
    var point = new PipePoint(handler);
    point.next = next;
    if (next) {
        next.prev = point;
    }
    return point;
}

module.exports.createPipePoint = createPipePoint;

var Types = {
    REQUEST: 1,
    RESPONSE: 2
};
module.exports.Type = Types;

/*
* Channel point forms a linked list node
*/
function PipePoint(handler) {
    this._messageHandlers = {};
    this.handler = handler;
    if (handler && typeof handler !== 'function') {
        this.handler = handler.handler;
        this.config = handler.config;
    }
    // build a unique identifer for every new instance of point
    // we do not anticipate creates of so many within one pipe to create conflicts
    PipePoint.instanceCounter = PipePoint.instanceCounter ? PipePoint.instanceCounter : 0;
    this._id = PipePoint.instanceCounter++;
}

module.exports.PipePoint = PipePoint;

PipePoint.prototype = {
    send: function send(message) {
        // pick the direction
        var nextPoint = message.flow === Types.REQUEST ?
            this.next : this.prev;

        if (nextPoint) {
            if (!this.context) {
                throw new Error('Context is missing, make sure context() is used first');
            }
            // attach context to the message to keep context flow
            // check processing step to see where context goes
            message.context = this.context;
            // forward message down the pipe
            nextPoint.process(message);
        }
        else if (message.type === 'error') {
            throw message.ref;
        }

        return this;
    },

    clone: function clone() {
        var ret = new PipePoint();
        ret.next = this.next;
        ret.prev = this.prev;
        ret._id = this._id;
        ret._messageHandlers = this._messageHandlers;
        ret.config = this.config;
        ret.handler = this.handler;
        return ret;
    },

    process: function process(message) {
        // IMPORTANT: This should always be the first to propagate context
        // create point bound to current message and assign the context
        var point = this.clone(); // this clone is 5 times faster then Object.create
        point.context = message.context;

        // context propagation is sync and
        // init all points in the pipeline
        if (message.type === 'context') {
            // allow hooks to happen
            point.handler(point, point.config);
        }
        else {
            // handle the hooks
            var messageHandlers = point.handlers();
            var processMessage = messageHandlers[message.type];
            if (processMessage) {
                // if sync delivery, than no callback needed before propagation further
                processMessage(message.ref, message.sync ? undefined : onComplete);
                if (!message.sync) {
                    // on complete has continued the flow
                    return;
                }
            }
            else if (processEndEvent()) {
                return;
            }
        }

        point.send(message);

        function onComplete(ref) {
            if (arguments.length) {
                message.ref = ref;
            }
            // special case for stream
            if (processEndEvent()) {
                return;
            }
            point.send(message);
        }

        function processEndEvent() {
            if ((message.type === 'response:data' ||
                message.type === 'request:data') && message.ref === undefined) {

                var endHandler = messageHandlers[
                    message.flow === Types.REQUEST ? 'request:end' : 'response:end'];
                if (endHandler) {
                    endHandler(function onComplete() {
                        point.send(message);
                    });
                    return true;
                }
            }
        }
    },

    /*
    * context method is sync methods that runs through all handlers
    * to allow them to hook to events they are interested in
    * The context will be attached to every message and bound to pipe (Object.create is pretty fast) at the time of
    * processing by different points to preserve the context
    */
    create: function create$(context) {
        context = context || {};

        if (this.context) {
            // inherit from existing context if any
            var self = this;
            Object.keys(this.context).forEach(function forEach(name) {
                if (name.charAt(0) !== '$' && !context[name]) {
                    context[name] = self.context[name];
                }
            });
        }

        // do not inherit message handles from previous context
        context.$points = undefined;

        // bind context to the point and return it
        var contextualPoint = Object.create(this);
        contextualPoint.context = context;
        contextualPoint.send({
            type: 'context',
            flow: Types.REQUEST,
            ref: context
        });
        return contextualPoint;
    },

    throw: function throw$(err) {
        this.send({
            type: 'error',
            flow: Types.RESPONSE,
            ref: err
        });
    },

    streamRequest: function streamRequest$(request) {
        this.context.$requestStream = true;
        var point = this.request(request);
        return createWriteStream({
            channel: point,
            flow: Types.REQUEST
        });
    },

    request: function request$(request, callback) {
        var point = this;
        if (!point.context) {
            // create default context
            point = point.create({});
        }

        function sendRequest() {
            point.send({
                type: 'request',
                flow: Types.REQUEST,
                ref: request
            });
        }

        if (callback) {
            point
            .on('error', callback)
            .on('response', function (res) { callback(null, res); });

            sendRequest();
            return point;
        }

        this.context.$requestStream ? sendRequest() : setTimeout(sendRequest, 0);

        return point;
    },

    respond: function respond$(response) {
        this.send({
            type: 'response',
            flow: Types.RESPONSE,
            ref: response
        });

        return this;
    },

    streamResponse: function streamResponse$(response) {
        this.context.$responseStream = true;
        var point = this.respond(response);

        return createWriteStream({
            channel: point,
            flow: Types.RESPONSE
        });
    },

    /*
    * Message handlers will be attached to specific context and mapped to a specific point by its _id
    * This is need to avoid re-creating pipe for every new context
    */
    on: function onEvent$(type, handler) {
        var handlers = this.handlers();
        if (handlers[type]) {
            throw new Error('The hook has already been registered, you can use only one hook for specific event type: ' + type);
        }
        handlers[type] = handler;
        return this;
    },

    once: function onceEvent$(type, handler) {
        var self = this;
        this.on(type, function onceFn() {
            delete self.handlers()[type];
            handler.apply(null, arguments);
        });
        return this;
    },

    handlers: function handlers() {
        var ctx = this.context;
        if (!ctx) {
            throw new Error('Context is missing, please make sure context() is used first');
        }
        ctx = ctx.$points = ctx.$points || {};
        ctx = ctx[this._id] = ctx[this._id] || {};
        ctx._messageHandlers = ctx._messageHandlers || {};
        return ctx._messageHandlers;
    }
};

function createWriteStream(ctx) {
    var type = ctx.flow === Types.REQUEST ? 'request:data' : 'response:data';
    var channel = ctx.channel;

    function _write(data) {
        if (channel._streamClosed) {
            throw new Error('The stream has been closed already');
        }

        if (data === undefined) {
            ctx.channel._streamClosed = true;
        }

        channel.send({
            type: type,
            flow: ctx.flow,
            ref: data
        });
    }

    return {
        write: function write$(data) {
            _write(data);
            return this;
        },

        end: function end$() {
            _write();
            return channel;
        }
    };
}
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var sass = require('node-sass');
var mime = require('mime');
var replaceall = require('replaceall');

var inlineImage = function(filepath, replace, done) {
  var mimeType = mime.lookup(filepath);
  if (mimeType !== 'image/svg+xml') {
    throw new Error('File ' + filepath + ' is not of type image/svg+xml.');
  } else {
    var data = fs.readFileSync(filepath); /* TODO error handling of fs.readFileSync? */
    if (!data || !data.length) {
      throw new Error('File ' + filepath + ' is empty or cannot be read')
    }
    var result = data.toString('utf8');
    if (replace.getLength()) {
      for (var i = 0; i < replace.getLength(); i++) {
        result = replaceall(replace.getKey(i).getValue(), replace.getValue(i).getValue(), result);
      }
    }
    done(result);
  }
}

module.exports = function() {
  return {
    'inline-svg($filename, $replace: ())': function(filename, replace, done) {
      inlineImage(filename.getValue(), replace, function(dataUrl) {
        var encodedUrl = encodeURIComponent(dataUrl);
        done(new sass.types.String('url(\'data:image/svg+xml;charset=utf-8,' + encodedUrl + '\')'));
      });
    }
  }
}
<commit_msg>remove comment<commit_after>var fs = require('fs');
var path = require('path');
var sass = require('node-sass');
var mime = require('mime');
var replaceall = require('replaceall');

var inlineImage = function(filepath, replace, done) {
  var mimeType = mime.lookup(filepath);
  if (mimeType !== 'image/svg+xml') {
    throw new Error('File ' + filepath + ' is not of type image/svg+xml.');
  } else {
    var data = fs.readFileSync(filepath);
    if (!data || !data.length) {
      throw new Error('File ' + filepath + ' is empty or cannot be read')
    }
    var result = data.toString('utf8');
    if (replace.getLength()) {
      for (var i = 0; i < replace.getLength(); i++) {
        result = replaceall(replace.getKey(i).getValue(), replace.getValue(i).getValue(), result);
      }
    }
    done(result);
  }
}

module.exports = function() {
  return {
    'inline-svg($filename, $replace: ())': function(filename, replace, done) {
      inlineImage(filename.getValue(), replace, function(dataUrl) {
        var encodedUrl = encodeURIComponent(dataUrl);
        done(new sass.types.String('url(\'data:image/svg+xml;charset=utf-8,' + encodedUrl + '\')'));
      });
    }
  }
}
<|endoftext|>


<commit_before>var isojs = require('isojs');
var express = require('express');
var mongoose = require('mongoose');

//var routes = require('./js/Routes.js');
var blog = require('./blog/app.js');

var app = express();

// Loading Database:
//var db = mongoose.connect('mongodb://localhost/isojs-demo');

app.set('port', (process.env.PORT || 5000));

app.listen(app.get('port'), function() {
	console.log("STARTED SERVER! PORT: ", app.get('port'));
});

app.use(function(req, res, next) {
	res.header("Access-Control-Allow-Origin", "*");
	next();
});

app.use('/js', express.static('./client/js'));
app.use('/css', express.static('./client/css'));
app.use('/font', express.static('./client/font'));
app.use('/img', express.static('./client/img'));
app.use('/favicon.ico', express.static('./client/img/favicon.ico'));

app.use('/blog', blog());

var config = {
	routesPath: 'client/js/Routes.js',
	getApiServerAddress: function() {
		return 'http://localhost:' + app.get('port') + '/';
	},
	uglify: true, // Switch this to false for easier client side debugging
	debug: true,
	head: '<title>isoJS</title><link href="http://fonts.googleapis.com/css?family=Dosis" rel="stylesheet" type="text/css"><link rel="stylesheet" href="/css/app.css"/>'
};

isojs.checkLocation.setServer();
var isoJSapp = isojs.appBuilder(config);

app.use(isoJSapp());
<commit_msg>HTTPS change<commit_after>var isojs = require('isojs');
var express = require('express');
var mongoose = require('mongoose');

//var routes = require('./js/Routes.js');
var blog = require('./blog/app.js');

var app = express();

// Loading Database:
//var db = mongoose.connect('mongodb://localhost/isojs-demo');

app.set('port', (process.env.PORT || 5000));

app.listen(app.get('port'), function() {
	console.log("STARTED SERVER! PORT: ", app.get('port'));
});

app.use(function(req, res, next) {
	res.header("Access-Control-Allow-Origin", "*");
	next();
});

app.use('/js', express.static('./client/js'));
app.use('/css', express.static('./client/css'));
app.use('/font', express.static('./client/font'));
app.use('/img', express.static('./client/img'));
app.use('/favicon.ico', express.static('./client/img/favicon.ico'));

app.use('/blog', blog());

var config = {
	routesPath: 'client/js/Routes.js',
	getApiServerAddress: function() {
		return 'http://localhost:' + app.get('port') + '/';
	},
	uglify: true, // Switch this to false for easier client side debugging
	debug: true,
	head: '<title>isoJS</title><link href="https://fonts.googleapis.com/css?family=Dosis" rel="stylesheet" type="text/css"><link rel="stylesheet" href="/css/app.css"/>'
};

isojs.checkLocation.setServer();
var isoJSapp = isojs.appBuilder(config);

app.use(isoJSapp());
<|endoftext|>


<commit_before>/**
 * RenRenChe JavaScript style guide
 */

module.exports = {
  extends: 'airbnb-base',
  globals: {
    RRC: true,
    _gaq: true,
    _hmt: true,
    _rls: true,
    _fxcmd: true,
    requirejs: true,
    casper: true,
    patchRequire: true,
    md5: true,
    FastClick: true,
    phantom: true,
    sinon: true,
    __DEVELOPMENT__: true,
  },
  env: {
    browser: true,
    node: true,
    es6: true,
    amd: true,
    mocha: true,
    jasmine: true,
    jquery: true,
  },
  rules: {
    indent: ['error', 4, { SwitchCase: 1 }], // 缩进
    'max-len': ['error', { code: 240, tabWidth: 4, ignoreUrls: true, ignoreComments: false }],
    camelcase: 'off', // 不强制使用 camel case 命名
    'consistent-return': 'off', // 不强制 return
    'global-require': 'off', // 不强制全局 require
    'newline-per-chained-call': 'off', // 不强制链接操作另起一行
    'no-underscore-dangle': 'off', // 不禁止使用下划线作为变量名前缀
    'comma-dangle': 'off', // 不强制尾逗号
    'no-console': 'off', // 不禁用 console
    'prefer-arrow-callback': 'off', // 不强制使用箭头函数
    'import/no-amd': 'off', // 不禁用 amd
    'func-names': 'off', // 不强制函数表达式有函数名
    'guard-for-in': 'off',
    'no-param-reassign': 'off',
    'no-restricted-syntax': [2, 'DebuggerStatement', 'LabeledStatement', 'WithStatement'], // 不禁止 for in 循环
    'arrow-parens': 'off',
    'padded-blocks': 'off',
    'no-plusplus': 'off',
    'no-mixed-operators': 'off',
    'no-danger-with-children': 'off',
    'padded-blocks': 'off',
    'class-methods-use-this': 'off',
    'import/newline-after-import': 'off',
    'import/no-dynamic-require': 'off',
    'import/no-extraneous-dependencies': 'off',
    'import/prefer-default-export': 'off',
  }
}
<commit_msg>Add comment, and add some rules<commit_after>/**
 * RenRenChe JavaScript style guide
 */

module.exports = {
  extends: 'airbnb-base',
  globals: {
    RRC: true,
    _gaq: true,
    _hmt: true,
    _rls: true,
    _fxcmd: true,
    requirejs: true,
    casper: true,
    patchRequire: true,
    md5: true,
    FastClick: true,
    phantom: true,
    sinon: true,
    __DEVELOPMENT__: true,
  },
  env: {
    browser: true,
    node: true,
    es6: true,
    amd: true,
    mocha: true,
    jasmine: true,
    jquery: true,
  },
  rules: {
    // 缩进
    indent: ['error', 4, { SwitchCase: 1 }],

    // 代码长度
    'max-len': ['error', {
      code: 240,
      tabWidth: 4,
      ignoreUrls: true,
      ignoreComments: false,
    }],

    // 不强制使用 camel case 命名
    camelcase: 'off',

    // 不强制 return
    'consistent-return': 'off',

    // 不强制全局 require
    'global-require': 'off',

    // 不强制链接操作另起一行
    'newline-per-chained-call': 'off',

    // 不强制尾逗号
    'no-underscore-dangle': 'off',
    'comma-dangle': 'off',

    // 不禁用 console
    'no-console': 'off',

    // 不禁用 console
    'prefer-arrow-callback': 'off',

    // 不禁用 amd
    'import/no-amd': 'off',

    // 不强制函数表达式有函数名
    'func-names': 'off',

    // for in 不强制检查 hasOwnProperty
    'guard-for-in': 'off',

    // 不禁止函数参数重新赋值
    'no-param-reassign': 'off',

    // 不禁止 for in 循环
    'no-restricted-syntax': [2, 'DebuggerStatement', 'LabeledStatement', 'WithStatement'],

    // 不禁止 ++ 操作符
    'no-plusplus': 'off',

    // 不强制 class 方法使用 this
    'class-methods-use-this': 'off',

    // 不禁止 require 变量
    'import/no-dynamic-require': 'off',

    // 不禁止 require devDependencies 中的包
    'import/no-extraneous-dependencies': ['error', {
      devDependencies: true,
      optionalDependencies: false,
    }],

    // 不强制 export default（只 export 一次）
    'import/prefer-default-export': 'off',
  },
};
<|endoftext|>


<commit_before>module.exports = babelPluginTransformReactEs6ClassDisplayName;

function babelPluginTransformReactEs6ClassDisplayName (babel) {
  var t = babel.types.t;
  return {
    visitor: {
      ClassDeclaration: function (path) {
        addDisplayName.call(path, t);
      }
    }
  };
}

function addDisplayName (t) {
  if (this.node.superClass.property.name === 'Component') {
    this.insertAfter([
      t.expressionStatement(t.assignmentExpression(
        '=',
        t.memberExpression(this.node.id, t.identifier('displayName')),
        t.stringLiteral(this.node.id.name)
      ))
    ]);
  }
}
<commit_msg>Fix types access<commit_after>module.exports = babelPluginTransformReactEs6ClassDisplayName;

function babelPluginTransformReactEs6ClassDisplayName (babel) {
  return {
    visitor: {
      ClassDeclaration: function (path) {
        addDisplayName.call(path, babel.types);
      }
    }
  };
}

function addDisplayName (t) {
  if (this.node.superClass.property.name === 'Component') {
    this.insertAfter([
      t.expressionStatement(t.assignmentExpression(
        '=',
        t.memberExpression(this.node.id, t.identifier('displayName')),
        t.stringLiteral(this.node.id.name)
      ))
    ]);
  }
}
<|endoftext|>


<commit_before>require('reapp-ui');
require('reapp-object-assign')

var React = require('react');
var Components = require('reapp-ui/all');
var shouldupdate = require('omniscient/shouldupdate');

// component
class Component extends React.Component {
  componentWillMount() {
    this.actions = this.context.actions;
    this.store = this.context.store;
    this.router = this.context.router;
  }

  shouldComponentUpdate(nextProps, nextState) {
    return shouldupdate.call(this, nextProps, nextState);
  }
}

Component.contextTypes = {
  theme: React.PropTypes.object,
  animations: React.PropTypes.object,
  router: React.PropTypes.func,
  store: React.PropTypes.func,
  actions: React.PropTypes.object
}

// router
var generator = require('reapp-routes/react-router/generator');
var render = require('reapp-routes/react-router/render');
var RoutedViewListMixin = require('reapp-routes/react-router/RoutedViewListMixin');
var ParentRouteMixin = require('reapp-routes/react-router/ParentRouteMixin');

// desktop touch demo
if (window.location.hash && window.location.hash.match(/_desktopTouch/))
  require('reapp-ui/lib/desktopTouch');

// inappbrowser
if (window.cordova && window.cordova.InAppBrowser)
  window.open = window.cordova.InAppBrowser.open;

var Theme = require('reapp-ui/helpers/Theme');

var statics = Object.assign(
  Components,
  {
    // react
    React: React,

    // component
    Component: Component,

    Reapp: function(opts, Component) {
      return React.createClass({
        mixins: [
          RoutedViewListMixin
        ],

        childContextTypes: {
          theme: React.PropTypes.object,
          animations: React.PropTypes.object,
          store: React.PropTypes.func,
          actions: React.PropTypes.object
        },

        getChildContext() {
          return opts;
        },

        // store refresh
        componentWillMount: function() {
          this.forceUpdater = function() {
            this.forceUpdate();
          }.bind(this);

          if (opts.store)
            opts.store.listen(this.forceUpdater);
        },
        componentWillUnmount: function() {
          if (opts.store)
            opts.store.unlisten(this.forceUpdater);
        },

        render: function() {
          const { children, theme, ...props } = this.props;

          const viewList =
            <Components.ViewList {...this.props.viewListProps}>
              {children}
            </Components.ViewList>

          const themedChildren = theme ?
            <Theme {...theme}>{viewList}</Theme> : viewList;

          return (
            <Component
              child={this.hasChildRoute() && this.createChildRouteHandler}
              viewListProps={this.routedViewListProps()}
            />
          )
        }
      })
    },

    // router
    router: function(require, routes) {
      return render.async(generator.routes(require, routes), {})
    },
    route: generator.route
  }
);

module.exports = statics;<commit_msg>use animating on shouldupdate<commit_after>require('reapp-ui');
require('reapp-object-assign')

var React = require('react');
var Components = require('reapp-ui/all');
var shouldupdate = require('omniscient/shouldupdate');
var Animated = require('reapp-ui/mixins/Animated');

// component
class Component extends React.Component {
  componentWillMount() {
    this.actions = this.context.actions;
    this.store = this.context.store;
    this.router = this.context.router;
  }

  shouldComponentUpdate(nextProps, nextState) {
    const isAnimating = this.context.animations['viewList'].step % 1 !== 0;
    return isAnimating || shouldupdate.call(this, nextProps, nextState);
  }
}

Component.contextTypes = {
  theme: React.PropTypes.object,
  animations: React.PropTypes.object,
  router: React.PropTypes.func,
  store: React.PropTypes.func,
  actions: React.PropTypes.object
}

// router
var generator = require('reapp-routes/react-router/generator');
var render = require('reapp-routes/react-router/render');
var RoutedViewListMixin = require('reapp-routes/react-router/RoutedViewListMixin');
var ParentRouteMixin = require('reapp-routes/react-router/ParentRouteMixin');

// desktop touch demo
if (window.location.hash && window.location.hash.match(/_desktopTouch/))
  require('reapp-ui/lib/desktopTouch');

// inappbrowser
if (window.cordova && window.cordova.InAppBrowser)
  window.open = window.cordova.InAppBrowser.open;

var Theme = require('reapp-ui/helpers/Theme');

var statics = Object.assign(
  Components,
  {
    // react
    React: React,

    // component
    Component: Component,

    Reapp: function(opts, Component) {
      return React.createClass({
        mixins: [
          RoutedViewListMixin
        ],

        childContextTypes: {
          theme: React.PropTypes.object,
          animations: React.PropTypes.object,
          store: React.PropTypes.func,
          actions: React.PropTypes.object
        },

        getChildContext() {
          return opts;
        },

        // store refresh
        componentWillMount: function() {
          this.forceUpdater = function() {
            this.forceUpdate();
          }.bind(this);

          if (opts.store)
            opts.store.listen(this.forceUpdater);
        },
        componentWillUnmount: function() {
          if (opts.store)
            opts.store.unlisten(this.forceUpdater);
        },

        render: function() {
          const { children, theme, ...props } = this.props;

          const viewList =
            <Components.ViewList {...this.props.viewListProps}>
              {children}
            </Components.ViewList>

          const themedChildren = theme ?
            <Theme {...theme}>{viewList}</Theme> : viewList;

          return (
            <Component
              child={this.hasChildRoute() && this.createChildRouteHandler}
              viewListProps={this.routedViewListProps()}
            />
          )
        }
      })
    },

    // router
    router: function(require, routes) {
      return render.async(generator.routes(require, routes), {})
    },
    route: generator.route
  }
);

module.exports = statics;<|endoftext|>


<commit_before>var os = require('os')
var path = require('path')
var homedir = require('os-homedir')

function linux (id) {
  return path.join(homedir(), '.cache', id)
}

function darwin (id) {
  return path.join(homedir(), 'Library', 'Caches', id)
}

function win32 (id) {
  var appData = process.env.LOCALAPPDATA || path.join(homedir(), 'AppData', 'Local')
  return path.join(appData, id, 'Cache')
}

var implementation = (function () {
  switch (os.platform()) {
    case 'linux': return linux
    case 'darwin': return darwin
    case 'win32': return win32
    default: throw new Error('Your OS is currently not supported by node-cachedir.')
  }
}())

module.exports = function (id) {
  if (typeof id !== 'string') {
    throw new TypeError('id is not a string')
  }
  if (id.length === 0) {
    throw new Error('id cannot be empty')
  }
  if (/[^0-9a-zA-Z-]/.test(id)) {
    throw new Error('id cannot contain special characters')
  }

  return implementation(id)
}
<commit_msg>🐛 Respect XDG_CACHE_HOME<commit_after>var os = require('os')
var path = require('path')
var homedir = require('os-homedir')

function linux (id) {
  var cacheHome = process.env.XDG_CACHE_HOME || path.join(homedir(), '.cache')
  return path.join(cacheHome, id)
}

function darwin (id) {
  return path.join(homedir(), 'Library', 'Caches', id)
}

function win32 (id) {
  var appData = process.env.LOCALAPPDATA || path.join(homedir(), 'AppData', 'Local')
  return path.join(appData, id, 'Cache')
}

var implementation = (function () {
  switch (os.platform()) {
    case 'linux': return linux
    case 'darwin': return darwin
    case 'win32': return win32
    default: throw new Error('Your OS is currently not supported by node-cachedir.')
  }
}())

module.exports = function (id) {
  if (typeof id !== 'string') {
    throw new TypeError('id is not a string')
  }
  if (id.length === 0) {
    throw new Error('id cannot be empty')
  }
  if (/[^0-9a-zA-Z-]/.test(id)) {
    throw new Error('id cannot contain special characters')
  }

  return implementation(id)
}
<|endoftext|>


<commit_before>
var express = require('express');
var app = express();
var fs = require('fs');
var isoBmff = require('iso-bmff');
var _ = require('lodash')

// some defaults for this media
var setup  = {
	video: {
		chunks: 119,
		length: 2910720
	},
	audio: {
		chunks: 114,
		length: 10039296
	}
}

function getChunk(request, response) {

	var segment = request.params.segment;
	var segmentId = segment.match(/(\d+)/)[0];
	var segmentType = /video/.test(segment) ? 'video' : 'audio';

	console.log('chunk request', segmentType, segmentId);

	var loopCount = Math.floor(segmentId / setup[segmentType].chunks);
	var currentSegment = segmentId % setup[segmentType].chunks;

	var chunkFile = './media/'  + segment.replace(/(\d+)/, '') + currentSegment +'.m4s';

	var chunkStream = fs.createReadStream(chunkFile, {
		flags: 'r',
		encoding: null,
		fd: null,
		mode: 0666,
		autoClose: true
	});

	chunkStream.on('error', function () {
		response.sendStatus(404);
	});

	var unboxing = new isoBmff.Parser(function (err, data) {
		if (err) {
			return response.sendStatus(500);
		}

		var newBaseTime = setup[segmentType].length * loopCount;

		data.forEach(function (d) {

			if (d.type == 'sidx') {
				d.content.earliestPresentationTime += newBaseTime;
			}

			if (d.type == 'moof') {
				d.content.forEach(function (m) {
					if (m.type == 'traf') {
						m.content.forEach(function (t) {
							if (t.type == 'tfdt') {
								console.log('chunk request', segmentType, segmentId, 'tfdt');
								t.content.baseMediaDecodeTime += newBaseTime;
							}
						});
					}
				});
			}
		});

		var build = new isoBmff.Builder(data, function (err, chunk) {
			response.set('Access-Control-Allow-Origin', '*');
			response.type(segmentType + '/mp4');
			response.send(chunk);

			unboxing = null;
			build = null

		});
		return data;

	});

	chunkStream
		.pipe(unboxing);
}

function getInit (request, response) {

	var segment = request.params.segment;
	var segmentType = /video/.test(segment) ? 'video' : 'audio';

	console.log('init segment request', segment );

	response.set('Access-Control-Allow-Origin', '*');
	response.type(segmentType + '/mp4');
	responseFileStream('./media/chick-' + segmentType + '_dashinit.mp4', response);

}

function getMpd (request, response) {

	console.log('MPD request' );

	response.set('Access-Control-Allow-Origin', '*');
	response.type('application/xml');
	responseFileStream('./chick.mpd', response)

}

function responseFileStream (file, response) {

	var fileStream = fs.createReadStream(file, {
		flags: 'r',
		encoding: null,
		fd: null,
		mode: 0666,
		autoClose: true
	});

	fileStream.on('error', function () {
		response.sendStatus(404);
	});

	fileStream.pipe(response)

}

app.get('/', function (req, res) {
	res.send('Hello World!')
})

app.get('/chunk/:segment.m4s', getChunk);
app.get('/init/:segment.mp4', getInit);
app.get('/chick.mpd', getMpd);

var server = app.listen(3000, function () {
	var host = server.address().address;
	var port = server.address().port;
	console.log('Example app listening at http://%s:%s', host, port)
});<commit_msg>fixes<commit_after>
var express = require('express');
var app = express();
var fs = require('fs');
var isoBmff = require('iso-bmff');
var _ = require('lodash')

// some defaults for this media
var setup  = {
	video: {
		chunks: 119,
		length: 2910720
	},
	audio: {
		chunks: 114,
		length: 10039296
	}
}

function getChunk(request, response) {

	var segment = request.params.segment;
	var segmentId = segment.match(/(\d+)/)[0];
	var segmentType = /video/.test(segment) ? 'video' : 'audio';

	console.log('chunk request', segmentType, segmentId);

	var loopCount = Math.floor(segmentId / setup[segmentType].chunks);
	var currentSegment = segmentId % setup[segmentType].chunks;

	if (currentSegment === 0) {
		currentSegment = setup[segmentType].chunks;
	}

	var chunkFile = './media/'  + segment.replace(/(\d+)/, '') + currentSegment +'.m4s';

	var chunkStream = fs.createReadStream(chunkFile, {
		flags: 'r',
		encoding: null,
		fd: null,
		mode: 0666,
		autoClose: true
	});

	chunkStream.on('error', function () {
		response.sendStatus(404);
	});

	var unboxing = new isoBmff.Parser(function (err, data) {
		if (err) {
			return response.sendStatus(500);
		}

		var newBaseTime = setup[segmentType].length * loopCount;

		data.forEach(function (d) {

			if (d.type == 'sidx') {
				d.content.earliestPresentationTime += newBaseTime;
			}

			if (d.type == 'moof') {
				d.content.forEach(function (m) {
					if (m.type == 'traf') {
						m.content.forEach(function (t) {
							if (t.type == 'tfdt') {
								t.content.baseMediaDecodeTime += newBaseTime;
							}
						});
					}
				});
			}
		});

		var build = new isoBmff.Builder(data, function (err, chunk) {
			response.set('Access-Control-Allow-Origin', '*');
			response.type(segmentType + '/mp4');
			response.send(chunk);

			unboxing = null;
			build = null

		});
		return data;

	});

	chunkStream
		.pipe(unboxing);
}

function getInit (request, response) {

	var segment = request.params.segment;
	var segmentType = /video/.test(segment) ? 'video' : 'audio';

	console.log('init segment request', segment );

	response.set('Access-Control-Allow-Origin', '*');
	response.type(segmentType + '/mp4');
	responseFileStream('./media/chick-' + segmentType + '_dashinit.mp4', response);

}

function getMpd (request, response) {

	console.log('MPD request' );

	response.set('Access-Control-Allow-Origin', '*');
	response.type('application/xml');
	responseFileStream('./chick.mpd', response)

}

function responseFileStream (file, response) {

	var fileStream = fs.createReadStream(file, {
		flags: 'r',
		encoding: null,
		fd: null,
		mode: 0666,
		autoClose: true
	});

	fileStream.on('error', function () {
		response.sendStatus(404);
	});

	fileStream.pipe(response)

}

app.get('/', function (req, res) {
	res.send('Hello World!')
})

app.get('/chunk/:segment.m4s', getChunk);
app.get('/init/:segment.mp4', getInit);
app.get('/chick.mpd', getMpd);

var server = app.listen(3000, function () {
	var host = server.address().address;
	var port = server.address().port;
	console.log('Example app listening at http://%s:%s', host, port)
});<|endoftext|>


<commit_before>var express = require('express'),
    snapsearch = require('snapsearch-client-nodejs'),
    logger = require ('morgan'),
    compress = require ('compression'),
    methodOverride = require ('method-override');

var app = express();

app.set('port', (process.env.PORT || 1337));

app.enable('trust proxy');

app.use(logger('dev'));    // will log out incoming requests
app.use(methodOverride()); // augments the req.method with non-standard PUT & DELETE
app.use(compress());       // conditionally gzip compresses the response body

// the snapsearch middleware should be after any kind of augmentation of the request or response
// in fact it should be as close to kernel of your software as possible
// any middleware added after the snapsearch middleware WILL NOT run during an interception, beware of this!
app.use(snapsearch.connect(
    new snapsearch.Interceptor(
        new snapsearch.Client(
            process.env.SNAPEMAIL,
            process.env.SNAPKEY,
            {},
            function (error, debugging) {

                console.log('Oh no SnapSearch node client met an error while trying to intercept the request!');
                console.log(error);
                console.log(debugging);

            }
        ),
        new snapsearch.Detector([], [], false, true)
    ),
    function (data) {

        console.log('SnapSearch node client successfully intercepted a robot!');
        console.log('We are returning the scraped snapshot from the SnapSearch API.');

        // it is important to understand the purpose of this function here
        // by default SnapSearch only passes through the Location header
        // you can add this custom function to control exactly how the snapshot is returned to the client
        // that means it's possible to pass through ALL the headers
        // this can mean big problems however!
        // if you pass through all the headers, the headers may introduce new errors
        // for example, if your snapshot has gzipped headers
        // and you return the gzipped headers, then the content returned better be gzipped
        // but there's a possibility that it might be not be gzipped because the content is being returned
        // in the SnapSearch express middleware layer
        // if you put your SnapSearch express middleware layer in the wrong place
        // this could cause the content not to be gzipped
        // below is an example of this exact problem
        // the snapshot returned will have `Content-Encoding` header indicating gzipped content
        // but the compression middleware will not gzip compress the content if it already detects a
        // preset `Content-Encoding` header
        // this means we need to remove that header specifically, before returning here
        // so the upstream compression middleware can then gzip the content, and readd the `Content-Encoding` header

        // remove the content-encoding header here
        var contentEncodingIndex;
        data.headers.forEach(function (header, index) {
            if (header.name.toLowerCase() == 'content-encoding') {
                contentEncodingIndex = index;
            }
        });
        if (contentEncodingIndex) {
            data.headers.splice(contentEncodingIndex, 1);
        }

        // return an object for custom response handling
        return {
            status: data.status,
            html: data.html,
            headers: data.headers
        };

    }
));

app.use(express.static('public'));

app.get('/', function (req, res) {

    // content-type and content-length is required in order to trigger compression
    // content-length needs to be greater than 1024
    res.type('html');

    var output = 'Some static content. <script>document.write("Some javascript injected content, only viewable with SnapSearch and JavaScript enabled clients!");</script>',
        buffer = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sit amet urna eget neque eleifend suscipit. Mauris id quam non tortor pretium hendrerit eu at ligula. Morbi neque leo, imperdiet a metus ut, auctor fringilla turpis. Etiam ut augue ultricies lacus rutrum laoreet. Aenean consectetur nisi vel dui rutrum, hendrerit congue felis ultricies. Suspendisse a lacus nibh. Cras et diam vel metus lacinia cursus eget ut turpis. Maecenas eu tempor elit. In scelerisque interdum orci, at lobortis lacus dapibus eu. Maecenas auctor lacus ac venenatis efficitur. Integer non vulputate velit. Etiam congue imperdiet est, ac porta tellus pharetra eu. Curabitur ut laoreet est. Donec porta, sapien eu porttitor laoreet, augue sapien faucibus dui, eu convallis nisl sem a lorem. Mauris neque orci, placerat eget pharetra ullamcorper, suscipit at justo. Aliquam mauris elit, sollicitudin sit amet odio vitae, cursus consequat magna. Nam tristique neque ipsum, quis dictum lorem ullamcorper non. Pellentesque iaculis sapien id nullam.';

    // we need some extra content to trigger the compress middleware
    output = output + ' ' + buffer;

    // res.send is a magic function that will auto-add content-length
    res.send(output);

    // do not use res.write(); res.end() without explicitly adding content-length

});

app.listen(app.get('port'), function () {
    console.log('SnapSearch demo running on localhost:' + app.get('port'));
});<commit_msg>ignore sitemap.xml<commit_after>var express = require('express'),
    snapsearch = require('snapsearch-client-nodejs'),
    logger = require ('morgan'),
    compress = require ('compression'),
    methodOverride = require ('method-override');

var app = express();

app.set('port', (process.env.PORT || 1337));

app.enable('trust proxy');

app.use(logger('dev'));    // will log out incoming requests
app.use(methodOverride()); // augments the req.method with non-standard PUT & DELETE
app.use(compress());       // conditionally gzip compresses the response body

// the snapsearch middleware should be after any kind of augmentation of the request or response
// in fact it should be as close to kernel of your software as possible
// any middleware added after the snapsearch middleware WILL NOT run during an interception, beware of this!
app.use(snapsearch.connect(
    new snapsearch.Interceptor(
        new snapsearch.Client(
            process.env.SNAPEMAIL,
            process.env.SNAPKEY,
            {},
            function (error, debugging) {

                console.log('Oh no SnapSearch node client met an error while trying to intercept the request!');
                console.log(error);
                console.log(debugging);

            }
        ),
        new snapsearch.Detector([
            '/sitemap.xml'
        ], [], false, true)
    ),
    function (data) {

        console.log('SnapSearch node client successfully intercepted a robot!');
        console.log('We are returning the scraped snapshot from the SnapSearch API.');

        // it is important to understand the purpose of this function here
        // by default SnapSearch only passes through the Location header
        // you can add this custom function to control exactly how the snapshot is returned to the client
        // that means it's possible to pass through ALL the headers
        // this can mean big problems however!
        // if you pass through all the headers, the headers may introduce new errors
        // for example, if your snapshot has gzipped headers
        // and you return the gzipped headers, then the content returned better be gzipped
        // but there's a possibility that it might be not be gzipped because the content is being returned
        // in the SnapSearch express middleware layer
        // if you put your SnapSearch express middleware layer in the wrong place
        // this could cause the content not to be gzipped
        // below is an example of this exact problem
        // the snapshot returned will have `Content-Encoding` header indicating gzipped content
        // but the compression middleware will not gzip compress the content if it already detects a
        // preset `Content-Encoding` header
        // this means we need to remove that header specifically, before returning here
        // so the upstream compression middleware can then gzip the content, and readd the `Content-Encoding` header

        // remove the content-encoding header here
        var contentEncodingIndex;
        data.headers.forEach(function (header, index) {
            if (header.name.toLowerCase() == 'content-encoding') {
                contentEncodingIndex = index;
            }
        });
        if (contentEncodingIndex) {
            data.headers.splice(contentEncodingIndex, 1);
        }

        // return an object for custom response handling
        return {
            status: data.status,
            html: data.html,
            headers: data.headers
        };

    }
));

app.use(express.static('public'));

app.get('/', function (req, res) {

    // content-type and content-length is required in order to trigger compression
    // content-length needs to be greater than 1024
    res.type('html');

    var output = 'Some static content. <script>document.write("Some javascript injected content, only viewable with SnapSearch and JavaScript enabled clients!");</script>',
        buffer = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sit amet urna eget neque eleifend suscipit. Mauris id quam non tortor pretium hendrerit eu at ligula. Morbi neque leo, imperdiet a metus ut, auctor fringilla turpis. Etiam ut augue ultricies lacus rutrum laoreet. Aenean consectetur nisi vel dui rutrum, hendrerit congue felis ultricies. Suspendisse a lacus nibh. Cras et diam vel metus lacinia cursus eget ut turpis. Maecenas eu tempor elit. In scelerisque interdum orci, at lobortis lacus dapibus eu. Maecenas auctor lacus ac venenatis efficitur. Integer non vulputate velit. Etiam congue imperdiet est, ac porta tellus pharetra eu. Curabitur ut laoreet est. Donec porta, sapien eu porttitor laoreet, augue sapien faucibus dui, eu convallis nisl sem a lorem. Mauris neque orci, placerat eget pharetra ullamcorper, suscipit at justo. Aliquam mauris elit, sollicitudin sit amet odio vitae, cursus consequat magna. Nam tristique neque ipsum, quis dictum lorem ullamcorper non. Pellentesque iaculis sapien id nullam.';

    // we need some extra content to trigger the compress middleware
    output = output + ' ' + buffer;

    // res.send is a magic function that will auto-add content-length
    res.send(output);

    // do not use res.write(); res.end() without explicitly adding content-length

});

app.listen(app.get('port'), function () {
    console.log('SnapSearch demo running on localhost:' + app.get('port'));
});<|endoftext|>


<commit_before>'use strict';

/**
 * module dependencies
 */

var path = require('path');
var util = require('util');
var async = require('async');
var runtimes = require('composer-runtimes');
var Boilerplate = require('boilerplate');
var Templates = require('templates');
var Scaffold = require('scaffold');
var Composer = require('composer');
var proto = Composer.prototype;
var utils = require('./lib/utils');

/**
 * Create an `assemble` application. This is the main function exported
 * by the assemble module.
 *
 * ```js
 * var assemble = require('assemble');
 * var app = assemble();
 * ```
 * @param {Object} `options` Optionally pass default options to use.
 * @api public
 */

function Assemble(options) {
  if (!(this instanceof Assemble)) {
    return new Assemble(options);
  }
  Templates.apply(this, arguments);
  Composer.apply(this, arguments);
  this.set('Boilerplate', this.options.Boilerplate || Boilerplate);
  this.set('Scaffold', this.options.Scaffold || Scaffold);
  this.boilerplates = {};
  this.scaffolds = {};
  this.init();
}

Templates.inherit(Assemble, Composer);

/**
 * `Assemble` prototype methods
 */

Templates.extend(Assemble, {
  constructor: Assemble,

  /**
   * Initialize Assemble defaults
   */

  init: function() {
    this.defaultEngine();
    this.defaultMiddleware();
    this.defaultViewTypes();
    this.loaded = true;
  },

  /**
   * Default template engine and related extensions.
   */

  defaultEngine: function () {
    this.engine(['hbs', 'html', 'md'], require('engine-handlebars'));
  },

  /**
   * Default middleware
   *  | Ensure user-defined layout is recognized
   *  | Parse front-matter
   */

  defaultMiddleware: function () {
    this.preLayout(/\.(hbs|md|html)$/, function (view, next) {
      if (!view.layout) view.layout = view.locals.layout || view.data.layout;
      next();
    });
    this.onLoad(/\.(hbs|md|html)$/, function (view, next) {
      utils.matter.parse(view, next);
    });
  },

  /**
   * Default `viewTypes`
   *  | partials
   *  | layouts
   *  | pages
   *  | files
   */

  defaultViewTypes: function () {
    this.create('partials', {
      viewType: 'partial',
      renameKey: function (fp) {
        return path.basename(fp, path.extname(fp));
      }
    });

    this.create('layouts', {
      viewType: 'layout',
      renameKey: function (fp) {
        return path.basename(fp, path.extname(fp));
      }
    });

    this.create('pages', {
      renameKey: function (fp) {
        return fp;
      }
    });

    this.create('files', {
      renameKey: function (fp) {
        return fp;
      }
    });
  },

  /**
   * Copy a file from `src` to `dest` and process any templates in
   * `file.contents`.
   *
   * @name .process
   * @param {Object} `file` [Vinyl][] file object.
   * @param {Object} `options`
   * @return {Stream} Returns a stream to continue processing if needed.
   * @api public
   */

  process: function (file, options) {
    options = options || {};
    var pre = options.preprocess || options.pipeline || utils.identity;
    var post = options.postprocess || utils.identity;
    var stream = this.src(file.src);

    stream = pre(stream, this).pipe(this.renderFile(file.data || {}));
    return post(stream, this).pipe(this.dest(file.dest));
  },

  /**
   * Generate all of the `src`/`dest` definitions in the given
   * `config` object. Used for generating [boilerplates][] and
   * [scaffolds][].
   *
   * @name .generate
   * @param {Object} `config` The configuration object to use.
   * @param {Function} `cb` Callback function, exposes `err` on the callback.
   * @return {Object} Returns the `Assemble` instance for chaining.
   * @api public
   */

  generate: function (config, cb) {
    var opts = {};
    opts.preprocess = config.preprocess;
    opts.postprocess = config.postprocess;
    async.each(config.files, function (file, next) {
      utils.parallel(this.process(file, opts), next);
    }.bind(this), cb);
    return this;
  },

  /**
   * Register and/or generate a boilerplate from the given `config`.
   *
   * @name .boilerplate
   * @param {String} `name` The name of the boilerplate to register
   * @param {Object} `config` The configuration object to use.
   * @return {Object} Returns the `Boilerplate` instance for chaining.
   * @api public
   */

  boilerplate: function (name, config) {
    var Boilerplate = this.get('Boilerplate');
    var boilerplate = !(config instanceof Boilerplate)
      ? new Boilerplate(config)
      : config;

    var app = this;
    boilerplate.generate = function (options, cb) {
      var targets = Object.keys(boilerplate.targets);
      async.each(targets, function (target, next) {
        app.generate(target, options, next);
      }, cb);
    };

    this.boilerplates[name] = boilerplate;
    return boilerplate;
  },

  /**
   * Generate a scaffold from the given `config`.
   *
   * @name .scaffold
   * @param {String} `name`
   * @param {Object} `config`
   * @return {Object} Returns the `Assemble` instance for chaining
   * @api public
   */

  scaffold: function (name, config) {
    var Scaffold = this.get('Scaffold');
    var scaffold = !(config instanceof Scaffold)
      ? new Scaffold(config)
      : config;

    var app = this;
    scaffold.generate = function (cb) {
      var args = [].slice.call(arguments);
      args.unshift(this);
      return app.generate.apply(app, args);
    };

    this.scaffolds[name] = scaffold;
    return this;
  },

  /**
   * Glob patterns or filepaths to source files.
   *
   * ```js
   * app.src('src/*.hbs', {layout: 'default'});
   * ```
   * @name .src
   * @param {String|Array} `glob` Glob patterns or file paths to source files.
   * @param {Object} `options` Options or locals to merge into the context and/or pass to `src` plugins
   * @api public
   */

  src: function () {
    if (!this.loaded) this.init();
    return utils.vfs.src.apply(utils.vfs, arguments);
  },

  symlink: function () {
    if (!this.loaded) this.init();
    return utils.vfs.symlink.apply(utils.vfs, arguments);
  },

  /**
   * Specify a destination for processed files.
   *
   * ```js
   * app.dest('dist/');
   * ```
   * @name .dest
   * @param {String|Function} `dest` File path or rename function.
   * @param {Object} `options` Options and locals to pass to `dest` plugins
   * @api public
   */

  dest: function () {
    return utils.vfs.dest.apply(utils.vfs, arguments)
      .on('data', function () {}); // TODO: fix this
  },

  /**
   * Copy files with the given glob `patterns` to the specified `destDir`.
   *
   * ```js
   * app.task('assets', function() {
   *   app.copy('assets/**', 'dist/');
   * });
   * ```
   * @name .copy
   * @param {String|Array} `patterns` Glob patterns of files to copy.
   * @param  {String|Function} `dest` Desination directory.
   * @return {Stream} Stream, to continue processing if necessary.
   * @api public
   */

  copy: function(patterns, dest, options) {
    return utils.vfs.src(patterns, options)
      .pipe(utils.vfs.dest(dest, options));
  },

  /**
   * Push a view collection into a vinyl stream.
   *
   * ```js
   * app.toStream('posts', function(file) {
   *   return file.path !== 'index.hbs';
   * })
   * ```
   * @name .toStream
   * @param {String} `collection` The name of the view collection to push into the stream.
   * @param {Function} Optionally pass a filter function to use for filtering views.
   * @return {Stream}
   * @api public
   */

  toStream: function (collection, fn) {
    var views = this.getViews(collection) || {};
    return utils.through.obj(function (file, enc, cb) {
      this.push(file);
      return cb();
    }, function (cb) {
      Object.keys(views).forEach(function (key) {
        var view = views[key];
        var file = utils.toVinyl(view);
        this.push(file);
      }.bind(this));
      cb();
    });
  },

  /**
   * Render a vinyl file.
   *
   * ```js
   * app.src('*.hbs')
   *   .pipe(app.renderFile());
   * ```
   *
   * @name .renderFile
   * @param  {Object} `locals` Optionally locals to pass to the template engine for rendering.
   * @return {Object}
   * @api public
   */

  renderFile: function (locals) {
    var app = this;
    var collection = this.collection();
    return utils.through.obj(function (file, enc, cb) {
      if (typeof locals === 'function') {
        cb = locals;
        locals = {};
      }
      var view = collection.view(file);
      app.handleView('onLoad', view)
      app.render(view, locals, function (err, res) {
        if (err) return cb(err);
        res.contents = new Buffer(res.content);
        file = new utils.Vinyl(res);
        cb(null, file);
      });
    });
  },

  /**
   * Define an Assemble task.
   *
   * ```js
   * app.task('default', function() {
   *   app.src('templates/*.hbs')
   *     .pipe(app.dest('dist/'));
   * });
   * ```
   *
   * @name .task
   * @param {String} `name` Task name
   * @param {Function} `fn` function that is called when the task is run.
   * @api public
   */

  task: function (name) {
    runtimes(this);
    if (!this.loaded) this.init();
    return proto.task.apply(this, arguments);
  },

  /**
   * Run one or more tasks.
   *
   * ```js
   * app.run(['foo', 'bar'], function(err) {
   *   if (err) console.error('ERROR:', err);
   * });
   * ```
   * @name .run
   * @param {Array|String} `tasks` Task name or array of task names.
   * @param {Function} `cb` callback function that exposes `err`
   * @api public
   */

  run: function (tasks, cb) {
    return proto.run.apply(this, arguments);
  },

  /**
   * Re-run the specified task(s) when a file changes.
   *
   * ```js
   * app.task('watch', function() {
   *   app.watch('docs/*.md', ['docs']);
   * });
   * ```
   *
   * @param  {String|Array} `glob` Filepaths or glob patterns.
   * @param  {Array} `tasks` Task(s) to watch.
   * @api public
   */

  watch: function (glob, tasks) {
    return proto.watch.apply(this, arguments);
  }
});

/**
 * Expose the `Assemble` constructor
 */

module.exports = Assemble;
<commit_msg>remove redundant `init` code. add comments<commit_after>'use strict';

/**
 * module dependencies
 */

var path = require('path');
var async = require('async');
var runtimes = require('composer-runtimes');
var Boilerplate = require('boilerplate');
var Templates = require('templates');
var Scaffold = require('scaffold');
var Composer = require('composer');
var proto = Composer.prototype;
var utils = require('./lib/utils');

/**
 * Create an `assemble` application. This is the main function exported
 * by the assemble module.
 *
 * ```js
 * var assemble = require('assemble');
 * var app = assemble();
 * ```
 * @param {Object} `options` Optionally pass default options to use.
 * @api public
 */

function Assemble(options) {
  if (!(this instanceof Assemble)) {
    return new Assemble(options);
  }

  Templates.apply(this, arguments);
  Composer.apply(this, arguments);
  this.set('Boilerplate', this.options.Boilerplate || Boilerplate);
  this.set('Scaffold', this.options.Scaffold || Scaffold);
  this.boilerplates = {};
  this.scaffolds = {};
  this.init();
}

Templates.inherit(Assemble, Composer);

/**
 * `Assemble` prototype methods
 */

Templates.extend(Assemble, {
  constructor: Assemble,

  /**
   * Initialize Assemble defaults
   */

  init: function() {
    this.defaultEngine();
    this.defaultMiddleware();
    this.defaultViewTypes();
  },

  /**
   * Default template engine and related extensions.
   */

  defaultEngine: function () {
    this.engine(['hbs', 'html', 'md'], require('engine-handlebars'));
  },

  /**
   * Default middleware
   *  | Ensure user-defined layout is recognized
   *  | Parse front-matter
   */

  defaultMiddleware: function () {
    this.preLayout(/\.(hbs|md|html)$/, function (view, next) {
      if (!view.layout) view.layout = view.locals.layout || view.data.layout;
      next();
    });
    this.onLoad(/\.(hbs|md|html)$/, function (view, next) {
      utils.matter.parse(view, next);
    });
  },

  /**
   * Default `viewTypes`
   *  | partials
   *  | layouts
   *  | pages
   *  | files
   */

  defaultViewTypes: function () {
    this.create('partials', {
      viewType: 'partial',
      renameKey: function (fp) {
        return path.basename(fp, path.extname(fp));
      }
    });

    this.create('layouts', {
      viewType: 'layout',
      renameKey: function (fp) {
        return path.basename(fp, path.extname(fp));
      }
    });

    this.create('pages', {
      renameKey: function (fp) {
        return fp;
      }
    });

    this.create('files', {
      renameKey: function (fp) {
        return fp;
      }
    });
  },

  /**
   * Copy a file from `src` to `dest` and process any templates in
   * `file.contents`.
   *
   * @name .process
   * @param {Object} `file` [Vinyl][] file object.
   * @param {Object} `options`
   * @return {Stream} Returns a stream to continue processing if needed.
   * @api public
   */

  process: function (file, options) {
    options = options || {};
    var pre = options.preprocess || options.pipeline || utils.identity;
    var post = options.postprocess || utils.identity;
    var stream = this.src(file.src);

    stream = pre(stream, this).pipe(this.renderFile(file.data || {}));
    return post(stream, this).pipe(this.dest(file.dest));
  },

  /**
   * Generate all of the `src`/`dest` definitions in the given
   * `config` object. Used for generating [boilerplates][] and
   * [scaffolds][].
   *
   * @name .generate
   * @param {Object} `config` The configuration object to use.
   * @param {Function} `cb` Callback function, exposes `err` on the callback.
   * @return {Object} Returns the `Assemble` instance for chaining.
   * @api public
   */

  generate: function (config, cb) {
    var opts = {};
    opts.preprocess = config.preprocess;
    opts.postprocess = config.postprocess;
    async.each(config.files, function (file, next) {
      utils.parallel(this.process(file, opts), next);
    }.bind(this), cb);
    return this;
  },

  /**
   * Register and/or generate a boilerplate from the given `config`.
   *
   * @name .boilerplate
   * @param {String} `name` The name of the boilerplate to register
   * @param {Object} `config` The configuration object to use.
   * @return {Object} Returns the `Boilerplate` instance for chaining.
   * @api public
   */

  boilerplate: function (name, config) {
    if (!config && typeof name === 'string') {
      return this.boilerplates[name];
    }

    var Boilerplate = this.get('Boilerplate');
    var boilerplate = !(config instanceof Boilerplate)
      ? new Boilerplate(config)
      : config;

    var app = this;
    boilerplate.generate = function (options, cb) {
      var targets = Object.keys(boilerplate.targets);
      async.each(targets, function (target, next) {
        app.generate(target, options, next);
      }, cb);
    };

    this.boilerplates[name] = boilerplate;
    return boilerplate;
  },

  /**
   * Generate a scaffold from the given `config`.
   *
   * @name .scaffold
   * @param {String} `name`
   * @param {Object} `config`
   * @return {Object} Returns the `Assemble` instance for chaining
   * @api public
   */

  scaffold: function (name, config) {
    if (!config && typeof name === 'string') {
      return this.scaffolds[name];
    }

    var Scaffold = this.get('Scaffold');
    var scaffold = !(config instanceof Scaffold)
      ? new Scaffold(config)
      : config;

    var app = this;
    scaffold.generate = function (cb) {
      var args = [].slice.call(arguments);
      args.unshift(this);
      return app.generate.apply(app, args);
    };

    this.scaffolds[name] = scaffold;
    return this;
  },

  /**
   * Glob patterns or filepaths to source files.
   *
   * ```js
   * app.src('src/*.hbs', {layout: 'default'});
   * ```
   * @name .src
   * @param {String|Array} `glob` Glob patterns or file paths to source files.
   * @param {Object} `options` Options or locals to merge into the context and/or pass to `src` plugins
   * @api public
   */

  src: function () {
    return utils.vfs.src.apply(utils.vfs, arguments);
  },

  /**
   * Glob patterns or paths for symlinks.
   *
   * ```js
   * app.symlink('src/**');
   * ```
   * @name .symlink
   * @param {String|Array} `glob`
   * @api public
   */

  symlink: function () {
    return utils.vfs.symlink.apply(utils.vfs, arguments);
  },

  /**
   * Specify a destination for processed files.
   *
   * ```js
   * app.dest('dist/');
   * ```
   * @name .dest
   * @param {String|Function} `dest` File path or rename function.
   * @param {Object} `options` Options and locals to pass to `dest` plugins
   * @api public
   */

  dest: function () {
    return utils.vfs.dest.apply(utils.vfs, arguments)
      .on('data', function () {}); // TODO: fix this
  },

  /**
   * Copy files with the given glob `patterns` to the specified `destDir`.
   *
   * ```js
   * app.task('assets', function() {
   *   app.copy('assets/**', 'dist/');
   * });
   * ```
   * @name .copy
   * @param {String|Array} `patterns` Glob patterns of files to copy.
   * @param  {String|Function} `dest` Desination directory.
   * @return {Stream} Stream, to continue processing if necessary.
   * @api public
   */

  copy: function(patterns, dest, options) {
    return utils.vfs.src(patterns, options)
      .pipe(utils.vfs.dest(dest, options));
  },

  /**
   * Push a view collection into a vinyl stream.
   *
   * ```js
   * app.toStream('posts', function(file) {
   *   return file.path !== 'index.hbs';
   * })
   * ```
   * @name .toStream
   * @param {String} `collection` The name of the view collection to push into the stream.
   * @param {Function} Optionally pass a filter function to use for filtering views.
   * @return {Stream}
   * @api public
   */

  toStream: function (collection, fn) {
    var views = this.getViews(collection) || {};
    return utils.through.obj(function (file, enc, cb) {
      this.push(file);
      return cb();
    }, function (cb) {
      Object.keys(views).forEach(function (key) {
        var view = views[key];
        var file = utils.toVinyl(view);
        this.push(file);
      }.bind(this));
      cb();
    });
  },

  /**
   * Render a vinyl file.
   *
   * ```js
   * app.src('*.hbs')
   *   .pipe(app.renderFile());
   * ```
   *
   * @name .renderFile
   * @param  {Object} `locals` Optionally locals to pass to the template engine for rendering.
   * @return {Object}
   * @api public
   */

  renderFile: function (locals) {
    var app = this;
    var collection = this.collection();
    return utils.through.obj(function (file, enc, cb) {
      if (typeof locals === 'function') {
        cb = locals;
        locals = {};
      }
      var view = collection.view(file);
      app.handleView('onLoad', view)
      app.render(view, locals, function (err, res) {
        if (err) return cb(err);
        res.contents = new Buffer(res.content);
        file = new utils.Vinyl(res);
        cb(null, file);
      });
    });
  },

  /**
   * Define an Assemble task.
   *
   * ```js
   * app.task('default', function() {
   *   app.src('templates/*.hbs')
   *     .pipe(app.dest('dist/'));
   * });
   * ```
   *
   * @name .task
   * @param {String} `name` Task name
   * @param {Function} `fn` function that is called when the task is run.
   * @api public
   */

  task: function (name) {
    runtimes(this);
    return proto.task.apply(this, arguments);
  },

  /**
   * Run one or more tasks.
   *
   * ```js
   * app.run(['foo', 'bar'], function(err) {
   *   if (err) console.error('ERROR:', err);
   * });
   * ```
   * @name .run
   * @param {Array|String} `tasks` Task name or array of task names.
   * @param {Function} `cb` callback function that exposes `err`
   * @api public
   */

  run: function (tasks, cb) {
    return proto.run.apply(this, arguments);
  },

  /**
   * Re-run the specified task(s) when a file changes.
   *
   * ```js
   * app.task('watch', function() {
   *   app.watch('docs/*.md', ['docs']);
   * });
   * ```
   *
   * @param  {String|Array} `glob` Filepaths or glob patterns.
   * @param  {Array} `tasks` Task(s) to watch.
   * @api public
   */

  watch: function (glob, tasks) {
    return proto.watch.apply(this, arguments);
  }
});

/**
 * Expose the `Assemble` constructor
 */

module.exports = Assemble;
<|endoftext|>


<commit_before>var katex = require("katex");

module.exports = {
    book: {
        assets: "./book",
        js: [],
        hooks: {
            page: function(page) {
                for (var i in page.sections) {
                    section = page.sections[i];
                    if ( section.type != "normal" ) continue;

                    var $ = cheerio.load(section.content);
                    $("script[type='math/tex']").each(function() {
                        var math = $(this).html();
                        $(this).replaceWith(katex.renderToString(math));
                    });

                    // Replace by transform
                    section.content = $.html();
                }

                return page;
            }
        }
    }
};
<commit_msg>Fix hooks position<commit_after>var katex = require("katex");
var cheerio = require("cheerio");

module.exports = {
    book: {
        assets: "./book",
        js: []
    },
    hooks: {
        page: function(page) {
            for (var i in page.sections) {
                section = page.sections[i];
                if ( section.type != "normal" ) continue;

                var $ = cheerio.load(section.content);
                $("script").each(function() {
                    // Check is math
                    var type = $(this).attr("type") || "";
                    if (type.indexOf("math/tex") < 0) return;

                    var math = $(this).html().toString("utf8");
                    console.log("convert '"+math+"'");
                    $(this).replaceWith(katex.renderToString(math));
                });

                // Replace by transform
                section.content = $.html();
            }

            return page;
        }
    }
};
<|endoftext|>