<commit_before>/* istanbul ignore if */
if (typeof define !== 'function') { var define = require('amdefine')(module); }
define(function() {
  "use strict";

  // The base Class implementation (does nothing)
  var Klass = function() {},
  extend, mixin, inherits,
  fnTest = /xyz/.test(function() {/*global xyz*/ return xyz; }) ?
    /\b_super\b/ :
    /.*/;

  // allows adding any object's properties into the class
  mixin = function(abstract) {
    var descriptor = {};
    Object.keys(abstract).forEach(function(prop) {
      descriptor[prop] = Object.getOwnPropertyDescriptor(abstract, prop);
    });
    Object.defineProperties(this.prototype, descriptor);
    return this;
  };

  // determines if current class inherits from superclass
  inherits = function(superclass) {
    var prop, result = false;
    if (typeof superclass === 'function') {
      // Testing linear inheritance
      return superclass.prototype.isPrototypeOf(this.prototype);
    }
    if (typeof superclass === 'object') {
      // Testing horizontal inheritance
      for (prop in superclass) {
        if (superclass.hasOwnProperty(prop) &&
            superclass[prop] !== this.prototype[prop]) {
          return false;
        }
        result = true;
      }
    }
    return result;
  };

  // Create a new Class that inherits from this class
  extend = function(prop, stat) {
    var _super = this.prototype,
    copy = function(name) { Class[name] = this[name]; },

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    prototype = Object.create(_super);
    prop = prop || {};
    stat = stat || {};

    function protochain(name, fn) {
      var applySuper = function() {
        return _super[name].apply(this, arguments);
      };
      return function() {
        var hadSuper = this.hasOwnProperty('_super'), tmp = this._super;

        // Add a new ._super() method that is the same method
        // but on the super-class
        this._super = applySuper;

        // The method only need to be bound temporarily, so we
        // remove it when we're done executing
        try {
          return fn.apply(this, arguments);
        }
        catch(e) {
          // Rethrow catch for IE 8
          throw e;
        }
        finally {
          if (hadSuper) {
            this._super = tmp;
          }
          else {
            delete this._super;
          }
        }
      };
    }

    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if (typeof this.init === "function") {
        this.init.apply(this, arguments);
      }
    }

    // Copy the properties over onto the new prototype
    Object.keys(prop).forEach(function(name) {
      var p = prop[name];
      // Check if we're overwriting an existing function
      prototype[name] =
        typeof p === "function" &&
        typeof _super[name] === "function" &&
        fnTest.test(p) ?
        protochain(name, p) :
        p;
    });

    // Copy the superclass's static properties
    Object.keys(this).forEach(copy, this);

    // Override the provided static properties
    Object.keys(stat).forEach(copy, stat);

    // Populate our constructed prototype object
    Class.prototype = prototype;

    // Enforce the constructor to be what we expect
    Object.defineProperty(Class.prototype, "constructor", { value: Class });

    // Class guaranteed methods
    Object.defineProperties(Class, {
      extend: { value: extend, enumerable: false },
      mixin: { value: mixin },
      inherits: { value: inherits }
    });

    return Class;
  };

  Klass.extend = extend;

  return Klass;
});
<commit_msg>Class: using single quotes<commit_after>/* istanbul ignore if */
if (typeof define !== 'function') { var define = require('amdefine')(module); }
define(function() {
  'use strict';

  // The base Class implementation (does nothing)
  var Klass = function() {},
  extend, mixin, inherits,
  fnTest = /xyz/.test(function() {/*global xyz*/ return xyz; }) ?
    /\b_super\b/ :
    /.*/;

  // allows adding any object's properties into the class
  mixin = function(abstract) {
    var descriptor = {};
    Object.keys(abstract).forEach(function(prop) {
      descriptor[prop] = Object.getOwnPropertyDescriptor(abstract, prop);
    });
    Object.defineProperties(this.prototype, descriptor);
    return this;
  };

  // determines if current class inherits from superclass
  inherits = function(superclass) {
    var prop, result = false;
    if (typeof superclass === 'function') {
      // Testing linear inheritance
      return superclass.prototype.isPrototypeOf(this.prototype);
    }
    if (typeof superclass === 'object') {
      // Testing horizontal inheritance
      for (prop in superclass) {
        if (superclass.hasOwnProperty(prop) &&
            superclass[prop] !== this.prototype[prop]) {
          return false;
        }
        result = true;
      }
    }
    return result;
  };

  // Create a new Class that inherits from this class
  extend = function(prop, stat) {
    var _super = this.prototype,
    copy = function(name) { Class[name] = this[name]; },

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    prototype = Object.create(_super);
    prop = prop || {};
    stat = stat || {};

    function protochain(name, fn) {
      var applySuper = function() {
        return _super[name].apply(this, arguments);
      };
      return function() {
        var hadSuper = this.hasOwnProperty('_super'), tmp = this._super;

        // Add a new ._super() method that is the same method
        // but on the super-class
        this._super = applySuper;

        // The method only need to be bound temporarily, so we
        // remove it when we're done executing
        try {
          return fn.apply(this, arguments);
        }
        catch(e) {
          // Rethrow catch for IE 8
          throw e;
        }
        finally {
          if (hadSuper) {
            this._super = tmp;
          }
          else {
            delete this._super;
          }
        }
      };
    }

    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if (typeof this.init === 'function') {
        this.init.apply(this, arguments);
      }
    }

    // Copy the properties over onto the new prototype
    Object.keys(prop).forEach(function(name) {
      var p = prop[name];
      // Check if we're overwriting an existing function
      prototype[name] =
        typeof p === 'function' &&
        typeof _super[name] === 'function' &&
        fnTest.test(p) ?
        protochain(name, p) :
        p;
    });

    // Copy the superclass's static properties
    Object.keys(this).forEach(copy, this);

    // Override the provided static properties
    Object.keys(stat).forEach(copy, stat);

    // Populate our constructed prototype object
    Class.prototype = prototype;

    // Enforce the constructor to be what we expect
    Object.defineProperty(Class.prototype, 'constructor', { value: Class });

    // Class guaranteed methods
    Object.defineProperties(Class, {
      extend: { value: extend, enumerable: false },
      mixin: { value: mixin },
      inherits: { value: inherits }
    });

    return Class;
  };

  Klass.extend = extend;

  return Klass;
});
<|endoftext|>


<commit_before>import _ from 'lodash'
import chalk from 'chalk'
import { FSWatcher } from 'chokidar'
import _debug from 'debug'
import Builder from './builder'
import { Utils } from 'common'

const debug = _debug('api:build')
debug.color = 2 // Green

const shift = Object.keys(Builder.Status).length

export default class Watcher extends Builder {
  constructor (dynapi) {
    super(dynapi)

    // Chokidar instance
    this.watcher = new FSWatcher({ ignoreInitial: true })

    // Dependents from transformed files
    this.dependents = {}

    // Extra files to watch from imports
    this.extraWatches = {}

    // TODO Check is it needs to be bind
    this.dynapi.plugin('close', this.close.bind(this))
  }

  static get Status () {
    return {
      INITIAL: Builder.Status.INITIAL,
      WATCHING: 1 << shift
    }
  }

  /* Override */
  fetch (filename) {
    if (!filename.startsWith(this.options.routesDir)) {
      this.add(filename)
    }
    return super.fetch(filename)
  }

  purge (filename) {
    const dependents = this.dependents[filename]
    if (dependents !== undefined) {
      // Recursive purge dependents
      dependents.forEach(dependent => this.purge(dependent))
      // Empty the requester array
      delete this.dependents[filename]
    }

    const buildFilename = this.dynapi.redirectTo('build', filename)
    delete this.handlers[buildFilename]

    if (filename.startsWith(this.options.routesDir)) {
      super.fetch(filename)
    } else {
      this.unwatch(filename)
    }
  }

  refresh (filename) {
    this.purge(filename)
    return super.fetch(filename)
  }

  /* Override */
  transform (filename) {
    const transformed = super.transform(filename)

    // Save dependents to refresh caches on file changed
    const imports = transformed.source.metadata.modules.imports
    imports.forEach(({ source }) => {
      if (source[0] === '~' || source[0] === '.') {
        const key = this.dynapi.resolve(source, filename)
        this.dependents[key] = this.dependents[key] || []
        this.dependents[key].push(filename)
      }
    })

    return transformed
  }

  watch () {
    /* istanbul ignore if */
    if (this._status & Watcher.Status.WATCHING) {
      return this.build()
    }

    this._status |= Watcher.Status.WATCHING

    const regenerateRenderer = _.debounce(() => {
      // TODO Improve performance
      this.dynapi.renderer.createRenderer(this.handlers)
    }, 200)

    const listeners = [{
      event: 'add',
      verb: 'created',
      callbacks: [this.fetch, regenerateRenderer]
    }, {
      event: 'unlink',
      verb: 'remove',
      callbacks: [this.purge, regenerateRenderer]
    }, {
      event: 'change',
      verb: 'modified',
      callbacks: [this.refresh]
    }]

    listeners.forEach(({ event, verb, callbacks }) => {
      this.watcher.on(event, filename => {
        debug(chalk`{magenta ${this.dynapi.relativeFrom('src', filename)}} has been {red ${verb}}.`)

        try {
          callbacks.forEach(cb => cb.call(this, filename))
        } catch (err) {
          Utils.printError(err, filename)
        }
      })
    })

    const patterns = [ this.options.routesDir ]
    this.watcher.add(patterns)

    debug('Start watching %O', patterns.map(p => this.dynapi.relativeFrom('src', p)))

    return this.build()
  }

  add (filename) {
    const exists = this.extraWatches[filename]

    if (!exists) {
      this.watcher.add(filename)
      this.extraWatches[filename] = true
    }

    return this
  }

  unwatch (filename) {
    const exists = this.extraWatches[filename]

    if (exists) {
      this.watcher.unwatch(filename)
      delete this.extraWatches[filename]
    }

    return this
  }

  close () {
    this._status &= ~Watcher.Status.WATCHING
    this.watcher.close()
  }
}
<commit_msg>[Builder] Reorder methods in Watcher<commit_after>import _ from 'lodash'
import chalk from 'chalk'
import { FSWatcher } from 'chokidar'
import _debug from 'debug'
import Builder from './builder'
import { Utils } from 'common'

const debug = _debug('api:build')
debug.color = 2 // Green

const shift = Object.keys(Builder.Status).length

export default class Watcher extends Builder {
  constructor (dynapi) {
    super(dynapi)

    // Chokidar instance
    this.watcher = new FSWatcher({ ignoreInitial: true })

    // Dependents from transformed files
    this.dependents = {}

    // Extra files to watch from imports
    this.extraWatches = {}

    // TODO Check is it needs to be bind
    this.dynapi.plugin('close', this.close.bind(this))
  }

  static get Status () {
    return {
      INITIAL: Builder.Status.INITIAL,
      WATCHING: 1 << shift
    }
  }

  watch () {
    /* istanbul ignore if */
    if (this._status & Watcher.Status.WATCHING) {
      return this.build()
    }

    this._status |= Watcher.Status.WATCHING

    const regenerateRenderer = _.debounce(() => {
      // TODO Improve performance
      this.dynapi.renderer.createRenderer(this.handlers)
    }, 200)

    const listeners = [{
      event: 'add',
      verb: 'created',
      callbacks: [this.fetch, regenerateRenderer]
    }, {
      event: 'unlink',
      verb: 'remove',
      callbacks: [this.purge, regenerateRenderer]
    }, {
      event: 'change',
      verb: 'modified',
      callbacks: [this.refresh]
    }]

    listeners.forEach(({ event, verb, callbacks }) => {
      this.watcher.on(event, filename => {
        debug(chalk`{magenta ${this.dynapi.relativeFrom('src', filename)}} has been {red ${verb}}.`)

        try {
          callbacks.forEach(cb => cb.call(this, filename))
        } catch (err) {
          Utils.printError(err, filename)
        }
      })
    })

    const patterns = [ this.options.routesDir ]
    this.watcher.add(patterns)

    debug('Start watching %O', patterns.map(p => this.dynapi.relativeFrom('src', p)))

    return this.build()
  }

  add (filename) {
    const exists = this.extraWatches[filename]

    if (!exists) {
      this.watcher.add(filename)
      this.extraWatches[filename] = true
    }

    return this
  }

  unwatch (filename) {
    const exists = this.extraWatches[filename]

    if (exists) {
      this.watcher.unwatch(filename)
      delete this.extraWatches[filename]
    }

    return this
  }

  close () {
    this._status &= ~Watcher.Status.WATCHING
    this.watcher.close()
  }

  /* Override */
  fetch (filename) {
    if (!filename.startsWith(this.options.routesDir)) {
      this.add(filename)
    }
    return super.fetch(filename)
  }

  purge (filename) {
    const dependents = this.dependents[filename]
    if (dependents !== undefined) {
      // Recursive purge dependents
      dependents.forEach(dependent => this.purge(dependent))
      // Empty the requester array
      delete this.dependents[filename]
    }

    const buildFilename = this.dynapi.redirectTo('build', filename)
    delete this.handlers[buildFilename]

    if (filename.startsWith(this.options.routesDir)) {
      super.fetch(filename)
    } else {
      this.unwatch(filename)
    }
  }

  refresh (filename) {
    this.purge(filename)
    return super.fetch(filename)
  }

  /* Override */
  transform (filename) {
    const transformed = super.transform(filename)

    // Save dependents to refresh caches on file changed
    const imports = transformed.source.metadata.modules.imports
    imports.forEach(({ source }) => {
      if (source[0] === '~' || source[0] === '.') {
        const key = this.dynapi.resolve(source, filename)
        this.dependents[key] = this.dependents[key] || []
        this.dependents[key].push(filename)
      }
    })

    return transformed
  }
}
<|endoftext|>


<commit_before>import assert from 'assert';

describe('generateRelationshipResolver', () => {

  describe('loading singular relationships', () => {
    it('loads correct results with a single query', () => {

    });
  });

  describe('loading plural relationships', () => {
    it('loads correct results', () => {

    });

    it('loads totalCount and pageInfo', () => {

    });
  });

});
<commit_msg>mark tests as pending<commit_after>import assert from 'assert';

describe('generateRelationshipResolver', () => {

  describe('loading singular relationships', () => {
    xit('loads correct results with a single query', () => {

    });
  });

  describe('loading plural relationships', () => {
    xit('loads correct results', () => {

    });

    xit('loads totalCount and pageInfo', () => {

    });
  });

});
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
//  Copyright (C) 2008-2012  The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// TextCell
//============================================================================

/**
    A module that allow to create different type of Text Cell
    @module IPython
    @namespace IPython
 */
var IPython = (function (IPython) {
    "use strict";

    // TextCell base class
    var key = IPython.utils.keycodes;

    /**
     * Construct a new TextCell, codemirror mode is by default 'htmlmixed', and cell type is 'text'
     * cell start as not redered.
     *
     * @class TextCell
     * @constructor TextCell
     * @extend IPython.Cell
     * @param {object|undefined} [options]
     *      @param [options.cm_config] {object} config to pass to CodeMirror, will extend/overwrite default config
     *      @param [options.placeholder] {string} default string to use when souce in empty for rendering (only use in some TextCell subclass)
     */
    var TextCell = function (options) {
        // in all TextCell/Cell subclasses
        // do not assign most of members here, just pass it down
        // in the options dict potentially overwriting what you wish.
        // they will be assigned in the base class.

        // we cannot put this as a class key as it has handle to "this".
        var cm_overwrite_options  = {
            onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
        };

        options = this.mergeopt(TextCell,options,{cm_config:cm_overwrite_options});

        IPython.Cell.apply(this, [options]);

        this.rendered = false;
        this.cell_type = this.cell_type || 'text';
    };

    TextCell.prototype = new IPython.Cell();

    TextCell.options_default = {
        cm_config : {
            extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess"},
            mode: 'htmlmixed',
            lineWrapping : true,
        }
    };

    /**
     * Create the DOM element of the TextCell
     * @method create_element
     * @private
     */
    TextCell.prototype.create_element = function () {
        IPython.Cell.prototype.create_element.apply(this, arguments);
        var cell = $("<div>").addClass('cell text_cell border-box-sizing');
        cell.attr('tabindex','2');

        this.celltoolbar = new IPython.CellToolbar(this);
        cell.append(this.celltoolbar.element);

        var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
        this.code_mirror = CodeMirror(input_area.get(0), this.cm_config);

        // The tabindex=-1 makes this div focusable.
        var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
            addClass('rendered_html').attr('tabindex','-1');
        cell.append(input_area).append(render_area);
        this.element = cell;
    };

    /**
     * Bind the DOM evet to cell actions
     * Need to be called after TextCell.create_element
     * @private
     * @method bind_event
     */
    TextCell.prototype.bind_events = function () {
        IPython.Cell.prototype.bind_events.apply(this);
        var that = this;
        this.element.keydown(function (event) {
            if (event.which === 13 && !event.shiftKey) {
                if (that.rendered) {
                    that.edit();
                    return false;
                };
            };
        });
        this.element.dblclick(function () {
            that.edit();
        });
    };

    /**
     * This method gets called in CodeMirror's onKeyDown/onKeyPress
     * handlers and is used to provide custom key handling.
     *
     * Subclass should override this method to have custom handeling
     *
     * @method handle_codemirror_keyevent
     * @param {CodeMirror} editor - The codemirror instance bound to the cell
     * @param {event} event -
     * @return {Boolean} `true` if CodeMirror should ignore the event, `false` Otherwise
     */
    TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {

        if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
            // Always ignore shift-enter in CodeMirror as we handle it.
            return true;
        }
        return false;
    };

    /**
     * Select the current cell and trigger 'focus'
     * @method select
     */
    TextCell.prototype.select = function () {
        IPython.Cell.prototype.select.apply(this);
        var output = this.element.find("div.text_cell_render");
        output.trigger('focus');
    };

    /**
     * unselect the current cell and `render` it
     * @method unselect
     */
    TextCell.prototype.unselect = function() {
        // render on selection of another cell
        this.render();
        IPython.Cell.prototype.unselect.apply(this);
    };

    /**
     *
     * put the current cell in edition mode
     * @method edit
     */
    TextCell.prototype.edit = function () {
        if ( this.read_only ) return;
        if (this.rendered === true) {
            var text_cell = this.element;
            var output = text_cell.find("div.text_cell_render");
            output.hide();
            text_cell.find('div.text_cell_input').show();
            this.code_mirror.refresh();
            this.code_mirror.focus();
            // We used to need an additional refresh() after the focus, but
            // it appears that this has been fixed in CM. This bug would show
            // up on FF when a newly loaded markdown cell was edited.
            this.rendered = false;
            if (this.get_text() === this.placeholder) {
                this.set_text('');
                this.refresh();
            }
        }
    };

    /**
     * Empty, Subclasses must define render.
     * @method render
     */
    TextCell.prototype.render = function () {};

    /**
     * setter: {{#crossLink "TextCell/set_text"}}{{/crossLink}}
     * @method get_text
     * @retrun {string} CodeMirror current text value
     */
    TextCell.prototype.get_text = function() {
        return this.code_mirror.getValue();
    };

    /**
     * @param {string} text - Codemiror text value
     * @see TextCell#get_text
     * @method set_text
     * */
    TextCell.prototype.set_text = function(text) {
        this.code_mirror.setValue(text);
        this.code_mirror.refresh();
    };

    /**
     * setter :{{#crossLink "TextCell/set_rendered"}}{{/crossLink}}
     * @method get_rendered
     * @return {html} html of rendered element
     * */
    TextCell.prototype.get_rendered = function() {
        return this.element.find('div.text_cell_render').html();
    };

    /**
     * @method set_rendered
     */
    TextCell.prototype.set_rendered = function(text) {
        this.element.find('div.text_cell_render').html(text);
    };

    /**
     * not deprecated, but implementation wrong
     * @method at_top
     * @deprecated
     * @return {Boolean} true is cell rendered, false otherwise
     * I doubt this is what it is supposed to do
     * this implementation is completly false
     */
    TextCell.prototype.at_top = function () {
        if (this.rendered) {
            return true;
        } else {
            return false;
        }
    };

    /**
     * not deprecated, but implementation wrong
     * @method at_bottom
     * @deprecated
     * @return {Boolean} true is cell rendered, false otherwise
     * I doubt this is what it is supposed to do
     * this implementation is completly false
     * */
    TextCell.prototype.at_bottom = function () {
        if (this.rendered) {
            return true;
        } else {
            return false;
        }
    };

    /**
     * Create Text cell from JSON
     * @param {json} data - JSON serialized text-cell
     * @method fromJSON
     */
    TextCell.prototype.fromJSON = function (data) {
        IPython.Cell.prototype.fromJSON.apply(this, arguments);
        if (data.cell_type === this.cell_type) {
            if (data.source !== undefined) {
                this.set_text(data.source);
                // make this value the starting point, so that we can only undo
                // to this state, instead of a blank cell
                this.code_mirror.clearHistory();
                this.set_rendered(data.rendered || '');
                this.rendered = false;
                this.render();
            }
        }
    };

    /** Generate JSON from cell
     * @return {object} cell data serialised to json
     */
    TextCell.prototype.toJSON = function () {
        var data = IPython.Cell.prototype.toJSON.apply(this);
        data.cell_type = this.cell_type;
        data.source = this.get_text();
        return data;
    };

    /**
     * @class MarkdownCell
     * @constructor MarkdownCell
     * @extends IPython.HTMLCell
     */
    var MarkdownCell = function (options) {
        var options = options || {};

        options = this.mergeopt(MarkdownCell,options);
        TextCell.apply(this, [options]);

        this.cell_type = 'markdown';
    };

    MarkdownCell.options_default = {
        cm_config: {
            mode: 'gfm'
        },
        placeholder: "Type *Markdown* and LaTeX: $\\alpha^2$"
    }

    MarkdownCell.prototype = new TextCell();

    /**
     * @method render
     */
    MarkdownCell.prototype.render = function () {
        if (this.rendered === false) {
            var text = this.get_text();
            if (text === "") { text = this.placeholder; }
            var text_math = IPython.mathjaxutils.remove_math(text);
            var text = text_math[0]
            var math = text_math[1]
            var html = marked.parser(marked.lexer(text));
            html = $(IPython.mathjaxutils.replace_math(html, math));
            // links in markdown cells should open in new tabs
            html.find("a[href]").attr("target", "_blank");
            try {
                this.set_rendered(html);
            } catch (e) {
                console.log("Error running Javascript in Markdown:");
                console.log(e);
                this.set_rendered($("<div/>").addClass("js-error").html(
                    "Error rendering Markdown!<br/>" + e.toString())
                );
            }
            this.element.find('div.text_cell_input').hide();
            this.element.find("div.text_cell_render").show();
            this.typeset()
            this.rendered = true;
        }
    };

    // RawCell

    /**
     * @class RawCell
     * @constructor RawCell
     * @extends IPython.TextCell
     */
    var RawCell = function (options) {

        options = this.mergeopt(RawCell,options)
        TextCell.apply(this, [options]);

        this.cell_type = 'raw';

        var that = this
        this.element.focusout(
                function() { that.auto_highlight(); }
            );
    };

    RawCell.options_default = {
        placeholder : "Type plain text and LaTeX: $\\alpha^2$"
    };

    RawCell.prototype = new TextCell();

    /**
     * Trigger autodetection of highlight scheme for current cell
     * @method auto_highlight
     */
    RawCell.prototype.auto_highlight = function () {
        this._auto_highlight(IPython.config.raw_cell_highlight);
    };

    /** @method render **/
    RawCell.prototype.render = function () {
        this.rendered = true;
        this.edit();
    };

    /** @method handle_codemirror_keyevent **/
    RawCell.prototype.handle_codemirror_keyevent = function (editor, event) {

        var that = this;
        if (event.which === key.UPARROW && event.type === 'keydown') {
            // If we are not at the top, let CM handle the up arrow and
            // prevent the global keydown handler from handling it.
            if (!that.at_top()) {
                event.stop();
                return false;
            } else {
                return true;
            };
        } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
            // If we are not at the bottom, let CM handle the down arrow and
            // prevent the global keydown handler from handling it.
            if (!that.at_bottom()) {
                event.stop();
                return false;
            } else {
                return true;
            };
        };
        return false;
    };

    /** @method select **/
    RawCell.prototype.select = function () {
        IPython.Cell.prototype.select.apply(this);
        this.code_mirror.refresh();
        this.code_mirror.focus();
    };

    /** @method at_top **/
    RawCell.prototype.at_top = function () {
        var cursor = this.code_mirror.getCursor();
        if (cursor.line === 0 && cursor.ch === 0) {
            return true;
        } else {
            return false;
        }
    };

    /** @method at_bottom **/
    RawCell.prototype.at_bottom = function () {
        var cursor = this.code_mirror.getCursor();
        if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
            return true;
        } else {
            return false;
        }
    };

    /**
     * @class HeadingCell
     * @extends IPython.TextCell
     */

    /**
     * @constructor HeadingCell
     * @extends IPython.TextCell
     */
    var HeadingCell = function (options) {

        options = this.mergeopt(HeadingCell,options)
        TextCell.apply(this, [options]);

        /**
         * heading level of the cell, use getter and setter to access
         * @property level
         */
        this.level = 1;
        this.cell_type = 'heading';
    };

    HeadingCell.options_default = {
        placeholder: "Type Heading Here"
    };

    HeadingCell.prototype = new TextCell();

    /** @method fromJSON */
    HeadingCell.prototype.fromJSON = function (data) {
        if (data.level != undefined){
            this.level = data.level;
        }
        TextCell.prototype.fromJSON.apply(this, arguments);
    };

    /** @method toJSON */
    HeadingCell.prototype.toJSON = function () {
        var data = TextCell.prototype.toJSON.apply(this);
        data.level = this.get_level();
        return data;
    };

    /**
     * Change heading level of cell, and re-render
     * @method set_level
     */
    HeadingCell.prototype.set_level = function (level) {
        this.level = level;
        if (this.rendered) {
            this.rendered = false;
            this.render();
        };
    };

    /** The depth of header cell, based on html (h1 to h6)
     * @method get_level
     * @return {integer} level - for 1 to 6
     */
    HeadingCell.prototype.get_level = function () {
        return this.level;
    };

    HeadingCell.prototype.set_rendered = function (html) {
        this.element.find("div.text_cell_render").html(html);
    };

    HeadingCell.prototype.get_rendered = function () {
        var r = this.element.find("div.text_cell_render");
        return r.children().first().html();
    };

    HeadingCell.prototype.render = function () {
        if (this.rendered === false) {
            var text = this.get_text();
            // Markdown headings must be a single line
            text = text.replace(/\n/g, ' ');
            if (text === "") { text = this.placeholder; }
            text = Array(this.level + 1).join("#") + " " + text;
            var text_and_math = IPython.mathjaxutils.remove_math(text);
            var text = text_and_math[0];
            var math = text_and_math[1];
            var html = marked.parser(marked.lexer(text));
            var h = $(IPython.mathjaxutils.replace_math(html, math));
            // add id and linkback anchor
            var hash = h.text().replace(/ /g, '-');
            h.attr('id', hash);
            h.append(
                $('<a/>')
                    .addClass('anchor-link')
                    .attr('href', '#' + hash)
                    .text('¶')
            );

            this.set_rendered(h);
            this.typeset();
            this.element.find('div.text_cell_input').hide();
            this.element.find("div.text_cell_render").show();
            this.rendered = true;
        };
    };

    IPython.TextCell = TextCell;
    IPython.MarkdownCell = MarkdownCell;
    IPython.RawCell = RawCell;
    IPython.HeadingCell = HeadingCell;

    return IPython;

}(IPython));

<commit_msg>add mising semicolon<commit_after>//----------------------------------------------------------------------------
//  Copyright (C) 2008-2012  The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// TextCell
//============================================================================

/**
    A module that allow to create different type of Text Cell
    @module IPython
    @namespace IPython
 */
var IPython = (function (IPython) {
    "use strict";

    // TextCell base class
    var key = IPython.utils.keycodes;

    /**
     * Construct a new TextCell, codemirror mode is by default 'htmlmixed', and cell type is 'text'
     * cell start as not redered.
     *
     * @class TextCell
     * @constructor TextCell
     * @extend IPython.Cell
     * @param {object|undefined} [options]
     *      @param [options.cm_config] {object} config to pass to CodeMirror, will extend/overwrite default config
     *      @param [options.placeholder] {string} default string to use when souce in empty for rendering (only use in some TextCell subclass)
     */
    var TextCell = function (options) {
        // in all TextCell/Cell subclasses
        // do not assign most of members here, just pass it down
        // in the options dict potentially overwriting what you wish.
        // they will be assigned in the base class.

        // we cannot put this as a class key as it has handle to "this".
        var cm_overwrite_options  = {
            onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
        };

        options = this.mergeopt(TextCell,options,{cm_config:cm_overwrite_options});

        IPython.Cell.apply(this, [options]);

        this.rendered = false;
        this.cell_type = this.cell_type || 'text';
    };

    TextCell.prototype = new IPython.Cell();

    TextCell.options_default = {
        cm_config : {
            extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess"},
            mode: 'htmlmixed',
            lineWrapping : true,
        }
    };

    /**
     * Create the DOM element of the TextCell
     * @method create_element
     * @private
     */
    TextCell.prototype.create_element = function () {
        IPython.Cell.prototype.create_element.apply(this, arguments);
        var cell = $("<div>").addClass('cell text_cell border-box-sizing');
        cell.attr('tabindex','2');

        this.celltoolbar = new IPython.CellToolbar(this);
        cell.append(this.celltoolbar.element);

        var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
        this.code_mirror = CodeMirror(input_area.get(0), this.cm_config);

        // The tabindex=-1 makes this div focusable.
        var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
            addClass('rendered_html').attr('tabindex','-1');
        cell.append(input_area).append(render_area);
        this.element = cell;
    };

    /**
     * Bind the DOM evet to cell actions
     * Need to be called after TextCell.create_element
     * @private
     * @method bind_event
     */
    TextCell.prototype.bind_events = function () {
        IPython.Cell.prototype.bind_events.apply(this);
        var that = this;
        this.element.keydown(function (event) {
            if (event.which === 13 && !event.shiftKey) {
                if (that.rendered) {
                    that.edit();
                    return false;
                };
            };
        });
        this.element.dblclick(function () {
            that.edit();
        });
    };

    /**
     * This method gets called in CodeMirror's onKeyDown/onKeyPress
     * handlers and is used to provide custom key handling.
     *
     * Subclass should override this method to have custom handeling
     *
     * @method handle_codemirror_keyevent
     * @param {CodeMirror} editor - The codemirror instance bound to the cell
     * @param {event} event -
     * @return {Boolean} `true` if CodeMirror should ignore the event, `false` Otherwise
     */
    TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {

        if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
            // Always ignore shift-enter in CodeMirror as we handle it.
            return true;
        }
        return false;
    };

    /**
     * Select the current cell and trigger 'focus'
     * @method select
     */
    TextCell.prototype.select = function () {
        IPython.Cell.prototype.select.apply(this);
        var output = this.element.find("div.text_cell_render");
        output.trigger('focus');
    };

    /**
     * unselect the current cell and `render` it
     * @method unselect
     */
    TextCell.prototype.unselect = function() {
        // render on selection of another cell
        this.render();
        IPython.Cell.prototype.unselect.apply(this);
    };

    /**
     *
     * put the current cell in edition mode
     * @method edit
     */
    TextCell.prototype.edit = function () {
        if ( this.read_only ) return;
        if (this.rendered === true) {
            var text_cell = this.element;
            var output = text_cell.find("div.text_cell_render");
            output.hide();
            text_cell.find('div.text_cell_input').show();
            this.code_mirror.refresh();
            this.code_mirror.focus();
            // We used to need an additional refresh() after the focus, but
            // it appears that this has been fixed in CM. This bug would show
            // up on FF when a newly loaded markdown cell was edited.
            this.rendered = false;
            if (this.get_text() === this.placeholder) {
                this.set_text('');
                this.refresh();
            }
        }
    };

    /**
     * Empty, Subclasses must define render.
     * @method render
     */
    TextCell.prototype.render = function () {};

    /**
     * setter: {{#crossLink "TextCell/set_text"}}{{/crossLink}}
     * @method get_text
     * @retrun {string} CodeMirror current text value
     */
    TextCell.prototype.get_text = function() {
        return this.code_mirror.getValue();
    };

    /**
     * @param {string} text - Codemiror text value
     * @see TextCell#get_text
     * @method set_text
     * */
    TextCell.prototype.set_text = function(text) {
        this.code_mirror.setValue(text);
        this.code_mirror.refresh();
    };

    /**
     * setter :{{#crossLink "TextCell/set_rendered"}}{{/crossLink}}
     * @method get_rendered
     * @return {html} html of rendered element
     * */
    TextCell.prototype.get_rendered = function() {
        return this.element.find('div.text_cell_render').html();
    };

    /**
     * @method set_rendered
     */
    TextCell.prototype.set_rendered = function(text) {
        this.element.find('div.text_cell_render').html(text);
    };

    /**
     * not deprecated, but implementation wrong
     * @method at_top
     * @deprecated
     * @return {Boolean} true is cell rendered, false otherwise
     * I doubt this is what it is supposed to do
     * this implementation is completly false
     */
    TextCell.prototype.at_top = function () {
        if (this.rendered) {
            return true;
        } else {
            return false;
        }
    };

    /**
     * not deprecated, but implementation wrong
     * @method at_bottom
     * @deprecated
     * @return {Boolean} true is cell rendered, false otherwise
     * I doubt this is what it is supposed to do
     * this implementation is completly false
     * */
    TextCell.prototype.at_bottom = function () {
        if (this.rendered) {
            return true;
        } else {
            return false;
        }
    };

    /**
     * Create Text cell from JSON
     * @param {json} data - JSON serialized text-cell
     * @method fromJSON
     */
    TextCell.prototype.fromJSON = function (data) {
        IPython.Cell.prototype.fromJSON.apply(this, arguments);
        if (data.cell_type === this.cell_type) {
            if (data.source !== undefined) {
                this.set_text(data.source);
                // make this value the starting point, so that we can only undo
                // to this state, instead of a blank cell
                this.code_mirror.clearHistory();
                this.set_rendered(data.rendered || '');
                this.rendered = false;
                this.render();
            }
        }
    };

    /** Generate JSON from cell
     * @return {object} cell data serialised to json
     */
    TextCell.prototype.toJSON = function () {
        var data = IPython.Cell.prototype.toJSON.apply(this);
        data.cell_type = this.cell_type;
        data.source = this.get_text();
        return data;
    };

    /**
     * @class MarkdownCell
     * @constructor MarkdownCell
     * @extends IPython.HTMLCell
     */
    var MarkdownCell = function (options) {
        var options = options || {};

        options = this.mergeopt(MarkdownCell,options);
        TextCell.apply(this, [options]);

        this.cell_type = 'markdown';
    };

    MarkdownCell.options_default = {
        cm_config: {
            mode: 'gfm'
        },
        placeholder: "Type *Markdown* and LaTeX: $\\alpha^2$"
    }

    MarkdownCell.prototype = new TextCell();

    /**
     * @method render
     */
    MarkdownCell.prototype.render = function () {
        if (this.rendered === false) {
            var text = this.get_text();
            if (text === "") { text = this.placeholder; }
            var text_math = IPython.mathjaxutils.remove_math(text);
            var text = text_math[0];
            var math = text_math[1];
            var html = marked.parser(marked.lexer(text));
            html = $(IPython.mathjaxutils.replace_math(html, math));
            // links in markdown cells should open in new tabs
            html.find("a[href]").attr("target", "_blank");
            try {
                this.set_rendered(html);
            } catch (e) {
                console.log("Error running Javascript in Markdown:");
                console.log(e);
                this.set_rendered($("<div/>").addClass("js-error").html(
                    "Error rendering Markdown!<br/>" + e.toString())
                );
            }
            this.element.find('div.text_cell_input').hide();
            this.element.find("div.text_cell_render").show();
            this.typeset()
            this.rendered = true;
        }
    };

    // RawCell

    /**
     * @class RawCell
     * @constructor RawCell
     * @extends IPython.TextCell
     */
    var RawCell = function (options) {

        options = this.mergeopt(RawCell,options)
        TextCell.apply(this, [options]);

        this.cell_type = 'raw';

        var that = this
        this.element.focusout(
                function() { that.auto_highlight(); }
            );
    };

    RawCell.options_default = {
        placeholder : "Type plain text and LaTeX: $\\alpha^2$"
    };

    RawCell.prototype = new TextCell();

    /**
     * Trigger autodetection of highlight scheme for current cell
     * @method auto_highlight
     */
    RawCell.prototype.auto_highlight = function () {
        this._auto_highlight(IPython.config.raw_cell_highlight);
    };

    /** @method render **/
    RawCell.prototype.render = function () {
        this.rendered = true;
        this.edit();
    };

    /** @method handle_codemirror_keyevent **/
    RawCell.prototype.handle_codemirror_keyevent = function (editor, event) {

        var that = this;
        if (event.which === key.UPARROW && event.type === 'keydown') {
            // If we are not at the top, let CM handle the up arrow and
            // prevent the global keydown handler from handling it.
            if (!that.at_top()) {
                event.stop();
                return false;
            } else {
                return true;
            };
        } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
            // If we are not at the bottom, let CM handle the down arrow and
            // prevent the global keydown handler from handling it.
            if (!that.at_bottom()) {
                event.stop();
                return false;
            } else {
                return true;
            };
        };
        return false;
    };

    /** @method select **/
    RawCell.prototype.select = function () {
        IPython.Cell.prototype.select.apply(this);
        this.code_mirror.refresh();
        this.code_mirror.focus();
    };

    /** @method at_top **/
    RawCell.prototype.at_top = function () {
        var cursor = this.code_mirror.getCursor();
        if (cursor.line === 0 && cursor.ch === 0) {
            return true;
        } else {
            return false;
        }
    };

    /** @method at_bottom **/
    RawCell.prototype.at_bottom = function () {
        var cursor = this.code_mirror.getCursor();
        if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
            return true;
        } else {
            return false;
        }
    };

    /**
     * @class HeadingCell
     * @extends IPython.TextCell
     */

    /**
     * @constructor HeadingCell
     * @extends IPython.TextCell
     */
    var HeadingCell = function (options) {

        options = this.mergeopt(HeadingCell,options)
        TextCell.apply(this, [options]);

        /**
         * heading level of the cell, use getter and setter to access
         * @property level
         */
        this.level = 1;
        this.cell_type = 'heading';
    };

    HeadingCell.options_default = {
        placeholder: "Type Heading Here"
    };

    HeadingCell.prototype = new TextCell();

    /** @method fromJSON */
    HeadingCell.prototype.fromJSON = function (data) {
        if (data.level != undefined){
            this.level = data.level;
        }
        TextCell.prototype.fromJSON.apply(this, arguments);
    };

    /** @method toJSON */
    HeadingCell.prototype.toJSON = function () {
        var data = TextCell.prototype.toJSON.apply(this);
        data.level = this.get_level();
        return data;
    };

    /**
     * Change heading level of cell, and re-render
     * @method set_level
     */
    HeadingCell.prototype.set_level = function (level) {
        this.level = level;
        if (this.rendered) {
            this.rendered = false;
            this.render();
        };
    };

    /** The depth of header cell, based on html (h1 to h6)
     * @method get_level
     * @return {integer} level - for 1 to 6
     */
    HeadingCell.prototype.get_level = function () {
        return this.level;
    };

    HeadingCell.prototype.set_rendered = function (html) {
        this.element.find("div.text_cell_render").html(html);
    };

    HeadingCell.prototype.get_rendered = function () {
        var r = this.element.find("div.text_cell_render");
        return r.children().first().html();
    };

    HeadingCell.prototype.render = function () {
        if (this.rendered === false) {
            var text = this.get_text();
            // Markdown headings must be a single line
            text = text.replace(/\n/g, ' ');
            if (text === "") { text = this.placeholder; }
            text = Array(this.level + 1).join("#") + " " + text;
            var text_and_math = IPython.mathjaxutils.remove_math(text);
            var text = text_and_math[0];
            var math = text_and_math[1];
            var html = marked.parser(marked.lexer(text));
            var h = $(IPython.mathjaxutils.replace_math(html, math));
            // add id and linkback anchor
            var hash = h.text().replace(/ /g, '-');
            h.attr('id', hash);
            h.append(
                $('<a/>')
                    .addClass('anchor-link')
                    .attr('href', '#' + hash)
                    .text('¶')
            );

            this.set_rendered(h);
            this.typeset();
            this.element.find('div.text_cell_input').hide();
            this.element.find("div.text_cell_render").show();
            this.rendered = true;
        };
    };

    IPython.TextCell = TextCell;
    IPython.MarkdownCell = MarkdownCell;
    IPython.RawCell = RawCell;
    IPython.HeadingCell = HeadingCell;

    return IPython;

}(IPython));

<|endoftext|>


<commit_before>/**
 * The Toggler Component
 *
 * @module aui-toggler
 */

var Lang = A.Lang,
    isBoolean = Lang.isBoolean,
    isObject = Lang.isObject,
    isString = Lang.isString,

    AArray = A.Array,

    DOC = A.config.doc,

    Toggler = A.Toggler,
    CUBIC_BEZIER = 'cubic-bezier(0, 0.1, 0, 1.0)',

    getCN = A.getClassName,

    CSS_TOGGLER_CONTENT_WRAPPER = getCN('toggler', 'content', 'wrapper'),
    CSS_TOGGLER_HEADER_COLLAPSED = getCN('toggler', 'header', 'collapsed'),
    CSS_TOGGLER_HEADER_EXPANDED = getCN('toggler', 'header', 'expanded');

/**
 * A base class for Toggler Delegate.
 *
 * Check the [live demo](http://alloyui.com/examples/toggler/).
 *
 * @class A.TogglerDelegate
 * @extends Base
 * @param {Object} config Object literal specifying widget configuration
 *     properties.
 * @constructor
 */
var TogglerDelegate = A.Component.create({

    /**
     * Static property provides a string to identify the class.
     *
     * @property NAME
     * @type String
     * @static
     */
    NAME: 'toggler-delegate',

    /**
     * Static property used to define the default attribute
     * configuration for the `A.TogglerDelegate`.
     *
     * @property ATTRS
     * @type Object
     * @static
     */
    ATTRS: {

        /**
         * Determine if the `A.TogglerDelegate` transitions will animate.
         *
         * @attribute animated
         * @default false
         * @type Boolean
         * @writeOnce
         */
        animated: {
            validator: isBoolean,
            value: false,
            writeOnce: true
        },

        /**
         * Determine if the `A.TogglerDelegate` switches
         * will be set to off when one switch is toggled on.
         *
         * @attribute closeAllOnExpand
         * @default false
         * @type Boolean
         */
        closeAllOnExpand: {
            validator: isBoolean,
            value: false
        },

        /**
         * The container of `A.TogglerDelegate` instance.
         *
         * @attribute container
         */
        container: {
            setter: A.one,
            value: DOC
        },

        /**
         * The content of a Toogler Delegate instance.
         *
         * @attribute content
         * @type String
         */
        content: {
            validator: isString
        },

        /**
         * Determine if the content starts as toggled on/off on page load.
         *
         * @attribute expanded
         * @default true
         * @type Boolean
         */
        expanded: {
            validator: isBoolean,
            value: true
        },

        /**
         * The header of a Toogler Delegate instance.
         *
         * @attribute header
         * @type String
         */
        header: {
            validator: isString
        },

        /**
         * User interaction that triggers the Toggler instance.
         *
         * @attribute toggleEvent
         * @type String
         * @writeOnce
         */
        toggleEvent: {
            validator: isString,
            value: 'tap',
            writeOnce: true
        },

        /**
         * Transition definitions such as duration and type of easing effect.
         *
         * @attribute transition
         * @type Object
         */
        transition: {
            validator: isObject,
            value: {
                duration: 0.4,
                easing: CUBIC_BEZIER
            }
        }

    },

    /**
     * Static property used to define which component it extends.
     *
     * @property EXTENDS
     * @type Object
     * @static
     */
    EXTENDS: A.Base,

    prototype: {

        items: null,

        /**
         * Construction logic executed during TogglerDelegate instantiation.
         * Lifecycle.
         *
         * @method initializer
         * @protected
         */
        initializer: function() {
            var instance = this;

            instance.items = [];

            instance.bindUI();
            instance.renderUI();
        },

        /**
         * Render the TogglerDelegate component instance. Lifecycle.
         *
         * @method renderUI
         * @protected
         */
        renderUI: function() {
            var instance = this;

            instance._createAll();
        },

        /**
         * Bind the events on the TogglerDelegate UI. Lifecycle.
         *
         * @method bindUI
         * @protected
         */
        bindUI: function() {
            var instance = this;
            var container = instance.get('container');
            var header = instance.get('header');

            instance._eventHandles = [
                container.delegate([instance.get('toggleEvent'), 'keydown'], A.bind('headerEventHandler', instance), header),
                instance.on('toggler:animatingChange', A.bind('_onAnimatingChange', instance))
            ];
        },

        /**
         * Destructor lifecycle implementation for the `TogglerDelegate` class.
         *
         * @method destructor
         * @protected
         */
        destructor: function() {
            var instance = this;

            AArray.each(instance.items, function(item) {
                item.destroy();
            });

            instance.items = null;

            (new A.EventHandle(instance._eventHandles)).detach();
        },

        /**
         * Collapse all items.
         *
         * @method collapseAll
         */
        collapseAll: function(payload) {
            var instance = this;

            instance._createAll();

            A.Array.invoke(instance.items, 'collapse', payload);
        },

        /**
         * Forces toggler creation on delegated header elements.
         *
         * @method _createAll
         * @protected
         */
        _createAll: function() {
            var instance = this;

            instance.get('container').all(instance.get('header')).each(function(header) {
                var markupCollapsed = header.hasClass(CSS_TOGGLER_HEADER_COLLAPSED),
                    markupExpanded = header.hasClass(CSS_TOGGLER_HEADER_EXPANDED),
                    expanded = instance.get('expanded'),
                    closeAllOnExpand = instance.get('closeAllOnExpand');

                if ((closeAllOnExpand && !markupCollapsed) ||
                    (expanded && markupCollapsed) ||
                    (!expanded && !markupExpanded && !markupCollapsed) && !header.getData('toggler')) {
                    instance._create(header);
                }
            });
        },

        /**
         * Expand all items.
         *
         * @method expandAll
         */
        expandAll: function(payload) {
            var instance = this;

            instance._createAll();

            A.Array.invoke(instance.items, 'expand', payload);
        },

        /**
         * Return the content node.
         *
         * @method findContentNode
         * @param header
         */
        findContentNode: function(header) {
            var instance = this;
            var content = instance.get('content');

            var contentNode = header.next(content) || header.one(content);

            if (!contentNode) {
                var wrapper = header.next('.' + CSS_TOGGLER_CONTENT_WRAPPER);

                if (wrapper) {
                    contentNode = wrapper.get('firstChild');
                }
            }

            return contentNode;
        },

        /**
         * Handle header events.
         *
         * @method headerEventHandler
         * @param event
         */
        headerEventHandler: function(event) {
            var instance = this;

            if (instance.animating) {
                return false;
            }

            var target = event.currentTarget;
            var toggler = target.getData('toggler') || instance._create(target);

            if (Toggler.headerEventHandler(event, toggler) && instance.get('closeAllOnExpand')) {
                var wrappingContent = toggler.get('content').ancestor(instance.get('content'));

                AArray.each(instance.items, function(item) {
                    if ((item !== toggler) && item.get('expanded')) {

                        if (wrappingContent) {
                            var itemContent = item.get('content');

                            if ((itemContent !== wrappingContent) && wrappingContent.contains(itemContent)) {
                                item.collapse();
                            }
                        }
                        else {
                            item.collapse();
                        }

                    }
                });
            }
        },

        /**
         * Create a Toggler instance.
         *
         * @method _create
         * @param header
         * @protected
         */
        _create: function(header) {
            var instance = this,
                expanded = instance.get('expanded');

            // Prioritize markup information to decide whether it's expanded or
            // not
            if (header.hasClass(CSS_TOGGLER_HEADER_EXPANDED)) {
                expanded = true;
            }
            else if (header.hasClass(CSS_TOGGLER_HEADER_COLLAPSED)) {
                expanded = false;
            }

            var toggler = new Toggler({
                animated: instance.get('animated'),
                bindDOMEvents: false,
                bubbleTargets: [instance],
                content: instance.findContentNode(header),
                expanded: expanded,
                header: header,
                toggleEvent: instance.get('toggleEvent'),
                transition: instance.get('transition')
            });

            instance.items.push(toggler);

            return toggler;
        },

        /**
         * Trigger when the `animating` attribute change its value.
         *
         * @method _onAnimatingChange
         * @param event
         * @protected
         */
        _onAnimatingChange: function(event) {
            var instance = this;

            instance.animating = event.newVal;
        }

    }
});

A.TogglerDelegate = TogglerDelegate;
<commit_msg>AUI-1196 Change `expanded` attribute to write once<commit_after>/**
 * The Toggler Component
 *
 * @module aui-toggler
 */

var Lang = A.Lang,
    isBoolean = Lang.isBoolean,
    isObject = Lang.isObject,
    isString = Lang.isString,

    AArray = A.Array,

    DOC = A.config.doc,

    Toggler = A.Toggler,
    CUBIC_BEZIER = 'cubic-bezier(0, 0.1, 0, 1.0)',

    getCN = A.getClassName,

    CSS_TOGGLER_CONTENT_WRAPPER = getCN('toggler', 'content', 'wrapper'),
    CSS_TOGGLER_HEADER_COLLAPSED = getCN('toggler', 'header', 'collapsed'),
    CSS_TOGGLER_HEADER_EXPANDED = getCN('toggler', 'header', 'expanded');

/**
 * A base class for Toggler Delegate.
 *
 * Check the [live demo](http://alloyui.com/examples/toggler/).
 *
 * @class A.TogglerDelegate
 * @extends Base
 * @param {Object} config Object literal specifying widget configuration
 *     properties.
 * @constructor
 */
var TogglerDelegate = A.Component.create({

    /**
     * Static property provides a string to identify the class.
     *
     * @property NAME
     * @type String
     * @static
     */
    NAME: 'toggler-delegate',

    /**
     * Static property used to define the default attribute
     * configuration for the `A.TogglerDelegate`.
     *
     * @property ATTRS
     * @type Object
     * @static
     */
    ATTRS: {

        /**
         * Determine if the `A.TogglerDelegate` transitions will animate.
         *
         * @attribute animated
         * @default false
         * @type Boolean
         * @writeOnce
         */
        animated: {
            validator: isBoolean,
            value: false,
            writeOnce: true
        },

        /**
         * Determine if the `A.TogglerDelegate` switches
         * will be set to off when one switch is toggled on.
         *
         * @attribute closeAllOnExpand
         * @default false
         * @type Boolean
         */
        closeAllOnExpand: {
            validator: isBoolean,
            value: false
        },

        /**
         * The container of `A.TogglerDelegate` instance.
         *
         * @attribute container
         */
        container: {
            setter: A.one,
            value: DOC
        },

        /**
         * The content of a Toogler Delegate instance.
         *
         * @attribute content
         * @type String
         */
        content: {
            validator: isString
        },

        /**
         * Determine if the content starts as toggled on/off on page load.
         *
         * @attribute expanded
         * @default true
         * @type Boolean
         */
        expanded: {
            validator: isBoolean,
            value: true,
            writeOnce: true
        },

        /**
         * The header of a Toogler Delegate instance.
         *
         * @attribute header
         * @type String
         */
        header: {
            validator: isString
        },

        /**
         * User interaction that triggers the Toggler instance.
         *
         * @attribute toggleEvent
         * @type String
         * @writeOnce
         */
        toggleEvent: {
            validator: isString,
            value: 'tap',
            writeOnce: true
        },

        /**
         * Transition definitions such as duration and type of easing effect.
         *
         * @attribute transition
         * @type Object
         */
        transition: {
            validator: isObject,
            value: {
                duration: 0.4,
                easing: CUBIC_BEZIER
            }
        }

    },

    /**
     * Static property used to define which component it extends.
     *
     * @property EXTENDS
     * @type Object
     * @static
     */
    EXTENDS: A.Base,

    prototype: {

        items: null,

        /**
         * Construction logic executed during TogglerDelegate instantiation.
         * Lifecycle.
         *
         * @method initializer
         * @protected
         */
        initializer: function() {
            var instance = this;

            instance.items = [];

            instance.bindUI();
            instance.renderUI();
        },

        /**
         * Render the TogglerDelegate component instance. Lifecycle.
         *
         * @method renderUI
         * @protected
         */
        renderUI: function() {
            var instance = this;

            instance._createAll();
        },

        /**
         * Bind the events on the TogglerDelegate UI. Lifecycle.
         *
         * @method bindUI
         * @protected
         */
        bindUI: function() {
            var instance = this;
            var container = instance.get('container');
            var header = instance.get('header');

            instance._eventHandles = [
                container.delegate([instance.get('toggleEvent'), 'keydown'], A.bind('headerEventHandler', instance), header),
                instance.on('toggler:animatingChange', A.bind('_onAnimatingChange', instance))
            ];
        },

        /**
         * Destructor lifecycle implementation for the `TogglerDelegate` class.
         *
         * @method destructor
         * @protected
         */
        destructor: function() {
            var instance = this;

            AArray.each(instance.items, function(item) {
                item.destroy();
            });

            instance.items = null;

            (new A.EventHandle(instance._eventHandles)).detach();
        },

        /**
         * Collapse all items.
         *
         * @method collapseAll
         */
        collapseAll: function(payload) {
            var instance = this;

            instance._createAll();

            A.Array.invoke(instance.items, 'collapse', payload);
        },

        /**
         * Forces toggler creation on delegated header elements.
         *
         * @method _createAll
         * @protected
         */
        _createAll: function() {
            var instance = this;

            instance.get('container').all(instance.get('header')).each(function(header) {
                var markupCollapsed = header.hasClass(CSS_TOGGLER_HEADER_COLLAPSED),
                    markupExpanded = header.hasClass(CSS_TOGGLER_HEADER_EXPANDED),
                    expanded = instance.get('expanded'),
                    closeAllOnExpand = instance.get('closeAllOnExpand');

                if ((closeAllOnExpand && !markupCollapsed) ||
                    (expanded && markupCollapsed) ||
                    (!expanded && !markupExpanded && !markupCollapsed) && !header.getData('toggler')) {
                    instance._create(header);
                }
            });
        },

        /**
         * Expand all items.
         *
         * @method expandAll
         */
        expandAll: function(payload) {
            var instance = this;

            instance._createAll();

            A.Array.invoke(instance.items, 'expand', payload);
        },

        /**
         * Return the content node.
         *
         * @method findContentNode
         * @param header
         */
        findContentNode: function(header) {
            var instance = this;
            var content = instance.get('content');

            var contentNode = header.next(content) || header.one(content);

            if (!contentNode) {
                var wrapper = header.next('.' + CSS_TOGGLER_CONTENT_WRAPPER);

                if (wrapper) {
                    contentNode = wrapper.get('firstChild');
                }
            }

            return contentNode;
        },

        /**
         * Handle header events.
         *
         * @method headerEventHandler
         * @param event
         */
        headerEventHandler: function(event) {
            var instance = this;

            if (instance.animating) {
                return false;
            }

            var target = event.currentTarget;
            var toggler = target.getData('toggler') || instance._create(target);

            if (Toggler.headerEventHandler(event, toggler) && instance.get('closeAllOnExpand')) {
                var wrappingContent = toggler.get('content').ancestor(instance.get('content'));

                AArray.each(instance.items, function(item) {
                    if ((item !== toggler) && item.get('expanded')) {

                        if (wrappingContent) {
                            var itemContent = item.get('content');

                            if ((itemContent !== wrappingContent) && wrappingContent.contains(itemContent)) {
                                item.collapse();
                            }
                        }
                        else {
                            item.collapse();
                        }

                    }
                });
            }
        },

        /**
         * Create a Toggler instance.
         *
         * @method _create
         * @param header
         * @protected
         */
        _create: function(header) {
            var instance = this,
                expanded = instance.get('expanded');

            // Prioritize markup information to decide whether it's expanded or
            // not
            if (header.hasClass(CSS_TOGGLER_HEADER_EXPANDED)) {
                expanded = true;
            }
            else if (header.hasClass(CSS_TOGGLER_HEADER_COLLAPSED)) {
                expanded = false;
            }

            var toggler = new Toggler({
                animated: instance.get('animated'),
                bindDOMEvents: false,
                bubbleTargets: [instance],
                content: instance.findContentNode(header),
                expanded: expanded,
                header: header,
                toggleEvent: instance.get('toggleEvent'),
                transition: instance.get('transition')
            });

            instance.items.push(toggler);

            return toggler;
        },

        /**
         * Trigger when the `animating` attribute change its value.
         *
         * @method _onAnimatingChange
         * @param event
         * @protected
         */
        _onAnimatingChange: function(event) {
            var instance = this;

            instance.animating = event.newVal;
        }

    }
});

A.TogglerDelegate = TogglerDelegate;
<|endoftext|>


<commit_before>'use strict';

describe('The CLI called', function () {
    var run = require('../../main/js/run');
    var args;

    this.timeout(10000);

    // chai
    require('chai').should();

    // std-mocks
    var stdMocks = require('std-mocks');

    function stdout() {
        return stdMocks.flush().stdout.join('');
    }

    // mock-stdin
    var stdin = require('mock-stdin').stdin();

    // tmp
    var tmp = require('tmp');

    // resources
    var fs = require('fs');
    var resourcePath = 'src/test/resources/';

    var resources = [0, 1].map(function (e) {
        var basePath = resourcePath + e + '/';
        return {
            gv: fs.readFileSync(basePath + 'source.gv', 'utf8'),
            dotXdot: fs.readFileSync(basePath + 'dot.xdot', 'utf8'),
            circoXdot: fs.readFileSync(basePath + 'circo.xdot', 'utf8'),
            dotSvg: fs.readFileSync(basePath + 'dot.svg', 'utf8'),
            circoSvg: fs.readFileSync(basePath + 'circo.svg', 'utf8')
        };
    });

    beforeEach(function () {
        args = {K: null, T: 'xdot', V: false, o: null, inputs: [], prog: 'dot'};

        stdMocks.use();
    });

    afterEach(function () {
        stdMocks.restore();
        stdMocks.flush();

        stdin.reset(true);
    });

    describe('without arguments', function () {
        it('should produce stdout xdot from stdin dot', function () {
            run(args);
            stdin.send(resources[0].gv);
            stdin.end();

            stdout().should.equal(resources[0].dotXdot);
        });
        it('should use the layout of the called executable', function () {
            args.prog = 'circo';

            run(args);
            stdin.send(resources[0].gv);
            stdin.end();

            stdout().should.equal(resources[0].circoXdot);
        });
    });

    describe('with -K', function () {
        it('should use the specified layout regardless of the called executable', function () {
            args.prog = 'fdp';
            args.K = 'circo';

            run(args);
            stdin.send(resources[0].gv);
            stdin.end();

            stdout().should.equal(resources[0].circoXdot);
        })
    });

    describe('with -T', function () {
        it('should produce the specified format', function () {
            args.T = 'svg';

            run(args);
            stdin.send(resources[0].gv);
            stdin.end();

            stdout().should.equal(resources[0].dotSvg);
        });
    });

    describe('with -V', function () {
        beforeEach(function () {
            args.V = true;
        });

        it('should print version information', function () {
            run(args);

            stdout().should.equal('dot - graphviz version 2.38.0 (20140413.2041)\n');
        });
        it('should print the called executable name', function () {
            args.prog = 'circo';

            run(args);

            stdout().should.equal('circo - graphviz version 2.38.0 (20140413.2041)\n');
        });
        it('should return quickly', function () {
            this.timeout(100);

            run(args);
        });
    });

    describe('with -o', function () {
        it('should write to the output file', function () {
            var file = tmp.fileSync();
            args.o = file.name;

            run(args);
            stdin.send(resources[0].gv);
            stdin.end();

            fs.readFileSync(file.name, 'utf8').should.equal(resources[0].dotXdot);
        });
        it('should not write to stdout', function () {
            var file = tmp.fileSync();
            args.o = file.name;

            run(args);
            stdin.send(resources[0].gv);
            stdin.end();

            stdout().should.equal('');
        });
    });

    describe('with input files', function () {
        it('should read from a single input file', function () {
            args.inputs.push(resourcePath + '0/source.gv');

            run(args);
            stdout().should.equal(resources[0].dotXdot);
        });
        it('should read from multiple input files and print their results to stdout', function () {
            args.inputs.push(resourcePath + '0/source.gv', resourcePath + '1/source.gv');

            run(args);
            stdout().should.equal(resources[0].dotXdot + resources[1].dotXdot);
        })
    });
});
<commit_msg>add multi args test<commit_after>'use strict';

describe('The CLI called', function () {
    var run = require('../../main/js/run');
    var args;

    this.timeout(10000);

    // chai
    require('chai').should();

    // std-mocks
    var stdMocks = require('std-mocks');

    function stdout() {
        return stdMocks.flush().stdout.join('');
    }

    // mock-stdin
    var stdin = require('mock-stdin').stdin();

    // tmp
    var tmp = require('tmp');

    // resources
    var fs = require('fs');
    var resourcePath = 'src/test/resources/';

    var resources = [0, 1].map(function (e) {
        var basePath = resourcePath + e + '/';
        return {
            gv: fs.readFileSync(basePath + 'source.gv', 'utf8'),
            dotXdot: fs.readFileSync(basePath + 'dot.xdot', 'utf8'),
            circoXdot: fs.readFileSync(basePath + 'circo.xdot', 'utf8'),
            dotSvg: fs.readFileSync(basePath + 'dot.svg', 'utf8'),
            circoSvg: fs.readFileSync(basePath + 'circo.svg', 'utf8')
        };
    });

    beforeEach(function () {
        args = {K: null, T: 'xdot', V: false, o: null, inputs: [], prog: 'dot'};

        stdMocks.use();
    });

    afterEach(function () {
        stdMocks.restore();
        stdMocks.flush();

        stdin.reset(true);
    });

    describe('without arguments', function () {
        it('should produce stdout xdot from stdin dot', function () {
            run(args);
            stdin.send(resources[0].gv);
            stdin.end();

            stdout().should.equal(resources[0].dotXdot);
        });
        it('should use the layout of the called executable', function () {
            args.prog = 'circo';

            run(args);
            stdin.send(resources[0].gv);
            stdin.end();

            stdout().should.equal(resources[0].circoXdot);
        });
    });

    describe('with -K', function () {
        it('should use the specified layout regardless of the called executable', function () {
            args.prog = 'fdp';
            args.K = 'circo';

            run(args);
            stdin.send(resources[0].gv);
            stdin.end();

            stdout().should.equal(resources[0].circoXdot);
        })
    });

    describe('with -T', function () {
        it('should produce the specified format', function () {
            args.T = 'svg';

            run(args);
            stdin.send(resources[0].gv);
            stdin.end();

            stdout().should.equal(resources[0].dotSvg);
        });
    });

    describe('with -V', function () {
        beforeEach(function () {
            args.V = true;
        });

        it('should print version information', function () {
            run(args);

            stdout().should.equal('dot - graphviz version 2.38.0 (20140413.2041)\n');
        });
        it('should print the called executable name', function () {
            args.prog = 'circo';

            run(args);

            stdout().should.equal('circo - graphviz version 2.38.0 (20140413.2041)\n');
        });
        it('should return quickly', function () {
            this.timeout(100);

            run(args);
        });
    });

    describe('with -o', function () {
        it('should write to the output file', function () {
            var file = tmp.fileSync();
            args.o = file.name;

            run(args);
            stdin.send(resources[0].gv);
            stdin.end();

            fs.readFileSync(file.name, 'utf8').should.equal(resources[0].dotXdot);
        });
        it('should not write to stdout', function () {
            var file = tmp.fileSync();
            args.o = file.name;

            run(args);
            stdin.send(resources[0].gv);
            stdin.end();

            stdout().should.equal('');
        });
    });

    describe('with input files', function () {
        it('should read from a single input file', function () {
            args.inputs.push(resourcePath + '0/source.gv');

            run(args);
            stdout().should.equal(resources[0].dotXdot);
        });
        it('should read from multiple input files and print their results to stdout', function () {
            args.inputs.push(resourcePath + '0/source.gv', resourcePath + '1/source.gv');

            run(args);
            stdout().should.equal(resources[0].dotXdot + resources[1].dotXdot);
        })
    });

    describe('with multiple arguments', function () {
        it('should read from multiple input files and write the first to the output file and the following to stdout ' +
            'in the specified format, using the specified layout regardless of the called executable', function () {
            args.prog = 'fdp';
            args.K = 'circo';
            args.T = 'svg';
            var file = tmp.fileSync();
            args.o = file.name;
            args.inputs.push(resourcePath + '0/source.gv', resourcePath + '1/source.gv');

            run(args);

            fs.readFileSync(file.name, 'utf8').should.equal(resources[0].circoSvg);
            stdout().should.equal(resources[1].circoSvg);
        });
    });
});
<|endoftext|>


<commit_before>/* vertebrae.js 0.0.0
 *
 * jQuery Plugin to mock AJAX requests for Backbone applications.
 * Tim Branyen @tbranyen, Copyright 2013
 * Dual licensed under the MIT or GPL Version 2 licenses.
 *
 * Date Built: Tue, 29 Jan 2013 19:48:25 GMT
 */
(function(global) {

// Internal state
var self = { vendor: {} };
// Cache internally all future defined routes
var _routes = {};
// Shorten Backbone regexp reference
var routeToRegExp = Backbone.Router.prototype._routeToRegExp;

// Load plugins
(function() {
  if (typeof jQuery !== "undefined") {
    (function(global) {

var defaults;

// Third-party hard dependencies
var jQuery = global.jQuery;

// Cache internally all future defined routes
var _routes = {};

// Assign directly onto jQuery to be indicative this is indeed
// a plugin and requires jQuery to use.
jQuery.vertebrae = function(routes) {
  // Convert all URLs passed to regex and assign defaults if they
  // are not provided.
  jQuery.each(routes, function(key, val) {
    _routes[key] = val;
  });
};

// Plugin defaults, can be overwritten
defaults = jQuery.vertebrae.options = {
  // @route is the template
  // @url is URL to be tested
  testRoute: function(route, url) {
    return route === url;
  },
  delay: {
    // Set 404 timeout to simulate real-world delay
    '404': 100
  },
  // Allow AJAX requests to pass through
  passthrough: true
};

// Adding transports in jQuery will push them to the end of the stack for
// filtering.  Without the + preceding the wildcard *, most requests would
// still be handled by jQuery's internal transports.  With the +, this
// catch-all transport is bumped to the front and hijacks *ALL* requests.
jQuery.ajaxTransport('+*', function(options, originalOptions, jqXHR) {
  var data;
  var timeout, captures, match, route;
  var method = options.type.toUpperCase();

  // Detect method to check if a route is found match will either be
  // undefined (falsy) or true (truthy).
  jQuery.each(_routes, function(key, val) {
    captures = defaults.testRoute(key, options.url);
    route = _routes[key];

    // Capture has been found, ensure the requested type has a handler
    if (captures && route[method]) {
      match = true;

      // Break the jQuery.each loop
      return false;
    }
  });

  // If no matches were found, instead of triggering a fake 404, attempt
  // to use real AJAX
  if (!match && defaults.passthrough) {
    return null;
  }

  // Per the documentation a transport should return an object
  // with two keys: send and abort.
  //
  // send: Passes the currently requested route through the routes
  // object and attempts to find a match.
  return {
    send: function(headers, completeCallback) {
      // If no matches, trigger 404 with delay
      if (!match) {
        // Return to ensure that the successful handler is never run
        return timeout = window.setTimeout(function() {
          completeCallback(404, 'error');
        }, defaults.delay['404']);
      }

      // Ensure captures is an array and not null
      captures = captures || [];

      // Slice off the path from captures, only want to send the
      // arguments.  Capture the return value.
      data = route[method].apply(jqXHR, captures.slice(1));

      // A timeout is useful for testing behavior that may require an abort
      // or simulating how slow requests will show up to an end user.
      timeout = window.setTimeout(function() {
        completeCallback(jqXHR.status || 200, 'success', {
          responseText: data
        });
      }, route.timeout || 0);
    },

    // This method will cancel any pending "request", by clearing the timeout
    // that is responsible for triggering the success callback.
    abort: function() {
      window.clearTimeout(timeout);
    }
  };
});

})(this);

  }

  // Vendor stuff
  (function(_, Backbone) {
  // A simple module to replace `Backbone.sync` with *localStorage*-based
  // persistence. Models are given GUIDS, and saved into a JSON object. Simple
  // as that.
  // Generate four random hex digits.

  function S4() {
      return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
  };

  // Generate a pseudo-GUID by concatenating random hexadecimal.

  function guid() {
      return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
  };

  Backbone.Storage = function (name,type) {
      type = type || "local";
      this.name = name;
      this.type = type + "Storage";
      var store = window[this.type].getItem(this.name);
      this.records = (store && store.split(",")) || [];
  }

  _.extend(Backbone.Storage.prototype, {

      // Save the current state of the **Store** to *localStorage*.
      save: function() {
          window[this.type].setItem(this.name, this.records.join(","));
      },

      // Add a model, giving it a (hopefully)-unique GUID, if it doesn't already
      // have an id of it's own.
      create: function(model) {
          if (!model.id) model.id = model.attributes.id = guid();
          window[this.type].setItem(this.name + "-" + model.id, JSON.stringify(model));
          this.records.push(model.id.toString());
          this.save();
          return model;
      },

      // Update a model by replacing its copy in `this.data`.
      update: function(model) {
          window[this.type].setItem(this.name + "-" + model.id, JSON.stringify(model));
          if (!_.include(this.records, model.id.toString())) this.records.push(model.id.toString());
          this.save();
          return model;
      },

      // Retrieve a model from `this.data` by id.
      find: function(model) {
          return JSON.parse(window[this.type].getItem(this.name + "-" + model.id));
      },

      // Return the array of all models currently in storage.
      findAll: function() {
          return _.map(this.records, function(id) {
              return JSON.parse(window[this.type].getItem(this.name + "-" + id))
          }, this);
      },

      // Delete a model from `this.data`, returning it.
      destroy: function(model) {
          window[this.type].removeItem(this.name + "-" + model.id);
          this.records = _.reject(this.records, function(record_id) {
              return record_id == model.id.toString();
          });
          this.save();
          return model;
      }

  });

  var normalSync = Backbone.sync;

  // Override `Backbone.sync` to use delegate to the model or collection's
  // *localStorage* property, which should be an instance of `Store`.
  // If there is no storage found, use the normal Backbone.sync
  Backbone.sync = function(method, model, options, error) {

    // Backwards compatibility with Backbone <= 0.3.3
    if (typeof options == 'function') {
      options = {
        success: options,
        error: error
      };
    }

    var resp,
        store =  model.localStorage || model.sessionStorage;

      if (!store && model.collection) {
        store = model.collection.localStorage || model.collection.sessionStorage;
      }
      if (!store) {
        return normalSync.apply(this, _.toArray(arguments));
      }

      switch (method) {
      case "read":    resp = model.id ? store.find(model) : store.findAll(); break;
      case "create":  resp = store.create(model);                            break;
      case "update":  resp = store.update(model);                            break;
      case "delete":  resp = store.destroy(model);                           break;
      }

      if (resp) {
        options.success(resp);
      } else {
        options.error("Record not found");
      }
  };

})(_, Backbone);

}).call(global);

// Allow for Backbone augmentation
if (typeof Backbone !== "undefined") {

  // Main Backbone plugin function
  Backbone.Vertebrae = function(options) {
    var i, len, type;

    // If persist is a function, call it
    if (typeof this.persist == "function") {
      this.persist = this.persist();
    }

    // Persistables
    if (this.persist && (len = this.persist.length)) {
      for (i = 0; i < len; i++) {
        this.persist[i].prototype.localStorage = new Backbone.Storage(this.profile || "");
      }
    }

    // Convert all URLs passed to regex and assign defaults if they
    // are not provided.
    _.each(this.routes, function(val, key) {
      _routes[key] = val;

      // Add in localStorage support
      if (type = val.model || val.collection) {
        type.prototype.localStorage = new Backbone.Storage(val.profile || "");
      }
    });

    if (typeof jQuery !== "undefined") {
      jQuery.vertebrae.options.testRoute = function(route, url) {
        return routeToRegExp(route).exec(url);
      };

      return jQuery.vertebrae(this.routes || {});
    }
  };

  // This extend method isn't publically available, so we'll just borrow it
  // from the Backbone.Model constructor.
  Backbone.Vertebrae.extend = Backbone.Model.extend;
}

})(this);
<commit_msg>removed dist<commit_after><|endoftext|>