<commit_before>/*
  postcss-inrule (v1.1.0)
  github.com/salsita/postcss-inrule
  2016 | MIT
  ============================== */

var postcss = require('postcss'),
    assign = require('object-assign');

// Get index of inRule tags
function getTagIndex(string, tag) {
  var tags = string.match('^' + tag + '+');
  return tags && tags[0].length || 0;
}

// Lil' Shavy™
function getShavedClone(clone) {
  var element, current, first = true;
  // Find current element and remove its props
  clone.walkAtRules('in', function (inRule) {
    if (first) {
      first = false;
      current = element = inRule.parent;
      element.removeAll();
    }
  });
  // Clean all parent props that don't lead to current element
  while (current.parent) {
    current.parent.each(function (node) {
      node !== current && node.remove();
    });
    current = current.parent;
  }
  return element;
}

// Process modifications on clone
function processModifications(clone, params, options, inRule) {
  for (var param of params) {
    var current = clone,
        appendIndex = getTagIndex(param, options.tagAppend),
        insertIndex = getTagIndex(param, options.tagInsert),
        replaceIndex = getTagIndex(param, options.tagReplace),
        currentIndex = Math.max(appendIndex, insertIndex, replaceIndex),
        nodeIndex = current.type !== 'rule' ? -1 : 0,
        modifier = param.slice(currentIndex, param.length),
        modified = false;
    while (current.parent && !modified) {
      var selectors = current.parent.selectors;
      if (selectors) {
        nodeIndex++;
        if (nodeIndex >= currentIndex && clone.parent.type !== 'root') {
          // Append
          if (appendIndex > 0) {
            current.parent.selectors = selectors.map(function (selector) {
              return selector + modifier;
            });
          // Insert
          } else if (insertIndex > 0) {
            current.parent.selectors = selectors.map(function (selector) {
              return selector + ' ' + modifier;
            });
          // Replace
          } else if (replaceIndex > 0) {
            current.parent.selectors = [modifier];
          } else {
            throw inRule.error('No valid tag found', { word: param });
          }
          modified = true;
        }
      }
      current = current.parent;
    }
    if (!modified) {
      throw inRule.error('No parent to modify found', { word: param });
    }
  }
  return clone;
}

module.exports = postcss.plugin('postcss-inrule', function (options) {
  return function (css) {

    // Options
    options = options || {};
    var defaultOptions = {
      tagAppend: '<',
      tagInsert: '\\^',
      tagReplace: '@'
    };
    options = assign({
      tagAppend: options.tagAppend || defaultOptions.tagAppend,
      tagInsert: options.tagInsert || defaultOptions.tagInsert,
      tagReplace: options.tagReplace || defaultOptions.tagReplace
    }, options);

    // Process @in at-rules
    css.walkAtRules('in', function (inRule) {

      // Clone a prop-less tree clone for every ',' param
      for (var params of inRule.params.split(',')) {
        var clone = getShavedClone(inRule.root().clone());

        // Process modifications and append new rule to root
        params = postcss.list.space(params);
        processModifications(clone, params, options, inRule);
        if (inRule.nodes.length > 0) {
          clone.append(inRule.nodes);
        } else {
          throw inRule.error('No children or decls', { word: inRule });
        }
        css.append(clone.root());
      }
      // Remove original @in rule and all children
      inRule.removeAll().remove();
    });
  };
});
<commit_msg>1.1.1<commit_after>/*
  postcss-inrule (v1.1.1)
  github.com/salsita/postcss-inrule
  2016 | MIT
  ============================== */

var postcss = require('postcss'),
    assign = require('object-assign');

// Get index of inRule tags
function getTagIndex(string, tag) {
  var tags = string.match('^' + tag + '+');
  return tags && tags[0].length || 0;
}

// Lil' Shavy™
function getShavedClone(clone) {
  var element, current, first = true;
  // Find current element and remove its props
  clone.walkAtRules('in', function (inRule) {
    if (first) {
      first = false;
      current = element = inRule.parent;
      element.removeAll();
    }
  });
  // Clean all parent props that don't lead to current element
  while (current.parent) {
    current.parent.each(function (node) {
      node !== current && node.remove();
    });
    current = current.parent;
  }
  return element;
}

// Process modifications on clone
function processModifications(clone, params, options, inRule) {
  for (var param of params) {
    var current = clone,
        appendIndex = getTagIndex(param, options.tagAppend),
        insertIndex = getTagIndex(param, options.tagInsert),
        replaceIndex = getTagIndex(param, options.tagReplace),
        currentIndex = Math.max(appendIndex, insertIndex, replaceIndex),
        nodeIndex = current.type !== 'rule' ? -1 : 0,
        modifier = param.slice(currentIndex, param.length),
        modified = false;
    while (current.parent && !modified) {
      var selectors = current.parent.selectors;
      if (selectors) {
        nodeIndex++;
        if (nodeIndex >= currentIndex && clone.parent.type !== 'root') {
          // Append
          if (appendIndex > 0) {
            current.parent.selectors = selectors.map(function (selector) {
              return selector + modifier;
            });
          // Insert
          } else if (insertIndex > 0) {
            current.parent.selectors = selectors.map(function (selector) {
              return selector + ' ' + modifier;
            });
          // Replace
          } else if (replaceIndex > 0) {
            current.parent.selectors = [modifier];
          } else {
            throw inRule.error('No valid tag found', { word: param });
          }
          modified = true;
        }
      }
      current = current.parent;
    }
    if (!modified) {
      throw inRule.error('No parent to modify found', { word: param });
    }
  }
  return clone;
}

module.exports = postcss.plugin('postcss-inrule', function (options) {
  return function (css) {

    // Options
    options = options || {};
    var defaultOptions = {
      tagAppend: '<',
      tagInsert: '\\^',
      tagReplace: '@'
    };
    options = assign({
      tagAppend: options.tagAppend || defaultOptions.tagAppend,
      tagInsert: options.tagInsert || defaultOptions.tagInsert,
      tagReplace: options.tagReplace || defaultOptions.tagReplace
    }, options);

    // Process @in at-rules
    css.walkAtRules('in', function (inRule) {

      // Clone a prop-less tree clone for every ',' param
      for (var params of inRule.params.split(',')) {
        var clone = getShavedClone(inRule.root().clone());

        // Process modifications and append new rule to root
        params = postcss.list.space(params);
        processModifications(clone, params, options, inRule);
        if (inRule.nodes.length > 0) {
          clone.append(inRule.nodes);
        } else {
          throw inRule.error('No children or decls', { word: inRule });
        }
        css.append(clone.root());
      }
      // Remove original @in rule and all children
      inRule.removeAll().remove();
    });
  };
});
<|endoftext|>


<commit_before>import { backtrack } from '../common/iterators';
import * as delaney from '../dsymbols/delaney';
import * as props from '../dsymbols/properties';
import * as dsets2d from './dsets2d';
import symbols from '../io/ds';

import { rationals as opsQ } from '../arithmetic/types';

const isLoopless = (ds, i, j, D) =>
  ds.orbit2(i, j, D).every(E => ds.s(i, E) != E && ds.s(j, E) != E);

const orbits = ds => {
  const result = [];

  for (const [i, j] of [[0, 1], [1, 2]]) {
    for (const D of ds.orbitReps2(i, j)) {
      result.push([i, D, ds.r(i, j, D), isLoopless(ds, i, j, D)]);
    }
  }

  return result;
};

const openOrbits = ds =>
  orbits(ds).filter(([i, D, r, loopless]) => !ds.v(i, i+1, D));

const compareMapped = (ds, m) => {
  for (const [i, j] of [[0, 1], [1, 2]]) {
    for (const D of ds.elements()) {
      const d = ds.v(i, j, D) - ds.v(i, j, m[D]);
      if (d != 0) return d;
    }
  }
  return 0;
};

const isCanonical = (ds, maps) => maps.every(m => compareMapped(ds, m) >= 0);

const newCurvature = (curv, loopless, v, vOld) =>
  opsQ.plus(
    curv,
    opsQ.times(loopless ? 2 : 1, opsQ.minus(opsQ.div(1, v), opsQ.div(1, vOld)))
  );

const withBranching = (ds, i, D, v) => {
  const orb = ds.orbit2(i, i+1, D);
  const getV = (j, E) => j == i && orb.includes(E) ? v : ds.v(j, j+1, E);

  return delaney.buildDSymbol({ getV }, ds);
};

const isMinimallyHyperbolic = (ds, curv) => {
  if (opsQ.ge(curv, 0))
    return false;

  for (const [i, D, r, loopless] of orbits(ds)) {
    const v = ds.v(i, i+1, D);

    if (v && v > Math.ceil(3 / r)) {
      const newCurv = newCurvature(curv, loopless, v-1, v);
      if (opsQ.lt(newCurv, 0))
        return false;
    }
  }

  return true;
};

const goodResult = (ds, curv) => {
  let good;

  if (opsQ.le(curv, 0))
    good = true;
  else {
    const cones = [];
    const corners = [];
    for (const [i, j] of [[0, 1], [0, 2], [1, 2]]) {
      for (const D of ds.orbitReps2(i, j)) {
        const v = ds.v(i, j, D);
        if (v > 1) {
          if (isLoopless(ds, i, j, D))
            cones.push(v);
          else
            corners.push(v);
        }
      }
    }
    const front = cones.sort().reverse().join('');
    const middle = props.isLoopless(ds) ? '' : '*';
    const back = corners.sort().reverse().join('');
    const cross = props.isWeaklyOriented(ds) ? '' : 'x';
    const key = front + middle + back + cross;

    const goodKeys = [
      '', '*', 'x',
      '532', '432', '332',
      '422', '322', '222',
      '44', '33', '22',
      '*532', '*432', '*332', '3*2',
      '*422', '*322', '*222', '2*4', '2*3', '2*2',
      '*44', '*33', '*22', '4*', '3*', '2*', '4x', '3x', '2x',
    ];

    good = goodKeys.indexOf(key) >= 0;
  }

  return good;
};

const morphism = (src, srcD0, img, imgD0) => {
  const idcs = src.indices();

  const q = [[srcD0, imgD0]];
  const m = new Array(src.size + 1);
  m[srcD0] = imgD0;

  while (q.length) {
    const [D, E] = q.shift();

    for (const i of idcs) {
      const Di = src.s(i, D);
      const Ei = img.s(i, E);

      if (Di != null || Ei != null) {
        if (m[Di] == null) {
          q.push([Di, Ei]);
          m[Di] = Ei;
        }
        else if (m[Di] != Ei)
          return null;
      }
    }
  }

  return m;
};

const automorphisms = ds => {
  const elms = ds.elements();
  if (elms.length) {
    const D = elms[0];
    return elms.map(E => morphism(ds, D, ds, E)).filter(m => m != null);
  }
};

const curvature = ds => {
  const denom = 420;
  let numer = -ds.size * denom;
  for (const [i, j] of [[0, 1], [0, 2], [1, 2]]) {
    for (const D of ds.orbitReps2(i, j)) {
      const k = isLoopless(ds, i, j, D) ? 2 : 1;
      numer += k * denom / ds.v(i, j, D);
    }
  }
  const curv = opsQ.div(numer, denom);

  return curv;
};

const withMinimalBranchings = ds => {
  const s = new Array((ds.dim +1) * ds.size).fill(0);
  const v = new Array(ds.dim * ds.size).fill(0);

  for (let D = 1; D <= ds.size; ++D) {
    for (let i = 0; i <= ds.dim; ++i)
      s[i * ds.size + D - 1] = ds.s(i, D);
  }

  for (let i = 0; i < ds.dim; ++i) {
    const j = i + 1;
    for (const D of ds.orbitReps2(i, j)) {
      const q = Math.ceil(3 / ds.r(i, j, D));
      for (const E of ds.orbit2(i, j, D))
        v[i * ds.size + E - 1] = q;
    }
  }

  return delaney.makeDSymbol(ds.dim, s, v);
};

const branchings = ds => {
  const unused = openOrbits(ds);
  const maps = automorphisms(ds);
  const ds0 = withMinimalBranchings(ds);
  const curv0 = curvature(ds0);

  return backtrack({
    root: [ds0, curv0, unused],

    extract([ds, curv, unused]) {
      if (unused.length == 0 && isCanonical(ds, maps) && goodResult(ds, curv))
        return ds;
    },

    children([ds, curv, unused]) {
      if (unused.length) {
        if (opsQ.lt(curv, 0))
          return [[ds, curv, []]];
        else {
          const [i, D, r, loopless] = unused[0];
          const v0 = ds.v(i, i+1, D);
          const out = [];

          for (let v = v0; v <= 7; ++v) {
            const newCurv = newCurvature(curv, loopless, v, v0);
            const newDs = withBranching(ds, i, D, v);

            if (opsQ.ge(newCurv, 0) || isMinimallyHyperbolic(newDs, newCurv))
              out.push([ newDs, newCurv, unused.slice(1) ]);

            if (opsQ.lt(newCurv, 0))
              break;
          }

          return out;
        }
      }
    }
  });
}

if (require.main == module) {
  const arg = process.argv[2];

  if (Number.isInteger(parseInt(arg))) {
    const maxSize = parseInt(arg);
    const ds0 = delaney.parse('<1.1:1:1,1,1:0,0>');

    for (const dset of dsets2d.delaneySets(maxSize)) {
      for (const ds of branchings(dset))
        console.log(`${ds}`);
    }
  }
  else {
    for (const ds of branchings([...symbols(arg)][0]))
      console.log(`${ds}`);
  }
}
<commit_msg>smallSymbols2d: use sgn() to check signs of curvatures<commit_after>import { backtrack } from '../common/iterators';
import * as delaney from '../dsymbols/delaney';
import * as props from '../dsymbols/properties';
import * as dsets2d from './dsets2d';
import symbols from '../io/ds';

import { rationals as opsQ } from '../arithmetic/types';

const isLoopless = (ds, i, j, D) =>
  ds.orbit2(i, j, D).every(E => ds.s(i, E) != E && ds.s(j, E) != E);

const orbits = ds => {
  const result = [];

  for (const [i, j] of [[0, 1], [1, 2]]) {
    for (const D of ds.orbitReps2(i, j)) {
      result.push([i, D, ds.r(i, j, D), isLoopless(ds, i, j, D)]);
    }
  }

  return result;
};

const openOrbits = ds =>
  orbits(ds).filter(([i, D, r, loopless]) => !ds.v(i, i+1, D));

const compareMapped = (ds, m) => {
  for (const [i, j] of [[0, 1], [1, 2]]) {
    for (const D of ds.elements()) {
      const d = ds.v(i, j, D) - ds.v(i, j, m[D]);
      if (d != 0) return d;
    }
  }
  return 0;
};

const isCanonical = (ds, maps) => maps.every(m => compareMapped(ds, m) >= 0);

const newCurvature = (curv, loopless, v, vOld) =>
  opsQ.plus(
    curv,
    opsQ.times(loopless ? 2 : 1, opsQ.minus(opsQ.div(1, v), opsQ.div(1, vOld)))
  );

const withBranching = (ds, i, D, v) => {
  const orb = ds.orbit2(i, i+1, D);
  const getV = (j, E) => j == i && orb.includes(E) ? v : ds.v(j, j+1, E);

  return delaney.buildDSymbol({ getV }, ds);
};

const isMinimallyHyperbolic = (ds, curv) => {
  if (opsQ.sgn(curv) >= 0)
    return false;

  for (const [i, D, r, loopless] of orbits(ds)) {
    const v = ds.v(i, i+1, D);

    if (v && v > Math.ceil(3 / r)) {
      const newCurv = newCurvature(curv, loopless, v-1, v);
      if (opsQ.sgn(newCurv) < 0)
        return false;
    }
  }

  return true;
};

const goodResult = (ds, curv) => {
  let good;

  if (opsQ.sgn(curv) <= 0)
    good = true;
  else {
    const cones = [];
    const corners = [];
    for (const [i, j] of [[0, 1], [0, 2], [1, 2]]) {
      for (const D of ds.orbitReps2(i, j)) {
        const v = ds.v(i, j, D);
        if (v > 1) {
          if (isLoopless(ds, i, j, D))
            cones.push(v);
          else
            corners.push(v);
        }
      }
    }
    const front = cones.sort().reverse().join('');
    const middle = props.isLoopless(ds) ? '' : '*';
    const back = corners.sort().reverse().join('');
    const cross = props.isWeaklyOriented(ds) ? '' : 'x';
    const key = front + middle + back + cross;

    const goodKeys = [
      '', '*', 'x',
      '532', '432', '332',
      '422', '322', '222',
      '44', '33', '22',
      '*532', '*432', '*332', '3*2',
      '*422', '*322', '*222', '2*4', '2*3', '2*2',
      '*44', '*33', '*22', '4*', '3*', '2*', '4x', '3x', '2x',
    ];

    good = goodKeys.indexOf(key) >= 0;
  }

  return good;
};

const morphism = (src, srcD0, img, imgD0) => {
  const idcs = src.indices();

  const q = [[srcD0, imgD0]];
  const m = new Array(src.size + 1);
  m[srcD0] = imgD0;

  while (q.length) {
    const [D, E] = q.shift();

    for (const i of idcs) {
      const Di = src.s(i, D);
      const Ei = img.s(i, E);

      if (Di != null || Ei != null) {
        if (m[Di] == null) {
          q.push([Di, Ei]);
          m[Di] = Ei;
        }
        else if (m[Di] != Ei)
          return null;
      }
    }
  }

  return m;
};

const automorphisms = ds => {
  const elms = ds.elements();
  if (elms.length) {
    const D = elms[0];
    return elms.map(E => morphism(ds, D, ds, E)).filter(m => m != null);
  }
};

const curvature = ds => {
  const denom = 420;
  let numer = -ds.size * denom;
  for (const [i, j] of [[0, 1], [0, 2], [1, 2]]) {
    for (const D of ds.orbitReps2(i, j)) {
      const k = isLoopless(ds, i, j, D) ? 2 : 1;
      numer += k * denom / ds.v(i, j, D);
    }
  }
  const curv = opsQ.div(numer, denom);

  return curv;
};

const withMinimalBranchings = ds => {
  const s = new Array((ds.dim +1) * ds.size).fill(0);
  const v = new Array(ds.dim * ds.size).fill(0);

  for (let D = 1; D <= ds.size; ++D) {
    for (let i = 0; i <= ds.dim; ++i)
      s[i * ds.size + D - 1] = ds.s(i, D);
  }

  for (let i = 0; i < ds.dim; ++i) {
    const j = i + 1;
    for (const D of ds.orbitReps2(i, j)) {
      const q = Math.ceil(3 / ds.r(i, j, D));
      for (const E of ds.orbit2(i, j, D))
        v[i * ds.size + E - 1] = q;
    }
  }

  return delaney.makeDSymbol(ds.dim, s, v);
};

const branchings = ds => {
  const unused = openOrbits(ds);
  const maps = automorphisms(ds);
  const ds0 = withMinimalBranchings(ds);
  const curv0 = curvature(ds0);

  return backtrack({
    root: [ds0, curv0, unused],

    extract([ds, curv, unused]) {
      if (unused.length == 0 && isCanonical(ds, maps) && goodResult(ds, curv))
        return ds;
    },

    children([ds, curv, unused]) {
      if (unused.length) {
        if (opsQ.sgn(curv) < 0)
          return [[ds, curv, []]];
        else {
          const [i, D, r, loopless] = unused[0];
          const v0 = ds.v(i, i+1, D);
          const out = [];

          for (let v = v0; v <= 7; ++v) {
            const newCurv = newCurvature(curv, loopless, v, v0);
            const newDs = withBranching(ds, i, D, v);

            if (opsQ.sgn(newCurv) >= 0 || isMinimallyHyperbolic(newDs, newCurv))
              out.push([ newDs, newCurv, unused.slice(1) ]);

            if (opsQ.sgn(newCurv) < 0)
              break;
          }

          return out;
        }
      }
    }
  });
}

if (require.main == module) {
  const arg = process.argv[2];

  if (Number.isInteger(parseInt(arg))) {
    const maxSize = parseInt(arg);
    const ds0 = delaney.parse('<1.1:1:1,1,1:0,0>');

    for (const dset of dsets2d.delaneySets(maxSize)) {
      for (const ds of branchings(dset))
        console.log(`${ds}`);
    }
  }
  else {
    for (const ds of branchings([...symbols(arg)][0]))
      console.log(`${ds}`);
  }
}
<|endoftext|>


<commit_before>'use strict';
const fileWriter = require('./lib/fileWriter'),
    serializeDocument = require('./lib/documentSerializer'),
    htmlWorker = require('./lib/htmlWorker'),
    datepickerProcessor = require('./rewriters/datepickerRewriter')
    ;

function updateDom(filePath, window, rewriters) {
    let updated = htmlWorker.updateDOM(window, rewriters);

    if (!updated) {
        return Promise.resolve({});
    }

    return Promise.resolve({
        filePath: filePath,
        processedContent: serializeDocument(window.document)
    });
}

module.exports = {
    htmlSeeker: require('./lib/htmlFilesLookup'),
    refactorAllInDirectory: function (directory, rewriters) {
        this.htmlSeeker(directory)
            .then((files) => {
                return Promise.all(files.map((filePath) => this.refactorFile(filePath, rewriters)));
            }, (err) => console.log(err))
            .then((processedFiles) =>
                fileWriter.writeAll(processedFiles.filter((file) => !!file.filePath))
        );
    },
    refactorFile: function (html, rewriters) {
        console.log('Process file: ', html);
        return htmlWorker.toDom(html).then((window) => {
            try {
                return updateDom(html, window, rewriters);
            } catch(e) {
                console.error(e.stack);
                return Promise.reject(e);
            }
        });
    }
};
<commit_msg>Removed missed package from index.js.<commit_after>'use strict';
const fileWriter = require('./lib/fileWriter'),
    serializeDocument = require('./lib/documentSerializer'),
    htmlWorker = require('./lib/htmlWorker')
    ;

function updateDom(filePath, window, rewriters) {
    let updated = htmlWorker.updateDOM(window, rewriters);

    if (!updated) {
        return Promise.resolve({});
    }

    return Promise.resolve({
        filePath: filePath,
        processedContent: serializeDocument(window.document)
    });
}

module.exports = {
    htmlSeeker: require('./lib/htmlFilesLookup'),
    refactorAllInDirectory: function (directory, rewriters) {
        this.htmlSeeker(directory)
            .then((files) => {
                return Promise.all(files.map((filePath) => this.refactorFile(filePath, rewriters)));
            }, (err) => console.log(err))
            .then((processedFiles) =>
                fileWriter.writeAll(processedFiles.filter((file) => !!file.filePath))
        );
    },
    refactorFile: function (html, rewriters) {
        console.log('Process file: ', html);
        return htmlWorker.toDom(html).then((window) => {
            try {
                return updateDom(html, window, rewriters);
            } catch(e) {
                console.error(e.stack);
                return Promise.reject(e);
            }
        });
    }
};
<|endoftext|>


<commit_before>'use strict';
/*jslint node: true */
/*jslint unparam: true */
/*global which, gulp, tempdir, test, exec, ls */
var gutil = require('gulp-util'),
    shelljs = require('shelljs/global'),
    through = require('through2'),

    stream = through.obj(function (file, enc, callback) {
        this.push(file);
        callback();
    });

var build_arguments = function (opts) {
        var i, args = [], // initialize command array
            keys = Object.keys(opts),
            parameter;
        for (i = 0; i < keys.length; i += 1) {
            if (opts[keys[i]]) { //handle false case if passed in explicitly
                parameter = ((keys[i].length === 1) ? '-' : '--'); // use - for d, w, n, etc.
                parameter += keys[i]; // add parameter name
                if (typeof opts[keys[i]] !== 'boolean') {
                    parameter += ' ' + opts[keys[i]];
                }
                args.push(parameter); // add parameter to command array
            }
        }
        return args.join(' ');
    },
    log_indent = '|   ',
    log_exec = function (output) {
        var output_lines, log_line;
        if (output) {
            output_lines = output.replace(/^\s+|\s+$/, '').split(/[\n\r]+/); // Trims the output and returns it split into an array of lines
            for (log_line = 0; log_line < output_lines.length; log_line += 1) {
                gutil.log(log_indent, output_lines[log_line]);
            }
        }
    };
/*jslint unparam: false*/

if (!which('php')) {
    stream.emit('error', new gutil.PluginError('gulp-composer', "PHP is a composer requirement and therefore it is required to use gulp-composer."));
}
module.exports = function (cmd, opts) {
    var commandToRun, execReturn,
        self_install = true,
        async = true,
        bin, cwd,
        handle_exec = function (code, output) {
            if (code !== 0) {
                stream.emit('error', new gutil.PluginError('gulp-composer', output));
            }

            log_exec(output);

            gutil.log(gutil.colors.cyan.inverse(" Composer completed.                                                       "));

            stream.end();
            stream.emit("end");
        };

    if (cmd === undefined || typeof cmd === 'object') {
        // Looks like this was called with either no parameters
        // or the options were passed through the first parameter
        // In this case, we'll ignore all subsequent params
        opts = cmd || {};
        cmd = 'install';
    } else {
        // Make sure opts is set
        opts = opts || {};
    }

    // optional self-install support
    if (opts['self-install'] !== undefined) {
        self_install = !!opts['self-install'];
        delete opts['self-install']; // avoid sending parameter to composer
    }

    // optional async support
    if (opts.async !== undefined) {
        async = !!opts.async;
        delete opts.async; // avoid sending parameter to composer
    }

    // cwd legacy support
    cwd = "\"" + (opts['working-dir'] || opts.d || opts.cwd || process.cwd()) + "\"";

    // using --working-dir=xxxx instead of -d makes logging clearer
    // and allows us to remove an unneeded `gutil.log` line
    opts['working-dir'] = cwd;

    delete opts.cwd; // avoid sending parameter to composer
    delete opts.d; // avoid sending duplicate -d parameter

    // Ensure opts.quiet is a bool
    opts.quiet = !!opts.quiet;

    if (!opts.quiet) {
        // Turn colors on by default
        if (!opts['no-ansi'] && opts.ansi === undefined) {
            opts.ansi = true;
        }
    }

    if (opts.bin === 'auto') {
        delete opts.bin;
    }

    bin = opts.bin || (function () {
        var self_install_cmd,
            self_install_dir = tempdir(),
            self_install_file = 'gulp-composer.phar',
            self_install_path = self_install_dir + '/' + self_install_file,
            self_install_options = build_arguments({
                'install-dir': self_install_dir,
                'filename': self_install_file,
                'quiet': opts.quiet,
                'ansi': opts.ansi,
                'no-ansi': !opts.ansi
            }),
            self_install_alert = function () {
                gutil.log();
                gutil.log(gutil.colors.yellow.inverse(" Significantly improve performance by installing composer on this machine. "));
                gutil.log(gutil.colors.yellow.inverse(" Installation: ") + gutil.colors.yellow.underline.inverse("https://getcomposer.org/doc/00-intro.md") + gutil.colors.yellow.inverse("                     "));
                gutil.log();
            };

        // Use composer.phar if it exists locally...
        if (test('-e', cwd + '/composer.phar')) {
            gutil.log(gutil.colors.green("Defaulting to locally installed " + cwd + "/composer.phar..."));
            return cwd + '/composer.phar';
        }
        gutil.log(gutil.colors.yellow("Composer is not available locally."));

        // Otherwise use composer if it's installed globally...
        if (which('composer')) {
            gutil.log(gutil.colors.green("Defaulting to globally installed composer..."));
			self_install = false;
            return 'composer';
        }
        gutil.log(gutil.colors.yellow("Composer is not available globally."));

        if (!self_install) {
            gutil.log(gutil.colors.red.inverse("Failed to load composer and self-install has been disabled."));
            gutil.log(gutil.colors.red.inverse("Installation instructions: ") + gutil.colors.blue.underline.inverse("https://getcomposer.org/doc/00-intro.md"));
            return '';
        }

        if (test('-e', self_install_path)) {
            gutil.log(gutil.colors.yellow("Loading composer from system temp directory..."));
            self_install_alert();
            return self_install_path;
        }

        gutil.log(gutil.colors.yellow("Composer is not available from the system temp, either."));

        // It doesn't exist, so we'll attempt to download it locally and delete it afterward
        if (self_install_options) {
            self_install_options = ' -- ' + self_install_options;
        }

        gutil.log(gutil.colors.magenta.inverse(" Attempting to download composer to system temp directory...               "));
        self_install_cmd = exec('php -r "readfile(\'https://getcomposer.org/installer\');" | php' + self_install_options, {
            async: false,
            silent: true
        });

        if (self_install_cmd.code !== 0) {
            stream.emit('error', new gutil.PluginError('gulp-composer', self_install_cmd.output));
        }
        log_exec(self_install_cmd.output);

        if (ls(self_install_path)[0]) {
            gutil.log(gutil.colors.magenta.inverse(" Successfully downloaded!                                                  "));
            self_install_alert();
            return self_install_path;
        }

        gutil.log(gutil.colors.red.inverse("Failed to download. All options have been exhausted."));
        gutil.log(gutil.colors.red.inverse("Installation instructions: ") + gutil.colors.blue.underline.inverse("https://getcomposer.org/doc/00-intro.md"));

        return '';
    }());
    delete opts.bin; // avoid sending bin parameter

    if (!bin) {
        stream.emit('error', new gutil.PluginError('gulp-composer', "Composer executable does not exist. " + (self_install ? "Self-install was unsuccessful. Please install before continuing." : "Please install or enable the self-install option before continuing.")));
    }

	// fix self install command
	if(self_install) {
        bin = 'php ' + bin;
    }

    // build the command array
    commandToRun = [bin, cmd, build_arguments(opts)].join(' ');
    gutil.log(gutil.colors.red(commandToRun));
    gutil.log();
    gutil.log(gutil.colors.cyan.inverse(" Executing composer...                                                     "));

    if (async) {
        exec(commandToRun, {
            silent: true
        }, handle_exec);
    } else {
        execReturn = exec(commandToRun, {
            silent: true,
            async: false
        });
        if(typeof execReturn.output === 'undefined') execReturn.output = execReturn.stderr;
        handle_exec(execReturn.code, execReturn.output);
    }

    return stream;
};
<commit_msg>When using custom binary turn of self install.<commit_after>'use strict';
/*jslint node: true */
/*jslint unparam: true */
/*global which, gulp, tempdir, test, exec, ls */
var gutil = require('gulp-util'),
    shelljs = require('shelljs/global'),
    through = require('through2'),

    stream = through.obj(function (file, enc, callback) {
        this.push(file);
        callback();
    });

var build_arguments = function (opts) {
        var i, args = [], // initialize command array
            keys = Object.keys(opts),
            parameter;
        for (i = 0; i < keys.length; i += 1) {
            if (opts[keys[i]]) { //handle false case if passed in explicitly
                parameter = ((keys[i].length === 1) ? '-' : '--'); // use - for d, w, n, etc.
                parameter += keys[i]; // add parameter name
                if (typeof opts[keys[i]] !== 'boolean') {
                    parameter += ' ' + opts[keys[i]];
                }
                args.push(parameter); // add parameter to command array
            }
        }
        return args.join(' ');
    },
    log_indent = '|   ',
    log_exec = function (output) {
        var output_lines, log_line;
        if (output) {
            output_lines = output.replace(/^\s+|\s+$/, '').split(/[\n\r]+/); // Trims the output and returns it split into an array of lines
            for (log_line = 0; log_line < output_lines.length; log_line += 1) {
                gutil.log(log_indent, output_lines[log_line]);
            }
        }
    };
/*jslint unparam: false*/

if (!which('php')) {
    stream.emit('error', new gutil.PluginError('gulp-composer', "PHP is a composer requirement and therefore it is required to use gulp-composer."));
}
module.exports = function (cmd, opts) {
    var commandToRun, execReturn,
        self_install = true,
        async = true,
        bin, cwd,
        handle_exec = function (code, output) {
            if (code !== 0) {
                stream.emit('error', new gutil.PluginError('gulp-composer', output));
            }

            log_exec(output);

            gutil.log(gutil.colors.cyan.inverse(" Composer completed.                                                       "));

            stream.end();
            stream.emit("end");
        };

    if (cmd === undefined || typeof cmd === 'object') {
        // Looks like this was called with either no parameters
        // or the options were passed through the first parameter
        // In this case, we'll ignore all subsequent params
        opts = cmd || {};
        cmd = 'install';
    } else {
        // Make sure opts is set
        opts = opts || {};
    }

    // optional self-install support
    if (opts['self-install'] !== undefined) {
        self_install = !!opts['self-install'];
        delete opts['self-install']; // avoid sending parameter to composer
    }

    // optional async support
    if (opts.async !== undefined) {
        async = !!opts.async;
        delete opts.async; // avoid sending parameter to composer
    }

    // cwd legacy support
    cwd = "\"" + (opts['working-dir'] || opts.d || opts.cwd || process.cwd()) + "\"";

    // using --working-dir=xxxx instead of -d makes logging clearer
    // and allows us to remove an unneeded `gutil.log` line
    opts['working-dir'] = cwd;

    delete opts.cwd; // avoid sending parameter to composer
    delete opts.d; // avoid sending duplicate -d parameter

    // Ensure opts.quiet is a bool
    opts.quiet = !!opts.quiet;

    if (!opts.quiet) {
        // Turn colors on by default
        if (!opts['no-ansi'] && opts.ansi === undefined) {
            opts.ansi = true;
        }
    }

    if (opts.bin === 'auto') {
        delete opts.bin;
    }

    // if supplied a custom binary make sure self install is off
    if (opts.bin) {
      self_install = false;
    }

    bin = opts.bin || (function () {
        var self_install_cmd,
            self_install_dir = tempdir(),
            self_install_file = 'gulp-composer.phar',
            self_install_path = self_install_dir + '/' + self_install_file,
            self_install_options = build_arguments({
                'install-dir': self_install_dir,
                'filename': self_install_file,
                'quiet': opts.quiet,
                'ansi': opts.ansi,
                'no-ansi': !opts.ansi
            }),
            self_install_alert = function () {
                gutil.log();
                gutil.log(gutil.colors.yellow.inverse(" Significantly improve performance by installing composer on this machine. "));
                gutil.log(gutil.colors.yellow.inverse(" Installation: ") + gutil.colors.yellow.underline.inverse("https://getcomposer.org/doc/00-intro.md") + gutil.colors.yellow.inverse("                     "));
                gutil.log();
            };

        // Use composer.phar if it exists locally...
        if (test('-e', cwd + '/composer.phar')) {
            gutil.log(gutil.colors.green("Defaulting to locally installed " + cwd + "/composer.phar..."));
            return cwd + '/composer.phar';
        }
        gutil.log(gutil.colors.yellow("Composer is not available locally."));

        // Otherwise use composer if it's installed globally...
        if (which('composer')) {
            gutil.log(gutil.colors.green("Defaulting to globally installed composer..."));
			self_install = false;
            return 'composer';
        }
        gutil.log(gutil.colors.yellow("Composer is not available globally."));

        if (!self_install) {
            gutil.log(gutil.colors.red.inverse("Failed to load composer and self-install has been disabled."));
            gutil.log(gutil.colors.red.inverse("Installation instructions: ") + gutil.colors.blue.underline.inverse("https://getcomposer.org/doc/00-intro.md"));
            return '';
        }

        if (test('-e', self_install_path)) {
            gutil.log(gutil.colors.yellow("Loading composer from system temp directory..."));
            self_install_alert();
            return self_install_path;
        }

        gutil.log(gutil.colors.yellow("Composer is not available from the system temp, either."));

        // It doesn't exist, so we'll attempt to download it locally and delete it afterward
        if (self_install_options) {
            self_install_options = ' -- ' + self_install_options;
        }

        gutil.log(gutil.colors.magenta.inverse(" Attempting to download composer to system temp directory...               "));
        self_install_cmd = exec('php -r "readfile(\'https://getcomposer.org/installer\');" | php' + self_install_options, {
            async: false,
            silent: true
        });

        if (self_install_cmd.code !== 0) {
            stream.emit('error', new gutil.PluginError('gulp-composer', self_install_cmd.output));
        }
        log_exec(self_install_cmd.output);

        if (ls(self_install_path)[0]) {
            gutil.log(gutil.colors.magenta.inverse(" Successfully downloaded!                                                  "));
            self_install_alert();
            return self_install_path;
        }

        gutil.log(gutil.colors.red.inverse("Failed to download. All options have been exhausted."));
        gutil.log(gutil.colors.red.inverse("Installation instructions: ") + gutil.colors.blue.underline.inverse("https://getcomposer.org/doc/00-intro.md"));

        return '';
    }());
    delete opts.bin; // avoid sending bin parameter

    if (!bin) {
        stream.emit('error', new gutil.PluginError('gulp-composer', "Composer executable does not exist. " + (self_install ? "Self-install was unsuccessful. Please install before continuing." : "Please install or enable the self-install option before continuing.")));
    }

	// fix self install command
	if(self_install) {
        bin = 'php ' + bin;
    }

    // build the command array
    commandToRun = [bin, cmd, build_arguments(opts)].join(' ');
    gutil.log(gutil.colors.red(commandToRun));
    gutil.log();
    gutil.log(gutil.colors.cyan.inverse(" Executing composer...                                                     "));

    if (async) {
        exec(commandToRun, {
            silent: true
        }, handle_exec);
    } else {
        execReturn = exec(commandToRun, {
            silent: true,
            async: false
        });
        if(typeof execReturn.output === 'undefined') execReturn.output = execReturn.stderr;
        handle_exec(execReturn.code, execReturn.output);
    }

    return stream;
};
<|endoftext|>


<commit_before>"use strict";

var fs            = require('fs'),
    EventEmitter  = require('events').EventEmitter,
    through       = require('through'),
    utils         = require('lodash');

/**
 * Decorator for dgraph which watches modules for changes and emits an 'update'
 * event.
 *
 * Possible options are:
 * - delay - delay before firing an event, allows I/O to calm down
 * - watchAll - allow watching for modules in node_modules
 */
function GraphLive(graph, opts) {
  this.graph = graph;
  this.opts = opts || {};
  this.watching = {};
  this.update = utils.debounce(
    this.update,
    this.opts.delay || 100,
    {maxWait: 1000});
}

GraphLive.prototype = {

  needWatch: function(id) {
    return this.opts.watchAll || !this.opts.watchAll && !id.match(/node_modules/)
  },

  close: function() {
    for (var id in this.watching) {
      this.watching[id].close();
      this.watching[id] = undefined;
    }
  },

  update: function(id, detected) {
    this.emit('update', id, detected);
  },

  watchModule: function(id) {
    this.watching[id] = fs.watch(id, function() {
      this.graph.invalidateModule(id);
      this.update(id, Date.now());
    }.bind(this));
  },

  toStream: function() {
    var interceptor = through(function(mod) {
      if (!this.watching[mod.id] && this.needWatch(mod.id))
        this.watchModule(mod.id);
      interceptor.queue(mod);
    }.bind(this));

    return this.graph.toStream()
      .on('error', function(err) { interceptor.emit('error', err); })
      .pipe(interceptor);
  }
};

utils.assign(GraphLive.prototype, EventEmitter.prototype);

module.exports = function(graph, opts) {
  return new GraphLive(graph, opts);
}
<commit_msg>Re-install watchers on change<commit_after>"use strict";

var fs            = require('fs'),
    EventEmitter  = require('events').EventEmitter,
    through       = require('through'),
    utils         = require('lodash');

/**
 * Decorator for dgraph which watches modules for changes and emits an 'update'
 * event.
 *
 * Possible options are:
 * - delay - delay before firing an event, allows I/O to calm down
 * - watchAll - allow watching for modules in node_modules
 */
function GraphLive(graph, opts) {
  this.graph = graph;
  this.opts = opts || {};
  this.watching = {};
  this.update = utils.debounce(
    this.update,
    this.opts.delay || 100,
    {maxWait: 1000});
}

GraphLive.prototype = {

  needWatch: function(id) {
    return this.opts.watchAll || !this.opts.watchAll && !id.match(/node_modules/)
  },

  close: function() {
    for (var id in this.watching) {
      this.watching[id].close();
      this.watching[id] = undefined;
    }
  },

  update: function(id, detected) {
    this.emit('update', id, detected);
    this.watchModule(id);
  },

  watchModule: function(id) {
    this.watching[id] = fs.watch(id, function() {
      this.watching[id].close();
      this.watching[id] = undefined;
      this.graph.invalidateModule(id);
      this.update(id, Date.now());
    }.bind(this));
  },

  toStream: function() {
    var interceptor = through(function(mod) {
      if (!this.watching[mod.id] && this.needWatch(mod.id))
        this.watchModule(mod.id);
      interceptor.queue(mod);
    }.bind(this));

    return this.graph.toStream()
      .on('error', function(err) { interceptor.emit('error', err); })
      .pipe(interceptor);
  }
};

utils.assign(GraphLive.prototype, EventEmitter.prototype);

module.exports = function(graph, opts) {
  return new GraphLive(graph, opts);
}
<|endoftext|>


<commit_before>'use strict';

const qiniu = require('qiniu');
const path = require('path');
const ora = require('ora');
const isRegExp = require('lodash.isregexp');

// Constants
const REGEXP_HASH = /\[hash(?::(\d+))?\]/gi;

// Uploading progress tip
const tip = (uploaded, total) => {
  let percentage = Math.round(uploaded / total * 100);
  return `Uploading to Qiniu CDN: ${percentage}% ${uploaded}/${total} files uploaded`;
};

// Replace path variable by hash with length
const withHashLength = (replacer) => {
  return function(_, hashLength) {
    const length = hashLength && parseInt(hashLength, 10);
    const hash = replacer.apply(this, arguments);
    return length ? hash.slice(0, length) : hash;
  };
};

// Perform hash replacement
const getReplacer = (value, allowEmpty) => {
  return function(match) {
    // last argument in replacer is the entire input string
    const input = arguments[arguments.length - 1];
    if(value === null || value === undefined) {
      if(!allowEmpty) throw new Error(`Path variable ${match} not implemented in this context of qn-webpack plugin: ${input}`);
      return '';
    } else {
      return `${value}`;
    }
  };
};

module.exports = class QiniuPlugin {
  constructor(options) {
    this.options = Object.assign({}, options);
  }

  apply(compiler) {
    compiler.plugin('after-emit', (compilation, callback) => {

      let assets = compilation.assets;
      let hash = compilation.hash;
      let uploadPath = this.options.path || '[hash]';
      let exclude = isRegExp(this.options.exclude) && this.options.exclude;
      let include = isRegExp(this.options.include) && this.options.include;
      let batch = this.options.batch || 50;
      let mac = new qiniu.auth.digest.Mac(this.options.accessKey, this.options.secretKey);
      let qiniuConfig = new qiniu.conf.Config();
      let bucket = this.options.bucket;
      let zone = this.options.zone;
      if (zone) qiniuConfig.zone = qiniu.zone[zone];
      uploadPath = uploadPath.replace(REGEXP_HASH, withHashLength(getReplacer(hash)));

      let filesNames = Object.keys(assets);
      let totalFiles = 0;
      let uploadedFiles = 0;

      // Mark finished
      let _finish = (err) => {
        spinner.succeed();
        // eslint-disable-next-line no-console
        console.log('\n');
        callback(err);
      };

      // Filter files that should be uploaded to Qiniu CDN
      filesNames = filesNames.filter(fileName => {
        let file = assets[fileName] || {};

        // Ignore unemitted files
        if (!file.emitted) return false;

        // Check excluced files
        if (exclude && exclude.test(fileName)) return false;

        // Check included files
        if (include) return include.test(fileName);

        return true;
      });

      totalFiles = filesNames.length;

      // eslint-disable-next-line no-console
      console.log('\n');
      let spinner = ora({
        text: tip(0, totalFiles),
        color: 'green'
      }).start();

      // Perform upload to qiniu
      const performUpload =function(fileName) {
        let file = assets[fileName] || {};
        let key = path.posix.join(uploadPath, fileName);
        let putPolicy = new qiniu.rs.PutPolicy({ scope: bucket + ':' + key });
        let uploadToken = putPolicy.uploadToken(mac);
        let formUploader = new qiniu.form_up.FormUploader(qiniuConfig);
        let putExtra = new qiniu.form_up.PutExtra();

        return new Promise((resolve, reject) => {
          let begin = Date.now();
          formUploader.putFile(uploadToken, key, file.existsAt, putExtra, function(respErr, respBody, respInfo) {
            uploadedFiles++;
            spinner.text = tip(uploadedFiles, totalFiles);

            if (respErr) return reject(respErr);
            respBody.duration = Date.now() - begin;
            resolve(respBody);
          })
        });
      };

      // Execute stack according to `batch` option
      const execStack = function(err) {
        if (err) {
          // eslint-disable-next-line no-console
          console.log('\n');
          return Promise.reject(err);
        }

        // Get 50 files
        let _files = filesNames.splice(0, batch);

        if (_files.length) {
          return Promise.all(
            _files.map(performUpload)
          ).then(() => execStack(), execStack);
        } else {
          return Promise.resolve();
        }
      };

      execStack().then(() => _finish(), _finish);
    });
  }
};
<commit_msg>zone 参数修改<commit_after>'use strict';

const qiniu = require('qiniu');
const path = require('path');
const ora = require('ora');
const isRegExp = require('lodash.isregexp');

// Constants
const REGEXP_HASH = /\[hash(?::(\d+))?\]/gi;

// Uploading progress tip
const tip = (uploaded, total) => {
  let percentage = Math.round(uploaded / total * 100);
  return `Uploading to Qiniu CDN: ${percentage}% ${uploaded}/${total} files uploaded`;
};

// Replace path variable by hash with length
const withHashLength = (replacer) => {
  return function(_, hashLength) {
    const length = hashLength && parseInt(hashLength, 10);
    const hash = replacer.apply(this, arguments);
    return length ? hash.slice(0, length) : hash;
  };
};

// Perform hash replacement
const getReplacer = (value, allowEmpty) => {
  return function(match) {
    // last argument in replacer is the entire input string
    const input = arguments[arguments.length - 1];
    if(value === null || value === undefined) {
      if(!allowEmpty) throw new Error(`Path variable ${match} not implemented in this context of qn-webpack plugin: ${input}`);
      return '';
    } else {
      return `${value}`;
    }
  };
};

module.exports = class QiniuPlugin {
  constructor(options) {
    this.options = Object.assign({}, options);
  }

  apply(compiler) {
    compiler.plugin('after-emit', (compilation, callback) => {

      let assets = compilation.assets;
      let hash = compilation.hash;
      let uploadPath = this.options.path || '[hash]';
      let exclude = isRegExp(this.options.exclude) && this.options.exclude;
      let include = isRegExp(this.options.include) && this.options.include;
      let batch = this.options.batch || 50;
      let mac = new qiniu.auth.digest.Mac(this.options.accessKey, this.options.secretKey);
      let qiniuConfig = new qiniu.conf.Config();
      let bucket = this.options.bucket;
      let zone = qiniu.zone[this.options.zone];
      if (zone) qiniuConfig.zone = zone;
      uploadPath = uploadPath.replace(REGEXP_HASH, withHashLength(getReplacer(hash)));

      let filesNames = Object.keys(assets);
      let totalFiles = 0;
      let uploadedFiles = 0;

      // Mark finished
      let _finish = (err) => {
        spinner.succeed();
        // eslint-disable-next-line no-console
        console.log('\n');
        callback(err);
      };

      // Filter files that should be uploaded to Qiniu CDN
      filesNames = filesNames.filter(fileName => {
        let file = assets[fileName] || {};

        // Ignore unemitted files
        if (!file.emitted) return false;

        // Check excluced files
        if (exclude && exclude.test(fileName)) return false;

        // Check included files
        if (include) return include.test(fileName);

        return true;
      });

      totalFiles = filesNames.length;

      // eslint-disable-next-line no-console
      console.log('\n');
      let spinner = ora({
        text: tip(0, totalFiles),
        color: 'green'
      }).start();

      // Perform upload to qiniu
      const performUpload =function(fileName) {
        let file = assets[fileName] || {};
        let key = path.posix.join(uploadPath, fileName);
        let putPolicy = new qiniu.rs.PutPolicy({ scope: bucket + ':' + key });
        let uploadToken = putPolicy.uploadToken(mac);
        let formUploader = new qiniu.form_up.FormUploader(qiniuConfig);
        let putExtra = new qiniu.form_up.PutExtra();

        return new Promise((resolve, reject) => {
          let begin = Date.now();
          formUploader.putFile(uploadToken, key, file.existsAt, putExtra, function(respErr, respBody, respInfo) {
            uploadedFiles++;
            spinner.text = tip(uploadedFiles, totalFiles);

            if (respErr) return reject(respErr);
            respBody.duration = Date.now() - begin;
            resolve(respBody);
          })
        });
      };

      // Execute stack according to `batch` option
      const execStack = function(err) {
        if (err) {
          // eslint-disable-next-line no-console
          console.log('\n');
          return Promise.reject(err);
        }

        // Get 50 files
        let _files = filesNames.splice(0, batch);

        if (_files.length) {
          return Promise.all(
            _files.map(performUpload)
          ).then(() => execStack(), execStack);
        } else {
          return Promise.resolve();
        }
      };

      execStack().then(() => _finish(), _finish);
    });
  }
};
<|endoftext|>


<commit_before>var basicEventuate = require('./basic'),
    pre            = require('call-hook/pre'),
    post           = require('call-hook/post')

module.exports = createEventuate

function createEventuate (options) {
    var eventuate              = basicEventuate(options)

    eventuate.consumerAdded    = basicEventuate({ destroyResidual: false })
    eventuate.consumerRemoved  = basicEventuate({ destroyResidual: false })
    eventuate.destroyed        = basicEventuate({ destroyResidual: false })
    eventuate.error            = basicEventuate({ destroyResidual: false })
    eventuate.produce          = pre(eventuate.produce, splitErrors)
    eventuate.consume          = post(eventuate.consume, eventuate.consumerAdded.produce)
    eventuate.removeConsumer   = post(eventuate.removeConsumer, consumerRemoved)
    eventuate.destroy          = post(eventuate.destroy, eventuate.destroyed.produce)
    eventuate.factory          = createEventuate
    eventuate.factory.basic    = basicEventuate

    return eventuate

    function splitErrors (data) {
        if (data instanceof Error && eventuate.error.hasConsumer()) {
            eventuate.error.produce(data)
            this.abort()
        }
    }

    function consumerRemoved (consumer) {
        if (this.returnValue) eventuate.consumerRemoved.produce(consumer)
        return this.returnValue
    }
}
<commit_msg>preserve return values of consume and destroy<commit_after>var basicEventuate = require('./basic'),
    pre            = require('call-hook/pre'),
    post           = require('call-hook/post')

module.exports = createEventuate

function createEventuate (options) {
    var eventuate              = basicEventuate(options)

    eventuate.consumerAdded    = basicEventuate({ destroyResidual: false })
    eventuate.consumerRemoved  = basicEventuate({ destroyResidual: false })
    eventuate.destroyed        = basicEventuate({ destroyResidual: false })
    eventuate.error            = basicEventuate({ destroyResidual: false })
    eventuate.produce          = pre(eventuate.produce, splitErrors)
    eventuate.consume          = post(eventuate.consume, consumerAdded)
    eventuate.removeConsumer   = post(eventuate.removeConsumer, consumerRemoved)
    eventuate.destroy          = post(eventuate.destroy, destroyed)
    eventuate.factory          = createEventuate
    eventuate.factory.basic    = basicEventuate

    return eventuate

    function splitErrors (data) {
        if (data instanceof Error && eventuate.error.hasConsumer()) {
            eventuate.error.produce(data)
            this.abort()
        }
    }

    function consumerAdded (consumer) {
        eventuate.consumerAdded.produce(consumer)
        return this.returnValue
    }

    function consumerRemoved (consumer) {
        if (this.returnValue) eventuate.consumerRemoved.produce(consumer)
        return this.returnValue
    }

    function destroyed () {
        eventuate.destroyed.produce()
        return this.returnValue
    }

}
<|endoftext|>


<commit_before>'use strict'

// setup
const http = require('http')
const Pg = require('pg').Pool
const jsonwebtoken = require('jsonwebtoken')
const tinyParams = require('tiny-params')
const port = process.env.PORT || process.env.port || 8091
const handlers = {
  search: resourceSearch,
  create: resourceCreate,
  read: resourceRead,
  update: resourceUpdate,
  delete: resourceDelete
}
const scrud = {
  GET: 'search',
  'GET?': 'search',
  POST: 'create',
  'POST/': 'create',
  'GET/': 'read',
  'PUT/': 'update',
  'DELETE/': 'delete'
}
const hasBody = {create: true, update: true}
const wlSign = [
  'algorithm',
  'expiresIn',
  'notBefore',
  'audience',
  'issuer',
  'jwtid',
  'subject',
  'noTimestamp',
  'header'
]

// globals
let logger
let pgPool
let jwtOpts
let authTrans
let pgPrefix = ''
let base = ''
let baseRgx = new RegExp(`^/?${base}/`)
let maxBodyBytes = 1e6
let resources = {}

// local helpers
const logIt = (e) => typeof logger === 'function' ? logger(e) : console.log(e)

const cleanPath = (url) => {
  return decodeURIComponent(url).replace(baseRgx, '').replace(/\/$/, '')
}

const parseId = (url) => {
  let id = (url.match(/\/(.+?)(\/|\?|$)/) || [])[1]
  return (id || '').match(/^\d+$/) ? parseInt(id, 10) : id || null
}

const callPgFunc = (name, params) => {
  let q = `SELECT * FROM ${name}($1);`
  if (!pgPool) return Promise.reject(new Error('no database configured'))
  return new Promise((resolve, reject) => {
    pgPool.connect((err, client, done) => {
      if (err) return reject(err)
      client.query(q, [params], (err, result) => {
        done(err)
        if (err) return reject(err)
        resolve((result.rows[0] || {})[name] ? result.rows[0][name] : [])
      })
    })
  })
}

const bodyParse = (req) => new Promise((resolve, reject) => {
  let body = ''
  req.on('data', (d) => {
    body += d.toString()
    if (body.length > maxBodyBytes) return reject(new Error('body too large'))
  })
  req.on('end', () => resolve(body ? JSON.parse(body) : {}))
})

const noIdErr = () => JSON.stringify(new Error('no id passed'))

const filterObj = (obj, ary) => {
  let base = {}
  ary.forEach((o) => { base[o] = obj[o] })
  return base
}

// exports
module.exports = {
  register,
  start,
  sendData,
  sendErr,
  fourOhOne,
  fourOhFour,
  genToken,
  authenticate,
  find,
  findAll,
  create,
  save,
  destroy
}

// register resource
function register (name, opts = {}) {
  if (!name) return Promise.reject(new Error(`no name specified in register`))
  return new Promise((resolve, reject) => {
    let r = resources[name] = Object.assign(opts, {name})
    if (Array.isArray(r.skipAuth)) {
      let skippers = {}
      r.skipAuth.forEach((a) => { skippers[a] = true })
      r.skipAuth = skippers
    }
    return resolve(r)
  })
}

// start server
function start (opts = {}) {
  if (opts.namespace) pgPrefix = `${opts.namespace.toLowerCase()}_`
  if (opts.maxBodyBytes) maxBodyBytes = opts.maxBodyBytes
  if (opts.jsonwebtoken) jwtOpts = opts.jsonwebtoken
  if (opts.logger) base = opts.logger
  if (opts.base) base = opts.base
  if (opts.authTrans) authTrans = opts.authTrans
  baseRgx = new RegExp(`^/?${base}/`)
  return new Promise((resolve, reject) => {
    let server = http.createServer(handleRequest)
    server.listen(opts.port || port)
    if (opts.postgres) pgPool = new Pg(opts.postgres)
    return resolve(server)
  })
}

// request handler
function handleRequest (req, res) {
  if (!baseRgx.test(req.url)) return fourOhFour(res)
  let url = cleanPath(req.url)
  let matches = url.match(/^\/?(.+?)(\/|\?|$)/) || []
  let resource = resources[matches[1] || '']
  let modifier = matches[2]
  let action = scrud[`${req.method}${modifier}`]
  if (!resource || !action) return fourOhFour(res)
  res.setHeader('Content-Type', 'application/json')
  res.setHeader('SCRUD', `${resource.name}:${action}`)
  req.id = parseId(url)
  req.params = tinyParams(url)
  let headers = req.headers || {}
  let connection = req.connection || {}
  req.params.ip = headers['x-forwarded-for'] || connection.remoteAddress
  req.once('error', (err) => sendErr(res, err))
  let handler = (resource[action] || handlers[action])
  let jwt = (headers.authorization || '').replace(/^Bearer\s/, '')
  let callHandler = () => {
    if (!hasBody[action]) return handler(req, res, resource.name)
    bodyParse(req).then((body) => {
      req.params = Object.assign(body, req.params)
      return handler(req, res, resource.name)
    })
  }
  if (resource.skipAuth && resource.skipAuth[action]) return callHandler()
  authenticate(jwt).then((authData) => {
    req.auth = req.params.auth = authTrans ? authTrans(authData) : authData
    return callHandler()
  }).catch((err) => fourOhOne(res, err))
}

function sendData (res, data = null) {
  return res.end(`{"data": ${JSON.stringify(data)}, "error": null}`)
}

function sendErr (res, err = new Error(), code = 500) {
  res.statusCode = code
  logIt(err, 'fatal')
  err = err instanceof Error ? (err.message || err.name) : err.toString()
  return res.end(`{"data": null, "error": "${err}"}`)
}

function fourOhOne (res, err = new Error(`unable to auhenticate request`)) {
  return sendErr(res, err, 401)
}

function fourOhFour (res, err = new Error(`no match for requested route`)) {
  return sendErr(res, err, 404)
}

function genToken (payload = {}) {
  let key = jwtOpts.secret || jwtOpts.privateKey
  let noOpts = () => new Error('missing required jsonwebtoken opts')
  if (!jwtOpts || !key) return Promise.reject(noOpts())
  let opts = filterObj(jwtOpts, wlSign)
  return new Promise((resolve, reject) => {
    jsonwebtoken.sign(payload, key, opts, (err, token) => {
      return err ? reject(err) : resolve(token)
    })
  })
}

function authenticate (jwt) {
  let key = jwtOpts.secret || jwtOpts.publicKey
  if (!jwtOpts || !key) return Promise.resolve()
  return new Promise((resolve, reject) => {
    jsonwebtoken.verify(jwt, key, jwtOpts, (err, d = {}) => {
      return err ? reject(err) : resolve(d)
    })
  })
}

// helper: find resource
function find (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id_array = [id]
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_read`, params).then(firstRecord)
}

// helper: find set of resources
function findAll (resource, params) {
  Object.keys(params).forEach((k) => {
    if (!Array.isArray(params[k])) return
    params[`${k}_array`] = params[k]
    delete params[k]
  })
  return callPgFunc(`${pgPrefix}${resource}_search`, params)
}

// helper: create resource
function create (resource, params) {
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_create`, params).then(firstRecord)
}

// helper: update resource
function save (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id = id
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_update`, params).then(firstRecord)
}

// helper: delete resource
function destroy (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id = id
  return callPgFunc(`${pgPrefix}${resource}_delete`, params)
}

// resource method: search
function resourceSearch (req, res, name) {
  findAll(name, req.params).then((d) => {
    return sendData(res, d)
  }).catch((e) => sendErr(res, e))
}

// resource method: create
function resourceCreate (req, res, name) {
  create(name, req.params).then((d) => {
    return sendData(res, d)
  }).catch((err) => sendErr(res, err))
}

// resource method: read
function resourceRead (req, res, name) {
  find(name, req.id, req.params).then((d) => {
    return sendData(res, d)
  }).catch((err) => sendErr(res, err))
}

// resource method: update
function resourceUpdate (req, res, name) {
  save(name, req.id, req.params).then((d) => {
    return sendData(res, d)
  }).catch((err) => sendErr(res, err))
}

// resource method: delete
function resourceDelete (req, res, name) {
  destroy(name, req.id, req.params).then((d) => {
    return sendData(res, 'success')
  }).catch((err) => sendErr(res, err))
}
<commit_msg>Stringify object on send<commit_after>'use strict'

// setup
const http = require('http')
const Pg = require('pg').Pool
const jsonwebtoken = require('jsonwebtoken')
const tinyParams = require('tiny-params')
const port = process.env.PORT || process.env.port || 8091
const handlers = {
  search: resourceSearch,
  create: resourceCreate,
  read: resourceRead,
  update: resourceUpdate,
  delete: resourceDelete
}
const scrud = {
  GET: 'search',
  'GET?': 'search',
  POST: 'create',
  'POST/': 'create',
  'GET/': 'read',
  'PUT/': 'update',
  'DELETE/': 'delete'
}
const hasBody = {create: true, update: true}
const wlSign = [
  'algorithm',
  'expiresIn',
  'notBefore',
  'audience',
  'issuer',
  'jwtid',
  'subject',
  'noTimestamp',
  'header'
]

// globals
let logger
let pgPool
let jwtOpts
let authTrans
let pgPrefix = ''
let base = ''
let baseRgx = new RegExp(`^/?${base}/`)
let maxBodyBytes = 1e6
let resources = {}

// local helpers
const logIt = (e) => typeof logger === 'function' ? logger(e) : console.log(e)

const cleanPath = (url) => {
  return decodeURIComponent(url).replace(baseRgx, '').replace(/\/$/, '')
}

const parseId = (url) => {
  let id = (url.match(/\/(.+?)(\/|\?|$)/) || [])[1]
  return (id || '').match(/^\d+$/) ? parseInt(id, 10) : id || null
}

const callPgFunc = (name, params) => {
  let q = `SELECT * FROM ${name}($1);`
  if (!pgPool) return Promise.reject(new Error('no database configured'))
  return new Promise((resolve, reject) => {
    pgPool.connect((err, client, done) => {
      if (err) return reject(err)
      client.query(q, [params], (err, result) => {
        done(err)
        if (err) return reject(err)
        resolve((result.rows[0] || {})[name] ? result.rows[0][name] : [])
      })
    })
  })
}

const bodyParse = (req) => new Promise((resolve, reject) => {
  let body = ''
  req.on('data', (d) => {
    body += d.toString()
    if (body.length > maxBodyBytes) return reject(new Error('body too large'))
  })
  req.on('end', () => resolve(body ? JSON.parse(body) : {}))
})

const noIdErr = () => JSON.stringify(new Error('no id passed'))

const filterObj = (obj, ary) => {
  let base = {}
  ary.forEach((o) => { base[o] = obj[o] })
  return base
}

// exports
module.exports = {
  register,
  start,
  sendData,
  sendErr,
  fourOhOne,
  fourOhFour,
  genToken,
  authenticate,
  find,
  findAll,
  create,
  save,
  destroy
}

// register resource
function register (name, opts = {}) {
  if (!name) return Promise.reject(new Error(`no name specified in register`))
  return new Promise((resolve, reject) => {
    let r = resources[name] = Object.assign(opts, {name})
    if (Array.isArray(r.skipAuth)) {
      let skippers = {}
      r.skipAuth.forEach((a) => { skippers[a] = true })
      r.skipAuth = skippers
    }
    return resolve(r)
  })
}

// start server
function start (opts = {}) {
  if (opts.namespace) pgPrefix = `${opts.namespace.toLowerCase()}_`
  if (opts.maxBodyBytes) maxBodyBytes = opts.maxBodyBytes
  if (opts.jsonwebtoken) jwtOpts = opts.jsonwebtoken
  if (opts.logger) base = opts.logger
  if (opts.base) base = opts.base
  if (opts.authTrans) authTrans = opts.authTrans
  baseRgx = new RegExp(`^/?${base}/`)
  return new Promise((resolve, reject) => {
    let server = http.createServer(handleRequest)
    server.listen(opts.port || port)
    if (opts.postgres) pgPool = new Pg(opts.postgres)
    return resolve(server)
  })
}

// request handler
function handleRequest (req, res) {
  if (!baseRgx.test(req.url)) return fourOhFour(res)
  let url = cleanPath(req.url)
  let matches = url.match(/^\/?(.+?)(\/|\?|$)/) || []
  let resource = resources[matches[1] || '']
  let modifier = matches[2]
  let action = scrud[`${req.method}${modifier}`]
  if (!resource || !action) return fourOhFour(res)
  res.setHeader('Content-Type', 'application/json')
  res.setHeader('SCRUD', `${resource.name}:${action}`)
  req.id = parseId(url)
  req.params = tinyParams(url)
  let headers = req.headers || {}
  let connection = req.connection || {}
  req.params.ip = headers['x-forwarded-for'] || connection.remoteAddress
  req.once('error', (err) => sendErr(res, err))
  let handler = (resource[action] || handlers[action])
  let jwt = (headers.authorization || '').replace(/^Bearer\s/, '')
  let callHandler = () => {
    if (!hasBody[action]) return handler(req, res, resource.name)
    bodyParse(req).then((body) => {
      req.params = Object.assign(body, req.params)
      return handler(req, res, resource.name)
    })
  }
  if (resource.skipAuth && resource.skipAuth[action]) return callHandler()
  authenticate(jwt).then((authData) => {
    req.auth = req.params.auth = authTrans ? authTrans(authData) : authData
    return callHandler()
  }).catch((err) => fourOhOne(res, err))
}

function sendData (res, data = null) {
  return res.end(JSON.stringify({data, error: null}))
}

function sendErr (res, err = new Error(), code = 500) {
  res.statusCode = code
  logIt(err, 'fatal')
  err = err instanceof Error ? (err.message || err.name) : err.toString()
  return res.end(JSON.stringify({data: null, error: err}))
}

function fourOhOne (res, err = new Error(`unable to auhenticate request`)) {
  return sendErr(res, err, 401)
}

function fourOhFour (res, err = new Error(`no match for requested route`)) {
  return sendErr(res, err, 404)
}

function genToken (payload = {}) {
  let key = jwtOpts.secret || jwtOpts.privateKey
  let noOpts = () => new Error('missing required jsonwebtoken opts')
  if (!jwtOpts || !key) return Promise.reject(noOpts())
  let opts = filterObj(jwtOpts, wlSign)
  return new Promise((resolve, reject) => {
    jsonwebtoken.sign(payload, key, opts, (err, token) => {
      return err ? reject(err) : resolve(token)
    })
  })
}

function authenticate (jwt) {
  let key = jwtOpts.secret || jwtOpts.publicKey
  if (!jwtOpts || !key) return Promise.resolve()
  return new Promise((resolve, reject) => {
    jsonwebtoken.verify(jwt, key, jwtOpts, (err, d = {}) => {
      return err ? reject(err) : resolve(d)
    })
  })
}

// helper: find resource
function find (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id_array = [id]
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_read`, params).then(firstRecord)
}

// helper: find set of resources
function findAll (resource, params) {
  Object.keys(params).forEach((k) => {
    if (!Array.isArray(params[k])) return
    params[`${k}_array`] = params[k]
    delete params[k]
  })
  return callPgFunc(`${pgPrefix}${resource}_search`, params)
}

// helper: create resource
function create (resource, params) {
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_create`, params).then(firstRecord)
}

// helper: update resource
function save (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id = id
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_update`, params).then(firstRecord)
}

// helper: delete resource
function destroy (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id = id
  return callPgFunc(`${pgPrefix}${resource}_delete`, params)
}

// resource method: search
function resourceSearch (req, res, name) {
  findAll(name, req.params).then((d) => {
    return sendData(res, d)
  }).catch((e) => sendErr(res, e))
}

// resource method: create
function resourceCreate (req, res, name) {
  create(name, req.params).then((d) => {
    return sendData(res, d)
  }).catch((err) => sendErr(res, err))
}

// resource method: read
function resourceRead (req, res, name) {
  find(name, req.id, req.params).then((d) => {
    return sendData(res, d)
  }).catch((err) => sendErr(res, err))
}

// resource method: update
function resourceUpdate (req, res, name) {
  save(name, req.id, req.params).then((d) => {
    return sendData(res, d)
  }).catch((err) => sendErr(res, err))
}

// resource method: delete
function resourceDelete (req, res, name) {
  destroy(name, req.id, req.params).then((d) => {
    return sendData(res, 'success')
  }).catch((err) => sendErr(res, err))
}
<|endoftext|>


<commit_before>var observer = require('observer-service'),
	widgets = require('sdk/widget'),
	pageMod = require('sdk/page-mod'),
	ss = require('sdk/simple-storage'),
	thisExtension = require('self'),
	{Cc, Ci} = require('chrome');

var mraidUrl = 'http://cdn.adnxs.com/js/mraid.js';

observer.add('http-on-modify-request', function(subject) {
	subject.QueryInterface(Ci.nsIHttpChannel);

	var url = subject.URI.spec;
	if (typeof url !== 'string' || !/mraid\.js($|\?)/.test(url) || url === mraidUrl) return;

	var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
	var uri = ios.newURI(mraidUrl, null, null);

	subject.redirectTo(uri);
});

pageMod.PageMod({
	include: '*',
	attachTo: ["top", "frame", "existing"],
	contentScriptWhen: 'start',
	contentScriptFile: thisExtension.data.url('content.compiled.js'),
	onAttach: function(w){
		w.port.on('save-origins', function(origins){
			ss.storage.anxOrigins = origins;
		});

		w.port.emit('load-origins', ss.storage.anxOrigins || []);
	}
});

widgets.Widget({
	id: "adnxs-mraid-link",
	label: "AppNexus MRAID Viewer",
	contentURL: thisExtension.data.url('icon128.png'),
	onClick: function() {}
});

<commit_msg>destructing doesn't work to well with parsing tools<commit_after>var observer = require('observer-service'),
	widgets = require('sdk/widget'),
	pageMod = require('sdk/page-mod'),
	ss = require('sdk/simple-storage'),
	thisExtension = require('self'),
	chrome = require('chrome'),
	Cc = chrome.Cc,
	Ci = chrome.Ci;

var mraidUrl = 'http://cdn.adnxs.com/js/mraid.js';

observer.add('http-on-modify-request', function(subject) {
	subject.QueryInterface(Ci.nsIHttpChannel);

	var url = subject.URI.spec;
	if (typeof url !== 'string' || !/mraid\.js($|\?)/.test(url) || url === mraidUrl) return;

	var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
	var uri = ios.newURI(mraidUrl, null, null);

	subject.redirectTo(uri);
});

pageMod.PageMod({
	include: '*',
	attachTo: ["top", "frame", "existing"],
	contentScriptWhen: 'start',
	contentScriptFile: thisExtension.data.url('content.compiled.js'),
	onAttach: function(w){
		w.port.on('save-origins', function(origins){
			ss.storage.anxOrigins = origins;
		});

		w.port.emit('load-origins', ss.storage.anxOrigins || []);
	}
});

widgets.Widget({
	id: "adnxs-mraid-link",
	label: "AppNexus MRAID Viewer",
	contentURL: thisExtension.data.url('icon128.png'),
	onClick: function() {}
});

<|endoftext|>


<commit_before>var isCanonicalBase64 = require('is-canonical-base64')
var isDomain = require('is-valid-domain')
var Querystring = require('querystring')
var ip = require('ip')

var parseLinkRegex = /^((@|%|&)[A-Za-z0-9\/+]{43}=\.[\w\d]+)(\?(.+))?$/
var linkRegex = exports.linkRegex = /^(@|%|&)[A-Za-z0-9\/+]{43}=\.[\w\d]+$/
var feedIdRegex = isCanonicalBase64('@', '\.(?:sha256|ed25519)', 32)
var blobIdRegex = isCanonicalBase64('&', '\.sha256', 32)
var msgIdRegex = isCanonicalBase64('%', '\.sha256', 32)

var extractRegex = /([@%&][A-Za-z0-9\/+]{43}=\.[\w\d]+)/

var MultiServerAddress = require('multiserver-address')

function isIP (s) {
  return ip.isV4Format(s) || ip.isV6Format(s)
}

var isInteger = Number.isInteger
var DEFAULT_PORT = 8008

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

var isHost = function (addr) {
  if(!isString(addr)) return
  addr = addr.replace(/^wss?:\/\//, '')
  return (isIP(addr)) || isDomain(addr) || addr === 'localhost'
}

var isPort = function (p) {
  return isInteger(p) && p <= 65536
}

function isObject (o) {
  return o && 'object' === typeof o && !Array.isArray(o)
}

var isLink = exports.isLink =
  function (data) {
    return isString(data) && parseLinkRegex.test(data)
  }

var isFeedId = exports.isFeed = exports.isFeedId =
  function (data) {
    return isString(data) && feedIdRegex.test(data)
  }

var isMsgId = exports.isMsg = exports.isMsgId =
  function (data) {
    return isString(data) && msgIdRegex.test(data)
  }

var isBlobId = exports.isBlob = exports.isBlobId =
  function (data) {
    return isString(data) && blobIdRegex.test(data)
  }

exports.isBlobLink = function (s) {
  return s[0] === '&' && isLink(s)
}

exports.isMsgLink = function (s) {
  return s[0] === '%' && isLink(s)
}

var normalizeChannel = exports.normalizeChannel =
  function (data) {
    if (typeof data === 'string') {
      data = data.toLowerCase().replace(/\s|,|\.|\?|!|<|>|\(|\)|\[|\]|"|#/g, '')
      if (data.length > 0 && data.length < 30) {
        return data
      }
    }
  }

function deprecate (name, fn) {
  var logged = false
  return function () {
    var args = [].slice.call(arguments)
    if(!logged) {
      console.trace('deprecated api used: '+name)
      logged = true
    }
    return fn.apply(this, args)
  }
}

var parseMultiServerAddress = deprecate('ssb-ref.parseMultiServerAddress', function (data) {
  if(!isString(data)) return false
  if(!MultiServerAddress.check(data)) return false

  var addr = MultiServerAddress.decode(data)
  addr = addr.find(function (address) {
    return /^(net|wss?|onion)$/.test(address[0].name) && /^shs/.test(address[1].name)
  })
  if (!Array.isArray(addr)) {
	  console.trace('got no addr from', data)
	  return false
  }
  var port = +addr[0].data.pop() //last item always port, to handle ipv6

  //preserve protocol type on websocket addresses
  var host = (/^wss?$/.test(addr[0].name) ? addr[0].name+':' : '') + addr[0].data.join(':')
  var key = '@'+addr[1].data[0]+'.ed25519'
  var seed = addr[1].data[2]
  // allow multiserver addresses that are not currently understood!
  if(!(isHost(host) && isPort(+port) && isFeedId(key))) return false
  var address = {
    host: host,
    port: port,
    key: key,
  }
  if(seed)
    address.seed = seed

  return address
})

var toLegacyAddress = exports.toLegacyAddress = parseMultiServerAddress

var isLegacyAddress = exports.isLegacyAddress = function (addr) {
  return isObject(addr) && isHost(addr.host) && isPort(addr.port) && isFeedId(addr.key)
}

var toMultiServerAddress = exports.toMultiServerAddress = function (addr) {
  if(MultiServerAddress.check(addr)) return addr
  if(!isPort(addr.port)) throw new Error('ssb-ref.toMultiServerAddress - invalid port:'+addr.port)
  if(!isHost(addr.host)) throw new Error('ssb-ref.toMultiServerAddress - invalid host:'+addr.host)
  if(!isFeedId(addr.key)) throw new Error('ssb-ref.toMultiServerAddress - invalid key:'+addr.key)

  return (
    /^wss?:/.test(addr.host)   ? addr.host
  : /\.onion$/.test(addr.host) ? 'onion:'+addr.host
  :                              'net:'+addr.host
  )+':'+addr.port+'~shs:'+addr.key.substring(1, addr.key.indexOf('.'))
}

var isAddress = exports.isAddress = function (data) {
  var host, port, id
  if(isObject(data)) {
    id = data.key
    host = data.host
    port = data.port
  }
  else if(!isString(data)) return false
  else if(MultiServerAddress.check(data)) return true
  else {
    var parts = data.split(':')
    var id = parts.pop(), port = parts.pop(), host = parts.join(':')
    return (
      isFeedId(id) && isPort(+port)
      && isHost(host)
    )
  }
}

//This is somewhat fragile, because maybe non-shs protocols get added...
//it would be better to treat all addresses as opaque or have multiserver handle
//extraction of a signing key from the address.
var getKeyFromAddress = exports.getKeyFromAddress = function (addr) {
  if(addr.key) return addr.key
  var data = MultiServerAddress.decode(addr)
  if(!data) return
  for(var k in data) {
    var address = data[k]
    for(var j in address) {
      var protocol = address[j]
      if(/^shs/.test(protocol.name)) //forwards compatible with future shs versions...
        return '@'+protocol.data[0]+'.ed25519'
    }
  }
}

var parseAddress = exports.parseAddress = deprecate('ssb-ref.parseAddress', function (e) {
  if(isString(e)) {
    if(~e.indexOf('~'))
      return parseMultiServerAddress(e)
    var parts = e.split(':')
    var id = parts.pop(), port = parts.pop(), host = parts.join(':')
    var e = {
      host: host,
      port: +(port || DEFAULT_PORT),
      key: id
    }
    return e
  }
  return e
})

var toAddress = exports.toAddress = function (e) {
  e = exports.parseAddress(e)
  e.port = e.port || DEFAULT_PORT
  e.host = e.host || 'localhost'
  return e
}

var legacyInviteRegex = /^[A-Za-z0-9\/+]{43}=$/
var legacyInviteFixerRegex = /#.*$/
var isLegacyInvite = exports.isLegacyInvite =
  function (data) {
    if(!isString(data)) return false
    data = data.replace(legacyInviteFixerRegex, '')
    var parts = data.split('~')
    return parts.length == 2 && isAddress(parts[0]) && legacyInviteRegex.test(parts[1])
  }

var isMultiServerInvite = exports.isMultiServerInvite =
  function (data) {
    if(!isString(data)) return false
    return !!parseMultiServerInvite(data)
  }

var isInvite = exports.isInvite =
  function (data) {
    if(!isString(data)) return false
    return isLegacyInvite(data) || isMultiServerInvite(data)
  }

exports.parseLink = function parseBlob (ref) {
  var match = parseLinkRegex.exec(ref)
  if (match && match[1]) {
    if (match[3]) {
      return {link: match[1], query: Querystring.parse(match[4])}
    } else {
      return {link: match[1]}
    }
  }
}

function parseLegacyInvite (invite) {
  var redirect = invite.split('#')
  invite = redirect.shift()
  var parts = invite.split('~')
  var addr = toAddress(parts[0])//.split(':')
  //convert legacy code to multiserver invite code.
  invite = remote+':'+parts[1]
  var remote = toMultiServerAddress(addr)
  return {
    invite: remote + ':' + parts[1],
    key: addr.key,
    redirect: null,
    remote: remote,
    redirect: redirect.length ? '#' + redirect.join('#') : null
  }
}

function parseMultiServerInvite (invite) {

  var redirect = invite.split('#')
  if(!redirect.length) return null

  invite = redirect.shift()
  var addr = toLegacyAddress(invite)
  delete addr.seed
  return {
    invite: invite,
    remote: toMultiServerAddress(addr),
    key: addr.key,
    redirect: redirect.length ? '#' + redirect.join('#') : null
  }
}

exports.parseLegacyInvite = deprecate('ssb-ref.parseLegacyInvite', parseLegacyInvite)
exports.parseMultiServerInvite = deprecate('ssb-ref.parseMultiServerInvite', parseMultiServerInvite)

exports.parseInvite = deprecate('ssb-ref.parseInvite', function (invite) {
  return (
    isLegacyInvite(invite)
  ? parseLegacyInvite(invite)
  : isMultiServerInvite(invite)
  ? parseMultiServerInvite(invite)
  : null
  )
})

exports.type =
  function (id) {
    if(!isString(id)) return false
    var c = id.charAt(0)
    if (c == '@' && isFeedId(id))
      return 'feed'
    else if (c == '%' && isMsgId(id))
      return 'msg'
    else if (c == '&' && isBlobId(id))
      return 'blob'
    else if(isAddress(id)) return 'address'
    else if(isInvite(id)) return 'invite'
    else
    return false
  }

exports.extract =
  function (data) {
    if (!isString(data))
      return false

    var _data = data

    var res = extractRegex.exec(_data)
    if (res) {
      return res && res[0]
    } else {
      try { _data = decodeURIComponent(data) }
      catch (e) {} // this may fail if it's not encoded, so don't worry if it does
      _data = _data.replace(/&/g, '&')

      var res = extractRegex.exec(_data)
      return res && res[0]
    }
  }

<commit_msg>remove trace<commit_after>var isCanonicalBase64 = require('is-canonical-base64')
var isDomain = require('is-valid-domain')
var Querystring = require('querystring')
var ip = require('ip')

var parseLinkRegex = /^((@|%|&)[A-Za-z0-9\/+]{43}=\.[\w\d]+)(\?(.+))?$/
var linkRegex = exports.linkRegex = /^(@|%|&)[A-Za-z0-9\/+]{43}=\.[\w\d]+$/
var feedIdRegex = isCanonicalBase64('@', '\.(?:sha256|ed25519)', 32)
var blobIdRegex = isCanonicalBase64('&', '\.sha256', 32)
var msgIdRegex = isCanonicalBase64('%', '\.sha256', 32)

var extractRegex = /([@%&][A-Za-z0-9\/+]{43}=\.[\w\d]+)/

var MultiServerAddress = require('multiserver-address')

function isIP (s) {
  return ip.isV4Format(s) || ip.isV6Format(s)
}

var isInteger = Number.isInteger
var DEFAULT_PORT = 8008

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

var isHost = function (addr) {
  if(!isString(addr)) return
  addr = addr.replace(/^wss?:\/\//, '')
  return (isIP(addr)) || isDomain(addr) || addr === 'localhost'
}

var isPort = function (p) {
  return isInteger(p) && p <= 65536
}

function isObject (o) {
  return o && 'object' === typeof o && !Array.isArray(o)
}

var isLink = exports.isLink =
  function (data) {
    return isString(data) && parseLinkRegex.test(data)
  }

var isFeedId = exports.isFeed = exports.isFeedId =
  function (data) {
    return isString(data) && feedIdRegex.test(data)
  }

var isMsgId = exports.isMsg = exports.isMsgId =
  function (data) {
    return isString(data) && msgIdRegex.test(data)
  }

var isBlobId = exports.isBlob = exports.isBlobId =
  function (data) {
    return isString(data) && blobIdRegex.test(data)
  }

exports.isBlobLink = function (s) {
  return s[0] === '&' && isLink(s)
}

exports.isMsgLink = function (s) {
  return s[0] === '%' && isLink(s)
}

var normalizeChannel = exports.normalizeChannel =
  function (data) {
    if (typeof data === 'string') {
      data = data.toLowerCase().replace(/\s|,|\.|\?|!|<|>|\(|\)|\[|\]|"|#/g, '')
      if (data.length > 0 && data.length < 30) {
        return data
      }
    }
  }

function deprecate (name, fn) {
  var logged = false
  return function () {
    var args = [].slice.call(arguments)
    if(!logged) {
      console.trace('deprecated api used: '+name)
      logged = true
    }
    return fn.apply(this, args)
  }
}

var parseMultiServerAddress = deprecate('ssb-ref.parseMultiServerAddress', function (data) {
  if(!isString(data)) return false
  if(!MultiServerAddress.check(data)) return false

  var addr = MultiServerAddress.decode(data)
  addr = addr.find(function (address) {
    return /^(net|wss?|onion)$/.test(address[0].name) && /^shs/.test(address[1].name)
  })
  if (!Array.isArray(addr)) {
    return false
  }
  var port = +addr[0].data.pop() //last item always port, to handle ipv6

  //preserve protocol type on websocket addresses
  var host = (/^wss?$/.test(addr[0].name) ? addr[0].name+':' : '') + addr[0].data.join(':')
  var key = '@'+addr[1].data[0]+'.ed25519'
  var seed = addr[1].data[2]
  // allow multiserver addresses that are not currently understood!
  if(!(isHost(host) && isPort(+port) && isFeedId(key))) return false
  var address = {
    host: host,
    port: port,
    key: key,
  }
  if(seed)
    address.seed = seed

  return address
})

var toLegacyAddress = exports.toLegacyAddress = parseMultiServerAddress

var isLegacyAddress = exports.isLegacyAddress = function (addr) {
  return isObject(addr) && isHost(addr.host) && isPort(addr.port) && isFeedId(addr.key)
}

var toMultiServerAddress = exports.toMultiServerAddress = function (addr) {
  if(MultiServerAddress.check(addr)) return addr
  if(!isPort(addr.port)) throw new Error('ssb-ref.toMultiServerAddress - invalid port:'+addr.port)
  if(!isHost(addr.host)) throw new Error('ssb-ref.toMultiServerAddress - invalid host:'+addr.host)
  if(!isFeedId(addr.key)) throw new Error('ssb-ref.toMultiServerAddress - invalid key:'+addr.key)

  return (
    /^wss?:/.test(addr.host)   ? addr.host
  : /\.onion$/.test(addr.host) ? 'onion:'+addr.host
  :                              'net:'+addr.host
  )+':'+addr.port+'~shs:'+addr.key.substring(1, addr.key.indexOf('.'))
}

var isAddress = exports.isAddress = function (data) {
  var host, port, id
  if(isObject(data)) {
    id = data.key
    host = data.host
    port = data.port
  }
  else if(!isString(data)) return false
  else if(MultiServerAddress.check(data)) return true
  else {
    var parts = data.split(':')
    var id = parts.pop(), port = parts.pop(), host = parts.join(':')
    return (
      isFeedId(id) && isPort(+port)
      && isHost(host)
    )
  }
}

//This is somewhat fragile, because maybe non-shs protocols get added...
//it would be better to treat all addresses as opaque or have multiserver handle
//extraction of a signing key from the address.
var getKeyFromAddress = exports.getKeyFromAddress = function (addr) {
  if(addr.key) return addr.key
  var data = MultiServerAddress.decode(addr)
  if(!data) return
  for(var k in data) {
    var address = data[k]
    for(var j in address) {
      var protocol = address[j]
      if(/^shs/.test(protocol.name)) //forwards compatible with future shs versions...
        return '@'+protocol.data[0]+'.ed25519'
    }
  }
}

var parseAddress = exports.parseAddress = deprecate('ssb-ref.parseAddress', function (e) {
  if(isString(e)) {
    if(~e.indexOf('~'))
      return parseMultiServerAddress(e)
    var parts = e.split(':')
    var id = parts.pop(), port = parts.pop(), host = parts.join(':')
    var e = {
      host: host,
      port: +(port || DEFAULT_PORT),
      key: id
    }
    return e
  }
  return e
})

var toAddress = exports.toAddress = function (e) {
  e = exports.parseAddress(e)
  e.port = e.port || DEFAULT_PORT
  e.host = e.host || 'localhost'
  return e
}

var legacyInviteRegex = /^[A-Za-z0-9\/+]{43}=$/
var legacyInviteFixerRegex = /#.*$/
var isLegacyInvite = exports.isLegacyInvite =
  function (data) {
    if(!isString(data)) return false
    data = data.replace(legacyInviteFixerRegex, '')
    var parts = data.split('~')
    return parts.length == 2 && isAddress(parts[0]) && legacyInviteRegex.test(parts[1])
  }

var isMultiServerInvite = exports.isMultiServerInvite =
  function (data) {
    if(!isString(data)) return false
    return !!parseMultiServerInvite(data)
  }

var isInvite = exports.isInvite =
  function (data) {
    if(!isString(data)) return false
    return isLegacyInvite(data) || isMultiServerInvite(data)
  }

exports.parseLink = function parseBlob (ref) {
  var match = parseLinkRegex.exec(ref)
  if (match && match[1]) {
    if (match[3]) {
      return {link: match[1], query: Querystring.parse(match[4])}
    } else {
      return {link: match[1]}
    }
  }
}

function parseLegacyInvite (invite) {
  var redirect = invite.split('#')
  invite = redirect.shift()
  var parts = invite.split('~')
  var addr = toAddress(parts[0])//.split(':')
  //convert legacy code to multiserver invite code.
  invite = remote+':'+parts[1]
  var remote = toMultiServerAddress(addr)
  return {
    invite: remote + ':' + parts[1],
    key: addr.key,
    redirect: null,
    remote: remote,
    redirect: redirect.length ? '#' + redirect.join('#') : null
  }
}

function parseMultiServerInvite (invite) {

  var redirect = invite.split('#')
  if(!redirect.length) return null

  invite = redirect.shift()
  var addr = toLegacyAddress(invite)
  if(!addr) return null
  delete addr.seed
  return {
    invite: invite,
    remote: toMultiServerAddress(addr),
    key: addr.key,
    redirect: redirect.length ? '#' + redirect.join('#') : null
  }
}

exports.parseLegacyInvite = deprecate('ssb-ref.parseLegacyInvite', parseLegacyInvite)
exports.parseMultiServerInvite = deprecate('ssb-ref.parseMultiServerInvite', parseMultiServerInvite)

exports.parseInvite = deprecate('ssb-ref.parseInvite', function (invite) {
  return (
    isLegacyInvite(invite)
  ? parseLegacyInvite(invite)
  : isMultiServerInvite(invite)
  ? parseMultiServerInvite(invite)
  : null
  )
})

exports.type =
  function (id) {
    if(!isString(id)) return false
    var c = id.charAt(0)
    if (c == '@' && isFeedId(id))
      return 'feed'
    else if (c == '%' && isMsgId(id))
      return 'msg'
    else if (c == '&' && isBlobId(id))
      return 'blob'
    else if(isAddress(id)) return 'address'
    else if(isInvite(id)) return 'invite'
    else
    return false
  }

exports.extract =
  function (data) {
    if (!isString(data))
      return false

    var _data = data

    var res = extractRegex.exec(_data)
    if (res) {
      return res && res[0]
    } else {
      try { _data = decodeURIComponent(data) }
      catch (e) {} // this may fail if it's not encoded, so don't worry if it does
      _data = _data.replace(/&/g, '&')

      var res = extractRegex.exec(_data)
      return res && res[0]
    }
  }

<|endoftext|>


<commit_before>var PouchDB = require('pouchdb');

// TODO: move this to a config lib
var db_name = location.pathname.split('/')[1];
var db_url = location.protocol + '//' + location.hostname
    + (location.port ? ':' + location.port : '') + '/' + db_name + '/';
var db = new PouchDB(db_url);

var default_data = {
  active: false,
  name: 'JSON',
  schema_url: '',
  doc: {},
  notebooks: {}
};

module.exports = {
  data: function() {
    return default_data;
  },
  components: {
    // TODO: make these dynamic...somehow
    'json': require('../json-editor'),
    'vue-schema': require('../vue-schema')
  },
  replace: true,
  template: require('./template.html'),
  computed: {
    name: function() {
      // TODO: make this smarter
      if (this.doc.type) {
        return this.doc.type;
      }
    },
    editor: function() {
      if (this.schema_url) {
        return 'vue-schema';
      } else if (this.doc.type && undefined != this.$root.types[this.doc.type]
          && undefined != this.$root.types[this.doc.type].editor) {
        return this.$root.types[this.doc.type].editor;
      } else {
        return 'json';
      }
    }
  },
  methods: {
    destroy: function() {
      this.$destroy(true);
    },
    save: function() {
      var self = this;
      // get doc from editor
      var doc = this.$.editor.output();
      // save doc
      db.post(doc, function(err, resp) {
        if (err) {
          // TODO: maybe tell somebody...
          console.log('error: ', err);
        } else {
          // TODO: trigger content reload, etc.
          self.$dispatch('thingMade', doc);
          self.destroy();
        }
      });
    },
    remove: function() {
      var self = this;
      db.remove(self.doc._id, self.doc._rev, function(err, resp) {
        if (err) {
          console.log('error: ', err);
        } else {
          self.$dispatch('thingGone', self.doc);
          // close the modal
          self.destroy();
        }
      });
    }

  }
};
<commit_msg>Store created/modified on save<commit_after>var PouchDB = require('pouchdb');

// TODO: move this to a config lib
var db_name = location.pathname.split('/')[1];
var db_url = location.protocol + '//' + location.hostname
    + (location.port ? ':' + location.port : '') + '/' + db_name + '/';
var db = new PouchDB(db_url);

var default_data = {
  active: false,
  name: 'JSON',
  schema_url: '',
  doc: {},
  notebooks: {}
};

module.exports = {
  data: function() {
    return default_data;
  },
  components: {
    // TODO: make these dynamic...somehow
    'json': require('../json-editor'),
    'vue-schema': require('../vue-schema')
  },
  replace: true,
  template: require('./template.html'),
  computed: {
    name: function() {
      // TODO: make this smarter
      if (this.doc.type) {
        return this.doc.type;
      }
    },
    editor: function() {
      if (this.schema_url) {
        return 'vue-schema';
      } else if (this.doc.type && undefined != this.$root.types[this.doc.type]
          && undefined != this.$root.types[this.doc.type].editor) {
        return this.$root.types[this.doc.type].editor;
      } else {
        return 'json';
      }
    }
  },
  methods: {
    destroy: function() {
      this.$destroy(true);
    },
    save: function() {
      var self = this;
      // get doc from editor
      var doc = this.$.editor.output();
      if (undefined === doc._id) {
        // we have a new doc, so add `created` date
        doc.created = (new Date).toISOString();
      }
      // regardless, add the `modified` date
      doc.modified = (new Date).toISOString();

      // save doc
      db.post(doc, function(err, resp) {
        if (err) {
          // TODO: maybe tell somebody...
          console.log('error: ', err);
        } else {
          // TODO: trigger content reload, etc.
          self.$dispatch('thingMade', doc);
          self.destroy();
        }
      });
    },
    remove: function() {
      var self = this;
      db.remove(self.doc._id, self.doc._rev, function(err, resp) {
        if (err) {
          console.log('error: ', err);
        } else {
          self.$dispatch('thingGone', self.doc);
          // close the modal
          self.destroy();
        }
      });
    }

  }
};
<|endoftext|>


<commit_before>/**
 * @author WestLangley / https://github.com/WestLangley
 * @author zz85 / https://github.com/zz85
 */

THREE.ArrowHelper = function ( origin, dir, length, hex ) {

    THREE.Object3D.call( this );

    var lineGeometry = new THREE.Geometry();
    lineGeometry.vertices.push( new THREE.Vertex() );
    lineGeometry.vertices.push( new THREE.Vertex( new THREE.Vector3( 0, 1, 0 ) ) );

    this.line = new THREE.Line( lineGeometry, new THREE.LineBasicMaterial( { color : hex } ) );
    this.add( this.line );

    var coneGeometry = new THREE.CylinderGeometry( 0, 0.05, 0.25, 5, 1 );

    this.cone = new THREE.Mesh( coneGeometry, new THREE.MeshBasicMaterial( { color : hex } ) );
    this.cone.position.set( 0, 1, 0 );
    this.add( this.cone );

    this.position = origin;

    this.setDirection( dir );

    this.setLength( length );

};

THREE.ArrowHelper.prototype = new THREE.Object3D();
THREE.ArrowHelper.prototype.constructor = THREE.ArrowHelper;

THREE.ArrowHelper.prototype.setDirection = function( dir ) {

    var axis = new THREE.Vector3( 0, 1, 0 ).crossSelf( dir );

    var radians = Math.acos( new THREE.Vector3( 0, 1, 0 ).dot( dir.clone().normalize() ) );

    this.matrix = new THREE.Matrix4().setRotationAxis( axis.normalize(), radians );

    this.rotation.getRotationFromMatrix( this.matrix, this.scale );

};

THREE.ArrowHelper.prototype.setLength = function( length ) {

    this.scale.set( length, length, length );

};

THREE.ArrowHelper.prototype.setColor = function( hex ) {

    this.line.material.color.setHex( hex );
    this.cone.material.color.setHex( hex );

};
<commit_msg>adding default parameters for THREE.ArrowHelper<commit_after>/**
 * @author WestLangley / https://github.com/WestLangley
 * @author zz85 / https://github.com/zz85
 *
 * Creates an arrow for visualizing directions
 *
 * Parameters:
 *  dir - Vector3
 *  origin - Vector3
 *  length - Number
 *  hex - color in hex value
 */

THREE.ArrowHelper = function ( dir, origin, length, hex ) {

    THREE.Object3D.call( this );

    if (hex ===undefined) {
        hex = 0xffff00;
    }

    if (length === undefined) {
        length = 20;
    }

    var lineGeometry = new THREE.Geometry();
    lineGeometry.vertices.push( new THREE.Vertex() );
    lineGeometry.vertices.push( new THREE.Vertex( new THREE.Vector3( 0, 1, 0 ) ) );

    this.line = new THREE.Line( lineGeometry, new THREE.LineBasicMaterial( { color : hex } ) );
    this.add( this.line );

    var coneGeometry = new THREE.CylinderGeometry( 0, 0.05, 0.25, 5, 1 );

    this.cone = new THREE.Mesh( coneGeometry, new THREE.MeshBasicMaterial( { color : hex } ) );
    this.cone.position.set( 0, 1, 0 );
    this.add( this.cone );

    if (origin instanceof THREE.Vector3) {
        this.position = origin;
    }

    this.setDirection( dir );

    this.setLength( length );

};

THREE.ArrowHelper.prototype = new THREE.Object3D();
THREE.ArrowHelper.prototype.constructor = THREE.ArrowHelper;

THREE.ArrowHelper.prototype.setDirection = function( dir ) {

    var axis = new THREE.Vector3( 0, 1, 0 ).crossSelf( dir );

    var radians = Math.acos( new THREE.Vector3( 0, 1, 0 ).dot( dir.clone().normalize() ) );

    this.matrix = new THREE.Matrix4().setRotationAxis( axis.normalize(), radians );

    this.rotation.getRotationFromMatrix( this.matrix, this.scale );

};

THREE.ArrowHelper.prototype.setLength = function( length ) {

    this.scale.set( length, length, length );

};

THREE.ArrowHelper.prototype.setColor = function( hex ) {

    this.line.material.color.setHex( hex );
    this.cone.material.color.setHex( hex );

};
<|endoftext|>