From c05d56c448ee5937dd88cc6756ad885ab1bd3cb0 Mon Sep 17 00:00:00 2001
From: Berkeley Martinez <Berkeley@robotie.com>
Date: Tue, 7 Jul 2015 22:25:10 -0700
Subject: [PATCH] add eslint use npm scripts for bundling remove gulp refactor
 folder structor major refactor

---
 .babelrc                       |   3 +
 .eslintignore                  |   2 +
 .eslintrc                      | 233 +++++++++++
 .gitignore                     |   2 +
 banner.js                      |  11 +
 bower.json                     |  32 --
 dist/react-video.css           | 104 -----
 dist/react-video.js            | 334 ----------------
 dist/react-video.min.css       |   8 -
 dist/react-video.min.js        |   8 -
 docs/css/github.css            | 127 ------
 docs/css/react-video.min.css   |   8 -
 docs/css/style.css             | 179 ---------
 docs/images/btn-vimeo.png      | Bin 7960 -> 0 bytes
 docs/images/btn-youtube.png    | Bin 3836 -> 0 bytes
 docs/images/cover.png          | Bin 11610 -> 0 bytes
 docs/index.html                | 137 -------
 docs/js/app.js                 |  28 --
 docs/js/highlight.pack.js      |   1 -
 docs/js/react-video.min.js     |   8 -
 example/index.html             |  22 +-
 gulpfile.js                    |  85 ----
 lib/Vimeo.css                  |  97 +++++
 lib/Vimeo.min.css              |   1 +
 lib/Vimeo.styl                 | 112 ++++++
 lib/components/play-button.jsx |  16 -
 lib/components/spinner.jsx     |  14 -
 lib/react-video.jsx            | 135 -------
 lib/react-video.scss           | 112 ------
 lib/react-video.styl           | 112 ------
 lib/umd/ReactVimeo.js          | 884 +++++++++++++++++++++++++++++++++++++++++
 lib/umd/ReactVimeo.min.js      |   8 +
 package.json                   |  62 ++-
 src/Play-Button.jsx            |  26 ++
 src/Spinner.jsx                |  21 +
 src/Vimeo.jsx                  | 139 +++++++
 src/ajax.js                    |  42 ++
 utils/ajax.js                  |  43 --
 utils/banner.js                |  13 -
 utils/classSet.js              |  13 -
 utils/jsx-preprocessor.js      |  12 -
 webpack.config.js              |  54 +--
 42 files changed, 1641 insertions(+), 1607 deletions(-)
 create mode 100644 .babelrc
 create mode 100644 .eslintignore
 create mode 100644 .eslintrc
 create mode 100644 banner.js
 delete mode 100644 bower.json
 delete mode 100644 dist/react-video.css
 delete mode 100644 dist/react-video.js
 delete mode 100644 dist/react-video.min.css
 delete mode 100644 dist/react-video.min.js
 delete mode 100644 docs/css/github.css
 delete mode 100644 docs/css/react-video.min.css
 delete mode 100644 docs/css/style.css
 delete mode 100644 docs/images/btn-vimeo.png
 delete mode 100644 docs/images/btn-youtube.png
 delete mode 100644 docs/images/cover.png
 delete mode 100644 docs/index.html
 delete mode 100644 docs/js/app.js
 delete mode 100644 docs/js/highlight.pack.js
 delete mode 100644 docs/js/react-video.min.js
 delete mode 100644 gulpfile.js
 create mode 100644 lib/Vimeo.css
 create mode 100644 lib/Vimeo.min.css
 create mode 100644 lib/Vimeo.styl
 delete mode 100644 lib/components/play-button.jsx
 delete mode 100644 lib/components/spinner.jsx
 delete mode 100644 lib/react-video.jsx
 delete mode 100644 lib/react-video.scss
 delete mode 100644 lib/react-video.styl
 create mode 100644 lib/umd/ReactVimeo.js
 create mode 100644 lib/umd/ReactVimeo.min.js
 create mode 100644 src/Play-Button.jsx
 create mode 100644 src/Spinner.jsx
 create mode 100644 src/Vimeo.jsx
 create mode 100644 src/ajax.js
 delete mode 100644 utils/ajax.js
 delete mode 100644 utils/banner.js
 delete mode 100644 utils/classSet.js
 delete mode 100644 utils/jsx-preprocessor.js

diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..12606a3
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,3 @@
+{
+    "stage": 0
+}
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..c56fc7a
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,2 @@
+lib/
+example/
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..fcd4ac0
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,233 @@
+{
+  "env": {
+    "browser": true,
+    "mocha": true,
+    "node": true
+  },
+  "globals": {
+    "window": true
+  },
+  "parser": "babel-eslint",
+  "plugins": [
+    "react"
+  ],
+  "rules": {
+    "indent": [2, 2, { "indentSwitchCase": true }],
+    "no-comma-dangle": 2,
+    "no-cond-assign": 2,
+    "no-console": 0,
+    "no-constant-condition": 2,
+    "no-control-regex": 2,
+    "no-debugger": 2,
+    "no-dupe-keys": 2,
+    "no-empty": 2,
+    "no-empty-class": 2,
+    "no-ex-assign": 2,
+    "no-extra-boolean-cast": 2,
+    "no-extra-parens": 0,
+    "no-extra-semi": 2,
+    "no-func-assign": 2,
+    "no-inner-declarations": 2,
+    "no-invalid-regexp": 2,
+    "no-irregular-whitespace": 2,
+    "no-negated-in-lhs": 2,
+    "no-obj-calls": 2,
+    "no-regex-spaces": 2,
+    "no-reserved-keys": 0,
+    "no-sparse-arrays": 2,
+    "no-unreachable": 2,
+    "use-isnan": 2,
+    "valid-jsdoc": 2,
+    "valid-typeof": 2,
+
+    "block-scoped-var": 0,
+    "complexity": 0,
+    "consistent-return": 0,
+    "curly": 2,
+    "default-case": 1,
+    "dot-notation": 0,
+    "eqeqeq": 1,
+    "guard-for-in": 1,
+    "no-alert": 1,
+    "no-caller": 2,
+    "no-div-regex": 2,
+    "no-else-return": 0,
+    "no-empty-label": 2,
+    "no-eq-null": 1,
+    "no-eval": 2,
+    "no-extend-native": 2,
+    "no-extra-bind": 2,
+    "no-fallthrough": 2,
+    "no-floating-decimal": 2,
+    "no-implied-eval": 2,
+    "no-iterator": 2,
+    "no-labels": 2,
+    "no-lone-blocks": 2,
+    "no-loop-func": 0,
+    "no-multi-spaces": 1,
+    "no-multi-str": 2,
+    "no-native-reassign": 2,
+    "no-new": 2,
+    "no-new-func": 2,
+    "no-new-wrappers": 2,
+    "no-octal": 2,
+    "no-octal-escape": 2,
+    "no-process-env": 0,
+    "no-proto": 2,
+    "no-redeclare": 1,
+    "no-return-assign": 2,
+    "no-script-url": 2,
+    "no-self-compare": 2,
+    "no-sequences": 2,
+    "no-unused-expressions": 2,
+    "no-void": 1,
+    "no-warning-comments": [
+        1,
+        {
+            "terms": [
+                "fixme"
+            ],
+            "location": "start"
+        }
+    ],
+    "no-with": 2,
+    "radix": 2,
+    "vars-on-top": 0,
+    "wrap-iife": [2, "any"],
+    "yoda": 0,
+
+    "strict": 0,
+
+    "no-catch-shadow": 2,
+    "no-delete-var": 2,
+    "no-label-var": 2,
+    "no-shadow": 0,
+    "no-shadow-restricted-names": 2,
+    "no-undef": 2,
+    "no-undef-init": 2,
+    "no-undefined": 1,
+    "no-unused-vars": 2,
+    "no-use-before-define": 0,
+
+    "handle-callback-err": 2,
+    "no-mixed-requires": 0,
+    "no-new-require": 2,
+    "no-path-concat": 2,
+    "no-process-exit": 2,
+    "no-restricted-modules": 0,
+    "no-sync": 0,
+
+    "brace-style": [
+        2,
+        "1tbs",
+        { "allowSingleLine": true }
+    ],
+    "camelcase": 1,
+    "comma-spacing": [
+        2,
+        {
+            "before": false,
+            "after": true
+        }
+    ],
+    "comma-style": [
+        2, "last"
+    ],
+    "consistent-this": 0,
+    "eol-last": 2,
+    "func-names": 0,
+    "func-style": 0,
+    "key-spacing": [
+        2,
+        {
+          "beforeColon": false,
+          "afterColon": true
+        }
+    ],
+    "max-nested-callbacks": 0,
+    "new-cap": 0,
+    "new-parens": 2,
+    "no-array-constructor": 2,
+    "no-inline-comments": 1,
+    "no-lonely-if": 1,
+    "no-mixed-spaces-and-tabs": 2,
+    "no-multiple-empty-lines": [
+        1,
+        { "max": 2 }
+    ],
+    "no-nested-ternary": 2,
+    "no-new-object": 2,
+    "no-space-before-semi": 2,
+    "no-spaced-func": 2,
+    "no-ternary": 0,
+    "no-trailing-spaces": 1,
+    "no-underscore-dangle": 0,
+    "no-wrap-func": 2,
+    "one-var": 0,
+    "operator-assignment": 0,
+    "padded-blocks": 0,
+    "quote-props": 0,
+    "quotes": [
+        2,
+        "single",
+        "avoid-escape"
+    ],
+    "semi": [
+        2,
+        "always"
+    ],
+    "sort-vars": 0,
+    "space-after-keywords": [
+        2,
+        "always"
+    ],
+    "space-before-function-paren": [ 2, "never" ],
+    "space-before-blocks": [
+        2,
+        "always"
+    ],
+    "space-in-brackets": 0,
+    "space-in-parens": 0,
+    "space-infix-ops": 2,
+    "space-return-throw-case": 2,
+    "space-unary-ops": [
+        1,
+        {
+            "words": true,
+            "nonwords": false
+        }
+    ],
+    "spaced-line-comment": [
+        2,
+        "always",
+        { "exceptions": ["-"] }
+    ],
+    "wrap-regex": 1,
+
+    "max-depth": 0,
+    "max-len": [
+        1,
+        80,
+        2
+    ],
+    "max-params": 0,
+    "max-statements": 0,
+    "no-bitwise": 1,
+    "no-plusplus": 0,
+
+    "react/display-name": 1,
+    "react/jsx-boolean-value": 1,
+    "react/jsx-quotes": [1, "single", "avoid-escape"],
+    "react/jsx-no-undef": 1,
+    "react/jsx-sort-props": 1,
+    "react/jsx-uses-react": 1,
+    "react/jsx-uses-vars": 1,
+    "react/no-did-mount-set-state": 2,
+    "react/no-did-update-set-state": 2,
+    "react/no-multi-comp": 2,
+    "react/prop-types": 2,
+    "react/react-in-jsx-scope": 1,
+    "react/self-closing-comp": 1,
+    "react/wrap-multilines": 1
+  }
+}
diff --git a/.gitignore b/.gitignore
index 62d5da0..bc3c076 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
 *.DS_Store
 *.log
 /node_modules
+lib/*.js
+!lib/umd
diff --git a/banner.js b/banner.js
new file mode 100644
index 0000000..ef65015
--- /dev/null
+++ b/banner.js
@@ -0,0 +1,11 @@
+module.exports = require('lodash').template([
+  '/*',
+  ' * React-Vimeo - <%= pkg.description %>',
+  ' * @version v<%= pkg.version %>',
+  ' * @link <%= pkg.homepage %>',
+  ' * @license <%= pkg.license %>',
+  ' * @author <%= pkg.author.name %> (<%= pkg.author.url %>)',
+  '*/\n'
+].join('\n'), {
+  pkg: require('./package.json')
+});
diff --git a/bower.json b/bower.json
deleted file mode 100644
index 551b246..0000000
--- a/bower.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
-  "name": "react-video",
-  "version": "1.5.3",
-  "description": "React component to load video from Vimeo or Youtube across any device",
-  "homepage": "https://github.com/pedronauck/react-video",
-  "authors": [
-    "Pedro Nauck <pedronauck@gmail.com> (https://github.com/pedronauck)"
-  ],
-  "main": "dist/react-video.js",
-  "moduleType": [
-    "amd",
-    "globals",
-    "node"
-  ],
-  "keywords": [
-    "react",
-    "react-component",
-    "react-video",
-    "video",
-    "youtube",
-    "video",
-    "player"
-  ],
-  "license": "MIT",
-  "ignore": [
-    "**/.*",
-    "node_modules",
-    "bower_components",
-    "test",
-    "tests"
-  ]
-}
diff --git a/dist/react-video.css b/dist/react-video.css
deleted file mode 100644
index 5005346..0000000
--- a/dist/react-video.css
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * React Video - React component to load video from Vimeo or Youtube across any device
- * @version v1.5.3
- * @link https://github.com/pedronauck/react-video
- * @license MIT
- * @author Pedro Nauck (https://github.com/pedronauck)
-*/
-.video-image,
-.video-image:after,
-.video-embed {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-}
-.video {
-  position: relative;
-  padding-bottom: 56.25%;
-  background: #e2e2e2;
-}
-.video iframe {
-  border: 0;
-}
-.video-image {
-  background-position: center center;
-  background-size: 100% auto;
-}
-.video-image:after {
-  z-index: 1;
-  display: block;
-  content: '';
-  background: rgba(0,0,0,0.3);
-}
-.video-play-button,
-.video-loading {
-  top: 50%;
-  left: 50%;
-  transform: translateX(-50%) translateY(-50%);
-}
-.video-play-button {
-  z-index: 2;
-  position: absolute;
-  padding: 0;
-  width: 70px;
-  border: 0;
-  background: none;
-}
-.video-play-button:focus {
-  outline: none;
-}
-.video-play-button svg {
-  fill: #fff;
-  -webkit-filter: drop-shadow(0 1px 1px rgba(0,0,0,0.8));
-  filter: drop-shadow(0 1px 1px rgba(0,0,0,0.8));
-}
-.video-loading {
-  z-index: 4;
-  position: absolute;
-  width: 32px;
-  height: 32px;
-}
-.video-loading svg {
-  fill: #000;
-  transform-origin: 50% 50%;
-  -webkit-animation: spinner 0.8s infinite linear;
-  animation: spinner 0.8s infinite linear;
-}
-.video-embed iframe {
-  width: 100%;
-  height: 100%;
-}
-@-moz-keyframes spinner {
-  from {
-    transform: rotate(0deg);
-  }
-  to {
-    transform: rotate(360deg);
-  }
-}
-@-webkit-keyframes spinner {
-  from {
-    transform: rotate(0deg);
-  }
-  to {
-    transform: rotate(360deg);
-  }
-}
-@-o-keyframes spinner {
-  from {
-    transform: rotate(0deg);
-  }
-  to {
-    transform: rotate(360deg);
-  }
-}
-@keyframes spinner {
-  from {
-    transform: rotate(0deg);
-  }
-  to {
-    transform: rotate(360deg);
-  }
-}
diff --git a/dist/react-video.js b/dist/react-video.js
deleted file mode 100644
index 42ec31f..0000000
--- a/dist/react-video.js
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * React Video - React component to load video from Vimeo or Youtube across any device
- * @version v1.5.3
- * @link https://github.com/pedronauck/react-video
- * @license MIT
- * @author Pedro Nauck (https://github.com/pedronauck)
-*/
-
-(function webpackUniversalModuleDefinition(root, factory) {
-	if(typeof exports === 'object' && typeof module === 'object')
-		module.exports = factory(require("react"));
-	else if(typeof define === 'function' && define.amd)
-		define(["react"], factory);
-	else if(typeof exports === 'object')
-		exports["ReactVideo"] = factory(require("react"));
-	else
-		root["ReactVideo"] = factory(root["React"]);
-})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {
-return /******/ (function(modules) { // webpackBootstrap
-/******/ 	// The module cache
-/******/ 	var installedModules = {};
-
-/******/ 	// The require function
-/******/ 	function __webpack_require__(moduleId) {
-
-/******/ 		// Check if module is in cache
-/******/ 		if(installedModules[moduleId])
-/******/ 			return installedModules[moduleId].exports;
-
-/******/ 		// Create a new module (and put it into the cache)
-/******/ 		var module = installedModules[moduleId] = {
-/******/ 			exports: {},
-/******/ 			id: moduleId,
-/******/ 			loaded: false
-/******/ 		};
-
-/******/ 		// Execute the module function
-/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
-
-/******/ 		// Flag the module as loaded
-/******/ 		module.loaded = true;
-
-/******/ 		// Return the exports of the module
-/******/ 		return module.exports;
-/******/ 	}
-
-
-/******/ 	// expose the modules object (__webpack_modules__)
-/******/ 	__webpack_require__.m = modules;
-
-/******/ 	// expose the module cache
-/******/ 	__webpack_require__.c = installedModules;
-
-/******/ 	// __webpack_public_path__
-/******/ 	__webpack_require__.p = "";
-
-/******/ 	// Load entry module and return exports
-/******/ 	return __webpack_require__(0);
-/******/ })
-/************************************************************************/
-/******/ ([
-/* 0 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var React = __webpack_require__(1);
-	var classSet = __webpack_require__(2);
-	var ajax = __webpack_require__(3);
-	var PlayButton = __webpack_require__(4);
-	var Spinner = __webpack_require__(5);
-
-	module.exports = React.createClass({
-	  displayName: 'Video',
-	  propTypes: {
-	    from: React.PropTypes.oneOf(['youtube', 'vimeo']),
-	    videoId: React.PropTypes.string.isRequired,
-	    onError: React.PropTypes.func
-	  },
-	  getDefaultProps: function getDefaultProps() {
-	    return {
-	      className: 'video'
-	    };
-	  },
-	  getInitialState: function getInitialState() {
-	    return {
-	      thumb: null,
-	      imageLoaded: false,
-	      showingVideo: false
-	    };
-	  },
-	  isYoutube: function isYoutube() {
-	    return this.props.from === 'youtube' || isNaN(this.props.videoId);
-	  },
-	  isVimeo: function isVimeo() {
-	    return this.props.from === 'vimeo' || !isNaN(this.props.videoId);
-	  },
-	  componentWillReceiveProps: function componentWillReceiveProps(nextProps) {
-	    if (nextProps.className !== this.props.className || nextProps.from !== this.props.from || nextProps.videoId !== this.props.videoId) {
-	      this.setState({
-	        thumb: null,
-	        imageLoaded: false,
-	        showingVideo: false
-	      });
-	    }
-	  },
-	  componentDidMount: function componentDidMount() {
-	    if (!this.state.imageLoaded) {
-	      this.isYoutube() && this.fetchYoutubeData();
-	      this.isVimeo() && this.fetchVimeoData();
-	    }
-	  },
-	  componentDidUpdate: function componentDidUpdate() {
-	    if (!this.state.imageLoaded) {
-	      this.isYoutube() && this.fetchYoutubeData();
-	      this.isVimeo() && this.fetchVimeoData();
-	    }
-	  },
-	  render: function render() {
-	    return React.createElement(
-	      'div',
-	      { className: this.props.className },
-	      !this.state.imageLoaded && React.createElement(Spinner, null),
-	      this.renderImage(),
-	      this.renderIframe()
-	    );
-	  },
-	  renderImage: function renderImage() {
-	    var style = {
-	      backgroundImage: 'url(' + this.state.thumb + ')'
-	    };
-
-	    if (this.state.imageLoaded && !this.state.showingVideo) {
-	      return React.createElement(
-	        'div',
-	        { className: 'video-image', style: style },
-	        React.createElement(PlayButton, { onClick: this.playVideo })
-	      );
-	    }
-	  },
-	  renderIframe: function renderIframe() {
-	    var embedVideoStyle = {
-	      display: this.state.showingVideo ? 'block' : 'none',
-	      width: '100%',
-	      height: '100%'
-	    };
-
-	    if (this.state.showingVideo) {
-	      return React.createElement(
-	        'div',
-	        { className: 'video-embed', style: embedVideoStyle },
-	        React.createElement('iframe', { frameBorder: '0', src: this.getIframeUrl() })
-	      );
-	    }
-	  },
-	  playVideo: function playVideo(ev) {
-	    this.setState({ showingVideo: true });
-	    ev.preventDefault();
-	  },
-	  getIframeUrl: function getIframeUrl() {
-	    if (this.isYoutube()) {
-	      return '//youtube.com/embed/' + this.props.videoId + '?autoplay=1';
-	    } else if (this.isVimeo()) {
-	      return '//player.vimeo.com/video/' + this.props.videoId + '?autoplay=1';
-	    }
-	  },
-	  fetchYoutubeData: function fetchYoutubeData() {
-	    var id = this.props.videoId;
-	    var that = this;
-
-	    ajax.get({
-	      url: '//gdata.youtube.com/feeds/api/videos/' + id + '?v=2&alt=json',
-	      onSuccess: function onSuccess(err, res) {
-	        var gallery = res.entry['media$group']['media$thumbnail'];
-	        var thumb = gallery.sort(function (a, b) {
-	          return b.width - a.width;
-	        })[0].url;
-
-	        that.setState({
-	          thumb: thumb,
-	          imageLoaded: true
-	        });
-	      },
-	      onError: that.props.onError
-	    });
-	  },
-	  fetchVimeoData: function fetchVimeoData() {
-	    var id = this.props.videoId;
-	    var that = this;
-
-	    ajax.get({
-	      url: '//vimeo.com/api/v2/video/' + id + '.json',
-	      onSuccess: function onSuccess(err, res) {
-	        that.setState({
-	          thumb: res[0].thumbnail_large,
-	          imageLoaded: true
-	        });
-	      },
-	      onError: that.props.onError
-	    });
-	  }
-	});
-
-/***/ },
-/* 1 */
-/***/ function(module, exports) {
-
-	module.exports = __WEBPACK_EXTERNAL_MODULE_1__;
-
-/***/ },
-/* 2 */
-/***/ function(module, exports) {
-
-	/**
-	 * Produces the same result as React.addons.classSet
-	 * @param  {object} classes
-	 * @return {string}
-	 *
-	 * @author Ciro S. Costa <https://github.com/cirocosta>
-	 */
-
-	'use strict';
-
-	var _arguments = arguments;
-	module.exports = function (classes) {
-	  return typeof classes !== 'object' ? Array.prototype.join.call(_arguments, ' ') : Object.keys(classes).filter(function (className) {
-	    return classes[className];
-	  }).join(' ');
-	};
-
-/***/ },
-/* 3 */
-/***/ function(module, exports) {
-
-	'use strict';
-
-	exports.get = function (opts) {
-	  var url = opts.url;
-	  var successCb = opts.onSuccess;
-	  var errorCb = opts.onError;
-	  var req = false;
-
-	  // XDomainRequest onload
-	  var _oldIE = function _oldIE() {
-	    successCb(null, JSON.parse(req.responseText));
-	  };
-
-	  // XMLHttpRequest onload
-	  var _onLoad = function _onLoad() {
-	    if (req.readyState !== 4) return;
-	    if (req.status === 200) successCb(null, JSON.parse(req.responseText));else {
-	      var err = { error: 'Sorry, an error ocurred on the server' };
-
-	      if (errorCb && typeof errorCb === 'function') return errorCb(err);
-	      successCb(err, null);
-	    }
-	  };
-
-	  var _onError = function _onError() {
-	    var err = { error: 'Sorry, an error ocurred on the server' };
-
-	    if (errorCb && typeof errorCb === 'function') return errorCb(err);
-	    successCb(err, null);
-	  };
-
-	  try {
-	    req = new XDomainRequest();
-	    req.onload = _oldIE;
-	  } catch (e) {
-	    req = new XMLHttpRequest();
-	    req.onreadystatechange = _onLoad;
-	  }
-
-	  req.onerror = _onError;
-	  req.open('GET', url, true);
-	  req.send();
-	};
-
-/***/ },
-/* 4 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var React = __webpack_require__(1);
-
-	module.exports = React.createClass({
-	  displayName: 'exports',
-
-	  propTypes: {
-	    onClick: React.PropTypes.func
-	  },
-	  render: function render() {
-	    return React.createElement(
-	      'button',
-	      { type: 'button', className: 'video-play-button', onClick: this.props.onClick },
-	      React.createElement(
-	        'svg',
-	        { xmlns: 'http://www.w3.org/2000/svg', version: '1.1', viewBox: '0 0 100 100' },
-	        React.createElement('path', { d: 'M79.674,53.719c2.59-2.046,2.59-5.392,0-7.437L22.566,1.053C19.977-0.993,18,0.035,18,3.335v93.331c0,3.3,1.977,4.326,4.566,2.281L79.674,53.719z' })
-	      )
-	    );
-	  }
-	});
-
-/***/ },
-/* 5 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var React = __webpack_require__(1);
-
-	module.exports = React.createClass({
-	  displayName: 'exports',
-
-	  render: function render() {
-	    return React.createElement(
-	      'div',
-	      { className: 'video-loading' },
-	      React.createElement(
-	        'svg',
-	        { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 32 32', width: '32', height: '32' },
-	        React.createElement('path', { opacity: '.25', d: 'M16 0 A16 16 0 0 0 16 32 A16 16 0 0 0 16 0 M16 4 A12 12 0 0 1 16 28 A12 12 0 0 1 16 4' }),
-	        React.createElement('path', { d: 'M16 0 A16 16 0 0 1 32 16 L28 16 A12 12 0 0 0 16 4z' })
-	      )
-	    );
-	  }
-	});
-
-/***/ }
-/******/ ])
-});
-;
\ No newline at end of file
diff --git a/dist/react-video.min.css b/dist/react-video.min.css
deleted file mode 100644
index 2f3cd7b..0000000
--- a/dist/react-video.min.css
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * React Video - React component to load video from Vimeo or Youtube across any device
- * @version v1.5.3
- * @link https://github.com/pedronauck/react-video
- * @license MIT
- * @author Pedro Nauck (https://github.com/pedronauck)
-*/
-.video-embed,.video-image,.video-image:after{position:absolute;top:0;left:0;width:100%;height:100%}.video{position:relative;padding-bottom:56.25%;background:#e2e2e2}.video iframe{border:0}.video-image{background-position:center center;background-size:100% auto}.video-image:after{z-index:1;display:block;content:'';background:rgba(0,0,0,.3)}.video-loading,.video-play-button{top:50%;left:50%;transform:translateX(-50%) translateY(-50%)}.video-play-button{z-index:2;position:absolute;padding:0;width:70px;border:0;background:0 0}.video-play-button:focus{outline:0}.video-play-button svg{fill:#fff;-webkit-filter:drop-shadow(0 1px 1px rgba(0,0,0,.8));filter:drop-shadow(0 1px 1px rgba(0,0,0,.8))}.video-loading{z-index:4;position:absolute;width:32px;height:32px}.video-loading svg{fill:#000;transform-origin:50% 50%;-webkit-animation:spinner .8s infinite linear;animation:spinner .8s infinite linear}.video-embed iframe{width:100%;height:100%}@-moz-keyframes spinner{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}@-webkit-keyframes spinner{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}@-o-keyframes spinner{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}@keyframes spinner{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}
\ No newline at end of file
diff --git a/dist/react-video.min.js b/dist/react-video.min.js
deleted file mode 100644
index 0bcd946..0000000
--- a/dist/react-video.min.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * React Video - React component to load video from Vimeo or Youtube across any device
- * @version v1.5.3
- * @link https://github.com/pedronauck/react-video
- * @license MIT
- * @author Pedro Nauck (https://github.com/pedronauck)
-*/
-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports.ReactVideo=t(require("react")):e.ReactVideo=t(e.React)}(this,function(e){return function(e){function t(r){if(o[r])return o[r].exports;var i=o[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var o={};return t.m=e,t.c=o,t.p="",t(0)}([function(e,t,o){"use strict";var r=o(1),i=(o(2),o(3)),n=o(4),s=o(5);e.exports=r.createClass({displayName:"Video",propTypes:{from:r.PropTypes.oneOf(["youtube","vimeo"]),videoId:r.PropTypes.string.isRequired,onError:r.PropTypes.func},getDefaultProps:function(){return{className:"video"}},getInitialState:function(){return{thumb:null,imageLoaded:!1,showingVideo:!1}},isYoutube:function(){return"youtube"===this.props.from||isNaN(this.props.videoId)},isVimeo:function(){return"vimeo"===this.props.from||!isNaN(this.props.videoId)},componentWillReceiveProps:function(e){(e.className!==this.props.className||e.from!==this.props.from||e.videoId!==this.props.videoId)&&this.setState({thumb:null,imageLoaded:!1,showingVideo:!1})},componentDidMount:function(){this.state.imageLoaded||(this.isYoutube()&&this.fetchYoutubeData(),this.isVimeo()&&this.fetchVimeoData())},componentDidUpdate:function(){this.state.imageLoaded||(this.isYoutube()&&this.fetchYoutubeData(),this.isVimeo()&&this.fetchVimeoData())},render:function(){return r.createElement("div",{className:this.props.className},!this.state.imageLoaded&&r.createElement(s,null),this.renderImage(),this.renderIframe())},renderImage:function(){var e={backgroundImage:"url("+this.state.thumb+")"};return this.state.imageLoaded&&!this.state.showingVideo?r.createElement("div",{className:"video-image",style:e},r.createElement(n,{onClick:this.playVideo})):void 0},renderIframe:function(){var e={display:this.state.showingVideo?"block":"none",width:"100%",height:"100%"};return this.state.showingVideo?r.createElement("div",{className:"video-embed",style:e},r.createElement("iframe",{frameBorder:"0",src:this.getIframeUrl()})):void 0},playVideo:function(e){this.setState({showingVideo:!0}),e.preventDefault()},getIframeUrl:function(){return this.isYoutube()?"//youtube.com/embed/"+this.props.videoId+"?autoplay=1":this.isVimeo()?"//player.vimeo.com/video/"+this.props.videoId+"?autoplay=1":void 0},fetchYoutubeData:function(){var e=this.props.videoId,t=this;i.get({url:"//gdata.youtube.com/feeds/api/videos/"+e+"?v=2&alt=json",onSuccess:function(e,o){var r=o.entry.media$group.media$thumbnail,i=r.sort(function(e,t){return t.width-e.width})[0].url;t.setState({thumb:i,imageLoaded:!0})},onError:t.props.onError})},fetchVimeoData:function(){var e=this.props.videoId,t=this;i.get({url:"//vimeo.com/api/v2/video/"+e+".json",onSuccess:function(e,o){t.setState({thumb:o[0].thumbnail_large,imageLoaded:!0})},onError:t.props.onError})}})},function(t,o){t.exports=e},function(e,t){"use strict";var o=arguments;e.exports=function(e){return"object"!=typeof e?Array.prototype.join.call(o," "):Object.keys(e).filter(function(t){return e[t]}).join(" ")}},function(e,t){"use strict";t.get=function(e){var t=e.url,o=e.onSuccess,r=e.onError,i=!1,n=function(){o(null,JSON.parse(i.responseText))},s=function(){if(4===i.readyState)if(200===i.status)o(null,JSON.parse(i.responseText));else{var e={error:"Sorry, an error ocurred on the server"};if(r&&"function"==typeof r)return r(e);o(e,null)}},a=function(){var e={error:"Sorry, an error ocurred on the server"};return r&&"function"==typeof r?r(e):void o(e,null)};try{i=new XDomainRequest,i.onload=n}catch(u){i=new XMLHttpRequest,i.onreadystatechange=s}i.onerror=a,i.open("GET",t,!0),i.send()}},function(e,t,o){"use strict";var r=o(1);e.exports=r.createClass({displayName:"exports",propTypes:{onClick:r.PropTypes.func},render:function(){return r.createElement("button",{type:"button",className:"video-play-button",onClick:this.props.onClick},r.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",version:"1.1",viewBox:"0 0 100 100"},r.createElement("path",{d:"M79.674,53.719c2.59-2.046,2.59-5.392,0-7.437L22.566,1.053C19.977-0.993,18,0.035,18,3.335v93.331c0,3.3,1.977,4.326,4.566,2.281L79.674,53.719z"})))}})},function(e,t,o){"use strict";var r=o(1);e.exports=r.createClass({displayName:"exports",render:function(){return r.createElement("div",{className:"video-loading"},r.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",width:"32",height:"32"},r.createElement("path",{opacity:".25",d:"M16 0 A16 16 0 0 0 16 32 A16 16 0 0 0 16 0 M16 4 A12 12 0 0 1 16 28 A12 12 0 0 1 16 4"}),r.createElement("path",{d:"M16 0 A16 16 0 0 1 32 16 L28 16 A12 12 0 0 0 16 4z"})))}})}])});
\ No newline at end of file
diff --git a/docs/css/github.css b/docs/css/github.css
deleted file mode 100644
index 34b1744..0000000
--- a/docs/css/github.css
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
-
-github.com style (c) Vasily Polovnyov <vast@whiteants.net>
-
-*/
-
-.hljs {
-  display: block;
-  overflow-x: auto;
-  padding: 0.5em;
-  color: #333;
-  background: #f8f8f8;
-  -webkit-text-size-adjust: none;
-}
-
-.hljs-comment,
-.hljs-template_comment,
-.diff .hljs-header,
-.hljs-javadoc {
-  color: #998;
-  font-style: italic;
-}
-
-.hljs-keyword,
-.css .rule .hljs-keyword,
-.hljs-winutils,
-.javascript .hljs-title,
-.nginx .hljs-title,
-.hljs-subst,
-.hljs-request,
-.hljs-status {
-  color: #333;
-  font-weight: bold;
-}
-
-.hljs-number,
-.hljs-hexcolor,
-.ruby .hljs-constant {
-  color: #008080;
-}
-
-.hljs-string,
-.hljs-tag .hljs-value,
-.hljs-phpdoc,
-.hljs-dartdoc,
-.tex .hljs-formula {
-  color: #d14;
-}
-
-.hljs-title,
-.hljs-id,
-.scss .hljs-preprocessor {
-  color: #900;
-  font-weight: bold;
-}
-
-.javascript .hljs-title,
-.hljs-list .hljs-keyword,
-.hljs-subst {
-  font-weight: normal;
-}
-
-.hljs-class .hljs-title,
-.hljs-type,
-.vhdl .hljs-literal,
-.tex .hljs-command {
-  color: #458;
-  font-weight: bold;
-}
-
-.hljs-tag,
-.hljs-tag .hljs-title,
-.hljs-rules .hljs-property,
-.django .hljs-tag .hljs-keyword {
-  color: #000080;
-  font-weight: normal;
-}
-
-.hljs-attribute,
-.hljs-variable,
-.lisp .hljs-body {
-  color: #008080;
-}
-
-.hljs-regexp {
-  color: #009926;
-}
-
-.hljs-symbol,
-.ruby .hljs-symbol .hljs-string,
-.lisp .hljs-keyword,
-.clojure .hljs-keyword,
-.scheme .hljs-keyword,
-.tex .hljs-special,
-.hljs-prompt {
-  color: #990073;
-}
-
-.hljs-built_in {
-  color: #0086b3;
-}
-
-.hljs-preprocessor,
-.hljs-pragma,
-.hljs-pi,
-.hljs-doctype,
-.hljs-shebang,
-.hljs-cdata {
-  color: #999;
-  font-weight: bold;
-}
-
-.hljs-deletion {
-  background: #fdd;
-}
-
-.hljs-addition {
-  background: #dfd;
-}
-
-.diff .hljs-change {
-  background: #0086b3;
-}
-
-.hljs-chunk {
-  color: #aaa;
-}
diff --git a/docs/css/react-video.min.css b/docs/css/react-video.min.css
deleted file mode 100644
index 001eb33..0000000
--- a/docs/css/react-video.min.css
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * React Video - React component to load video from Vimeo or Youtube across any device
- * @version v1.1.5
- * @link https://github.com/pedronauck/react-video
- * @license MIT
- * @author Pedro Nauck (https://github.com/pedronauck)
-*/
-.video-embed,.video-image,.video-image:after{position:absolute;top:0;left:0;width:100%;height:100%}.video{position:relative;padding-bottom:56.25%;background:#e2e2e2}.video iframe{border:0}.video-image{background-position:center center;background-size:100% auto}.video-image:after{z-index:1;display:block;content:'';background:rgba(0,0,0,.3)}.video-loading,.video-play-button{top:50%;left:50%;transform:translateX(-50%) translateY(-50%)}.video-play-button{z-index:2;position:absolute;padding:0;width:70px;border:0;background:0 0}.video-play-button:focus{outline:0}.video-play-button svg{fill:#fff;-webkit-filter:drop-shadow(0 1px 1px rgba(0,0,0,.8));filter:drop-shadow(0 1px 1px rgba(0,0,0,.8))}.video-loading{z-index:4;position:absolute;width:32px;height:32px}.video-loading svg{fill:#000;transform-origin:50% 50%;-webkit-animation:spinner .8s infinite linear;animation:spinner .8s infinite linear}.video-embed iframe{width:100%;height:100%}@-moz-keyframes spinner{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}@-webkit-keyframes spinner{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}@-o-keyframes spinner{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}@keyframes spinner{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}
diff --git a/docs/css/style.css b/docs/css/style.css
deleted file mode 100644
index a421738..0000000
--- a/docs/css/style.css
+++ /dev/null
@@ -1,179 +0,0 @@
-@import url("http://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400|Montserrat");
-
-body {
-  font-family: 'Source Sans Pro', Helvetica, sans-serif;
-  font-size: 18px;
-  line-height: 1.5;
-}
-
-a {
-  color: #d35400;
-  text-decoration: none;
-}
-
-code:not(.hljs) {
-  background: #f2f2f2;
-  color: #DC2250;
-  font-size: 16px;
-  padding: 3px;
-  border-radius: 3px;
-}
-
-/* ----------------------------------------------------------------------------
- *  Header
- * ---------------------------------------------------------------------------*/
-
-.header-container {
-  background: #222222;
-  padding: 80px 0 0 0;
-}
-
-.header {
-  width: 100%;
-  margin: 0 auto;
-  color: white;
-  text-align: center;
-}
-
-@media screen and (min-width: 960px) {
-  .header {
-    width: 53.33em;
-  }
-};
-
-.header .title {
-  font-family: 'Montserrat';
-  font-size: 60px;
-  font-weight: 300;
-  margin: 0 0 40px;
-}
-
-.header .subtitle {
-  font-size: 30px;
-  font-weight: 300;
-  color: #999;
-  padding: 0 50px 70px;
-}
-
-@media screen and (min-width: 960px) {
-  .header .subtitle {
-    padding: 0 150px 70px;
-  }
-}
-
-.github-buttons {
-  display: table;
-  padding: 0;
-  margin: 0 auto 40px auto;
-  list-style: none;
-}
-
-.github-buttons li ~ li {
-  margin-top: 10px;
-}
-
-@media screen and (min-width: 420px) {
-  .github-buttons li {
-    float: left;
-    margin: 0 10px;
-  }
-}
-
-.github-buttons li a {
-  display: inline-block;
-  padding: 20px 20px;
-  color: white;
-  font-size: 20px;
-  background: #d35400;
-  border-radius: 5px;
-}
-
-.github-buttons li a svg {
-  float: left;
-  margin-right: 10px;
-}
-
-.cover-buttons {
-  padding: 0;
-  margin: 0 0 50px 0;
-  list-style: none;
-}
-
-.cover-button-item {
-  display: inline-block;
-  margin: 0 20px;
-  opacity: .4;
-}
-
-.cover-button-item.is-active {
-  opacity: 1;
-}
-
-.cover-button-item a {
-  display: block;
-  width: 130px;
-}
-
-.cover-button-item a img {
-  width: 100%;
-}
-
-/* ----------------------------------------------------------------------------
- *  Content
- * ---------------------------------------------------------------------------*/
-
-.content-section {
-  width: 100%;
-  margin: 0 auto;
-  padding: 40px 0;
-}
-
-.content-section ~ .content-section {
-  padding-top: 0;
-}
-
-@media screen and (min-width: 960px) {
-  .content-section {
-    width: 44.44em;
-    padding: 80px 0;
-  }
-};
-
-.content-section ~ .content-section {
-  padding-top: 0;
-}
-
-.section-title {
-  font-family: "Montserrat";
-  font-size: 50px;
-  text-align: center;
-  color: #D15418;
-  margin: 0 0 30px 0;
-}
-
-.content-section p {
-  text-align: center;
-  margin-bottom: 30px;
-  padding: 0 30px;
-}
-
-@media screen and (min-width: 960px) {
-  .content-section p {
-    padding: 0 80px;
-  }
-}
-
-.content-section pre {
-  margin-top: -10px;
-  margin-bottom: 0;
-}
-
-/* ----------------------------------------------------------------------------
- *  Footer
- * --------------------------------------------------------------------------*/
-
-.footer {
-  padding: 0 0 80px 0;
-  color: #ee9368;
-  text-align: center;
-}
diff --git a/docs/images/btn-vimeo.png b/docs/images/btn-vimeo.png
deleted file mode 100644
index ad3afdc0bd6f561d7eda9a6ab5be1fd83691f290..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/docs/images/btn-youtube.png b/docs/images/btn-youtube.png
deleted file mode 100644
index 8de45ab39b52f9d61440698599936616566721af..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/docs/images/cover.png b/docs/images/cover.png
deleted file mode 100644
index 20b4d07cf365533d25cddaf52eda142b3b21182c..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/docs/index.html b/docs/index.html
deleted file mode 100644
index 24ce506..0000000
--- a/docs/index.html
+++ /dev/null
@@ -1,137 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-  <meta charset="utf-8">
-  <meta http-equiv="X-UA-Compatible" content="IE=edge">
-  <meta name="viewport" content="width=device-width, initial-scale=1">
-  <title>React Video</title>
-
-  <link rel="stylesheet" href="http://necolas.github.io/normalize.css/3.0.1/normalize.css">
-  <link rel="stylesheet" href="css/react-video.min.css">
-  <link rel="stylesheet" href="css/github.css">
-
-  <link rel="stylesheet" href="css/style.css">
-  <meta property="og:title" content="React Video" />
-  <meta property="og:type" content="website" />
-  <meta property="og:description" content="A pretty good and effective way to create a video placeholder from Youtube or Vimeo using a high-res image." />
-  <meta property="og:url" content="http://pedronauck.github.io/react-video" />
-  <meta property="og:image" content="http://f.cl.ly/items/440F3Y0w1l293g3e3g3N/cover.png" />
-</head>
-<body>
-  <a href="https://github.com/pedronauck/react-video"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/52760788cde945287fbb584134c4cbc2bc36f904/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f77686974655f6666666666662e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png"></a>
-  <div class="header-container">
-    <header class="header">
-      <h1 class="title">React Video</h1>
-      <ul class="github-buttons">
-        <li>
-          <a href="https://github.com/pedronauck/react-video/archive/v1.5.3.zip">Download v1.5.3</a>
-        </li>
-        <li>
-          <a href="http://github.com/pedronauck/react-video">
-            <!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In  -->
-            <svg version="1.1"
-               xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
-               x="0px" y="0px" width="26px" height="26px" viewBox="0 0 31.984 32" enable-background="new 0 0 31.984 32"
-               xml:space="preserve" fill="white">
-              <path d="M31.984,16c0,8.844-7.156,16-16,16C7.156,32,0,24.843,0,16C0,7.171,7.156,0,15.984,0C24.828,0,31.984,7.171,31.984,16z
-                 M20,29c5.5-1.812,9.484-6.938,9.484-13c0-7.453-6.047-13.5-13.5-13.5C8.547,2.5,2.5,8.546,2.5,16c0,6.062,4,11.203,9.516,13
-                v-2.547c-3.938,0.891-4.766-1.844-4.766-1.844C6.625,23,5.719,22.578,5.719,22.578c-1.266-0.859,0.094-0.844,0.094-0.844
-                c1.391,0.094,2.125,1.422,2.125,1.422c1.312,2.25,3.484,1.438,4.156,1.109c0.203-0.984,0.969-1.188,1.219-1.266
-                c-3.547-0.375-7.344-1.656-7.344-7.797c0-1.719,0.609-3.125,1.609-4.219c-0.156-0.406-0.703-2,0.156-4.172
-                c0,0,1.328-0.421,4.328,1.609C13.312,8.078,14.656,7.906,16,7.89c1.328,0.016,2.672,0.187,3.938,0.531
-                c3-2.031,4.312-1.609,4.312-1.609c0.859,2.172,0.328,3.766,0.156,4.172c1.016,1.094,1.625,2.5,1.625,4.219
-                c0,6.141-3.797,7.406-7.344,7.781C19.328,23.421,20,24.25,20,25.828V29z"/>
-            </svg>
-            Fork on Github
-          </a>
-        </li>
-      </ul>
-      <h3 class="subtitle">A pretty good and effective way to create a video placeholder from Youtube or Vimeo</h3>
-      <ul class="cover-buttons">
-        <li class="cover-button-item is-active" data-from="youtube">
-          <a href="#"><img src="images/btn-youtube.png" /></a>
-        </li>
-        <li class="cover-button-item" data-from="vimeo">
-          <a href="#"><img src="images/btn-vimeo.png" /></a>
-        </li>
-      </ul>
-      <div id="cover-video"></div>
-    </header>
-  </div>
-
-  <section class="content-section install">
-    <h2 class="section-title">Install</h2>
-    <p>
-      You need just one thing to make the component work. After <a href="https://github.com/pedronauck/react-video#install">download</a> <def>(using NPM, bower or whatever you want)</def>, put the base component style at the your page.
-    </p>
-    <pre>
-      <code class="hljs bash">
-        &lt;link rel="stylesheet" href="/path/react-video.css" /&gt;
-      </code>
-    </pre>
-  </section>
-
-  <section class="content-section usage">
-    <h2 class="section-title">Usage</h2>
-    <p>
-      Using the component is simpler than installing. See an example with browserify to bundle your script:
-    </p>
-    <pre><code class="hljs javascript">
-      /** @jsx React.DOM */
-      var Video = require('react-video');
-
-      React.render(
-        &lt;Video from='youtube' videoId={videoId} /&gt;,
-        document.querySelector('#your-div')
-      );
-
-      React.render(
-        &lt;Video from='vimeo' videoId={videoId} /&gt;,
-        document.querySelector('#your-div')
-      );
-    </code></pre>
-    <p>
-      The property <code>videoId</code> is optional, so you can use it or not. If you don't pass the property, the component will select your type of video based on your id.
-    </p>
-    <pre><code class="hljs javascript">
-      React.render(
-        &lt;Video videoId={videoId} /&gt;,
-        document.querySelector('#your-div')
-      );
-    </code></pre>
-    <p>
-      To handle errors when something happens, like your video can't be loaded, you can pass a callback with a prop <code>onError</code> in the component:
-
-      <pre><code class="hljs javascript">
-        var _onError = function(err) {
-          console.log(err);
-        };
-
-        React.render(
-          &lt;Video onError={_onError} videoId={videoId} /&gt;
-          document.querySelector('#your-div')
-        );
-      </code></pre>
-    </p>
-    <p>
-      If you decide to use just Javascript without any module loader, you can get the global variable <code>window.ReactVideo</code>:
-    </p>
-    <pre><code class="hljs javascript">
-      /** @jsx React.DOM */
-
-      var Video = ReactVideo;
-    </code></pre>
-  </section>
-
-  <footer class="footer">
-    Made with ❤︎ by <a href="http://github.com/pedronauck">Pedro Nauck</a>
-  </footer>
-
-  <script src="//cdnjs.cloudflare.com/ajax/libs/react/0.12.2/react-with-addons.min.js"></script>
-  <script src="//cdnjs.cloudflare.com/ajax/libs/react/0.12.2/JSXTransformer.js"></script>
-  <script src="js/react-video.min.js"></script>
-  <script src="js/highlight.pack.js"></script>
-  <script>hljs.initHighlightingOnLoad();</script>
-  <script src="js/app.js" type="text/jsx"></script>
-</body>
-</html>
diff --git a/docs/js/app.js b/docs/js/app.js
deleted file mode 100644
index 8e4c90c..0000000
--- a/docs/js/app.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/** @jsx React.DOM */
-
-(function() {
-  var Video = ReactVideo;
-  var $youtubeBtn = document.querySelector('.cover-button-item[data-from="youtube"]');
-  var $vimeoBtn = document.querySelector('.cover-button-item[data-from="vimeo"]');
-  var mountNode = document.querySelector('#cover-video');
-
-  React.render(<Video from='youtube' videoId='gZD0ahZHgBM' />, mountNode);
-
-  $youtubeBtn.addEventListener('click', function(ev) {
-    $youtubeBtn.classList.add('is-active');
-    $vimeoBtn.classList.remove('is-active');
-
-    React.unmountComponentAtNode(mountNode);
-    React.render(<Video from='youtube' videoId='gZD0ahZHgBM' />, mountNode);
-    ev.preventDefault();
-  });
-
-  $vimeoBtn.addEventListener('click', function(ev) {
-    $vimeoBtn.classList.add('is-active');
-    $youtubeBtn.classList.remove('is-active');
-
-    React.unmountComponentAtNode(mountNode);
-    React.render(<Video from='vimeo' videoId='63836620' />, mountNode);
-    ev.preventDefault();
-  });
-})();
diff --git a/docs/js/highlight.pack.js b/docs/js/highlight.pack.js
deleted file mode 100644
index 8a7957e..0000000
--- a/docs/js/highlight.pack.js
+++ /dev/null
@@ -1 +0,0 @@
-var hljs=new function(){function e(e){return e.replace(/&/gm,"&amp;").replace(/</gm,"&lt;").replace(/>/gm,"&gt;")}function t(e){return e.nodeName.toLowerCase()}function n(e,t){var n=e&&e.exec(t);return n&&0==n.index}function r(e){var t=(e.className+" "+(e.parentNode?e.parentNode.className:"")).split(/\s+/);return t=t.map(function(e){return e.replace(/^lang(uage)?-/,"")}),t.filter(function(e){return m(e)||/no(-?)highlight/.test(e)})[0]}function i(e,t){var n={};for(var r in e)n[r]=e[r];if(t)for(var r in t)n[r]=t[r];return n}function a(e){var n=[];return function r(e,i){for(var a=e.firstChild;a;a=a.nextSibling)3==a.nodeType?i+=a.nodeValue.length:1==a.nodeType&&(n.push({event:"start",offset:i,node:a}),i=r(a,i),t(a).match(/br|hr|img|input/)||n.push({event:"stop",offset:i,node:a}));return i}(e,0),n}function s(n,r,i){function a(){return n.length&&r.length?n[0].offset!=r[0].offset?n[0].offset<r[0].offset?n:r:"start"==r[0].event?n:r:n.length?n:r}function s(n){function r(t){return" "+t.nodeName+'="'+e(t.value)+'"'}l+="<"+t(n)+Array.prototype.map.call(n.attributes,r).join("")+">"}function o(e){l+="</"+t(e)+">"}function c(e){("start"==e.event?s:o)(e.node)}for(var u=0,l="",f=[];n.length||r.length;){var h=a();if(l+=e(i.substr(u,h[0].offset-u)),u=h[0].offset,h==n){f.reverse().forEach(o);do c(h.splice(0,1)[0]),h=a();while(h==n&&h.length&&h[0].offset==u);f.reverse().forEach(s)}else"start"==h[0].event?f.push(h[0].node):f.pop(),c(h.splice(0,1)[0])}return l+e(i.substr(u))}function o(e){function t(e){return e&&e.source||e}function n(n,r){return RegExp(t(n),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,s){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var o={},c=function(t,n){e.cI&&(n=n.toLowerCase()),n.split(" ").forEach(function(e){var n=e.split("|");o[n[0]]=[t,n[1]?Number(n[1]):1]})};"string"==typeof a.k?c("keyword",a.k):Object.keys(a.k).forEach(function(e){c(e,a.k[e])}),a.k=o}a.lR=n(a.l||/\b[A-Za-z0-9_]+\b/,!0),s&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=n(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=n(a.e)),a.tE=t(a.e)||"",a.eW&&s.tE&&(a.tE+=(a.e?"|":"")+s.tE)),a.i&&(a.iR=n(a.i)),void 0===a.r&&(a.r=1),a.c||(a.c=[]);var u=[];a.c.forEach(function(e){e.v?e.v.forEach(function(t){u.push(i(e,t))}):u.push("self"==e?a:e)}),a.c=u,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,s);var l=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(t).filter(Boolean);a.t=l.length?n(l.join("|"),!0):{exec:function(){return null}}}}r(e)}function c(t,r,i,a){function s(e,t){for(var r=0;r<t.c.length;r++)if(n(t.c[r].bR,e))return t.c[r]}function l(e,t){return n(e.eR,t)?e:e.eW?l(e.parent,t):void 0}function f(e,t){return!i&&n(t.iR,e)}function h(e,t){var n=x.cI?t[0].toLowerCase():t[0];return e.k.hasOwnProperty(n)&&e.k[n]}function g(e,t,n,r){var i=r?"":N.classPrefix,a='<span class="'+i,s=n?"":"</span>";return a+=e+'">',a+t+s}function p(){if(!w.k)return e(B);var t="",n=0;w.lR.lastIndex=0;for(var r=w.lR.exec(B);r;){t+=e(B.substr(n,r.index-n));var i=h(w,r);i?(y+=i[1],t+=g(i[0],e(r[0]))):t+=e(r[0]),n=w.lR.lastIndex,r=w.lR.exec(B)}return t+e(B.substr(n))}function v(){if(w.sL&&!E[w.sL])return e(B);var t=w.sL?c(w.sL,B,!0,L[w.sL]):u(B);return w.r>0&&(y+=t.r),"continuous"==w.subLanguageMode&&(L[w.sL]=t.top),g(t.language,t.value,!1,!0)}function b(){return void 0!==w.sL?v():p()}function d(t,n){var r=t.cN?g(t.cN,"",!0):"";t.rB?(M+=r,B=""):t.eB?(M+=e(n)+r,B=""):(M+=r,B=n),w=Object.create(t,{parent:{value:w}})}function R(t,n){if(B+=t,void 0===n)return M+=b(),0;var r=s(n,w);if(r)return M+=b(),d(r,n),r.rB?0:n.length;var i=l(w,n);if(i){var a=w;a.rE||a.eE||(B+=n),M+=b();do w.cN&&(M+="</span>"),y+=w.r,w=w.parent;while(w!=i.parent);return a.eE&&(M+=e(n)),B="",i.starts&&d(i.starts,""),a.rE?0:n.length}if(f(n,w))throw new Error('Illegal lexeme "'+n+'" for mode "'+(w.cN||"<unnamed>")+'"');return B+=n,n.length||1}var x=m(t);if(!x)throw new Error('Unknown language: "'+t+'"');o(x);for(var w=a||x,L={},M="",k=w;k!=x;k=k.parent)k.cN&&(M=g(k.cN,"",!0)+M);var B="",y=0;try{for(var C,I,j=0;;){if(w.t.lastIndex=j,C=w.t.exec(r),!C)break;I=R(r.substr(j,C.index-j),C[0]),j=C.index+I}R(r.substr(j));for(var k=w;k.parent;k=k.parent)k.cN&&(M+="</span>");return{r:y,value:M,language:t,top:w}}catch(A){if(-1!=A.message.indexOf("Illegal"))return{r:0,value:e(r)};throw A}}function u(t,n){n=n||N.languages||Object.keys(E);var r={r:0,value:e(t)},i=r;return n.forEach(function(e){if(m(e)){var n=c(e,t,!1);n.language=e,n.r>i.r&&(i=n),n.r>r.r&&(i=r,r=n)}}),i.language&&(r.second_best=i),r}function l(e){return N.tabReplace&&(e=e.replace(/^((<[^>]+>|\t)+)/gm,function(e,t){return t.replace(/\t/g,N.tabReplace)})),N.useBR&&(e=e.replace(/\n/g,"<br>")),e}function f(e,t,n){var r=t?R[t]:n,i=[e.trim()];return e.match(/(\s|^)hljs(\s|$)/)||i.push("hljs"),r&&i.push(r),i.join(" ").trim()}function h(e){var t=r(e);if(!/no(-?)highlight/.test(t)){var n;N.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(/<br[ \/]*>/g,"\n")):n=e;var i=n.textContent,o=t?c(t,i,!0):u(i),h=a(n);if(h.length){var g=document.createElementNS("http://www.w3.org/1999/xhtml","div");g.innerHTML=o.value,o.value=s(h,a(g),i)}o.value=l(o.value),e.innerHTML=o.value,e.className=f(e.className,t,o.language),e.result={language:o.language,re:o.r},o.second_best&&(e.second_best={language:o.second_best.language,re:o.second_best.r})}}function g(e){N=i(N,e)}function p(){if(!p.called){p.called=!0;var e=document.querySelectorAll("pre code");Array.prototype.forEach.call(e,h)}}function v(){addEventListener("DOMContentLoaded",p,!1),addEventListener("load",p,!1)}function b(e,t){var n=E[e]=t(this);n.aliases&&n.aliases.forEach(function(t){R[t]=e})}function d(){return Object.keys(E)}function m(e){return E[e]||E[R[e]]}var N={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},E={},R={};this.highlight=c,this.highlightAuto=u,this.fixMarkup=l,this.highlightBlock=h,this.configure=g,this.initHighlighting=p,this.initHighlightingOnLoad=v,this.registerLanguage=b,this.listLanguages=d,this.getLanguage=m,this.inherit=i,this.IR="[a-zA-Z][a-zA-Z0-9_]*",this.UIR="[a-zA-Z_][a-zA-Z0-9_]*",this.NR="\\b\\d+(\\.\\d+)?",this.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",this.BNR="\\b(0b[01]+)",this.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",this.BE={b:"\\\\[\\s\\S]",r:0},this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE]},this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE]},this.PWM={b:/\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such)\b/},this.CLCM={cN:"comment",b:"//",e:"$",c:[this.PWM]},this.CBCM={cN:"comment",b:"/\\*",e:"\\*/",c:[this.PWM]},this.HCM={cN:"comment",b:"#",e:"$",c:[this.PWM]},this.NM={cN:"number",b:this.NR,r:0},this.CNM={cN:"number",b:this.CNR,r:0},this.BNM={cN:"number",b:this.BNR,r:0},this.CSSNM={cN:"number",b:this.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},this.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[this.BE,{b:/\[/,e:/\]/,r:0,c:[this.BE]}]},this.TM={cN:"title",b:this.IR,r:0},this.UTM={cN:"title",b:this.UIR,r:0}};hljs.registerLanguage("javascript",function(r){return{aliases:["js"],k:{keyword:"in if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const class",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document"},c:[{cN:"pi",b:/^\s*('|")use strict('|")/,r:10},r.ASM,r.QSM,r.CLCM,r.CBCM,r.CNM,{b:"("+r.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[r.CLCM,r.CBCM,r.RM,{b:/</,e:/>;/,r:0,sL:"xml"}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[r.inherit(r.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{cN:"params",b:/\(/,e:/\)/,c:[r.CLCM,r.CBCM],i:/["'\(]/}],i:/\[|%/},{b:/\$[(.]/},{b:"\\."+r.IR,r:0}]}});hljs.registerLanguage("sql",function(e){var t={cN:"comment",b:"--",e:"$"};return{cI:!0,i:/[<>]/,c:[{cN:"operator",bK:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate savepoint release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup",e:/;/,eW:!0,k:{keyword:"abs absolute acos action add adddate addtime aes_decrypt aes_encrypt after aggregate all allocate alter analyze and any are as asc ascii asin assertion at atan atan2 atn2 authorization authors avg backup before begin benchmark between bin binlog bit_and bit_count bit_length bit_or bit_xor both by cache call cascade cascaded case cast catalog ceil ceiling chain change changed char_length character_length charindex charset check checksum checksum_agg choose close coalesce coercibility collate collation collationproperty column columns columns_updated commit compress concat concat_ws concurrent connect connection connection_id consistent constraint constraints continue contributors conv convert convert_tz corresponding cos cot count count_big crc32 create cross cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime data database databases datalength date_add date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts datetimeoffsetfromparts day dayname dayofmonth dayofweek dayofyear deallocate declare decode default deferrable deferred degrees delayed delete des_decrypt des_encrypt des_key_file desc describe descriptor diagnostics difference disconnect distinct distinctrow div do domain double drop dumpfile each else elt enclosed encode encrypt end end-exec engine engines eomonth errors escape escaped event eventdata events except exception exec execute exists exp explain export_set extended external extract fast fetch field fields find_in_set first first_value floor flush for force foreign format found found_rows from from_base64 from_days from_unixtime full function get get_format get_lock getdate getutcdate global go goto grant grants greatest group group_concat grouping grouping_id gtid_subset gtid_subtract handler having help hex high_priority hosts hour ident_current ident_incr ident_seed identified identity if ifnull ignore iif ilike immediate in index indicator inet6_aton inet6_ntoa inet_aton inet_ntoa infile initially inner innodb input insert install instr intersect into is is_free_lock is_ipv4 is_ipv4_compat is_ipv4_mapped is_not is_not_null is_used_lock isdate isnull isolation join key kill language last last_day last_insert_id last_value lcase lead leading least leaves left len lenght level like limit lines ln load load_file local localtime localtimestamp locate lock log log10 log2 logfile logs low_priority lower lpad ltrim make_set makedate maketime master master_pos_wait match matched max md5 medium merge microsecond mid min minute mod mode module month monthname mutex name_const names national natural nchar next no no_write_to_binlog not now nullif nvarchar oct octet_length of old_password on only open optimize option optionally or ord order outer outfile output pad parse partial partition password patindex percent_rank percentile_cont percentile_disc period_add period_diff pi plugin position pow power pragma precision prepare preserve primary prior privileges procedure procedure_analyze processlist profile profiles public publishingservername purge quarter query quick quote quotename radians rand read references regexp relative relaylog release release_lock rename repair repeat replace replicate reset restore restrict return returns reverse revoke right rlike rollback rollup round row row_count rows rpad rtrim savepoint schema scroll sec_to_time second section select serializable server session session_user set sha sha1 sha2 share show sign sin size slave sleep smalldatetimefromparts snapshot some soname soundex sounds_like space sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sql_variant_property sqlstate sqrt square start starting status std stddev stddev_pop stddev_samp stdev stdevp stop str str_to_date straight_join strcmp string stuff subdate substr substring subtime subtring_index sum switchoffset sysdate sysdatetime sysdatetimeoffset system_user sysutcdatetime table tables tablespace tan temporary terminated tertiary_weights then time time_format time_to_sec timediff timefromparts timestamp timestampadd timestampdiff timezone_hour timezone_minute to to_base64 to_days to_seconds todatetimeoffset trailing transaction translation trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse ucase uncompress uncompressed_length unhex unicode uninstall union unique unix_timestamp unknown unlock update upgrade upped upper usage use user user_resources using utc_date utc_time utc_timestamp uuid uuid_short validate_password_strength value values var var_pop var_samp variables variance varp version view warnings week weekday weekofyear weight_string when whenever where with work write xml xor year yearweek zon",literal:"true false null",built_in:"array bigint binary bit blob boolean char character date dec decimal float int integer interval number numeric real serial smallint varchar varying int8 serial8 text"},c:[{cN:"string",b:"'",e:"'",c:[e.BE,{b:"''"}]},{cN:"string",b:'"',e:'"',c:[e.BE,{b:'""'}]},{cN:"string",b:"`",e:"`",c:[e.BE]},e.CNM,e.CBCM,t]},e.CBCM,t]}});hljs.registerLanguage("python",function(e){var r={cN:"prompt",b:/^(>>>|\.\.\.) /},b={cN:"string",c:[e.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,c:[r],r:10},{b:/(u|b)?r?"""/,e:/"""/,c:[r],r:10},{b:/(u|r|ur)'/,e:/'/,r:10},{b:/(u|r|ur)"/,e:/"/,r:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)"/,e:/"/},e.ASM,e.QSM]},i={cN:"number",r:0,v:[{b:e.BNR+"[lLjJ]?"},{b:"\\b(0o[0-7]+)[lLjJ]?"},{b:e.CNR+"[lLjJ]?"}]},l={cN:"params",b:/\(/,e:/\)/,c:["self",r,i,b]},n={e:/:/,i:/[${=;\n]/,c:[e.UTM,l]};return{aliases:["py","gyp"],k:{keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda nonlocal|10 None True False",built_in:"Ellipsis NotImplemented"},i:/(<\/|->|\?)/,c:[r,i,b,e.HCM,e.inherit(n,{cN:"function",bK:"def",r:10}),e.inherit(n,{cN:"class",bK:"class"}),{cN:"decorator",b:/@/,e:/$/},{b:/\b(print|exec)\(/}]}});hljs.registerLanguage("perl",function(e){var t="getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when",r={cN:"subst",b:"[$@]\\{",e:"\\}",k:t},s={b:"->{",e:"}"},n={cN:"variable",v:[{b:/\$\d/},{b:/[\$\%\@](\^\w\b|#\w+(\:\:\w+)*|{\w+}|\w+(\:\:\w*)*)/},{b:/[\$\%\@][^\s\w{]/,r:0}]},o={cN:"comment",b:"^(__END__|__DATA__)",e:"\\n$",r:5},i=[e.BE,r,n],c=[n,e.HCM,o,{cN:"comment",b:"^\\=\\w",e:"\\=cut",eW:!0},s,{cN:"string",c:i,v:[{b:"q[qwxr]?\\s*\\(",e:"\\)",r:5},{b:"q[qwxr]?\\s*\\[",e:"\\]",r:5},{b:"q[qwxr]?\\s*\\{",e:"\\}",r:5},{b:"q[qwxr]?\\s*\\|",e:"\\|",r:5},{b:"q[qwxr]?\\s*\\<",e:"\\>",r:5},{b:"qw\\s+q",e:"q",r:5},{b:"'",e:"'",c:[e.BE]},{b:'"',e:'"'},{b:"`",e:"`",c:[e.BE]},{b:"{\\w+}",c:[],r:0},{b:"-?\\w+\\s*\\=\\>",c:[],r:0}]},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\/\\/|"+e.RSR+"|\\b(split|return|print|reverse|grep)\\b)\\s*",k:"split return print reverse grep",r:0,c:[e.HCM,o,{cN:"regexp",b:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",r:10},{cN:"regexp",b:"(m|qr)?/",e:"/[a-z]*",c:[e.BE],r:0}]},{cN:"sub",bK:"sub",e:"(\\s*\\(.*?\\))?[;{]",r:5},{cN:"operator",b:"-\\w\\b",r:0}];return r.c=c,s.c=c,{aliases:["pl"],k:t,c:c}});hljs.registerLanguage("apache",function(e){var r={cN:"number",b:"[\\$%]\\d+"};return{aliases:["apacheconf"],cI:!0,c:[e.HCM,{cN:"tag",b:"</?",e:">"},{cN:"keyword",b:/\w+/,r:0,k:{common:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{e:/$/,r:0,k:{literal:"on off all"},c:[{cN:"sqbracket",b:"\\s\\[",e:"\\]$"},{cN:"cbracket",b:"[\\$%]\\{",e:"\\}",c:["self",r]},r,e.QSM]}}],i:/\S/}});hljs.registerLanguage("xml",function(){var t="[A-Za-z0-9\\._:-]+",e={b:/<\?(php)?(?!\w)/,e:/\?>/,sL:"php",subLanguageMode:"continuous"},c={eW:!0,i:/</,r:0,c:[e,{cN:"attribute",b:t,r:0},{b:"=",r:0,c:[{cN:"value",c:[e],v:[{b:/"/,e:/"/},{b:/'/,e:/'/},{b:/[^\s\/>]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xsl","plist"],cI:!0,c:[{cN:"doctype",b:"<!DOCTYPE",e:">",r:10,c:[{b:"\\[",e:"\\]"}]},{cN:"comment",b:"<!--",e:"-->",r:10},{cN:"cdata",b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"tag",b:"<style(?=\\s|>|$)",e:">",k:{title:"style"},c:[c],starts:{e:"</style>",rE:!0,sL:"css"}},{cN:"tag",b:"<script(?=\\s|>|$)",e:">",k:{title:"script"},c:[c],starts:{e:"</script>",rE:!0,sL:"javascript"}},e,{cN:"pi",b:/<\?\w+/,e:/\?>/,r:10},{cN:"tag",b:"</?",e:"/?>",c:[{cN:"title",b:/[^ \/><\n\t]+/,r:0},c]}]}});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",a={cN:"function",b:c+"\\(",rB:!0,eE:!0,e:"\\("};return{cI:!0,i:"[=/|']",c:[e.CBCM,{cN:"id",b:"\\#[A-Za-z0-9_-]+"},{cN:"class",b:"\\.[A-Za-z0-9_-]+",r:0},{cN:"attr_selector",b:"\\[",e:"\\]",i:"$"},{cN:"pseudo",b:":(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\\\"\\']+"},{cN:"at_rule",b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{cN:"at_rule",b:"@",e:"[{;]",c:[{cN:"keyword",b:/\S+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[a,e.ASM,e.QSM,e.CSSNM]}]},{cN:"tag",b:c,r:0},{cN:"rules",b:"{",e:"}",i:"[^\\s]",r:0,c:[e.CBCM,{cN:"rule",b:"[^\\s]",rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:"[A-Z\\_\\.\\-]+",e:":",eE:!0,i:"[^\\s]",starts:{cN:"value",eW:!0,eE:!0,c:[a,e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"hexcolor",b:"#[0-9A-Fa-f]+"},{cN:"important",b:"!important"}]}}]}]}]}});hljs.registerLanguage("cpp",function(t){var e={keyword:"false int float while private char catch export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const struct for static_cast|10 union namespace unsigned long throw volatile static protected bool template mutable if public friend do return goto auto void enum else break new extern using true class asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue wchar_t inline delete alignof char16_t char32_t constexpr decltype noexcept nullptr static_assert thread_local restrict _Bool complex _Complex _Imaginary",built_in:"std string cin cout cerr clog stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf"};return{aliases:["c","h","c++","h++"],k:e,i:"</",c:[t.CLCM,t.CBCM,t.QSM,{cN:"string",b:"'\\\\?.",e:"'",i:"."},{cN:"number",b:"\\b(\\d+(\\.\\d*)?|\\.\\d+)(u|U|l|L|ul|UL|f|F)"},t.CNM,{cN:"preprocessor",b:"#",e:"$",k:"if else elif endif define undef warning error line pragma",c:[{b:'include\\s*[<"]',e:'[>"]',k:"include",i:"\\n"},t.CLCM]},{cN:"stl_container",b:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",e:">",k:e,c:["self"]},{b:t.IR+"::"}]}});hljs.registerLanguage("json",function(e){var t={literal:"true false null"},i=[e.QSM,e.CNM],l={cN:"value",e:",",eW:!0,eE:!0,c:i,k:t},c={b:"{",e:"}",c:[{cN:"attribute",b:'\\s*"',e:'"\\s*:\\s*',eB:!0,eE:!0,c:[e.BE],i:"\\n",starts:l}],i:"\\S"},n={b:"\\[",e:"\\]",c:[e.inherit(l,{cN:null})],i:"\\S"};return i.splice(i.length,0,c,n),{c:i,k:t,i:"\\S"}});hljs.registerLanguage("coffeescript",function(e){var c={keyword:"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super then unless until loop of by when and or is isnt not",literal:"true false null undefined yes no on off",reserved:"case default function var void with const let enum export import native __hasProp __extends __slice __bind __indexOf",built_in:"npm require console print module global window document"},n="[A-Za-z$_][0-9A-Za-z$_]*",t={cN:"subst",b:/#\{/,e:/}/,k:c},r=[e.BNM,e.inherit(e.CNM,{starts:{e:"(\\s*/)?",r:0}}),{cN:"string",v:[{b:/'''/,e:/'''/,c:[e.BE]},{b:/'/,e:/'/,c:[e.BE]},{b:/"""/,e:/"""/,c:[e.BE,t]},{b:/"/,e:/"/,c:[e.BE,t]}]},{cN:"regexp",v:[{b:"///",e:"///",c:[t,e.HCM]},{b:"//[gim]*",r:0},{b:/\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/}]},{cN:"property",b:"@"+n},{b:"`",e:"`",eB:!0,eE:!0,sL:"javascript"}];t.c=r;var i=e.inherit(e.TM,{b:n}),s="(\\(.*\\))?\\s*\\B[-=]>",o={cN:"params",b:"\\([^\\(]",rB:!0,c:[{b:/\(/,e:/\)/,k:c,c:["self"].concat(r)}]};return{aliases:["coffee","cson","iced"],k:c,i:/\/\*/,c:r.concat([{cN:"comment",b:"###",e:"###",c:[e.PWM]},e.HCM,{cN:"function",b:"^\\s*"+n+"\\s*=\\s*"+s,e:"[-=]>",rB:!0,c:[i,o]},{b:/[:\(,=]\s*/,r:0,c:[{cN:"function",b:s,e:"[-=]>",rB:!0,c:[o]}]},{cN:"class",bK:"class",e:"$",i:/[:="\[\]]/,c:[{bK:"extends",eW:!0,i:/[:="\[\]]/,c:[i]},i]},{cN:"attribute",b:n+":",e:":",rB:!0,rE:!0,r:0}])}});hljs.registerLanguage("php",function(e){var c={cN:"variable",b:"\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*"},i={cN:"preprocessor",b:/<\?(php)?|\?>/},a={cN:"string",c:[e.BE,i],v:[{b:'b"',e:'"'},{b:"b'",e:"'"},e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null})]},n={v:[e.BNM,e.CNM]};return{aliases:["php3","php4","php5","php6"],cI:!0,k:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally",c:[e.CLCM,e.HCM,{cN:"comment",b:"/\\*",e:"\\*/",c:[{cN:"phpdoc",b:"\\s@[A-Za-z]+"},i]},{cN:"comment",b:"__halt_compiler.+?;",eW:!0,k:"__halt_compiler",l:e.UIR},{cN:"string",b:"<<<['\"]?\\w+['\"]?$",e:"^\\w+;",c:[e.BE]},i,c,{b:/->+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{cN:"function",bK:"function",e:/[;{]/,eE:!0,i:"\\$|\\[|%",c:[e.UTM,{cN:"params",b:"\\(",e:"\\)",c:["self",c,e.CBCM,a,n]}]},{cN:"class",bK:"class interface",e:"{",eE:!0,i:/[:\(\$"]/,c:[{bK:"extends implements"},e.UTM]},{bK:"namespace",e:";",i:/[\.']/,c:[e.UTM]},{bK:"use",e:";",c:[e.UTM]},{b:"=>"},a,n]}});hljs.registerLanguage("nginx",function(e){var r={cN:"variable",v:[{b:/\$\d+/},{b:/\$\{/,e:/}/},{b:"[\\$\\@]"+e.UIR}]},b={eW:!0,l:"[a-z/_]+",k:{built_in:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},r:0,i:"=>",c:[e.HCM,{cN:"string",c:[e.BE,r],v:[{b:/"/,e:/"/},{b:/'/,e:/'/}]},{cN:"url",b:"([a-z]+):/",e:"\\s",eW:!0,eE:!0,c:[r]},{cN:"regexp",c:[e.BE,r],v:[{b:"\\s\\^",e:"\\s|{|;",rE:!0},{b:"~\\*?\\s+",e:"\\s|{|;",rE:!0},{b:"\\*(\\.[a-z\\-]+)+"},{b:"([a-z\\-]+\\.)+\\*"}]},{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{cN:"number",b:"\\b\\d+[kKmMgGdshdwy]*\\b",r:0},r]};return{aliases:["nginxconf"],c:[e.HCM,{b:e.UIR+"\\s",e:";|{",rB:!0,c:[{cN:"title",b:e.UIR,starts:b}],r:0}],i:"[^\\s\\}]"}});hljs.registerLanguage("diff",function(){return{aliases:["patch"],c:[{cN:"chunk",r:10,v:[{b:/^\@\@ +\-\d+,\d+ +\+\d+,\d+ +\@\@$/},{b:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{b:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{cN:"header",v:[{b:/Index: /,e:/$/},{b:/=====/,e:/=====$/},{b:/^\-\-\-/,e:/$/},{b:/^\*{3} /,e:/$/},{b:/^\+\+\+/,e:/$/},{b:/\*{5}/,e:/\*{5}$/}]},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"change",b:"^\\!",e:"$"}]}});hljs.registerLanguage("objectivec",function(e){var t={keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"NSString NSData NSDictionary CGRect CGPoint UIButton UILabel UITextView UIWebView MKMapView NSView NSViewController NSWindow NSWindowController NSSet NSUUID NSIndexSet UISegmentedControl NSObject UITableViewDelegate UITableViewDataSource NSThread UIActivityIndicator UITabbar UIToolBar UIBarButtonItem UIImageView NSAutoreleasePool UITableView BOOL NSInteger CGFloat NSException NSLog NSMutableString NSMutableArray NSMutableDictionary NSURL NSIndexPath CGSize UITableViewCell UIView UIViewController UINavigationBar UINavigationController UITabBarController UIPopoverController UIPopoverControllerDelegate UIImage NSNumber UISearchBar NSFetchedResultsController NSFetchedResultsChangeType UIScrollView UIScrollViewDelegate UIEdgeInsets UIColor UIFont UIApplication NSNotFound NSNotificationCenter NSNotification UILocalNotification NSBundle NSFileManager NSTimeInterval NSDate NSCalendar NSUserDefaults UIWindow NSRange NSArray NSError NSURLRequest NSURLConnection NSURLSession NSURLSessionDataTask NSURLSessionDownloadTask NSURLSessionUploadTask NSURLResponseUIInterfaceOrientation MPMoviePlayerController dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},o=/[a-zA-Z@][a-zA-Z0-9_]*/,a="@interface @class @protocol @implementation";return{aliases:["m","mm","objc","obj-c"],k:t,l:o,i:"</",c:[e.CLCM,e.CBCM,e.CNM,e.QSM,{cN:"string",v:[{b:'@"',e:'"',i:"\\n",c:[e.BE]},{b:"'",e:"[^\\\\]'",i:"[^\\\\][^']"}]},{cN:"preprocessor",b:"#",e:"$",c:[{cN:"title",v:[{b:'"',e:'"'},{b:"<",e:">"}]}]},{cN:"class",b:"("+a.split(" ").join("|")+")\\b",e:"({|$)",eE:!0,k:a,l:o,c:[e.UTM]},{cN:"variable",b:"\\."+e.UIR,r:0}]}});hljs.registerLanguage("makefile",function(e){var a={cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]};return{aliases:["mk","mak"],c:[e.HCM,{b:/^\w+\s*\W*=/,rB:!0,r:0,starts:{cN:"constant",e:/\s*\W*=/,eE:!0,starts:{e:/$/,r:0,c:[a]}}},{cN:"title",b:/^[\w]+:\s*$/},{cN:"phony",b:/^\.PHONY:/,e:/$/,k:".PHONY",l:/[\.\w]+/},{b:/^\t+/,e:/$/,r:0,c:[e.QSM,a]}]}});hljs.registerLanguage("ruby",function(e){var b="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",r="and false then defined module in return redo if BEGIN retry end for true self when next until do begin unless END rescue nil else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",c={cN:"yardoctag",b:"@[A-Za-z]+"},a={cN:"value",b:"#<",e:">"},s={cN:"comment",v:[{b:"#",e:"$",c:[c]},{b:"^\\=begin",e:"^\\=end",c:[c],r:10},{b:"^__END__",e:"\\n$"}]},n={cN:"subst",b:"#\\{",e:"}",k:r},t={cN:"string",c:[e.BE,n],v:[{b:/'/,e:/'/},{b:/"/,e:/"/},{b:/`/,e:/`/},{b:"%[qQwWx]?\\(",e:"\\)"},{b:"%[qQwWx]?\\[",e:"\\]"},{b:"%[qQwWx]?{",e:"}"},{b:"%[qQwWx]?<",e:">"},{b:"%[qQwWx]?/",e:"/"},{b:"%[qQwWx]?%",e:"%"},{b:"%[qQwWx]?-",e:"-"},{b:"%[qQwWx]?\\|",e:"\\|"},{b:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/}]},i={cN:"params",b:"\\(",e:"\\)",k:r},l=[t,a,s,{cN:"class",bK:"class module",e:"$|;",i:/=/,c:[e.inherit(e.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{cN:"inheritance",b:"<\\s*",c:[{cN:"parent",b:"("+e.IR+"::)?"+e.IR}]},s]},{cN:"function",bK:"def",e:" |$|;",r:0,c:[e.inherit(e.TM,{b:b}),i,s]},{cN:"constant",b:"(::)?(\\b[A-Z]\\w*(::)?)+",r:0},{cN:"symbol",b:e.UIR+"(\\!|\\?)?:",r:0},{cN:"symbol",b:":",c:[t,{b:b}],r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{cN:"variable",b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{b:"("+e.RSR+")\\s*",c:[a,s,{cN:"regexp",c:[e.BE,n],i:/\n/,v:[{b:"/",e:"/[a-z]*"},{b:"%r{",e:"}[a-z]*"},{b:"%r\\(",e:"\\)[a-z]*"},{b:"%r!",e:"![a-z]*"},{b:"%r\\[",e:"\\][a-z]*"}]}],r:0}];n.c=l,i.c=l;var u=[{b:/^\s*=>/,cN:"status",starts:{e:"$",c:l}},{cN:"prompt",b:/^\S[^=>\n]*>+/,starts:{e:"$",c:l}}];return{aliases:["rb","gemspec","podspec","thor","irb"],k:r,c:[s].concat(u).concat(l)}});hljs.registerLanguage("bash",function(e){var r={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)\}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,r,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]},t={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/-?[a-z\.]+/,k:{keyword:"if then else elif fi for break continue while in do done exit return set declare case esac export exec function",literal:"true false",built_in:"printf echo read cd pwd pushd popd dirs let eval unset typeset readonly getopts source shopt caller type hash bind help sudo",operator:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"shebang",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,e.NM,s,t,r]}});hljs.registerLanguage("cs",function(e){var r="abstract as base bool break byte case catch char checked const continue decimal default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long new null object operator out override params private protected public readonly ref return sbyte sealed short sizeof stackalloc static string struct switch this throw true try typeof uint ulong unchecked unsafe ushort using virtual volatile void while async await protected public private internal ascending descending from get group into join let orderby partial select set value var where yield",t=e.IR+"(<"+e.IR+">)?";return{aliases:["csharp"],k:r,i:/::/,c:[{cN:"comment",b:"///",e:"$",rB:!0,c:[{cN:"xmlDocTag",v:[{b:"///",r:0},{b:"<!--|-->"},{b:"</?",e:">"}]}]},e.CLCM,e.CBCM,{cN:"preprocessor",b:"#",e:"$",k:"if else elif endif define undef warning error line region endregion pragma checksum"},{cN:"string",b:'@"',e:'"',c:[{b:'""'}]},e.ASM,e.QSM,e.CNM,{bK:"class namespace interface",e:/[{;=]/,i:/[^\s:]/,c:[e.TM,e.CLCM,e.CBCM]},{bK:"new",e:/\s/,r:0},{cN:"function",b:"("+t+"\\s+)+"+e.IR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:r,c:[{b:e.IR+"\\s*\\(",rB:!0,c:[e.TM]},{cN:"params",b:/\(/,e:/\)/,k:r,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]}]}});hljs.registerLanguage("markdown",function(){return{aliases:["md","mkdown","mkd"],c:[{cN:"header",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"blockquote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"`.+?`"},{b:"^( {4}|	)",e:"$",r:0}]},{cN:"horizontal_rule",b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].*?[\\)\\]]",rB:!0,c:[{cN:"link_label",b:"\\[",e:"\\]",eB:!0,rE:!0,r:0},{cN:"link_url",b:"\\]\\(",e:"\\)",eB:!0,eE:!0},{cN:"link_reference",b:"\\]\\[",e:"\\]",eB:!0,eE:!0}],r:10},{b:"^\\[.+\\]:",rB:!0,c:[{cN:"link_reference",b:"\\[",e:"\\]:",eB:!0,eE:!0,starts:{cN:"link_url",e:"$"}}]}]}});hljs.registerLanguage("ini",function(e){return{cI:!0,i:/\S/,c:[{cN:"comment",b:";",e:"$"},{cN:"title",b:"^\\[",e:"\\]"},{cN:"setting",b:"^[a-z0-9\\[\\]_-]+[ \\t]*=[ \\t]*",e:"$",c:[{cN:"value",eW:!0,k:"on off true false yes no",c:[e.QSM,e.NM],r:0}]}]}});hljs.registerLanguage("http",function(){return{i:"\\S",c:[{cN:"status",b:"^HTTP/[0-9\\.]+",e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{cN:"request",b:"^[A-Z]+ (.*?) HTTP/[0-9\\.]+$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{cN:"string",e:"$"}},{b:"\\n\\n",starts:{sL:"",eW:!0}}]}});hljs.registerLanguage("java",function(e){var t=e.UIR+"(<"+e.UIR+">)?",a="false synchronized int abstract float private char boolean static null if const for true while long throw strictfp finally protected import native final return void enum else break transient new catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private";return{aliases:["jsp"],k:a,i:/<\//,c:[{cN:"javadoc",b:"/\\*\\*",e:"\\*/",r:0,c:[{cN:"javadoctag",b:"(^|\\s)@[A-Za-z]+"}]},e.CLCM,e.CBCM,e.ASM,e.QSM,{cN:"class",bK:"class interface",e:/[{;=]/,eE:!0,k:"class interface",i:/[:"\[\]]/,c:[{bK:"extends implements"},e.UTM]},{bK:"new throw",e:/\s/,r:0},{cN:"function",b:"("+t+"\\s+)+"+e.UIR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:a,c:[{b:e.UIR+"\\s*\\(",rB:!0,c:[e.UTM]},{cN:"params",b:/\(/,e:/\)/,k:a,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]},e.CNM,{cN:"annotation",b:"@[A-Za-z]+"}]}});
\ No newline at end of file
diff --git a/docs/js/react-video.min.js b/docs/js/react-video.min.js
deleted file mode 100644
index b9ba007..0000000
--- a/docs/js/react-video.min.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * React Video - React component to load video from Vimeo or Youtube across any device
- * @version v1.3.0
- * @link https://github.com/pedronauck/react-video
- * @license MIT
- * @author Pedro Nauck (https://github.com/pedronauck)
-*/
-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports.ReactVideo=t(require("react")):e.ReactVideo=t(e.React)}(this,function(e){return function(e){function t(i){if(o[i])return o[i].exports;var r=o[i]={exports:{},id:i,loaded:!1};return e[i].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var o={};return t.m=e,t.c=o,t.p="",t(0)}([function(e,t,o){var i=o(1),r=(o(2),o(3)),n=o(4),s=o(5);e.exports=i.createClass({displayName:"Video",propTypes:{from:i.PropTypes.oneOf(["youtube","vimeo"]),videoId:i.PropTypes.string.isRequired},getDefaultProps:function(){return{className:"video"}},getInitialState:function(){return{thumb:null,imageLoaded:!1,showingVideo:!1}},isYoutube:function(){return"youtube"===this.props.from||isNaN(this.props.id)},isVimeo:function(){return"vimeo"===this.props.from||!isNaN(this.props.id)},componentDidMount:function(){this.isYoutube()&&this.fetchYoutubeData(),this.isVimeo()&&this.fetchVimeoData()},render:function(){return i.DOM.div({className:this.props.className},!this.state.imageLoaded&&s(null),this.renderImage(),this.renderIframe())},renderImage:function(){var e={backgroundImage:"url("+this.state.thumb+")"};return this.state.imageLoaded&&!this.state.showingVideo?i.DOM.div({className:"video-image",style:e},n({onClick:this.playVideo})):void 0},renderIframe:function(){var e={display:this.state.showingVideo?"block":"none",width:"100%",height:"100%"};return this.state.showingVideo?i.DOM.div({className:"video-embed",style:e},i.DOM.iframe({frameborder:"0",src:this.getIframeUrl()})):void 0},playVideo:function(e){this.setState({showingVideo:!0}),e.preventDefault()},getIframeUrl:function(){return this.isYoutube()?"//youtube.com/embed/"+this.props.videoId+"?autoplay=1":this.isVimeo()?"//player.vimeo.com/video/"+this.props.videoId+"?autoplay=1":void 0},fetchYoutubeData:function(){var e=this.props.videoId,t="//gdata.youtube.com/feeds/api/videos/"+e+"?v=2&alt=json";r.get(t,function(e,t){var o=t.entry.media$group.media$thumbnail,i=o.sort(function(e,t){return t.width-e.width})[0].url;this.setState({thumb:i,imageLoaded:!0})}.bind(this))},fetchVimeoData:function(){var e=this.props.videoId,t="//vimeo.com/api/v2/video/"+e+".json";r.get(t,function(e,t){this.setState({thumb:t[0].thumbnail_large,imageLoaded:!0})}.bind(this))}})},function(t){t.exports=e},function(e){e.exports=function(e){return"object"!=typeof e?Array.prototype.join.call(arguments," "):Object.keys(e).filter(function(t){return e[t]}).join(" ")}},function(e){var t=function(e,t){var o=!1,i=function(){t(null,JSON.parse(o.responseText))},r=function(){4===o.readyState&&(200===o.status?t(null,JSON.parse(o.responseText)):t({error:"Sorry, an error ocurred on the server"},null))},n=function(){t({error:"Problem with your internet conection"},null)};try{o=new XDomainRequest,o.onload=i}catch(s){o=new XMLHttpRequest,o.onreadystatechange=r}o.onerror=n,o.open("GET",e,!0),o.send()};e.exports={get:t}},function(e,t,o){var i=o(1);e.exports=i.createClass({displayName:"exports",propTypes:{onClick:i.PropTypes.func},render:function(){return i.DOM.button({type:"button",className:"video-play-button",onClick:this.props.onClick},i.DOM.svg({xmlns:"http://www.w3.org/2000/svg",version:"1.1",viewBox:"0 0 100 100"},i.DOM.path({d:"M79.674,53.719c2.59-2.046,2.59-5.392,0-7.437L22.566,1.053C19.977-0.993,18,0.035,18,3.335v93.331c0,3.3,1.977,4.326,4.566,2.281L79.674,53.719z"})))}})},function(e,t,o){var i=o(1);e.exports=i.createClass({displayName:"exports",render:function(){return i.DOM.div({className:"video-loading"},i.DOM.svg({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",width:"32",height:"32"},i.DOM.path({opacity:".25",d:"M16 0 A16 16 0 0 0 16 32 A16 16 0 0 0 16 0 M16 4 A12 12 0 0 1 16 28 A12 12 0 0 1 16 4"}),i.DOM.path({d:"M16 0 A16 16 0 0 1 32 16 L28 16 A12 12 0 0 0 16 4z"})))}})}])});
diff --git a/example/index.html b/example/index.html
index d6439e7..793aca5 100644
--- a/example/index.html
+++ b/example/index.html
@@ -28,25 +28,15 @@
   </head>
   <body>
     <div class="content">
-      <div id="video-youtube"></div>
-      <div id="video-vimeo"></div>
+      <div id="vimeo"></div>
     </div>
 
-    <script src="//cdnjs.cloudflare.com/ajax/libs/react/0.12.2/react-with-addons.min.js"></script>
-    <script src="//cdnjs.cloudflare.com/ajax/libs/react/0.12.2/JSXTransformer.js"></script>
-    <script src="react-video.js"></script>
-    <script type="text/jsx">
-      /** @jsx React.DOM */
-      var Video = ReactVideo;
-
-      React.render(
-        <Video videoId='jhg8XRTorYg' />,
-        document.getElementById('video-youtube')
-      );
-
+    <script src="//cdnjs.cloudflare.com/ajax/libs/react/0.13.3/react.js"></script>
+    <script src="vimeo.js"></script>
+    <script type="text/javascript">
       React.render(
-        <Video videoId='108843586' />,
-        document.getElementById('video-vimeo')
+        React.createElement(ReactVimeo, { videoId: '108843586' }),
+        document.getElementById('vimeo')
       );
     </script>
   </body>
diff --git a/gulpfile.js b/gulpfile.js
deleted file mode 100644
index 1bbc675..0000000
--- a/gulpfile.js
+++ /dev/null
@@ -1,85 +0,0 @@
-'use strict';
-
-var gulp = require('gulp'),
-    deploy = require('gulp-gh-pages'),
-    gutil = require('gulp-util'),
-    shell = require('gulp-shell'),
-    stylus = require('gulp-stylus'),
-    header = require('gulp-header'),
-    rename = require('gulp-rename'),
-    minifyCSS = require('gulp-minify-css'),
-    browserSync = require('browser-sync'),
-    argv = require('yargs').argv,
-    webpack = require('webpack'),
-    webpackConfig = require('./webpack.config.js'),
-    nib = require('nib');
-
-gulp.task('webpack', function(callback) {
-  var jsFilename = webpackConfig.output.filename;
-
-  if (argv.production || argv.p) {
-    webpackConfig.output.filename = gutil.replaceExtension(jsFilename, '.min.js');
-    webpackConfig.plugins = webpackConfig.plugins.concat(
-      new webpack.DefinePlugin({
-        'process.env': { 'NODE_ENV': JSON.stringify('production') }
-      }),
-      new webpack.optimize.DedupePlugin(),
-      new webpack.optimize.UglifyJsPlugin()
-    );
-  }
-
-  webpack(webpackConfig).run(function(err, stats) {
-    if (err) {
-      throw new gutil.PluginError('webpack', err);
-    }
-
-    gutil.log('[webpack]', stats.toString({ colors: true }));
-    callback();
-  });
-});
-
-gulp.task('css', function () {
-  if (argv.production || argv.p) {
-    return gulp.src('./dist/react-video.css')
-      .pipe(minifyCSS())
-      .pipe(rename({ suffix: '.min'}))
-      .pipe(header(require('./utils/banner')))
-      .pipe(gulp.dest('./dist'));
-  }
-  else {
-    return gulp.src('./lib/*.styl')
-      .pipe(stylus({ use: [nib()], errors: true }))
-      .pipe(header(require('./utils/banner')))
-      .pipe(gulp.dest('./dist'));
-  }
-});
-
-gulp.task('server', function() {
-  browserSync({
-    open: false,
-    notify: false,
-    server: {
-      baseDir: ['example', 'dist']
-    }
-  });
-});
-
-gulp.task('watch', function() {
-  gulp.watch('./lib/**/*.jsx', ['webpack', browserSync.reload]);
-  gulp.watch('./lib/*.styl', ['css', browserSync.reload]);
-});
-
-gulp.task('deploy', function () {
-  gulp.src('./docs/**/*')
-    .pipe(deploy());
-});
-
-gulp.task('bundle', shell.task([
-  'gulp webpack',
-  'gulp webpack -p',
-  'gulp css',
-  'gulp css -p',
-  'gulp deploy'
-]));
-
-gulp.task('default', ['css', 'webpack', 'server', 'watch']);
diff --git a/lib/Vimeo.css b/lib/Vimeo.css
new file mode 100644
index 0000000..1bdb4b9
--- /dev/null
+++ b/lib/Vimeo.css
@@ -0,0 +1,97 @@
+.vimeo-image,
+.vimeo-image:after,
+.vimeo-embed {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+}
+.vimeo {
+  position: relative;
+  padding-bottom: 56.25%;
+  background: #e2e2e2;
+}
+.vimeo iframe {
+  border: 0;
+}
+.vimeo-image {
+  background-position: center center;
+  background-size: 100% auto;
+}
+.vimeo-image:after {
+  z-index: 1;
+  display: block;
+  content: '';
+  background: rgba(0,0,0,0.3);
+}
+.vimeo-play-button,
+.vimeo-loading {
+  top: 50%;
+  left: 50%;
+  transform: translateX(-50%) translateY(-50%);
+}
+.vimeo-play-button {
+  z-index: 2;
+  position: absolute;
+  padding: 0;
+  width: 70px;
+  border: 0;
+  background: none;
+}
+.vimeo-play-button:focus {
+  outline: none;
+}
+.vimeo-play-button svg {
+  fill: #fff;
+  -webkit-filter: drop-shadow(0 1px 1px rgba(0,0,0,0.8));
+  filter: drop-shadow(0 1px 1px rgba(0,0,0,0.8));
+}
+.vimeo-loading {
+  z-index: 4;
+  position: absolute;
+  width: 32px;
+  height: 32px;
+}
+.vimeo-loading svg {
+  fill: #000;
+  transform-origin: 50% 50%;
+  -webkit-animation: spinner 0.8s infinite linear;
+  animation: spinner 0.8s infinite linear;
+}
+.vimeo-embed iframe {
+  width: 100%;
+  height: 100%;
+}
+@-moz-keyframes spinner {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+@-webkit-keyframes spinner {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+@-o-keyframes spinner {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+@keyframes spinner {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
diff --git a/lib/Vimeo.min.css b/lib/Vimeo.min.css
new file mode 100644
index 0000000..d9ba827
--- /dev/null
+++ b/lib/Vimeo.min.css
@@ -0,0 +1 @@
+.vimeo-image,.vimeo-image:after,.vimeo-embed{position:absolute;top:0;left:0;width:100%;height:100%}.vimeo{position:relative;padding-bottom:56.25%;background:#e2e2e2;}.vimeo iframe{border:0}.vimeo-image{background-position:center center;background-size:100% auto;}.vimeo-image:after{z-index:1;display:block;content:'';background:rgba(0,0,0,0.3)}.vimeo-play-button,.vimeo-loading{top:50%;left:50%;transform:translateX(-50%) translateY(-50%)}.vimeo-play-button{z-index:2;position:absolute;padding:0;width:70px;border:0;background:none;}.vimeo-play-button:focus{outline:none}.vimeo-play-button svg{fill:#fff;-webkit-filter:drop-shadow(0 1px 1px rgba(0,0,0,0.8));filter:drop-shadow(0 1px 1px rgba(0,0,0,0.8))}.vimeo-loading{z-index:4;position:absolute;width:32px;height:32px;}.vimeo-loading svg{fill:#000;transform-origin:50% 50%;-webkit-animation:spinner .8s infinite linear;animation:spinner .8s infinite linear}.vimeo-embed iframe{width:100%;height:100%}@-moz-keyframes spinner{from{transform:rotate(0)}to{transform:rotate(360deg)}}@-webkit-keyframes spinner{from{transform:rotate(0)}to{transform:rotate(360deg)}}@-o-keyframes spinner{from{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes spinner{from{transform:rotate(0)}to{transform:rotate(360deg)}}
\ No newline at end of file
diff --git a/lib/Vimeo.styl b/lib/Vimeo.styl
new file mode 100644
index 0000000..eae843c
--- /dev/null
+++ b/lib/Vimeo.styl
@@ -0,0 +1,112 @@
+// ----------------------------------------------------------------------------
+//
+//  React Vimeo
+//
+// ----------------------------------------------------------------------------
+
+$full-width {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+}
+
+.vimeo {
+  position: relative;
+  padding-bottom: 56.25%;
+  background: #E2E2E2;
+
+  iframe {
+    border: 0;
+  }
+}
+
+// ----------------------------------------------------------------------------
+//  Video Image
+// ----------------------------------------------------------------------------
+
+.vimeo-image {
+  @extends $full-width;
+  background-position: center center;
+  background-size: 100% auto;
+
+  &:after {
+    @extends $full-width;
+    z-index: 1;
+    display: block;
+    content: '';
+    background: rgba(black, .3);
+  }
+}
+
+// ----------------------------------------------------------------------------
+//  Play Button
+// ----------------------------------------------------------------------------
+
+$to-center {
+  top: 50%;
+  left: 50%;
+  transform: translateX(-50%) translateY(-50%);
+}
+
+.vimeo-play-button {
+  @extends $to-center;
+  z-index: 2;
+  position: absolute;
+  padding: 0;
+  width: 70px;
+  border: 0;
+  background: none;
+
+  &:focus {
+    outline: none;
+  }
+
+  svg {
+    fill: white;
+    -webkit-filter: drop-shadow(0 1px 1px rgba(black, .8));
+            filter: drop-shadow(0 1px 1px rgba(black, .8));
+  }
+}
+
+// ----------------------------------------------------------------------------
+//  Loading Spinner
+// ----------------------------------------------------------------------------
+
+.vimeo-loading {
+  @extends $to-center;
+  z-index: 4;
+  position: absolute;
+  width: 32px;
+  height: 32px;
+
+  svg {
+    fill: black;
+    transform-origin: 50% 50%;
+    -webkit-animation: spinner .8s infinite linear;
+            animation: spinner .8s infinite linear;
+  }
+}
+
+@keyframes spinner {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+// ----------------------------------------------------------------------------
+//  Video Embed
+// ----------------------------------------------------------------------------
+
+.vimeo-embed {
+  @extends $full-width;
+
+  iframe {
+    width: 100%;
+    height: 100%;
+  }
+}
diff --git a/lib/components/play-button.jsx b/lib/components/play-button.jsx
deleted file mode 100644
index a6d6a1b..0000000
--- a/lib/components/play-button.jsx
+++ /dev/null
@@ -1,16 +0,0 @@
-var React = require('react');
-
-module.exports = React.createClass({
-  propTypes: {
-    onClick: React.PropTypes.func
-  },
-  render() {
-    return (
-      <button type='button' className='video-play-button' onClick={this.props.onClick}>
-        <svg xmlns='http://www.w3.org/2000/svg' version='1.1' viewBox='0 0 100 100'>
-          <path d="M79.674,53.719c2.59-2.046,2.59-5.392,0-7.437L22.566,1.053C19.977-0.993,18,0.035,18,3.335v93.331c0,3.3,1.977,4.326,4.566,2.281L79.674,53.719z"/>
-        </svg>
-      </button>
-    );
-  }
-});
diff --git a/lib/components/spinner.jsx b/lib/components/spinner.jsx
deleted file mode 100644
index 533d64d..0000000
--- a/lib/components/spinner.jsx
+++ /dev/null
@@ -1,14 +0,0 @@
-var React = require('react');
-
-module.exports = React.createClass({
-  render() {
-    return (
-      <div className='video-loading'>
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32">
-          <path opacity=".25" d="M16 0 A16 16 0 0 0 16 32 A16 16 0 0 0 16 0 M16 4 A12 12 0 0 1 16 28 A12 12 0 0 1 16 4"/>
-          <path d="M16 0 A16 16 0 0 1 32 16 L28 16 A12 12 0 0 0 16 4z"></path>
-        </svg>
-      </div>
-    );
-  }
-});
diff --git a/lib/react-video.jsx b/lib/react-video.jsx
deleted file mode 100644
index 344f71b..0000000
--- a/lib/react-video.jsx
+++ /dev/null
@@ -1,135 +0,0 @@
-var React = require('react');
-var classSet = require('../utils/classSet');
-var ajax = require('../utils/ajax');
-var PlayButton = require('./components/play-button');
-var Spinner = require('./components/spinner');
-
-module.exports = React.createClass({
-  displayName: 'Video',
-  propTypes: {
-    from: React.PropTypes.oneOf(['youtube', 'vimeo']),
-    videoId: React.PropTypes.string.isRequired,
-    onError: React.PropTypes.func
-  },
-  getDefaultProps() {
-    return {
-      className: 'video'
-    };
-  },
-  getInitialState() {
-    return {
-      thumb: null,
-      imageLoaded: false,
-      showingVideo: false
-    };
-  },
-  isYoutube() {
-    return this.props.from === 'youtube' || isNaN(this.props.videoId);
-  },
-  isVimeo() {
-    return this.props.from === 'vimeo' || !isNaN(this.props.videoId);
-  },
-  componentWillReceiveProps(nextProps) {
-    if (nextProps.className !== this.props.className || nextProps.from !== this.props.from || nextProps.videoId !== this.props.videoId) {
-      this.setState({
-        thumb: null,
-        imageLoaded: false,
-        showingVideo: false
-      });
-    }
-  },
-  componentDidMount() {
-    if (!this.state.imageLoaded) {
-      this.isYoutube() && this.fetchYoutubeData();
-      this.isVimeo() && this.fetchVimeoData();
-    }
-  },
-  componentDidUpdate() {
-    if (!this.state.imageLoaded) {
-      this.isYoutube() && this.fetchYoutubeData();
-      this.isVimeo() && this.fetchVimeoData();
-    }
-  },
-  render() {
-    return (
-      <div className={this.props.className} >
-        {!this.state.imageLoaded && <Spinner />}
-        {this.renderImage()}
-        {this.renderIframe()}
-      </div>
-    );
-  },
-  renderImage() {
-    var style = {
-      backgroundImage: `url(${this.state.thumb})`
-    };
-
-    if (this.state.imageLoaded && !this.state.showingVideo) {
-      return (
-        <div className='video-image' style={style}>
-          <PlayButton onClick={this.playVideo} />
-        </div>
-      );
-    }
-  },
-  renderIframe() {
-    var embedVideoStyle = {
-      display: this.state.showingVideo ? 'block' : 'none',
-      width: '100%',
-      height: '100%'
-    };
-
-    if (this.state.showingVideo) {
-      return (
-        <div className='video-embed' style={embedVideoStyle}>
-          <iframe frameBorder='0' src={this.getIframeUrl()}></iframe>
-        </div>
-      );
-    }
-  },
-  playVideo(ev) {
-    this.setState({ showingVideo: true });
-    ev.preventDefault();
-  },
-  getIframeUrl() {
-    if (this.isYoutube()) {
-      return `//youtube.com/embed/${this.props.videoId}?autoplay=1`
-    }
-    else if (this.isVimeo()) {
-      return `//player.vimeo.com/video/${this.props.videoId}?autoplay=1`
-    }
-  },
-  fetchYoutubeData() {
-    var id = this.props.videoId;
-    var that = this;
-
-    ajax.get({
-      url: `//gdata.youtube.com/feeds/api/videos/${id}?v=2&alt=json`,
-      onSuccess(err, res) {
-        var gallery = res.entry['media$group']['media$thumbnail'];
-        var thumb = gallery.sort((a, b) => b.width - a.width)[0].url;
-
-        that.setState({
-          thumb: thumb,
-          imageLoaded: true
-        })
-      },
-      onError: that.props.onError
-    });
-  },
-  fetchVimeoData() {
-    var id = this.props.videoId;
-    var that = this;
-
-    ajax.get({
-      url: `//vimeo.com/api/v2/video/${id}.json`,
-      onSuccess(err, res) {
-        that.setState({
-          thumb: res[0].thumbnail_large,
-          imageLoaded: true
-        });
-      },
-      onError: that.props.onError
-    });
-  }
-});
diff --git a/lib/react-video.scss b/lib/react-video.scss
deleted file mode 100644
index 7ba3908..0000000
--- a/lib/react-video.scss
+++ /dev/null
@@ -1,112 +0,0 @@
-// ----------------------------------------------------------------------------
-//
-//  React Video
-//
-// ----------------------------------------------------------------------------
-
-%full-width {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-}
-
-.video {
-  position: relative;
-  padding-bottom: 56.25%;
-  background: #E2E2E2;
-
-  iframe {
-    border: 0;
-  }
-}
-
-// ----------------------------------------------------------------------------
-//  Video Image
-// ----------------------------------------------------------------------------
-
-.video-image {
-  @extend %full-width;
-  background-position: center center;
-  background-size: 100% auto;
-
-  &:after {
-    @extend %full-width;
-    z-index: 1;
-    display: block;
-    content: '';
-    background: rgba(black, .3);
-  }
-}
-
-// ----------------------------------------------------------------------------
-//  Play Button
-// ----------------------------------------------------------------------------
-
-%to-center {
-  top: 50%;
-  left: 50%;
-  transform: translateX(-50%) translateY(-50%);
-}
-
-.video-play-button {
-  @extend %to-center;
-  z-index: 2;
-  position: absolute;
-  padding: 0;
-  width: 70px;
-  border: 0;
-  background: none;
-
-  &:focus {
-    outline: none;
-  }
-
-  svg {
-    fill: white;
-    -webkit-filter: drop-shadow(0 1px 1px rgba(black, .8));
-            filter: drop-shadow(0 1px 1px rgba(black, .8));
-  }
-}
-
-// ----------------------------------------------------------------------------
-//  Loading Spinner
-// ----------------------------------------------------------------------------
-
-.video-loading {
-  @extend %to-center;
-  z-index: 4;
-  position: absolute;
-  width: 32px;
-  height: 32px;
-
-  svg {
-    fill: black;
-    transform-origin: 50% 50%;
-    -webkit-animation: spinner .8s infinite linear;
-            animation: spinner .8s infinite linear;
-  }
-}
-
-@keyframes spinner {
-  from {
-    transform: rotate(0deg);
-  }
-  to {
-    transform: rotate(360deg);
-  }
-}
-
-// ----------------------------------------------------------------------------
-//  Video Embed
-// ----------------------------------------------------------------------------
-
-.video-embed {
-  @extend %full-width;
-
-  iframe {
-    width: 100%;
-    height: 100%;
-  }
-}
diff --git a/lib/react-video.styl b/lib/react-video.styl
deleted file mode 100644
index 16d1433..0000000
--- a/lib/react-video.styl
+++ /dev/null
@@ -1,112 +0,0 @@
-// ----------------------------------------------------------------------------
-//
-//  React Video
-//
-// ----------------------------------------------------------------------------
-
-$full-width {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-}
-
-.video {
-  position: relative;
-  padding-bottom: 56.25%;
-  background: #E2E2E2;
-
-  iframe {
-    border: 0;
-  }
-}
-
-// ----------------------------------------------------------------------------
-//  Video Image
-// ----------------------------------------------------------------------------
-
-.video-image {
-  @extends $full-width;
-  background-position: center center;
-  background-size: 100% auto;
-
-  &:after {
-    @extends $full-width;
-    z-index: 1;
-    display: block;
-    content: '';
-    background: rgba(black, .3);
-  }
-}
-
-// ----------------------------------------------------------------------------
-//  Play Button
-// ----------------------------------------------------------------------------
-
-$to-center {
-  top: 50%;
-  left: 50%;
-  transform: translateX(-50%) translateY(-50%);
-}
-
-.video-play-button {
-  @extends $to-center;
-  z-index: 2;
-  position: absolute;
-  padding: 0;
-  width: 70px;
-  border: 0;
-  background: none;
-
-  &:focus {
-    outline: none;
-  }
-
-  svg {
-    fill: white;
-    -webkit-filter: drop-shadow(0 1px 1px rgba(black, .8));
-            filter: drop-shadow(0 1px 1px rgba(black, .8));
-  }
-}
-
-// ----------------------------------------------------------------------------
-//  Loading Spinner
-// ----------------------------------------------------------------------------
-
-.video-loading {
-  @extends $to-center;
-  z-index: 4;
-  position: absolute;
-  width: 32px;
-  height: 32px;
-
-  svg {
-    fill: black;
-    transform-origin: 50% 50%;
-    -webkit-animation: spinner .8s infinite linear;
-            animation: spinner .8s infinite linear;
-  }
-}
-
-@keyframes spinner {
-  from {
-    transform: rotate(0deg);
-  }
-  to {
-    transform: rotate(360deg);
-  }
-}
-
-// ----------------------------------------------------------------------------
-//  Video Embed
-// ----------------------------------------------------------------------------
-
-.video-embed {
-  @extends $full-width;
-
-  iframe {
-    width: 100%;
-    height: 100%;
-  }
-}
diff --git a/lib/umd/ReactVimeo.js b/lib/umd/ReactVimeo.js
new file mode 100644
index 0000000..732763e
--- /dev/null
+++ b/lib/umd/ReactVimeo.js
@@ -0,0 +1,884 @@
+/*
+ * React-Vimeo - React component to load video from Vimeo or Youtube across any device
+ * @version v0.0.1
+ * @link https://github.com/freecodecamp/react-vimeo
+ * @license MIT
+ * @author Berkeley Martinez (https://github.com/berkeleytrue)
+*/
+
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory(require("react"));
+	else if(typeof define === 'function' && define.amd)
+		define(["react"], factory);
+	else if(typeof exports === 'object')
+		exports["ReactVimeo"] = factory(require("react"));
+	else
+		root["ReactVimeo"] = factory(root["React"]);
+})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId])
+/******/ 			return installedModules[moduleId].exports;
+
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			exports: {},
+/******/ 			id: moduleId,
+/******/ 			loaded: false
+/******/ 		};
+
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/ 		// Flag the module as loaded
+/******/ 		module.loaded = true;
+
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+
+
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ function(module, exports, __webpack_require__) {
+
+	'use strict';
+
+	Object.defineProperty(exports, '__esModule', {
+	  value: true
+	});
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
+
+	var _react = __webpack_require__(1);
+
+	var _react2 = _interopRequireDefault(_react);
+
+	var _PlayButtonJsx = __webpack_require__(2);
+
+	var _PlayButtonJsx2 = _interopRequireDefault(_PlayButtonJsx);
+
+	var _SpinnerJsx = __webpack_require__(3);
+
+	var _SpinnerJsx2 = _interopRequireDefault(_SpinnerJsx);
+
+	var _ajax = __webpack_require__(4);
+
+	var _ajax2 = _interopRequireDefault(_ajax);
+
+	exports['default'] = _react2['default'].createClass({
+	  displayName: 'Vimeo',
+
+	  propTypes: {
+	    className: _react.PropTypes.string,
+	    loading: _react.PropTypes.element,
+	    onError: _react.PropTypes.func,
+	    playButton: _react.PropTypes.node,
+	    videoId: _react.PropTypes.string.isRequired
+	  },
+
+	  getDefaultProps: function getDefaultProps() {
+	    return {
+	      className: 'video'
+	    };
+	  },
+
+	  getInitialState: function getInitialState() {
+	    return {
+	      thumb: null,
+	      imageLoaded: false,
+	      showingVideo: false
+	    };
+	  },
+
+	  componentWillReceiveProps: function componentWillReceiveProps(nextProps) {
+	    if (nextProps.className !== this.props.className || nextProps.videoId !== this.props.videoId) {
+	      this.setState({
+	        thumb: null,
+	        imageLoaded: false,
+	        showingVideo: false
+	      });
+	    }
+	  },
+
+	  componentDidMount: function componentDidMount() {
+	    this.fetchVimeoData();
+	  },
+
+	  componentDidUpdate: function componentDidUpdate() {
+	    this.fetchVimeoData();
+	  },
+
+	  playVideo: function playVideo(e) {
+	    e.preventDefault();
+	    this.setState({ showingVideo: true });
+	  },
+
+	  getIframeUrl: function getIframeUrl() {
+	    return '//player.vimeo.com/video/' + this.props.videoId + '?autoplay=1';
+	  },
+
+	  fetchVimeoData: function fetchVimeoData() {
+	    var _this = this;
+
+	    if (!this.state.imageLoaded) {
+	      return;
+	    }
+	    var id = this.props.videoId;
+
+	    _ajax2['default'].get({
+	      url: '//vimeo.com/api/v2/video/' + id + '.json',
+	      onSuccess: function onSuccess(res) {
+	        _this.setState({
+	          thumb: res[0].thumbnail_large,
+	          imageLoaded: true
+	        });
+	      },
+	      onError: this.props.onError || function () {}
+	    });
+	  },
+
+	  renderImage: function renderImage() {
+	    if (!this.state.imageLoaded || this.state.showingVideo) {
+	      return;
+	    }
+
+	    var style = {
+	      backgroundImage: 'url(' + this.state.thumb + ')',
+	      display: this.state.showingVideo ? 'block' : 'none',
+	      height: '100%',
+	      width: '100%'
+	    };
+
+	    return _react2['default'].createElement(
+	      'div',
+	      { className: 'video-image', style: style },
+	      _react2['default'].createElement(_PlayButtonJsx2['default'], { onClick: this.playVideo })
+	    );
+	  },
+
+	  renderIframe: function renderIframe() {
+	    if (!this.state.showingVideo) {
+	      return;
+	    }
+
+	    var embedVideoStyle = {
+	      display: this.state.showingVideo ? 'block' : 'none',
+	      height: '100%',
+	      width: '100%'
+	    };
+
+	    return _react2['default'].createElement(
+	      'div',
+	      { className: 'video-embed', style: embedVideoStyle },
+	      _react2['default'].createElement('iframe', { frameBorder: '0', src: this.getIframeUrl() })
+	    );
+	  },
+
+	  renderLoading: function renderLoading(imageLoaded, loadingElement) {
+	    if (imageLoaded) {
+	      return;
+	    }
+	    if (loadingElement) {
+	      return loadingElement;
+	    }
+	    return _react2['default'].createElement(_SpinnerJsx2['default'], null);
+	  },
+
+	  render: function render() {
+	    return _react2['default'].createElement(
+	      'div',
+	      { className: this.props.className },
+	      this.renderLoading(this.state.imageLoaded, this.props.loading),
+	      this.renderImage(),
+	      this.renderIframe()
+	    );
+	  }
+	});
+	module.exports = exports['default'];
+
+/***/ },
+/* 1 */
+/***/ function(module, exports) {
+
+	module.exports = __WEBPACK_EXTERNAL_MODULE_1__;
+
+/***/ },
+/* 2 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/* eslint-disable max-len */
+	'use strict';
+
+	Object.defineProperty(exports, '__esModule', {
+	  value: true
+	});
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
+
+	var _react = __webpack_require__(1);
+
+	var _react2 = _interopRequireDefault(_react);
+
+	exports['default'] = _react2['default'].createClass({
+	  displayName: 'PlayButton',
+
+	  propTypes: {
+	    onClick: _react2['default'].PropTypes.func
+	  },
+
+	  render: function render() {
+	    return _react2['default'].createElement(
+	      'button',
+	      {
+	        className: 'video-play-button',
+	        onClick: this.props.onClick,
+	        type: 'button' },
+	      _react2['default'].createElement(
+	        'svg',
+	        {
+	          version: '1.1',
+	          viewBox: '0 0 100 100',
+	          xmlns: 'http://www.w3.org/2000/svg' },
+	        _react2['default'].createElement('path', { d: 'M79.674,53.719c2.59-2.046,2.59-5.392,0-7.437L22.566,1.053C19.977-0.993,18,0.035,18,3.335v93.331c0,3.3,1.977,4.326,4.566,2.281L79.674,53.719z' })
+	      )
+	    );
+	  }
+	});
+	module.exports = exports['default'];
+
+/***/ },
+/* 3 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/* eslint-disable max-len */
+	'use strict';
+
+	Object.defineProperty(exports, '__esModule', {
+	  value: true
+	});
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
+
+	var _react = __webpack_require__(1);
+
+	var _react2 = _interopRequireDefault(_react);
+
+	exports['default'] = _react2['default'].createClass({
+	  displayName: 'Spinner',
+
+	  render: function render() {
+	    return _react2['default'].createElement(
+	      'div',
+	      { className: 'video-loading' },
+	      _react2['default'].createElement(
+	        'svg',
+	        {
+	          height: '32',
+	          viewBox: '0 0 32 32',
+	          width: '32',
+	          xmlns: 'http://www.w3.org/2000/svg' },
+	        _react2['default'].createElement('path', {
+	          d: 'M16 0 A16 16 0 0 0 16 32 A16 16 0 0 0 16 0 M16 4 A12 12 0 0 1 16 28 A12 12 0 0 1 16 4',
+	          opacity: '.25' }),
+	        _react2['default'].createElement('path', { d: 'M16 0 A16 16 0 0 1 32 16 L28 16 A12 12 0 0 0 16 4z' })
+	      )
+	    );
+	  }
+	});
+	module.exports = exports['default'];
+
+/***/ },
+/* 4 */
+/***/ function(module, exports, __webpack_require__) {
+
+	'use strict';
+
+	Object.defineProperty(exports, '__esModule', {
+	  value: true
+	});
+	exports['default'] = get;
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
+
+	var _debug = __webpack_require__(5);
+
+	var _debug2 = _interopRequireDefault(_debug);
+
+	var errMessage = { error: 'Sorry, an error occurred on the server' };
+	var debug = (0, _debug2['default'])('vimeo:ajax');
+
+	function get(opts) {
+	  var url = opts.url;
+	  var onSuccess = opts.onSuccess;
+	  var onError = opts.onError;
+	  var req = undefined;
+
+	  try {
+	    req = new XMLHttpRequest();
+	  } catch (e) {
+	    req = new XDomainRequest();
+	  }
+
+	  // XDomainRequest onload
+	  // ie 8-9 support
+	  function oldIE() {
+	    onSuccess(JSON.parse(req.responseText));
+	  }
+
+	  // XMLHttpRequest onload
+	  function onReadyStateChange() {
+	    if (req.readyState !== 4 || req.status !== 200) {
+	      return;
+	    }
+	    return onSuccess(JSON.parse(req.responseText));
+	  }
+
+	  function errHandler(err) {
+	    debug('error occured fetching video data', err);
+	    return onError(errMessage);
+	  }
+
+	  req.onreadystatechange = onReadyStateChange;
+	  req.onload = oldIE;
+	  req.onerror = errHandler;
+	  req.open('GET', url, true);
+	  req.send();
+
+	  return req.abort.bind(req);
+	}
+
+	module.exports = exports['default'];
+
+/***/ },
+/* 5 */
+/***/ function(module, exports, __webpack_require__) {
+
+	
+	/**
+	 * This is the web browser implementation of `debug()`.
+	 *
+	 * Expose `debug()` as the module.
+	 */
+
+	exports = module.exports = __webpack_require__(6);
+	exports.log = log;
+	exports.formatArgs = formatArgs;
+	exports.save = save;
+	exports.load = load;
+	exports.useColors = useColors;
+	exports.storage = 'undefined' != typeof chrome
+	               && 'undefined' != typeof chrome.storage
+	                  ? chrome.storage.local
+	                  : localstorage();
+
+	/**
+	 * Colors.
+	 */
+
+	exports.colors = [
+	  'lightseagreen',
+	  'forestgreen',
+	  'goldenrod',
+	  'dodgerblue',
+	  'darkorchid',
+	  'crimson'
+	];
+
+	/**
+	 * Currently only WebKit-based Web Inspectors, Firefox >= v31,
+	 * and the Firebug extension (any Firefox version) are known
+	 * to support "%c" CSS customizations.
+	 *
+	 * TODO: add a `localStorage` variable to explicitly enable/disable colors
+	 */
+
+	function useColors() {
+	  // is webkit? http://stackoverflow.com/a/16459606/376773
+	  return ('WebkitAppearance' in document.documentElement.style) ||
+	    // is firebug? http://stackoverflow.com/a/398120/376773
+	    (window.console && (console.firebug || (console.exception && console.table))) ||
+	    // is firefox >= v31?
+	    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+	    (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
+	}
+
+	/**
+	 * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+	 */
+
+	exports.formatters.j = function(v) {
+	  return JSON.stringify(v);
+	};
+
+
+	/**
+	 * Colorize log arguments if enabled.
+	 *
+	 * @api public
+	 */
+
+	function formatArgs() {
+	  var args = arguments;
+	  var useColors = this.useColors;
+
+	  args[0] = (useColors ? '%c' : '')
+	    + this.namespace
+	    + (useColors ? ' %c' : ' ')
+	    + args[0]
+	    + (useColors ? '%c ' : ' ')
+	    + '+' + exports.humanize(this.diff);
+
+	  if (!useColors) return args;
+
+	  var c = 'color: ' + this.color;
+	  args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
+
+	  // the final "%c" is somewhat tricky, because there could be other
+	  // arguments passed either before or after the %c, so we need to
+	  // figure out the correct index to insert the CSS into
+	  var index = 0;
+	  var lastC = 0;
+	  args[0].replace(/%[a-z%]/g, function(match) {
+	    if ('%%' === match) return;
+	    index++;
+	    if ('%c' === match) {
+	      // we only are interested in the *last* %c
+	      // (the user may have provided their own)
+	      lastC = index;
+	    }
+	  });
+
+	  args.splice(lastC, 0, c);
+	  return args;
+	}
+
+	/**
+	 * Invokes `console.log()` when available.
+	 * No-op when `console.log` is not a "function".
+	 *
+	 * @api public
+	 */
+
+	function log() {
+	  // this hackery is required for IE8/9, where
+	  // the `console.log` function doesn't have 'apply'
+	  return 'object' === typeof console
+	    && console.log
+	    && Function.prototype.apply.call(console.log, console, arguments);
+	}
+
+	/**
+	 * Save `namespaces`.
+	 *
+	 * @param {String} namespaces
+	 * @api private
+	 */
+
+	function save(namespaces) {
+	  try {
+	    if (null == namespaces) {
+	      exports.storage.removeItem('debug');
+	    } else {
+	      exports.storage.debug = namespaces;
+	    }
+	  } catch(e) {}
+	}
+
+	/**
+	 * Load `namespaces`.
+	 *
+	 * @return {String} returns the previously persisted debug modes
+	 * @api private
+	 */
+
+	function load() {
+	  var r;
+	  try {
+	    r = exports.storage.debug;
+	  } catch(e) {}
+	  return r;
+	}
+
+	/**
+	 * Enable namespaces listed in `localStorage.debug` initially.
+	 */
+
+	exports.enable(load());
+
+	/**
+	 * Localstorage attempts to return the localstorage.
+	 *
+	 * This is necessary because safari throws
+	 * when a user disables cookies/localstorage
+	 * and you attempt to access it.
+	 *
+	 * @return {LocalStorage}
+	 * @api private
+	 */
+
+	function localstorage(){
+	  try {
+	    return window.localStorage;
+	  } catch (e) {}
+	}
+
+
+/***/ },
+/* 6 */
+/***/ function(module, exports, __webpack_require__) {
+
+	
+	/**
+	 * This is the common logic for both the Node.js and web browser
+	 * implementations of `debug()`.
+	 *
+	 * Expose `debug()` as the module.
+	 */
+
+	exports = module.exports = debug;
+	exports.coerce = coerce;
+	exports.disable = disable;
+	exports.enable = enable;
+	exports.enabled = enabled;
+	exports.humanize = __webpack_require__(7);
+
+	/**
+	 * The currently active debug mode names, and names to skip.
+	 */
+
+	exports.names = [];
+	exports.skips = [];
+
+	/**
+	 * Map of special "%n" handling functions, for the debug "format" argument.
+	 *
+	 * Valid key names are a single, lowercased letter, i.e. "n".
+	 */
+
+	exports.formatters = {};
+
+	/**
+	 * Previously assigned color.
+	 */
+
+	var prevColor = 0;
+
+	/**
+	 * Previous log timestamp.
+	 */
+
+	var prevTime;
+
+	/**
+	 * Select a color.
+	 *
+	 * @return {Number}
+	 * @api private
+	 */
+
+	function selectColor() {
+	  return exports.colors[prevColor++ % exports.colors.length];
+	}
+
+	/**
+	 * Create a debugger with the given `namespace`.
+	 *
+	 * @param {String} namespace
+	 * @return {Function}
+	 * @api public
+	 */
+
+	function debug(namespace) {
+
+	  // define the `disabled` version
+	  function disabled() {
+	  }
+	  disabled.enabled = false;
+
+	  // define the `enabled` version
+	  function enabled() {
+
+	    var self = enabled;
+
+	    // set `diff` timestamp
+	    var curr = +new Date();
+	    var ms = curr - (prevTime || curr);
+	    self.diff = ms;
+	    self.prev = prevTime;
+	    self.curr = curr;
+	    prevTime = curr;
+
+	    // add the `color` if not set
+	    if (null == self.useColors) self.useColors = exports.useColors();
+	    if (null == self.color && self.useColors) self.color = selectColor();
+
+	    var args = Array.prototype.slice.call(arguments);
+
+	    args[0] = exports.coerce(args[0]);
+
+	    if ('string' !== typeof args[0]) {
+	      // anything else let's inspect with %o
+	      args = ['%o'].concat(args);
+	    }
+
+	    // apply any `formatters` transformations
+	    var index = 0;
+	    args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
+	      // if we encounter an escaped % then don't increase the array index
+	      if (match === '%%') return match;
+	      index++;
+	      var formatter = exports.formatters[format];
+	      if ('function' === typeof formatter) {
+	        var val = args[index];
+	        match = formatter.call(self, val);
+
+	        // now we need to remove `args[index]` since it's inlined in the `format`
+	        args.splice(index, 1);
+	        index--;
+	      }
+	      return match;
+	    });
+
+	    if ('function' === typeof exports.formatArgs) {
+	      args = exports.formatArgs.apply(self, args);
+	    }
+	    var logFn = enabled.log || exports.log || console.log.bind(console);
+	    logFn.apply(self, args);
+	  }
+	  enabled.enabled = true;
+
+	  var fn = exports.enabled(namespace) ? enabled : disabled;
+
+	  fn.namespace = namespace;
+
+	  return fn;
+	}
+
+	/**
+	 * Enables a debug mode by namespaces. This can include modes
+	 * separated by a colon and wildcards.
+	 *
+	 * @param {String} namespaces
+	 * @api public
+	 */
+
+	function enable(namespaces) {
+	  exports.save(namespaces);
+
+	  var split = (namespaces || '').split(/[\s,]+/);
+	  var len = split.length;
+
+	  for (var i = 0; i < len; i++) {
+	    if (!split[i]) continue; // ignore empty strings
+	    namespaces = split[i].replace(/\*/g, '.*?');
+	    if (namespaces[0] === '-') {
+	      exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
+	    } else {
+	      exports.names.push(new RegExp('^' + namespaces + '$'));
+	    }
+	  }
+	}
+
+	/**
+	 * Disable debug output.
+	 *
+	 * @api public
+	 */
+
+	function disable() {
+	  exports.enable('');
+	}
+
+	/**
+	 * Returns true if the given mode name is enabled, false otherwise.
+	 *
+	 * @param {String} name
+	 * @return {Boolean}
+	 * @api public
+	 */
+
+	function enabled(name) {
+	  var i, len;
+	  for (i = 0, len = exports.skips.length; i < len; i++) {
+	    if (exports.skips[i].test(name)) {
+	      return false;
+	    }
+	  }
+	  for (i = 0, len = exports.names.length; i < len; i++) {
+	    if (exports.names[i].test(name)) {
+	      return true;
+	    }
+	  }
+	  return false;
+	}
+
+	/**
+	 * Coerce `val`.
+	 *
+	 * @param {Mixed} val
+	 * @return {Mixed}
+	 * @api private
+	 */
+
+	function coerce(val) {
+	  if (val instanceof Error) return val.stack || val.message;
+	  return val;
+	}
+
+
+/***/ },
+/* 7 */
+/***/ function(module, exports) {
+
+	/**
+	 * Helpers.
+	 */
+
+	var s = 1000;
+	var m = s * 60;
+	var h = m * 60;
+	var d = h * 24;
+	var y = d * 365.25;
+
+	/**
+	 * Parse or format the given `val`.
+	 *
+	 * Options:
+	 *
+	 *  - `long` verbose formatting [false]
+	 *
+	 * @param {String|Number} val
+	 * @param {Object} options
+	 * @return {String|Number}
+	 * @api public
+	 */
+
+	module.exports = function(val, options){
+	  options = options || {};
+	  if ('string' == typeof val) return parse(val);
+	  return options.long
+	    ? long(val)
+	    : short(val);
+	};
+
+	/**
+	 * Parse the given `str` and return milliseconds.
+	 *
+	 * @param {String} str
+	 * @return {Number}
+	 * @api private
+	 */
+
+	function parse(str) {
+	  str = '' + str;
+	  if (str.length > 10000) return;
+	  var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str);
+	  if (!match) return;
+	  var n = parseFloat(match[1]);
+	  var type = (match[2] || 'ms').toLowerCase();
+	  switch (type) {
+	    case 'years':
+	    case 'year':
+	    case 'yrs':
+	    case 'yr':
+	    case 'y':
+	      return n * y;
+	    case 'days':
+	    case 'day':
+	    case 'd':
+	      return n * d;
+	    case 'hours':
+	    case 'hour':
+	    case 'hrs':
+	    case 'hr':
+	    case 'h':
+	      return n * h;
+	    case 'minutes':
+	    case 'minute':
+	    case 'mins':
+	    case 'min':
+	    case 'm':
+	      return n * m;
+	    case 'seconds':
+	    case 'second':
+	    case 'secs':
+	    case 'sec':
+	    case 's':
+	      return n * s;
+	    case 'milliseconds':
+	    case 'millisecond':
+	    case 'msecs':
+	    case 'msec':
+	    case 'ms':
+	      return n;
+	  }
+	}
+
+	/**
+	 * Short format for `ms`.
+	 *
+	 * @param {Number} ms
+	 * @return {String}
+	 * @api private
+	 */
+
+	function short(ms) {
+	  if (ms >= d) return Math.round(ms / d) + 'd';
+	  if (ms >= h) return Math.round(ms / h) + 'h';
+	  if (ms >= m) return Math.round(ms / m) + 'm';
+	  if (ms >= s) return Math.round(ms / s) + 's';
+	  return ms + 'ms';
+	}
+
+	/**
+	 * Long format for `ms`.
+	 *
+	 * @param {Number} ms
+	 * @return {String}
+	 * @api private
+	 */
+
+	function long(ms) {
+	  return plural(ms, d, 'day')
+	    || plural(ms, h, 'hour')
+	    || plural(ms, m, 'minute')
+	    || plural(ms, s, 'second')
+	    || ms + ' ms';
+	}
+
+	/**
+	 * Pluralization helper.
+	 */
+
+	function plural(ms, n, name) {
+	  if (ms < n) return;
+	  if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
+	  return Math.ceil(ms / n) + ' ' + name + 's';
+	}
+
+
+/***/ }
+/******/ ])
+});
+;
\ No newline at end of file
diff --git a/lib/umd/ReactVimeo.min.js b/lib/umd/ReactVimeo.min.js
new file mode 100644
index 0000000..5224c09
--- /dev/null
+++ b/lib/umd/ReactVimeo.min.js
@@ -0,0 +1,8 @@
+/*
+ * React-Vimeo - React component to load video from Vimeo or Youtube across any device
+ * @version v0.0.1
+ * @link https://github.com/freecodecamp/react-vimeo
+ * @license MIT
+ * @author Berkeley Martinez (https://github.com/berkeleytrue)
+*/
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports.ReactVimeo=t(require("react")):e.ReactVimeo=t(e.React)}(this,function(e){return function(e){function t(o){if(r[o])return r[o].exports;var n=r[o]={exports:{},id:o,loaded:!1};return e[o].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}([function(e,t,r){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(t,"__esModule",{value:!0});var n=r(1),a=o(n),s=r(2),i=o(s),c=r(3),u=o(c),l=r(4),d=o(l);t["default"]=a["default"].createClass({displayName:"Vimeo",propTypes:{className:n.PropTypes.string,loading:n.PropTypes.element,onError:n.PropTypes.func,playButton:n.PropTypes.node,videoId:n.PropTypes.string.isRequired},getDefaultProps:function(){return{className:"video"}},getInitialState:function(){return{thumb:null,imageLoaded:!1,showingVideo:!1}},componentWillReceiveProps:function(e){(e.className!==this.props.className||e.videoId!==this.props.videoId)&&this.setState({thumb:null,imageLoaded:!1,showingVideo:!1})},componentDidMount:function(){this.fetchVimeoData()},componentDidUpdate:function(){this.fetchVimeoData()},playVideo:function(e){e.preventDefault(),this.setState({showingVideo:!0})},getIframeUrl:function(){return"//player.vimeo.com/video/"+this.props.videoId+"?autoplay=1"},fetchVimeoData:function(){var e=this;if(this.state.imageLoaded){var t=this.props.videoId;d["default"].get({url:"//vimeo.com/api/v2/video/"+t+".json",onSuccess:function(t){e.setState({thumb:t[0].thumbnail_large,imageLoaded:!0})},onError:this.props.onError||function(){}})}},renderImage:function(){if(this.state.imageLoaded&&!this.state.showingVideo){var e={backgroundImage:"url("+this.state.thumb+")",display:this.state.showingVideo?"block":"none",height:"100%",width:"100%"};return a["default"].createElement("div",{className:"video-image",style:e},a["default"].createElement(i["default"],{onClick:this.playVideo}))}},renderIframe:function(){if(this.state.showingVideo){var e={display:this.state.showingVideo?"block":"none",height:"100%",width:"100%"};return a["default"].createElement("div",{className:"video-embed",style:e},a["default"].createElement("iframe",{frameBorder:"0",src:this.getIframeUrl()}))}},renderLoading:function(e,t){return e?void 0:t?t:a["default"].createElement(u["default"],null)},render:function(){return a["default"].createElement("div",{className:this.props.className},this.renderLoading(this.state.imageLoaded,this.props.loading),this.renderImage(),this.renderIframe())}}),e.exports=t["default"]},function(t,r){t.exports=e},function(e,t,r){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(t,"__esModule",{value:!0});var n=r(1),a=o(n);t["default"]=a["default"].createClass({displayName:"PlayButton",propTypes:{onClick:a["default"].PropTypes.func},render:function(){return a["default"].createElement("button",{className:"video-play-button",onClick:this.props.onClick,type:"button"},a["default"].createElement("svg",{version:"1.1",viewBox:"0 0 100 100",xmlns:"http://www.w3.org/2000/svg"},a["default"].createElement("path",{d:"M79.674,53.719c2.59-2.046,2.59-5.392,0-7.437L22.566,1.053C19.977-0.993,18,0.035,18,3.335v93.331c0,3.3,1.977,4.326,4.566,2.281L79.674,53.719z"})))}}),e.exports=t["default"]},function(e,t,r){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(t,"__esModule",{value:!0});var n=r(1),a=o(n);t["default"]=a["default"].createClass({displayName:"Spinner",render:function(){return a["default"].createElement("div",{className:"video-loading"},a["default"].createElement("svg",{height:"32",viewBox:"0 0 32 32",width:"32",xmlns:"http://www.w3.org/2000/svg"},a["default"].createElement("path",{d:"M16 0 A16 16 0 0 0 16 32 A16 16 0 0 0 16 0 M16 4 A12 12 0 0 1 16 28 A12 12 0 0 1 16 4",opacity:".25"}),a["default"].createElement("path",{d:"M16 0 A16 16 0 0 1 32 16 L28 16 A12 12 0 0 0 16 4z"})))}}),e.exports=t["default"]},function(e,t,r){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function n(e){function t(){a(JSON.parse(u.responseText))}function r(){return 4===u.readyState&&200===u.status?a(JSON.parse(u.responseText)):void 0}function o(e){return c("error occured fetching video data",e),s(i)}var n=e.url,a=e.onSuccess,s=e.onError,u=void 0;try{u=new XMLHttpRequest}catch(l){u=new XDomainRequest}return u.onreadystatechange=r,u.onload=t,u.onerror=o,u.open("GET",n,!0),u.send(),u.abort.bind(u)}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=n;var a=r(5),s=o(a),i={error:"Sorry, an error occurred on the server"},c=s["default"]("vimeo:ajax");e.exports=t["default"]},function(e,t,r){function o(){return"WebkitAppearance"in document.documentElement.style||window.console&&(console.firebug||console.exception&&console.table)||navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31}function n(){var e=arguments,r=this.useColors;if(e[0]=(r?"%c":"")+this.namespace+(r?" %c":" ")+e[0]+(r?"%c ":" ")+"+"+t.humanize(this.diff),!r)return e;var o="color: "+this.color;e=[e[0],o,"color: inherit"].concat(Array.prototype.slice.call(e,1));var n=0,a=0;return e[0].replace(/%[a-z%]/g,function(e){"%%"!==e&&(n++,"%c"===e&&(a=n))}),e.splice(a,0,o),e}function a(){return"object"==typeof console&&console.log&&Function.prototype.apply.call(console.log,console,arguments)}function s(e){try{null==e?t.storage.removeItem("debug"):t.storage.debug=e}catch(r){}}function i(){var e;try{e=t.storage.debug}catch(r){}return e}function c(){try{return window.localStorage}catch(e){}}t=e.exports=r(6),t.log=a,t.formatArgs=n,t.save=s,t.load=i,t.useColors=o,t.storage="undefined"!=typeof chrome&&"undefined"!=typeof chrome.storage?chrome.storage.local:c(),t.colors=["lightseagreen","forestgreen","goldenrod","dodgerblue","darkorchid","crimson"],t.formatters.j=function(e){return JSON.stringify(e)},t.enable(i())},function(e,t,r){function o(){return t.colors[l++%t.colors.length]}function n(e){function r(){}function n(){var e=n,r=+new Date,a=r-(u||r);e.diff=a,e.prev=u,e.curr=r,u=r,null==e.useColors&&(e.useColors=t.useColors()),null==e.color&&e.useColors&&(e.color=o());var s=Array.prototype.slice.call(arguments);s[0]=t.coerce(s[0]),"string"!=typeof s[0]&&(s=["%o"].concat(s));var i=0;s[0]=s[0].replace(/%([a-z%])/g,function(r,o){if("%%"===r)return r;i++;var n=t.formatters[o];if("function"==typeof n){var a=s[i];r=n.call(e,a),s.splice(i,1),i--}return r}),"function"==typeof t.formatArgs&&(s=t.formatArgs.apply(e,s));var c=n.log||t.log||console.log.bind(console);c.apply(e,s)}r.enabled=!1,n.enabled=!0;var a=t.enabled(e)?n:r;return a.namespace=e,a}function a(e){t.save(e);for(var r=(e||"").split(/[\s,]+/),o=r.length,n=0;o>n;n++)r[n]&&(e=r[n].replace(/\*/g,".*?"),"-"===e[0]?t.skips.push(new RegExp("^"+e.substr(1)+"$")):t.names.push(new RegExp("^"+e+"$")))}function s(){t.enable("")}function i(e){var r,o;for(r=0,o=t.skips.length;o>r;r++)if(t.skips[r].test(e))return!1;for(r=0,o=t.names.length;o>r;r++)if(t.names[r].test(e))return!0;return!1}function c(e){return e instanceof Error?e.stack||e.message:e}t=e.exports=n,t.coerce=c,t.disable=s,t.enable=a,t.enabled=i,t.humanize=r(7),t.names=[],t.skips=[],t.formatters={};var u,l=0},function(e,t){function r(e){if(e=""+e,!(e.length>1e4)){var t=/^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(e);if(t){var r=parseFloat(t[1]),o=(t[2]||"ms").toLowerCase();switch(o){case"years":case"year":case"yrs":case"yr":case"y":return r*l;case"days":case"day":case"d":return r*u;case"hours":case"hour":case"hrs":case"hr":case"h":return r*c;case"minutes":case"minute":case"mins":case"min":case"m":return r*i;case"seconds":case"second":case"secs":case"sec":case"s":return r*s;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return r}}}}function o(e){return e>=u?Math.round(e/u)+"d":e>=c?Math.round(e/c)+"h":e>=i?Math.round(e/i)+"m":e>=s?Math.round(e/s)+"s":e+"ms"}function n(e){return a(e,u,"day")||a(e,c,"hour")||a(e,i,"minute")||a(e,s,"second")||e+" ms"}function a(e,t,r){return t>e?void 0:1.5*t>e?Math.floor(e/t)+" "+r:Math.ceil(e/t)+" "+r+"s"}var s=1e3,i=60*s,c=60*i,u=24*c,l=365.25*u;e.exports=function(e,t){return t=t||{},"string"==typeof e?r(e):t["long"]?n(e):o(e)}}])});
\ No newline at end of file
diff --git a/package.json b/package.json
index 8202dff..7dada42 100644
--- a/package.json
+++ b/package.json
@@ -1,71 +1,59 @@
 {
   "name": "react-video",
-  "version": "1.5.3",
+  "version": "0.0.1",
   "description": "React component to load video from Vimeo or Youtube across any device",
   "author": {
-    "name": "Pedro Nauck",
-    "email": "pedronauck@gmail.com",
-    "url": "https://github.com/pedronauck"
+    "name": "Berkeley Martinez",
+    "email": "berkeley@r3dm.com",
+    "url": "https://github.com/berkeleytrue"
   },
   "bugs": {
-    "url": "https://github.com/pedronauck/react-video/issues"
+    "url": "https://github.com/freecodecamp/react-vimeo/issues"
   },
-  "homepage": "https://github.com/pedronauck/react-video",
+  "homepage": "https://github.com/freecodecamp/react-vimeo",
   "license": "MIT",
-  "main": "dist/react-video.js",
+  "main": "lib/Vimeo.js",
   "repository": {
     "type": "git",
-    "url": "git://github.com/pedronauck/react-video"
+    "url": "git://github.com/freecodecamp/react-vimeo"
   },
   "keywords": [
     "react",
     "react-component",
     "react-video",
     "video",
-    "youtube",
-    "video",
+    "vimeo",
     "player"
   ],
   "scripts": {
-    "bundle": "gulp bundle",
-    "start": "gulp",
-    "test": "jest"
-  },
-  "jest": {
-    "scriptPreprocessor": "./utils/jsx-preprocessor.js",
-    "unmockedModulePathPatterns": [
-      "./node_modules/react"
-    ],
-    "testFileExtensions": [
-      "js",
-      "jsx"
-    ],
-    "moduleFileExtensions": [
-      "js",
-      "jsx",
-      "json"
-    ]
+    "build": "npm run build-npm && npm run build-umd && npm run build-css",
+    "build-css": "stylus --use nib src/Vimeo.styl -o lib/ && stylus --compress --use nib src/Vimeo.styl -o lib/Vimeo.min.css && cp src/Vimeo.styl lib/Vimeo.styl",
+    "build-npm": "babel src --out-dir lib",
+    "build-umd": "NODE_ENV=production webpack src/Vimeo.jsx lib/umd/ReactVimeo.js && NODE_ENV=production webpack -p src/Vimeo.jsx lib/umd/ReactVimeo.min.js",
+    "lint": "eslint .",
+    "prepublish": "npm run build",
+    "test": "npm run lint"
   },
   "peerDependencies": {
-    "react": ">=0.12.2"
+    "react": ">=0.13.0"
   },
   "devDependencies": {
     "babel-core": "^5.6.15",
+    "babel-eslint": "^3.1.23",
     "babel-loader": "^5.3.1",
     "browser-sync": "^1.5.2",
-    "gulp": "^3.8.6",
-    "gulp-gh-pages": "^0.4.0",
-    "gulp-header": "^1.2.1",
-    "gulp-minify-css": "^0.3.11",
-    "gulp-rename": "^1.2.0",
-    "gulp-shell": "^0.2.10",
-    "gulp-stylus": "^1.3.3",
-    "gulp-util": "^3.0.1",
+    "eslint": "^0.24.0",
+    "eslint-plugin-react": "^2.6.4",
     "jest-cli": "^0.1.18",
     "lodash": "^2.4.1",
     "nib": "^1.0.4",
     "node-libs-browser": "^0.5.2",
     "webpack": "^1.10.1",
     "yargs": "^1.3.2"
+  },
+  "dependencies": {
+    "debug": "^2.2.0",
+    "nib": "^1.1.0",
+    "stylus": "^0.51.1"
   }
 }
diff --git a/src/Play-Button.jsx b/src/Play-Button.jsx
new file mode 100644
index 0000000..19f3232
--- /dev/null
+++ b/src/Play-Button.jsx
@@ -0,0 +1,26 @@
+/* eslint-disable max-len */
+import React from 'react';
+
+export default React.createClass({
+  displayName: 'PlayButton',
+
+  propTypes: {
+    onClick: React.PropTypes.func
+  },
+
+  render() {
+    return (
+      <button
+        className='video-play-button'
+        onClick={ this.props.onClick }
+        type='button'>
+        <svg
+          version='1.1'
+          viewBox='0 0 100 100'
+          xmlns='http://www.w3.org/2000/svg'>
+          <path d='M79.674,53.719c2.59-2.046,2.59-5.392,0-7.437L22.566,1.053C19.977-0.993,18,0.035,18,3.335v93.331c0,3.3,1.977,4.326,4.566,2.281L79.674,53.719z' />
+        </svg>
+      </button>
+    );
+  }
+});
diff --git a/src/Spinner.jsx b/src/Spinner.jsx
new file mode 100644
index 0000000..67a7337
--- /dev/null
+++ b/src/Spinner.jsx
@@ -0,0 +1,21 @@
+/* eslint-disable max-len */
+import React from 'react';
+
+export default React.createClass({
+  render() {
+    return (
+      <div className='video-loading'>
+        <svg
+          height='32'
+          viewBox='0 0 32 32'
+          width='32'
+          xmlns='http://www.w3.org/2000/svg'>
+          <path
+            d='M16 0 A16 16 0 0 0 16 32 A16 16 0 0 0 16 0 M16 4 A12 12 0 0 1 16 28 A12 12 0 0 1 16 4'
+            opacity='.25' />
+          <path d='M16 0 A16 16 0 0 1 32 16 L28 16 A12 12 0 0 0 16 4z' />
+        </svg>
+      </div>
+    );
+  }
+});
diff --git a/src/Vimeo.jsx b/src/Vimeo.jsx
new file mode 100644
index 0000000..593b129
--- /dev/null
+++ b/src/Vimeo.jsx
@@ -0,0 +1,139 @@
+import React, { PropTypes } from 'react';
+
+import PlayButton from './Play-Button.jsx';
+import Spinner from './Spinner.jsx';
+
+import ajax from './ajax';
+
+export default React.createClass({
+  displayName: 'Vimeo',
+
+  propTypes: {
+    className: PropTypes.string,
+    loading: PropTypes.element,
+    onError: PropTypes.func,
+    playButton: PropTypes.node,
+    videoId: PropTypes.string.isRequired
+  },
+
+  getDefaultProps() {
+    return {
+      className: 'video'
+    };
+  },
+
+  getInitialState() {
+    return {
+      thumb: null,
+      imageLoaded: false,
+      showingVideo: false
+    };
+  },
+
+  componentWillReceiveProps(nextProps) {
+    if (
+      nextProps.className !== this.props.className ||
+      nextProps.videoId !== this.props.videoId
+    ) {
+      this.setState({
+        thumb: null,
+        imageLoaded: false,
+        showingVideo: false
+      });
+    }
+  },
+
+  componentDidMount() {
+    this.fetchVimeoData();
+  },
+
+  componentDidUpdate() {
+    this.fetchVimeoData();
+  },
+
+  playVideo(e) {
+    e.preventDefault();
+    this.setState({ showingVideo: true });
+  },
+
+  getIframeUrl() {
+    return `//player.vimeo.com/video/${this.props.videoId}?autoplay=1`;
+  },
+
+  fetchVimeoData() {
+    if (!this.state.imageLoaded) {
+      return;
+    }
+    const id = this.props.videoId;
+
+    ajax.get({
+      url: `//vimeo.com/api/v2/video/${id}.json`,
+      onSuccess: (res) => {
+        this.setState({
+          thumb: res[0].thumbnail_large,
+          imageLoaded: true
+        });
+      },
+      onError: this.props.onError || (() => {})
+    });
+  },
+
+  renderImage() {
+    if (!this.state.imageLoaded || this.state.showingVideo) {
+      return;
+    }
+
+    const style = {
+      backgroundImage: `url(${this.state.thumb})`,
+      display: this.state.showingVideo ? 'block' : 'none',
+      height: '100%',
+      width: '100%'
+    };
+
+    return (
+      <div className='video-image' style={ style }>
+        <PlayButton onClick={ this.playVideo } />
+      </div>
+    );
+  },
+
+  renderIframe() {
+    if (!this.state.showingVideo) {
+      return;
+    }
+
+    const embedVideoStyle = {
+      display: this.state.showingVideo ? 'block' : 'none',
+      height: '100%',
+      width: '100%'
+    };
+
+    return (
+      <div className='video-embed' style={ embedVideoStyle }>
+        <iframe frameBorder='0' src={ this.getIframeUrl() }></iframe>
+      </div>
+    );
+  },
+
+  renderLoading(imageLoaded, loadingElement) {
+    if (imageLoaded) {
+      return;
+    }
+    if (loadingElement) {
+      return loadingElement;
+    }
+    return (
+      <Spinner />
+    );
+  },
+
+  render() {
+    return (
+      <div className={ this.props.className } >
+        { this.renderLoading(this.state.imageLoaded, this.props.loading) }
+        { this.renderImage() }
+        { this.renderIframe() }
+      </div>
+    );
+  }
+});
diff --git a/src/ajax.js b/src/ajax.js
new file mode 100644
index 0000000..3467f91
--- /dev/null
+++ b/src/ajax.js
@@ -0,0 +1,42 @@
+import debugFactory from 'debug';
+
+const errMessage = { error: 'Sorry, an error occurred on the server' };
+const debug = debugFactory('vimeo:ajax');
+
+export default function get(opts) {
+  const url = opts.url;
+  const onSuccess = opts.onSuccess;
+  const onError = opts.onError;
+  let req;
+
+  try {
+    req = new XMLHttpRequest();
+  } catch (e) {
+    req = new XDomainRequest();
+  }
+
+  // XDomainRequest onload
+  // ie 8-9 support
+  function oldIE() {
+    onSuccess(JSON.parse(req.responseText));
+  }
+
+  // XMLHttpRequest onload
+  function onReadyStateChange() {
+    if (req.readyState !== 4 || req.status !== 200) { return; }
+    return onSuccess(JSON.parse(req.responseText));
+  }
+
+  function errHandler(err) {
+    debug('error occured fetching video data', err);
+    return onError(errMessage);
+  }
+
+  req.onreadystatechange = onReadyStateChange;
+  req.onload = oldIE;
+  req.onerror = errHandler;
+  req.open('GET', url, true);
+  req.send();
+
+  return req.abort.bind(req);
+}
diff --git a/utils/ajax.js b/utils/ajax.js
deleted file mode 100644
index 96967be..0000000
--- a/utils/ajax.js
+++ /dev/null
@@ -1,43 +0,0 @@
-exports.get = function(opts) {
-  var url = opts.url;
-  var successCb = opts.onSuccess;
-  var errorCb = opts.onError;
-  var req = false;
-
-  // XDomainRequest onload
-  var _oldIE = function () {
-    successCb(null, JSON.parse(req.responseText));
-  };
-
-  // XMLHttpRequest onload
-  var _onLoad = function () {
-    if (req.readyState !== 4) return;
-    if (req.status === 200) successCb(null, JSON.parse(req.responseText));
-    else {
-      var err = { error: 'Sorry, an error ocurred on the server' };
-
-      if (errorCb && typeof errorCb === 'function') return errorCb(err);
-      successCb(err, null);
-    }
-  };
-
-  var _onError = function() {
-    var err = { error: 'Sorry, an error ocurred on the server' };
-
-    if (errorCb && typeof errorCb === 'function') return errorCb(err);
-    successCb(err, null);
-  };
-
-  try {
-    req = new XDomainRequest();
-    req.onload = _oldIE;
-  }
-  catch (e) {
-    req = new XMLHttpRequest();
-    req.onreadystatechange = _onLoad;
-  }
-
-  req.onerror = _onError;
-  req.open('GET', url, true);
-  req.send();
-};
diff --git a/utils/banner.js b/utils/banner.js
deleted file mode 100644
index d91c163..0000000
--- a/utils/banner.js
+++ /dev/null
@@ -1,13 +0,0 @@
-'use strict';
-
-module.exports = require('lodash').template([
-  '/*',
-  ' * React Video - <%= pkg.description %>',
-  ' * @version v<%= pkg.version %>',
-  ' * @link <%= pkg.homepage %>',
-  ' * @license <%= pkg.license %>',
-  ' * @author <%= pkg.author.name %> (<%= pkg.author.url %>)',
-  '*/\n',
-].join('\n'), {
-  pkg: require('../package.json')
-});
diff --git a/utils/classSet.js b/utils/classSet.js
deleted file mode 100644
index 1d61afa..0000000
--- a/utils/classSet.js
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * Produces the same result as React.addons.classSet
- * @param  {object} classes
- * @return {string}
- *
- * @author Ciro S. Costa <https://github.com/cirocosta>
- */
-
-module.exports = (classes) => {
-  return typeof classes !== 'object' ?
-    Array.prototype.join.call(arguments, ' ') :
-    Object.keys(classes).filter((className) => classes[className]).join(' ');
-};
diff --git a/utils/jsx-preprocessor.js b/utils/jsx-preprocessor.js
deleted file mode 100644
index 2b5a9c4..0000000
--- a/utils/jsx-preprocessor.js
+++ /dev/null
@@ -1,12 +0,0 @@
-'use strict';
-
-var ReactTools = require('react-tools');
-
-module.exports = {
-  process: function (src, path) {
-    if (!path.match(/\.jsx$/))
-      return src;
-
-    return ReactTools.transform(src);
-  }
-};
diff --git a/webpack.config.js b/webpack.config.js
index f96d2b6..52b2311 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,39 +1,43 @@
-var _ = require('lodash');
 var webpack = require('webpack');
-var banner = require('./utils/banner');
-var LIB_NAME = 'react-video';
-var GLOBAL_VAR = 'ReactVideo';
+
+var banner = require('./banner');
 
 module.exports = {
-  entry: './lib/' + LIB_NAME + '.jsx',
+
   output: {
-    path: __dirname + '/dist',
-    filename: LIB_NAME + '.js',
-    libraryTarget: 'umd',
-    library: GLOBAL_VAR
+    library: 'ReactVimeo',
+    libraryTarget: 'umd'
   },
-  externals: {
-    react: {
-      root: 'React',
-      commonjs: 'react',
-      commonjs2: 'react',
-      amd: 'react'
+
+  externals: [
+    {
+      'react': {
+        root: 'React',
+        commonjs2: 'react',
+        commonjs: 'react',
+        amd: 'react'
+      }
     }
-  },
+  ],
+
   module: {
-    loaders: [{
-      test: /\.(js|jsx)$/,
-      loader: 'babel-loader'
-    }]
+    loaders: [
+      {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        loader: 'babel-loader'
+      }
+    ]
   },
-  resolve: {
-    extensions: ['', '.js', '.jsx']
+
+  node: {
+    Buffer: false
   },
+
   plugins: [
+    new webpack.optimize.OccurenceOrderPlugin(),
     new webpack.DefinePlugin({
-      'process.env': {
-        NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development'),
-      }
+      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
     }),
     new webpack.BannerPlugin(banner, { raw: true, entryOnly: true })
   ]
