<commit_before>'use strict';

var superagent= require('superagent');
var Promise = require('bluebird');
var Base64 = require('./Base64');

module.exports = {};

/**
 * FlavorUtils constructor
 * @param {Object} config - options
 * @param {string} config.couchUrl - couchdb root url. It should contain username + password if necessary
 * @param {string} config.couchDatabase - couchdb database
 */
module.exports = function FlavorUtils(config) {
    this.config = config;
    this.config.couchUrl = this.config.couchUrl.replace(/\/$/,'');
    this.dbUrl = this.config.couchUrl + '/' + this.config.couchDatabase;
};

/**
 * Clone a flavor from one user to another
 * @param {Object} opts - clone options
 * @param {Object} opts.source - source description
 * @param {string} opts.source.username - The name of the user's from which to clone
 * @param {string} opts.source.flavor - The name of the flavor to clone
 * @param {string} opts.target - target description
 * @param {String} opts.target.username - The target username to which to clone the flavor
 * @param {string} opts.target.flavor - The name of the flavor in the target
 */
module.exports.prototype.cloneFlavor = function(opts) {
    var that = this;
    var key = [opts.source.flavor, opts.source.username];
    var url = this.dbUrl + '/_design/flavor/_view/docs?key=' + encodeURIComponent(JSON.stringify(key));
    getJSON(url).then(function(res) {
        var result = res.rows;
        if(!result) return;
        var done = Promise.resolve();
        var i= 0;
        var uuids = [];
        done.then(function() {
            return that.getUUIDs(result.length)
        }).then(function(res) {
            uuids = res.uuids;
        });
        for(i=0; i<result.length; i++) {
            done = done.then(doEl(i));
        }
        done.then(function() {
            console.log('all done');
        });

        done.catch(function(err) {
            console.log('error', err);
        });

        function doEl(i) {
            return function () {
                var prom = [];
                var view, data, meta, doc, newDoc;
                prom.push(getJSON(that.dbUrl + '/' + result[i].id));
                if (result[i].value.view) {
                    view = getJSON(that.dbUrl + '/' + result[i].id + '/view.json');
                    prom.push(view);
                }
                else prom.push(undefined);
                if (result[i].value.data) {
                    data = getJSON(that.dbUrl + '/' + result[i].id + '/data.json');
                    prom.push(data);
                }
                else prom.push(undefined);
                if (result[i].value.meta) {
                    meta = getJSON(that.dbUrl + '/' + result[i].id + '/meta.json');
                    prom.push(meta);
                }
                else prom.push(undefined);
                var prom = Promise.all(prom);
                prom.then(function (arr) {
                    doc = arr[0];
                    newDoc = {};
                    var view = arr[1];
                    var data = arr[2];
                    var meta = arr[3];
                    newDoc._id = uuids[i];
                    delete doc._rev;

                    newDoc.flavors = {};
                    if(doc.flavors[opts.source.flavor]) {
                        newDoc.flavors[opts.target.flavor] = doc.flavors[opts.source.flavor];
                    }

                    newDoc.name = opts.target.username;

                    if(meta) {
                        newDoc._attachments = newDoc._attachments || {};
                        newDoc._attachments['meta.json'] = {
                            'content_type': 'application/json',
                            'data': Base64.encode(JSON.stringify(meta))
                        };
                    }
                    if(view) {
                        newDoc._attachments = newDoc._attachments || {};
                        newDoc._attachments['view.json'] = {
                            'content_type': 'application/json',
                            'data': Base64.encode(JSON.stringify(view))
                        };
                    }
                    if(data) {
                        newDoc._attachments = newDoc._attachments || {};
                        newDoc._attachments['data.json'] = {
                            'content_type': 'application/json',
                            'data': Base64.encode(JSON.stringify(data))
                        };
                    }
                });
                prom.catch(function(err) {
                    console.log('error!', err, err.stack);
                });
                return prom.then(function() {
                    return that.saveDoc(newDoc);
                });
            }
        }
    });
};

module.exports.prototype.saveDoc = function(doc) {
    var that = this;
    delete doc._id;
    var url = that.dbUrl;
        return new Promise(function(resolve, reject) {
            superagent
                .post(url)
                .set('Content-Type', 'application/json')
                .send(doc)
                .end(function(err, res) {
                    if(err) {
                        return reject(err);
                    }
                    resolve(res.body);
                })
        });
};
/**
 * Get couchdb uuids
 * @param {Object} count - the number of uuids needed
 *
 */
module.exports.prototype.getUUIDs = function(count) {
    var that = this;
    count = count || 1;
    return getJSON(that.config.couchUrl + '/_uuids?count=' + count);
};

function getJSON(url) {
    return new Promise(function(resolve, reject) {
        superagent
            .get(url)
            .set('Accept', 'application/json')
            .end(function(err, res) {
                if(err) {
                    return reject(err);
                }
                resolve(res.body);
            })
    });
}

<commit_msg>fix promise micmac<commit_after>'use strict';

var superagent= require('superagent');
var Base64 = require('./Base64');
var Promise = require('bluebird')

module.exports = {};

/**
 * FlavorUtils constructor
 * @param {Object} config - options
 * @param {string} config.couchUrl - couchdb root url. It should contain username + password if necessary
 * @param {string} config.couchDatabase - couchdb database
 */
module.exports = function FlavorUtils(config) {
    this.config = config;
    this.config.couchUrl = this.config.couchUrl.replace(/\/$/,'');
    this.dbUrl = this.config.couchUrl + '/' + this.config.couchDatabase;
};

/**
 * Clone a flavor from one user to another
 * @param {Object} opts - clone options
 * @param {Object} opts.source - source description
 * @param {string} opts.source.username - The name of the user's from which to clone
 * @param {string} opts.source.flavor - The name of the flavor to clone
 * @param {string} opts.target - target description
 * @param {String} opts.target.username - The target username to which to clone the flavor
 * @param {string} opts.target.flavor - The name of the flavor in the target
 */
module.exports.prototype.cloneFlavor = function(opts) {
    var that = this;
    var key = [opts.source.flavor, opts.source.username];
    var url = this.dbUrl + '/_design/flavor/_view/docs?key=' + encodeURIComponent(JSON.stringify(key));
    getJSON(url).then(function(res) {
        var result = res.rows;
        if(!result) return;
        var done = Promise.resolve();
        var i= 0;
        var uuids = [];
        done.then(function() {
            return that.getUUIDs(result.length)
        }).then(function(res) {
            uuids = res.uuids;
        });
        for(i=0; i<result.length; i++) {
            done = done.then(doEl(i));
        }
        done.then(function() {
            console.log('all done');
        }, function(err) {
            console.log('error:', err);
        });

        function doEl(i) {
            return function () {
                var prom = [];
                var view, data, meta, doc, newDoc;
                prom.push(getJSON(that.dbUrl + '/' + result[i].id));
                if (result[i].value.view) {
                    view = getJSON(that.dbUrl + '/' + result[i].id + '/view.json');
                    prom.push(view);
                }
                else prom.push(undefined);
                if (result[i].value.data) {
                    data = getJSON(that.dbUrl + '/' + result[i].id + '/data.json');
                    prom.push(data);
                }
                else prom.push(undefined);
                if (result[i].value.meta) {
                    meta = getJSON(that.dbUrl + '/' + result[i].id + '/meta.json');
                    prom.push(meta);
                }
                else prom.push(undefined);
                var prom = Promise.all(prom);
                prom = prom.then(function (arr) {
                    doc = arr[0];
                    newDoc = {};
                    var view = arr[1];
                    var data = arr[2];
                    var meta = arr[3];
                    newDoc._id = uuids[i];
                    delete doc._rev;

                    newDoc.flavors = {};
                    if(doc.flavors[opts.source.flavor]) {
                        newDoc.flavors[opts.target.flavor] = doc.flavors[opts.source.flavor];
                    }

                    newDoc.name = opts.target.username;

                    if(meta) {
                        newDoc._attachments = newDoc._attachments || {};
                        newDoc._attachments['meta.json'] = {
                            'content_type': 'application/json',
                            'data': Base64.encode(JSON.stringify(meta))
                        };
                    }
                    if(view) {
                        newDoc._attachments = newDoc._attachments || {};
                        newDoc._attachments['view.json'] = {
                            'content_type': 'application/json',
                            'data': Base64.encode(JSON.stringify(view))
                        };
                    }
                    if(data) {
                        newDoc._attachments = newDoc._attachments || {};
                        newDoc._attachments['data.json'] = {
                            'content_type': 'application/json',
                            'data': Base64.encode(JSON.stringify(data))
                        };
                    }
                });
                return prom.then(function() {
                    return that.saveDoc(newDoc);
                });
            }
        }
    });
};

module.exports.prototype.saveDoc = function(doc) {
    var that = this;
    delete doc._id;
    var url = that.dbUrl;
        return new Promise(function(resolve, reject) {
            superagent
                .post(url)
                .set('Content-Type', 'application/json')
                .send(doc)
                .end(function(err, res) {
                    if(err) {
                        return reject(err);
                    }
                    resolve(res.body);
                })
        });
};
/**
 * Get couchdb uuids
 * @param {Object} count - the number of uuids needed
 *
 */
module.exports.prototype.getUUIDs = function(count) {
    var that = this;
    count = count || 1;
    return getJSON(that.config.couchUrl + '/_uuids?count=' + count);
};

function getJSON(url) {
    return new Promise(function(resolve, reject) {
        superagent
            .get(url)
            .set('Accept', 'application/json')
            .end(function(err, res) {
                if(err) {
                    return reject(err);
                }
                resolve(res.body);
            })
    });
}

<|endoftext|>


<commit_before>import './assets/scss/_all.scss';

import Button from './components/button/Button';
import ButtonGroup from './components/button/ButtonGroup';
import Radio from './components/radio/Radio';
import RadioGroup from './components/radio/RadioGroup';
import {Nav, NavItem, NavDropDownItem, NavHrefItem} from './components/navbar';
import Popup from './components/Popup';
import Input from './components/Input';
import IconInput from './components/IconInput';
import CheckBox from './components/CheckBox';
import Avatar from './components/Avatar';
import Select from './components/select/Select';
import MultiSelect from './components/select/MultiSelect';
import DatePicker from './components/datepicker/DatePicker';
import MonthPicker from './components/monthpicker/MonthPicker';
import DateRangePicker from './components/datepicker/DateRangePicker';
import EventPlanner from './components/eventplanner';
import FormField from './components/form/FormField';
import Label from './components/Label';
import TextArea from './components/TextArea';
import FeedbackManager from './components/feedback/FeedbackManager';
import Pager from './components/Pager';
import MonthPager from './components/MonthPager';
import Link from './components/Link';
import Alert from './components/Alert';
import Tabs from './components/tabs/Tabs';
import Tab from './components/tabs/Tab';

import * as dateUtils from './util/date-utils';
import * as dateFormats from './util/date-formats';

export {
    Button,
    ButtonGroup,
    Radio,
    RadioGroup,
    Nav,
    NavItem,
    NavHrefItem,
    NavDropDownItem,
    Input,
    IconInput,
    TextArea,
    Popup,
    CheckBox,
    Avatar,
    Select,
    MultiSelect,
    EventPlanner,
    FormField,
    Label,
    DatePicker,
    DateRangePicker,
    dateUtils,
    dateFormats,
    FeedbackManager,
    Pager,
    Link,
    MonthPicker,
    MonthPager,
    Alert,
    Tabs
};
<commit_msg>exporting Tab component<commit_after>import './assets/scss/_all.scss';

import Button from './components/button/Button';
import ButtonGroup from './components/button/ButtonGroup';
import Radio from './components/radio/Radio';
import RadioGroup from './components/radio/RadioGroup';
import {Nav, NavItem, NavDropDownItem, NavHrefItem} from './components/navbar';
import Popup from './components/Popup';
import Input from './components/Input';
import IconInput from './components/IconInput';
import CheckBox from './components/CheckBox';
import Avatar from './components/Avatar';
import Select from './components/select/Select';
import MultiSelect from './components/select/MultiSelect';
import DatePicker from './components/datepicker/DatePicker';
import MonthPicker from './components/monthpicker/MonthPicker';
import DateRangePicker from './components/datepicker/DateRangePicker';
import EventPlanner from './components/eventplanner';
import FormField from './components/form/FormField';
import Label from './components/Label';
import TextArea from './components/TextArea';
import FeedbackManager from './components/feedback/FeedbackManager';
import Pager from './components/Pager';
import MonthPager from './components/MonthPager';
import Link from './components/Link';
import Alert from './components/Alert';
import Tabs from './components/tabs/Tabs';
import Tab from './components/tabs/Tab';

import * as dateUtils from './util/date-utils';
import * as dateFormats from './util/date-formats';

export {
    Button,
    ButtonGroup,
    Radio,
    RadioGroup,
    Nav,
    NavItem,
    NavHrefItem,
    NavDropDownItem,
    Input,
    IconInput,
    TextArea,
    Popup,
    CheckBox,
    Avatar,
    Select,
    MultiSelect,
    EventPlanner,
    FormField,
    Label,
    DatePicker,
    DateRangePicker,
    dateUtils,
    dateFormats,
    FeedbackManager,
    Pager,
    Link,
    MonthPicker,
    MonthPager,
    Alert,
    Tabs,
    Tab
};
<|endoftext|>


<commit_before><commit_msg>Update indexfile<commit_after>import Button from './Button';
import ButtonGroup from './ButtonGroup';
import Card from './Card';
import Dialog from './Dialog/Dialog';
import DialogContent from './Dialog/DialogContent';
import DialogHeader from './Dialog/DialogHeader';
import Icon from './Icon';
import FormContainer from './FormContainer';
import List from './List';
import Table from './Table';
import TextInput from './TextInput';
import Toolbar from './Toolbar';

import {
	AppHeader,
	Cell,
	ContentCell,
	Drawer,
	Grid,
	GridContainer,
	GridFrame,
	VerticalSpace,
} from './layout';

export {
	Button,
	ButtonGroup,
	Card,
	Dialog,
	DialogContent,
	DialogHeader,
	FormContainer,
	Icon,
	List,
	Table,
	TextInput,
	Toolbar,
	AppHeader,
	Cell,
	ContentCell,
	Drawer,
	Grid,
	GridContainer,
	GridFrame,
	VerticalSpace,
};
<|endoftext|>


<commit_before>import {Logger} from 'aurelia-logging';

(function(global) {
  global.console = global.console || {};
  let con = global.console;
  let prop;
  let method;
  let empty = {};
  let dummy = function() {};
  let properties = 'memory'.split(',');
  let methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' +
     'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' +
     'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn').split(',');
  while (prop = properties.pop()) if (!con[prop]) con[prop] = empty;
  while (method = methods.pop()) if (!con[method]) con[method] = dummy;
})(typeof window === 'undefined' ? this : window);
// Using `this` for web workers while maintaining compatibility with browser
// targeted script loaders such as Browserify or Webpack where the only way to
// get to the global object is via `window`.

if (Function.prototype.bind && window.console && typeof console.log === 'object') {
  ['log', 'info', 'warn', 'error', 'assert', 'dir', 'clear', 'profile', 'profileEnd'].forEach(function(method) {
    console[method] = this.bind(console[method], console);
  }, Function.prototype.call);
}

export class ConsoleAppender {
  debug(logger : Logger, ...rest : any[]) : void {
    console.debug(`DEBUG [${logger.id}]`, ...rest);
  }

  info(logger : Logger, ...rest : any[]) : void {
    console.info(`INFO [${logger.id}]`, ...rest);
  }

  warn(logger : Logger, ...rest : any[]) : void {
    console.warn(`WARN [${logger.id}]`, ...rest);
  }

  error(logger : Logger, ...rest : any[]) : void {
    console.error(`ERROR [${logger.id}]`, ...rest);
  }
}
<commit_msg>doc(all): add more api docs<commit_after>import {Logger} from 'aurelia-logging';

(function(global) {
  global.console = global.console || {};
  let con = global.console;
  let prop;
  let method;
  let empty = {};
  let dummy = function() {};
  let properties = 'memory'.split(',');
  let methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' +
     'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' +
     'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn').split(',');
  while (prop = properties.pop()) if (!con[prop]) con[prop] = empty;
  while (method = methods.pop()) if (!con[method]) con[method] = dummy;
})(typeof window === 'undefined' ? this : window);
// Using `this` for web workers while maintaining compatibility with browser
// targeted script loaders such as Browserify or Webpack where the only way to
// get to the global object is via `window`.

if (Function.prototype.bind && window.console && typeof console.log === 'object') {
  ['log', 'info', 'warn', 'error', 'assert', 'dir', 'clear', 'profile', 'profileEnd'].forEach(function(method) {
    console[method] = this.bind(console[method], console);
  }, Function.prototype.call);
}

/*
 * An implementation of the Appender interface.
 */
export class ConsoleAppender {
  /**
  * Appends a debug log.
  *
  * @param logger The source logger.
  * @param rest The data to log.
  */
  debug(logger: Logger, ...rest : any[]): void {
    console.debug(`DEBUG [${logger.id}]`, ...rest);
  }

  /**
  * Appends an info log.
  *
  * @param logger The source logger.
  * @param rest The data to log.
  */
  info(logger: Logger, ...rest : any[]): void {
    console.info(`INFO [${logger.id}]`, ...rest);
  }

  /**
  * Appends a warning log.
  *
  * @param logger The source logger.
  * @param rest The data to log.
  */
  warn(logger: Logger, ...rest : any[]): void {
    console.warn(`WARN [${logger.id}]`, ...rest);
  }

  /**
  * Appends an error log.
  *
  * @param logger The source logger.
  * @param rest The data to log.
  */
  error(logger: Logger, ...rest : any[]): void {
    console.error(`ERROR [${logger.id}]`, ...rest);
  }
}
<|endoftext|>


<commit_before>var AuthInfo   = require('./authinfo');
var blobClient = require('./blob');
var kdf        = require('./kdf');

function VaultClient(opts) {
  if (!opts) opts = {};
  else if (typeof opts === "string") opts = {domain:opts};

  this.domain    = opts.domain || 'ripple.com';
  this.authInfo  = new AuthInfo;
};

VaultClient.prototype.login = function(username, password, fn) {
  var self = this;

  self.authInfo.get(self.domain, username, function(err, authInfo){
    if (err) return fn(err);

    console.log(authInfo);

    if (authInfo.version !== 3) {
      return fn(new Error("This wallet is incompatible with this version of ripple-client."));
    }

    if (!authInfo.pakdf) {
      return fn(new Error("No settings for PAKDF in auth packet."));
    }

    if (!authInfo.exists) {
      return fn(new Error("User does not exist."));
    }

    if ("string" !== typeof authInfo.blobvault) {
      return fn(new Error("No blobvault specified in the authinfo."));
    }

    //derive login keys
    kdf.deriveRemotely(authInfo.pakdf, 'login', username.toLowerCase(), password, function(err, keys){
      if (err) return fn(err);

      blobClient.get(authInfo.blobvault, keys.id, keys.crypt, function (err, blob) {
        if (err) return fn(err);

        fn (null, {
          blob     : blob,
          keys     : keys
        });
      });
    });
  });
};

VaultClient.prototype.relogin = function(id, cryptKey, fn) {

  fn(null, {
    blob: true
  });

};

VaultClient.prototype.unlock = function(username, password, encryptSecret, fn) {

  fn(null, {
    wallet: {
      secret: true
    }
  });

};

VaultClient.prototype.loginAndUnlock = function(username, password, fn) {

  fn(null, {
    wallet: {
      address: true,
      secret: true
    }
  });

};

module.exports = VaultClient;
<commit_msg>[FEATURE] Unlock and LoginAndUnlock<commit_after>var AuthInfo   = require('./authinfo');
var blobClient = require('./blob');
var crypt      = require('./crypt');

function VaultClient(opts) {
  if (!opts) opts = {};
  else if (typeof opts === "string") opts = {domain:opts};

  this.domain    = opts.domain || 'ripple.com';
  this.authInfo  = new AuthInfo;
  this.infos     = {};
};

/*
 * Login -
 * authenticate and retrieve a decrypted blob using a ripple name and password
 *
 */
VaultClient.prototype.login = function(username, password, fn) {
  var self = this;

  self.authInfo.get(self.domain, username, function(err, authInfo){
    if (err) return fn(err);

    console.log(authInfo);

    if (authInfo.version !== 3) {
      return fn(new Error("This wallet is incompatible with this version of ripple-client."));
    }

    if (!authInfo.pakdf) {
      return fn(new Error("No settings for PAKDF in auth packet."));
    }

    if (!authInfo.exists) {
      return fn(new Error("User does not exist."));
    }

    if ("string" !== typeof authInfo.blobvault) {
      return fn(new Error("No blobvault specified in the authinfo."));
    }

    //derive login keys
    crypt.derive(authInfo.pakdf, 'login', username.toLowerCase(), password, function(err, keys){
      if (err) return fn(err);

      blobClient.get(authInfo.blobvault, keys.id, keys.crypt, function (err, blob) {
        if (err) return fn(err);

        self.infos[keys.id] = authInfo;  //save for relogin

        fn (null, {
          blob : blob,
          keys : keys
        });
      });
    });
  });
};

/*
 * Relogin -
 * retreive and decrypt blob using id and crypt derived previously.
 *
 */
VaultClient.prototype.relogin = function(id, cryptKey, fn) {
  var authInfo = this.infos[id];

  if (!authInfo) return fn(new Error("Unable to find authInfo"));

  blobClient.get(authInfo.blobvault, id, cryptKey, function (err, blob) {
    if (err) return fn(err);

    fn (null, {
      blob : blob,
    });
  });
};

/*
 * Unlock -
 * decrypt the secret key using a username and password
 */
VaultClient.prototype.unlock = function(username, password, encryptSecret, fn) {
  var self = this;

  self.authInfo.get(self.domain, username, function(err, authInfo){
    if (err) return fn(err);

    //derive unlock key
    crypt.derive(authInfo.pakdf, 'unlock', username.toLowerCase(), password, function(err, keys){
      if (err) return fn(err);

      fn(null, {
        keys   : keys,
        secret : crypt.decrypt(keys.unlock, encryptSecret)
      });
    });
  });
};

/*
 * LoginAndUnlock
 * retrieve the decrypted blob and secret key in one step using
 * the username and password
 *
 */
VaultClient.prototype.loginAndUnlock = function(username, password, fn) {
  var self = this;

  this.login(username, password, function(err, resp){
    if (err) return fn(err);

    if (!resp.blob ||
        !resp.blob.data ||
        !resp.blob.data.encrypted_secret)
      return (new Error("Unable to retrieve blob and secret."));

    if (!resp.keys) return (new Error("Unable to retrieve keys."));

    //get authInfo via id - would have been saved from login
    var authInfo = self.infos[resp.keys.id];
    if (!authInfo) return fn(new Error("Unable to find authInfo"));

    //derive unlock key
    crypt.derive(authInfo.pakdf, 'unlock', username.toLowerCase(), password, function(err, keys){
      if (err) return fn(err);
      fn(null, {
        blob : resp.blob,
        keys : {
          id     : resp.keys.id,
          crypt  : resp.keys.crypt,
          unlock : keys.unlocked
        },
        secret: crypt.decrypt(keys.unlock, resp.blob.data.encrypted_secret)
      });
    });
  });
};

module.exports = VaultClient;
<|endoftext|>


<commit_before>import apiCreate from './api/create';
import apiEmit from './api/emit';
import apiFragment from './api/fragment';
import apiInit from './api/init';
import apiVersion from './api/version';
import assign from './util/assign';
import assignSafe from './util/assign-safe';
import attached from './lifecycle/attached';
import attribute from './lifecycle/attribute';
import created from './lifecycle/created';
import debounce from './util/debounce';
import defaults from './defaults';
import detached from './lifecycle/detached';
import documentObserver from './global/document-observer';
import elementConstructor from './util/element-constructor';
import registry from './global/registry';
import supportsCustomElements from './support/custom-elements';
import typeElement from './type/element';
import utilWalkTree from './util/walk-tree';
import validCustomElement from './support/valid-custom-element';

function makeOptions (userOptions) {
  var options = assignSafe({}, defaults);

  // Copy over all standard options if the user has defined them.
  for (let name in defaults) {
    if (userOptions[name] !== undefined) {
      options[name] = userOptions[name];
    }
  }

  // Copy over non-standard options.
  for (let name in userOptions) {
    options[name] = userOptions[name];
  }

  return options;
}

function makeNonNewableWrapper (Ctor) {
  var CtorWrapper = function (props = {}) {
    return assign(new Ctor(), props);
  };
  CtorWrapper.prototype = Ctor.prototype;
  return CtorWrapper;
}

var HTMLElement = window.HTMLElement;
var initDocument = debounce(function () {
  utilWalkTree(document.documentElement.childNodes, function (element) {
    var components = registry.find(element);
    var componentsLength = components.length;

    for (let a = 0; a < componentsLength; a++) {
      created(components[a]).call(element);
    }

    for (let a = 0; a < componentsLength; a++) {
      attached(components[a]).call(element);
    }
  });
});

function skate (id, userOptions) {
  var Ctor, CtorParent, isNative;
  var opts = makeOptions(userOptions);

  CtorParent = opts.extends ? document.createElement(opts.extends).constructor : HTMLElement;
  isNative = opts.type === typeElement && supportsCustomElements() && validCustomElement(id);

  // Inherit from parent prototype.
  if (!CtorParent.prototype.isPrototypeOf(opts.prototype)) {
    opts.prototype = assignSafe(Object.create(CtorParent.prototype), opts.prototype);
  }

  // Native doesn't like if you pass a falsy value. Must be undefined.
  opts.extends = opts.extends || undefined;

  // Extend behaviour of existing callbacks.
  opts.prototype.createdCallback = created(opts);
  opts.prototype.attachedCallback = attached(opts);
  opts.prototype.detachedCallback = detached(opts);
  opts.prototype.attributeChangedCallback = attribute(opts);

  // Ensure the ID can be retrieved from the options or constructor.
  opts.id = id;

  // Make a constructor for the definition.
  if (isNative) {
    Ctor = document.registerElement(id, opts);
  } else {

    // Store the check for a native custom element so we don't need to re-calculate it later.
    opts.isNative = isNative;

    Ctor = elementConstructor(opts);
    initDocument();
    documentObserver.register();
  }

  Ctor = makeNonNewableWrapper(Ctor);
  assignSafe(Ctor, opts);
  registry.set(id, Ctor);

  return Ctor;
}

skate.create = apiCreate;
skate.emit = apiEmit;
skate.fragment = apiFragment;
skate.init = apiInit;
skate.version = apiVersion;

// ES6
export default skate;
<commit_msg>Ensure original object isn't passed into the native registerElement function and we're only passing in what we need.<commit_after>import apiCreate from './api/create';
import apiEmit from './api/emit';
import apiFragment from './api/fragment';
import apiInit from './api/init';
import apiVersion from './api/version';
import assign from './util/assign';
import assignSafe from './util/assign-safe';
import attached from './lifecycle/attached';
import attribute from './lifecycle/attribute';
import created from './lifecycle/created';
import debounce from './util/debounce';
import defaults from './defaults';
import detached from './lifecycle/detached';
import documentObserver from './global/document-observer';
import elementConstructor from './util/element-constructor';
import registry from './global/registry';
import supportsCustomElements from './support/custom-elements';
import typeElement from './type/element';
import utilWalkTree from './util/walk-tree';
import validCustomElement from './support/valid-custom-element';

function makeOptions (userOptions) {
  var options = assignSafe({}, defaults);

  // Copy over all standard options if the user has defined them.
  for (let name in defaults) {
    if (userOptions[name] !== undefined) {
      options[name] = userOptions[name];
    }
  }

  // Copy over non-standard options.
  for (let name in userOptions) {
    options[name] = userOptions[name];
  }

  return options;
}

function makeNonNewableWrapper (Ctor) {
  var CtorWrapper = function (props = {}) {
    return assign(new Ctor(), props);
  };
  CtorWrapper.prototype = Ctor.prototype;
  return CtorWrapper;
}

var HTMLElement = window.HTMLElement;
var initDocument = debounce(function () {
  utilWalkTree(document.documentElement.childNodes, function (element) {
    var components = registry.find(element);
    var componentsLength = components.length;

    for (let a = 0; a < componentsLength; a++) {
      created(components[a]).call(element);
    }

    for (let a = 0; a < componentsLength; a++) {
      attached(components[a]).call(element);
    }
  });
});

function skate (id, userOptions) {
  var Ctor, CtorParent;
  var opts = makeOptions(userOptions);

  CtorParent = opts.extends ? document.createElement(opts.extends).constructor : HTMLElement;
  opts.isNative = opts.type === typeElement && supportsCustomElements() && validCustomElement(id);

  // Inherit from parent prototype.
  if (!CtorParent.prototype.isPrototypeOf(opts.prototype)) {
    opts.prototype = assignSafe(Object.create(CtorParent.prototype), opts.prototype);
  }

  // Native doesn't like if you pass a falsy value. Must be undefined.
  opts.extends = opts.extends || undefined;

  // Extend behaviour of existing callbacks.
  opts.prototype.createdCallback = created(opts);
  opts.prototype.attachedCallback = attached(opts);
  opts.prototype.detachedCallback = detached(opts);
  opts.prototype.attributeChangedCallback = attribute(opts);

  // Ensure the ID can be retrieved from the options or constructor.
  opts.id = id;

  // Make a constructor for the definition.
  if (opts.isNative) {
    Ctor = document.registerElement(id, {
      extends: opts.extends || undefined,
      prototype: opts.prototype
    });
  } else {
    Ctor = elementConstructor(opts);
    initDocument();
    documentObserver.register();
  }

  Ctor = makeNonNewableWrapper(Ctor);
  assignSafe(Ctor, opts);
  registry.set(id, Ctor);

  return Ctor;
}

skate.create = apiCreate;
skate.emit = apiEmit;
skate.fragment = apiFragment;
skate.init = apiInit;
skate.version = apiVersion;

// ES6
export default skate;
<|endoftext|>


<commit_before>(function() {
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
  module.exports = domify
} else {
  Node.prototype.dom = domify
  Document.prototype.dom = domify
}

/**
 * Just generates some kind-of-random ID. It just needs to be distinguishable from regular IDs
 * @return {string}  The generated ID
 */
let counter = 0
function generateId () {
  counter++
  return `p-${counter}-${Date.now()}`
}

/**
 * Generates an array of DOM Nodes
 * @param  {...any} partials   Might be anything. DOM Nodes are handled, arrays are iterated over and then handled, everything else just gets passed through
 * @return {Node[]}            An array of DOM Nodes
 */
function generateNodes (doc, ...partials) {
  // Array of placeholder IDs
  const placeholders = []
  // Generate regular HTML string first
  function reducer(carry, partial) {
    if (partial && partial.nodeType == Node.DOCUMENT_FRAGMENT_NODE) {
      partial = partial.childNodes
    }
    if (Array.isArray(partial)) {
      carry.concat(partial)
    } else if (typeof partial === 'object' && partial instanceof Node) {
      const id = generateId()
      placeholders.push({ id, node: partial })
      return carry.concat(`<${partial.nodeName} id="${id}"></${partial.nodeName}>`)
    } else if (partial && typeof partial.item == "function" && typeof partial.length == "number") {
      return carry.concat(Array.prototype.reduce.call(partial, reducer, []))
    } else {
      return carry.concat(partial)
    }
  }
  const html = partials.reduce(reducer, []).join('').replace(/^\s*</, "<").replace(/>\s*$/, ">")

  // Wrap in temporary container node
  let template = doc.createElement('template')
  template.innerHTML = html
  let container = template.content

  // Replace placeholders with real Nodes
  placeholders.forEach(({ id, node }) => {
    const placeholder = container.querySelector(`${node.nodeName}#${id}`)
    placeholder.parentNode.replaceChild(node, placeholder)
  })

  // Get array of Nodes
  return container
}

/**
 * A function that is suitable to be used as a function for tagged template strings
 * @param  {string[]}    strings  The literal parts of the template string
 * @param  {...values}   values   The interpolated parts of the template string
 * @return {Node[]}               An array of DOM Nodes
 */
function taggedTemplateHandler (doc, strings, ...values) {
  // Create an array that puts the values back in their place
  const arr = strings.reduce((carry, current, index) => {
    return carry.concat(current, (index + 1 === strings.length) ? [] : values[index])
  }, [])

  // Generate the Node array
  return generateNodes(doc, ...arr)
}

function domify (strings, ...values) {
  var doc = document
  if (this) {
    if (this.nodeType == Node.DOCUMENT_NODE) doc = this
    else if (this.ownerDocument) doc = this.ownerDocument
  }
  let result = taggedTemplateHandler(doc, strings, ...values)
  if (result.childNodes.length == 1) {
    let child = result.firstChild
    result.removeChild(child)
    return child
  } else {
    return result
  }
}

})()
<commit_msg>Detect if replacing an array of nodes and return fragment<commit_after>(function() {
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
  module.exports = domify
} else {
  Node.prototype.dom = domify
  Document.prototype.dom = domify
}

/**
 * Just generates some kind-of-random ID. It just needs to be distinguishable from regular IDs
 * @return {string}  The generated ID
 */
let counter = 0
function generateId () {
  counter++
  return `p-${counter}-${Date.now()}`
}

/**
 * Generates an array of DOM Nodes
 * @param  {...any} partials   Might be anything. DOM Nodes are handled, arrays are iterated over and then handled, everything else just gets passed through
 * @return {Node[]}            An array of DOM Nodes
 */
function generateNodes (doc, ...partials) {
  // Array of placeholder IDs
  const placeholders = []
  // Generate regular HTML string first
  function reducer(carry, partial) {
    if (partial && partial.nodeType == Node.DOCUMENT_FRAGMENT_NODE) {
      partial = partial.childNodes
    }
    if (Array.isArray(partial)) {
      carry.concat(partial)
    } else if (typeof partial === 'object' && partial instanceof Node) {
      const id = generateId()
      placeholders.push({ id, node: partial })
      return carry.concat(`<${partial.nodeName} id="${id}"></${partial.nodeName}>`)
    } else if (partial && typeof partial.item == "function" && typeof partial.length == "number") {
      return carry.concat(Array.prototype.reduce.call(partial, reducer, []))
    } else {
      return carry.concat(partial)
    }
  }
  const html = partials.reduce(reducer, []).join('').replace(/^\s*</, "<").replace(/>\s*$/, ">")

  // Wrap in temporary container node
  let template = doc.createElement('template')
  template.innerHTML = html
  let container = template.content

  // Replace placeholders with real Nodes
  placeholders.forEach(({ id, node }) => {
    const placeholder = container.querySelector(`${node.nodeName}#${id}`)
    placeholder.parentNode.replaceChild(node, placeholder)
  })

  const shouldBeFragment = partials.some(item => typeof item === 'object' && item instanceof Node)

  if (container.childNodes.length == 1 && !shouldBeFragment) {
    let child = container.firstChild
    container.removeChild(child)
    return child
  } else {
    return container
  }
  return container
}

/**
 * A function that is suitable to be used as a function for tagged template strings
 * @param  {string[]}    strings  The literal parts of the template string
 * @param  {...values}   values   The interpolated parts of the template string
 * @return {Node[]}               An array of DOM Nodes
 */
function taggedTemplateHandler (doc, strings, ...values) {
  // Create an array that puts the values back in their place
  const arr = strings.reduce((carry, current, index) => {
    return carry.concat(current, (index + 1 === strings.length) ? [] : values[index])
  }, [])

  return generateNodes(doc, ...arr)
}

function domify (strings, ...values) {
  var doc = document
  if (this) {
    if (this.nodeType == Node.DOCUMENT_NODE) doc = this
    else if (this.ownerDocument) doc = this.ownerDocument
  }
  return taggedTemplateHandler(doc, strings, ...values)
}

})()
<|endoftext|>


<commit_before>import { isFSA } from 'flux-standard-action';

const typeOf = (type) => (val) => typeof val === type;
const isFunction = typeOf('function');

export default runIO => function futureMiddleware({ dispatch }) {
  const isIO = io => io && isFunction(io[runIO]);

  return next => action => {
    if (!isFSA(action)) {
      return isIO(action)
        ? dispatch(action[runIO]())
        : next(action);
    }

    return isIO(action.payload)
      ? dispatch({ ...action, payload: action.payload[runIO]() })
      : next(action);
  };
}
<commit_msg>rename function<commit_after>import { isFSA } from 'flux-standard-action';

const typeOf = (type) => (val) => typeof val === type;
const isFunction = typeOf('function');

export default runIO => function ioMiddleware({ dispatch }) {
  const isIO = io => io && isFunction(io[runIO]);

  return next => action => {
    if (!isFSA(action)) {
      return isIO(action)
        ? dispatch(action[runIO]())
        : next(action);
    }

    return isIO(action.payload)
      ? dispatch({ ...action, payload: action.payload[runIO]() })
      : next(action);
  };
}
<|endoftext|>


<commit_before>require('babel-polyfill')

const AWS = require('aws-sdk')
const request = require('request')
const blogs = require('./art-blogs.json')
const date_format = require('date-format')

let s3 = new AWS.S3()

const gen_key = function (date, blog_name) {
  let date_dir = 'feeds/' + date
  let dir = date_dir + '/' + blog_name
  let key = (dir + '/feed.rss')
  return key
}

exports.handler = function (event, context) {
  console.log('just called. event:', event, 'context:', context)

  let now = new Date()
  let date = date_format(now, 'isoDateTime')

  console.log('gonna do the blogs. there are', blogs.length)

  for (let blog of blogs) {
    console.log('doing a blog', date, blog.name)

    let key = gen_key(date, blog.name)

    request(blog.url, function (err, res, body) {
      if (err) {
        context.fail(err)
        return
      }
      let params = {
        Bucket: 'art-data',
        Key: key,
        Body: body
      }
      s3.upload(params, function (err, data) {
        if (err) {
          context.fail(err)
        } else {
          context.succeed(data)
        }
      })
    })
  }
}

<commit_msg>better-dates<commit_after>require('babel-polyfill')

const AWS = require('aws-sdk')
const request = require('request')
const blogs = require('./art-blogs.json')
const date_format = require('date-format')

let s3 = new AWS.S3()

const gen_key = function (date, blog_name) {
  let date_dir = 'feeds/' + date
  let dir = date_dir + '/' + blog_name
  let key = (dir + '/feed.rss')
  return key
}

exports.handler = function (event, context) {
  let now = new Date()
  let date = date_format(now, 'YYYY-MM-dd-at-hh-mm-ss')

  for (let blog of blogs) {
    let key = gen_key(date, blog.name)

    request(blog.url, function (err, res, body) {
      if (err) {
        context.fail(err)
        return
      }
      let params = {
        Bucket: 'art-data',
        Key: key,
        Body: body
      }
      s3.upload(params, function (err, data) {
        if (err) {
          context.fail(err)
        } else {
          context.succeed(data)
        }
      })
    })
  }
}

<|endoftext|>


<commit_before>export default function($q) {
  'ngInject';

  // Chain a query into a new one (when the query updates so does the new query)
  function Chain(origQry, Model, qryFn) {
    var initialSync = false;

    if (!qryFn) {
      qryFn = Model;
      Model = origQry.$Model;
    }

    // Make sure we have at least finished an initial load before generating the
    // query object
    var _qry = origQry.$promise.then(function() {
      initialSync = true;
      return qryFn(origQry);
    });
    var newqry = Model.query(_qry);

    // Watch our results. If they change then reattempt the query
    origQry.$emitter.on('update', function(newRes) {
      // Only do this if we have initially synced
      if (initialSync) {
        newqry.replace(qryFn(newRes));
      }
    });

    return newqry;
  }

  function all(origQueries, Model, qryFn) {
    var newqry;
    var proms = [];
    var initialSync;
    var allqries;
    origQueries.forEach(function(origQry) {
      proms.push(origQry.$promise);
      origQry.$emitter.on('update', function() {
        if (initialSync) {
          newqry.replace(qryFn(allqries));
        }
      });
    });

    newqry = Model.query($q.all(proms).then(function(res) {
      initialSync = true;
      allqries = res;
      return qryFn(res);
    }));

    return newqry;
  }

  Chain.all = all;

  return Chain;
};
<commit_msg>all `this` in chaining to get at results array<commit_after>export default function($q) {
  'ngInject';

  // Chain a query into a new one (when the query updates so does the new query)
  function Chain(origQry, Model, qryFn) {
    var initialSync = false;

    if (!qryFn) {
      qryFn = Model;
      Model = origQry.$Model;
    }

    // Make sure we have at least finished an initial load before generating the
    // query object
    var _qry = origQry.$promise.then(function() {
      initialSync = true;
      return qryFn(origQry);
    });
    var newqry = Model.query(_qry);

    // Bind qryFn to newqry
    qryFn = qryFn.bind(newqry);

    // Watch our results. If they change then reattempt the query
    origQry.$emitter.on('update', function(newRes) {
      // Only do this if we have initially synced
      if (initialSync) {
        newqry.replace(qryFn(newRes));
      }
    });

    return newqry;
  }

  function all(origQueries, Model, qryFn) {
    var newqry;
    var proms = [];
    var initialSync;
    var allqries;

    origQueries.forEach(function(origQry) {
      proms.push(origQry.$promise);
      origQry.$emitter.on('update', function() {
        if (initialSync) {
          newqry.replace(qryFn(allqries));
        }
      });
    });

    newqry = Model.query($q.all(proms).then(function(res) {
      initialSync = true;
      allqries = res;
      return qryFn(res);
    }));

    qryFn = qryFn.bind(newqry);

    return newqry;
  }

  Chain.all = all;

  return Chain;
}
<|endoftext|>


<commit_before>import * as drawing from './util/drawing.js';

// V3 EXPORTS
export { default as init } from './init.js';

// ~~~~~~ TOOLS ~~~~~ //
export {
  default as arrowAnnotateTool
} from './fancy-tools/arrowAnnotateTool.js';
export { default as angleTool } from './fancy-tools/angleTool.js';
export {
  default as ellipticalRoiTool
} from './fancy-tools/ellipticalRoiTool.js';
export { default as eraserTool } from './fancy-tools/eraserTool.js';
export {
  default as freehandMouseTool
} from './fancy-tools/freehandMouseTool.js';
export {
  default as freehandSculpterMouseTool
} from './fancy-tools/freehandSculpterMouseTool.js';
export { default as lengthTool } from './fancy-tools/lengthTool.js';
export { default as magnifyTool } from './fancy-tools/magnifyTool.js';
export { default as probeTool } from './fancy-tools/probeTool.js';
export { default as rectangleRoiTool } from './fancy-tools/rectangleRoiTool.js';
export { default as rotateTool } from './fancy-tools/rotateTool.js';
export { default as scaleOverlayTool } from './fancy-tools/scaleOverlay.js';
export { default as wwwcTool } from './fancy-tools/wwwcTool.js';
export { default as wwwcRegionTool } from './fancy-tools/wwwcRegionTool.js';
export { default as zoomTool } from './fancy-tools/zoomTool.js';
export {
  default as zoomTouchPinchTool
} from './fancy-tools/zoomTouchPinchTool.js';
export {
  default as zoomMouseWheelTool
} from './fancy-tools/zoomMouseWheelTool.js';

// END V3 EXPORTS

export { drawing };

export { default as external } from './externalModules.js';
export { default as EVENTS } from './events.js';

export { default as referenceLines } from './referenceLines/index.js';
export { default as orientation } from './orientation/index.js';

export {
  default as requestPoolManager
} from './requestPool/requestPoolManager.js';

export {
  default as setContextToDisplayFontSize
} from './util/setContextToDisplayFontSize.js';
export { default as scrollToIndex } from './util/scrollToIndex.js';
export { default as scroll } from './util/scroll.js';
export { default as roundToDecimal } from './util/roundToDecimal.js';
export {
  projectPatientPointToImagePlane,
  imagePointToPatientPoint,
  planePlaneIntersection
} from './util/pointProjector.js';

export {
  default as pointInsideBoundingBox
} from './util/pointInsideBoundingBox.js';
export { default as pointInEllipse } from './util/pointInEllipse.js';
export { default as makeUnselectable } from './util/makeUnselectable.js';
export {
  default as isMouseButtonEnabled
} from './util/isMouseButtonEnabled.js';
export { default as getRGBPixels } from './util/getRGBPixels.js';
export {
  getDefaultSimultaneousRequests,
  getMaxSimultaneousRequests,
  getBrowserInfo,
  isMobileDevice
} from './util/getMaxSimultaneousRequests.js';

export { default as getLuminance } from './util/getLuminance.js';
export { default as drawTextBox } from './util/drawTextBox.js';
export { default as drawEllipse } from './util/drawEllipse.js';
export { default as drawCircle } from './util/drawCircle.js';
export { default as drawArrow } from './util/drawArrow.js';
export { default as copyPoints } from './util/copyPoints.js';
export { default as calculateSUV } from './util/calculateSUV.js';
export {
  default as calculateEllipseStatistics
} from './util/calculateEllipseStatistics.js';

export {
  default as incrementTimePoint
} from './timeSeriesTools/incrementTimePoint.js';
export {
  default as timeSeriesPlayer
} from './timeSeriesTools/timeSeriesPlayer.js';

export {
  default as wwwcSynchronizer
} from './synchronization/wwwcSynchronizer.js';
export {
  default as updateImageSynchronizer
} from './synchronization/updateImageSynchronizer.js';
export { default as Synchronizer } from './synchronization/Synchronizer.js';
export {
  default as stackScrollSynchronizer
} from './synchronization/stackScrollSynchronizer.js';
export {
  default as stackImagePositionSynchronizer
} from './synchronization/stackImagePositionSynchronizer.js';
export {
  default as stackImagePositionOffsetSynchronizer
} from './synchronization/stackImagePositionOffsetSynchronizer.js';
export {
  default as stackImageIndexSynchronizer
} from './synchronization/stackImageIndexSynchronizer.js';
export {
  default as panZoomSynchronizer
} from './synchronization/panZoomSynchronizer.js';

export { default as toolStyle } from './stateManagement/toolStyle.js';
export {
  addToolState,
  getToolState,
  removeToolState,
  clearToolState,
  setElementToolStateManager,
  getElementToolStateManager
} from './stateManagement/toolState.js';
export {
  default as toolCoordinates
} from './stateManagement/toolCoordinates.js';
export { default as toolColors } from './stateManagement/toolColors.js';
export {
  addTimeSeriesStateManager,
  newTimeSeriesSpecificToolStateManager
} from './stateManagement/timeSeriesSpecificStateManager.js';
export { default as textStyle } from './stateManagement/textStyle.js';

export {
  stackSpecificStateManager,
  newStackSpecificToolStateManager,
  addStackStateManager
} from './stateManagement/stackSpecificStateManager.js';

export {
  default as loadHandlerManager
} from './stateManagement/loadHandlerManager.js';

export {
  newImageIdSpecificToolStateManager,
  globalImageIdSpecificToolStateManager
} from './stateManagement/imageIdSpecificStateManager.js';

export {
  newFrameOfReferenceSpecificToolStateManager,
  globalFrameOfReferenceSpecificToolStateManager
} from './stateManagement/frameOfReferenceStateManager.js';

export { default as appState } from './stateManagement/appState.js';

export { default as stackPrefetch } from './stackTools/stackPrefetch.js';
export { default as stackRenderers } from './stackTools/stackRenderers.js';
export { playClip, stopClip } from './stackTools/playClip.js';

export {
  default as anyHandlesOutsideImage
} from './manipulators/anyHandlesOutsideImage.js';
export { default as drawHandles } from './manipulators/drawHandles.js';
export {
  default as getHandleNearImagePoint
} from './manipulators/getHandleNearImagePoint.js';
export { default as handleActivator } from './manipulators/handleActivator.js';
export { default as moveAllHandles } from './manipulators/moveAllHandles.js';
export { default as moveHandle } from './manipulators/moveHandle.js';
export { default as moveNewHandle } from './manipulators/moveNewHandle.js';
export {
  default as moveNewHandleTouch
} from './manipulators/moveNewHandleTouch.js';
export {
  default as touchMoveAllHandles
} from './manipulators/touchMoveAllHandles.js';
export { default as touchMoveHandle } from './manipulators/touchMoveHandle.js';

export { default as keyboardInput } from './inputSources/keyboardInput.js';
export { default as mouseInput } from './inputSources/mouseInput.js';
export { default as mouseWheelInput } from './inputSources/mouseWheelInput.js';
export {
  default as preventGhostClick
} from './inputSources/preventGhostClick.js';
export { default as touchInput } from './inputSources/touchInput.js';

export { default as version } from './version.js';

export { setToolOptions, getToolOptions } from './toolOptions.js';
<commit_msg>Remove event listeners from exposed api<commit_after>import * as drawing from './util/drawing.js';

// V3 EXPORTS
export { default as init } from './init.js';

// ~~~~~~ TOOLS ~~~~~ //
export {
  default as arrowAnnotateTool
} from './fancy-tools/arrowAnnotateTool.js';
export { default as angleTool } from './fancy-tools/angleTool.js';
export {
  default as ellipticalRoiTool
} from './fancy-tools/ellipticalRoiTool.js';
export { default as eraserTool } from './fancy-tools/eraserTool.js';
export {
  default as freehandMouseTool
} from './fancy-tools/freehandMouseTool.js';
export {
  default as freehandSculpterMouseTool
} from './fancy-tools/freehandSculpterMouseTool.js';
export { default as lengthTool } from './fancy-tools/lengthTool.js';
export { default as magnifyTool } from './fancy-tools/magnifyTool.js';
export { default as probeTool } from './fancy-tools/probeTool.js';
export { default as rectangleRoiTool } from './fancy-tools/rectangleRoiTool.js';
export { default as rotateTool } from './fancy-tools/rotateTool.js';
export { default as scaleOverlayTool } from './fancy-tools/scaleOverlay.js';
export { default as wwwcTool } from './fancy-tools/wwwcTool.js';
export { default as wwwcRegionTool } from './fancy-tools/wwwcRegionTool.js';
export { default as zoomTool } from './fancy-tools/zoomTool.js';
export {
  default as zoomTouchPinchTool
} from './fancy-tools/zoomTouchPinchTool.js';
export {
  default as zoomMouseWheelTool
} from './fancy-tools/zoomMouseWheelTool.js';

// END V3 EXPORTS

export { drawing };

export { default as external } from './externalModules.js';
export { default as EVENTS } from './events.js';

export { default as referenceLines } from './referenceLines/index.js';
export { default as orientation } from './orientation/index.js';

export {
  default as requestPoolManager
} from './requestPool/requestPoolManager.js';

export {
  default as setContextToDisplayFontSize
} from './util/setContextToDisplayFontSize.js';
export { default as scrollToIndex } from './util/scrollToIndex.js';
export { default as scroll } from './util/scroll.js';
export { default as roundToDecimal } from './util/roundToDecimal.js';
export {
  projectPatientPointToImagePlane,
  imagePointToPatientPoint,
  planePlaneIntersection
} from './util/pointProjector.js';

export {
  default as pointInsideBoundingBox
} from './util/pointInsideBoundingBox.js';
export { default as pointInEllipse } from './util/pointInEllipse.js';
export { default as makeUnselectable } from './util/makeUnselectable.js';
export {
  default as isMouseButtonEnabled
} from './util/isMouseButtonEnabled.js';
export { default as getRGBPixels } from './util/getRGBPixels.js';
export {
  getDefaultSimultaneousRequests,
  getMaxSimultaneousRequests,
  getBrowserInfo,
  isMobileDevice
} from './util/getMaxSimultaneousRequests.js';

export { default as getLuminance } from './util/getLuminance.js';
export { default as drawTextBox } from './util/drawTextBox.js';
export { default as drawEllipse } from './util/drawEllipse.js';
export { default as drawCircle } from './util/drawCircle.js';
export { default as drawArrow } from './util/drawArrow.js';
export { default as copyPoints } from './util/copyPoints.js';
export { default as calculateSUV } from './util/calculateSUV.js';
export {
  default as calculateEllipseStatistics
} from './util/calculateEllipseStatistics.js';

export {
  default as incrementTimePoint
} from './timeSeriesTools/incrementTimePoint.js';
export {
  default as timeSeriesPlayer
} from './timeSeriesTools/timeSeriesPlayer.js';

export {
  default as wwwcSynchronizer
} from './synchronization/wwwcSynchronizer.js';
export {
  default as updateImageSynchronizer
} from './synchronization/updateImageSynchronizer.js';
export { default as Synchronizer } from './synchronization/Synchronizer.js';
export {
  default as stackScrollSynchronizer
} from './synchronization/stackScrollSynchronizer.js';
export {
  default as stackImagePositionSynchronizer
} from './synchronization/stackImagePositionSynchronizer.js';
export {
  default as stackImagePositionOffsetSynchronizer
} from './synchronization/stackImagePositionOffsetSynchronizer.js';
export {
  default as stackImageIndexSynchronizer
} from './synchronization/stackImageIndexSynchronizer.js';
export {
  default as panZoomSynchronizer
} from './synchronization/panZoomSynchronizer.js';

export { default as toolStyle } from './stateManagement/toolStyle.js';
export {
  addToolState,
  getToolState,
  removeToolState,
  clearToolState,
  setElementToolStateManager,
  getElementToolStateManager
} from './stateManagement/toolState.js';
export {
  default as toolCoordinates
} from './stateManagement/toolCoordinates.js';
export { default as toolColors } from './stateManagement/toolColors.js';
export {
  addTimeSeriesStateManager,
  newTimeSeriesSpecificToolStateManager
} from './stateManagement/timeSeriesSpecificStateManager.js';
export { default as textStyle } from './stateManagement/textStyle.js';

export {
  stackSpecificStateManager,
  newStackSpecificToolStateManager,
  addStackStateManager
} from './stateManagement/stackSpecificStateManager.js';

export {
  default as loadHandlerManager
} from './stateManagement/loadHandlerManager.js';

export {
  newImageIdSpecificToolStateManager,
  globalImageIdSpecificToolStateManager
} from './stateManagement/imageIdSpecificStateManager.js';

export {
  newFrameOfReferenceSpecificToolStateManager,
  globalFrameOfReferenceSpecificToolStateManager
} from './stateManagement/frameOfReferenceStateManager.js';

export { default as appState } from './stateManagement/appState.js';

export { default as stackPrefetch } from './stackTools/stackPrefetch.js';
export { default as stackRenderers } from './stackTools/stackRenderers.js';
export { playClip, stopClip } from './stackTools/playClip.js';

export {
  default as anyHandlesOutsideImage
} from './manipulators/anyHandlesOutsideImage.js';
export { default as drawHandles } from './manipulators/drawHandles.js';
export {
  default as getHandleNearImagePoint
} from './manipulators/getHandleNearImagePoint.js';
export { default as handleActivator } from './manipulators/handleActivator.js';
export { default as moveAllHandles } from './manipulators/moveAllHandles.js';
export { default as moveHandle } from './manipulators/moveHandle.js';
export { default as moveNewHandle } from './manipulators/moveNewHandle.js';
export {
  default as moveNewHandleTouch
} from './manipulators/moveNewHandleTouch.js';
export {
  default as touchMoveAllHandles
} from './manipulators/touchMoveAllHandles.js';
export { default as touchMoveHandle } from './manipulators/touchMoveHandle.js';

export { default as version } from './version.js';

export { setToolOptions, getToolOptions } from './toolOptions.js';
<|endoftext|>


<commit_before>/*!
 * Clamp.js 0.7.0
 * Based on: https://github.com/xavi160/Clamp.js/commit/e313818da231b8dd8fd603dd9c9a61a9d725c22f
 * Mixins:
 * - https://github.com/josephschmitt/Clamp.js/pull/50
 * - https://github.com/josephschmitt/Clamp.js/pull/49
 *
 * Copyright 2011-2013, Joseph Schmitt http://joe.sh
 * Released under the WTFPL license
 * http://sam.zoy.org/wtfpl/
 */

(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD
    define([], factory);
  } else if (typeof exports === 'object') {
    // Node, CommonJS-like
    module.exports = factory();
  } else {
    // Browser globals
    root.$clamp = factory();
  }
}(this, function() {
  /**
   * Clamps a text node.
   * @param {HTMLElement} element. Element containing the text node to clamp.
   * @param {Object} options. Options to pass to the clamper.
   */
  function clamp(element, options) {
    options = options || {};

    var self = this,
      win = window,
      opt = {
        clamp: options.clamp || 2,
        useNativeClamp: typeof(options.useNativeClamp) != 'undefined' ? options.useNativeClamp : true,
        splitOnChars: options.splitOnChars || ['.', '-', '–', '—', ' '], //Split on sentences (periods), hypens, en-dashes, em-dashes, and words (spaces).
        animate: options.animate || false,
        truncationChar: options.truncationChar || '…',
        truncationHTML: options.truncationHTML
      },

      sty = element.style,
      originalText = element.innerHTML,

      supportsNativeClamp = typeof(element.style.webkitLineClamp) != 'undefined',
      clampValue = opt.clamp,
      isCSSValue = clampValue.indexOf && (clampValue.indexOf('px') > -1 || clampValue.indexOf('em') > -1),
      truncationHTMLContainer;

    if (opt.truncationHTML) {
      truncationHTMLContainer = document.createElement('span');
      truncationHTMLContainer.innerHTML = opt.truncationHTML;
    }

    // UTILITY FUNCTIONS __________________________________________________________

    /**
     * Return the current style for an element.
     * @param {HTMLElement} elem The element to compute.
     * @param {string} prop The style property.
     * @returns {number}
     */
    function computeStyle(elem, prop) {
      if (!win.getComputedStyle) {
        win.getComputedStyle = function(el, pseudo) {
          this.el = el;
          this.getPropertyValue = function(prop) {
            var re = /(\-([a-z]){1})/g;
            if (prop == 'float') prop = 'styleFloat';
            if (re.test(prop)) {
              prop = prop.replace(re, function() {
                return arguments[2].toUpperCase();
              });
            }
            return el.currentStyle && el.currentStyle[prop] ? el.currentStyle[prop] : null;
          };
          return this;
        };
      }

      return win.getComputedStyle(elem, null).getPropertyValue(prop);
    }

    /**
     * Returns the maximum number of lines of text that should be rendered based
     * on the current height of the element and the line-height of the text.
     */
    function getMaxLines(height) {
      var availHeight = height || (element.parentNode.clientHeight-element.offsetTop),
        lineHeight = getLineHeight(element);

      return Math.max(Math.floor(availHeight / lineHeight), 0);
    }

    /**
     * Returns the maximum height a given element should have based on the line-
     * height of the text and the given clamp value.
     */
    function getMaxHeight(clmp) {
      var lineHeight = getLineHeight(element);
      return lineHeight * clmp;
    }

    /**
     * Returns the line-height of an element as an integer.
     */
    function getLineHeight(elem) {
      var lh = computeStyle(elem, 'line-height');
      if (lh == 'normal') {
        // Normal line heights vary from browser to browser. The spec recommends
        // a value between 1.0 and 1.2 of the font size. Using 1.1 to split the diff.
        lh = parseInt(computeStyle(elem, 'font-size'), 10) * 1.2;
      }
      return parseInt(lh, 10);
    }

    // MEAT AND POTATOES (MMMM, POTATOES...) ______________________________________
    var splitOnChars = opt.splitOnChars.slice(0),
      splitChar = splitOnChars[0],
      chunks,
      lastChunk;

    /**
     * Gets an element's last child. That may be another node or a node's contents.
     */
    function getLastChild(elem) {
      if (!elem.lastChild) {
        return;
      }
      //Current element has children, need to go deeper and get last child as a text node
      if (elem.lastChild.children && elem.lastChild.children.length > 0) {
        return getLastChild(Array.prototype.slice.call(elem.children).pop());
      } else if (
        !elem.lastChild
        || !elem.lastChild.nodeValue
        || elem.lastChild.nodeValue == opt.truncationChar
        || elem.lastChild.nodeType === Node.COMMENT_NODE
      ) {
        // Handle scenario where the last child is white-space node
        var sibling = elem.lastChild;
        do {
          if (!sibling) {
            return;
          }
          // TEXT_NODE
          if (
            sibling.nodeType === 3
            && ['', opt.truncationChar].indexOf(sibling.nodeValue) === -1
            && elem.lastChild.nodeType !== Node.COMMENT_NODE
          ) {
            return sibling;
          }
          if (sibling.lastChild) {
            var lastChild = getLastChild(sibling);
            if (lastChild) {
              return lastChild;
            }
          }
          //Current sibling is pretty useless
          sibling.parentNode.removeChild(sibling);
        } while (sibling = sibling.previousSibling);
      }
      //This is the last child we want, return it
      else {
        return elem.lastChild;
      }
    }

    /**
     * Removes one character at a time from the text until its width or
     * height is beneath the passed-in max param.
     */
    function truncate(target, maxHeight) {
      if (!target || !maxHeight) {
        return;
      }

      /**
       * Resets global variables.
       */
      function reset() {
        splitOnChars = opt.splitOnChars.slice(0);
        splitChar = splitOnChars[0];
        chunks = null;
        lastChunk = null;
      }

      var nodeValue = target.nodeValue.replace(opt.truncationChar, '');

      //Grab the next chunks
      if (!chunks) {
        //If there are more characters to try, grab the next one
        if (splitOnChars.length > 0) {
          splitChar = splitOnChars.shift();
        }
        //No characters to chunk by. Go character-by-character
        else {
          splitChar = '';
        }

        chunks = nodeValue.split(splitChar);
      }

      //If there are chunks left to remove, remove the last one and see if
      // the nodeValue fits.
      if (chunks.length > 1) {
        // console.log('chunks', chunks);
        lastChunk = chunks.pop();
        // console.log('lastChunk', lastChunk);
        applyEllipsis(target, chunks.join(splitChar));
      }
      //No more chunks can be removed using this character
      else {
        chunks = null;
      }

      //Insert the custom HTML before the truncation character
      if (truncationHTMLContainer) {
        target.nodeValue = target.nodeValue.replace(opt.truncationChar, '');
        element.innerHTML = target.nodeValue + ' ' + truncationHTMLContainer.innerHTML + opt.truncationChar;
      }

      //Search produced valid chunks
      if (chunks) {
        //It fits
        if (element.clientHeight <= maxHeight) {
          //There's still more characters to try splitting on, not quite done yet
          if (splitOnChars.length >= 0 && splitChar !== '') {
            applyEllipsis(target, chunks.join(splitChar) + splitChar + lastChunk);
            chunks = null;
          }
          //Finished!
          else {
            return element.innerHTML;
          }
        }
      }
      //No valid chunks produced
      else {
        //No valid chunks even when splitting by letter, time to move
        //on to the next node
        if (splitChar === '') {
          applyEllipsis(target, '');
          target = getLastChild(element);

          reset();
        }
      }

      //If you get here it means still too big, let's keep truncating
      if (opt.animate) {
        setTimeout(function() {
          truncate(target, maxHeight);
        }, opt.animate === true ? 10 : opt.animate);
      } else {
        return truncate(target, maxHeight);
      }
    }

    function applyEllipsis(elem, str) {
      elem.nodeValue = str + opt.truncationChar;
    }

    // CONSTRUCTOR ________________________________________________________________

    if (clampValue == 'auto') {
      clampValue = getMaxLines();
    } else if (isCSSValue) {
      clampValue = getMaxLines(parseInt(clampValue, 10));
    }

    var clampedText;
    if (supportsNativeClamp && opt.useNativeClamp) {
      sty.overflow = 'hidden';
      sty.textOverflow = 'ellipsis';
      sty.webkitBoxOrient = 'vertical';
      sty.display = '-webkit-box';
      sty.webkitLineClamp = clampValue;

      if (isCSSValue) {
        sty.height = opt.clamp + 'px';
      }
    } else {
      var height = getMaxHeight(clampValue);
      if (height < element.clientHeight) {
        clampedText = truncate(getLastChild(element), height);
      }
    }

    return {
      'original': originalText,
      'clamped': clampedText
    };
  }

  return clamp;
}));
<commit_msg>round line-height value from computed float value (#50)<commit_after>/*!
 * Clamp.js 0.7.0
 * Based on: https://github.com/xavi160/Clamp.js/commit/e313818da231b8dd8fd603dd9c9a61a9d725c22f
 * Mixins:
 * - https://github.com/josephschmitt/Clamp.js/pull/50
 * - https://github.com/josephschmitt/Clamp.js/pull/49
 *
 * Copyright 2011-2013, Joseph Schmitt http://joe.sh
 * Released under the WTFPL license
 * http://sam.zoy.org/wtfpl/
 */

(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD
    define([], factory);
  } else if (typeof exports === 'object') {
    // Node, CommonJS-like
    module.exports = factory();
  } else {
    // Browser globals
    root.$clamp = factory();
  }
}(this, function() {
  /**
   * Clamps a text node.
   * @param {HTMLElement} element. Element containing the text node to clamp.
   * @param {Object} options. Options to pass to the clamper.
   */
  function clamp(element, options) {
    options = options || {};

    var self = this,
      win = window,
      opt = {
        clamp: options.clamp || 2,
        useNativeClamp: typeof(options.useNativeClamp) != 'undefined' ? options.useNativeClamp : true,
        splitOnChars: options.splitOnChars || ['.', '-', '–', '—', ' '], //Split on sentences (periods), hypens, en-dashes, em-dashes, and words (spaces).
        animate: options.animate || false,
        truncationChar: options.truncationChar || '…',
        truncationHTML: options.truncationHTML
      },

      sty = element.style,
      originalText = element.innerHTML,

      supportsNativeClamp = typeof(element.style.webkitLineClamp) != 'undefined',
      clampValue = opt.clamp,
      isCSSValue = clampValue.indexOf && (clampValue.indexOf('px') > -1 || clampValue.indexOf('em') > -1),
      truncationHTMLContainer;

    if (opt.truncationHTML) {
      truncationHTMLContainer = document.createElement('span');
      truncationHTMLContainer.innerHTML = opt.truncationHTML;
    }

    // UTILITY FUNCTIONS __________________________________________________________

    /**
     * Return the current style for an element.
     * @param {HTMLElement} elem The element to compute.
     * @param {string} prop The style property.
     * @returns {number}
     */
    function computeStyle(elem, prop) {
      if (!win.getComputedStyle) {
        win.getComputedStyle = function(el, pseudo) {
          this.el = el;
          this.getPropertyValue = function(prop) {
            var re = /(\-([a-z]){1})/g;
            if (prop == 'float') prop = 'styleFloat';
            if (re.test(prop)) {
              prop = prop.replace(re, function() {
                return arguments[2].toUpperCase();
              });
            }
            return el.currentStyle && el.currentStyle[prop] ? el.currentStyle[prop] : null;
          };
          return this;
        };
      }

      return win.getComputedStyle(elem, null).getPropertyValue(prop);
    }

    /**
     * Returns the maximum number of lines of text that should be rendered based
     * on the current height of the element and the line-height of the text.
     */
    function getMaxLines(height) {
      var availHeight = height || (element.parentNode.clientHeight-element.offsetTop),
        lineHeight = getLineHeight(element);

      return Math.max(Math.floor(availHeight / lineHeight), 0);
    }

    /**
     * Returns the maximum height a given element should have based on the line-
     * height of the text and the given clamp value.
     */
    function getMaxHeight(clmp) {
      var lineHeight = getLineHeight(element);
      return lineHeight * clmp;
    }

    /**
     * Returns the line-height of an element as an integer.
     */
    function getLineHeight(elem) {
      var lh = computeStyle(elem, 'line-height');
      if (lh == 'normal') {
        // Normal line heights vary from browser to browser. The spec recommends
        // a value between 1.0 and 1.2 of the font size. Using 1.1 to split the diff.
        lh = parseFloat(computeStyle(elem, 'font-size')) * 1.2;
      }
      return Math.round(parseFloat(lh));
    }

    // MEAT AND POTATOES (MMMM, POTATOES...) ______________________________________
    var splitOnChars = opt.splitOnChars.slice(0),
      splitChar = splitOnChars[0],
      chunks,
      lastChunk;

    /**
     * Gets an element's last child. That may be another node or a node's contents.
     */
    function getLastChild(elem) {
      if (!elem.lastChild) {
        return;
      }
      //Current element has children, need to go deeper and get last child as a text node
      if (elem.lastChild.children && elem.lastChild.children.length > 0) {
        return getLastChild(Array.prototype.slice.call(elem.children).pop());
      } else if (
        !elem.lastChild
        || !elem.lastChild.nodeValue
        || elem.lastChild.nodeValue == opt.truncationChar
        || elem.lastChild.nodeType === Node.COMMENT_NODE
      ) {
        // Handle scenario where the last child is white-space node
        var sibling = elem.lastChild;
        do {
          if (!sibling) {
            return;
          }
          // TEXT_NODE
          if (
            sibling.nodeType === 3
            && ['', opt.truncationChar].indexOf(sibling.nodeValue) === -1
            && elem.lastChild.nodeType !== Node.COMMENT_NODE
          ) {
            return sibling;
          }
          if (sibling.lastChild) {
            var lastChild = getLastChild(sibling);
            if (lastChild) {
              return lastChild;
            }
          }
          //Current sibling is pretty useless
          sibling.parentNode.removeChild(sibling);
        } while (sibling = sibling.previousSibling);
      }
      //This is the last child we want, return it
      else {
        return elem.lastChild;
      }
    }

    /**
     * Removes one character at a time from the text until its width or
     * height is beneath the passed-in max param.
     */
    function truncate(target, maxHeight) {
      if (!target || !maxHeight) {
        return;
      }

      /**
       * Resets global variables.
       */
      function reset() {
        splitOnChars = opt.splitOnChars.slice(0);
        splitChar = splitOnChars[0];
        chunks = null;
        lastChunk = null;
      }

      var nodeValue = target.nodeValue.replace(opt.truncationChar, '');

      //Grab the next chunks
      if (!chunks) {
        //If there are more characters to try, grab the next one
        if (splitOnChars.length > 0) {
          splitChar = splitOnChars.shift();
        }
        //No characters to chunk by. Go character-by-character
        else {
          splitChar = '';
        }

        chunks = nodeValue.split(splitChar);
      }

      //If there are chunks left to remove, remove the last one and see if
      // the nodeValue fits.
      if (chunks.length > 1) {
        // console.log('chunks', chunks);
        lastChunk = chunks.pop();
        // console.log('lastChunk', lastChunk);
        applyEllipsis(target, chunks.join(splitChar));
      }
      //No more chunks can be removed using this character
      else {
        chunks = null;
      }

      //Insert the custom HTML before the truncation character
      if (truncationHTMLContainer) {
        target.nodeValue = target.nodeValue.replace(opt.truncationChar, '');
        element.innerHTML = target.nodeValue + ' ' + truncationHTMLContainer.innerHTML + opt.truncationChar;
      }

      //Search produced valid chunks
      if (chunks) {
        //It fits
        if (element.clientHeight <= maxHeight) {
          //There's still more characters to try splitting on, not quite done yet
          if (splitOnChars.length >= 0 && splitChar !== '') {
            applyEllipsis(target, chunks.join(splitChar) + splitChar + lastChunk);
            chunks = null;
          }
          //Finished!
          else {
            return element.innerHTML;
          }
        }
      }
      //No valid chunks produced
      else {
        //No valid chunks even when splitting by letter, time to move
        //on to the next node
        if (splitChar === '') {
          applyEllipsis(target, '');
          target = getLastChild(element);

          reset();
        }
      }

      //If you get here it means still too big, let's keep truncating
      if (opt.animate) {
        setTimeout(function() {
          truncate(target, maxHeight);
        }, opt.animate === true ? 10 : opt.animate);
      } else {
        return truncate(target, maxHeight);
      }
    }

    function applyEllipsis(elem, str) {
      elem.nodeValue = str + opt.truncationChar;
    }

    // CONSTRUCTOR ________________________________________________________________

    if (clampValue == 'auto') {
      clampValue = getMaxLines();
    } else if (isCSSValue) {
      clampValue = getMaxLines(parseInt(clampValue, 10));
    }

    var clampedText;
    if (supportsNativeClamp && opt.useNativeClamp) {
      sty.overflow = 'hidden';
      sty.textOverflow = 'ellipsis';
      sty.webkitBoxOrient = 'vertical';
      sty.display = '-webkit-box';
      sty.webkitLineClamp = clampValue;

      if (isCSSValue) {
        sty.height = opt.clamp + 'px';
      }
    } else {
      var height = getMaxHeight(clampValue);
      if (height < element.clientHeight) {
        clampedText = truncate(getLastChild(element), height);
      }
    }

    return {
      'original': originalText,
      'clamped': clampedText
    };
  }

  return clamp;
}));
<|endoftext|>


<commit_before>module.exports = require("./");
<commit_msg>modify index file.<commit_after>'use strict';

exports.Derivate = require("./derivate");
exports.Integrals = require("./integrals");
<|endoftext|>


<commit_before>/*!
 * Clamp.js 0.7.0
 * Based on: https://github.com/xavi160/Clamp.js/commit/e313818da231b8dd8fd603dd9c9a61a9d725c22f
 * Mixins:
 * - https://github.com/josephschmitt/Clamp.js/pull/50
 * - https://github.com/josephschmitt/Clamp.js/pull/49
 *
 * Copyright 2011-2013, Joseph Schmitt http://joe.sh
 * Released under the WTFPL license
 * http://sam.zoy.org/wtfpl/
 */

(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD
    define([], factory);
  } else if (typeof exports === 'object') {
    // Node, CommonJS-like
    module.exports = factory();
  } else {
    // Browser globals
    root.$clamp = factory();
  }
}(this, function() {
  /**
   * Clamps a text node.
   * @param {HTMLElement} element. Element containing the text node to clamp.
   * @param {Object} options. Options to pass to the clamper.
   */
  function clamp(element, options) {
    options = options || {};

    var self = this,
      win = window,
      opt = {
        clamp: options.clamp || 2,
        useNativeClamp: typeof(options.useNativeClamp) != 'undefined' ? options.useNativeClamp : true,
        splitOnChars: options.splitOnChars || ['.', '-', '–', '—', ' '], //Split on sentences (periods), hypens, en-dashes, em-dashes, and words (spaces).
        animate: options.animate || false,
        truncationChar: options.truncationChar || '…',
        truncationHTML: options.truncationHTML
      },

      sty = element.style,
      originalText = element.innerHTML,

      supportsNativeClamp = typeof(element.style.webkitLineClamp) != 'undefined',
      clampValue = opt.clamp,
      isCSSValue = clampValue.indexOf && (clampValue.indexOf('px') > -1 || clampValue.indexOf('em') > -1),
      truncationHTMLContainer;

    if (opt.truncationHTML) {
      truncationHTMLContainer = document.createElement('span');
      truncationHTMLContainer.innerHTML = opt.truncationHTML;
    }

    // UTILITY FUNCTIONS __________________________________________________________

    /**
     * Return the current style for an element.
     * @param {HTMLElement} elem The element to compute.
     * @param {string} prop The style property.
     * @returns {number}
     */
    function computeStyle(elem, prop) {
      if (!win.getComputedStyle) {
        win.getComputedStyle = function(el, pseudo) {
          this.el = el;
          this.getPropertyValue = function(prop) {
            var re = /(\-([a-z]){1})/g;
            if (prop == 'float') prop = 'styleFloat';
            if (re.test(prop)) {
              prop = prop.replace(re, function() {
                return arguments[2].toUpperCase();
              });
            }
            return el.currentStyle && el.currentStyle[prop] ? el.currentStyle[prop] : null;
          };
          return this;
        };
      }

      return win.getComputedStyle(elem, null).getPropertyValue(prop);
    }

    /**
     * Returns the maximum number of lines of text that should be rendered based
     * on the current height of the element and the line-height of the text.
     */
    function getMaxLines(height) {
      var availHeight = height || element.clientHeight,
        lineHeight = getLineHeight(element);

      return Math.max(Math.floor(availHeight / lineHeight), 0);
    }

    /**
     * Returns the maximum height a given element should have based on the line-
     * height of the text and the given clamp value.
     */
    function getMaxHeight(clmp) {
      var lineHeight = getLineHeight(element);
      return lineHeight * clmp;
    }

    /**
     * Returns the line-height of an element as an integer.
     */
    function getLineHeight(elem) {
      var lh = computeStyle(elem, 'line-height');
      if (lh == 'normal') {
        // Normal line heights vary from browser to browser. The spec recommends
        // a value between 1.0 and 1.2 of the font size. Using 1.1 to split the diff.
        lh = parseInt(computeStyle(elem, 'font-size')) * 1.2;
      }
      return parseInt(lh);
    }

    // MEAT AND POTATOES (MMMM, POTATOES...) ______________________________________
    var splitOnChars = opt.splitOnChars.slice(0),
      splitChar = splitOnChars[0],
      chunks,
      lastChunk;

    /**
     * Gets an element's last child. That may be another node or a node's contents.
     */
    function getLastChild(elem) {
      if (!elem.lastChild) {
        return;
      }
      //Current element has children, need to go deeper and get last child as a text node
      if (elem.lastChild.children && elem.lastChild.children.length > 0) {
        return getLastChild(Array.prototype.slice.call(elem.children).pop());
      }
      //This is the absolute last child, a text node, but something's wrong with it. Nest into it and keep trying
      else if (!elem.lastChild || !elem.lastChild.nodeValue || elem.lastChild.nodeValue === '' || elem.lastChild.nodeValue == opt.truncationChar) {
        return getLastChild(element.lastChild);
      }
      //This is the last child we want, return it
      else {
        return elem.lastChild;
      }
    }

    /**
     * Removes one character at a time from the text until its width or
     * height is beneath the passed-in max param.
     */
    function truncate(target, maxHeight) {
      if (!target || !maxHeight) {
        return;
      }

      /**
       * Resets global variables.
       */
      function reset() {
        splitOnChars = opt.splitOnChars.slice(0);
        splitChar = splitOnChars[0];
        chunks = null;
        lastChunk = null;
      }

      var nodeValue = target.nodeValue.replace(opt.truncationChar, '');

      //Grab the next chunks
      if (!chunks) {
        //If there are more characters to try, grab the next one
        if (splitOnChars.length > 0) {
          splitChar = splitOnChars.shift();
        }
        //No characters to chunk by. Go character-by-character
        else {
          splitChar = '';
        }

        chunks = nodeValue.split(splitChar);
      }

      //If there are chunks left to remove, remove the last one and see if
      // the nodeValue fits.
      if (chunks.length > 1) {
        // console.log('chunks', chunks);
        lastChunk = chunks.pop();
        // console.log('lastChunk', lastChunk);
        applyEllipsis(target, chunks.join(splitChar));
      }
      //No more chunks can be removed using this character
      else {
        chunks = null;
      }

      //Insert the custom HTML before the truncation character
      if (truncationHTMLContainer) {
        target.nodeValue = target.nodeValue.replace(opt.truncationChar, '');
        element.innerHTML = target.nodeValue + ' ' + truncationHTMLContainer.innerHTML + opt.truncationChar;
      }

      //Search produced valid chunks
      if (chunks) {
        //It fits
        if (element.clientHeight <= maxHeight) {
          //There's still more characters to try splitting on, not quite done yet
          if (splitOnChars.length >= 0 && splitChar !== '') {
            applyEllipsis(target, chunks.join(splitChar) + splitChar + lastChunk);
            chunks = null;
          }
          //Finished!
          else {
            return element.innerHTML;
          }
        }
      }
      //No valid chunks produced
      else {
        //No valid chunks even when splitting by letter, time to move
        //on to the next node
        if (splitChar === '') {
          applyEllipsis(target, '');
          target = getLastChild(element);

          reset();
        }
      }

      //If you get here it means still too big, let's keep truncating
      if (opt.animate) {
        setTimeout(function() {
          truncate(target, maxHeight);
        }, opt.animate === true ? 10 : opt.animate);
      } else {
        return truncate(target, maxHeight);
      }
    }

    function applyEllipsis(elem, str) {
      elem.nodeValue = str + opt.truncationChar;
    }

    // CONSTRUCTOR ________________________________________________________________

    if (clampValue == 'auto') {
      clampValue = getMaxLines();
    } else if (isCSSValue) {
      clampValue = getMaxLines(parseInt(clampValue));
    }

    var clampedText;
    if (supportsNativeClamp && opt.useNativeClamp) {
      sty.overflow = 'hidden';
      sty.textOverflow = 'ellipsis';
      sty.webkitBoxOrient = 'vertical';
      sty.display = '-webkit-box';
      sty.webkitLineClamp = clampValue;

      if (isCSSValue) {
        sty.height = opt.clamp + 'px';
      }
    } else {
      var height = getMaxHeight(clampValue);
      if (height < element.clientHeight) {
        clampedText = truncate(getLastChild(element), height);
      }
    }

    return {
      'original': originalText,
      'clamped': clampedText
    };
  }

  return clamp;
}));
<commit_msg>Nested white space text nodes trimming fix<commit_after>/*!
 * Clamp.js 0.7.0
 * Based on: https://github.com/xavi160/Clamp.js/commit/e313818da231b8dd8fd603dd9c9a61a9d725c22f
 * Mixins:
 * - https://github.com/josephschmitt/Clamp.js/pull/50
 * - https://github.com/josephschmitt/Clamp.js/pull/49
 *
 * Copyright 2011-2013, Joseph Schmitt http://joe.sh
 * Released under the WTFPL license
 * http://sam.zoy.org/wtfpl/
 */

(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD
    define([], factory);
  } else if (typeof exports === 'object') {
    // Node, CommonJS-like
    module.exports = factory();
  } else {
    // Browser globals
    root.$clamp = factory();
  }
}(this, function() {
  /**
   * Clamps a text node.
   * @param {HTMLElement} element. Element containing the text node to clamp.
   * @param {Object} options. Options to pass to the clamper.
   */
  function clamp(element, options) {
    options = options || {};

    var self = this,
      win = window,
      opt = {
        clamp: options.clamp || 2,
        useNativeClamp: typeof(options.useNativeClamp) != 'undefined' ? options.useNativeClamp : true,
        splitOnChars: options.splitOnChars || ['.', '-', '–', '—', ' '], //Split on sentences (periods), hypens, en-dashes, em-dashes, and words (spaces).
        animate: options.animate || false,
        truncationChar: options.truncationChar || '…',
        truncationHTML: options.truncationHTML
      },

      sty = element.style,
      originalText = element.innerHTML,

      supportsNativeClamp = typeof(element.style.webkitLineClamp) != 'undefined',
      clampValue = opt.clamp,
      isCSSValue = clampValue.indexOf && (clampValue.indexOf('px') > -1 || clampValue.indexOf('em') > -1),
      truncationHTMLContainer;

    if (opt.truncationHTML) {
      truncationHTMLContainer = document.createElement('span');
      truncationHTMLContainer.innerHTML = opt.truncationHTML;
    }

    // UTILITY FUNCTIONS __________________________________________________________

    /**
     * Return the current style for an element.
     * @param {HTMLElement} elem The element to compute.
     * @param {string} prop The style property.
     * @returns {number}
     */
    function computeStyle(elem, prop) {
      if (!win.getComputedStyle) {
        win.getComputedStyle = function(el, pseudo) {
          this.el = el;
          this.getPropertyValue = function(prop) {
            var re = /(\-([a-z]){1})/g;
            if (prop == 'float') prop = 'styleFloat';
            if (re.test(prop)) {
              prop = prop.replace(re, function() {
                return arguments[2].toUpperCase();
              });
            }
            return el.currentStyle && el.currentStyle[prop] ? el.currentStyle[prop] : null;
          };
          return this;
        };
      }

      return win.getComputedStyle(elem, null).getPropertyValue(prop);
    }

    /**
     * Returns the maximum number of lines of text that should be rendered based
     * on the current height of the element and the line-height of the text.
     */
    function getMaxLines(height) {
      var availHeight = height || element.clientHeight,
        lineHeight = getLineHeight(element);

      return Math.max(Math.floor(availHeight / lineHeight), 0);
    }

    /**
     * Returns the maximum height a given element should have based on the line-
     * height of the text and the given clamp value.
     */
    function getMaxHeight(clmp) {
      var lineHeight = getLineHeight(element);
      return lineHeight * clmp;
    }

    /**
     * Returns the line-height of an element as an integer.
     */
    function getLineHeight(elem) {
      var lh = computeStyle(elem, 'line-height');
      if (lh == 'normal') {
        // Normal line heights vary from browser to browser. The spec recommends
        // a value between 1.0 and 1.2 of the font size. Using 1.1 to split the diff.
        lh = parseInt(computeStyle(elem, 'font-size')) * 1.2;
      }
      return parseInt(lh);
    }

    // MEAT AND POTATOES (MMMM, POTATOES...) ______________________________________
    var splitOnChars = opt.splitOnChars.slice(0),
      splitChar = splitOnChars[0],
      chunks,
      lastChunk;

    /**
     * Gets an element's last child. That may be another node or a node's contents.
     */
    function getLastChild(elem) {
      if (!elem.lastChild) {
        return;
      }
      //Current element has children, need to go deeper and get last child as a text node
      if (elem.lastChild.children && elem.lastChild.children.length > 0) {
        return getLastChild(Array.prototype.slice.call(elem.children).pop());
      }
      //Handle scenario where the last child is white-space node
      else if (!elem.lastChild || !elem.lastChild.nodeValue || elem.lastChild.nodeValue === '' || elem.lastChild.nodeValue == opt.truncationChar) {
        var sibling = elem.lastChild;
        do {
          if (!sibling) {
            return;
          }
          //TEXT_NODE
          if (sibling.nodeType === 3 && ['', opt.truncationChar].indexOf(sibling.nodeValue) === -1) {
            return sibling;
          }
          if (sibling.lastChild) {
            var lastChild = getLastChild(sibling);
            if (lastChild) {
              return lastChild;
            }
          }
          //Current sibling is pretty useless
          sibling.parentNode.removeChild(sibling);
        } while (sibling = sibling.previousSibling);
      }
      //This is the last child we want, return it
      else {
        return elem.lastChild;
      }
    }

    /**
     * Removes one character at a time from the text until its width or
     * height is beneath the passed-in max param.
     */
    function truncate(target, maxHeight) {
      if (!target || !maxHeight) {
        return;
      }

      /**
       * Resets global variables.
       */
      function reset() {
        splitOnChars = opt.splitOnChars.slice(0);
        splitChar = splitOnChars[0];
        chunks = null;
        lastChunk = null;
      }

      var nodeValue = target.nodeValue.replace(opt.truncationChar, '');

      //Grab the next chunks
      if (!chunks) {
        //If there are more characters to try, grab the next one
        if (splitOnChars.length > 0) {
          splitChar = splitOnChars.shift();
        }
        //No characters to chunk by. Go character-by-character
        else {
          splitChar = '';
        }

        chunks = nodeValue.split(splitChar);
      }

      //If there are chunks left to remove, remove the last one and see if
      // the nodeValue fits.
      if (chunks.length > 1) {
        // console.log('chunks', chunks);
        lastChunk = chunks.pop();
        // console.log('lastChunk', lastChunk);
        applyEllipsis(target, chunks.join(splitChar));
      }
      //No more chunks can be removed using this character
      else {
        chunks = null;
      }

      //Insert the custom HTML before the truncation character
      if (truncationHTMLContainer) {
        target.nodeValue = target.nodeValue.replace(opt.truncationChar, '');
        element.innerHTML = target.nodeValue + ' ' + truncationHTMLContainer.innerHTML + opt.truncationChar;
      }

      //Search produced valid chunks
      if (chunks) {
        //It fits
        if (element.clientHeight <= maxHeight) {
          //There's still more characters to try splitting on, not quite done yet
          if (splitOnChars.length >= 0 && splitChar !== '') {
            applyEllipsis(target, chunks.join(splitChar) + splitChar + lastChunk);
            chunks = null;
          }
          //Finished!
          else {
            return element.innerHTML;
          }
        }
      }
      //No valid chunks produced
      else {
        //No valid chunks even when splitting by letter, time to move
        //on to the next node
        if (splitChar === '') {
          applyEllipsis(target, '');
          target = getLastChild(element);

          reset();
        }
      }

      //If you get here it means still too big, let's keep truncating
      if (opt.animate) {
        setTimeout(function() {
          truncate(target, maxHeight);
        }, opt.animate === true ? 10 : opt.animate);
      } else {
        return truncate(target, maxHeight);
      }
    }

    function applyEllipsis(elem, str) {
      elem.nodeValue = str + opt.truncationChar;
    }

    // CONSTRUCTOR ________________________________________________________________

    if (clampValue == 'auto') {
      clampValue = getMaxLines();
    } else if (isCSSValue) {
      clampValue = getMaxLines(parseInt(clampValue));
    }

    var clampedText;
    if (supportsNativeClamp && opt.useNativeClamp) {
      sty.overflow = 'hidden';
      sty.textOverflow = 'ellipsis';
      sty.webkitBoxOrient = 'vertical';
      sty.display = '-webkit-box';
      sty.webkitLineClamp = clampValue;

      if (isCSSValue) {
        sty.height = opt.clamp + 'px';
      }
    } else {
      var height = getMaxHeight(clampValue);
      if (height < element.clientHeight) {
        clampedText = truncate(getLastChild(element), height);
      }
    }

    return {
      'original': originalText,
      'clamped': clampedText
    };
  }

  return clamp;
}));
<|endoftext|>


<commit_before>"use strict";

/**
 * Exports the InstantLink class
 * @module instant-link
 */

const Cache = require('./cache');

const init = require('./init');
const handler = require('./handler');
const fetchPage = require('./fetch-page');
const replacePage = require('./replace-page');

class InstantLink{
    /**
     * Creates a new InstantLink instance
     * @param {object} options
     * @param {boolean} [options.cache=true] - Enable/disable caching
     * @param {boolean} [options.compress=false] - Enable/disable compression
     * @param {string}  [options.event=onmouseover] - Event handler for triggering preload
     * @param {boolean} [options.comment=true] - If enabled, script tags with 'no-instant' data attribute will be replaced by comment
     */
    constructor(options){
        this.options = {
            cache: true,
            compress: false,
            event: 'mouseover',
            comment: true
        }
        this.options = Object.assign(this.options, options);
        if(this.options.cache) this.cache = new Cache(this.options.compress);
        this.init();
    }
}

InstantLink.prototype.init = init;
InstantLink.prototype.handler = handler;
InstantLink.prototype.fetchPage = fetchPage;
InstantLink.prototype.replacePage = replacePage;

if(typeof window === 'undefined'){
    throw new ReferenceError('window is undefined, InstantLink must be run in a browser');
}

window.InstantLink = InstantLink;

module.exports = InstantLink;<commit_msg>Added support for the new fullCompress option<commit_after>"use strict";

/**
 * Exports the InstantLink class
 * @module instant-link
 */

const Cache = require('./cache');

const init = require('./init');
const handler = require('./handler');
const fetchPage = require('./fetch-page');
const replacePage = require('./replace-page');

class InstantLink{
    /**
     * Creates a new InstantLink instance
     * @param {object} options
     * @param {boolean} [options.cache=true] - Enable/disable caching
     * @param {boolean} [options.compress=false] - Enable/disable compression
     * @param {string}  [options.event=onmouseover] - Event handler for triggering preload
     * @param {boolean} [options.comment=true] - If enabled, script tags with 'no-instant' data attribute will be replaced by comment
     */
    constructor(options){
        this.options = {
            cache: true,
            compress: false,
            fullCompress: false,
            event: 'mouseover',
            comment: true
        }
        this.options = Object.assign(this.options, options);
        if(this.options.cache) this.cache = new Cache(this.options);
        this.init();
    }
}

InstantLink.prototype.init = init;
InstantLink.prototype.handler = handler;
InstantLink.prototype.fetchPage = fetchPage;
InstantLink.prototype.replacePage = replacePage;

if(typeof window === 'undefined'){
    throw new ReferenceError('window is undefined, InstantLink must be run in a browser');
}

window.InstantLink = InstantLink;

module.exports = InstantLink;<|endoftext|>