<commit_before>import React, { Component } from "react";
import ReactDOM from "react-dom";
import PropTypes from "prop-types";
import ModalPortal from "./ModalPortal";
import * as ariaAppHider from "../helpers/ariaAppHider";
import SafeHTMLElement, { canUseDOM } from "../helpers/safeHTMLElement";

import { polyfill } from "react-lifecycles-compat";

export const portalClassName = "ReactModalPortal";
export const bodyOpenClassName = "ReactModal__Body--open";

const isReact16 = ReactDOM.createPortal !== undefined;

const getCreatePortal = () =>
  isReact16
    ? ReactDOM.createPortal
    : ReactDOM.unstable_renderSubtreeIntoContainer;

function getParentElement(parentSelector) {
  return parentSelector();
}

class Modal extends Component {
  static setAppElement(element) {
    ariaAppHider.setElement(element);
  }

  /* eslint-disable react/no-unused-prop-types */
  static propTypes = {
    isOpen: PropTypes.bool.isRequired,
    style: PropTypes.shape({
      content: PropTypes.object,
      overlay: PropTypes.object
    }),
    portalClassName: PropTypes.string,
    bodyOpenClassName: PropTypes.string,
    htmlOpenClassName: PropTypes.string,
    className: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.shape({
        base: PropTypes.string.isRequired,
        afterOpen: PropTypes.string.isRequired,
        beforeClose: PropTypes.string.isRequired
      })
    ]),
    overlayClassName: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.shape({
        base: PropTypes.string.isRequired,
        afterOpen: PropTypes.string.isRequired,
        beforeClose: PropTypes.string.isRequired
      })
    ]),
    appElement: PropTypes.instanceOf(SafeHTMLElement),
    onAfterOpen: PropTypes.func,
    onRequestClose: PropTypes.func,
    closeTimeoutMS: PropTypes.number,
    ariaHideApp: PropTypes.bool,
    shouldFocusAfterRender: PropTypes.bool,
    shouldCloseOnOverlayClick: PropTypes.bool,
    shouldReturnFocusAfterClose: PropTypes.bool,
    preventScroll: PropTypes.bool,
    parentSelector: PropTypes.func,
    aria: PropTypes.object,
    data: PropTypes.object,
    role: PropTypes.string,
    contentLabel: PropTypes.string,
    shouldCloseOnEsc: PropTypes.bool,
    overlayRef: PropTypes.func,
    contentRef: PropTypes.func,
    id: PropTypes.string,
    overlayElement: PropTypes.func,
    contentElement: PropTypes.func
  };
  /* eslint-enable react/no-unused-prop-types */

  static defaultProps = {
    isOpen: false,
    portalClassName,
    bodyOpenClassName,
    role: "dialog",
    ariaHideApp: true,
    closeTimeoutMS: 0,
    shouldFocusAfterRender: true,
    shouldCloseOnEsc: true,
    shouldCloseOnOverlayClick: true,
    shouldReturnFocusAfterClose: true,
    preventScroll: false,
    parentSelector: () => document.body,
    overlayElement: (props, contentEl) =>
{contentEl}
,
    contentElement: (props, children) =>
{children}

  };

  static defaultStyles = {
    overlay: {
      position: "fixed",
      top: 0,
      left: 0,
      right: 0,
      bottom: 0,
      backgroundColor: "rgba(255, 255, 255, 0.75)"
    },
    content: {
      position: "absolute",
      top: "40px",
      left: "40px",
      right: "40px",
      bottom: "40px",
      border: "1px solid #ccc",
      background: "#fff",
      overflow: "auto",
      WebkitOverflowScrolling: "touch",
      borderRadius: "4px",
      outline: "none",
      padding: "20px"
    }
  };

  componentDidMount() {
    if (!canUseDOM) return;

    if (!isReact16) {
      this.node = document.createElement("div");
    }
    this.node.className = this.props.portalClassName;

    const parent = getParentElement(this.props.parentSelector);
    parent.appendChild(this.node);

    !isReact16 && this.renderPortal(this.props);
  }

  getSnapshotBeforeUpdate(prevProps) {
    const prevParent = getParentElement(prevProps.parentSelector);
    const nextParent = getParentElement(this.props.parentSelector);
    return { prevParent, nextParent };
  }

  componentDidUpdate(prevProps, _, snapshot) {
    if (!canUseDOM) return;
    const { isOpen, portalClassName } = this.props;

    if (prevProps.portalClassName !== portalClassName) {
      this.node.className = portalClassName;
    }

    const { prevParent, nextParent } = snapshot;
    if (nextParent !== prevParent) {
      prevParent.removeChild(this.node);
      nextParent.appendChild(this.node);
    }

    // Stop unnecessary renders if modal is remaining closed
    if (!prevProps.isOpen && !isOpen) return;

    !isReact16 && this.renderPortal(this.props);
  }

  componentWillUnmount() {
    if (!canUseDOM || !this.node || !this.portal) return;

    const state = this.portal.state;
    const now = Date.now();
    const closesAt =
      state.isOpen &&
      this.props.closeTimeoutMS &&
      (state.closesAt || now + this.props.closeTimeoutMS);

    if (closesAt) {
      if (!state.beforeClose) {
        this.portal.closeWithTimeout();
      }

      setTimeout(this.removePortal, closesAt - now);
    } else {
      this.removePortal();
    }
  }

  removePortal = () => {
    !isReact16 && ReactDOM.unmountComponentAtNode(this.node);
    const parent = getParentElement(this.props.parentSelector);
    if (parent && parent.contains(this.node)) {
      parent.removeChild(this.node);
    } else {
      // eslint-disable-next-line no-console
      console.warn(
        'React-Modal: "parentSelector" prop did not returned any DOM ' +
          "element. Make sure that the parent element is unmounted to " +
          "avoid any memory leaks."
      );
    }
  };

  portalRef = ref => {
    this.portal = ref;
  };

  renderPortal = props => {
    const createPortal = getCreatePortal();
    const portal = createPortal(
      this,
      <ModalPortal defaultStyles={Modal.defaultStyles} {...props} />,
      this.node
    );
    this.portalRef(portal);
  };

  render() {
    if (!canUseDOM || !isReact16) {
      return null;
    }

    if (!this.node && isReact16) {
      this.node = document.createElement("div");
    }

    const createPortal = getCreatePortal();
    return createPortal(
      <ModalPortal
        ref={this.portalRef}
        defaultStyles={Modal.defaultStyles}
        {...this.props}
      />,
      this.node
    );
  }
}

polyfill(Modal);

export default Modal;
<commit_msg>[fixed] don't access ReactDOM.createPortal if DOM not available<commit_after>import React, { Component } from "react";
import ReactDOM from "react-dom";
import PropTypes from "prop-types";
import ModalPortal from "./ModalPortal";
import * as ariaAppHider from "../helpers/ariaAppHider";
import SafeHTMLElement, { canUseDOM } from "../helpers/safeHTMLElement";

import { polyfill } from "react-lifecycles-compat";

export const portalClassName = "ReactModalPortal";
export const bodyOpenClassName = "ReactModal__Body--open";

const isReact16 = canUseDOM && ReactDOM.createPortal !== undefined;

const getCreatePortal = () =>
  isReact16
    ? ReactDOM.createPortal
    : ReactDOM.unstable_renderSubtreeIntoContainer;

function getParentElement(parentSelector) {
  return parentSelector();
}

class Modal extends Component {
  static setAppElement(element) {
    ariaAppHider.setElement(element);
  }

  /* eslint-disable react/no-unused-prop-types */
  static propTypes = {
    isOpen: PropTypes.bool.isRequired,
    style: PropTypes.shape({
      content: PropTypes.object,
      overlay: PropTypes.object
    }),
    portalClassName: PropTypes.string,
    bodyOpenClassName: PropTypes.string,
    htmlOpenClassName: PropTypes.string,
    className: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.shape({
        base: PropTypes.string.isRequired,
        afterOpen: PropTypes.string.isRequired,
        beforeClose: PropTypes.string.isRequired
      })
    ]),
    overlayClassName: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.shape({
        base: PropTypes.string.isRequired,
        afterOpen: PropTypes.string.isRequired,
        beforeClose: PropTypes.string.isRequired
      })
    ]),
    appElement: PropTypes.instanceOf(SafeHTMLElement),
    onAfterOpen: PropTypes.func,
    onRequestClose: PropTypes.func,
    closeTimeoutMS: PropTypes.number,
    ariaHideApp: PropTypes.bool,
    shouldFocusAfterRender: PropTypes.bool,
    shouldCloseOnOverlayClick: PropTypes.bool,
    shouldReturnFocusAfterClose: PropTypes.bool,
    preventScroll: PropTypes.bool,
    parentSelector: PropTypes.func,
    aria: PropTypes.object,
    data: PropTypes.object,
    role: PropTypes.string,
    contentLabel: PropTypes.string,
    shouldCloseOnEsc: PropTypes.bool,
    overlayRef: PropTypes.func,
    contentRef: PropTypes.func,
    id: PropTypes.string,
    overlayElement: PropTypes.func,
    contentElement: PropTypes.func
  };
  /* eslint-enable react/no-unused-prop-types */

  static defaultProps = {
    isOpen: false,
    portalClassName,
    bodyOpenClassName,
    role: "dialog",
    ariaHideApp: true,
    closeTimeoutMS: 0,
    shouldFocusAfterRender: true,
    shouldCloseOnEsc: true,
    shouldCloseOnOverlayClick: true,
    shouldReturnFocusAfterClose: true,
    preventScroll: false,
    parentSelector: () => document.body,
    overlayElement: (props, contentEl) =>
{contentEl}
,
    contentElement: (props, children) =>
{children}

  };

  static defaultStyles = {
    overlay: {
      position: "fixed",
      top: 0,
      left: 0,
      right: 0,
      bottom: 0,
      backgroundColor: "rgba(255, 255, 255, 0.75)"
    },
    content: {
      position: "absolute",
      top: "40px",
      left: "40px",
      right: "40px",
      bottom: "40px",
      border: "1px solid #ccc",
      background: "#fff",
      overflow: "auto",
      WebkitOverflowScrolling: "touch",
      borderRadius: "4px",
      outline: "none",
      padding: "20px"
    }
  };

  componentDidMount() {
    if (!canUseDOM) return;

    if (!isReact16) {
      this.node = document.createElement("div");
    }
    this.node.className = this.props.portalClassName;

    const parent = getParentElement(this.props.parentSelector);
    parent.appendChild(this.node);

    !isReact16 && this.renderPortal(this.props);
  }

  getSnapshotBeforeUpdate(prevProps) {
    const prevParent = getParentElement(prevProps.parentSelector);
    const nextParent = getParentElement(this.props.parentSelector);
    return { prevParent, nextParent };
  }

  componentDidUpdate(prevProps, _, snapshot) {
    if (!canUseDOM) return;
    const { isOpen, portalClassName } = this.props;

    if (prevProps.portalClassName !== portalClassName) {
      this.node.className = portalClassName;
    }

    const { prevParent, nextParent } = snapshot;
    if (nextParent !== prevParent) {
      prevParent.removeChild(this.node);
      nextParent.appendChild(this.node);
    }

    // Stop unnecessary renders if modal is remaining closed
    if (!prevProps.isOpen && !isOpen) return;

    !isReact16 && this.renderPortal(this.props);
  }

  componentWillUnmount() {
    if (!canUseDOM || !this.node || !this.portal) return;

    const state = this.portal.state;
    const now = Date.now();
    const closesAt =
      state.isOpen &&
      this.props.closeTimeoutMS &&
      (state.closesAt || now + this.props.closeTimeoutMS);

    if (closesAt) {
      if (!state.beforeClose) {
        this.portal.closeWithTimeout();
      }

      setTimeout(this.removePortal, closesAt - now);
    } else {
      this.removePortal();
    }
  }

  removePortal = () => {
    !isReact16 && ReactDOM.unmountComponentAtNode(this.node);
    const parent = getParentElement(this.props.parentSelector);
    if (parent && parent.contains(this.node)) {
      parent.removeChild(this.node);
    } else {
      // eslint-disable-next-line no-console
      console.warn(
        'React-Modal: "parentSelector" prop did not returned any DOM ' +
          "element. Make sure that the parent element is unmounted to " +
          "avoid any memory leaks."
      );
    }
  };

  portalRef = ref => {
    this.portal = ref;
  };

  renderPortal = props => {
    const createPortal = getCreatePortal();
    const portal = createPortal(
      this,
      <ModalPortal defaultStyles={Modal.defaultStyles} {...props} />,
      this.node
    );
    this.portalRef(portal);
  };

  render() {
    if (!canUseDOM || !isReact16) {
      return null;
    }

    if (!this.node && isReact16) {
      this.node = document.createElement("div");
    }

    const createPortal = getCreatePortal();
    return createPortal(
      <ModalPortal
        ref={this.portalRef}
        defaultStyles={Modal.defaultStyles}
        {...this.props}
      />,
      this.node
    );
  }
}

polyfill(Modal);

export default Modal;
<|endoftext|>


<commit_before>import Molecule from './molecule'

export default Molecule;
<commit_msg>Export VibrationalModesChart<commit_after>import Molecule from './molecule'
import { VibrationalModesChart } from './chart'

export Molecule;
export VibrationalModesChart
<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const expect = require('chai').expect;
const cp = require('child_process');
const fs = require('fs-extra');
const fixturify = require('fixturify');
const run = require('../../src/run');

function gitInit(cwd) {
  run('git init', {
    cwd
  });

  run('git config user.email "you@example.com"', {
    cwd
  });

  run('git config user.name "Your Name"', {
    cwd
  });

  run('git config merge.tool "vimdiff"', {
    cwd
  });

  run('git config mergetool.keepBackup false', {
    cwd
  });
}

function buildTmp(
  fixturesPath,
  tmpPath
) {
  gitInit(tmpPath);

  fs.copySync(fixturesPath, tmpPath);

  run('git add -A', {
    cwd: tmpPath
  });

  run('git commit -m "add files"', {
    cwd: tmpPath
  });
}

function fixtureCompare(
  tmpPath,
  mergeFixtures
) {
  let actual = fixturify.readSync(tmpPath);
  let expected = fixturify.readSync(mergeFixtures);

  delete actual['.git'];

  expect(actual).to.deep.equal(expected);
}

describe('Acceptance - ember-cli-build', function() {
  this.timeout(30000);

  let cwd;

  before(function() {
    cwd = process.cwd();
  });

  function merge(
    fixturesPath,
    tmpPath
  ) {
    fs.emptyDirSync(tmpPath);

    buildTmp(
      fixturesPath,
      tmpPath
    );

    let binFile = path.join(cwd, 'bin/ember-cli-update');

    return new Promise(resolve => {
      let ps = cp.spawn('node', [
        binFile,
        '--tag',
        'v2.14.1'
      ], {
        cwd: tmpPath,
        env: process.env
      });

      ps.stdout.on('data', data => {
        let str = data.toString();
        if (str.includes('Normal merge conflict')) {
          ps.stdin.write(']c\n');
          ps.stdin.write(':diffg 3\n');
          ps.stdin.write(':wqa\n');
        } else if (str.includes('Deleted merge conflict')) {
          ps.stdin.write('d\n');
        }
      });

      let stderr = '';

      ps.stderr.on('data', data => {
        stderr += data.toString();
      });

      ps.stderr.pipe(process.stdout);

      ps.on('exit', () => {
        let status = run('git status', {
          cwd: tmpPath
        });

        expect(stderr).to.not.contain('Error:');
        expect(stderr).to.not.contain('fatal:');
        expect(stderr).to.not.contain('Command failed');

        let result = run('git log -1', {
          cwd: tmpPath
        });

        // verify it is not committed
        expect(result).to.contain('Author: Your Name <you@example.com>');
        expect(result).to.contain('add files');

        result = run('git branch', {
          cwd: tmpPath
        });

        // verify branch was deleted
        expect(result.trim()).to.contain('* master');

        resolve({
          status,
          stderr
        });
      });
    });
  }

  it('updates app', function() {
    return merge(
      'test/fixtures/local/my-app',
      'tmp/my-app'
    ).then(result => {
      let status = result.status;

      fixtureCompare(
        'tmp/my-app',
        'test/fixtures/merge/my-app'
      );

      // changed locally, no change upstream
      expect(status).to.not.contain(' .ember-cli');

      // exists locally, also added upstream with changes
      expect(status).to.contain('modified:   .eslintrc.js');

      // changed locally, removed upstream
      expect(status).to.contain('deleted:    bower.json');

      // changed locally, also changed upstream
      expect(status).to.contain('modified:   README.md');
    });
  });

  it('updates addon', function() {
    return merge(
      'test/fixtures/local/my-addon',
      'tmp/my-addon'
    ).then(result => {
      let status = result.status;

      fixtureCompare(
        'tmp/my-addon',
        'test/fixtures/merge/my-addon'
      );

      // changed locally, no change upstream
      expect(status).to.not.contain(' .ember-cli');

      // exists locally, also added upstream with changes
      expect(status).to.contain('modified:   .eslintrc.js');

      // changed locally, removed upstream
      expect(status).to.contain('deleted:    bower.json');

      // changed locally, also changed upstream
      expect(status).to.contain('modified:   README.md');
    });
  });
});
<commit_msg>fix --end-tag in test<commit_after>'use strict';

const path = require('path');
const expect = require('chai').expect;
const cp = require('child_process');
const fs = require('fs-extra');
const fixturify = require('fixturify');
const run = require('../../src/run');

function gitInit(cwd) {
  run('git init', {
    cwd
  });

  run('git config user.email "you@example.com"', {
    cwd
  });

  run('git config user.name "Your Name"', {
    cwd
  });

  run('git config merge.tool "vimdiff"', {
    cwd
  });

  run('git config mergetool.keepBackup false', {
    cwd
  });
}

function buildTmp(
  fixturesPath,
  tmpPath
) {
  gitInit(tmpPath);

  fs.copySync(fixturesPath, tmpPath);

  run('git add -A', {
    cwd: tmpPath
  });

  run('git commit -m "add files"', {
    cwd: tmpPath
  });
}

function fixtureCompare(
  tmpPath,
  mergeFixtures
) {
  let actual = fixturify.readSync(tmpPath);
  let expected = fixturify.readSync(mergeFixtures);

  delete actual['.git'];

  expect(actual).to.deep.equal(expected);
}

describe('Acceptance - ember-cli-build', function() {
  this.timeout(30000);

  let cwd;

  before(function() {
    cwd = process.cwd();
  });

  function merge(
    fixturesPath,
    tmpPath
  ) {
    fs.emptyDirSync(tmpPath);

    buildTmp(
      fixturesPath,
      tmpPath
    );

    let binFile = path.join(cwd, 'bin/ember-cli-update');

    return new Promise(resolve => {
      let ps = cp.spawn('node', [
        binFile,
        '--end-tag',
        'v2.14.1'
      ], {
        cwd: tmpPath,
        env: process.env
      });

      ps.stdout.on('data', data => {
        let str = data.toString();
        if (str.includes('Normal merge conflict')) {
          ps.stdin.write(']c\n');
          ps.stdin.write(':diffg 3\n');
          ps.stdin.write(':wqa\n');
        } else if (str.includes('Deleted merge conflict')) {
          ps.stdin.write('d\n');
        }
      });

      let stderr = '';

      ps.stderr.on('data', data => {
        stderr += data.toString();
      });

      ps.stderr.pipe(process.stdout);

      ps.on('exit', () => {
        let status = run('git status', {
          cwd: tmpPath
        });

        expect(stderr).to.not.contain('Error:');
        expect(stderr).to.not.contain('fatal:');
        expect(stderr).to.not.contain('Command failed');

        let result = run('git log -1', {
          cwd: tmpPath
        });

        // verify it is not committed
        expect(result).to.contain('Author: Your Name <you@example.com>');
        expect(result).to.contain('add files');

        result = run('git branch', {
          cwd: tmpPath
        });

        // verify branch was deleted
        expect(result.trim()).to.contain('* master');

        resolve({
          status,
          stderr
        });
      });
    });
  }

  it('updates app', function() {
    return merge(
      'test/fixtures/local/my-app',
      'tmp/my-app'
    ).then(result => {
      let status = result.status;

      fixtureCompare(
        'tmp/my-app',
        'test/fixtures/merge/my-app'
      );

      // changed locally, no change upstream
      expect(status).to.not.contain(' .ember-cli');

      // exists locally, also added upstream with changes
      expect(status).to.contain('modified:   .eslintrc.js');

      // changed locally, removed upstream
      expect(status).to.contain('deleted:    bower.json');

      // changed locally, also changed upstream
      expect(status).to.contain('modified:   README.md');
    });
  });

  it('updates addon', function() {
    return merge(
      'test/fixtures/local/my-addon',
      'tmp/my-addon'
    ).then(result => {
      let status = result.status;

      fixtureCompare(
        'tmp/my-addon',
        'test/fixtures/merge/my-addon'
      );

      // changed locally, no change upstream
      expect(status).to.not.contain(' .ember-cli');

      // exists locally, also added upstream with changes
      expect(status).to.contain('modified:   .eslintrc.js');

      // changed locally, removed upstream
      expect(status).to.contain('deleted:    bower.json');

      // changed locally, also changed upstream
      expect(status).to.contain('modified:   README.md');
    });
  });
});
<|endoftext|>


<commit_before>var HTMLLinkElement = function

  // http://w3c.github.io/webcomponents/spec/imports/#h-interface-import

(tag) {

  var
    evt = new Event ('load')

  , target = document.querySelector // use CSS :any ?
      ('link[href*='+tag+'][rel=import]')

  // https://github.com/webcomponents/html-imports#htmlimports
  ;(evt.target = target)
    && window.HTMLImports
    && !!! window.HTMLImports.useNative
    && HTMLImports.whenReady ( function (_) { return target.dispatchEvent (evt); } ) // eww

  return target
}

var TokenList = function (node) {

  this
    .sift (node)
    .map(this.tokenize, this)
};

TokenList.prototype.tokenize = function (node) {
    var this$1 = this;

  var
    insert = function (node) { return function (symbol) { return (this$1 [symbol] = this$1 [symbol] || []).push (node); }; }

  void (node.text = node.textContent)
    .match (/([^{]*?)(\w|#)(?=\})/g)
    .map (insert (node))
};

TokenList.prototype.sift = function (node) {

  var
    nodes = []
  , expression = /{(\w+|#)}/

  , visit = function (node) { return node.nodeType === Node.TEXT_NODE
        ? TEXT_NODE (node)
        : ELEMENT_NODE (node.attributes)
      && NodeFilter.FILTER_REJECT; } // We don't need 'em

  , TEXT_NODE = function (node) { return expression.test (node.textContent)
      && nodes.push (node); }

  , ELEMENT_NODE = function (attrs) { return Array
        .from (attrs)
        .map(function (attr) { return expression.test (attr.value) && nodes.push (attr); }); }

  , walker =
      document.createNodeIterator
        (node, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, visit)
        // by default breaks on template YAY! 🎉

  while (walker.nextNode ()) { 0 } // Walk all nodes and do nothing.

  return nodes
};

TokenList.prototype.bind = function (context) {
    var this$1 = this;

  var
    keys = Object.keys (this)

  , reset = function (symbol) { return this$1 [symbol].map
        (function (node) { return (node.textContent = node.text) && symbol; }); }

  , replace =
      function (symbol, token) {
            if ( token === void 0 ) token = '{'+symbol+'}';

            return function (item) { return (item.textContent = item.textContent.replace (token, context [symbol])); };
    }

  keys.map (reset)

  for (var symbol$1 in this$1)
    { this$1 [symbol$1]
      .map (replace (symbol$1)) }
};

// INTERESTING! Converting `Template` to a class increases size by ~16 octets

// https://github.com/webcomponents/template
var Template = HTMLTemplateElement = function (template) {

  template =
    (typeof template == 'string')
      ? document.querySelector ('template[name='+template+']')
      : template

  // create shallow clone using `.getOwnPropertyDescriptors`
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors#Examples
  // https://docs.microsoft.com/en-us/scripting/javascript/reference/object-getownpropertydescriptor-function-javascript
  // NO IE SUPPORT!!!!
  return Object.assign (template, { bind: bind } )

  function bind (context) {

    var
      html     = ''
    , template = this.innerHTML
    , contexts =
        (ref = []).concat.apply ( ref, [context] )
        // https://dom.spec.whatwg.org/#converting-nodes-into-a-node

    , keys =
        Object
          .keys (contexts [0] || [])    // memoize keys
          .concat (['#', 'self']) // add helper keys

    , tokens   = keys.map (function (key) { return '{'+key+'}'; }) // memoize tokens
    , fragment = document.createElement ('template')

    , deposit = function (context, index) {
        var clone = template

        context = (typeof context  === 'object')
          ? context : { self: context }

        context ['#'] = index

        for (var i=0; i<tokens.length; i++)
          { clone = clone
            .split (tokens [i])
            .join  (context [keys [i]]) }

        return clone
      }

    void (this.dependents || [])
      .map (function (dependent) { return dependent.remove (); })

    for (var i=0, final = ''; i<contexts.length; i++)
      { html += deposit (contexts [i], i) }

    fragment.innerHTML = html

    this.dependents = Array.from // non-live
      (fragment.content.childNodes)

    (ref$1 = this).after.apply ( ref$1, this.dependents )
    var ref;
    var ref$1;
  }
}

var EventTarget = function (HTMLElement) { return ((function (HTMLElement) {
    function anonymous () {
      HTMLElement.apply(this, arguments);
    }

    if ( HTMLElement ) anonymous.__proto__ = HTMLElement;
    anonymous.prototype = Object.create( HTMLElement && HTMLElement.prototype );
    anonymous.prototype.constructor = anonymous;

    anonymous.prototype.on = function ( event, handler ) {

    this.addEventListener
      (event, this.renderable (handler))
  };

  anonymous.prototype.renderable = function ( handler ) {
    var this$1 = this;

    // BIG BUG IN IE!!!
    //
    // https://connect.microsoft.com/IE/feedback/details/790389/event-defaultprevented-returns-false-after-preventdefault-was-called
    //
    // https://github.com/webcomponents/webcomponents-platform/blob/master/webcomponents-platform.js#L16

    return function (event, render) {
        if ( render === void 0 ) render = true;

        return (event.prevent = function (_) { return (render = false) && event.preventDefault (); })

      && handler.call (this$1, event) !== false // for `return false`

      && render && this$1.render ();
    } // check render availability
  };

    return anonymous;
  }(HTMLElement))); }

var ParentNode = function (Element) { return ((function (Element) {
    function anonymous () {
      Element.apply(this, arguments);
    }

    if ( Element ) anonymous.__proto__ = Element;
    anonymous.prototype = Object.create( Element && Element.prototype );
    anonymous.prototype.constructor = anonymous;

    anonymous.prototype.selectAll = function ( fragments ) {
    var tokens = [], len = arguments.length - 1;
    while ( len-- > 0 ) tokens[ len ] = arguments[ len + 1 ];

    fragments =
      (ref = []).concat.apply ( ref, [fragments] )

    var
      zip = function (selector, token) { return selector + token + fragments.shift (); }

    return Array
      .from
        (this.querySelectorAll
          (tokens.reduce (zip, fragments.shift ())))
    var ref;
  };

  anonymous.prototype.select = function ()
    // watch out for clobbering `HTMLInputElement.select ()`
    // https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/select
    {
    var selector = [], len = arguments.length;
    while ( len-- ) selector[ len ] = arguments[ len ];
 return (ref = this).selectAll.apply ( ref, selector ) [0]
    var ref; };

    return anonymous;
  }(Element))); }

//function comb
//  // ElementTraversal interface
//  // https://www.w3.org/TR/ElementTraversal/#interface-elementTraversal
//
//(parent) {
//  if (parent.hasChildNodes())
//    for (let node = parent.firstChild; node; node = node.nextSibling)
//      comb (node)
//}

var GlobalEventHandlers = function (Element) { return ((function (Element) {
    function anonymous () {
      Element.apply(this, arguments);
    }

    if ( Element ) anonymous.__proto__ = Element;
    anonymous.prototype = Object.create( Element && Element.prototype );
    anonymous.prototype.constructor = anonymous;

    anonymous.prototype.onconnect = function (event, target) {

    (target = event.target)
      && this.mirror (target.import.querySelector ('template'))

    Element.prototype.onconnect
      && Element.prototype.onconnect.call (this)

    this.tokens = new TokenList (this)
    this.render ()
  };

  // Reflection - https://en.wikipedia.org/wiki/Reflection_(computer_programming)
  // Type Introspection - https://en.wikipedia.org/wiki/Type_introspection
  //
  // In computing, type introspection is the ability of a program
  // to examine the type or properties of an object at runtime.
  // Some programming languages possess this capability.
  //
  // Introspection should not be confused with reflection,
  // which goes a step further and is the ability for a program to manipulate the values,
  // meta-data, properties and/or functions of an object at runtime.

  anonymous.prototype.reflect = function (handler, event) {
    ( event = ( handler.match (/^on(.+)$/) || [] ) [1] )

    && Object.keys // ensure W3C on event
     ( HTMLElement.prototype )
       .includes ( handler )

    && this.on (event, this [handler])
  };

  anonymous.prototype.register = function (node) {
    var this$1 = this;

    var
      register = function (event, handler) { return (handler = /{\s*(\w+)\s*}/.exec (node [event]))

        && ( handler = this$1 [ (handler || []) [1] ] )
        && ( node [event] = this$1.renderable (handler) ); }

    Array
      .from (node.attributes)
      .map (function (attr) { return attr.name; })
      .filter (function (name) { return /^on/.test (name); })
      .map (register)
  };

    return anonymous;
  }(Element))); }

var Custom = function (Element) { return ( (function (superclass) {
    function anonymous () {
  var this$1 = this;
 superclass.call (this)

    var
      descriptions =
        Object.getOwnPropertyDescriptors
          (Element.prototype)

    , bind = function (key) { return 'function' === typeof descriptions [key].value
        && (this$1 [key] = this$1 [key].bind (this$1)); }

    Object
      .keys (descriptions)
      .map (bind)

    Object
      .getOwnPropertyNames (Element.prototype)
      // POTENTIAL REDUNDANCY
      // Aren't `on` events set up in `.bind` on 20?
      // If so we are `.bind`ing to `this` on two iterations
      // of the same function
      .map (this.reflect, this)

    this.context = {}
    this.initialize && this.initialize ()
  }

    if ( superclass ) anonymous.__proto__ = superclass;
    anonymous.prototype = Object.create( superclass && superclass.prototype );
    anonymous.prototype.constructor = anonymous;

  anonymous.prototype.connectedCallback = function (link) {
    link = HTMLLinkElement
      (this.tagName.toLowerCase ())

    link
      ? link.addEventListener ('load', this.onconnect.bind (this))
      : this.onconnect (new Event ('load'))
  };

  anonymous.prototype.render = function () {
    var this$1 = this;

    this.tokens.bind (this)

    Array
      .from
        (this.selectAll ('template[name]'))

      .map
        (function (template) { return template.getAttribute ('name'); })

      .map
        (function (name) { return (new Template (name)).bind (this$1 [name]); })

    Array
      .from (this.selectAll ('*'))

      .concat ([this])

      .map (this.register, this)

    superclass.prototype.onidle && superclass.prototype.onidle.call (this)
  };

  anonymous.prototype.mirror = function (template, insert) {
    var this$1 = this;

    template = template.cloneNode (true)

    insert = function (replacement, name, slot) { return (name = replacement.getAttribute ('slot')) &&

      (slot = template.content.querySelector ('slot[name='+name+']'))
         // prefer to use replaceWith however support is sparse
         // https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/replaceWith
         // using `Node.parentNode` - https://developer.mozilla.org/en-US/docs/Web/API/Node/parentNode
         // & `Node.replaceChid` - https://developer.mozilla.org/en-US/docs/Web/API/Node/replaceChild
         // as is defined in (ancient) W3C DOM Level 1,2,3
         .parentNode
         .replaceChild (replacement, slot); }

    for (var i = 0, list = this$1.selectAll ('[slot]'); i < list.length; i += 1)
      {
      var replacement = list[i];

      insert (replacement)
    }

    Array
      .from (template.attributes)

      // skip swapping attribute if setting exists
      .filter (function (attr) { return !!! this$1.attributes [attr.name]; })

      .map  (function (attr) { return this$1.setAttribute (attr.name, attr.value); })

    this.innerHTML = template.innerHTML
  };

    return anonymous;
  }(( EventTarget ( ParentNode ( GlobalEventHandlers (Element) )))))); }

var ElementPrototype = window.Element.prototype // see bottom of this file

var Element = function (tag) {

  var constructor =// swizzle
    typeof tag === 'string'
      ? HTMLCustomElement
      : HTMLElement

    //https://gist.github.com/allenwb/53927e46b31564168a1d
    // https://github.com/w3c/webcomponents/issues/587#issuecomment-271031208
    // https://github.com/w3c/webcomponents/issues/587#issuecomment-254017839

    return function (klass) { // https://en.wikipedia.org/wiki/Higher-order_function
      void (ref = window.customElements).define.apply
        ( ref, (ref$1 = []).concat.apply ( ref$1, [tag]).concat( [Custom (klass)], [constructor] ))
      var ref;
      var ref$1;
    }
}

// Assign `window.Element.prototype` in case of feature checking on `Element`
Element.prototype = ElementPrototype
  // http://2ality.com/2013/09/window.html
  // http://tobyho.com/2013/03/13/window-prop-vs-global-var
  // https://github.com/webcomponents/webcomponentsjs/blob/master/webcomponents-es5-loader.js#L19

<commit_msg>:muscle: bump TRANSPILED distribution dist/snuggsi.js<commit_after>var HTMLLinkElement = function

  // http://w3c.github.io/webcomponents/spec/imports/#h-interface-import

(tag) {

  var
    evt = new Event ('load')

  , target = document.querySelector // use CSS :any ?
      ('link[href*='+tag+'][rel=import]')

  // https://github.com/webcomponents/html-imports#htmlimports
  ;(evt.target = target)
    && window.HTMLImports
    && !!! window.HTMLImports.useNative
    && HTMLImports.whenReady ( function (_) { return target.dispatchEvent (evt); } ) // eww

  return target
}

var TokenList = function (node) {

  this
    .sift (node)
    .map(this.tokenize, this)
};

TokenList.prototype.tokenize = function (node) {
    var this$1 = this;

  var
    insert = function (node) { return function (symbol) { return (this$1 [symbol] = this$1 [symbol] || []).push (node); }; }

  void (node.text = node.textContent)
    .match (/([^{]*?)(\w|#)(?=\})/g)
    .map (insert (node))
};

TokenList.prototype.sift = function (node) {

  var
    nodes = []
  , expression = /{(\w+|#)}/

  , visit = function (node) { return node.nodeType === Node.TEXT_NODE
        ? TEXT_NODE (node)
        : ELEMENT_NODE (node.attributes)
      && NodeFilter.FILTER_REJECT; } // We don't need 'em

  , TEXT_NODE = function (node) { return expression.test (node.textContent)
      && nodes.push (node); }

  , ELEMENT_NODE = function (attrs) { return Array
        .from (attrs)
        .map(function (attr) { return expression.test (attr.value) && nodes.push (attr); }); }

  , walker =
      document.createNodeIterator
        (node, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, visit)
        // by default breaks on template YAY! 🎉

  while (walker.nextNode ()) { 0 } // Walk all nodes and do nothing.

  return nodes
};

TokenList.prototype.bind = function (context) {
    var this$1 = this;

  var
    keys = Object.keys (this)

  , reset = function (symbol) { return this$1 [symbol].map
        (function (node) { return (node.textContent = node.text) && symbol; }); }

  , replace =
      function (symbol, token) {
            if ( token === void 0 ) token = '{'+symbol+'}';

            return function (item) { return (item.textContent = item.textContent.replace (token, context [symbol])); };
    }

  keys.map (reset)

  for (var symbol$1 in this$1)
    { this$1 [symbol$1]
      .map (replace (symbol$1)) }
};

// INTERESTING! Converting `Template` to a class increases size by ~16 octets

// https://github.com/webcomponents/template
var Template = HTMLTemplateElement = function (template) {

  template =
    (typeof template == 'string')
      ? document.querySelector ('template[name='+template+']')
      : template

  // create shallow clone using `.getOwnPropertyDescriptors`
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors#Examples
  // https://docs.microsoft.com/en-us/scripting/javascript/reference/object-getownpropertydescriptor-function-javascript
  // NO IE SUPPORT!!!!
  return Object.assign (template, { bind: bind } )

  function bind (context) {

    var
      html     = ''
    , template = this.innerHTML
    , contexts =
        (ref = []).concat.apply ( ref, [context] )
        // https://dom.spec.whatwg.org/#converting-nodes-into-a-node

    , keys =
        Object
          .keys (contexts [0] || [])    // memoize keys
          .concat (['#', 'self']) // add helper keys

    , tokens   = keys.map (function (key) { return '{'+key+'}'; }) // memoize tokens
    , fragment = document.createElement ('template')

    , deposit = function (context, index) {
        var clone = template

        context = (typeof context  === 'object')
          ? context : { self: context }

        context ['#'] = index

        for (var i=0; i<tokens.length; i++)
          { clone = clone
            .split (tokens [i])
            .join  (context [keys [i]]) }

        return clone
      }

    void (this.dependents || [])
      .map (function (dependent) { return dependent.remove (); })

    for (var i=0, final = ''; i<contexts.length; i++)
      { html += deposit (contexts [i], i) }

    fragment.innerHTML = html

    this.dependents = Array.from // non-live
      (fragment.content.childNodes)

    (ref$1 = this).after.apply ( ref$1, this.dependents )
    var ref;
    var ref$1;
  }
}

var EventTarget = function (HTMLElement) { return ((function (HTMLElement) {
    function anonymous () {
      HTMLElement.apply(this, arguments);
    }

    if ( HTMLElement ) anonymous.__proto__ = HTMLElement;
    anonymous.prototype = Object.create( HTMLElement && HTMLElement.prototype );
    anonymous.prototype.constructor = anonymous;

    anonymous.prototype.on = function ( event, handler ) {

    this.addEventListener
      (event, this.renderable (handler))
  };

  anonymous.prototype.renderable = function ( handler ) {
    var this$1 = this;

    // BIG BUG IN IE!!!
    //
    // https://connect.microsoft.com/IE/feedback/details/790389/event-defaultprevented-returns-false-after-preventdefault-was-called
    //
    // https://github.com/webcomponents/webcomponents-platform/blob/master/webcomponents-platform.js#L16

    return function (event, render) {
        if ( render === void 0 ) render = true;

        return (event.prevent = function (_) { return (render = false) && event.preventDefault (); })

      && handler.call (this$1, event) !== false // for `return false`

      && render && this$1.render ();
    } // check render availability
  };

    return anonymous;
  }(HTMLElement))); }

var ParentNode = function (Element) { return ((function (Element) {
    function anonymous () {
      Element.apply(this, arguments);
    }

    if ( Element ) anonymous.__proto__ = Element;
    anonymous.prototype = Object.create( Element && Element.prototype );
    anonymous.prototype.constructor = anonymous;

    anonymous.prototype.selectAll = function ( fragments ) {
    var tokens = [], len = arguments.length - 1;
    while ( len-- > 0 ) tokens[ len ] = arguments[ len + 1 ];

    fragments =
      (ref = []).concat.apply ( ref, [fragments] )

    var
      zip = function (selector, token) { return selector + token + fragments.shift (); }

    return Array
      .from
        (this.querySelectorAll
          (tokens.reduce (zip, fragments.shift ())))
    var ref;
  };

  anonymous.prototype.select = function ()
    // watch out for clobbering `HTMLInputElement.select ()`
    // https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/select
    {
    var selector = [], len = arguments.length;
    while ( len-- ) selector[ len ] = arguments[ len ];
 return (ref = this).selectAll.apply ( ref, selector ) [0]
    var ref; };

    return anonymous;
  }(Element))); }

//function comb
//  // ElementTraversal interface
//  // https://www.w3.org/TR/ElementTraversal/#interface-elementTraversal
//
//(parent) {
//  if (parent.hasChildNodes())
//    for (let node = parent.firstChild; node; node = node.nextSibling)
//      comb (node)
//}

var GlobalEventHandlers = function (Element) { return ((function (Element) {
    function anonymous () {
      Element.apply(this, arguments);
    }

    if ( Element ) anonymous.__proto__ = Element;
    anonymous.prototype = Object.create( Element && Element.prototype );
    anonymous.prototype.constructor = anonymous;

    anonymous.prototype.onconnect = function (event, target) {

    (target = event.target)
      && this.mirror (target.import.querySelector ('template'))

    Element.prototype.onconnect
      && Element.prototype.onconnect.call (this)

    this.tokens = new TokenList (this)
    this.render ()
  };

  // Reflection - https://en.wikipedia.org/wiki/Reflection_(computer_programming)
  // Type Introspection - https://en.wikipedia.org/wiki/Type_introspection
  //
  // In computing, type introspection is the ability of a program
  // to examine the type or properties of an object at runtime.
  // Some programming languages possess this capability.
  //
  // Introspection should not be confused with reflection,
  // which goes a step further and is the ability for a program to manipulate the values,
  // meta-data, properties and/or functions of an object at runtime.

  anonymous.prototype.reflect = function (handler, event) {
    ( event = ( handler.match (/^on(.+)$/) || [] ) [1] )

    && Object.keys // ensure W3C on event
     ( HTMLElement.prototype )
       .includes ( handler )

    && this.on (event, this [handler])
  };

  anonymous.prototype.register = function (node) {
    var this$1 = this;

    var
      register = function (event, handler) { return (handler = /{\s*(\w+)\s*}/.exec (node [event]))

        && ( handler = this$1 [ (handler || []) [1] ] )
        && ( node [event] = this$1.renderable (handler) ); }

    Array
      .from (node.attributes)
      .map (function (attr) { return attr.name; })
      .filter (function (name) { return /^on/.test (name); })
      .map (register)
  };

    return anonymous;
  }(Element))); }

var Custom = function (Element) { return ( (function (superclass) {
    function anonymous () {
  var this$1 = this;
 superclass.call (this)

    console.log ('holy fuck this is working!!!', this)

    return this

    var
      descriptions =
        Object.getOwnPropertyDescriptors
          (Element.prototype)

    , bind = function (key) { return 'function' === typeof descriptions [key].value
        && (this$1 [key] = this$1 [key].bind (this$1)); }

    Object
      .keys (descriptions)
      .map (bind)

    Object
      .getOwnPropertyNames (Element.prototype)
      // POTENTIAL REDUNDANCY
      // Aren't `on` events set up in `.bind` on 20?
      // If so we are `.bind`ing to `this` on two iterations
      // of the same function
      .map (this.reflect, this)

    this.context = {}
    this.initialize && this.initialize ()
  }

    if ( superclass ) anonymous.__proto__ = superclass;
    anonymous.prototype = Object.create( superclass && superclass.prototype );
    anonymous.prototype.constructor = anonymous;

  anonymous.prototype.connectedCallback = function (link) {
    console.warn ('HAIL MARY', this, this.foo, this.bar, this.baz, this.onconnect)

    return

    link = HTMLLinkElement
      (this.tagName.toLowerCase ())

    link
      ? link.addEventListener ('load', this.onconnect.bind (this))
      : this.onconnect (new Event ('load'))
  };

  anonymous.prototype.render = function () {
    var this$1 = this;

    this.tokens.bind (this)

    Array
      .from
        (this.selectAll ('template[name]'))

      .map
        (function (template) { return template.getAttribute ('name'); })

      .map
        (function (name) { return (new Template (name)).bind (this$1 [name]); })

    Array
      .from (this.selectAll ('*'))

      .concat ([this])

      .map (this.register, this)

    superclass.prototype.onidle && superclass.prototype.onidle.call (this)
  };

  anonymous.prototype.mirror = function (template, insert) {
    var this$1 = this;

    template = template.cloneNode (true)

    insert = function (replacement, name, slot) { return (name = replacement.getAttribute ('slot')) &&

      (slot = template.content.querySelector ('slot[name='+name+']'))
         // prefer to use replaceWith however support is sparse
         // https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/replaceWith
         // using `Node.parentNode` - https://developer.mozilla.org/en-US/docs/Web/API/Node/parentNode
         // & `Node.replaceChid` - https://developer.mozilla.org/en-US/docs/Web/API/Node/replaceChild
         // as is defined in (ancient) W3C DOM Level 1,2,3
         .parentNode
         .replaceChild (replacement, slot); }

    for (var i = 0, list = this$1.selectAll ('[slot]'); i < list.length; i += 1)
      {
      var replacement = list[i];

      insert (replacement)
    }

    Array
      .from (template.attributes)

      // skip swapping attribute if setting exists
      .filter (function (attr) { return !!! this$1.attributes [attr.name]; })

      .map  (function (attr) { return this$1.setAttribute (attr.name, attr.value); })

    this.innerHTML = template.innerHTML
  };

    return anonymous;
  }(( EventTarget ( ParentNode ( GlobalEventHandlers (Element) )))))); }

var ElementPrototype = window.Element.prototype // see bottom of this file

var Element = function (tag) {

  var constructor =// swizzle
    typeof tag === 'string'
//    ? HTMLCustomElement
//    : HTMLElement

    //https://gist.github.com/allenwb/53927e46b31564168a1d
    // https://github.com/w3c/webcomponents/issues/587#issuecomment-271031208
    // https://github.com/w3c/webcomponents/issues/587#issuecomment-254017839

    return function (klass) { // https://en.wikipedia.org/wiki/Higher-order_function
      void (ref = window.customElements).define.apply
        ( ref, (ref$1 = []).concat.apply ( ref$1, [tag]).concat( [Custom (klass)], [constructor] ))
      var ref;
      var ref$1;
    }
}

// Assign `window.Element.prototype` in case of feature checking on `Element`
Element.prototype = ElementPrototype
  // http://2ality.com/2013/09/window.html
  // http://tobyho.com/2013/03/13/window-prop-vs-global-var
  // https://github.com/webcomponents/webcomponentsjs/blob/master/webcomponents-es5-loader.js#L19

<|endoftext|>


<commit_before>import RootApp from '../../src/classes/root-app';
import Route from '../../src/classes/route';

class TestRoute extends Route {
    expectedOutlets() {
        return [];
    }
}

describe('RootApp Options', () => {
    describe('stripTrailingSlash', () => {
        class MyRootApp extends RootApp {
            expectedOutlets() {
                return [];
            }
            mount() {
                return {
                    'hasSlash/' : TestRoute,
                };
            }
        }

        it('defaults to not stripping the trailing slash', done => {
            let dest = '/hasSlash/';
            let rootApp = new MyRootApp({});
            rootApp.navigate(dest).then(() => {
                done();
            }).catch(() => {
                done(new Error('expected the trailing slash to be kept'));
            });
        });

        it('strips the trailing slash on URL passed to navigate', done => {
            let dest = '/hasSlash/';
            let rootApp = new MyRootApp({stripTrailingSlash: true});
            rootApp.navigate(dest).then(() => {
                done(new Error('expected the trailing slash to be stripped, giving 404'));
            }).catch(err => {
                expect(err).to.be.instanceof(Error);
                err.message.should.equal(`404 for path: "${dest}".`);
                done();
            });
        });
    });

    describe('addTrailingSlash', () => {
        class MyRootApp extends RootApp {
            expectedOutlets() {
                return [];
            }
            mount() {
                return {
                    'hasSlash/' : TestRoute,
                };
            }
        }

        it('defaults to not adding the trailing slash', done => {
            let dest = '/hasSlash';
            let rootApp = new MyRootApp({});
            rootApp.navigate(dest).then(() => {
                done(new Error('expected the trailing slash to not be added'));
            }).catch(err => {
                expect(err).to.be.instanceof(Error);
                err.message.should.equal(`404 for path: "${dest}".`);
                done();
            });
        });

        it('adds the trailing slash on URL passed to navigate if it is missing', done => {
            let dest = '/hasSlash';
            let rootApp = new MyRootApp({addTrailingSlash: true});
            rootApp.navigate(dest).then(() => {
                done();
            }).catch(() => {
                done(new Error('expected the trailing slash to be added, making navigation a success'));
            });
        });

        it('overrides stripTrailingSlash option', done => {
            let dest = '/hasSlash/';
            let rootApp = new MyRootApp({
                stripTrailingSlash: true,
                addTrailingSlash: true,
            });
            rootApp.navigate(dest).then(() => {
                done();
            }).catch(() => {
                done(new Error('expected the trailing slash to be added/kept, making navigation a success'));
            });
        });
    });

    describe('transitionImmediately', () => {
        class MyRootApp extends RootApp {
            expectedOutlets() {
                return [];
            }
            mount() {
                return {
                    'first' : TestRoute,
                    'second' : TestRoute,
                };
            }
        }

        describe('defaulting to false', () => {
            it('queues transitions', done => {
                let rootApp = new MyRootApp({});
                let firstTransition, secondTransition;

                expect(rootApp.getCurrentTransition()).to.be.null;
                expect(rootApp._transitionQueue).to.be.an('array');
                expect(rootApp._transitionQueue).to.be.empty;

                rootApp.navigate('first?x=1').then(() => {
                    expect(firstTransition).to.be.ok;
                    expect(firstTransition.state).to.equal('succeeded');
                }).catch(() => {
                    done(new Error('expected first navigation to succeed'));
                });

                firstTransition = rootApp.getCurrentTransition();
                expect(firstTransition.url).to.equal('first?x=1');
                expect(firstTransition.state).to.equal('started');
                expect(rootApp._transitionQueue).to.be.empty;

                rootApp.navigate('second').then(() => {
                    expect(firstTransition).to.be.ok;
                    expect(firstTransition.state).to.equal('succeeded');
                    expect(rootApp.getCurrentTransition()).to.equal(secondTransition);
                    expect(secondTransition.state).to.equal('succeeded');
                    done();
                }).catch(() => {
                    done(new Error('expected second navigation to succeed'));
                });

                expect(rootApp._transitionQueue).to.have.length(1);
                secondTransition = rootApp._transitionQueue[0];
                expect(secondTransition.url).to.equal('second');
                expect(secondTransition.state).to.equal('pending');
                expect(secondTransition).to.not.equal(firstTransition);
            });

            it('continues transition queue even if some fail', done => {
                let rootApp = new MyRootApp({});
                let firstTransition, secondTransition;

                expect(rootApp.getCurrentTransition()).to.be.null;
                expect(rootApp._transitionQueue).to.be.an('array');
                expect(rootApp._transitionQueue).to.be.empty;

                rootApp.navigate('non-existent-url').then(() => {
                    done(new Error('expected first navigation to fail'));
                }).catch(() => {
                    expect(firstTransition).to.be.ok;
                    expect(firstTransition.state).to.equal('failed');
                });

                firstTransition = rootApp.getCurrentTransition();
                expect(firstTransition.url).to.equal('non-existent-url');
                expect(firstTransition.state).to.equal('started');
                expect(rootApp._transitionQueue).to.be.empty;

                rootApp.navigate('second').then(() => {
                    expect(firstTransition).to.be.ok;
                    expect(firstTransition.state).to.equal('failed');
                    expect(rootApp.getCurrentTransition()).to.equal(secondTransition);
                    expect(secondTransition.state).to.equal('succeeded');
                    done();
                }).catch(() => {
                    done(new Error('expected second navigation to succeed'));
                });

                expect(rootApp._transitionQueue).to.have.length(1);
                secondTransition = rootApp._transitionQueue[0];
                expect(secondTransition.url).to.equal('second');
                expect(secondTransition.state).to.equal('pending');
                expect(secondTransition).to.not.equal(firstTransition);
            });
        });

        describe.skip('set to true', () => {
            it('cancels the current transition and begins the new navigate() call immediately');
        });
    });

    describe('navOnWindowLoad', () => {
        class MyRootApp extends RootApp {
            expectedOutlets() {
                return [];
            }
            mount() {
                return {
                    'first': TestRoute,
                };
            }
        }

        if (!window.EtherTestEnvironment) {
            it.skip('defaults to true, navigates to destination in URL');
            it.skip('defaults to true, navigates to destination in URL, respecting `basePath` config option');
        } else {
            it('defaults to true, navigates to destination in URL', () => {
                let pathname = '/first';
                let effectivePath = 'first';
                let oldLocation = window.location;
                window.location = {pathname};
                let rootApp = new MyRootApp({});
                rootApp.start();
                expect(rootApp.getCurrentTransition()).to.be.null;
                window.fire('load');
                let transition = rootApp.getCurrentTransition();
                expect(transition).to.be.ok;
                expect(transition.url).to.equal(effectivePath);
                expect(transition.state).to.equal('started');
                window.location = oldLocation;
                window.clearListeners();
            });

            it('defaults to true, navigates to destination in URL, respecting `basePath` config option', () => {
                let pathname = '/basepath/first';
                let effectivePath = 'first';
                let oldLocation = window.location;
                window.location = {pathname};
                let rootApp = new MyRootApp({basePath: '/basepath'});
                rootApp.start();
                expect(rootApp.getCurrentTransition()).to.be.null;
                window.fire('load');
                let transition = rootApp.getCurrentTransition();
                expect(transition).to.be.ok;
                expect(transition.url).to.equal(effectivePath);
                expect(transition.state).to.equal('started');
                window.location = oldLocation;
                window.clearListeners();
            });
        }
    });
});
<commit_msg>Remove some unnecessary tests<commit_after>import RootApp from '../../src/classes/root-app';
import Route from '../../src/classes/route';

class TestRoute extends Route {
    expectedOutlets() {
        return [];
    }
}

describe('RootApp Options', () => {
    describe('stripTrailingSlash', () => {
        class MyRootApp extends RootApp {
            expectedOutlets() {
                return [];
            }
            mount() {
                return {
                    'hasSlash/' : TestRoute,
                };
            }
        }

        it('defaults to not stripping the trailing slash', done => {
            let dest = '/hasSlash/';
            let rootApp = new MyRootApp({});
            rootApp.navigate(dest).then(() => {
                done();
            }).catch(() => {
                done(new Error('expected the trailing slash to be kept'));
            });
        });

        it('strips the trailing slash on URL passed to navigate', done => {
            let dest = '/hasSlash/';
            let rootApp = new MyRootApp({stripTrailingSlash: true});
            rootApp.navigate(dest).then(() => {
                done(new Error('expected the trailing slash to be stripped, giving 404'));
            }).catch(err => {
                expect(err).to.be.instanceof(Error);
                err.message.should.equal(`404 for path: "${dest}".`);
                done();
            });
        });
    });

    describe('addTrailingSlash', () => {
        class MyRootApp extends RootApp {
            expectedOutlets() {
                return [];
            }
            mount() {
                return {
                    'hasSlash/' : TestRoute,
                };
            }
        }

        it('defaults to not adding the trailing slash', done => {
            let dest = '/hasSlash';
            let rootApp = new MyRootApp({});
            rootApp.navigate(dest).then(() => {
                done(new Error('expected the trailing slash to not be added'));
            }).catch(err => {
                expect(err).to.be.instanceof(Error);
                err.message.should.equal(`404 for path: "${dest}".`);
                done();
            });
        });

        it('adds the trailing slash on URL passed to navigate if it is missing', done => {
            let dest = '/hasSlash';
            let rootApp = new MyRootApp({addTrailingSlash: true});
            rootApp.navigate(dest).then(() => {
                done();
            }).catch(() => {
                done(new Error('expected the trailing slash to be added, making navigation a success'));
            });
        });

        it('overrides stripTrailingSlash option', done => {
            let dest = '/hasSlash/';
            let rootApp = new MyRootApp({
                stripTrailingSlash: true,
                addTrailingSlash: true,
            });
            rootApp.navigate(dest).then(() => {
                done();
            }).catch(() => {
                done(new Error('expected the trailing slash to be added/kept, making navigation a success'));
            });
        });
    });

    describe('Transition Queueing', () => {
        class MyRootApp extends RootApp {
            expectedOutlets() {
                return [];
            }
            mount() {
                return {
                    'first' : TestRoute,
                    'second' : TestRoute,
                };
            }
        }

        it('queues transitions', done => {
            let rootApp = new MyRootApp({});
            let firstTransition, secondTransition;

            expect(rootApp.getCurrentTransition()).to.be.null;
            expect(rootApp._transitionQueue).to.be.an('array');
            expect(rootApp._transitionQueue).to.be.empty;

            rootApp.navigate('first?x=1').then(() => {
                expect(firstTransition).to.be.ok;
                expect(firstTransition.state).to.equal('succeeded');
            }).catch(() => {
                done(new Error('expected first navigation to succeed'));
            });

            firstTransition = rootApp.getCurrentTransition();
            expect(firstTransition.url).to.equal('first?x=1');
            expect(firstTransition.state).to.equal('started');
            expect(rootApp._transitionQueue).to.be.empty;

            rootApp.navigate('second').then(() => {
                expect(firstTransition).to.be.ok;
                expect(firstTransition.state).to.equal('succeeded');
                expect(rootApp.getCurrentTransition()).to.equal(secondTransition);
                expect(secondTransition.state).to.equal('succeeded');
                done();
            }).catch(() => {
                done(new Error('expected second navigation to succeed'));
            });

            expect(rootApp._transitionQueue).to.have.length(1);
            secondTransition = rootApp._transitionQueue[0];
            expect(secondTransition.url).to.equal('second');
            expect(secondTransition.state).to.equal('pending');
            expect(secondTransition).to.not.equal(firstTransition);
        });

        it('continues transition queue even if some fail', done => {
            let rootApp = new MyRootApp({});
            let firstTransition, secondTransition;

            expect(rootApp.getCurrentTransition()).to.be.null;
            expect(rootApp._transitionQueue).to.be.an('array');
            expect(rootApp._transitionQueue).to.be.empty;

            rootApp.navigate('non-existent-url').then(() => {
                done(new Error('expected first navigation to fail'));
            }).catch(() => {
                expect(firstTransition).to.be.ok;
                expect(firstTransition.state).to.equal('failed');
            });

            firstTransition = rootApp.getCurrentTransition();
            expect(firstTransition.url).to.equal('non-existent-url');
            expect(firstTransition.state).to.equal('started');
            expect(rootApp._transitionQueue).to.be.empty;

            rootApp.navigate('second').then(() => {
                expect(firstTransition).to.be.ok;
                expect(firstTransition.state).to.equal('failed');
                expect(rootApp.getCurrentTransition()).to.equal(secondTransition);
                expect(secondTransition.state).to.equal('succeeded');
                done();
            }).catch(() => {
                done(new Error('expected second navigation to succeed'));
            });

            expect(rootApp._transitionQueue).to.have.length(1);
            secondTransition = rootApp._transitionQueue[0];
            expect(secondTransition.url).to.equal('second');
            expect(secondTransition.state).to.equal('pending');
            expect(secondTransition).to.not.equal(firstTransition);
        });
    });
});
<|endoftext|>


<commit_before>var HTMLLinkElement = function

  // http://w3c.github.io/webcomponents/spec/imports/#h-interface-import

(tag) {

  var
    proxy = {}

  , link = document.querySelector // use CSS :any ?
      ('link[href*='+tag+'][rel=import]')

  , register = function (event, handler) { return (HTMLImports && !!! HTMLImports.useNative)
        ? HTMLImports.whenReady
            ( function (_) { return handler ({ target: link }); } ) // eww

        : link.addEventListener
            (event, handler); }

    Object
      .defineProperties (proxy, {

        'addEventListener': {
          writable: false,

          value: function (event, handler) {
            !!! link
              ? handler  ({ target: proxy })
              : register (event, handler)
          }
        }

// TODO: definition for onerror
//    , 'onerror':
//        { set (handler) {} }
      })

  return proxy
}

var TokenList = function (node) {

  this
    .sift (node)
    .map(this.tokenize, this)
};

TokenList.prototype.tokenize = function (node) {
    var this$1 = this;

  var
    insert = function (node) { return function (symbol) { return (this$1 [symbol] = this$1 [symbol] || []).push (node); }; }

  void (node.text = node.textContent)
    .match (/([^{]*?)(\w|#)(?=\})/g)
    .map (insert (node))
};

TokenList.prototype.sift = function (node) {

  var
    nodes = []
  , expression = /{(\w+|#)}/

  , visit = function (node) { return node.nodeType === Node.TEXT_NODE
        ? TEXT_NODE (node)
        : ELEMENT_NODE (node.attributes)
      && NodeFilter.FILTER_REJECT; } // We don't need 'em

  , TEXT_NODE = function (node) { return expression.test (node.textContent)
      && nodes.push (node); }

  , ELEMENT_NODE = function (attrs) { return Array
        .from (attrs)
        .map(function (attr) { return expression.test (attr.value) && nodes.push (attr); }); }

  , walker =
      document.createNodeIterator
        (node, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, visit)
        // by default breaks on template YAY! 🎉

  while (walker.nextNode ()) { 0 } // Walk all nodes and do nothing.

  return nodes
};

TokenList.prototype.bind = function (context) {
    var this$1 = this;

  var
    keys = Object.keys (this)

  , reset = function (symbol) { return this$1 [symbol].map
        (function (node) { return (node.textContent = node.text) && symbol; }); }

  , replace =
      function (symbol, token) {
            if ( token === void 0 ) token = '{'+symbol+'}';

            return function (item) { return (item.textContent = item.textContent.replace (token, context [symbol])); };
    }

  keys.map (reset)

  for (var symbol$1 in this$1)
    { this$1 [symbol$1]
      .map (replace (symbol$1)) }
};

// INTERESTING! Converting `Template` to a class increases size by ~16 octets

var Template = HTMLTemplateElement = function (name) {

  // create shallow clone using `.getOwnPropertyDescriptors`
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors#Examples
  // https://docs.microsoft.com/en-us/scripting/javascript/reference/object-getownpropertydescriptor-function-javascript
  // NO IE SUPPORT!!!!
  return Object.assign
    (document.querySelector ('template[name='+name+']'), { bind: bind } )

  function bind (context) {

    var
      html     = ''
    , template = this.innerHTML
    , contexts =
        (ref = []).concat.apply ( ref, [context] )
        // https://dom.spec.whatwg.org/#converting-nodes-into-a-node

    , keys =
        Object
          .keys (contexts [0] || [])    // memoize keys
          .concat (['#', 'self']) // add helper keys

    , tokens   = keys.map (function (key) { return '{'+key+'}'; }) // memoize tokens
    , fragment = document.createElement ('template')

    , deposit = function (context, index) {
        var clone = template

        context = (typeof context  === 'object')
          ? context : { self: context }

        context ['#'] = index

        for (var i=0; i<tokens.length; i++)
          { clone = clone
            .split (tokens [i])
            .join  (context [keys [i]]) }

        return clone
      }

    void (this.dependents || [])
      .map (function (dependent) { return dependent.remove (); })

    for (var i=0, final = ''; i<contexts.length; i++)
      { html += deposit (contexts [i], i) }

    fragment.innerHTML = html

    this.dependents = Array.from // non-live
      (fragment.content.childNodes)

    (ref$1 = this).after.apply ( ref$1, this.dependents )
    var ref;
    var ref$1;
  }
}
var EventTarget = function (HTMLElement) { return ((function (HTMLElement) {
    function anonymous () {
      HTMLElement.apply(this, arguments);
    }

    if ( HTMLElement ) anonymous.__proto__ = HTMLElement;
    anonymous.prototype = Object.create( HTMLElement && HTMLElement.prototype );
    anonymous.prototype.constructor = anonymous;

    anonymous.prototype.on = function ( event, handler ) {

    this.addEventListener
      (event, this.renderable (handler))
  };

  anonymous.prototype.renderable = function ( handler ) {
    var this$1 = this;

    return function (event, render) {
        if ( render === void 0 ) render = true;

        return (event.prevent = function (_) { return (render = false) && event.preventDefault (); })

      && handler.call (this$1, event) !== false // for `return false`

      && render && this$1.render ();
    } // check render availability
  };

    return anonymous;
  }(HTMLElement))); }

var ParentNode = function (Element) { return ((function (Element) {
    function anonymous () {
      Element.apply(this, arguments);
    }

    if ( Element ) anonymous.__proto__ = Element;
    anonymous.prototype = Object.create( Element && Element.prototype );
    anonymous.prototype.constructor = anonymous;

    anonymous.prototype.selectAll = function ( fragments ) {
    var tokens = [], len = arguments.length - 1;
    while ( len-- > 0 ) tokens[ len ] = arguments[ len + 1 ];

    fragments =
      (ref = []).concat.apply ( ref, [fragments] )

    var
      zip = function (selector, token) { return selector + token + fragments.shift (); }

    return Array
      .from
        (this.querySelectorAll
          (tokens.reduce (zip, fragments.shift ())))
    var ref;
  };

  anonymous.prototype.select = function ()
    // watch out for clobbering `HTMLInputElement.select ()`
    // https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/select
    {
    var selector = [], len = arguments.length;
    while ( len-- ) selector[ len ] = arguments[ len ];
 return (ref = this).selectAll.apply ( ref, selector ) [0]
    var ref; };

    return anonymous;
  }(Element))); }

//function comb
//  // ElementTraversal interface
//  // https://www.w3.org/TR/ElementTraversal/#interface-elementTraversal
//
//(parent) {
//  if (parent.hasChildNodes())
//    for (let node = parent.firstChild; node; node = node.nextSibling)
//      comb (node)
//}

var GlobalEventHandlers = function (Element) { return ((function (Element) {
    function anonymous () {
      Element.apply(this, arguments);
    }

    if ( Element ) anonymous.__proto__ = Element;
    anonymous.prototype = Object.create( Element && Element.prototype );
    anonymous.prototype.constructor = anonymous;

    anonymous.prototype.onconnect = function (event, document) {

    (document = event.target.import)
      && this.mirror (document.querySelector ('template'))

    Element.prototype.onconnect
      && Element.prototype.onconnect.call (this)

    this.tokens = new TokenList (this)
    this.render ()
  };

  // Reflection - https://en.wikipedia.org/wiki/Reflection_(computer_programming)
  // Type Introspection - https://en.wikipedia.org/wiki/Type_introspection
  //
  // In computing, type introspection is the ability of a program
  // to examine the type or properties of an object at runtime.
  // Some programming languages possess this capability.
  //
  // Introspection should not be confused with reflection,
  // which goes a step further and is the ability for a program to manipulate the values,
  // meta-data, properties and/or functions of an object at runtime.

  anonymous.prototype.reflect = function (handler, event) {
    ( event = ( handler.match (/^on(.+)$/) || [] ) [1] )

    && Object.keys // ensure W3C on event
     ( HTMLElement.prototype )
       .includes ( handler )

    && this.on (event, this [handler])
  };

  anonymous.prototype.register = function (node) {
    var this$1 = this;

    var
      register = function (event, handler) { return (handler = /{\s*(\w+)\s*}/.exec (node [event]))

        && ( handler = this$1 [ (handler || []) [1] ] )
        && ( node [event] = this$1.renderable (handler) ); }

    Array
      .from (node.attributes)
      .map (function (attr) { return attr.name; })
      .filter (function (name) { return /^on/.test (name); })
      .map (register)
  };

    return anonymous;
  }(Element))); }

var Component = function (HTMLElement) { return ( (function (superclass) {
    function anonymous () {
  var this$1 = this;
 superclass.call (this)

    var
      descriptions =
        Object.getOwnPropertyDescriptors
          (HTMLElement.prototype)

    , bind = function (key) { return 'function' === typeof descriptions [key].value
        && (this$1 [key] = this$1 [key].bind (this$1)); }

    Object
      .keys (descriptions)
      .map (bind)

    Object
      .getOwnPropertyNames (HTMLElement.prototype)
      // POTENTIAL REDUNDANCY
      // Aren't `on` events set up in `.bind` on 20?
      // If so we are `.bind`ing to `this` on two iterations
      // of the same function
      .map (this.reflect, this)

    this.context = {}
    this.initialize && this.initialize ()
  }

    if ( superclass ) anonymous.__proto__ = superclass;
    anonymous.prototype = Object.create( superclass && superclass.prototype );
    anonymous.prototype.constructor = anonymous;

  anonymous.prototype.connectedCallback = function () {

    superclass.prototype.connectedCallback
      && superclass.prototype.connectedCallback.call (this)

    HTMLLinkElement
      (this.tagName.toLowerCase ())
        .addEventListener ('load', this.onconnect.bind (this))
  };

  anonymous.prototype.render = function () {
    var this$1 = this;

    this.tokens.bind (this)

    Array
      .from
        (this.selectAll ('template[name]'))

      .map
        (function (template) { return template.getAttribute ('name'); })

      .map
        (function (name) { return (new Template (name)).bind (this$1 [name]); })

    Array
      .from (this.selectAll ('*'))

      .concat ([this])

      .map (this.register, this)

    superclass.prototype.onidle && superclass.prototype.onidle.call (this)
  };

  anonymous.prototype.mirror = function (template, insert) {
    var this$1 = this;

    template = template.cloneNode (true)

    insert = function (replacement, name, slot) { return (name = replacement.getAttribute ('slot')) &&

      (slot = template.content.querySelector ('slot[name='+name+']'))
         // prefer to use replaceWith however support is sparse
         // https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/replaceWith
         // using `Node.parentNode` - https://developer.mozilla.org/en-US/docs/Web/API/Node/parentNode
         // & `Node.replaceChid` - https://developer.mozilla.org/en-US/docs/Web/API/Node/replaceChild
         // as is defined in (ancient) W3C DOM Level 1,2,3
         .parentNode
         .replaceChild (replacement, slot); }

    for (var i = 0, list = this$1.selectAll ('[slot]'); i < list.length; i += 1)
      {
      var replacement = list[i];

      insert (replacement)
    }

    Array
      .from (template.attributes)

      // skip swapping attribute if setting exists
      .filter (function (attr) { return !!! this$1.attributes [attr.name]; })

      .map  (function (attr) { return this$1.setAttribute (attr.name, attr.value); })

    this.innerHTML = template.innerHTML
  };

    return anonymous;
  }(( EventTarget ( ParentNode ( GlobalEventHandlers ( HTMLElement ))))))); }

var ElementPrototype = window.Element.prototype // see bottom of this file

var Element = function (tag) { return function (Element) { return (ref = window.customElements).define.apply
        ( ref, (ref$1 = []).concat.apply ( ref$1, [tag]).concat( [Component (Element)] ))
        var ref;
        var ref$1;; }; }

// Assign `window.Element.prototype` in case of feature checking on `Element`
Element.prototype = ElementPrototype
  // http://2ality.com/2013/09/window.html
  // http://tobyho.com/2013/03/13/window-prop-vs-global-var
  // https://github.com/webcomponents/webcomponentsjs/blob/master/webcomponents-es5-loader.js#L19

<commit_msg>:muscle: bump TRANSPILED distribution dist/snuggsi.js<commit_after>var HTMLLinkElement = function

  // http://w3c.github.io/webcomponents/spec/imports/#h-interface-import

(tag) {

  var
    proxy = {}

  , link = document.querySelector // use CSS :any ?
      ('link[href*='+tag+'][rel=import]')

  , register = function (event, handler) { return (HTMLImports && !!! HTMLImports.useNative)
        ? HTMLImports.whenReady
            ( function (_) { return handler ({ target: link }); } ) // eww

        : link.addEventListener
            (event, handler); }

    Object
      .defineProperties (proxy, {

        'addEventListener': {
          writable: false,

          value: function (event, handler) {
            !!! link
              ? handler  ({ target: proxy })
              : register (event, handler)
          }
        }

// TODO: definition for onerror
//    , 'onerror':
//        { set (handler) {} }
      })

  return proxy
}

var TokenList = function (node) {

  this
    .sift (node)
    .map(this.tokenize, this)
};

TokenList.prototype.tokenize = function (node) {
    var this$1 = this;

  var
    insert = function (node) { return function (symbol) { return (this$1 [symbol] = this$1 [symbol] || []).push (node); }; }

  void (node.text = node.textContent)
    .match (/([^{]*?)(\w|#)(?=\})/g)
    .map (insert (node))
};

TokenList.prototype.sift = function (node) {

  var
    nodes = []
  , expression = /{(\w+|#)}/

  , visit = function (node) { return node.nodeType === Node.TEXT_NODE
        ? TEXT_NODE (node)
        : ELEMENT_NODE (node.attributes)
      && NodeFilter.FILTER_REJECT; } // We don't need 'em

  , TEXT_NODE = function (node) { return expression.test (node.textContent)
      && nodes.push (node); }

  , ELEMENT_NODE = function (attrs) { return Array
        .from (attrs)
        .map(function (attr) { return expression.test (attr.value) && nodes.push (attr); }); }

  , walker =
      document.createNodeIterator
        (node, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, visit)
        // by default breaks on template YAY! 🎉

  while (walker.nextNode ()) { 0 } // Walk all nodes and do nothing.

  return nodes
};

TokenList.prototype.bind = function (context) {
    var this$1 = this;

  var
    keys = Object.keys (this)

  , reset = function (symbol) { return this$1 [symbol].map
        (function (node) { return (node.textContent = node.text) && symbol; }); }

  , replace =
      function (symbol, token) {
            if ( token === void 0 ) token = '{'+symbol+'}';

            return function (item) { return (item.textContent = item.textContent.replace (token, context [symbol])); };
    }

  keys.map (reset)

  for (var symbol$1 in this$1)
    { this$1 [symbol$1]
      .map (replace (symbol$1)) }
};

// INTERESTING! Converting `Template` to a class increases size by ~16 octets

var Template = HTMLTemplateElement = function (template) {

  template =
    (typeof template == 'string')
      ? document.querySelector ('template[name='+template+']')
      : template

  // create shallow clone using `.getOwnPropertyDescriptors`
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors#Examples
  // https://docs.microsoft.com/en-us/scripting/javascript/reference/object-getownpropertydescriptor-function-javascript
  // NO IE SUPPORT!!!!
  return Object.assign (template, { bind: bind } )

  function bind (context) {

    var
      html     = ''
    , template = this.innerHTML
    , contexts =
        (ref = []).concat.apply ( ref, [context] )
        // https://dom.spec.whatwg.org/#converting-nodes-into-a-node

    , keys =
        Object
          .keys (contexts [0] || [])    // memoize keys
          .concat (['#', 'self']) // add helper keys

    , tokens   = keys.map (function (key) { return '{'+key+'}'; }) // memoize tokens
    , fragment = document.createElement ('template')

    , deposit = function (context, index) {
        var clone = template

        context = (typeof context  === 'object')
          ? context : { self: context }

        context ['#'] = index

        for (var i=0; i<tokens.length; i++)
          { clone = clone
            .split (tokens [i])
            .join  (context [keys [i]]) }

        return clone
      }

    void (this.dependents || [])
      .map (function (dependent) { return dependent.remove (); })

    for (var i=0, final = ''; i<contexts.length; i++)
      { html += deposit (contexts [i], i) }

    fragment.innerHTML = html

    this.dependents = Array.from // non-live
      (fragment.content.childNodes)

    (ref$1 = this).after.apply ( ref$1, this.dependents )
    var ref;
    var ref$1;
  }
}
var EventTarget = function (HTMLElement) { return ((function (HTMLElement) {
    function anonymous () {
      HTMLElement.apply(this, arguments);
    }

    if ( HTMLElement ) anonymous.__proto__ = HTMLElement;
    anonymous.prototype = Object.create( HTMLElement && HTMLElement.prototype );
    anonymous.prototype.constructor = anonymous;

    anonymous.prototype.on = function ( event, handler ) {

    this.addEventListener
      (event, this.renderable (handler))
  };

  anonymous.prototype.renderable = function ( handler ) {
    var this$1 = this;

    return function (event, render) {
        if ( render === void 0 ) render = true;

        return (event.prevent = function (_) { return (render = false) && event.preventDefault (); })

      && handler.call (this$1, event) !== false // for `return false`

      && render && this$1.render ();
    } // check render availability
  };

    return anonymous;
  }(HTMLElement))); }

var ParentNode = function (Element) { return ((function (Element) {
    function anonymous () {
      Element.apply(this, arguments);
    }

    if ( Element ) anonymous.__proto__ = Element;
    anonymous.prototype = Object.create( Element && Element.prototype );
    anonymous.prototype.constructor = anonymous;

    anonymous.prototype.selectAll = function ( fragments ) {
    var tokens = [], len = arguments.length - 1;
    while ( len-- > 0 ) tokens[ len ] = arguments[ len + 1 ];

    fragments =
      (ref = []).concat.apply ( ref, [fragments] )

    var
      zip = function (selector, token) { return selector + token + fragments.shift (); }

    return Array
      .from
        (this.querySelectorAll
          (tokens.reduce (zip, fragments.shift ())))
    var ref;
  };

  anonymous.prototype.select = function ()
    // watch out for clobbering `HTMLInputElement.select ()`
    // https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/select
    {
    var selector = [], len = arguments.length;
    while ( len-- ) selector[ len ] = arguments[ len ];
 return (ref = this).selectAll.apply ( ref, selector ) [0]
    var ref; };

    return anonymous;
  }(Element))); }

//function comb
//  // ElementTraversal interface
//  // https://www.w3.org/TR/ElementTraversal/#interface-elementTraversal
//
//(parent) {
//  if (parent.hasChildNodes())
//    for (let node = parent.firstChild; node; node = node.nextSibling)
//      comb (node)
//}

var GlobalEventHandlers = function (Element) { return ((function (Element) {
    function anonymous () {
      Element.apply(this, arguments);
    }

    if ( Element ) anonymous.__proto__ = Element;
    anonymous.prototype = Object.create( Element && Element.prototype );
    anonymous.prototype.constructor = anonymous;

    anonymous.prototype.onconnect = function (event, document) {

    (document = event.target.import)
      && this.mirror (document.querySelector ('template'))

    Element.prototype.onconnect
      && Element.prototype.onconnect.call (this)

    this.tokens = new TokenList (this)
    this.render ()
  };

  // Reflection - https://en.wikipedia.org/wiki/Reflection_(computer_programming)
  // Type Introspection - https://en.wikipedia.org/wiki/Type_introspection
  //
  // In computing, type introspection is the ability of a program
  // to examine the type or properties of an object at runtime.
  // Some programming languages possess this capability.
  //
  // Introspection should not be confused with reflection,
  // which goes a step further and is the ability for a program to manipulate the values,
  // meta-data, properties and/or functions of an object at runtime.

  anonymous.prototype.reflect = function (handler, event) {
    ( event = ( handler.match (/^on(.+)$/) || [] ) [1] )

    && Object.keys // ensure W3C on event
     ( HTMLElement.prototype )
       .includes ( handler )

    && this.on (event, this [handler])
  };

  anonymous.prototype.register = function (node) {
    var this$1 = this;

    var
      register = function (event, handler) { return (handler = /{\s*(\w+)\s*}/.exec (node [event]))

        && ( handler = this$1 [ (handler || []) [1] ] )
        && ( node [event] = this$1.renderable (handler) ); }

    Array
      .from (node.attributes)
      .map (function (attr) { return attr.name; })
      .filter (function (name) { return /^on/.test (name); })
      .map (register)
  };

    return anonymous;
  }(Element))); }

var Component = function (HTMLElement) { return ( (function (superclass) {
    function anonymous () {
  var this$1 = this;
 superclass.call (this)

    var
      descriptions =
        Object.getOwnPropertyDescriptors
          (HTMLElement.prototype)

    , bind = function (key) { return 'function' === typeof descriptions [key].value
        && (this$1 [key] = this$1 [key].bind (this$1)); }

    Object
      .keys (descriptions)
      .map (bind)

    Object
      .getOwnPropertyNames (HTMLElement.prototype)
      // POTENTIAL REDUNDANCY
      // Aren't `on` events set up in `.bind` on 20?
      // If so we are `.bind`ing to `this` on two iterations
      // of the same function
      .map (this.reflect, this)

    this.context = {}
    this.initialize && this.initialize ()
  }

    if ( superclass ) anonymous.__proto__ = superclass;
    anonymous.prototype = Object.create( superclass && superclass.prototype );
    anonymous.prototype.constructor = anonymous;

  anonymous.prototype.connectedCallback = function () {

    superclass.prototype.connectedCallback
      && superclass.prototype.connectedCallback.call (this)

    HTMLLinkElement
      (this.tagName.toLowerCase ())
        .addEventListener ('load', this.onconnect.bind (this))
  };

  anonymous.prototype.render = function () {
    var this$1 = this;

    this.tokens.bind (this)

    Array
      .from
        (this.selectAll ('template[name]'))

      .map
        (function (template) { return template.getAttribute ('name'); })

      .map
        (function (name) { return (new Template (name)).bind (this$1 [name]); })

    Array
      .from (this.selectAll ('*'))

      .concat ([this])

      .map (this.register, this)

    superclass.prototype.onidle && superclass.prototype.onidle.call (this)
  };

  anonymous.prototype.mirror = function (template, insert) {
    var this$1 = this;

    template = template.cloneNode (true)

    insert = function (replacement, name, slot) { return (name = replacement.getAttribute ('slot')) &&

      (slot = template.content.querySelector ('slot[name='+name+']'))
         // prefer to use replaceWith however support is sparse
         // https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/replaceWith
         // using `Node.parentNode` - https://developer.mozilla.org/en-US/docs/Web/API/Node/parentNode
         // & `Node.replaceChid` - https://developer.mozilla.org/en-US/docs/Web/API/Node/replaceChild
         // as is defined in (ancient) W3C DOM Level 1,2,3
         .parentNode
         .replaceChild (replacement, slot); }

    for (var i = 0, list = this$1.selectAll ('[slot]'); i < list.length; i += 1)
      {
      var replacement = list[i];

      insert (replacement)
    }

    Array
      .from (template.attributes)

      // skip swapping attribute if setting exists
      .filter (function (attr) { return !!! this$1.attributes [attr.name]; })

      .map  (function (attr) { return this$1.setAttribute (attr.name, attr.value); })

    this.innerHTML = template.innerHTML
  };

    return anonymous;
  }(( EventTarget ( ParentNode ( GlobalEventHandlers ( HTMLElement ))))))); }

var ElementPrototype = window.Element.prototype // see bottom of this file

var Element = function (tag) { return function (Element) { return (ref = window.customElements).define.apply
        ( ref, (ref$1 = []).concat.apply ( ref$1, [tag]).concat( [Component (Element)] ))
        var ref;
        var ref$1;; }; }

// Assign `window.Element.prototype` in case of feature checking on `Element`
Element.prototype = ElementPrototype
  // http://2ality.com/2013/09/window.html
  // http://tobyho.com/2013/03/13/window-prop-vs-global-var
  // https://github.com/webcomponents/webcomponentsjs/blob/master/webcomponents-es5-loader.js#L19

<|endoftext|>