diff options
132 files changed, 21427 insertions, 9258 deletions
diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..dd9beec5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +# See editorconfig.org +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..89426cd5 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,40 @@ +{ + "parser": "babel-eslint", + "extends": ["airbnb", "prettier"], + "env": { + "browser": true, + "es6": true + }, + "globals": { "Plyr": false, "jQuery": false }, + "rules": { + "no-const-assign": 1, + "no-this-before-super": 1, + "no-undef": 1, + "no-unreachable": 1, + "no-unused-vars": 1, + "constructor-super": 1, + "valid-typeof": 1, + "indent": [2, 4, { "SwitchCase": 1 }], + "quotes": [2, "single", "avoid-escape"], + "semi": [2, "always"], + "eqeqeq": [2, "always"], + "one-var": [2, "never"], + "comma-dangle": [2, "always-multiline"], + "no-restricted-globals": [ + "error", + { + "name": "event", + "message": "Use local parameter instead." + }, + { + "name": "error", + "message": "Use local parameter instead." + } + ], + "array-bracket-newline": [2, { "minItems": 2 }], + "array-element-newline": [2, { "minItems": 2 }] + }, + "parserOptions": { + "sourceType": "module" + } +} diff --git a/.github/issue_template.md b/.github/issue_template.md index 8e3b85b7..f503b944 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,28 +1,17 @@ -<!--- -Please use this issue template as it makes replicating and fixing the issue easier! +<!--- +Please use this issue template as it makes replicating and fixing the issue easier! ---> -- [ ] Issue does not already exist -- [ ] Issue observed on https://plyr.io - -### Expected behaviour +### Expected behaviour ### Actual behaviour ### Environment - Browser: -- Version: +- Version: - Operating System: -- Version: - -Players affected: -- [ ] HTML5 Video -- [ ] HTML5 Audio -- [ ] YouTube -- [ ] Vimeo - -### Steps to reproduce -- +- Version: -### Relevant links +### Steps to reproduce +-
\ No newline at end of file @@ -1,11 +1,8 @@ node_modules -*.sublime-project -*.sublime-workspace .DS_Store aws.json -docs/index.dev.html *.mp4 -index-dev.html -notes.txt -*.vtt -docs/index.dev.php +!dist/blank.mp4 +index-*.html +npm-debug.log +*.webm diff --git a/.jsbeautifyrc b/.jsbeautifyrc deleted file mode 100644 index 064bf950..00000000 --- a/.jsbeautifyrc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "html": { - "allowed_file_extensions": [] - }, - "css": { - "allowed_file_extensions": [] - }, - "js": { - "allowed_file_extensions": [] - } -} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 7a55e036..00000000 --- a/.jshintrc +++ /dev/null @@ -1,55 +0,0 @@ -{ - // Settings - "passfail" : false, // Stop on first error. - "maxerr" : 100, // Maximum error before stopping. - - // Predefined globals whom JSHint will ignore. - "browser" : true, // Standard browser globals e.g. `window`, `document`. - "node" : false, - "rhino" : false, - "couch" : false, - "wsh" : false, // Windows Scripting Host. - "jquery" : false, - - // Development. - "debug" : true, // Allow debugger statements e.g. browser breakpoints. - "devel" : true, // Allow developments statements e.g. `console.log();`. - - // ECMAScript 5. - "strict" : false, // Require `use strict` pragma in every file. - "globalstrict" : false, // Allow global "use strict" (also enables 'strict'). - - // The Good Parts. - "asi" : true, // Tolerate Automatic Semicolon Insertion (no semicolons). - "laxbreak" : true, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons. - "bitwise" : false, // Prohibit bitwise operators (&, |, ^, etc.). - "boss" : false, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments. - "curly" : true, // Require {} for every new block or scope. - "eqeqeq" : true, // Require triple equals i.e. `===`. - "eqnull" : false, // Tolerate use of `== null`. - "evil" : false, // Tolerate use of `eval`. - "expr" : false, // Tolerate `ExpressionStatement` as Programs. - "forin" : false, // Tolerate `for in` loops without `hasOwnPrototype`. - "immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );` - "latedef" : false, // Prohipit variable use before definition. - "loopfunc" : true, // Allow functions to be defined within loops. - "noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`. - "regexp" : true, // Prohibit `.` and `[^...]` in regular expressions. - "regexdash" : false, // Tolerate unescaped last dash i.e. `[-...]`. - "scripturl" : true, // Tolerate script-targeted URLs. - "shadow" : false, // Allows re-define variables later in code e.g. `var x=1; x=2;`. - "supernew" : false, // Tolerate `new function () { ... };` and `new Object;`. - "undef" : true, // Require all non-global variables be declared before they are used. - - // Personal styling preferences. - "newcap" : true, // Require capitalization of all constructor functions e.g. `new F()`. - "noempty" : true, // Prohibit use of empty blocks. - "nonew" : true, // Prohibit use of constructors for side-effects. - "nomen" : true, // Prohibit use of initial or trailing underbars in names. - "onevar" : false, // Allow only one `var` statement per function. - "plusplus" : false, // Prohibit use of `++` & `--`. - "sub" : false, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`. - "trailing" : true, // Prohibit trailing whitespaces. - "white" : true, // Check against strict whitespace and indentation rules. - "indent" : 4 // Specify indentation spacing -}
\ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..223a51a5 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "useTabs": false, + "tabWidth": 4, + "printWidth": 160, + "singleQuote": true, + "trailingComma": "es5" +} diff --git a/.stylelintrc.json b/.stylelintrc.json new file mode 100644 index 00000000..728265e3 --- /dev/null +++ b/.stylelintrc.json @@ -0,0 +1,24 @@ +{ + "plugins": ["stylelint-selector-bem-pattern", "stylelint-scss"], + "extends": ["stylelint-config-sass-guidelines", "stylelint-config-prettier"], + "rules": { + "selector-class-pattern": null, + "selector-no-qualifying-type": [ + true, + { + "ignore": ["attribute", "class"] + } + ], + "indentation": 4, + "string-quotes": "single", + "max-nesting-depth": 2, + "plugin/selector-bem-pattern": { + "preset": "bem", + "componentName": "(([a-z0-9]+(?!-$)-?)+)", + "componentSelectors": { + "initial": "\\.{componentName}(((__|--)(([a-z0-9\\[\\]'=]+(?!-$)-?)+))+)?$" + }, + "ignoreSelectors": [".*\\.has-.*", ".*\\.is-.*"] + } + } +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 7a73a41b..9e26dfee 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,2 +1 @@ -{ -}
\ No newline at end of file +{}
\ No newline at end of file @@ -6,7 +6,7 @@ "Audio", "Video", "HTML5 Audio", - "HTml5 Video" + "HTML5 Video" ], "authors": [ "Sam Potts <sam@potts.es>" @@ -30,4 +30,4 @@ "url": "git://github.com/sampotts/plyr.git" }, "license": "MIT" -} +}
\ No newline at end of file diff --git a/bundles.json b/bundles.json index d6fdf733..bdfa2c8d 100644 --- a/bundles.json +++ b/bundles.json @@ -1,24 +1,19 @@ { "plyr": { - "less": { - "plyr.css": ["src/less/plyr.less"] - }, - "scss": { - "plyr.css": ["src/scss/plyr.scss"] + "sass": { + "plyr.css": "src/sass/plyr.scss" }, "js": { - "plyr.js": ["src/js/plyr.js"] + "plyr.js": "src/js/plyr.js" } }, "demo": { - "less": { - "demo.css": ["demo/src/less/demo.less"] + "sass": { + "demo.css": "demo/src/sass/bundles/demo.scss", + "error.css": "demo/src/sass/bundles/error.csss" }, "js": { - "demo.js": [ - "demo/src/js/lib/classlist.js", - "demo/src/js/main.js" - ] + "demo.js": "demo/src/js/demo.js" } } } diff --git a/changelog.md b/changelog.md index 09864472..7451288b 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,71 @@ -# Changelog +# v3.0.0 + +This is a massive release. A _mostly_ complete rewrite in ES6. What started out as a few changes quickly snowballed. There's many breaking changes so be careful upgrading. + +### Big changes + +* New settings menu complete with funky animations +* Ability to adjust speed of playback +* Ability to toggle caption language (HTML5 and Vimeo only) +* Ability to set YouTube quality (HTML5 will follow) +* Added support for Vimeo captions +* Added Picture-in-Picture support (Safari only) +* Added AirPlay support (again, Safari only) +* Added `playsinline` support for iOS 10+ +* Soundcloud removed until I can work on a plugin framework + +### Other stuff + +* Now using SASS exclusively. Sorry, LESS folk it just made sense to maintain one method as SASS is what the cool kids use +* Moved to ES6. All the rage these days +* Added basic looping support +* Added an aspect ratio option for those that can't leave the 90s and want 4:3 +* `controlshidden` and `controlsshown` events added for when the controls show or hide +* `qualityrequested` and `qualitychange` events for YouTube quality control (HTML5 will follow) +* Volume is now `0` to `1` as per HTML5 spec +* No longer bodging a `<progress>` behind the `<input type="range">` to make up for WebKit's lack of lower fill styling +* Captions now render with line breaks as intended +* Captions now render without AJAX using the native events etc +* Added a fallback for getting YouTube video data incase `.getVideoData()` disappears when one of their developers randomly deletes it again +* Setup and building of the UI should be way "snappier" +* Click to toggle inverted time (e.g. 0:01 or -2:59 for a 3 minute video at 1 seconds) - new `toggleInvert` and `invertTime` options +* Added `autopause` option for Vimeo +* Added `muted` option for you guessed it, muted playback +* Restored the `.off()` API method +* `.play()` will now return a promise to prevent that pesky uncaught promise issue in Chrome etc +* Pressing and hold the seek bar no longer freezes all other updates of the UI + +...plus loads of bug fixes. + +### Breaking changes + +You gotta break eggs to make an omelette. Sadly, there's quite a few breaking changes: + +* Setup now uses proper constructor, accepts a single selector/element/node and returns a single instance - much simpler than before +* Much of the API is now using getters and setters rather than methods (where it makes sense) to match the HTML5 API - see the docs for more info +* `blankUrl` -> `blankVideo` +* `volume` is now `0` to `1` as per HTML5 spec +* `keyboardShorcuts` (typo) is now just `keyboard` +* `loop` is now `loop.active` in preparation for loop enhancements later +* `html` option for custom controls removed in favour of the `controls` option which now accepts an array (to use built in controls) or a string of HTML for custom controls. +* `classes` -> `classNames` +* `classes.videoWrapper` -> `classNames.video` +* `classes.embedWrapper` -> `classNames.embed` +* `classes.ready` removed +* `classes.setup` removed +* `classes.muted` removed +* `classes.fullscreen.active` removed in favour of the `:fullscreen` selector +* `selectors.html5` removed +* `selectors.embed` removed +* `selectors.buttons.seek` -> `selectors.inputs.seek` +* `selectors.volume.input` -> `selectors.inputs.volume` +* `selectors.volume.display` -> `selectors.display.volume` +* `selectors.currentTime` -> `selectors.display.currentTime` +* `selectors.duration` -> `selectors.display.duration` + +### Polyfilling + +Because we're using the fancy new ES6 syntax, you will need to polyfill for vintage browsers if you want to use Plyr and still support them. Luckily there's a decent service for this that makes it painless, [https://polyfill.io](polyfill.io). ## v2.0.18 - Fix for YouTube .getVideoData() issue (fixes #709) @@ -24,530 +91,646 @@ - Repo moved and Vimeo demo fix ## v2.0.12 -- Ability to set custom `blankUrl` for source changes (https://github.com/sampotts/plyr/pull/504) -- Ability to set caption button listener (https://github.com/sampotts/plyr/pull/468) + +* Ability to set custom `blankUrl` for source changes (https://github.com/sampotts/plyr/pull/504) +* Ability to set caption button listener (https://github.com/sampotts/plyr/pull/468) ## v2.0.11 -- Fix for `cleanUp` being called twice (thanks to @sebastiancarlsson) -- Fix for YouTube controls on iPad (fixes #391) + +* Fix for `cleanUp` being called twice (thanks to @sebastiancarlsson) +* Fix for YouTube controls on iPad (fixes #391) ## v2.0.10 -- Added seek event fixes for Vimeo and YouTube (fixes #409) -- Added support for embed URLs rather than ID only (fixes #345) + +* Added seek event fixes for Vimeo and YouTube (fixes #409) +* Added support for embed URLs rather than ID only (fixes #345) ## v2.0.9 -- Temporary patch for the YouTube API issues with `getDuration()` (relates to #374) + +* Temporary patch for the YouTube API issues with `getDuration()` (relates to #374) ## v2.0.8 -- Added `isPaused()` API method (thanks to @darrena092) -- Allowed `.on()` API method to be chainable (thanks to @gurupras) (fixes #357) -- Improved the "awful" rendering of captions on small screens in fullscreen mode (fixes #390) -- Fix for Firefox VTT compatibility (thanks to @magourex) -- Fix for Firefox Developer Edition blank video due to `-webkit-mask-image` issue (fixes #392) -- Added Issue and PR templates with the aim of reducing duplicate or duff issues + +* Added `isPaused()` API method (thanks to @darrena092) +* Allowed `.on()` API method to be chainable (thanks to @gurupras) (fixes #357) +* Improved the "awful" rendering of captions on small screens in fullscreen mode (fixes #390) +* Fix for Firefox VTT compatibility (thanks to @magourex) +* Fix for Firefox Developer Edition blank video due to `-webkit-mask-image` issue (fixes #392) +* Added Issue and PR templates with the aim of reducing duplicate or duff issues ## v2.0.7 -- Fixed `getCurrentTime()` method (fixes #351) -- Added `getVolume()` , `isMuted()` and `getDuration()` API methods (fixes #346) + +* Fixed `getCurrentTime()` method (fixes #351) +* Added `getVolume()` , `isMuted()` and `getDuration()` API methods (fixes #346) ## v2.0.6 -- Fixed merge issue with `Updated define to work with AMD imports #326` PR -- Code formatting + +* Fixed merge issue with `Updated define to work with AMD imports #326` PR +* Code formatting ## v2.0.5 -- Fix for Vimeo in IE9 & IE10 -- Fix for HTML5 elements not firing `ready` event + +* Fix for Vimeo in IE9 & IE10 +* Fix for HTML5 elements not firing `ready` event ## v2.0.4 -- Fix for Firefox full screen (fixes #343) + +* Fix for Firefox full screen (fixes #343) ## v2.0.3 -- Set 'global' keyboard shortcut option to false as default, added `<textarea>` to editable elements to be ignored + +* Set 'global' keyboard shortcut option to false as default, added `<textarea>` to editable elements to be ignored ## v2.0.2 -- Added 'global' keyboard shortcut option + +* Added 'global' keyboard shortcut option ## v2.0.1 -- Version bump for NPM (sorry for folks who upgraded to the now deleted v1.9.0 through NPM) + +* Version bump for NPM (sorry for folks who upgraded to the now deleted v1.9.0 through NPM) # v2.0.0 -This version contains several potential ***breaking changes***: -- `setup()` has been reverted to pre v1.8.0 behaviour; meaning it will return the *instance* rather than the *element*. This is because the reference to the instance is no longer added to the original element (see below). -- The reference to the `plyr` instance is now added to the media element rather than original container. This is because if a container with multiple children was passed to `setup()` the references to all instances would have been added to the container, creating issues. I would recommend using the return value from `setup()` or the new `get()` method to access the instance. -- Players will always be wrapped in their own div now - this makes `setup()` and `destroy()` cleaner. This *may* break any custom styling based on DOM position. -- Players no longer seek to 0 on 'ended' - this is to fix a bug with Microsoft Edge as it triggers 'ended' on media change for whatever reason. They'll never change ;-) +This version contains several potential **_breaking changes_**: + +* `setup()` has been reverted to pre v1.8.0 behaviour; meaning it will return the _instance_ rather than the _element_. This is because the reference to the instance is no longer added to the original element (see below). +* The reference to the `plyr` instance is now added to the media element rather than original container. This is because if a container with multiple children was passed to `setup()` the references to all instances would have been added to the container, creating issues. I would recommend using the return value from `setup()` or the new `get()` method to access the instance. +* Players will always be wrapped in their own div now - this makes `setup()` and `destroy()` cleaner. This _may_ break any custom styling based on DOM position. +* Players no longer seek to 0 on 'ended' - this is to fix a bug with Microsoft Edge as it triggers 'ended' on media change for whatever reason. They'll never change ;-) And some other changes and bug fixes: -- New `get()` method on the global plyr object to get all instances inside a container -- New API methods: - - `getOriginal()` to get the original, *unmodified* element plyr was setup on (`<video>`, `<audio>` or empty `<div>` for YouTube and Vimeo) - - `getContainer()` to get the players outer wrapper element - - `getMedia()` to get the players media element (`<video>`, `<audio>` or empty `<div>` for YouTube and Vimeo) - - `getEmbed()` to access the YouTube or Vimeo API directly - - `getType()` to get the type of the player - - `isReady()` to determine if an instance has completed setup and necessary APIs are loaded (for YouTube / Vimeo) - - `on()` to provide an easy way to listen to events - - `stop()` to, you guessed it, stop the player -- `destroy()` now works correctly for YouTube and Vimeo (fixes #272) -- New `destroyed` event when `destroy()` has completed (original element is passed as event.target) -- Default volume is now 10 (max) rather than 5 -- Sprite is only loaded once (fixes #259) -- Fixes for Vimeo post message bugs on source change or destroy (fixes #318) -- Save caption state in storage (fixes #311) -- Added keyboard shortcuts to the current focused player (with `keyboardShortcuts` boolean option to disable) (fixes #309) -- Fix for captions bug (fixes #332) -- Change to AMD (fixes #298) +* New `get()` method on the global plyr object to get all instances inside a container +* New API methods: - `getOriginal()` to get the original, _unmodified_ element plyr was setup on (`<video>`, `<audio>` or empty `<div>` for YouTube and Vimeo) - `getContainer()` to get the players outer wrapper element - `getMedia()` to get the players media element (`<video>`, `<audio>` or empty `<div>` for YouTube and Vimeo) - `getEmbed()` to access the YouTube or Vimeo API directly - `getType()` to get the type of the player - `isReady()` to determine if an instance has completed setup and necessary APIs are loaded (for YouTube / Vimeo) - `on()` to provide an easy way to listen to events - `stop()` to, you guessed it, stop the player +* `destroy()` now works correctly for YouTube and Vimeo (fixes #272) +* New `destroyed` event when `destroy()` has completed (original element is passed as event.target) +* Default volume is now 10 (max) rather than 5 +* Sprite is only loaded once (fixes #259) +* Fixes for Vimeo post message bugs on source change or destroy (fixes #318) +* Save caption state in storage (fixes #311) +* Added keyboard shortcuts to the current focused player (with `keyboardShortcuts` boolean option to disable) (fixes #309) +* Fix for captions bug (fixes #332) +* Change to AMD (fixes #298) ## v1.8.12 -- Vimeo keyboard focus fix (Fixes #317) -- Fix for Vimeo on basic support devices + +* Vimeo keyboard focus fix (Fixes #317) +* Fix for Vimeo on basic support devices ## v1.8.11 -- Fix for keyboard navigation on Vimeo (Fixes #317) -- Fix for bug introduced in v1.8.9 related to additional controls -- Vimeo API upgrade -- Fix for YouTube bug introduced in v1.8.9 -- Added support for passing array to .setup() (Fixes #319) + +* Fix for keyboard navigation on Vimeo (Fixes #317) +* Fix for bug introduced in v1.8.9 related to additional controls +* Vimeo API upgrade +* Fix for YouTube bug introduced in v1.8.9 +* Added support for passing array to .setup() (Fixes #319) ## v1.8.10 -- Fix for seek issues introduced in v1.8.9 + +* Fix for seek issues introduced in v1.8.9 ## v1.8.9 -- Fix for fullscreen not being defined (Fixes #295) -- Fix for multiline captions (Fixes #314) -- Clean up of type checks and fix for `restart()` (Fixes #315) -- Fix for `MEDIA_ERR_SRC_NOT_SUPPORTED` when calling `.source()` API method + +* Fix for fullscreen not being defined (Fixes #295) +* Fix for multiline captions (Fixes #314) +* Clean up of type checks and fix for `restart()` (Fixes #315) +* Fix for `MEDIA_ERR_SRC_NOT_SUPPORTED` when calling `.source()` API method ## v1.8.8 -- Added getCurrentTime API method (fixes #292) -- Fix for !hideControls on touch devices (fixes #303) + +* Added getCurrentTime API method (fixes #292) +* Fix for !hideControls on touch devices (fixes #303) ## v1.8.7 -- Line height fix + +* Line height fix ## v1.8.6 -- Reverted font size change + +* Reverted font size change ## v1.8.5 -- Fixed overflow issues (fixes #286) + +* Fixed overflow issues (fixes #286) ## v1.8.4 -- Fix for large play button on small videos + +* Fix for large play button on small videos ## v1.8.3 -- Disabled iPad support for YouTube and Vimeo due to iOS limitations with iFrame playback -- Fixed IE11 icon loading (fixes #269) -- Updated screenshot (fixes #281) -- Added WordPress plugin (fixes #239) -- Added Neos plugin -- Added HLS, Shaka and dash.js examples (see #235 for more) -- Improvements for controls hiding and showing on touch devices + +* Disabled iPad support for YouTube and Vimeo due to iOS limitations with iFrame playback +* Fixed IE11 icon loading (fixes #269) +* Updated screenshot (fixes #281) +* Added WordPress plugin (fixes #239) +* Added Neos plugin +* Added HLS, Shaka and dash.js examples (see #235 for more) +* Improvements for controls hiding and showing on touch devices ## v1.8.2 -- Fixed event bubbling + +* Fixed event bubbling ## v1.8.1 -- Fixed inaccurate log message + +* Fixed inaccurate log message # v1.8.0 -- ***(Important)*** `setup()` now returns the element Plyr was setup on rather than the `plyr` object. This means `var player = plyr.setup()[0];` would now be `var player = plyr.setup()[0].plyr;`. This improves support for React and other virtual dom frameworks as mentioned in #254 -- Fixed using a relative URL for `iconUrl` in IE (fixes #269) + +* **_(Important)_** `setup()` now returns the element Plyr was setup on rather than the `plyr` object. This means `var player = plyr.setup()[0];` would now be `var player = plyr.setup()[0].plyr;`. This improves support for React and other virtual dom frameworks as mentioned in #254 +* Fixed using a relative URL for `iconUrl` in IE (fixes #269) # v1.7.0 -- SASS cleanup (fixes #265) -- Docs tidy up to help quick start (fixes #253) -- Fix for issues with data attribute options passing (fixes #257) -- ***(Important)*** Removed the requirement for a wrapper div to setup Plyr and removed the dependency on the `plyr` classname as a JS hook. By default it will now look for `<video>`, `<audio>` and `[data-type]` elements. If you are just calling `setup()` with a `<div class="plyr">` you may want to give it a good test after upgrading. You can probably remove the wrapper div. The reason behind this is to make setup easier for newcomers and prevent the styling being used on unsupported players (because the plyr classname was used as a CSS and JS hook - which isn't ideal) -- Renamed the 'docs' folder to `demo` to avoid confusion - the readme is the docs after all + +* SASS cleanup (fixes #265) +* Docs tidy up to help quick start (fixes #253) +* Fix for issues with data attribute options passing (fixes #257) +* **_(Important)_** Removed the requirement for a wrapper div to setup Plyr and removed the dependency on the `plyr` classname as a JS hook. By default it will now look for `<video>`, `<audio>` and `[data-type]` elements. If you are just calling `setup()` with a `<div class="plyr">` you may want to give it a good test after upgrading. You can probably remove the wrapper div. The reason behind this is to make setup easier for newcomers and prevent the styling being used on unsupported players (because the plyr classname was used as a CSS and JS hook - which isn't ideal) +* Renamed the 'docs' folder to `demo` to avoid confusion - the readme is the docs after all ## v1.6.20 -- Fix for multiple sprites being requested (fixes #259) + +* Fix for multiple sprites being requested (fixes #259) ## v1.6.19 -- Fix for scroll direction issues on volume control (fixes #258) + +* Fix for scroll direction issues on volume control (fixes #258) ## v1.6.18 -- Reduced rounding of seek value from 1 decimal point to 4 (fixes #242) + +* Reduced rounding of seek value from 1 decimal point to 4 (fixes #242) ## v1.6.17 -- Added `disableContextMenu` option to hide the right click context menu (fixes #248 and #225) + +* Added `disableContextMenu` option to hide the right click context menu (fixes #248 and #225) ## v1.6.16 -- Always hide standard controls (fixes #225) -- Fix for Tooltips overflowing (fixes #230) + +* Always hide standard controls (fixes #225) +* Fix for Tooltips overflowing (fixes #230) ## v1.6.15 -- Restore scroll position when exiting full screen (fixes #236) + +* Restore scroll position when exiting full screen (fixes #236) ## v1.6.14 -- SVG sprite loading automatically for an easier setup -- Touch devices now show controls on touch rather than pausing playback + +* SVG sprite loading automatically for an easier setup +* Touch devices now show controls on touch rather than pausing playback ## v1.6.13 -- Decreased sensitivity and inverted scroll on volume slider (scroll up to increase, down to decrease) + +* Decreased sensitivity and inverted scroll on volume slider (scroll up to increase, down to decrease) ## v1.6.12 -- Fix for undefined buffer error -- Add scroll listener on volume slider (PR #227 bty @igoradamenko) + +* Fix for undefined buffer error +* Add scroll listener on volume slider (PR #227 bty @igoradamenko) ## v1.6.11 -- Fix for Vimeo fullscreen (fixes #214) + +* Fix for Vimeo fullscreen (fixes #214) ## v1.6.10 -- Changed default icon prefix from 'icon' to 'plyr' to avoid clashes + +* Changed default icon prefix from 'icon' to 'plyr' to avoid clashes ## v1.6.9 -- Added 'latest' CDN option -- Renamed `sprite.svg` to `plyr.svg` to be inline with the other package files + +* Added 'latest' CDN option +* Renamed `sprite.svg` to `plyr.svg` to be inline with the other package files ## v1.6.8 -- Fix for bug introduced in v1.6.7 + +* Fix for bug introduced in v1.6.7 ## v1.6.7 -- Fixes for using `source` API method on iOS + +* Fixes for using `source` API method on iOS ## v1.6.6 -- Icons cleaned up -- IE11 button fix for tooltips (fixes #210) + +* Icons cleaned up +* IE11 button fix for tooltips (fixes #210) ## v1.6.5 -- IE UI bug fixes + +* IE UI bug fixes ## v1.6.4 -- Bug fix for undefined progress bar + +* Bug fix for undefined progress bar ## v1.6.3 -- Seek back to 0 for all media on ended -- Check for HTML5 video on ended reload -- Update to docs for `showPosterOnEnd` option + +* Seek back to 0 for all media on ended +* Check for HTML5 video on ended reload +* Update to docs for `showPosterOnEnd` option ## v1.6.2 -- Fix for tooltip displaying when duration is not set (fixes #177) -- `showPosterOnEnd` option to show poster when HTML5 video ended (fixes #59) -- Error handler for YouTube (fixes #189) -- Initial SoundCloud support (fixes #194) -- Other minor bug fixes + +* Fix for tooltip displaying when duration is not set (fixes #177) +* `showPosterOnEnd` option to show poster when HTML5 video ended (fixes #59) +* Error handler for YouTube (fixes #189) +* Initial SoundCloud support (fixes #194) +* Other minor bug fixes ## v1.6.1 -- Tooltip changes for accessibility + +* Tooltip changes for accessibility ## v1.6.0 -- New, cleaner, UI: - - Controls are now overlaid, maintaining the video's ratio and making sizing easier - - A large play button can now be overlaid over videos - - Default number of control buttons reduced - - New play, pause, rewind and fast forward icons - - Flexbox all the things! -- Tidied up the LESS (and SCSS) as part of the above, variables and mixins in seprate files amking customization and upgrades easier -- Toggle mute bug fix; if a player was muted previously and the user refreshed, unmuting would have meant volume was still zero (effectively muted), now the config default value is used. Not ideal but good for now -- New `iconUrl` option allowing specifying a same origin SVG sprite location. Loading this way means you don't need the AJAX sprite loading JavaScript -- `click` option renamed to `clickToPlay` to make it a bit more self explanatory. Unfortunately cross origin SVG sprites is not supported in any browser yet :-( -- `hideControls` is now a global option, rather than being exclusive to fullscreen. Controls are now hidden after 2 seconds of no mouse movement. Controls are always shown when media is paused or stopped. This is defaulted to true. -- `sass` folder in `src` renamed from to `scss` + +* New, cleaner, UI: - Controls are now overlaid, maintaining the video's ratio and making sizing easier - A large play button can now be overlaid over videos - Default number of control buttons reduced - New play, pause, rewind and fast forward icons - Flexbox all the things! +* Tidied up the LESS (and SCSS) as part of the above, variables and mixins in seprate files amking customization and upgrades easier +* Toggle mute bug fix; if a player was muted previously and the user refreshed, unmuting would have meant volume was still zero (effectively muted), now the config default value is used. Not ideal but good for now +* New `iconUrl` option allowing specifying a same origin SVG sprite location. Loading this way means you don't need the AJAX sprite loading JavaScript +* `click` option renamed to `clickToPlay` to make it a bit more self explanatory. Unfortunately cross origin SVG sprites is not supported in any browser yet :-( +* `hideControls` is now a global option, rather than being exclusive to fullscreen. Controls are now hidden after 2 seconds of no mouse movement. Controls are always shown when media is paused or stopped. This is defaulted to true. +* `sass` folder in `src` renamed from to `scss` ## v1.5.21 -- Bug fix for embeds: `play` not being defined (fixes #185 and #186) + +* Bug fix for embeds: `play` not being defined (fixes #185 and #186) ## v1.5.20 -- Bug fix for autoplay option + +* Bug fix for autoplay option ## v1.5.19 -- Fix for accessing `embed` property after `ready` event fired + +* Fix for accessing `embed` property after `ready` event fired ## v1.5.18 -- Added 'ready' event for initial setup complete or source change occurs -- Fixed SASS stylesheet references to transparentize -- Added default font stack to controls -- Docs fixes inc controls HTML (fixes #180) + +* Added 'ready' event for initial setup complete or source change occurs +* Fixed SASS stylesheet references to transparentize +* Added default font stack to controls +* Docs fixes inc controls HTML (fixes #180) ## v1.5.17 -- Expose YouTube and Vimeo API (docs update required) (fixes #176) -- Auto set title based on YouTube getVideoData() title property -- Bug fix for Vimeo API change (Uncaught TypeError: Cannot read property 'value' of undefined) due to a change their end + +* Expose YouTube and Vimeo API (docs update required) (fixes #176) +* Auto set title based on YouTube getVideoData() title property +* Bug fix for Vimeo API change (Uncaught TypeError: Cannot read property 'value' of undefined) due to a change their end ## v1.5.16 -- Cancel requests on source change (fixes #174) + +* Cancel requests on source change (fixes #174) ## v1.5.15 -- Fix for CustomEvent polyfill and related bug (see #172) + +* Fix for CustomEvent polyfill and related bug (see #172) ## v1.5.14 -- Volume storage fix (fixes #171) + +* Volume storage fix (fixes #171) ## v1.5.13 -- Fix for manual caption rendering + +* Fix for manual caption rendering ## v1.5.12 -- Added a duration option to pass the duration of the file -- Added the ability to set options per element by setting a data-plyr attribute on the target elements (this might be useful for the duration option for example) -- Fixes for Chrome and Safari caption rendering, they now use the default texttrack and cuechange events -- Firefox bug fix for event not defined + +* Added a duration option to pass the duration of the file +* Added the ability to set options per element by setting a data-plyr attribute on the target elements (this might be useful for the duration option for example) +* Fixes for Chrome and Safari caption rendering, they now use the default texttrack and cuechange events +* Firefox bug fix for event not defined ## v1.5.11 -- iOS embed bug fixes (fixes #166) -- Hide IE/Edge <input type='range'> tooltip (since we have a styled one) (fixes #160) -- SASS bug fix for default values (fixes #158) + +* iOS embed bug fixes (fixes #166) +* Hide IE/Edge <input type='range'> tooltip (since we have a styled one) (fixes #160) +* SASS bug fix for default values (fixes #158) ## v1.5.9 + v1.5.10 -- NPM bug fixes + +* NPM bug fixes ## v1.5.8 -- Fix for touch device seek tooltip -- Seek improvements + +* Fix for touch device seek tooltip +* Seek improvements ## v1.5.7 -- Fix for control tooltips always showing + +* Fix for control tooltips always showing ## v1.5.6 -- Seek tooltip (option for tooltips changed, please check docs) -- SASS compile error fixes (fixes #148) -- Fullscreen fixes for controls not always hiding/showing (fixes #149) -- Screen reader icon fixes (title was being read twice due to the tooltip/hidden label) + +* Seek tooltip (option for tooltips changed, please check docs) +* SASS compile error fixes (fixes #148) +* Fullscreen fixes for controls not always hiding/showing (fixes #149) +* Screen reader icon fixes (title was being read twice due to the tooltip/hidden label) ## v1.5.5 -- Fixed controls.md example -- Bug fix for docs error page -- Bug fix for controls tooltips + +* Fixed controls.md example +* Bug fix for docs error page +* Bug fix for controls tooltips ## v1.5.4 -- Minor bug fix for clicking video to play/pause after source change + +* Minor bug fix for clicking video to play/pause after source change ## v1.5.3 -- Minor bug fix for occasional display of 0:00 as the media duration + +* Minor bug fix for occasional display of 0:00 as the media duration ## v1.5.2 -- `handlers` option renamed to `listeners` -- Added event listeners for all types to the plyr container (playback, fullscreen, captions etc - see docs) -- Removed onSetup config option (use the 'setup' event instead, plyr element is event.plyr) -- Style bug fixes -- Vimeo seek bug fix (requires whole seconds when seeking) -- Fix for fullscreen player (using class hook, not browser fullscreen) + +* `handlers` option renamed to `listeners` +* Added event listeners for all types to the plyr container (playback, fullscreen, captions etc - see docs) +* Removed onSetup config option (use the 'setup' event instead, plyr element is event.plyr) +* Style bug fixes +* Vimeo seek bug fix (requires whole seconds when seeking) +* Fix for fullscreen player (using class hook, not browser fullscreen) ## v1.5.1 -- Fix for event listeners being duplicated on source change + +* Fix for event listeners being duplicated on source change # v1.5.0 -- Vimeo support (fixes #8) -- New options for initialization (you can now pass a selector, HTMLElement or NodeList) (fixes #118) -- Switched to BEM methodology (you will need to change CSS and probably HTML) -- Decoupled CSS and JS hooks (fixes #129) -- Custom controls container (fixes #98) -- Fix for private/incognito mode local storage bug (fixes #131) -- UMD module setup (fixes #121) -- Specify iframe title for Vimeo and YouTube (fixes #124) -- Better handling of mission controls (fixes #132) -- Retain classname on source change (fixes #120) -- Increased thumb size on seek (partially fixes #130) -- Passing no argument to `source` api method, now returns current source (by @gurupras) -- Ability to add custom handlers to controls prior to Plyr bindings (by @gurupras) -- Keyboard navigation improvements (focus on seek, focus trap in fullscreen) (fixes #135) + +* Vimeo support (fixes #8) +* New options for initialization (you can now pass a selector, HTMLElement or NodeList) (fixes #118) +* Switched to BEM methodology (you will need to change CSS and probably HTML) +* Decoupled CSS and JS hooks (fixes #129) +* Custom controls container (fixes #98) +* Fix for private/incognito mode local storage bug (fixes #131) +* UMD module setup (fixes #121) +* Specify iframe title for Vimeo and YouTube (fixes #124) +* Better handling of mission controls (fixes #132) +* Retain classname on source change (fixes #120) +* Increased thumb size on seek (partially fixes #130) +* Passing no argument to `source` api method, now returns current source (by @gurupras) +* Ability to add custom handlers to controls prior to Plyr bindings (by @gurupras) +* Keyboard navigation improvements (focus on seek, focus trap in fullscreen) (fixes #135) ## v1.3.5 -- Fixed bug with API use on basic supported browsers + +* Fixed bug with API use on basic supported browsers ## v1.3.4 -- Code cleanup by @calvintam236 + +* Code cleanup by @calvintam236 ## v1.3.3 -- Removed captions being read by screen readers + +* Removed captions being read by screen readers ## v1.3.2 -- Voiceover fix for captions + +* Voiceover fix for captions ## v1.3.1 -- ARIA improvements for captions being read + +* ARIA improvements for captions being read ## v1.3.0 -- Internationalization support (i18n) using default controls (required markup changes to controls) -- ARIA enhancements for controls (required markup changes to controls) -- Captions legibility improvements -- YouTube bug fixes + +* Internationalization support (i18n) using default controls (required markup changes to controls) +* ARIA enhancements for controls (required markup changes to controls) +* Captions legibility improvements +* YouTube bug fixes ## v1.2.6 -- SASS updates and fixes (cheers @ChristianPV) + +* SASS updates and fixes (cheers @ChristianPV) ## v1.2.5 -- Fix for YouTube quality (let them decide quality) + +* Fix for YouTube quality (let them decide quality) ## v1.2.4 -- Fix for omitted kind attribute on <track> (fixes #88) + +* Fix for omitted kind attribute on <track> (fixes #88) ## v1.2.3 -- Fix for YouTube on iPhone or unsupported browsers (fallback to YouTube native) -- Docs tidy up -- Fullscreen for Safari fix (fixes #96) + +* Fix for YouTube on iPhone or unsupported browsers (fallback to YouTube native) +* Docs tidy up +* Fullscreen for Safari fix (fixes #96) ## v1.2.2 -- Fix for :focus keyboard vs mouse (fixes #61) -- Fix for caption positioning in full screen (fixes #92) + +* Fix for :focus keyboard vs mouse (fixes #61) +* Fix for caption positioning in full screen (fixes #92) ## v1.2.1 -- Tooltip bug fix + +* Tooltip bug fix # v1.2.0 -- Added YouTube support + +* Added YouTube support ## v1.1.13 -- Added icon prefix option for when using default controls + +* Added icon prefix option for when using default controls ## v1.1.13 -- Logic tweaks for hiding controls in fullscreen + +* Logic tweaks for hiding controls in fullscreen ## v1.1.12 -- Bug fix for Chrome Canary + +* Bug fix for Chrome Canary ## v1.1.11 -- Bug fix + +* Bug fix ## v1.1.10 -- Bug fix + +* Bug fix ## v1.1.9 -- Bug fix for 1.1.8 + +* Bug fix for 1.1.8 ## v1.1.8 -- setVolume API method improvements (fixes #83) + +* setVolume API method improvements (fixes #83) ## v1.1.7 -- Restore classname on destroy() + +* Restore classname on destroy() ## v1.1.6 -- New API methods (fixes #77), Fix for non strict mode (fixes #78) + +* New API methods (fixes #77), Fix for non strict mode (fixes #78) ## v1.1.5 -- Fix for incorrect `isFullscreen()` return value in Mozilla (fixes #38) + +* Fix for incorrect `isFullscreen()` return value in Mozilla (fixes #38) ## v1.1.4 -- Minor bug fixes + +* Minor bug fixes ## v1.1.3 -- Fixes for random id used in controls with multiple instances and one call to setup -- Audio player UI improvements + +* Fixes for random id used in controls with multiple instances and one call to setup +* Audio player UI improvements ## v1.1.2 -- Added an onSetup callback option -- Added fullscreen API methods `toggleFullscreen()` (must be user iniated), and `isFullscreen()` + +* Added an onSetup callback option +* Added fullscreen API methods `toggleFullscreen()` (must be user iniated), and `isFullscreen()` ## v1.1.1 -- Fix for unsupported browser handling -- Fix for config.controls having no effect + +* Fix for unsupported browser handling +* Fix for config.controls having no effect ## v1.1.0 -- Added config option to set which controls are shown (if using the default controls html) and better handling of missing controls + +* Added config option to set which controls are shown (if using the default controls html) and better handling of missing controls ## v1.0.31 -- Display duration on `metadataloaded` + +* Display duration on `metadataloaded` ## v1.0.30 -- Fixed bug with media longer than 60 minutes (fixes #69) + +* Fixed bug with media longer than 60 minutes (fixes #69) ## v1.0.29 -- Added option to hide controls on fullscreen (default `true`) while palying, after 1s. Pause, mouse hover on progress, or focus on a child control re-shows the controls. On touch a tap of the video (which plays/pauses the video by default) is required. (fixes #47) -- Fixed a bug with caption toggle in 1.0.28 + +* Added option to hide controls on fullscreen (default `true`) while palying, after 1s. Pause, mouse hover on progress, or focus on a child control re-shows the controls. On touch a tap of the video (which plays/pauses the video by default) is required. (fixes #47) +* Fixed a bug with caption toggle in 1.0.28 ## v1.0.28 -- Added API support for browsers that don't have full plyr support (pretty much <=IE9 and `<video>` on iPhone/iPod) + +* Added API support for browsers that don't have full plyr support (pretty much <=IE9 and `<video>` on iPhone/iPod) ## v1.0.27 -- Keyboard accessibility improvements (fixes #66) + +* Keyboard accessibility improvements (fixes #66) ## v1.0.26 -- Fixes for SASS (cheers @brunowego) -- Indentation reset to 4 spaces + +* Fixes for SASS (cheers @brunowego) +* Indentation reset to 4 spaces ## v1.0.25 -- Fixes for iOS volume controls (hidden) -- Classnames for left/right controls changed + +* Fixes for iOS volume controls (hidden) +* Classnames for left/right controls changed ## v1.0.24 -- Added tooltip option to display labels as tooltips (fixes #50) + +* Added tooltip option to display labels as tooltips (fixes #50) ## v1.0.23 -- Handling loading states in the UI (fixes #36) + +* Handling loading states in the UI (fixes #36) ## v1.0.22 -- Added support() API method for checking mimetype support -- Added source() API method for setting media source(s) (fixes #44) -- Added poster() API method for setting poster source -- Refactored captions logic for manual captions + +* Added support() API method for checking mimetype support +* Added source() API method for setting media source(s) (fixes #44) +* Added poster() API method for setting poster source +* Refactored captions logic for manual captions ## v1.0.21 -- Added an <input type="range"> for seeking to improve experience (and support dragging) (fixes #40, #42) -- Icons for restart and captions improved (and some IDs changed) (fixes #49) + +* Added an <input type="range"> for seeking to improve experience (and support dragging) (fixes #40, #42) +* Icons for restart and captions improved (and some IDs changed) (fixes #49) ## v1.0.20 -- Default controls included (Fixes #45) -- Volume changes on `input` as well as `change` (fixes #43) -- Fix for undefined Play text -- License changed to MIT + +* Default controls included (Fixes #45) +* Volume changes on `input` as well as `change` (fixes #43) +* Fix for undefined Play text +* License changed to MIT ## v1.0.19 -- Fixed firefox fullscreen issue (fixes #38) + +* Fixed firefox fullscreen issue (fixes #38) ## v1.0.18 -- Added CDN references + +* Added CDN references ## v1.0.17 -- SASS support added (thanks to @brunowego) -- Docs completely separated to avoid any confusion -- New gulp tasks (will add more documentation for this) + +* SASS support added (thanks to @brunowego) +* Docs completely separated to avoid any confusion +* New gulp tasks (will add more documentation for this) ## v1.0.16 -- Aria label is now dynamic + +* Aria label is now dynamic ## v1.0.15 -- Fix for seek time display in controls -- More documentation for controls html + +* Fix for seek time display in controls +* More documentation for controls html ## v1.0.14 -- Minor change for bootstrap compatibility + +* Minor change for bootstrap compatibility ## v1.0.13 -- Minor tweaks + +* Minor tweaks ## v1.0.12 -- Handle native events (issue #34) + +* Handle native events (issue #34) ## v1.0.11 -- Bug fixes for fullscreen mode + +* Bug fixes for fullscreen mode ## v1.0.10 -- Bower includes src files now -- Folder re-arrangement + +* Bower includes src files now +* Folder re-arrangement ## v1.0.9 -- Added buffer progress bar -- Fixed Safari 8 caption track (it needs to be removed from the DOM like in Safari 7) -- Added validation (it works or it doesn't basically) of the `html` option passed + +* Added buffer progress bar +* Fixed Safari 8 caption track (it needs to be removed from the DOM like in Safari 7) +* Added validation (it works or it doesn't basically) of the `html` option passed ## v1.0.8 -- Bug fix + +* Bug fix ## v1.0.7 -- Storing user selected volume in local storage + +* Storing user selected volume in local storage ## v1.0.6 -- Fullscreen fallback for older browsers to use "full window" + +* Fullscreen fallback for older browsers to use "full window" ## v1.0.5 -- More minor bug fixes and improvements + +* More minor bug fixes and improvements ## v1.0.4 -- Fixed caption legibility issues + +* Fixed caption legibility issues ## v1.0.3 -- Minor bug fixes + +* Minor bug fixes ## v1.0.2 -- Added OGG to <audio> example for Firefox -- Fixed IE11 fullscreen issues + +* Added OGG to <audio> example for Firefox +* Fixed IE11 fullscreen issues ## v1.0.1 -- Bug fixes for IE (as per usual) -- Added CSS hooks for media type -- Return instances of Plyr to the element + +* Bug fixes for IE (as per usual) +* Added CSS hooks for media type +* Return instances of Plyr to the element ## v1.0.0 -- Initial release + +* Initial release diff --git a/demo/dist/demo.css b/demo/dist/demo.css index c01a1dd5..2f44268b 100644 --- a/demo/dist/demo.css +++ b/demo/dist/demo.css @@ -1 +1 @@ -/*! normalize.css v2.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}a{background:0 0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=search]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@-webkit-keyframes fade-in{0%{opacity:0}100%{opacity:1}}@keyframes fade-in{0%{opacity:0}100%{opacity:1}}@font-face{font-family:Avenir;src:url(https://cdn.plyr.io/static/fonts/avenir-medium.woff2) format('woff2'),url(https://cdn.plyr.io/static/fonts/avenir-medium.woff) format('woff');font-style:normal;font-weight:500;font-display:swap}@font-face{font-family:Avenir;src:url(https://cdn.plyr.io/static/fonts/avenir-bold.woff2) format('woff2'),url(https://cdn.plyr.io/static/fonts/avenir-bold.woff) format('woff');font-style:normal;font-weight:700;font-display:swap}html{font-size:100%}body{font-family:Avenir,"Helvetica Neue",Helvetica,Arial,sans-serif;line-height:1.5;text-align:center;color:#55646b;font-weight:500;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}h1,h2{letter-spacing:-.025em;color:#3498db;margin:0 0 10px;line-height:1.2;font-weight:700}h1{font-size:64px;font-size:4rem}p,small{margin:0 0 20px}small{display:block;padding:0 10px;font-size:14px;font-size:.875rem}li,ul{list-style:none;margin:0;padding:0}a{text-decoration:none;color:#3498db;border-bottom:1px dotted currentColor;-webkit-transition:background .3s ease,color .3s ease,border .3s ease;transition:background .3s ease,color .3s ease,border .3s ease}a:focus,a:hover{color:#343f4a;border-bottom-color:transparent}a:focus{outline:thin dotted #343f4a;outline-offset:1px}a.logo{border:0}.color--vimeo{color:#19b7ed}.color--youtube{color:#cc181e}*,::after,::before{-webkit-box-sizing:border-box;box-sizing:border-box}[hidden]{display:none}html{height:100%;background:#f2f5f7 fixed}body{margin:0;padding:10px}header{padding:20px;margin-bottom:20px}header p{font-size:18px;font-size:1.125rem}@media (min-width:480px){header{padding-top:60px;padding-bottom:60px}}section{max-width:1200px;margin:0 auto 20px}@media (min-width:480px){section{margin-bottom:40px}}.icon{fill:currentColor;width:18px;height:18px;vertical-align:-3px}a svg,button svg,label svg{pointer-events:none}.btn .icon,a .icon{margin-right:10px}.btn:not(.btn-large) .icon{width:16px;height:16px}nav ul{list-style:none;margin:0;padding:0;font-size:0}nav li{display:inline-block;margin-top:10px;font-size:16px;font-size:1rem;white-space:nowrap}nav li+li{margin-left:20px}.btn__bar{position:relative;margin:0 auto 20px;max-width:1200px;white-space:nowrap}.btn__bar::before{content:"";position:absolute;top:50%;left:0;right:0;height:1px;background:#dbe3e8}.btn__bar ul{position:relative;z-index:1;display:inline-block;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn__bar li{margin:0}.btn__bar li:first-child .btn{border-radius:4px 0 0 4px}.btn__bar li:last-child .btn{border-radius:0 4px 4px 0}.btn__bar li+li .btn{margin-left:-1px}.btn__bar li.active .btn{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.2);box-shadow:inset 0 1px 1px rgba(0,0,0,.2);position:relative;z-index:1}.btn__bar li.active .btn .icon{color:inherit}.btn__bar li.active+li .btn:hover{z-index:0}.btn__bar .btn{position:relative;display:block;border-radius:0}.btn__bar .btn:focus,.btn__bar .btn:hover{z-index:1}@media (min-width:560px){.btn__bar{margin-bottom:40px}}.btn,.btn__count{display:inline-block;vertical-align:middle;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-weight:700}.btn{padding:10px 12px;background:-webkit-gradient(linear,left top,left bottom,from(#f8fafb),to(#e9eef1));background:linear-gradient(#f8fafb,#e9eef1);border:1px solid #cbd0d3;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05);text-shadow:0 1px 1px #fff;color:#55646b;-webkit-transition:background .1s ease,color .1s ease;transition:background .1s ease,color .1s ease;font-size:14px;font-size:.875rem}.btn:focus,.btn:hover{border-color:#b5bcc0;color:#55646b;outline:0}.btn--large{padding:10px 20px;font-size:16px;font-size:1rem}.btn--primary,.btn__bar li.active .btn{background-image:-webkit-gradient(linear,left top,left bottom,from(#3498db),to(#258cd1));background-image:linear-gradient(#3498db,#258cd1);background-color:#3498db;border-color:#217dbb;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.15);box-shadow:0 1px 1px rgba(0,0,0,.15);text-shadow:0 1px 1px rgba(0,0,0,.1);color:#fff}.btn--primary:focus,.btn--primary:hover{color:#fff;border-color:#196090}.btn--youtube .icon{color:#cc181e}.btn--vimeo .icon{color:#19b7ed}.btn--twitter .icon{color:#4baaf4}.btn__count{position:relative;margin-left:10px;padding:10px 15px;background:#fff;border:1px solid #cbd0d3}.btn__count::before{content:"";position:absolute;display:block;width:8px;height:8px;left:1px;top:50%;margin-top:-4px;background:inherit;border:inherit;border-width:1px 0 0 1px;-webkit-transform:rotate(-45deg) translate(-50%,-50%);transform:rotate(-45deg) translate(-50%,-50%)}.error body,html.error{height:100%}.error body{width:100%;display:table;table-layout:fixed}.error main{display:table-cell;width:100%;vertical-align:middle}video{max-width:100%;vertical-align:middle}.plyr{margin:0 auto;border-radius:6px}.plyr--audio{max-width:520px}.plyr__video-wrapper::after{content:"";pointer-events:none;position:absolute;top:0;bottom:0;left:0;right:0;border:1px solid rgba(0,0,0,.15);border-radius:inherit}.plyr__cite{display:none;margin-top:20px}.plyr__cite .icon{margin-right:5px}.plyr--audio~ul .plyr__cite--audio,.plyr--video:not(.plyr--youtube):not(.plyr--vimeo)~ul .plyr__cite--video,.plyr--vimeo~ul .plyr__cite--vimeo,.plyr--youtube~ul .plyr__cite--youtube{display:block}
\ No newline at end of file +@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:300;src:url(https://cdn.plyr.io/static/fonts/gordita-light.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-light.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:400;src:url(https://cdn.plyr.io/static/fonts/gordita-regular.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-regular.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:500;src:url(https://cdn.plyr.io/static/fonts/gordita-medium.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-medium.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:600;src:url(https://cdn.plyr.io/static/fonts/gordita-bold.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-bold.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:900;src:url(https://cdn.plyr.io/static/fonts/gordita-black.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-black.woff) format("woff")}@-webkit-keyframes fadein{0%{opacity:0}100%{opacity:1}}@keyframes fadein{0%{opacity:0}100%{opacity:1}}/*! normalize.css v2.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}a,button.faux-link{background:0 0}a:focus,button.faux-link:focus{outline:thin dotted}a:active,a:hover,button.faux-link:active,button.faux-link:hover{outline:0}h1{font-size:2em;margin:.67em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}hr{box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:'\201C' '\201D' '\2018' '\2019'}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}*,::after,::before{box-sizing:border-box}body,html{display:-webkit-box;display:flex;width:100%}html{background:linear-gradient(to left top,#4dc1ff,#0074b3);background-attachment:fixed;height:100%}body{-webkit-box-align:center;align-items:center;display:-webkit-box;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-direction:column;min-height:100%}.grid{-webkit-box-flex:1;flex:1;overflow:auto}main{margin:auto;text-align:center}aside{-webkit-box-align:center;align-items:center;background:#fff;color:#55646b;display:-webkit-box;display:flex;flex-shrink:0;-webkit-box-pack:center;justify-content:center;padding:15px;position:relative;text-align:center;text-shadow:none;width:100%}aside .icon{fill:#4baaf4;margin-right:10px}aside p{margin:0}aside a,aside button.faux-link{color:#4baaf4}aside a.tab-focus,aside button.tab-focus.faux-link{box-shadow:0 0 0 3px rgba(75,170,244,.35);outline:0}.grid{margin:0 auto;padding:20px}@media only screen and (min-width:768px){.grid{-webkit-box-align:center;align-items:center;display:-webkit-box;display:flex;max-width:1280px;width:100%}.grid>*{-webkit-box-flex:1;flex:1}}html{font-size:100%}body{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-size:15px;font-size:.9375rem;color:#fff;font-family:Gordita,Avenir,"Helvetica Neue",sans-serif;font-weight:500;line-height:1.75;text-shadow:0 1px 1px rgba(0,0,0,.15)}button,input,select,textarea{font:inherit}p,small{margin:0 0 20px}small{font-size:13px;font-size:.8125rem;display:block}h1{font-size:64px;font-size:4rem;font-weight:600;letter-spacing:-.025em;margin:0 0 10px}.button,.button__count{-webkit-box-align:center;align-items:center;background:#fff;border:0;border-radius:4px;box-shadow:0 1px 1px rgba(0,0,0,.1);color:#55646b;display:-webkit-inline-box;display:inline-flex;padding:15px;position:relative;text-shadow:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle}.button{font-weight:600;padding-left:20px;padding-right:20px;transition:all .2s ease}.button:focus,.button:hover{color:#343f4a}.button:focus::after,.button:hover::after{display:none}.button:hover{box-shadow:0 2px 2px rgba(0,0,0,.1);-webkit-transform:translateY(-1px);transform:translateY(-1px)}.button:focus{outline:0}.button.tab-focus{box-shadow:0 0 0 3px rgba(255,255,255,.35);outline:0}.button:active{-webkit-transform:translateY(1px);transform:translateY(1px)}.button--with-count{display:-webkit-inline-box;display:inline-flex}.button--with-count .button .icon{flex-shrink:0}.button__count{-webkit-animation:fadein .2s ease;animation:fadein .2s ease;margin-left:10px}.button__count::before{border:5px solid transparent;border-left-width:0;border-right-color:#fff;content:'';height:0;position:absolute;right:100%;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);width:0}header{padding-bottom:20px;text-align:center}header .call-to-action{margin-top:30px}@media only screen and (min-width:768px){header{margin-right:60px;max-width:360px;padding-bottom:40px;text-align:left}}.icon{fill:currentColor;height:16px;vertical-align:-3px;width:16px}a svg,button svg,button.faux-link svg,label svg{pointer-events:none}.btn .icon,a .icon,button.faux-link .icon{margin-right:6px}button.faux-link{background:0 0;border:0;border-radius:0;cursor:pointer;font:inherit;line-height:1.75;margin:0;padding:0;position:relative;text-align:inherit;text-shadow:inherit;-moz-user-select:text;vertical-align:baseline;width:auto}a,button.faux-link{border-bottom:1px dotted currentColor;color:#fff;font-weight:600;position:relative;text-decoration:none;transition:all .2s ease}a::after,button.faux-link::after{background:currentColor;content:'';height:1px;left:50%;position:absolute;top:100%;-webkit-transform:translateX(-50%);transform:translateX(-50%);transition:width .2s ease;width:0}a:focus,a:hover,button.faux-link:focus,button.faux-link:hover{border-bottom-color:transparent;outline:0}a:focus::after,a:hover::after,button.faux-link:focus::after,button.faux-link:hover::after{width:100%}a.tab-focus,button.tab-focus.faux-link{box-shadow:0 0 0 3px rgba(255,255,255,.35);outline:0}li,ul{list-style:none;margin:0;padding:0}nav{display:-webkit-box;display:flex;-webkit-box-pack:center;justify-content:center;margin-bottom:20px}video{max-width:100%;vertical-align:middle}.plyr{border-radius:4px;box-shadow:0 2px 5px rgba(0,0,0,.2);margin:20px auto}.plyr.plyr--audio{max-width:480px}.plyr__video-wrapper::after{border:1px solid rgba(0,0,0,.15);border-radius:inherit;bottom:0;content:'';left:0;pointer-events:none;position:absolute;right:0;top:0}.plyr__cite{display:none;margin-top:20px}.plyr__cite .icon{margin-right:4px}.plyr--audio~ul .plyr__cite--audio,.plyr--video:not(.plyr--youtube):not(.plyr--vimeo)~ul .plyr__cite--video,.plyr--vimeo~ul .plyr__cite--vimeo,.plyr--youtube~ul .plyr__cite--youtube{display:block}@-webkit-keyframes plyr-progress{to{background-position:25px 0}}@keyframes plyr-progress{to{background-position:25px 0}}@-webkit-keyframes plyr-popup{0%{opacity:.5;-webkit-transform:translateY(10px);transform:translateY(10px)}to{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes plyr-popup{0%{opacity:.5;-webkit-transform:translateY(10px);transform:translateY(10px)}to{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes plyr-fade-in{from{opacity:0}to{opacity:1}}@keyframes plyr-fade-in{from{opacity:0}to{opacity:1}}.plyr{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;direction:ltr;font-family:inherit;font-weight:500;line-height:1.7;max-width:100%;min-width:200px;position:relative;text-shadow:none;transition:box-shadow .3s ease}.plyr audio,.plyr video{border-radius:inherit;height:auto;vertical-align:middle;width:100%}.plyr:focus{outline:0}.plyr--full-ui{box-sizing:border-box}.plyr--full-ui *,.plyr--full-ui ::after,.plyr--full-ui ::before{box-sizing:inherit}.plyr--full-ui a,.plyr--full-ui button,.plyr--full-ui button.faux-link,.plyr--full-ui input,.plyr--full-ui label{touch-action:manipulation}.plyr__badge{background:#4f5b5f;border-radius:2px;color:rgba(255,255,255,.9);font-size:9px;line-height:1;padding:3px 4px}.plyr--full-ui ::-webkit-media-text-track-container{display:none}.plyr__captions{-webkit-animation:plyr-fade-in .3s ease;animation:plyr-fade-in .3s ease;bottom:0;color:#fff;display:none;font-size:12px;left:0;padding:10px;position:absolute;text-align:center;-webkit-transform:translateY(-40px);transform:translateY(-40px);transition:-webkit-transform .4s ease-in-out;transition:transform .4s ease-in-out;transition:transform .4s ease-in-out,-webkit-transform .4s ease-in-out;width:100%}.plyr__captions span{background:rgba(0,0,0,.8);border-radius:2px;-webkit-box-decoration-break:clone;box-decoration-break:clone;line-height:185%;padding:.2em .5em;white-space:pre-wrap}.plyr__captions span div{display:inline}.plyr__captions span:empty{display:none}@media (min-width:480px){.plyr__captions{font-size:13px;padding:20px}}@media (min-width:768px){.plyr__captions{font-size:18px}}.plyr--captions-active .plyr__captions{display:block}.plyr--hide-controls .plyr__captions{-webkit-transform:translateY(-15px);transform:translateY(-15px)}.plyr__control{background:0 0;border:0;border-radius:3px;color:inherit;cursor:pointer;flex-shrink:0;overflow:visible;padding:7px;position:relative;transition:all .3s ease}.plyr__control svg{display:block;fill:currentColor;height:18px;pointer-events:none;width:18px}.plyr__control:focus{outline:0}.plyr__control.plyr__tab-focus{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr__control[aria-pressed=false] .icon--pressed,.plyr__control[aria-pressed=false] .label--pressed,.plyr__control[aria-pressed=true] .icon--not-pressed,.plyr__control[aria-pressed=true] .label--not-pressed{display:none}.plyr--audio .plyr__control.plyr__tab-focus,.plyr--audio .plyr__control:hover,.plyr--audio .plyr__control[aria-expanded=true]{background:#1aafff;color:#fff}.plyr__control--overlaid{background:rgba(26,175,255,.8);border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15);color:#fff;display:none;left:50%;padding:15px;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);z-index:2}.plyr__control--overlaid svg{height:20px;left:2px;position:relative;width:20px}.plyr__control--overlaid:focus,.plyr__control--overlaid:hover{background:#1aafff}.plyr--playing .plyr__control--overlaid{opacity:0;visibility:hidden}.plyr--full-ui.plyr--video .plyr__control--overlaid{display:block}.plyr--full-ui ::-webkit-media-controls{display:none}.plyr__controls{-webkit-box-align:center;align-items:center;display:-webkit-box;display:flex;text-align:center}.plyr__controls .plyr__menu,.plyr__controls .plyr__progress,.plyr__controls .plyr__time,.plyr__controls>.plyr__control{margin-left:5px}.plyr__controls .plyr__menu:first-child,.plyr__controls .plyr__menu:first-child+[data-plyr=pause],.plyr__controls .plyr__progress:first-child,.plyr__controls .plyr__progress:first-child+[data-plyr=pause],.plyr__controls .plyr__time:first-child,.plyr__controls .plyr__time:first-child+[data-plyr=pause],.plyr__controls>.plyr__control:first-child,.plyr__controls>.plyr__control:first-child+[data-plyr=pause]{margin-left:0}.plyr__controls .plyr__volume{margin-left:5px}@media (min-width:480px){.plyr__controls .plyr__menu,.plyr__controls .plyr__progress,.plyr__controls .plyr__time,.plyr__controls>.plyr__control{margin-left:10px}.plyr__controls .plyr__menu+.plyr__control,.plyr__controls>.plyr__control+.plyr__control,.plyr__controls>.plyr__control+.plyr__menu{margin-left:5px}}.plyr--video .plyr__controls{background:linear-gradient(transparent,rgba(0,0,0,.7));border-bottom-left-radius:inherit;border-bottom-right-radius:inherit;bottom:0;color:#fff;left:0;padding:35px 10px 10px;position:absolute;right:0;transition:opacity .4s ease-in-out,-webkit-transform .4s ease-in-out;transition:opacity .4s ease-in-out,transform .4s ease-in-out;transition:opacity .4s ease-in-out,transform .4s ease-in-out,-webkit-transform .4s ease-in-out;z-index:2}.plyr--video .plyr__controls .plyr__control svg{-webkit-filter:drop-shadow(0 1px 1px rgba(0, 0, 0, .15));filter:drop-shadow(0 1px 1px rgba(0, 0, 0, .15))}.plyr--video .plyr__controls .plyr__control.plyr__tab-focus,.plyr--video .plyr__controls .plyr__control:hover,.plyr--video .plyr__controls .plyr__control[aria-expanded=true]{background:#1aafff;color:#fff}.plyr--audio .plyr__controls{background:#fff;border-radius:inherit;color:#4f5b5f;padding:10px}.plyr--video.plyr--hide-controls .plyr__controls{opacity:0;pointer-events:none;-webkit-transform:translateY(100%);transform:translateY(100%)}.plyr [data-plyr=airplay],.plyr [data-plyr=captions],.plyr [data-plyr=fullscreen],.plyr [data-plyr=pip]{display:none}.plyr--airplay-supported [data-plyr=airplay],.plyr--captions-enabled [data-plyr=captions],.plyr--fullscreen-enabled [data-plyr=fullscreen],.plyr--pip-supported [data-plyr=pip]{display:inline-block}.plyr__video-embed{height:0;padding-bottom:56.25%}.plyr__video-embed iframe{border:0;height:100%;left:0;position:absolute;top:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.plyr__video-embed>div{padding-bottom:200%;position:relative;-webkit-transform:translateY(-35.9375%);transform:translateY(-35.9375%)}.plyr--full-ui .plyr__video-embed iframe{pointer-events:none}.plyr__menu{display:-webkit-box;display:flex;position:relative}.plyr__menu .plyr__control svg{transition:-webkit-transform .3s ease;transition:transform .3s ease;transition:transform .3s ease,-webkit-transform .3s ease}.plyr__menu .plyr__control[aria-expanded=true] svg{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.plyr__menu .plyr__control[aria-expanded=true] .plyr__tooltip{display:none}.plyr__menu__container{-webkit-animation:plyr-popup .2s ease;animation:plyr-popup .2s ease;background:rgba(255,255,255,.9);border-radius:4px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);color:#4f5b5f;font-size:13px;margin-bottom:10px;position:absolute;right:-3px;text-align:left;white-space:nowrap;z-index:1}.plyr__menu__container>div{overflow:hidden;transition:height .35s cubic-bezier(.4,0,.2,1),width .35s cubic-bezier(.4,0,.2,1)}.plyr__menu__container::after{border:4px solid transparent;border-top-color:rgba(255,255,255,.9);content:'';height:0;position:absolute;right:15px;top:100%;width:0}.plyr__menu__container ul{list-style:none;margin:0;overflow:hidden;padding:7px}.plyr__menu__container .plyr__control{-webkit-box-align:center;align-items:center;color:#4f5b5f;display:-webkit-box;display:flex;padding:4px 14px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.plyr__menu__container .plyr__control::after{border:4px solid transparent;content:'';position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);transition:border-color .2s ease}.plyr__menu__container .plyr__control--forward{padding-right:28px}.plyr__menu__container .plyr__control--forward::after{border-left-color:rgba(79,91,95,.8);right:5px}.plyr__menu__container .plyr__control--forward.plyr__tab-focus::after,.plyr__menu__container .plyr__control--forward:hover::after{border-left-color:currentColor}.plyr__menu__container .plyr__control--back{font-weight:500;margin:7px;margin-bottom:3px;padding-left:28px;position:relative;width:calc(100% - 14px)}.plyr__menu__container .plyr__control--back::after{border-right-color:rgba(79,91,95,.8);left:7px}.plyr__menu__container .plyr__control--back::before{background:#b7c5cd;box-shadow:0 1px 0 #fff;content:'';height:1px;left:0;margin-top:4px;overflow:hidden;position:absolute;right:0;top:100%}.plyr__menu__container .plyr__control--back.plyr__tab-focus::after,.plyr__menu__container .plyr__control--back:hover::after{border-right-color:currentColor}.plyr__menu__container label.plyr__control{padding-left:7px}.plyr__menu__container label.plyr__control input[type=radio]+span{background:rgba(0,0,0,.1);border-radius:100%;display:block;flex-shrink:0;height:16px;margin-right:10px;position:relative;transition:all .3s ease;width:16px}.plyr__menu__container label.plyr__control input[type=radio]+span::after{background:#fff;border-radius:100%;content:'';height:6px;left:5px;opacity:0;position:absolute;top:5px;-webkit-transform:scale(0);transform:scale(0);transition:opacity .3s ease,-webkit-transform .3s ease;transition:transform .3s ease,opacity .3s ease;transition:transform .3s ease,opacity .3s ease,-webkit-transform .3s ease;width:6px}.plyr__menu__container label.plyr__control input[type=radio]:checked+span{background:#1aafff}.plyr__menu__container label.plyr__control input[type=radio]:checked+span::after{opacity:1;-webkit-transform:scale(1);transform:scale(1)}.plyr__menu__container label.plyr__control input[type=radio]:focus+span{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr__menu__container label.plyr__control.plyr__tab-focus input[type=radio]+span,.plyr__menu__container label.plyr__control:hover input[type=radio]+span{background:rgba(0,0,0,.1)}.plyr__menu__container .plyr__menu__value{-webkit-box-align:center;align-items:center;display:-webkit-box;display:flex;margin-left:auto;margin-right:-7px;overflow:hidden;padding-left:25px;pointer-events:none}.plyr__progress{display:-webkit-box;display:flex;-webkit-box-flex:1;flex:1;position:relative}.plyr__progress input[type=range]{position:relative;z-index:2}.plyr__progress .plyr__tooltip{font-size:11px;left:0}.plyr__progress--buffer{-webkit-appearance:none;background:0 0;border:0;border-radius:100px;height:6px;left:0;margin:-3px 0 0;padding:0;position:absolute;top:50%;width:100%}.plyr__progress--buffer::-webkit-progress-bar{background:0 0;transition:width .2s ease}.plyr__progress--buffer::-webkit-progress-value{background:currentColor;border-radius:100px;min-width:6px}.plyr__progress--buffer::-moz-progress-bar{background:currentColor;border-radius:100px;min-width:6px;transition:width .2s ease}.plyr__progress--buffer::-ms-fill{border-radius:100px;transition:width .2s ease}.plyr--video .plyr__progress--buffer{box-shadow:0 1px 1px rgba(0,0,0,.15);color:rgba(255,255,255,.25)}.plyr--audio .plyr__progress--buffer{color:rgba(183,197,205,.66)}.plyr--loading .plyr__progress--buffer{-webkit-animation:plyr-progress 1s linear infinite;animation:plyr-progress 1s linear infinite;background-image:linear-gradient(-45deg,rgba(47,52,61,.6) 25%,transparent 25%,transparent 50%,rgba(47,52,61,.6) 50%,rgba(47,52,61,.6) 75%,transparent 75%,transparent);background-repeat:repeat-x;background-size:25px 25px;color:transparent}.plyr--video.plyr--loading .plyr__progress--buffer{background-color:rgba(255,255,255,.25)}.plyr--audio.plyr--loading .plyr__progress--buffer{background-color:rgba(183,197,205,.66)}.plyr--full-ui input[type=range]{-webkit-appearance:none;background:0 0;border:0;border-radius:28px;color:#1aafff;cursor:pointer;display:block;height:20px;margin:0;padding:0;transition:box-shadow .3s ease;width:100%}.plyr--full-ui input[type=range]::-webkit-slider-runnable-track{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-webkit-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-webkit-slider-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);box-sizing:border-box;height:14px;position:relative;transition:all .2s ease;width:14px;-webkit-appearance:none;margin-top:-4px}.plyr--full-ui input[type=range]::-moz-range-track{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-moz-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-moz-range-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);box-sizing:border-box;height:14px;position:relative;transition:all .2s ease;width:14px}.plyr--full-ui input[type=range]::-moz-range-progress{background:currentColor;border-radius:3px;height:6px}.plyr--full-ui input[type=range]::-ms-track{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-ms-user-select:none;user-select:none;color:transparent}.plyr--full-ui input[type=range]::-ms-fill-upper{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-ms-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-ms-fill-lower{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-ms-user-select:none;user-select:none;background:currentColor}.plyr--full-ui input[type=range]::-ms-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);box-sizing:border-box;height:14px;position:relative;transition:all .2s ease;width:14px;margin-top:0}.plyr--full-ui input[type=range]::-ms-tooltip{display:none}.plyr--full-ui input[type=range]:focus{outline:0}.plyr--full-ui input[type=range]::-moz-focus-outer{border:0}.plyr--full-ui input[type=range].plyr__tab-focus::-webkit-slider-runnable-track{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr--full-ui input[type=range].plyr__tab-focus::-moz-range-track{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr--full-ui input[type=range].plyr__tab-focus::-ms-track{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr--full-ui input[type=range]:active::-webkit-slider-thumb{box-shadow:0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui input[type=range]:active::-moz-range-thumb{box-shadow:0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui input[type=range]:active::-ms-thumb{box-shadow:0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui.plyr--video input[type=range]::-webkit-slider-runnable-track{background:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]::-moz-range-track{background:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]::-ms-track{background:rgba(255,255,255,.25)}.plyr--full-ui.plyr--audio input[type=range]::-webkit-slider-runnable-track{background:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]::-moz-range-track{background:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]::-ms-track{background:rgba(183,197,205,.66)}.plyr__time{font-size:11px}.plyr__time+.plyr__time::before{content:'\2044';margin-right:10px}@media (max-width:767px){.plyr__time+.plyr__time{display:none}}.plyr--video .plyr__time{text-shadow:0 1px 1px rgba(0,0,0,.15)}.plyr__tooltip{background:rgba(255,255,255,.9);border-radius:3px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);color:#4f5b5f;font-size:12px;font-weight:500;line-height:1.3;margin-bottom:10px;opacity:0;padding:5px 7.5px;pointer-events:none;position:absolute;-webkit-transform:translate(-50%,10px) scale(.8);transform:translate(-50%,10px) scale(.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;transition:opacity .2s .1s ease,-webkit-transform .2s .1s ease;transition:transform .2s .1s ease,opacity .2s .1s ease;transition:transform .2s .1s ease,opacity .2s .1s ease,-webkit-transform .2s .1s ease;z-index:2}.plyr__tooltip::before{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(255,255,255,.9);bottom:-4px;content:'';height:0;left:50%;position:absolute;-webkit-transform:translateX(-50%);transform:translateX(-50%);width:0;z-index:2}.plyr .plyr__control.plyr__tab-focus .plyr__tooltip,.plyr .plyr__control:hover .plyr__tooltip,.plyr__tooltip--visible{opacity:1;-webkit-transform:translate(-50%,0) scale(1);transform:translate(-50%,0) scale(1)}.plyr .plyr__control:hover .plyr__tooltip{z-index:3}.plyr__controls>.plyr__control:first-child .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip{left:0;-webkit-transform:translate(0,10px) scale(.8);transform:translate(0,10px) scale(.8);-webkit-transform-origin:0 100%;transform-origin:0 100%}.plyr__controls>.plyr__control:first-child .plyr__tooltip::before,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip::before{left:16px}.plyr__controls>.plyr__control:last-child .plyr__tooltip{right:0;-webkit-transform:translate(0,10px) scale(.8);transform:translate(0,10px) scale(.8);-webkit-transform-origin:100% 100%;transform-origin:100% 100%}.plyr__controls>.plyr__control:last-child .plyr__tooltip::before{left:auto;right:16px;-webkit-transform:translateX(50%);transform:translateX(50%)}.plyr__controls>.plyr__control:first-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control:hover .plyr__tooltip,.plyr__controls>.plyr__control:first-child.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:first-child:hover .plyr__tooltip,.plyr__controls>.plyr__control:last-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:last-child.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:last-child:hover .plyr__tooltip{-webkit-transform:translate(0,0) scale(1);transform:translate(0,0) scale(1)}.plyr--video{overflow:hidden}.plyr--video.plyr--menu-open{overflow:visible}.plyr__video-wrapper{background:#000;border-radius:inherit;overflow:hidden;position:relative;z-index:0}.plyr__volume{-webkit-box-flex:1;flex:1;position:relative}.plyr__volume input[type=range]{position:relative;z-index:2}@media (min-width:480px){.plyr__volume{max-width:50px}}@media (min-width:768px){.plyr__volume{max-width:80px}}.plyr--is-ios .plyr__volume,.plyr--is-ios [data-plyr=mute]{display:none!important}.plyr--has-error{pointer-events:none}.plyr--has-error::after{-webkit-box-align:center;align-items:center;background:#000;color:#fff;content:attr(data-plyr-error);display:-webkit-box;display:flex;font-size:13px;height:100%;-webkit-box-pack:center;justify-content:center;left:0;position:absolute;text-align:center;text-shadow:0 1px 1px #000;top:0;width:100%;z-index:10}.plyr:-webkit-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-moz-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-ms-fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-webkit-full-screen video{height:100%}.plyr:-moz-full-screen video{height:100%}.plyr:-ms-fullscreen video{height:100%}.plyr:fullscreen video{height:100%}.plyr:-webkit-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-moz-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-ms-fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:-webkit-full-screen .plyr__video-embed{overflow:visible}.plyr:-moz-full-screen .plyr__video-embed{overflow:visible}.plyr:-ms-fullscreen .plyr__video-embed{overflow:visible}.plyr:fullscreen .plyr__video-embed{overflow:visible}.plyr:-webkit-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.plyr:-moz-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-ms-fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}@media (min-width:1024px){.plyr:-webkit-full-screen .plyr__captions{font-size:21px}.plyr:-moz-full-screen .plyr__captions{font-size:21px}.plyr:-ms-fullscreen .plyr__captions{font-size:21px}.plyr:fullscreen .plyr__captions{font-size:21px}}.plyr:-webkit-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-webkit-full-screen video{height:100%}.plyr:-webkit-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-webkit-full-screen .plyr__video-embed{overflow:visible}.plyr:-webkit-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}@media (min-width:1024px){.plyr:-webkit-full-screen .plyr__captions{font-size:21px}}.plyr:-moz-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-moz-full-screen video{height:100%}.plyr:-moz-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-moz-full-screen .plyr__video-embed{overflow:visible}.plyr:-moz-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}@media (min-width:1024px){.plyr:-moz-full-screen .plyr__captions{font-size:21px}}.plyr:-ms-fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-ms-fullscreen video{height:100%}.plyr:-ms-fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:-ms-fullscreen .plyr__video-embed{overflow:visible}.plyr:-ms-fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}@media (min-width:1024px){.plyr:-ms-fullscreen .plyr__captions{font-size:21px}}.plyr--fullscreen-fallback{background:#000;border-radius:0!important;height:100%;margin:0;width:100%;bottom:0;left:0;position:fixed;right:0;top:0;z-index:10000000}.plyr--fullscreen-fallback video{height:100%}.plyr--fullscreen-fallback .plyr__video-wrapper{height:100%;width:100%}.plyr--fullscreen-fallback .plyr__video-embed{overflow:visible}.plyr--fullscreen-fallback.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen{display:block}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen+svg{display:none}@media (min-width:1024px){.plyr--fullscreen-fallback .plyr__captions{font-size:21px}}.plyr--no-transition{transition:none!important}.plyr--full-ui [hidden]{display:none}.plyr--full-ui [aria-hidden=true]{display:none}.plyr__sr-only{clip:rect(1px,1px,1px,1px);overflow:hidden;border:0!important;height:1px!important;padding:0!important;position:absolute!important;width:1px!important}
\ No newline at end of file diff --git a/demo/dist/demo.js b/demo/dist/demo.js index c823e18e..07a5e9b8 100644 --- a/demo/dist/demo.js +++ b/demo/dist/demo.js @@ -1 +1,3 @@ -"document"in self&&("classList"in document.createElement("_")?function(){"use strict";var t=document.createElement("_");if(t.classList.add("c1","c2"),!t.classList.contains("c2")){var e=function(t){var e=DOMTokenList.prototype[t];DOMTokenList.prototype[t]=function(t){var i,o=arguments.length;for(i=0;i<o;i++)t=arguments[i],e.call(this,t)}};e("add"),e("remove")}if(t.classList.toggle("c3",!1),t.classList.contains("c3")){var i=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(t,e){return 1 in arguments&&!this.contains(t)==!e?e:i.call(this,t)}}t=null}():function(t){"use strict";if("Element"in t){var e=t.Element.prototype,i=Object,o=String.prototype.trim||function(){return this.replace(/^\s+|\s+$/g,"")},s=Array.prototype.indexOf||function(t){for(var e=0,i=this.length;e<i;e++)if(e in this&&this[e]===t)return e;return-1},n=function(t,e){this.name=t,this.code=DOMException[t],this.message=e},r=function(t,e){if(""===e)throw new n("SYNTAX_ERR","An invalid or illegal string was specified");if(/\s/.test(e))throw new n("INVALID_CHARACTER_ERR","String contains an invalid character");return s.call(t,e)},a=function(t){for(var e=o.call(t.getAttribute("class")||""),i=e?e.split(/\s+/):[],s=0,n=i.length;s<n;s++)this.push(i[s]);this._updateClassName=function(){t.setAttribute("class",this.toString())}},c=a.prototype=[],l=function(){return new a(this)};if(n.prototype=Error.prototype,c.item=function(t){return this[t]||null},c.contains=function(t){return t+="",-1!==r(this,t)},c.add=function(){var t,e=arguments,i=0,o=e.length,s=!1;do{t=e[i]+"",-1===r(this,t)&&(this.push(t),s=!0)}while(++i<o);s&&this._updateClassName()},c.remove=function(){var t,e,i=arguments,o=0,s=i.length,n=!1;do{for(t=i[o]+"",e=r(this,t);-1!==e;)this.splice(e,1),n=!0,e=r(this,t)}while(++o<s);n&&this._updateClassName()},c.toggle=function(t,e){t+="";var i=this.contains(t),o=i?!0!==e&&"remove":!1!==e&&"add";return o&&this[o](t),!0===e||!1===e?e:!i},c.toString=function(){return this.join(" ")},i.defineProperty){var u={get:l,enumerable:!0,configurable:!0};try{i.defineProperty(e,"classList",u)}catch(t){-2146823252===t.number&&(u.enumerable=!1,i.defineProperty(e,"classList",u))}}else i.prototype.__defineGetter__&&e.__defineGetter__("classList",l)}}(self)),function(){function t(t,e,i){if(t)if(t.classList)t.classList[i?"add":"remove"](e);else{var o=(" "+t.className+" ").replace(/\s+/g," ").replace(" "+e+" ","");t.className=o+(i?" "+e:"")}}function e(e,i){if(e in n&&(i||e!==r)&&(r.length||e!==n.video)){switch(e){case n.video:o.source({type:"video",title:"View From A Blue Moon",sources:[{src:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4",type:"video/mp4"},{src:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.webm",type:"video/webm"}],poster:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg",tracks:[{kind:"captions",label:"English",srclang:"en",src:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt",default:!0}]});break;case n.audio:o.source({type:"audio",title:"Kishi Bashi – “It All Began With A Burst”",sources:[{src:"https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3",type:"audio/mp3"},{src:"https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg",type:"audio/ogg"}]});break;case n.youtube:o.source({type:"video",title:"View From A Blue Moon",sources:[{src:"bTqVqk7FSmY",type:"youtube"}]});break;case n.vimeo:o.source({type:"video",title:"View From A Blue Moon",sources:[{src:"147865858",type:"vimeo"}]})}r=e;for(var a=s.length-1;a>=0;a--)t(s[a].parentElement,"active",!1);t(document.querySelector('[data-source="'+e+'"]').parentElement,"active",!0)}}var i=plyr.setup({debug:!0,title:"Video demo",iconUrl:"../dist/plyr.svg",tooltips:{controls:!0},captions:{defaultActive:!0}});plyr.loadSprite("dist/demo.svg");for(var o=i[0],s=document.querySelectorAll("[data-source]"),n={video:"video",audio:"audio",youtube:"youtube",vimeo:"vimeo"},r=window.location.hash.replace("#",""),a=window.history&&window.history.pushState,c=s.length-1;c>=0;c--)s[c].addEventListener("click",function(){var t=this.getAttribute("data-source");e(t),a&&history.pushState({type:t},"","#"+t)});if(window.addEventListener("popstate",function(t){t.state&&"type"in t.state&&e(t.state.type)}),a){var l=!r.length;l&&(r=n.video),r in n&&history.replaceState({type:r},"",l?"":"#"+r),r!==n.video&&e(r,!0)}}(),document.domain.indexOf("plyr.io")>-1&&(!function(t,e,i,o,s,n,r){t.GoogleAnalyticsObject=s,t.ga=t.ga||function(){(t.ga.q=t.ga.q||[]).push(arguments)},t.ga.l=1*new Date,n=e.createElement(i),r=e.getElementsByTagName(i)[0],n.async=1,n.src="//www.google-analytics.com/analytics.js",r.parentNode.insertBefore(n,r)}(window,document,"script",0,"ga"),ga("create","UA-40881672-11","auto"),ga("send","pageview"));
\ No newline at end of file +document.addEventListener("DOMContentLoaded",function(){function e(e,t,o){e&&e.classList[o?"add":"remove"](t)}function t(t,o){if(t in a&&(o||t!==n)&&(n.length||t!==a.video)){switch(t){case a.video:i.source={type:"video",title:"View From A Blue Moon",sources:[{src:"media/View_From_A_Blue_Moon_Trailer-HD.mp4",type:"video/mp4"}],poster:"media/View_From_A_Blue_Moon_Trailer-HD.jpg",tracks:[{kind:"captions",label:"English",srclang:"en",src:"media/View_From_A_Blue_Moon_Trailer-HD.en.vtt",default:!0},{kind:"captions",label:"French",srclang:"fr",src:"media/View_From_A_Blue_Moon_Trailer-HD.fr.vtt"}]};break;case a.audio:i.source={type:"audio",title:"Kishi Bashi – “It All Began With A Burst”",sources:[{src:"https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3",type:"audio/mp3"},{src:"https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg",type:"audio/ogg"}]};break;case a.youtube:i.source={type:"video",title:"View From A Blue Moon",sources:[{src:"https://youtube.com/watch?v=bTqVqk7FSmY",provider:"youtube"}]};break;case a.vimeo:i.source={type:"video",sources:[{src:"https://vimeo.com/76979871",provider:"vimeo"}]}}n=t,Array.from(r).forEach(function(t){return e(t.parentElement,"active",!1)}),e(document.querySelector('[data-source="'+t+'"]'),"active",!0),Array.from(document.querySelectorAll(".plyr__cite")).forEach(function(e){e.setAttribute("hidden","")}),document.querySelector(".plyr__cite--"+t).removeAttribute("hidden")}}window.shr&&window.shr.setup({count:{classname:"button__count"}});var o="tab-focus";document.addEventListener("focusout",function(e){e.target.classList.remove(o)}),document.addEventListener("keydown",function(e){9===e.keyCode&&window.setTimeout(function(){document.activeElement.classList.add(o)},0)});var i=new window.Plyr("#player",{debug:!0,title:"View From A Blue Moon",iconUrl:"../dist/plyr.svg",keyboard:{global:!0},tooltips:{controls:!0},captions:{active:!0},controls:["play-large","play","progress","current-time","mute","volume","captions","settings","fullscreen","pip","airplay"],keys:{google:"AIzaSyDrNwtN3nLH_8rjCmu5Wq3ZCm4MNAVdc0c"}});window.player=i;var r=document.querySelectorAll("[data-source]"),a={video:"video",audio:"audio",youtube:"youtube",vimeo:"vimeo"},n=window.location.hash.replace("#",""),s=window.history&&window.history.pushState;if(Array.from(r).forEach(function(e){e.addEventListener("click",function(){var o=e.getAttribute("data-source");t(o),s&&window.history.pushState({type:o},"","#"+o)})}),window.addEventListener("popstate",function(e){e.state&&"type"in e.state&&t(e.state.type)}),s){var c=!n.length;c&&(n=a.video),n in a&&window.history.replaceState({type:n},"",c?"":"#"+n),n!==a.video&&t(n,!0)}}),"plyr.io"===window.location.host&&(!function(e,t,o,i,r,a,n){e.GoogleAnalyticsObject="ga",e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,a=t.createElement("script"),n=t.getElementsByTagName("script")[0],a.async=1,a.src="//www.google-analytics.com/analytics.js",n.parentNode.insertBefore(a,n)}(window,document),window.ga("create","UA-40881672-11","auto"),window.ga("send","pageview")); + +//# sourceMappingURL=demo.js.map diff --git a/demo/dist/demo.js.map b/demo/dist/demo.js.map new file mode 100644 index 00000000..0826b4cf --- /dev/null +++ b/demo/dist/demo.js.map @@ -0,0 +1 @@ +{"version":3,"file":"demo.js","sources":["demo/src/js/demo.js"],"sourcesContent":["// ==========================================================================\n// Plyr.io demo\n// This code is purely for the https://plyr.io website\n// Please see readme.md in the root or github.com/sampotts/plyr\n// ==========================================================================\n\ndocument.addEventListener('DOMContentLoaded', () => {\n if (window.shr) {\n window.shr.setup({\n count: {\n classname: 'button__count',\n },\n });\n }\n\n // Setup tab focus\n const tabClassName = 'tab-focus';\n\n // Remove class on blur\n document.addEventListener('focusout', event => {\n event.target.classList.remove(tabClassName);\n });\n\n // Add classname to tabbed elements\n document.addEventListener('keydown', event => {\n if (event.keyCode !== 9) {\n return;\n }\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n window.setTimeout(() => {\n document.activeElement.classList.add(tabClassName);\n }, 0);\n });\n\n // Setup the player\n const player = new window.Plyr('#player', {\n debug: true,\n title: 'View From A Blue Moon',\n iconUrl: '../dist/plyr.svg',\n keyboard: {\n global: true,\n },\n tooltips: {\n controls: true,\n },\n captions: {\n active: true,\n },\n controls: [\n 'play-large',\n 'play',\n 'progress',\n 'current-time',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'fullscreen',\n 'pip',\n 'airplay',\n ],\n keys: {\n google: 'AIzaSyDrNwtN3nLH_8rjCmu5Wq3ZCm4MNAVdc0c',\n },\n });\n\n // Expose for testing\n window.player = player;\n\n // Setup type toggle\n const buttons = document.querySelectorAll('[data-source]');\n const types = {\n video: 'video',\n audio: 'audio',\n youtube: 'youtube',\n vimeo: 'vimeo',\n };\n let currentType = window.location.hash.replace('#', '');\n const historySupport = window.history && window.history.pushState;\n\n // Toggle class on an element\n function toggleClass(element, className, state) {\n if (element) {\n element.classList[state ? 'add' : 'remove'](className);\n }\n }\n\n // Set a new source\n function newSource(type, init) {\n // Bail if new type isn't known, it's the current type, or current type is empty (video is default) and new type is video\n if (!(type in types) || (!init && type === currentType) || (!currentType.length && type === types.video)) {\n return;\n }\n\n switch (type) {\n case types.video:\n player.source = {\n type: 'video',\n title: 'View From A Blue Moon',\n sources: [{\n src: 'media/View_From_A_Blue_Moon_Trailer-HD.mp4',\n type: 'video/mp4',\n }],\n poster: 'media/View_From_A_Blue_Moon_Trailer-HD.jpg',\n tracks: [\n {\n kind: 'captions',\n label: 'English',\n srclang: 'en',\n src: 'media/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n default: true,\n },\n {\n kind: 'captions',\n label: 'French',\n srclang: 'fr',\n src: 'media/View_From_A_Blue_Moon_Trailer-HD.fr.vtt',\n },\n ],\n };\n\n break;\n\n case types.audio:\n player.source = {\n type: 'audio',\n title: 'Kishi Bashi – “It All Began With A Burst”',\n sources: [\n {\n src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3',\n type: 'audio/mp3',\n },\n {\n src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg',\n type: 'audio/ogg',\n },\n ],\n };\n\n break;\n\n case types.youtube:\n player.source = {\n type: 'video',\n title: 'View From A Blue Moon',\n sources: [{\n src: 'https://youtube.com/watch?v=bTqVqk7FSmY',\n provider: 'youtube',\n }],\n };\n\n break;\n\n case types.vimeo:\n player.source = {\n type: 'video',\n sources: [{\n src: 'https://vimeo.com/76979871',\n provider: 'vimeo',\n }],\n };\n\n break;\n\n default:\n break;\n }\n\n // Set the current type for next time\n currentType = type;\n\n // Remove active classes\n Array.from(buttons).forEach(button => toggleClass(button.parentElement, 'active', false));\n\n // Set active on parent\n toggleClass(document.querySelector(`[data-source=\"${type}\"]`), 'active', true);\n\n // Show cite\n Array.from(document.querySelectorAll('.plyr__cite')).forEach(cite => {\n cite.setAttribute('hidden', '');\n });\n document.querySelector(`.plyr__cite--${type}`).removeAttribute('hidden');\n }\n\n // Bind to each button\n Array.from(buttons).forEach(button => {\n button.addEventListener('click', () => {\n const type = button.getAttribute('data-source');\n\n newSource(type);\n\n if (historySupport) {\n window.history.pushState({ type }, '', `#${type}`);\n }\n });\n });\n\n // List for backwards/forwards\n window.addEventListener('popstate', event => {\n if (event.state && 'type' in event.state) {\n newSource(event.state.type);\n }\n });\n\n // On load\n if (historySupport) {\n const video = !currentType.length;\n\n // If there's no current type set, assume video\n if (video) {\n currentType = types.video;\n }\n\n // Replace current history state\n if (currentType in types) {\n window.history.replaceState(\n {\n type: currentType,\n },\n '',\n video ? '' : `#${currentType}`\n );\n }\n\n // If it's not video, load the source\n if (currentType !== types.video) {\n newSource(currentType, true);\n }\n }\n});\n\n// Google analytics\n// For demo site (https://plyr.io) only\n/* eslint-disable */\nif (window.location.host === 'plyr.io') {\n (function(i, s, o, g, r, a, m) {\n i.GoogleAnalyticsObject = r;\n i[r] =\n i[r] ||\n function() {\n (i[r].q = i[r].q || []).push(arguments);\n };\n i[r].l = 1 * new Date();\n a = s.createElement(o);\n m = s.getElementsByTagName(o)[0];\n a.async = 1;\n a.src = g;\n m.parentNode.insertBefore(a, m);\n })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');\n window.ga('create', 'UA-40881672-11', 'auto');\n window.ga('send', 'pageview');\n}\n/* eslint-enable */\n"],"names":["document","addEventListener","toggleClass","element","className","state","classList","newSource","type","init","types","currentType","length","video","source","audio","youtube","vimeo","from","buttons","forEach","button","parentElement","querySelector","querySelectorAll","setAttribute","removeAttribute","window","shr","setup","tabClassName","target","remove","event","keyCode","setTimeout","activeElement","add","player","Plyr","location","hash","replace","historySupport","history","pushState","getAttribute","replaceState","host","i","s","o","g","r","a","m","GoogleAnalyticsObject","q","push","arguments","l","Date","createElement","getElementsByTagName","async","src","parentNode","insertBefore","ga"],"mappings":"AAMAA,SAASC,iBAAiB,mBAAoB,oBA6EjCC,EAAYC,EAASC,EAAWC,GACjCF,KACQG,UAAUD,EAAQ,MAAQ,UAAUD,YAK3CG,EAAUC,EAAMC,MAEfD,KAAQE,IAAYD,GAAQD,IAASG,KAAkBA,EAAYC,QAAUJ,IAASE,EAAMG,eAI1FL,QACCE,EAAMG,QACAC,aACG,cACC,sCAEE,kDACC,qBAEF,2DAGM,iBACC,kBACE,SACJ,yDACI,SAGH,iBACC,iBACE,SACJ,8DAOhBJ,EAAMK,QACAD,aACG,cACC,4EAGM,mFACC,kBAGD,mFACC,0BAOjBJ,EAAMM,UACAF,aACG,cACC,sCAEE,mDACK,wBAMjBJ,EAAMO,QACAH,aACG,sBAEG,sCACK,aAWZN,QAGRU,KAAKC,GAASC,QAAQ,mBAAUlB,EAAYmB,EAAOC,cAAe,UAAU,OAGtEtB,SAASuB,+BAA+Bf,QAAW,UAAU,SAGnEU,KAAKlB,SAASwB,iBAAiB,gBAAgBJ,QAAQ,cACpDK,aAAa,SAAU,eAEvBF,8BAA8Bf,GAAQkB,gBAAgB,WAhL/DC,OAAOC,YACAA,IAAIC,wBAEQ,uBAMjBC,EAAe,qBAGZ7B,iBAAiB,WAAY,cAC5B8B,OAAOzB,UAAU0B,OAAOF,cAIzB7B,iBAAiB,UAAW,YACX,IAAlBgC,EAAMC,gBAMHC,WAAW,oBACLC,cAAc9B,UAAU+B,IAAIP,IACtC,SAIDQ,EAAS,IAAIX,OAAOY,KAAK,kBACpB,QACA,gCACE,qCAEG,uBAGE,qBAGF,aAGR,aACA,OACA,WACA,eACA,OACA,SACA,WACA,WACA,aACA,MACA,wBAGQ,oDAKTD,OAASA,MAGVnB,EAAUnB,SAASwB,iBAAiB,iBACpCd,SACK,cACA,gBACE,gBACF,SAEPC,EAAcgB,OAAOa,SAASC,KAAKC,QAAQ,IAAK,IAC9CC,EAAiBhB,OAAOiB,SAAWjB,OAAOiB,QAAQC,mBA2GlD3B,KAAKC,GAASC,QAAQ,cACjBnB,iBAAiB,QAAS,eACvBO,EAAOa,EAAOyB,aAAa,iBAEvBtC,GAENmC,UACOC,QAAQC,WAAYrC,QAAQ,OAAQA,cAMhDP,iBAAiB,WAAY,YAC5BgC,EAAM5B,OAAS,SAAU4B,EAAM5B,SACrB4B,EAAM5B,MAAMG,QAK1BmC,EAAgB,KACV9B,GAASF,EAAYC,OAGvBC,MACcH,EAAMG,OAIpBF,KAAeD,UACRkC,QAAQG,mBAEDpC,GAEV,GACAE,EAAQ,OAASF,GAKrBA,IAAgBD,EAAMG,SACZF,GAAa,MAQN,YAAzBgB,OAAOa,SAASQ,iBACNC,EAAGC,EAAGC,EAAGC,EAAGC,EAAGC,EAAGC,KACtBC,sBAYoE,OAXtE,GACIP,EAAA,IACA,YACKA,EAAA,GAAKQ,EAAIR,EAAA,GAAKQ,OAASC,KAAKC,cAErC,GAAKC,EAAI,EAAI,IAAIC,OACbX,EAAEY,cAKW,YAJbZ,EAAEa,qBAIW,UAJa,KAC5BC,MAAQ,IACRC,IAEyB,4CADzBC,WAAWC,aAAab,EAAGC,IAC9B5B,OAAQ3B,iBACJoE,GAAG,SAAU,iBAAkB,eAC/BA,GAAG,OAAQ"}
\ No newline at end of file diff --git a/demo/dist/demo.svg b/demo/dist/demo.svg deleted file mode 100644 index 6f09b44b..00000000 --- a/demo/dist/demo.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg"><symbol id="icon-github" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M8 .2c-4.4 0-8 3.6-8 8 0 3.5 2.3 6.5 5.5 7.6.4.1.5-.2.5-.4V14c-2.2.5-2.7-1-2.7-1-.4-.9-.9-1.2-.9-1.2-.7-.5.1-.5.1-.5.8.1 1.2.8 1.2.8.7 1.3 1.9.9 2.3.7.1-.5.3-.9.5-1.1-1.8-.2-3.6-.9-3.6-4 0-.9.3-1.6.8-2.1-.1-.2-.4-1 .1-2.1 0 0 .7-.2 2.2.8.6-.2 1.3-.3 2-.3s1.4.1 2 .3c1.5-1 2.2-.8 2.2-.8.4 1.1.2 1.9.1 2.1.5.6.8 1.3.8 2.1 0 3.1-1.9 3.7-3.7 3.9.3.4.6.9.6 1.6v2.2c0 .2.1.5.6.4 3.2-1.1 5.5-4.1 5.5-7.6-.1-4.4-3.7-8-8.1-8z"/></symbol><symbol id="icon-twitter" viewBox="0 0 16 16"><title>Twitter</title><path d="M16 3c-.6.3-1.2.4-1.9.5.7-.4 1.2-1 1.4-1.8-.6.4-1.3.6-2.1.8-.6-.6-1.5-1-2.4-1-1.7 0-3.2 1.5-3.2 3.3 0 .3 0 .5.1.7-2.7-.1-5.2-1.4-6.8-3.4-.3.5-.4 1-.4 1.7 0 1.1.6 2.1 1.5 2.7-.5 0-1-.2-1.5-.4C.7 7.7 1.8 9 3.3 9.3c-.3.1-.6.1-.9.1-.2 0-.4 0-.6-.1.4 1.3 1.6 2.3 3.1 2.3-1.1.9-2.5 1.4-4.1 1.4H0c1.5.9 3.2 1.5 5 1.5 6 0 9.3-5 9.3-9.3v-.4C15 4.3 15.6 3.7 16 3z"/></symbol><symbol id="icon-vimeo" viewBox="0 0 16 16"><path d="M16 4.3c-.1 1.6-1.2 3.7-3.3 6.4-2.2 2.8-4 4.2-5.5 4.2-.9 0-1.7-.9-2.4-2.6C4 9.9 3.4 5 2 5c-.1 0-.5.3-1.2.8l-.8-1c.8-.7 3.5-3.4 4.7-3.5 1.2-.1 2 .7 2.3 2.5.3 2 .8 6.1 1.8 6.1.9 0 2.5-3.4 2.6-4 .1-.9-.3-1.9-2.3-1.1.8-2.6 2.3-3.8 4.5-3.8 1.7.1 2.5 1.2 2.4 3.3z"/></symbol><symbol id="icon-youtube" viewBox="0 0 16 16"><path d="M15.8 4.8c-.2-1.3-.8-2.2-2.2-2.4C11.4 2 8 2 8 2s-3.4 0-5.6.4C1 2.6.3 3.5.2 4.8 0 6.1 0 8 0 8s0 1.9.2 3.2c.2 1.3.8 2.2 2.2 2.4C4.6 14 8 14 8 14s3.4 0 5.6-.4c1.4-.3 2-1.1 2.2-2.4C16 9.9 16 8 16 8s0-1.9-.2-3.2zM6 11V5l5 3-5 3z"/></symbol></svg>
\ No newline at end of file diff --git a/demo/error.html b/demo/error.html index 6dc22cb1..915aa4b5 100644 --- a/demo/error.html +++ b/demo/error.html @@ -7,18 +7,18 @@ <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Docs styles --> - <link rel="stylesheet" href="dist/demo.css"> + <link rel="stylesheet" href="dist/error.css"> <!-- Preload --> - <link rel="preload" as="font" crossorigin type="font/woff2" href="https://cdn.plyr.io/static/fonts/avenir-medium.woff2"> - <link rel="preload" as="font" crossorigin type="font/woff2" href="https://cdn.plyr.io/static/fonts/avenir-bold.woff2"> + <link rel="preload" as="font" crossorigin type="font/woff2" href="https://cdn.plyr.io/static/fonts/gordita-medium.woff2"> + <link rel="preload" as="font" crossorigin type="font/woff2" href="https://cdn.plyr.io/static/fonts/gordita-bold.woff2"> </head> <body> <main> <h1>Doh.</h1> <p>Looks like something went wrong.</p> - <a href="http://plyr.io" class="btn btn--primary">Back to plyr.io</a> + <a href="javascript:history.back()" class="button">Go back</a> </main> </body> diff --git a/demo/index.html b/demo/index.html index b6941537..47714de0 100644 --- a/demo/index.html +++ b/demo/index.html @@ -3,101 +3,181 @@ <head> <meta charset="utf-8" /> - <title>Plyr - A simple HTML5 media player</title> - <meta name="description" content="A simple HTML5 media player with custom controls and WebVTT captions."> + <title>Plyr - A simple, customizable HTML5 Video, Audio, YouTube and Vimeo player</title> + <meta name="description" property="og:description" content="A simple HTML5 media player with custom controls and WebVTT captions."> <meta name="author" content="Sam Potts"> <meta name="viewport" content="width=device-width, initial-scale=1"> - <!-- Styles --> - <link rel="stylesheet" href="../dist/plyr.css"> + <!-- Icons --> + <link rel="icon" href="https://cdn.plyr.io/static/icons/favicon.ico"> + <link rel="icon" type="image/png" href="https://cdn.plyr.io/static/icons/32x32.png" sizes="32x32"> + <link rel="icon" type="image/png" href="https://cdn.plyr.io/static/icons/16x16.png" sizes="16x16"> + <link rel="apple-touch-icon" sizes="180x180" href="https://cdn.plyr.io/static/icons/180x180.png"> + + <!-- Opengraph --> + <meta property="og:title" content="Plyr - A simple, customizable HTML5 Video, Audio, YouTube and Vimeo player"> + <meta property="og:site_name" content="Plyr"> + <meta property="og:url" content="https://plyr.io"> + <meta property="og:image" content="https://cdn.plyr.io/static/icons/1200x630.png"> + + <!-- Twitter --> + <meta name="twitter:card" content="summary"> + <meta name="twitter:site" content="@sam_potts"> + <meta name="twitter:creator" content="@sam_potts"> + <meta name="twitter:card" content="summary_large_image"> <!-- Docs styles --> <link rel="stylesheet" href="dist/demo.css"> <!-- Preload --> - <link rel="preload" as="font" crossorigin type="font/woff2" href="https://cdn.plyr.io/static/fonts/avenir-medium.woff2"> - <link rel="preload" as="font" crossorigin type="font/woff2" href="https://cdn.plyr.io/static/fonts/avenir-bold.woff2"> + <link rel="preload" as="font" crossorigin type="font/woff2" href="https://cdn.plyr.io/static/fonts/gordita-medium.woff2"> + <link rel="preload" as="font" crossorigin type="font/woff2" href="https://cdn.plyr.io/static/fonts/gordita-bold.woff2"> </head> <body> - <header> - <h1>Plyr</h1> - <p>A simple, accessible HTML5 media player by <a href="https://twitter.com/sam_potts" target="_blank">@sam_potts</a></p> - <nav> - <ul> - <li> - <a href="https://github.com/sampotts/plyr" target="_blank" class="btn btn--large btn--primary" data-shr-network="github"> - <svg class="icon"> - <use xlink:href="#icon-github" /> - </svg>Download on GitHub - </a> - </li> - <li> - <a href="https://twitter.com/intent/tweet?text=A+simple+HTML5+media+player+with+custom+controls+and+WebVTT+captions.&url=http%3A%2F%2Fplyr.io&via=Sam_Potts" - target="_blank" class="btn btn--large btn--twitter" data-shr-network="twitter"> - <svg class="icon"> - <use xlink:href="#icon-twitter" /> - </svg>Tweet + <div class="grid"> + <header> + <h1>Plyr</h1> + <p>A simple, accessible and customisable media player for + <button type="button" class="faux-link" data-source="video"> + <svg class="icon"> + <title>HTML5</title> + <path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path> + </svg>Video</button>, + <button type="button" class="faux-link" data-source="audio"> + <svg class="icon"> + <title>HTML5</title> + <path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path> + </svg>Audio</button>, + <button type="button" class="faux-link" data-source="youtube"> + <svg class="icon" role="presentation"> + <title>YouTube</title> + <path d="M15.8,4.8c-0.2-1.3-0.8-2.2-2.2-2.4C11.4,2,8,2,8,2S4.6,2,2.4,2.4C1,2.6,0.3,3.5,0.2,4.8C0,6.1,0,8,0,8 + s0,1.9,0.2,3.2c0.2,1.3,0.8,2.2,2.2,2.4C4.6,14,8,14,8,14s3.4,0,5.6-0.4c1.4-0.3,2-1.1,2.2-2.4C16,9.9,16,8,16,8S16,6.1,15.8,4.8z + M6,11V5l5,3L6,11z"></path> + </svg>YouTube</button> and + <button type="button" class="faux-link" data-source="vimeo"> + <svg class="icon" role="presentation"> + <title>Vimeo</title> + <path d="M16,4.3c-0.1,1.6-1.2,3.7-3.3,6.4c-2.2,2.8-4,4.2-5.5,4.2c-0.9,0-1.7-0.9-2.4-2.6C4,9.9,3.4,5,2,5 + C1.9,5,1.5,5.3,0.8,5.8L0,4.8c0.8-0.7,3.5-3.4,4.7-3.5C5.9,1.2,6.7,2,7,3.8c0.3,2,0.8,6.1,1.8,6.1c0.9,0,2.5-3.4,2.6-4 + c0.1-0.9-0.3-1.9-2.3-1.1c0.8-2.6,2.3-3.8,4.5-3.8C15.3,1.1,16.1,2.2,16,4.3z"></path> + </svg>Vimeo</button> + </p> + + <!--<p>Monetization options provided by + <a href="https://vi.ai" target="_blank">vi.ai</a> + </p>--> + + <div class="call-to-action"> + <span class="button--with-count"> + <a href="https://github.com/sampotts/plyr" target="_blank" class="button" data-shr-network="github"> + <svg class="icon" role="presentation"> + <title>GitHub</title> + <path d="M8,0.2c-4.4,0-8,3.6-8,8c0,3.5,2.3,6.5,5.5,7.6 + C5.9,15.9,6,15.6,6,15.4c0-0.2,0-0.7,0-1.4C3.8,14.5,3.3,13,3.3,13c-0.4-0.9-0.9-1.2-0.9-1.2c-0.7-0.5,0.1-0.5,0.1-0.5 + c0.8,0.1,1.2,0.8,1.2,0.8C4.4,13.4,5.6,13,6,12.8c0.1-0.5,0.3-0.9,0.5-1.1c-1.8-0.2-3.6-0.9-3.6-4c0-0.9,0.3-1.6,0.8-2.1 + c-0.1-0.2-0.4-1,0.1-2.1c0,0,0.7-0.2,2.2,0.8c0.6-0.2,1.3-0.3,2-0.3c0.7,0,1.4,0.1,2,0.3c1.5-1,2.2-0.8,2.2-0.8 + c0.4,1.1,0.2,1.9,0.1,2.1c0.5,0.6,0.8,1.3,0.8,2.1c0,3.1-1.9,3.7-3.7,3.9C9.7,12,10,12.5,10,13.2c0,1.1,0,1.9,0,2.2 + c0,0.2,0.1,0.5,0.6,0.4c3.2-1.1,5.5-4.1,5.5-7.6C16,3.8,12.4,0.2,8,0.2z"></path> + </svg> + Download on GitHub </a> - </li> - </ul> - </nav> - </header> + </span> + </div> + </header> - <main role="main" id="main"> - <nav class="btn__bar"> - <ul> - <li class="active"> - <button type="button" class="btn" data-source="video">Video</button> - </li> - <li> - <button type="button" class="btn" data-source="audio">Audio</button> - </li> - <li> - <button type="button" class="btn btn--youtube" data-source="youtube"><svg class="icon"><use xlink:href="#icon-youtube"/></svg>YouTube</button> - </li> - <li> - <button type="button" class="btn btn--vimeo" data-source="vimeo"><svg class="icon"><use xlink:href="#icon-vimeo"/></svg>Vimeo</button> - </li> - </ul> - </nav> - <section> - <video poster="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg?v1" controls crossorigin> + <main> + <video controls crossorigin playsinline poster="media/View_From_A_Blue_Moon_Trailer-HD.jpg" id="player"> <!-- Video files --> - <source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4" type="video/mp4"> - <source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.webm" type="video/webm"> + <source src="media/View_From_A_Blue_Moon_Trailer-HD.mp4" type="video/mp4"> + <!--<source src="media/View_From_A_Blue_Moon_Trailer-UHD.mp4" type="video/mp4">--> <!-- Text track file --> - <track kind="captions" label="English" srclang="en" src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt" - default> + <track kind="captions" label="English" srclang="en" src="media/View_From_A_Blue_Moon_Trailer-HD.en.vtt" default> + <track kind="captions" label="Français" srclang="fr" src="media/View_From_A_Blue_Moon_Trailer-HD.fr.vtt"> <!-- Fallback for browsers that don't support the <video> element --> - <a href="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4" download>Download</a> + <a href="media/View_From_A_Blue_Moon_Trailer-HD.mp4" download>Download</a> </video> <ul> - <li class="plyr__cite plyr__cite--video"><small><a href="http://viewfromabluemoon.com/" target="_blank">View From A Blue Moon</a> © Brainfarm</small></li> - <li class="plyr__cite plyr__cite--audio"><small><a href="http://www.kishibashi.com/" target="_blank">Kishi Bashi – “It All Began With A Burst”</a> © Kishi Bashi</small></li> - <li class="plyr__cite plyr__cite--youtube"><small><a href="https://www.youtube.com/watch?v=bTqVqk7FSmY" target="_blank">View From A Blue Moon</a> on <span class="color--youtube"><svg class="icon"><use xlink:href="#icon-youtube"/></svg>YouTube</span></small></li> - <li class="plyr__cite plyr__cite--vimeo"><small><a href="https://vimeo.com/ondemand/viewfromabluemoon4k" target="_blank">View From A Blue Moon</a> on <span class="color--vimeo"><svg class="icon"><use xlink:href="#icon-vimeo"/></svg>Vimeo</span></small></li> + <li class="plyr__cite plyr__cite--video" hidden> + <small> + <svg class="icon"> + <title>HTML5</title> + <path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path> + </svg> + <a href="http://viewfromabluemoon.com/" target="_blank">View From A Blue Moon</a> © Brainfarm + </small> + </li> + <li class="plyr__cite plyr__cite--audio" hidden> + <small> + <svg class="icon" title="HTML5"> + <title>HTML5</title> + <path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path> + </svg> + <a href="http://www.kishibashi.com/" target="_blank">Kishi Bashi – “It All Began With A Burst”</a> © Kishi Bashi + </small> + </li> + <li class="plyr__cite plyr__cite--youtube" hidden> + <small> + <a href="https://www.youtube.com/watch?v=bTqVqk7FSmY" target="_blank">View From A Blue Moon</a> on + <span class="color--youtube"> + <svg class="icon" role="presentation"> + <title>YouTube</title> + <path d="M15.8,4.8c-0.2-1.3-0.8-2.2-2.2-2.4C11.4,2,8,2,8,2S4.6,2,2.4,2.4C1,2.6,0.3,3.5,0.2,4.8C0,6.1,0,8,0,8 + s0,1.9,0.2,3.2c0.2,1.3,0.8,2.2,2.2,2.4C4.6,14,8,14,8,14s3.4,0,5.6-0.4c1.4-0.3,2-1.1,2.2-2.4C16,9.9,16,8,16,8S16,6.1,15.8,4.8z + M6,11V5l5,3L6,11z"></path> + </svg>YouTube + </span> + </small> + </li> + <li class="plyr__cite plyr__cite--vimeo" hidden> + <small> + <a href="https://vimeo.com/ondemand/viewfromabluemoon4k" target="_blank">View From A Blue Moon</a> on + <span class="color--vimeo"> + <svg class="icon" role="presentation"> + <title>Vimeo</title> + <path d="M16,4.3c-0.1,1.6-1.2,3.7-3.3,6.4c-2.2,2.8-4,4.2-5.5,4.2c-0.9,0-1.7-0.9-2.4-2.6C4,9.9,3.4,5,2,5 + C1.9,5,1.5,5.3,0.8,5.8L0,4.8c0.8-0.7,3.5-3.4,4.7-3.5C5.9,1.2,6.7,2,7,3.8c0.3,2,0.8,6.1,1.8,6.1c0.9,0,2.5-3.4,2.6-4 + c0.1-0.9-0.3-1.9-2.3-1.1c0.8-2.6,2.3-3.8,4.5-3.8C15.3,1.1,16.1,2.2,16,4.3z"></path> + </svg>Vimeo + </span> + </small> + </li> </ul> - </section> - </main> + </main> + </div> + + <aside> + <svg class="icon"> + <title>Twitter</title> + <path d="M16,3c-0.6,0.3-1.2,0.4-1.9,0.5c0.7-0.4,1.2-1,1.4-1.8c-0.6,0.4-1.3,0.6-2.1,0.8c-0.6-0.6-1.5-1-2.4-1 + C9.3,1.5,7.8,3,7.8,4.8c0,0.3,0,0.5,0.1,0.7C5.2,5.4,2.7,4.1,1.1,2.1c-0.3,0.5-0.4,1-0.4,1.7c0,1.1,0.6,2.1,1.5,2.7 + c-0.5,0-1-0.2-1.5-0.4c0,0,0,0,0,0c0,1.6,1.1,2.9,2.6,3.2C3,9.4,2.7,9.4,2.4,9.4c-0.2,0-0.4,0-0.6-0.1c0.4,1.3,1.6,2.3,3.1,2.3 + c-1.1,0.9-2.5,1.4-4.1,1.4c-0.3,0-0.5,0-0.8,0c1.5,0.9,3.2,1.5,5,1.5c6,0,9.3-5,9.3-9.3c0-0.1,0-0.3,0-0.4C15,4.3,15.6,3.7,16,3z"></path> + </svg> + <p>If you think Plyr's good, + <a href="https://twitter.com/intent/tweet?text=A+simple+HTML5+media+player+with+custom+controls+and+WebVTT+captions.&url=http%3A%2F%2Fplyr.io&via=Sam_Potts" + target="_blank" data-shr-network="twitter">tweet it</a> + </p> + </aside> + + <!-- Polyfills --> + <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=es6,Array.prototype.includes,CustomEvent,fetch"></script> <!-- Plyr core script --> <script src="../dist/plyr.js"></script> - <!-- Docs script --> - <script src="dist/demo.js"></script> + <!-- Sharing libary (https://shr.one) --> + <script src="https://cdn.shr.one/1.0.1/shr.js"></script> <!-- Rangetouch to fix <input type="range"> on touch devices (see https://rangetouch.com) --> <script src="https://cdn.rangetouch.com/1.0.1/rangetouch.js" async></script> - <!-- Sharing libary (https://shr.one) --> - <script src="https://cdn.shr.one/1.0.1/shr.js"></script> - <script> - if (window.shr) { window.shr.setup({ count: { classname: 'btn__count' } }); } - </script> + <!-- Docs script --> + <script src="dist/demo.js"></script> </body> </html>
\ No newline at end of file diff --git a/demo/media/View_From_A_Blue_Moon_Trailer-HD.en.vtt b/demo/media/View_From_A_Blue_Moon_Trailer-HD.en.vtt new file mode 100644 index 00000000..5da5f307 --- /dev/null +++ b/demo/media/View_From_A_Blue_Moon_Trailer-HD.en.vtt @@ -0,0 +1,29 @@ +WEBVTT FILE + +1 +00:00:09.500 --> 00:00:12.000 +The ocean floor rises 5 miles to the shores + +2 +00:00:12.001 --> 00:00:16.500 +of what people call, the seven mile miracle + +3 +00:00:25.500 --> 00:00:28.000 +What would it be like to be born on this island? + +4 +00:00:32.500 --> 00:00:34.500 +To grow up on these shores + +5 +00:00:37.500 --> 00:00:40.000 +To witness this water, every day + +6 +00:00:43.500 --> 00:00:46.000 +You're about to meet someone, who did + +7 +00:02:45.500 --> 00:02:49.000 +This is a film about John John Florence
\ No newline at end of file diff --git a/demo/media/View_From_A_Blue_Moon_Trailer-HD.fr.vtt b/demo/media/View_From_A_Blue_Moon_Trailer-HD.fr.vtt new file mode 100644 index 00000000..52e3af7d --- /dev/null +++ b/demo/media/View_From_A_Blue_Moon_Trailer-HD.fr.vtt @@ -0,0 +1,29 @@ +WEBVTT FILE + +1 +00:00:09.500 --> 00:00:12.000 +Le fond de l'océan monte 5 miles des rives + +2 +00:00:12.001 --> 00:00:16.500 +de ce que les gens appellent le miracle de sept mile + +3 +00:00:25.500 --> 00:00:28.000 +Que serait-il d'être né sur cette île? + +4 +00:00:32.500 --> 00:00:34.500 +Pour grandir sur ces rivages + +5 +00:00:37.500 --> 00:00:40.000 +Pour assister à cette eau, tous les jours + +6 +00:00:43.500 --> 00:00:46.000 +Vous êtes sur le point de rencontrer quelqu'un, qui ne + +7 +00:02:45.500 --> 00:02:49.000 +Ceci est un film sur John John Florence
\ No newline at end of file diff --git a/demo/media/View_From_A_Blue_Moon_Trailer-HD.jpg b/demo/media/View_From_A_Blue_Moon_Trailer-HD.jpg Binary files differnew file mode 100644 index 00000000..9e7b883c --- /dev/null +++ b/demo/media/View_From_A_Blue_Moon_Trailer-HD.jpg diff --git a/demo/src/js/demo.js b/demo/src/js/demo.js new file mode 100644 index 00000000..ee52dfd8 --- /dev/null +++ b/demo/src/js/demo.js @@ -0,0 +1,255 @@ +// ========================================================================== +// Plyr.io demo +// This code is purely for the https://plyr.io website +// Please see readme.md in the root or github.com/sampotts/plyr +// ========================================================================== + +document.addEventListener('DOMContentLoaded', () => { + if (window.shr) { + window.shr.setup({ + count: { + classname: 'button__count', + }, + }); + } + + // Setup tab focus + const tabClassName = 'tab-focus'; + + // Remove class on blur + document.addEventListener('focusout', event => { + event.target.classList.remove(tabClassName); + }); + + // Add classname to tabbed elements + document.addEventListener('keydown', event => { + if (event.keyCode !== 9) { + return; + } + + // Delay the adding of classname until the focus has changed + // This event fires before the focusin event + window.setTimeout(() => { + document.activeElement.classList.add(tabClassName); + }, 0); + }); + + // Setup the player + const player = new window.Plyr('#player', { + debug: true, + title: 'View From A Blue Moon', + iconUrl: '../dist/plyr.svg', + keyboard: { + global: true, + }, + tooltips: { + controls: true, + }, + captions: { + active: true, + }, + controls: [ + 'play-large', + 'play', + 'progress', + 'current-time', + 'mute', + 'volume', + 'captions', + 'settings', + 'fullscreen', + 'pip', + 'airplay', + ], + keys: { + google: 'AIzaSyDrNwtN3nLH_8rjCmu5Wq3ZCm4MNAVdc0c', + }, + }); + + // Expose for testing + window.player = player; + + // Setup type toggle + const buttons = document.querySelectorAll('[data-source]'); + const types = { + video: 'video', + audio: 'audio', + youtube: 'youtube', + vimeo: 'vimeo', + }; + let currentType = window.location.hash.replace('#', ''); + const historySupport = window.history && window.history.pushState; + + // Toggle class on an element + function toggleClass(element, className, state) { + if (element) { + element.classList[state ? 'add' : 'remove'](className); + } + } + + // Set a new source + function newSource(type, init) { + // Bail if new type isn't known, it's the current type, or current type is empty (video is default) and new type is video + if (!(type in types) || (!init && type === currentType) || (!currentType.length && type === types.video)) { + return; + } + + switch (type) { + case types.video: + player.source = { + type: 'video', + title: 'View From A Blue Moon', + sources: [{ + src: 'media/View_From_A_Blue_Moon_Trailer-HD.mp4', + type: 'video/mp4', + }], + poster: 'media/View_From_A_Blue_Moon_Trailer-HD.jpg', + tracks: [ + { + kind: 'captions', + label: 'English', + srclang: 'en', + src: 'media/View_From_A_Blue_Moon_Trailer-HD.en.vtt', + default: true, + }, + { + kind: 'captions', + label: 'French', + srclang: 'fr', + src: 'media/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', + }, + ], + }; + + break; + + case types.audio: + player.source = { + type: 'audio', + title: 'Kishi Bashi – “It All Began With A Burst”', + sources: [ + { + src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3', + type: 'audio/mp3', + }, + { + src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg', + type: 'audio/ogg', + }, + ], + }; + + break; + + case types.youtube: + player.source = { + type: 'video', + title: 'View From A Blue Moon', + sources: [{ + src: 'https://youtube.com/watch?v=bTqVqk7FSmY', + provider: 'youtube', + }], + }; + + break; + + case types.vimeo: + player.source = { + type: 'video', + sources: [{ + src: 'https://vimeo.com/76979871', + provider: 'vimeo', + }], + }; + + break; + + default: + break; + } + + // Set the current type for next time + currentType = type; + + // Remove active classes + Array.from(buttons).forEach(button => toggleClass(button.parentElement, 'active', false)); + + // Set active on parent + toggleClass(document.querySelector(`[data-source="${type}"]`), 'active', true); + + // Show cite + Array.from(document.querySelectorAll('.plyr__cite')).forEach(cite => { + cite.setAttribute('hidden', ''); + }); + document.querySelector(`.plyr__cite--${type}`).removeAttribute('hidden'); + } + + // Bind to each button + Array.from(buttons).forEach(button => { + button.addEventListener('click', () => { + const type = button.getAttribute('data-source'); + + newSource(type); + + if (historySupport) { + window.history.pushState({ type }, '', `#${type}`); + } + }); + }); + + // List for backwards/forwards + window.addEventListener('popstate', event => { + if (event.state && 'type' in event.state) { + newSource(event.state.type); + } + }); + + // On load + if (historySupport) { + const video = !currentType.length; + + // If there's no current type set, assume video + if (video) { + currentType = types.video; + } + + // Replace current history state + if (currentType in types) { + window.history.replaceState( + { + type: currentType, + }, + '', + video ? '' : `#${currentType}` + ); + } + + // If it's not video, load the source + if (currentType !== types.video) { + newSource(currentType, true); + } + } +}); + +// Google analytics +// For demo site (https://plyr.io) only +/* eslint-disable */ +if (window.location.host === 'plyr.io') { + (function(i, s, o, g, r, a, m) { + i.GoogleAnalyticsObject = r; + i[r] = + i[r] || + function() { + (i[r].q = i[r].q || []).push(arguments); + }; + i[r].l = 1 * new Date(); + a = s.createElement(o); + m = s.getElementsByTagName(o)[0]; + a.async = 1; + a.src = g; + m.parentNode.insertBefore(a, m); + })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga'); + window.ga('create', 'UA-40881672-11', 'auto'); + window.ga('send', 'pageview'); +} +/* eslint-enable */ diff --git a/demo/src/js/lib/classlist.js b/demo/src/js/lib/classlist.js deleted file mode 100644 index eac1e99e..00000000 --- a/demo/src/js/lib/classlist.js +++ /dev/null @@ -1,237 +0,0 @@ -/* - * classList.js: Cross-browser full element.classList implementation. - * 1.1.20150312 - * - * By Eli Grey, http://eligrey.com - * License: Dedicated to the public domain. - * See https://github.com/eligrey/classList.js/blob/master/LICENSE.md - */ - -/*global self, document, DOMException */ - -/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js */ - -if ("document" in self) { - -// Full polyfill for browsers with no classList support -if (!("classList" in document.createElement("_"))) { - -(function (view) { - -"use strict"; - -if (!('Element' in view)) return; - -var - classListProp = "classList" - , protoProp = "prototype" - , elemCtrProto = view.Element[protoProp] - , objCtr = Object - , strTrim = String[protoProp].trim || function () { - return this.replace(/^\s+|\s+$/g, ""); - } - , arrIndexOf = Array[protoProp].indexOf || function (item) { - var - i = 0 - , len = this.length - ; - for (; i < len; i++) { - if (i in this && this[i] === item) { - return i; - } - } - return -1; - } - // Vendors: please allow content code to instantiate DOMExceptions - , DOMEx = function (type, message) { - this.name = type; - this.code = DOMException[type]; - this.message = message; - } - , checkTokenAndGetIndex = function (classList, token) { - if (token === "") { - throw new DOMEx( - "SYNTAX_ERR" - , "An invalid or illegal string was specified" - ); - } - if (/\s/.test(token)) { - throw new DOMEx( - "INVALID_CHARACTER_ERR" - , "String contains an invalid character" - ); - } - return arrIndexOf.call(classList, token); - } - , ClassList = function (elem) { - var - trimmedClasses = strTrim.call(elem.getAttribute("class") || "") - , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : [] - , i = 0 - , len = classes.length - ; - for (; i < len; i++) { - this.push(classes[i]); - } - this._updateClassName = function () { - elem.setAttribute("class", this.toString()); - }; - } - , classListProto = ClassList[protoProp] = [] - , classListGetter = function () { - return new ClassList(this); - } -; -// Most DOMException implementations don't allow calling DOMException's toString() -// on non-DOMExceptions. Error's toString() is sufficient here. -DOMEx[protoProp] = Error[protoProp]; -classListProto.item = function (i) { - return this[i] || null; -}; -classListProto.contains = function (token) { - token += ""; - return checkTokenAndGetIndex(this, token) !== -1; -}; -classListProto.add = function () { - var - tokens = arguments - , i = 0 - , l = tokens.length - , token - , updated = false - ; - do { - token = tokens[i] + ""; - if (checkTokenAndGetIndex(this, token) === -1) { - this.push(token); - updated = true; - } - } - while (++i < l); - - if (updated) { - this._updateClassName(); - } -}; -classListProto.remove = function () { - var - tokens = arguments - , i = 0 - , l = tokens.length - , token - , updated = false - , index - ; - do { - token = tokens[i] + ""; - index = checkTokenAndGetIndex(this, token); - while (index !== -1) { - this.splice(index, 1); - updated = true; - index = checkTokenAndGetIndex(this, token); - } - } - while (++i < l); - - if (updated) { - this._updateClassName(); - } -}; -classListProto.toggle = function (token, force) { - token += ""; - - var - result = this.contains(token) - , method = result ? - force !== true && "remove" - : - force !== false && "add" - ; - - if (method) { - this[method](token); - } - - if (force === true || force === false) { - return force; - } else { - return !result; - } -}; -classListProto.toString = function () { - return this.join(" "); -}; - -if (objCtr.defineProperty) { - var classListPropDesc = { - get: classListGetter - , enumerable: true - , configurable: true - }; - try { - objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc); - } catch (ex) { // IE 8 doesn't support enumerable:true - if (ex.number === -0x7FF5EC54) { - classListPropDesc.enumerable = false; - objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc); - } - } -} else if (objCtr[protoProp].__defineGetter__) { - elemCtrProto.__defineGetter__(classListProp, classListGetter); -} - -}(self)); - -} else { -// There is full or partial native classList support, so just check if we need -// to normalize the add/remove and toggle APIs. - -(function () { - "use strict"; - - var testElement = document.createElement("_"); - - testElement.classList.add("c1", "c2"); - - // Polyfill for IE 10/11 and Firefox <26, where classList.add and - // classList.remove exist but support only one argument at a time. - if (!testElement.classList.contains("c2")) { - var createMethod = function(method) { - var original = DOMTokenList.prototype[method]; - - DOMTokenList.prototype[method] = function(token) { - var i, len = arguments.length; - - for (i = 0; i < len; i++) { - token = arguments[i]; - original.call(this, token); - } - }; - }; - createMethod('add'); - createMethod('remove'); - } - - testElement.classList.toggle("c3", false); - - // Polyfill for IE 10 and Firefox <24, where classList.toggle does not - // support the second argument. - if (testElement.classList.contains("c3")) { - var _toggle = DOMTokenList.prototype.toggle; - - DOMTokenList.prototype.toggle = function(token, force) { - if (1 in arguments && !this.contains(token) === !force) { - return force; - } else { - return _toggle.call(this, token); - } - }; - - } - - testElement = null; -}()); - -} - -}
\ No newline at end of file diff --git a/demo/src/js/main.js b/demo/src/js/main.js deleted file mode 100644 index 7d732dcd..00000000 --- a/demo/src/js/main.js +++ /dev/null @@ -1,203 +0,0 @@ -// ========================================================================== -// Plyr.io demo -// This code is purely for the plyr.io website -// Please see readme.md in the root or github.com/selz/plyr -// ========================================================================== - -/*global plyr*/ - -// General functions -(function() { - //document.body.addEventListener('ready', function(event) { console.log(event); }); - - // Setup the player - var instances = plyr.setup({ - debug: true, - title: "Video demo", - iconUrl: "../dist/plyr.svg", - tooltips: { - controls: true - }, - captions: { - defaultActive: true - } - }); - plyr.loadSprite("dist/demo.svg"); - - // Plyr returns an array regardless - var player = instances[0]; - - // Setup type toggle - var buttons = document.querySelectorAll("[data-source]"), - types = { - video: "video", - audio: "audio", - youtube: "youtube", - vimeo: "vimeo" - }, - currentType = window.location.hash.replace("#", ""), - historySupport = window.history && window.history.pushState; - - // Bind to each button - for (var i = buttons.length - 1; i >= 0; i--) { - buttons[i].addEventListener("click", function() { - var type = this.getAttribute("data-source"); - - newSource(type); - - if (historySupport) { - history.pushState({ type: type }, "", "#" + type); - } - }); - } - - // List for backwards/forwards - window.addEventListener("popstate", function(event) { - if (event.state && "type" in event.state) { - newSource(event.state.type); - } - }); - - // On load - if (historySupport) { - var video = !currentType.length; - - // If there's no current type set, assume video - if (video) { - currentType = types.video; - } - - // Replace current history state - if (currentType in types) { - history.replaceState({ type: currentType }, "", video ? "" : "#" + currentType); - } - - // If it's not video, load the source - if (currentType !== types.video) { - newSource(currentType, true); - } - } - - // Toggle class on an element - function toggleClass(element, className, state) { - if (element) { - if (element.classList) { - element.classList[state ? "add" : "remove"](className); - } else { - var name = (" " + element.className + " ").replace(/\s+/g, " ").replace(" " + className + " ", ""); - element.className = name + (state ? " " + className : ""); - } - } - } - - // Set a new source - function newSource(type, init) { - // Bail if new type isn't known, it's the current type, or current type is empty (video is default) and new type is video - if (!(type in types) || (!init && type === currentType) || (!currentType.length && type === types.video)) { - return; - } - - switch (type) { - case types.video: - player.source({ - type: "video", - title: "View From A Blue Moon", - sources: [ - { - src: "https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4", - type: "video/mp4" - }, - { - src: "https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.webm", - type: "video/webm" - } - ], - poster: "https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg", - tracks: [ - { - kind: "captions", - label: "English", - srclang: "en", - src: "https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt", - default: true - } - ] - }); - break; - - case types.audio: - player.source({ - type: "audio", - title: "Kishi Bashi – “It All Began With A Burst”", - sources: [ - { - src: "https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3", - type: "audio/mp3" - }, - { - src: "https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg", - type: "audio/ogg" - } - ] - }); - break; - - case types.youtube: - player.source({ - type: "video", - title: "View From A Blue Moon", - sources: [ - { - src: "bTqVqk7FSmY", - type: "youtube" - } - ] - }); - break; - - case types.vimeo: - player.source({ - type: "video", - title: "View From A Blue Moon", - sources: [ - { - src: "147865858", - type: "vimeo" - } - ] - }); - break; - } - - // Set the current type for next time - currentType = type; - - // Remove active classes - for (var x = buttons.length - 1; x >= 0; x--) { - toggleClass(buttons[x].parentElement, "active", false); - } - - // Set active on parent - toggleClass(document.querySelector('[data-source="' + type + '"]').parentElement, "active", true); - } -})(); - -// Google analytics -// For demo site (http://[www.]plyr.io) only -if (document.domain.indexOf("plyr.io") > -1) { - (function(i, s, o, g, r, a, m) { - i.GoogleAnalyticsObject = r; - (i[r] = - i[r] || - function() { - (i[r].q = i[r].q || []).push(arguments); - }), - (i[r].l = 1 * new Date()); - (a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]); - a.async = 1; - a.src = g; - m.parentNode.insertBefore(a, m); - })(window, document, "script", "//www.google-analytics.com/analytics.js", "ga"); - ga("create", "UA-40881672-11", "auto"); - ga("send", "pageview"); -} diff --git a/demo/src/less/components/base.less b/demo/src/less/components/base.less deleted file mode 100644 index 502196cf..00000000 --- a/demo/src/less/components/base.less +++ /dev/null @@ -1,48 +0,0 @@ -// ========================================================================== -// Base layout -// ========================================================================== - -// BORDER-BOX ALL THE THINGS! -// http://paulirish.com/2012/box-sizing-border-box-ftw/ -*, *::after, *::before { - box-sizing: border-box; -} - -// Hidden -[hidden] { - display: none; -} - -// Base -html { - height: 100%; - background: @body-background fixed; -} -body { - margin: 0; - padding: (@padding-base / 2); -} - -// Header -header { - padding: @padding-base; - margin-bottom: @padding-base; - - p { - .font-size(18); - } - @media (min-width: @screen-sm) { - padding-top: (@padding-base * 3); - padding-bottom: (@padding-base * 3); - } -} - -// Sections -section { - max-width: @example-width-video; - margin: 0 auto @padding-base; - - @media (min-width: @screen-sm) { - margin-bottom: (@padding-base * 2); - } -}
\ No newline at end of file diff --git a/demo/src/less/components/buttons.less b/demo/src/less/components/buttons.less deleted file mode 100644 index c99a0836..00000000 --- a/demo/src/less/components/buttons.less +++ /dev/null @@ -1,172 +0,0 @@ -// ========================================================================== -// Buttons -// ========================================================================== - -nav { - ul { - list-style: none; - margin: 0; - padding: 0; - font-size: 0; - } - li { - display: inline-block; - margin-top: (@padding-base / 2); - .font-size(); - white-space: nowrap; - } - li + li { - margin-left: @padding-base; - } -} - -// Tabs -.btn__bar { - position: relative; - margin: 0 auto @padding-base; - max-width: @example-width-video; - white-space: nowrap; - - &::before { - content: ""; - position: absolute; - top: 50%; - left: 0; - right: 0; - height: 1px; - background: @gray-lighter; - } - - ul { - position: relative; - z-index: 1; - display: inline-block; - user-select: none; - } - li { - margin: 0; - - &:first-child .btn { - border-radius: 4px 0 0 4px; - } - &:last-child .btn { - border-radius: 0 4px 4px 0; - } - & + li .btn { - margin-left: -1px; - } - - &.active .btn { - &:extend(.btn--primary); - box-shadow: inset 0 1px 1px rgba(0,0,0, .2); - position: relative; - z-index: 1; - - .icon { - color: inherit; - } - } - &.active + li .btn:hover { - z-index: 0; - } - } - .btn { - position: relative; - display: block; - border-radius: 0; - - &:hover, - &:focus { - z-index: 1; - } - } - - @media (min-width: 560px) { - margin-bottom: (@padding-base * 2); - } -} - -// Shared -.btn, -.btn__count { - display: inline-block; - vertical-align: middle; - border-radius: @border-radius-base; - user-select: none; - font-weight: @font-weight-bold; -} - -// Buttons -.btn { - padding: (@padding-base / 2) ((@padding-base / 2) + 2); - background: linear-gradient(lighten(@off-white, 2%), darken(@off-white, 3%)); - border: 1px solid @gray-light; - box-shadow: 0 1px 1px rgba(0,0,0, .05); - text-shadow: 0 1px 1px #fff; - color: @gray; - transition: background .1s ease, color .1s ease; - .font-size(@font-size-small); - - &:hover, - &:focus { - border-color: darken(@gray-light, 8%); - color: @gray; - outline: 0; - } -} - -// Sizes -.btn--large { - padding: (@padding-base / 2) @padding-base; - .font-size(); -} - -// Styles -.btn--primary { - background-image: linear-gradient(@link-color, darken(@link-color, 5%)); - background-color: @link-color; - border-color: darken(@link-color, 10%); - box-shadow: 0 1px 1px rgba(0,0,0, .15); - text-shadow: 0 1px 1px rgba(0,0,0, .1); - color: #fff; - - &:hover, - &:focus { - color: #fff; - border-color: darken(@link-color, 20%); - } -} -.btn--youtube .icon { - color: @color-youtube; -} -.btn--vimeo .icon { - color: @color-vimeo; -} -.btn--twitter .icon { - color: @color-twitter; -} - -// Count bubble -.btn__count { - position: relative; - margin-left: (@padding-base / 2); - padding: (@padding-base / 2) (@padding-base * .75); - background: #fff; - border: 1px solid @gray-light; - - &::before { - content: ""; - position: absolute; - display: block; - width: @arrow-size; - height: @arrow-size; - left: 1px; - top: 50%; - margin-top: -(@arrow-size / 2); - - background: inherit; - border: inherit; - border-width: 1px 0 0 1px; - transform: rotate(-45deg) translate(-50%, -50%); - } -} diff --git a/demo/src/less/components/type.less b/demo/src/less/components/type.less deleted file mode 100644 index 951be36d..00000000 --- a/demo/src/less/components/type.less +++ /dev/null @@ -1,75 +0,0 @@ -// ========================================================================== -// Typography -// ========================================================================== - -// Base -html { - font-size: 100%; -} -body { - font-family: "Avenir", "Helvetica Neue", Helvetica, Arial, sans-serif; - line-height: 1.5; - text-align: center; - color: @gray; - font-weight: @font-weight-base; - .font-smoothing(); -} - -// Headings -h1, -h2 { - letter-spacing: -.025em; - color: @brand-primary; - margin: 0 0 (@padding-base / 2); - line-height: 1.2; - font-weight: @font-weight-bold; -} -h1 { - .font-size(@font-size-h1); -} - -// Paragraph and small -p, -small { - margin: 0 0 @padding-base; -} -small { - display: block; - padding: 0 (@padding-base / 2); - .font-size(@font-size-small); -} - -// Lists -ul, -li { - list-style: none; - margin: 0; - padding: 0; -} - -// Links -a { - text-decoration: none; - color: @link-color; - border-bottom: 1px dotted currentColor; - transition: background .3s ease, color .3s ease, border .3s ease; - - &:hover, - &:focus { - color: @gray-dark; - border-bottom-color: rgba(0,0,0,0); - } - &:focus { - .tab-focus(); - } - &.logo { - border: 0; - } -} - -.color--vimeo { - color: @color-vimeo; -} -.color--youtube { - color: @color-youtube; -} diff --git a/demo/src/less/demo.less b/demo/src/less/demo.less deleted file mode 100644 index ac15a3c0..00000000 --- a/demo/src/less/demo.less +++ /dev/null @@ -1,26 +0,0 @@ -// ========================================================================== -// Plyr.io Demo Page -// ========================================================================== - -// CSS Reset -@import "lib/normalize.less"; - -// Mixins -@import "lib/mixins.less"; - -// Variables -@import "variables.less"; - -// Animation -@import "lib/animation.less"; - -// Type -@import "lib/fontface.less"; -@import "components/type.less"; - -// Components -@import "components/base.less"; -@import "components/icons.less"; -@import "components/buttons.less"; -@import "components/error.less"; -@import "components/examples.less"; diff --git a/demo/src/less/lib/fontface.less b/demo/src/less/lib/fontface.less deleted file mode 100644 index 82a2a160..00000000 --- a/demo/src/less/lib/fontface.less +++ /dev/null @@ -1,18 +0,0 @@ -// ========================================================================== -// Fonts -// ========================================================================== - -@font-face { - font-family: 'Avenir'; - src: url('https://cdn.plyr.io/static/fonts/avenir-medium.woff2') format('woff2'), url('https://cdn.plyr.io/static/fonts/avenir-medium.woff') format('woff'); - font-style: normal; - font-weight: @font-weight-base; - font-display: swap; -} -@font-face { - font-family: 'Avenir'; - src: url('https://cdn.plyr.io/static/fonts/avenir-bold.woff2') format('woff2'), url('https://cdn.plyr.io/static/fonts/avenir-bold.woff') format('woff'); - font-style: normal; - font-weight: @font-weight-bold; - font-display: swap; -} diff --git a/demo/src/less/lib/mixins.less b/demo/src/less/lib/mixins.less deleted file mode 100644 index 923df1ea..00000000 --- a/demo/src/less/lib/mixins.less +++ /dev/null @@ -1,41 +0,0 @@ -// ========================================================================== -// Mixins -// ========================================================================== - -// Contain floats: nicolasgallagher.com/micro-clearfix-hack/ -// --------------------------------------- -.clearfix() { - zoom: 1; - &:before, - &:after { content: ""; display: table; } - &:after { clear: both; } -} - -// Webkit-style focus -// --------------------------------------- -.tab-focus() { - // Default - outline: thin dotted @gray-dark; - // Webkit - outline-offset: 1px; -} - -// Use rems for font sizing -// Leave <body> at 100%/16px -// --------------------------------------- -.font-size(@font-size: 16){ - @rem: round((@font-size / 16), 3); - font-size: (@font-size * 1px); - font-size: ~"@{rem}rem"; -} - -// Font smoothing -// --------------------------------------- -.font-smoothing(@mode: on) when (@mode = on) { - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; -} -.font-smoothing(@mode: on) when (@mode = off) { - -moz-osx-font-smoothing: auto; - -webkit-font-smoothing: subpixel-antialiased; -}
\ No newline at end of file diff --git a/demo/src/less/variables.less b/demo/src/less/variables.less deleted file mode 100644 index 4768cdd6..00000000 --- a/demo/src/less/variables.less +++ /dev/null @@ -1,48 +0,0 @@ -// ========================================================================== -// Variables -// ========================================================================== - -// Colors -@gray-dark: #343f4a; -@gray: #55646b; -@gray-light: #cbd0d3; -@gray-lighter: #dbe3e8; -@off-white: #f2f5f7; - -@brand-primary: #3498db; -@brand-secondary: #02BD9B; - -// Brands -@color-twitter: #4BAAF4; -@color-youtube: #cc181e; -@color-vimeo: #19b7ed; - -// Base -@body-background: @off-white; //linear-gradient(to left top, @brand-secondary, @brand-primary); - -// Type -@font-size-base: 16; -@font-size-small: 14; -@font-size-h1: 64; -@font-weight-base: 500; -@font-weight-bold: 700; - -// Elements -@link-color: @brand-primary; -@padding-base: 20px; -@arrow-size: 8px; - -// Icons -@icon-size: 18px; - -// Breakpoints -@screen-sm: 480px; -@screen-md: 768px; - -// Radii -@border-radius-base: 4px; -@border-radius-large: 6px; - -// Examples -@example-width-audio: 520px; -@example-width-video: 1200px; diff --git a/demo/src/sass/bundles/demo.scss b/demo/src/sass/bundles/demo.scss new file mode 100644 index 00000000..96438483 --- /dev/null +++ b/demo/src/sass/bundles/demo.scss @@ -0,0 +1,41 @@ +// ========================================================================== +// Plyr.io Demo Page +// ========================================================================== +@charset 'UTF-8'; + +// Settings +@import '../settings/breakpoints'; +@import '../settings/colors'; +@import '../settings/cosmetic'; +@import '../settings/icons'; +@import '../settings/layout'; +@import '../settings/plyr'; +@import '../settings/spacing'; +@import '../settings/type'; + +// Libs +@import '../lib/fontface'; +@import '../lib/animation'; +@import '../lib/mixins'; +@import '../lib/normalize'; +@import '../lib/reset'; + +// Layout +@import '../layout/core'; +@import '../layout/grid'; + +// Type +@import '../type/base'; +@import '../type/headings'; + +// Components +@import '../components/buttons'; +@import '../components/header'; +@import '../components/icons'; +@import '../components/links'; +@import '../components/lists'; +@import '../components/navigation'; +@import '../components/players'; + +// Plyr +@import '../../../../src/sass/plyr'; diff --git a/demo/src/sass/bundles/error.scss b/demo/src/sass/bundles/error.scss new file mode 100644 index 00000000..29c98947 --- /dev/null +++ b/demo/src/sass/bundles/error.scss @@ -0,0 +1,29 @@ +// ========================================================================== +// Plyr.io Error Page +// ========================================================================== +@charset 'UTF-8'; + +// Libs +@import '../lib/fontface'; +@import '../lib/mixins'; +@import '../lib/normalize'; +@import '../lib/reset'; + +// Settings +@import '../settings/colors'; +@import '../settings/cosmetic'; +@import '../settings/icons'; +@import '../settings/layout'; +@import '../settings/spacing'; +@import '../settings/type'; + +// Layout +@import '../layout/error'; + +// Type +@import '../type/base'; +@import '../type/headings'; + +// Components +@import '../components/buttons'; +@import '../components/links'; diff --git a/demo/src/sass/components/buttons.scss b/demo/src/sass/components/buttons.scss new file mode 100644 index 00000000..db821ad3 --- /dev/null +++ b/demo/src/sass/components/buttons.scss @@ -0,0 +1,83 @@ +// ========================================================================== +// Buttons +// ========================================================================== + +// Shared +.button, +.button__count { + align-items: center; + background: #fff; + border: 0; + border-radius: $border-radius-base; + box-shadow: 0 1px 1px rgba(#000, 0.1); + color: $gray; + display: inline-flex; + padding: ($spacing-base * 0.75); + position: relative; + text-shadow: none; + user-select: none; + vertical-align: middle; +} + +// Buttons +.button { + font-weight: $font-weight-bold; + padding-left: $spacing-base; + padding-right: $spacing-base; + transition: all 0.2s ease; + + &:hover, + &:focus { + color: $gray-dark; + + // Remove the underline/border + &::after { + display: none; + } + } + + &:hover { + box-shadow: 0 2px 2px rgba(#000, 0.1); + transform: translateY(-1px); + } + + &:focus { + outline: 0; + } + + &.tab-focus { + @include tab-focus(); + } + + &:active { + transform: translateY(1px); + } +} + +// Button group +.button--with-count { + display: inline-flex; + + .button .icon { + flex-shrink: 0; + } +} + +// Count bubble +.button__count { + animation: fadein 0.2s ease; + margin-left: ($spacing-base / 2); + + &::before { + border: $arrow-size solid transparent; + border-left-width: 0; + border-right-color: #fff; + content: ''; + height: 0; + position: absolute; + right: 100%; + top: 50%; + transform: translateY(-50%); + width: 0; + } +} diff --git a/demo/src/sass/components/header.scss b/demo/src/sass/components/header.scss new file mode 100644 index 00000000..eab2214e --- /dev/null +++ b/demo/src/sass/components/header.scss @@ -0,0 +1,19 @@ +// ========================================================================== +// Header +// ========================================================================== + +header { + padding-bottom: $spacing-base; + text-align: center; + + .call-to-action { + margin-top: ($spacing-base * 1.5); + } + + @media only screen and (min-width: $screen-md) { + margin-right: ($spacing-base * 3); + max-width: 360px; + padding-bottom: ($spacing-base * 2); + text-align: left; + } +} diff --git a/demo/src/less/components/icons.less b/demo/src/sass/components/icons.scss index 9530b601..b2b353a6 100644 --- a/demo/src/less/components/icons.less +++ b/demo/src/sass/components/icons.scss @@ -4,23 +4,20 @@ // Base size icon styles .icon { - fill: currentColor; - width: @icon-size; - height: @icon-size; - vertical-align: -3px; + fill: currentColor; + height: $icon-size; + vertical-align: -3px; + width: $icon-size; } // Within elements a svg, button svg, label svg { - pointer-events: none; + pointer-events: none; } + a .icon, .btn .icon { - margin-right: (@padding-base / 2); -} -.btn:not(.btn-large) .icon { - width: (@icon-size - 2); - height: (@icon-size - 2); + margin-right: floor($spacing-base / 3); } diff --git a/demo/src/sass/components/links.scss b/demo/src/sass/components/links.scss new file mode 100644 index 00000000..25780b41 --- /dev/null +++ b/demo/src/sass/components/links.scss @@ -0,0 +1,45 @@ +// ========================================================================== +// Links +// ========================================================================== + +// Make a <button> look like an <a> +button.faux-link { + @extend a; // stylelint-disable-line + @include cancel-button-styles(); +} + +// Links +a { + border-bottom: 1px dotted currentColor; + color: $color-link; + font-weight: $font-weight-bold; + position: relative; + text-decoration: none; + transition: all 0.2s ease; + + &::after { + background: currentColor; + content: ''; + height: 1px; + left: 50%; + position: absolute; + top: 100%; + transform: translateX(-50%); + transition: width 0.2s ease; + width: 0; + } + + &:hover, + &:focus { + border-bottom-color: transparent; + outline: 0; + + &::after { + width: 100%; + } + } + + &.tab-focus { + @include tab-focus(); + } +} diff --git a/demo/src/sass/components/lists.scss b/demo/src/sass/components/lists.scss new file mode 100644 index 00000000..bae3d11d --- /dev/null +++ b/demo/src/sass/components/lists.scss @@ -0,0 +1,11 @@ +// ========================================================================== +// Lists +// ========================================================================== + +// Lists +ul, +li { + list-style: none; + margin: 0; + padding: 0; +} diff --git a/demo/src/sass/components/navigation.scss b/demo/src/sass/components/navigation.scss new file mode 100644 index 00000000..fe14c000 --- /dev/null +++ b/demo/src/sass/components/navigation.scss @@ -0,0 +1,9 @@ +// ========================================================================== +// Navigation +// ========================================================================== + +nav { + display: flex; + justify-content: center; + margin-bottom: $spacing-base; +} diff --git a/demo/src/less/components/examples.less b/demo/src/sass/components/players.scss index a9e72d21..90e2bc94 100644 --- a/demo/src/less/components/examples.less +++ b/demo/src/sass/components/players.scss @@ -10,31 +10,34 @@ video { // Example players .plyr { - margin: 0 auto; - border-radius: @border-radius-large; -} -.plyr--audio { - max-width: @example-width-audio; + border-radius: $border-radius-base; + box-shadow: 0 2px 5px rgba(#000, 0.2); + margin: $spacing-base auto; + + &.plyr--audio { + max-width: 480px; + } } + .plyr__video-wrapper::after { - content: ""; - pointer-events: none; - position: absolute; - top: 0; + border: 1px solid rgba(#000, 0.15); + border-radius: inherit; bottom: 0; + content: ''; left: 0; + pointer-events: none; + position: absolute; right: 0; - border: 1px solid fade(#000, 15%); - border-radius: inherit; + top: 0; } // Style full supported player .plyr__cite { display: none; - margin-top: @padding-base; + margin-top: $spacing-base; .icon { - margin-right: (@padding-base / 4); + margin-right: ceil($spacing-base / 6); } } diff --git a/demo/src/sass/layout/core.scss b/demo/src/sass/layout/core.scss new file mode 100644 index 00000000..c4d9a445 --- /dev/null +++ b/demo/src/sass/layout/core.scss @@ -0,0 +1,63 @@ +// ========================================================================== +// Core +// ========================================================================== + +html, +body { + display: flex; + width: 100%; +} + +html { + background: $page-background; + background-attachment: fixed; + height: 100%; +} + +body { + align-items: center; + display: flex; + flex-direction: column; + min-height: 100%; +} + +.grid { + flex: 1; + overflow: auto; +} + +main { + margin: auto; + text-align: center; +} + +aside { + align-items: center; + background: #fff; + color: $gray; + display: flex; + flex-shrink: 0; + justify-content: center; + padding: ($spacing-base * 0.75); + position: relative; + text-align: center; + text-shadow: none; + width: 100%; + + .icon { + fill: $color-twitter; + margin-right: ($spacing-base / 2); + } + + p { + margin: 0; + } + + a { + color: $color-twitter; + + &.tab-focus { + @include tab-focus($color-twitter); + } + } +} diff --git a/demo/src/less/components/error.less b/demo/src/sass/layout/error.scss index b1427173..385ecbf3 100644 --- a/demo/src/less/components/error.less +++ b/demo/src/sass/layout/error.scss @@ -7,13 +7,24 @@ html.error, .error body { height: 100%; } + +html.error { + background: $page-background; + background-attachment: fixed; +} + .error body { + align-items: center; + display: flex; width: 100%; - display: table; - table-layout: fixed; } + .error main { - display: table-cell; + padding: $spacing-base; + text-align: center; width: 100%; - vertical-align: middle; -}
\ No newline at end of file + + p { + @include font-size($font-size-large); + } +} diff --git a/demo/src/sass/layout/grid.scss b/demo/src/sass/layout/grid.scss new file mode 100644 index 00000000..40dd829e --- /dev/null +++ b/demo/src/sass/layout/grid.scss @@ -0,0 +1,19 @@ +// ========================================================================== +// Super basic grid +// ========================================================================== + +.grid { + margin: 0 auto; + padding: $spacing-base; + + @media only screen and (min-width: $screen-md) { + align-items: center; + display: flex; + max-width: $container-max-width; + width: 100%; + + > * { + flex: 1; + } + } +} diff --git a/demo/src/less/lib/animation.less b/demo/src/sass/lib/animation.scss index 386c6613..3c14b0a7 100644 --- a/demo/src/less/lib/animation.less +++ b/demo/src/sass/lib/animation.scss @@ -3,7 +3,11 @@ // ========================================================================== // Fade -@keyframes fade-in { - 0% { opacity: 0 } - 100% { opacity: 1 } -}
\ No newline at end of file +@keyframes fadein { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} diff --git a/demo/src/sass/lib/fontface.scss b/demo/src/sass/lib/fontface.scss new file mode 100644 index 00000000..e7e4edf8 --- /dev/null +++ b/demo/src/sass/lib/fontface.scss @@ -0,0 +1,45 @@ +// ========================================================================== +// Fonts +// ========================================================================== + +@font-face { + font-display: swap; + font-family: 'Gordita'; + font-style: normal; + font-weight: $font-weight-light; + src: url('https://cdn.plyr.io/static/fonts/gordita-light.woff2') format('woff2'), url('https://cdn.plyr.io/static/fonts/gordita-light.woff') format('woff'); +} + +@font-face { + font-display: swap; + font-family: 'Gordita'; + font-style: normal; + font-weight: $font-weight-regular; + src: url('https://cdn.plyr.io/static/fonts/gordita-regular.woff2') format('woff2'), + url('https://cdn.plyr.io/static/fonts/gordita-regular.woff') format('woff'); +} + +@font-face { + font-display: swap; + font-family: 'Gordita'; + font-style: normal; + font-weight: $font-weight-medium; + src: url('https://cdn.plyr.io/static/fonts/gordita-medium.woff2') format('woff2'), + url('https://cdn.plyr.io/static/fonts/gordita-medium.woff') format('woff'); +} + +@font-face { + font-display: swap; + font-family: 'Gordita'; + font-style: normal; + font-weight: $font-weight-bold; + src: url('https://cdn.plyr.io/static/fonts/gordita-bold.woff2') format('woff2'), url('https://cdn.plyr.io/static/fonts/gordita-bold.woff') format('woff'); +} + +@font-face { + font-display: swap; + font-family: 'Gordita'; + font-style: normal; + font-weight: $font-weight-black; + src: url('https://cdn.plyr.io/static/fonts/gordita-black.woff2') format('woff2'), url('https://cdn.plyr.io/static/fonts/gordita-black.woff') format('woff'); +} diff --git a/demo/src/sass/lib/mixins.scss b/demo/src/sass/lib/mixins.scss new file mode 100644 index 00000000..cdfcb87d --- /dev/null +++ b/demo/src/sass/lib/mixins.scss @@ -0,0 +1,54 @@ +// ========================================================================== +// Mixins +// ========================================================================== + +// Convert a <button> into an <a> +// --------------------------------------- +@mixin cancel-button-styles() { + background: transparent; + border: 0; + border-radius: 0; + cursor: pointer; + font: inherit; + line-height: $line-height-base; + margin: 0; + padding: 0; + position: relative; + text-align: inherit; + text-shadow: inherit; + -moz-user-select: text; // stylelint-disable-line + vertical-align: baseline; + width: auto; +} + +// Nicer focus styles +// --------------------------------------- +@mixin tab-focus($color: $tab-focus-default-color) { + box-shadow: 0 0 0 3px rgba($color, 0.35); + outline: 0; +} + +// Use rems for font sizing +// Leave <body> at 100%/16px +// --------------------------------------- +@function calculate-rem($size) { + $rem: $size / 16; + @return #{$rem}rem; +} + +@mixin font-size($size: 16) { + font-size: $size * 1px; // Fallback in px + font-size: calculate-rem($size); +} + +// Font smoothing +// --------------------------------------- +@mixin font-smoothing($enabled: true) { + @if $enabled { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + } @else { + -moz-osx-font-smoothing: auto; + -webkit-font-smoothing: subpixel-antialiased; + } +} diff --git a/demo/src/less/lib/normalize.less b/demo/src/sass/lib/normalize.scss index 562891ab..34743e73 100644 --- a/demo/src/less/lib/normalize.less +++ b/demo/src/sass/lib/normalize.scss @@ -189,7 +189,7 @@ pre { */ q { - quotes: "\201C" "\201D" "\2018" "\2019"; + quotes: '\201C' '\201D' '\2018' '\2019'; } /** @@ -322,9 +322,9 @@ select { */ button, -html input[type="button"], /* 1 */ -input[type="reset"], -input[type="submit"] { +html input[type='button'], +input[type='reset'], +input[type='submit'] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ } @@ -343,8 +343,8 @@ html input[disabled] { * 2. Remove excess padding in IE 8/9/10. */ -input[type="checkbox"], -input[type="radio"] { +input[type='checkbox'], +input[type='radio'] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ } @@ -355,7 +355,7 @@ input[type="radio"] { * (include `-moz` to future-proof). */ -input[type="search"] { +input[type='search'] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ @@ -367,8 +367,8 @@ input[type="search"] { * on OS X. */ -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { +input[type='search']::-webkit-search-cancel-button, +input[type='search']::-webkit-search-decoration { -webkit-appearance: none; } @@ -403,4 +403,4 @@ textarea { table { border-collapse: collapse; border-spacing: 0; -}
\ No newline at end of file +} diff --git a/demo/src/sass/lib/reset.scss b/demo/src/sass/lib/reset.scss new file mode 100644 index 00000000..50798b10 --- /dev/null +++ b/demo/src/sass/lib/reset.scss @@ -0,0 +1,11 @@ +// ========================================================================== +// Resets +// ========================================================================== + +// BORDER-BOX ALL THE THINGS! +// http://paulirish.com/2012/box-sizing-border-box-ftw/ +*, +*::after, +*::before { + box-sizing: border-box; +} diff --git a/demo/src/sass/settings/breakpoints.scss b/demo/src/sass/settings/breakpoints.scss new file mode 100644 index 00000000..65940ad6 --- /dev/null +++ b/demo/src/sass/settings/breakpoints.scss @@ -0,0 +1,6 @@ +// ========================================================================== +// Breakpoints +// ========================================================================== + +$screen-sm: 480px; +$screen-md: 768px; diff --git a/demo/src/sass/settings/colors.scss b/demo/src/sass/settings/colors.scss new file mode 100644 index 00000000..aa1c96ee --- /dev/null +++ b/demo/src/sass/settings/colors.scss @@ -0,0 +1,27 @@ +// ========================================================================== +// Colors +// ========================================================================== + +// Greyscale +$gray-dark: #343f4a; +$gray: #55646b; +$gray-light: #cbd0d3; +$gray-lighter: #dbe3e8; +$off-white: #f2f5f7; + +// Text +$color-text: #fff; + +// Plyr +$color-brand-primary: #1aafff; + +// Brands +$color-twitter: #4baaf4; +$color-youtube: #cc181e; +$color-vimeo: #19b7ed; + +// Elements +$color-link: #fff; + +// Focus +$tab-focus-default-color: #fff; diff --git a/demo/src/sass/settings/cosmetic.scss b/demo/src/sass/settings/cosmetic.scss new file mode 100644 index 00000000..dee536e5 --- /dev/null +++ b/demo/src/sass/settings/cosmetic.scss @@ -0,0 +1,12 @@ +// ========================================================================== +// Misc cosmetic +// ========================================================================== + +// Button count arrow size +$arrow-size: 5px; + +// Radii +$border-radius-base: 4px; + +// Background +$page-background: linear-gradient(to left top, lighten($color-brand-primary, 10%), darken($color-brand-primary, 20%)); diff --git a/demo/src/sass/settings/icons.scss b/demo/src/sass/settings/icons.scss new file mode 100644 index 00000000..ad16a645 --- /dev/null +++ b/demo/src/sass/settings/icons.scss @@ -0,0 +1,5 @@ +// ========================================================================== +// Icons +// ========================================================================== + +$icon-size: 16px; diff --git a/demo/src/sass/settings/layout.scss b/demo/src/sass/settings/layout.scss new file mode 100644 index 00000000..8d1fbd28 --- /dev/null +++ b/demo/src/sass/settings/layout.scss @@ -0,0 +1,5 @@ +// ========================================================================== +// Layout +// ========================================================================== + +$container-max-width: 1280px; diff --git a/demo/src/sass/settings/plyr.scss b/demo/src/sass/settings/plyr.scss new file mode 100644 index 00000000..3d30ce71 --- /dev/null +++ b/demo/src/sass/settings/plyr.scss @@ -0,0 +1,18 @@ +// ========================================================================== +// Plyr Settings +// ========================================================================== + +// Font +$plyr-font-family: inherit; + +// Sizes +$plyr-font-size-base: 13px; +$plyr-font-size-small: 12px; +$plyr-font-size-time: 11px; +$plyr-font-size-badges: 9px; + +// Captions +$plyr-font-size-captions-base: $plyr-font-size-base; +$plyr-font-size-captions-small: $plyr-font-size-small; +$plyr-font-size-captions-medium: 18px; +$plyr-font-size-captions-large: 21px; diff --git a/demo/src/sass/settings/spacing.scss b/demo/src/sass/settings/spacing.scss new file mode 100644 index 00000000..a19b0a95 --- /dev/null +++ b/demo/src/sass/settings/spacing.scss @@ -0,0 +1,5 @@ +// ========================================================================== +// Colors +// ========================================================================== + +$spacing-base: 20px; diff --git a/demo/src/sass/settings/type.scss b/demo/src/sass/settings/type.scss new file mode 100644 index 00000000..e8f0b2c8 --- /dev/null +++ b/demo/src/sass/settings/type.scss @@ -0,0 +1,20 @@ +// ========================================================================== +// Typography +// ========================================================================== + +$font-sans-serif: 'Gordita', 'Avenir', 'Helvetica Neue', sans-serif; + +$font-size-base: 15; +$font-size-small: 13; +$font-size-large: 18; +$font-size-h1: 64; + +$font-weight-light: 300; +$font-weight-regular: 400; +$font-weight-medium: 500; +$font-weight-bold: 600; +$font-weight-black: 900; + +$line-height-base: 1.75; + +$letter-spacing-headings: -0.025em; diff --git a/demo/src/sass/type/base.scss b/demo/src/sass/type/base.scss new file mode 100644 index 00000000..452298bd --- /dev/null +++ b/demo/src/sass/type/base.scss @@ -0,0 +1,35 @@ +// ========================================================================== +// Base +// ========================================================================== + +// Set to 100% for rem sizing +html { + font-size: 100%; +} + +body { + @include font-smoothing(); + @include font-size($font-size-base); + color: $color-text; + font-family: $font-sans-serif; + font-weight: $font-weight-medium; + line-height: $line-height-base; + text-shadow: 0 1px 1px rgba(#000, 0.15); +} + +button, +input, +select, +textarea { + font: inherit; +} + +p, +small { + margin: 0 0 $spacing-base; +} + +small { + @include font-size($font-size-small); + display: block; +} diff --git a/demo/src/sass/type/headings.scss b/demo/src/sass/type/headings.scss new file mode 100644 index 00000000..c2abc97e --- /dev/null +++ b/demo/src/sass/type/headings.scss @@ -0,0 +1,10 @@ +// ========================================================================== +// Headings +// ========================================================================== + +h1 { + @include font-size($font-size-h1); + font-weight: $font-weight-bold; + letter-spacing: $letter-spacing-headings; + margin: 0 0 ($spacing-base / 2); +} diff --git a/demo/src/sass/utilities/color.scss b/demo/src/sass/utilities/color.scss new file mode 100644 index 00000000..786e6ccb --- /dev/null +++ b/demo/src/sass/utilities/color.scss @@ -0,0 +1,11 @@ +// ========================================================================== +// Color +// ========================================================================== + +.color--vimeo { + color: $color-vimeo; +} + +.color--youtube { + color: $color-youtube; +} diff --git a/demo/src/sass/utilities/hidden.scss b/demo/src/sass/utilities/hidden.scss new file mode 100644 index 00000000..a48b107a --- /dev/null +++ b/demo/src/sass/utilities/hidden.scss @@ -0,0 +1,7 @@ +// ========================================================================== +// Hidden +// ========================================================================== + +[hidden] { + display: none; +} diff --git a/demo/src/sprite/icon-github.svg b/demo/src/sprite/icon-github.svg deleted file mode 100755 index 685dd746..00000000 --- a/demo/src/sprite/icon-github.svg +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
-<path fill-rule="evenodd" clip-rule="evenodd" d="M8,0.2c-4.4,0-8,3.6-8,8c0,3.5,2.3,6.5,5.5,7.6
- C5.9,15.9,6,15.6,6,15.4c0-0.2,0-0.7,0-1.4C3.8,14.5,3.3,13,3.3,13c-0.4-0.9-0.9-1.2-0.9-1.2c-0.7-0.5,0.1-0.5,0.1-0.5
- c0.8,0.1,1.2,0.8,1.2,0.8C4.4,13.4,5.6,13,6,12.8c0.1-0.5,0.3-0.9,0.5-1.1c-1.8-0.2-3.6-0.9-3.6-4c0-0.9,0.3-1.6,0.8-2.1
- c-0.1-0.2-0.4-1,0.1-2.1c0,0,0.7-0.2,2.2,0.8c0.6-0.2,1.3-0.3,2-0.3c0.7,0,1.4,0.1,2,0.3c1.5-1,2.2-0.8,2.2-0.8
- c0.4,1.1,0.2,1.9,0.1,2.1c0.5,0.6,0.8,1.3,0.8,2.1c0,3.1-1.9,3.7-3.7,3.9C9.7,12,10,12.5,10,13.2c0,1.1,0,1.9,0,2.2
- c0,0.2,0.1,0.5,0.6,0.4c3.2-1.1,5.5-4.1,5.5-7.6C16,3.8,12.4,0.2,8,0.2z"/>
-</svg>
diff --git a/demo/src/sprite/icon-twitter.svg b/demo/src/sprite/icon-twitter.svg deleted file mode 100755 index b3f644b1..00000000 --- a/demo/src/sprite/icon-twitter.svg +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
- <title>Twitter</title>
-<path d="M16,3c-0.6,0.3-1.2,0.4-1.9,0.5c0.7-0.4,1.2-1,1.4-1.8c-0.6,0.4-1.3,0.6-2.1,0.8c-0.6-0.6-1.5-1-2.4-1
- C9.3,1.5,7.8,3,7.8,4.8c0,0.3,0,0.5,0.1,0.7C5.2,5.4,2.7,4.1,1.1,2.1c-0.3,0.5-0.4,1-0.4,1.7c0,1.1,0.6,2.1,1.5,2.7
- c-0.5,0-1-0.2-1.5-0.4c0,0,0,0,0,0c0,1.6,1.1,2.9,2.6,3.2C3,9.4,2.7,9.4,2.4,9.4c-0.2,0-0.4,0-0.6-0.1c0.4,1.3,1.6,2.3,3.1,2.3
- c-1.1,0.9-2.5,1.4-4.1,1.4c-0.3,0-0.5,0-0.8,0c1.5,0.9,3.2,1.5,5,1.5c6,0,9.3-5,9.3-9.3c0-0.1,0-0.3,0-0.4C15,4.3,15.6,3.7,16,3z"/>
-</svg>
diff --git a/demo/src/sprite/icon-vimeo.svg b/demo/src/sprite/icon-vimeo.svg deleted file mode 100755 index 83dd3dc0..00000000 --- a/demo/src/sprite/icon-vimeo.svg +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
-<path d="M16,4.3c-0.1,1.6-1.2,3.7-3.3,6.4c-2.2,2.8-4,4.2-5.5,4.2c-0.9,0-1.7-0.9-2.4-2.6C4,9.9,3.4,5,2,5
- C1.9,5,1.5,5.3,0.8,5.8L0,4.8c0.8-0.7,3.5-3.4,4.7-3.5C5.9,1.2,6.7,2,7,3.8c0.3,2,0.8,6.1,1.8,6.1c0.9,0,2.5-3.4,2.6-4
- c0.1-0.9-0.3-1.9-2.3-1.1c0.8-2.6,2.3-3.8,4.5-3.8C15.3,1.1,16.1,2.2,16,4.3z"/>
-</svg>
diff --git a/demo/src/sprite/icon-youtube.svg b/demo/src/sprite/icon-youtube.svg deleted file mode 100755 index 8b5d6897..00000000 --- a/demo/src/sprite/icon-youtube.svg +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
-<path d="M15.8,4.8c-0.2-1.3-0.8-2.2-2.2-2.4C11.4,2,8,2,8,2S4.6,2,2.4,2.4C1,2.6,0.3,3.5,0.2,4.8C0,6.1,0,8,0,8
- s0,1.9,0.2,3.2c0.2,1.3,0.8,2.2,2.2,2.4C4.6,14,8,14,8,14s3.4,0,5.6-0.4c1.4-0.3,2-1.1,2.2-2.4C16,9.9,16,8,16,8S16,6.1,15.8,4.8z
- M6,11V5l5,3L6,11z"/>
-</svg>
diff --git a/dist/blank.mp4 b/dist/blank.mp4 Binary files differnew file mode 100644 index 00000000..d8982b63 --- /dev/null +++ b/dist/blank.mp4 diff --git a/dist/plyr.css b/dist/plyr.css index d95aaee2..21a68b30 100644 --- a/dist/plyr.css +++ b/dist/plyr.css @@ -1 +1 @@ -@-webkit-keyframes plyr-progress{to{background-position:25px 0}}@keyframes plyr-progress{to{background-position:25px 0}}.plyr{position:relative;max-width:100%;min-width:200px;font-family:Avenir,'Avenir Next','Helvetica Neue','Segoe UI',Helvetica,Arial,sans-serif;direction:ltr}.plyr,.plyr *,.plyr ::after,.plyr ::before{-webkit-box-sizing:border-box;box-sizing:border-box}.plyr a,.plyr button,.plyr input,.plyr label{-ms-touch-action:manipulation;touch-action:manipulation}.plyr:focus{outline:0}.plyr audio,.plyr video{width:100%;height:auto;vertical-align:middle;border-radius:inherit}.plyr input[type=range]{display:block;height:20px;width:100%;margin:0;padding:0;-webkit-appearance:none;-moz-appearance:none;cursor:pointer;border:none;background:0 0}.plyr input[type=range]::-webkit-slider-runnable-track{height:8px;background:0 0;border:0;border-radius:4px;-webkit-user-select:none;user-select:none}.plyr input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;margin-top:-4px;position:relative;height:16px;width:16px;background:#fff;border:2px solid transparent;border-radius:100%;-webkit-transition:background .2s ease,border .2s ease,-webkit-transform .2s ease;transition:background .2s ease,border .2s ease,-webkit-transform .2s ease;transition:background .2s ease,border .2s ease,transform .2s ease;transition:background .2s ease,border .2s ease,transform .2s ease,-webkit-transform .2s ease;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(0,0,0,.15);box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(0,0,0,.15);-webkit-box-sizing:border-box;box-sizing:border-box}.plyr input[type=range]::-moz-range-track{height:8px;background:0 0;border:0;border-radius:4px;-moz-user-select:none;user-select:none}.plyr input[type=range]::-moz-range-thumb{position:relative;height:16px;width:16px;background:#fff;border:2px solid transparent;border-radius:100%;-webkit-transition:background .2s ease,border .2s ease,-webkit-transform .2s ease;transition:background .2s ease,border .2s ease,-webkit-transform .2s ease;transition:background .2s ease,border .2s ease,transform .2s ease;transition:background .2s ease,border .2s ease,transform .2s ease,-webkit-transform .2s ease;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(0,0,0,.15);box-sizing:border-box}.plyr input[type=range]::-ms-track{height:8px;background:0 0;border:0;color:transparent}.plyr input[type=range]::-ms-fill-upper{height:8px;background:0 0;border:0;border-radius:4px;-ms-user-select:none;user-select:none}.plyr input[type=range]::-ms-fill-lower{height:8px;background:0 0;border:0;border-radius:4px;-ms-user-select:none;user-select:none;background:#3498db}.plyr input[type=range]::-ms-thumb{position:relative;height:16px;width:16px;background:#fff;border:2px solid transparent;border-radius:100%;-webkit-transition:background .2s ease,border .2s ease,-webkit-transform .2s ease;transition:background .2s ease,border .2s ease,-webkit-transform .2s ease;transition:background .2s ease,border .2s ease,transform .2s ease;transition:background .2s ease,border .2s ease,transform .2s ease,-webkit-transform .2s ease;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(0,0,0,.15);box-sizing:border-box;margin-top:0}.plyr input[type=range]::-ms-tooltip{display:none}.plyr input[type=range]:focus{outline:0}.plyr input[type=range]::-moz-focus-outer{border:0}.plyr input[type=range].tab-focus:focus{outline-offset:3px}.plyr input[type=range]:active::-webkit-slider-thumb{background:#3498db;border-color:#fff;-webkit-transform:scale(1.25);transform:scale(1.25)}.plyr input[type=range]:active::-moz-range-thumb{background:#3498db;border-color:#fff;transform:scale(1.25)}.plyr input[type=range]:active::-ms-thumb{background:#3498db;border-color:#fff;transform:scale(1.25)}.plyr--video input[type=range].tab-focus:focus{outline:1px dotted rgba(255,255,255,.5)}.plyr--audio input[type=range].tab-focus:focus{outline:1px dotted rgba(86,93,100,.5)}.plyr__sr-only{clip:rect(1px,1px,1px,1px);overflow:hidden;position:absolute!important;padding:0!important;border:0!important;height:1px!important;width:1px!important}.plyr__video-wrapper{position:relative;background:#000;border-radius:inherit}.plyr__video-embed{padding-bottom:56.25%;height:0;border-radius:inherit;overflow:hidden;z-index:0}.plyr__video-embed iframe{position:absolute;top:0;left:0;width:100%;height:100%;border:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.plyr__video-embed>div{position:relative;padding-bottom:200%;-webkit-transform:translateY(-35.95%);transform:translateY(-35.95%)}.plyr .plyr__video-embed iframe{pointer-events:none}.plyr video::-webkit-media-text-track-container{display:none}.plyr__captions{display:none;position:absolute;bottom:0;left:0;width:100%;padding:20px;-webkit-transform:translateY(-40px);transform:translateY(-40px);-webkit-transition:-webkit-transform .3s ease;transition:-webkit-transform .3s ease;transition:transform .3s ease;transition:transform .3s ease,-webkit-transform .3s ease;color:#fff;font-size:16px;text-align:center;font-weight:400}.plyr__captions span{border-radius:2px;padding:3px 10px;background:rgba(0,0,0,.7);-webkit-box-decoration-break:clone;box-decoration-break:clone;line-height:150%}.plyr__captions span:empty{display:none}@media (min-width:768px){.plyr__captions{font-size:24px}}.plyr--captions-active .plyr__captions{display:block}.plyr--hide-controls .plyr__captions{-webkit-transform:translateY(-15px);transform:translateY(-15px)}@media (min-width:1024px){.plyr--fullscreen-active .plyr__captions{font-size:32px}}.plyr ::-webkit-media-controls{display:none}.plyr__controls{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:1;text-align:center;pointer-events:none}.plyr__controls>*{pointer-events:all}.plyr__controls .plyr__progress,.plyr__controls .plyr__time,.plyr__controls>button{margin-left:5px}.plyr__controls .plyr__progress:first-child,.plyr__controls .plyr__time:first-child,.plyr__controls>button:first-child{margin-left:0}.plyr__controls .plyr__volume{margin-left:5px}.plyr__controls [data-plyr=pause]{margin-left:0}.plyr__controls button{position:relative;display:inline-block;-ms-flex-negative:0;flex-shrink:0;overflow:visible;vertical-align:middle;padding:7px;border:0;background:0 0;border-radius:3px;cursor:pointer;-webkit-transition:background .3s ease,color .3s ease,opacity .3s ease;transition:background .3s ease,color .3s ease,opacity .3s ease;color:inherit}.plyr__controls button svg{width:18px;height:18px;display:block;fill:currentColor}.plyr__controls button:focus{outline:0}.plyr__controls .icon--captions-on,.plyr__controls .icon--exit-fullscreen,.plyr__controls .icon--muted{display:none}@media (min-width:480px){.plyr__controls .plyr__progress,.plyr__controls .plyr__time,.plyr__controls>button{margin-left:10px}}.plyr--hide-controls .plyr__controls{opacity:0;pointer-events:none}.plyr--video .plyr__controls{position:absolute;left:0;right:0;bottom:0;z-index:2;padding:50px 10px 10px;background:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0)),to(rgba(0,0,0,.5)));background:linear-gradient(rgba(0,0,0,0),rgba(0,0,0,.5));border-bottom-left-radius:inherit;border-bottom-right-radius:inherit;color:#fff;-webkit-transition:opacity .3s ease;transition:opacity .3s ease}.plyr--video .plyr__controls button.tab-focus:focus,.plyr--video .plyr__controls button:hover{background:#3498db;color:#fff}.plyr--audio .plyr__controls{padding:10px;border-radius:inherit;background:#fff;border:1px solid #dbe3e8;color:#565d64}.plyr--audio .plyr__controls button.tab-focus:focus,.plyr--audio .plyr__controls button:hover{background:#3498db;color:#fff}.plyr__play-large{display:none;position:absolute;z-index:1;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);padding:10px;background:#3498db;border:4px solid currentColor;border-radius:100%;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.15);box-shadow:0 1px 1px rgba(0,0,0,.15);color:#fff;-webkit-transition:all .3s ease;transition:all .3s ease}.plyr__play-large svg{position:relative;left:2px;width:20px;height:20px;display:block;fill:currentColor}.plyr__play-large:focus{outline:1px dotted rgba(255,255,255,.5)}.plyr .plyr__play-large{display:inline-block}.plyr--audio .plyr__play-large{display:none}.plyr--playing .plyr__play-large{opacity:0;visibility:hidden}.plyr--playing .plyr__controls [data-plyr=play],.plyr__controls [data-plyr=pause]{display:none}.plyr--playing .plyr__controls [data-plyr=pause]{display:inline-block}.plyr--captions-active .plyr__controls .icon--captions-on,.plyr--fullscreen-active .icon--exit-fullscreen,.plyr--muted .plyr__controls .icon--muted{display:block}.plyr--captions-active .plyr__controls .icon--captions-on+svg,.plyr--fullscreen-active .icon--exit-fullscreen+svg,.plyr--muted .plyr__controls .icon--muted+svg{display:none}.plyr [data-plyr=captions],.plyr [data-plyr=fullscreen]{display:none}.plyr--captions-enabled [data-plyr=captions],.plyr--fullscreen-enabled [data-plyr=fullscreen]{display:inline-block}.plyr__tooltip{position:absolute;z-index:2;bottom:100%;margin-bottom:10px;padding:5px 7.5px;pointer-events:none;opacity:0;background:rgba(0,0,0,.7);border-radius:3px;color:#fff;font-size:14px;line-height:1.3;-webkit-transform:translate(-50%,10px) scale(.8);transform:translate(-50%,10px) scale(.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;-webkit-transition:opacity .2s .1s ease,-webkit-transform .2s .1s ease;transition:opacity .2s .1s ease,-webkit-transform .2s .1s ease;transition:transform .2s .1s ease,opacity .2s .1s ease;transition:transform .2s .1s ease,opacity .2s .1s ease,-webkit-transform .2s .1s ease}.plyr__tooltip::before{content:'';position:absolute;width:0;height:0;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%);bottom:-4px;border-right:4px solid transparent;border-top:4px solid rgba(0,0,0,.7);border-left:4px solid transparent;z-index:2}.plyr button.tab-focus:focus .plyr__tooltip,.plyr button:hover .plyr__tooltip,.plyr__tooltip--visible{opacity:1;-webkit-transform:translate(-50%,0) scale(1);transform:translate(-50%,0) scale(1)}.plyr button:hover .plyr__tooltip{z-index:3}.plyr__controls button:first-child .plyr__tooltip{left:0;-webkit-transform:translate(0,10px) scale(.8);transform:translate(0,10px) scale(.8);-webkit-transform-origin:0 100%;transform-origin:0 100%}.plyr__controls button:first-child .plyr__tooltip::before{left:16px}.plyr__controls button:last-child .plyr__tooltip{right:0;-webkit-transform:translate(0,10px) scale(.8);transform:translate(0,10px) scale(.8);-webkit-transform-origin:100% 100%;transform-origin:100% 100%}.plyr__controls button:last-child .plyr__tooltip::before{left:auto;right:16px;-webkit-transform:translateX(50%);transform:translateX(50%)}.plyr__controls button:first-child .plyr__tooltip--visible,.plyr__controls button:first-child.tab-focus:focus .plyr__tooltip,.plyr__controls button:first-child:hover .plyr__tooltip,.plyr__controls button:last-child .plyr__tooltip--visible,.plyr__controls button:last-child.tab-focus:focus .plyr__tooltip,.plyr__controls button:last-child:hover .plyr__tooltip{-webkit-transform:translate(0,0) scale(1);transform:translate(0,0) scale(1)}.plyr__progress{position:relative;display:none;-webkit-box-flex:1;-ms-flex:1;flex:1}.plyr__progress input[type=range]{position:relative;z-index:2}.plyr__progress input[type=range]::-webkit-slider-runnable-track{background:0 0}.plyr__progress input[type=range]::-moz-range-track{background:0 0}.plyr__progress input[type=range]::-ms-fill-upper{background:0 0}.plyr__progress .plyr__tooltip{left:0}.plyr .plyr__progress{display:inline-block}.plyr__progress--buffer,.plyr__progress--played,.plyr__volume--display{position:absolute;left:0;top:50%;width:100%;height:8px;margin:-4px 0 0;padding:0;vertical-align:top;-webkit-appearance:none;-moz-appearance:none;border:none;border-radius:100px}.plyr__progress--buffer::-webkit-progress-bar,.plyr__progress--played::-webkit-progress-bar,.plyr__volume--display::-webkit-progress-bar{background:0 0}.plyr__progress--buffer::-webkit-progress-value,.plyr__progress--played::-webkit-progress-value,.plyr__volume--display::-webkit-progress-value{background:currentColor;border-radius:100px;min-width:8px}.plyr__progress--buffer::-moz-progress-bar,.plyr__progress--played::-moz-progress-bar,.plyr__volume--display::-moz-progress-bar{background:currentColor;border-radius:100px;min-width:8px}.plyr__progress--buffer::-ms-fill,.plyr__progress--played::-ms-fill,.plyr__volume--display::-ms-fill{border-radius:100px}.plyr__progress--played,.plyr__volume--display{z-index:1;color:#3498db;background:0 0;-webkit-transition:none;transition:none}.plyr__progress--played::-webkit-progress-value,.plyr__volume--display::-webkit-progress-value{min-width:8px;max-width:99%;border-top-right-radius:0;border-bottom-right-radius:0;-webkit-transition:none;transition:none}.plyr__progress--played::-moz-progress-bar,.plyr__volume--display::-moz-progress-bar{min-width:8px;max-width:99%;border-top-right-radius:0;border-bottom-right-radius:0;-webkit-transition:none;transition:none}.plyr__progress--played::-ms-fill,.plyr__volume--display::-ms-fill{display:none}.plyr__progress--buffer::-webkit-progress-value{-webkit-transition:width .2s ease;transition:width .2s ease}.plyr__progress--buffer::-moz-progress-bar{-webkit-transition:width .2s ease;transition:width .2s ease}.plyr__progress--buffer::-ms-fill{-webkit-transition:width .2s ease;transition:width .2s ease}.plyr--video .plyr__progress--buffer,.plyr--video .plyr__volume--display{background:rgba(255,255,255,.25)}.plyr--video .plyr__progress--buffer{color:rgba(255,255,255,.25)}.plyr--audio .plyr__progress--buffer,.plyr--audio .plyr__volume--display{background:rgba(198,214,219,.66)}.plyr--audio .plyr__progress--buffer{color:rgba(198,214,219,.66)}.plyr--loading .plyr__progress--buffer{-webkit-animation:plyr-progress 1s linear infinite;animation:plyr-progress 1s linear infinite;background-size:25px 25px;background-repeat:repeat-x;background-image:linear-gradient(-45deg,rgba(0,0,0,.15) 25%,transparent 25%,transparent 50%,rgba(0,0,0,.15) 50%,rgba(0,0,0,.15) 75%,transparent 75%,transparent);color:transparent}.plyr--video.plyr--loading .plyr__progress--buffer{background-color:rgba(255,255,255,.25)}.plyr--audio.plyr--loading .plyr__progress--buffer{background-color:rgba(198,214,219,.66)}.plyr__time{display:inline-block;vertical-align:middle;font-size:14px}.plyr__time+.plyr__time{display:none}@media (min-width:768px){.plyr__time+.plyr__time{display:inline-block}}.plyr__time+.plyr__time::before{content:'\2044';margin-right:10px}.plyr__volume{display:none}.plyr .plyr__volume{-webkit-box-flex:1;-ms-flex:1;flex:1;position:relative}.plyr .plyr__volume input[type=range]{position:relative;z-index:2}@media (min-width:480px){.plyr .plyr__volume{display:block;max-width:60px}}@media (min-width:768px){.plyr .plyr__volume{max-width:100px}}.plyr--is-ios .plyr__volume,.plyr--is-ios [data-plyr=mute]{display:none!important}.plyr--fullscreen-active{height:100%;width:100%;background:#000;border-radius:0!important}.plyr--fullscreen-active video{height:100%}.plyr--fullscreen-active .plyr__video-wrapper{height:100%;width:100%}.plyr--fullscreen-active .plyr__video-embed{overflow:visible}.plyr--fullscreen-active.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.plyr--fullscreen-fallback.plyr--fullscreen-active{position:fixed;top:0;left:0;right:0;bottom:0;z-index:10000000}
\ No newline at end of file +@-webkit-keyframes plyr-progress{to{background-position:25px 0}}@keyframes plyr-progress{to{background-position:25px 0}}@-webkit-keyframes plyr-popup{0%{opacity:.5;-webkit-transform:translateY(10px);transform:translateY(10px)}to{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes plyr-popup{0%{opacity:.5;-webkit-transform:translateY(10px);transform:translateY(10px)}to{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes plyr-fade-in{from{opacity:0}to{opacity:1}}@keyframes plyr-fade-in{from{opacity:0}to{opacity:1}}.plyr{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;direction:ltr;font-family:Avenir,"Avenir Next","Helvetica Neue","Segoe UI",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.7;max-width:100%;min-width:200px;position:relative;text-shadow:none;transition:box-shadow .3s ease}.plyr audio,.plyr video{border-radius:inherit;height:auto;vertical-align:middle;width:100%}.plyr:focus{outline:0}.plyr--full-ui{box-sizing:border-box}.plyr--full-ui *,.plyr--full-ui ::after,.plyr--full-ui ::before{box-sizing:inherit}.plyr--full-ui a,.plyr--full-ui button,.plyr--full-ui input,.plyr--full-ui label{touch-action:manipulation}.plyr__badge{background:#4f5b5f;border-radius:2px;color:rgba(255,255,255,.9);font-size:9px;line-height:1;padding:3px 4px}.plyr--full-ui ::-webkit-media-text-track-container{display:none}.plyr__captions{-webkit-animation:plyr-fade-in .3s ease;animation:plyr-fade-in .3s ease;bottom:0;color:#fff;display:none;font-size:14px;left:0;padding:10px;position:absolute;text-align:center;-webkit-transform:translateY(-40px);transform:translateY(-40px);transition:-webkit-transform .4s ease-in-out;transition:transform .4s ease-in-out;transition:transform .4s ease-in-out,-webkit-transform .4s ease-in-out;width:100%}.plyr__captions span{background:rgba(0,0,0,.8);border-radius:2px;-webkit-box-decoration-break:clone;box-decoration-break:clone;line-height:185%;padding:.2em .5em;white-space:pre-wrap}.plyr__captions span div{display:inline}.plyr__captions span:empty{display:none}@media (min-width:480px){.plyr__captions{font-size:16px;padding:20px}}@media (min-width:768px){.plyr__captions{font-size:18px}}.plyr--captions-active .plyr__captions{display:block}.plyr--hide-controls .plyr__captions{-webkit-transform:translateY(-15px);transform:translateY(-15px)}.plyr__control{background:0 0;border:0;border-radius:3px;color:inherit;cursor:pointer;flex-shrink:0;overflow:visible;padding:7px;position:relative;transition:all .3s ease}.plyr__control svg{display:block;fill:currentColor;height:18px;pointer-events:none;width:18px}.plyr__control:focus{outline:0}.plyr__control.plyr__tab-focus{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr__control[aria-pressed=false] .icon--pressed,.plyr__control[aria-pressed=false] .label--pressed,.plyr__control[aria-pressed=true] .icon--not-pressed,.plyr__control[aria-pressed=true] .label--not-pressed{display:none}.plyr--audio .plyr__control.plyr__tab-focus,.plyr--audio .plyr__control:hover,.plyr--audio .plyr__control[aria-expanded=true]{background:#1aafff;color:#fff}.plyr__control--overlaid{background:rgba(26,175,255,.8);border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15);color:#fff;display:none;left:50%;padding:15px;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);z-index:2}.plyr__control--overlaid svg{height:20px;left:2px;position:relative;width:20px}.plyr__control--overlaid:focus,.plyr__control--overlaid:hover{background:#1aafff}.plyr--playing .plyr__control--overlaid{opacity:0;visibility:hidden}.plyr--full-ui.plyr--video .plyr__control--overlaid{display:block}.plyr--full-ui ::-webkit-media-controls{display:none}.plyr__controls{-webkit-box-align:center;align-items:center;display:-webkit-box;display:flex;text-align:center}.plyr__controls .plyr__menu,.plyr__controls .plyr__progress,.plyr__controls .plyr__time,.plyr__controls>.plyr__control{margin-left:5px}.plyr__controls .plyr__menu:first-child,.plyr__controls .plyr__menu:first-child+[data-plyr=pause],.plyr__controls .plyr__progress:first-child,.plyr__controls .plyr__progress:first-child+[data-plyr=pause],.plyr__controls .plyr__time:first-child,.plyr__controls .plyr__time:first-child+[data-plyr=pause],.plyr__controls>.plyr__control:first-child,.plyr__controls>.plyr__control:first-child+[data-plyr=pause]{margin-left:0}.plyr__controls .plyr__volume{margin-left:5px}@media (min-width:480px){.plyr__controls .plyr__menu,.plyr__controls .plyr__progress,.plyr__controls .plyr__time,.plyr__controls>.plyr__control{margin-left:10px}.plyr__controls .plyr__menu+.plyr__control,.plyr__controls>.plyr__control+.plyr__control,.plyr__controls>.plyr__control+.plyr__menu{margin-left:5px}}.plyr--video .plyr__controls{background:linear-gradient(transparent,rgba(0,0,0,.7));border-bottom-left-radius:inherit;border-bottom-right-radius:inherit;bottom:0;color:#fff;left:0;padding:35px 10px 10px;position:absolute;right:0;transition:opacity .4s ease-in-out,-webkit-transform .4s ease-in-out;transition:opacity .4s ease-in-out,transform .4s ease-in-out;transition:opacity .4s ease-in-out,transform .4s ease-in-out,-webkit-transform .4s ease-in-out;z-index:2}.plyr--video .plyr__controls .plyr__control svg{-webkit-filter:drop-shadow(0 1px 1px rgba(0, 0, 0, .15));filter:drop-shadow(0 1px 1px rgba(0, 0, 0, .15))}.plyr--video .plyr__controls .plyr__control.plyr__tab-focus,.plyr--video .plyr__controls .plyr__control:hover,.plyr--video .plyr__controls .plyr__control[aria-expanded=true]{background:#1aafff;color:#fff}.plyr--audio .plyr__controls{background:#fff;border-radius:inherit;color:#4f5b5f;padding:10px}.plyr--video.plyr--hide-controls .plyr__controls{opacity:0;pointer-events:none;-webkit-transform:translateY(100%);transform:translateY(100%)}.plyr [data-plyr=airplay],.plyr [data-plyr=captions],.plyr [data-plyr=fullscreen],.plyr [data-plyr=pip]{display:none}.plyr--airplay-supported [data-plyr=airplay],.plyr--captions-enabled [data-plyr=captions],.plyr--fullscreen-enabled [data-plyr=fullscreen],.plyr--pip-supported [data-plyr=pip]{display:inline-block}.plyr__video-embed{height:0;padding-bottom:56.25%}.plyr__video-embed iframe{border:0;height:100%;left:0;position:absolute;top:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.plyr__video-embed>div{padding-bottom:200%;position:relative;-webkit-transform:translateY(-35.9375%);transform:translateY(-35.9375%)}.plyr--full-ui .plyr__video-embed iframe{pointer-events:none}.plyr__menu{display:-webkit-box;display:flex;position:relative}.plyr__menu .plyr__control svg{transition:-webkit-transform .3s ease;transition:transform .3s ease;transition:transform .3s ease,-webkit-transform .3s ease}.plyr__menu .plyr__control[aria-expanded=true] svg{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.plyr__menu .plyr__control[aria-expanded=true] .plyr__tooltip{display:none}.plyr__menu__container{-webkit-animation:plyr-popup .2s ease;animation:plyr-popup .2s ease;background:rgba(255,255,255,.9);border-radius:4px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);color:#4f5b5f;font-size:16px;margin-bottom:10px;position:absolute;right:-3px;text-align:left;white-space:nowrap;z-index:1}.plyr__menu__container>div{overflow:hidden;transition:height .35s cubic-bezier(.4,0,.2,1),width .35s cubic-bezier(.4,0,.2,1)}.plyr__menu__container::after{border:4px solid transparent;border-top-color:rgba(255,255,255,.9);content:'';height:0;position:absolute;right:15px;top:100%;width:0}.plyr__menu__container ul{list-style:none;margin:0;overflow:hidden;padding:7px}.plyr__menu__container .plyr__control{-webkit-box-align:center;align-items:center;color:#4f5b5f;display:-webkit-box;display:flex;padding:4px 14px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.plyr__menu__container .plyr__control::after{border:4px solid transparent;content:'';position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);transition:border-color .2s ease}.plyr__menu__container .plyr__control--forward{padding-right:28px}.plyr__menu__container .plyr__control--forward::after{border-left-color:rgba(79,91,95,.8);right:5px}.plyr__menu__container .plyr__control--forward.plyr__tab-focus::after,.plyr__menu__container .plyr__control--forward:hover::after{border-left-color:currentColor}.plyr__menu__container .plyr__control--back{font-weight:500;margin:7px;margin-bottom:3px;padding-left:28px;position:relative;width:calc(100% - 14px)}.plyr__menu__container .plyr__control--back::after{border-right-color:rgba(79,91,95,.8);left:7px}.plyr__menu__container .plyr__control--back::before{background:#b7c5cd;box-shadow:0 1px 0 #fff;content:'';height:1px;left:0;margin-top:4px;overflow:hidden;position:absolute;right:0;top:100%}.plyr__menu__container .plyr__control--back.plyr__tab-focus::after,.plyr__menu__container .plyr__control--back:hover::after{border-right-color:currentColor}.plyr__menu__container label.plyr__control{padding-left:7px}.plyr__menu__container label.plyr__control input[type=radio]+span{background:rgba(0,0,0,.1);border-radius:100%;display:block;flex-shrink:0;height:16px;margin-right:10px;position:relative;transition:all .3s ease;width:16px}.plyr__menu__container label.plyr__control input[type=radio]+span::after{background:#fff;border-radius:100%;content:'';height:6px;left:5px;opacity:0;position:absolute;top:5px;-webkit-transform:scale(0);transform:scale(0);transition:opacity .3s ease,-webkit-transform .3s ease;transition:transform .3s ease,opacity .3s ease;transition:transform .3s ease,opacity .3s ease,-webkit-transform .3s ease;width:6px}.plyr__menu__container label.plyr__control input[type=radio]:checked+span{background:#1aafff}.plyr__menu__container label.plyr__control input[type=radio]:checked+span::after{opacity:1;-webkit-transform:scale(1);transform:scale(1)}.plyr__menu__container label.plyr__control input[type=radio]:focus+span{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr__menu__container label.plyr__control.plyr__tab-focus input[type=radio]+span,.plyr__menu__container label.plyr__control:hover input[type=radio]+span{background:rgba(0,0,0,.1)}.plyr__menu__container .plyr__menu__value{-webkit-box-align:center;align-items:center;display:-webkit-box;display:flex;margin-left:auto;margin-right:-7px;overflow:hidden;padding-left:25px;pointer-events:none}.plyr__progress{display:-webkit-box;display:flex;-webkit-box-flex:1;flex:1;position:relative}.plyr__progress input[type=range]{position:relative;z-index:2}.plyr__progress .plyr__tooltip{font-size:14px;left:0}.plyr__progress--buffer{-webkit-appearance:none;background:0 0;border:0;border-radius:100px;height:6px;left:0;margin:-3px 0 0;padding:0;position:absolute;top:50%;width:100%}.plyr__progress--buffer::-webkit-progress-bar{background:0 0;transition:width .2s ease}.plyr__progress--buffer::-webkit-progress-value{background:currentColor;border-radius:100px;min-width:6px}.plyr__progress--buffer::-moz-progress-bar{background:currentColor;border-radius:100px;min-width:6px;transition:width .2s ease}.plyr__progress--buffer::-ms-fill{border-radius:100px;transition:width .2s ease}.plyr--video .plyr__progress--buffer{box-shadow:0 1px 1px rgba(0,0,0,.15);color:rgba(255,255,255,.25)}.plyr--audio .plyr__progress--buffer{color:rgba(183,197,205,.66)}.plyr--loading .plyr__progress--buffer{-webkit-animation:plyr-progress 1s linear infinite;animation:plyr-progress 1s linear infinite;background-image:linear-gradient(-45deg,rgba(47,52,61,.6) 25%,transparent 25%,transparent 50%,rgba(47,52,61,.6) 50%,rgba(47,52,61,.6) 75%,transparent 75%,transparent);background-repeat:repeat-x;background-size:25px 25px;color:transparent}.plyr--video.plyr--loading .plyr__progress--buffer{background-color:rgba(255,255,255,.25)}.plyr--audio.plyr--loading .plyr__progress--buffer{background-color:rgba(183,197,205,.66)}.plyr--full-ui input[type=range]{-webkit-appearance:none;background:0 0;border:0;border-radius:28px;color:#1aafff;cursor:pointer;display:block;height:20px;margin:0;padding:0;transition:box-shadow .3s ease;width:100%}.plyr--full-ui input[type=range]::-webkit-slider-runnable-track{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-webkit-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-webkit-slider-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);box-sizing:border-box;height:14px;position:relative;transition:all .2s ease;width:14px;-webkit-appearance:none;margin-top:-4px}.plyr--full-ui input[type=range]::-moz-range-track{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-moz-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-moz-range-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);box-sizing:border-box;height:14px;position:relative;transition:all .2s ease;width:14px}.plyr--full-ui input[type=range]::-moz-range-progress{background:currentColor;border-radius:3px;height:6px}.plyr--full-ui input[type=range]::-ms-track{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-ms-user-select:none;user-select:none;color:transparent}.plyr--full-ui input[type=range]::-ms-fill-upper{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-ms-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-ms-fill-lower{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-ms-user-select:none;user-select:none;background:currentColor}.plyr--full-ui input[type=range]::-ms-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);box-sizing:border-box;height:14px;position:relative;transition:all .2s ease;width:14px;margin-top:0}.plyr--full-ui input[type=range]::-ms-tooltip{display:none}.plyr--full-ui input[type=range]:focus{outline:0}.plyr--full-ui input[type=range]::-moz-focus-outer{border:0}.plyr--full-ui input[type=range].plyr__tab-focus::-webkit-slider-runnable-track{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr--full-ui input[type=range].plyr__tab-focus::-moz-range-track{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr--full-ui input[type=range].plyr__tab-focus::-ms-track{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr--full-ui input[type=range]:active::-webkit-slider-thumb{box-shadow:0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui input[type=range]:active::-moz-range-thumb{box-shadow:0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui input[type=range]:active::-ms-thumb{box-shadow:0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui.plyr--video input[type=range]::-webkit-slider-runnable-track{background:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]::-moz-range-track{background:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]::-ms-track{background:rgba(255,255,255,.25)}.plyr--full-ui.plyr--audio input[type=range]::-webkit-slider-runnable-track{background:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]::-moz-range-track{background:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]::-ms-track{background:rgba(183,197,205,.66)}.plyr__time{font-size:14px}.plyr__time+.plyr__time::before{content:'\2044';margin-right:10px}@media (max-width:767px){.plyr__time+.plyr__time{display:none}}.plyr--video .plyr__time{text-shadow:0 1px 1px rgba(0,0,0,.15)}.plyr__tooltip{background:rgba(255,255,255,.9);border-radius:3px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);color:#4f5b5f;font-size:14px;font-weight:500;line-height:1.3;margin-bottom:10px;opacity:0;padding:5px 7.5px;pointer-events:none;position:absolute;-webkit-transform:translate(-50%,10px) scale(.8);transform:translate(-50%,10px) scale(.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;transition:opacity .2s .1s ease,-webkit-transform .2s .1s ease;transition:transform .2s .1s ease,opacity .2s .1s ease;transition:transform .2s .1s ease,opacity .2s .1s ease,-webkit-transform .2s .1s ease;z-index:2}.plyr__tooltip::before{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(255,255,255,.9);bottom:-4px;content:'';height:0;left:50%;position:absolute;-webkit-transform:translateX(-50%);transform:translateX(-50%);width:0;z-index:2}.plyr .plyr__control.plyr__tab-focus .plyr__tooltip,.plyr .plyr__control:hover .plyr__tooltip,.plyr__tooltip--visible{opacity:1;-webkit-transform:translate(-50%,0) scale(1);transform:translate(-50%,0) scale(1)}.plyr .plyr__control:hover .plyr__tooltip{z-index:3}.plyr__controls>.plyr__control:first-child .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip{left:0;-webkit-transform:translate(0,10px) scale(.8);transform:translate(0,10px) scale(.8);-webkit-transform-origin:0 100%;transform-origin:0 100%}.plyr__controls>.plyr__control:first-child .plyr__tooltip::before,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip::before{left:16px}.plyr__controls>.plyr__control:last-child .plyr__tooltip{right:0;-webkit-transform:translate(0,10px) scale(.8);transform:translate(0,10px) scale(.8);-webkit-transform-origin:100% 100%;transform-origin:100% 100%}.plyr__controls>.plyr__control:last-child .plyr__tooltip::before{left:auto;right:16px;-webkit-transform:translateX(50%);transform:translateX(50%)}.plyr__controls>.plyr__control:first-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control:hover .plyr__tooltip,.plyr__controls>.plyr__control:first-child.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:first-child:hover .plyr__tooltip,.plyr__controls>.plyr__control:last-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:last-child.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:last-child:hover .plyr__tooltip{-webkit-transform:translate(0,0) scale(1);transform:translate(0,0) scale(1)}.plyr--video{overflow:hidden}.plyr--video.plyr--menu-open{overflow:visible}.plyr__video-wrapper{background:#000;border-radius:inherit;overflow:hidden;position:relative;z-index:0}.plyr__volume{-webkit-box-flex:1;flex:1;position:relative}.plyr__volume input[type=range]{position:relative;z-index:2}@media (min-width:480px){.plyr__volume{max-width:50px}}@media (min-width:768px){.plyr__volume{max-width:80px}}.plyr--is-ios .plyr__volume,.plyr--is-ios [data-plyr=mute]{display:none!important}.plyr--has-error{pointer-events:none}.plyr--has-error::after{-webkit-box-align:center;align-items:center;background:#000;color:#fff;content:attr(data-plyr-error);display:-webkit-box;display:flex;font-size:16px;height:100%;-webkit-box-pack:center;justify-content:center;left:0;position:absolute;text-align:center;text-shadow:0 1px 1px #000;top:0;width:100%;z-index:10}.plyr:-webkit-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-moz-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-ms-fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-webkit-full-screen video{height:100%}.plyr:-moz-full-screen video{height:100%}.plyr:-ms-fullscreen video{height:100%}.plyr:fullscreen video{height:100%}.plyr:-webkit-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-moz-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-ms-fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:-webkit-full-screen .plyr__video-embed{overflow:visible}.plyr:-moz-full-screen .plyr__video-embed{overflow:visible}.plyr:-ms-fullscreen .plyr__video-embed{overflow:visible}.plyr:fullscreen .plyr__video-embed{overflow:visible}.plyr:-webkit-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.plyr:-moz-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-ms-fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}@media (min-width:1024px){.plyr:-webkit-full-screen .plyr__captions{font-size:21px}.plyr:-moz-full-screen .plyr__captions{font-size:21px}.plyr:-ms-fullscreen .plyr__captions{font-size:21px}.plyr:fullscreen .plyr__captions{font-size:21px}}.plyr:-webkit-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-webkit-full-screen video{height:100%}.plyr:-webkit-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-webkit-full-screen .plyr__video-embed{overflow:visible}.plyr:-webkit-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}@media (min-width:1024px){.plyr:-webkit-full-screen .plyr__captions{font-size:21px}}.plyr:-moz-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-moz-full-screen video{height:100%}.plyr:-moz-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-moz-full-screen .plyr__video-embed{overflow:visible}.plyr:-moz-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}@media (min-width:1024px){.plyr:-moz-full-screen .plyr__captions{font-size:21px}}.plyr:-ms-fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-ms-fullscreen video{height:100%}.plyr:-ms-fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:-ms-fullscreen .plyr__video-embed{overflow:visible}.plyr:-ms-fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}@media (min-width:1024px){.plyr:-ms-fullscreen .plyr__captions{font-size:21px}}.plyr--fullscreen-fallback{background:#000;border-radius:0!important;height:100%;margin:0;width:100%;bottom:0;left:0;position:fixed;right:0;top:0;z-index:10000000}.plyr--fullscreen-fallback video{height:100%}.plyr--fullscreen-fallback .plyr__video-wrapper{height:100%;width:100%}.plyr--fullscreen-fallback .plyr__video-embed{overflow:visible}.plyr--fullscreen-fallback.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen{display:block}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen+svg{display:none}@media (min-width:1024px){.plyr--fullscreen-fallback .plyr__captions{font-size:21px}}.plyr--no-transition{transition:none!important}.plyr--full-ui [hidden]{display:none}.plyr--full-ui [aria-hidden=true]{display:none}.plyr__sr-only{clip:rect(1px,1px,1px,1px);overflow:hidden;border:0!important;height:1px!important;padding:0!important;position:absolute!important;width:1px!important}
\ No newline at end of file diff --git a/dist/plyr.js b/dist/plyr.js index c01ce978..0f444b16 100644 --- a/dist/plyr.js +++ b/dist/plyr.js @@ -1 +1,3 @@ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=t(e,document):"function"==typeof define&&define.amd?define([],function(){return t(e,document)}):e.plyr=t(e,document)}("undefined"!=typeof window?window:this,function(e,t){"use strict";function n(){var e,n,r,a=navigator.userAgent,s=navigator.appName,o=""+parseFloat(navigator.appVersion),i=parseInt(navigator.appVersion,10),l=!1,u=!1,c=!1,d=!1;return-1!==navigator.appVersion.indexOf("Windows NT")&&-1!==navigator.appVersion.indexOf("rv:11")?(l=!0,s="IE",o="11"):-1!==(n=a.indexOf("MSIE"))?(l=!0,s="IE",o=a.substring(n+5)):-1!==(n=a.indexOf("Chrome"))?(c=!0,s="Chrome",o=a.substring(n+7)):-1!==(n=a.indexOf("Safari"))?(d=!0,s="Safari",o=a.substring(n+7),-1!==(n=a.indexOf("Version"))&&(o=a.substring(n+8))):-1!==(n=a.indexOf("Firefox"))?(u=!0,s="Firefox",o=a.substring(n+8)):(e=a.lastIndexOf(" ")+1)<(n=a.lastIndexOf("/"))&&(s=a.substring(e,n),o=a.substring(n+1),s.toLowerCase()===s.toUpperCase()&&(s=navigator.appName)),-1!==(r=o.indexOf(";"))&&(o=o.substring(0,r)),-1!==(r=o.indexOf(" "))&&(o=o.substring(0,r)),i=parseInt(""+o,10),isNaN(i)&&(o=""+parseFloat(navigator.appVersion),i=parseInt(navigator.appVersion,10)),{name:s,version:i,isIE:l,isFirefox:u,isChrome:c,isSafari:d,isIos:/(iPad|iPhone|iPod)/g.test(navigator.platform),isIphone:/(iPhone|iPod)/g.test(navigator.userAgent),isTouch:"ontouchstart"in t.documentElement}}function r(e,t){var n=e.media;if("video"===e.type)switch(t){case"video/webm":return!(!n.canPlayType||!n.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/,""));case"video/mp4":return!(!n.canPlayType||!n.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/,""));case"video/ogg":return!(!n.canPlayType||!n.canPlayType('video/ogg; codecs="theora"').replace(/no/,""))}else if("audio"===e.type)switch(t){case"audio/mpeg":return!(!n.canPlayType||!n.canPlayType("audio/mpeg;").replace(/no/,""));case"audio/ogg":return!(!n.canPlayType||!n.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/,""));case"audio/wav":return!(!n.canPlayType||!n.canPlayType('audio/wav; codecs="1"').replace(/no/,""))}return!1}function a(e){if(!t.querySelectorAll('script[src="'+e+'"]').length){var n=t.createElement("script");n.src=e;var r=t.getElementsByTagName("script")[0];r.parentNode.insertBefore(n,r)}}function s(e,t){return Array.prototype.indexOf&&-1!==e.indexOf(t)}function o(e,t,n){return e.replace(new RegExp(t.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g,"\\$1"),"g"),n)}function i(e,t){e.length||(e=[e]);for(var n=e.length-1;n>=0;n--){var r=n>0?t.cloneNode(!0):t,a=e[n],s=a.parentNode,o=a.nextSibling;return r.appendChild(a),o?s.insertBefore(r,o):s.appendChild(r),r}}function l(e){e&&e.parentNode.removeChild(e)}function u(e,t){e.insertBefore(t,e.firstChild)}function c(e,t){for(var n in t)e.setAttribute(n,O.boolean(t[n])&&t[n]?"":t[n])}function d(e,n,r){var a=t.createElement(e);c(a,r),u(n,a)}function p(e){return e.replace(".","")}function m(e,t,n){if(e)if(e.classList)e.classList[n?"add":"remove"](t);else{var r=(" "+e.className+" ").replace(/\s+/g," ").replace(" "+t+" ","");e.className=r+(n?" "+t:"")}}function f(e,t){return!!e&&(e.classList?e.classList.contains(t):new RegExp("(\\s|^)"+t+"(\\s|$)").test(e.className))}function y(e,n){var r=Element.prototype;return(r.matches||r.webkitMatchesSelector||r.mozMatchesSelector||r.msMatchesSelector||function(e){return-1!==[].indexOf.call(t.querySelectorAll(e),this)}).call(e,n)}function b(e,t,n,r,a){n&&g(e,t,function(t){n.apply(e,[t])},a),g(e,t,function(t){r.apply(e,[t])},a)}function v(e,t,n,r,a){var s=t.split(" ");if(O.boolean(a)||(a=!1),e instanceof NodeList)for(var o=0;o<e.length;o++)e[o]instanceof Node&&v(e[o],arguments[1],arguments[2],arguments[3]);else for(var i=0;i<s.length;i++)e[r?"addEventListener":"removeEventListener"](s[i],n,a)}function g(e,t,n,r){e&&v(e,t,n,!0,r)}function h(e,t,n,r){e&&v(e,t,n,!1,r)}function k(e,t,n,r){if(e&&t){O.boolean(n)||(n=!1);var a=new CustomEvent(t,{bubbles:n,detail:r});e.dispatchEvent(a)}}function w(e,t){if(e)return t=O.boolean(t)?t:!e.getAttribute("aria-pressed"),e.setAttribute("aria-pressed",t),t}function x(e,t){return 0===e||0===t||isNaN(e)||isNaN(t)?0:(e/t*100).toFixed(2)}function T(){var e=arguments;if(e.length){if(1===e.length)return e[0];for(var t=Array.prototype.shift.call(e),n=e.length,r=0;r<n;r++){var a=e[r];for(var s in a)a[s]&&a[s].constructor&&a[s].constructor===Object?(t[s]=t[s]||{},T(t[s],a[s])):t[s]=a[s]}return t}}function S(e){return e.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/)?RegExp.$2:e}function E(e){return e.match(/^.*(vimeo.com\/|video\/)(\d+).*/)?RegExp.$2:e}function _(){var e={supportsFullScreen:!1,isFullScreen:function(){return!1},requestFullScreen:function(){},cancelFullScreen:function(){},fullScreenEventName:"",element:null,prefix:""},n="webkit o moz ms khtml".split(" ");if(O.undefined(t.cancelFullScreen))for(var r=0,a=n.length;r<a;r++){if(e.prefix=n[r],!O.undefined(t[e.prefix+"CancelFullScreen"])){e.supportsFullScreen=!0;break}if(!O.undefined(t.msExitFullscreen)&&t.msFullscreenEnabled){e.prefix="ms",e.supportsFullScreen=!0;break}}else e.supportsFullScreen=!0;return e.supportsFullScreen&&(e.fullScreenEventName="ms"===e.prefix?"MSFullscreenChange":e.prefix+"fullscreenchange",e.isFullScreen=function(e){switch(O.undefined(e)&&(e=t.body),this.prefix){case"":return t.fullscreenElement===e;case"moz":return t.mozFullScreenElement===e;default:return t[this.prefix+"FullscreenElement"]===e}},e.requestFullScreen=function(e){return O.undefined(e)&&(e=t.body),""===this.prefix?e.requestFullScreen():e[this.prefix+("ms"===this.prefix?"RequestFullscreen":"RequestFullScreen")]()},e.cancelFullScreen=function(){return""===this.prefix?t.cancelFullScreen():t[this.prefix+("ms"===this.prefix?"ExitFullscreen":"CancelFullScreen")]()},e.element=function(){return""===this.prefix?t.fullscreenElement:t[this.prefix+"FullscreenElement"]}),e}function C(v,C){function j(e,t,n,r){k(e,t,n,T({},r,{plyr:We}))}function R(t,n){C.debug&&e.console&&(n=Array.prototype.slice.call(n),O.string(C.logPrefix)&&C.logPrefix.length&&n.unshift(C.logPrefix),console[t].apply(console,n))}function V(){return{url:C.iconUrl,absolute:0===C.iconUrl.indexOf("http")||Ye.browser.isIE&&!e.svg4everybody}}function q(){var e=[],t=V(),n=(t.absolute?"":t.url)+"#"+C.iconPrefix;return s(C.controls,"play-large")&&e.push('<button type="button" data-plyr="play" class="plyr__play-large">','<svg><use xlink:href="'+n+'-play" /></svg>','<span class="plyr__sr-only">'+C.i18n.play+"</span>","</button>"),e.push('<div class="plyr__controls">'),s(C.controls,"restart")&&e.push('<button type="button" data-plyr="restart">','<svg><use xlink:href="'+n+'-restart" /></svg>','<span class="plyr__sr-only">'+C.i18n.restart+"</span>","</button>"),s(C.controls,"rewind")&&e.push('<button type="button" data-plyr="rewind">','<svg><use xlink:href="'+n+'-rewind" /></svg>','<span class="plyr__sr-only">'+C.i18n.rewind+"</span>","</button>"),s(C.controls,"play")&&e.push('<button type="button" data-plyr="play">','<svg><use xlink:href="'+n+'-play" /></svg>','<span class="plyr__sr-only">'+C.i18n.play+"</span>","</button>",'<button type="button" data-plyr="pause">','<svg><use xlink:href="'+n+'-pause" /></svg>','<span class="plyr__sr-only">'+C.i18n.pause+"</span>","</button>"),s(C.controls,"fast-forward")&&e.push('<button type="button" data-plyr="fast-forward">','<svg><use xlink:href="'+n+'-fast-forward" /></svg>','<span class="plyr__sr-only">'+C.i18n.forward+"</span>","</button>"),s(C.controls,"progress")&&(e.push('<span class="plyr__progress">','<label for="seek{id}" class="plyr__sr-only">Seek</label>','<input id="seek{id}" class="plyr__progress--seek" type="range" min="0" max="100" step="0.1" value="0" data-plyr="seek">','<progress class="plyr__progress--played" max="100" value="0" role="presentation"></progress>','<progress class="plyr__progress--buffer" max="100" value="0">',"<span>0</span>% "+C.i18n.buffered,"</progress>"),C.tooltips.seek&&e.push('<span class="plyr__tooltip">00:00</span>'),e.push("</span>")),s(C.controls,"current-time")&&e.push('<span class="plyr__time">','<span class="plyr__sr-only">'+C.i18n.currentTime+"</span>",'<span class="plyr__time--current">00:00</span>',"</span>"),s(C.controls,"duration")&&e.push('<span class="plyr__time">','<span class="plyr__sr-only">'+C.i18n.duration+"</span>",'<span class="plyr__time--duration">00:00</span>',"</span>"),s(C.controls,"mute")&&e.push('<button type="button" data-plyr="mute">','<svg class="icon--muted"><use xlink:href="'+n+'-muted" /></svg>','<svg><use xlink:href="'+n+'-volume" /></svg>','<span class="plyr__sr-only">'+C.i18n.toggleMute+"</span>","</button>"),s(C.controls,"volume")&&e.push('<span class="plyr__volume">','<label for="volume{id}" class="plyr__sr-only">'+C.i18n.volume+"</label>",'<input id="volume{id}" class="plyr__volume--input" type="range" min="'+C.volumeMin+'" max="'+C.volumeMax+'" value="'+C.volume+'" data-plyr="volume">','<progress class="plyr__volume--display" max="'+C.volumeMax+'" value="'+C.volumeMin+'" role="presentation"></progress>',"</span>"),s(C.controls,"captions")&&e.push('<button type="button" data-plyr="captions">','<svg class="icon--captions-on"><use xlink:href="'+n+'-captions-on" /></svg>','<svg><use xlink:href="'+n+'-captions-off" /></svg>','<span class="plyr__sr-only">'+C.i18n.toggleCaptions+"</span>","</button>"),s(C.controls,"fullscreen")&&e.push('<button type="button" data-plyr="fullscreen">','<svg class="icon--exit-fullscreen"><use xlink:href="'+n+'-exit-fullscreen" /></svg>','<svg><use xlink:href="'+n+'-enter-fullscreen" /></svg>','<span class="plyr__sr-only">'+C.i18n.toggleFullscreen+"</span>","</button>"),e.push("</div>"),e.join("")}function D(){if(Ye.supported.full&&("audio"!==Ye.type||C.fullscreen.allowAudio)&&C.fullscreen.enabled){var e=N.supportsFullScreen;e||C.fullscreen.fallback&&!$()?($e((e?"Native":"Fallback")+" fullscreen enabled"),e||m(Ye.container,C.classes.fullscreen.fallback,!0),m(Ye.container,C.classes.fullscreen.enabled,!0)):$e("Fullscreen not supported and fallback disabled"),Ye.buttons&&Ye.buttons.fullscreen&&w(Ye.buttons.fullscreen,!1),J()}}function H(){if("video"===Ye.type){X(C.selectors.captions)||Ye.videoContainer.insertAdjacentHTML("afterbegin",'<div class="'+p(C.selectors.captions)+'"></div>'),Ye.usingTextTracks=!1,Ye.media.textTracks&&(Ye.usingTextTracks=!0);for(var e,t="",n=Ye.media.childNodes,r=0;r<n.length;r++)"track"===n[r].nodeName.toLowerCase()&&("captions"!==(e=n[r].kind)&&"subtitles"!==e||(t=n[r].getAttribute("src")));if(Ye.captionExists=!0,""===t?(Ye.captionExists=!1,$e("No caption track found")):$e("Caption track found; URI: "+t),Ye.captionExists){for(var a=Ye.media.textTracks,s=0;s<a.length;s++)a[s].mode="hidden";if(Y(),(Ye.browser.isIE&&Ye.browser.version>=10||Ye.browser.isFirefox&&Ye.browser.version>=31)&&($e("Detected browser with known TextTrack issues - using manual fallback"),Ye.usingTextTracks=!1),Ye.usingTextTracks){$e("TextTracks supported");for(var o=0;o<a.length;o++){var i=a[o];"captions"!==i.kind&&"subtitles"!==i.kind||g(i,"cuechange",function(){this.activeCues[0]&&"text"in this.activeCues[0]?U(this.activeCues[0].getCueAsHTML()):U()})}}else if($e("TextTracks not supported so rendering captions manually"),Ye.currentCaption="",Ye.captions=[],""!==t){var l=new XMLHttpRequest;l.onreadystatechange=function(){if(4===l.readyState)if(200===l.status){var e,t=[],n=l.responseText,r="\r\n";-1===n.indexOf(r+r)&&(r=-1!==n.indexOf("\r\r")?"\r":"\n"),t=n.split(r+r);for(var a=0;a<t.length;a++){e=t[a],Ye.captions[a]=[];var s=e.split(r),o=0;-1===s[o].indexOf(":")&&(o=1),Ye.captions[a]=[s[o],s[o+1]]}Ye.captions.shift(),$e("Successfully loaded the caption file via AJAX")}else Je(C.logPrefix+"There was a problem loading the caption file via AJAX")},l.open("get",t,!0),l.send()}}else m(Ye.container,C.classes.captions.enabled)}}function U(e){var n=X(C.selectors.captions),r=t.createElement("span");n.innerHTML="",O.undefined(e)&&(e=""),O.string(e)?r.innerHTML=e.trim():r.appendChild(e),n.appendChild(r);n.offsetHeight}function W(e){function t(e,t){var n=[];n=e.split(" --\x3e ");for(var a=0;a<n.length;a++)n[a]=n[a].replace(/(\d+:\d+:\d+\.\d+).*/,"$1");return r(n[t])}function n(e){return t(e,1)}function r(e){if(null===e||void 0===e)return 0;var t=[],n=[];return t=e.split(","),n=t[0].split(":"),Math.floor(60*n[0]*60)+Math.floor(60*n[1])+Math.floor(n[2])}if(!Ye.usingTextTracks&&"video"===Ye.type&&Ye.supported.full&&(Ye.subcount=0,e=O.number(e)?e:Ye.media.currentTime,Ye.captions[Ye.subcount])){for(;n(Ye.captions[Ye.subcount][0])<e.toFixed(1);)if(Ye.subcount++,Ye.subcount>Ye.captions.length-1){Ye.subcount=Ye.captions.length-1;break}Ye.media.currentTime.toFixed(1)>=function(e){return t(e,0)}(Ye.captions[Ye.subcount][0])&&Ye.media.currentTime.toFixed(1)<=n(Ye.captions[Ye.subcount][0])?(Ye.currentCaption=Ye.captions[Ye.subcount][1],U(Ye.currentCaption)):U()}}function Y(){if(Ye.buttons.captions){m(Ye.container,C.classes.captions.enabled,!0);var e=Ye.storage.captionsEnabled;O.boolean(e)||(e=C.captions.defaultActive),e&&(m(Ye.container,C.classes.captions.active,!0),w(Ye.buttons.captions,!0))}}function B(e){return Ye.container.querySelectorAll(e)}function X(e){return B(e)[0]}function $(){try{return e.self!==e.top}catch(e){return!0}}function J(){var e=B("input:not([disabled]), button:not([disabled])"),t=e[0],n=e[e.length-1];g(Ye.container,"keydown",function(e){9===e.which&&Ye.isFullscreen&&(e.target!==n||e.shiftKey?e.target===t&&e.shiftKey&&(e.preventDefault(),n.focus()):(e.preventDefault(),t.focus()))})}function z(e,t){if(O.string(t))d(e,Ye.media,{src:t});else if(t.constructor===Array)for(var n=t.length-1;n>=0;n--)d(e,Ye.media,t[n])}function G(){if(C.loadSprite){var e=V();e.absolute?($e("AJAX loading absolute SVG sprite"+(Ye.browser.isIE?" (due to IE)":"")),F(e.url,"sprite-plyr")):$e("Sprite will be used as external resource directly")}var n=C.html;$e("Injecting custom controls"),n||(n=q()),n=o(n=o(n,"{seektime}",C.seekTime),"{id}",Math.floor(1e4*Math.random())),C.title&&(n=o(n,"{title}",C.title));var r;if(O.string(C.selectors.controls.container)&&(r=t.querySelector(C.selectors.controls.container)),O.htmlElement(r)||(r=Ye.container),r.insertAdjacentHTML("beforeend",n),C.tooltips.controls)for(var a=B([C.selectors.controls.wrapper," ",C.selectors.labels," .",C.classes.hidden].join("")),s=a.length-1;s>=0;s--){var i=a[s];m(i,C.classes.hidden,!1),m(i,C.classes.tooltip,!0)}}function K(){try{return Ye.controls=X(C.selectors.controls.wrapper),Ye.buttons={},Ye.buttons.seek=X(C.selectors.buttons.seek),Ye.buttons.play=B(C.selectors.buttons.play),Ye.buttons.pause=X(C.selectors.buttons.pause),Ye.buttons.restart=X(C.selectors.buttons.restart),Ye.buttons.rewind=X(C.selectors.buttons.rewind),Ye.buttons.forward=X(C.selectors.buttons.forward),Ye.buttons.fullscreen=X(C.selectors.buttons.fullscreen),Ye.buttons.mute=X(C.selectors.buttons.mute),Ye.buttons.captions=X(C.selectors.buttons.captions),Ye.progress={},Ye.progress.container=X(C.selectors.progress.container),Ye.progress.buffer={},Ye.progress.buffer.bar=X(C.selectors.progress.buffer),Ye.progress.buffer.text=Ye.progress.buffer.bar&&Ye.progress.buffer.bar.getElementsByTagName("span")[0],Ye.progress.played=X(C.selectors.progress.played),Ye.progress.tooltip=Ye.progress.container&&Ye.progress.container.querySelector("."+C.classes.tooltip),Ye.volume={},Ye.volume.input=X(C.selectors.volume.input),Ye.volume.display=X(C.selectors.volume.display),Ye.duration=X(C.selectors.duration),Ye.currentTime=X(C.selectors.currentTime),Ye.seekTime=B(C.selectors.seekTime),!0}catch(e){return Je("It looks like there is a problem with your controls HTML"),Z(!0),!1}}function Q(){m(Ye.container,C.selectors.container.replace(".",""),Ye.supported.full)}function Z(e){e&&s(C.types.html5,Ye.type)?Ye.media.setAttribute("controls",""):Ye.media.removeAttribute("controls")}function ee(e){var t=C.i18n.play;if(O.string(C.title)&&C.title.length&&(t+=", "+C.title,Ye.container.setAttribute("aria-label",C.title)),Ye.supported.full&&Ye.buttons.play)for(var n=Ye.buttons.play.length-1;n>=0;n--)Ye.buttons.play[n].setAttribute("aria-label",t);O.htmlElement(e)&&e.setAttribute("title",C.i18n.frameTitle.replace("{title}",C.title))}function te(){var t=null;Ye.storage={},L.supported&&C.storage.enabled&&(e.localStorage.removeItem("plyr-volume"),(t=e.localStorage.getItem(C.storage.key))&&(/^\d+(\.\d+)?$/.test(t)?ne({volume:parseFloat(t)}):Ye.storage=JSON.parse(t)))}function ne(t){L.supported&&C.storage.enabled&&(T(Ye.storage,t),e.localStorage.setItem(C.storage.key,JSON.stringify(Ye.storage)))}function re(){if(Ye.media){if(Ye.supported.full&&(m(Ye.container,C.classes.type.replace("{0}",Ye.type),!0),s(C.types.embed,Ye.type)&&m(Ye.container,C.classes.type.replace("{0}","video"),!0),m(Ye.container,C.classes.stopped,C.autoplay),m(Ye.container,C.classes.isIos,Ye.browser.isIos),m(Ye.container,C.classes.isTouch,Ye.browser.isTouch),"video"===Ye.type)){var e=t.createElement("div");e.setAttribute("class",C.classes.videoWrapper),i(Ye.media,e),Ye.videoContainer=e}s(C.types.embed,Ye.type)&&ae()}else Je("No media element found!")}function ae(){var n,r=t.createElement("div"),s=Ye.type+"-"+Math.floor(1e4*Math.random());switch(Ye.type){case"youtube":n=S(Ye.embedId);break;case"vimeo":n=E(Ye.embedId);break;default:n=Ye.embedId}for(var o=B('[id^="'+Ye.type+'-"]'),i=o.length-1;i>=0;i--)l(o[i]);if(m(Ye.media,C.classes.videoWrapper,!0),m(Ye.media,C.classes.embedWrapper,!0),"youtube"===Ye.type)Ye.media.appendChild(r),r.setAttribute("id",s),O.object(e.YT)?oe(n,r):(a(C.urls.youtube.api),e.onYouTubeReadyCallbacks=e.onYouTubeReadyCallbacks||[],e.onYouTubeReadyCallbacks.push(function(){oe(n,r)}),e.onYouTubeIframeAPIReady=function(){e.onYouTubeReadyCallbacks.forEach(function(e){e()})});else if("vimeo"===Ye.type)if(Ye.supported.full?Ye.media.appendChild(r):r=Ye.media,r.setAttribute("id",s),O.object(e.Vimeo))ie(n,r);else{a(C.urls.vimeo.api);var u=e.setInterval(function(){O.object(e.Vimeo)&&(e.clearInterval(u),ie(n,r))},50)}else if("soundcloud"===Ye.type){var d=t.createElement("iframe");d.loaded=!1,g(d,"load",function(){d.loaded=!0}),c(d,{src:"https://w.soundcloud.com/player/?url=https://api.soundcloud.com/tracks/"+n,id:s}),r.appendChild(d),Ye.media.appendChild(r),e.SC||a(C.urls.soundcloud.api);var p=e.setInterval(function(){e.SC&&d.loaded&&(e.clearInterval(p),le.call(d))},50)}}function se(){Ye.supported.full&&(He(),Ue()),ee(X("iframe"))}function oe(t,n){Ye.embed=new e.YT.Player(n.id,{videoId:t,playerVars:{autoplay:C.autoplay?1:0,controls:Ye.supported.full?0:1,rel:0,showinfo:0,iv_load_policy:3,cc_load_policy:C.captions.defaultActive?1:0,cc_lang_pref:"en",wmode:"transparent",modestbranding:1,disablekb:1,origin:"*"},events:{onError:function(e){j(Ye.container,"error",!0,{code:e.data,embed:e.target})},onReady:function(t){var n=t.target;Ye.media.play=function(){n.playVideo(),Ye.media.paused=!1},Ye.media.pause=function(){n.pauseVideo(),Ye.media.paused=!0},Ye.media.stop=function(){n.stopVideo(),Ye.media.paused=!0},Ye.media.duration=n.getDuration(),Ye.media.paused=!0,Ye.media.currentTime=0,Ye.media.muted=n.isMuted(),"function"==typeof n.getVideoData&&(C.title=n.getVideoData().title),Ye.supported.full&&Ye.media.querySelector("iframe").setAttribute("tabindex","-1"),se(),j(Ye.media,"timeupdate"),j(Ye.media,"durationchange"),e.clearInterval(Be.buffering),Be.buffering=e.setInterval(function(){Ye.media.buffered=n.getVideoLoadedFraction(),(null===Ye.media.lastBuffered||Ye.media.lastBuffered<Ye.media.buffered)&&j(Ye.media,"progress"),Ye.media.lastBuffered=Ye.media.buffered,1===Ye.media.buffered&&(e.clearInterval(Be.buffering),j(Ye.media,"canplaythrough"))},200)},onStateChange:function(t){var n=t.target;switch(e.clearInterval(Be.playing),t.data){case 0:Ye.media.paused=!0,j(Ye.media,"ended");break;case 1:Ye.media.paused=!1,Ye.media.seeking&&j(Ye.media,"seeked"),Ye.media.seeking=!1,j(Ye.media,"play"),j(Ye.media,"playing"),Be.playing=e.setInterval(function(){Ye.media.currentTime=n.getCurrentTime(),j(Ye.media,"timeupdate")},100),Ye.media.duration!==n.getDuration()&&(Ye.media.duration=n.getDuration(),j(Ye.media,"durationchange"));break;case 2:Ye.media.paused=!0,j(Ye.media,"pause")}j(Ye.container,"statechange",!1,{code:t.data})}}})}function ie(n,r){var a=function(e){return Object.keys(e).map(function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])}).join("&")}({loop:C.loop,autoplay:C.autoplay,byline:!1,portrait:!1,title:!1,speed:!0,transparent:0}),s=t.createElement("iframe"),o="https://player.vimeo.com/video/"+n+"?"+a;s.setAttribute("src",o),s.setAttribute("allowfullscreen",""),r.appendChild(s),Ye.embed=new e.Vimeo.Player(s),Ye.media.play=function(){Ye.embed.play(),Ye.media.paused=!1},Ye.media.pause=function(){Ye.embed.pause(),Ye.media.paused=!0},Ye.media.stop=function(){Ye.embed.stop(),Ye.media.paused=!0},Ye.media.paused=!0,Ye.media.currentTime=0,se(),Ye.embed.getCurrentTime().then(function(e){Ye.media.currentTime=e,j(Ye.media,"timeupdate")}),Ye.embed.getDuration().then(function(e){Ye.media.duration=e,j(Ye.media,"durationchange")}),Ye.embed.on("loaded",function(){O.htmlElement(Ye.embed.element)&&Ye.supported.full&&Ye.embed.element.setAttribute("tabindex","-1")}),Ye.embed.on("play",function(){Ye.media.paused=!1,j(Ye.media,"play"),j(Ye.media,"playing")}),Ye.embed.on("pause",function(){Ye.media.paused=!0,j(Ye.media,"pause")}),Ye.embed.on("timeupdate",function(e){Ye.media.seeking=!1,Ye.media.currentTime=e.seconds,j(Ye.media,"timeupdate")}),Ye.embed.on("progress",function(e){Ye.media.buffered=e.percent,j(Ye.media,"progress"),1===parseInt(e.percent)&&j(Ye.media,"canplaythrough")}),Ye.embed.on("seeked",function(){Ye.media.seeking=!1,j(Ye.media,"seeked"),j(Ye.media,"play")}),Ye.embed.on("ended",function(){Ye.media.paused=!0,j(Ye.media,"ended")})}function le(){Ye.embed=e.SC.Widget(this),Ye.embed.bind(e.SC.Widget.Events.READY,function(){Ye.media.play=function(){Ye.embed.play(),Ye.media.paused=!1},Ye.media.pause=function(){Ye.embed.pause(),Ye.media.paused=!0},Ye.media.stop=function(){Ye.embed.seekTo(0),Ye.embed.pause(),Ye.media.paused=!0},Ye.media.paused=!0,Ye.media.currentTime=0,Ye.embed.getDuration(function(e){Ye.media.duration=e/1e3,se()}),Ye.embed.getPosition(function(e){Ye.media.currentTime=e,j(Ye.media,"timeupdate")}),Ye.embed.bind(e.SC.Widget.Events.PLAY,function(){Ye.media.paused=!1,j(Ye.media,"play"),j(Ye.media,"playing")}),Ye.embed.bind(e.SC.Widget.Events.PAUSE,function(){Ye.media.paused=!0,j(Ye.media,"pause")}),Ye.embed.bind(e.SC.Widget.Events.PLAY_PROGRESS,function(e){Ye.media.seeking=!1,Ye.media.currentTime=e.currentPosition/1e3,j(Ye.media,"timeupdate")}),Ye.embed.bind(e.SC.Widget.Events.LOAD_PROGRESS,function(e){Ye.media.buffered=e.loadProgress,j(Ye.media,"progress"),1===parseInt(e.loadProgress)&&j(Ye.media,"canplaythrough")}),Ye.embed.bind(e.SC.Widget.Events.FINISH,function(){Ye.media.paused=!0,j(Ye.media,"ended")})})}function ue(){"play"in Ye.media&&Ye.media.play()}function ce(){"pause"in Ye.media&&Ye.media.pause()}function de(e){return O.boolean(e)||(e=Ye.media.paused),e?ue():ce(),e}function pe(e){O.number(e)||(e=C.seekTime),fe(Ye.media.currentTime-e)}function me(e){O.number(e)||(e=C.seekTime),fe(Ye.media.currentTime+e)}function fe(e){var t=0,n=Ye.media.paused,r=ye();O.number(e)?t=e:O.object(e)&&s(["input","change"],e.type)&&(t=e.target.value/e.target.max*r),t<0?t=0:t>r&&(t=r),Pe(t);try{Ye.media.currentTime=t.toFixed(4)}catch(e){}if(s(C.types.embed,Ye.type)){switch(Ye.type){case"youtube":Ye.embed.seekTo(t);break;case"vimeo":Ye.embed.setCurrentTime(t.toFixed(0));break;case"soundcloud":Ye.embed.seekTo(1e3*t)}n&&ce(),j(Ye.media,"timeupdate"),Ye.media.seeking=!0,j(Ye.media,"seeking")}$e("Seeking to "+Ye.media.currentTime+" seconds"),W(t)}function ye(){var e=parseInt(C.duration),t=0;return null===Ye.media.duration||isNaN(Ye.media.duration)||(t=Ye.media.duration),isNaN(e)?t:e}function be(){m(Ye.container,C.classes.playing,!Ye.media.paused),m(Ye.container,C.classes.stopped,Ye.media.paused),Oe(Ye.media.paused)}function ve(){P={x:e.pageXOffset||0,y:e.pageYOffset||0}}function ge(){e.scrollTo(P.x,P.y)}function he(e){var n=N.supportsFullScreen;if(n){if(!e||e.type!==N.fullScreenEventName)return N.isFullScreen(Ye.container)?N.cancelFullScreen():(ve(),N.requestFullScreen(Ye.container)),void(Ye.isFullscreen=N.isFullScreen(Ye.container));Ye.isFullscreen=N.isFullScreen(Ye.container)}else Ye.isFullscreen=!Ye.isFullscreen,t.body.style.overflow=Ye.isFullscreen?"hidden":"";m(Ye.container,C.classes.fullscreen.active,Ye.isFullscreen),J(Ye.isFullscreen),Ye.buttons&&Ye.buttons.fullscreen&&w(Ye.buttons.fullscreen,Ye.isFullscreen),j(Ye.container,Ye.isFullscreen?"enterfullscreen":"exitfullscreen",!0),!Ye.isFullscreen&&n&&ge()}function ke(e){if(O.boolean(e)||(e=!Ye.media.muted),w(Ye.buttons.mute,e),Ye.media.muted=e,0===Ye.media.volume&&we(C.volume),s(C.types.embed,Ye.type)){switch(Ye.type){case"youtube":Ye.embed[Ye.media.muted?"mute":"unMute"]();break;case"vimeo":case"soundcloud":Ye.embed.setVolume(Ye.media.muted?0:parseFloat(C.volume/C.volumeMax))}j(Ye.media,"volumechange")}}function we(e){var t=C.volumeMax,n=C.volumeMin;if(O.undefined(e)&&(e=Ye.storage.volume),(null===e||isNaN(e))&&(e=C.volume),e>t&&(e=t),e<n&&(e=n),Ye.media.volume=parseFloat(e/t),Ye.volume.display&&(Ye.volume.display.value=e),s(C.types.embed,Ye.type)){switch(Ye.type){case"youtube":Ye.embed.setVolume(100*Ye.media.volume);break;case"vimeo":case"soundcloud":Ye.embed.setVolume(Ye.media.volume)}j(Ye.media,"volumechange")}0===e?Ye.media.muted=!0:Ye.media.muted&&e>0&&ke()}function xe(e){var t=Ye.media.muted?0:Ye.media.volume*C.volumeMax;O.number(e)||(e=C.volumeStep),we(t+e)}function Te(e){var t=Ye.media.muted?0:Ye.media.volume*C.volumeMax;O.number(e)||(e=C.volumeStep),we(t-e)}function Se(){var e=Ye.media.muted?0:Ye.media.volume*C.volumeMax;Ye.supported.full&&(Ye.volume.input&&(Ye.volume.input.value=e),Ye.volume.display&&(Ye.volume.display.value=e)),ne({volume:e}),m(Ye.container,C.classes.muted,0===e),Ye.supported.full&&Ye.buttons.mute&&w(Ye.buttons.mute,0===e)}function Ee(e){Ye.supported.full&&Ye.buttons.captions&&(O.boolean(e)||(e=-1===Ye.container.className.indexOf(C.classes.captions.active)),Ye.captionsEnabled=e,w(Ye.buttons.captions,Ye.captionsEnabled),m(Ye.container,C.classes.captions.active,Ye.captionsEnabled),j(Ye.container,Ye.captionsEnabled?"captionsenabled":"captionsdisabled",!0),ne({captionsEnabled:Ye.captionsEnabled}))}function _e(e){var t="waiting"===e.type;clearTimeout(Be.loading),Be.loading=setTimeout(function(){m(Ye.container,C.classes.loading,t),Oe(t)},t?250:0)}function Ce(e){if(Ye.supported.full){var t=Ye.progress.played,n=0,r=ye();if(e)switch(e.type){case"timeupdate":case"seeking":if(Ye.controls.pressed)return;n=x(Ye.media.currentTime,r),"timeupdate"===e.type&&Ye.buttons.seek&&(Ye.buttons.seek.value=n);break;case"playing":case"progress":t=Ye.progress.buffer,n=function(){var e=Ye.media.buffered;return e&&e.length?x(e.end(0),r):O.number(e)?100*e:0}()}Fe(t,n)}}function Fe(e,t){if(Ye.supported.full){if(O.undefined(t)&&(t=0),O.undefined(e)){if(!Ye.progress||!Ye.progress.buffer)return;e=Ye.progress.buffer}O.htmlElement(e)?e.value=t:e&&(e.bar&&(e.bar.value=t),e.text&&(e.text.innerHTML=t))}}function Ae(e,t){if(t){isNaN(e)&&(e=0),Ye.secs=parseInt(e%60),Ye.mins=parseInt(e/60%60),Ye.hours=parseInt(e/60/60%60);var n=parseInt(ye()/60/60%60)>0;Ye.secs=("0"+Ye.secs).slice(-2),Ye.mins=("0"+Ye.mins).slice(-2),t.innerHTML=(n?Ye.hours+":":"")+Ye.mins+":"+Ye.secs}}function Ie(){if(Ye.supported.full){var e=ye()||0;!Ye.duration&&C.displayDuration&&Ye.media.paused&&Ae(e,Ye.currentTime),Ye.duration&&Ae(e,Ye.duration),Me()}}function Ne(e){Ae(Ye.media.currentTime,Ye.currentTime),e&&"timeupdate"===e.type&&Ye.media.seeking||Ce(e)}function Pe(e){O.number(e)||(e=0);var t=x(e,ye());Ye.progress&&Ye.progress.played&&(Ye.progress.played.value=t),Ye.buttons&&Ye.buttons.seek&&(Ye.buttons.seek.value=t)}function Me(e){var t=ye();if(C.tooltips.seek&&Ye.progress.container&&0!==t){var n=Ye.progress.container.getBoundingClientRect(),r=0,a=C.classes.tooltip+"--visible";if(e)r=100/n.width*(e.pageX-n.left);else{if(!f(Ye.progress.tooltip,a))return;r=Ye.progress.tooltip.style.left.replace("%","")}r<0?r=0:r>100&&(r=100),Ae(t/100*r,Ye.progress.tooltip),Ye.progress.tooltip.style.left=r+"%",e&&s(["mouseenter","mouseleave"],e.type)&&m(Ye.progress.tooltip,a,"mouseenter"===e.type)}}function Oe(t){if(C.hideControls&&"audio"!==Ye.type){var n=0,r=!1,a=t,o=f(Ye.container,C.classes.loading);if(O.boolean(t)||(t&&t.type?(r="enterfullscreen"===t.type,a=s(["mousemove","touchstart","mouseenter","focus"],t.type),s(["mousemove","touchmove"],t.type)&&(n=2e3),"focus"===t.type&&(n=3e3)):a=f(Ye.container,C.classes.hideControls)),e.clearTimeout(Be.hover),a||Ye.media.paused||o){if(m(Ye.container,C.classes.hideControls,!1),Ye.media.paused||o)return;Ye.browser.isTouch&&(n=3e3)}a&&Ye.media.paused||(Be.hover=e.setTimeout(function(){(!Ye.controls.pressed&&!Ye.controls.hover||r)&&m(Ye.container,C.classes.hideControls,!0)},n))}}function Le(e){O.object(e)&&"sources"in e&&e.sources.length?(m(Ye.container,C.classes.ready,!1),ce(),Pe(),Fe(),qe(),De(function(){if(Ye.embed=null,l(Ye.media),"video"===Ye.type&&Ye.videoContainer&&l(Ye.videoContainer),Ye.container&&Ye.container.removeAttribute("class"),"type"in e&&(Ye.type=e.type,"video"===Ye.type)){var n=e.sources[0];"type"in n&&s(C.types.embed,n.type)&&(Ye.type=n.type)}switch(Ye.supported=A(Ye.type),Ye.type){case"video":Ye.media=t.createElement("video");break;case"audio":Ye.media=t.createElement("audio");break;case"youtube":case"vimeo":case"soundcloud":Ye.media=t.createElement("div"),Ye.embedId=e.sources[0].src}u(Ye.container,Ye.media),O.boolean(e.autoplay)&&(C.autoplay=e.autoplay),s(C.types.html5,Ye.type)&&(C.crossorigin&&Ye.media.setAttribute("crossorigin",""),C.autoplay&&Ye.media.setAttribute("autoplay",""),"poster"in e&&Ye.media.setAttribute("poster",e.poster),C.loop&&Ye.media.setAttribute("loop","")),m(Ye.container,C.classes.fullscreen.active,Ye.isFullscreen),m(Ye.container,C.classes.captions.active,Ye.captionsEnabled),Q(),s(C.types.html5,Ye.type)&&z("source",e.sources),re(),s(C.types.html5,Ye.type)&&("tracks"in e&&z("track",e.tracks),Ye.media.load()),(s(C.types.html5,Ye.type)||s(C.types.embed,Ye.type)&&!Ye.supported.full)&&(He(),Ue()),C.title=e.title,ee()},!1)):Je("Invalid source format")}function je(){m(X("."+C.classes.tabFocus),C.classes.tabFocus,!1)}function Re(){function n(){var e=de(),t=Ye.buttons[e?"play":"pause"],n=Ye.buttons[e?"pause":"play"];if(n&&(n=n.length>1?n[n.length-1]:n[0]),n){var r=f(t,C.classes.tabFocus);setTimeout(function(){n.focus(),r&&(m(t,C.classes.tabFocus,!1),m(n,C.classes.tabFocus,!0))},100)}}function r(){var e=t.activeElement;return e=e&&e!==t.body?t.querySelector(":focus"):null}function a(e){return e.keyCode?e.keyCode:e.which}function o(e){for(var t in Ye.buttons){var n=Ye.buttons[t];if(O.nodeList(n))for(var r=0;r<n.length;r++)m(n[r],C.classes.tabFocus,n[r]===e);else m(n,C.classes.tabFocus,n===e)}}function i(e){var t=a(e),n="keydown"===e.type,r=n&&t===u;if(O.number(t))if(n){switch(s([48,49,50,51,52,53,54,56,57,32,75,38,40,77,39,37,70,67],t)&&(e.preventDefault(),e.stopPropagation()),t){case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:r||function(){var e=Ye.media.duration;O.number(e)&&fe(e/10*(t-48))}();break;case 32:case 75:r||de();break;case 38:xe();break;case 40:Te();break;case 77:r||ke();break;case 39:me();break;case 37:pe();break;case 70:he();break;case 67:r||Ee()}!N.supportsFullScreen&&Ye.isFullscreen&&27===t&&he(),u=t}else u=null}var l=Ye.browser.isIE?"change":"input";if(C.keyboardShorcuts.focused){var u=null;C.keyboardShorcuts.global&&g(e,"keydown keyup",function(e){var t=a(e),n=r();1!==I().length||!s([48,49,50,51,52,53,54,56,57,75,77,70,67],t)||O.htmlElement(n)&&y(n,C.selectors.editable)||i(e)}),g(Ye.container,"keydown keyup",i)}g(e,"keyup",function(e){var t=a(e),n=r();9===t&&o(n)}),g(t.body,"click",je);for(var c in Ye.buttons){var d=Ye.buttons[c];g(d,"blur",function(){m(d,"tab-focus",!1)})}b(Ye.buttons.play,"click",C.listeners.play,n),b(Ye.buttons.pause,"click",C.listeners.pause,n),b(Ye.buttons.restart,"click",C.listeners.restart,fe),b(Ye.buttons.rewind,"click",C.listeners.rewind,pe),b(Ye.buttons.forward,"click",C.listeners.forward,me),b(Ye.buttons.seek,l,C.listeners.seek,fe),b(Ye.volume.input,l,C.listeners.volume,function(){we(Ye.volume.input.value)}),b(Ye.buttons.mute,"click",C.listeners.mute,ke),b(Ye.buttons.fullscreen,"click",C.listeners.fullscreen,he),N.supportsFullScreen&&g(t,N.fullScreenEventName,he),b(Ye.buttons.captions,"click",C.listeners.captions,Ee),g(Ye.progress.container,"mouseenter mouseleave mousemove",Me),C.hideControls&&(g(Ye.container,"mouseenter mouseleave mousemove touchstart touchend touchcancel touchmove enterfullscreen",Oe),g(Ye.controls,"mouseenter mouseleave",function(e){Ye.controls.hover="mouseenter"===e.type}),g(Ye.controls,"mousedown mouseup touchstart touchend touchcancel",function(e){Ye.controls.pressed=s(["mousedown","touchstart"],e.type)}),g(Ye.controls,"focus blur",Oe,!0)),g(Ye.volume.input,"wheel",function(e){e.preventDefault();var t=e.webkitDirectionInvertedFromDevice,n=C.volumeStep/5;(e.deltaY<0||e.deltaX>0)&&(t?Te(n):xe(n)),(e.deltaY>0||e.deltaX<0)&&(t?xe(n):Te(n))})}function Ve(){if(g(Ye.media,"timeupdate seeking",Ne),g(Ye.media,"timeupdate",W),g(Ye.media,"durationchange loadedmetadata",Ie),g(Ye.media,"ended",function(){"video"===Ye.type&&C.showPosterOnEnd&&("video"===Ye.type&&U(),fe(),Ye.media.load())}),g(Ye.media,"progress playing",Ce),g(Ye.media,"volumechange",Se),g(Ye.media,"play pause ended",be),g(Ye.media,"waiting canplay seeked",_e),C.clickToPlay&&"audio"!==Ye.type){var e=X("."+C.classes.videoWrapper);if(!e)return;e.style.cursor="pointer",g(e,"click",function(){C.hideControls&&Ye.browser.isTouch&&!Ye.media.paused||(Ye.media.paused?ue():Ye.media.ended?(fe(),ue()):ce())})}C.disableContextMenu&&g(Ye.media,"contextmenu",function(e){e.preventDefault()}),g(Ye.media,C.events.concat(["keyup","keydown"]).join(" "),function(e){j(Ye.container,e.type,!0)})}function qe(){if(s(C.types.html5,Ye.type)){for(var e=Ye.media.querySelectorAll("source"),t=0;t<e.length;t++)l(e[t]);Ye.media.setAttribute("src",C.blankUrl),Ye.media.load(),$e("Cancelled network requests")}}function De(n,r){function a(){clearTimeout(Be.cleanUp),O.boolean(r)||(r=!0),O.function(n)&&n.call(Xe),r&&(Ye.init=!1,Ye.container.parentNode.replaceChild(Xe,Ye.container),Ye.container=null,t.body.style.overflow="",h(t.body,"click",je),j(Xe,"destroyed",!0))}if(!Ye.init)return null;switch(Ye.type){case"youtube":e.clearInterval(Be.buffering),e.clearInterval(Be.playing),Ye.embed.destroy(),a();break;case"vimeo":Ye.embed.unload().then(a),Be.cleanUp=e.setTimeout(a,200);break;case"video":case"audio":Z(!0),a()}}function He(){if(!Ye.supported.full)return Je("Basic support only",Ye.type),l(X(C.selectors.controls.wrapper)),l(X(C.selectors.buttons.play)),void Z(!0);var e=!B(C.selectors.controls.wrapper).length;e&&G(),K()&&(e&&Re(),Ve(),Z(),D(),H(),we(),Se(),Ne(),be(),Ie())}function Ue(){e.setTimeout(function(){j(Ye.media,"ready")},0),m(Ye.media,M.classes.setup,!0),m(Ye.container,C.classes.ready,!0),Ye.media.plyr=We,C.autoplay&&ue()}var We,Ye=this,Be={};Ye.media=v;var Xe=v.cloneNode(!0),$e=function(){R("log",arguments)},Je=function(){R("warn",arguments)};return $e("Config",C),We={getOriginal:function(){return Xe},getContainer:function(){return Ye.container},getEmbed:function(){return Ye.embed},getMedia:function(){return Ye.media},getType:function(){return Ye.type},getDuration:ye,getCurrentTime:function(){return Ye.media.currentTime},getVolume:function(){return Ye.media.volume},isMuted:function(){return Ye.media.muted},isReady:function(){return f(Ye.container,C.classes.ready)},isLoading:function(){return f(Ye.container,C.classes.loading)},isPaused:function(){return Ye.media.paused},on:function(e,t){return g(Ye.container,e,t),this},play:ue,pause:ce,stop:function(){ce(),fe()},restart:fe,rewind:pe,forward:me,seek:fe,source:function(e){if(O.undefined(e)){var t;switch(Ye.type){case"youtube":t=Ye.embed.getVideoUrl();break;case"vimeo":Ye.embed.getVideoUrl.then(function(e){t=e});break;case"soundcloud":Ye.embed.getCurrentSound(function(e){t=e.permalink_url});break;default:t=Ye.media.currentSrc}return t||""}Le(e)},poster:function(e){"video"===Ye.type&&Ye.media.setAttribute("poster",e)},setVolume:we,togglePlay:de,toggleMute:ke,toggleCaptions:Ee,toggleFullscreen:he,toggleControls:Oe,isFullscreen:function(){return Ye.isFullscreen||!1},support:function(e){return r(Ye,e)},destroy:De},function(){if(Ye.init)return null;if(N=_(),Ye.browser=n(),O.htmlElement(Ye.media)){te();var e=v.tagName.toLowerCase();"div"===e?(Ye.type=v.getAttribute("data-type"),Ye.embedId=v.getAttribute("data-video-id"),v.removeAttribute("data-type"),v.removeAttribute("data-video-id")):(Ye.type=e,C.crossorigin=null!==v.getAttribute("crossorigin"),C.autoplay=C.autoplay||null!==v.getAttribute("autoplay"),C.loop=C.loop||null!==v.getAttribute("loop")),Ye.supported=A(Ye.type),Ye.supported.basic&&(Ye.container=i(v,t.createElement("div")),Ye.container.setAttribute("tabindex",0),Q(),$e(Ye.browser.name+" "+Ye.browser.version),re(),(s(C.types.html5,Ye.type)||s(C.types.embed,Ye.type)&&!Ye.supported.full)&&(He(),Ue(),ee()),Ye.init=!0)}}(),Ye.init?We:null}function F(e,n){var r=new XMLHttpRequest;if(!O.string(n)||!O.htmlElement(t.querySelector("#"+n))){var a=t.createElement("div");a.setAttribute("hidden",""),O.string(n)&&a.setAttribute("id",n),t.body.insertBefore(a,t.body.childNodes[0]),"withCredentials"in r&&(r.open("GET",e,!0),r.onload=function(){a.innerHTML=r.responseText},r.send())}}function A(e){var r=n(),a=r.isIE&&r.version<=9,s=r.isIos,o=r.isIphone,i=!!t.createElement("audio").canPlayType,l=!!t.createElement("video").canPlayType,u=!1,c=!1;switch(e){case"video":c=(u=l)&&!a&&!o;break;case"audio":c=(u=i)&&!a;break;case"vimeo":u=!0,c=!a&&!s;break;case"youtube":u=!0,c=!a&&!s,s&&!o&&r.version>=10&&(c=!0);break;case"soundcloud":u=!0,c=!a&&!o;break;default:c=(u=i&&l)&&!a}return{basic:u,full:c}}function I(e){if(O.string(e)?e=t.querySelector(e):O.undefined(e)&&(e=t.body),O.htmlElement(e)){var n=e.querySelectorAll("."+M.classes.setup),r=[];return Array.prototype.slice.call(n).forEach(function(e){O.object(e.plyr)&&r.push(e.plyr)}),r}return[]}var N,P={x:0,y:0},M={enabled:!0,debug:!1,autoplay:!1,loop:!1,seekTime:10,volume:10,volumeMin:0,volumeMax:10,volumeStep:1,duration:null,displayDuration:!0,loadSprite:!0,iconPrefix:"plyr",iconUrl:"https://cdn.plyr.io/2.0.17/plyr.svg",blankUrl:"https://cdn.plyr.io/static/blank.mp4",clickToPlay:!0,hideControls:!0,showPosterOnEnd:!1,disableContextMenu:!0,keyboardShorcuts:{focused:!0,global:!1},tooltips:{controls:!1,seek:!0},selectors:{html5:"video, audio",embed:"[data-type]",editable:"input, textarea, select, [contenteditable]",container:".plyr",controls:{container:null,wrapper:".plyr__controls"},labels:"[data-plyr]",buttons:{seek:'[data-plyr="seek"]',play:'[data-plyr="play"]',pause:'[data-plyr="pause"]',restart:'[data-plyr="restart"]',rewind:'[data-plyr="rewind"]',forward:'[data-plyr="fast-forward"]',mute:'[data-plyr="mute"]',captions:'[data-plyr="captions"]',fullscreen:'[data-plyr="fullscreen"]'},volume:{input:'[data-plyr="volume"]',display:".plyr__volume--display"},progress:{container:".plyr__progress",buffer:".plyr__progress--buffer",played:".plyr__progress--played"},captions:".plyr__captions",currentTime:".plyr__time--current",duration:".plyr__time--duration"},classes:{setup:"plyr--setup",ready:"plyr--ready",videoWrapper:"plyr__video-wrapper",embedWrapper:"plyr__video-embed",type:"plyr--{0}",stopped:"plyr--stopped",playing:"plyr--playing",muted:"plyr--muted",loading:"plyr--loading",hover:"plyr--hover",tooltip:"plyr__tooltip",hidden:"plyr__sr-only",hideControls:"plyr--hide-controls",isIos:"plyr--is-ios",isTouch:"plyr--is-touch",captions:{enabled:"plyr--captions-enabled",active:"plyr--captions-active"},fullscreen:{enabled:"plyr--fullscreen-enabled",fallback:"plyr--fullscreen-fallback",active:"plyr--fullscreen-active"},tabFocus:"tab-focus"},captions:{defaultActive:!1},fullscreen:{enabled:!0,fallback:!0,allowAudio:!1},storage:{enabled:!0,key:"plyr"},controls:["play-large","play","progress","current-time","mute","volume","captions","fullscreen"],i18n:{restart:"Restart",rewind:"Rewind {seektime} secs",play:"Play",pause:"Pause",forward:"Forward {seektime} secs",played:"played",buffered:"buffered",currentTime:"Current time",duration:"Duration",volume:"Volume",toggleMute:"Toggle Mute",toggleCaptions:"Toggle Captions",toggleFullscreen:"Toggle Fullscreen",frameTitle:"Player for {title}"},types:{embed:["youtube","vimeo","soundcloud"],html5:["video","audio"]},urls:{vimeo:{api:"https://player.vimeo.com/api/player.js"},youtube:{api:"https://www.youtube.com/iframe_api"},soundcloud:{api:"https://w.soundcloud.com/player/api.js"}},listeners:{seek:null,play:null,pause:null,restart:null,rewind:null,forward:null,mute:null,volume:null,captions:null,fullscreen:null},events:["ready","ended","progress","stalled","playing","waiting","canplay","canplaythrough","loadstart","loadeddata","loadedmetadata","timeupdate","volumechange","play","pause","error","seeking","seeked","emptied"],logPrefix:"[Plyr]"},O={object:function(e){return null!==e&&"object"==typeof e},array:function(e){return null!==e&&"object"==typeof e&&e.constructor===Array},number:function(e){return null!==e&&("number"==typeof e&&!isNaN(e-0)||"object"==typeof e&&e.constructor===Number)},string:function(e){return null!==e&&("string"==typeof e||"object"==typeof e&&e.constructor===String)},boolean:function(e){return null!==e&&"boolean"==typeof e},nodeList:function(e){return null!==e&&e instanceof NodeList},htmlElement:function(e){return null!==e&&e instanceof HTMLElement},function:function(e){return null!==e&&"function"==typeof e},undefined:function(e){return null!==e&&void 0===e}},L={supported:function(){try{e.localStorage.setItem("___test","OK");var t=e.localStorage.getItem("___test");return e.localStorage.removeItem("___test"),"OK"===t}catch(e){return!1}return!1}()};return{setup:function(e,n){function r(e,t){f(t,M.classes.hook)||a.push({target:e,media:t})}var a=[],s=[],o=[M.selectors.html5,M.selectors.embed].join(",");if(O.string(e)?e=t.querySelectorAll(e):O.htmlElement(e)?e=[e]:O.nodeList(e)||O.array(e)||O.string(e)||(O.undefined(n)&&O.object(e)&&(n=e),e=t.querySelectorAll(o)),O.nodeList(e)&&(e=Array.prototype.slice.call(e)),!A().basic||!e.length)return!1;for(var i=0;i<e.length;i++){var l=e[i],u=l.querySelectorAll(o);if(u.length)for(var c=0;c<u.length;c++)r(l,u[c]);else y(l,o)&&r(l,l)}return a.forEach(function(e){var t=e.target,r=e.media,a={};try{a=JSON.parse(t.getAttribute("data-plyr"))}catch(e){}var o=T({},M,n,a);if(!o.enabled)return null;var i=new C(r,o);if(O.object(i)){if(o.debug){var l=o.events.concat(["setup","statechange","enterfullscreen","exitfullscreen","captionsenabled","captionsdisabled"]);g(i.getContainer(),l.join(" "),function(e){console.log([o.logPrefix,"event:",e.type].join(" "),e.detail.plyr)})}k(i.getContainer(),"setup",!0,{plyr:i}),s.push(i)}}),s},supported:A,loadSprite:F,get:I}}),function(){function e(e,t){t=t||{bubbles:!1,cancelable:!1,detail:void 0};var n=document.createEvent("CustomEvent");return n.initCustomEvent(e,t.bubbles,t.cancelable,t.detail),n}"function"!=typeof window.CustomEvent&&(e.prototype=window.Event.prototype,window.CustomEvent=e)}();
\ No newline at end of file +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define("Plyr",t):e.Plyr=t()}(this,function(){"use strict";var e={html5:"html5",youtube:"youtube",vimeo:"vimeo"},t={audio:"audio",video:"video"},i={enabled:!0,title:"",debug:!1,autoplay:!1,autopause:!0,seekTime:10,volume:1,muted:!1,duration:null,displayDuration:!0,invertTime:!0,toggleInvert:!0,ratio:"16:9",clickToPlay:!0,hideControls:!0,showPosterOnEnd:!1,disableContextMenu:!0,loadSprite:!0,iconPrefix:"plyr",iconUrl:"https://cdn.plyr.io/2.0.10/plyr.svg",blankVideo:"https://cdn.plyr.io/static/blank.mp4",quality:{default:"default",options:["hd2160","hd1440","hd1080","hd720","large","medium","small","tiny","default"]},loop:{active:!1},speed:{selected:1,options:[.5,.75,1,1.25,1.5,1.75,2]},keyboard:{focused:!0,global:!1},tooltips:{controls:!1,seek:!0},captions:{active:!1,language:window.navigator.language.split("-")[0]},fullscreen:{enabled:!0,fallback:!0},storage:{enabled:!0,key:"plyr"},controls:["play-large","play","progress","current-time","mute","volume","captions","settings","pip","airplay","fullscreen"],settings:["captions","quality","speed"],i18n:{restart:"Restart",rewind:"Rewind {seektime} secs",play:"Play",pause:"Pause",forward:"Forward {seektime} secs",seek:"Seek",played:"Played",buffered:"Buffered",currentTime:"Current time",duration:"Duration",volume:"Volume",mute:"Mute",unmute:"Unmute",enableCaptions:"Enable captions",disableCaptions:"Disable captions",enterFullscreen:"Enter fullscreen",exitFullscreen:"Exit fullscreen",frameTitle:"Player for {title}",captions:"Captions",settings:"Settings",speed:"Speed",quality:"Quality",loop:"Loop",start:"Start",end:"End",all:"All",reset:"Reset",none:"None",disabled:"Disabled"},urls:{vimeo:{api:"https://player.vimeo.com/api/player.js"},youtube:{api:"https://www.youtube.com/iframe_api"}},listeners:{seek:null,play:null,pause:null,restart:null,rewind:null,forward:null,mute:null,volume:null,captions:null,fullscreen:null,pip:null,airplay:null,speed:null,quality:null,loop:null,language:null},events:["ended","progress","stalled","playing","waiting","canplay","canplaythrough","loadstart","loadeddata","loadedmetadata","timeupdate","volumechange","play","pause","error","seeking","seeked","emptied","ratechange","cuechange","enterfullscreen","exitfullscreen","captionsenabled","captionsdisabled","languagechange","controlshidden","controlsshown","ready","statechange","qualitychange","qualityrequested"],selectors:{editable:"input, textarea, select, [contenteditable]",container:".plyr",controls:{container:null,wrapper:".plyr__controls"},labels:"[data-plyr]",buttons:{play:'[data-plyr="play"]',pause:'[data-plyr="pause"]',restart:'[data-plyr="restart"]',rewind:'[data-plyr="rewind"]',forward:'[data-plyr="fast-forward"]',mute:'[data-plyr="mute"]',captions:'[data-plyr="captions"]',fullscreen:'[data-plyr="fullscreen"]',pip:'[data-plyr="pip"]',airplay:'[data-plyr="airplay"]',settings:'[data-plyr="settings"]',loop:'[data-plyr="loop"]'},inputs:{seek:'[data-plyr="seek"]',volume:'[data-plyr="volume"]',speed:'[data-plyr="speed"]',language:'[data-plyr="language"]',quality:'[data-plyr="quality"]'},display:{currentTime:".plyr__time--current",duration:".plyr__time--duration",buffer:".plyr__progress--buffer",played:".plyr__progress--played",loop:".plyr__progress--loop",volume:".plyr__volume--display"},progress:".plyr__progress",captions:".plyr__captions",menu:{quality:".js-plyr__menu__list--quality"}},classNames:{video:"plyr__video-wrapper",embed:"plyr__video-embed",control:"plyr__control",type:"plyr--{0}",provider:"plyr--{0}",stopped:"plyr--stopped",playing:"plyr--playing",loading:"plyr--loading",error:"plyr--has-error",hover:"plyr--hover",tooltip:"plyr__tooltip",hidden:"plyr__sr-only",hideControls:"plyr--hide-controls",isIos:"plyr--is-ios",isTouch:"plyr--is-touch",uiSupported:"plyr--full-ui",noTransition:"plyr--no-transition",menu:{value:"plyr__menu__value",badge:"plyr__badge",open:"plyr--menu-open"},captions:{enabled:"plyr--captions-enabled",active:"plyr--captions-active"},fullscreen:{enabled:"plyr--fullscreen-enabled",fallback:"plyr--fullscreen-fallback"},pip:{supported:"plyr--pip-supported",active:"plyr--pip-active"},airplay:{supported:"plyr--airplay-supported",active:"plyr--airplay-active"},tabFocus:"plyr__tab-focus"},keys:{google:null}},n=(function(){function e(e){this.value=e}function t(t){function i(s,a){try{var o=t[s](a),l=o.value;l instanceof e?Promise.resolve(l.value).then(function(e){i("next",e)},function(e){i("throw",e)}):n(o.done?"return":"normal",o.value)}catch(e){n("throw",e)}}function n(e,t){switch(e){case"return":s.resolve({value:t,done:!0});break;case"throw":s.reject(t);break;default:s.resolve({value:t,done:!1})}(s=s.next)?i(s.key,s.arg):a=null}var s,a;this._invoke=function(e,t){return new Promise(function(n,o){var l={key:e,arg:t,resolve:n,reject:o,next:null};a?a=a.next=l:(s=a=l,i(e,t))})},"function"!=typeof t.return&&(this.return=void 0)}"function"==typeof Symbol&&Symbol.asyncIterator&&(t.prototype[Symbol.asyncIterator]=function(){return this}),t.prototype.next=function(e){return this._invoke("next",e)},t.prototype.throw=function(e){return this._invoke("throw",e)},t.prototype.return=function(e){return this._invoke("return",e)}}(),function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}),s=function(){function e(e,t){for(var i=0;i<t.length;i++){var n=t[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,i,n){return i&&e(t.prototype,i),n&&e(t,n),t}}(),a=function(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e},o={is:{plyr:function(e){return this.instanceof(e,Plyr)},object:function(e){return this.getConstructor(e)===Object},number:function(e){return this.getConstructor(e)===Number&&!Number.isNaN(e)},string:function(e){return this.getConstructor(e)===String},boolean:function(e){return this.getConstructor(e)===Boolean},function:function(e){return this.getConstructor(e)===Function},array:function(e){return!this.nullOrUndefined(e)&&Array.isArray(e)},weakMap:function(e){return this.instanceof(e,window.WeakMap)},nodeList:function(e){return this.instanceof(e,window.NodeList)},element:function(e){return this.instanceof(e,window.Element)},textNode:function(e){return this.getConstructor(e)===Text},event:function(e){return this.instanceof(e,window.Event)},cue:function(e){return this.instanceof(e,window.TextTrackCue)||this.instanceof(e,window.VTTCue)},track:function(e){return this.instanceof(e,TextTrack)||!this.nullOrUndefined(e)&&this.string(e.kind)},nullOrUndefined:function(e){return null===e||void 0===e},empty:function(e){return this.nullOrUndefined(e)||(this.string(e)||this.array(e)||this.nodeList(e))&&!e.length||this.object(e)&&!Object.keys(e).length},instanceof:function(e,t){return Boolean(e&&t&&e instanceof t)},getConstructor:function(e){return this.nullOrUndefined(e)?null:e.constructor}},getBrowser:function(){return{isIE:!!document.documentMode,isWebkit:"WebkitAppearance"in document.documentElement.style&&!/Edge/.test(navigator.userAgent),isIPhone:/(iPhone|iPod)/gi.test(navigator.platform),isIos:/(iPad|iPhone|iPod)/gi.test(navigator.platform)}},loadScript:function(e,t){var i=document.querySelector('script[src="'+e+'"]');if(null!==i)return i.callbacks=i.callbacks||[],void i.callbacks.push(t);var n=document.createElement("script");n.callbacks=n.callbacks||[],n.callbacks.push(t),o.is.function(t)&&n.addEventListener("load",function(e){n.callbacks.forEach(function(t){return t.call(null,e)}),n.callbacks=null},!1),n.src=e;var s=document.getElementsByTagName("script")[0];s.parentNode.insertBefore(n,s)},loadSprite:function(e,t){function i(e){this.innerHTML=e,document.body.insertBefore(this,document.body.childNodes[0])}if(o.is.string(e)){var n=o.is.string(t);if(!n||!document.querySelectorAll("#"+t).length){var s=document.createElement("div");if(o.toggleHidden(s,!0),n&&s.setAttribute("id",t),l.storage){var a=window.localStorage.getItem("cache-"+t);if(null!==a){var r=JSON.parse(a);return void i.call(s,r.content)}}fetch(e).then(function(e){return e.ok?e.text():null}).then(function(e){null!==e&&(l.storage&&window.localStorage.setItem("cache-"+t,JSON.stringify({content:e})),i.call(s,e))}).catch(function(){})}}},generateId:function(e){return e+"-"+Math.floor(1e4*Math.random())},inFrame:function(){try{return window.self!==window.top}catch(e){return!0}},wrap:function(e,t){var i=e.length?e:[e];Array.from(i).reverse().forEach(function(e,i){var n=i>0?t.cloneNode(!0):t,s=e.parentNode,a=e.nextSibling;n.appendChild(e),a?s.insertBefore(n,a):s.appendChild(n)})},createElement:function(e,t,i){var n=document.createElement(e);return o.is.object(t)&&o.setAttributes(n,t),o.is.string(i)&&(n.textContent=i),n},insertAfter:function(e,t){t.parentNode.insertBefore(e,t.nextSibling)},insertElement:function(e,t,i,n){t.appendChild(o.createElement(e,i,n))},removeElement:function(e){return o.is.element(e)&&o.is.element(e.parentNode)?(e.parentNode.removeChild(e),e):null},emptyElement:function(e){for(var t=e.childNodes.length;t>0;)e.removeChild(e.lastChild),t-=1},setAttributes:function(e,t){o.is.element(e)&&!o.is.empty(t)&&Object.keys(t).forEach(function(i){e.setAttribute(i,t[i])})},getAttributesFromSelector:function(e,t){if(!o.is.string(e)||o.is.empty(e))return{};var i={},n=t;return e.split(",").forEach(function(e){var t=e.trim(),s=t.replace(".",""),a=t.replace(/[[\]]/g,"").split("="),l=a[0],r=a.length>1?a[1].replace(/["']/g,""):"";switch(t.charAt(0)){case".":o.is.object(n)&&o.is.string(n.class)&&(n.class+=" "+s),i.class=s;break;case"#":i.id=t.replace("#","");break;case"[":i[l]=r}}),i},toggleClass:function(e,t,i){if(o.is.element(e)){var n=e.classList.contains(t);return e.classList[i?"add":"remove"](t),i&&!n||!i&&n}return null},hasClass:function(e,t){return o.is.element(e)&&e.classList.contains(t)},toggleHidden:function(e,t){o.is.element(e)&&(t?e.setAttribute("hidden",""):e.removeAttribute("hidden"))},matches:function(e,t){var i={Element:Element},n=i.matches||i.webkitMatchesSelector||i.mozMatchesSelector||i.msMatchesSelector||function(){return Array.from(document.querySelectorAll(t)).includes(this)};return n.call(e,t)},getElements:function(e){return this.elements.container.querySelectorAll(e)},getElement:function(e){return this.elements.container.querySelector(e)},findElements:function(){try{return this.elements.controls=o.getElement.call(this,this.config.selectors.controls.wrapper),this.elements.buttons={play:o.getElements.call(this,this.config.selectors.buttons.play),pause:o.getElement.call(this,this.config.selectors.buttons.pause),restart:o.getElement.call(this,this.config.selectors.buttons.restart),rewind:o.getElement.call(this,this.config.selectors.buttons.rewind),forward:o.getElement.call(this,this.config.selectors.buttons.forward),mute:o.getElement.call(this,this.config.selectors.buttons.mute),pip:o.getElement.call(this,this.config.selectors.buttons.pip),airplay:o.getElement.call(this,this.config.selectors.buttons.airplay),settings:o.getElement.call(this,this.config.selectors.buttons.settings),captions:o.getElement.call(this,this.config.selectors.buttons.captions),fullscreen:o.getElement.call(this,this.config.selectors.buttons.fullscreen)},this.elements.progress=o.getElement.call(this,this.config.selectors.progress),this.elements.inputs={seek:o.getElement.call(this,this.config.selectors.inputs.seek),volume:o.getElement.call(this,this.config.selectors.inputs.volume)},this.elements.display={buffer:o.getElement.call(this,this.config.selectors.display.buffer),duration:o.getElement.call(this,this.config.selectors.display.duration),currentTime:o.getElement.call(this,this.config.selectors.display.currentTime)},o.is.element(this.elements.progress)&&(this.elements.display.seekTooltip=this.elements.progress.querySelector("."+this.config.classNames.tooltip)),!0}catch(e){return this.debug.warn("It looks like there is a problem with your custom controls HTML",e),this.toggleNativeControls(!0),!1}},getFocusElement:function(){var e=document.activeElement;return e=e&&e!==document.body?document.querySelector(":focus"):null},trapFocus:function(){var e=this,t=o.getElements.call(this,"button:not(:disabled), input:not(:disabled), [tabindex]"),i=t[0],n=t[t.length-1];o.on(this.elements.container,"keydown",function(t){if("Tab"===t.key&&9===t.keyCode&&e.fullscreen.active){var s=o.getFocusElement();s!==n||t.shiftKey?s===i&&t.shiftKey&&(n.focus(),t.preventDefault()):(i.focus(),t.preventDefault())}},!1)},toggleListener:function(e,t,i,n,s,a){if(!o.is.nullOrUndefined(e))if(o.is.nodeList(e))Array.from(e).forEach(function(e){e instanceof Node&&o.toggleListener.call(null,e,t,i,n,s,a)});else{var r=t.split(" "),c=!!o.is.boolean(a)&&a;l.passiveListeners&&(c={passive:!o.is.boolean(s)||s,capture:!!o.is.boolean(a)&&a}),r.forEach(function(t){e[n?"addEventListener":"removeEventListener"](t,i,c)})}},on:function(e,t,i,n,s){o.toggleListener(e,t,i,!0,n,s)},off:function(e,t,i,n,s){o.toggleListener(e,t,i,!1,n,s)},dispatchEvent:function(e,t,i,n){if(e&&t){var s=new CustomEvent(t,{bubbles:!!o.is.boolean(i)&&i,detail:Object.assign({},n,{plyr:this instanceof Plyr?this:null})});e.dispatchEvent(s)}},toggleState:function(e,t){if(o.is.element(e)){var i="true"===e.getAttribute("aria-pressed"),n=o.is.boolean(t)?t:!i;e.setAttribute("aria-pressed",n)}},getPercentage:function(e,t){return 0===e||0===t||Number.isNaN(e)||Number.isNaN(t)?0:(e/t*100).toFixed(2)},extend:function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length,i=Array(t>1?t-1:0),n=1;n<t;n++)i[n-1]=arguments[n];if(!i.length)return e;var s=i.shift();return o.is.object(s)?(Object.keys(s).forEach(function(t){o.is.object(s[t])?(Object.keys(e).includes(t)||Object.assign(e,a({},t,{})),o.extend(e[t],s[t])):Object.assign(e,a({},t,s[t]))}),o.extend.apply(o,[e].concat(function(e){if(Array.isArray(e)){for(var t=0,i=Array(e.length);t<e.length;t++)i[t]=e[t];return i}return Array.from(e)}(i)))):e},parseYouTubeId:function(e){return e.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/)?RegExp.$2:e},parseVimeoId:function(e){if(o.is.number(Number(e)))return e;return e.match(/^.*(vimeo.com\/|video\/)(\d+).*/)?RegExp.$2:e},buildUrlParameters:function(e){return o.is.object(e)?Object.keys(e).map(function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])}).join("&"):""},stripHTML:function(e){var t=document.createDocumentFragment(),i=document.createElement("div");return t.appendChild(i),i.innerHTML=e,t.firstChild.innerText},getAspectRatio:function(e,t){var i=function e(t,i){return 0===i?t:e(i,t%i)}(e,t);return e/i+":"+t/i},transitionEnd:function(){var e=document.createElement("span"),t=Object.keys({WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"}).find(function(t){return void 0!==e.style[t]});return"string"==typeof t&&t}(),repaint:function(e){window.setTimeout(function(){e.setAttribute("hidden",""),e.offsetHeight,e.removeAttribute("hidden")},0)}},l={audio:"canPlayType"in document.createElement("audio"),video:"canPlayType"in document.createElement("video"),check:function(e,t,i){var n=!1,s=!1,a=o.getBrowser(),r=a.isIPhone&&i&&l.inline;switch(t+":"+e){case"html5:video":s=(n=l.video)&&l.rangeInput&&(!a.isIPhone||r);break;case"html5:audio":s=(n=l.audio)&&l.rangeInput;break;case"youtube:video":n=!0,s=l.rangeInput&&(!a.isIPhone||r);break;case"vimeo:video":n=!0,s=l.rangeInput&&!a.isIPhone;break;default:s=(n=l.audio&&l.video)&&l.rangeInput}return{api:n,ui:s}},pip:!o.getBrowser().isIPhone&&o.is.function(o.createElement("video").webkitSetPresentationMode),airplay:o.is.function(window.WebKitPlaybackTargetAvailabilityEvent),inline:"playsInline"in document.createElement("video"),mime:function(e){var t=this.media;try{if(!this.isHTML5||!o.is.function(t.canPlayType))return!1;if(this.isVideo)switch(e){case"video/webm":return t.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/,"");case"video/mp4":return t.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/,"");case"video/ogg":return t.canPlayType('video/ogg; codecs="theora"').replace(/no/,"");default:return!1}else if(this.isAudio)switch(e){case"audio/mpeg":return t.canPlayType("audio/mpeg;").replace(/no/,"");case"audio/ogg":return t.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/,"");case"audio/wav":return t.canPlayType('audio/wav; codecs="1"').replace(/no/,"");default:return!1}}catch(e){return!1}return!1},textTracks:"textTracks"in document.createElement("video"),passiveListeners:function(){var e=!1;try{var t=Object.defineProperty({},"passive",{get:function(){return e=!0,null}});window.addEventListener("test",null,t)}catch(e){}return e}(),rangeInput:function(){var e=document.createElement("input");return e.type="range","range"===e.type}(),touch:"ontouchstart"in document.documentElement,transitions:!1!==o.transitionEnd,reducedMotion:"matchMedia"in window&&window.matchMedia("(prefers-reduced-motion)").matches},r=function(){},c=function(){function e(t){n(this,e),this.enabled=window.console&&t.config.debug,this.enabled&&this.log("Debugging enabled")}return s(e,[{key:"log",get:function(){return this.enabled?Function.prototype.bind.call(console.log,console):r}},{key:"warn",get:function(){return this.enabled?Function.prototype.bind.call(console.warn,console):r}},{key:"error",get:function(){return this.enabled?Function.prototype.bind.call(console.error,console):r}}]),e}(),u=function(){function e(t){n(this,e),this.enabled=t.config.storage.enabled,this.key=t.config.storage.key}return s(e,[{key:"get",value:function(t){var i=window.localStorage.getItem(this.key);if(!e.supported||o.is.empty(i))return null;var n=JSON.parse(i);return o.is.string(t)&&t.length?n[t]:n}},{key:"set",value:function(t){if(e.supported&&this.enabled&&o.is.object(t)){var i=this.get();o.extend(i,t),window.localStorage.setItem(this.key,JSON.stringify(i))}}}],[{key:"supported",get:function(){if(!("localStorage"in window))return!1;try{return window.localStorage.setItem("___test","___test"),window.localStorage.removeItem("___test"),!0}catch(e){return!1}}}]),e}(),d=function(){var e=!1;return o.is.function(document.cancelFullScreen)?e="":["webkit","o","moz","ms","khtml"].some(function(t){return o.is.function(document[t+"CancelFullScreen"])?(e=t,!0):!(!o.is.function(document.msExitFullscreen)||!document.msFullscreenEnabled)&&(e="ms",!0)}),e}(),p={prefix:d,enabled:document.fullscreenEnabled||document.webkitFullscreenEnabled||document.mozFullScreenEnabled||document.msFullscreenEnabled,eventType:"ms"===d?"MSFullscreenChange":d+"fullscreenchange",isFullScreen:function(e){if(!p.enabled)return!1;var t=o.is.nullOrUndefined(e)?document.body:e;switch(d){case"":return document.fullscreenElement===t;case"moz":return document.mozFullScreenElement===t;default:return document[d+"FullscreenElement"]===t}},requestFullScreen:function(e){if(!p.enabled)return!1;var t=o.is.nullOrUndefined(e)?document.body:e;return d.length?t[d+("ms"===d?"RequestFullscreen":"RequestFullScreen")]():t.requestFullScreen()},cancelFullScreen:function(){return!!p.enabled&&(d.length?document[d+("ms"===d?"ExitFullscreen":"CancelFullScreen")]():document.cancelFullScreen())},element:function(){return p.enabled?d.length?document[d+"FullscreenElement"]:document.fullscreenElement:null},setup:function(){if(this.supported.ui&&!this.isAudio&&this.config.fullscreen.enabled){var e=p.enabled;e||this.config.fullscreen.fallback&&!o.inFrame()?(this.debug.log((e?"Native":"Fallback")+" fullscreen enabled"),o.toggleClass(this.elements.container,this.config.classNames.fullscreen.enabled,!0)):this.debug.log("Fullscreen not supported and fallback disabled"),this.elements.buttons&&this.elements.buttons.fullscreen&&o.toggleState(this.elements.buttons.fullscreen,!1),o.trapFocus.call(this)}}},h=o.getBrowser(),m={global:function(){var e=this,t=null,i=function(i){var n=function(e){return e.keyCode?e.keyCode:e.which}(i),s="keydown"===i.type,a=s&&n===t;if(!(i.altKey||i.ctrlKey||i.metaKey||i.shiftKey)&&o.is.number(n)){if(s){var l=[48,49,50,51,52,53,54,56,57,32,75,38,40,77,39,37,70,67,73,76,79],r=o.getFocusElement();if(o.is.element(r)&&o.matches(r,e.config.selectors.editable))return;switch(l.includes(n)&&(i.preventDefault(),i.stopPropagation()),n){case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:a||(e.currentTime=e.duration/10*(n-48));break;case 32:case 75:a||e.togglePlay();break;case 38:e.increaseVolume(.1);break;case 40:e.decreaseVolume(.1);break;case 77:a||(e.muted=!e.muted);break;case 39:e.forward();break;case 37:e.rewind();break;case 70:e.toggleFullscreen();break;case 67:a||e.toggleCaptions();break;case 76:e.loop=!e.loop}!p.enabled&&e.fullscreen.active&&27===n&&e.toggleFullscreen(),t=n}else t=null}};this.config.keyboard.global?o.on(window,"keydown keyup",i,!1):this.config.keyboard.focused&&o.on(this.elements.container,"keydown keyup",i,!1),o.on(this.elements.container,"focusout",function(t){o.toggleClass(t.target,e.config.classNames.tabFocus,!1)}),o.on(this.elements.container,"keydown",function(t){9===t.keyCode&&window.setTimeout(function(){o.toggleClass(o.getFocusElement(),e.config.classNames.tabFocus,!0)},0)}),this.config.hideControls&&o.on(this.elements.container,"mouseenter mouseleave mousemove touchstart touchend touchmove enterfullscreen exitfullscreen",function(t){e.toggleControls(t)}),p.enabled&&(o.on(document,p.eventType,function(t){e.toggleFullscreen(t)}),o.on(this.elements.container,"dblclick",function(t){e.toggleFullscreen(t)}))},media:function(){var e=this;if(o.on(this.media,"timeupdate seeking",function(t){return g.timeUpdate.call(e,t)}),o.on(this.media,"durationchange loadedmetadata",function(t){return g.durationUpdate.call(e,t)}),o.on(this.media,"loadeddata",function(){o.toggleHidden(e.elements.volume,!e.hasAudio),o.toggleHidden(e.elements.buttons.mute,!e.hasAudio)}),o.on(this.media,"ended",function(){e.isHTML5&&e.isVideo&&e.config.showPosterOnEnd&&(e.restart(),e.media.load())}),o.on(this.media,"progress playing",function(t){return g.updateProgress.call(e,t)}),o.on(this.media,"volumechange",function(t){return g.updateVolume.call(e,t)}),o.on(this.media,"playing play pause ended",function(t){return g.checkPlaying.call(e,t)}),o.on(this.media,"stalled waiting canplay seeked playing",function(t){return g.checkLoading.call(e,t)}),this.supported.ui&&this.config.clickToPlay&&!this.isAudio){var t=o.getElement.call(this,"."+this.config.classNames.video);if(!o.is.element(t))return;o.on(t,"click",function(){e.config.hideControls&&l.touch&&!e.paused||(e.paused?e.play():e.ended?(e.restart(),e.play()):e.pause())})}this.supported.ui&&this.config.disableContextMenu&&o.on(this.media,"contextmenu",function(e){e.preventDefault()},!1),o.on(this.media,"volumechange",function(){e.storage.set({volume:e.volume,muted:e.muted})}),o.on(this.media,"ratechange",function(){y.updateSetting.call(e,"speed"),e.storage.set({speed:e.speed})}),o.on(this.media,"qualitychange",function(){y.updateSetting.call(e,"quality"),e.storage.set({quality:e.quality})}),o.on(this.media,"languagechange",function(){y.updateSetting.call(e,"captions"),e.storage.set({language:e.language})}),o.on(this.media,"captionsenabled captionsdisabled",function(){y.updateSetting.call(e,"captions"),e.storage.set({captions:e.captions.active})}),o.on(this.media,this.config.events.concat(["keyup","keydown"]).join(" "),function(t){var i={};"error"===t.type&&(i=e.media.error),o.dispatchEvent.call(e,e.elements.container,t.type,!0,i)})},controls:function(){var e=this,t=h.isIE?"change":"input",i=function(t,i,n){var s=e.config.listeners[i];o.is.function(s)&&s.call(e,t),!t.defaultPrevented&&o.is.function(n)&&n.call(e,t)};o.on(this.elements.buttons.play,"click",function(t){return i(t,"play",function(){e.togglePlay()})}),o.on(this.elements.buttons.restart,"click",function(t){return i(t,"restart",function(){e.restart()})}),o.on(this.elements.buttons.rewind,"click",function(t){return i(t,"rewind",function(){e.rewind()})}),o.on(this.elements.buttons.forward,"click",function(t){return i(t,"forward",function(){e.forward()})}),o.on(this.elements.buttons.mute,"click",function(t){return i(t,"mute",function(){e.muted=!e.muted})}),o.on(this.elements.buttons.captions,"click",function(t){return i(t,"captions",function(){e.toggleCaptions()})}),o.on(this.elements.buttons.fullscreen,"click",function(t){return i(t,"fullscreen",function(){e.toggleFullscreen()})}),o.on(this.elements.buttons.pip,"click",function(t){return i(t,"pip",function(){e.pip="toggle"})}),o.on(this.elements.buttons.airplay,"click",function(t){return i(t,"airplay",function(){e.airplay()})}),o.on(this.elements.buttons.settings,"click",function(t){y.toggleMenu.call(e,t)}),o.on(document.documentElement,"click",function(t){y.toggleMenu.call(e,t)}),o.on(this.elements.settings.form,"click",function(t){t.stopPropagation(),o.matches(t.target,e.config.selectors.inputs.language)?i(t,"language",function(){e.language=t.target.value}):o.matches(t.target,e.config.selectors.inputs.quality)?i(t,"quality",function(){e.quality=t.target.value}):o.matches(t.target,e.config.selectors.inputs.speed)?i(t,"speed",function(){e.speed=parseFloat(t.target.value)}):y.showTab.call(e,t)}),o.on(this.elements.inputs.seek,t,function(t){return i(t,"seek",function(){e.currentTime=t.target.value/t.target.max*e.duration})}),this.config.toggleInvert&&!o.is.element(this.elements.display.duration)&&o.on(this.elements.display.currentTime,"click",function(){0!==e.currentTime&&(e.config.invertTime=!e.config.invertTime,g.timeUpdate.call(e))}),o.on(this.elements.inputs.volume,t,function(t){return i(t,"volume",function(){e.volume=t.target.value})}),h.isWebkit&&o.on(o.getElements.call(this,'input[type="range"]'),"input",function(t){y.updateRangeFill.call(e,t.target)}),o.on(this.elements.progress,"mouseenter mouseleave mousemove",function(t){return y.updateSeekTooltip.call(e,t)}),this.config.hideControls&&(o.on(this.elements.controls,"mouseenter mouseleave",function(t){e.elements.controls.hover="mouseenter"===t.type}),o.on(this.elements.controls,"mousedown mouseup touchstart touchend touchcancel",function(t){e.elements.controls.pressed=["mousedown","touchstart"].includes(t.type)}),o.on(this.elements.controls,"focusin focusout",function(t){e.toggleControls(t)})),o.on(this.elements.inputs.volume,"wheel",function(t){return i(t,"volume",function(){var i=t.webkitDirectionInvertedFromDevice,n=0;(t.deltaY<0||t.deltaX>0)&&(i?(e.decreaseVolume(.02),n=-1):(e.increaseVolume(.02),n=1)),(t.deltaY>0||t.deltaX<0)&&(i?(e.increaseVolume(.02),n=1):(e.decreaseVolume(.02),n=-1)),(1===n&&e.media.volume<1||-1===n&&e.media.volume>0)&&t.preventDefault()})},!1)}},g={addStyleHook:function(){o.toggleClass(this.elements.container,this.config.selectors.container.replace(".",""),!0),o.toggleClass(this.elements.container,this.config.classNames.uiSupported,this.supported.ui)},toggleNativeControls:function(){arguments.length>0&&void 0!==arguments[0]&&arguments[0]&&this.isHTML5?this.media.setAttribute("controls",""):this.media.removeAttribute("controls")},build:function(){if(m.media.call(this),!this.supported.ui)return this.debug.warn("Basic support only for "+this.provider+" "+this.type),o.removeElement.call(this,"controls"),o.removeElement.call(this,"buttons.play"),void g.toggleNativeControls.call(this,!0);o.is.element(this.elements.controls)||(y.inject.call(this),m.controls.call(this)),o.is.element(this.elements.controls)&&(g.toggleNativeControls.call(this),p.setup.call(this),b.setup.call(this),this.volume=null,this.muted=null,this.speed=null,this.loop=null,this.options.quality=[],g.timeUpdate.call(this),g.checkPlaying.call(this),this.ready=!0,o.dispatchEvent.call(this,this.media,"ready"),g.setTitle.call(this))},setTitle:function(){var e=this.config.i18n.play;if(o.is.string(this.config.title)&&!o.is.empty(this.config.title)&&(e+=", "+this.config.title,this.elements.container.setAttribute("aria-label",this.config.title)),o.is.nodeList(this.elements.buttons.play)&&Array.from(this.elements.buttons.play).forEach(function(t){t.setAttribute("aria-label",e)}),this.isEmbed){var t=o.getElement.call(this,"iframe");if(!o.is.element(t))return;var i=o.is.empty(this.config.title)?"video":this.config.title;t.setAttribute("title",this.config.i18n.frameTitle.replace("{title}",i))}},checkPlaying:function(){var e=this;o.toggleClass(this.elements.container,this.config.classNames.playing,this.playing),o.toggleClass(this.elements.container,this.config.classNames.stopped,this.paused),o.is.nodeList(this.elements.buttons.play)&&Array.from(this.elements.buttons.play).forEach(function(t){return o.toggleState(t,e.playing)}),this.toggleControls(!this.playing)},checkLoading:function(e){var t=this;this.loading=2===this.media.networkState||["stalled","waiting"].includes(e.type),clearTimeout(this.timers.loading),this.timers.loading=setTimeout(function(){o.toggleClass(t.elements.container,t.config.classNames.loading,t.loading),t.toggleControls(t.loading)},this.loading?250:0)},checkFailed:function(){var e=this;this.failed=3===this.media.networkState,this.failed&&(o.toggleClass(this.elements.container,this.config.classNames.loading,!1),o.toggleClass(this.elements.container,this.config.classNames.error,!0)),clearTimeout(this.timers.failed),this.timers.loading=setTimeout(function(){o.toggleClass(e.elements.container,e.config.classNames.loading,e.loading),e.toggleControls(e.loading)},this.loading?250:0)},updateVolume:function(){this.supported.ui&&(o.is.element(this.elements.inputs.volume)&&g.setRange.call(this,this.elements.inputs.volume,this.muted?0:this.volume),o.is.element(this.elements.buttons.mute)&&o.toggleState(this.elements.buttons.mute,this.muted||0===this.volume))},setRange:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;o.is.element(e)&&(e.value=t,y.updateRangeFill.call(this,e))},setProgress:function(e,t){var i=o.is.number(t)?t:0,n=o.is.element(e)?e:this.elements.display.buffer;if(o.is.element(n)){n.value=i;var s=n.getElementsByTagName("span")[0];o.is.element(s)&&(s.childNodes[0].nodeValue=i)}},updateProgress:function(e){var t=this;if(this.supported.ui&&o.is.event(e)){var i=0;if(e)switch(e.type){case"timeupdate":case"seeking":i=o.getPercentage(this.currentTime,this.duration),"timeupdate"===e.type&&g.setRange.call(this,this.elements.inputs.seek,i);break;case"playing":case"progress":i=function(){var e=t.media.buffered;return e&&e.length?o.getPercentage(e.end(0),t.duration):o.is.number(e)?100*e:0}(),g.setProgress.call(this,this.elements.display.buffer,i)}}},updateTimeDisplay:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(o.is.element(e)&&o.is.number(t)){var n=function(e){return("0"+e).slice(-2)},s=function(e){return parseInt(e/60/60%60,10)},a=s(t),l=function(e){return parseInt(e/60%60,10)}(t),r=function(e){return parseInt(e%60,10)}(t);s(this.duration)>0?a+=":":a="",e.textContent=(i?"-":"")+a+n(l)+":"+n(r)}},timeUpdate:function(e){var t=!o.is.element(this.elements.display.duration)&&this.config.invertTime;g.updateTimeDisplay.call(this,this.elements.display.currentTime,t?this.duration-this.currentTime:this.currentTime,t),e&&"timeupdate"===e.type&&this.media.seeking||g.updateProgress.call(this,e)},durationUpdate:function(){this.supported.ui&&(!o.is.element(this.elements.display.duration)&&this.config.displayDuration&&this.paused&&g.updateTimeDisplay.call(this,this.elements.display.currentTime,this.duration),o.is.element(this.elements.display.duration)&&g.updateTimeDisplay.call(this,this.elements.display.duration,this.duration),y.updateSeekTooltip.call(this))}},f=o.getBrowser(),y={updateRangeFill:function(e){if(f.isWebkit){var t=o.is.event(e)?e.target:e;if(o.is.element(t)&&"range"===t.getAttribute("type")){o.is.element(this.elements.styleSheet)||(this.elements.styleSheet=o.createElement("style"),this.elements.container.appendChild(this.elements.styleSheet));var i=this.elements.styleSheet.sheet,n=t.value/t.max*100,s="#"+t.id+"::-webkit-slider-runnable-track",a="{ background-image: linear-gradient(to right, currentColor "+n+"%, transparent "+n+"%) }",l=Array.from(i.rules).findIndex(function(e){return e.selectorText===s});-1!==l&&i.deleteRule(l),i.insertRule([s,a].join(" "))}}},getIconUrl:function(){return{url:this.config.iconUrl,absolute:0===this.config.iconUrl.indexOf("http")||f.isIE&&!window.svg4everybody}},createIcon:function(e,t){var i="http://www.w3.org/2000/svg",n=y.getIconUrl.call(this),s=(n.absolute?"":n.url)+"#"+this.config.iconPrefix,a=document.createElementNS(i,"svg");o.setAttributes(a,o.extend(t,{role:"presentation"}));var l=document.createElementNS(i,"use"),r=s+"-"+e;return"href"in l?l.setAttributeNS("http://www.w3.org/1999/xlink","href",r):l.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",r),a.appendChild(l),a},createLabel:function(e,t){var i=this.config.i18n[e],n=Object.assign({},t);switch(e){case"pip":i="PIP";break;case"airplay":i="AirPlay"}return"class"in n?n.class+=" "+this.config.classNames.hidden:n.class=this.config.classNames.hidden,o.createElement("span",n,i)},createBadge:function(e){if(o.is.empty(e))return null;var t=o.createElement("span",{class:this.config.classNames.menu.value});return t.appendChild(o.createElement("span",{class:this.config.classNames.menu.badge},e)),t},createButton:function(e,t){var i=o.createElement("button"),n=Object.assign({},t),s=e,a=!1,l=void 0,r=void 0,c=void 0,u=void 0;switch("type"in n||(n.type="button"),"class"in n?n.class.includes(this.config.classNames.control)&&(n.class+=" "+this.config.classNames.control):n.class=this.config.classNames.control,s){case"play":a=!0,l="play",c="pause",r="play",u="pause";break;case"mute":a=!0,l="mute",c="unmute",r="volume",u="muted";break;case"captions":a=!0,l="enableCaptions",c="disableCaptions",r="captions-off",u="captions-on";break;case"fullscreen":a=!0,l="enterFullscreen",c="exitFullscreen",r="enter-fullscreen",u="exit-fullscreen";break;case"play-large":n.class+=" "+this.config.classNames.control+"--overlaid",s="play",l="play",r="play";break;default:l=s,r=s}return a?(i.appendChild(y.createIcon.call(this,u,{class:"icon--pressed"})),i.appendChild(y.createIcon.call(this,r,{class:"icon--not-pressed"})),i.appendChild(y.createLabel.call(this,c,{class:"label--pressed"})),i.appendChild(y.createLabel.call(this,l,{class:"label--not-pressed"})),n["aria-pressed"]=!1,n["aria-label"]=this.config.i18n[l]):(i.appendChild(y.createIcon.call(this,r)),i.appendChild(y.createLabel.call(this,l))),o.extend(n,o.getAttributesFromSelector(this.config.selectors.buttons[s],n)),o.setAttributes(i,n),this.elements.buttons[s]=i,i},createRange:function(e,t){var i=o.createElement("label",{for:t.id,class:this.config.classNames.hidden},this.config.i18n[e]),n=o.createElement("input",o.extend(o.getAttributesFromSelector(this.config.selectors.inputs[e]),{type:"range",min:0,max:100,step:.01,value:0,autocomplete:"off"},t));return this.elements.inputs[e]=n,y.updateRangeFill.call(this,n),{label:i,input:n}},createProgress:function(e,t){var i=o.createElement("progress",o.extend(o.getAttributesFromSelector(this.config.selectors.display[e]),{min:0,max:100,value:0},t));if("volume"!==e){i.appendChild(o.createElement("span",null,"0"));var n="";switch(e){case"played":n=this.config.i18n.played;break;case"buffer":n=this.config.i18n.buffered}i.textContent="% "+n.toLowerCase()}return this.elements.display[e]=i,i},createTime:function(e){var t=o.createElement("div",{class:"plyr__time"});return t.appendChild(o.createElement("span",{class:this.config.classNames.hidden},this.config.i18n[e])),t.appendChild(o.createElement("span",o.getAttributesFromSelector(this.config.selectors.display[e]),"00:00")),this.elements.display[e]=t,t},createMenuItem:function(e,t,i,n){var s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null,a=arguments.length>5&&void 0!==arguments[5]&&arguments[5],l=o.createElement("li"),r=o.createElement("label",{class:this.config.classNames.control}),c=o.createElement("input",o.extend(o.getAttributesFromSelector(this.config.selectors.inputs[i]),{type:"radio",name:"plyr-"+i,value:e,checked:a,class:"plyr__sr-only"})),u=o.createElement("span",{"aria-hidden":!0});r.appendChild(c),r.appendChild(u),r.insertAdjacentHTML("beforeend",n),o.is.element(s)&&r.appendChild(s),l.appendChild(r),t.appendChild(l)},updateSeekTooltip:function(e){if(this.config.tooltips.seek&&o.is.element(this.elements.inputs.seek)&&o.is.element(this.elements.display.seekTooltip)&&0!==this.duration){var t=0,i=this.elements.inputs.seek.getBoundingClientRect(),n=this.config.classNames.tooltip+"--visible";if(o.is.event(e))t=100/i.width*(e.pageX-i.left);else{if(!o.hasClass(this.elements.display.seekTooltip,n))return;t=parseFloat(this.elements.display.seekTooltip.style.left,10)}t<0?t=0:t>100&&(t=100),g.updateTimeDisplay.call(this,this.elements.display.seekTooltip,this.duration/100*t),this.elements.display.seekTooltip.style.left=t+"%",o.is.event(e)&&["mouseenter","mouseleave"].includes(e.type)&&o.toggleClass(this.elements.display.seekTooltip,n,"mouseenter"===e.type)}},toggleTab:function(e,t){var i=this.elements.settings.tabs[e],n=this.elements.settings.panes[e];o.toggleHidden(i,!t),o.toggleHidden(n,!t)},setQualityMenu:function(e){var t=this,i=this.elements.settings.panes.quality.querySelector("ul");o.is.array(e)?this.options.quality=e.filter(function(e){return t.config.quality.options.includes(e)}):this.options.quality=this.config.quality.options;var n=!o.is.empty(this.options.quality)&&this.isYouTube;if(y.toggleTab.call(this,"quality",n),n){o.emptyElement(i);this.options.quality.forEach(function(e){return y.createMenuItem.call(t,e,i,"quality",y.getLabel.call(t,"quality",e),function(e){var i="";switch(e){case"hd2160":i="4K";break;case"hd1440":i="WQHD";break;case"hd1080":case"hd720":i="HD"}return i.length?y.createBadge.call(t,i):null}(e))}),y.updateSetting.call(this,"quality",i)}},getLabel:function(e,t){switch(e){case"speed":return 1===t?"Normal":t+"×";case"quality":switch(t){case"hd2160":return"2160P";case"hd1440":return"1440P";case"hd1080":return"1080P";case"hd720":return"720P";case"large":return"480P";case"medium":return"360P";case"small":return"240P";case"tiny":return"Tiny";case"default":return"Auto";default:return t}case"captions":return y.getLanguage.call(this);default:return null}},updateSetting:function(e,t){var i=this.elements.settings.panes[e],n=null,s=t;switch(e){case"captions":n=this.captions.active?this.captions.language:"";break;default:if(n=this[e],o.is.empty(n)&&(n=this.config[e].default),!this.options[e].includes(n))return void this.debug.warn("Unsupported value of '"+n+"' for "+e);if(!this.config[e].options.includes(n))return void this.debug.warn("Disabled value of '"+n+"' for "+e)}if(o.is.element(s)||(s=i&&i.querySelector("ul")),!o.is.empty(n)){this.elements.settings.tabs[e].querySelector("."+this.config.classNames.menu.value).innerHTML=y.getLabel.call(this,e,n)}var a=s&&s.querySelector('input[value="'+n+'"]');o.is.element(a)&&(a.checked=!0)},getLanguage:function(){if(!this.supported.ui)return null;if(!l.textTracks||!b.getTracks.call(this).length)return this.config.i18n.none;if(this.captions.active){var e=b.getCurrentTrack.call(this);if(o.is.track(e))return e.label}return this.config.i18n.disabled},setCaptionsMenu:function(){var e=this,t=this.elements.settings.panes.captions.querySelector("ul"),i=b.getTracks.call(this).length;if(y.toggleTab.call(this,"captions",i),o.emptyElement(t),i){var n=b.getTracks.call(this).map(function(e){return{language:e.language,label:o.is.empty(e.label)?e.language.toUpperCase():e.label}});n.unshift({language:"",label:this.config.i18n.none}),n.forEach(function(i){y.createMenuItem.call(e,i.language,t,"language",i.label||i.language,y.createBadge.call(e,i.language.toUpperCase()),i.language.toLowerCase()===e.captions.language.toLowerCase())}),y.updateSetting.call(this,"captions",t)}},setSpeedMenu:function(){var e=this;o.is.object(this.options.speed)&&Object.keys(this.options.speed).length||(this.options.speed=[.5,.75,1,1.25,1.5,1.75,2]),this.options.speed=this.options.speed.filter(function(t){return e.config.speed.options.includes(t)});var t=!o.is.empty(this.options.speed);if(y.toggleTab.call(this,"speed",t),t){var i=this.elements.settings.panes.speed.querySelector("ul");o.toggleHidden(this.elements.settings.tabs.speed,!1),o.toggleHidden(this.elements.settings.panes.speed,!1),o.emptyElement(i),this.options.speed.forEach(function(t){return y.createMenuItem.call(e,t,i,"speed",y.getLabel.call(e,"speed",t))}),y.updateSetting.call(this,"speed",i)}},toggleMenu:function(e){var t=this.elements.settings.form,i=this.elements.buttons.settings,n=o.is.boolean(e)?e:o.is.element(t)&&"true"===t.getAttribute("aria-hidden");if(o.is.event(e)){var s=o.is.element(t)&&t.contains(e.target),a=e.target===this.elements.buttons.settings;if(s||!s&&!a&&n)return;a&&e.stopPropagation()}o.is.element(i)&&i.setAttribute("aria-expanded",n),o.is.element(t)&&(t.setAttribute("aria-hidden",!n),o.toggleClass(this.elements.container,this.config.classNames.menu.open,n),n?t.removeAttribute("tabindex"):t.setAttribute("tabindex",-1))},getTabSize:function(e){var t=e.cloneNode(!0);t.style.position="absolute",t.style.opacity=0,t.setAttribute("aria-hidden",!1),Array.from(t.querySelectorAll("input[name]")).forEach(function(e){var t=e.getAttribute("name");e.setAttribute("name",t+"-clone")}),e.parentNode.appendChild(t);var i=t.scrollWidth,n=t.scrollHeight;return o.removeElement(t),{width:i,height:n}},showTab:function(e){var t=this.elements.settings.menu,i=e.target,n="false"===i.getAttribute("aria-expanded"),s=document.getElementById(i.getAttribute("aria-controls"));if(o.is.element(s)){if("tabpanel"===s.getAttribute("role")){var a=t.querySelector('[role="tabpanel"][aria-hidden="false"]'),r=a.parentNode;if(Array.from(t.querySelectorAll('[aria-controls="'+a.getAttribute("id")+'"]')).forEach(function(e){e.setAttribute("aria-expanded",!1)}),l.transitions&&!l.reducedMotion){r.style.width=a.scrollWidth+"px",r.style.height=a.scrollHeight+"px";var c=y.getTabSize.call(this,s),u=function e(t){t.target===r&&["width","height"].includes(t.propertyName)&&(r.style.width="",r.style.height="",o.off(r,o.transitionEnd,e))};o.on(r,o.transitionEnd,u),r.style.width=c.width+"px",r.style.height=c.height+"px"}a.setAttribute("aria-hidden",!0),a.setAttribute("tabindex",-1),s.setAttribute("aria-hidden",!n),i.setAttribute("aria-expanded",n),s.removeAttribute("tabindex"),s.querySelectorAll("button:not(:disabled), input:not(:disabled), [tabindex]")[0].focus()}}},create:function(e){var t=this;if(o.is.empty(this.config.controls))return null;var i=o.createElement("div",o.getAttributesFromSelector(this.config.selectors.controls.wrapper));if(this.config.controls.includes("restart")&&i.appendChild(y.createButton.call(this,"restart")),this.config.controls.includes("rewind")&&i.appendChild(y.createButton.call(this,"rewind")),this.config.controls.includes("play")&&i.appendChild(y.createButton.call(this,"play")),this.config.controls.includes("fast-forward")&&i.appendChild(y.createButton.call(this,"fast-forward")),this.config.controls.includes("progress")){var n=o.createElement("div",o.getAttributesFromSelector(this.config.selectors.progress)),s=y.createRange.call(this,"seek",{id:"plyr-seek-"+e.id});if(n.appendChild(s.label),n.appendChild(s.input),n.appendChild(y.createProgress.call(this,"buffer")),this.config.tooltips.seek){var a=o.createElement("span",{role:"tooltip",class:this.config.classNames.tooltip},"00:00");n.appendChild(a),this.elements.display.seekTooltip=a}this.elements.progress=n,i.appendChild(this.elements.progress)}if(this.config.controls.includes("current-time")&&i.appendChild(y.createTime.call(this,"currentTime")),this.config.controls.includes("duration")&&i.appendChild(y.createTime.call(this,"duration")),this.config.controls.includes("mute")&&i.appendChild(y.createButton.call(this,"mute")),this.config.controls.includes("volume")){var r=o.createElement("div",{class:"plyr__volume"}),c={max:1,step:.05,value:this.config.volume},u=y.createRange.call(this,"volume",o.extend(c,{id:"plyr-volume-"+e.id}));r.appendChild(u.label),r.appendChild(u.input),this.elements.volume=r,i.appendChild(r)}if(this.config.controls.includes("captions")&&i.appendChild(y.createButton.call(this,"captions")),this.config.controls.includes("settings")&&!o.is.empty(this.config.settings)){var d=o.createElement("div",{class:"plyr__menu"});d.appendChild(y.createButton.call(this,"settings",{id:"plyr-settings-toggle-"+e.id,"aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id,"aria-expanded":!1}));var p=o.createElement("form",{class:"plyr__menu__container",id:"plyr-settings-"+e.id,"aria-hidden":!0,"aria-labelled-by":"plyr-settings-toggle-"+e.id,role:"tablist",tabindex:-1}),h=o.createElement("div"),m=o.createElement("div",{id:"plyr-settings-"+e.id+"-home","aria-hidden":!1,"aria-labelled-by":"plyr-settings-toggle-"+e.id,role:"tabpanel"}),g=o.createElement("ul",{role:"tablist"});this.config.settings.forEach(function(i){var n=o.createElement("li",{role:"tab",hidden:""}),s=o.createElement("button",o.extend(o.getAttributesFromSelector(t.config.selectors.buttons.settings),{type:"button",class:t.config.classNames.control+" "+t.config.classNames.control+"--forward",id:"plyr-settings-"+e.id+"-"+i+"-tab","aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id+"-"+i,"aria-expanded":!1}),t.config.i18n[i]),a=o.createElement("span",{class:t.config.classNames.menu.value});a.innerHTML=e[i],s.appendChild(a),n.appendChild(s),g.appendChild(n),t.elements.settings.tabs[i]=n}),m.appendChild(g),h.appendChild(m),this.config.settings.forEach(function(i){var n=o.createElement("div",{id:"plyr-settings-"+e.id+"-"+i,"aria-hidden":!0,"aria-labelled-by":"plyr-settings-"+e.id+"-"+i+"-tab",role:"tabpanel",tabindex:-1,hidden:""}),s=o.createElement("button",{type:"button",class:t.config.classNames.control+" "+t.config.classNames.control+"--back","aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id+"-home","aria-expanded":!1},t.config.i18n[i]);n.appendChild(s);var a=o.createElement("ul");n.appendChild(a),h.appendChild(n),t.elements.settings.panes[i]=n}),p.appendChild(h),d.appendChild(p),i.appendChild(d),this.elements.settings.form=p,this.elements.settings.menu=d}return this.config.controls.includes("pip")&&l.pip&&i.appendChild(y.createButton.call(this,"pip")),this.config.controls.includes("airplay")&&l.airplay&&i.appendChild(y.createButton.call(this,"airplay")),this.config.controls.includes("fullscreen")&&i.appendChild(y.createButton.call(this,"fullscreen")),this.config.controls.includes("play-large")&&this.elements.container.appendChild(y.createButton.call(this,"play-large")),this.elements.controls=i,this.config.controls.includes("settings")&&this.config.settings.includes("speed")&&y.setSpeedMenu.call(this),i},inject:function(){var e=this;if(this.config.loadSprite){var t=y.getIconUrl.call(this);t.absolute&&o.loadSprite(t.url,"sprite-plyr")}this.id=Math.floor(1e4*Math.random());var i=null;i=o.is.string(this.config.controls)?this.config.controls:o.is.function(this.config.controls)?this.config.controls({id:this.id,seektime:this.config.seekTime,title:this.config.title}):y.create.call(this,{id:this.id,seektime:this.config.seekTime,speed:this.speed,quality:this.quality,captions:y.getLanguage.call(this)});var n=void 0;if(o.is.string(this.config.selectors.controls.container)&&(n=document.querySelector(this.config.selectors.controls.container)),o.is.element(n)||(n=this.elements.container),o.is.element(i)?n.appendChild(i):n.insertAdjacentHTML("beforeend",i),o.is.element(this.elements.controls)&&o.findElements.call(this),window.navigator.userAgent.includes("Edge")&&o.repaint(n),this.config.tooltips.controls){var s=o.getElements.call(this,[this.config.selectors.controls.wrapper," ",this.config.selectors.labels," .",this.config.classNames.hidden].join(""));Array.from(s).forEach(function(t){o.toggleClass(t,e.config.classNames.hidden,!1),o.toggleClass(t,e.config.classNames.tooltip,!0),t.setAttribute("role","tooltip")})}}},b={setup:function(){if(this.supported.ui){var e=this.storage.get("language");if(o.is.empty(e)||(this.captions.language=e),o.is.empty(this.captions.language)&&(this.captions.language=this.config.captions.language.toLowerCase()),!o.is.boolean(this.captions.active)){var t=this.storage.get("captions");o.is.boolean(t)?this.captions.active=t:this.captions.active=this.config.captions.active}!this.isVideo||this.isYouTube||this.isHTML5&&!l.textTracks?this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&y.setCaptionsMenu.call(this):(o.is.element(this.elements.captions)||(this.elements.captions=o.createElement("div",o.getAttributesFromSelector(this.config.selectors.captions)),o.insertAfter(this.elements.captions,this.elements.wrapper)),o.toggleClass(this.elements.container,this.config.classNames.captions.enabled,!o.is.empty(b.getTracks.call(this))),o.is.empty(b.getTracks.call(this))||(b.setLanguage.call(this),b.show.call(this),this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&y.setCaptionsMenu.call(this)))}},setLanguage:function(){var e=this;if(this.isHTML5&&this.isVideo){b.getTracks.call(this).forEach(function(t){o.on(t,"cuechange",function(t){return b.setCue.call(e,t)}),t.mode="hidden"});var t=b.getCurrentTrack.call(this);o.is.track(t)&&Array.from(t.activeCues||[]).length&&b.setCue.call(this,t)}else this.isVimeo&&this.captions.active&&this.embed.enableTextTrack(this.language)},getTracks:function(){return o.is.nullOrUndefined(this.media)?[]:Array.from(this.media.textTracks||[]).filter(function(e){return["captions","subtitles"].includes(e.kind)})},getCurrentTrack:function(){var e=this;return b.getTracks.call(this).find(function(t){return t.language.toLowerCase()===e.language})},setCue:function(e){var t=o.is.event(e)?e.target:e,i=t.activeCues[0];t===b.getCurrentTrack.call(this)&&(o.is.cue(i)?b.setText.call(this,i.getCueAsHTML()):b.setText.call(this,null),o.dispatchEvent.call(this,this.media,"cuechange"))},setText:function(e){if(this.supported.ui)if(o.is.element(this.elements.captions)){var t=o.createElement("span");o.emptyElement(this.elements.captions);var i=o.is.nullOrUndefined(e)?"":e;o.is.string(i)?t.textContent=i.trim():t.appendChild(i),this.elements.captions.appendChild(t)}else this.debug.warn("No captions element to render to")},show:function(){if(o.is.element(this.elements.buttons.captions)){var e=this.storage.get("captions");o.is.boolean(e)?this.captions.active=e:e=this.config.captions.active,e&&(o.toggleClass(this.elements.container,this.config.classNames.captions.active,!0),o.toggleState(this.elements.buttons.captions,!0))}}},v={setup:function(){var e=this,t=o.parseYouTubeId(this.embedId),i=o.getElements.call(this,'[id^="'+this.provider+'-"]');Array.from(i).forEach(o.removeElement),o.toggleClass(this.elements.wrapper,this.config.classNames.embed,!0),v.setAspectRatio.call(this),this.media.setAttribute("id",o.generateId(this.provider)),o.is.object(window.YT)?v.ready.call(this,t):(o.loadScript(this.config.urls.youtube.api),window.onYouTubeReadyCallbacks=window.onYouTubeReadyCallbacks||[],window.onYouTubeReadyCallbacks.push(function(){v.ready.call(e,t)}),window.onYouTubeIframeAPIReady=function(){window.onYouTubeReadyCallbacks.forEach(function(e){e()})})},getTitle:function(){var e=this;if(o.is.function(this.embed.getVideoData)){var t=this.embed.getVideoData().title;if(o.is.empty(t))return this.config.title=t,void g.setTitle.call(this)}var i=this.config.keys.google,n=o.parseYouTubeId(this.embedId);if(o.is.string(i)&&!o.is.empty(i)){var s="https://www.googleapis.com/youtube/v3/videos?id="+n+"&key="+i+"&fields=items(snippet(title))&part=snippet";fetch(s).then(function(e){return e.ok?e.json():null}).then(function(t){null!==t&&o.is.object(t)&&(e.config.title=t.items[0].snippet.title,g.setTitle.call(e))}).catch(function(){})}},setAspectRatio:function(){var e=this.config.ratio.split(":");this.elements.wrapper.style.paddingBottom=100/e[0]*e[1]+"%"},ready:function(e){var t=this;t.embed=new window.YT.Player(t.media.id,{videoId:e,playerVars:{autoplay:t.config.autoplay?1:0,controls:t.supported.ui?0:1,rel:0,showinfo:0,iv_load_policy:3,modestbranding:1,disablekb:1,playsinline:1,origin:window&&window.location.hostname,widget_referrer:window&&window.location.href,cc_load_policy:this.captions.active?1:0,cc_lang_pref:this.config.captions.language},events:{onError:function(e){if(!o.is.object(t.media.error)){var i={code:e.data};switch(e.data){case 2:i.message="The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.";break;case 5:i.message="The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.";break;case 100:i.message="The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.";break;case 101:case 150:i.message="The owner of the requested video does not allow it to be played in embedded players.";break;default:i.message="An unknown error occured"}t.media.error=i,o.dispatchEvent.call(t,t.media,"error")}},onPlaybackQualityChange:function(e){var i=e.target;t.media.quality=i.getPlaybackQuality(),o.dispatchEvent.call(t,t.media,"qualitychange")},onPlaybackRateChange:function(e){var i=e.target;t.media.playbackRate=i.getPlaybackRate(),o.dispatchEvent.call(t,t.media,"ratechange")},onReady:function(e){var i=e.target;v.getTitle.call(t),t.media.play=function(){i.playVideo(),t.media.paused=!1},t.media.pause=function(){i.pauseVideo(),t.media.paused=!0},t.media.stop=function(){i.stopVideo(),t.media.paused=!0},t.media.duration=i.getDuration(),t.media.paused=!0,t.media.currentTime=0,Object.defineProperty(t.media,"currentTime",{get:function(){return Number(i.getCurrentTime())},set:function(e){t.media.seeking=!0,o.dispatchEvent.call(t,t.media,"seeking"),i.seekTo(e)}}),Object.defineProperty(t.media,"playbackRate",{get:function(){return i.getPlaybackRate()},set:function(e){i.setPlaybackRate(e)}}),Object.defineProperty(t.media,"quality",{get:function(){return i.getPlaybackQuality()},set:function(e){o.dispatchEvent.call(t,t.media,"qualityrequested",!1,{quality:e}),i.setPlaybackQuality(e)}});var n=t.config.volume;Object.defineProperty(t.media,"volume",{get:function(){return n},set:function(e){n=e,i.setVolume(100*n),o.dispatchEvent.call(t,t.media,"volumechange")}});var s=t.config.muted;Object.defineProperty(t.media,"muted",{get:function(){return s},set:function(e){var n=o.is.boolean(e)?e:s;s=n,i[n?"mute":"unMute"](),o.dispatchEvent.call(t,t.media,"volumechange")}}),Object.defineProperty(t.media,"currentSrc",{get:function(){return i.getVideoUrl()}}),Object.defineProperty(t.media,"ended",{get:function(){return t.currentTime===t.duration}}),t.options.speed=i.getAvailablePlaybackRates(),t.supported.ui&&t.media.setAttribute("tabindex",-1),o.dispatchEvent.call(t,t.media,"timeupdate"),o.dispatchEvent.call(t,t.media,"durationchange"),window.clearInterval(t.timers.buffering),t.timers.buffering=window.setInterval(function(){t.media.buffered=i.getVideoLoadedFraction(),(null===t.media.lastBuffered||t.media.lastBuffered<t.media.buffered)&&o.dispatchEvent.call(t,t.media,"progress"),t.media.lastBuffered=t.media.buffered,1===t.media.buffered&&(window.clearInterval(t.timers.buffering),o.dispatchEvent.call(t,t.media,"canplaythrough"))},200),window.setTimeout(function(){return g.build.call(t)},50)},onStateChange:function(e){var i=e.target;switch(window.clearInterval(t.timers.playing),e.data){case 0:t.media.paused=!0,t.media.loop?(i.stopVideo(),i.playVideo()):o.dispatchEvent.call(t,t.media,"ended");break;case 1:t.media.seeking&&o.dispatchEvent.call(t,t.media,"seeked"),t.media.seeking=!1,t.media.paused&&o.dispatchEvent.call(t,t.media,"play"),t.media.paused=!1,o.dispatchEvent.call(t,t.media,"playing"),t.timers.playing=window.setInterval(function(){o.dispatchEvent.call(t,t.media,"timeupdate")},50),t.media.duration!==i.getDuration()&&(t.media.duration=i.getDuration(),o.dispatchEvent.call(t,t.media,"durationchange")),y.setQualityMenu.call(t,i.getAvailableQualityLevels());break;case 2:t.media.paused=!0,o.dispatchEvent.call(t,t.media,"pause")}o.dispatchEvent.call(t,t.elements.container,"statechange",!1,{code:e.data})}}})}},k={setup:function(){var e=this,t=o.getElements.call(this,'[id^="'+this.provider+'-"]');Array.from(t).forEach(o.removeElement),o.toggleClass(this.elements.wrapper,this.config.classNames.embed,!0),k.setAspectRatio.call(this),this.media.setAttribute("id",o.generateId(this.provider)),o.is.object(window.Vimeo)?k.ready.call(this):o.loadScript(this.config.urls.vimeo.api,function(){k.ready.call(e)})},setAspectRatio:function(e){var t=o.is.string(e)?e.split(":"):this.config.ratio.split(":"),i=100/t[0]*t[1],n=(200-i)/4;this.elements.wrapper.style.paddingBottom=i+"%",this.media.style.transform="translateY(-"+n+"%)"},ready:function(){var e=this,t=this,i={loop:t.config.loop.active,autoplay:t.autoplay,byline:!1,portrait:!1,title:!1,speed:!0,transparent:0,gesture:"media"},n=o.buildUrlParameters(i),s=o.parseVimeoId(t.embedId),a=o.createElement("iframe"),l="https://player.vimeo.com/video/"+s+"?"+n;a.setAttribute("src",l),a.setAttribute("allowfullscreen",""),t.media.appendChild(a),t.embed=new window.Vimeo.Player(a),t.media.paused=!0,t.media.currentTime=0,t.media.play=function(){t.embed.play().then(function(){t.media.paused=!1})},t.media.pause=function(){t.embed.pause().then(function(){t.media.paused=!0})},t.media.stop=function(){t.embed.stop().then(function(){t.media.paused=!0,t.currentTime=0})};var r=t.media.currentTime;Object.defineProperty(t.media,"currentTime",{get:function(){return r},set:function(e){var i=t.media.paused;t.media.seeking=!0,o.dispatchEvent.call(t,t.media,"seeking"),t.embed.setCurrentTime(e),i&&t.pause()}});var c=t.config.speed.selected;Object.defineProperty(t.media,"playbackRate",{get:function(){return c},set:function(e){t.embed.setPlaybackRate(e).then(function(){c=e,o.dispatchEvent.call(t,t.media,"ratechange")})}});var u=t.config.volume;Object.defineProperty(t.media,"volume",{get:function(){return u},set:function(e){t.embed.setVolume(e).then(function(){u=e,o.dispatchEvent.call(t,t.media,"volumechange")})}});var d=t.config.muted;Object.defineProperty(t.media,"muted",{get:function(){return d},set:function(e){var i=!!o.is.boolean(e)&&e;t.embed.setVolume(i?0:t.config.volume).then(function(){d=i,o.dispatchEvent.call(t,t.media,"volumechange")})}});var p=t.config.loop;Object.defineProperty(t.media,"loop",{get:function(){return p},set:function(e){var i=o.is.boolean(e)?e:t.config.loop.active;t.embed.setLoop(i).then(function(){p=i})}});var h=void 0;t.embed.getVideoUrl().then(function(e){h=e}),Object.defineProperty(t.media,"currentSrc",{get:function(){return h}}),Object.defineProperty(t.media,"ended",{get:function(){return t.currentTime===t.duration}}),Promise.all([t.embed.getVideoWidth(),t.embed.getVideoHeight()]).then(function(t){var i=o.getAspectRatio(t[0],t[1]);k.setAspectRatio.call(e,i)}),t.embed.setAutopause(t.config.autopause).then(function(e){t.config.autopause=e}),t.embed.getVideoTitle().then(function(i){t.config.title=i,g.setTitle.call(e)}),t.embed.getCurrentTime().then(function(e){r=e,o.dispatchEvent.call(t,t.media,"timeupdate")}),t.embed.getDuration().then(function(e){t.media.duration=e,o.dispatchEvent.call(t,t.media,"durationchange")}),t.embed.getTextTracks().then(function(e){t.media.textTracks=e,b.setup.call(t)}),t.embed.on("cuechange",function(e){var i=null;e.cues.length&&(i=o.stripHTML(e.cues[0].text)),b.setText.call(t,i)}),t.embed.on("loaded",function(){if(o.is.element(t.embed.element)&&t.supported.ui){t.embed.element.setAttribute("tabindex",-1)}}),t.embed.on("play",function(){t.media.paused&&o.dispatchEvent.call(t,t.media,"play"),t.media.paused=!1,o.dispatchEvent.call(t,t.media,"playing")}),t.embed.on("pause",function(){t.media.paused=!0,o.dispatchEvent.call(t,t.media,"pause")}),t.embed.on("timeupdate",function(e){t.media.seeking=!1,r=e.seconds,o.dispatchEvent.call(t,t.media,"timeupdate")}),t.embed.on("progress",function(e){t.media.buffered=e.percent,o.dispatchEvent.call(t,t.media,"progress"),1===parseInt(e.percent,10)&&o.dispatchEvent.call(t,t.media,"canplaythrough")}),t.embed.on("seeked",function(){t.media.seeking=!1,o.dispatchEvent.call(t,t.media,"seeked"),o.dispatchEvent.call(t,t.media,"play")}),t.embed.on("ended",function(){t.media.paused=!0,o.dispatchEvent.call(t,t.media,"ended")}),t.embed.on("error",function(e){t.media.error=e,o.dispatchEvent.call(t,t.media,"error")}),window.setTimeout(function(){return g.build.call(t)},0)}},w=o.getBrowser(),E={setup:function(){if(this.media)if(o.toggleClass(this.elements.container,this.config.classNames.type.replace("{0}",this.type),!0),o.toggleClass(this.elements.container,this.config.classNames.provider.replace("{0}",this.provider),!0),this.isEmbed&&o.toggleClass(this.elements.container,this.config.classNames.type.replace("{0}","video"),!0),this.supported.ui&&(o.toggleClass(this.elements.container,this.config.classNames.pip.supported,l.pip&&this.isHTML5&&this.isVideo),o.toggleClass(this.elements.container,this.config.classNames.airplay.supported,l.airplay&&this.isHTML5),o.toggleClass(this.elements.container,this.config.classNames.stopped,this.config.autoplay),o.toggleClass(this.elements.container,this.config.classNames.isIos,w.isIos),o.toggleClass(this.elements.container,this.config.classNames.isTouch,l.touch)),(this.isVideo||this.isYouTube||this.isVimeo)&&(this.elements.wrapper=o.createElement("div",{class:this.config.classNames.video}),o.wrap(this.media,this.elements.wrapper)),this.isEmbed)switch(this.provider){case"youtube":v.setup.call(this);break;case"vimeo":k.setup.call(this)}else this.isHTML5&&g.setTitle.call(this);else this.debug.warn("No media element found!")},cancelRequests:function(){this.isHTML5&&(Array.from(this.media.querySelectorAll("source")).forEach(o.removeElement),this.media.setAttribute("src",this.config.blankVideo),this.media.load(),this.debug.log("Cancelled network requests"))}},T={insertElements:function(e,t){var i=this;o.is.string(t)?o.insertElement(e,this.media,{src:t}):o.is.array(t)&&t.forEach(function(t){o.insertElement(e,i.media,t)})},change:function(t){var i=this;o.is.object(t)&&"sources"in t&&t.sources.length?(E.cancelRequests.call(this),this.destroy.call(this,function(){switch(o.removeElement(i.media),i.media=null,o.is.element(i.elements.container)&&i.elements.container.removeAttribute("class"),i.type=t.type,i.provider=o.is.empty(t.sources[0].provider)?e.html5:t.sources[0].provider,i.supported=l.check(i.type,i.provider,i.config.inline),i.provider+":"+i.type){case"html5:video":i.media=o.createElement("video");break;case"html5:audio":i.media=o.createElement("audio");break;case"youtube:video":case"vimeo:video":i.media=o.createElement("div"),i.embedId=t.sources[0].src}i.elements.container.appendChild(i.media),o.is.boolean(t.autoplay)&&(i.config.autoplay=t.autoplay),i.isHTML5&&(i.config.crossorigin&&i.media.setAttribute("crossorigin",""),i.config.autoplay&&i.media.setAttribute("autoplay",""),"poster"in t&&i.media.setAttribute("poster",t.poster),i.config.loop.active&&i.media.setAttribute("loop",""),i.config.muted&&i.media.setAttribute("muted",""),i.config.inline&&i.media.setAttribute("playsinline","")),g.addStyleHook.call(i),i.isHTML5&&T.insertElements.call(i,"source",t.sources),i.config.title=t.title,E.setup.call(i),i.isHTML5&&("tracks"in t&&T.insertElements.call(i,"track",t.tracks),i.media.load()),(i.isHTML5||i.isEmbed&&!i.supported.ui)&&g.build.call(i)},!0)):this.debug.warn("Invalid source format")}},C={x:0,y:0};return function(){function a(s,r){var d=this;if(n(this,a),this.timers={},this.ready=!1,this.loading=!1,this.failed=!1,this.media=s,o.is.string(this.media)&&(this.media=document.querySelectorAll(this.media)),(window.jQuery&&this.media instanceof jQuery||o.is.nodeList(this.media)||o.is.array(this.media))&&(this.media=this.media[0]),this.config=o.extend({},i,r,function(){try{return JSON.parse(d.media.getAttribute("data-plyr-config"))}catch(e){return{}}}()),this.elements={container:null,buttons:{},display:{},progress:{},inputs:{},settings:{menu:null,panes:{},tabs:{}},captions:null},this.captions={active:null,currentTrack:null},this.fullscreen={active:!1},this.options={speed:[],quality:[]},this.debug=new c(this),this.debug.log("Config",this.config),this.debug.log("Support",l),!o.is.nullOrUndefined(this.media)&&o.is.element(this.media))if(this.media.plyr)this.debug.warn("Target already setup");else if(this.config.enabled)if(l.check().api){this.elements.original=this.media.cloneNode(!0);var p=this.media.tagName.toLowerCase(),h="data-plyr-provider",f="data-plyr-embed-id";switch(p){case"div":if(this.type=t.video,this.provider=this.media.getAttribute(h),this.embedId=this.media.getAttribute(f),o.is.empty(this.provider)||!Object.keys(e).includes(this.provider))return void this.debug.error("Setup failed: Invalid provider");if(o.is.empty(this.embedId))return void this.debug.error("Setup failed: Embed ID or URL missing");this.media.removeAttribute(h),this.media.removeAttribute(f);break;case"video":case"audio":this.type=p,this.provider=e.html5,this.media.hasAttribute("crossorigin")&&(this.config.crossorigin=!0),this.media.hasAttribute("autoplay")&&(this.config.autoplay=!0),this.media.hasAttribute("playsinline")&&(this.config.inline=!0),this.media.hasAttribute("muted")&&(this.config.muted=!0),this.media.hasAttribute("loop")&&(this.config.loop.active=!0);break;default:return void this.debug.error("Setup failed: unsupported type")}this.storage=new u(this),this.supported=l.check(this.type,this.provider,this.config.inline),this.supported.api?(this.media.plyr=this,this.elements.container=o.createElement("div"),o.wrap(this.media,this.elements.container),this.elements.container.setAttribute("tabindex",0),m.global.call(this),g.addStyleHook.call(this),E.setup.call(this),this.config.debug&&o.on(this.elements.container,this.config.events.join(" "),function(e){d.debug.log("event: "+e.type)}),(this.isHTML5||this.isEmbed&&!this.supported.ui)&&g.build.call(this)):this.debug.error("Setup failed: no support")}else this.debug.error("Setup failed: no support");else this.debug.error("Setup failed: disabled by config");else this.debug.error("Setup failed: no suitable element passed")}return s(a,[{key:"play",value:function(){return this.media.play()}},{key:"pause",value:function(){this.playing&&this.media.pause()}},{key:"togglePlay",value:function(e){(o.is.boolean(e)?e:!this.playing)?this.play():this.pause()}},{key:"stop",value:function(){this.restart(),this.pause()}},{key:"restart",value:function(){this.currentTime=0}},{key:"rewind",value:function(e){this.currentTime=this.currentTime-(o.is.number(e)?e:this.config.seekTime)}},{key:"forward",value:function(e){this.currentTime=this.currentTime+(o.is.number(e)?e:this.config.seekTime)}},{key:"increaseVolume",value:function(e){var t=this.media.muted?0:this.volume;this.volume=t+(o.is.number(e)?e:1)}},{key:"decreaseVolume",value:function(e){var t=this.media.muted?0:this.volume;this.volume=t-(o.is.number(e)?e:1)}},{key:"toggleCaptions",value:function(e){if(this.supported.ui&&o.is.element(this.elements.buttons.captions)){var t=o.is.boolean(e)?e:-1===this.elements.container.className.indexOf(this.config.classNames.captions.active);this.captions.active!==t&&(this.captions.active=t,o.toggleState(this.elements.buttons.captions,this.captions.active),o.toggleClass(this.elements.container,this.config.classNames.captions.active,this.captions.active),o.dispatchEvent.call(this,this.media,this.captions.active?"captionsenabled":"captionsdisabled"))}}},{key:"toggleFullscreen",value:function(e){if(!this.isAudio){if(p.enabled){if(!o.is.event(e)||e.type!==p.eventType)return void(this.fullscreen.active?p.cancelFullScreen():p.requestFullScreen(this.elements.container));this.fullscreen.active=p.isFullScreen(this.elements.container)}else this.fullscreen.active=!this.fullscreen.active,o.toggleClass(this.elements.container,this.config.classNames.fullscreen.fallback,this.fullscreen.active),this.fullscreen.active?C={x:window.pageXOffset||0,y:window.pageYOffset||0}:window.scrollTo(C.x,C.y),document.body.style.overflow=this.fullscreen.active?"hidden":"";o.is.element(this.elements.buttons.fullscreen)&&o.toggleState(this.elements.buttons.fullscreen,this.fullscreen.active),o.dispatchEvent.call(this,this.media,this.fullscreen.active?"enterfullscreen":"exitfullscreen")}}},{key:"airplay",value:function(){l.airplay&&this.media.webkitShowPlaybackTargetPicker()}},{key:"toggleControls",value:function(e){var t=this;if(o.is.element(this.elements.controls)&&this.supported.ui&&!this.isAudio){var i=0,n=e,s=!1;if(o.is.boolean(e)||(o.is.event(e)?(s="enterfullscreen"===e.type,n=["mouseenter","mousemove","touchstart","touchmove","focusin"].includes(e.type),["mousemove","touchmove","touchend"].includes(e.type)&&(i=2e3),"focusin"===e.type&&(i=3e3,o.toggleClass(this.elements.controls,this.config.classNames.noTransition,!0))):n=o.hasClass(this.elements.container,this.config.classNames.hideControls)),window.clearTimeout(this.timers.controls),n||this.paused||this.loading){if(o.toggleClass(this.elements.container,this.config.classNames.hideControls,!1)&&o.dispatchEvent.call(this,this.media,"controlsshown"),this.paused||this.loading)return;l.touch&&(i=3e3)}n&&!this.playing||(this.timers.controls=window.setTimeout(function(){if(!t.elements.controls.pressed&&!t.elements.controls.hover||s){o.hasClass(t.elements.container,t.config.classNames.hideControls)||o.toggleClass(t.elements.controls,t.config.classNames.noTransition,!1);o.toggleClass(t.elements.container,t.config.classNames.hideControls,!0)&&(o.dispatchEvent.call(t,t.media,"controlshidden"),t.config.controls.includes("settings")&&!o.is.empty(t.config.settings)&&y.toggleMenu.call(t,!1))}},i))}}},{key:"on",value:function(e,t){o.on(this.elements.container,e,t)}},{key:"off",value:function(e,t){o.off(this.elements.container,e,t)}},{key:"destroy",value:function(e){var t=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=function(){if(document.body.style.overflow="",t.embed=null,t.embedId=null,i)Object.keys(t.elements).length&&(t.elements.buttons&&t.elements.buttons.play&&Array.from(t.elements.buttons.play).forEach(function(e){return o.removeElement(e)}),o.removeElement(t.elements.captions),o.removeElement(t.elements.controls),o.removeElement(t.elements.wrapper),t.elements.buttons.play=null,t.elements.captions=null,t.elements.controls=null,t.elements.wrapper=null),o.is.function(e)&&e();else{var n=t.elements.container.parentNode;o.is.element(n)&&n.replaceChild(t.elements.original,t.elements.container),o.dispatchEvent.call(t,t.elements.original,"destroyed",!0),o.is.function(e)&&e.call(t.elements.original),t.elements=null}};switch(this.provider+":"+this.type){case"html5:video":case"html5:audio":g.toggleNativeControls.call(this,!0),n();break;case"youtube:video":window.clearInterval(this.timers.buffering),window.clearInterval(this.timers.playing),this.embed.destroy(),n();break;case"vimeo:video":this.embed.unload().then(n),window.setTimeout(n,200)}}},{key:"supports",value:function(e){return l.mime.call(this,e)}},{key:"isHTML5",get:function(){return this.provider===e.html5}},{key:"isEmbed",get:function(){return this.isYouTube||this.isVimeo}},{key:"isYouTube",get:function(){return this.provider===e.youtube}},{key:"isVimeo",get:function(){return this.provider===e.vimeo}},{key:"isVideo",get:function(){return this.type===t.video}},{key:"isAudio",get:function(){return this.type===t.audio}},{key:"paused",get:function(){return this.media.paused}},{key:"playing",get:function(){return!this.paused&&!this.ended&&(!this.isHTML5||this.media.readyState>2)}},{key:"ended",get:function(){return this.media.ended}},{key:"currentTime",set:function(e){var t=0;o.is.number(e)&&(t=e),t<0?t=0:t>this.duration&&(t=this.duration),this.media.currentTime=t.toFixed(4),this.debug.log("Seeking to "+this.currentTime+" seconds")},get:function(){return Number(this.media.currentTime)}},{key:"seeking",get:function(){return this.media.seeking}},{key:"duration",get:function(){var e=parseInt(this.config.duration,10),t=Number(this.media.duration);return Number.isNaN(e)?t:e}},{key:"volume",set:function(e){var t=e;o.is.string(t)&&(t=Number(t)),o.is.number(t)||(t=this.storage.get("volume")),o.is.number(t)||(t=this.config.volume),t>1&&(t=1),t<0&&(t=0),this.config.volume=t,this.media.volume=t,this.muted&&t>0&&(this.muted=!1)},get:function(){return this.media.volume}},{key:"muted",set:function(e){var t=e;o.is.boolean(t)||(t=this.storage.get("muted")),o.is.boolean(t)||(t=this.config.muted),this.config.muted=t,this.media.muted=t},get:function(){return this.media.muted}},{key:"hasAudio",get:function(){return!this.isHTML5||(this.media.mozHasAudio||Boolean(this.media.webkitAudioDecodedByteCount)||Boolean(this.media.audioTracks&&this.media.audioTracks.length))}},{key:"speed",set:function(e){var t=null;o.is.number(e)&&(t=e),o.is.number(t)||(t=this.storage.get("speed")),o.is.number(t)||(t=this.config.speed.selected),t<.1&&(t=.1),t>2&&(t=2),this.config.speed.options.includes(t)?(this.config.speed.selected=t,this.media.playbackRate=t):this.debug.warn("Unsupported speed ("+t+")")},get:function(){return this.media.playbackRate}},{key:"quality",set:function(e){var t=null;o.is.string(e)&&(t=e),o.is.string(t)||(t=this.storage.get("quality")),o.is.string(t)||(t=this.config.quality.selected),this.options.quality.includes(t)?(this.config.quality.selected=t,this.media.quality=t):this.debug.warn("Unsupported quality option ("+t+")")},get:function(){return this.media.quality}},{key:"loop",set:function(e){var t=o.is.boolean(e)?e:this.config.loop.active;this.config.loop.active=t,this.media.loop=t},get:function(){return this.media.loop}},{key:"source",set:function(e){T.change.call(this,e)},get:function(){return this.media.currentSrc}},{key:"poster",set:function(e){this.isHTML5&&this.isVideo?o.is.string(e)&&this.media.setAttribute("poster",e):this.debug.warn("Poster can only be set on HTML5 video")},get:function(){return this.isHTML5&&this.isVideo?this.media.getAttribute("poster"):null}},{key:"autoplay",set:function(e){var t=o.is.boolean(e)?e:this.config.autoplay;this.config.autoplay=t},get:function(){return this.config.autoplay}},{key:"language",set:function(e){if(o.is.string(e)&&(this.toggleCaptions(!o.is.empty(e)),!o.is.empty(e))){var t=e.toLowerCase();this.language!==t&&(this.captions.language=t,b.setText.call(this,null),b.setLanguage.call(this),o.dispatchEvent.call(this,this.media,"languagechange"))}},get:function(){return this.captions.language}},{key:"pip",set:function(e){var t="picture-in-picture",i="inline";if(l.pip){var n=o.is.boolean(e)?e:this.pip===i;this.media.webkitSetPresentationMode(n?t:i)}},get:function(){return l.pip?this.media.webkitPresentationMode:null}}],[{key:"supported",value:function(e,t,i){return l.check(e,t,i)}},{key:"loadSprite",value:function(e,t){return o.loadSprite(e,t)}}]),a}()}); + +//# sourceMappingURL=plyr.js.map diff --git a/dist/plyr.js.map b/dist/plyr.js.map new file mode 100644 index 00000000..6efd836e --- /dev/null +++ b/dist/plyr.js.map @@ -0,0 +1 @@ +{"version":3,"file":"plyr.js","sources":["src/js/types.js","src/js/defaults.js","src/js/utils.js","src/js/support.js","src/js/console.js","src/js/storage.js","src/js/fullscreen.js","src/js/listeners.js","src/js/ui.js","src/js/controls.js","src/js/captions.js","src/js/plugins/youtube.js","src/js/plugins/vimeo.js","src/js/media.js","src/js/source.js","src/js/plyr.js"],"sourcesContent":["// ==========================================================================\n// Plyr supported types and providers\n// ==========================================================================\n\nexport const providers = {\n html5: 'html5',\n youtube: 'youtube',\n vimeo: 'vimeo',\n};\n\nexport const types = {\n audio: 'audio',\n video: 'video',\n};\n\nexport default { providers, types };\n","// Default config\nconst defaults = {\n // Disable\n enabled: true,\n\n // Custom media title\n title: '',\n\n // Logging to console\n debug: false,\n\n // Auto play (if supported)\n autoplay: false,\n\n // Only allow one media playing at once (vimeo only)\n autopause: true,\n\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n\n // Default volume\n volume: 1,\n muted: false,\n\n // Pass a custom duration\n duration: null,\n\n // Display the media duration on load in the current time position\n // If you have opted to display both duration and currentTime, this is ignored\n displayDuration: true,\n\n // Invert the current time to be a countdown\n invertTime: true,\n\n // Clicking the currentTime inverts it's value to show time left rather than elapsed\n toggleInvert: true,\n\n // Aspect ratio (for embeds)\n ratio: '16:9',\n\n // Click video container to play/pause\n clickToPlay: true,\n\n // Auto hide the controls\n hideControls: true,\n\n // Revert to poster on finish (HTML5 - will cause reload)\n showPosterOnEnd: false,\n\n // Disable the standard context menu\n disableContextMenu: true,\n\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/2.0.10/plyr.svg',\n\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n // Quality default\n quality: {\n default: 'default',\n options: [\n 'hd2160',\n 'hd1440',\n 'hd1080',\n 'hd720',\n 'large',\n 'medium',\n 'small',\n 'tiny',\n 'default',\n ],\n },\n\n // Set loops\n loop: {\n active: false,\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n options: [\n 0.5,\n 0.75,\n 1,\n 1.25,\n 1.5,\n 1.75,\n 2,\n ],\n },\n\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false,\n },\n\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true,\n },\n\n // Captions settings\n captions: {\n active: false,\n language: window.navigator.language.split('-')[0],\n },\n\n // Fullscreen settings\n fullscreen: {\n enabled: true, // Allow fullscreen?\n fallback: true, // Fallback for vintage browsers\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr',\n },\n\n // Default controls\n controls: [\n 'play-large',\n 'play',\n 'progress',\n 'current-time',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n 'fullscreen',\n ],\n settings: [\n 'captions',\n 'quality',\n 'speed',\n ],\n\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime} secs',\n play: 'Play',\n pause: 'Pause',\n forward: 'Forward {seektime} secs',\n seek: 'Seek',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n mute: 'Mute',\n unmute: 'Unmute',\n enableCaptions: 'Enable captions',\n disableCaptions: 'Disable captions',\n enterFullscreen: 'Enter fullscreen',\n exitFullscreen: 'Exit fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n speed: 'Speed',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n none: 'None',\n disabled: 'Disabled',\n },\n\n // URLs\n urls: {\n vimeo: {\n api: 'https://player.vimeo.com/api/player.js',\n },\n youtube: {\n api: 'https://www.youtube.com/iframe_api',\n },\n },\n\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n forward: null,\n mute: null,\n volume: null,\n captions: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null,\n },\n\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended',\n 'progress',\n 'stalled',\n 'playing',\n 'waiting',\n 'canplay',\n 'canplaythrough',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'timeupdate',\n 'volumechange',\n 'play',\n 'pause',\n 'error',\n 'seeking',\n 'seeked',\n 'emptied',\n 'ratechange',\n 'cuechange',\n\n // Custom events\n 'enterfullscreen',\n 'exitfullscreen',\n 'captionsenabled',\n 'captionsdisabled',\n 'languagechange',\n 'controlshidden',\n 'controlsshown',\n 'ready',\n\n // YouTube\n 'statechange',\n 'qualitychange',\n 'qualityrequested',\n ],\n\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls',\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n forward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]',\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]',\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress--buffer',\n played: '.plyr__progress--played',\n loop: '.plyr__progress--loop',\n volume: '.plyr__volume--display',\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n menu: {\n quality: '.js-plyr__menu__list--quality',\n },\n },\n\n // Class hooks added to the player in different states\n classNames: {\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n control: 'plyr__control',\n type: 'plyr--{0}',\n provider: 'plyr--{0}',\n stopped: 'plyr--stopped',\n playing: 'plyr--playing',\n loading: 'plyr--loading',\n error: 'plyr--has-error',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isIos: 'plyr--is-ios',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n noTransition: 'plyr--no-transition',\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n open: 'plyr--menu-open',\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active',\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback',\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active',\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active',\n },\n tabFocus: 'plyr__tab-focus',\n },\n\n // API keys\n keys: {\n google: null,\n },\n};\n\nexport default defaults;\n","// ==========================================================================\n// Plyr utils\n// ==========================================================================\n\nimport support from './support';\n\nconst utils = {\n // Check variable types\n is: {\n plyr(input) {\n return this.instanceof(input, Plyr);\n },\n object(input) {\n return this.getConstructor(input) === Object;\n },\n number(input) {\n return this.getConstructor(input) === Number && !Number.isNaN(input);\n },\n string(input) {\n return this.getConstructor(input) === String;\n },\n boolean(input) {\n return this.getConstructor(input) === Boolean;\n },\n function(input) {\n return this.getConstructor(input) === Function;\n },\n array(input) {\n return !this.nullOrUndefined(input) && Array.isArray(input);\n },\n weakMap(input) {\n return this.instanceof(input, window.WeakMap);\n },\n nodeList(input) {\n return this.instanceof(input, window.NodeList);\n },\n element(input) {\n return this.instanceof(input, window.Element);\n },\n textNode(input) {\n return this.getConstructor(input) === Text;\n },\n event(input) {\n return this.instanceof(input, window.Event);\n },\n cue(input) {\n return this.instanceof(input, window.TextTrackCue) || this.instanceof(input, window.VTTCue);\n },\n track(input) {\n return this.instanceof(input, TextTrack) || (!this.nullOrUndefined(input) && this.string(input.kind));\n },\n nullOrUndefined(input) {\n return input === null || typeof input === 'undefined';\n },\n empty(input) {\n return (\n this.nullOrUndefined(input) ||\n ((this.string(input) || this.array(input) || this.nodeList(input)) && !input.length) ||\n (this.object(input) && !Object.keys(input).length)\n );\n },\n instanceof(input, constructor) {\n return Boolean(input && constructor && input instanceof constructor);\n },\n getConstructor(input) {\n return !this.nullOrUndefined(input) ? input.constructor : null;\n },\n },\n\n // Unfortunately, due to mixed support, UA sniffing is required\n getBrowser() {\n return {\n isIE: /* @cc_on!@ */ false || !!document.documentMode,\n isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),\n };\n },\n\n // Load an external script\n loadScript(url, callback) {\n const current = document.querySelector(`script[src=\"${url}\"]`);\n\n // Check script is not already referenced, if so wait for load\n if (current !== null) {\n current.callbacks = current.callbacks || [];\n current.callbacks.push(callback);\n return;\n }\n\n // Build the element\n const element = document.createElement('script');\n\n // Callback queue\n element.callbacks = element.callbacks || [];\n element.callbacks.push(callback);\n\n // Bind callback\n if (utils.is.function(callback)) {\n element.addEventListener(\n 'load',\n event => {\n element.callbacks.forEach(cb => cb.call(null, event));\n element.callbacks = null;\n },\n false\n );\n }\n\n // Set the URL after binding callback\n element.src = url;\n\n // Inject\n const first = document.getElementsByTagName('script')[0];\n first.parentNode.insertBefore(element, first);\n },\n\n // Load an external SVG sprite\n loadSprite(url, id) {\n if (!utils.is.string(url)) {\n return;\n }\n\n const prefix = 'cache-';\n const hasId = utils.is.string(id);\n let isCached = false;\n\n function updateSprite(data) {\n // Inject content\n this.innerHTML = data;\n\n // Inject the SVG to the body\n document.body.insertBefore(this, document.body.childNodes[0]);\n }\n\n // Only load once\n if (!hasId || !document.querySelectorAll(`#${id}`).length) {\n // Create container\n const container = document.createElement('div');\n utils.toggleHidden(container, true);\n\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (support.storage) {\n const cached = window.localStorage.getItem(prefix + id);\n isCached = cached !== null;\n\n if (isCached) {\n const data = JSON.parse(cached);\n updateSprite.call(container, data.content);\n return;\n }\n }\n\n // Get the sprite\n fetch(url)\n .then(response => (response.ok ? response.text() : null))\n .then(text => {\n if (text === null) {\n return;\n }\n\n if (support.storage) {\n window.localStorage.setItem(\n prefix + id,\n JSON.stringify({\n content: text,\n })\n );\n }\n\n updateSprite.call(container, text);\n })\n .catch(() => {});\n }\n },\n\n // Generate a random ID\n generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n },\n\n // Determine if we're in an iframe\n inFrame() {\n try {\n return window.self !== window.top;\n } catch (e) {\n return true;\n }\n },\n\n // Wrap an element\n wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets)\n .reverse()\n .forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n },\n\n // Create a DocumentFragment\n createElement(type, attributes, text) {\n // Create a new <element>\n const element = document.createElement(type);\n\n // Set all passed attributes\n if (utils.is.object(attributes)) {\n utils.setAttributes(element, attributes);\n }\n\n // Add text node\n if (utils.is.string(text)) {\n element.textContent = text;\n }\n\n // Return built element\n return element;\n },\n\n // Inaert an element after another\n insertAfter(element, target) {\n target.parentNode.insertBefore(element, target.nextSibling);\n },\n\n // Insert a DocumentFragment\n insertElement(type, parent, attributes, text) {\n // Inject the new <element>\n parent.appendChild(utils.createElement(type, attributes, text));\n },\n\n // Remove an element\n removeElement(element) {\n if (!utils.is.element(element) || !utils.is.element(element.parentNode)) {\n return null;\n }\n\n element.parentNode.removeChild(element);\n\n return element;\n },\n\n // Remove all child elements\n emptyElement(element) {\n let { length } = element.childNodes;\n\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n },\n\n // Set attributes\n setAttributes(element, attributes) {\n if (!utils.is.element(element) || utils.is.empty(attributes)) {\n return;\n }\n\n Object.keys(attributes).forEach(key => {\n element.setAttribute(key, attributes[key]);\n });\n },\n\n // Get an attribute object from a string selector\n getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!utils.is.string(sel) || utils.is.empty(sel)) {\n return {};\n }\n\n const attributes = {};\n const existing = existingAttributes;\n\n sel.split(',').forEach(s => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n\n // Get the parts and value\n const parts = stripped.split('=');\n const key = parts[0];\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n\n // Get the first character\n const start = selector.charAt(0);\n\n switch (start) {\n case '.':\n // Add to existing classname\n if (utils.is.object(existing) && utils.is.string(existing.class)) {\n existing.class += ` ${className}`;\n }\n\n attributes.class = className;\n break;\n\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n\n case '[':\n // Attribute selector\n attributes[key] = value;\n\n break;\n\n default:\n break;\n }\n });\n\n return attributes;\n },\n\n // Toggle class on an element\n toggleClass(element, className, toggle) {\n if (utils.is.element(element)) {\n const contains = element.classList.contains(className);\n\n element.classList[toggle ? 'add' : 'remove'](className);\n\n return (toggle && !contains) || (!toggle && contains);\n }\n\n return null;\n },\n\n // Has class name\n hasClass(element, className) {\n return utils.is.element(element) && element.classList.contains(className);\n },\n\n // Toggle hidden attribute on an element\n toggleHidden(element, toggle) {\n if (!utils.is.element(element)) {\n return;\n }\n\n if (toggle) {\n element.setAttribute('hidden', '');\n } else {\n element.removeAttribute('hidden');\n }\n },\n\n // Element matches selector\n matches(element, selector) {\n const prototype = { Element };\n\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n\n const matches = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match;\n\n return matches.call(element, selector);\n },\n\n // Find all elements\n getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n },\n\n // Find a single element\n getElement(selector) {\n return this.elements.container.querySelector(selector);\n },\n\n // Find the UI controls and store references in custom controls\n // TODO: Allow settings menus with custom controls\n findElements() {\n try {\n this.elements.controls = utils.getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: utils.getElements.call(this, this.config.selectors.buttons.play),\n pause: utils.getElement.call(this, this.config.selectors.buttons.pause),\n restart: utils.getElement.call(this, this.config.selectors.buttons.restart),\n rewind: utils.getElement.call(this, this.config.selectors.buttons.rewind),\n forward: utils.getElement.call(this, this.config.selectors.buttons.forward),\n mute: utils.getElement.call(this, this.config.selectors.buttons.mute),\n pip: utils.getElement.call(this, this.config.selectors.buttons.pip),\n airplay: utils.getElement.call(this, this.config.selectors.buttons.airplay),\n settings: utils.getElement.call(this, this.config.selectors.buttons.settings),\n captions: utils.getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: utils.getElement.call(this, this.config.selectors.buttons.fullscreen),\n };\n\n // Progress\n this.elements.progress = utils.getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: utils.getElement.call(this, this.config.selectors.inputs.seek),\n volume: utils.getElement.call(this, this.config.selectors.inputs.volume),\n };\n\n // Display\n this.elements.display = {\n buffer: utils.getElement.call(this, this.config.selectors.display.buffer),\n duration: utils.getElement.call(this, this.config.selectors.display.duration),\n currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime),\n };\n\n // Seek tooltip\n if (utils.is.element(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(`.${this.config.classNames.tooltip}`);\n }\n\n return true;\n } catch (error) {\n // Log it\n this.debug.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n\n return false;\n }\n },\n\n // Get the focused element\n getFocusElement() {\n let focused = document.activeElement;\n\n if (!focused || focused === document.body) {\n focused = null;\n } else {\n focused = document.querySelector(':focus');\n }\n\n return focused;\n },\n\n // Trap focus inside container\n trapFocus() {\n const focusable = utils.getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n utils.on(\n this.elements.container,\n 'keydown',\n event => {\n // Bail if not tab key or not fullscreen\n if (event.key !== 'Tab' || event.keyCode !== 9 || !this.fullscreen.active) {\n return;\n }\n\n // Get the current focused element\n const focused = utils.getFocusElement();\n\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n },\n false\n );\n },\n\n // Toggle event listener\n toggleListener(elements, event, callback, toggle, passive, capture) {\n // Bail if no elements\n if (utils.is.nullOrUndefined(elements)) {\n return;\n }\n\n // If a nodelist is passed, call itself on each node\n if (utils.is.nodeList(elements)) {\n // Create listener for each node\n Array.from(elements).forEach(element => {\n if (element instanceof Node) {\n utils.toggleListener.call(null, element, event, callback, toggle, passive, capture);\n }\n });\n\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n\n // Build options\n // Default to just capture boolean\n let options = utils.is.boolean(capture) ? capture : false;\n\n // If passive events listeners are supported\n if (support.passiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive: utils.is.boolean(passive) ? passive : true,\n // Whether the listener is a capturing listener or not\n capture: utils.is.boolean(capture) ? capture : false,\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach(type => {\n elements[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n },\n\n // Bind event handler\n on(element, events, callback, passive, capture) {\n utils.toggleListener(element, events, callback, true, passive, capture);\n },\n\n // Unbind event handler\n off(element, events, callback, passive, capture) {\n utils.toggleListener(element, events, callback, false, passive, capture);\n },\n\n // Trigger event\n dispatchEvent(element, type, bubbles, detail) {\n // Bail if no element\n if (!element || !type) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles: utils.is.boolean(bubbles) ? bubbles : false,\n detail: Object.assign({}, detail, {\n plyr: this instanceof Plyr ? this : null,\n }),\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n },\n\n // Toggle aria-pressed state on a toggle button\n // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles\n toggleState(element, input) {\n // Bail if no target\n if (!utils.is.element(element)) {\n return;\n }\n\n // Get state\n const pressed = element.getAttribute('aria-pressed') === 'true';\n const state = utils.is.boolean(input) ? input : !pressed;\n\n // Set the attribute on target\n element.setAttribute('aria-pressed', state);\n },\n\n // Get percentage\n getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n return (current / max * 100).toFixed(2);\n },\n\n // Deep extend destination object with N more objects\n extend(target = {}, ...sources) {\n if (!sources.length) {\n return target;\n }\n\n const source = sources.shift();\n\n if (!utils.is.object(source)) {\n return target;\n }\n\n Object.keys(source).forEach(key => {\n if (utils.is.object(source[key])) {\n if (!Object.keys(target).includes(key)) {\n Object.assign(target, { [key]: {} });\n }\n\n utils.extend(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n });\n\n return utils.extend(target, ...sources);\n },\n\n // Parse YouTube ID from URL\n parseYouTubeId(url) {\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Parse Vimeo ID from URL\n parseVimeoId(url) {\n if (utils.is.number(Number(url))) {\n return url;\n }\n\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Convert object to URL parameters\n buildUrlParameters(input) {\n if (!utils.is.object(input)) {\n return '';\n }\n\n return Object.keys(input)\n .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(input[key])}`)\n .join('&');\n },\n\n // Remove HTML from a string\n stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n },\n\n // Get aspect ratio for dimensions\n getAspectRatio(width, height) {\n const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h));\n const ratio = getRatio(width, height);\n return `${width / ratio}:${height / ratio}`;\n },\n\n // Get the transition end event\n transitionEnd: (() => {\n const element = document.createElement('span');\n\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend',\n };\n\n const type = Object.keys(events).find(event => element.style[event] !== undefined);\n\n return typeof type === 'string' ? type : false;\n })(),\n\n // Force repaint of element\n repaint(element) {\n window.setTimeout(() => {\n element.setAttribute('hidden', '');\n element.offsetHeight; // eslint-disable-line\n element.removeAttribute('hidden');\n }, 0);\n },\n};\n\nexport default utils;\n","// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport utils from './utils';\n\n// Check for feature support\nconst support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n\n // Check for support\n // Basic functionality vs full UI\n check(type, provider, inline) {\n let api = false;\n let ui = false;\n const browser = utils.getBrowser();\n const playsInline = browser.isIPhone && inline && support.inline;\n\n switch (`${provider}:${type}`) {\n case 'html5:video':\n api = support.video;\n ui = api && support.rangeInput && (!browser.isIPhone || playsInline);\n break;\n\n case 'html5:audio':\n api = support.audio;\n ui = api && support.rangeInput;\n break;\n\n case 'youtube:video':\n api = true;\n ui = support.rangeInput && (!browser.isIPhone || playsInline);\n break;\n\n case 'vimeo:video':\n api = true;\n ui = support.rangeInput && !browser.isIPhone;\n break;\n\n default:\n api = support.audio && support.video;\n ui = api && support.rangeInput;\n }\n\n return {\n api,\n ui,\n };\n },\n\n // Picture-in-picture support\n // Safari only currently\n pip: (() => {\n const browser = utils.getBrowser();\n return !browser.isIPhone && utils.is.function(utils.createElement('video').webkitSetPresentationMode);\n })(),\n\n // Airplay support\n // Safari only currently\n airplay: utils.is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n inline: 'playsInline' in document.createElement('video'),\n\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(type) {\n const { media } = this;\n\n try {\n // Bail if no checking function\n if (!this.isHTML5 || !utils.is.function(media.canPlayType)) {\n return false;\n }\n\n // Type specific checks\n if (this.isVideo) {\n switch (type) {\n case 'video/webm':\n return media.canPlayType('video/webm; codecs=\"vp8, vorbis\"').replace(/no/, '');\n\n case 'video/mp4':\n return media.canPlayType('video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"').replace(/no/, '');\n\n case 'video/ogg':\n return media.canPlayType('video/ogg; codecs=\"theora\"').replace(/no/, '');\n\n default:\n return false;\n }\n } else if (this.isAudio) {\n switch (type) {\n case 'audio/mpeg':\n return media.canPlayType('audio/mpeg;').replace(/no/, '');\n\n case 'audio/ogg':\n return media.canPlayType('audio/ogg; codecs=\"vorbis\"').replace(/no/, '');\n\n case 'audio/wav':\n return media.canPlayType('audio/wav; codecs=\"1\"').replace(/no/, '');\n\n default:\n return false;\n }\n }\n } catch (e) {\n return false;\n }\n\n // If we got this far, we're stuffed\n return false;\n },\n\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n\n // Check for passive event listener support\n // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n // https://www.youtube.com/watch?v=NPM6172J22g\n passiveListeners: (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n },\n });\n window.addEventListener('test', null, options);\n } catch (e) {\n // Do nothing\n }\n\n return supported;\n })(),\n\n // <input type=\"range\"> Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n\n // Touch\n // Remember a device can be moust + touch enabled\n touch: 'ontouchstart' in document.documentElement,\n\n // Detect transitions support\n transitions: utils.transitionEnd !== false,\n\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n","// ==========================================================================\n// Console wrapper\n// ==========================================================================\n\nconst noop = () => {};\n\nexport default class Console {\n constructor(player) {\n this.enabled = window.console && player.config.debug;\n\n if (this.enabled) {\n this.log('Debugging enabled');\n }\n }\n\n get log() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;\n }\n get warn() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;\n }\n get error() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;\n }\n}\n","// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport utils from './utils';\n\nclass Storage {\n constructor(player) {\n this.enabled = player.config.storage.enabled;\n this.key = player.config.storage.key;\n }\n\n // Check for actual support (see if we can use it)\n static get supported() {\n if (!('localStorage' in window)) {\n return false;\n }\n\n const test = '___test';\n\n // Try to use it (it might be disabled, e.g. user is in private mode)\n // see: https://github.com/sampotts/plyr/issues/131\n try {\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n return true;\n } catch (e) {\n return false;\n }\n }\n\n get(key) {\n const store = window.localStorage.getItem(this.key);\n\n if (!Storage.supported || utils.is.empty(store)) {\n return null;\n }\n\n const json = JSON.parse(store);\n\n return utils.is.string(key) && key.length ? json[key] : json;\n }\n\n set(object) {\n // Bail if we don't have localStorage support or it's disabled\n if (!Storage.supported || !this.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!utils.is.object(object)) {\n return;\n }\n\n // Get current storage\n const storage = this.get();\n\n // Update the working copy of the values\n utils.extend(storage, object);\n\n // Update storage\n window.localStorage.setItem(this.key, JSON.stringify(storage));\n }\n}\n\nexport default Storage;\n","// ==========================================================================\n// Plyr fullscreen API\n// ==========================================================================\n\nimport utils from './utils';\n\n// Determine the prefix\nconst prefix = (() => {\n let value = false;\n\n if (utils.is.function(document.cancelFullScreen)) {\n value = '';\n } else {\n // Check for fullscreen support by vendor prefix\n [\n 'webkit',\n 'o',\n 'moz',\n 'ms',\n 'khtml',\n ].some(pre => {\n if (utils.is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n } else if (utils.is.function(document.msExitFullscreen) && document.msFullscreenEnabled) {\n // Special case for MS (when isn't it?)\n value = 'ms';\n return true;\n }\n\n return false;\n });\n }\n\n return value;\n})();\n\n// Fullscreen API\nconst fullscreen = {\n // Get the prefix\n prefix,\n\n // Check if we can use it\n enabled: document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled,\n\n // Yet again Microsoft awesomeness,\n // Sometimes the prefix is 'ms', sometimes 'MS' to keep you on your toes\n eventType: prefix === 'ms' ? 'MSFullscreenChange' : `${prefix}fullscreenchange`,\n\n // Is an element fullscreen\n isFullScreen(element) {\n if (!fullscreen.enabled) {\n return false;\n }\n\n const target = utils.is.nullOrUndefined(element) ? document.body : element;\n\n switch (prefix) {\n case '':\n return document.fullscreenElement === target;\n\n case 'moz':\n return document.mozFullScreenElement === target;\n\n default:\n return document[`${prefix}FullscreenElement`] === target;\n }\n },\n\n // Make an element fullscreen\n requestFullScreen(element) {\n if (!fullscreen.enabled) {\n return false;\n }\n\n const target = utils.is.nullOrUndefined(element) ? document.body : element;\n\n return !prefix.length ? target.requestFullScreen() : target[prefix + (prefix === 'ms' ? 'RequestFullscreen' : 'RequestFullScreen')]();\n },\n\n // Bail from fullscreen\n cancelFullScreen() {\n if (!fullscreen.enabled) {\n return false;\n }\n\n return !prefix.length ? document.cancelFullScreen() : document[prefix + (prefix === 'ms' ? 'ExitFullscreen' : 'CancelFullScreen')]();\n },\n\n // Get the current element\n element() {\n if (!fullscreen.enabled) {\n return null;\n }\n\n return !prefix.length ? document.fullscreenElement : document[`${prefix}FullscreenElement`];\n },\n\n // Setup fullscreen\n setup() {\n if (!this.supported.ui || this.isAudio || !this.config.fullscreen.enabled) {\n return;\n }\n\n // Check for native support\n const nativeSupport = fullscreen.enabled;\n\n if (nativeSupport || (this.config.fullscreen.fallback && !utils.inFrame())) {\n this.debug.log(`${nativeSupport ? 'Native' : 'Fallback'} fullscreen enabled`);\n\n // Add styling hook to show button\n utils.toggleClass(this.elements.container, this.config.classNames.fullscreen.enabled, true);\n } else {\n this.debug.log('Fullscreen not supported and fallback disabled');\n }\n\n // Toggle state\n if (this.elements.buttons && this.elements.buttons.fullscreen) {\n utils.toggleState(this.elements.buttons.fullscreen, false);\n }\n\n // Trap focus in container\n utils.trapFocus.call(this);\n },\n};\n\nexport default fullscreen;\n","// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport controls from './controls';\nimport fullscreen from './fullscreen';\nimport ui from './ui';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst listeners = {\n // Global listeners\n global() {\n let last = null;\n\n // Get the key code for an event\n const getKeyCode = event => (event.keyCode ? event.keyCode : event.which);\n\n // Handle key press\n const handleKey = event => {\n const code = getKeyCode(event);\n const pressed = event.type === 'keydown';\n const repeat = pressed && code === last;\n\n // Bail if a modifier key is set\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return;\n }\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the keycode for whatever reason\n if (!utils.is.number(code)) {\n return;\n }\n\n // Seek by the number keys\n const seekByKey = () => {\n // Divide the max duration into 10th's and times by the number value\n this.currentTime = this.duration / 10 * (code - 48);\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Which keycodes should we prevent default\n const preventDefault = [\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 56,\n 57,\n 32,\n 75,\n 38,\n 40,\n 77,\n 39,\n 37,\n 70,\n 67,\n 73,\n 76,\n 79,\n ];\n\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = utils.getFocusElement();\n if (utils.is.element(focused) && utils.matches(focused, this.config.selectors.editable)) {\n return;\n }\n\n // If the code is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(code)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (code) {\n case 48:\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57:\n // 0-9\n if (!repeat) {\n seekByKey();\n }\n break;\n\n case 32:\n case 75:\n // Space and K key\n if (!repeat) {\n this.togglePlay();\n }\n break;\n\n case 38:\n // Arrow up\n this.increaseVolume(0.1);\n break;\n\n case 40:\n // Arrow down\n this.decreaseVolume(0.1);\n break;\n\n case 77:\n // M key\n if (!repeat) {\n this.muted = !this.muted;\n }\n break;\n\n case 39:\n // Arrow forward\n this.forward();\n break;\n\n case 37:\n // Arrow back\n this.rewind();\n break;\n\n case 70:\n // F key\n this.toggleFullscreen();\n break;\n\n case 67:\n // C key\n if (!repeat) {\n this.toggleCaptions();\n }\n break;\n\n case 76:\n // L key\n this.loop = !this.loop;\n break;\n\n /* case 73:\n this.setLoop('start');\n break;\n\n case 76:\n this.setLoop();\n break;\n\n case 79:\n this.setLoop('end');\n break; */\n\n default:\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (!fullscreen.enabled && this.fullscreen.active && code === 27) {\n this.toggleFullscreen();\n }\n\n // Store last code for next cycle\n last = code;\n } else {\n last = null;\n }\n };\n\n // Keyboard shortcuts\n if (this.config.keyboard.global) {\n utils.on(window, 'keydown keyup', handleKey, false);\n } else if (this.config.keyboard.focused) {\n utils.on(this.elements.container, 'keydown keyup', handleKey, false);\n }\n\n // Detect tab focus\n // Remove class on blur/focusout\n utils.on(this.elements.container, 'focusout', event => {\n utils.toggleClass(event.target, this.config.classNames.tabFocus, false);\n });\n\n // Add classname to tabbed elements\n utils.on(this.elements.container, 'keydown', event => {\n if (event.keyCode !== 9) {\n return;\n }\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n window.setTimeout(() => {\n utils.toggleClass(utils.getFocusElement(), this.config.classNames.tabFocus, true);\n }, 0);\n });\n\n // Toggle controls visibility based on mouse movement\n if (this.config.hideControls) {\n // Toggle controls on mouse events and entering fullscreen\n utils.on(this.elements.container, 'mouseenter mouseleave mousemove touchstart touchend touchmove enterfullscreen exitfullscreen', event => {\n this.toggleControls(event);\n });\n }\n\n // Handle user exiting fullscreen by escaping etc\n if (fullscreen.enabled) {\n utils.on(document, fullscreen.eventType, event => {\n this.toggleFullscreen(event);\n });\n\n // Fullscreen toggle on double click\n utils.on(this.elements.container, 'dblclick', event => {\n this.toggleFullscreen(event);\n });\n }\n },\n\n // Listen for media events\n media() {\n // Time change on media\n utils.on(this.media, 'timeupdate seeking', event => ui.timeUpdate.call(this, event));\n\n // Display duration\n utils.on(this.media, 'durationchange loadedmetadata', event => ui.durationUpdate.call(this, event));\n\n // Check for audio tracks on load\n // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point\n utils.on(this.media, 'loadeddata', () => {\n utils.toggleHidden(this.elements.volume, !this.hasAudio);\n utils.toggleHidden(this.elements.buttons.mute, !this.hasAudio);\n });\n\n // Handle the media finishing\n utils.on(this.media, 'ended', () => {\n // Show poster on end\n if (this.isHTML5 && this.isVideo && this.config.showPosterOnEnd) {\n // Restart\n this.restart();\n\n // Re-load media\n this.media.load();\n }\n });\n\n // Check for buffer progress\n utils.on(this.media, 'progress playing', event => ui.updateProgress.call(this, event));\n\n // Handle native mute\n utils.on(this.media, 'volumechange', event => ui.updateVolume.call(this, event));\n\n // Handle native play/pause\n utils.on(this.media, 'playing play pause ended', event => ui.checkPlaying.call(this, event));\n\n // Loading\n utils.on(this.media, 'stalled waiting canplay seeked playing', event => ui.checkLoading.call(this, event));\n\n // Check if media failed to load\n // utils.on(this.media, 'play', event => ui.checkFailed.call(this, event));\n\n // Click video\n if (this.supported.ui && this.config.clickToPlay && !this.isAudio) {\n // Re-fetch the wrapper\n const wrapper = utils.getElement.call(this, `.${this.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!utils.is.element(wrapper)) {\n return;\n }\n\n // On click play, pause ore restart\n utils.on(wrapper, 'click', () => {\n // Touch devices will just show controls (if we're hiding controls)\n if (this.config.hideControls && support.touch && !this.paused) {\n return;\n }\n\n if (this.paused) {\n this.play();\n } else if (this.ended) {\n this.restart();\n this.play();\n } else {\n this.pause();\n }\n });\n }\n\n // Disable right click\n if (this.supported.ui && this.config.disableContextMenu) {\n utils.on(\n this.media,\n 'contextmenu',\n event => {\n event.preventDefault();\n },\n false\n );\n }\n\n // Volume change\n utils.on(this.media, 'volumechange', () => {\n // Save to storage\n this.storage.set({ volume: this.volume, muted: this.muted });\n });\n\n // Speed change\n utils.on(this.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(this, 'speed');\n\n // Save to storage\n this.storage.set({ speed: this.speed });\n });\n\n // Quality change\n utils.on(this.media, 'qualitychange', () => {\n // Update UI\n controls.updateSetting.call(this, 'quality');\n\n // Save to storage\n this.storage.set({ quality: this.quality });\n });\n\n // Caption language change\n utils.on(this.media, 'languagechange', () => {\n // Update UI\n controls.updateSetting.call(this, 'captions');\n\n // Save to storage\n this.storage.set({ language: this.language });\n });\n\n // Captions toggle\n utils.on(this.media, 'captionsenabled captionsdisabled', () => {\n // Update UI\n controls.updateSetting.call(this, 'captions');\n\n // Save to storage\n this.storage.set({ captions: this.captions.active });\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n utils.on(this.media, this.config.events.concat([\n 'keyup',\n 'keydown',\n ]).join(' '), event => {\n let detail = {};\n\n // Get error details from media\n if (event.type === 'error') {\n detail = this.media.error;\n }\n\n utils.dispatchEvent.call(this, this.elements.container, event.type, true, detail);\n });\n },\n\n // Listen for control events\n controls() {\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Trigger custom and default handlers\n const proxy = (event, handlerKey, defaultHandler) => {\n const customHandler = this.config.listeners[handlerKey];\n\n // Execute custom handler\n if (utils.is.function(customHandler)) {\n customHandler.call(this, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (!event.defaultPrevented && utils.is.function(defaultHandler)) {\n defaultHandler.call(this, event);\n }\n };\n\n // Play/pause toggle\n utils.on(this.elements.buttons.play, 'click', event =>\n proxy(event, 'play', () => {\n this.togglePlay();\n })\n );\n\n // Pause\n utils.on(this.elements.buttons.restart, 'click', event =>\n proxy(event, 'restart', () => {\n this.restart();\n })\n );\n\n // Rewind\n utils.on(this.elements.buttons.rewind, 'click', event =>\n proxy(event, 'rewind', () => {\n this.rewind();\n })\n );\n\n // Rewind\n utils.on(this.elements.buttons.forward, 'click', event =>\n proxy(event, 'forward', () => {\n this.forward();\n })\n );\n\n // Mute toggle\n utils.on(this.elements.buttons.mute, 'click', event =>\n proxy(event, 'mute', () => {\n this.muted = !this.muted;\n })\n );\n\n // Captions toggle\n utils.on(this.elements.buttons.captions, 'click', event =>\n proxy(event, 'captions', () => {\n this.toggleCaptions();\n })\n );\n\n // Fullscreen toggle\n utils.on(this.elements.buttons.fullscreen, 'click', event =>\n proxy(event, 'fullscreen', () => {\n this.toggleFullscreen();\n })\n );\n\n // Picture-in-Picture\n utils.on(this.elements.buttons.pip, 'click', event =>\n proxy(event, 'pip', () => {\n this.pip = 'toggle';\n })\n );\n\n // Airplay\n utils.on(this.elements.buttons.airplay, 'click', event =>\n proxy(event, 'airplay', () => {\n this.airplay();\n })\n );\n\n // Settings menu\n utils.on(this.elements.buttons.settings, 'click', event => {\n controls.toggleMenu.call(this, event);\n });\n\n // Click anywhere closes menu\n utils.on(document.documentElement, 'click', event => {\n controls.toggleMenu.call(this, event);\n });\n\n // Settings menu\n utils.on(this.elements.settings.form, 'click', event => {\n event.stopPropagation();\n\n // Settings menu items - use event delegation as items are added/removed\n if (utils.matches(event.target, this.config.selectors.inputs.language)) {\n proxy(event, 'language', () => {\n this.language = event.target.value;\n });\n } else if (utils.matches(event.target, this.config.selectors.inputs.quality)) {\n proxy(event, 'quality', () => {\n this.quality = event.target.value;\n });\n } else if (utils.matches(event.target, this.config.selectors.inputs.speed)) {\n proxy(event, 'speed', () => {\n this.speed = parseFloat(event.target.value);\n });\n } else {\n controls.showTab.call(this, event);\n }\n });\n\n // Seek\n utils.on(this.elements.inputs.seek, inputEvent, event =>\n proxy(event, 'seek', () => {\n this.currentTime = event.target.value / event.target.max * this.duration;\n })\n );\n\n // Current time invert\n // Only if one time element is used for both currentTime and duration\n if (this.config.toggleInvert && !utils.is.element(this.elements.display.duration)) {\n utils.on(this.elements.display.currentTime, 'click', () => {\n // Do nothing if we're at the start\n if (this.currentTime === 0) {\n return;\n }\n\n this.config.invertTime = !this.config.invertTime;\n ui.timeUpdate.call(this);\n });\n }\n\n // Volume\n utils.on(this.elements.inputs.volume, inputEvent, event =>\n proxy(event, 'volume', () => {\n this.volume = event.target.value;\n })\n );\n\n // Polyfill for lower fill in <input type=\"range\"> for webkit\n if (browser.isWebkit) {\n utils.on(utils.getElements.call(this, 'input[type=\"range\"]'), 'input', event => {\n controls.updateRangeFill.call(this, event.target);\n });\n }\n\n // Seek tooltip\n utils.on(this.elements.progress, 'mouseenter mouseleave mousemove', event => controls.updateSeekTooltip.call(this, event));\n\n // Toggle controls visibility based on mouse movement\n if (this.config.hideControls) {\n // Watch for cursor over controls so they don't hide when trying to interact\n utils.on(this.elements.controls, 'mouseenter mouseleave', event => {\n this.elements.controls.hover = event.type === 'mouseenter';\n });\n\n // Watch for cursor over controls so they don't hide when trying to interact\n utils.on(this.elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n this.elements.controls.pressed = [\n 'mousedown',\n 'touchstart',\n ].includes(event.type);\n });\n\n // Focus in/out on controls\n utils.on(this.elements.controls, 'focusin focusout', event => {\n this.toggleControls(event);\n });\n }\n\n // Mouse wheel for volume\n utils.on(\n this.elements.inputs.volume,\n 'wheel',\n event =>\n proxy(event, 'volume', () => {\n // Detect \"natural\" scroll - suppored on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n const step = 1 / 50;\n let direction = 0;\n\n // Scroll down (or up on natural) to decrease\n if (event.deltaY < 0 || event.deltaX > 0) {\n if (inverted) {\n this.decreaseVolume(step);\n direction = -1;\n } else {\n this.increaseVolume(step);\n direction = 1;\n }\n }\n\n // Scroll up (or down on natural) to increase\n if (event.deltaY > 0 || event.deltaX < 0) {\n if (inverted) {\n this.increaseVolume(step);\n direction = 1;\n } else {\n this.decreaseVolume(step);\n direction = -1;\n }\n }\n\n // Don't break page scrolling at max and min\n if ((direction === 1 && this.media.volume < 1) || (direction === -1 && this.media.volume > 0)) {\n event.preventDefault();\n }\n }),\n false\n );\n },\n};\n\nexport default listeners;\n","// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport utils from './utils';\nimport captions from './captions';\nimport controls from './controls';\nimport fullscreen from './fullscreen';\nimport listeners from './listeners';\n\nconst ui = {\n addStyleHook() {\n utils.toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n utils.toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle = false) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling\n listeners.media.call(this);\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.debug.warn(`Basic support only for ${this.provider} ${this.type}`);\n\n // Remove controls\n utils.removeElement.call(this, 'controls');\n\n // Remove large play\n utils.removeElement.call(this, 'buttons.play');\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!utils.is.element(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n listeners.controls.call(this);\n }\n\n // If there's no controls, bail\n if (!utils.is.element(this.elements.controls)) {\n return;\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Setup fullscreen\n fullscreen.setup.call(this);\n\n // Captions\n captions.setup.call(this);\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality options\n this.options.quality = [];\n\n // Reset time display\n ui.timeUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n utils.dispatchEvent.call(this, this.media, 'ready');\n\n // Set the title\n ui.setTitle.call(this);\n },\n\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = this.config.i18n.play;\n\n // If there's a media title set, use that for the label\n if (utils.is.string(this.config.title) && !utils.is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n\n // Set container label\n this.elements.container.setAttribute('aria-label', this.config.title);\n }\n\n // If there's a play button, set label\n if (utils.is.nodeList(this.elements.buttons.play)) {\n Array.from(this.elements.buttons.play).forEach(button => {\n button.setAttribute('aria-label', label);\n });\n }\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = utils.getElement.call(this, 'iframe');\n\n if (!utils.is.element(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !utils.is.empty(this.config.title) ? this.config.title : 'video';\n\n iframe.setAttribute('title', this.config.i18n.frameTitle.replace('{title}', title));\n }\n },\n\n // Check playing state\n checkPlaying() {\n // Class hooks\n utils.toggleClass(this.elements.container, this.config.classNames.playing, this.playing);\n utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.paused);\n\n // Set aria state\n if (utils.is.nodeList(this.elements.buttons.play)) {\n Array.from(this.elements.buttons.play).forEach(button => utils.toggleState(button, this.playing));\n }\n\n // Toggle controls\n this.toggleControls(!this.playing);\n },\n\n // Check if media is loading\n checkLoading(event) {\n this.loading = this.media.networkState === 2 || [\n 'stalled',\n 'waiting',\n ].includes(event.type);\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Toggle container class hook\n utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Show controls if loading, hide if done\n this.toggleControls(this.loading);\n }, this.loading ? 250 : 0);\n },\n\n // Check if media failed to load\n checkFailed() {\n // https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/networkState\n this.failed = this.media.networkState === 3;\n\n if (this.failed) {\n utils.toggleClass(this.elements.container, this.config.classNames.loading, false);\n utils.toggleClass(this.elements.container, this.config.classNames.error, true);\n }\n\n // Clear timer\n clearTimeout(this.timers.failed);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Toggle container class hook\n utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Show controls if loading, hide if done\n this.toggleControls(this.loading);\n }, this.loading ? 250 : 0);\n },\n\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (utils.is.element(this.elements.inputs.volume)) {\n ui.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update mute state\n if (utils.is.element(this.elements.buttons.mute)) {\n utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0);\n }\n },\n\n // Update seek value and lower fill\n setRange(target, value = 0) {\n if (!utils.is.element(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n\n // Set <progress> value\n setProgress(target, input) {\n const value = utils.is.number(input) ? input : 0;\n const progress = utils.is.element(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (utils.is.element(progress)) {\n progress.value = value;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (utils.is.element(label)) {\n label.childNodes[0].nodeValue = value;\n }\n }\n },\n\n // Update <progress> elements\n updateProgress(event) {\n if (!this.supported.ui || !utils.is.event(event)) {\n return;\n }\n\n let value = 0;\n\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n value = utils.getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n ui.setRange.call(this, this.elements.inputs.seek, value);\n }\n\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n value = (() => {\n const { buffered } = this.media;\n\n if (buffered && buffered.length) {\n // HTML5\n return utils.getPercentage(buffered.end(0), this.duration);\n } else if (utils.is.number(buffered)) {\n // YouTube returns between 0 and 1\n return buffered * 100;\n }\n\n return 0;\n })();\n\n ui.setProgress.call(this, this.elements.display.buffer, value);\n\n break;\n\n default:\n break;\n }\n }\n },\n\n // Update the displayed time\n updateTimeDisplay(target = null, time = 0, inverted = false) {\n // Bail if there's no element to display or the value isn't a number\n if (!utils.is.element(target) || !utils.is.number(time)) {\n return;\n }\n\n // Format time component to add leading zero\n const format = value => `0${value}`.slice(-2);\n\n // Helpers\n const getHours = value => parseInt((value / 60 / 60) % 60, 10);\n const getMinutes = value => parseInt((value / 60) % 60, 10);\n const getSeconds = value => parseInt(value % 60, 10);\n\n // Breakdown to hours, mins, secs\n let hours = getHours(time);\n const mins = getMinutes(time);\n const secs = getSeconds(time);\n\n // Do we need to display hours?\n if (getHours(this.duration) > 0) {\n hours = `${hours}:`;\n } else {\n hours = '';\n }\n\n // Render\n // eslint-disable-next-line no-param-reassign\n target.textContent = `${inverted ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;\n },\n\n // Handle time change event\n timeUpdate(event) {\n // Only invert if only one time element is displayed and used for both duration and currentTime\n const invert = !utils.is.element(this.elements.display.duration) && this.config.invertTime;\n\n // Duration\n ui.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert);\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n ui.updateProgress.call(this, event);\n },\n\n // Show the duration on metadataloaded\n durationUpdate() {\n if (!this.supported.ui) {\n return;\n }\n\n // If there's only one time display, display duration there\n if (!utils.is.element(this.elements.display.duration) && this.config.displayDuration && this.paused) {\n ui.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration);\n }\n\n // If there's a duration element, update content\n if (utils.is.element(this.elements.display.duration)) {\n ui.updateTimeDisplay.call(this, this.elements.display.duration, this.duration);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n};\n\nexport default ui;\n","// ==========================================================================\n// Plyr controls\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport ui from './ui';\nimport captions from './captions';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst controls = {\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // WebKit only\n if (!browser.isWebkit) {\n return;\n }\n\n // Get range from event if event passed\n const range = utils.is.event(target) ? target.target : target;\n\n // Needs to be a valid <input type='range'>\n if (!utils.is.element(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Inject the stylesheet if needed\n if (!utils.is.element(this.elements.styleSheet)) {\n this.elements.styleSheet = utils.createElement('style');\n this.elements.container.appendChild(this.elements.styleSheet);\n }\n\n const styleSheet = this.elements.styleSheet.sheet;\n const percentage = range.value / range.max * 100;\n const selector = `#${range.id}::-webkit-slider-runnable-track`;\n const styles = `{ background-image: linear-gradient(to right, currentColor ${percentage}%, transparent ${percentage}%) }`;\n\n // Find old rule if it exists\n const index = Array.from(styleSheet.rules).findIndex(rule => rule.selectorText === selector);\n\n // Remove old rule\n if (index !== -1) {\n styleSheet.deleteRule(index);\n }\n\n // Insert new one\n styleSheet.insertRule([\n selector,\n styles,\n ].join(' '));\n },\n\n // Get icon URL\n getIconUrl() {\n return {\n url: this.config.iconUrl,\n absolute: this.config.iconUrl.indexOf('http') === 0 || (browser.isIE && !window.svg4everybody),\n };\n },\n\n // Create <svg> icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.absolute ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n\n // Create <svg>\n const icon = document.createElementNS(namespace, 'svg');\n utils.setAttributes(\n icon,\n utils.extend(attributes, {\n role: 'presentation',\n })\n );\n\n // Create the <use> to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // Set `href` attributes\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);\n } else {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n }\n\n // Add <use> to <svg>\n icon.appendChild(use);\n\n return icon;\n },\n\n // Create hidden text label\n createLabel(type, attr) {\n let text = this.config.i18n[type];\n const attributes = Object.assign({}, attr);\n\n switch (type) {\n case 'pip':\n text = 'PIP';\n break;\n\n case 'airplay':\n text = 'AirPlay';\n break;\n\n default:\n break;\n }\n\n if ('class' in attributes) {\n attributes.class += ` ${this.config.classNames.hidden}`;\n } else {\n attributes.class = this.config.classNames.hidden;\n }\n\n return utils.createElement('span', attributes, text);\n },\n\n // Create a badge\n createBadge(text) {\n if (utils.is.empty(text)) {\n return null;\n }\n\n const badge = utils.createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n badge.appendChild(\n utils.createElement(\n 'span',\n {\n class: this.config.classNames.menu.badge,\n },\n text\n )\n );\n\n return badge;\n },\n\n // Create a <button>\n createButton(buttonType, attr) {\n const button = utils.createElement('button');\n const attributes = Object.assign({}, attr);\n let type = buttonType;\n\n let toggle = false;\n let label;\n let icon;\n let labelPressed;\n let iconPressed;\n\n if (!('type' in attributes)) {\n attributes.type = 'button';\n }\n\n if ('class' in attributes) {\n if (attributes.class.includes(this.config.classNames.control)) {\n attributes.class += ` ${this.config.classNames.control}`;\n }\n } else {\n attributes.class = this.config.classNames.control;\n }\n\n // Large play button\n switch (type) {\n case 'play':\n toggle = true;\n label = 'play';\n labelPressed = 'pause';\n icon = 'play';\n iconPressed = 'pause';\n break;\n\n case 'mute':\n toggle = true;\n label = 'mute';\n labelPressed = 'unmute';\n icon = 'volume';\n iconPressed = 'muted';\n break;\n\n case 'captions':\n toggle = true;\n label = 'enableCaptions';\n labelPressed = 'disableCaptions';\n icon = 'captions-off';\n iconPressed = 'captions-on';\n break;\n\n case 'fullscreen':\n toggle = true;\n label = 'enterFullscreen';\n labelPressed = 'exitFullscreen';\n icon = 'enter-fullscreen';\n iconPressed = 'exit-fullscreen';\n break;\n\n case 'play-large':\n attributes.class += ` ${this.config.classNames.control}--overlaid`;\n type = 'play';\n label = 'play';\n icon = 'play';\n break;\n\n default:\n label = type;\n icon = type;\n }\n\n // Setup toggle icon and labels\n if (toggle) {\n // Icon\n button.appendChild(controls.createIcon.call(this, iconPressed, { class: 'icon--pressed' }));\n button.appendChild(controls.createIcon.call(this, icon, { class: 'icon--not-pressed' }));\n\n // Label/Tooltip\n button.appendChild(controls.createLabel.call(this, labelPressed, { class: 'label--pressed' }));\n button.appendChild(controls.createLabel.call(this, label, { class: 'label--not-pressed' }));\n\n // Add aria attributes\n attributes['aria-pressed'] = false;\n attributes['aria-label'] = this.config.i18n[label];\n } else {\n button.appendChild(controls.createIcon.call(this, icon));\n button.appendChild(controls.createLabel.call(this, label));\n }\n\n // Merge attributes\n utils.extend(attributes, utils.getAttributesFromSelector(this.config.selectors.buttons[type], attributes));\n\n utils.setAttributes(button, attributes);\n\n this.elements.buttons[type] = button;\n\n return button;\n },\n\n // Create an <input type='range'>\n createRange(type, attributes) {\n // Seek label\n const label = utils.createElement(\n 'label',\n {\n for: attributes.id,\n class: this.config.classNames.hidden,\n },\n this.config.i18n[type]\n );\n\n // Seek input\n const input = utils.createElement(\n 'input',\n utils.extend(\n utils.getAttributesFromSelector(this.config.selectors.inputs[type]),\n {\n type: 'range',\n min: 0,\n max: 100,\n step: 0.01,\n value: 0,\n autocomplete: 'off',\n },\n attributes\n )\n );\n\n this.elements.inputs[type] = input;\n\n // Set the fill for webkit now\n controls.updateRangeFill.call(this, input);\n\n return {\n label,\n input,\n };\n },\n\n // Create a <progress>\n createProgress(type, attributes) {\n const progress = utils.createElement(\n 'progress',\n utils.extend(\n utils.getAttributesFromSelector(this.config.selectors.display[type]),\n {\n min: 0,\n max: 100,\n value: 0,\n },\n attributes\n )\n );\n\n // Create the label inside\n if (type !== 'volume') {\n progress.appendChild(utils.createElement('span', null, '0'));\n\n let suffix = '';\n switch (type) {\n case 'played':\n suffix = this.config.i18n.played;\n break;\n\n case 'buffer':\n suffix = this.config.i18n.buffered;\n break;\n\n default:\n break;\n }\n\n progress.textContent = `% ${suffix.toLowerCase()}`;\n }\n\n this.elements.display[type] = progress;\n\n return progress;\n },\n\n // Create time display\n createTime(type) {\n const container = utils.createElement('div', {\n class: 'plyr__time',\n });\n\n container.appendChild(\n utils.createElement(\n 'span',\n {\n class: this.config.classNames.hidden,\n },\n this.config.i18n[type]\n )\n );\n\n container.appendChild(utils.createElement('span', utils.getAttributesFromSelector(this.config.selectors.display[type]), '00:00'));\n\n this.elements.display[type] = container;\n\n return container;\n },\n\n // Create a settings menu item\n createMenuItem(value, list, type, title, badge = null, checked = false) {\n const item = utils.createElement('li');\n\n const label = utils.createElement('label', {\n class: this.config.classNames.control,\n });\n\n const radio = utils.createElement(\n 'input',\n utils.extend(utils.getAttributesFromSelector(this.config.selectors.inputs[type]), {\n type: 'radio',\n name: `plyr-${type}`,\n value,\n checked,\n class: 'plyr__sr-only',\n })\n );\n\n const faux = utils.createElement('span', { 'aria-hidden': true });\n\n label.appendChild(radio);\n label.appendChild(faux);\n label.insertAdjacentHTML('beforeend', title);\n\n if (utils.is.element(badge)) {\n label.appendChild(badge);\n }\n\n item.appendChild(label);\n list.appendChild(item);\n },\n\n // Update hover tooltip for seeking\n updateSeekTooltip(event) {\n // Bail if setting not true\n if (\n !this.config.tooltips.seek ||\n !utils.is.element(this.elements.inputs.seek) ||\n !utils.is.element(this.elements.display.seekTooltip) ||\n this.duration === 0\n ) {\n return;\n }\n\n // Calculate percentage\n let percent = 0;\n const clientRect = this.elements.inputs.seek.getBoundingClientRect();\n const visible = `${this.config.classNames.tooltip}--visible`;\n\n // Determine percentage, if already visible\n if (utils.is.event(event)) {\n percent = 100 / clientRect.width * (event.pageX - clientRect.left);\n } else if (utils.hasClass(this.elements.display.seekTooltip, visible)) {\n percent = parseFloat(this.elements.display.seekTooltip.style.left, 10);\n } else {\n return;\n }\n\n // Set bounds\n if (percent < 0) {\n percent = 0;\n } else if (percent > 100) {\n percent = 100;\n }\n\n // Display the time a click would seek to\n ui.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent);\n\n // Set position\n this.elements.display.seekTooltip.style.left = `${percent}%`;\n\n // Show/hide the tooltip\n // If the event is a moues in/out and percentage is inside bounds\n if (utils.is.event(event) && [\n 'mouseenter',\n 'mouseleave',\n ].includes(event.type)) {\n utils.toggleClass(this.elements.display.seekTooltip, visible, event.type === 'mouseenter');\n }\n },\n\n // Hide/show a tab\n toggleTab(setting, toggle) {\n const tab = this.elements.settings.tabs[setting];\n const pane = this.elements.settings.panes[setting];\n\n utils.toggleHidden(tab, !toggle);\n utils.toggleHidden(pane, !toggle);\n },\n\n // Set the YouTube quality menu\n // TODO: Support for HTML5\n setQualityMenu(options) {\n const type = 'quality';\n const list = this.elements.settings.panes.quality.querySelector('ul');\n\n // Set options if passed and filter based on config\n if (utils.is.array(options)) {\n this.options.quality = options.filter(quality => this.config.quality.options.includes(quality));\n } else {\n this.options.quality = this.config.quality.options;\n }\n\n // Toggle the pane and tab\n const toggle = !utils.is.empty(this.options.quality) && this.isYouTube;\n controls.toggleTab.call(this, type, toggle);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Empty the menu\n utils.emptyElement(list);\n\n // Get the badge HTML for HD, 4K etc\n const getBadge = quality => {\n let label = '';\n\n switch (quality) {\n case 'hd2160':\n label = '4K';\n break;\n\n case 'hd1440':\n label = 'WQHD';\n break;\n\n case 'hd1080':\n label = 'HD';\n break;\n\n case 'hd720':\n label = 'HD';\n break;\n\n default:\n break;\n }\n\n if (!label.length) {\n return null;\n }\n\n return controls.createBadge.call(this, label);\n };\n\n this.options.quality.forEach(quality =>\n controls.createMenuItem.call(this, quality, list, type, controls.getLabel.call(this, 'quality', quality), getBadge(quality))\n );\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Translate a value into a nice label\n // TODO: Localisation\n getLabel(setting, value) {\n switch (setting) {\n case 'speed':\n return value === 1 ? 'Normal' : `${value}×`;\n\n case 'quality':\n switch (value) {\n case 'hd2160':\n return '2160P';\n case 'hd1440':\n return '1440P';\n case 'hd1080':\n return '1080P';\n case 'hd720':\n return '720P';\n case 'large':\n return '480P';\n case 'medium':\n return '360P';\n case 'small':\n return '240P';\n case 'tiny':\n return 'Tiny';\n case 'default':\n return 'Auto';\n default:\n return value;\n }\n\n case 'captions':\n return controls.getLanguage.call(this);\n\n default:\n return null;\n }\n },\n\n // Update the selected setting\n updateSetting(setting, container) {\n const pane = this.elements.settings.panes[setting];\n let value = null;\n let list = container;\n\n switch (setting) {\n case 'captions':\n value = this.captions.active ? this.captions.language : '';\n break;\n\n default:\n value = this[setting];\n\n // Get default\n if (utils.is.empty(value)) {\n value = this.config[setting].default;\n }\n\n // Unsupported value\n if (!this.options[setting].includes(value)) {\n this.debug.warn(`Unsupported value of '${value}' for ${setting}`);\n return;\n }\n\n // Disabled value\n if (!this.config[setting].options.includes(value)) {\n this.debug.warn(`Disabled value of '${value}' for ${setting}`);\n return;\n }\n\n break;\n }\n\n // Get the list if we need to\n if (!utils.is.element(list)) {\n list = pane && pane.querySelector('ul');\n }\n\n // Update the label\n if (!utils.is.empty(value)) {\n const label = this.elements.settings.tabs[setting].querySelector(`.${this.config.classNames.menu.value}`);\n label.innerHTML = controls.getLabel.call(this, setting, value);\n }\n\n // Find the radio option\n const target = list && list.querySelector(`input[value=\"${value}\"]`);\n\n if (utils.is.element(target)) {\n // Check it\n target.checked = true;\n }\n },\n\n // Set the looping options\n /* setLoopMenu() {\n const options = ['start', 'end', 'all', 'reset'];\n const list = this.elements.settings.panes.loop.querySelector('ul');\n\n // Show the pane and tab\n utils.toggleHidden(this.elements.settings.tabs.loop, false);\n utils.toggleHidden(this.elements.settings.panes.loop, false);\n\n // Toggle the pane and tab\n const toggle = !utils.is.empty(this.loop.options);\n controls.toggleTab.call(this, 'loop', toggle);\n\n // Empty the menu\n utils.emptyElement(list);\n\n options.forEach(option => {\n const item = utils.createElement('li');\n\n const button = utils.createElement(\n 'button',\n utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.loop), {\n type: 'button',\n class: this.config.classNames.control,\n 'data-plyr-loop-action': option,\n }),\n this.config.i18n[option]\n );\n\n if (['start', 'end'].includes(option)) {\n const badge = controls.createBadge.call(this, '00:00');\n button.appendChild(badge);\n }\n\n item.appendChild(button);\n list.appendChild(item);\n });\n }, */\n\n // Get current selected caption language\n // TODO: rework this to user the getter in the API?\n getLanguage() {\n if (!this.supported.ui) {\n return null;\n }\n\n if (!support.textTracks || !captions.getTracks.call(this).length) {\n return this.config.i18n.none;\n }\n\n if (this.captions.active) {\n const currentTrack = captions.getCurrentTrack.call(this);\n\n if (utils.is.track(currentTrack)) {\n return currentTrack.label;\n }\n }\n\n return this.config.i18n.disabled;\n },\n\n // Set a list of available captions languages\n setCaptionsMenu() {\n // TODO: Captions or language? Currently it's mixed\n const type = 'captions';\n const list = this.elements.settings.panes.captions.querySelector('ul');\n\n // Toggle the pane and tab\n const hasTracks = captions.getTracks.call(this).length;\n controls.toggleTab.call(this, type, hasTracks);\n\n // Empty the menu\n utils.emptyElement(list);\n\n // If there's no captions, bail\n if (!hasTracks) {\n return;\n }\n\n // Re-map the tracks into just the data we need\n const tracks = captions.getTracks.call(this).map(track => ({\n language: track.language,\n label: !utils.is.empty(track.label) ? track.label : track.language.toUpperCase(),\n }));\n\n // Add the \"None\" option to turn off captions\n tracks.unshift({\n language: '',\n label: this.config.i18n.none,\n });\n\n // Generate options\n tracks.forEach(track => {\n controls.createMenuItem.call(\n this,\n track.language,\n list,\n 'language',\n track.label || track.language,\n controls.createBadge.call(this, track.language.toUpperCase()),\n track.language.toLowerCase() === this.captions.language.toLowerCase()\n );\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set a list of available captions languages\n setSpeedMenu() {\n const type = 'speed';\n\n // Set the default speeds\n if (!utils.is.object(this.options.speed) || !Object.keys(this.options.speed).length) {\n this.options.speed = [\n 0.5,\n 0.75,\n 1,\n 1.25,\n 1.5,\n 1.75,\n 2,\n ];\n }\n\n // Set options if passed and filter based on config\n this.options.speed = this.options.speed.filter(speed => this.config.speed.options.includes(speed));\n\n // Toggle the pane and tab\n const toggle = !utils.is.empty(this.options.speed);\n controls.toggleTab.call(this, type, toggle);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Get the list to populate\n const list = this.elements.settings.panes.speed.querySelector('ul');\n\n // Show the pane and tab\n utils.toggleHidden(this.elements.settings.tabs.speed, false);\n utils.toggleHidden(this.elements.settings.panes.speed, false);\n\n // Empty the menu\n utils.emptyElement(list);\n\n // Create items\n this.options.speed.forEach(speed => controls.createMenuItem.call(this, speed, list, type, controls.getLabel.call(this, 'speed', speed)));\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Show/hide menu\n toggleMenu(event) {\n const { form } = this.elements.settings;\n const button = this.elements.buttons.settings;\n const show = utils.is.boolean(event) ? event : utils.is.element(form) && form.getAttribute('aria-hidden') === 'true';\n\n if (utils.is.event(event)) {\n const isMenuItem = utils.is.element(form) && form.contains(event.target);\n const isButton = event.target === this.elements.buttons.settings;\n\n // If the click was inside the form or if the click\n // wasn't the button or menu item and we're trying to\n // show the menu (a doc click shouldn't show the menu)\n if (isMenuItem || (!isMenuItem && !isButton && show)) {\n return;\n }\n\n // Prevent the toggle being caught by the doc listener\n if (isButton) {\n event.stopPropagation();\n }\n }\n\n // Set form and button attributes\n if (utils.is.element(button)) {\n button.setAttribute('aria-expanded', show);\n }\n\n if (utils.is.element(form)) {\n form.setAttribute('aria-hidden', !show);\n utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show);\n\n if (show) {\n form.removeAttribute('tabindex');\n } else {\n form.setAttribute('tabindex', -1);\n }\n }\n },\n\n // Get the natural size of a tab\n getTabSize(tab) {\n const clone = tab.cloneNode(true);\n clone.style.position = 'absolute';\n clone.style.opacity = 0;\n clone.setAttribute('aria-hidden', false);\n\n // Prevent input's being unchecked due to the name being identical\n Array.from(clone.querySelectorAll('input[name]')).forEach(input => {\n const name = input.getAttribute('name');\n input.setAttribute('name', `${name}-clone`);\n });\n\n // Append to parent so we get the \"real\" size\n tab.parentNode.appendChild(clone);\n\n // Get the sizes before we remove\n const width = clone.scrollWidth;\n const height = clone.scrollHeight;\n\n // Remove from the DOM\n utils.removeElement(clone);\n\n return {\n width,\n height,\n };\n },\n\n // Toggle Menu\n showTab(event) {\n const { menu } = this.elements.settings;\n const tab = event.target;\n const show = tab.getAttribute('aria-expanded') === 'false';\n const pane = document.getElementById(tab.getAttribute('aria-controls'));\n\n // Nothing to show, bail\n if (!utils.is.element(pane)) {\n return;\n }\n\n // Are we targetting a tab? If not, bail\n const isTab = pane.getAttribute('role') === 'tabpanel';\n if (!isTab) {\n return;\n }\n\n // Hide all other tabs\n // Get other tabs\n const current = menu.querySelector('[role=\"tabpanel\"][aria-hidden=\"false\"]');\n const container = current.parentNode;\n\n // Set other toggles to be expanded false\n Array.from(menu.querySelectorAll(`[aria-controls=\"${current.getAttribute('id')}\"]`)).forEach(toggle => {\n toggle.setAttribute('aria-expanded', false);\n });\n\n // If we can do fancy animations, we'll animate the height/width\n if (support.transitions && !support.reducedMotion) {\n // Set the current width as a base\n container.style.width = `${current.scrollWidth}px`;\n container.style.height = `${current.scrollHeight}px`;\n\n // Get potential sizes\n const size = controls.getTabSize.call(this, pane);\n\n // Restore auto height/width\n const restore = e => {\n // We're only bothered about height and width on the container\n if (e.target !== container || ![\n 'width',\n 'height',\n ].includes(e.propertyName)) {\n return;\n }\n\n // Revert back to auto\n container.style.width = '';\n container.style.height = '';\n\n // Only listen once\n utils.off(container, utils.transitionEnd, restore);\n };\n\n // Listen for the transition finishing and restore auto height/width\n utils.on(container, utils.transitionEnd, restore);\n\n // Set dimensions to target\n container.style.width = `${size.width}px`;\n container.style.height = `${size.height}px`;\n }\n\n // Set attributes on current tab\n current.setAttribute('aria-hidden', true);\n current.setAttribute('tabindex', -1);\n\n // Set attributes on target\n pane.setAttribute('aria-hidden', !show);\n tab.setAttribute('aria-expanded', show);\n pane.removeAttribute('tabindex');\n\n // Focus the first item\n pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus();\n },\n\n // Build the default HTML\n // TODO: Set order based on order in the config.controls array?\n create(data) {\n // Do nothing if we want no controls\n if (utils.is.empty(this.config.controls)) {\n return null;\n }\n\n // Create the container\n const container = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.controls.wrapper));\n\n // Restart button\n if (this.config.controls.includes('restart')) {\n container.appendChild(controls.createButton.call(this, 'restart'));\n }\n\n // Rewind button\n if (this.config.controls.includes('rewind')) {\n container.appendChild(controls.createButton.call(this, 'rewind'));\n }\n\n // Play/Pause button\n if (this.config.controls.includes('play')) {\n container.appendChild(controls.createButton.call(this, 'play'));\n // container.appendChild(controls.createButton.call(this, 'pause'));\n }\n\n // Fast forward button\n if (this.config.controls.includes('fast-forward')) {\n container.appendChild(controls.createButton.call(this, 'fast-forward'));\n }\n\n // Progress\n if (this.config.controls.includes('progress')) {\n const progress = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.progress));\n\n // Seek range slider\n const seek = controls.createRange.call(this, 'seek', {\n id: `plyr-seek-${data.id}`,\n });\n progress.appendChild(seek.label);\n progress.appendChild(seek.input);\n\n // Buffer progress\n progress.appendChild(controls.createProgress.call(this, 'buffer'));\n\n // TODO: Add loop display indicator\n\n // Seek tooltip\n if (this.config.tooltips.seek) {\n const tooltip = utils.createElement(\n 'span',\n {\n role: 'tooltip',\n class: this.config.classNames.tooltip,\n },\n '00:00'\n );\n\n progress.appendChild(tooltip);\n this.elements.display.seekTooltip = tooltip;\n }\n\n this.elements.progress = progress;\n container.appendChild(this.elements.progress);\n }\n\n // Media current time display\n if (this.config.controls.includes('current-time')) {\n container.appendChild(controls.createTime.call(this, 'currentTime'));\n }\n\n // Media duration display\n if (this.config.controls.includes('duration')) {\n container.appendChild(controls.createTime.call(this, 'duration'));\n }\n\n // Toggle mute button\n if (this.config.controls.includes('mute')) {\n container.appendChild(controls.createButton.call(this, 'mute'));\n }\n\n // Volume range control\n if (this.config.controls.includes('volume')) {\n const volume = utils.createElement('div', {\n class: 'plyr__volume',\n });\n\n // Set the attributes\n const attributes = {\n max: 1,\n step: 0.05,\n value: this.config.volume,\n };\n\n // Create the volume range slider\n const range = controls.createRange.call(\n this,\n 'volume',\n utils.extend(attributes, {\n id: `plyr-volume-${data.id}`,\n })\n );\n volume.appendChild(range.label);\n volume.appendChild(range.input);\n\n this.elements.volume = volume;\n\n container.appendChild(volume);\n }\n\n // Toggle captions button\n if (this.config.controls.includes('captions')) {\n container.appendChild(controls.createButton.call(this, 'captions'));\n }\n\n // Settings button / menu\n if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {\n const menu = utils.createElement('div', {\n class: 'plyr__menu',\n });\n\n menu.appendChild(\n controls.createButton.call(this, 'settings', {\n id: `plyr-settings-toggle-${data.id}`,\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}`,\n 'aria-expanded': false,\n })\n );\n\n const form = utils.createElement('form', {\n class: 'plyr__menu__container',\n id: `plyr-settings-${data.id}`,\n 'aria-hidden': true,\n 'aria-labelled-by': `plyr-settings-toggle-${data.id}`,\n role: 'tablist',\n tabindex: -1,\n });\n\n const inner = utils.createElement('div');\n\n const home = utils.createElement('div', {\n id: `plyr-settings-${data.id}-home`,\n 'aria-hidden': false,\n 'aria-labelled-by': `plyr-settings-toggle-${data.id}`,\n role: 'tabpanel',\n });\n\n // Create the tab list\n const tabs = utils.createElement('ul', {\n role: 'tablist',\n });\n\n // Build the tabs\n this.config.settings.forEach(type => {\n const tab = utils.createElement('li', {\n role: 'tab',\n hidden: '',\n });\n\n const button = utils.createElement(\n 'button',\n utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.settings), {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,\n id: `plyr-settings-${data.id}-${type}-tab`,\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}-${type}`,\n 'aria-expanded': false,\n }),\n this.config.i18n[type]\n );\n\n const value = utils.createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n // Speed contains HTML entities\n value.innerHTML = data[type];\n\n button.appendChild(value);\n tab.appendChild(button);\n tabs.appendChild(tab);\n\n this.elements.settings.tabs[type] = tab;\n });\n\n home.appendChild(tabs);\n inner.appendChild(home);\n\n // Build the panes\n this.config.settings.forEach(type => {\n const pane = utils.createElement('div', {\n id: `plyr-settings-${data.id}-${type}`,\n 'aria-hidden': true,\n 'aria-labelled-by': `plyr-settings-${data.id}-${type}-tab`,\n role: 'tabpanel',\n tabindex: -1,\n hidden: '',\n });\n\n const back = utils.createElement(\n 'button',\n {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}-home`,\n 'aria-expanded': false,\n },\n this.config.i18n[type]\n );\n\n pane.appendChild(back);\n\n const options = utils.createElement('ul');\n\n pane.appendChild(options);\n inner.appendChild(pane);\n\n this.elements.settings.panes[type] = pane;\n });\n\n form.appendChild(inner);\n menu.appendChild(form);\n container.appendChild(menu);\n\n this.elements.settings.form = form;\n this.elements.settings.menu = menu;\n }\n\n // Picture in picture button\n if (this.config.controls.includes('pip') && support.pip) {\n container.appendChild(controls.createButton.call(this, 'pip'));\n }\n\n // Airplay button\n if (this.config.controls.includes('airplay') && support.airplay) {\n container.appendChild(controls.createButton.call(this, 'airplay'));\n }\n\n // Toggle fullscreen button\n if (this.config.controls.includes('fullscreen')) {\n container.appendChild(controls.createButton.call(this, 'fullscreen'));\n }\n\n // Larger overlaid play button\n if (this.config.controls.includes('play-large')) {\n this.elements.container.appendChild(controls.createButton.call(this, 'play-large'));\n }\n\n this.elements.controls = container;\n\n if (this.config.controls.includes('settings') && this.config.settings.includes('speed')) {\n controls.setSpeedMenu.call(this);\n }\n\n return container;\n },\n\n // Insert controls\n inject() {\n // Sprite\n if (this.config.loadSprite) {\n const icon = controls.getIconUrl.call(this);\n\n // Only load external sprite using AJAX\n if (icon.absolute) {\n utils.loadSprite(icon.url, 'sprite-plyr');\n }\n }\n\n // Create a unique ID\n this.id = Math.floor(Math.random() * 10000);\n\n // Null by default\n let container = null;\n\n // HTML passed as the option\n if (utils.is.string(this.config.controls)) {\n container = this.config.controls;\n } else if (utils.is.function(this.config.controls)) {\n // A custom function to build controls\n // The function can return a HTMLElement or String\n container = this.config.controls({\n id: this.id,\n seektime: this.config.seekTime,\n title: this.config.title,\n });\n } else {\n // Create controls\n container = controls.create.call(this, {\n id: this.id,\n seektime: this.config.seekTime,\n speed: this.speed,\n quality: this.quality,\n captions: controls.getLanguage.call(this),\n // TODO: Looping\n // loop: 'None',\n });\n }\n\n // Controls container\n let target;\n\n // Inject to custom location\n if (utils.is.string(this.config.selectors.controls.container)) {\n target = document.querySelector(this.config.selectors.controls.container);\n }\n\n // Inject into the container by default\n if (!utils.is.element(target)) {\n target = this.elements.container;\n }\n\n // Inject controls HTML\n if (utils.is.element(container)) {\n target.appendChild(container);\n } else {\n target.insertAdjacentHTML('beforeend', container);\n }\n\n // Find the elements if need be\n if (utils.is.element(this.elements.controls)) {\n utils.findElements.call(this);\n }\n\n // Edge sometimes doesn't finish the paint so force a redraw\n if (window.navigator.userAgent.includes('Edge')) {\n utils.repaint(target);\n }\n\n // Setup tooltips\n if (this.config.tooltips.controls) {\n const labels = utils.getElements.call(\n this,\n [\n this.config.selectors.controls.wrapper,\n ' ',\n this.config.selectors.labels,\n ' .',\n this.config.classNames.hidden,\n ].join('')\n );\n\n Array.from(labels).forEach(label => {\n utils.toggleClass(label, this.config.classNames.hidden, false);\n utils.toggleClass(label, this.config.classNames.tooltip, true);\n label.setAttribute('role', 'tooltip');\n });\n }\n },\n};\n\nexport default controls;\n","// ==========================================================================\n// Plyr Captions\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport controls from './controls';\n\nconst captions = {\n // Setup captions\n setup() {\n // Requires UI support\n if (!this.supported.ui) {\n return;\n }\n\n // Set default language if not set\n const stored = this.storage.get('language');\n\n if (!utils.is.empty(stored)) {\n this.captions.language = stored;\n }\n\n if (utils.is.empty(this.captions.language)) {\n this.captions.language = this.config.captions.language.toLowerCase();\n }\n\n // Set captions enabled state if not set\n if (!utils.is.boolean(this.captions.active)) {\n const active = this.storage.get('captions');\n\n if (utils.is.boolean(active)) {\n this.captions.active = active;\n } else {\n this.captions.active = this.config.captions.active;\n }\n }\n\n // Only Vimeo and HTML5 video supported at this point\n if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) {\n // Clear menu and hide\n if (this.config.controls.includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n\n return;\n }\n\n // Inject the container\n if (!utils.is.element(this.elements.captions)) {\n this.elements.captions = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.captions));\n\n utils.insertAfter(this.elements.captions, this.elements.wrapper);\n }\n\n // Set the class hook\n utils.toggleClass(this.elements.container, this.config.classNames.captions.enabled, !utils.is.empty(captions.getTracks.call(this)));\n\n // If no caption file exists, hide container for caption text\n if (utils.is.empty(captions.getTracks.call(this))) {\n return;\n }\n\n // Set language\n captions.setLanguage.call(this);\n\n // Enable UI\n captions.show.call(this);\n\n // Set available languages in list\n if (this.config.controls.includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n },\n\n // Set the captions language\n setLanguage() {\n // Setup HTML5 track rendering\n if (this.isHTML5 && this.isVideo) {\n captions.getTracks.call(this).forEach(track => {\n // Remove previous bindings\n utils.on(track, 'cuechange', event => captions.setCue.call(this, event));\n\n // Turn off native caption rendering to avoid double captions\n // eslint-disable-next-line\n track.mode = 'hidden';\n });\n\n // Get current track\n const currentTrack = captions.getCurrentTrack.call(this);\n\n // Check if suported kind\n if (utils.is.track(currentTrack)) {\n // If we change the active track while a cue is already displayed we need to update it\n if (Array.from(currentTrack.activeCues || []).length) {\n captions.setCue.call(this, currentTrack);\n }\n }\n } else if (this.isVimeo && this.captions.active) {\n this.embed.enableTextTrack(this.language);\n }\n },\n\n // Get the tracks\n getTracks() {\n // Return empty array at least\n if (utils.is.nullOrUndefined(this.media)) {\n return [];\n }\n\n // Only get accepted kinds\n return Array.from(this.media.textTracks || []).filter(track => [\n 'captions',\n 'subtitles',\n ].includes(track.kind));\n },\n\n // Get the current track for the current language\n getCurrentTrack() {\n return captions.getTracks.call(this).find(track => track.language.toLowerCase() === this.language);\n },\n\n // Display active caption if it contains text\n setCue(input) {\n // Get the track from the event if needed\n const track = utils.is.event(input) ? input.target : input;\n const active = track.activeCues[0];\n const currentTrack = captions.getCurrentTrack.call(this);\n\n // Only display current track\n if (track !== currentTrack) {\n return;\n }\n\n // Display a cue, if there is one\n if (utils.is.cue(active)) {\n captions.setText.call(this, active.getCueAsHTML());\n } else {\n captions.setText.call(this, null);\n }\n\n utils.dispatchEvent.call(this, this.media, 'cuechange');\n },\n\n // Set the current caption\n setText(input) {\n // Requires UI\n if (!this.supported.ui) {\n return;\n }\n\n if (utils.is.element(this.elements.captions)) {\n const content = utils.createElement('span');\n\n // Empty the container\n utils.emptyElement(this.elements.captions);\n\n // Default to empty\n const caption = !utils.is.nullOrUndefined(input) ? input : '';\n\n // Set the span content\n if (utils.is.string(caption)) {\n content.textContent = caption.trim();\n } else {\n content.appendChild(caption);\n }\n\n // Set new caption text\n this.elements.captions.appendChild(content);\n } else {\n this.debug.warn('No captions element to render to');\n }\n },\n\n // Display captions container and button (for initialization)\n show() {\n // If there's no caption toggle, bail\n if (!utils.is.element(this.elements.buttons.captions)) {\n return;\n }\n\n // Try to load the value from storage\n let active = this.storage.get('captions');\n\n // Otherwise fall back to the default config\n if (!utils.is.boolean(active)) {\n ({ active } = this.config.captions);\n } else {\n this.captions.active = active;\n }\n\n if (active) {\n utils.toggleClass(this.elements.container, this.config.classNames.captions.active, true);\n utils.toggleState(this.elements.buttons.captions, true);\n }\n },\n};\n\nexport default captions;\n","// ==========================================================================\n// YouTube plugin\n// ==========================================================================\n\nimport utils from './../utils';\nimport controls from './../controls';\nimport ui from './../ui';\n\nconst youtube = {\n setup() {\n const videoId = utils.parseYouTubeId(this.embedId);\n\n // Remove old containers\n const containers = utils.getElements.call(this, `[id^=\"${this.provider}-\"]`);\n Array.from(containers).forEach(utils.removeElement);\n\n // Add embed class for responsive\n utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set aspect ratio\n youtube.setAspectRatio.call(this);\n\n // Set ID\n this.media.setAttribute('id', utils.generateId(this.provider));\n\n // Setup API\n if (utils.is.object(window.YT)) {\n youtube.ready.call(this, videoId);\n } else {\n // Load the API\n utils.loadScript(this.config.urls.youtube.api);\n\n // Setup callback for the API\n // YouTube has it's own system of course...\n window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || [];\n\n // Add to queue\n window.onYouTubeReadyCallbacks.push(() => {\n youtube.ready.call(this, videoId);\n });\n\n // Set callback to process queue\n window.onYouTubeIframeAPIReady = () => {\n window.onYouTubeReadyCallbacks.forEach(callback => {\n callback();\n });\n };\n }\n },\n\n // Get the media title\n getTitle() {\n // Try via undocumented API method first\n // This method disappears now and then though...\n // https://github.com/sampotts/plyr/issues/709\n if (utils.is.function(this.embed.getVideoData)) {\n const { title } = this.embed.getVideoData();\n\n if (utils.is.empty(title)) {\n this.config.title = title;\n ui.setTitle.call(this);\n return;\n }\n }\n\n // Or via Google API\n const key = this.config.keys.google;\n const videoId = utils.parseYouTubeId(this.embedId);\n if (utils.is.string(key) && !utils.is.empty(key)) {\n const url = `https://www.googleapis.com/youtube/v3/videos?id=${videoId}&key=${key}&fields=items(snippet(title))&part=snippet`;\n\n fetch(url)\n .then(response => (response.ok ? response.json() : null))\n .then(result => {\n if (result !== null && utils.is.object(result)) {\n this.config.title = result.items[0].snippet.title;\n ui.setTitle.call(this);\n }\n })\n .catch(() => {});\n }\n },\n\n // Set aspect ratio\n setAspectRatio() {\n const ratio = this.config.ratio.split(':');\n this.elements.wrapper.style.paddingBottom = `${100 / ratio[0] * ratio[1]}%`;\n },\n\n // API ready\n ready(videoId) {\n const player = this;\n\n // Setup instance\n // https://developers.google.com/youtube/iframe_api_reference\n player.embed = new window.YT.Player(player.media.id, {\n videoId,\n playerVars: {\n autoplay: player.config.autoplay ? 1 : 0, // Autoplay\n controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported\n rel: 0, // No related vids\n showinfo: 0, // Hide info\n iv_load_policy: 3, // Hide annotations\n modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)\n disablekb: 1, // Disable keyboard as we handle it\n playsinline: 1, // Allow iOS inline playback\n\n // Tracking for stats\n origin: window && window.location.hostname,\n widget_referrer: window && window.location.href,\n\n // Captions are flaky on YouTube\n cc_load_policy: this.captions.active ? 1 : 0,\n cc_lang_pref: this.config.captions.language,\n },\n events: {\n onError(event) {\n // If we've already fired an error, don't do it again\n // YouTube fires onError twice\n if (utils.is.object(player.media.error)) {\n return;\n }\n\n const detail = {\n code: event.data,\n };\n\n // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError\n switch (event.data) {\n case 2:\n detail.message =\n 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.';\n break;\n\n case 5:\n detail.message =\n 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.';\n break;\n\n case 100:\n detail.message =\n 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.';\n break;\n\n case 101:\n case 150:\n detail.message = 'The owner of the requested video does not allow it to be played in embedded players.';\n break;\n\n default:\n detail.message = 'An unknown error occured';\n break;\n }\n\n player.media.error = detail;\n\n utils.dispatchEvent.call(player, player.media, 'error');\n },\n onPlaybackQualityChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Get current quality\n player.media.quality = instance.getPlaybackQuality();\n\n utils.dispatchEvent.call(player, player.media, 'qualitychange');\n },\n onPlaybackRateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Get current speed\n player.media.playbackRate = instance.getPlaybackRate();\n\n utils.dispatchEvent.call(player, player.media, 'ratechange');\n },\n onReady(event) {\n // Get the instance\n const instance = event.target;\n\n // Get the title\n youtube.getTitle.call(player);\n\n // Create a faux HTML5 API using the YouTube API\n player.media.play = () => {\n instance.playVideo();\n player.media.paused = false;\n };\n\n player.media.pause = () => {\n instance.pauseVideo();\n player.media.paused = true;\n };\n\n player.media.stop = () => {\n instance.stopVideo();\n player.media.paused = true;\n };\n\n player.media.duration = instance.getDuration();\n player.media.paused = true;\n\n // Seeking\n player.media.currentTime = 0;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return Number(instance.getCurrentTime());\n },\n set(time) {\n // Set seeking flag\n player.media.seeking = true;\n\n // Trigger seeking\n utils.dispatchEvent.call(player, player.media, 'seeking');\n\n // Seek after events sent\n instance.seekTo(time);\n },\n });\n\n // Playback speed\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return instance.getPlaybackRate();\n },\n set(input) {\n instance.setPlaybackRate(input);\n },\n });\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n return instance.getPlaybackQuality();\n },\n set(input) {\n // Trigger request event\n utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, {\n quality: input,\n });\n\n instance.setPlaybackQuality(input);\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n instance.setVolume(volume * 100);\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : muted;\n muted = toggle;\n instance[toggle ? 'mute' : 'unMute']();\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Source\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return instance.getVideoUrl();\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Get available speeds\n player.options.speed = instance.getAvailablePlaybackRates();\n\n // Set the tabindex to avoid focus entering iframe\n if (player.supported.ui) {\n player.media.setAttribute('tabindex', -1);\n }\n\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n\n // Reset timer\n window.clearInterval(player.timers.buffering);\n\n // Setup buffering\n player.timers.buffering = window.setInterval(() => {\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n\n // Trigger progress only when we actually buffer something\n if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) {\n utils.dispatchEvent.call(player, player.media, 'progress');\n }\n\n // Set last buffer point\n player.media.lastBuffered = player.media.buffered;\n\n // Bail if we're at 100%\n if (player.media.buffered === 1) {\n window.clearInterval(player.timers.buffering);\n\n // Trigger event\n utils.dispatchEvent.call(player, player.media, 'canplaythrough');\n }\n }, 200);\n\n // Rebuild UI\n window.setTimeout(() => ui.build.call(player), 50);\n },\n onStateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Reset timer\n window.clearInterval(player.timers.playing);\n\n // Handle events\n // -1 Unstarted\n // 0 Ended\n // 1 Playing\n // 2 Paused\n // 3 Buffering\n // 5 Video cued\n switch (event.data) {\n case 0:\n player.media.paused = true;\n\n // YouTube doesn't support loop for a single video, so mimick it.\n if (player.media.loop) {\n // YouTube needs a call to `stopVideo` before playing again\n instance.stopVideo();\n instance.playVideo();\n } else {\n utils.dispatchEvent.call(player, player.media, 'ended');\n }\n\n break;\n\n case 1:\n // If we were seeking, fire seeked event\n if (player.media.seeking) {\n utils.dispatchEvent.call(player, player.media, 'seeked');\n }\n player.media.seeking = false;\n\n // Only fire play if paused before\n if (player.media.paused) {\n utils.dispatchEvent.call(player, player.media, 'play');\n }\n player.media.paused = false;\n\n utils.dispatchEvent.call(player, player.media, 'playing');\n\n // Poll to get playback progress\n player.timers.playing = window.setInterval(() => {\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n }, 50);\n\n // Check duration again due to YouTube bug\n // https://github.com/sampotts/plyr/issues/374\n // https://code.google.com/p/gdata-issues/issues/detail?id=8690\n if (player.media.duration !== instance.getDuration()) {\n player.media.duration = instance.getDuration();\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n }\n\n // Get quality\n controls.setQualityMenu.call(player, instance.getAvailableQualityLevels());\n\n break;\n\n case 2:\n player.media.paused = true;\n\n utils.dispatchEvent.call(player, player.media, 'pause');\n\n break;\n\n default:\n break;\n }\n\n utils.dispatchEvent.call(player, player.elements.container, 'statechange', false, {\n code: event.data,\n });\n },\n },\n });\n },\n};\n\nexport default youtube;\n","// ==========================================================================\n// Vimeo plugin\n// ==========================================================================\n\nimport utils from './../utils';\nimport captions from './../captions';\nimport ui from './../ui';\n\nconst vimeo = {\n setup() {\n // Remove old containers\n const containers = utils.getElements.call(this, `[id^=\"${this.provider}-\"]`);\n Array.from(containers).forEach(utils.removeElement);\n\n // Add embed class for responsive\n utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set intial ratio\n vimeo.setAspectRatio.call(this);\n\n // Set ID\n this.media.setAttribute('id', utils.generateId(this.provider));\n\n // Load the API if not already\n if (!utils.is.object(window.Vimeo)) {\n utils.loadScript(this.config.urls.vimeo.api, () => {\n vimeo.ready.call(this);\n });\n } else {\n vimeo.ready.call(this);\n }\n },\n\n // Set aspect ratio\n // For Vimeo we have an extra 300% height <div> to hide the standard controls and UI\n setAspectRatio(input) {\n const ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':');\n const padding = 100 / ratio[0] * ratio[1];\n const height = 200;\n const offset = (height - padding) / (height / 50);\n this.elements.wrapper.style.paddingBottom = `${padding}%`;\n this.media.style.transform = `translateY(-${offset}%)`;\n },\n\n // API Ready\n ready() {\n const player = this;\n\n // Get Vimeo params for the iframe\n const options = {\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: 0,\n gesture: 'media',\n };\n const params = utils.buildUrlParameters(options);\n const id = utils.parseVimeoId(player.embedId);\n\n // Build an iframe\n const iframe = utils.createElement('iframe');\n const src = `https://player.vimeo.com/video/${id}?${params}`;\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n player.media.appendChild(iframe);\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe);\n\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n player.embed.play().then(() => {\n player.media.paused = false;\n });\n };\n\n player.media.pause = () => {\n player.embed.pause().then(() => {\n player.media.paused = true;\n });\n };\n\n player.media.stop = () => {\n player.embed.stop().then(() => {\n player.media.paused = true;\n player.currentTime = 0;\n });\n };\n\n // Seeking\n let { currentTime } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Get current paused state\n // Vimeo will automatically play on seek\n const { paused } = player.media;\n\n // Set seeking flag\n player.media.seeking = true;\n\n // Trigger seeking\n utils.dispatchEvent.call(player, player.media, 'seeking');\n\n // Seek after events\n player.embed.setCurrentTime(time);\n\n // Restore pause state\n if (paused) {\n player.pause();\n }\n },\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n player.embed.setPlaybackRate(input).then(() => {\n speed = input;\n utils.dispatchEvent.call(player, player.media, 'ratechange');\n });\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n player.embed.setVolume(input).then(() => {\n volume = input;\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : false;\n\n player.embed.setVolume(toggle ? 0 : player.config.volume).then(() => {\n muted = toggle;\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Loop\n let { loop } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : player.config.loop.active;\n\n player.embed.setLoop(toggle).then(() => {\n loop = toggle;\n });\n },\n });\n\n // Source\n let currentSrc;\n player.embed.getVideoUrl().then(value => {\n currentSrc = value;\n });\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Set aspect ratio based on video size\n Promise.all([\n player.embed.getVideoWidth(),\n player.embed.getVideoHeight(),\n ]).then(dimensions => {\n const ratio = utils.getAspectRatio(dimensions[0], dimensions[1]);\n vimeo.setAspectRatio.call(this, ratio);\n });\n\n // Set autopause\n player.embed.setAutopause(player.config.autopause).then(state => {\n player.config.autopause = state;\n });\n\n // Get title\n player.embed.getVideoTitle().then(title => {\n player.config.title = title;\n ui.setTitle.call(this);\n });\n\n // Get current time\n player.embed.getCurrentTime().then(value => {\n currentTime = value;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then(value => {\n player.media.duration = value;\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then(tracks => {\n player.media.textTracks = tracks;\n captions.setup.call(player);\n });\n\n player.embed.on('cuechange', data => {\n let cue = null;\n\n if (data.cues.length) {\n cue = utils.stripHTML(data.cues[0].text);\n }\n\n captions.setText.call(player, cue);\n });\n\n player.embed.on('loaded', () => {\n if (utils.is.element(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n\n player.embed.on('play', () => {\n // Only fire play if paused before\n if (player.media.paused) {\n utils.dispatchEvent.call(player, player.media, 'play');\n }\n player.media.paused = false;\n utils.dispatchEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('pause', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'pause');\n });\n\n player.embed.on('timeupdate', data => {\n player.media.seeking = false;\n currentTime = data.seconds;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n player.embed.on('progress', data => {\n player.media.buffered = data.percent;\n utils.dispatchEvent.call(player, player.media, 'progress');\n\n // Check all loaded\n if (parseInt(data.percent, 10) === 1) {\n utils.dispatchEvent.call(player, player.media, 'canplaythrough');\n }\n });\n\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n utils.dispatchEvent.call(player, player.media, 'seeked');\n utils.dispatchEvent.call(player, player.media, 'play');\n });\n\n player.embed.on('ended', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'ended');\n });\n\n player.embed.on('error', detail => {\n player.media.error = detail;\n utils.dispatchEvent.call(player, player.media, 'error');\n });\n\n // Rebuild UI\n window.setTimeout(() => ui.build.call(player), 0);\n },\n};\n\nexport default vimeo;\n","// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport youtube from './plugins/youtube';\nimport vimeo from './plugins/vimeo';\nimport ui from './ui';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.debug.warn('No media element found!');\n return;\n }\n\n // Add type class\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add provider class\n utils.toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n if (this.supported.ui) {\n // Check for picture-in-picture support\n utils.toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo);\n\n // Check for airplay support\n utils.toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5);\n\n // If there's no autoplay attribute, assume the video is stopped and add state class\n utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.config.autoplay);\n\n // Add iOS class\n utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);\n\n // Add touch class\n utils.toggleClass(this.elements.container, this.config.classNames.isTouch, support.touch);\n }\n\n // Inject the player wrapper\n if (this.isVideo || this.isYouTube || this.isVimeo) {\n // Create the wrapper div\n this.elements.wrapper = utils.createElement('div', {\n class: this.config.classNames.video,\n });\n\n // Wrap the video in a container\n utils.wrap(this.media, this.elements.wrapper);\n }\n\n if (this.isEmbed) {\n switch (this.provider) {\n case 'youtube':\n youtube.setup.call(this);\n break;\n\n case 'vimeo':\n vimeo.setup.call(this);\n break;\n\n default:\n break;\n }\n } else if (this.isHTML5) {\n ui.setTitle.call(this);\n }\n },\n\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n Array.from(this.media.querySelectorAll('source')).forEach(utils.removeElement);\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.debug.log('Cancelled network requests');\n },\n};\n\nexport default media;\n","// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport { providers } from './types';\nimport utils from './utils';\nimport media from './media';\nimport ui from './ui';\nimport support from './support';\n\nconst source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (utils.is.string(attributes)) {\n utils.insertElement(type, this.media, {\n src: attributes,\n });\n } else if (utils.is.array(attributes)) {\n attributes.forEach(attribute => {\n utils.insertElement(type, this.media, attribute);\n });\n }\n },\n\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!utils.is.object(input) || !('sources' in input) || !input.sources.length) {\n this.debug.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n media.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(\n this,\n () => {\n // TODO: Reset menus here\n\n // Remove elements\n utils.removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (utils.is.element(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type and provider\n this.type = input.type;\n this.provider = !utils.is.empty(input.sources[0].provider) ? input.sources[0].provider : providers.html5;\n\n // Check for support\n this.supported = support.check(this.type, this.provider, this.config.inline);\n\n // Create new markup\n switch (`${this.provider}:${this.type}`) {\n case 'html5:video':\n this.media = utils.createElement('video');\n break;\n\n case 'html5:audio':\n this.media = utils.createElement('audio');\n break;\n\n case 'youtube:video':\n case 'vimeo:video':\n this.media = utils.createElement('div');\n this.embedId = input.sources[0].src;\n break;\n\n default:\n break;\n }\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (utils.is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if ('poster' in input) {\n this.media.setAttribute('poster', input.poster);\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.inline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hook\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', input.sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if ('tracks' in input) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n\n // Load HTML5 sources\n this.media.load();\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n // Setup interface\n ui.build.call(this);\n }\n },\n true\n );\n },\n};\n\nexport default source;\n","// ==========================================================================\n// Plyr\n// plyr.js v3.0.0\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport { providers, types } from './types';\nimport defaults from './defaults';\nimport support from './support';\nimport utils from './utils';\n\nimport Console from './console';\nimport Storage from './storage';\n\nimport captions from './captions';\nimport controls from './controls';\nimport fullscreen from './fullscreen';\nimport listeners from './listeners';\nimport media from './media';\nimport source from './source';\nimport ui from './ui';\n\n// Private properties\n// TODO: Use a WeakMap for private globals\n// const globals = new WeakMap();\n\n// Globals\nlet scrollPosition = {\n x: 0,\n y: 0,\n};\n\n// Plyr instance\nclass Plyr {\n constructor(target, options) {\n this.timers = {};\n\n // State\n this.ready = false;\n this.loading = false;\n this.failed = false;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (utils.is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if ((window.jQuery && this.media instanceof jQuery) || utils.is.nodeList(this.media) || utils.is.array(this.media)) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = utils.extend(\n {},\n defaults,\n options,\n (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr-config'));\n } catch (e) {\n return {};\n }\n })()\n );\n\n // Elements cache\n this.elements = {\n container: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n menu: null,\n panes: {},\n tabs: {},\n },\n captions: null,\n };\n\n // Captions\n this.captions = {\n active: null,\n currentTrack: null,\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false,\n };\n\n // Options\n this.options = {\n speed: [],\n quality: [],\n };\n\n // Debugging\n // TODO: move to globals\n this.debug = new Console(this);\n\n // Log config options and support\n this.debug.log('Config', this.config);\n this.debug.log('Support', support);\n\n // We need an element to setup\n if (utils.is.nullOrUndefined(this.media) || !utils.is.element(this.media)) {\n this.debug.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.debug.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.debug.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n this.elements.original = this.media.cloneNode(true);\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const type = this.media.tagName.toLowerCase();\n\n // Embed attributes\n const attributes = {\n provider: 'data-plyr-provider',\n id: 'data-plyr-embed-id',\n };\n\n // Different setup based on type\n switch (type) {\n // TODO: Handle passing an iframe for true progressive enhancement\n // case 'iframe':\n case 'div':\n this.type = types.video; // Audio will come later for external providers\n this.provider = this.media.getAttribute(attributes.provider);\n this.embedId = this.media.getAttribute(attributes.id);\n\n if (utils.is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) {\n this.debug.error('Setup failed: Invalid provider');\n return;\n }\n\n // Try and get the embed id\n if (utils.is.empty(this.embedId)) {\n this.debug.error('Setup failed: Embed ID or URL missing');\n return;\n }\n\n // Clean up\n this.media.removeAttribute(attributes.provider);\n this.media.removeAttribute(attributes.id);\n\n break;\n\n case 'video':\n case 'audio':\n this.type = type;\n this.provider = providers.html5;\n\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n\n if (this.media.hasAttribute('playsinline')) {\n this.config.inline = true;\n }\n\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n\n break;\n\n default:\n this.debug.error('Setup failed: unsupported type');\n return;\n }\n\n // Setup local storage for user settings\n this.storage = new Storage(this);\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.provider, this.config.inline);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n this.elements.container = utils.createElement('div');\n utils.wrap(this.media, this.elements.container);\n\n // Allow focus to be captured\n this.elements.container.setAttribute('tabindex', 0);\n\n // Global listeners\n listeners.global.call(this);\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n utils.on(this.elements.container, this.config.events.join(' '), event => {\n this.debug.log(`event: ${event.type}`);\n });\n }\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n ui.build.call(this);\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * Types and provider helpers\n */\n get isHTML5() {\n return this.provider === providers.html5;\n }\n get isEmbed() {\n return this.isYouTube || this.isVimeo;\n }\n get isYouTube() {\n return this.provider === providers.youtube;\n }\n get isVimeo() {\n return this.provider === providers.vimeo;\n }\n get isVideo() {\n return this.type === types.video;\n }\n get isAudio() {\n return this.type === types.audio;\n }\n\n /**\n * Play the media\n */\n play() {\n return this.media.play();\n }\n\n /**\n * Pause the media\n */\n pause() {\n if (!this.playing) {\n return;\n }\n\n this.media.pause();\n }\n\n /**\n * Get paused state\n */\n get paused() {\n return this.media.paused;\n }\n\n /**\n * Get playing state\n */\n get playing() {\n return !this.paused && !this.ended && (this.isHTML5 ? this.media.readyState > 2 : true);\n }\n\n /**\n * Get ended state\n */\n get ended() {\n return this.media.ended;\n }\n\n /**\n * Toggle playback based on current status\n * @param {boolean} input\n */\n togglePlay(input) {\n // Toggle based on current state if nothing passed\n const toggle = utils.is.boolean(input) ? input : !this.playing;\n\n if (toggle) {\n this.play();\n } else {\n this.pause();\n }\n }\n\n /**\n * Stop playback\n */\n stop() {\n this.restart();\n this.pause();\n }\n\n /**\n * Restart playback\n */\n restart() {\n this.currentTime = 0;\n }\n\n /**\n * Rewind\n * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n rewind(seekTime) {\n this.currentTime = this.currentTime - (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Fast forward\n * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n forward(seekTime) {\n this.currentTime = this.currentTime + (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Seek to a time\n * @param {number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n let targetTime = 0;\n\n if (utils.is.number(input)) {\n targetTime = input;\n }\n\n // Normalise targetTime\n if (targetTime < 0) {\n targetTime = 0;\n } else if (targetTime > this.duration) {\n targetTime = this.duration;\n }\n\n // Set\n this.media.currentTime = targetTime.toFixed(4);\n\n // Logging\n this.debug.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n /**\n * Get current time\n */\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n /**\n * Get seeking status\n */\n get seeking() {\n return this.media.seeking;\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseInt(this.config.duration, 10);\n\n // True duration\n const realDuration = Number(this.media.duration);\n\n // If custom duration is funky, use regular duration\n return !Number.isNaN(fauxDuration) ? fauxDuration : realDuration;\n }\n\n /**\n * Set the player volume\n * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n\n if (utils.is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!utils.is.number(volume)) {\n volume = this.storage.get('volume');\n }\n\n // Use config if all else fails\n if (!utils.is.number(volume)) {\n ({ volume } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume, reset muted state\n if (this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return this.media.volume;\n }\n\n /**\n * Increase volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n increaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + (utils.is.number(step) ? step : 1);\n }\n\n /**\n * Decrease volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n decreaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume - (utils.is.number(step) ? step : 1);\n }\n\n /**\n * Set muted state\n * @param {boolean} mute\n */\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!utils.is.boolean(toggle)) {\n toggle = this.storage.get('muted');\n }\n\n // Use config if all else fails\n if (!utils.is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n /**\n * Get current muted state\n */\n get muted() {\n return this.media.muted;\n }\n\n /**\n * Check if the media has audio\n */\n get hasAudio() {\n // Assume yes for all non HTML5 (as we can't tell...)\n if (!this.isHTML5) {\n return true;\n }\n\n // Get audio tracks\n return this.media.mozHasAudio || Boolean(this.media.webkitAudioDecodedByteCount) || Boolean(this.media.audioTracks && this.media.audioTracks.length);\n }\n\n /**\n * Set playback speed\n * @param {decimal} speed - the speed of playback (0.5-2.0)\n */\n set speed(input) {\n let speed = null;\n\n if (utils.is.number(input)) {\n speed = input;\n }\n\n if (!utils.is.number(speed)) {\n speed = this.storage.get('speed');\n }\n\n if (!utils.is.number(speed)) {\n speed = this.config.speed.selected;\n }\n\n // Set min/max\n if (speed < 0.1) {\n speed = 0.1;\n }\n if (speed > 2.0) {\n speed = 2.0;\n }\n\n if (!this.config.speed.options.includes(speed)) {\n this.debug.warn(`Unsupported speed (${speed})`);\n return;\n }\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n this.media.playbackRate = speed;\n }\n\n /**\n * Get current playback speed\n */\n get speed() {\n return this.media.playbackRate;\n }\n\n /**\n * Set playback quality\n * Currently YouTube only\n * @param {string} input - Quality level\n */\n set quality(input) {\n let quality = null;\n\n if (utils.is.string(input)) {\n quality = input;\n }\n\n if (!utils.is.string(quality)) {\n quality = this.storage.get('quality');\n }\n\n if (!utils.is.string(quality)) {\n quality = this.config.quality.selected;\n }\n\n if (!this.options.quality.includes(quality)) {\n this.debug.warn(`Unsupported quality option (${quality})`);\n return;\n }\n\n // Update config\n this.config.quality.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n }\n\n /**\n * Get current quality level\n */\n get quality() {\n return this.media.quality;\n }\n\n /**\n * Toggle loop\n * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n * @param {boolean} input - Whether to loop or not\n */\n set loop(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n /**\n * Get current loop state\n */\n get loop() {\n return this.media.loop;\n }\n\n /**\n * Set new media source\n * @param {object} input - The new source object (see docs)\n */\n set source(input) {\n source.change.call(this, input);\n }\n\n /**\n * Get current source\n */\n get source() {\n return this.media.currentSrc;\n }\n\n /**\n * Set the poster image for a HTML5 video\n * @param {input} - the URL for the new poster image\n */\n set poster(input) {\n if (!this.isHTML5 || !this.isVideo) {\n this.debug.warn('Poster can only be set on HTML5 video');\n return;\n }\n\n if (utils.is.string(input)) {\n this.media.setAttribute('poster', input);\n }\n }\n\n /**\n * Get the current poster image\n */\n get poster() {\n if (!this.isHTML5 || !this.isVideo) {\n return null;\n }\n\n return this.media.getAttribute('poster');\n }\n\n /**\n * Set the autoplay state\n * @param {boolean} input - Whether to autoplay or not\n */\n set autoplay(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.autoplay;\n this.config.autoplay = toggle;\n }\n\n /**\n * Get the current autoplay state\n */\n get autoplay() {\n return this.config.autoplay;\n }\n\n /**\n * Toggle captions\n * @param {boolean} input - Whether to enable captions\n */\n toggleCaptions(input) {\n // If there's no full support, or there's no caption toggle\n if (!this.supported.ui || !utils.is.element(this.elements.buttons.captions)) {\n return;\n }\n\n // If the method is called without parameter, toggle based on current value\n const show = utils.is.boolean(input) ? input : this.elements.container.className.indexOf(this.config.classNames.captions.active) === -1;\n\n // Nothing to change...\n if (this.captions.active === show) {\n return;\n }\n\n // Set global\n this.captions.active = show;\n\n // Toggle state\n utils.toggleState(this.elements.buttons.captions, this.captions.active);\n\n // Add class hook\n utils.toggleClass(this.elements.container, this.config.classNames.captions.active, this.captions.active);\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, this.captions.active ? 'captionsenabled' : 'captionsdisabled');\n }\n\n /**\n * Set the captions language\n * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc)\n */\n set language(input) {\n // Nothing specified\n if (!utils.is.string(input)) {\n return;\n }\n\n // Toggle captions based on input\n this.toggleCaptions(!utils.is.empty(input));\n\n // If empty string is passed, assume disable captions\n if (utils.is.empty(input)) {\n return;\n }\n\n // Normalize\n const language = input.toLowerCase();\n\n // If nothing to change, bail\n if (this.language === language) {\n return;\n }\n\n // Update config\n this.captions.language = language;\n\n // Clear caption\n captions.setText.call(this, null);\n\n // Update captions\n captions.setLanguage.call(this);\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, 'languagechange');\n }\n\n /**\n * Get the current captions language\n */\n get language() {\n return this.captions.language;\n }\n\n /**\n * Toggle fullscreen playback\n * Requires user input event\n * @param {event} event\n */\n toggleFullscreen(event) {\n // Video only\n if (this.isAudio) {\n return;\n }\n\n // Check for native support\n if (fullscreen.enabled) {\n if (utils.is.event(event) && event.type === fullscreen.eventType) {\n // If it's a fullscreen change event, update the state\n this.fullscreen.active = fullscreen.isFullScreen(this.elements.container);\n } else {\n // Else it's a user request to enter or exit\n if (!this.fullscreen.active) {\n fullscreen.requestFullScreen(this.elements.container);\n } else {\n fullscreen.cancelFullScreen();\n }\n\n return;\n }\n } else {\n // Otherwise, it's a simple toggle\n this.fullscreen.active = !this.fullscreen.active;\n\n // Add class hook\n utils.toggleClass(this.elements.container, this.config.classNames.fullscreen.fallback, this.fullscreen.active);\n\n // Make sure we don't lose scroll position\n if (this.fullscreen.active) {\n scrollPosition = {\n x: window.pageXOffset || 0,\n y: window.pageYOffset || 0,\n };\n } else {\n window.scrollTo(scrollPosition.x, scrollPosition.y);\n }\n\n // Bind/unbind escape key\n document.body.style.overflow = this.fullscreen.active ? 'hidden' : '';\n }\n\n // Set button state\n if (utils.is.element(this.elements.buttons.fullscreen)) {\n utils.toggleState(this.elements.buttons.fullscreen, this.fullscreen.active);\n }\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, this.fullscreen.active ? 'enterfullscreen' : 'exitfullscreen');\n }\n\n /**\n * Toggle picture-in-picture playback on WebKit/MacOS\n * TODO: update player with state, support, enabled\n * TODO: detect outside changes\n */\n set pip(input) {\n const states = {\n pip: 'picture-in-picture',\n inline: 'inline',\n };\n\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = utils.is.boolean(input) ? input : this.pip === states.inline;\n\n // Toggle based on current state\n this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline);\n }\n\n /**\n * Get the current picture-in-picture state\n */\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n return this.media.webkitPresentationMode;\n }\n\n /**\n * Trigger the airplay dialog\n * TODO: update player with state, support, enabled\n */\n airplay() {\n // Show dialog if supported\n if (support.airplay) {\n this.media.webkitShowPlaybackTargetPicker();\n }\n }\n\n /**\n * Toggle the player controls\n * @param {boolean} toggle - Whether to show the controls\n */\n toggleControls(toggle) {\n // We need controls of course...\n if (!utils.is.element(this.elements.controls)) {\n return;\n }\n\n // Don't hide if no UI support or it's audio\n if (!this.supported.ui || this.isAudio) {\n return;\n }\n\n let delay = 0;\n let show = toggle;\n let isEnterFullscreen = false;\n\n // Get toggle state if not set\n if (!utils.is.boolean(toggle)) {\n if (utils.is.event(toggle)) {\n // Is the enter fullscreen event\n isEnterFullscreen = toggle.type === 'enterfullscreen';\n\n // Whether to show controls\n show = [\n 'mouseenter',\n 'mousemove',\n 'touchstart',\n 'touchmove',\n 'focusin',\n ].includes(toggle.type);\n\n // Delay hiding on move events\n if ([\n 'mousemove',\n 'touchmove',\n 'touchend',\n ].includes(toggle.type)) {\n delay = 2000;\n }\n\n // Delay a little more for keyboard users\n if (toggle.type === 'focusin') {\n delay = 3000;\n utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, true);\n }\n } else {\n show = utils.hasClass(this.elements.container, this.config.classNames.hideControls);\n }\n }\n\n // Clear timer on every call\n window.clearTimeout(this.timers.controls);\n\n // If the mouse is not over the controls, set a timeout to hide them\n if (show || this.paused || this.loading) {\n // Check if controls toggled\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, false);\n\n // Trigger event\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlsshown');\n }\n\n // Always show controls when paused or if touch\n if (this.paused || this.loading) {\n return;\n }\n\n // Delay for hiding on touch\n if (support.touch) {\n delay = 3000;\n }\n }\n\n // If toggle is false or if we're playing (regardless of toggle),\n // then set the timer to hide the controls\n if (!show || this.playing) {\n this.timers.controls = window.setTimeout(() => {\n /* this.debug.warn({\n pressed: this.elements.controls.pressed,\n hover: this.elements.controls.pressed,\n playing: this.playing,\n paused: this.paused,\n loading: this.loading,\n }); */\n\n // If the mouse is over the controls (and not entering fullscreen), bail\n if ((this.elements.controls.pressed || this.elements.controls.hover) && !isEnterFullscreen) {\n return;\n }\n\n // Restore transition behaviour\n if (!utils.hasClass(this.elements.container, this.config.classNames.hideControls)) {\n utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, false);\n }\n\n // Check if controls toggled\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, true);\n\n // Trigger event and close menu\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlshidden');\n\n if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {\n controls.toggleMenu.call(this, false);\n }\n }\n }, delay);\n }\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n on(event, callback) {\n utils.on(this.elements.container, event, callback);\n }\n\n /**\n * Remove event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n off(event, callback) {\n utils.off(this.elements.container, event, callback);\n }\n\n\n\n /**\n * Destroy an instance\n * Event listeners are removed when elements are removed\n * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n * @param {function} callback - Callback for when destroy is complete\n * @param {boolean} soft - Whether it's a soft destroy (for source changes etc)\n */\n destroy(callback, soft = false) {\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n this.embedId = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove buttons\n if (this.elements.buttons && this.elements.buttons.play) {\n Array.from(this.elements.buttons.play).forEach(button => utils.removeElement(button));\n }\n\n // Remove others\n utils.removeElement(this.elements.captions);\n utils.removeElement(this.elements.controls);\n utils.removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (utils.is.function(callback)) {\n callback();\n }\n } else {\n // Replace the container with the original element provided\n const parent = this.elements.container.parentNode;\n\n if (utils.is.element(parent)) {\n parent.replaceChild(this.elements.original, this.elements.container);\n }\n\n // Event\n utils.dispatchEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (utils.is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Clear for GC\n this.elements = null;\n }\n };\n\n // Type specific stuff\n switch (`${this.provider}:${this.type}`) {\n case 'html5:video':\n case 'html5:audio':\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n\n break;\n\n case 'youtube:video':\n // Clear timers\n window.clearInterval(this.timers.buffering);\n window.clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n this.embed.destroy();\n\n // Clean up\n done();\n\n break;\n\n case 'vimeo:video':\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n this.embed.unload().then(done);\n\n // Vimeo does not always return\n window.setTimeout(done, 200);\n\n break;\n\n default:\n break;\n }\n }\n\n /**\n * Check for support for a mime type (HTML5 only)\n * @param {string} type - Mime type\n */\n supports(type) {\n return support.mime.call(this, type);\n }\n\n /**\n * Check for support\n * @param {string} type - Player type (audio/video)\n * @param {string} provider - Provider (html5/youtube/vimeo)\n * @param {bool} inline - Where player has `playsinline` sttribute\n */\n static supported(type, provider, inline) {\n return support.check(type, provider, inline);\n }\n\n /**\n * Load an SVG sprite into the page\n * @param {string} url - URL for the SVG sprite\n * @param {string} [id] - Unique ID\n */\n static loadSprite(url, id) {\n return utils.loadSprite(url, id);\n }\n}\n\nexport default Plyr;\n"],"names":["providers","types","defaults","window","navigator","language","split","utils","input","this","instanceof","Plyr","getConstructor","Object","Number","isNaN","String","Boolean","Function","nullOrUndefined","Array","isArray","WeakMap","NodeList","Element","Text","Event","TextTrackCue","VTTCue","TextTrack","string","kind","array","nodeList","length","object","keys","constructor","document","documentMode","documentElement","style","test","userAgent","platform","url","callback","current","querySelector","callbacks","push","element","createElement","is","function","addEventListener","forEach","cb","call","event","src","first","getElementsByTagName","parentNode","insertBefore","id","updateSprite","data","innerHTML","body","childNodes","hasId","querySelectorAll","container","toggleHidden","setAttribute","support","storage","cached","localStorage","getItem","JSON","parse","content","then","response","ok","text","setItem","stringify","catch","prefix","Math","floor","random","self","top","e","elements","wrapper","targets","from","reverse","index","child","cloneNode","parent","sibling","nextSibling","appendChild","type","attributes","setAttributes","textContent","target","removeChild","lastChild","empty","key","sel","existingAttributes","existing","selector","s","trim","className","replace","parts","value","charAt","class","toggle","contains","classList","removeAttribute","prototype","matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","includes","controls","getElement","config","selectors","buttons","getElements","play","pause","restart","rewind","forward","mute","pip","airplay","settings","captions","fullscreen","progress","inputs","seek","volume","display","buffer","duration","currentTime","seekTooltip","classNames","tooltip","error","debug","warn","toggleNativeControls","focused","activeElement","focusable","last","on","keyCode","_this","active","getFocusElement","shiftKey","focus","preventDefault","passive","capture","Node","toggleListener","events","options","boolean","passiveListeners","bubbles","detail","CustomEvent","assign","dispatchEvent","pressed","getAttribute","state","max","toFixed","sources","source","shift","extend","match","RegExp","$2","number","map","encodeURIComponent","join","fragment","createDocumentFragment","firstChild","innerText","width","height","ratio","getRatio","w","h","find","undefined","setTimeout","offsetHeight","provider","inline","api","ui","browser","getBrowser","playsInline","isIPhone","video","rangeInput","audio","webkitSetPresentationMode","WebKitPlaybackTargetAvailabilityEvent","media","isHTML5","canPlayType","isVideo","isAudio","supported","defineProperty","range","transitionEnd","matchMedia","noop","Console","player","enabled","console","log","bind","Storage","store","json","get","removeItem","cancelFullScreen","some","pre","msExitFullscreen","msFullscreenEnabled","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","fullscreenElement","mozFullScreenElement","requestFullScreen","nativeSupport","fallback","inFrame","toggleClass","toggleState","trapFocus","listeners","handleKey","code","which","getKeyCode","repeat","altKey","ctrlKey","metaKey","editable","stopPropagation","togglePlay","increaseVolume","decreaseVolume","muted","toggleFullscreen","toggleCaptions","loop","keyboard","global","tabFocus","hideControls","toggleControls","eventType","timeUpdate","durationUpdate","_this2","hasAudio","showPosterOnEnd","load","updateProgress","updateVolume","checkPlaying","checkLoading","clickToPlay","touch","paused","ended","disableContextMenu","set","updateSetting","speed","quality","concat","inputEvent","isIE","proxy","handlerKey","defaultHandler","customHandler","_this3","defaultPrevented","toggleMenu","form","parseFloat","showTab","toggleInvert","invertTime","isWebkit","updateRangeFill","updateSeekTooltip","hover","inverted","webkitDirectionInvertedFromDevice","direction","deltaY","deltaX","uiSupported","removeElement","inject","setup","ready","setTitle","label","i18n","title","isEmbed","iframe","frameTitle","playing","stopped","button","loading","networkState","timers","failed","setRange","nodeValue","getPercentage","buffered","_this4","end","setProgress","time","format","slice","getHours","parseInt","hours","mins","getMinutes","secs","getSeconds","invert","updateTimeDisplay","seeking","displayDuration","styleSheet","sheet","percentage","styles","rules","findIndex","rule","selectorText","deleteRule","insertRule","iconUrl","indexOf","svg4everybody","namespace","getIconUrl","iconPath","absolute","iconPrefix","icon","createElementNS","use","path","setAttributeNS","attr","hidden","badge","menu","buttonType","labelPressed","iconPressed","control","createIcon","createLabel","getAttributesFromSelector","suffix","played","toLowerCase","list","checked","item","radio","faux","aria-hidden","insertAdjacentHTML","tooltips","percent","clientRect","getBoundingClientRect","visible","pageX","left","hasClass","setting","tab","tabs","pane","panes","filter","isYouTube","toggleTab","emptyElement","createMenuItem","getLabel","createBadge","getBadge","getLanguage","default","textTracks","getTracks","none","currentTrack","getCurrentTrack","track","disabled","hasTracks","tracks","toUpperCase","unshift","show","isMenuItem","isButton","open","clone","position","opacity","name","scrollWidth","scrollHeight","getElementById","transitions","reducedMotion","size","getTabSize","restore","propertyName","off","createButton","createRange","createProgress","createTime","inner","home","back","setSpeedMenu","loadSprite","seekTime","create","findElements","repaint","labels","_this5","stored","setCaptionsMenu","insertAfter","setLanguage","setCue","mode","activeCues","isVimeo","embed","enableTextTrack","cue","setText","getCueAsHTML","caption","youtube","videoId","parseYouTubeId","embedId","containers","setAspectRatio","generateId","YT","loadScript","urls","onYouTubeReadyCallbacks","onYouTubeIframeAPIReady","getVideoData","google","result","items","snippet","paddingBottom","Player","autoplay","location","hostname","href","message","instance","getPlaybackQuality","playbackRate","getPlaybackRate","getTitle","playVideo","pauseVideo","stop","stopVideo","getDuration","getCurrentTime","seekTo","setPlaybackRate","setPlaybackQuality","setVolume","getVideoUrl","getAvailablePlaybackRates","clearInterval","buffering","setInterval","getVideoLoadedFraction","lastBuffered","build","setQualityMenu","getAvailableQualityLevels","vimeo","Vimeo","padding","offset","transform","params","buildUrlParameters","parseVimeoId","setCurrentTime","selected","setLoop","currentSrc","all","getVideoWidth","getVideoHeight","getAspectRatio","dimensions","setAutopause","autopause","getVideoTitle","getTextTracks","cues","stripHTML","seconds","isIos","isTouch","wrap","blankVideo","insertElement","attribute","cancelRequests","destroy","html5","check","crossorigin","poster","addStyleHook","insertElements","scrollPosition","jQuery","plyr","original","tagName","hasAttribute","step","isFullScreen","pageXOffset","pageYOffset","scrollTo","x","y","overflow","webkitShowPlaybackTargetPicker","delay","isEnterFullscreen","noTransition","clearTimeout","soft","done","replaceChild","unload","mime","readyState","targetTime","fauxDuration","realDuration","mozHasAudio","webkitAudioDecodedByteCount","audioTracks","change","states","webkitPresentationMode"],"mappings":"uLAIA,IAAaA,SACF,gBACE,gBACF,SAGEC,SACF,cACA,SCXLC,YAEO,QAGF,UAGA,YAGG,aAGC,WAGD,UAGF,SACD,WAGG,sBAIO,cAGL,gBAGE,QAGP,oBAGM,gBAGC,mBAGG,sBAGG,cAGR,aACA,eACH,iDAGG,wDAIC,mBAEL,SACA,SACA,SACA,QACA,QACA,SACA,QACA,OACA,0BAMI,mBAOE,WAEN,GACA,IACA,EACA,KACA,IACA,KACA,uBAMK,UACD,uBAKE,QACJ,qBAKE,WACEC,OAAOC,UAAUC,SAASC,MAAM,KAAK,yBAKtC,YACC,qBAKD,MACJ,kBAKL,aACA,OACA,WACA,eACA,OACA,SACA,WACA,WACA,MACA,UACA,wBAGA,WACA,UACA,uBAKS,iBACD,8BACF,aACC,gBACE,+BACH,cACE,kBACE,uBACG,wBACH,kBACF,cACF,cACE,wBACQ,kCACC,mCACA,kCACD,6BACJ,8BACF,oBACA,iBACH,gBACE,eACH,aACC,YACF,UACA,YACE,aACD,gBACI,6BAMD,uDAGA,uDAMH,UACA,WACC,aACE,YACD,aACC,UACH,YACE,cACE,gBACE,SACP,aACI,WACF,aACE,UACH,cACI,sBAQV,WACA,UACA,UACA,UACA,UACA,iBACA,YACA,aACA,iBACA,aACA,eACA,OACA,QACA,QACA,UACA,SACA,UACA,aACA,8BAIA,iBACA,kBACA,mBACA,iBACA,iBACA,gBACA,sBAIA,gBACA,wCAMU,uDACC,4BAEI,aACF,0BAEL,4BAEE,2BACC,8BACE,+BACD,+BACC,kCACH,8BACI,oCACE,+BACP,4BACI,iCACC,8BACJ,mCAGA,4BACE,6BACD,+BACG,iCACD,8CAGI,gCACH,+BACF,iCACA,+BACF,+BACE,mCAEF,2BACA,gCAEG,oDAMN,4BACA,4BACE,qBACH,qBACI,oBACD,wBACA,wBACA,sBACF,wBACA,sBACE,uBACD,6BACM,4BACP,uBACE,6BACI,6BACC,kCAEH,0BACA,mBACD,qCAGG,gCACD,6CAGC,oCACC,4CAGC,6BACH,uCAGG,iCACH,iCAEF,gCAKF,g3CChVVC,qBAGOC,UACMC,KAAKC,WAAWF,EAAOG,uBAE3BH,UACIC,KAAKG,eAAeJ,KAAWK,wBAEnCL,UACIC,KAAKG,eAAeJ,KAAWM,SAAWA,OAAOC,MAAMP,oBAE3DA,UACIC,KAAKG,eAAeJ,KAAWQ,yBAElCR,UACGC,KAAKG,eAAeJ,KAAWS,2BAEjCT,UACEC,KAAKG,eAAeJ,KAAWU,yBAEpCV,UACMC,KAAKU,gBAAgBX,IAAUY,MAAMC,QAAQb,qBAEjDA,UACGC,KAAKC,WAAWF,EAAOL,OAAOmB,4BAEhCd,UACEC,KAAKC,WAAWF,EAAOL,OAAOoB,4BAEjCf,UACGC,KAAKC,WAAWF,EAAOL,OAAOqB,4BAEhChB,UACEC,KAAKG,eAAeJ,KAAWiB,qBAEpCjB,UACKC,KAAKC,WAAWF,EAAOL,OAAOuB,qBAErClB,UACOC,KAAKC,WAAWF,EAAOL,OAAOwB,eAAiBlB,KAAKC,WAAWF,EAAOL,OAAOyB,wBAElFpB,UACKC,KAAKC,WAAWF,EAAOqB,aAAgBpB,KAAKU,gBAAgBX,IAAUC,KAAKqB,OAAOtB,EAAMuB,gCAEnFvB,UACK,OAAVA,QAAmC,IAAVA,kBAE9BA,UAEEC,KAAKU,gBAAgBX,KACnBC,KAAKqB,OAAOtB,IAAUC,KAAKuB,MAAMxB,IAAUC,KAAKwB,SAASzB,MAAYA,EAAM0B,QAC5EzB,KAAK0B,OAAO3B,KAAWK,OAAOuB,KAAK5B,GAAO0B,4BAGxC1B,EAAO6B,UACPpB,QAAQT,GAAS6B,GAAe7B,aAAiB6B,4BAE7C7B,UACHC,KAAKU,gBAAgBX,GAA6B,KAApBA,EAAM6B,kDAOZC,SAASC,sBAC/B,qBAAsBD,SAASE,gBAAgBC,QAAU,OAAOC,KAAKtC,UAAUuC,oBAC/E,kBAAkBD,KAAKtC,UAAUwC,gBACpC,uBAAuBF,KAAKtC,UAAUwC,gCAK1CC,EAAKC,OACNC,EAAUT,SAASU,6BAA6BH,WAGtC,OAAZE,WACQE,UAAYF,EAAQE,qBACpBA,UAAUC,KAAKJ,OAKrBK,EAAUb,SAASc,cAAc,YAG/BH,UAAYE,EAAQF,gBACpBA,UAAUC,KAAKJ,GAGnBvC,EAAM8C,GAAGC,SAASR,MACVS,iBACJ,OACA,cACYN,UAAUO,QAAQ,mBAAMC,EAAGC,KAAK,KAAMC,OACtCV,UAAY,OAExB,KAKAW,IAAMf,MAGRgB,EAAQvB,SAASwB,qBAAqB,UAAU,KAChDC,WAAWC,aAAab,EAASU,wBAIhChB,EAAKoB,YASHC,EAAaC,QAEbC,UAAYD,WAGRE,KAAKL,aAAavD,KAAM6B,SAAS+B,KAAKC,WAAW,OAbzD/D,EAAM8C,GAAGvB,OAAOe,QAKf0B,EAAQhE,EAAM8C,GAAGvB,OAAOmC,OAYzBM,IAAUjC,SAASkC,qBAAqBP,GAAM/B,OAAQ,KAEjDuC,EAAYnC,SAASc,cAAc,YACnCsB,aAAaD,GAAW,GAE1BF,KACUI,aAAa,KAAMV,GAI7BW,EAAQC,QAAS,KACXC,EAAS3E,OAAO4E,aAAaC,QAxB5B,SAwB6Cf,MAC9B,OAAXa,EAEG,KACJX,EAAOc,KAAKC,MAAMJ,iBACXpB,KAAKe,EAAWN,EAAKgB,gBAMpCtC,GACDuC,KAAK,mBAAaC,EAASC,GAAKD,EAASE,OAAS,OAClDH,KAAK,YACW,OAATG,IAIAX,EAAQC,gBACDE,aAAaS,QA3CrB,SA4CcvB,EACTgB,KAAKQ,mBACQF,OAKR7B,KAAKe,EAAWc,MAEhCG,MAAM,qCAKRC,UACGA,MAAUC,KAAKC,MAAsB,IAAhBD,KAAKE,yCAMzB3F,OAAO4F,OAAS5F,OAAO6F,IAChC,MAAOC,UACE,kBAKVC,EAAUC,OAELC,EAAUF,EAAShE,OAASgE,GAAYA,SAIxCG,KAAKD,GACNE,UACA9C,QAAQ,SAACL,EAASoD,OACTC,EAAQD,EAAQ,EAAIJ,EAAQM,WAAU,GAAQN,EAG9CO,EAASvD,EAAQY,WACjB4C,EAAUxD,EAAQyD,cAIlBC,YAAY1D,GAKdwD,IACO3C,aAAawC,EAAOG,KAEpBE,YAAYL,6BAMrBM,EAAMC,EAAYxB,OAEtBpC,EAAUb,SAASc,cAAc0D,UAGnCvG,EAAM8C,GAAGlB,OAAO4E,MACVC,cAAc7D,EAAS4D,GAI7BxG,EAAM8C,GAAGvB,OAAOyD,OACR0B,YAAc1B,GAInBpC,wBAICA,EAAS+D,KACVnD,WAAWC,aAAab,EAAS+D,EAAON,qCAIrCE,EAAMJ,EAAQK,EAAYxB,KAE7BsB,YAAYtG,EAAM6C,cAAc0D,EAAMC,EAAYxB,4BAI/CpC,UACL5C,EAAM8C,GAAGF,QAAQA,IAAa5C,EAAM8C,GAAGF,QAAQA,EAAQY,eAIpDA,WAAWoD,YAAYhE,GAExBA,GALI,4BASFA,WACHjB,EAAWiB,EAAQmB,WAAnBpC,OAECA,EAAS,KACJiF,YAAYhE,EAAQiE,cAClB,0BAKJjE,EAAS4D,GACdxG,EAAM8C,GAAGF,QAAQA,KAAY5C,EAAM8C,GAAGgE,MAAMN,WAI1C3E,KAAK2E,GAAYvD,QAAQ,cACpBmB,aAAa2C,EAAKP,EAAWO,0CAKnBC,EAAKC,OAMtBjH,EAAM8C,GAAGvB,OAAOyF,IAAQhH,EAAM8C,GAAGgE,MAAME,gBAItCR,KACAU,EAAWD,WAEblH,MAAM,KAAKkD,QAAQ,gBAEbkE,EAAWC,EAAEC,OACbC,EAAYH,EAASI,QAAQ,IAAK,IAIlCC,EAHWL,EAASI,QAAQ,SAAU,IAGrBxH,MAAM,KACvBgH,EAAMS,EAAM,GACZC,EAAQD,EAAM7F,OAAS,EAAI6F,EAAM,GAAGD,QAAQ,QAAS,IAAM,UAGnDJ,EAASO,OAAO,QAGrB,IAEG1H,EAAM8C,GAAGlB,OAAOsF,IAAalH,EAAM8C,GAAGvB,OAAO2F,EAASS,WAC7CA,WAAaL,KAGfK,MAAQL,YAGlB,MAEU5D,GAAKyD,EAASI,QAAQ,IAAK,cAGrC,MAEUR,GAAOU,KASvBjB,wBAIC5D,EAAS0E,EAAWM,MACxB5H,EAAM8C,GAAGF,QAAQA,GAAU,KACrBiF,EAAWjF,EAAQkF,UAAUD,SAASP,YAEpCQ,UAAUF,EAAS,MAAQ,UAAUN,GAErCM,IAAWC,IAAeD,GAAUC,SAGzC,wBAIFjF,EAAS0E,UACPtH,EAAM8C,GAAGF,QAAQA,IAAYA,EAAQkF,UAAUD,SAASP,0BAItD1E,EAASgF,GACb5H,EAAM8C,GAAGF,QAAQA,KAIlBgF,IACQxD,aAAa,SAAU,MAEvB2D,gBAAgB,6BAKxBnF,EAASuE,OACPa,GAAc/G,iBAMdgH,EAAUD,EAAUC,SAAWD,EAAUE,uBAAyBF,EAAUG,oBAAsBH,EAAUI,qCAHvGvH,MAAMiF,KAAK/D,SAASkC,iBAAiBkD,IAAWkB,SAASnI,cAK7D+H,EAAQ9E,KAAKP,EAASuE,yBAIrBA,UACDjH,KAAKyF,SAASzB,UAAUD,iBAAiBkD,wBAIzCA,UACAjH,KAAKyF,SAASzB,UAAUzB,cAAc0E,4CAOpCxB,SAAS2C,SAAWtI,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUH,SAAS1C,cAG/ED,SAAS+C,cACJ1I,EAAM2I,YAAYxF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUC,QAAQE,YAC1D5I,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUC,QAAQG,eACxD7I,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUC,QAAQI,gBAC3D9I,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUC,QAAQK,gBACzD/I,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUC,QAAQM,cAC7DhJ,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUC,QAAQO,UAC3DjJ,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUC,QAAQQ,aACtDlJ,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUC,QAAQS,kBACzDnJ,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUC,QAAQU,mBAC1DpJ,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUC,QAAQW,qBACxDrJ,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUC,QAAQY,kBAIrE3D,SAAS4D,SAAWvJ,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUc,eAGtE5D,SAAS6D,aACJxJ,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUe,OAAOC,aACvDzJ,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUe,OAAOE,cAIhE/D,SAASgE,gBACF3J,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUkB,QAAQC,iBACxD5J,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUkB,QAAQE,sBACvD7J,EAAMuI,WAAWpF,KAAKjD,KAAMA,KAAKsI,OAAOC,UAAUkB,QAAQG,cAIvE9J,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAAS4D,iBAC1B5D,SAASgE,QAAQI,YAAc7J,KAAKyF,SAAS4D,SAAS9G,kBAAkBvC,KAAKsI,OAAOwB,WAAWC,WAGjG,EACT,MAAOC,eAEAC,MAAMC,KAAK,kEAAmEF,QAG9EG,sBAAqB,IAEnB,mCAMPC,EAAUvI,SAASwI,uBAElBD,GAAWA,IAAYvI,SAAS+B,KAGvB/B,SAASU,cAAc,UAFvB,sCAUR+H,EAAYxK,EAAM2I,YAAYxF,KAAKjD,KAAM,2DACzCoD,EAAQkH,EAAU,GAClBC,EAAOD,EAAUA,EAAU7I,OAAS,KAEpC+I,GACFxK,KAAKyF,SAASzB,UACd,UACA,eAEsB,QAAdd,EAAM2D,KAAmC,IAAlB3D,EAAMuH,SAAkBC,EAAKtB,WAAWuB,YAK7DP,EAAUtK,EAAM8K,kBAElBR,IAAYG,GAASrH,EAAM2H,SAIpBT,IAAYhH,GAASF,EAAM2H,aAE7BC,UACCC,qBALAD,UACAC,qBAOd,4BAKOtF,EAAUvC,EAAOb,EAAUqF,EAAQsD,EAASC,OAEnDnL,EAAM8C,GAAGlC,gBAAgB+E,MAKzB3F,EAAM8C,GAAGpB,SAASiE,SAEZG,KAAKH,GAAU1C,QAAQ,YACrBL,aAAmBwI,QACbC,eAAelI,KAAK,KAAMP,EAASQ,EAAOb,EAAUqF,EAAQsD,EAASC,cAQjFG,EAASlI,EAAMrD,MAAM,KAIvBwL,IAAUvL,EAAM8C,GAAG0I,QAAQL,IAAWA,EAGtC9G,EAAQoH,+BAGKzL,EAAM8C,GAAG0I,QAAQN,IAAWA,YAE5BlL,EAAM8C,GAAG0I,QAAQL,IAAWA,MAKtClI,QAAQ,cACF2E,EAAS,mBAAqB,uBAAuBrB,EAAMhE,EAAUgJ,mBAKnF3I,EAAS0I,EAAQ/I,EAAU2I,EAASC,KAC7BE,eAAezI,EAAS0I,EAAQ/I,GAAU,EAAM2I,EAASC,iBAI/DvI,EAAS0I,EAAQ/I,EAAU2I,EAASC,KAC9BE,eAAezI,EAAS0I,EAAQ/I,GAAU,EAAO2I,EAASC,2BAItDvI,EAAS2D,EAAMmF,EAASC,MAE7B/I,GAAY2D,OAKXnD,EAAQ,IAAIwI,YAAYrF,aACjBvG,EAAM8C,GAAG0I,QAAQE,IAAWA,SAC7BpL,OAAOuL,UAAWF,QAChBzL,gBAAgBE,KAAOF,KAAO,WAKpC4L,cAAc1I,0BAKdR,EAAS3C,MAEZD,EAAM8C,GAAGF,QAAQA,QAKhBmJ,EAAmD,SAAzCnJ,EAAQoJ,aAAa,gBAC/BC,EAAQjM,EAAM8C,GAAG0I,QAAQvL,GAASA,GAAS8L,IAGzC3H,aAAa,eAAgB6H,4BAI3BzJ,EAAS0J,UACH,IAAZ1J,GAAyB,IAAR0J,GAAa3L,OAAOC,MAAMgC,IAAYjC,OAAOC,MAAM0L,GAC7D,GAEH1J,EAAU0J,EAAM,KAAKC,QAAQ,8BAIlCxF,+EAAgByF,uDACdA,EAAQzK,cACFgF,MAGL0F,EAASD,EAAQE,eAElBtM,EAAM8C,GAAGlB,OAAOyK,WAIdxK,KAAKwK,GAAQpJ,QAAQ,YACpBjD,EAAM8C,GAAGlB,OAAOyK,EAAOtF,KAClBzG,OAAOuB,KAAK8E,GAAQ0B,SAAStB,WACvB8E,OAAOlF,OAAWI,SAGvBwF,OAAO5F,EAAOI,GAAMsF,EAAOtF,YAE1B8E,OAAOlF,OAAWI,EAAMsF,EAAOtF,OAIvC/G,EAAMuM,gBAAO5F,iIAAWyF,MAfpBzF,2BAmBArE,UAEJA,EAAIkK,MADG,gEACYC,OAAOC,GAAKpK,yBAI7BA,MACLtC,EAAM8C,GAAG6J,OAAOpM,OAAO+B,WAChBA,SAIJA,EAAIkK,MADG,mCACYC,OAAOC,GAAKpK,+BAIvBrC,UACVD,EAAM8C,GAAGlB,OAAO3B,GAIdK,OAAOuB,KAAK5B,GACd2M,IAAI,mBAAUC,mBAAmB9F,OAAQ8F,mBAAmB5M,EAAM8G,MAClE+F,KAAK,KALC,uBASLT,OACAU,EAAWhL,SAASiL,yBACpBpK,EAAUb,SAASc,cAAc,gBAC9ByD,YAAY1D,KACbiB,UAAYwI,EACbU,EAASE,WAAWC,mCAIhBC,EAAOC,OAEZC,EADW,SAAXC,EAAYC,EAAGC,UAAa,IAANA,EAAUD,EAAID,EAASE,EAAGD,EAAIC,GAC5CF,CAASH,EAAOC,UACpBD,EAAQE,MAASD,EAASC,iBAIxB,eACNzK,EAAUb,SAASc,cAAc,QASjC0D,EAAOjG,OAAOuB,uBANE,oCACH,4BACF,2CACD,kBAGiB4L,KAAK,wBAAkCC,IAAzB9K,EAAQV,MAAMkB,WAEtC,iBAATmD,GAAoBA,EAZtB,oBAgBR3D,UACG+K,WAAW,aACNvJ,aAAa,SAAU,MACvBwJ,eACA7F,gBAAgB,WACzB,KCrqBL1D,SAEK,gBAAiBtC,SAASc,cAAc,eACxC,gBAAiBd,SAASc,cAAc,wBAIzC0D,EAAMsH,EAAUC,OACdC,GAAM,EACNC,GAAK,EACHC,EAAUjO,EAAMkO,aAChBC,EAAcF,EAAQG,UAAYN,GAAUzJ,EAAQyJ,cAE/CD,MAAYtH,OACd,mBACKlC,EAAQgK,QACFhK,EAAQiK,cAAgBL,EAAQG,UAAYD,aAGvD,mBACK9J,EAAQkK,QACFlK,EAAQiK,qBAGnB,mBACK,IACDjK,EAAQiK,cAAgBL,EAAQG,UAAYD,aAGhD,iBACK,IACD9J,EAAQiK,aAAeL,EAAQG,4BAI9B/J,EAAQkK,OAASlK,EAAQgK,QACnBhK,EAAQiK,oCAYZtO,EAAMkO,aACNE,UAAYpO,EAAM8C,GAAGC,SAAS/C,EAAM6C,cAAc,SAAS2L,mCAKtExO,EAAM8C,GAAGC,SAASnD,OAAO6O,8CAI1B,gBAAiB1M,SAASc,cAAc,uBAK3C0D,OACOmI,EAAUxO,KAAVwO,cAICxO,KAAKyO,UAAY3O,EAAM8C,GAAGC,SAAS2L,EAAME,oBACnC,KAIP1O,KAAK2O,eACGtI,OACC,oBACMmI,EAAME,YAAY,oCAAoCrH,QAAQ,KAAM,QAE1E,mBACMmH,EAAME,YAAY,8CAA8CrH,QAAQ,KAAM,QAEpF,mBACMmH,EAAME,YAAY,8BAA8BrH,QAAQ,KAAM,mBAG9D,OAEZ,GAAIrH,KAAK4O,eACJvI,OACC,oBACMmI,EAAME,YAAY,eAAerH,QAAQ,KAAM,QAErD,mBACMmH,EAAME,YAAY,8BAA8BrH,QAAQ,KAAM,QAEpE,mBACMmH,EAAME,YAAY,yBAAyBrH,QAAQ,KAAM,mBAGzD,GAGrB,MAAO7B,UACE,SAIJ,cAIC,eAAgB3D,SAASc,cAAc,0BAKhC,eAEXkM,GAAY,UAENxD,EAAUjL,OAAO0O,kBAAmB,oCAEtB,EACL,eAGRhM,iBAAiB,OAAQ,KAAMuI,GACxC,MAAO7F,WAIFqJ,EAfQ,cAmBN,eACHE,EAAQlN,SAASc,cAAc,kBAC/B0D,KAAO,QACS,UAAf0I,EAAM1I,KAHJ,SAQN,iBAAkBxE,SAASE,6BAGG,IAAxBjC,EAAMkP,4BAIJ,eAAgBtP,QAAUA,OAAOuP,WAAW,4BAA4BlH,SCzJrFmH,EAAO,aAEQC,wBACLC,kBACHC,QAAU3P,OAAO4P,SAAWF,EAAO9G,OAAO2B,MAE3CjK,KAAKqP,cACAE,IAAI,kEAMNvP,KAAKqP,QAAU5O,SAASqH,UAAU0H,KAAKvM,KAAKqM,QAAQC,IAAKD,SAAWJ,sCAIpElP,KAAKqP,QAAU5O,SAASqH,UAAU0H,KAAKvM,KAAKqM,QAAQpF,KAAMoF,SAAWJ,uCAIrElP,KAAKqP,QAAU5O,SAASqH,UAAU0H,KAAKvM,KAAKqM,QAAQtF,MAAOsF,SAAWJ,WCnB/EO,wBACUL,kBACHC,QAAUD,EAAO9G,OAAOlE,QAAQiL,aAChCxI,IAAMuI,EAAO9G,OAAOlE,QAAQyC,0CAsBjCA,OACM6I,EAAQhQ,OAAO4E,aAAaC,QAAQvE,KAAK6G,SAE1C4I,EAAQZ,WAAa/O,EAAM8C,GAAGgE,MAAM8I,UAC9B,SAGLC,EAAOnL,KAAKC,MAAMiL,UAEjB5P,EAAM8C,GAAGvB,OAAOwF,IAAQA,EAAIpF,OAASkO,EAAK9I,GAAO8I,8BAGxDjO,MAEK+N,EAAQZ,WAAc7O,KAAKqP,SAK3BvP,EAAM8C,GAAGlB,OAAOA,QAKf0C,EAAUpE,KAAK4P,QAGfvD,OAAOjI,EAAS1C,UAGf4C,aAAaS,QAAQ/E,KAAK6G,IAAKrC,KAAKQ,UAAUZ,8CA/C/C,iBAAkB1E,eACb,oBAQA4E,aAAaS,QALX,UAAA,kBAMFT,aAAauL,WANX,YAOF,EACT,MAAOrK,UACE,YCpBbN,EAAU,eACRqC,GAAQ,SAERzH,EAAM8C,GAAGC,SAAShB,SAASiO,oBACnB,IAIJ,SACA,IACA,MACA,KACA,SACFC,KAAK,mBACCjQ,EAAM8C,GAAGC,SAAShB,SAAYmO,0BACtBA,GACD,MACAlQ,EAAM8C,GAAGC,SAAShB,SAASoO,oBAAqBpO,SAASqO,yBAExD,MACD,KAOZ3I,EA3BK,GA+BV6B,oBAKOvH,SAASsO,mBAAqBtO,SAASuO,yBAA2BvO,SAASwO,sBAAwBxO,SAASqO,8BAI/F,OAAXhL,EAAkB,qBAA0BA,2CAG1CxC,OACJ0G,EAAWiG,eACL,MAGL5I,EAAS3G,EAAM8C,GAAGlC,gBAAgBgC,GAAWb,SAAS+B,KAAOlB,SAE3DwC,OACC,UACMrD,SAASyO,oBAAsB7J,MAErC,aACM5E,SAAS0O,uBAAyB9J,iBAGlC5E,SAAYqD,yBAA+BuB,+BAK5C/D,OACT0G,EAAWiG,eACL,MAGL5I,EAAS3G,EAAM8C,GAAGlC,gBAAgBgC,GAAWb,SAAS+B,KAAOlB,SAE3DwC,EAAOzD,OAAsCgF,EAAOvB,GAAqB,OAAXA,EAAkB,oBAAsB,wBAAtFuB,EAAO+J,yDAK1BpH,EAAWiG,UAIRnK,EAAOzD,OAAuCI,SAASqD,GAAqB,OAAXA,EAAkB,iBAAmB,uBAAtFrD,SAASiO,+CAK5B1G,EAAWiG,QAIRnK,EAAOzD,OAAsCI,SAAYqD,uBAAzCrD,SAASyO,kBAHtB,0BAQNtQ,KAAK6O,UAAUf,KAAM9N,KAAK4O,SAAY5O,KAAKsI,OAAOc,WAAWiG,aAK5DoB,EAAgBrH,EAAWiG,QAE7BoB,GAAkBzQ,KAAKsI,OAAOc,WAAWsH,WAAa5Q,EAAM6Q,gBACvD1G,MAAMsF,KAAOkB,EAAgB,SAAW,qCAGvCG,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWV,WAAWiG,SAAS,SAEjFpF,MAAMsF,IAAI,kDAIfvP,KAAKyF,SAAS+C,SAAWxI,KAAKyF,SAAS+C,QAAQY,cACzCyH,YAAY7Q,KAAKyF,SAAS+C,QAAQY,YAAY,KAIlD0H,UAAU7N,KAAKjD,SC/GvB+N,EAAUjO,EAAMkO,aAEhB+C,gCAGMxG,EAAO,KAMLyG,EAAY,gBACRC,EAJS,mBAAU/N,EAAMuH,QAAUvH,EAAMuH,QAAUvH,EAAMgO,MAIlDC,CAAWjO,GAClB2I,EAAyB,YAAf3I,EAAMmD,KAChB+K,EAASvF,GAAWoF,IAAS1G,OAG/BrH,EAAMmO,QAAUnO,EAAMoO,SAAWpO,EAAMqO,SAAWrO,EAAM2H,WAMvD/K,EAAM8C,GAAG6J,OAAOwE,OAYjBpF,EAAS,KAEHd,GACF,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,IAMEX,EAAUtK,EAAM8K,qBAClB9K,EAAM8C,GAAGF,QAAQ0H,IAAYtK,EAAMiI,QAAQqC,EAASM,EAAKpC,OAAOC,UAAUiJ,wBAK1EzG,EAAe5C,SAAS8I,OAClBlG,mBACA0G,mBAGFR,QACC,QACA,QACA,QACA,QACA,QACA,QACA,QACA,QACA,QACA,GAEIG,MAzDRxH,YAAcc,EAAKf,SAAW,IAAMsH,EAAO,gBA8DvC,QACA,GAEIG,KACIM,wBAIR,KAEIC,eAAe,eAGnB,KAEIC,eAAe,eAGnB,GAEIR,MACIS,OAASnH,EAAKmH,kBAItB,KAEI/I,qBAGJ,KAEID,oBAGJ,KAEIiJ,8BAGJ,GAEIV,KACIW,4BAIR,KAEIC,MAAQtH,EAAKsH,MAqBrB5I,EAAWiG,SAAW3E,EAAKtB,WAAWuB,QAAmB,KAATsG,KAC5Ca,qBAIFb,SAEA,OAKXjR,KAAKsI,OAAO2J,SAASC,SACf1H,GAAG9K,OAAQ,gBAAiBsR,GAAW,GACtChR,KAAKsI,OAAO2J,SAAS7H,WACtBI,GAAGxK,KAAKyF,SAASzB,UAAW,gBAAiBgN,GAAW,KAK5DxG,GAAGxK,KAAKyF,SAASzB,UAAW,WAAY,cACpC4M,YAAY1N,EAAMuD,OAAQiE,EAAKpC,OAAOwB,WAAWqI,UAAU,OAI/D3H,GAAGxK,KAAKyF,SAASzB,UAAW,UAAW,YACnB,IAAlBd,EAAMuH,gBAMHgD,WAAW,aACRmD,YAAY9Q,EAAM8K,kBAAmBF,EAAKpC,OAAOwB,WAAWqI,UAAU,IAC7E,KAIHnS,KAAKsI,OAAO8J,gBAEN5H,GAAGxK,KAAKyF,SAASzB,UAAW,+FAAgG,cACzHqO,eAAenP,KAKxBkG,EAAWiG,YACL7E,GAAG3I,SAAUuH,EAAWkJ,UAAW,cAChCR,iBAAiB5O,OAIpBsH,GAAGxK,KAAKyF,SAASzB,UAAW,WAAY,cACrC8N,iBAAiB5O,wCAQxBsH,GAAGxK,KAAKwO,MAAO,qBAAsB,mBAASV,EAAGyE,WAAWtP,OAAWC,OAGvEsH,GAAGxK,KAAKwO,MAAO,gCAAiC,mBAASV,EAAG0E,eAAevP,OAAWC,OAItFsH,GAAGxK,KAAKwO,MAAO,aAAc,aACzBvK,aAAawO,EAAKhN,SAAS+D,QAASiJ,EAAKC,YACzCzO,aAAawO,EAAKhN,SAAS+C,QAAQO,MAAO0J,EAAKC,cAInDlI,GAAGxK,KAAKwO,MAAO,QAAS,WAEtBiE,EAAKhE,SAAWgE,EAAK9D,SAAW8D,EAAKnK,OAAOqK,oBAEvC/J,YAGA4F,MAAMoE,YAKbpI,GAAGxK,KAAKwO,MAAO,mBAAoB,mBAASV,EAAG+E,eAAe5P,OAAWC,OAGzEsH,GAAGxK,KAAKwO,MAAO,eAAgB,mBAASV,EAAGgF,aAAa7P,OAAWC,OAGnEsH,GAAGxK,KAAKwO,MAAO,2BAA4B,mBAASV,EAAGiF,aAAa9P,OAAWC,OAG/EsH,GAAGxK,KAAKwO,MAAO,yCAA0C,mBAASV,EAAGkF,aAAa/P,OAAWC,KAM/FlD,KAAK6O,UAAUf,IAAM9N,KAAKsI,OAAO2K,cAAgBjT,KAAK4O,QAAS,KAEzDlJ,EAAU5F,EAAMuI,WAAWpF,KAAKjD,SAAUA,KAAKsI,OAAOwB,WAAWqE,WAGlErO,EAAM8C,GAAGF,QAAQgD,YAKhB8E,GAAG9E,EAAS,QAAS,WAEnB+M,EAAKnK,OAAO8J,cAAgBjO,EAAQ+O,QAAUT,EAAKU,SAInDV,EAAKU,SACAzK,OACE+J,EAAKW,SACPxK,YACAF,UAEAC,WAMb3I,KAAK6O,UAAUf,IAAM9N,KAAKsI,OAAO+K,sBAC3B7I,GACFxK,KAAKwO,MACL,cACA,cACUzD,mBAEV,KAKFP,GAAGxK,KAAKwO,MAAO,eAAgB,aAE5BpK,QAAQkP,KAAM9J,OAAQiJ,EAAKjJ,OAAQqI,MAAOY,EAAKZ,YAIlDrH,GAAGxK,KAAKwO,MAAO,aAAc,aAEtB+E,cAActQ,OAAW,WAG7BmB,QAAQkP,KAAME,MAAOf,EAAKe,YAI7BhJ,GAAGxK,KAAKwO,MAAO,gBAAiB,aAEzB+E,cAActQ,OAAW,aAG7BmB,QAAQkP,KAAMG,QAAShB,EAAKgB,cAI/BjJ,GAAGxK,KAAKwO,MAAO,iBAAkB,aAE1B+E,cAActQ,OAAW,cAG7BmB,QAAQkP,KAAM1T,SAAU6S,EAAK7S,eAIhC4K,GAAGxK,KAAKwO,MAAO,mCAAoC,aAE5C+E,cAActQ,OAAW,cAG7BmB,QAAQkP,KAAMnK,SAAUsJ,EAAKtJ,SAASwB,aAKzCH,GAAGxK,KAAKwO,MAAOxO,KAAKsI,OAAO8C,OAAOsI,QACpC,QACA,YACD9G,KAAK,KAAM,gBACNnB,KAGe,UAAfvI,EAAMmD,SACGoM,EAAKjE,MAAMxE,SAGlB4B,cAAc3I,OAAWwP,EAAKhN,SAASzB,UAAWd,EAAMmD,MAAM,EAAMoF,qCAOxEkI,EAAa5F,EAAQ6F,KAAO,SAAW,QAGvCC,EAAQ,SAAC3Q,EAAO4Q,EAAYC,OACxBC,EAAgBC,EAAK3L,OAAOyI,UAAU+C,GAGxChU,EAAM8C,GAAGC,SAASmR,MACJ/Q,OAAWC,IAIxBA,EAAMgR,kBAAoBpU,EAAM8C,GAAGC,SAASkR,MAC9B9Q,OAAWC,MAK5BsH,GAAGxK,KAAKyF,SAAS+C,QAAQE,KAAM,QAAS,mBAC1CmL,EAAM3Q,EAAO,OAAQ,aACZwO,mBAKPlH,GAAGxK,KAAKyF,SAAS+C,QAAQI,QAAS,QAAS,mBAC7CiL,EAAM3Q,EAAO,UAAW,aACf0F,gBAKP4B,GAAGxK,KAAKyF,SAAS+C,QAAQK,OAAQ,QAAS,mBAC5CgL,EAAM3Q,EAAO,SAAU,aACd2F,eAKP2B,GAAGxK,KAAKyF,SAAS+C,QAAQM,QAAS,QAAS,mBAC7C+K,EAAM3Q,EAAO,UAAW,aACf4F,gBAKP0B,GAAGxK,KAAKyF,SAAS+C,QAAQO,KAAM,QAAS,mBAC1C8K,EAAM3Q,EAAO,OAAQ,aACZ2O,OAASoC,EAAKpC,YAKrBrH,GAAGxK,KAAKyF,SAAS+C,QAAQW,SAAU,QAAS,mBAC9C0K,EAAM3Q,EAAO,WAAY,aAChB6O,uBAKPvH,GAAGxK,KAAKyF,SAAS+C,QAAQY,WAAY,QAAS,mBAChDyK,EAAM3Q,EAAO,aAAc,aAClB4O,yBAKPtH,GAAGxK,KAAKyF,SAAS+C,QAAQQ,IAAK,QAAS,mBACzC6K,EAAM3Q,EAAO,MAAO,aACX8F,IAAM,eAKbwB,GAAGxK,KAAKyF,SAAS+C,QAAQS,QAAS,QAAS,mBAC7C4K,EAAM3Q,EAAO,UAAW,aACf+F,gBAKPuB,GAAGxK,KAAKyF,SAAS+C,QAAQU,SAAU,QAAS,cACrCiL,WAAWlR,OAAWC,OAI7BsH,GAAG3I,SAASE,gBAAiB,QAAS,cAC/BoS,WAAWlR,OAAWC,OAI7BsH,GAAGxK,KAAKyF,SAASyD,SAASkL,KAAM,QAAS,cACrC3C,kBAGF3R,EAAMiI,QAAQ7E,EAAMuD,OAAQwN,EAAK3L,OAAOC,UAAUe,OAAO1J,YACnDsD,EAAO,WAAY,aAChBtD,SAAWsD,EAAMuD,OAAOc,QAE1BzH,EAAMiI,QAAQ7E,EAAMuD,OAAQwN,EAAK3L,OAAOC,UAAUe,OAAOmK,WAC1DvQ,EAAO,UAAW,aACfuQ,QAAUvQ,EAAMuD,OAAOc,QAEzBzH,EAAMiI,QAAQ7E,EAAMuD,OAAQwN,EAAK3L,OAAOC,UAAUe,OAAOkK,SAC1DtQ,EAAO,QAAS,aACbsQ,MAAQa,WAAWnR,EAAMuD,OAAOc,WAGhC+M,QAAQrR,OAAWC,OAK9BsH,GAAGxK,KAAKyF,SAAS6D,OAAOC,KAAMoK,EAAY,mBAC5CE,EAAM3Q,EAAO,OAAQ,aACZ0G,YAAc1G,EAAMuD,OAAOc,MAAQrE,EAAMuD,OAAOuF,IAAMiI,EAAKtK,aAMpE3J,KAAKsI,OAAOiM,eAAiBzU,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAASgE,QAAQE,aAC9Da,GAAGxK,KAAKyF,SAASgE,QAAQG,YAAa,QAAS,WAExB,IAArBqK,EAAKrK,gBAIJtB,OAAOkM,YAAcP,EAAK3L,OAAOkM,aACnCjC,WAAWtP,aAKhBuH,GAAGxK,KAAKyF,SAAS6D,OAAOE,OAAQmK,EAAY,mBAC9CE,EAAM3Q,EAAO,SAAU,aACdsG,OAAStG,EAAMuD,OAAOc,UAK/BwG,EAAQ0G,YACFjK,GAAG1K,EAAM2I,YAAYxF,KAAKjD,KAAM,uBAAwB,QAAS,cAC1D0U,gBAAgBzR,OAAWC,EAAMuD,YAK5C+D,GAAGxK,KAAKyF,SAAS4D,SAAU,kCAAmC,mBAASjB,EAASuM,kBAAkB1R,OAAWC,KAG/GlD,KAAKsI,OAAO8J,iBAEN5H,GAAGxK,KAAKyF,SAAS2C,SAAU,wBAAyB,cACjD3C,SAAS2C,SAASwM,MAAuB,eAAf1R,EAAMmD,SAInCmE,GAAGxK,KAAKyF,SAAS2C,SAAU,oDAAqD,cAC7E3C,SAAS2C,SAASyD,SACnB,YACA,cACF1D,SAASjF,EAAMmD,UAIfmE,GAAGxK,KAAKyF,SAAS2C,SAAU,mBAAoB,cAC5CiK,eAAenP,QAKtBsH,GACFxK,KAAKyF,SAAS6D,OAAOE,OACrB,QACA,mBACIqK,EAAM3Q,EAAO,SAAU,eAGb2R,EAAW3R,EAAM4R,kCAEnBC,EAAY,GAGZ7R,EAAM8R,OAAS,GAAK9R,EAAM+R,OAAS,KAC/BJ,KACKjD,eANA,QAOQ,MAERD,eATA,OAUO,KAKhBzO,EAAM8R,OAAS,GAAK9R,EAAM+R,OAAS,KAC/BJ,KACKlD,eAjBA,OAkBO,MAEPC,eApBA,QAqBQ,KAKF,IAAdmD,GAAmBd,EAAKzF,MAAMhF,OAAS,IAAsB,IAAfuL,GAAoBd,EAAKzF,MAAMhF,OAAS,MACjFuB,qBAGlB,KC/jBN+C,6BAEQ8C,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOC,UAAUvE,UAAUqD,QAAQ,IAAK,KAAK,KACvFuJ,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWoL,YAAalV,KAAK6O,UAAUf,8FAKhF9N,KAAKyO,aACVD,MAAMtK,aAAa,WAAY,SAE/BsK,MAAM3G,gBAAgB,mCAQrB2G,MAAMvL,KAAKjD,OAGhBA,KAAK6O,UAAUf,eACX7D,MAAMC,+BAA+BlK,KAAK2N,aAAY3N,KAAKqG,QAG1D8O,cAAclS,KAAKjD,KAAM,cAGzBmV,cAAclS,KAAKjD,KAAM,uBAG5BmK,qBAAqBlH,KAAKjD,MAAM,GAOlCF,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAAS2C,cAEvBgN,OAAOnS,KAAKjD,QAGXoI,SAASnF,KAAKjD,OAIvBF,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAAS2C,cAKjC+B,qBAAqBlH,KAAKjD,QAGlBqV,MAAMpS,KAAKjD,QAGbqV,MAAMpS,KAAKjD,WAGfwJ,OAAS,UAGTqI,MAAQ,UAGR2B,MAAQ,UAGRxB,KAAO,UAGP3G,QAAQoI,aAGVlB,WAAWtP,KAAKjD,QAGhB+S,aAAa9P,KAAKjD,WAGhBsV,OAAQ,IAGP1J,cAAc3I,KAAKjD,KAAMA,KAAKwO,MAAO,WAGxC+G,SAAStS,KAAKjD,gCAMbwV,EAAQxV,KAAKsI,OAAOmN,KAAK/M,QAGzB5I,EAAM8C,GAAGvB,OAAOrB,KAAKsI,OAAOoN,SAAW5V,EAAM8C,GAAGgE,MAAM5G,KAAKsI,OAAOoN,iBACpD1V,KAAKsI,OAAOoN,WAGrBjQ,SAASzB,UAAUE,aAAa,aAAclE,KAAKsI,OAAOoN,QAI/D5V,EAAM8C,GAAGpB,SAASxB,KAAKyF,SAAS+C,QAAQE,aAClC9C,KAAK5F,KAAKyF,SAAS+C,QAAQE,MAAM3F,QAAQ,cACpCmB,aAAa,aAAcsR,KAMtCxV,KAAK2V,QAAS,KACRC,EAAS9V,EAAMuI,WAAWpF,KAAKjD,KAAM,cAEtCF,EAAM8C,GAAGF,QAAQkT,cAKhBF,EAAS5V,EAAM8C,GAAGgE,MAAM5G,KAAKsI,OAAOoN,OAA6B,QAApB1V,KAAKsI,OAAOoN,QAExDxR,aAAa,QAASlE,KAAKsI,OAAOmN,KAAKI,WAAWxO,QAAQ,UAAWqO,2CAO1E9E,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWgM,QAAS9V,KAAK8V,WAC1ElF,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWiM,QAAS/V,KAAKmT,QAG5ErT,EAAM8C,GAAGpB,SAASxB,KAAKyF,SAAS+C,QAAQE,aAClC9C,KAAK5F,KAAKyF,SAAS+C,QAAQE,MAAM3F,QAAQ,mBAAUjD,EAAM+Q,YAAYmF,EAAQtL,EAAKoL,gBAIvFzD,gBAAgBrS,KAAK8V,gCAIjB5S,mBACJ+S,QAAsC,IAA5BjW,KAAKwO,MAAM0H,eACtB,UACA,WACF/N,SAASjF,EAAMmD,mBAGJrG,KAAKmW,OAAOF,cAGpBE,OAAOF,QAAUxI,WAAW,aAEvBmD,YAAY6B,EAAKhN,SAASzB,UAAWyO,EAAKnK,OAAOwB,WAAWmM,QAASxD,EAAKwD,WAG3E5D,eAAeI,EAAKwD,UAC1BjW,KAAKiW,QAAU,IAAM,2CAMnBG,OAAqC,IAA5BpW,KAAKwO,MAAM0H,aAErBlW,KAAKoW,WACCxF,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWmM,SAAS,KACrErF,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWE,OAAO,iBAIhEhK,KAAKmW,OAAOC,aAGpBD,OAAOF,QAAUxI,WAAW,aAEvBmD,YAAYqD,EAAKxO,SAASzB,UAAWiQ,EAAK3L,OAAOwB,WAAWmM,QAAShC,EAAKgC,WAG3E5D,eAAe4B,EAAKgC,UAC1BjW,KAAKiW,QAAU,IAAM,4BAKnBjW,KAAK6O,UAAUf,KAKhBhO,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAAS6D,OAAOE,WACnC6M,SAASpT,KAAKjD,KAAMA,KAAKyF,SAAS6D,OAAOE,OAAQxJ,KAAK6R,MAAQ,EAAI7R,KAAKwJ,QAI1E1J,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAAS+C,QAAQO,SACjC8H,YAAY7Q,KAAKyF,SAAS+C,QAAQO,KAAM/I,KAAK6R,OAAyB,IAAhB7R,KAAKwJ,4BAKhE/C,OAAQc,yDAAQ,EAChBzH,EAAM8C,GAAGF,QAAQ+D,OAKfc,MAAQA,IAGNmN,gBAAgBzR,KAAKjD,KAAMyG,0BAI5BA,EAAQ1G,OACVwH,EAAQzH,EAAM8C,GAAG6J,OAAO1M,GAASA,EAAQ,EACzCsJ,EAAWvJ,EAAM8C,GAAGF,QAAQ+D,GAAUA,EAASzG,KAAKyF,SAASgE,QAAQC,UAGvE5J,EAAM8C,GAAGF,QAAQ2G,GAAW,GACnB9B,MAAQA,MAGXiO,EAAQnM,EAAShG,qBAAqB,QAAQ,GAChDvD,EAAM8C,GAAGF,QAAQ8S,OACX3R,WAAW,GAAGyS,UAAY/O,6BAM7BrE,iBACNlD,KAAK6O,UAAUf,IAAOhO,EAAM8C,GAAGM,MAAMA,QAItCqE,EAAQ,KAERrE,SACQA,EAAMmD,UAEL,iBACA,YACOvG,EAAMyW,cAAcvW,KAAK4J,YAAa5J,KAAK2J,UAGhC,eAAfzG,EAAMmD,QACHgQ,SAASpT,KAAKjD,KAAMA,KAAKyF,SAAS6D,OAAOC,KAAMhC,aAMrD,cACA,aACQ,eACGiP,EAAaC,EAAKjI,MAAlBgI,gBAEJA,GAAYA,EAAS/U,OAEd3B,EAAMyW,cAAcC,EAASE,IAAI,GAAID,EAAK9M,UAC1C7J,EAAM8C,GAAG6J,OAAO+J,GAEL,IAAXA,EAGJ,EAXF,KAcNG,YAAY1T,KAAKjD,KAAMA,KAAKyF,SAASgE,QAAQC,OAAQnC,uCAWtDd,yDAAS,KAAMmQ,yDAAO,EAAG/B,6DAElC/U,EAAM8C,GAAGF,QAAQ+D,IAAY3G,EAAM8C,GAAG6J,OAAOmK,QAK5CC,EAAS,uBAAatP,GAAQuP,OAAO,IAGrCC,EAAW,mBAASC,SAAUzP,EAAQ,GAAK,GAAM,GAAI,KAKvD0P,EAAQF,EAASH,GACfM,EALa,mBAASF,SAAUzP,EAAQ,GAAM,GAAI,IAK3C4P,CAAWP,GAClBQ,EALa,mBAASJ,SAASzP,EAAQ,GAAI,IAKpC8P,CAAWT,GAGpBG,EAAS/W,KAAK2J,UAAY,WAGlB,KAKLnD,aAAiBqO,EAAW,IAAM,IAAKoC,EAAQJ,EAAOK,OAASL,EAAOO,yBAItElU,OAEDoU,GAAUxX,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAASgE,QAAQE,WAAa3J,KAAKsI,OAAOkM,aAG7E+C,kBAAkBtU,KAAKjD,KAAMA,KAAKyF,SAASgE,QAAQG,YAAa0N,EAAStX,KAAK2J,SAAW3J,KAAK4J,YAAc5J,KAAK4J,YAAa0N,GAG7HpU,GAAwB,eAAfA,EAAMmD,MAAyBrG,KAAKwO,MAAMgJ,WAKpD3E,eAAe5P,KAAKjD,KAAMkD,8BAKxBlD,KAAK6O,UAAUf,MAKfhO,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAASgE,QAAQE,WAAa3J,KAAKsI,OAAOmP,iBAAmBzX,KAAKmT,UACtFoE,kBAAkBtU,KAAKjD,KAAMA,KAAKyF,SAASgE,QAAQG,YAAa5J,KAAK2J,UAIxE7J,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAASgE,QAAQE,aACpC4N,kBAAkBtU,KAAKjD,KAAMA,KAAKyF,SAASgE,QAAQE,SAAU3J,KAAK2J,YAIhEgL,kBAAkB1R,KAAKjD,SC5VlC+N,EAAUjO,EAAMkO,aAEhB5F,4BAEc3B,MAEPsH,EAAQ0G,cAKP1F,EAAQjP,EAAM8C,GAAGM,MAAMuD,GAAUA,EAAOA,OAASA,KAGlD3G,EAAM8C,GAAGF,QAAQqM,IAAyC,UAA/BA,EAAMjD,aAAa,SAK9ChM,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAASiS,mBAC3BjS,SAASiS,WAAa5X,EAAM6C,cAAc,cAC1C8C,SAASzB,UAAUoC,YAAYpG,KAAKyF,SAASiS,iBAGhDA,EAAa1X,KAAKyF,SAASiS,WAAWC,MACtCC,EAAa7I,EAAMxH,MAAQwH,EAAM/C,IAAM,IACvC/E,MAAe8H,EAAMvL,qCACrBqU,gEAAuED,oBAA4BA,SAGnG9R,EAAQnF,MAAMiF,KAAK8R,EAAWI,OAAOC,UAAU,mBAAQC,EAAKC,eAAiBhR,KAGpE,IAAXnB,KACWoS,WAAWpS,KAIfqS,YACPlR,EACA4Q,GACFjL,KAAK,0CAME5M,KAAKsI,OAAO8P,iBACiC,IAAxCpY,KAAKsI,OAAO8P,QAAQC,QAAQ,SAAkBtK,EAAQ6F,OAASlU,OAAO4Y,oCAK7EjS,EAAMC,OACPiS,EAAY,6BACZH,EAAUhQ,EAASoQ,WAAWvV,KAAKjD,MACnCyY,GAAeL,EAAQM,SAAyB,GAAdN,EAAQhW,SAAYpC,KAAKsI,OAAOqQ,WAGlEC,EAAO/W,SAASgX,gBAAgBN,EAAW,SAC3ChS,cACFqS,EACA9Y,EAAMuM,OAAO/F,QACH,sBAKRwS,EAAMjX,SAASgX,gBAAgBN,EAAW,OAC1CQ,EAAUN,MAAYpS,QAKxB,SAAUyS,IACNE,eAAe,+BAAgC,OAAQD,KAEvDC,eAAe,+BAAgC,aAAcD,KAIhE3S,YAAY0S,GAEVF,wBAICvS,EAAM4S,OACVnU,EAAO9E,KAAKsI,OAAOmN,KAAKpP,GACtBC,EAAalG,OAAOuL,UAAWsN,UAE7B5S,OACC,QACM,gBAGN,YACM,gBAOX,UAAWC,IACAmB,WAAazH,KAAKsI,OAAOwB,WAAWoP,SAEpCzR,MAAQzH,KAAKsI,OAAOwB,WAAWoP,OAGvCpZ,EAAM6C,cAAc,OAAQ2D,EAAYxB,yBAIvCA,MACJhF,EAAM8C,GAAGgE,MAAM9B,UACR,SAGLqU,EAAQrZ,EAAM6C,cAAc,cACvB3C,KAAKsI,OAAOwB,WAAWsP,KAAK7R,iBAGjCnB,YACFtG,EAAM6C,cACF,cAEW3C,KAAKsI,OAAOwB,WAAWsP,KAAKD,OAEvCrU,IAIDqU,yBAIEE,EAAYJ,OACfjD,EAASlW,EAAM6C,cAAc,UAC7B2D,EAAalG,OAAOuL,UAAWsN,GACjC5S,EAAOgT,EAEP3R,GAAS,EACT8N,SACAoD,SACAU,SACAC,gBAEE,SAAUjT,MACDD,KAAO,UAGlB,UAAWC,EACPA,EAAWmB,MAAMU,SAASnI,KAAKsI,OAAOwB,WAAW0P,aACtC/R,WAAazH,KAAKsI,OAAOwB,WAAW0P,WAGxC/R,MAAQzH,KAAKsI,OAAOwB,WAAW0P,QAItCnT,OACC,UACQ,IACD,SACO,UACR,SACO,kBAGb,UACQ,IACD,SACO,WACR,WACO,kBAGb,cACQ,IACD,mBACO,oBACR,iBACO,wBAGb,gBACQ,IACD,oBACO,mBACR,qBACO,4BAGb,eACUoB,WAAazH,KAAKsI,OAAOwB,WAAW0P,uBACxC,SACC,SACD,uBAICnT,IACDA,SAIXqB,KAEOtB,YAAYgC,EAASqR,WAAWxW,KAAKjD,KAAMuZ,GAAe9R,MAAO,qBACjErB,YAAYgC,EAASqR,WAAWxW,KAAKjD,KAAM4Y,GAAQnR,MAAO,yBAG1DrB,YAAYgC,EAASsR,YAAYzW,KAAKjD,KAAMsZ,GAAgB7R,MAAO,sBACnErB,YAAYgC,EAASsR,YAAYzW,KAAKjD,KAAMwV,GAAS/N,MAAO,0BAGxD,iBAAkB,IAClB,cAAgBzH,KAAKsI,OAAOmN,KAAKD,OAErCpP,YAAYgC,EAASqR,WAAWxW,KAAKjD,KAAM4Y,MAC3CxS,YAAYgC,EAASsR,YAAYzW,KAAKjD,KAAMwV,OAIjDnJ,OAAO/F,EAAYxG,EAAM6Z,0BAA0B3Z,KAAKsI,OAAOC,UAAUC,QAAQnC,GAAOC,MAExFC,cAAcyP,EAAQ1P,QAEvBb,SAAS+C,QAAQnC,GAAQ2P,EAEvBA,wBAIC3P,EAAMC,OAERkP,EAAQ1V,EAAM6C,cAChB,aAES2D,EAAW9C,SACTxD,KAAKsI,OAAOwB,WAAWoP,QAElClZ,KAAKsI,OAAOmN,KAAKpP,IAIftG,EAAQD,EAAM6C,cAChB,QACA7C,EAAMuM,OACFvM,EAAM6Z,0BAA0B3Z,KAAKsI,OAAOC,UAAUe,OAAOjD,UAEnD,YACD,MACA,SACC,UACC,eACO,OAElBC,gBAIHb,SAAS6D,OAAOjD,GAAQtG,IAGpB2U,gBAAgBzR,KAAKjD,KAAMD,8CASzBsG,EAAMC,OACX+C,EAAWvJ,EAAM6C,cACnB,WACA7C,EAAMuM,OACFvM,EAAM6Z,0BAA0B3Z,KAAKsI,OAAOC,UAAUkB,QAAQpD,SAErD,MACA,UACE,GAEXC,OAKK,WAATD,EAAmB,GACVD,YAAYtG,EAAM6C,cAAc,OAAQ,KAAM,UAEnDiX,EAAS,UACLvT,OACC,WACQrG,KAAKsI,OAAOmN,KAAKoE,iBAGzB,WACQ7Z,KAAKsI,OAAOmN,KAAKe,WAOzBhQ,iBAAmBoT,EAAOE,0BAGlCrU,SAASgE,QAAQpD,GAAQgD,EAEvBA,uBAIAhD,OACDrC,EAAYlE,EAAM6C,cAAc,aAC3B,wBAGDyD,YACNtG,EAAM6C,cACF,cAEW3C,KAAKsI,OAAOwB,WAAWoP,QAElClZ,KAAKsI,OAAOmN,KAAKpP,OAIfD,YAAYtG,EAAM6C,cAAc,OAAQ7C,EAAM6Z,0BAA0B3Z,KAAKsI,OAAOC,UAAUkB,QAAQpD,IAAQ,eAEnHZ,SAASgE,QAAQpD,GAAQrC,EAEvBA,2BAIIuD,EAAOwS,EAAM1T,EAAMqP,OAAOyD,yDAAQ,KAAMa,0DAC7CC,EAAOna,EAAM6C,cAAc,MAE3B6S,EAAQ1V,EAAM6C,cAAc,eACvB3C,KAAKsI,OAAOwB,WAAW0P,UAG5BU,EAAQpa,EAAM6C,cAChB,QACA7C,EAAMuM,OAAOvM,EAAM6Z,0BAA0B3Z,KAAKsI,OAAOC,UAAUe,OAAOjD,UAChE,qBACQA,0BAGP,mBAIT8T,EAAOra,EAAM6C,cAAc,QAAUyX,eAAe,MAEpDhU,YAAY8T,KACZ9T,YAAY+T,KACZE,mBAAmB,YAAa3E,GAElC5V,EAAM8C,GAAGF,QAAQyW,MACX/S,YAAY+S,KAGjB/S,YAAYoP,KACZpP,YAAY6T,+BAIH/W,MAGTlD,KAAKsI,OAAOgS,SAAS/Q,MACrBzJ,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAAS6D,OAAOC,OACtCzJ,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAASgE,QAAQI,cACtB,IAAlB7J,KAAK2J,cAML4Q,EAAU,EACRC,EAAaxa,KAAKyF,SAAS6D,OAAOC,KAAKkR,wBACvCC,EAAa1a,KAAKsI,OAAOwB,WAAWC,uBAGtCjK,EAAM8C,GAAGM,MAAMA,KACL,IAAMsX,EAAWvN,OAAS/J,EAAMyX,MAAQH,EAAWI,UAC1D,CAAA,IAAI9a,EAAM+a,SAAS7a,KAAKyF,SAASgE,QAAQI,YAAa6Q,YAC/CrG,WAAWrU,KAAKyF,SAASgE,QAAQI,YAAY7H,MAAM4Y,KAAM,IAMnEL,EAAU,IACA,EACHA,EAAU,QACP,OAIXhD,kBAAkBtU,KAAKjD,KAAMA,KAAKyF,SAASgE,QAAQI,YAAa7J,KAAK2J,SAAW,IAAM4Q,QAGpF9U,SAASgE,QAAQI,YAAY7H,MAAM4Y,KAAUL,MAI9Cza,EAAM8C,GAAGM,MAAMA,KACf,aACA,cACFiF,SAASjF,EAAMmD,SACPuK,YAAY5Q,KAAKyF,SAASgE,QAAQI,YAAa6Q,EAAwB,eAAfxX,EAAMmD,2BAKlEyU,EAASpT,OACTqT,EAAM/a,KAAKyF,SAASyD,SAAS8R,KAAKF,GAClCG,EAAOjb,KAAKyF,SAASyD,SAASgS,MAAMJ,KAEpC7W,aAAa8W,GAAMrT,KACnBzD,aAAagX,GAAOvT,4BAKf2D,cAEL0O,EAAO/Z,KAAKyF,SAASyD,SAASgS,MAAMzH,QAAQlR,cAAc,MAG5DzC,EAAM8C,GAAGrB,MAAM8J,QACVA,QAAQoI,QAAUpI,EAAQ8P,OAAO,mBAAWzQ,EAAKpC,OAAOmL,QAAQpI,QAAQlD,SAASsL,UAEjFpI,QAAQoI,QAAUzT,KAAKsI,OAAOmL,QAAQpI,YAIzC3D,GAAU5H,EAAM8C,GAAGgE,MAAM5G,KAAKqL,QAAQoI,UAAYzT,KAAKob,eACpDC,UAAUpY,KAAKjD,KAZX,UAYuB0H,GAG/BA,KAKC4T,aAAavB,QAkCd1O,QAAQoI,QAAQ1Q,QAAQ,mBACzBqF,EAASmT,eAAetY,OAAWwQ,EAASsG,EAvDnC,UAuD+C3R,EAASoT,SAASvY,OAAW,UAAWwQ,GAhCnF,gBACT+B,EAAQ,UAEJ/B,OACC,WACO,eAGP,WACO,iBAGP,aAIA,UACO,YAOX+B,EAAM/T,OAIJ2G,EAASqT,YAAYxY,OAAWuS,GAH5B,KAO+FkG,CAASjI,QAG9GF,cAActQ,KAAKjD,KA1Df,UA0D2B+Z,uBAKnCe,EAASvT,UACNuT,OACC,eACgB,IAAVvT,EAAc,SAAcA,gBAElC,iBACOA,OACC,eACM,YACN,eACM,YACN,eACM,YACN,cACM,WACN,cACM,WACN,eACM,WACN,cACM,WACN,aACM,WACN,gBACM,sBAEAA,MAGd,kBACMa,EAASuT,YAAY1Y,KAAKjD,qBAG1B,8BAKL8a,EAAS9W,OACbiX,EAAOjb,KAAKyF,SAASyD,SAASgS,MAAMJ,GACtCvT,EAAQ,KACRwS,EAAO/V,SAEH8W,OACC,aACO9a,KAAKmJ,SAASwB,OAAS3K,KAAKmJ,SAASvJ,SAAW,sBAIhDI,KAAK8a,GAGThb,EAAM8C,GAAGgE,MAAMW,OACPvH,KAAKsI,OAAOwS,GAASc,UAI5B5b,KAAKqL,QAAQyP,GAAS3S,SAASZ,oBAC3B0C,MAAMC,8BAA8B3C,WAAcuT,OAKtD9a,KAAKsI,OAAOwS,GAASzP,QAAQlD,SAASZ,oBAClC0C,MAAMC,2BAA2B3C,WAAcuT,MAQ3Dhb,EAAM8C,GAAGF,QAAQqX,OACXkB,GAAQA,EAAK1Y,cAAc,QAIjCzC,EAAM8C,GAAGgE,MAAMW,GAAQ,CACVvH,KAAKyF,SAASyD,SAAS8R,KAAKF,GAASvY,kBAAkBvC,KAAKsI,OAAOwB,WAAWsP,KAAK7R,OAC3F5D,UAAYyE,EAASoT,SAASvY,KAAKjD,KAAM8a,EAASvT,OAItDd,EAASsT,GAAQA,EAAKxX,8BAA8BgF,QAEtDzH,EAAM8C,GAAGF,QAAQ+D,OAEVuT,SAAU,+BA8ChBha,KAAK6O,UAAUf,UACT,SAGN3J,EAAQ0X,aAAe1S,EAAS2S,UAAU7Y,KAAKjD,MAAMyB,cAC/CzB,KAAKsI,OAAOmN,KAAKsG,QAGxB/b,KAAKmJ,SAASwB,OAAQ,KAChBqR,EAAe7S,EAAS8S,gBAAgBhZ,KAAKjD,SAE/CF,EAAM8C,GAAGsZ,MAAMF,UACRA,EAAaxG,aAIrBxV,KAAKsI,OAAOmN,KAAK0G,gDAOlBpC,EAAO/Z,KAAKyF,SAASyD,SAASgS,MAAM/R,SAAS5G,cAAc,MAG3D6Z,EAAYjT,EAAS2S,UAAU7Y,KAAKjD,MAAMyB,YACvC4Z,UAAUpY,KAAKjD,KALX,WAKuBoc,KAG9Bd,aAAavB,GAGdqC,OAKCC,EAASlT,EAAS2S,UAAU7Y,KAAKjD,MAAM0M,IAAI,4BACnCwP,EAAMtc,eACRE,EAAM8C,GAAGgE,MAAMsV,EAAM1G,OAAuB0G,EAAMtc,SAAS0c,cAA7BJ,EAAM1G,WAIzC+G,kBACO,SACHvc,KAAKsI,OAAOmN,KAAKsG,SAIrBhZ,QAAQ,cACFwY,eAAetY,OAEpBiZ,EAAMtc,SACNma,EACA,WACAmC,EAAM1G,OAAS0G,EAAMtc,SACrBwI,EAASqT,YAAYxY,OAAWiZ,EAAMtc,SAAS0c,eAC/CJ,EAAMtc,SAASka,gBAAkBrH,EAAKtJ,SAASvJ,SAASka,mBAIvDvG,cAActQ,KAAKjD,KAxCf,WAwC2B+Z,wCAQnCja,EAAM8C,GAAGlB,OAAO1B,KAAKqL,QAAQmI,QAAWpT,OAAOuB,KAAK3B,KAAKqL,QAAQmI,OAAO/R,cACpE4J,QAAQmI,OACT,GACA,IACA,EACA,KACA,IACA,KACA,SAKHnI,QAAQmI,MAAQxT,KAAKqL,QAAQmI,MAAM2H,OAAO,mBAASlH,EAAK3L,OAAOkL,MAAMnI,QAAQlD,SAASqL,SAGrF9L,GAAU5H,EAAM8C,GAAGgE,MAAM5G,KAAKqL,QAAQmI,YACnC6H,UAAUpY,KAAKjD,KApBX,QAoBuB0H,GAG/BA,OAKCqS,EAAO/Z,KAAKyF,SAASyD,SAASgS,MAAM1H,MAAMjR,cAAc,QAGxD0B,aAAajE,KAAKyF,SAASyD,SAAS8R,KAAKxH,OAAO,KAChDvP,aAAajE,KAAKyF,SAASyD,SAASgS,MAAM1H,OAAO,KAGjD8H,aAAavB,QAGd1O,QAAQmI,MAAMzQ,QAAQ,mBAASqF,EAASmT,eAAetY,OAAWuQ,EAAOuG,EAtCjE,QAsC6E3R,EAASoT,SAASvY,OAAW,QAASuQ,QAEvHD,cAActQ,KAAKjD,KAxCf,QAwC2B+Z,yBAIjC7W,OACCkR,EAASpU,KAAKyF,SAASyD,SAAvBkL,KACF4B,EAAShW,KAAKyF,SAAS+C,QAAQU,SAC/BsT,EAAO1c,EAAM8C,GAAG0I,QAAQpI,GAASA,EAAQpD,EAAM8C,GAAGF,QAAQ0R,IAA8C,SAArCA,EAAKtI,aAAa,kBAEvFhM,EAAM8C,GAAGM,MAAMA,GAAQ,KACjBuZ,EAAa3c,EAAM8C,GAAGF,QAAQ0R,IAASA,EAAKzM,SAASzE,EAAMuD,QAC3DiW,EAAWxZ,EAAMuD,SAAWzG,KAAKyF,SAAS+C,QAAQU,YAKpDuT,IAAgBA,IAAeC,GAAYF,SAK3CE,KACMjL,kBAKV3R,EAAM8C,GAAGF,QAAQsT,MACV9R,aAAa,gBAAiBsY,GAGrC1c,EAAM8C,GAAGF,QAAQ0R,OACZlQ,aAAa,eAAgBsY,KAC5B5L,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWsP,KAAKuD,KAAMH,GAEzEA,IACK3U,gBAAgB,cAEhB3D,aAAa,YAAa,yBAMhC6W,OACD6B,EAAQ7B,EAAI/U,WAAU,KACtBhE,MAAM6a,SAAW,aACjB7a,MAAM8a,QAAU,IAChB5Y,aAAa,eAAe,SAG5B0B,KAAKgX,EAAM7Y,iBAAiB,gBAAgBhB,QAAQ,gBAChDga,EAAOhd,EAAM+L,aAAa,UAC1B5H,aAAa,OAAW6Y,gBAI9BzZ,WAAW8C,YAAYwW,OAGrB3P,EAAQ2P,EAAMI,YACd9P,EAAS0P,EAAMK,sBAGf9H,cAAcyH,wCAShB1Z,OACIkW,EAASpZ,KAAKyF,SAASyD,SAAvBkQ,KACF2B,EAAM7X,EAAMuD,OACZ+V,EAA6C,UAAtCzB,EAAIjP,aAAa,iBACxBmP,EAAOpZ,SAASqb,eAAenC,EAAIjP,aAAa,qBAGjDhM,EAAM8C,GAAGF,QAAQuY,OAKsB,aAA9BA,EAAKnP,aAAa,aAO1BxJ,EAAU8W,EAAK7W,cAAc,0CAC7ByB,EAAY1B,EAAQgB,oBAGpBsC,KAAKwT,EAAKrV,oCAAoCzB,EAAQwJ,aAAa,aAAY/I,QAAQ,cAClFmB,aAAa,iBAAiB,KAIrCC,EAAQgZ,cAAgBhZ,EAAQiZ,cAAe,GAErCpb,MAAMiL,MAAW3K,EAAQ0a,mBACzBhb,MAAMkL,OAAY5K,EAAQ2a,sBAG9BI,EAAOjV,EAASkV,WAAWra,KAAKjD,KAAMib,GAGtCsC,EAAU,SAAVA,KAEE/X,EAAEiB,SAAWzC,IACb,QACA,UACFmE,SAAS3C,EAAEgY,kBAKHxb,MAAMiL,MAAQ,KACdjL,MAAMkL,OAAS,KAGnBuQ,IAAIzZ,EAAWlE,EAAMkP,cAAeuO,OAIxC/S,GAAGxG,EAAWlE,EAAMkP,cAAeuO,KAG/Bvb,MAAMiL,MAAWoQ,EAAKpQ,aACtBjL,MAAMkL,OAAYmQ,EAAKnQ,cAI7BhJ,aAAa,eAAe,KAC5BA,aAAa,YAAa,KAG7BA,aAAa,eAAgBsY,KAC9BtY,aAAa,gBAAiBsY,KAC7B3U,gBAAgB,cAGhB9D,iBAAiB,2DAA2D,GAAG+G,2BAKjFpH,iBAEC5D,EAAM8C,GAAGgE,MAAM5G,KAAKsI,OAAOF,iBACpB,SAILpE,EAAYlE,EAAM6C,cAAc,MAAO7C,EAAM6Z,0BAA0B3Z,KAAKsI,OAAOC,UAAUH,SAAS1C,aAGxG1F,KAAKsI,OAAOF,SAASD,SAAS,cACpB/B,YAAYgC,EAASsV,aAAaza,KAAKjD,KAAM,YAIvDA,KAAKsI,OAAOF,SAASD,SAAS,aACpB/B,YAAYgC,EAASsV,aAAaza,KAAKjD,KAAM,WAIvDA,KAAKsI,OAAOF,SAASD,SAAS,WACpB/B,YAAYgC,EAASsV,aAAaza,KAAKjD,KAAM,SAKvDA,KAAKsI,OAAOF,SAASD,SAAS,mBACpB/B,YAAYgC,EAASsV,aAAaza,KAAKjD,KAAM,iBAIvDA,KAAKsI,OAAOF,SAASD,SAAS,YAAa,KACrCkB,EAAWvJ,EAAM6C,cAAc,MAAO7C,EAAM6Z,0BAA0B3Z,KAAKsI,OAAOC,UAAUc,WAG5FE,EAAOnB,EAASuV,YAAY1a,KAAKjD,KAAM,wBACxB0D,EAAKF,UAEjB4C,YAAYmD,EAAKiM,SACjBpP,YAAYmD,EAAKxJ,SAGjBqG,YAAYgC,EAASwV,eAAe3a,KAAKjD,KAAM,WAKpDA,KAAKsI,OAAOgS,SAAS/Q,KAAM,KACrBQ,EAAUjK,EAAM6C,cAClB,aAEU,gBACC3C,KAAKsI,OAAOwB,WAAWC,SAElC,WAGK3D,YAAY2D,QAChBtE,SAASgE,QAAQI,YAAcE,OAGnCtE,SAAS4D,SAAWA,IACfjD,YAAYpG,KAAKyF,SAAS4D,aAIpCrJ,KAAKsI,OAAOF,SAASD,SAAS,mBACpB/B,YAAYgC,EAASyV,WAAW5a,KAAKjD,KAAM,gBAIrDA,KAAKsI,OAAOF,SAASD,SAAS,eACpB/B,YAAYgC,EAASyV,WAAW5a,KAAKjD,KAAM,aAIrDA,KAAKsI,OAAOF,SAASD,SAAS,WACpB/B,YAAYgC,EAASsV,aAAaza,KAAKjD,KAAM,SAIvDA,KAAKsI,OAAOF,SAASD,SAAS,UAAW,KACnCqB,EAAS1J,EAAM6C,cAAc,aACxB,iBAIL2D,OACG,OACC,UACCtG,KAAKsI,OAAOkB,QAIjBuF,EAAQ3G,EAASuV,YAAY1a,KAC/BjD,KACA,SACAF,EAAMuM,OAAO/F,qBACU5C,EAAKF,QAGzB4C,YAAY2I,EAAMyG,SAClBpP,YAAY2I,EAAMhP,YAEpB0F,SAAS+D,OAASA,IAEbpD,YAAYoD,MAItBxJ,KAAKsI,OAAOF,SAASD,SAAS,eACpB/B,YAAYgC,EAASsV,aAAaza,KAAKjD,KAAM,aAIvDA,KAAKsI,OAAOF,SAASD,SAAS,cAAgBrI,EAAM8C,GAAGgE,MAAM5G,KAAKsI,OAAOY,UAAW,KAC9EkQ,EAAOtZ,EAAM6C,cAAc,aACtB,iBAGNyD,YACDgC,EAASsV,aAAaza,KAAKjD,KAAM,uCACD0D,EAAKF,oBAChB,mCACiBE,EAAKF,oBACtB,SAInB4Q,EAAOtU,EAAM6C,cAAc,cACtB,4CACce,EAAKF,kBACX,6CAC6BE,EAAKF,QAC3C,oBACK,IAGTsa,EAAQhe,EAAM6C,cAAc,OAE5Bob,EAAOje,EAAM6C,cAAc,2BACRe,EAAKF,0BACX,6CAC6BE,EAAKF,QAC3C,aAIJwX,EAAOlb,EAAM6C,cAAc,WACvB,iBAIL2F,OAAOY,SAASnG,QAAQ,gBACnBgY,EAAMjb,EAAM6C,cAAc,WACtB,aACE,KAGNqT,EAASlW,EAAM6C,cACjB,SACA7C,EAAMuM,OAAOvM,EAAM6Z,0BAA0BlD,EAAKnO,OAAOC,UAAUC,QAAQU,gBACjE,eACIuN,EAAKnO,OAAOwB,WAAW0P,YAAW/C,EAAKnO,OAAOwB,WAAW0P,wCAC9C9V,EAAKF,OAAM6C,0BACf,mCACiB3C,EAAKF,OAAM6C,mBAC5B,IAErBoQ,EAAKnO,OAAOmN,KAAKpP,IAGfkB,EAAQzH,EAAM6C,cAAc,cACvB8T,EAAKnO,OAAOwB,WAAWsP,KAAK7R,UAIjC5D,UAAYD,EAAK2C,KAEhBD,YAAYmB,KACfnB,YAAY4P,KACX5P,YAAY2U,KAEZtV,SAASyD,SAAS8R,KAAK3U,GAAQ0U,MAGnC3U,YAAY4U,KACX5U,YAAY2X,QAGbzV,OAAOY,SAASnG,QAAQ,gBACnBkY,EAAOnb,EAAM6C,cAAc,2BACRe,EAAKF,OAAM6C,iBACjB,sCACsB3C,EAAKF,OAAM6C,cAC1C,qBACK,SACH,KAGN2X,EAAOle,EAAM6C,cACf,eAEU,eACI8T,EAAKnO,OAAOwB,WAAW0P,YAAW/C,EAAKnO,OAAOwB,WAAW0P,kCAClD,mCACiB9V,EAAKF,4BACtB,GAErBiT,EAAKnO,OAAOmN,KAAKpP,MAGhBD,YAAY4X,OAEX3S,EAAUvL,EAAM6C,cAAc,QAE/ByD,YAAYiF,KACXjF,YAAY6U,KAEbxV,SAASyD,SAASgS,MAAM7U,GAAQ4U,MAGpC7U,YAAY0X,KACZ1X,YAAYgO,KACPhO,YAAYgT,QAEjB3T,SAASyD,SAASkL,KAAOA,OACzB3O,SAASyD,SAASkQ,KAAOA,SAI9BpZ,KAAKsI,OAAOF,SAASD,SAAS,QAAUhE,EAAQ6E,OACtC5C,YAAYgC,EAASsV,aAAaza,KAAKjD,KAAM,QAIvDA,KAAKsI,OAAOF,SAASD,SAAS,YAAchE,EAAQ8E,WAC1C7C,YAAYgC,EAASsV,aAAaza,KAAKjD,KAAM,YAIvDA,KAAKsI,OAAOF,SAASD,SAAS,iBACpB/B,YAAYgC,EAASsV,aAAaza,KAAKjD,KAAM,eAIvDA,KAAKsI,OAAOF,SAASD,SAAS,oBACzB1C,SAASzB,UAAUoC,YAAYgC,EAASsV,aAAaza,KAAKjD,KAAM,oBAGpEyF,SAAS2C,SAAWpE,EAErBhE,KAAKsI,OAAOF,SAASD,SAAS,aAAenI,KAAKsI,OAAOY,SAASf,SAAS,YAClE8V,aAAahb,KAAKjD,MAGxBgE,mCAMHhE,KAAKsI,OAAO4V,WAAY,KAClBtF,EAAOxQ,EAASoQ,WAAWvV,KAAKjD,MAGlC4Y,EAAKF,YACCwF,WAAWtF,EAAKxW,IAAK,oBAK9BoB,GAAK2B,KAAKC,MAAsB,IAAhBD,KAAKE,cAGtBrB,EAAY,OAGZlE,EAAM8C,GAAGvB,OAAOrB,KAAKsI,OAAOF,UAChBpI,KAAKsI,OAAOF,SACjBtI,EAAM8C,GAAGC,SAAS7C,KAAKsI,OAAOF,UAGzBpI,KAAKsI,OAAOF,aAChBpI,KAAKwD,YACCxD,KAAKsI,OAAO6V,eACfne,KAAKsI,OAAOoN,QAIXtN,EAASgW,OAAOnb,KAAKjD,SACzBA,KAAKwD,YACCxD,KAAKsI,OAAO6V,eACfne,KAAKwT,cACHxT,KAAKyT,iBACJrL,EAASuT,YAAY1Y,KAAKjD,YAOxCyG,YAGA3G,EAAM8C,GAAGvB,OAAOrB,KAAKsI,OAAOC,UAAUH,SAASpE,eACtCnC,SAASU,cAAcvC,KAAKsI,OAAOC,UAAUH,SAASpE,YAI9DlE,EAAM8C,GAAGF,QAAQ+D,OACTzG,KAAKyF,SAASzB,WAIvBlE,EAAM8C,GAAGF,QAAQsB,KACVoC,YAAYpC,KAEZqW,mBAAmB,YAAarW,GAIvClE,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAAS2C,aACzBiW,aAAapb,KAAKjD,MAIxBN,OAAOC,UAAUuC,UAAUiG,SAAS,WAC9BmW,QAAQ7X,GAIdzG,KAAKsI,OAAOgS,SAASlS,SAAU,KACzBmW,EAASze,EAAM2I,YAAYxF,KAC7BjD,MAEIA,KAAKsI,OAAOC,UAAUH,SAAS1C,QAC/B,IACA1F,KAAKsI,OAAOC,UAAUgW,OACtB,KACAve,KAAKsI,OAAOwB,WAAWoP,QACzBtM,KAAK,WAGLhH,KAAK2Y,GAAQxb,QAAQ,cACjB6N,YAAY4E,EAAOgJ,EAAKlW,OAAOwB,WAAWoP,QAAQ,KAClDtI,YAAY4E,EAAOgJ,EAAKlW,OAAOwB,WAAWC,SAAS,KACnD7F,aAAa,OAAQ,gBCltCrCiF,uBAIOnJ,KAAK6O,UAAUf,QAKd2Q,EAASze,KAAKoE,QAAQwL,IAAI,eAE3B9P,EAAM8C,GAAGgE,MAAM6X,UACXtV,SAASvJ,SAAW6e,GAGzB3e,EAAM8C,GAAGgE,MAAM5G,KAAKmJ,SAASvJ,iBACxBuJ,SAASvJ,SAAWI,KAAKsI,OAAOa,SAASvJ,SAASka,gBAItDha,EAAM8C,GAAG0I,QAAQtL,KAAKmJ,SAASwB,QAAS,KACnCA,EAAS3K,KAAKoE,QAAQwL,IAAI,YAE5B9P,EAAM8C,GAAG0I,QAAQX,QACZxB,SAASwB,OAASA,OAElBxB,SAASwB,OAAS3K,KAAKsI,OAAOa,SAASwB,QAK/C3K,KAAK2O,SAAW3O,KAAKob,WAAcpb,KAAKyO,UAAYtK,EAAQ0X,WAEzD7b,KAAKsI,OAAOF,SAASD,SAAS,aAAenI,KAAKsI,OAAOY,SAASf,SAAS,eAClEuW,gBAAgBzb,KAAKjD,OAOjCF,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAAS0D,iBAC3B1D,SAAS0D,SAAWrJ,EAAM6C,cAAc,MAAO7C,EAAM6Z,0BAA0B3Z,KAAKsI,OAAOC,UAAUY,aAEpGwV,YAAY3e,KAAKyF,SAAS0D,SAAUnJ,KAAKyF,SAASC,YAItDkL,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWX,SAASkG,SAAUvP,EAAM8C,GAAGgE,MAAMuC,EAAS2S,UAAU7Y,KAAKjD,QAGxHF,EAAM8C,GAAGgE,MAAMuC,EAAS2S,UAAU7Y,KAAKjD,WAKlC4e,YAAY3b,KAAKjD,QAGjBwc,KAAKvZ,KAAKjD,MAGfA,KAAKsI,OAAOF,SAASD,SAAS,aAAenI,KAAKsI,OAAOY,SAASf,SAAS,eAClEuW,gBAAgBzb,KAAKjD,+CAO9BA,KAAKyO,SAAWzO,KAAK2O,QAAS,GACrBmN,UAAU7Y,KAAKjD,MAAM+C,QAAQ,cAE5ByH,GAAG0R,EAAO,YAAa,mBAAS/S,EAAS0V,OAAO5b,OAAWC,OAI3D4b,KAAO,eAIX9C,EAAe7S,EAAS8S,gBAAgBhZ,KAAKjD,MAG/CF,EAAM8C,GAAGsZ,MAAMF,IAEXrb,MAAMiF,KAAKoW,EAAa+C,gBAAkBtd,UACjCod,OAAO5b,KAAKjD,KAAMgc,QAG5Bhc,KAAKgf,SAAWhf,KAAKmJ,SAASwB,aAChCsU,MAAMC,gBAAgBlf,KAAKJ,uCAOhCE,EAAM8C,GAAGlC,gBAAgBV,KAAKwO,UAK3B7N,MAAMiF,KAAK5F,KAAKwO,MAAMqN,gBAAkBV,OAAO,mBAClD,WACA,aACFhT,SAAS+T,EAAM5a,sDAKV6H,EAAS2S,UAAU7Y,KAAKjD,MAAMuN,KAAK,mBAAS2O,EAAMtc,SAASka,gBAAkBrH,EAAK7S,4BAItFG,OAEGmc,EAAQpc,EAAM8C,GAAGM,MAAMnD,GAASA,EAAM0G,OAAS1G,EAC/C4K,EAASuR,EAAM6C,WAAW,GAI5B7C,IAHiB/S,EAAS8S,gBAAgBhZ,KAAKjD,QAQ/CF,EAAM8C,GAAGuc,IAAIxU,KACJyU,QAAQnc,KAAKjD,KAAM2K,EAAO0U,kBAE1BD,QAAQnc,KAAKjD,KAAM,QAG1B4L,cAAc3I,KAAKjD,KAAMA,KAAKwO,MAAO,gCAIvCzO,MAECC,KAAK6O,UAAUf,MAIhBhO,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAAS0D,UAAW,KACpCzE,EAAU5E,EAAM6C,cAAc,UAG9B2Y,aAAatb,KAAKyF,SAAS0D,cAG3BmW,EAAWxf,EAAM8C,GAAGlC,gBAAgBX,GAAiB,GAARA,EAG/CD,EAAM8C,GAAGvB,OAAOie,KACR9Y,YAAc8Y,EAAQnY,SAEtBf,YAAYkZ,QAInB7Z,SAAS0D,SAAS/C,YAAY1B,aAE9BuF,MAAMC,KAAK,wDAOfpK,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAAS+C,QAAQW,eAKxCwB,EAAS3K,KAAKoE,QAAQwL,IAAI,YAGzB9P,EAAM8C,GAAG0I,QAAQX,QAGbxB,SAASwB,OAASA,IAFT3K,KAAKsI,OAAOa,SAAvBwB,OAKHA,MACMiG,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWX,SAASwB,QAAQ,KAC7EkG,YAAY7Q,KAAKyF,SAAS+C,QAAQW,UAAU,OCzLxDoW,+BAEQC,EAAU1f,EAAM2f,eAAezf,KAAK0f,SAGpCC,EAAa7f,EAAM2I,YAAYxF,KAAKjD,cAAeA,KAAK2N,sBACxD/H,KAAK+Z,GAAY5c,QAAQjD,EAAMqV,iBAG/BvE,YAAY5Q,KAAKyF,SAASC,QAAS1F,KAAKsI,OAAOwB,WAAWmV,OAAO,KAG/DW,eAAe3c,KAAKjD,WAGvBwO,MAAMtK,aAAa,KAAMpE,EAAM+f,WAAW7f,KAAK2N,WAGhD7N,EAAM8C,GAAGlB,OAAOhC,OAAOogB,MACfxK,MAAMrS,KAAKjD,KAAMwf,MAGnBO,WAAW/f,KAAKsI,OAAO0X,KAAKT,QAAQ1R,YAInCoS,wBAA0BvgB,OAAOugB,mCAGjCA,wBAAwBxd,KAAK,aACxB6S,MAAMrS,OAAWuc,YAItBU,wBAA0B,kBACtBD,wBAAwBld,QAAQ,uDAY3CjD,EAAM8C,GAAGC,SAAS7C,KAAKif,MAAMkB,cAAe,KACpCzK,EAAU1V,KAAKif,MAAMkB,eAArBzK,SAEJ5V,EAAM8C,GAAGgE,MAAM8O,eACVpN,OAAOoN,MAAQA,SACjBH,SAAStS,KAAKjD,UAMnB6G,EAAM7G,KAAKsI,OAAO3G,KAAKye,OACvBZ,EAAU1f,EAAM2f,eAAezf,KAAK0f,YACtC5f,EAAM8C,GAAGvB,OAAOwF,KAAS/G,EAAM8C,GAAGgE,MAAMC,GAAM,KACxCzE,qDAAyDod,UAAe3Y,qDAExEzE,GACDuC,KAAK,mBAAaC,EAASC,GAAKD,EAAS+K,OAAS,OAClDhL,KAAK,YACa,OAAX0b,GAAmBvgB,EAAM8C,GAAGlB,OAAO2e,OAC9B/X,OAAOoN,MAAQ2K,EAAOC,MAAM,GAAGC,QAAQ7K,QACzCH,SAAStS,WAGnBgC,MAAM,8CAMTkI,EAAQnN,KAAKsI,OAAO6E,MAAMtN,MAAM,UACjC4F,SAASC,QAAQ1D,MAAMwe,cAAmB,IAAMrT,EAAM,GAAKA,EAAM,uBAIpEqS,OACIpQ,EAASpP,OAIRif,MAAQ,IAAIvf,OAAOogB,GAAGW,OAAOrR,EAAOZ,MAAMhL,mCAG/B4L,EAAO9G,OAAOoY,SAAW,EAAI,WAC7BtR,EAAOP,UAAUf,GAAK,EAAI,MAC/B,WACK,iBACM,iBACA,YACL,cACE,SAGLpO,QAAUA,OAAOihB,SAASC,yBACjBlhB,QAAUA,OAAOihB,SAASE,oBAG3B7gB,KAAKmJ,SAASwB,OAAS,EAAI,eAC7B3K,KAAKsI,OAAOa,SAASvJ,mCAG3BsD,OAGApD,EAAM8C,GAAGlB,OAAO0N,EAAOZ,MAAMxE,YAI3ByB,QACIvI,EAAMQ,aAIRR,EAAMQ,WACL,IACMod,QACH,kPAGH,IACMA,QACH,kIAGH,MACMA,QACH,gJAGH,SACA,MACMA,QAAU,uGAIVA,QAAU,6BAIlBtS,MAAMxE,MAAQyB,IAEfG,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,4CAE3BtL,OAEd6d,EAAW7d,EAAMuD,SAGhB+H,MAAMiF,QAAUsN,EAASC,uBAE1BpV,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,gDAE9BtL,OAEX6d,EAAW7d,EAAMuD,SAGhB+H,MAAMyS,aAAeF,EAASG,oBAE/BtV,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,gCAE3CtL,OAEE6d,EAAW7d,EAAMuD,SAGf0a,SAASle,KAAKmM,KAGfZ,MAAM9F,KAAO,aACP0Y,cACF5S,MAAM2E,QAAS,KAGnB3E,MAAM7F,MAAQ,aACR0Y,eACF7S,MAAM2E,QAAS,KAGnB3E,MAAM8S,KAAO,aACPC,cACF/S,MAAM2E,QAAS,KAGnB3E,MAAM7E,SAAWoX,EAASS,gBAC1BhT,MAAM2E,QAAS,IAGf3E,MAAM5E,YAAc,SACpBkF,eAAeM,EAAOZ,MAAO,qCAErBnO,OAAO0gB,EAASU,gCAEvB7K,KAEOpI,MAAMgJ,SAAU,IAGjB5L,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,aAGtCkT,OAAO9K,aAKjB9H,eAAeM,EAAOZ,MAAO,sCAErBuS,EAASG,gCAEhBnhB,KACS4hB,gBAAgB5hB,aAK1B+O,eAAeM,EAAOZ,MAAO,iCAErBuS,EAASC,mCAEhBjhB,KAEM6L,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,oBAAoB,WACtDzO,MAGJ6hB,mBAAmB7hB,UAK9ByJ,EAAW4F,EAAO9G,OAAlBkB,cACCsF,eAAeM,EAAOZ,MAAO,gCAErBhF,gBAEPzJ,KACSA,IACA8hB,UAAmB,IAATrY,KACboC,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,uBAKjDqD,EAAUzC,EAAO9G,OAAjBuJ,aACC/C,eAAeM,EAAOZ,MAAO,+BAErBqD,gBAEP9R,OACM2H,EAAS5H,EAAM8C,GAAG0I,QAAQvL,GAASA,EAAQ8R,IACzCnK,IACCA,EAAS,OAAS,cACrBkE,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,0BAKhDM,eAAeM,EAAOZ,MAAO,oCAErBuS,EAASe,wBAKjBhT,eAAeM,EAAOZ,MAAO,+BAErBY,EAAOxF,cAAgBwF,EAAOzF,cAKtC0B,QAAQmI,MAAQuN,EAASgB,4BAG5B3S,EAAOP,UAAUf,MACVU,MAAMtK,aAAa,YAAa,KAGrC0H,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,gBACzC5C,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,yBAGxCwT,cAAc5S,EAAO+G,OAAO8L,aAG5B9L,OAAO8L,UAAYviB,OAAOwiB,YAAY,aAElC1T,MAAMgI,SAAWuK,EAASoB,0BAGC,OAA9B/S,EAAOZ,MAAM4T,cAAyBhT,EAAOZ,MAAM4T,aAAehT,EAAOZ,MAAMgI,aACzE5K,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,cAI5CA,MAAM4T,aAAehT,EAAOZ,MAAMgI,SAGX,IAA1BpH,EAAOZ,MAAMgI,kBACNwL,cAAc5S,EAAO+G,OAAO8L,aAG7BrW,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,oBAEpD,YAGIf,WAAW,kBAAMK,EAAGuU,MAAMpf,KAAKmM,IAAS,4BAErClM,OAEJ6d,EAAW7d,EAAMuD,qBAGhBub,cAAc5S,EAAO+G,OAAOL,SAS3B5S,EAAMQ,WACL,IACM8K,MAAM2E,QAAS,EAGlB/D,EAAOZ,MAAMwD,QAEJuP,cACAH,eAEHxV,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,oBAKlD,EAEGY,EAAOZ,MAAMgJ,WACP5L,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,YAE5CA,MAAMgJ,SAAU,EAGnBpI,EAAOZ,MAAM2E,UACPvH,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,UAE5CA,MAAM2E,QAAS,IAEhBvH,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,aAGxC2H,OAAOL,QAAUpW,OAAOwiB,YAAY,aACjCtW,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,eAChD,IAKCY,EAAOZ,MAAM7E,WAAaoX,EAASS,kBAC5BhT,MAAM7E,SAAWoX,EAASS,gBAC3B5V,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,qBAI1C8T,eAAerf,KAAKmM,EAAQ2R,EAASwB,wCAI7C,IACM/T,MAAM2E,QAAS,IAEhBvH,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,WAQjD5C,cAAc3I,KAAKmM,EAAQA,EAAO3J,SAASzB,UAAW,eAAe,QACjEd,EAAMQ,aCvY9B8e,+BAGQ7C,EAAa7f,EAAM2I,YAAYxF,KAAKjD,cAAeA,KAAK2N,sBACxD/H,KAAK+Z,GAAY5c,QAAQjD,EAAMqV,iBAG/BvE,YAAY5Q,KAAKyF,SAASC,QAAS1F,KAAKsI,OAAOwB,WAAWmV,OAAO,KAGjEW,eAAe3c,KAAKjD,WAGrBwO,MAAMtK,aAAa,KAAMpE,EAAM+f,WAAW7f,KAAK2N,WAG/C7N,EAAM8C,GAAGlB,OAAOhC,OAAO+iB,SAKlBnN,MAAMrS,KAAKjD,QAJX+f,WAAW/f,KAAKsI,OAAO0X,KAAKwC,MAAM3U,IAAK,aACnCyH,MAAMrS,mCASTlD,OACLoN,EAAQrN,EAAM8C,GAAGvB,OAAOtB,GAASA,EAAMF,MAAM,KAAOG,KAAKsI,OAAO6E,MAAMtN,MAAM,KAC5E6iB,EAAU,IAAMvV,EAAM,GAAKA,EAAM,GAEjCwV,GADS,IACUD,UACpBjd,SAASC,QAAQ1D,MAAMwe,cAAmBkC,WAC1ClU,MAAMxM,MAAM4gB,yBAA2BD,oCAKtCvT,EAASpP,KAGTqL,QACI+D,EAAO9G,OAAO0J,KAAKrH,gBACfyE,EAAOsR,iBACT,YACE,SACH,SACA,cACM,UACJ,SAEPmC,EAAS/iB,EAAMgjB,mBAAmBzX,GAClC7H,EAAK1D,EAAMijB,aAAa3T,EAAOsQ,SAG/B9J,EAAS9V,EAAM6C,cAAc,UAC7BQ,oCAAwCK,MAAMqf,IAC7C3e,aAAa,MAAOf,KACpBe,aAAa,kBAAmB,MAChCsK,MAAMpI,YAAYwP,KAIlBqJ,MAAQ,IAAIvf,OAAO+iB,MAAMhC,OAAO7K,KAEhCpH,MAAM2E,QAAS,IACf3E,MAAM5E,YAAc,IAGpB4E,MAAM9F,KAAO,aACTuW,MAAMvW,OAAO/D,KAAK,aACd6J,MAAM2E,QAAS,OAIvB3E,MAAM7F,MAAQ,aACVsW,MAAMtW,QAAQhE,KAAK,aACf6J,MAAM2E,QAAS,OAIvB3E,MAAM8S,KAAO,aACTrC,MAAMqC,OAAO3c,KAAK,aACd6J,MAAM2E,QAAS,IACfvJ,YAAc,SAKvBA,EAAgBwF,EAAOZ,MAAvB5E,mBACCkF,eAAeM,EAAOZ,MAAO,qCAErB5E,gBAEPgN,OAGQzD,EAAW/D,EAAOZ,MAAlB2E,SAGD3E,MAAMgJ,SAAU,IAGjB5L,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,aAGxCyQ,MAAM+D,eAAepM,GAGxBzD,KACOxK,eAMf6K,EAAQpE,EAAO9G,OAAOkL,MAAMyP,gBACzBnU,eAAeM,EAAOZ,MAAO,sCAErBgF,gBAEPzT,KACOkf,MAAM0C,gBAAgB5hB,GAAO4E,KAAK,aAC7B5E,IACF6L,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,uBAMrDhF,EAAW4F,EAAO9G,OAAlBkB,cACCsF,eAAeM,EAAOZ,MAAO,gCAErBhF,gBAEPzJ,KACOkf,MAAM4C,UAAU9hB,GAAO4E,KAAK,aACtB5E,IACH6L,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,yBAMrDqD,EAAUzC,EAAO9G,OAAjBuJ,aACC/C,eAAeM,EAAOZ,MAAO,+BAErBqD,gBAEP9R,OACM2H,IAAS5H,EAAM8C,GAAG0I,QAAQvL,IAASA,IAElCkf,MAAM4C,UAAUna,EAAS,EAAI0H,EAAO9G,OAAOkB,QAAQ7E,KAAK,aACnD+C,IACFkE,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,yBAMrDwD,EAAS5C,EAAO9G,OAAhB0J,YACClD,eAAeM,EAAOZ,MAAO,8BAErBwD,gBAEPjS,OACM2H,EAAS5H,EAAM8C,GAAG0I,QAAQvL,GAASA,EAAQqP,EAAO9G,OAAO0J,KAAKrH,SAE7DsU,MAAMiE,QAAQxb,GAAQ/C,KAAK,aACvB+C,WAMfyb,WACGlE,MAAM6C,cAAcnd,KAAK,cACf4C,WAEVuH,eAAeM,EAAOZ,MAAO,oCAErB2U,YAKRrU,eAAeM,EAAOZ,MAAO,+BAErBY,EAAOxF,cAAgBwF,EAAOzF,oBAKrCyZ,KACJhU,EAAO6P,MAAMoE,gBACbjU,EAAO6P,MAAMqE,mBACd3e,KAAK,gBACEwI,EAAQrN,EAAMyjB,eAAeC,EAAW,GAAIA,EAAW,MACvD5D,eAAe3c,OAAWkK,OAI7B8R,MAAMwE,aAAarU,EAAO9G,OAAOob,WAAW/e,KAAK,cAC7C2D,OAAOob,UAAY3X,MAIvBkT,MAAM0E,gBAAgBhf,KAAK,cACvB2D,OAAOoN,MAAQA,IACnBH,SAAStS,YAITgc,MAAMwC,iBAAiB9c,KAAK,cACjB4C,IACRqE,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,kBAI5CyQ,MAAMuC,cAAc7c,KAAK,cACrB6J,MAAM7E,SAAWpC,IAClBqE,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,sBAI5CyQ,MAAM2E,gBAAgBjf,KAAK,cACvB6J,MAAMqN,WAAaQ,IACjBhH,MAAMpS,KAAKmM,OAGjB6P,MAAMzU,GAAG,YAAa,gBACrB2U,EAAM,KAENzb,EAAKmgB,KAAKpiB,WACJ3B,EAAMgkB,UAAUpgB,EAAKmgB,KAAK,GAAG/e,SAG9Bsa,QAAQnc,KAAKmM,EAAQ+P,OAG3BF,MAAMzU,GAAG,SAAU,cAClB1K,EAAM8C,GAAGF,QAAQ0M,EAAO6P,MAAMvc,UAAY0M,EAAOP,UAAUf,GAAI,CACjDsB,EAAO6P,MAAMvc,QAIrBwB,aAAa,YAAa,QAIjC+a,MAAMzU,GAAG,OAAQ,WAEhB4E,EAAOZ,MAAM2E,UACPvH,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,UAE5CA,MAAM2E,QAAS,IAChBvH,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,eAG5CyQ,MAAMzU,GAAG,QAAS,aACdgE,MAAM2E,QAAS,IAChBvH,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,aAG5CyQ,MAAMzU,GAAG,aAAc,cACnBgE,MAAMgJ,SAAU,IACT9T,EAAKqgB,UACbnY,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,kBAG5CyQ,MAAMzU,GAAG,WAAY,cACjBgE,MAAMgI,SAAW9S,EAAK6W,UACvB3O,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,YAGZ,IAA/BwI,SAAStT,EAAK6W,QAAS,OACjB3O,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,sBAIhDyQ,MAAMzU,GAAG,SAAU,aACfgE,MAAMgJ,SAAU,IACjB5L,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,YACzC5C,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,YAG5CyQ,MAAMzU,GAAG,QAAS,aACdgE,MAAM2E,QAAS,IAChBvH,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,aAG5CyQ,MAAMzU,GAAG,QAAS,cACdgE,MAAMxE,MAAQyB,IACfG,cAAc3I,KAAKmM,EAAQA,EAAOZ,MAAO,kBAI5Cf,WAAW,kBAAMK,EAAGuU,MAAMpf,KAAKmM,IAAS,KCtSjDrB,EAAUjO,EAAMkO,aAEhBQ,uBAIOxO,KAAKwO,WAMJoC,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWzD,KAAKgB,QAAQ,MAAOrH,KAAKqG,OAAO,KAG5FuK,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAW6D,SAAStG,QAAQ,MAAOrH,KAAK2N,WAAW,GAItG3N,KAAK2V,WACC/E,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWzD,KAAKgB,QAAQ,MAAO,UAAU,GAGhGrH,KAAK6O,UAAUf,OAET8C,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWd,IAAI6F,UAAW1K,EAAQ6E,KAAOhJ,KAAKyO,SAAWzO,KAAK2O,WAG/GiC,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWb,QAAQ4F,UAAW1K,EAAQ8E,SAAWjJ,KAAKyO,WAGvGmC,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWiM,QAAS/V,KAAKsI,OAAOoY,YAGjF9P,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWka,MAAOjW,EAAQiW,SAG3EpT,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWma,QAAS9f,EAAQ+O,SAInFlT,KAAK2O,SAAW3O,KAAKob,WAAapb,KAAKgf,gBAElCvZ,SAASC,QAAU5F,EAAM6C,cAAc,aACjC3C,KAAKsI,OAAOwB,WAAWqE,UAI5B+V,KAAKlkB,KAAKwO,MAAOxO,KAAKyF,SAASC,UAGrC1F,KAAK2V,eACG3V,KAAK2N,cACJ,YACO0H,MAAMpS,KAAKjD,gBAGlB,UACKqV,MAAMpS,KAAKjD,WAMlBA,KAAKyO,WACT8G,SAAStS,KAAKjD,gBA1DZiK,MAAMC,KAAK,sDAiEflK,KAAKyO,gBAKJ7I,KAAK5F,KAAKwO,MAAMzK,iBAAiB,WAAWhB,QAAQjD,EAAMqV,oBAK3D3G,MAAMtK,aAAa,MAAOlE,KAAKsI,OAAO6b,iBAKtC3V,MAAMoE,YAGN3I,MAAMsF,IAAI,iCC3FjBpD,2BAEa9F,EAAMC,cACbxG,EAAM8C,GAAGvB,OAAOiF,KACV8d,cAAc/d,EAAMrG,KAAKwO,WACtBlI,IAEFxG,EAAM8C,GAAGrB,MAAM+E,MACXvD,QAAQ,cACTqhB,cAAc/d,EAAMqE,EAAK8D,MAAO6V,sBAO3CtkB,cACED,EAAM8C,GAAGlB,OAAO3B,IAAY,YAAaA,GAAWA,EAAMmM,QAAQzK,UAMjE6iB,eAAerhB,KAAKjD,WAGrBukB,QAAQthB,KACTjD,KACA,oBAIUmV,cAAc1C,EAAKjE,SACpBA,MAAQ,KAGT1O,EAAM8C,GAAGF,QAAQ+P,EAAKhN,SAASzB,cAC1ByB,SAASzB,UAAU6D,gBAAgB,WAIvCxB,KAAOtG,EAAMsG,OACbsH,SAAY7N,EAAM8C,GAAGgE,MAAM7G,EAAMmM,QAAQ,GAAGyB,UAAwCpO,EAAUilB,MAAtCzkB,EAAMmM,QAAQ,GAAGyB,WAGzEkB,UAAY1K,EAAQsgB,MAAMhS,EAAKpM,KAAMoM,EAAK9E,SAAU8E,EAAKnK,OAAOsF,QAG1D6E,EAAK9E,aAAY8E,EAAKpM,UACxB,gBACImI,MAAQ1O,EAAM6C,cAAc,mBAGhC,gBACI6L,MAAQ1O,EAAM6C,cAAc,mBAGhC,oBACA,gBACI6L,MAAQ1O,EAAM6C,cAAc,SAC5B+c,QAAU3f,EAAMmM,QAAQ,GAAG/I,MAQnCsC,SAASzB,UAAUoC,YAAYqM,EAAKjE,OAGrC1O,EAAM8C,GAAG0I,QAAQvL,EAAM2gB,cAClBpY,OAAOoY,SAAW3gB,EAAM2gB,UAI7BjO,EAAKhE,UACDgE,EAAKnK,OAAOoc,eACPlW,MAAMtK,aAAa,cAAe,IAEvCuO,EAAKnK,OAAOoY,YACPlS,MAAMtK,aAAa,WAAY,IAEpC,WAAYnE,KACPyO,MAAMtK,aAAa,SAAUnE,EAAM4kB,QAExClS,EAAKnK,OAAO0J,KAAKrH,UACZ6D,MAAMtK,aAAa,OAAQ,IAEhCuO,EAAKnK,OAAOuJ,SACPrD,MAAMtK,aAAa,QAAS,IAEjCuO,EAAKnK,OAAOsF,UACPY,MAAMtK,aAAa,cAAe,OAK5C0gB,aAAa3hB,QAGZwP,EAAKhE,WACEoW,eAAe5hB,OAAW,SAAUlD,EAAMmM,WAIhD5D,OAAOoN,MAAQ3V,EAAM2V,QAGpBL,MAAMpS,QAGRwP,EAAKhE,UAED,WAAY1O,KACL8kB,eAAe5hB,OAAW,QAASlD,EAAMsc,UAI/C7N,MAAMoE,SAIXH,EAAKhE,SAAYgE,EAAKkD,UAAYlD,EAAK5D,UAAUf,OAE9CuU,MAAMpf,UAGjB,SA9GKgH,MAAMC,KAAK,2BCAxB4a,KACG,IACA,gCAKSre,EAAQ4E,gCACX8K,eAGAb,OAAQ,OACRW,SAAU,OACVG,QAAS,OAGT5H,MAAQ/H,EAGT3G,EAAM8C,GAAGvB,OAAOrB,KAAKwO,cAChBA,MAAQ3M,SAASkC,iBAAiB/D,KAAKwO,SAI3C9O,OAAOqlB,QAAU/kB,KAAKwO,iBAAiBuW,QAAWjlB,EAAM8C,GAAGpB,SAASxB,KAAKwO,QAAU1O,EAAM8C,GAAGrB,MAAMvB,KAAKwO,eAEnGA,MAAQxO,KAAKwO,MAAM,SAIvBlG,OAASxI,EAAMuM,UAEhB5M,EACA4L,EACC,sBAEc7G,KAAKC,MAAMiG,EAAK8D,MAAM1C,aAAa,qBAC5C,MAAOtG,aAHZ,SAUAC,oBACU,gEAMD,gCAIA,WAIT0D,iBACO,kBACM,WAIbC,oBACO,QAIPiC,mCAOApB,MAAQ,IAAIkF,EAAQnP,WAGpBiK,MAAMsF,IAAI,SAAUvP,KAAKsI,aACzB2B,MAAMsF,IAAI,UAAWpL,IAGtBrE,EAAM8C,GAAGlC,gBAAgBV,KAAKwO,QAAW1O,EAAM8C,GAAGF,QAAQ1C,KAAKwO,UAM/DxO,KAAKwO,MAAMwW,UACN/a,MAAMC,KAAK,gCAKflK,KAAKsI,OAAO+G,WAOZlL,EAAQsgB,QAAQ5W,UAMhBpI,SAASwf,SAAWjlB,KAAKwO,MAAMxI,WAAU,OAIxCK,EAAOrG,KAAKwO,MAAM0W,QAAQpL,cAG1BxT,EACQ,qBADRA,EAEE,4BAIAD,OAGC,cACIA,KAAO7G,EAAM2O,WACbR,SAAW3N,KAAKwO,MAAM1C,aAAaxF,QACnCoZ,QAAU1f,KAAKwO,MAAM1C,aAAaxF,GAEnCxG,EAAM8C,GAAGgE,MAAM5G,KAAK2N,YAAcvN,OAAOuB,KAAKpC,GAAW4I,SAASnI,KAAK2N,2BAClE1D,MAAMD,MAAM,qCAKjBlK,EAAM8C,GAAGgE,MAAM5G,KAAK0f,0BACfzV,MAAMD,MAAM,8CAKhBwE,MAAM3G,gBAAgBvB,QACtBkI,MAAM3G,gBAAgBvB,aAI1B,YACA,aACID,KAAOA,OACPsH,SAAWpO,EAAUilB,MAEtBxkB,KAAKwO,MAAM2W,aAAa,sBACnB7c,OAAOoc,aAAc,GAG1B1kB,KAAKwO,MAAM2W,aAAa,mBACnB7c,OAAOoY,UAAW,GAGvB1gB,KAAKwO,MAAM2W,aAAa,sBACnB7c,OAAOsF,QAAS,GAGrB5N,KAAKwO,MAAM2W,aAAa,gBACnB7c,OAAOuJ,OAAQ,GAGpB7R,KAAKwO,MAAM2W,aAAa,eACnB7c,OAAO0J,KAAKrH,QAAS,kCAMzBV,MAAMD,MAAM,uCAKpB5F,QAAU,IAAIqL,EAAQzP,WAGtB6O,UAAY1K,EAAQsgB,MAAMzkB,KAAKqG,KAAMrG,KAAK2N,SAAU3N,KAAKsI,OAAOsF,QAGhE5N,KAAK6O,UAAUhB,UAMfW,MAAMwW,KAAOhlB,UAGbyF,SAASzB,UAAYlE,EAAM6C,cAAc,SACxCuhB,KAAKlkB,KAAKwO,MAAOxO,KAAKyF,SAASzB,gBAGhCyB,SAASzB,UAAUE,aAAa,WAAY,KAGvCgO,OAAOjP,KAAKjD,QAGnB4kB,aAAa3hB,KAAKjD,QAGfqV,MAAMpS,KAAKjD,MAGbA,KAAKsI,OAAO2B,SACNO,GAAGxK,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAO8C,OAAOwB,KAAK,KAAM,cACvD3C,MAAMsF,cAAcrM,EAAMmD,SAMnCrG,KAAKyO,SAAYzO,KAAK2V,UAAY3V,KAAK6O,UAAUf,OAC9CuU,MAAMpf,KAAKjD,YAjCTiK,MAAMD,MAAM,sCAnFZC,MAAMD,MAAM,sCAPZC,MAAMD,MAAM,8CAZZC,MAAMD,MAAM,4FAyKdhK,KAAKwO,MAAM9F,uCAOb1I,KAAK8V,cAILtH,MAAM7F,2CA4BJ5I,IAEQD,EAAM8C,GAAG0I,QAAQvL,GAASA,GAASC,KAAK8V,cAG9CpN,YAEAC,4CAQJC,eACAD,+CAOAiB,YAAc,iCAOhBuU,QACEvU,YAAc5J,KAAK4J,aAAe9J,EAAM8C,GAAG6J,OAAO0R,GAAYA,EAAWne,KAAKsI,OAAO6V,0CAOtFA,QACCvU,YAAc5J,KAAK4J,aAAe9J,EAAM8C,GAAG6J,OAAO0R,GAAYA,EAAWne,KAAKsI,OAAO6V,iDA+G/EiH,OACL5b,EAASxJ,KAAKwO,MAAMqD,MAAQ,EAAI7R,KAAKwJ,YACtCA,OAASA,GAAU1J,EAAM8C,GAAG6J,OAAO2Y,GAAQA,EAAO,0CAO5CA,OACL5b,EAASxJ,KAAKwO,MAAMqD,MAAQ,EAAI7R,KAAKwJ,YACtCA,OAASA,GAAU1J,EAAM8C,GAAG6J,OAAO2Y,GAAQA,EAAO,0CA8P5CrlB,MAENC,KAAK6O,UAAUf,IAAOhO,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAAS+C,QAAQW,eAK5DqT,EAAO1c,EAAM8C,GAAG0I,QAAQvL,GAASA,GAA+F,IAAvFC,KAAKyF,SAASzB,UAAUoD,UAAUiR,QAAQrY,KAAKsI,OAAOwB,WAAWX,SAASwB,QAGrH3K,KAAKmJ,SAASwB,SAAW6R,SAKxBrT,SAASwB,OAAS6R,IAGjB3L,YAAY7Q,KAAKyF,SAAS+C,QAAQW,SAAUnJ,KAAKmJ,SAASwB,UAG1DiG,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWX,SAASwB,OAAQ3K,KAAKmJ,SAASwB,UAG3FiB,cAAc3I,KAAKjD,KAAMA,KAAKwO,MAAOxO,KAAKmJ,SAASwB,OAAS,kBAAoB,+DAsDzEzH,OAETlD,KAAK4O,YAKLxF,EAAWiG,QAAS,KAChBvP,EAAM8C,GAAGM,MAAMA,IAAUA,EAAMmD,OAAS+C,EAAWkJ,sBAK9CtS,KAAKoJ,WAAWuB,SAGNmF,qBAFAU,kBAAkBxQ,KAAKyF,SAASzB,iBAJ1CoF,WAAWuB,OAASvB,EAAWic,aAAarlB,KAAKyF,SAASzB,qBAa9DoF,WAAWuB,QAAU3K,KAAKoJ,WAAWuB,SAGpCiG,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWV,WAAWsH,SAAU1Q,KAAKoJ,WAAWuB,QAGnG3K,KAAKoJ,WAAWuB,YAETjL,OAAO4lB,aAAe,IACtB5lB,OAAO6lB,aAAe,UAGtBC,SAASV,EAAeW,EAAGX,EAAeY,YAI5C9hB,KAAK5B,MAAM2jB,SAAW3lB,KAAKoJ,WAAWuB,OAAS,SAAW,GAInE7K,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAAS+C,QAAQY,eACjCyH,YAAY7Q,KAAKyF,SAAS+C,QAAQY,WAAYpJ,KAAKoJ,WAAWuB,UAIlEiB,cAAc3I,KAAKjD,KAAMA,KAAKwO,MAAOxO,KAAKoJ,WAAWuB,OAAS,kBAAoB,qDA2CpFxG,EAAQ8E,cACHuF,MAAMoX,wEAQJle,iBAEN5H,EAAM8C,GAAGF,QAAQ1C,KAAKyF,SAAS2C,WAK/BpI,KAAK6O,UAAUf,KAAM9N,KAAK4O,aAI3BiX,EAAQ,EACRrJ,EAAO9U,EACPoe,GAAoB,KAGnBhmB,EAAM8C,GAAG0I,QAAQ5D,KACd5H,EAAM8C,GAAGM,MAAMwE,MAEqB,oBAAhBA,EAAOrB,QAIvB,aACA,YACA,aACA,YACA,WACF8B,SAAST,EAAOrB,OAId,YACA,YACA,YACF8B,SAAST,EAAOrB,UACN,KAIQ,YAAhBqB,EAAOrB,SACC,MACFuK,YAAY5Q,KAAKyF,SAAS2C,SAAUpI,KAAKsI,OAAOwB,WAAWic,cAAc,OAG5EjmB,EAAM+a,SAAS7a,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWsI,sBAKvE4T,aAAahmB,KAAKmW,OAAO/N,UAG5BoU,GAAQxc,KAAKmT,QAAUnT,KAAKiW,QAAS,IAErBnW,EAAM8Q,YAAY5Q,KAAKyF,SAASzB,UAAWhE,KAAKsI,OAAOwB,WAAWsI,cAAc,MAItFxG,cAAc3I,KAAKjD,KAAMA,KAAKwO,MAAO,iBAI3CxO,KAAKmT,QAAUnT,KAAKiW,eAKpB9R,EAAQ+O,UACA,KAMXsJ,IAAQxc,KAAK8V,eACTK,OAAO/N,SAAW1I,OAAO+N,WAAW,eAUhCgF,EAAKhN,SAAS2C,SAASyD,UAAW4G,EAAKhN,SAAS2C,SAASwM,OAAWkR,GAKpEhmB,EAAM+a,SAASpI,EAAKhN,SAASzB,UAAWyO,EAAKnK,OAAOwB,WAAWsI,iBAC1DxB,YAAY6B,EAAKhN,SAAS2C,SAAUqK,EAAKnK,OAAOwB,WAAWic,cAAc,GAInEjmB,EAAM8Q,YAAY6B,EAAKhN,SAASzB,UAAWyO,EAAKnK,OAAOwB,WAAWsI,cAAc,OAItFxG,cAAc3I,OAAWwP,EAAKjE,MAAO,kBAEvCiE,EAAKnK,OAAOF,SAASD,SAAS,cAAgBrI,EAAM8C,GAAGgE,MAAM6L,EAAKnK,OAAOY,aAChEiL,WAAWlR,QAAW,MAGxC4iB,gCASR3iB,EAAOb,KACAmI,GAAGxK,KAAKyF,SAASzB,UAAWd,EAAOb,+BAQzCa,EAAOb,KACDob,IAAIzd,KAAKyF,SAASzB,UAAWd,EAAOb,mCAYtCA,cAAU4jB,0DACRC,EAAO,uBAEAtiB,KAAK5B,MAAM2jB,SAAW,KAG1B1G,MAAQ,OACRS,QAAU,KAGXuG,EACI7lB,OAAOuB,KAAKsS,EAAKxO,UAAUhE,SAEvBwS,EAAKxO,SAAS+C,SAAWyL,EAAKxO,SAAS+C,QAAQE,YACzC9C,KAAKqO,EAAKxO,SAAS+C,QAAQE,MAAM3F,QAAQ,mBAAUjD,EAAMqV,cAAca,OAI3Eb,cAAclB,EAAKxO,SAAS0D,YAC5BgM,cAAclB,EAAKxO,SAAS2C,YAC5B+M,cAAclB,EAAKxO,SAASC,WAG7BD,SAAS+C,QAAQE,KAAO,OACxBjD,SAAS0D,SAAW,OACpB1D,SAAS2C,SAAW,OACpB3C,SAASC,QAAU,MAIxB5F,EAAM8C,GAAGC,SAASR,YAGnB,KAEG4D,EAASgO,EAAKxO,SAASzB,UAAUV,WAEnCxD,EAAM8C,GAAGF,QAAQuD,MACVkgB,aAAalS,EAAKxO,SAASwf,SAAUhR,EAAKxO,SAASzB,aAIxD4H,cAAc3I,OAAWgR,EAAKxO,SAASwf,SAAU,aAAa,GAGhEnlB,EAAM8C,GAAGC,SAASR,MACTY,KAAKgR,EAAKxO,SAASwf,YAI3Bxf,SAAW,cAKbzF,KAAK2N,aAAY3N,KAAKqG,UACxB,kBACA,gBAEE8D,qBAAqBlH,KAAKjD,MAAM,iBAOlC,uBAEMgiB,cAAchiB,KAAKmW,OAAO8L,kBAC1BD,cAAchiB,KAAKmW,OAAOL,cAG5BmJ,MAAMsF,wBAOV,mBAGItF,MAAMmH,SAASzhB,KAAKuhB,UAGlBzY,WAAWyY,EAAM,uCAa3B7f,UACElC,EAAQkiB,KAAKpjB,KAAKjD,KAAMqG,0CA13BxBrG,KAAK2N,WAAapO,EAAUilB,6CAG5BxkB,KAAKob,WAAapb,KAAKgf,iDAGvBhf,KAAK2N,WAAapO,EAAUggB,+CAG5Bvf,KAAK2N,WAAapO,EAAUijB,6CAG5BxiB,KAAKqG,OAAS7G,EAAM2O,6CAGpBnO,KAAKqG,OAAS7G,EAAM6O,4CAyBpBrO,KAAKwO,MAAM2E,8CAOVnT,KAAKmT,SAAWnT,KAAKoT,SAAUpT,KAAKyO,SAAUzO,KAAKwO,MAAM8X,WAAa,wCAOvEtmB,KAAKwO,MAAM4E,wCAqDNrT,OACRwmB,EAAa,EAEbzmB,EAAM8C,GAAG6J,OAAO1M,OACHA,GAIbwmB,EAAa,IACA,EACNA,EAAavmB,KAAK2J,aACZ3J,KAAK2J,eAIjB6E,MAAM5E,YAAc2c,EAAWta,QAAQ,QAGvChC,MAAMsF,kBAAkBvP,KAAK4J,+CAO3BvJ,OAAOL,KAAKwO,MAAM5E,oDAOlB5J,KAAKwO,MAAMgJ,6CAQZgP,EAAexP,SAAShX,KAAKsI,OAAOqB,SAAU,IAG9C8c,EAAepmB,OAAOL,KAAKwO,MAAM7E,iBAG/BtJ,OAAOC,MAAMkmB,GAA+BC,EAAfD,+BAO9Bjf,OACHiC,EAASjC,EAITzH,EAAM8C,GAAGvB,OAAOmI,OACPnJ,OAAOmJ,IAIf1J,EAAM8C,GAAG6J,OAAOjD,OACRxJ,KAAKoE,QAAQwL,IAAI,WAIzB9P,EAAM8C,GAAG6J,OAAOjD,OACHxJ,KAAKsI,OAAhBkB,QAIHA,EAlBQ,MAAA,GAsBRA,EArBQ,MAAA,QA0BPlB,OAAOkB,OAASA,OAGhBgF,MAAMhF,OAASA,EAGhBxJ,KAAK6R,OAASrI,EAAS,SAClBqI,OAAQ,0BAQV7R,KAAKwO,MAAMhF,mCAyBZT,OACFrB,EAASqB,EAGRjJ,EAAM8C,GAAG0I,QAAQ5D,OACT1H,KAAKoE,QAAQwL,IAAI,UAIzB9P,EAAM8C,GAAG0I,QAAQ5D,OACT1H,KAAKsI,OAAOuJ,YAIpBvJ,OAAOuJ,MAAQnK,OAGf8G,MAAMqD,MAAQnK,yBAOZ1H,KAAKwO,MAAMqD,8CAQb7R,KAAKyO,UAKHzO,KAAKwO,MAAMkY,aAAelmB,QAAQR,KAAKwO,MAAMmY,8BAAgCnmB,QAAQR,KAAKwO,MAAMoY,aAAe5mB,KAAKwO,MAAMoY,YAAYnlB,qCAOvI1B,OACFyT,EAAQ,KAER1T,EAAM8C,GAAG6J,OAAO1M,OACRA,GAGPD,EAAM8C,GAAG6J,OAAO+G,OACTxT,KAAKoE,QAAQwL,IAAI,UAGxB9P,EAAM8C,GAAG6J,OAAO+G,OACTxT,KAAKsI,OAAOkL,MAAMyP,UAI1BzP,EAAQ,OACA,IAERA,EAAQ,MACA,GAGPxT,KAAKsI,OAAOkL,MAAMnI,QAAQlD,SAASqL,SAMnClL,OAAOkL,MAAMyP,SAAWzP,OAGxBhF,MAAMyS,aAAezN,QARjBvJ,MAAMC,2BAA2BsJ,8BAenCxT,KAAKwO,MAAMyS,2CAQVlhB,OACJ0T,EAAU,KAEV3T,EAAM8C,GAAGvB,OAAOtB,OACNA,GAGTD,EAAM8C,GAAGvB,OAAOoS,OACPzT,KAAKoE,QAAQwL,IAAI,YAG1B9P,EAAM8C,GAAGvB,OAAOoS,OACPzT,KAAKsI,OAAOmL,QAAQwP,UAG7BjjB,KAAKqL,QAAQoI,QAAQtL,SAASsL,SAM9BnL,OAAOmL,QAAQwP,SAAWxP,OAG1BjF,MAAMiF,QAAUA,QARZxJ,MAAMC,oCAAoCuJ,8BAe5CzT,KAAKwO,MAAMiF,mCAQb1T,OACC2H,EAAS5H,EAAM8C,GAAG0I,QAAQvL,GAASA,EAAQC,KAAKsI,OAAO0J,KAAKrH,YAC7DrC,OAAO0J,KAAKrH,OAASjD,OACrB8G,MAAMwD,KAAOtK,yBAkDX1H,KAAKwO,MAAMwD,kCAOXjS,KACA8mB,OAAO5jB,KAAKjD,KAAMD,0BAOlBC,KAAKwO,MAAM2U,wCAOXpjB,GACFC,KAAKyO,SAAYzO,KAAK2O,QAKvB7O,EAAM8C,GAAGvB,OAAOtB,SACXyO,MAAMtK,aAAa,SAAUnE,QAL7BkK,MAAMC,KAAK,gEAaflK,KAAKyO,SAAYzO,KAAK2O,QAIpB3O,KAAKwO,MAAM1C,aAAa,UAHpB,oCAUF/L,OACH2H,EAAS5H,EAAM8C,GAAG0I,QAAQvL,GAASA,EAAQC,KAAKsI,OAAOoY,cACxDpY,OAAOoY,SAAWhZ,yBAOhB1H,KAAKsI,OAAOoY,wCAsCV3gB,MAEJD,EAAM8C,GAAGvB,OAAOtB,UAKhBgS,gBAAgBjS,EAAM8C,GAAGgE,MAAM7G,KAGhCD,EAAM8C,GAAGgE,MAAM7G,SAKbH,EAAWG,EAAM+Z,cAGnB9Z,KAAKJ,WAAaA,SAKjBuJ,SAASvJ,SAAWA,IAGhBwf,QAAQnc,KAAKjD,KAAM,QAGnB4e,YAAY3b,KAAKjD,QAGpB4L,cAAc3I,KAAKjD,KAAMA,KAAKwO,MAAO,2CAOpCxO,KAAKmJ,SAASvJ,mCAgEjBG,OACE+mB,EACG,qBADHA,EAEM,YAIP3iB,EAAQ6E,SAKPtB,EAAS5H,EAAM8C,GAAG0I,QAAQvL,GAASA,EAAQC,KAAKgJ,MAAQ8d,OAGzDtY,MAAMF,0BAA0B5G,EAASof,EAAaA,2BAOtD3iB,EAAQ6E,IAINhJ,KAAKwO,MAAMuY,uBAHP,yCA0QE1gB,EAAMsH,EAAUC,UACtBzJ,EAAQsgB,MAAMpe,EAAMsH,EAAUC,sCAQvBxL,EAAKoB,UACZ1D,EAAMoe,WAAW9b,EAAKoB"}
\ No newline at end of file diff --git a/dist/plyr.svg b/dist/plyr.svg index aab6e3e3..3db87c38 100644 --- a/dist/plyr.svg +++ b/dist/plyr.svg @@ -1 +1 @@ -<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg"><symbol id="plyr-captions-off" viewBox="0 0 18 18"><path d="M1 1c-.6 0-1 .4-1 1v11c0 .6.4 1 1 1h4.6l2.7 2.7c.2.2.4.3.7.3.3 0 .5-.1.7-.3l2.7-2.7H17c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1H1zm4.52 10.15c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41C8.47 4.96 7.46 3.76 5.5 3.76c-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69zm7.57 0c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41c-.28-1.15-1.29-2.35-3.25-2.35-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69z" fill-rule="evenodd" fill-opacity=".5"/></symbol><symbol id="plyr-captions-on" viewBox="0 0 18 18"><path d="M1 1c-.6 0-1 .4-1 1v11c0 .6.4 1 1 1h4.6l2.7 2.7c.2.2.4.3.7.3.3 0 .5-.1.7-.3l2.7-2.7H17c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1H1zm4.52 10.15c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41C8.47 4.96 7.46 3.76 5.5 3.76c-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69zm7.57 0c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41c-.28-1.15-1.29-2.35-3.25-2.35-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69z" fill-rule="evenodd"/></symbol><symbol id="plyr-enter-fullscreen" viewBox="0 0 18 18"><path d="M10 3h3.6l-4 4L11 8.4l4-4V8h2V1h-7zM7 9.6l-4 4V10H1v7h7v-2H4.4l4-4z"/></symbol><symbol id="plyr-exit-fullscreen" viewBox="0 0 18 18"><path d="M1 12h3.6l-4 4L2 17.4l4-4V17h2v-7H1zM16 .6l-4 4V1h-2v7h7V6h-3.6l4-4z"/></symbol><symbol id="plyr-fast-forward" viewBox="0 0 18 18"><path d="M7.875 7.171L0 1v16l7.875-6.171V17L18 9 7.875 1z"/></symbol><symbol id="plyr-muted" viewBox="0 0 18 18"><path d="M12.4 12.5l2.1-2.1 2.1 2.1 1.4-1.4L15.9 9 18 6.9l-1.4-1.4-2.1 2.1-2.1-2.1L11 6.9 13.1 9 11 11.1zM3.786 6.008H.714C.286 6.008 0 6.31 0 6.76v4.512c0 .452.286.752.714.752h3.072l4.071 3.858c.5.3 1.143 0 1.143-.602V2.752c0-.601-.643-.977-1.143-.601L3.786 6.008z"/></symbol><symbol id="plyr-pause" viewBox="0 0 18 18"><path d="M6 1H3c-.6 0-1 .4-1 1v14c0 .6.4 1 1 1h3c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1zM12 1c-.6 0-1 .4-1 1v14c0 .6.4 1 1 1h3c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1h-3z"/></symbol><symbol id="plyr-play" viewBox="0 0 18 18"><path d="M15.562 8.1L3.87.225C3.052-.337 2 .225 2 1.125v15.75c0 .9 1.052 1.462 1.87.9L15.563 9.9c.584-.45.584-1.35 0-1.8z"/></symbol><symbol id="plyr-restart" viewBox="0 0 18 18"><path d="M9.7 1.2l.7 6.4 2.1-2.1c1.9 1.9 1.9 5.1 0 7-.9 1-2.2 1.5-3.5 1.5-1.3 0-2.6-.5-3.5-1.5-1.9-1.9-1.9-5.1 0-7 .6-.6 1.4-1.1 2.3-1.3l-.6-1.9C6 2.6 4.9 3.2 4 4.1 1.3 6.8 1.3 11.2 4 14c1.3 1.3 3.1 2 4.9 2 1.9 0 3.6-.7 4.9-2 2.7-2.7 2.7-7.1 0-9.9L16 1.9l-6.3-.7z"/></symbol><symbol id="plyr-rewind" viewBox="0 0 18 18"><path d="M10.125 1L0 9l10.125 8v-6.171L18 17V1l-7.875 6.171z"/></symbol><symbol id="plyr-volume" viewBox="0 0 18 18"><path d="M15.6 3.3c-.4-.4-1-.4-1.4 0-.4.4-.4 1 0 1.4C15.4 5.9 16 7.4 16 9c0 1.6-.6 3.1-1.8 4.3-.4.4-.4 1 0 1.4.2.2.5.3.7.3.3 0 .5-.1.7-.3C17.1 13.2 18 11.2 18 9s-.9-4.2-2.4-5.7z"/><path d="M11.282 5.282a.909.909 0 0 0 0 1.316c.735.735.995 1.458.995 2.402 0 .936-.425 1.917-.995 2.487a.909.909 0 0 0 0 1.316c.145.145.636.262 1.018.156a.725.725 0 0 0 .298-.156C13.773 11.733 14.13 10.16 14.13 9c0-.17-.002-.34-.011-.51-.053-.992-.319-2.005-1.522-3.208a.909.909 0 0 0-1.316 0zM3.786 6.008H.714C.286 6.008 0 6.31 0 6.76v4.512c0 .452.286.752.714.752h3.072l4.071 3.858c.5.3 1.143 0 1.143-.602V2.752c0-.601-.643-.977-1.143-.601L3.786 6.008z"/></symbol></svg>
\ No newline at end of file +<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg"><symbol id="plyr-airplay" viewBox="0 0 18 18"><path d="M16 1H2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h3v-2H3V3h12v8h-2v2h3a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1z"/><path d="M4 17h10l-5-6z"/></symbol><symbol id="plyr-captions-off" viewBox="0 0 18 18"><path d="M1 1c-.6 0-1 .4-1 1v11c0 .6.4 1 1 1h4.6l2.7 2.7c.2.2.4.3.7.3.3 0 .5-.1.7-.3l2.7-2.7H17c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1H1zm4.52 10.15c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41C8.47 4.96 7.46 3.76 5.5 3.76c-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69zm7.57 0c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41c-.28-1.15-1.29-2.35-3.25-2.35-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69z" fill-rule="evenodd" fill-opacity=".5"/></symbol><symbol id="plyr-captions-on" viewBox="0 0 18 18"><path d="M1 1c-.6 0-1 .4-1 1v11c0 .6.4 1 1 1h4.6l2.7 2.7c.2.2.4.3.7.3.3 0 .5-.1.7-.3l2.7-2.7H17c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1H1zm4.52 10.15c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41C8.47 4.96 7.46 3.76 5.5 3.76c-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69zm7.57 0c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41c-.28-1.15-1.29-2.35-3.25-2.35-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69z" fill-rule="evenodd"/></symbol><symbol id="plyr-enter-fullscreen" viewBox="0 0 18 18"><path d="M10 3h3.6l-4 4L11 8.4l4-4V8h2V1h-7zM7 9.6l-4 4V10H1v7h7v-2H4.4l4-4z"/></symbol><symbol id="plyr-exit-fullscreen" viewBox="0 0 18 18"><path d="M1 12h3.6l-4 4L2 17.4l4-4V17h2v-7H1zM16 .6l-4 4V1h-2v7h7V6h-3.6l4-4z"/></symbol><symbol id="plyr-fast-forward" viewBox="0 0 18 18"><path d="M7.875 7.171L0 1v16l7.875-6.171V17L18 9 7.875 1z"/></symbol><symbol id="plyr-muted" viewBox="0 0 18 18"><path d="M12.4 12.5l2.1-2.1 2.1 2.1 1.4-1.4L15.9 9 18 6.9l-1.4-1.4-2.1 2.1-2.1-2.1L11 6.9 13.1 9 11 11.1zM3.786 6.008H.714C.286 6.008 0 6.31 0 6.76v4.512c0 .452.286.752.714.752h3.072l4.071 3.858c.5.3 1.143 0 1.143-.602V2.752c0-.601-.643-.977-1.143-.601L3.786 6.008z"/></symbol><symbol id="plyr-pause" viewBox="0 0 18 18"><path d="M6 1H3c-.6 0-1 .4-1 1v14c0 .6.4 1 1 1h3c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1zM12 1c-.6 0-1 .4-1 1v14c0 .6.4 1 1 1h3c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1h-3z"/></symbol><symbol id="plyr-pip" viewBox="0 0 18 18"><path d="M13.293 3.293L7.022 9.564l1.414 1.414 6.271-6.271L17 7V1h-6z"/><path d="M13 15H3V5h5V3H2a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-6h-2v5z"/></symbol><symbol id="plyr-play" viewBox="0 0 18 18"><path d="M15.562 8.1L3.87.225C3.052-.337 2 .225 2 1.125v15.75c0 .9 1.052 1.462 1.87.9L15.563 9.9c.584-.45.584-1.35 0-1.8z"/></symbol><symbol id="plyr-restart" viewBox="0 0 18 18"><path d="M9.7 1.2l.7 6.4 2.1-2.1c1.9 1.9 1.9 5.1 0 7-.9 1-2.2 1.5-3.5 1.5-1.3 0-2.6-.5-3.5-1.5-1.9-1.9-1.9-5.1 0-7 .6-.6 1.4-1.1 2.3-1.3l-.6-1.9C6 2.6 4.9 3.2 4 4.1 1.3 6.8 1.3 11.2 4 14c1.3 1.3 3.1 2 4.9 2 1.9 0 3.6-.7 4.9-2 2.7-2.7 2.7-7.1 0-9.9L16 1.9l-6.3-.7z"/></symbol><symbol id="plyr-rewind" viewBox="0 0 18 18"><path d="M10.125 1L0 9l10.125 8v-6.171L18 17V1l-7.875 6.171z"/></symbol><symbol id="plyr-settings" viewBox="0 0 18 18"><path d="M16.135 7.784a2 2 0 0 1-1.23-2.969c.322-.536.225-.998-.094-1.316l-.31-.31c-.318-.318-.78-.415-1.316-.094a2 2 0 0 1-2.969-1.23C10.065 1.258 9.669 1 9.219 1h-.438c-.45 0-.845.258-.997.865a2 2 0 0 1-2.969 1.23c-.536-.322-.999-.225-1.317.093l-.31.31c-.318.318-.415.781-.093 1.317a2 2 0 0 1-1.23 2.969C1.26 7.935 1 8.33 1 8.781v.438c0 .45.258.845.865.997a2 2 0 0 1 1.23 2.969c-.322.536-.225.998.094 1.316l.31.31c.319.319.782.415 1.316.094a2 2 0 0 1 2.969 1.23c.151.607.547.865.997.865h.438c.45 0 .845-.258.997-.865a2 2 0 0 1 2.969-1.23c.535.321.997.225 1.316-.094l.31-.31c.318-.318.415-.781.094-1.316a2 2 0 0 1 1.23-2.969c.607-.151.865-.547.865-.997v-.438c0-.451-.26-.846-.865-.997zM9 12a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></symbol><symbol id="plyr-volume" viewBox="0 0 18 18"><path d="M15.6 3.3c-.4-.4-1-.4-1.4 0-.4.4-.4 1 0 1.4C15.4 5.9 16 7.4 16 9c0 1.6-.6 3.1-1.8 4.3-.4.4-.4 1 0 1.4.2.2.5.3.7.3.3 0 .5-.1.7-.3C17.1 13.2 18 11.2 18 9s-.9-4.2-2.4-5.7z"/><path d="M11.282 5.282a.909.909 0 0 0 0 1.316c.735.735.995 1.458.995 2.402 0 .936-.425 1.917-.995 2.487a.909.909 0 0 0 0 1.316c.145.145.636.262 1.018.156a.725.725 0 0 0 .298-.156C13.773 11.733 14.13 10.16 14.13 9c0-.17-.002-.34-.011-.51-.053-.992-.319-2.005-1.522-3.208a.909.909 0 0 0-1.316 0zM3.786 6.008H.714C.286 6.008 0 6.31 0 6.76v4.512c0 .452.286.752.714.752h3.072l4.071 3.858c.5.3 1.143 0 1.143-.602V2.752c0-.601-.643-.977-1.143-.601L3.786 6.008z"/></symbol></svg>
\ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 7f33abcc..ae48db56 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,353 +1,345 @@ // ========================================================================== // Gulp build script // ========================================================================== -/*global require, __dirname,Buffer*/ -/*jshint -W079 */ - -var fs = require('fs'), - path = require('path'), - gulp = require('gulp'), - gutil = require('gulp-util'), - concat = require('gulp-concat'), - uglify = require('gulp-uglify'), - less = require('gulp-less'), - sass = require('gulp-sass'), - cleanCSS = require('gulp-clean-css'), - run = require('run-sequence'), - prefix = require('gulp-autoprefixer'), - svgstore = require('gulp-svgstore'), - svgmin = require('gulp-svgmin'), - rename = require('gulp-rename'), - s3 = require('gulp-s3'), - replace = require('gulp-replace'), - open = require('gulp-open'), - size = require('gulp-size'), - through = require('through2'); - -var root = __dirname, - paths = { - plyr: { - // Source paths - src: { - less: path.join(root, 'src/less/**/*'), - scss: path.join(root, 'src/scss/**/*'), - js: path.join(root, 'src/js/**/*'), - sprite: path.join(root, 'src/sprite/*.svg'), - }, - // Output paths - output: path.join(root, 'dist/'), - }, - demo: { - // Source paths - src: { - less: path.join(root, 'demo/src/less/**/*'), - js: path.join(root, 'demo/src/js/**/*'), - sprite: path.join(root, 'demo/src/sprite/**/*'), - }, - // Output paths - output: path.join(root, 'demo/dist/'), - // Demo - root: path.join(root, 'demo/'), +/* global require, __dirname */ +/* eslint no-console: "off" */ + +const del = require('del'); +const path = require('path'); +const gulp = require('gulp'); +const gutil = require('gulp-util'); +const concat = require('gulp-concat'); +const sass = require('gulp-sass'); +const cleancss = require('gulp-clean-css'); +const run = require('run-sequence'); +const prefix = require('gulp-autoprefixer'); +const svgstore = require('gulp-svgstore'); +const svgmin = require('gulp-svgmin'); +const rename = require('gulp-rename'); +const s3 = require('gulp-s3'); +const replace = require('gulp-replace'); +const open = require('gulp-open'); +const size = require('gulp-size'); +const rollup = require('gulp-better-rollup'); +const babel = require('rollup-plugin-babel'); +const sourcemaps = require('gulp-sourcemaps'); +const uglify = require('rollup-plugin-uglify'); +const { minify } = require('uglify-es'); +const commonjs = require('rollup-plugin-commonjs'); +const resolve = require('rollup-plugin-node-resolve'); + +const bundles = require('./bundles.json'); +const pkg = require('./package.json'); +const aws = require('./aws.json'); + +// Paths +const root = __dirname; +const paths = { + plyr: { + // Source paths + src: { + sass: path.join(root, 'src/sass/**/*.scss'), + js: path.join(root, 'src/js/**/*'), + sprite: path.join(root, 'src/sprite/*.svg'), }, - upload: [path.join(root, 'dist/**'), path.join(root, 'demo/dist/**')], - }, - // Task arrays - tasks = { - less: [], - scss: [], - js: [], - sprite: [], + + // Output paths + output: path.join(root, 'dist/'), }, - // Fetch bundles from JSON - bundles = loadJSON(path.join(root, 'bundles.json')), - package = loadJSON(path.join(root, 'package.json')); - -// Load json -function loadJSON(path) { - try { - return JSON.parse(fs.readFileSync(path)); - } catch (err) { - return {}; - } -} + demo: { + // Source paths + src: { + sass: path.join(root, 'demo/src/sass/**/*.scss'), + js: path.join(root, 'demo/src/js/**/*'), + }, -// Create a file from a string -// http://stackoverflow.com/questions/23230569/how-do-you-create-a-file-from-a-string-in-gulp -function createFile(filename, string) { - var src = require('stream').Readable({ - objectMode: true, - }); - src._read = function() { - this.push( - new gutil.File({ - cwd: '', - base: '', - path: filename, - contents: new Buffer(string), - // stats also required for some functions - // https://nodejs.org/api/fs.html#fs_class_fs_stats - stat: { - size: string.length, - }, - }), - ); - this.push(null); - }; - return src; -} + // Output paths + output: path.join(root, 'demo/dist/'), -var build = { - js: function(files, bundle) { - for (var key in files) { - (function(key) { - var name = 'js-' + key; - tasks.js.push(name); - - gulp.task(name, function() { - return gulp - .src(bundles[bundle].js[key]) - .pipe(concat(key)) - .pipe(uglify().on('error', gutil.log)) - .pipe(gulp.dest(paths[bundle].output)); - }); - })(key); - } + // Demo + root: path.join(root, 'demo/'), }, - less: function(files, bundle) { - for (var key in files) { - (function(key) { - var name = 'less-' + key; - tasks.less.push(name); - - gulp.task(name, function() { - return gulp - .src(bundles[bundle].less[key]) - .pipe(less()) - .on('error', gutil.log) - .pipe(concat(key)) - .pipe(prefix(['last 2 versions'], { cascade: true })) - .pipe(cleanCSS()) - .pipe(gulp.dest(paths[bundle].output)); - }); - })(key); - } + upload: [ + path.join(root, 'dist/**'), + path.join(root, 'demo/dist/**'), + ], +}; + +// Task arrays +const tasks = { + sass: [], + js: [], + sprite: [], + clean: ['clean'], +}; + +// Size plugin +const sizeOptions = { showFiles: true, gzip: true }; + +// Browserlist +const browsers = ['> 1%']; + +// Babel config +const babelrc = { + presets: [[ + 'env', + { + targets: { + browsers, + }, + useBuiltIns: true, + modules: false, + }, + ]], + plugins: ['external-helpers'], + babelrc: false, + exclude: 'node_modules/**', +}; + +// Clean out /dist +gulp.task('clean', () => { + const dirs = [ + paths.plyr.output, + paths.demo.output, + ].map(dir => path.join(dir, '**/*')); + + // Don't delete the mp4 + dirs.push(`!${path.join(paths.plyr.output, '**/*.mp4')}`); + + del(dirs); +}); + +const build = { + js(files, bundle, options) { + Object.keys(files).forEach(key => { + const name = `js:${key}`; + tasks.js.push(name); + + gulp.task(name, () => + gulp + .src(bundles[bundle].js[key]) + .pipe(concat(key)) + .pipe(sourcemaps.init()) + .pipe( + rollup( + { + plugins: [ + resolve(), + commonjs(), + babel(babelrc), + uglify({}, minify), + ], + }, + options + ) + ) + .pipe(size(sizeOptions)) + .pipe(sourcemaps.write('')) + .pipe(gulp.dest(paths[bundle].output)) + ); + }); }, - scss: function(files, bundle) { - for (var key in files) { - (function(key) { - var name = 'scss-' + key; - tasks.scss.push(name); - - gulp.task(name, function() { - return gulp - .src(bundles[bundle].scss[key]) - .pipe(sass()) - .on('error', gutil.log) - .pipe(concat(key)) - .pipe(prefix(['last 2 versions'], { cascade: true })) - .pipe(cleanCSS()) - .pipe(gulp.dest(paths[bundle].output)); - }); - })(key); - } + sass(files, bundle) { + Object.keys(files).forEach(key => { + const name = `sass:${key}`; + tasks.sass.push(name); + + gulp.task(name, () => + gulp + .src(bundles[bundle].sass[key]) + .pipe(sass()) + .on('error', gutil.log) + .pipe(concat(key)) + .pipe(prefix(browsers, { cascade: false })) + .pipe(cleancss()) + .pipe(size(sizeOptions)) + .pipe(gulp.dest(paths[bundle].output)) + ); + }); }, - sprite: function(bundle) { - var name = 'sprite-' + bundle; + sprite(bundle) { + const name = `svg:sprite:${bundle}`; tasks.sprite.push(name); // Process Icons - gulp.task(name, function() { - return gulp + gulp.task(name, () => + gulp .src(paths[bundle].src.sprite) .pipe( svgmin({ - plugins: [ - { - removeDesc: true, - }, - ], - }), + plugins: [{ + removeDesc: true, + }], + }) ) .pipe(svgstore()) .pipe(rename({ basename: bundle })) - .pipe(gulp.dest(paths[bundle].output)); - }); + .pipe(size(sizeOptions)) + .pipe(gulp.dest(paths[bundle].output)) + ); }, }; // Plyr core files -build.js(bundles.plyr.js, 'plyr'); -build.less(bundles.plyr.less, 'plyr'); -build.scss(bundles.plyr.scss, 'plyr'); +build.js(bundles.plyr.js, 'plyr', { name: 'Plyr', format: 'umd' }); +build.sass(bundles.plyr.sass, 'plyr'); build.sprite('plyr'); // Demo files -build.less(bundles.demo.less, 'demo'); -build.js(bundles.demo.js, 'demo'); -build.sprite('demo'); +build.sass(bundles.demo.sass, 'demo'); +build.js(bundles.demo.js, 'demo', { format: 'es' }); // Build all JS -gulp.task('js', function() { +gulp.task('js', () => { run(tasks.js); }); -// Build SCSS (for testing, default is LESS) -gulp.task('scss', function() { - run(tasks.scss); -}); - // Watch for file changes -gulp.task('watch', function() { +gulp.task('watch', () => { // Plyr core gulp.watch(paths.plyr.src.js, tasks.js); - gulp.watch(paths.plyr.src.less, tasks.less); + gulp.watch(paths.plyr.src.sass, tasks.sass); gulp.watch(paths.plyr.src.sprite, tasks.sprite); // Demo gulp.watch(paths.demo.src.js, tasks.js); - gulp.watch(paths.demo.src.less, tasks.less); - gulp.watch(paths.demo.src.sprite, tasks.sprite); + gulp.watch(paths.demo.src.sass, tasks.sass); }); // Default gulp task -gulp.task('default', function() { - run(tasks.js, tasks.less, tasks.sprite, 'watch'); +gulp.task('default', () => { + run(tasks.clean, tasks.js, tasks.sass, tasks.sprite, 'watch'); }); // Publish a version to CDN and demo // -------------------------------------------- - -// Some options -var aws = loadJSON(path.join(root, 'aws.json')), - version = package.version, - maxAge = 31536000, // seconds 1 year - options = { - cdn: { - headers: { - 'Cache-Control': 'max-age=' + maxAge, - Vary: 'Accept-Encoding', - }, +const { version } = pkg; +const maxAge = 31536000; // 1 year +const options = { + cdn: { + headers: { + 'Cache-Control': `max-age=${maxAge}`, + Vary: 'Accept-Encoding', + }, + }, + demo: { + headers: { + 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0', + Vary: 'Accept-Encoding', }, - demo: { + }, + symlinks(ver, filename) { + return { headers: { + // http://stackoverflow.com/questions/2272835/amazon-s3-object-redirect + 'x-amz-website-redirect-location': `/${ver}/${filename}`, 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0', - Vary: 'Accept-Encoding', }, - }, - symlinks: function(version, filename) { - return { - headers: { - // http://stackoverflow.com/questions/2272835/amazon-s3-object-redirect - 'x-amz-website-redirect-location': '/' + version + '/' + filename, - 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0', - }, - }; - }, - }; + }; + }, +}; // If aws is setup if ('cdn' in aws) { - var regex = '(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*).(?:0|[1-9][0-9]*)(?:-[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?(?:\\+[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?', - cdnpath = new RegExp(aws.cdn.domain + '/' + regex, 'gi'), - semver = new RegExp('v' + regex, 'gi'), - localPath = new RegExp('(../)?dist', 'gi'), - versionPath = 'https://' + aws.cdn.domain + '/' + version; -} - -// Publish version to CDN bucket -gulp.task('cdn', function() { - console.log('Uploading ' + version + ' to ' + aws.cdn.domain + '...'); - - // Upload to CDN - return gulp - .src(paths.upload) - .pipe( - size({ - showFiles: true, - gzip: true, - }), - ) - .pipe( - rename(function(path) { - path.dirname = path.dirname.replace('.', version); - }), - ) - .pipe(replace(localPath, versionPath)) - .pipe(s3(aws.cdn, options.cdn)); -}); - -// Publish to demo bucket -gulp.task('demo', function() { - console.log('Uploading ' + version + ' demo to ' + aws.demo.domain + '...'); - - // Replace versioned files in readme.md - gulp - .src([root + '/readme.md']) - .pipe(replace(cdnpath, aws.cdn.domain + '/' + version)) - .pipe(gulp.dest(root)); - - // Replace versioned files in plyr.js - gulp - .src(path.join(root, 'src/js/plyr.js')) - .pipe(replace(semver, 'v' + version)) - .pipe(replace(cdnpath, aws.cdn.domain + '/' + version)) - .pipe(gulp.dest(path.join(root, 'src/js/'))); - - // Replace local file paths with remote paths in demo HTML - // e.g. "../dist/plyr.js" to "https://cdn.plyr.io/x.x.x/plyr.js" - gulp - .src([paths.demo.root + '*.html']) - .pipe(replace(localPath, versionPath)) - .pipe(s3(aws.demo, options.demo)); - - // Upload error.html to cdn (as well as demo site) - return gulp - .src([paths.demo.root + 'error.html']) - .pipe(replace(localPath, versionPath)) - .pipe(s3(aws.cdn, options.demo)); -}); - -// Open the demo site to check it's sweet -gulp.task('symlinks', function() { - console.log('Updating symlinks...'); - - return gulp.src(paths.upload).pipe( - through.obj(function(chunk, enc, callback) { - if (chunk.stat.isFile()) { - // Get the filename - var filename = chunk.path.split('/').reverse()[0]; - - // Create the 0 byte redirect files to upload - createFile(filename, '') - .pipe( - rename(function(path) { - path.dirname = path.dirname.replace('.', 'latest'); - }), - ) - // Upload to S3 with correct headers - .pipe(s3(aws.cdn, options.symlinks(version, filename))); - } + const regex = '(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*).(?:0|[1-9][0-9]*)(?:-[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?(?:\\+[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?'; + const cdnpath = new RegExp(`${aws.cdn.domain}/${regex}`, 'gi'); + const semver = new RegExp(`v${regex}`, 'gi'); + const localPath = new RegExp('(../)?dist', 'gi'); + const versionPath = `https://${aws.cdn.domain}/${version}`; + + // Publish version to CDN bucket + gulp.task('cdn', () => { + console.log(`Uploading ${version} to ${aws.cdn.domain}...`); + + // Upload to CDN + return gulp + .src(paths.upload) + .pipe( + size({ + showFiles: true, + gzip: true, + }) + ) + .pipe( + rename(p => { + // eslint-disable-next-line + p.dirname = p.dirname.replace('.', version); + }) + ) + .pipe(replace(localPath, versionPath)) + .pipe(s3(aws.cdn, options.cdn)); + }); - callback(null, chunk); - }), - ); -}); + // Publish to demo bucket + gulp.task('demo', () => { + console.log(`Uploading ${version} demo to ${aws.demo.domain}...`); + + // Replace versioned files in readme.md + gulp + .src([`${root}/readme.md`]) + .pipe(replace(cdnpath, `${aws.cdn.domain}/${version}`)) + .pipe(gulp.dest(root)); + + // Replace versioned files in plyr.js + gulp + .src(path.join(root, 'src/js/plyr.js')) + .pipe(replace(semver, `v${version}`)) + .pipe(replace(cdnpath, `${aws.cdn.domain}/${version}`)) + .pipe(gulp.dest(path.join(root, 'src/js/'))); + + // Replace local file paths with remote paths in demo HTML + // e.g. "../dist/plyr.js" to "https://cdn.plyr.io/x.x.x/plyr.js" + gulp + .src([`${paths.demo.root}*.html`]) + .pipe(replace(localPath, versionPath)) + .pipe(s3(aws.demo, options.demo)); + + // Upload error.html to cdn (as well as demo site) + return gulp + .src([`${paths.demo.root}error.html`]) + .pipe(replace(localPath, versionPath)) + .pipe(s3(aws.cdn, options.demo)); + }); -// Open the demo site to check it's sweet -gulp.task('open', function() { - console.log('Opening ' + aws.demo.domain + '...'); - - // A file must be specified or gulp will skip the task - // Doesn't matter which file since we set the URL above - // Weird, I know... - return gulp.src([paths.demo.root + 'index.html']).pipe( - open('', { - url: 'http://' + aws.demo.domain, - }), - ); -}); + // Update symlinks for latest + /* gulp.task("symlinks", function () { + console.log("Updating symlinks..."); + + return gulp.src(paths.upload) + .pipe(through.obj(function (chunk, enc, callback) { + if (chunk.stat.isFile()) { + // Get the filename + var filename = chunk.path.split("/").reverse()[0]; + + // Create the 0 byte redirect files to upload + createFile(filename, "") + .pipe(rename(function (path) { + path.dirname = path.dirname.replace(".", "latest"); + })) + // Upload to S3 with correct headers + .pipe(s3(aws.cdn, options.symlinks(version, filename))); + } + + callback(null, chunk); + })); + }); */ + + // Open the demo site to check it's sweet + gulp.task('open', () => { + console.log(`Opening ${aws.demo.domain}...`); + + // A file must be specified or gulp will skip the task + // Doesn't matter which file since we set the URL above + // Weird, I know... + return gulp.src([`${paths.demo.root}index.html`]).pipe( + open('', { + url: `http://${aws.demo.domain}`, + }) + ); + }); -// Do everything -gulp.task('publish', function() { - run(tasks.js, tasks.less, tasks.sprite, 'cdn', 'demo', 'symlinks'); -}); + // Do everything + gulp.task('publish', () => { + run(tasks.clean, tasks.js, tasks.sass, tasks.sprite, 'cdn', 'demo'); + }); +} diff --git a/package-lock.json b/package-lock.json index ad506bda..085338ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,95 +1,259 @@ { "name": "plyr", - "version": "2.0.18", + "version": "3.0.0-alpha.1", "lockfileVersion": 1, "requires": true, "dependencies": { - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "accord": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/accord/-/accord-0.27.3.tgz", - "integrity": "sha1-f7kSlwkoXK6oTrNyxOiCAxtxOOg=", + "@babel/code-frame": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.31.tgz", + "integrity": "sha512-yd7CkUughvHQoEahQqcMdrZw6o/6PwUxiRkfZuVDVHCDe77mysD/suoNyk5mK6phTnRW1kyIbPHyCJgxw++LXg==", "dev": true, "requires": { - "convert-source-map": "1.5.0", - "glob": "7.1.2", - "indx": "0.2.3", - "lodash.clone": "4.5.0", - "lodash.defaults": "4.2.0", - "lodash.flatten": "4.4.0", - "lodash.merge": "4.6.0", - "lodash.partialright": "4.2.1", - "lodash.pick": "4.4.0", - "lodash.uniq": "4.5.0", - "resolve": "1.5.0", - "semver": "5.4.1", - "uglify-js": "2.8.29", - "when": "3.7.8" + "chalk": "2.3.0", + "esutils": "2.0.2", + "js-tokens": "3.0.2" }, "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.3.3", - "path-is-absolute": "1.0.1" + "color-convert": "1.9.1" } }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" } }, - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "@babel/helper-function-name": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.31.tgz", + "integrity": "sha512-c+DAyp8LMm2nzSs2uXEuxp4LYGSUYEyHtU3fU57avFChjsnTmmpWmXj2dv0yUxHTEydgVAv5fIzA+4KJwoqWDA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "7.0.0-beta.31", + "@babel/template": "7.0.0-beta.31", + "@babel/traverse": "7.0.0-beta.31", + "@babel/types": "7.0.0-beta.31" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.31.tgz", + "integrity": "sha512-m7rVVX/dMLbbB9NCzKYRrrFb0qZxgpmQ4Wv6y7zEsB6skoJHRuXVeb/hAFze79vXBbuD63ci7AVHXzAdZSk9KQ==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.31" + } + }, + "@babel/template": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.31.tgz", + "integrity": "sha512-97IRmLvoDhIDSQkqklVt3UCxJsv0LUEVb/0DzXWtc8Lgiyxj567qZkmTG9aR21CmcJVVIvq2Y/moZj4oEpl5AA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.31", + "@babel/types": "7.0.0-beta.31", + "babylon": "7.0.0-beta.31", + "lodash": "4.17.4" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.31.tgz", + "integrity": "sha512-6lm2mV3S51yEnKmQQNnswoABL1U1H1KHoCCVwdwI3hvIv+W7ya4ki7Aw4o4KxtUHjNKkK5WpZb22rrMMOcJXJQ==", "dev": true } } }, - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "@babel/traverse": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.31.tgz", + "integrity": "sha512-3N+VJW+KlezEjFBG7WSYeMyC5kIqVLPb/PGSzCDPFcJrnArluD1GIl7Y3xC7cjKiTq2/JohaLWHVPjJWHlo9Gg==", "dev": true, "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "@babel/code-frame": "7.0.0-beta.31", + "@babel/helper-function-name": "7.0.0-beta.31", + "@babel/types": "7.0.0-beta.31", + "babylon": "7.0.0-beta.31", + "debug": "3.1.0", + "globals": "10.4.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.31.tgz", + "integrity": "sha512-6lm2mV3S51yEnKmQQNnswoABL1U1H1KHoCCVwdwI3hvIv+W7ya4ki7Aw4o4KxtUHjNKkK5WpZb22rrMMOcJXJQ==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-10.4.0.tgz", + "integrity": "sha512-uNUtxIZpGyuaq+5BqGGQHsL4wUlJAXRqOm6g3Y48/CWNGTLONgBibI0lh6lGxjR2HljFYUfszb+mk4WkgMntsA==", + "dev": true + } } }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "@babel/types": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.31.tgz", + "integrity": "sha512-exAHB+NeFGxkfQ5dSUD03xl3zYGneeSk2Mw2ldTt/nTvYxuDiuSp3DlxgUBgzbdTFG4fbwPk0WtKWOoTXCmNGg==", "dev": true, "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@gulp-sourcemaps/identity-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", + "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=", + "dev": true, + "requires": { + "acorn": "5.3.0", + "css": "2.2.1", + "normalize-path": "2.1.1", + "source-map": "0.5.7", + "through2": "2.0.3" + } + }, + "@gulp-sourcemaps/map-sources": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", + "dev": true, + "requires": { + "normalize-path": "2.1.1", + "through2": "2.0.3" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "acorn": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", + "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" } }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-escapes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", + "dev": true + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -102,6 +266,12 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -122,38 +292,6 @@ "requires": { "delegates": "1.0.0", "readable-stream": "2.3.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } } }, "argparse": { @@ -165,21 +303,33 @@ "sprintf-js": "1.0.3" } }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "aria-query": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-0.7.0.tgz", + "integrity": "sha512-/r2lHl09V3o74+2MLKEdewoj37YZqiQZnfen1O4iNlrOjUgeKuu1U2yF3iKh6HJxqF+OXkLMfQv65Z/cvxD6vA==", "dev": true, "requires": { - "arr-flatten": "1.1.0" + "ast-types-flow": "0.0.7" } }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, "array-differ": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", @@ -198,12 +348,37 @@ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.10.0" + } + }, + "array-iterate": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.1.tgz", + "integrity": "sha1-hlv3+K851rCYLGCQKRSsdrwBCPY=", + "dev": true + }, "array-slice": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.0.0.tgz", - "integrity": "sha1-5zA08A3MH0CHYAj9IP6ud71LfC8=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", "dev": true }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", @@ -211,17 +386,22 @@ "dev": true }, "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true, - "optional": true + "dev": true }, "asn1": { "version": "0.2.3", @@ -235,6 +415,27 @@ "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", "dev": true }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", + "dev": true + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, "async-foreach": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", @@ -247,6 +448,26 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "atob": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", + "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", + "dev": true + }, + "autoprefixer": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.3.tgz", + "integrity": "sha512-dqzVGiz3v934+s3YZA6nk7tAs9xuTz5wMJbX1M+L4cY/MTNkOUqP61c1GWkEVlUL/PEy1pKRSCFuoRZrXYx9qA==", + "dev": true, + "requires": { + "browserslist": "2.10.1", + "caniuse-lite": "1.0.30000784", + "normalize-range": "0.1.2", + "num2fraction": "1.2.2", + "postcss": "6.0.14", + "postcss-value-parser": "3.3.0" + } + }, "aws-sign2": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", @@ -259,12 +480,686 @@ "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", "dev": true }, + "axobject-query": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-0.1.0.tgz", + "integrity": "sha1-YvWdvFnJ+SQnWco0mWDnov48NsA=", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-core": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.0", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.1", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + } + }, + "babel-eslint": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.1.2.tgz", + "integrity": "sha512-IE+glF8t0lLoldylN7JyR8gT7e3jwyuNH2ds8g3UVUwGob/U4iT7Xpsiq2kQ8QGLb0eX4RcQXNqeW6mgPysu9A==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.31", + "@babel/traverse": "7.0.0-beta.31", + "@babel/types": "7.0.0-beta.31", + "babylon": "7.0.0-beta.31", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.31.tgz", + "integrity": "sha512-6lm2mV3S51yEnKmQQNnswoABL1U1H1KHoCCVwdwI3hvIv+W7ya4ki7Aw4o4KxtUHjNKkK5WpZb22rrMMOcJXJQ==", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", + "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", + "dev": true, + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.4", + "source-map": "0.5.7", + "trim-right": "1.0.1" + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-external-helpers": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-external-helpers/-/babel-plugin-external-helpers-6.22.0.tgz", + "integrity": "sha1-IoX0iwK9Xe3oUXXK+MYuhq3M76E=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "regexpu-core": "2.0.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "requires": { + "regenerator-transform": "0.10.1" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-preset-env": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", + "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0", + "browserslist": "2.10.1", + "invariant": "2.2.2", + "semver": "5.4.1" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "6.26.0", + "babel-runtime": "6.26.0", + "core-js": "2.5.3", + "home-or-tmp": "2.0.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "bail": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.2.tgz", + "integrity": "sha1-99bBcxYwqfnw1NNe0fli4gdKF2Q=", + "dev": true + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.5", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.0", + "pascalcase": "0.1.1" + } + }, "bcrypt-pbkdf": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", @@ -322,14 +1217,49 @@ } }, "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.0.tgz", + "integrity": "sha512-P4O8UQRdGiMLWSizsApmXVQDBS6KCt7dSexgLKBmH5Hr1CZq7vsnscFh8oR1sP1ab1Zj0uCHCEzZeV6SfUf3rA==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.1", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.1" + } + }, + "browser-resolve": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browserslist": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.10.1.tgz", + "integrity": "sha512-vUe1YhphiCb5lJ4YQwA5VbmAhZgv9cwgAQm/rZT6GA2X97ewDMOLPyDr08iGsqvPajvC/wEwWBZNtFFa8l4Hlw==", "dev": true, "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" + "caniuse-lite": "1.0.30000784", + "electron-to-chromium": "1.3.30" } }, "builtin-modules": { @@ -338,10 +1268,42 @@ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + } + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", "dev": true }, "camelcase-keys": { @@ -352,37 +1314,25 @@ "requires": { "camelcase": "2.1.1", "map-obj": "1.0.1" - }, - "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - } } }, "caniuse-lite": { - "version": "1.0.30000758", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000758.tgz", - "integrity": "sha1-4mEUAHZlEEnPaJHtS8ZJtcjCbGk=", + "version": "1.0.30000784", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000784.tgz", + "integrity": "sha1-EpztdOmhKApEGIC2zSvOMO9Z5sA=", "dev": true }, "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", "dev": true }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" - } + "ccount": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.2.tgz", + "integrity": "sha1-U7ai+BW7d7nChx97mnLDol8djok=", + "dev": true }, "chalk": { "version": "1.1.3", @@ -397,6 +1347,36 @@ "supports-color": "2.0.0" } }, + "character-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.1.tgz", + "integrity": "sha1-92hxvl72bdt/j440eOzDdMJ9bco=", + "dev": true + }, + "character-entities-html4": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.1.tgz", + "integrity": "sha1-NZoqSg9+KdPcKsmb2+Ie45Q46lA=", + "dev": true + }, + "character-entities-legacy": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz", + "integrity": "sha1-9Ad53xoQGHK7UQo9KV4fzPFHIC8=", + "dev": true + }, + "character-reference-invalid": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.1.tgz", + "integrity": "sha1-lCg191Dk7GGjCOYMLvjMEBEgLvw=", + "dev": true + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, "cheerio": { "version": "0.22.0", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", @@ -419,8 +1399,22 @@ "lodash.reduce": "4.6.0", "lodash.reject": "4.6.0", "lodash.some": "4.6.0" + }, + "dependencies": { + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + } } }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, "clap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", @@ -430,6 +1424,87 @@ "chalk": "1.1.3" } }, + "class-utils": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.5.tgz", + "integrity": "sha1-F+eTEDdQ+WJ7IXbqNM/RtWWQPIA=", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "lazy-cache": "2.0.2", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "clean-css": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.9.tgz", @@ -439,21 +1514,58 @@ "source-map": "0.5.7" } }, - "cliui": { + "cli-cursor": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" + "restore-cursor": "2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } } }, "clone": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", - "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", "dev": true }, "clone-buffer": { @@ -462,6 +1574,16 @@ "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", "dev": true }, + "clone-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.0.tgz", + "integrity": "sha1-6uCiQT9VwJQvgYwin+/OhF1/Oxw=", + "dev": true, + "requires": { + "is-regexp": "1.0.0", + "is-supported-regexp-flag": "1.0.0" + } + }, "clone-stats": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", @@ -500,10 +1622,26 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, + "collapse-white-space": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.3.tgz", + "integrity": "sha1-S5BvZw5aljqHt2sOFolkM0G2Ajw=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, "color-convert": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", - "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", "dev": true, "requires": { "color-name": "1.1.3" @@ -515,6 +1653,12 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, "colors": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", @@ -531,9 +1675,15 @@ } }, "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", "dev": true }, "concat-map": { @@ -542,6 +1692,17 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + } + }, "concat-with-sourcemaps": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.4.tgz", @@ -557,10 +1718,28 @@ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, "convert-source-map": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", - "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=", "dev": true }, "core-util-is": { @@ -569,28 +1748,40 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, - "cross-spawn": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", - "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "cosmiconfig": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-3.1.0.tgz", + "integrity": "sha512-zedsBhLSbPBms+kE7AH4vHg6JsKDz6epSv2/+5XHs8ILHlgDciSJfSWf8sX9aQ52Jb7KI7VswUTsLpR/G0cr2Q==", "dev": true, "requires": { - "lru-cache": "4.1.1", - "which": "1.3.0" + "is-directory": "0.3.1", + "js-yaml": "3.10.0", + "parse-json": "3.0.0", + "require-from-string": "2.0.1" }, "dependencies": { - "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "parse-json": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-3.0.0.tgz", + "integrity": "sha1-+m9HsY4jgm6tMvJj50TQ4ehH+xM=", "dev": true, "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "error-ex": "1.3.1" } } } }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, "cryptiles": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", @@ -600,6 +1791,53 @@ "boom": "2.10.1" } }, + "css": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", + "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "source-map": "0.1.43", + "source-map-resolve": "0.3.1", + "urix": "0.1.0" + }, + "dependencies": { + "atob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", + "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", + "dev": true + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "source-map-resolve": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", + "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", + "dev": true, + "requires": { + "atob": "1.1.3", + "resolve-url": "0.2.1", + "source-map-url": "0.3.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", + "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=", + "dev": true + } + } + }, "css-select": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", @@ -637,6 +1875,21 @@ "array-find-index": "1.0.2" } }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.37" + } + }, + "damerau-levenshtein": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz", + "integrity": "sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ=", + "dev": true + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -661,27 +1914,104 @@ "dev": true }, "debug": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.5.tgz", - "integrity": "sha1-9yQSF0MPmd7EwrRz6rkiKOh0wqw=", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { "ms": "2.0.0" } }, + "debug-fabulous": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.0.0.tgz", + "integrity": "sha512-dsd50qQ1atDeurcxL7XOjPp4nZCGZzWIONDujDXzl1atSyC3hMbZD+v6440etw+Vt0Pr8ce4TQzHfX3KZM05Mw==", + "dev": true, + "requires": { + "debug": "3.1.0", + "memoizee": "0.4.11", + "object-assign": "4.1.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "1.2.0", + "map-obj": "1.0.1" + } + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, "defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, "requires": { - "clone": "1.0.2" + "clone": "1.0.3" + } + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "dev": true, + "requires": { + "globby": "6.1.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "p-map": "1.2.0", + "pify": "3.0.0", + "rimraf": "2.6.2" } }, "delayed-stream": { @@ -703,12 +2033,54 @@ "dev": true }, "detect-file": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", - "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "path-type": "3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "3.0.0" + } + } + } + }, + "doctrine": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.2.tgz", + "integrity": "sha512-y0tm5Pq6ywp3qSTZ1vPgVdAnbDEoeoc5wlOHXoY1c4Wug/a7JvqHIl7BTvwodaHmejWkK/9dSb3sCYfyo/om8A==", "dev": true, "requires": { - "fs-exists-sync": "0.1.0" + "esutils": "2.0.2" } }, "dom-serializer": { @@ -754,6 +2126,15 @@ "domelementtype": "1.3.0" } }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "1.0.1" + } + }, "duplexer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", @@ -767,6 +2148,32 @@ "dev": true, "requires": { "readable-stream": "1.1.14" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } } }, "ecc-jsbn": { @@ -779,12 +2186,36 @@ "jsbn": "0.1.1" } }, + "electron-releases": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/electron-releases/-/electron-releases-2.1.0.tgz", + "integrity": "sha512-cyKFD1bTE/UgULXfaueIN1k5EPFzs+FRc/rvCY5tIynefAPqopQEgjr0EzY+U3Dqrk/G4m9tXSPuZ77v6dL/Rw==", + "dev": true + }, "electron-to-chromium": { - "version": "1.3.27", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz", - "integrity": "sha1-eOy4o5kGYYe7N07t412ccFZagD0=", + "version": "1.3.30", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.30.tgz", + "integrity": "sha512-zx1Prv7kYLfc4OA60FhxGbSo4qrEjgSzpo1/37i7l9ltXPYOoQBtjQxY9KmsgfHnBxHlBGXwLlsbt/gub1w5lw==", + "dev": true, + "requires": { + "electron-releases": "2.1.0" + } + }, + "emoji-regex": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.5.1.tgz", + "integrity": "sha512-PAHp6TxrCy7MGMFidro8uikr+zlJJKJ/Q6mm2ExZ7HwkyR9lSVFfE3kt36qcwa24BQL7y0G9axycGjK1A/0uNQ==", "dev": true }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "dev": true, + "requires": { + "iconv-lite": "0.4.19" + } + }, "end-of-stream": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", @@ -792,6 +2223,17 @@ "dev": true, "requires": { "once": "1.3.3" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + } } }, "entities": { @@ -800,16 +2242,6 @@ "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", "dev": true }, - "errno": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", - "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", - "dev": true, - "optional": true, - "requires": { - "prr": "0.0.0" - } - }, "error-ex": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", @@ -819,18 +2251,374 @@ "is-arrayish": "0.2.1" } }, + "es-abstract": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", + "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", + "dev": true, + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.1", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, + "requires": { + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" + } + }, + "es5-ext": { + "version": "0.10.37", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", + "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-symbol": "3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "eslint": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.14.0.tgz", + "integrity": "sha512-Ul6CSGRjKscEyg0X/EeNs7o2XdnbTEOD1OM8cTjmx85RPcBJQrEhZLevhuJZNAE/vS2iVl5Uhgiqf3h5uLMCJQ==", + "dev": true, + "requires": { + "ajv": "5.5.2", + "babel-code-frame": "6.26.0", + "chalk": "2.3.0", + "concat-stream": "1.6.0", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "doctrine": "2.0.2", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0", + "espree": "3.5.2", + "esquery": "1.0.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "11.1.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.0.1", + "js-yaml": "3.10.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "require-uncached": "1.0.3", + "semver": "5.4.1", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.2", + "text-table": "0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.1.0.tgz", + "integrity": "sha512-uEuWt9mqTlPDwSqi+sHjD4nWU/1N+q0fiWI9T1mZpD2UENqX20CFD5T/ziLZvztPaBKl7ZylUi1q6Qfm7E2CiQ==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "eslint-config-airbnb": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-16.1.0.tgz", + "integrity": "sha512-zLyOhVWhzB/jwbz7IPSbkUuj7X2ox4PHXTcZkEmDqTvd0baJmJyuxlFPDlZOE/Y5bC+HQRaEkT3FoHo9wIdRiw==", + "dev": true, + "requires": { + "eslint-config-airbnb-base": "12.1.0" + } + }, + "eslint-config-airbnb-base": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-12.1.0.tgz", + "integrity": "sha512-/vjm0Px5ZCpmJqnjIzcFb9TKZrKWz0gnuG/7Gfkt0Db1ELJR51xkZth+t14rYdqWgX836XbuxtArbIHlVhbLBA==", + "dev": true, + "requires": { + "eslint-restricted-globals": "0.1.1" + } + }, + "eslint-config-prettier": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz", + "integrity": "sha512-ag8YEyBXsm3nmOv1Hz991VtNNDMRa+MNy8cY47Pl4bw6iuzqKbJajXdqUpiw13STdLLrznxgm1hj9NhxeOYq0A==", + "dev": true, + "requires": { + "get-stdin": "5.0.1" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz", + "integrity": "sha512-yUtXS15gIcij68NmXmP9Ni77AQuCN0itXbCc/jWd8C6/yKZaSNXicpC8cgvjnxVdmfsosIXrjpzFq7GcDryb6A==", + "dev": true, + "requires": { + "debug": "2.6.9", + "resolve": "1.5.0" + } + }, + "eslint-module-utils": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", + "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", + "dev": true, + "requires": { + "debug": "2.6.9", + "pkg-dir": "1.0.0" + } + }, + "eslint-plugin-import": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz", + "integrity": "sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g==", + "dev": true, + "requires": { + "builtin-modules": "1.1.1", + "contains-path": "0.1.0", + "debug": "2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "0.3.1", + "eslint-module-utils": "2.1.1", + "has": "1.0.1", + "lodash.cond": "4.5.2", + "minimatch": "3.0.4", + "read-pkg-up": "2.0.0" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + } + } + }, + "eslint-plugin-jsx-a11y": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.0.3.tgz", + "integrity": "sha1-VFg9GuRCSDFi4EDhPMMYZUZRAOU=", + "dev": true, + "requires": { + "aria-query": "0.7.0", + "array-includes": "3.0.3", + "ast-types-flow": "0.0.7", + "axobject-query": "0.1.0", + "damerau-levenshtein": "1.0.4", + "emoji-regex": "6.5.1", + "jsx-ast-utils": "2.0.1" + } + }, + "eslint-plugin-react": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.5.1.tgz", + "integrity": "sha512-YGSjB9Qu6QbVTroUZi66pYky3DfoIPLdHQ/wmrBGyBRnwxQsBXAov9j2rpXt/55i8nyMv6IRWJv2s4d4YnduzQ==", + "dev": true, + "requires": { + "doctrine": "2.0.2", + "has": "1.0.1", + "jsx-ast-utils": "2.0.1", + "prop-types": "15.6.0" + } + }, + "eslint-restricted-globals": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz", + "integrity": "sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=", + "dev": true + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz", + "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==", + "dev": true, + "requires": { + "acorn": "5.3.0", + "acorn-jsx": "3.0.1" + } + }, "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "estree-walker": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.2.1.tgz", + "integrity": "sha1-va/oCVOD2EFNXcLs9MkXO225QS4=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37" + } + }, "event-stream": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", @@ -846,13 +2634,96 @@ "through": "2.3.8" } }, + "execall": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execall/-/execall-1.0.0.tgz", + "integrity": "sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M=", + "dev": true, + "requires": { + "clone-regexp": "1.0.0" + } + }, "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "is-posix-bracket": "0.1.1" + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.0", + "snapdragon": "0.8.1", + "to-regex": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } } }, "expand-range": { @@ -862,15 +2733,57 @@ "dev": true, "requires": { "fill-range": "2.2.3" + }, + "dependencies": { + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } } }, "expand-tilde": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", - "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "homedir-polyfill": "1.0.1" } }, "extend": { @@ -879,13 +2792,40 @@ "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", "dev": true }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "external-editor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", + "dev": true, + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.19", + "tmp": "0.0.33" + } + }, "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.3.tgz", + "integrity": "sha512-AyptZexgu7qppEPq59DtN/XJGZDrLcVxSHai+4hdgMMS9EpF4GBvygcWWApno8lL9qSjVpYt7Raao28qzJX1ww==", "dev": true, "requires": { - "is-extglob": "1.0.0" + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.0", + "snapdragon": "0.8.1", + "to-regex": "3.0.1" } }, "extsprintf": { @@ -895,15 +2835,76 @@ "dev": true }, "fancy-log": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", - "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", "dev": true, "requires": { - "chalk": "1.1.3", + "ansi-gray": "0.1.1", + "color-support": "1.1.3", "time-stamp": "1.1.0" } }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fbjs": { + "version": "0.8.16", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz", + "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=", + "dev": true, + "requires": { + "core-js": "1.2.7", + "isomorphic-fetch": "2.2.1", + "loose-envify": "1.3.1", + "object-assign": "4.1.1", + "promise": "7.3.1", + "setimmediate": "1.0.5", + "ua-parser-js": "0.7.17" + }, + "dependencies": { + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", + "dev": true + } + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", @@ -911,16 +2912,15 @@ "dev": true }, "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" } }, "find-index": { @@ -940,15 +2940,15 @@ } }, "findup-sync": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", - "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", "dev": true, "requires": { - "detect-file": "0.1.0", - "is-glob": "2.0.1", - "micromatch": "2.3.11", - "resolve-dir": "0.1.1" + "detect-file": "1.0.0", + "is-glob": "3.1.0", + "micromatch": "3.1.4", + "resolve-dir": "1.0.1" } }, "fined": { @@ -961,18 +2961,7 @@ "is-plain-object": "2.0.4", "object.defaults": "1.1.0", "object.pick": "1.3.0", - "parse-filepath": "1.0.1" - }, - "dependencies": { - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1" - } - } + "parse-filepath": "1.0.2" } }, "first-chunk-stream": { @@ -982,11 +2971,60 @@ "dev": true }, "flagged-respawn": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", - "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", "dev": true }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + }, + "dependencies": { + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -994,14 +3032,20 @@ "dev": true }, "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, "requires": { "for-in": "1.0.2" } }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -1019,18 +3063,21 @@ "mime-types": "2.1.17" } }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, "from": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", "dev": true }, - "fs-exists-sync": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", - "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", - "dev": true - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1047,16 +3094,20 @@ "inherits": "2.0.3", "mkdirp": "0.5.1", "rimraf": "2.6.2" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } } }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -1073,11 +3124,25 @@ "wide-align": "1.1.2" }, "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } } } }, @@ -1090,6 +3155,21 @@ "globule": "0.1.0" } }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, "get-caller-file": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", @@ -1097,9 +3177,15 @@ "dev": true }, "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", + "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, "getpass": { @@ -1120,15 +3206,17 @@ } }, "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { + "fs.realpath": "1.0.0", "inflight": "1.0.6", "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.3.3" + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "glob-base": { @@ -1139,6 +3227,23 @@ "requires": { "glob-parent": "2.0.0", "is-glob": "2.0.1" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } } }, "glob-parent": { @@ -1148,6 +3253,23 @@ "dev": true, "requires": { "is-glob": "2.0.1" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } } }, "glob-stream": { @@ -1164,6 +3286,33 @@ "unique-stream": "1.0.0" }, "dependencies": { + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, "readable-stream": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", @@ -1176,6 +3325,12 @@ "string_decoder": "0.10.31" } }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, "through2": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", @@ -1207,27 +3362,62 @@ } }, "global-modules": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", - "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "requires": { - "global-prefix": "0.1.5", - "is-windows": "0.2.0" + "global-prefix": "1.0.2", + "is-windows": "1.0.1", + "resolve-dir": "1.0.1" } }, "global-prefix": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", - "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "requires": { + "expand-tilde": "2.0.2", "homedir-polyfill": "1.0.1", - "ini": "1.3.4", - "is-windows": "0.2.0", + "ini": "1.3.5", + "is-windows": "1.0.1", "which": "1.3.0" } }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=", + "dev": true + }, "globule": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", @@ -1262,6 +3452,18 @@ "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", "dev": true }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, "minimatch": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", @@ -1283,15 +3485,29 @@ "sparkles": "1.0.0" } }, - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "gonzales-pe": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.2.3.tgz", + "integrity": "sha512-Kjhohco0esHQnOiqqdJeNz/5fyPkOMD/d6XVjwTAoPGUFh0mCollPUTUTa2OZy4dYNAqlPIQdTiNzJTWdd9Htw==", "dev": true, "requires": { - "natives": "1.1.0" + "minimist": "1.1.3" + }, + "dependencies": { + "minimist": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz", + "integrity": "sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=", + "dev": true + } } }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, "gulp": { "version": "3.9.1", "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", @@ -1302,8 +3518,8 @@ "chalk": "1.1.3", "deprecated": "0.0.1", "gulp-util": "3.0.8", - "interpret": "1.0.4", - "liftoff": "2.3.0", + "interpret": "1.1.0", + "liftoff": "2.5.0", "minimist": "1.2.0", "orchestrator": "0.3.8", "pretty-hrtime": "1.0.3", @@ -1311,107 +3527,56 @@ "tildify": "1.2.0", "v8flags": "2.1.1", "vinyl-fs": "0.3.14" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + } } }, "gulp-autoprefixer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/gulp-autoprefixer/-/gulp-autoprefixer-4.0.0.tgz", - "integrity": "sha1-4AqMVxuF0GUWrCY0G+kN/Z/B6rA=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/gulp-autoprefixer/-/gulp-autoprefixer-4.1.0.tgz", + "integrity": "sha1-Bkr3PMAsrayP800L+T/9+5TqEqo=", "dev": true, "requires": { - "autoprefixer": "7.1.6", - "gulp-util": "3.0.8", + "autoprefixer": "7.2.3", + "fancy-log": "1.3.2", + "plugin-error": "0.1.2", "postcss": "6.0.14", "through2": "2.0.3", "vinyl-sourcemaps-apply": "0.2.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.0" - } - }, - "autoprefixer": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.1.6.tgz", - "integrity": "sha512-C9yv/UF3X+eJTi/zvfxuyfxmLibYrntpF3qoJYrMeQwgUJOZrZvpJiMG2FMQ3qnhWtF/be4pYONBBw95ZGe3vA==", - "dev": true, - "requires": { - "browserslist": "2.7.0", - "caniuse-lite": "1.0.30000758", - "normalize-range": "0.1.2", - "num2fraction": "1.2.2", - "postcss": "6.0.14", - "postcss-value-parser": "3.3.0" - } - }, - "browserslist": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.7.0.tgz", - "integrity": "sha512-s34mrlczJsfbJu//mz/m9zlOy/S6tiP6El1u8iC1gTfEnzKXvxo8RAoCxS/MmojB7rd7bnfYzvKQNHykWaUWWw==", - "dev": true, - "requires": { - "caniuse-lite": "1.0.30000758", - "electron-to-chromium": "1.3.27" - } - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", - "dev": true, - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - } + } + }, + "gulp-better-rollup": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gulp-better-rollup/-/gulp-better-rollup-2.0.0.tgz", + "integrity": "sha512-CmK3LYY9RTXliAtptVisaGLP5XG3m3y5k0TV7bA9ksYgDSwPtHjnc0IzIZvYwRXfhWL1Uoscz5FZ7a4ieXHPcQ==", + "dev": true, + "requires": { + "gulp-util": "3.0.8", + "lodash.camelcase": "4.3.0", + "rollup": "0.50.1", + "vinyl-sourcemaps-apply": "0.2.1" } }, "gulp-clean-css": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/gulp-clean-css/-/gulp-clean-css-3.9.0.tgz", - "integrity": "sha512-CsqaSO2ZTMQI/WwbWloZWBudhsRMKgxBthzxt4bbcbWrjOY4pRFziyK9IH6YbTpaWAPKEwWpopPkpiAEoDofxw==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/gulp-clean-css/-/gulp-clean-css-3.9.2.tgz", + "integrity": "sha512-NaBtCOmhk2FP1D1pgv5jEvZaKr+6FZHvEgsl1iPGmTpyUOWpECR3Mzdciwo+hEWwtlnkZSueoAf74YCMtar48A==", "dev": true, "requires": { "clean-css": "4.1.9", - "gulp-util": "3.0.8", + "plugin-error": "0.1.2", "through2": "2.0.3", "vinyl-sourcemaps-apply": "0.2.1" } @@ -1461,37 +3626,15 @@ } } }, - "gulp-less": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/gulp-less/-/gulp-less-3.3.2.tgz", - "integrity": "sha1-9mNq3MZhUKiQJxn6WZY/x/hipJo=", - "dev": true, - "requires": { - "accord": "0.27.3", - "gulp-util": "3.0.8", - "less": "2.7.3", - "object-assign": "4.1.1", - "through2": "2.0.3", - "vinyl-sourcemaps-apply": "0.2.1" - }, - "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - } - } - }, "gulp-open": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/gulp-open/-/gulp-open-2.0.0.tgz", - "integrity": "sha1-oW9n6VzqiyBhtjo7jDibxVm44c4=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/gulp-open/-/gulp-open-2.1.0.tgz", + "integrity": "sha512-JzFlG7szoFyjNtlo6f7JnkaNOm0ZaYKofSGvs+4YRI4G+oTknJDn8N14Ocau06yJA1eQoFSOQVHhVWqas1cnHA==", "dev": true, "requires": { "colors": "1.1.2", - "gulp-util": "3.0.8", "open": "0.0.5", + "plugin-log": "0.1.0", "through2": "2.0.3" } }, @@ -1510,38 +3653,6 @@ "istextorbinary": "1.0.2", "readable-stream": "2.3.3", "replacestream": "4.0.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } } }, "gulp-s3": { @@ -1550,7 +3661,7 @@ "integrity": "sha1-njArVkUgbiF6Ul0gvvoe0pNEJJI=", "dev": true, "requires": { - "async": "2.5.0", + "async": "2.6.0", "event-stream": "3.3.4", "gulp-util": "2.2.20", "knox": "0.9.2", @@ -1569,15 +3680,6 @@ "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", "dev": true }, - "async": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", - "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", - "dev": true, - "requires": { - "lodash": "4.17.4" - } - }, "chalk": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", @@ -1601,6 +3703,12 @@ "meow": "3.7.0" } }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, "gulp-util": { "version": "2.2.20", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", @@ -1626,23 +3734,10 @@ "ansi-regex": "0.2.1" } }, - "knox": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/knox/-/knox-0.9.2.tgz", - "integrity": "sha1-NzZZNmniTwJP2vcjtqHcSv2DmnE=", - "dev": true, - "requires": { - "debug": "1.0.5", - "mime": "1.2.11", - "once": "1.3.3", - "stream-counter": "1.0.0", - "xml2js": "0.4.19" - } - }, - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "lodash._reinterpolate": { @@ -1651,16 +3746,6 @@ "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", "dev": true }, - "lodash.defaults": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", - "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", - "dev": true, - "requires": { - "lodash._objecttypes": "2.4.1", - "lodash.keys": "2.4.1" - } - }, "lodash.escape": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", @@ -1708,12 +3793,6 @@ "lodash.escape": "2.4.1" } }, - "mime": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", - "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", - "dev": true - }, "minimist": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", @@ -1732,6 +3811,12 @@ "string_decoder": "0.10.31" } }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, "strip-ansi": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", @@ -1782,86 +3867,9 @@ "requires": { "gulp-util": "3.0.8", "lodash.clonedeep": "4.5.0", - "node-sass": "4.6.0", + "node-sass": "4.7.2", "through2": "2.0.3", "vinyl-sourcemaps-apply": "0.2.1" - }, - "dependencies": { - "gaze": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", - "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", - "dev": true, - "requires": { - "globule": "1.2.0" - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.3.3", - "path-is-absolute": "1.0.1" - } - }, - "globule": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", - "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=", - "dev": true, - "requires": { - "glob": "7.1.2", - "lodash": "4.17.4", - "minimatch": "3.0.4" - } - }, - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - }, - "node-sass": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.6.0.tgz", - "integrity": "sha512-rh0CvkxpYdQdbWx4EQfunmG0+99BVyVwQHlFE+yUzc6lteF5K3WUcJ0bdmv9E9CqQA1RfuMyvmpDP99cmBObow==", - "dev": true, - "requires": { - "async-foreach": "0.1.3", - "chalk": "1.1.3", - "cross-spawn": "3.0.1", - "gaze": "1.1.2", - "get-stdin": "4.0.1", - "glob": "7.1.2", - "in-publish": "2.0.0", - "lodash.assign": "4.2.0", - "lodash.clonedeep": "4.5.0", - "lodash.mergewith": "4.6.0", - "meow": "3.7.0", - "mkdirp": "0.5.1", - "nan": "2.7.0", - "node-gyp": "3.6.2", - "npmlog": "4.1.2", - "request": "2.81.0", - "sass-graph": "2.2.4", - "stdout-stream": "1.4.0" - } - } } }, "gulp-size": { @@ -1877,14 +3885,25 @@ "pretty-bytes": "3.0.1", "stream-counter": "1.0.0", "through2": "2.0.3" - }, - "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - } + } + }, + "gulp-sourcemaps": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.2.tgz", + "integrity": "sha1-T0HHKzWn6ga2ZtLj9XkX4sDnHE4=", + "dev": true, + "requires": { + "@gulp-sourcemaps/identity-map": "1.0.1", + "@gulp-sourcemaps/map-sources": "1.0.0", + "acorn": "5.3.0", + "convert-source-map": "1.5.1", + "css": "2.2.1", + "debug-fabulous": "1.0.0", + "detect-newline": "2.1.0", + "graceful-fs": "4.1.11", + "source-map": "0.5.7", + "strip-bom-string": "1.0.0", + "through2": "2.0.3" } }, "gulp-svgmin": { @@ -1898,50 +3917,47 @@ } }, "gulp-svgstore": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/gulp-svgstore/-/gulp-svgstore-6.1.0.tgz", - "integrity": "sha1-BLIDrA4T+O1tv8lA0lllxOJFZnY=", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/gulp-svgstore/-/gulp-svgstore-6.1.1.tgz", + "integrity": "sha1-f6ivAFwjuwM4+fNlpgEMhmUfE9A=", "dev": true, "requires": { "cheerio": "0.22.0", - "gulp-util": "3.0.8" - } - }, - "gulp-uglify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.0.tgz", - "integrity": "sha1-DfAzHXKg0wLj434QlIXd3zPG0co=", - "dev": true, - "requires": { - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash": "4.17.4", - "make-error-cause": "1.2.2", - "through2": "2.0.3", - "uglify-js": "3.1.6", - "vinyl-sourcemaps-apply": "0.2.1" + "fancy-log": "1.3.2", + "plugin-error": "0.1.2", + "vinyl": "2.1.0" }, "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", "dev": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", "dev": true }, - "uglify-js": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.1.6.tgz", - "integrity": "sha512-/rseyxEKEVMBo8279lqpoJgD6C/i/CIi+9TJDvWmb+Xo6mqMKwjA8Io3IMHlcXQzj99feR6zrN8m3wqqvm/nYA==", + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "vinyl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", "dev": true, "requires": { - "commander": "2.11.0", - "source-map": "0.6.1" + "clone": "2.1.1", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.0.0", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" } } } @@ -1957,7 +3973,7 @@ "beeper": "1.1.1", "chalk": "1.1.3", "dateformat": "2.2.0", - "fancy-log": "1.3.0", + "fancy-log": "1.3.2", "gulplog": "1.0.0", "has-gulplog": "0.1.0", "lodash._reescape": "3.0.0", @@ -1970,6 +3986,20 @@ "replace-ext": "0.0.1", "through2": "2.0.3", "vinyl": "0.5.3" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + } } }, "gulplog": { @@ -1990,20 +4020,25 @@ "duplexer": "0.1.1" } }, - "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", - "dev": true - }, "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "commander": "2.12.2", + "is-my-json-valid": "2.17.1", + "pinkie-promise": "2.0.1" + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", "dev": true, "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" + "function-bind": "1.1.1" } }, "has-ansi": { @@ -2015,6 +4050,12 @@ "ansi-regex": "2.1.1" } }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, "has-gulplog": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", @@ -2030,6 +4071,38 @@ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, "hawk": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", @@ -2048,6 +4121,16 @@ "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", "dev": true }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, "homedir-polyfill": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", @@ -2063,6 +4146,12 @@ "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", "dev": true }, + "html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", + "dev": true + }, "htmlparser2": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", @@ -2075,38 +4164,6 @@ "entities": "1.1.1", "inherits": "2.0.3", "readable-stream": "2.3.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } } }, "http-signature": { @@ -2120,12 +4177,23 @@ "sshpk": "1.13.1" } }, - "image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", - "dev": true, - "optional": true + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "dev": true + }, + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true }, "in-publish": { "version": "2.0.0", @@ -2142,10 +4210,10 @@ "repeating": "2.0.1" } }, - "indx": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/indx/-/indx-0.2.3.tgz", - "integrity": "sha1-Fdz1bunPZcAjTFE8J/vVgOcPvFA=", + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", "dev": true }, "inflight": { @@ -2154,7 +4222,7 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.3.3", + "once": "1.4.0", "wrappy": "1.0.2" } }, @@ -2165,17 +4233,94 @@ "dev": true }, "ini": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "3.0.0", + "chalk": "2.3.0", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.1.0", + "figures": "2.0.0", + "lodash": "4.17.4", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, "interpret": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.4.tgz", - "integrity": "sha1-ggzdWIuGj/sZGoCVBtbJyPISsbA=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, + "invariant": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", + "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", @@ -2183,13 +4328,44 @@ "dev": true }, "is-absolute": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", - "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", "dev": true, "requires": { - "is-relative": "0.2.1", - "is-windows": "0.2.0" + "is-relative": "1.0.0", + "is-windows": "1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-alphabetical": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.1.tgz", + "integrity": "sha1-x3B5zJHU76x3W+EDS/LSQ/lebwg=", + "dev": true + }, + "is-alphanumeric": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", + "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=", + "dev": true + }, + "is-alphanumerical": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz", + "integrity": "sha1-37SqTRCF4zvbYcLe6cgOnGwZ9Ts=", + "dev": true, + "requires": { + "is-alphabetical": "1.0.1", + "is-decimal": "1.0.1" } }, "is-arrayish": { @@ -2213,6 +4389,50 @@ "builtin-modules": "1.1.1" } }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "dev": true + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-decimal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz", + "integrity": "sha1-9ftqlJlq2ejjdh+/vQkfH8qMToI=", + "dev": true + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", @@ -2235,9 +4455,9 @@ "dev": true }, "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, "is-finite": { @@ -2250,32 +4470,109 @@ } }, "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "is-extglob": "2.1.1" } }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "is-hexadecimal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz", + "integrity": "sha1-bghLvJIGH7sJcexYts5tQE4k2mk=", + "dev": true + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-my-json-valid": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz", + "integrity": "sha512-Q2khNw+oBlWuaYvEEHtKSw/pCxD2L5Rc1C+UQme9X6JdRDh7m5D7HkozA0qa3DUkQ6VzCnEm8mVIQPyIRkI5sQ==", "dev": true, "requires": { - "is-extglob": "1.0.0" + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" } }, "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-odd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-1.0.0.tgz", + "integrity": "sha1-O4qTLrAos3dcObsJ6RdnrM22kIg=", + "dev": true, + "requires": { + "is-number": "3.0.0" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.1" } }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -2283,14 +4580,6 @@ "dev": true, "requires": { "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "is-posix-bracket": { @@ -2305,15 +4594,66 @@ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", "dev": true }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "1.0.1" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, "is-relative": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", - "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", "dev": true, "requires": { - "is-unc-path": "0.1.2" + "is-unc-path": "1.0.0" } }, + "is-resolvable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.1.tgz", + "integrity": "sha512-y5CXYbzvB3jTnWAZH1Nl7ykUWb6T3BcTs56HUruwBf8MhF56n1HWqhDWnVFo8GHrUPDgvUUNVhrc2U8W7iqz5g==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-supported-regexp-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.0.tgz", + "integrity": "sha1-i1IMhfrnolM4LUsCZS4EVXbhO7g=", + "dev": true + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -2321,9 +4661,9 @@ "dev": true }, "is-unc-path": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", - "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", "dev": true, "requires": { "unc-path-regex": "0.1.2" @@ -2335,16 +4675,28 @@ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, + "is-whitespace-character": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz", + "integrity": "sha1-muAXbzKCtlRXoZks2whPil+DPjs=", + "dev": true + }, "is-windows": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", - "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.1.tgz", + "integrity": "sha1-MQ23D3QtJZoWo2kgK1GvhCMzENk=", + "dev": true + }, + "is-word-character": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.1.tgz", + "integrity": "sha1-WgP6HqkazopusMfNdw64bWXIvvs=", "dev": true }, "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "isexe": { @@ -2354,20 +4706,19 @@ "dev": true }, "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", "dev": true, "requires": { - "isarray": "1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } + "node-fetch": "1.7.3", + "whatwg-fetch": "2.0.3" } }, "isstream": { @@ -2387,19 +4738,25 @@ } }, "js-base64": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.3.2.tgz", - "integrity": "sha512-Y2/+DnfJJXT1/FCwUebUhLWb3QihxiSC42+ctHLGogmW2jPY6LCapMdFZXRvVP2z6qyKW7s6qncE/9gSqZiArw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.0.tgz", + "integrity": "sha512-Wehd+7Pf9tFvGb+ydPm9TjYjV8X1YHOVyG8QyELZxEMqOhemVwGRmoG8iQ/soqI3n8v4xn59zaLxiCJiaaRzKA==", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", "dev": true }, "js-yaml": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", - "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", "dev": true, "requires": { "argparse": "1.0.9", - "esprima": "2.7.3" + "esprima": "4.0.0" } }, "jsbn": { @@ -2409,20 +4766,35 @@ "dev": true, "optional": true }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", + "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==", + "dev": true + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "dev": true }, - "json-stable-stringify": { + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "0.0.0" - } + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true }, "json-stringify-safe": { "version": "5.0.1", @@ -2430,10 +4802,16 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", "dev": true }, "jsprim": { @@ -2456,20 +4834,59 @@ } } }, + "jsx-ast-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz", + "integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=", + "dev": true, + "requires": { + "array-includes": "3.0.3" + } + }, "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "known-css-properties": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.5.0.tgz", + "integrity": "sha512-LOS0CoS8zcZnB1EjLw4LLqDXw8nvt3AGH5dXLQP3D9O1nLLA+9GC5GnPl5mmF+JiQAtSX4VyZC7KvEtcA4kUtA==", + "dev": true + }, + "knox": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/knox/-/knox-0.9.2.tgz", + "integrity": "sha1-NzZZNmniTwJP2vcjtqHcSv2DmnE=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "debug": "1.0.5", + "mime": "1.2.11", + "once": "1.4.0", + "stream-counter": "1.0.0", + "xml2js": "0.4.19" + }, + "dependencies": { + "debug": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.5.tgz", + "integrity": "sha1-9yQSF0MPmd7EwrRz6rkiKOh0wqw=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } } }, "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", + "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", + "dev": true, + "requires": { + "set-getter": "0.1.0" + } }, "lcid": { "version": "1.0.0", @@ -2480,82 +4897,74 @@ "invert-kv": "1.0.0" } }, - "less": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", - "integrity": "sha512-KPdIJKWcEAb02TuJtaLrhue0krtRLoRoo7x6BNJIBelO00t/CCdJQUnHW5V34OnHMWzIktSalJxRO+FvytQlCQ==", + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "errno": "0.1.4", - "graceful-fs": "4.1.11", - "image-size": "0.5.5", - "mime": "1.4.1", - "mkdirp": "0.5.1", - "promise": "7.3.1", - "request": "2.81.0", - "source-map": "0.5.7" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true, - "optional": true - } + "prelude-ls": "1.1.2", + "type-check": "0.3.2" } }, "liftoff": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", - "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", "dev": true, "requires": { "extend": "3.0.1", - "findup-sync": "0.4.3", + "findup-sync": "2.0.0", "fined": "1.1.0", - "flagged-respawn": "0.3.2", - "lodash.isplainobject": "4.0.6", - "lodash.isstring": "4.0.1", - "lodash.mapvalues": "4.6.0", + "flagged-respawn": "1.0.0", + "is-plain-object": "2.0.4", + "object.map": "1.0.1", "rechoir": "0.6.2", "resolve": "1.5.0" } }, "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { "graceful-fs": "4.1.11", "parse-json": "2.2.0", "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" + "strip-bom": "3.0.0" }, "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } } } }, "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", "dev": true }, "lodash._basecopy": { @@ -2695,10 +5104,10 @@ "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=", "dev": true }, - "lodash.clone": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", "dev": true }, "lodash.clonedeep": { @@ -2707,12 +5116,35 @@ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "lodash.cond": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", + "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", "dev": true }, + "lodash.defaults": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", + "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1", + "lodash.keys": "2.4.1" + }, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + } + } + }, "lodash.escape": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", @@ -2761,18 +5193,6 @@ "lodash._objecttypes": "2.4.1" } }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", - "dev": true - }, "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", @@ -2790,12 +5210,6 @@ "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=", "dev": true }, - "lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", - "dev": true - }, "lodash.merge": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.0.tgz", @@ -2808,12 +5222,6 @@ "integrity": "sha1-FQzwoWeR9ZA7iJHqsVRgknS96lU=", "dev": true }, - "lodash.partialright": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.partialright/-/lodash.partialright-4.2.1.tgz", - "integrity": "sha1-ATDYDoM2MmTUAHTzKbij56ihzEs=", - "dev": true - }, "lodash.pick": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", @@ -2871,12 +5279,6 @@ "lodash.escape": "3.2.0" } }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, "lodash.values": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", @@ -2899,12 +5301,61 @@ } } }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "log-symbols": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.1.0.tgz", + "integrity": "sha512-zLeLrzMA1A2vRF1e/0Mo+LNINzi6jzBylHj5WqvQ/WK/5WCZt8si9SyN4p9llr/HRYvVR1AoXHRHl4WTHyQAzQ==", + "dev": true, + "requires": { + "chalk": "2.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "longest-streak": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", + "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", "dev": true }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", @@ -2916,24 +5367,51 @@ } }, "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } }, - "make-error": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.0.tgz", - "integrity": "sha1-Uq06M5zPEM5itAQLcI/nByRLi5Y=", - "dev": true + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "0.10.37" + } }, - "make-error-cause": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", - "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", + "magic-string": { + "version": "0.22.4", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.4.tgz", + "integrity": "sha512-kxBL06p6iO2qPBHsqGK2b3cRwiRGpnmSuVWNhwHcMX7qJOUr1HvricYP1LZOCdkQBUp0jiWg2d6WJwR3vYgByw==", + "dev": true, + "requires": { + "vlq": "0.2.3" + } + }, + "make-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz", + "integrity": "sha1-V7713IXSOSO6I3ZzJNjo+PPZaUs=", "dev": true, "requires": { - "make-error": "1.3.0" + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } } }, "map-cache": { @@ -2954,6 +5432,59 @@ "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", "dev": true }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, + "markdown-escapes": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.1.tgz", + "integrity": "sha1-GZTfLTr0gR3lmmcUk0wrIpJzRRg=", + "dev": true + }, + "markdown-table": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.1.tgz", + "integrity": "sha1-Sz3ToTPRUYuO8NvHCb8qG0gkvIw=", + "dev": true + }, + "mathml-tag-names": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.0.1.tgz", + "integrity": "sha1-jUEmgWi/htEQK5gQnijlMeejRXg=", + "dev": true + }, + "mdast-util-compact": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", + "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", + "dev": true, + "requires": { + "unist-util-modify-children": "1.1.1", + "unist-util-visit": "1.3.0" + } + }, + "memoizee": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.11.tgz", + "integrity": "sha1-vemBdmPJ5A/bKk6hw2cpYIeujI8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-weak-map": "2.0.2", + "event-emitter": "0.3.5", + "is-promise": "2.1.0", + "lru-queue": "0.1.0", + "next-tick": "1.0.0", + "timers-ext": "0.1.2" + } + }, "meow": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", @@ -2972,41 +5503,100 @@ "trim-newlines": "1.0.0" }, "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } } } }, "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.4.tgz", + "integrity": "sha512-kFRtviKYoAJT+t7HggMl0tBFGNAKLw/S7N+CO9qfEQyisob1Oy4pao+geRbkyeEd+V9aOkvZ4mhuyPvI/q9Sfg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.0", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "extglob": "2.0.3", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.6", + "object.pick": "1.3.0", + "regex-not": "1.0.0", + "snapdragon": "0.8.1", + "to-regex": "3.0.1" } }, "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true, - "optional": true + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "dev": true }, "mime-db": { "version": "1.30.0", @@ -3023,21 +5613,58 @@ "mime-db": "1.30.0" } }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "dev": true + }, "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" } }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "is-plain-obj": "1.1.0" + } + }, + "mixin-deep": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.0.tgz", + "integrity": "sha512-dgaCvoh6i1nosAUBKb0l0pfJ78K8+S9fluyIR2YvAeUD/QuMahnFnF3xYty5eYXMjhGSsB0DsW6A0uAZyetoAg==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -3045,14 +5672,6 @@ "dev": true, "requires": { "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } } }, "ms": { @@ -3070,18 +5689,73 @@ "duplexer2": "0.0.2" } }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, "nan": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", - "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", "dev": true }, + "nanomatch": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.6.tgz", + "integrity": "sha512-WJ6XTCbvWXUFPbi/bDwKcYkCeOGUHzaJj72KbuPqGn78Ba/F5Vu26Zlo6SuMQbCIst1RGKL1zfWBCOGAlbRLAg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "is-odd": "1.0.0", + "kind-of": "5.1.0", + "object.pick": "1.3.0", + "regex-not": "1.0.0", + "snapdragon": "0.8.1", + "to-regex": "3.0.1" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "natives": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", - "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz", + "integrity": "sha512-8eRaxn8u/4wN8tGkhlc2cgwwvOLMLUMUn4IYTexMgWd+LyUDfeXVkk2ygQR0hvIHbJQXgHujia3ieUUDwNGkEA==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "dev": true, + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + } + }, "node-gyp": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", @@ -3096,47 +5770,83 @@ "nopt": "3.0.6", "npmlog": "4.1.2", "osenv": "0.1.4", - "request": "2.81.0", + "request": "2.79.0", "rimraf": "2.6.2", "semver": "5.3.0", "tar": "2.2.1", "which": "1.3.0" }, "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "node-sass": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.7.2.tgz", + "integrity": "sha512-CaV+wLqZ7//Jdom5aUFCpGNoECd7BbNhjuwdsX/LkXBrHl8eb1Wjw4HvWqcFvhr5KuNgAk8i/myf/MQ1YYeroA==", + "dev": true, + "requires": { + "async-foreach": "0.1.3", + "chalk": "1.1.3", + "cross-spawn": "3.0.1", + "gaze": "1.1.2", + "get-stdin": "4.0.1", + "glob": "7.1.2", + "in-publish": "2.0.0", + "lodash.assign": "4.2.0", + "lodash.clonedeep": "4.5.0", + "lodash.mergewith": "4.6.0", + "meow": "3.7.0", + "mkdirp": "0.5.1", + "nan": "2.8.0", + "node-gyp": "3.6.2", + "npmlog": "4.1.2", + "request": "2.79.0", + "sass-graph": "2.2.4", + "stdout-stream": "1.4.0", + "true-case-path": "1.0.2" + }, + "dependencies": { + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.3.3", - "path-is-absolute": "1.0.1" + "lru-cache": "4.1.1", + "which": "1.3.0" } }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "gaze": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", + "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "globule": "1.2.0" } }, - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true + }, + "globule": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", + "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=", + "dev": true, + "requires": { + "glob": "7.1.2", + "lodash": "4.17.4", + "minimatch": "3.0.4" + } } } }, @@ -3157,7 +5867,7 @@ "requires": { "hosted-git-info": "2.5.0", "is-builtin-module": "1.0.0", - "semver": "4.3.6", + "semver": "5.4.1", "validate-npm-package-license": "3.0.1" } }, @@ -3176,6 +5886,12 @@ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "dev": true }, + "normalize-selector": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", + "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", + "dev": true + }, "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", @@ -3216,40 +5932,116 @@ "dev": true }, "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "array-each": "1.0.1", - "array-slice": "1.0.0", - "for-own": "1.0.0", - "isobject": "3.0.1" + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" }, "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "for-in": "1.0.2" + "is-descriptor": "0.1.6" } }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } } } }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "1.0.1", + "array-slice": "1.1.0", + "for-own": "1.0.0", + "isobject": "3.0.1" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "1.0.0", + "make-iterator": "1.0.0" + } + }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", @@ -3258,6 +6050,17 @@ "requires": { "for-own": "0.1.5", "is-extendable": "0.1.1" + }, + "dependencies": { + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + } } }, "object.pick": { @@ -3267,31 +6070,46 @@ "dev": true, "requires": { "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { "wrappy": "1.0.2" } }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, "open": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=", "dev": true }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, "orchestrator": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", @@ -3340,13 +6158,48 @@ "os-tmpdir": "1.0.2" } }, + "p-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", + "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", + "dev": true + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.1.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "parse-entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.1.tgz", + "integrity": "sha1-gRLYhHExnyerrk1klksSL+ThuJA=", + "dev": true, + "requires": { + "character-entities": "1.2.1", + "character-entities-legacy": "1.1.1", + "character-reference-invalid": "1.1.1", + "is-alphanumerical": "1.0.1", + "is-decimal": "1.0.1", + "is-hexadecimal": "1.0.1" + } + }, "parse-filepath": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", - "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", "dev": true, "requires": { - "is-absolute": "0.2.6", + "is-absolute": "1.0.0", "map-cache": "0.2.2", "path-root": "0.1.1" } @@ -3361,6 +6214,23 @@ "is-dotfile": "1.0.3", "is-extglob": "1.0.0", "is-glob": "2.0.1" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } } }, "parse-json": { @@ -3378,6 +6248,12 @@ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", @@ -3393,6 +6269,12 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, "path-parse": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", @@ -3415,20 +6297,18 @@ "dev": true }, "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "pify": "2.3.0" }, "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } } @@ -3442,16 +6322,10 @@ "through": "2.3.8" } }, - "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", - "dev": true - }, "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, "pinkie": { @@ -3469,12 +6343,331 @@ "pinkie": "2.0.4" } }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "1.1.2" + } + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + } + } + }, + "plugin-log": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/plugin-log/-/plugin-log-0.1.0.tgz", + "integrity": "sha1-hgSc9qsQgzOYqTHzaJy67nteEzM=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "dateformat": "1.0.12" + }, + "dependencies": { + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + } + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "6.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", + "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "4.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "postcss-bem-linter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-bem-linter/-/postcss-bem-linter-3.1.0.tgz", + "integrity": "sha512-mtEdAdNQfdTxrE9tEfm3ShST3HLlBTgFlc+O9ui9Fb2w++ltHce5rY/vjNypLtDBt+HBGV/P7qX6gAuP4gHDIA==", + "dev": true, + "requires": { + "minimatch": "3.0.4", + "postcss": "6.0.14", + "postcss-resolve-nested-selector": "0.1.1" + } + }, + "postcss-html": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.12.0.tgz", + "integrity": "sha512-KxKUpj7AY7nlCbLcTOYxdfJnGE7QFAfU2n95ADj1Q90RM/pOLdz8k3n4avOyRFs7MDQHcRzJQWM1dehCwJxisQ==", + "dev": true, + "requires": { + "htmlparser2": "3.9.2", + "remark": "8.0.0", + "unist-util-find-all-after": "1.0.1" + } + }, + "postcss-less": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-1.1.3.tgz", + "integrity": "sha512-WS0wsQxRm+kmN8wEYAGZ3t4lnoNfoyx9EJZrhiPR1K0lMHR0UNWnz52Ya5QRXChHtY75Ef+kDc05FpnBujebgw==", + "dev": true, + "requires": { + "postcss": "5.2.18" + }, + "dependencies": { + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", + "dev": true + }, + "postcss-reporter": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-5.0.0.tgz", + "integrity": "sha512-rBkDbaHAu5uywbCR2XE8a25tats3xSOsGNx6mppK6Q9kSFGKc/FyAzfci+fWM2l+K402p1D0pNcfDGxeje5IKg==", + "dev": true, + "requires": { + "chalk": "2.3.0", + "lodash": "4.17.4", + "log-symbols": "2.1.0", + "postcss": "6.0.14" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=", + "dev": true + }, + "postcss-safe-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-3.0.1.tgz", + "integrity": "sha1-t1Pv9sfArqXoN1++TN6L+QY/8UI=", + "dev": true, + "requires": { + "postcss": "6.0.14" + } + }, + "postcss-sass": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.2.0.tgz", + "integrity": "sha512-cUmYzkP747fPCQE6d+CH2l1L4VSyIlAzZsok3HPjb5Gzsq3jE+VjpAdGlPsnQ310WKWI42sw+ar0UNN59/f3hg==", + "dev": true, + "requires": { + "gonzales-pe": "4.2.3", + "postcss": "6.0.14" + } + }, + "postcss-scss": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-1.0.2.tgz", + "integrity": "sha1-/0XPM1S4ee6JpOtoaA9GrJuxT5Q=", + "dev": true, + "requires": { + "postcss": "6.0.14" + } + }, + "postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "dev": true, + "requires": { + "dot-prop": "4.2.0", + "indexes-of": "1.0.1", + "uniq": "1.0.1" + } + }, + "postcss-sorting": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-3.1.0.tgz", + "integrity": "sha512-YCPTcJwGIInF1LpMD1lIYvMHTGUL4s97o/OraA6eKvoauhhk6vjwOWDDjm6uRKqug/kyDPMKEzmYZ6FtW6RDgw==", + "dev": true, + "requires": { + "lodash": "4.17.4", + "postcss": "6.0.14" + } + }, "postcss-value-parser": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", "dev": true }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", @@ -3496,28 +6689,43 @@ "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", "dev": true }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", "dev": true }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "dev": true, - "optional": true, "requires": { "asap": "2.0.6" } }, - "prr": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", - "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", + "prop-types": { + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz", + "integrity": "sha1-zq8IMCL8RrSjX2nhPvda7Q1jmFY=", "dev": true, - "optional": true + "requires": { + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1" + } }, "pseudomap": { "version": "1.0.2", @@ -3538,9 +6746,15 @@ "dev": true }, "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "dev": true + }, + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", "dev": true }, "randomatic": { @@ -3553,26 +6767,6 @@ "kind-of": "4.0.0" }, "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", @@ -3585,36 +6779,50 @@ } }, "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", "dev": true, "requires": { - "load-json-file": "1.1.0", + "load-json-file": "2.0.0", "normalize-package-data": "2.4.0", - "path-type": "1.1.0" + "path-type": "2.0.0" } }, "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", "dev": true, "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" + "find-up": "2.1.0", + "read-pkg": "2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + } } }, "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" } }, "rechoir": { @@ -3636,6 +6844,29 @@ "strip-indent": "1.0.1" } }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "private": "0.1.8" + } + }, "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", @@ -3645,6 +6876,105 @@ "is-equal-shallow": "0.1.3" } }, + "regex-not": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.0.tgz", + "integrity": "sha1-Qvg+OXcWIt+CawKvF2Ul1qXxV/k=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1" + } + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "1.3.3", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remark": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/remark/-/remark-8.0.0.tgz", + "integrity": "sha512-K0PTsaZvJlXTl9DN6qYlvjTkqSZBFELhROZMrblm2rB+085flN84nz4g/BscKRMqDvhzlK1oQ/xnWQumdeNZYw==", + "dev": true, + "requires": { + "remark-parse": "4.0.0", + "remark-stringify": "4.0.0", + "unified": "6.1.6" + } + }, + "remark-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-4.0.0.tgz", + "integrity": "sha512-XZgICP2gJ1MHU7+vQaRM+VA9HEL3X253uwUM/BGgx3iv6TH2B3bF3B8q00DKcyP9YrJV+/7WOWEWBFF/u8cIsw==", + "dev": true, + "requires": { + "collapse-white-space": "1.0.3", + "is-alphabetical": "1.0.1", + "is-decimal": "1.0.1", + "is-whitespace-character": "1.0.1", + "is-word-character": "1.0.1", + "markdown-escapes": "1.0.1", + "parse-entities": "1.1.1", + "repeat-string": "1.6.1", + "state-toggle": "1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "1.1.0", + "unherit": "1.1.0", + "unist-util-remove-position": "1.1.1", + "vfile-location": "2.0.2", + "xtend": "4.0.1" + } + }, + "remark-stringify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-4.0.0.tgz", + "integrity": "sha512-xLuyKTnuQer3ke9hkU38SUYLiTmS078QOnoFavztmbt/pAJtNSkNtFgR0U//uCcmG0qnyxao+PDuatQav46F1w==", + "dev": true, + "requires": { + "ccount": "1.0.2", + "is-alphanumeric": "1.0.0", + "is-decimal": "1.0.1", + "is-whitespace-character": "1.0.1", + "longest-streak": "2.0.2", + "markdown-escapes": "1.0.1", + "markdown-table": "1.1.1", + "mdast-util-compact": "1.0.1", + "parse-entities": "1.1.1", + "repeat-string": "1.6.1", + "state-toggle": "1.0.0", + "stringify-entities": "1.3.1", + "unherit": "1.1.0", + "xtend": "4.0.1" + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -3687,60 +7017,22 @@ "escape-string-regexp": "1.0.5", "object-assign": "4.1.1", "readable-stream": "2.3.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } } }, "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "version": "2.79.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", "dev": true, "requires": { "aws-sign2": "0.6.0", "aws4": "1.6.0", - "caseless": "0.12.0", + "caseless": "0.11.0", "combined-stream": "1.0.5", "extend": "3.0.1", "forever-agent": "0.6.1", "form-data": "2.1.4", - "har-validator": "4.2.1", + "har-validator": "2.0.6", "hawk": "3.1.3", "http-signature": "1.1.1", "is-typedarray": "1.0.0", @@ -3748,12 +7040,10 @@ "json-stringify-safe": "5.0.1", "mime-types": "2.1.17", "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.1.1", + "qs": "6.3.2", "stringstream": "0.0.5", "tough-cookie": "2.3.3", - "tunnel-agent": "0.6.0", + "tunnel-agent": "0.4.3", "uuid": "3.1.0" } }, @@ -3763,12 +7053,28 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, + "require-from-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.1.tgz", + "integrity": "sha1-xUUjPp19pmFunVmt+zn8n1iGdv8=", + "dev": true + }, "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, "resolve": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", @@ -3779,22 +7085,35 @@ } }, "resolve-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", - "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "requires": { - "expand-tilde": "1.2.2", - "global-modules": "0.2.3" + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" } }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "align-text": "0.1.4" + "onetime": "2.0.1", + "signal-exit": "3.0.2" } }, "rimraf": { @@ -3804,33 +7123,209 @@ "dev": true, "requires": { "glob": "7.1.2" + } + }, + "rollup": { + "version": "0.50.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.50.1.tgz", + "integrity": "sha512-XwrnqjSTk+yR8GbP6hiJuVe83MVmBw/gm4P3qP34A10fRXvv6ppl0ZUg1+Pj1tIZSR/aw5ZaILLEiVxwXIAdAw==", + "dev": true + }, + "rollup-plugin-babel": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-3.0.3.tgz", + "integrity": "sha512-5kzM/Rr4jQSRPLc2eN5NuD+CI/6AAy7S1O18Ogu4U3nq1Q42VJn0C9EMtqnvxtfwf1XrezOtdA9ro1VZI5B0mA==", + "dev": true, + "requires": { + "rollup-pluginutils": "1.5.2" + } + }, + "rollup-plugin-commonjs": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-8.2.6.tgz", + "integrity": "sha512-qK0+uhktmnAgZkHkqFuajNmPw93fjrO7+CysDaxWE5jrUR9XSlSvuao5ZJP+XizxA8weakhgYYBtbVz9SGBpjA==", + "dev": true, + "requires": { + "acorn": "5.3.0", + "estree-walker": "0.5.1", + "magic-string": "0.22.4", + "resolve": "1.5.0", + "rollup-pluginutils": "2.0.1" }, "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.3.3", - "path-is-absolute": "1.0.1" + "arr-flatten": "1.1.0" } }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "estree-walker": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.5.1.tgz", + "integrity": "sha512-7HgCgz1axW7w5aOvgOQkoR1RMBkllygJrssU3BvymKQ95lxXYv6Pon17fBRDm9qhkvXZGijOULoSF9ShOk/ZLg==", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "rollup-pluginutils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz", + "integrity": "sha1-fslbNXP2VDpGpkYb2afFRFJdD8A=", + "dev": true, + "requires": { + "estree-walker": "0.3.1", + "micromatch": "2.3.11" + }, + "dependencies": { + "estree-walker": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz", + "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=", + "dev": true + } } } } }, + "rollup-plugin-node-resolve": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.0.0.tgz", + "integrity": "sha1-i4l8TDAw1QASd7BRSyXSygloPuA=", + "dev": true, + "requires": { + "browser-resolve": "1.11.2", + "builtin-modules": "1.1.1", + "is-module": "1.0.0", + "resolve": "1.5.0" + } + }, + "rollup-plugin-uglify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-uglify/-/rollup-plugin-uglify-2.0.1.tgz", + "integrity": "sha1-Z7N60e/a+9g69MNrQMGJ7khmyWk=", + "dev": true, + "requires": { + "uglify-js": "3.3.4" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "uglify-js": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.4.tgz", + "integrity": "sha512-hfIwuAQI5dlXP30UtdmWoYF9k+ypVqBXIdmd6ZKBiaNHHvA8ty7ZloMe3+7S5AEKVkxHbjByl4DfRHQ7QpZquw==", + "dev": true, + "requires": { + "commander": "2.12.2", + "source-map": "0.6.1" + } + } + } + }, + "rollup-pluginutils": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz", + "integrity": "sha1-HhVud4+UtyVb+hs9AXi+j1xVJAg=", + "dev": true, + "requires": { + "estree-walker": "0.2.1", + "minimatch": "3.0.4" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "2.1.0" + } + }, "run-sequence": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-2.2.0.tgz", @@ -3841,6 +7336,21 @@ "gulp-util": "3.0.8" } }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "4.0.8" + } + }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", @@ -3857,75 +7367,6 @@ "lodash": "4.17.4", "scss-tokenizer": "0.2.3", "yargs": "7.1.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.3.3", - "path-is-absolute": "1.0.1" - } - }, - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - }, - "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "dev": true, - "requires": { - "camelcase": "3.0.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "os-locale": "1.4.0", - "read-pkg-up": "1.0.1", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "1.0.2", - "which-module": "1.0.0", - "y18n": "3.2.1", - "yargs-parser": "5.0.0" - } - } } }, "sax": { @@ -3940,7 +7381,7 @@ "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", "dev": true, "requires": { - "js-base64": "2.3.2", + "js-base64": "2.4.0", "source-map": "0.4.4" }, "dependencies": { @@ -3956,9 +7397,9 @@ } }, "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", "dev": true }, "sequencify": { @@ -3973,6 +7414,48 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "set-getter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", + "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", + "dev": true, + "requires": { + "to-object-path": "0.3.0" + } + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, "sigmund": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", @@ -3985,6 +7468,136 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + } + }, + "snapdragon": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", + "integrity": "sha1-4StUh/re0+PeoKyR6UAL91tAE3A=", + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.1", + "use": "2.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, "sntp": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", @@ -4000,6 +7613,34 @@ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, + "source-map-resolve": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", + "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", + "dev": true, + "requires": { + "atob": "2.0.3", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, "sparkles": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", @@ -4027,6 +7668,12 @@ "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", "dev": true }, + "specificity": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.3.2.tgz", + "integrity": "sha512-Nc/QN/A425Qog7j9aHmwOrlwX2e7pNI47ciwxwy4jOlvbbMHkNNJchit+FX+UjF3IAdiaaV5BKeWuDUnws6G1A==", + "dev": true + }, "split": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", @@ -4036,6 +7683,36 @@ "through": "2.3.8" } }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -4066,47 +7743,99 @@ } } }, - "stdout-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.0.tgz", - "integrity": "sha1-osfIWH5U2UJ+qe2zrD8s1SLfN4s=", + "state-toggle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.0.tgz", + "integrity": "sha1-0g+aYWu08MO5i5GSLSW2QKorxCU=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "readable-stream": "2.3.3" + "define-property": "0.2.5", + "object-copy": "0.1.0" }, "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } } }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true } } }, + "stdout-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.0.tgz", + "integrity": "sha1-osfIWH5U2UJ+qe2zrD8s1SLfN4s=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, "stream-combiner": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", @@ -4129,21 +7858,52 @@ "dev": true }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringify-entities": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.1.tgz", + "integrity": "sha1-sVDsLXKsTBtfMktR+2soyc3/BYw=", + "dev": true, + "requires": { + "character-entities-html4": "1.1.1", + "character-entities-legacy": "1.1.1", + "is-alphanumerical": "1.0.1", + "is-hexadecimal": "1.0.1" + } }, "stringstream": { "version": "0.0.5", @@ -4161,14 +7921,16 @@ } }, "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-bom-string": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true, - "requires": { - "first-chunk-stream": "1.0.0", - "is-utf8": "0.2.1" - } + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "dev": true }, "strip-indent": { "version": "1.0.1", @@ -4177,6 +7939,429 @@ "dev": true, "requires": { "get-stdin": "4.0.1" + }, + "dependencies": { + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + } + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=", + "dev": true + }, + "stylelint": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-8.4.0.tgz", + "integrity": "sha512-56hPH5mTFnk8LzlEuTWq0epa34fHuS54UFYQidBOFt563RJBNi1nz1F2HK2MoT1X1waq47milvRsRahFCCJs/Q==", + "dev": true, + "requires": { + "autoprefixer": "7.2.3", + "balanced-match": "1.0.0", + "chalk": "2.3.0", + "cosmiconfig": "3.1.0", + "debug": "3.1.0", + "execall": "1.0.0", + "file-entry-cache": "2.0.0", + "get-stdin": "5.0.1", + "globby": "7.1.1", + "globjoin": "0.1.4", + "html-tags": "2.0.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "known-css-properties": "0.5.0", + "lodash": "4.17.4", + "log-symbols": "2.1.0", + "mathml-tag-names": "2.0.1", + "meow": "4.0.0", + "micromatch": "2.3.11", + "normalize-selector": "0.2.0", + "pify": "3.0.0", + "postcss": "6.0.14", + "postcss-html": "0.12.0", + "postcss-less": "1.1.3", + "postcss-media-query-parser": "0.2.3", + "postcss-reporter": "5.0.0", + "postcss-resolve-nested-selector": "0.1.1", + "postcss-safe-parser": "3.0.1", + "postcss-sass": "0.2.0", + "postcss-scss": "1.0.2", + "postcss-selector-parser": "3.1.1", + "postcss-value-parser": "3.3.0", + "resolve-from": "4.0.0", + "specificity": "0.3.2", + "string-width": "2.1.1", + "style-search": "0.1.0", + "sugarss": "1.0.1", + "svg-tags": "1.0.0", + "table": "4.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "4.1.0", + "map-obj": "2.0.0", + "quick-lru": "1.1.0" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "glob": "7.1.2", + "ignore": "3.3.7", + "pify": "3.0.0", + "slash": "1.0.0" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "4.0.0", + "pify": "3.0.0", + "strip-bom": "3.0.0" + } + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "meow": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.0.tgz", + "integrity": "sha512-Me/kel335m6vMKmEmA6c87Z6DUFW3JqkINRnxkbC+A/PUm0D5Fl2dEBQrPKnqCL9Te/CIa1MUt/0InMJhuC/sw==", + "dev": true, + "requires": { + "camelcase-keys": "4.2.0", + "decamelize-keys": "1.1.0", + "loud-rejection": "1.6.0", + "minimist": "1.2.0", + "minimist-options": "3.0.2", + "normalize-package-data": "2.4.0", + "read-pkg-up": "3.0.0", + "redent": "2.0.0", + "trim-newlines": "2.0.0" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "1.3.1", + "json-parse-better-errors": "1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "3.0.0" + } + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "4.0.0", + "normalize-package-data": "2.4.0", + "path-type": "3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "3.0.0" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "3.2.0", + "strip-indent": "2.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + } + } + }, + "stylelint-config-prettier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-prettier/-/stylelint-config-prettier-2.0.0.tgz", + "integrity": "sha512-B5kiuzUOiZreh9nikOKJ9+AtH5iNpDLQbyN+oGcrflNA1M6BEgbDnI/qeCn50NoQieav/ajsmB6HU9YtIYx5SQ==", + "dev": true + }, + "stylelint-config-recommended": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-2.0.1.tgz", + "integrity": "sha512-FXdgdOEGpaFQoKGhsi8IbsCI6dkxHQPa1CCqIybkN1d8LKtdxrn/A1rgu8DpJ6J+/4L30FOJeVdPttGfxCDHBQ==", + "dev": true + }, + "stylelint-config-sass-guidelines": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/stylelint-config-sass-guidelines/-/stylelint-config-sass-guidelines-4.0.1.tgz", + "integrity": "sha512-IFaizPqp9Y2ZDVD7mCM/1KHRrwfdG53u9c2mQntmOS74CEtJA4Y4lzfIjwNLJnoakg73xEt3C+cF3QbE5N9Biw==", + "dev": true + }, + "stylelint-config-standard": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-18.0.0.tgz", + "integrity": "sha1-DYcrQPr9zdz0GI+1tk3bOIforvw=", + "dev": true, + "requires": { + "stylelint-config-recommended": "2.0.1" + } + }, + "stylelint-order": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-0.8.0.tgz", + "integrity": "sha512-XwJO7rIAt/hnBJjOsDgEwNSeqw+5jE22da4pVKaePbojM9bGwhOoAWV7Q2BL8caOg81IlTesmYCEf8s0+2Cc5g==", + "dev": true, + "requires": { + "lodash": "4.17.4", + "postcss": "6.0.14", + "postcss-sorting": "3.1.0" + } + }, + "stylelint-scss": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-2.2.0.tgz", + "integrity": "sha512-O3jIpujSDrMHlGoXT3AYsOz2DPb49Y+0rCPGU34BHrbMBWSciwkvtm4WFrYi/cDnbpkXFemC0lHwmtspK8IQEA==", + "dev": true, + "requires": { + "lodash": "4.17.4", + "postcss-media-query-parser": "0.2.3", + "postcss-resolve-nested-selector": "0.1.1", + "postcss-selector-parser": "3.1.1", + "postcss-value-parser": "3.3.0" + } + }, + "stylelint-selector-bem-pattern": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stylelint-selector-bem-pattern/-/stylelint-selector-bem-pattern-2.0.0.tgz", + "integrity": "sha512-J5NQeNcweS56US29oHHb7GAX8taG44lYn5cY9YEE3xA5ibeWmPBiCGLg6HskPlmVBO0hcJ4JUQ9A4Ngyu8avxQ==", + "dev": true, + "requires": { + "lodash": "4.17.4", + "postcss": "6.0.14", + "postcss-bem-linter": "3.1.0", + "stylelint": "8.4.0" + } + }, + "sugarss": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-1.0.1.tgz", + "integrity": "sha512-3qgLZytikQQEVn1/FrhY7B68gPUUGY3R1Q1vTiD5xT+Ti1DP/8iZuwFet9ONs5+bmL8pZoDQ6JrQHVgrNlK6mA==", + "dev": true, + "requires": { + "postcss": "6.0.14" } }, "supports-color": { @@ -4185,6 +8370,12 @@ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, + "svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", + "dev": true + }, "svgo": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", @@ -4198,6 +8389,69 @@ "mkdirp": "0.5.1", "sax": "1.2.4", "whet.extend": "0.9.9" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "js-yaml": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", + "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "2.7.3" + } + } + } + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "dev": true, + "requires": { + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.3.0", + "lodash": "4.17.4", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } } }, "tar": { @@ -4211,6 +8465,12 @@ "inherits": "2.0.3" } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "textextensions": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz", @@ -4231,38 +8491,6 @@ "requires": { "readable-stream": "2.3.3", "xtend": "4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } } }, "tildify": { @@ -4280,6 +8508,140 @@ "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", "dev": true }, + "timers-ext": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.2.tgz", + "integrity": "sha1-YcxHp2wavTGV8UUn+XjViulMUgQ=", + "dev": true, + "requires": { + "es5-ext": "0.10.37", + "next-tick": "1.0.0" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "to-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.1.tgz", + "integrity": "sha1-FTWL7kosg712N3uh3ASdDxiDeq4=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "regex-not": "1.0.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + } + }, "tough-cookie": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", @@ -4289,21 +8651,66 @@ "punycode": "1.4.1" } }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, "trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "trim-trailing-lines": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz", + "integrity": "sha1-eu+7eAjfnWafbaLkOMrIxGradoQ=", + "dev": true + }, + "trough": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.1.tgz", + "integrity": "sha1-qf2LA5Swro//guBjOgo2zK1bX4Y=", + "dev": true + }, + "true-case-path": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.2.tgz", + "integrity": "sha1-fskRMJJHZsf1c74wIMNPj9/QDWI=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "glob": "6.0.4" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + } } }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", @@ -4311,23 +8718,44 @@ "dev": true, "optional": true }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "prelude-ls": "1.1.2" } }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.17", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz", + "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==", + "dev": true + }, + "uglify-es": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.4.tgz", + "integrity": "sha512-vDOyDaf7LcABZI5oJt8bin5FD8kYONux5jd8FY6SsV2SfD+MMXaPeGUotysbycSxdu170y5IQ8FvlKzU/TUryw==", "dev": true, - "optional": true + "requires": { + "commander": "2.12.2", + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } }, "unc-path-regex": { "version": "0.1.2", @@ -4335,12 +8763,242 @@ "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", "dev": true }, + "unherit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.0.tgz", + "integrity": "sha1-a5qu379z3xdWrZ4xbdmBiFhAzX0=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "xtend": "4.0.1" + } + }, + "unified": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/unified/-/unified-6.1.6.tgz", + "integrity": "sha512-pW2f82bCIo2ifuIGYcV12fL96kMMYgw7JKVEgh7ODlrM9rj6vXSY3BV+H6lCcv1ksxynFf582hwWLnA1qRFy4w==", + "dev": true, + "requires": { + "bail": "1.0.2", + "extend": "3.0.1", + "is-plain-obj": "1.1.0", + "trough": "1.0.1", + "vfile": "2.3.0", + "x-is-function": "1.0.4", + "x-is-string": "0.1.0" + } + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, "unique-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", "dev": true }, + "unist-util-find-all-after": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unist-util-find-all-after/-/unist-util-find-all-after-1.0.1.tgz", + "integrity": "sha1-TlUSq/734GFnga7Pex7XUcAK+Qg=", + "dev": true, + "requires": { + "unist-util-is": "2.1.1" + } + }, + "unist-util-is": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.1.tgz", + "integrity": "sha1-DDEmKeP5YMZukx6BLT2A53AQlHs=", + "dev": true + }, + "unist-util-modify-children": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.1.tgz", + "integrity": "sha1-ZtfmpEnm9nIguXarPLi166w55R0=", + "dev": true, + "requires": { + "array-iterate": "1.1.1" + } + }, + "unist-util-remove-position": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz", + "integrity": "sha1-WoXBVV/BugwQG4ZwfRXlD6TIcbs=", + "dev": true, + "requires": { + "unist-util-visit": "1.3.0" + } + }, + "unist-util-stringify-position": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz", + "integrity": "sha1-PMvcU2ee7W7PN3fdf14yKcG2qjw=", + "dev": true + }, + "unist-util-visit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz", + "integrity": "sha512-9ntYcxPFtl44gnwXrQKZ5bMqXMY0ZHzUpqMFiU4zcc8mmf/jzYm8GhYgezuUlX4cJIM1zIDYaO6fG/fI+L6iiQ==", + "dev": true, + "requires": { + "unist-util-is": "2.1.1" + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/use/-/use-2.0.2.tgz", + "integrity": "sha1-riig1y+TvyJCKhii43mZMRLeyOg=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "isobject": "3.0.1", + "lazy-cache": "2.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "user-home": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", @@ -4397,13 +9055,48 @@ } } }, + "vfile": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", + "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "dev": true, + "requires": { + "is-buffer": "1.1.6", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "1.1.1", + "vfile-message": "1.0.0" + }, + "dependencies": { + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + } + } + }, + "vfile-location": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.2.tgz", + "integrity": "sha1-02dcWch3SY5JK0dW/2Xkrxp1IlU=", + "dev": true + }, + "vfile-message": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.0.tgz", + "integrity": "sha512-HPREhzTOB/sNDc9/Mxf8w0FmHnThg5CRSJdR9VRFkD2riqYWs+fuXlj5z8mIpv2LrD7uU41+oPWFOL4Mjlf+dw==", + "dev": true, + "requires": { + "unist-util-stringify-position": "1.1.1" + } + }, "vinyl": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", "dev": true, "requires": { - "clone": "1.0.2", + "clone": "1.0.3", "clone-stats": "0.0.1", "replace-ext": "0.0.1" } @@ -4430,6 +9123,21 @@ "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", "dev": true }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, "readable-stream": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", @@ -4442,6 +9150,22 @@ "string_decoder": "0.10.31" } }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" + } + }, "through2": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", @@ -4473,10 +9197,16 @@ "source-map": "0.5.7" } }, - "when": { - "version": "3.7.8", - "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", - "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", + "dev": true + }, + "whatwg-fetch": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz", + "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ=", "dev": true }, "whet.extend": { @@ -4507,18 +9237,34 @@ "dev": true, "requires": { "string-width": "1.0.2" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } } }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, "wrap-ansi": { @@ -4529,6 +9275,28 @@ "requires": { "string-width": "1.0.2", "strip-ansi": "3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } } }, "wrappy": { @@ -4537,6 +9305,27 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "x-is-function": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/x-is-function/-/x-is-function-1.0.4.tgz", + "integrity": "sha1-XSlNw9Joy90GJYDgxd93o5HR+h4=", + "dev": true + }, + "x-is-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", + "dev": true + }, "xml2js": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", @@ -4572,15 +9361,112 @@ "dev": true }, "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", "dev": true, "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", + "camelcase": "3.0.0", + "cliui": "3.2.0", "decamelize": "1.2.0", - "window-size": "0.1.0" + "get-caller-file": "1.0.2", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "5.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + } } }, "yargs-parser": { diff --git a/package.json b/package.json index 6a512bb4..1e0f1f5e 100644 --- a/package.json +++ b/package.json @@ -1,28 +1,51 @@ { "name": "plyr", - "version": "2.0.18", + "version": "3.0.0-alpha.1", "description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player", - "homepage": "http://plyr.io", - "main": "src/js/plyr.js", - "dependencies": {}, + "homepage": "https://plyr.io", + "main": "./dist", + "sass": "./src/sass/plyr.scss", + "style": "./dist/plyr.css", "devDependencies": { + "babel-core": "^6.26.0", + "babel-eslint": "^8.0.3", + "babel-plugin-external-helpers": "^6.22.0", + "babel-preset-env": "^1.6.1", + "del": "^3.0.0", + "eslint": "^4.13.1", + "eslint-config-airbnb": "^16.1.0", + "eslint-config-prettier": "^2.9.0", + "eslint-plugin-import": "^2.8.0", + "eslint-plugin-jsx-a11y": "^6.0.3", + "eslint-plugin-react": "^7.5.1", "gulp": "^3.9.1", "gulp-autoprefixer": "^4.0.0", + "gulp-better-rollup": "^2.0.0", "gulp-clean-css": "^3.9.0", "gulp-concat": "^2.6.1", - "gulp-less": "^3.3.2", "gulp-open": "^2.0.0", "gulp-rename": "^1.2.2", "gulp-replace": "^0.6.1", "gulp-s3": "^0.11.0", "gulp-sass": "^3.1.0", "gulp-size": "^2.1.0", + "gulp-sourcemaps": "^2.6.1", "gulp-svgmin": "^1.2.4", "gulp-svgstore": "^6.1.0", - "gulp-uglify": "^3.0.0", "gulp-util": "^3.0.8", + "rollup-plugin-babel": "^3.0.3", + "rollup-plugin-commonjs": "^8.2.6", + "rollup-plugin-node-resolve": "^3.0.0", + "rollup-plugin-uglify": "^2.0.1", "run-sequence": "^2.2.0", - "through2": "^2.0.3" + "stylelint": "^8.4.0", + "stylelint-config-prettier": "^2.0.0", + "stylelint-config-sass-guidelines": "^4.0.1", + "stylelint-config-standard": "^18.0.0", + "stylelint-order": "^0.8.0", + "stylelint-scss": "^2.2.0", + "stylelint-selector-bem-pattern": "^2.0.0", + "uglify-es": "^3.2.2" }, "keywords": [ "HTML5 Video", @@ -47,5 +70,6 @@ "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, - "author": "Sam Potts <sam@potts.es>" + "author": "Sam Potts <sam@potts.es>", + "dependencies": {} } diff --git a/plyr.code-workspace b/plyr.code-workspace new file mode 100644 index 00000000..c0b30608 --- /dev/null +++ b/plyr.code-workspace @@ -0,0 +1,31 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + // Exclude from the editor + "files.exclude": { + "**/node_modules": true + }, + // Exclude from search + "search.exclude": { + "dist/": true + }, + // Linting + "stylelint.enable": true, + "css.validate": false, + "scss.validate": false, + "javascript.validate.enable": false, + // Prettier + "prettier.eslintIntegration": true, + "prettier.stylelintIntegration": true, + // Formatting + "editor.tabSize": 4, + "editor.insertSpaces": true, + "editor.formatOnSave": true, + // Trim on save + "files.trimTrailingWhitespace": true + } +}
\ No newline at end of file @@ -1,149 +1,130 @@ +--- +Beware: This branch is currently in beta and not production-ready +--- + # Plyr -A simple, accessible and customizable HTML5, YouTube and Vimeo media player. -[Donate to support Plyr](#donate) +A simple, lightweight, accessible and customizable HTML5, YouTube and Vimeo media player that supports [_modern_](#browser-support) browsers. -[Checkout the demo](https://plyr.io) +[Checkout the demo](https://plyr.io) - [Donate to support Plyr](#donate) [](https://plyr.io) -## Why? -We wanted a lightweight, accessible and customizable media player that supports [*modern*](#browser-support) browsers. Sure, there are many other players out there but we wanted to keep things simple, using the right elements for the job. - ## Features -- **Accessible** - full support for VTT captions and screen readers -- **Lightweight** - under 10KB minified and gzipped -- **[Customisable](#html)** - make the player look how you want with the markup you want -- **Semantic** - uses the *right* elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no `<span>` or `<a href="#">` button hacks -- **Responsive** - works with any screen size -- **HTML Video & Audio** - support for both formats -- **[Embedded Video](#embeds)** - support for YouTube and Vimeo video playback -- **[Streaming](#streaming)** - support for hls.js, Shaka and dash.js streaming playback -- **[API](#api)** - toggle playback, volume, seeking, and more -- **[Events](#events)** - no messing around with Vimeo and YouTube APIs, all events are standardized across formats -- **[Fullscreen](#fullscreen)** - supports native fullscreen with fallback to "full window" modes -- **[Shortcuts](#shortcuts)** - supports keyboard shortcuts -- **i18n support** - support for internationalization of controls -- **No dependencies** - written in "vanilla" JavaScript, no jQuery required -- **SASS and LESS** - to include in your build processes + +* **Accessible** - full support for VTT captions and screen readers +* **Lightweight** - just 18KB minified and gzipped +* **[Customisable](#html)** - make the player look how you want with the markup you want +* **Semantic** - uses the _right_ elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no + `<span>` or `<a href="#">` button hacks +* **Responsive** - works with any screen size +* **HTML Video & Audio** - support for both formats +* **[Embedded Video](#embeds)** - support for YouTube and Vimeo video playback +* **[Streaming](#streaming)** - support for hls.js, Shaka and dash.js streaming playback +* **[API](#api)** - toggle playback, volume, seeking, and more through a standardized API +* **[Events](#events)** - no messing around with Vimeo and YouTube APIs, all events are standardized across formats +* **[Fullscreen](#fullscreen)** - supports native fullscreen with fallback to "full window" modes +* **[Shortcuts](#shortcuts)** - supports keyboard shortcuts +* **i18n support** - support for internationalization of controls +* **No dependencies** - written in "vanilla" ES6 JavaScript, no jQuery required +* **SASS** - to include in your build processes Oh and yes, it works with Bootstrap. ## Changelog -Check out the [changelog](changelog.md) to see what's new with Plyr. - -## Features currently being developed -- Playback speed selection -- Quality selection -- Caption language selection -- AirPlay -- Picture in Picture (MacOS Sierra + Safari) - -[more info](https://github.com/sampotts/plyr/issues?q=is%3Aissue+is%3Aopen+label%3A%22In+Development%22) -## Planned features -- Playlists -- Google cast -- Facebook video support -- Wistia video support -- YouTube and Vimeo audio support -- Audio captions -...and whatever else has been raised in [issues](https://github.com/sampotts/plyr/issues) - -If you have any cool ideas or features, please let me know by [creating an issue](https://github.com/sampotts/plyr/issues/new) or, of course, forking and sending a pull request. +Check out the [changelog](changelog.md) to see what's new with Plyr. ## CMS plugins ### [WordPress](https://wordpress.org/plugins/plyr/) + Created and maintained by Ryan Anthony Drake ([@iamryandrake](https://github.com/iamryandrake)) ### [Neos](https://packagist.org/packages/jonnitto/plyr) + Created and maintained by Jon Uhlmann ([@jonnitto](https://github.com/jonnitto)) ### [Kirby](https://github.com/dpschen/kirby-plyrtag) -Created and maintained by Dominik Pschenitschni ([@dpschen](https://github.com/dpschen)) -### [React](https://github.com/xDae/react-plyr) -Created and maintained by Jose Miguel Bejarano ([@xDae](https://github.com/xDae)) +Created and maintained by Dominik Pschenitschni ([@dpschen](https://github.com/dpschen)) ## Using package managers + You can grab the source using one of the following package managers. ### npm -``` -npm install plyr -``` -[https://www.npmjs.com/package/plyr](https://www.npmjs.com/package/plyr) -### Bower ``` -bower install plyr +npm install plyr ``` -[http://bower.io/search/?q=plyr](http://bower.io/search/?q=plyr) -More info on setting up dependencies can be found in the [Bower Docs](http://bower.io/docs/creating-packages/#maintaining-dependencies) - -### Ember -The awesome [@louisrudner](https://twitter.com/louisrudner) has created an ember component, available by running: -``` -ember addon:install ember-cli-plyr -``` -More info is on [npm](https://www.npmjs.com/package/ember-cli-plyr) and [GitHub](https://github.com/louisrudner/ember-cli-plyr) +[https://www.npmjs.com/package/plyr](https://www.npmjs.com/package/plyr) ## Quick setup + Here's a quick run through on getting up and running. There's also a [demo on Codepen](http://codepen.io/sampotts/pen/jARJYp). ### HTML -Plyr extends upon the standard HTML5 markup so that's all you need for those types. More info on advanced HTML markup can be found under [initialising](#initialising). + +Plyr extends upon the standard HTML5 markup so that's all you need for those types. More info on advanced HTML markup can be found under +[initialising](#initialising). #### HTML5 Video + ```html -<video poster="/path/to/poster.jpg" controls> - <source src="/path/to/video.mp4" type="video/mp4"> - <source src="/path/to/video.webm" type="video/webm"> - <!-- Captions are optional --> - <track kind="captions" label="English captions" src="/path/to/captions.vtt" srclang="en" default> +<video poster="/path/to/poster.jpg" id="player" playsinline controls> + <source src="/path/to/video.mp4" type="video/mp4"> + <source src="/path/to/video.webm" type="video/webm"> + + <!-- Captions are optional --> + <track kind="captions" label="English captions" src="/path/to/captions.vtt" srclang="en" default> </video> ``` #### HTML5 Audio + ```html -<audio controls> - <source src="/path/to/audio.mp3" type="audio/mp3"> - <source src="/path/to/audio.ogg" type="audio/ogg"> +<audio id="player" controls> + <source src="/path/to/audio.mp3" type="audio/mp3"> + <source src="/path/to/audio.ogg" type="audio/ogg"> </audio> ``` For YouTube and Vimeo, Plyr uses the standard YouTube API markup (an empty `<div>`): #### YouTube embed + ```html -<div data-type="youtube" data-video-id="bTqVqk7FSmY"></div> +<div id="player" data-plyr-provider="youtube" data-plyr-embed-id="bTqVqk7FSmY"></div> ``` -Note: `data-video-id` value can now be the ID or URL for the video. This attribute name will change in a future release to reflect this change. - #### Vimeo embed + ```html -<div data-type="vimeo" data-video-id="143418951"></div> +<div id="player" data-plyr-provider="vimeo" data-plyr-embed-id="143418951"></div> ``` -Note: `data-video-id` value can now be the ID or URL for the video. This attribute name will change in a future release to reflect this change. + +Note: In both cases, `data-plyr-embed-id` value can be the ID or URL for the media. ### JavaScript -Include the `plyr.js` script before the closing `</body>` tag and then call `plyr.setup()`. More info on `setup()` can be found under [initialising](#initialising). + +Include the `plyr.js` script before the closing `</body>` tag and then call `plyr.setup()`. More info on `setup()` can be found under +[initialising](#initialising). ```html <script src="path/to/plyr.js"></script> -<script>plyr.setup();</script> +<script>const player = new Plyr('#player');</script> ``` If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the JavaScript, you can use the following: ```html -<script src="https://cdn.plyr.io/2.0.18/plyr.js"></script> +<script src="https://cdn.plyr.io/2.0.13/plyr.js"></script> ``` ### CSS + Include the `plyr.css` stylsheet into your `<head>` ```html @@ -153,937 +134,544 @@ Include the `plyr.css` stylsheet into your `<head>` If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the default CSS, you can use the following: ```html -<link rel="stylesheet" href="https://cdn.plyr.io/2.0.18/plyr.css"> +<link rel="stylesheet" href="https://cdn.plyr.io/2.0.13/plyr.css"> ``` ### SVG Sprite -The SVG sprite is loaded automatically from our CDN (provided by [Fastly](https://www.fastly.com/)). To change this, see the [options](#options) below. For reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/2.0.18/plyr.svg`. + +The SVG sprite is loaded automatically from our CDN (provided by [Fastly](https://www.fastly.com/)). To change this, see the [options](#options) below. For +reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/2.0.13/plyr.svg`. ## Advanced -### LESS & SASS/SCSS -You can use `plyr.less` or `plyr.scss` file included in `/src` as part of your build and change variables to suit your design. The LESS and SASS require you to use the [autoprefixer](https://www.npmjs.com/package/gulp-autoprefixer) plugin (you should already) as all declerations use the W3C definitions - e.g. `appearance: none;` will be prefixed to `-webkit-appearance: none;` by autoprefixer. +### SASS + +You can use `bundle.scss` file included in `/src` as part of your build and change variables to suit your design. The SASS require you to +use the [autoprefixer](https://www.npmjs.com/package/gulp-autoprefixer) plugin (you be should already!) as all declarations use the W3C definitions. -The HTML markup uses the BEM methodology with `plyr` as the block, e.g. `.plyr__controls`. You can change the class hooks in the options to match any custom CSS you write. Check out the JavaScript source for more on this. +The HTML markup uses the BEM methodology with `plyr` as the block, e.g. `.plyr__controls`. You can change the class hooks in the options to match any custom CSS +you write. Check out the JavaScript source for more on this. ### SVG -The icons used in the Plyr controls are loaded in an SVG sprite. The sprite is automatically loaded from our CDN by default. If you already have an icon build system in place, you can include the source plyr icons (see `/src/sprite` for source icons). + +The icons used in the Plyr controls are loaded in an SVG sprite. The sprite is automatically loaded from our CDN by default. If you already have an icon build +system in place, you can include the source plyr icons (see `/src/sprite` for source icons). #### Using the `iconUrl` option -You can however specify your own `iconUrl` option and Plyr will determine if the url is absolute and requires loading by AJAX/CORS due to current browser limitations or if it's a relative path, just use the path directly. -If you're using the `<base>` tag on your site, you may need to use something like this: -[svgfixer.js](https://gist.github.com/leonderijke/c5cf7c5b2e424c0061d2) +You can however specify your own `iconUrl` option and Plyr will determine if the url is absolute and requires loading by AJAX/CORS due to current browser +limitations or if it's a relative path, just use the path directly. + +If you're using the `<base>` tag on your site, you may need to use something like this: [svgfixer.js](https://gist.github.com/leonderijke/c5cf7c5b2e424c0061d2) -More info on SVG sprites here: -[http://css-tricks.com/svg-sprites-use-better-icon-fonts/](http://css-tricks.com/svg-sprites-use-better-icon-fonts/) -and the AJAX technique here: -[http://css-tricks.com/ajaxing-svg-sprite/](http://css-tricks.com/ajaxing-svg-sprite/) +More info on SVG sprites here: [http://css-tricks.com/svg-sprites-use-better-icon-fonts/](http://css-tricks.com/svg-sprites-use-better-icon-fonts/) and the AJAX +technique here: [http://css-tricks.com/ajaxing-svg-sprite/](http://css-tricks.com/ajaxing-svg-sprite/) ### Cross Origin (CORS) -You'll notice the `crossorigin` attribute on the example `<video>` elements. This is because the TextTrack captions are loaded from another domain. If your TextTrack captions are also hosted on another domain, you will need to add this attribute and make sure your host has the correct headers setup. For more info on CORS checkout the MDN docs: + +You'll notice the `crossorigin` attribute on the example `<video>` elements. This is because the TextTrack captions are loaded from another domain. If your +TextTrack captions are also hosted on another domain, you will need to add this attribute and make sure your host has the correct headers setup. For more info +on CORS checkout the MDN docs: [https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) ### Captions -WebVTT captions are supported. To add a caption track, check the HTML example above and look for the `<track>` element. Be sure to [validate your caption files](https://quuz.org/webvtt/). + +WebVTT captions are supported. To add a caption track, check the HTML example above and look for the `<track>` element. Be sure to +[validate your caption files](https://quuz.org/webvtt/). ### JavaScript #### Initialising -By default, `setup()` will find all `<video>`, `<audio>` and `[data-type]` elements with the document and initialises on any found. Each target media element found will be wrapped in a `<div>` for styling and setup individually. You can specify a variety of arguments to `setup()` to use, including a different NodeList, HTMLElement, Array of HTMLElements or string selector as below: +You can specify a range of arguments for the constructor to use: + +* A CSS string selector that's compatible with [`querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector) +* A [HTMLElement](https://developer.mozilla.org/en/docs/Web/API/HTMLElement) +* A [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList) or Array of [HTMLElement](https://developer.mozilla.org/en/docs/Web/API/HTMLElement) - + the first element will be used +* A [jQuery](https://jquery.com) object - if multiple are passed, the first element will be used + +Here's some examples + +Passing a [string selector](https://developer.mozilla.org/en-US/docs/Web/API/NodeList): -Passing a [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList): ```javascript -plyr.setup(document.querySelectorAll('.js-player'), options); +const player = new Plyr('#player'); ``` Passing a [HTMLElement](https://developer.mozilla.org/en/docs/Web/API/HTMLElement): -```javascript -plyr.setup(document.querySelector('.js-player'), options); -``` -Passing an [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) of [HTMLElement](https://developer.mozilla.org/en/docs/Web/API/HTMLElement)s: ```javascript -plyr.setup([ - document.querySelector('.js-player-1'), - document.querySelector('.js-player-2') -], options); +const player = new Plyr(document.getElementById('player')); ``` -Passing a [string selector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll): +Passing a [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList): + ```javascript -plyr.setup('.js-player', options); +const player = new Plyr(document.querySelectorAll('.js-player')); ``` -The NodeList, HTMLElement or string selector can be the target `<video>`, `<audio>` or `[data-type]` (for embeds) element itself or a container element. +The NodeList, HTMLElement or string selector can be the target `<video>`, `<audio>` or `[data-plyr-provider]` (for embeds) element itself or a container +element. + +The second argument for the constructor is the [#options](options) object: -Passing just the options object: ```javascript -plyr.setup(options); +const player = new Plyr('#player', { + /* options */ +}); ``` -`setup()` will return an array of *instances* that can be used with the [API](#api) methods. See the [API](#api) section for more info. - -#### RangeTouch -Some touch browsers (particularly Mobile Safari on iOS) seem to have issues with `<input type="range">` elements whereby touching the track to set the value doesn't work and sliding the thumb can be tricky. To combat this, I've created [RangeTouch](https://rangetouch.com) which I'd recommend including in your solution. It's a tiny script with a nice benefit for users on touch devices. +The constructor will return a Plyr object that can be used with the [API](#api) methods. See the [API](#api) section for more info. #### Options -Options must be passed as an object to the `setup()` method as above or as JSON in `data-plyr` attribute on each of your target elements: + +Options can be passed as an object to the constructor as above or as JSON in `data-plyr-config` attribute on each of your target elements: ```html -<video data-plyr='{ "title": "testing", "volume": 10 }'></video> +<video src="/path/to/video.mp4" id="player" controls data-plyr-config='{ "title": "This is an example video", "volume": 1, "debug": true }'></video> ``` -Note the single quotes encapsulating the JSON and double quotes on the object keys. - -<table class="table" width="100%"> - <thead> - <tr> - <th width="20%">Option</th> - <th width="15%">Type</th> - <th width="15%">Default</th> - <th width="50%">Description</th> - </tr> - </thead> - <tbody> - <tr> - <td><code>enabled</code></td> - <td>Boolean</td> - <td><code>true</code></td> - <td>Completely disable Plyr. This would allow you to do a User Agent check or similar to programmatically enable or disable Plyr for a certain UA. Example below.</td> - </tr> - <tr> - <td><code>html</code></td> - <td>String</td> - <td><code><a href="controls.md">See controls.md</a></code></td> - <td>See <a href="controls.md">controls.md</a> for more info on how the html needs to be structured.</td> - </tr> - <tr> - <td><code>controls</code></td> - <td>Array</td> - <td><code>['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'fullscreen']</code></td> - <td>Toggle which control elements you would like to display when using the default controls html. If you specify a <code>html</code> option, this is redundant. The default value is to display everything.</td> - </tr> - <tr> - <td><code>i18n</code></td> - <td>Object</td> - <td><code><a href="controls.md">See controls.md</a></code></td> - <td>Used for internationalization (i18n) of the tooltips/labels within the buttons.</td> - </tr> - <tr> - <td><code>loadSprite</code></td> - <td>Boolean</td> - <td><code>true</code></td> - <td>Load the SVG sprite specified as the <code>iconUrl</code> option (if a URL). If <code>false</code>, it is assumed you are handling sprite loading yourself.</td> - </tr> - <tr> - <td><code>iconUrl</code></td> - <td>String</td> - <td><code>null</code></td> - <td>Specify a URL or path to the SVG sprite. See the <a href="#svg">SVG section</a> for more info.</td> - </tr> - <tr> - <td><code>iconPrefix</code></td> - <td>String</td> - <td><code>plyr</code></td> - <td>Specify the id prefix for the icons used in the default controls (e.g. "plyr-play" would be "plyr"). This is to prevent clashes if you're using your own SVG sprite but with the default controls. Most people can ignore this option.</td> - </tr> - <tr> - <td><code>blankUrl</code></td> - <td>String</td> - <td><code>https://cdn.selz.com/plyr/blank.mp4</code></td> - <td>Specify a URL or path to a blank video file used to properly cancel network requests. See <a href="https://github.com/sampotts/plyr/issues/174">issue #174</a> for more info.</td> - </tr> - <tr> - <td><code>debug</code></td> - <td>Boolean</td> - <td><code>false</code></td> - <td>Display debugging information on what Plyr is doing.</td> - </tr> - <tr> - <td><code>autoplay</code></td> - <td>Boolean</td> - <td><code>false</code></td> - <td>Autoplay the media on load. This is generally advised against on UX grounds. It is also disabled on iOS (an Apple limitation).</td> - </tr> - <tr> - <td><code>seekTime</code></td> - <td>Number</td> - <td><code>10</code></td> - <td>The time, in seconds, to seek when a user hits fast forward or rewind.</td> - </tr> - <tr> - <td><code>volume</code></td> - <td>Number</td> - <td><code>5</code></td> - <td>A number, between 1 and 10, representing the initial volume of the player.</td> - </tr> - <tr> - <td><code>clickToPlay</code></td> - <td>Boolean</td> - <td><code>true</code></td> - <td>Click (or tap) of the video container will toggle pause/play.</td> - </tr> - <tr> - <td><code>disableContextMenu</code></td> - <td>Boolean</td> - <td><code>true</code></td> - <td>Disable right click menu on video to <em>help</em> as very primitive obfuscation to prevent downloads of content.</td> - </tr> - <tr> - <td><code>hideControls</code></td> - <td>Boolean</td> - <td><code>true</code></td> - <td>Hide video controls automatically after 2s of no mouse or focus movement, on control element blur (tab out), on playback start or entering fullscreen. As soon as the mouse is moved, a control element is focused or playback is paused, the controls reappear instantly.</td> - </tr> - <tr> - <td><code>showPosterOnEnd</code></td> - <td>Boolean</td> - <td><code>false</code></td> - <td>This will restore and *reload* HTML5 video once playback is complete. Note: depending on the browser caching, this may result in the video downloading again (or parts of it). Use with caution.</td> - </tr> - <tr> - <td><code>keyboardShortcuts</code></td> - <td>Object</td> - <td><code>{ focused: true, global: false }</code></td> - <td>Enable <a href="#shortcuts">keyboard shortcuts</a> for focused players only or globally as well (this will only work if there's one player in the document)</td> - </tr> - <tr> - <td><code>tooltips</code></td> - <td>Object</td> - <td><code>{ controls: false, seek: true }</code></td> - <td> - <strong>controls</strong>: Display control labels as tooltips on :hover & :focus (by default, the labels are screen reader only). - <br><br> - <strong>seek</strong>: Display a seek tooltip to indicate on click where the media would seek to. - </td> - </tr> - <tr> - <td><code>duration</code></td> - <td>Number</td> - <td><code>null</code></td> - <td>Specify a custom duration.</td> - </tr> - <tr> - <td><code>displayDuration</code></td> - <td>Boolean</td> - <td><code>true</code></td> - <td>Displays the duration of the media on the "metadataloaded" event (on startup) in the current time display. This will only work if the `preload` attribute is not set to `none` (or is not set at all) and you choose not to display the duration (see <code>controls</code> option).</td> - </tr> - <tr> - <td><code>selectors</code></td> - <td>Object</td> - <td>—</td> - <td>See <code>plyr.js</code> in <code>/src</code> for more info. You probably don't need to change any of these.</td> - </tr> - <tr> - <td><code>listeners</code></td> - <td>Object</td> - <td>—</td> - <td>Allows early binding of event listeners to the controls. See <code>controls</code> above for list of controls and see <code>plyr.js</code> in <code>/src</code> for more info.</td> - </tr> - <tr> - <td><code>classes</code></td> - <td>Object</td> - <td>—</td> - <td>Similar to above, these are the classes added to the player when state changes occur.</td> - </tr> - <tr> - <td><code>captions</code></td> - <td>Object</td> - <td>—</td> - <td>One property <code>defaultActive</code> which toggles if captions should be on by default. The default value is <code>false</code>.</td> - </tr> - <tr> - <td><code>fullscreen</code></td> - <td>Object</td> - <td>—</td> - <td>See <a href="#fullscreen-options">below</a></td> - </tr> - <tr> - <td><code>storage</code></td> - <td>Object</td> - <td>—</td> - <td>Two properties; <code>enabled</code> which toggles if local storage should be enabled (if the browser supports it). The default value is `true`. This enables storing user settings, currently it only stores volume but more will be added later. The second property <code>key</code> is the key used for the local storage. The default is <code>plyr_volume</code> until more settings are stored.</td> - </tr> - </tbody> -</table> - -#### Fullscreen options - -<table class="table" width="100%" id="fullscreen-options"> - <thead> - <tr> - <th width="20%">Option</th> - <th width="15%">Type</th> - <th width="15%">Default</th> - <th width="50%">Description</th> - </tr> - </thead> - <tbody> - <tr> - <td><code>enabled</code></td> - <td>Boolean</td> - <td><code>true</code></td> - <td>Toggles if fullscreen should be enabled (if the browser supports it).</td> - </tr> - <tr> - <td><code>fallback</code></td> - <td>Boolean</td> - <td><code>true</code></td> - <td>Enable a full viewport view for older browsers.</td> - </tr> - <tr> - <td><code>allowAudio</code></td> - <td>Boolean</td> - <td><code>false</code></td> - <td>Allow audio play to toggle fullscreen. This will be more useful later when posters are supported.</td> - </tr> - </tbody> -</table> +Note the single quotes encapsulating the JSON and double quotes on the object keys. Only string values need double quotes. + +| Option | Type | Default | Description | +| -------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `enabled` | Boolean | `true` | Completely disable Plyr. This would allow you to do a User Agent check or similar to programmatically enable or disable Plyr for a certain UA. Example below. | +| `debug` | Boolean | `false` | Display debugging information in the console | +| `controls` | Function or Array | `['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen']` | If a function is passed, it is assumed your method will return a string of HTML for the controls. Three arguments will be passed to your function; id (the unique id for the player), seektime (the seektime step in seconds), and title (the media title). See [controls.md](controls.md) for more info on how the html needs to be structured. | +| `settings` | Array | `['captions', 'quality', 'speed', 'loop']` | If you're using the default controls are used then you can specify which settings to show in the menu | +| `i18n` | Object | See [defaults.js](/src/js/defaults.js) | Used for internationalization (i18n) of the text within the UI. | +| `loadSprite` | Boolean | `true` | Load the SVG sprite specified as the `iconUrl` option (if a URL). If `false`, it is assumed you are handling sprite loading yourself. | +| `iconUrl` | String | `null` | Specify a URL or path to the SVG sprite. See the [SVG section](#svg) for more info. | +| `iconPrefix` | String | `plyr` | Specify the id prefix for the icons used in the default controls (e.g. "plyr-play" would be "plyr"). This is to prevent clashes if you're using your own SVG sprite but with the default controls. Most people can ignore this option. | +| `blankUrl` | String | `https://cdn.plyr.io/static/blank.mp4` | Specify a URL or path to a blank video file used to properly cancel network requests. | +| `autoplay` | Boolean | `false` | Autoplay the media on load. This is generally advised against on UX grounds. It is also disabled by default in some browsers. If the `autoplay` attribute is present on a `<video>` or `<audio>` element, this will be automatically set to true. | +| `autopause`¹ | Boolean | `true` | Only allow one player playing at once. | +| `seekTime` | Number | `10` | The time, in seconds, to seek when a user hits fast forward or rewind. | +| `volume` | Number | `1` | A number, between 0 and 1, representing the initial volume of the player. | +| `muted` | Boolean | `false` | Whether to start playback muted. If the `muted` attribute is present on a `<video>` or `<audio>` element, this will be automatically set to true. | +| `clickToPlay` | Boolean | `true` | Click (or tap) of the video container will toggle play/pause. | +| `disableContextMenu` | Boolean | `true` | Disable right click menu on video to <em>help</em> as very primitive obfuscation to prevent downloads of content. | +| `hideControls` | Boolean | `true` | Hide video controls automatically after 2s of no mouse or focus movement, on control element blur (tab out), on playback start or entering fullscreen. As soon as the mouse is moved, a control element is focused or playback is paused, the controls reappear instantly. | +| `showPosterOnEnd` | Boolean | false | This will restore and _reload_ HTML5 video once playback is complete. Note: depending on the browser caching, this may result in the video downloading again (or parts of it). Use with caution. | +| `keyboard` | Object | `{ focused: true, global: false }` | Enable [keyboard shortcuts](#shortcuts) for focused players only or globally | +| `tooltips` | Object | `{ controls: false, seek: true }` | `controls`: Display control labels as tooltips on `:hover` & `:focus` (by default, the labels are screen reader only). `seek`: Display a seek tooltip to indicate on click where the media would seek to. | +| `duration` | Number | `null` | Specify a custom duration for media. | +| `displayDuration` | Boolean | `true` | Displays the duration of the media on the "metadataloaded" event (on startup) in the current time display. This will only work if the `preload` attribute is not set to `none` (or is not set at all) and you choose not to display the duration (see `controls` option). | +| `invertTime` | Boolean | `true` | Display the current time as a countdown rather than an incremental counter. | +| `toggleInvert` | Boolean | `true` | Allow users to click to toggle the above. | +| `listeners` | Object | `null` | Allows binding of event listeners to the controls before the default handlers. See the `defaults.js` for available listeners. If your handler prevents default on the event (`event.preventDefault()`), the default handler will not fire. | +| `captions` | Object | `{ active: false, language: window.navigator.language.split('-')[0] }` | `active`: Toggles if captions should be active by default. `language`: Sets the default language to load (if available). | +| `fullscreen` | Object | `{ enabled: true, fallback: true }` | `enabled`: Toggles whether fullscreen should be enabled. `fallback`: Allow fallback to a full-window solution. | +| `ratio` | String | `16:9` | The aspect ratio you want to use for embedded players. | +| `storage` | Object | `{ enabled: true, key: 'plyr' }` | `enabled`: Allow use of local storage to store user settings. `key`: The key name to use. | +| `speed` | Object | `{ selected: 1, options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] }` | `selected`: The default speed for playback. `options`: Options to display in the menu. Most browsers will refuse to play slower than 0.5. | +| `quality` | Object | `{ default: 'default', options: ['hd2160', 'hd1440', 'hd1080', 'hd720', 'large', 'medium', 'small', 'tiny', 'default'] }` | Currently only supported by YouTube. `default` is the default quality level, determined by YouTube. `options` are the options to display. | +| `loop` | Object | `{ active: false }` | `active`: Whether to loop the current video. If the `loop` attribute is present on a `<video>` or `<audio>` element, this will be automatically set to true This is an object to support future functionality. | + +1. Vimeo only ## API -### Instance +There are methods, setters and getters on a Plyr object. + +### Object -The easiest way to access the plyr instances is to store the return value from your call to `setup()`: +The easiest way to access the Plyr object is to set the return value from your call to the constructor to a variable. For example: ```javascript -var players = plyr.setup('.js-player'); +const player = new Plyr('#player', { + /* options */ +}); ``` -This will return an array of all instances that were setup. Another way is to use `plyr.get()` to get all instances within a given container, for example: +You can also access the object through any events: ```javascript -var players = plyr.get('.js-player'); +element.addEventListener('ready', event => { + const player = event.detail.plyr; +}); ``` -If no argument is passed, it will find all instances in the current document. This will return an array of all instances that were found in the given selector. +### Methods -A final option is to access the instance through the event handlers: +Methods are not chainable. An example use of a method: ```javascript -instance.on('ready', function(event) { - var instance = event.detail.plyr; -}); +player.play(); ``` -### Methods +| Method | Parameters | Description | +| ------------------------- | ---------------- | ---------------------------------------------------------------------------------------------------------- | +| `play()`¹ | - | Start playback. | +| `pause()` | - | Pause playback. | +| `togglePlay(toggle)` | Boolean | Toggle playback, if no parameters are passed, it will toggle based on current status. | +| `stop()` | - | Stop playback and reset to start. | +| `restart()` | - | Restart playback. | +| `rewind(seekTime)` | Number | Rewind playback by the specified seek time. If no parameter is passed, the default seek time will be used. | +| `forward(seekTime)` | Number | Fast forward by the specified seek time. If no parameter is passed, the default seek time will be used. | +| `increaseVolume(step)` | Number | Increase volume by the specified step. If no parameter is passed, the default step will be used. | +| `decreaseVolume(step)` | Number | Increase volume by the specified step. If no parameter is passed, the default step will be used. | +| `toggleCaptions(toggle)` | Boolean | Toggle captions display. If no parameter is passed, it will toggle based on current status. | +| `toggleFullscreen(event)` | Event | Toggle fullscreen. Fullscreen can only be initiated by a user event. Exit is possible without user input. | +| `airplay()` | - | Trigger the airplay dialog on supported devices. | +| `toggleControls(toggle)` | Boolean | Toggle the controls based on the specified boolean. | +| `on(event, function)` | String, Function | Add an event listener for the specified event. | +| `off(event, function)` | String, Function | Remove an event listener for the specified event. | +| `supports(type)` | String | Check support for a mime type. | +| `destroy()` | - | Destroy the instance and garbage collect any elements. | + +1. For HTML5 players, `play()` will return a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) in _some_ browsers - WebKit and Mozilla [according to MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play) at time of writing. + +### Getters and Setters + +An example setter: -Once you have your instances, you can use the API methods below on it. For example to pause the first player: +```javascript +player.volume = 0.5; +``` + +An example getter: ```javascript -players[0].pause(); +player.volume; // returns 0.5; ``` -Here's a list of the methods supported: - -<table class="table" width="100%"> -<thead> - <tr> - <th width="20%">Method</th> - <th width="15%">Parameters</th> - <th width="65%">Description</th> - </tr> -</thead> -<tbody> - <tr> - <td><code>getContainer()</code></td> - <td>—</td> - <td>Get the players outer container element that is automatically injected.</td> - </tr> - <tr> - <td><code>getMedia()</code></td> - <td>—</td> - <td>Get the media element (<code>>video<</code>, <code>>audio<</code> or <code>>div<</code> for YouTube or Vimeo).</td> - </tr> - <tr> - <td><code>getEmbed()</code></td> - <td>—</td> - <td>Get the [embed](#embed) API to access those methods - either YouTube or Vimeo.</td> - </tr> - <tr> - <td><code>getType()</code></td> - <td>—</td> - <td>Get the type - 'video', 'audio', 'youtube' or 'vimeo'.</td> - </tr> - <tr> - <td><code>isReady()</code></td> - <td>—</td> - <td>Determine if the player is loaded and UI ready.</td> - </tr> - <tr> - <td><code>on()</code></td> - <td>String, Function</td> - <td>Watch for an event (first argument) and run a callback function (second argument). This saves you doing your own <code>addEventListner</code> code. This is chainable.</td> - </tr> - <tr> - <td><code>play()</code></td> - <td>—</td> - <td>Plays the media</td> - </tr> - <tr> - <td><code>pause()</code></td> - <td>—</td> - <td>Pauses the media</td> - </tr> - <tr> - <td><code>stop()</code></td> - <td>—</td> - <td>Stops the media</td> - </tr> - <tr> - <td><code>restart()</code></td> - <td>—</td> - <td>Restarts playback</td> - </tr> - <tr> - <td><code>rewind(...)</code></td> - <td>Number</td> - <td>Rewinds by the provided parameter, in seconds. If no parameter is provided, the default seekInterval is used (10 seconds).</td> - </tr> - <tr> - <td><code>forward(...)</code></td> - <td>Number</td> - <td>Fast forwards by the provided parameter, in seconds. If no parameter is provided, the default seekInterval is used (10 seconds).</td> - </tr> - <tr> - <td><code>seek(...)</code></td> - <td>Number</td> - <td>Seeks the media to the provided parameter, time in seconds.</td> - </tr> - <tr> - <td><code>getCurrentTime()</code></td> - <td>—</td> - <td>Will return a float with the current time in seconds.</td> - </tr> - <tr> - <td><code>getDuration()</code></td> - <td>—</td> - <td>Will return a float with the duration in seconds.</td> - </tr> - <tr> - <td><code>getVolume()</code></td> - <td>—</td> - <td>Will return a float between 0 and 1 for the current volume level.</td> - </tr> - <tr> - <td><code>isMuted()</code></td> - <td>—</td> - <td>Will return a boolean for whether the media is currently muted.</td> - </tr> - <tr> - <td><code>setVolume(...)</code></td> - <td>Number</td> - <td>Sets the player volume to the provided parameter. The value should be between 0 (muted) and 10 (loudest). If no parameter is provided, the default volume is used (5). Values over 10 are ignored.</td> - </tr> - <tr> - <td><code>togglePlay()</code></td> - <td>Boolean</td> - <td>Toggles playback for the player based on either the boolean argument or it's current state.</td> - </tr> - <tr> - <td><code>isPaused()</code></td> - <td>—</td> - <td>Will return a boolean for whether the media is currently paused.</td> - </tr> - <tr> - <td><code>toggleMute()</code></td> - <td>—</td> - <td>Toggles mute for the player.</td> - </tr> - <tr> - <td><code>toggleCaptions()</code></td> - <td>—</td> - <td>Toggles whether captions are enabled.</td> - </tr> - <tr> - <td><code>toggleFullscreen()</code></td> - <td>Event</td> - <td>Toggles fullscreen. This can only be initiated by a user gesture due to browser security, i.e. a user event such as click.</td> - </tr> - <tr> - <td><code>isFullscreen()</code></td> - <td>—</td> - <td>Boolean returned if the player is in fullscreen.</td> - </tr> - <tr> - <td><code>support(...)</code></td> - <td>String</td> - <td>Determine if a player supports a certain MIME type. This is not supported for embedded content (YouTube).</td> - </tr> - <tr> - <td><code>source(...)</code></td> - <td>Object or undefined</td> - <td> - Get/Set the media source. - <br><br> - <strong>Object</strong><br> - See <a href="#source-method">below</a> - <br><br> - <strong>YouTube</strong><br> - Currently this API method only accepts a YouTube ID when used with a YouTube player. I will add URL support soon, along with being able to swap between types (e.g. YouTube to Audio or Video and vice versa.) - <br><br> - <strong>undefined</strong><br> - Returns the current media source url. Works for both native videos and embeds. - </td> - </tr> - <tr> - <td><code>poster(...)</code></td> - <td>String</td> - <td>Set the poster url. This is supported for the <code>video</code> element only.</td> - </tr> - <tr> - <td><code>destroy()</code></td> - <td>—</td> - <td>Restores the original element, reversing the effects of <code>setup()</code>.</td> - </tr> - </tbody> -</table> - -#### .source() method -This allows changing the plyr source and type on the fly. +| Property | Getter | Setter | Description | +| --------------- | ------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `isHTML5` | ✔ | - | Returns a boolean indicating if the current player is HTML5. | +| `isEmbed` | ✔ | - | Returns a boolean indicating if the current player is an embedded player. | +| `paused` | ✔ | - | Returns a boolean indicating if the current player is paused. | +| `playing` | ✔ | - | Returns a boolean indicating if the current player is playing. | +| `ended` | ✔ | - | Returns a boolean indicating if the current player has finished playback. | +| `currentTime` | ✔ | ✔ | Gets or sets the currentTime for the player. The setter accepts a float in seconds. | +| `seeking` | ✔ | - | Returns a boolean indicating if the current player is seeking. | +| `duration` | ✔ | - | Returns the duration for the current media. | +| `volume` | ✔ | ✔ | Gets or sets the volume for the player. The setter accepts a float between 0 and 1. | +| `muted` | ✔ | ✔ | Gets or sets the muted state of the player. The setter accepts a boolean. | +| `hasAudio` | ✔ | - | Returns a boolean indicating if the current media has an audio track. | +| `speed` | ✔ | ✔ | Gets or sets the speed for the player. The setter accepts a value in the options specified in your config. Generally the minimum should be 0.5. | +| `quality`¹ | ✔ | ✔ | Gets or sets the quality for the player. The setter accepts a value from the options specified in your config. | +| `loop` | ✔ | ✔ | Gets or sets the current loop state of the player. The setter accepts a boolean. | +| `source` | ✔ | ✔ | Gets or sets the current source for the player. The setter accepts an object. See [source setter](#source-setter) below for examples. | +| `poster`² | ✔ | ✔ | Gets or sets the current poster image for the player. The setter accepts a string; the URL for the updated poster image. | +| `autoplay` | ✔ | ✔ | Gets or sets the autoplay state of the player. The setter accepts a boolean. | +| `language` | ✔ | ✔ | Gets or sets the preferred captions language for the player. The setter accepts an ISO two-letter language code. Support for the languages is dependent on the captions you include. | +| `pip` | ✔ | ✔ | Gets or sets the picture-in-picture state of the player. The setter accepts a boolean. This currently only supported on Safari 10+ on MacOS Sierra+ and iOS 10+. | + +1. YouTube only. HTML5 will follow. +2. HTML5 only + +#### The `.source` setter + +This allows changing the player source and type on the fly. Video example: ```javascript -player.source({ - type: 'video', - title: 'Example title', - sources: [{ - src: '/path/to/movie.mp4', - type: 'video/mp4' - }, - { - src: '/path/to/movie.webm', - type: 'video/webm' - }], - poster: '/path/to/poster.jpg', - tracks: [{ - kind: 'captions', - label: 'English', - srclang:'en', - src: '/path/to/captions.vtt', - default: true - }] -}); +player.source = { + type: 'video', + title: 'Example title', + sources: [ + { + src: '/path/to/movie.mp4', + type: 'video/mp4', + }, + { + src: '/path/to/movie.webm', + type: 'video/webm', + }, + ], + poster: '/path/to/poster.jpg', + tracks: [ + { + kind: 'captions', + label: 'English', + srclang: 'en', + src: '/path/to/captions.en.vtt', + default: true, + }, + { + kind: 'captions', + label: 'French', + srclang: 'fr', + src: '/path/to/captions.fr.vtt', + }, + ], +}; ``` Audio example: ```javascript -player.source({ - type: 'audio', - title: 'Example title', - sources: [{ - src: '/path/to/audio.mp3', - type: 'audio/mp3' - }, - { - src: '/path/to/audio.ogg', - type: 'audio/ogg' - }] -}); +player.source = { + type: 'audio', + title: 'Example title', + sources: [ + { + src: '/path/to/audio.mp3', + type: 'audio/mp3', + }, + { + src: '/path/to/audio.ogg', + type: 'audio/ogg', + }, + ], +}; ``` YouTube example: ```javascript -player.source({ - type: 'video', - title: 'Example title', - sources: [{ - src: 'bTqVqk7FSmY', - type: 'youtube' - }] -}); +player.source = { + type: 'video', + sources: [ + { + src: 'bTqVqk7FSmY', + provider: 'youtube', + }, + ], +}; ``` -Note: `src` can be the video ID or URL +_Note_: `src` can be the video ID or URL Vimeo example ```javascript -player.source({ - type: 'video', - title: 'Example title', - sources: [{ - src: '143418951', - type: 'vimeo' - }] -}); +player.source = { + type: 'video', + sources: [ + { + src: '143418951', + provider: 'vimeo', + }, + ], +}; ``` -Note: `src` can be the video ID or URL - -More details on the object parameters - -<table class="table" width="100%"> - <thead> - <tr> - <th width="20%">Key</th> - <th width="15%">Type</th> - <th width="65%">Description</th> - </tr> - </thead> - <tbody> - <tr> - <td><code>type</code></td> - <td>String</td> - <td>Options are <code>video</code>, <code>audio</code>, <code>youtube</code> and <code>vimeo</code></td> - </tr> - <tr> - <td><code>title</code></td> - <td>String</td> - <td>Title of the new media. Used for the `aria-label` attribute on the play button, and outer container.</td> - </tr> - <tr> - <td><code>sources</code></td> - <td>Array</td> - <td>This is an array of sources. <code>type</code> is optional for YouTube and Vimeo when specifying an array. For YouTube and Vimeo media, the video ID or URL must be passed as the source as shown above. The keys of this object are mapped directly to HTML attributes so more can be added to the object if required.</td> - </tr> - <tr> - <td><code>poster</code></td> - <td>String</td> - <td>URL for the poster image (video only).</td> - </tr> - <tr> - <td><code>tracks</code></td> - <td>Array</td> - <td>An array of track objects. Each element in the array is mapped directly to a track element and any keys mapped directly to HTML attributes so as in the example above, it will render as `<track kind="captions" label="English" srclang="en" src="https://cdn.selz.com/plyr/1.0/example_captions_en.vtt" default>`. Booleans are converted to HTML5 value-less attributes.</td> - </tr> - </tbody> -</table> +_Note:_ `src` property for YouTube and Vimeo can either be the video ID or the whole URL. + +| Property | Type | Description | +| -------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `type` | String | Either `video` or `audio`. _Note:_ YouTube and Vimeo are currently not supported as audio sources. | +| `title` | String | _Optional._ Title of the new media. Used for the `aria-label` attribute on the play button, and outer container. YouTube and Vimeo are populated automatically. | +| `sources` | Array | This is an array of sources. For HTML5 media, the properties of this object are mapped directly to HTML attributes so more can be added to the object if required. | +| `poster`¹ | String | The URL for the poster image (HTML5 video only). | +| `tracks`¹ | String | An array of track objects. Each element in the array is mapped directly to a track element and any keys mapped directly to HTML attributes so as in the example above, it will render as `<track kind="captions" label="English" srclang="en" src="https://cdn.selz.com/plyr/1.0/example_captions_en.vtt" default>` and similar for the French version. Booleans are converted to HTML5 value-less attributes. | + +1. HTML5 only ## Events -You can listen for events on the target element you setup Plyr on (see example under the table). Some events only apply to HTML5 audio and video. Using your reference to the instance, you can use the `on()` API method or `addEventListener()`. Access to the API can be obtained this way through the `event.detail.plyr` property. Here's an example: + +You can listen for events on the target element you setup Plyr on (see example under the table). Some events only apply to HTML5 audio and video. Using your +reference to the instance, you can use the `on()` API method or `addEventListener()`. Access to the API can be obtained this way through the `event.detail.plyr` +property. Here's an example: ```javascript -instance.on('ready', function(event) { - var instance = event.detail.plyr; +player.on('ready', event => { + const instance = event.detail.plyr; }); ``` -These events also bubble up the DOM. The event target will be the container element. - -<table class="table" width="100%"> - <thead> - <tr> - <th width="20%">Event name</th> - <th width="20%">HTML5 only</th> - <th width="60%">Description</th> - </tr> - </thead> - <tbody> - <tr> - <td><code>setup</code></td> - <td></td> - <td>When an initial setup has completed</td> - </tr> - <tr> - <td><code>ready</code></td> - <td></td> - <td>Triggered when the instance is ready for API use and external APIs are ready (in the case of YouTube and Vimeo).</td> - </tr> - <tr> - <td><code>canplay</code></td> - <td>✔</td> - <td>Sent when enough data is available that the media can be played, at least for a couple of frames. This corresponds to the <code>HAVE_ENOUGH_DATA</code> <code>readyState</code>.</td> - </tr> - <tr> - <td><code>canplaythrough</code></td> - <td></td> - <td>Sent when the ready state changes to <code>CAN_PLAY_THROUGH</code>, indicating that the entire media can be played without interruption, assuming the download rate remains at least at the current level. <strong>Note</strong>: Manually setting the <code>currentTime</code> will eventually fire a <code>canplaythrough</code> event in firefox. Other browsers might not fire this event.</td> - </tr> - <tr> - <td><code>emptied</code></td> - <td>✔</td> - <td>The media has become empty; for example, this event is sent if the media has already been loaded (or partially loaded), and the <code>load()</code> method is called to reload it.</td> - </tr> - <tr> - <td><code>ended</code></td> - <td></td> - <td>Sent when playback completes. Note: with Vimeo this does not occur if `loop` is enabled.</td> - </tr> - <tr> - <td><code>error</code></td> - <td>✔</td> - <td>Sent when an error occurs. The element's <code>error</code> attribute contains more information.</td> - </tr> - <tr> - <td><code>loadeddata</code></td> - <td>✔</td> - <td>The first frame of the media has finished loading.</td> - </tr> - <tr> - <td><code>loadedmetadata</code></td> - <td>✔</td> - <td>The media's metadata has finished loading; all attributes now contain as much useful information as they're going to.</td> - </tr> - <tr> - <td><code>loadstart</code></td> - <td>✔</td> - <td>Sent when loading of the media begins.</td> - </tr> - <tr> - <td><code>pause</code></td> - <td></td> - <td>Sent when playback is paused.</td> - </tr> - <tr> - <td><code>play</code></td> - <td></td> - <td>Sent when playback of the media starts after having been paused; that is, when playback is resumed after a prior <code>pause</code> event.</td> - </tr> - <tr> - <td><code>playing</code></td> - <td></td> - <td>Sent when the media begins to play (either for the first time, after having been paused, or after ending and then restarting).</td> - </tr> - <tr> - <td><code>progress</code></td> - <td></td> - <td>Sent periodically to inform interested parties of progress downloading the media. Information about the current amount of the media that has been downloaded is available in the media element's <code>buffered</code> attribute.</td> - </tr> - <tr> - <td><code>seeked</code></td> - <td></td> - <td>Sent when a seek operation completes.</td> - </tr> - <tr> - <td><code>seeking</code></td> - <td></td> - <td>Sent when a seek operation begins.</td> - </tr> - <tr> - <td><code>stalled</code></td> - <td>✔</td> - <td>Sent when the user agent is trying to fetch media data, but data is unexpectedly not forthcoming.</td> - </tr> - <tr> - <td><code>timeupdate</code></td> - <td></td> - <td>The time indicated by the element's <code>currentTime</code> attribute has changed.</td> - </tr> - <tr> - <td><code>volumechange</code></td> - <td></td> - <td>Sent when the audio volume changes (both when the volume is set and when the <code>muted</code> attribute is changed).</td> - </tr> - <tr> - <td><code>waiting</code></td> - <td>✔</td> - <td>Sent when the requested operation (such as playback) is delayed pending the completion of another operation (such as a seek).</td> - </tr> - <tr> - <td><code>enterfullscreen</code></td> - <td></td> - <td>User enters fullscreen (either the proper fullscreen or full-window fallback for older browsers)</td> - </tr> - <tr> - <td><code>exitfullscreen</code></td> - <td></td> - <td>User exits fullscreen</td> - </tr> - <tr> - <td><code>captionsenabled</code></td> - <td></td> - <td>Captions toggled on</td> - </tr> - <tr> - <td><code>captionsdisabled</code></td> - <td></td> - <td>Captions toggled off</td> - </tr> - <tr> - <td><code>destroyed</code></td> - <td></td> - <td>When an instance is destroyed. The original element that replaced the container will be returned to your handler as the event target.</td> - </tr> - </tbody> -</table> - -Details borrowed from: [https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events) +### Standard Media Events + +| Event Type | Description | +| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `progress` | Sent periodically to inform interested parties of progress downloading the media. Information about the current amount of the media that has been downloaded is available in the media element's `buffered` attribute. | +| `playing` | Sent when the media begins to play (either for the first time, after having been paused, or after ending and then restarting). | +| `play` | Sent when playback of the media starts after having been paused; that is, when playback is resumed after a prior `pause` event. | +| `pause` | Sent when playback is paused. | +| `timeupdate` | The time indicated by the element's `currentTime` attribute has changed. | +| `volumechange` | Sent when the audio volume changes (both when the volume is set and when the `muted` state is changed). | +| `seeking` | Sent when a seek operation begins. | +| `seeked` | Sent when a seek operation completes. | +| `ratechange` | Sent when the playback speed changes. | +| `ended` | Sent when playback completes. _Note:_ This does not fire if `autoplay` is true. | +| `enterfullscreen` | Sent when the player enters fullscreen mode (either the proper fullscreen or full-window fallback for older browsers). | +| `exitfullscreen` | Sent when the player exits fullscreen mode. | +| `captionsenabled` | Sent when captions are enabled. | +| `captionsdisabled` | Sent when captions are disabled. | +| `languagechange` | Sent when the caption language is changed. | +| `controlshidden` | Sent when the controls are hidden. | +| `controlsshown` | Sent when the controls are shown. | +| `ready` | Triggered when the instance is ready for API calls. | + +#### HTML5 only + +| Event Type | Description | +| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `loadstart` | Sent when loading of the media begins. | +| `loadeddata` | The first frame of the media has finished loading. | +| `loadedmetadata` | The media's metadata has finished loading; all attributes now contain as much useful information as they're going to. | +| `canplay` | Sent when enough data is available that the media can be played, at least for a couple of frames. This corresponds to the `HAVE_ENOUGH_DATA` `readyState`. | +| `canplaythrough` | Sent when the ready state changes to `CAN_PLAY_THROUGH`, indicating that the entire media can be played without interruption, assuming the download rate remains at least at the current level. _Note:_ Manually setting the `currentTime` will eventually fire a `canplaythrough` event in firefox. Other browsers might not fire this event. | +| `stalled` | Sent when the user agent is trying to fetch media data, but data is unexpectedly not forthcoming. | +| `waiting` | Sent when the requested operation (such as playback) is delayed pending the completion of another operation (such as a seek). | +| `emptied` | he media has become empty; for example, this event is sent if the media has already been loaded (or partially loaded), and the `load()` method is called to reload it. | +| `cuechange` | Sent when a `TextTrack` has changed the currently displaying cues. | +| `error` | Sent when an error occurs. The element's `error` attribute contains more information. | + +#### YouTube only + +| Event Type | Description | +| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `statechange` | The state of the player has changed. The code can be accessed via `event.detail.code`. Possible values are `-1`: Unstarted, `0`: Ended, `1`: Playing, `2`: Paused, `3`: Buffering, `5`: Video cued. See the [YouTube Docs](https://developers.google.com/youtube/iframe_api_reference#onStateChange) for more information. | +| `qualitychange` | The quality of playback has changed. | +| `qualityrequested` | A change to playback quality has been requested. _Note:_ A change to quality can only be _requested_ via the API. There is no guarantee the quality will change to the level requested. You should listen to the `qualitychange` event for true changes. | + +_Note:_ These events also bubble up the DOM. The event target will be the container element. + +Some event details borrowed from [MDN](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events). ## Embeds -YouTube and Vimeo are currently supported and function much like a HTML5 video. Check the relevant documentation sections for any differences. You don't need to worry about including your own versions of the Vimeo or YouTube JavaScript APIs. Plyr will automatically include them. -The embed third party API's can be accessed through the `getEmbed()` API method. +YouTube and Vimeo are currently supported and function much like a HTML5 video. Similar events and API methods are available for all types. However if you wish +to access the API's directly. You can do so via the `embed` property of your player object - e.g. `player.embed`. You can then use the relevant methods from the +third party APIs. More info on the respective API's here: -More info on the respective API's here: +* [YouTube iframe API Reference](https://developers.google.com/youtube/iframe_api_reference) +* [Vimeo player.js Reference](https://github.com/vimeo/player.js) -- [YouTube API Reference](https://developers.google.com/youtube/js_api_reference) -- [Vimeo API Reference](https://github.com/vimeo/player.js) - -*Please note*: not all API methods may work 100%. Your mileage may vary. It's better to use the universal plyr API where possible. +_Note_: Not all API methods may work 100%. Your mileage may vary. It's better to use the Plyr API where possible. ## Shortcuts -By default, a player will bind the following keyboard shortcuts when it has focus. If you have the `global` option to `true` and there's only one player in the document then the shortcuts will work when any element has focus, apart from an element that requires input. - -<table class="table" width="100%"> - <thead> - <tr> - <th width="25%">Key</th> - <th width="25%">Global</th> - <th width="50%">Action</th> - </tr> - </thead> - <tbody> - <tr> - <td><code>0</code> to <code>9</code></td> - <td>✔</td> - <td>Seek from 0 to 90% respectively</td> - </tr> - <tr> - <td><code>space</code></td> - <td></td> - <td>Toggle playback</td> - </tr> - <tr> - <td><code>K</code></td> - <td>✔</td> - <td>Toggle playback</td> - </tr> - <tr> - <td><code>←</code></td> - <td></td> - <td>Seek backward by the <code>seekTime</code> option</td> - </tr> - <tr> - <td><code>→</code></td> - <td></td> - <td>Seek forward by the <code>seekTime</code> option</td> - </tr> - <tr> - <td><code>↑</code></td> - <td></td> - <td>Increase volume</td> - </tr> - <tr> - <td><code>↓</code></td> - <td></td> - <td>Decrease volume</td> - </tr> - <tr> - <td><code>M</code></td> - <td>✔</td> - <td>Toggle mute</td> - </tr> - <tr> - <td><code>F</code></td> - <td>✔</td> - <td>Toggle fullscreen</td> - </tr> - <tr> - <td><code>C</code></td> - <td>✔</td> - <td>Toggle captions</td> - </tr> - </tbody> -</table> + +By default, a player will bind the following keyboard shortcuts when it has focus. If you have the `global` option to `true` and there's only one player in the +document then the shortcuts will work when any element has focus, apart from an element that requires input. + +| Key | Action | +| ---------- | -------------------------------------- | +| `0` to `9` | Seek from 0 to 90% respectively | +| `space` | Toggle playback | +| `K` | Toggle playback | +| ← | Seek backward by the `seekTime` option | +| → | Seek forward by the `seekTime` option | +| ↑ | Increase volume | +| ↓ | Decrease volume | +| `M` | Toggle mute | +| `F` | Toggle fullscreen | +| `C` | Toggle captions | +| `L` | Toggle loop | ## Streaming -Because Plyr is an extension of the standard HTML5 video and audio elements, third party streaming plugins can be used with Plyr. Massive thanks to Matias Russitto ([@russitto](https://github.com/russitto)) for working on this. Here's a few examples: -- Using [hls.js](https://github.com/dailymotion/hls.js) - [Demo](http://codepen.io/sampotts/pen/JKEMqB) -- Using [Shaka](https://github.com/google/shaka-player) - [Demo](http://codepen.io/sampotts/pen/zBNpVR) -- Using [dash.js](https://github.com/Dash-Industry-Forum/dash.js) - [Demo](http://codepen.io/sampotts/pen/BzpJXN) +Because Plyr is an extension of the standard HTML5 video and audio elements, third party streaming plugins can be used with Plyr. Massive thanks to Matias +Russitto ([@russitto](https://github.com/russitto)) for working on this. Here's a few examples: + +* Using [hls.js](https://github.com/dailymotion/hls.js) - [Demo](http://codepen.io/sampotts/pen/JKEMqB) +* Using [Shaka](https://github.com/google/shaka-player) - [Demo](http://codepen.io/sampotts/pen/zBNpVR) +* Using [dash.js](https://github.com/Dash-Industry-Forum/dash.js) - [Demo](http://codepen.io/sampotts/pen/BzpJXN) ## Fullscreen + Fullscreen in Plyr is supported by all browsers that [currently support it](http://caniuse.com/#feat=fullscreen). ## Browser support -<table width="100%" style="text-align: center"> - <thead> - <tr> - <td>Safari</td> - <td>Firefox</td> - <td>Chrome</td> - <td>Opera</td> - <td>IE9</td> - <td>IE10+</td> - </tr> - </thead> - <tbody> - <tr> - <td>✔¹</td> - <td>✔</td> - <td>✔</td> - <td>✔</td> - <td>API²</td> - <td>✔³</td> - </tr> - </tbody> -</table> - -¹ Mobile Safari on the iPhone forces the native player for `<video>` so no useful customization is possible. `<audio>` elements have volume controls disabled. - -² Native player used (no support for `<progress>` or `<input type="range">`) but the API is supported (v1.0.28+) - -³ IE10 has no native fullscreen support, fallback can be used (see [options](#options)) +Plyr supports the last 2 versions of most _modern_ browsers. IE11 is also supported. + +| Browser | Supported | +| ------------- | -------------- | +| Safari | ✔ | +| Mobile Safari | ✔¹ | +| Firefox | ✔ | +| Chrome | ✔ | +| Opera | ✔ | +| Edge | ✔ | +| IE10+ | ✔² | +| IE9 | API only³ | + +1. Mobile Safari on the iPhone forces the native player for `<video>` unless the `playsinline` attribute is present. Volume controls are also disabled. +2. Native player used (no support for `<progress>` or `<input type="range">`) but the API is supported (v1.0.28+) +3. IE10 has no native fullscreen support, fallback can be used (see [options](#options)) + +### Checking for support + +You can use the static method to check for support. For example + +```javascript +const supported = Plyr.supported('video', 'html5', true); +``` + +The arguments are: + +* Media type (`audio` or `video`) +* Provider (`html5`, `youtube` or `vimeo`) +* Whether the player has the `playsinline` attribute (only applicable to iOS 10+) + +### Disable support programatically The `enabled` option can be used to disable certain User Agents. For example, if you don't want to use Plyr for smartphones, you could use: ```javascript -enabled: !/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) +{ + enabled: /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent); +} ``` + If a User Agent is disabled but supports `<video>` and `<audio>` natively, it will use the native player. -Any unsupported browsers will display links to download the media if the correct html is used. +## RangeTouch -### Checking for support -There's an API method for checking support. You can call `plyr.supported()` and optionally pass a type to it, e.g. `plyr.supported("video")`. It will return an object with two keys; `basic` meaning there's basic support for that media type (or both if no type is passed) and `full` meaning there's full support for plyr. +Some touch browsers (particularly Mobile Safari on iOS) seem to have issues with `<input type="range">` elements whereby touching the track to set the value +doesn't work and sliding the thumb can be tricky. To combat this, I've created [RangeTouch](https://rangetouch.com) which I'd recommend including in your +solution. It's a tiny script with a nice benefit for users on touch devices. ## Issues + If you find anything weird with Plyr, please let us know using the GitHub issues tracker. ## Author -Plyr is developed by [@sam_potts](https://twitter.com/sam_potts) / [sampotts.me](http://sampotts.me) with help from the awesome [contributors](https://github.com/sampotts/plyr/graphs/contributors) + +Plyr is developed by [@sam_potts](https://twitter.com/sam_potts) / [sampotts.me](http://sampotts.me) with help from the awesome +[contributors](https://github.com/sampotts/plyr/graphs/contributors) ## Donate -Plyr costs money to run, not my time - I donate that for free but domains, hosting and more. Any help is appreciated... + +Plyr costs money to run, not only my time - I donate that for free but domains, hosting and more. Any help is appreciated... [Donate to support Plyr](https://www.paypal.me/pottsy/20usd) ## Mentions -- [ProductHunt](https://www.producthunt.com/tech/plyr) -- [The Changelog](http://thechangelog.com/plyr-simple-html5-media-player-custom-controls-webvtt-captions/) -- [HTML5 Weekly #177](http://html5weekly.com/issues/177) -- [Responsive Design #149](http://us4.campaign-archive2.com/?u=559bc631fe5294fc66f5f7f89&id=451a61490f) -- [Web Design Weekly #174](https://web-design-weekly.com/2015/02/24/web-design-weekly-174/) -- [Hacker News](https://news.ycombinator.com/item?id=9136774) -- [Web Platform Daily](http://webplatformdaily.org/releases/2015-03-04) -- [LayerVault Designer News](https://news.layervault.com/stories/45394-plyr--a-simple-html5-media-player) -- [The Treehouse Show #131](https://teamtreehouse.com/library/episode-131-origami-react-responsive-hero-images) -- [noupe.com](http://www.noupe.com/design/html5-plyr-is-a-responsive-and-accessible-video-player-94389.html) + +* [ProductHunt](https://www.producthunt.com/tech/plyr) +* [The Changelog](http://thechangelog.com/plyr-simple-html5-media-player-custom-controls-webvtt-captions/) +* [HTML5 Weekly #177](http://html5weekly.com/issues/177) +* [Responsive Design #149](http://us4.campaign-archive2.com/?u=559bc631fe5294fc66f5f7f89&id=451a61490f) +* [Web Design Weekly #174](https://web-design-weekly.com/2015/02/24/web-design-weekly-174/) +* [Hacker News](https://news.ycombinator.com/item?id=9136774) +* [Web Platform Daily](http://webplatformdaily.org/releases/2015-03-04) +* [LayerVault Designer News](https://news.layervault.com/stories/45394-plyr--a-simple-html5-media-player) +* [The Treehouse Show #131](https://teamtreehouse.com/library/episode-131-origami-react-responsive-hero-images) +* [noupe.com](http://www.noupe.com/design/html5-plyr-is-a-responsive-and-accessible-video-player-94389.html) ## Used by -- [Selz.com](https://selz.com) -- [Peugeot.fr](http://www.peugeot.fr/marque-et-technologie/technologies/peugeot-i-cockpit.html) -- [Peugeot.de](http://www.peugeot.de/modelle/modellberater/208-3-turer/fotos-videos.html) -- [TomTom.com](http://prioritydriving.tomtom.com/) -- [DIGBMX](http://digbmx.com/) -- [Grime Archive](https://grimearchive.com/) -- [koel - A personal music streaming server that works.](http://koel.phanan.net/) -- [Oscar Radio](http://oscar-radio.xyz/) + +* [Selz.com](https://selz.com) +* [Peugeot.fr](http://www.peugeot.fr/marque-et-technologie/technologies/peugeot-i-cockpit.html) +* [Peugeot.de](http://www.peugeot.de/modelle/modellberater/208-3-turer/fotos-videos.html) +* [TomTom.com](http://prioritydriving.tomtom.com/) +* [DIGBMX](http://digbmx.com/) +* [Grime Archive](https://grimearchive.com/) +* [koel - A personal music streaming server that works.](http://koel.phanan.net/) +* [Oscar Radio](http://oscar-radio.xyz/) +* [Sparkk TV](https://www.sparkktv.com/) Let me know on [Twitter](https://twitter.com/sam_potts) I can add you to the above list. It'd be awesome to see how you're using Plyr :-) ## Useful links and credits -Credit to the PayPal HTML5 Video player from which Plyr's caption functionality is ported from: -- [PayPal's Accessible HTML5 Video Player](https://github.com/paypal/accessible-html5-video-player) -- The icons used in Plyr are [Vicons](https://dribbble.com/shots/1663443-60-Vicons-Free-Icon-Set) plus some ones I made -- [An awesome guide for Plyr in Japanese!](http://syncer.jp/how-to-use-plyr-io) by [@arayutw](https://twitter.com/arayutw) -Also these links helped created Plyr: -- [Media Events - W3.org](http://www.w3.org/2010/05/video/mediaevents.html) -- [Styling the `<progress>` element - hongkiat.com](http://www.hongkiat.com/blog/html5-progress-bar/) +Credit to the PayPal HTML5 Video player from which Plyr's caption functionality was originally ported from: + +* [PayPal's Accessible HTML5 Video Player](https://github.com/paypal/accessible-html5-video-player) +* [An awesome guide for Plyr in Japanese!](http://syncer.jp/how-to-use-plyr-io) by [@arayutw](https://twitter.com/arayutw) ## Thanks + [](https://www.fastly.com/) -Thanks to [Fastly](https://www.fastly.com/) for providing the CDN services. +Massive thanks to [Fastly](https://www.fastly.com/) for providing the CDN services. ## Copyright and License -[The MIT license](license.md). + +[The MIT license](license.md) diff --git a/src/js/captions.js b/src/js/captions.js new file mode 100644 index 00000000..847ef7ff --- /dev/null +++ b/src/js/captions.js @@ -0,0 +1,199 @@ +// ========================================================================== +// Plyr Captions +// ========================================================================== + +import support from './support'; +import utils from './utils'; +import controls from './controls'; + +const captions = { + // Setup captions + setup() { + // Requires UI support + if (!this.supported.ui) { + return; + } + + // Set default language if not set + const stored = this.storage.get('language'); + + if (!utils.is.empty(stored)) { + this.captions.language = stored; + } + + if (utils.is.empty(this.captions.language)) { + this.captions.language = this.config.captions.language.toLowerCase(); + } + + // Set captions enabled state if not set + if (!utils.is.boolean(this.captions.active)) { + const active = this.storage.get('captions'); + + if (utils.is.boolean(active)) { + this.captions.active = active; + } else { + this.captions.active = this.config.captions.active; + } + } + + // Only Vimeo and HTML5 video supported at this point + if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) { + // Clear menu and hide + if (this.config.controls.includes('settings') && this.config.settings.includes('captions')) { + controls.setCaptionsMenu.call(this); + } + + return; + } + + // Inject the container + if (!utils.is.element(this.elements.captions)) { + this.elements.captions = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.captions)); + + utils.insertAfter(this.elements.captions, this.elements.wrapper); + } + + // Set the class hook + utils.toggleClass(this.elements.container, this.config.classNames.captions.enabled, !utils.is.empty(captions.getTracks.call(this))); + + // If no caption file exists, hide container for caption text + if (utils.is.empty(captions.getTracks.call(this))) { + return; + } + + // Set language + captions.setLanguage.call(this); + + // Enable UI + captions.show.call(this); + + // Set available languages in list + if (this.config.controls.includes('settings') && this.config.settings.includes('captions')) { + controls.setCaptionsMenu.call(this); + } + }, + + // Set the captions language + setLanguage() { + // Setup HTML5 track rendering + if (this.isHTML5 && this.isVideo) { + captions.getTracks.call(this).forEach(track => { + // Remove previous bindings + utils.on(track, 'cuechange', event => captions.setCue.call(this, event)); + + // Turn off native caption rendering to avoid double captions + // eslint-disable-next-line + track.mode = 'hidden'; + }); + + // Get current track + const currentTrack = captions.getCurrentTrack.call(this); + + // Check if suported kind + if (utils.is.track(currentTrack)) { + // If we change the active track while a cue is already displayed we need to update it + if (Array.from(currentTrack.activeCues || []).length) { + captions.setCue.call(this, currentTrack); + } + } + } else if (this.isVimeo && this.captions.active) { + this.embed.enableTextTrack(this.language); + } + }, + + // Get the tracks + getTracks() { + // Return empty array at least + if (utils.is.nullOrUndefined(this.media)) { + return []; + } + + // Only get accepted kinds + return Array.from(this.media.textTracks || []).filter(track => [ + 'captions', + 'subtitles', + ].includes(track.kind)); + }, + + // Get the current track for the current language + getCurrentTrack() { + return captions.getTracks.call(this).find(track => track.language.toLowerCase() === this.language); + }, + + // Display active caption if it contains text + setCue(input) { + // Get the track from the event if needed + const track = utils.is.event(input) ? input.target : input; + const active = track.activeCues[0]; + const currentTrack = captions.getCurrentTrack.call(this); + + // Only display current track + if (track !== currentTrack) { + return; + } + + // Display a cue, if there is one + if (utils.is.cue(active)) { + captions.setText.call(this, active.getCueAsHTML()); + } else { + captions.setText.call(this, null); + } + + utils.dispatchEvent.call(this, this.media, 'cuechange'); + }, + + // Set the current caption + setText(input) { + // Requires UI + if (!this.supported.ui) { + return; + } + + if (utils.is.element(this.elements.captions)) { + const content = utils.createElement('span'); + + // Empty the container + utils.emptyElement(this.elements.captions); + + // Default to empty + const caption = !utils.is.nullOrUndefined(input) ? input : ''; + + // Set the span content + if (utils.is.string(caption)) { + content.textContent = caption.trim(); + } else { + content.appendChild(caption); + } + + // Set new caption text + this.elements.captions.appendChild(content); + } else { + this.debug.warn('No captions element to render to'); + } + }, + + // Display captions container and button (for initialization) + show() { + // If there's no caption toggle, bail + if (!utils.is.element(this.elements.buttons.captions)) { + return; + } + + // Try to load the value from storage + let active = this.storage.get('captions'); + + // Otherwise fall back to the default config + if (!utils.is.boolean(active)) { + ({ active } = this.config.captions); + } else { + this.captions.active = active; + } + + if (active) { + utils.toggleClass(this.elements.container, this.config.classNames.captions.active, true); + utils.toggleState(this.elements.buttons.captions, true); + } + }, +}; + +export default captions; diff --git a/src/js/console.js b/src/js/console.js new file mode 100644 index 00000000..c5389970 --- /dev/null +++ b/src/js/console.js @@ -0,0 +1,28 @@ +// ========================================================================== +// Console wrapper +// ========================================================================== + +const noop = () => {}; + +export default class Console { + constructor(player) { + this.enabled = window.console && player.config.debug; + + if (this.enabled) { + this.log('Debugging enabled'); + } + } + + get log() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.log, console) : noop; + } + get warn() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop; + } + get error() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.error, console) : noop; + } +} diff --git a/src/js/controls.js b/src/js/controls.js new file mode 100644 index 00000000..22ca30ad --- /dev/null +++ b/src/js/controls.js @@ -0,0 +1,1249 @@ +// ========================================================================== +// Plyr controls +// ========================================================================== + +import support from './support'; +import utils from './utils'; +import ui from './ui'; +import captions from './captions'; + +// Sniff out the browser +const browser = utils.getBrowser(); + +const controls = { + // Webkit polyfill for lower fill range + updateRangeFill(target) { + // WebKit only + if (!browser.isWebkit) { + return; + } + + // Get range from event if event passed + const range = utils.is.event(target) ? target.target : target; + + // Needs to be a valid <input type='range'> + if (!utils.is.element(range) || range.getAttribute('type') !== 'range') { + return; + } + + // Inject the stylesheet if needed + if (!utils.is.element(this.elements.styleSheet)) { + this.elements.styleSheet = utils.createElement('style'); + this.elements.container.appendChild(this.elements.styleSheet); + } + + const styleSheet = this.elements.styleSheet.sheet; + const percentage = range.value / range.max * 100; + const selector = `#${range.id}::-webkit-slider-runnable-track`; + const styles = `{ background-image: linear-gradient(to right, currentColor ${percentage}%, transparent ${percentage}%) }`; + + // Find old rule if it exists + const index = Array.from(styleSheet.rules).findIndex(rule => rule.selectorText === selector); + + // Remove old rule + if (index !== -1) { + styleSheet.deleteRule(index); + } + + // Insert new one + styleSheet.insertRule([ + selector, + styles, + ].join(' ')); + }, + + // Get icon URL + getIconUrl() { + return { + url: this.config.iconUrl, + absolute: this.config.iconUrl.indexOf('http') === 0 || (browser.isIE && !window.svg4everybody), + }; + }, + + // Create <svg> icon + createIcon(type, attributes) { + const namespace = 'http://www.w3.org/2000/svg'; + const iconUrl = controls.getIconUrl.call(this); + const iconPath = `${!iconUrl.absolute ? iconUrl.url : ''}#${this.config.iconPrefix}`; + + // Create <svg> + const icon = document.createElementNS(namespace, 'svg'); + utils.setAttributes( + icon, + utils.extend(attributes, { + role: 'presentation', + }) + ); + + // Create the <use> to reference sprite + const use = document.createElementNS(namespace, 'use'); + const path = `${iconPath}-${type}`; + + // Set `href` attributes + // https://github.com/sampotts/plyr/issues/460 + // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href + if ('href' in use) { + use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path); + } else { + use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path); + } + + // Add <use> to <svg> + icon.appendChild(use); + + return icon; + }, + + // Create hidden text label + createLabel(type, attr) { + let text = this.config.i18n[type]; + const attributes = Object.assign({}, attr); + + switch (type) { + case 'pip': + text = 'PIP'; + break; + + case 'airplay': + text = 'AirPlay'; + break; + + default: + break; + } + + if ('class' in attributes) { + attributes.class += ` ${this.config.classNames.hidden}`; + } else { + attributes.class = this.config.classNames.hidden; + } + + return utils.createElement('span', attributes, text); + }, + + // Create a badge + createBadge(text) { + if (utils.is.empty(text)) { + return null; + } + + const badge = utils.createElement('span', { + class: this.config.classNames.menu.value, + }); + + badge.appendChild( + utils.createElement( + 'span', + { + class: this.config.classNames.menu.badge, + }, + text + ) + ); + + return badge; + }, + + // Create a <button> + createButton(buttonType, attr) { + const button = utils.createElement('button'); + const attributes = Object.assign({}, attr); + let type = buttonType; + + let toggle = false; + let label; + let icon; + let labelPressed; + let iconPressed; + + if (!('type' in attributes)) { + attributes.type = 'button'; + } + + if ('class' in attributes) { + if (attributes.class.includes(this.config.classNames.control)) { + attributes.class += ` ${this.config.classNames.control}`; + } + } else { + attributes.class = this.config.classNames.control; + } + + // Large play button + switch (type) { + case 'play': + toggle = true; + label = 'play'; + labelPressed = 'pause'; + icon = 'play'; + iconPressed = 'pause'; + break; + + case 'mute': + toggle = true; + label = 'mute'; + labelPressed = 'unmute'; + icon = 'volume'; + iconPressed = 'muted'; + break; + + case 'captions': + toggle = true; + label = 'enableCaptions'; + labelPressed = 'disableCaptions'; + icon = 'captions-off'; + iconPressed = 'captions-on'; + break; + + case 'fullscreen': + toggle = true; + label = 'enterFullscreen'; + labelPressed = 'exitFullscreen'; + icon = 'enter-fullscreen'; + iconPressed = 'exit-fullscreen'; + break; + + case 'play-large': + attributes.class += ` ${this.config.classNames.control}--overlaid`; + type = 'play'; + label = 'play'; + icon = 'play'; + break; + + default: + label = type; + icon = type; + } + + // Setup toggle icon and labels + if (toggle) { + // Icon + button.appendChild(controls.createIcon.call(this, iconPressed, { class: 'icon--pressed' })); + button.appendChild(controls.createIcon.call(this, icon, { class: 'icon--not-pressed' })); + + // Label/Tooltip + button.appendChild(controls.createLabel.call(this, labelPressed, { class: 'label--pressed' })); + button.appendChild(controls.createLabel.call(this, label, { class: 'label--not-pressed' })); + + // Add aria attributes + attributes['aria-pressed'] = false; + attributes['aria-label'] = this.config.i18n[label]; + } else { + button.appendChild(controls.createIcon.call(this, icon)); + button.appendChild(controls.createLabel.call(this, label)); + } + + // Merge attributes + utils.extend(attributes, utils.getAttributesFromSelector(this.config.selectors.buttons[type], attributes)); + + utils.setAttributes(button, attributes); + + this.elements.buttons[type] = button; + + return button; + }, + + // Create an <input type='range'> + createRange(type, attributes) { + // Seek label + const label = utils.createElement( + 'label', + { + for: attributes.id, + class: this.config.classNames.hidden, + }, + this.config.i18n[type] + ); + + // Seek input + const input = utils.createElement( + 'input', + utils.extend( + utils.getAttributesFromSelector(this.config.selectors.inputs[type]), + { + type: 'range', + min: 0, + max: 100, + step: 0.01, + value: 0, + autocomplete: 'off', + }, + attributes + ) + ); + + this.elements.inputs[type] = input; + + // Set the fill for webkit now + controls.updateRangeFill.call(this, input); + + return { + label, + input, + }; + }, + + // Create a <progress> + createProgress(type, attributes) { + const progress = utils.createElement( + 'progress', + utils.extend( + utils.getAttributesFromSelector(this.config.selectors.display[type]), + { + min: 0, + max: 100, + value: 0, + }, + attributes + ) + ); + + // Create the label inside + if (type !== 'volume') { + progress.appendChild(utils.createElement('span', null, '0')); + + let suffix = ''; + switch (type) { + case 'played': + suffix = this.config.i18n.played; + break; + + case 'buffer': + suffix = this.config.i18n.buffered; + break; + + default: + break; + } + + progress.textContent = `% ${suffix.toLowerCase()}`; + } + + this.elements.display[type] = progress; + + return progress; + }, + + // Create time display + createTime(type) { + const container = utils.createElement('div', { + class: 'plyr__time', + }); + + container.appendChild( + utils.createElement( + 'span', + { + class: this.config.classNames.hidden, + }, + this.config.i18n[type] + ) + ); + + container.appendChild(utils.createElement('span', utils.getAttributesFromSelector(this.config.selectors.display[type]), '00:00')); + + this.elements.display[type] = container; + + return container; + }, + + // Create a settings menu item + createMenuItem(value, list, type, title, badge = null, checked = false) { + const item = utils.createElement('li'); + + const label = utils.createElement('label', { + class: this.config.classNames.control, + }); + + const radio = utils.createElement( + 'input', + utils.extend(utils.getAttributesFromSelector(this.config.selectors.inputs[type]), { + type: 'radio', + name: `plyr-${type}`, + value, + checked, + class: 'plyr__sr-only', + }) + ); + + const faux = utils.createElement('span', { 'aria-hidden': true }); + + label.appendChild(radio); + label.appendChild(faux); + label.insertAdjacentHTML('beforeend', title); + + if (utils.is.element(badge)) { + label.appendChild(badge); + } + + item.appendChild(label); + list.appendChild(item); + }, + + // Update hover tooltip for seeking + updateSeekTooltip(event) { + // Bail if setting not true + if ( + !this.config.tooltips.seek || + !utils.is.element(this.elements.inputs.seek) || + !utils.is.element(this.elements.display.seekTooltip) || + this.duration === 0 + ) { + return; + } + + // Calculate percentage + let percent = 0; + const clientRect = this.elements.inputs.seek.getBoundingClientRect(); + const visible = `${this.config.classNames.tooltip}--visible`; + + // Determine percentage, if already visible + if (utils.is.event(event)) { + percent = 100 / clientRect.width * (event.pageX - clientRect.left); + } else if (utils.hasClass(this.elements.display.seekTooltip, visible)) { + percent = parseFloat(this.elements.display.seekTooltip.style.left, 10); + } else { + return; + } + + // Set bounds + if (percent < 0) { + percent = 0; + } else if (percent > 100) { + percent = 100; + } + + // Display the time a click would seek to + ui.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent); + + // Set position + this.elements.display.seekTooltip.style.left = `${percent}%`; + + // Show/hide the tooltip + // If the event is a moues in/out and percentage is inside bounds + if (utils.is.event(event) && [ + 'mouseenter', + 'mouseleave', + ].includes(event.type)) { + utils.toggleClass(this.elements.display.seekTooltip, visible, event.type === 'mouseenter'); + } + }, + + // Hide/show a tab + toggleTab(setting, toggle) { + const tab = this.elements.settings.tabs[setting]; + const pane = this.elements.settings.panes[setting]; + + utils.toggleHidden(tab, !toggle); + utils.toggleHidden(pane, !toggle); + }, + + // Set the YouTube quality menu + // TODO: Support for HTML5 + setQualityMenu(options) { + const type = 'quality'; + const list = this.elements.settings.panes.quality.querySelector('ul'); + + // Set options if passed and filter based on config + if (utils.is.array(options)) { + this.options.quality = options.filter(quality => this.config.quality.options.includes(quality)); + } else { + this.options.quality = this.config.quality.options; + } + + // Toggle the pane and tab + const toggle = !utils.is.empty(this.options.quality) && this.isYouTube; + controls.toggleTab.call(this, type, toggle); + + // If we're hiding, nothing more to do + if (!toggle) { + return; + } + + // Empty the menu + utils.emptyElement(list); + + // Get the badge HTML for HD, 4K etc + const getBadge = quality => { + let label = ''; + + switch (quality) { + case 'hd2160': + label = '4K'; + break; + + case 'hd1440': + label = 'WQHD'; + break; + + case 'hd1080': + label = 'HD'; + break; + + case 'hd720': + label = 'HD'; + break; + + default: + break; + } + + if (!label.length) { + return null; + } + + return controls.createBadge.call(this, label); + }; + + this.options.quality.forEach(quality => + controls.createMenuItem.call(this, quality, list, type, controls.getLabel.call(this, 'quality', quality), getBadge(quality)) + ); + + controls.updateSetting.call(this, type, list); + }, + + // Translate a value into a nice label + // TODO: Localisation + getLabel(setting, value) { + switch (setting) { + case 'speed': + return value === 1 ? 'Normal' : `${value}×`; + + case 'quality': + switch (value) { + case 'hd2160': + return '2160P'; + case 'hd1440': + return '1440P'; + case 'hd1080': + return '1080P'; + case 'hd720': + return '720P'; + case 'large': + return '480P'; + case 'medium': + return '360P'; + case 'small': + return '240P'; + case 'tiny': + return 'Tiny'; + case 'default': + return 'Auto'; + default: + return value; + } + + case 'captions': + return controls.getLanguage.call(this); + + default: + return null; + } + }, + + // Update the selected setting + updateSetting(setting, container) { + const pane = this.elements.settings.panes[setting]; + let value = null; + let list = container; + + switch (setting) { + case 'captions': + value = this.captions.active ? this.captions.language : ''; + break; + + default: + value = this[setting]; + + // Get default + if (utils.is.empty(value)) { + value = this.config[setting].default; + } + + // Unsupported value + if (!this.options[setting].includes(value)) { + this.debug.warn(`Unsupported value of '${value}' for ${setting}`); + return; + } + + // Disabled value + if (!this.config[setting].options.includes(value)) { + this.debug.warn(`Disabled value of '${value}' for ${setting}`); + return; + } + + break; + } + + // Get the list if we need to + if (!utils.is.element(list)) { + list = pane && pane.querySelector('ul'); + } + + // Update the label + if (!utils.is.empty(value)) { + const label = this.elements.settings.tabs[setting].querySelector(`.${this.config.classNames.menu.value}`); + label.innerHTML = controls.getLabel.call(this, setting, value); + } + + // Find the radio option + const target = list && list.querySelector(`input[value="${value}"]`); + + if (utils.is.element(target)) { + // Check it + target.checked = true; + } + }, + + // Set the looping options + /* setLoopMenu() { + const options = ['start', 'end', 'all', 'reset']; + const list = this.elements.settings.panes.loop.querySelector('ul'); + + // Show the pane and tab + utils.toggleHidden(this.elements.settings.tabs.loop, false); + utils.toggleHidden(this.elements.settings.panes.loop, false); + + // Toggle the pane and tab + const toggle = !utils.is.empty(this.loop.options); + controls.toggleTab.call(this, 'loop', toggle); + + // Empty the menu + utils.emptyElement(list); + + options.forEach(option => { + const item = utils.createElement('li'); + + const button = utils.createElement( + 'button', + utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.loop), { + type: 'button', + class: this.config.classNames.control, + 'data-plyr-loop-action': option, + }), + this.config.i18n[option] + ); + + if (['start', 'end'].includes(option)) { + const badge = controls.createBadge.call(this, '00:00'); + button.appendChild(badge); + } + + item.appendChild(button); + list.appendChild(item); + }); + }, */ + + // Get current selected caption language + // TODO: rework this to user the getter in the API? + getLanguage() { + if (!this.supported.ui) { + return null; + } + + if (!support.textTracks || !captions.getTracks.call(this).length) { + return this.config.i18n.none; + } + + if (this.captions.active) { + const currentTrack = captions.getCurrentTrack.call(this); + + if (utils.is.track(currentTrack)) { + return currentTrack.label; + } + } + + return this.config.i18n.disabled; + }, + + // Set a list of available captions languages + setCaptionsMenu() { + // TODO: Captions or language? Currently it's mixed + const type = 'captions'; + const list = this.elements.settings.panes.captions.querySelector('ul'); + + // Toggle the pane and tab + const hasTracks = captions.getTracks.call(this).length; + controls.toggleTab.call(this, type, hasTracks); + + // Empty the menu + utils.emptyElement(list); + + // If there's no captions, bail + if (!hasTracks) { + return; + } + + // Re-map the tracks into just the data we need + const tracks = captions.getTracks.call(this).map(track => ({ + language: track.language, + label: !utils.is.empty(track.label) ? track.label : track.language.toUpperCase(), + })); + + // Add the "None" option to turn off captions + tracks.unshift({ + language: '', + label: this.config.i18n.none, + }); + + // Generate options + tracks.forEach(track => { + controls.createMenuItem.call( + this, + track.language, + list, + 'language', + track.label || track.language, + controls.createBadge.call(this, track.language.toUpperCase()), + track.language.toLowerCase() === this.captions.language.toLowerCase() + ); + }); + + controls.updateSetting.call(this, type, list); + }, + + // Set a list of available captions languages + setSpeedMenu() { + const type = 'speed'; + + // Set the default speeds + if (!utils.is.object(this.options.speed) || !Object.keys(this.options.speed).length) { + this.options.speed = [ + 0.5, + 0.75, + 1, + 1.25, + 1.5, + 1.75, + 2, + ]; + } + + // Set options if passed and filter based on config + this.options.speed = this.options.speed.filter(speed => this.config.speed.options.includes(speed)); + + // Toggle the pane and tab + const toggle = !utils.is.empty(this.options.speed); + controls.toggleTab.call(this, type, toggle); + + // If we're hiding, nothing more to do + if (!toggle) { + return; + } + + // Get the list to populate + const list = this.elements.settings.panes.speed.querySelector('ul'); + + // Show the pane and tab + utils.toggleHidden(this.elements.settings.tabs.speed, false); + utils.toggleHidden(this.elements.settings.panes.speed, false); + + // Empty the menu + utils.emptyElement(list); + + // Create items + this.options.speed.forEach(speed => controls.createMenuItem.call(this, speed, list, type, controls.getLabel.call(this, 'speed', speed))); + + controls.updateSetting.call(this, type, list); + }, + + // Show/hide menu + toggleMenu(event) { + const { form } = this.elements.settings; + const button = this.elements.buttons.settings; + const show = utils.is.boolean(event) ? event : utils.is.element(form) && form.getAttribute('aria-hidden') === 'true'; + + if (utils.is.event(event)) { + const isMenuItem = utils.is.element(form) && form.contains(event.target); + const isButton = event.target === this.elements.buttons.settings; + + // If the click was inside the form or if the click + // wasn't the button or menu item and we're trying to + // show the menu (a doc click shouldn't show the menu) + if (isMenuItem || (!isMenuItem && !isButton && show)) { + return; + } + + // Prevent the toggle being caught by the doc listener + if (isButton) { + event.stopPropagation(); + } + } + + // Set form and button attributes + if (utils.is.element(button)) { + button.setAttribute('aria-expanded', show); + } + + if (utils.is.element(form)) { + form.setAttribute('aria-hidden', !show); + utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show); + + if (show) { + form.removeAttribute('tabindex'); + } else { + form.setAttribute('tabindex', -1); + } + } + }, + + // Get the natural size of a tab + getTabSize(tab) { + const clone = tab.cloneNode(true); + clone.style.position = 'absolute'; + clone.style.opacity = 0; + clone.setAttribute('aria-hidden', false); + + // Prevent input's being unchecked due to the name being identical + Array.from(clone.querySelectorAll('input[name]')).forEach(input => { + const name = input.getAttribute('name'); + input.setAttribute('name', `${name}-clone`); + }); + + // Append to parent so we get the "real" size + tab.parentNode.appendChild(clone); + + // Get the sizes before we remove + const width = clone.scrollWidth; + const height = clone.scrollHeight; + + // Remove from the DOM + utils.removeElement(clone); + + return { + width, + height, + }; + }, + + // Toggle Menu + showTab(event) { + const { menu } = this.elements.settings; + const tab = event.target; + const show = tab.getAttribute('aria-expanded') === 'false'; + const pane = document.getElementById(tab.getAttribute('aria-controls')); + + // Nothing to show, bail + if (!utils.is.element(pane)) { + return; + } + + // Are we targetting a tab? If not, bail + const isTab = pane.getAttribute('role') === 'tabpanel'; + if (!isTab) { + return; + } + + // Hide all other tabs + // Get other tabs + const current = menu.querySelector('[role="tabpanel"][aria-hidden="false"]'); + const container = current.parentNode; + + // Set other toggles to be expanded false + Array.from(menu.querySelectorAll(`[aria-controls="${current.getAttribute('id')}"]`)).forEach(toggle => { + toggle.setAttribute('aria-expanded', false); + }); + + // If we can do fancy animations, we'll animate the height/width + if (support.transitions && !support.reducedMotion) { + // Set the current width as a base + container.style.width = `${current.scrollWidth}px`; + container.style.height = `${current.scrollHeight}px`; + + // Get potential sizes + const size = controls.getTabSize.call(this, pane); + + // Restore auto height/width + const restore = e => { + // We're only bothered about height and width on the container + if (e.target !== container || ![ + 'width', + 'height', + ].includes(e.propertyName)) { + return; + } + + // Revert back to auto + container.style.width = ''; + container.style.height = ''; + + // Only listen once + utils.off(container, utils.transitionEnd, restore); + }; + + // Listen for the transition finishing and restore auto height/width + utils.on(container, utils.transitionEnd, restore); + + // Set dimensions to target + container.style.width = `${size.width}px`; + container.style.height = `${size.height}px`; + } + + // Set attributes on current tab + current.setAttribute('aria-hidden', true); + current.setAttribute('tabindex', -1); + + // Set attributes on target + pane.setAttribute('aria-hidden', !show); + tab.setAttribute('aria-expanded', show); + pane.removeAttribute('tabindex'); + + // Focus the first item + pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus(); + }, + + // Build the default HTML + // TODO: Set order based on order in the config.controls array? + create(data) { + // Do nothing if we want no controls + if (utils.is.empty(this.config.controls)) { + return null; + } + + // Create the container + const container = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.controls.wrapper)); + + // Restart button + if (this.config.controls.includes('restart')) { + container.appendChild(controls.createButton.call(this, 'restart')); + } + + // Rewind button + if (this.config.controls.includes('rewind')) { + container.appendChild(controls.createButton.call(this, 'rewind')); + } + + // Play/Pause button + if (this.config.controls.includes('play')) { + container.appendChild(controls.createButton.call(this, 'play')); + // container.appendChild(controls.createButton.call(this, 'pause')); + } + + // Fast forward button + if (this.config.controls.includes('fast-forward')) { + container.appendChild(controls.createButton.call(this, 'fast-forward')); + } + + // Progress + if (this.config.controls.includes('progress')) { + const progress = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.progress)); + + // Seek range slider + const seek = controls.createRange.call(this, 'seek', { + id: `plyr-seek-${data.id}`, + }); + progress.appendChild(seek.label); + progress.appendChild(seek.input); + + // Buffer progress + progress.appendChild(controls.createProgress.call(this, 'buffer')); + + // TODO: Add loop display indicator + + // Seek tooltip + if (this.config.tooltips.seek) { + const tooltip = utils.createElement( + 'span', + { + role: 'tooltip', + class: this.config.classNames.tooltip, + }, + '00:00' + ); + + progress.appendChild(tooltip); + this.elements.display.seekTooltip = tooltip; + } + + this.elements.progress = progress; + container.appendChild(this.elements.progress); + } + + // Media current time display + if (this.config.controls.includes('current-time')) { + container.appendChild(controls.createTime.call(this, 'currentTime')); + } + + // Media duration display + if (this.config.controls.includes('duration')) { + container.appendChild(controls.createTime.call(this, 'duration')); + } + + // Toggle mute button + if (this.config.controls.includes('mute')) { + container.appendChild(controls.createButton.call(this, 'mute')); + } + + // Volume range control + if (this.config.controls.includes('volume')) { + const volume = utils.createElement('div', { + class: 'plyr__volume', + }); + + // Set the attributes + const attributes = { + max: 1, + step: 0.05, + value: this.config.volume, + }; + + // Create the volume range slider + const range = controls.createRange.call( + this, + 'volume', + utils.extend(attributes, { + id: `plyr-volume-${data.id}`, + }) + ); + volume.appendChild(range.label); + volume.appendChild(range.input); + + this.elements.volume = volume; + + container.appendChild(volume); + } + + // Toggle captions button + if (this.config.controls.includes('captions')) { + container.appendChild(controls.createButton.call(this, 'captions')); + } + + // Settings button / menu + if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) { + const menu = utils.createElement('div', { + class: 'plyr__menu', + }); + + menu.appendChild( + controls.createButton.call(this, 'settings', { + id: `plyr-settings-toggle-${data.id}`, + 'aria-haspopup': true, + 'aria-controls': `plyr-settings-${data.id}`, + 'aria-expanded': false, + }) + ); + + const form = utils.createElement('form', { + class: 'plyr__menu__container', + id: `plyr-settings-${data.id}`, + 'aria-hidden': true, + 'aria-labelled-by': `plyr-settings-toggle-${data.id}`, + role: 'tablist', + tabindex: -1, + }); + + const inner = utils.createElement('div'); + + const home = utils.createElement('div', { + id: `plyr-settings-${data.id}-home`, + 'aria-hidden': false, + 'aria-labelled-by': `plyr-settings-toggle-${data.id}`, + role: 'tabpanel', + }); + + // Create the tab list + const tabs = utils.createElement('ul', { + role: 'tablist', + }); + + // Build the tabs + this.config.settings.forEach(type => { + const tab = utils.createElement('li', { + role: 'tab', + hidden: '', + }); + + const button = utils.createElement( + 'button', + utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.settings), { + type: 'button', + class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`, + id: `plyr-settings-${data.id}-${type}-tab`, + 'aria-haspopup': true, + 'aria-controls': `plyr-settings-${data.id}-${type}`, + 'aria-expanded': false, + }), + this.config.i18n[type] + ); + + const value = utils.createElement('span', { + class: this.config.classNames.menu.value, + }); + + // Speed contains HTML entities + value.innerHTML = data[type]; + + button.appendChild(value); + tab.appendChild(button); + tabs.appendChild(tab); + + this.elements.settings.tabs[type] = tab; + }); + + home.appendChild(tabs); + inner.appendChild(home); + + // Build the panes + this.config.settings.forEach(type => { + const pane = utils.createElement('div', { + id: `plyr-settings-${data.id}-${type}`, + 'aria-hidden': true, + 'aria-labelled-by': `plyr-settings-${data.id}-${type}-tab`, + role: 'tabpanel', + tabindex: -1, + hidden: '', + }); + + const back = utils.createElement( + 'button', + { + type: 'button', + class: `${this.config.classNames.control} ${this.config.classNames.control}--back`, + 'aria-haspopup': true, + 'aria-controls': `plyr-settings-${data.id}-home`, + 'aria-expanded': false, + }, + this.config.i18n[type] + ); + + pane.appendChild(back); + + const options = utils.createElement('ul'); + + pane.appendChild(options); + inner.appendChild(pane); + + this.elements.settings.panes[type] = pane; + }); + + form.appendChild(inner); + menu.appendChild(form); + container.appendChild(menu); + + this.elements.settings.form = form; + this.elements.settings.menu = menu; + } + + // Picture in picture button + if (this.config.controls.includes('pip') && support.pip) { + container.appendChild(controls.createButton.call(this, 'pip')); + } + + // Airplay button + if (this.config.controls.includes('airplay') && support.airplay) { + container.appendChild(controls.createButton.call(this, 'airplay')); + } + + // Toggle fullscreen button + if (this.config.controls.includes('fullscreen')) { + container.appendChild(controls.createButton.call(this, 'fullscreen')); + } + + // Larger overlaid play button + if (this.config.controls.includes('play-large')) { + this.elements.container.appendChild(controls.createButton.call(this, 'play-large')); + } + + this.elements.controls = container; + + if (this.config.controls.includes('settings') && this.config.settings.includes('speed')) { + controls.setSpeedMenu.call(this); + } + + return container; + }, + + // Insert controls + inject() { + // Sprite + if (this.config.loadSprite) { + const icon = controls.getIconUrl.call(this); + + // Only load external sprite using AJAX + if (icon.absolute) { + utils.loadSprite(icon.url, 'sprite-plyr'); + } + } + + // Create a unique ID + this.id = Math.floor(Math.random() * 10000); + + // Null by default + let container = null; + + // HTML passed as the option + if (utils.is.string(this.config.controls)) { + container = this.config.controls; + } else if (utils.is.function(this.config.controls)) { + // A custom function to build controls + // The function can return a HTMLElement or String + container = this.config.controls({ + id: this.id, + seektime: this.config.seekTime, + title: this.config.title, + }); + } else { + // Create controls + container = controls.create.call(this, { + id: this.id, + seektime: this.config.seekTime, + speed: this.speed, + quality: this.quality, + captions: controls.getLanguage.call(this), + // TODO: Looping + // loop: 'None', + }); + } + + // Controls container + let target; + + // Inject to custom location + if (utils.is.string(this.config.selectors.controls.container)) { + target = document.querySelector(this.config.selectors.controls.container); + } + + // Inject into the container by default + if (!utils.is.element(target)) { + target = this.elements.container; + } + + // Inject controls HTML + if (utils.is.element(container)) { + target.appendChild(container); + } else { + target.insertAdjacentHTML('beforeend', container); + } + + // Find the elements if need be + if (utils.is.element(this.elements.controls)) { + utils.findElements.call(this); + } + + // Edge sometimes doesn't finish the paint so force a redraw + if (window.navigator.userAgent.includes('Edge')) { + utils.repaint(target); + } + + // Setup tooltips + if (this.config.tooltips.controls) { + const labels = utils.getElements.call( + this, + [ + this.config.selectors.controls.wrapper, + ' ', + this.config.selectors.labels, + ' .', + this.config.classNames.hidden, + ].join('') + ); + + Array.from(labels).forEach(label => { + utils.toggleClass(label, this.config.classNames.hidden, false); + utils.toggleClass(label, this.config.classNames.tooltip, true); + label.setAttribute('role', 'tooltip'); + }); + } + }, +}; + +export default controls; diff --git a/src/js/defaults.js b/src/js/defaults.js new file mode 100644 index 00000000..15fadac7 --- /dev/null +++ b/src/js/defaults.js @@ -0,0 +1,347 @@ +// Default config +const defaults = { + // Disable + enabled: true, + + // Custom media title + title: '', + + // Logging to console + debug: false, + + // Auto play (if supported) + autoplay: false, + + // Only allow one media playing at once (vimeo only) + autopause: true, + + // Default time to skip when rewind/fast forward + seekTime: 10, + + // Default volume + volume: 1, + muted: false, + + // Pass a custom duration + duration: null, + + // Display the media duration on load in the current time position + // If you have opted to display both duration and currentTime, this is ignored + displayDuration: true, + + // Invert the current time to be a countdown + invertTime: true, + + // Clicking the currentTime inverts it's value to show time left rather than elapsed + toggleInvert: true, + + // Aspect ratio (for embeds) + ratio: '16:9', + + // Click video container to play/pause + clickToPlay: true, + + // Auto hide the controls + hideControls: true, + + // Revert to poster on finish (HTML5 - will cause reload) + showPosterOnEnd: false, + + // Disable the standard context menu + disableContextMenu: true, + + // Sprite (for icons) + loadSprite: true, + iconPrefix: 'plyr', + iconUrl: 'https://cdn.plyr.io/2.0.10/plyr.svg', + + // Blank video (used to prevent errors on source change) + blankVideo: 'https://cdn.plyr.io/static/blank.mp4', + + // Quality default + quality: { + default: 'default', + options: [ + 'hd2160', + 'hd1440', + 'hd1080', + 'hd720', + 'large', + 'medium', + 'small', + 'tiny', + 'default', + ], + }, + + // Set loops + loop: { + active: false, + // start: null, + // end: null, + }, + + // Speed default and options to display + speed: { + selected: 1, + options: [ + 0.5, + 0.75, + 1, + 1.25, + 1.5, + 1.75, + 2, + ], + }, + + // Keyboard shortcut settings + keyboard: { + focused: true, + global: false, + }, + + // Display tooltips + tooltips: { + controls: false, + seek: true, + }, + + // Captions settings + captions: { + active: false, + language: window.navigator.language.split('-')[0], + }, + + // Fullscreen settings + fullscreen: { + enabled: true, // Allow fullscreen? + fallback: true, // Fallback for vintage browsers + }, + + // Local storage + storage: { + enabled: true, + key: 'plyr', + }, + + // Default controls + controls: [ + 'play-large', + 'play', + 'progress', + 'current-time', + 'mute', + 'volume', + 'captions', + 'settings', + 'pip', + 'airplay', + 'fullscreen', + ], + settings: [ + 'captions', + 'quality', + 'speed', + ], + + // Localisation + i18n: { + restart: 'Restart', + rewind: 'Rewind {seektime} secs', + play: 'Play', + pause: 'Pause', + forward: 'Forward {seektime} secs', + seek: 'Seek', + played: 'Played', + buffered: 'Buffered', + currentTime: 'Current time', + duration: 'Duration', + volume: 'Volume', + mute: 'Mute', + unmute: 'Unmute', + enableCaptions: 'Enable captions', + disableCaptions: 'Disable captions', + enterFullscreen: 'Enter fullscreen', + exitFullscreen: 'Exit fullscreen', + frameTitle: 'Player for {title}', + captions: 'Captions', + settings: 'Settings', + speed: 'Speed', + quality: 'Quality', + loop: 'Loop', + start: 'Start', + end: 'End', + all: 'All', + reset: 'Reset', + none: 'None', + disabled: 'Disabled', + }, + + // URLs + urls: { + vimeo: { + api: 'https://player.vimeo.com/api/player.js', + }, + youtube: { + api: 'https://www.youtube.com/iframe_api', + }, + }, + + // Custom control listeners + listeners: { + seek: null, + play: null, + pause: null, + restart: null, + rewind: null, + forward: null, + mute: null, + volume: null, + captions: null, + fullscreen: null, + pip: null, + airplay: null, + speed: null, + quality: null, + loop: null, + language: null, + }, + + // Events to watch and bubble + events: [ + // Events to watch on HTML5 media elements and bubble + // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events + 'ended', + 'progress', + 'stalled', + 'playing', + 'waiting', + 'canplay', + 'canplaythrough', + 'loadstart', + 'loadeddata', + 'loadedmetadata', + 'timeupdate', + 'volumechange', + 'play', + 'pause', + 'error', + 'seeking', + 'seeked', + 'emptied', + 'ratechange', + 'cuechange', + + // Custom events + 'enterfullscreen', + 'exitfullscreen', + 'captionsenabled', + 'captionsdisabled', + 'languagechange', + 'controlshidden', + 'controlsshown', + 'ready', + + // YouTube + 'statechange', + 'qualitychange', + 'qualityrequested', + ], + + // Selectors + // Change these to match your template if using custom HTML + selectors: { + editable: 'input, textarea, select, [contenteditable]', + container: '.plyr', + controls: { + container: null, + wrapper: '.plyr__controls', + }, + labels: '[data-plyr]', + buttons: { + play: '[data-plyr="play"]', + pause: '[data-plyr="pause"]', + restart: '[data-plyr="restart"]', + rewind: '[data-plyr="rewind"]', + forward: '[data-plyr="fast-forward"]', + mute: '[data-plyr="mute"]', + captions: '[data-plyr="captions"]', + fullscreen: '[data-plyr="fullscreen"]', + pip: '[data-plyr="pip"]', + airplay: '[data-plyr="airplay"]', + settings: '[data-plyr="settings"]', + loop: '[data-plyr="loop"]', + }, + inputs: { + seek: '[data-plyr="seek"]', + volume: '[data-plyr="volume"]', + speed: '[data-plyr="speed"]', + language: '[data-plyr="language"]', + quality: '[data-plyr="quality"]', + }, + display: { + currentTime: '.plyr__time--current', + duration: '.plyr__time--duration', + buffer: '.plyr__progress--buffer', + played: '.plyr__progress--played', + loop: '.plyr__progress--loop', + volume: '.plyr__volume--display', + }, + progress: '.plyr__progress', + captions: '.plyr__captions', + menu: { + quality: '.js-plyr__menu__list--quality', + }, + }, + + // Class hooks added to the player in different states + classNames: { + video: 'plyr__video-wrapper', + embed: 'plyr__video-embed', + control: 'plyr__control', + type: 'plyr--{0}', + provider: 'plyr--{0}', + stopped: 'plyr--stopped', + playing: 'plyr--playing', + loading: 'plyr--loading', + error: 'plyr--has-error', + hover: 'plyr--hover', + tooltip: 'plyr__tooltip', + hidden: 'plyr__sr-only', + hideControls: 'plyr--hide-controls', + isIos: 'plyr--is-ios', + isTouch: 'plyr--is-touch', + uiSupported: 'plyr--full-ui', + noTransition: 'plyr--no-transition', + menu: { + value: 'plyr__menu__value', + badge: 'plyr__badge', + open: 'plyr--menu-open', + }, + captions: { + enabled: 'plyr--captions-enabled', + active: 'plyr--captions-active', + }, + fullscreen: { + enabled: 'plyr--fullscreen-enabled', + fallback: 'plyr--fullscreen-fallback', + }, + pip: { + supported: 'plyr--pip-supported', + active: 'plyr--pip-active', + }, + airplay: { + supported: 'plyr--airplay-supported', + active: 'plyr--airplay-active', + }, + tabFocus: 'plyr__tab-focus', + }, + + // API keys + keys: { + google: null, + }, +}; + +export default defaults; diff --git a/src/js/fullscreen.js b/src/js/fullscreen.js new file mode 100644 index 00000000..366ea729 --- /dev/null +++ b/src/js/fullscreen.js @@ -0,0 +1,127 @@ +// ========================================================================== +// Plyr fullscreen API +// ========================================================================== + +import utils from './utils'; + +// Determine the prefix +const prefix = (() => { + let value = false; + + if (utils.is.function(document.cancelFullScreen)) { + value = ''; + } else { + // Check for fullscreen support by vendor prefix + [ + 'webkit', + 'o', + 'moz', + 'ms', + 'khtml', + ].some(pre => { + if (utils.is.function(document[`${pre}CancelFullScreen`])) { + value = pre; + return true; + } else if (utils.is.function(document.msExitFullscreen) && document.msFullscreenEnabled) { + // Special case for MS (when isn't it?) + value = 'ms'; + return true; + } + + return false; + }); + } + + return value; +})(); + +// Fullscreen API +const fullscreen = { + // Get the prefix + prefix, + + // Check if we can use it + enabled: document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled, + + // Yet again Microsoft awesomeness, + // Sometimes the prefix is 'ms', sometimes 'MS' to keep you on your toes + eventType: prefix === 'ms' ? 'MSFullscreenChange' : `${prefix}fullscreenchange`, + + // Is an element fullscreen + isFullScreen(element) { + if (!fullscreen.enabled) { + return false; + } + + const target = utils.is.nullOrUndefined(element) ? document.body : element; + + switch (prefix) { + case '': + return document.fullscreenElement === target; + + case 'moz': + return document.mozFullScreenElement === target; + + default: + return document[`${prefix}FullscreenElement`] === target; + } + }, + + // Make an element fullscreen + requestFullScreen(element) { + if (!fullscreen.enabled) { + return false; + } + + const target = utils.is.nullOrUndefined(element) ? document.body : element; + + return !prefix.length ? target.requestFullScreen() : target[prefix + (prefix === 'ms' ? 'RequestFullscreen' : 'RequestFullScreen')](); + }, + + // Bail from fullscreen + cancelFullScreen() { + if (!fullscreen.enabled) { + return false; + } + + return !prefix.length ? document.cancelFullScreen() : document[prefix + (prefix === 'ms' ? 'ExitFullscreen' : 'CancelFullScreen')](); + }, + + // Get the current element + element() { + if (!fullscreen.enabled) { + return null; + } + + return !prefix.length ? document.fullscreenElement : document[`${prefix}FullscreenElement`]; + }, + + // Setup fullscreen + setup() { + if (!this.supported.ui || this.isAudio || !this.config.fullscreen.enabled) { + return; + } + + // Check for native support + const nativeSupport = fullscreen.enabled; + + if (nativeSupport || (this.config.fullscreen.fallback && !utils.inFrame())) { + this.debug.log(`${nativeSupport ? 'Native' : 'Fallback'} fullscreen enabled`); + + // Add styling hook to show button + utils.toggleClass(this.elements.container, this.config.classNames.fullscreen.enabled, true); + } else { + this.debug.log('Fullscreen not supported and fallback disabled'); + } + + // Toggle state + if (this.elements.buttons && this.elements.buttons.fullscreen) { + utils.toggleState(this.elements.buttons.fullscreen, false); + } + + // Trap focus in container + utils.trapFocus.call(this); + }, +}; + +export default fullscreen; diff --git a/src/js/listeners.js b/src/js/listeners.js new file mode 100644 index 00000000..b3ccc1c6 --- /dev/null +++ b/src/js/listeners.js @@ -0,0 +1,591 @@ +// ========================================================================== +// Plyr Event Listeners +// ========================================================================== + +import support from './support'; +import utils from './utils'; +import controls from './controls'; +import fullscreen from './fullscreen'; +import ui from './ui'; + +// Sniff out the browser +const browser = utils.getBrowser(); + +const listeners = { + // Global listeners + global() { + let last = null; + + // Get the key code for an event + const getKeyCode = event => (event.keyCode ? event.keyCode : event.which); + + // Handle key press + const handleKey = event => { + const code = getKeyCode(event); + const pressed = event.type === 'keydown'; + const repeat = pressed && code === last; + + // Bail if a modifier key is set + if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { + return; + } + + // If the event is bubbled from the media element + // Firefox doesn't get the keycode for whatever reason + if (!utils.is.number(code)) { + return; + } + + // Seek by the number keys + const seekByKey = () => { + // Divide the max duration into 10th's and times by the number value + this.currentTime = this.duration / 10 * (code - 48); + }; + + // Handle the key on keydown + // Reset on keyup + if (pressed) { + // Which keycodes should we prevent default + const preventDefault = [ + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 56, + 57, + 32, + 75, + 38, + 40, + 77, + 39, + 37, + 70, + 67, + 73, + 76, + 79, + ]; + + // Check focused element + // and if the focused element is not editable (e.g. text input) + // and any that accept key input http://webaim.org/techniques/keyboard/ + const focused = utils.getFocusElement(); + if (utils.is.element(focused) && utils.matches(focused, this.config.selectors.editable)) { + return; + } + + // If the code is found prevent default (e.g. prevent scrolling for arrows) + if (preventDefault.includes(code)) { + event.preventDefault(); + event.stopPropagation(); + } + + switch (code) { + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + // 0-9 + if (!repeat) { + seekByKey(); + } + break; + + case 32: + case 75: + // Space and K key + if (!repeat) { + this.togglePlay(); + } + break; + + case 38: + // Arrow up + this.increaseVolume(0.1); + break; + + case 40: + // Arrow down + this.decreaseVolume(0.1); + break; + + case 77: + // M key + if (!repeat) { + this.muted = !this.muted; + } + break; + + case 39: + // Arrow forward + this.forward(); + break; + + case 37: + // Arrow back + this.rewind(); + break; + + case 70: + // F key + this.toggleFullscreen(); + break; + + case 67: + // C key + if (!repeat) { + this.toggleCaptions(); + } + break; + + case 76: + // L key + this.loop = !this.loop; + break; + + /* case 73: + this.setLoop('start'); + break; + + case 76: + this.setLoop(); + break; + + case 79: + this.setLoop('end'); + break; */ + + default: + break; + } + + // Escape is handle natively when in full screen + // So we only need to worry about non native + if (!fullscreen.enabled && this.fullscreen.active && code === 27) { + this.toggleFullscreen(); + } + + // Store last code for next cycle + last = code; + } else { + last = null; + } + }; + + // Keyboard shortcuts + if (this.config.keyboard.global) { + utils.on(window, 'keydown keyup', handleKey, false); + } else if (this.config.keyboard.focused) { + utils.on(this.elements.container, 'keydown keyup', handleKey, false); + } + + // Detect tab focus + // Remove class on blur/focusout + utils.on(this.elements.container, 'focusout', event => { + utils.toggleClass(event.target, this.config.classNames.tabFocus, false); + }); + + // Add classname to tabbed elements + utils.on(this.elements.container, 'keydown', event => { + if (event.keyCode !== 9) { + return; + } + + // Delay the adding of classname until the focus has changed + // This event fires before the focusin event + window.setTimeout(() => { + utils.toggleClass(utils.getFocusElement(), this.config.classNames.tabFocus, true); + }, 0); + }); + + // Toggle controls visibility based on mouse movement + if (this.config.hideControls) { + // Toggle controls on mouse events and entering fullscreen + utils.on(this.elements.container, 'mouseenter mouseleave mousemove touchstart touchend touchmove enterfullscreen exitfullscreen', event => { + this.toggleControls(event); + }); + } + + // Handle user exiting fullscreen by escaping etc + if (fullscreen.enabled) { + utils.on(document, fullscreen.eventType, event => { + this.toggleFullscreen(event); + }); + + // Fullscreen toggle on double click + utils.on(this.elements.container, 'dblclick', event => { + this.toggleFullscreen(event); + }); + } + }, + + // Listen for media events + media() { + // Time change on media + utils.on(this.media, 'timeupdate seeking', event => ui.timeUpdate.call(this, event)); + + // Display duration + utils.on(this.media, 'durationchange loadedmetadata', event => ui.durationUpdate.call(this, event)); + + // Check for audio tracks on load + // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point + utils.on(this.media, 'loadeddata', () => { + utils.toggleHidden(this.elements.volume, !this.hasAudio); + utils.toggleHidden(this.elements.buttons.mute, !this.hasAudio); + }); + + // Handle the media finishing + utils.on(this.media, 'ended', () => { + // Show poster on end + if (this.isHTML5 && this.isVideo && this.config.showPosterOnEnd) { + // Restart + this.restart(); + + // Re-load media + this.media.load(); + } + }); + + // Check for buffer progress + utils.on(this.media, 'progress playing', event => ui.updateProgress.call(this, event)); + + // Handle native mute + utils.on(this.media, 'volumechange', event => ui.updateVolume.call(this, event)); + + // Handle native play/pause + utils.on(this.media, 'playing play pause ended', event => ui.checkPlaying.call(this, event)); + + // Loading + utils.on(this.media, 'stalled waiting canplay seeked playing', event => ui.checkLoading.call(this, event)); + + // Check if media failed to load + // utils.on(this.media, 'play', event => ui.checkFailed.call(this, event)); + + // Click video + if (this.supported.ui && this.config.clickToPlay && !this.isAudio) { + // Re-fetch the wrapper + const wrapper = utils.getElement.call(this, `.${this.config.classNames.video}`); + + // Bail if there's no wrapper (this should never happen) + if (!utils.is.element(wrapper)) { + return; + } + + // On click play, pause ore restart + utils.on(wrapper, 'click', () => { + // Touch devices will just show controls (if we're hiding controls) + if (this.config.hideControls && support.touch && !this.paused) { + return; + } + + if (this.paused) { + this.play(); + } else if (this.ended) { + this.restart(); + this.play(); + } else { + this.pause(); + } + }); + } + + // Disable right click + if (this.supported.ui && this.config.disableContextMenu) { + utils.on( + this.media, + 'contextmenu', + event => { + event.preventDefault(); + }, + false + ); + } + + // Volume change + utils.on(this.media, 'volumechange', () => { + // Save to storage + this.storage.set({ volume: this.volume, muted: this.muted }); + }); + + // Speed change + utils.on(this.media, 'ratechange', () => { + // Update UI + controls.updateSetting.call(this, 'speed'); + + // Save to storage + this.storage.set({ speed: this.speed }); + }); + + // Quality change + utils.on(this.media, 'qualitychange', () => { + // Update UI + controls.updateSetting.call(this, 'quality'); + + // Save to storage + this.storage.set({ quality: this.quality }); + }); + + // Caption language change + utils.on(this.media, 'languagechange', () => { + // Update UI + controls.updateSetting.call(this, 'captions'); + + // Save to storage + this.storage.set({ language: this.language }); + }); + + // Captions toggle + utils.on(this.media, 'captionsenabled captionsdisabled', () => { + // Update UI + controls.updateSetting.call(this, 'captions'); + + // Save to storage + this.storage.set({ captions: this.captions.active }); + }); + + // Proxy events to container + // Bubble up key events for Edge + utils.on(this.media, this.config.events.concat([ + 'keyup', + 'keydown', + ]).join(' '), event => { + let detail = {}; + + // Get error details from media + if (event.type === 'error') { + detail = this.media.error; + } + + utils.dispatchEvent.call(this, this.elements.container, event.type, true, detail); + }); + }, + + // Listen for control events + controls() { + // IE doesn't support input event, so we fallback to change + const inputEvent = browser.isIE ? 'change' : 'input'; + + // Trigger custom and default handlers + const proxy = (event, handlerKey, defaultHandler) => { + const customHandler = this.config.listeners[handlerKey]; + + // Execute custom handler + if (utils.is.function(customHandler)) { + customHandler.call(this, event); + } + + // Only call default handler if not prevented in custom handler + if (!event.defaultPrevented && utils.is.function(defaultHandler)) { + defaultHandler.call(this, event); + } + }; + + // Play/pause toggle + utils.on(this.elements.buttons.play, 'click', event => + proxy(event, 'play', () => { + this.togglePlay(); + }) + ); + + // Pause + utils.on(this.elements.buttons.restart, 'click', event => + proxy(event, 'restart', () => { + this.restart(); + }) + ); + + // Rewind + utils.on(this.elements.buttons.rewind, 'click', event => + proxy(event, 'rewind', () => { + this.rewind(); + }) + ); + + // Rewind + utils.on(this.elements.buttons.forward, 'click', event => + proxy(event, 'forward', () => { + this.forward(); + }) + ); + + // Mute toggle + utils.on(this.elements.buttons.mute, 'click', event => + proxy(event, 'mute', () => { + this.muted = !this.muted; + }) + ); + + // Captions toggle + utils.on(this.elements.buttons.captions, 'click', event => + proxy(event, 'captions', () => { + this.toggleCaptions(); + }) + ); + + // Fullscreen toggle + utils.on(this.elements.buttons.fullscreen, 'click', event => + proxy(event, 'fullscreen', () => { + this.toggleFullscreen(); + }) + ); + + // Picture-in-Picture + utils.on(this.elements.buttons.pip, 'click', event => + proxy(event, 'pip', () => { + this.pip = 'toggle'; + }) + ); + + // Airplay + utils.on(this.elements.buttons.airplay, 'click', event => + proxy(event, 'airplay', () => { + this.airplay(); + }) + ); + + // Settings menu + utils.on(this.elements.buttons.settings, 'click', event => { + controls.toggleMenu.call(this, event); + }); + + // Click anywhere closes menu + utils.on(document.documentElement, 'click', event => { + controls.toggleMenu.call(this, event); + }); + + // Settings menu + utils.on(this.elements.settings.form, 'click', event => { + event.stopPropagation(); + + // Settings menu items - use event delegation as items are added/removed + if (utils.matches(event.target, this.config.selectors.inputs.language)) { + proxy(event, 'language', () => { + this.language = event.target.value; + }); + } else if (utils.matches(event.target, this.config.selectors.inputs.quality)) { + proxy(event, 'quality', () => { + this.quality = event.target.value; + }); + } else if (utils.matches(event.target, this.config.selectors.inputs.speed)) { + proxy(event, 'speed', () => { + this.speed = parseFloat(event.target.value); + }); + } else { + controls.showTab.call(this, event); + } + }); + + // Seek + utils.on(this.elements.inputs.seek, inputEvent, event => + proxy(event, 'seek', () => { + this.currentTime = event.target.value / event.target.max * this.duration; + }) + ); + + // Current time invert + // Only if one time element is used for both currentTime and duration + if (this.config.toggleInvert && !utils.is.element(this.elements.display.duration)) { + utils.on(this.elements.display.currentTime, 'click', () => { + // Do nothing if we're at the start + if (this.currentTime === 0) { + return; + } + + this.config.invertTime = !this.config.invertTime; + ui.timeUpdate.call(this); + }); + } + + // Volume + utils.on(this.elements.inputs.volume, inputEvent, event => + proxy(event, 'volume', () => { + this.volume = event.target.value; + }) + ); + + // Polyfill for lower fill in <input type="range"> for webkit + if (browser.isWebkit) { + utils.on(utils.getElements.call(this, 'input[type="range"]'), 'input', event => { + controls.updateRangeFill.call(this, event.target); + }); + } + + // Seek tooltip + utils.on(this.elements.progress, 'mouseenter mouseleave mousemove', event => controls.updateSeekTooltip.call(this, event)); + + // Toggle controls visibility based on mouse movement + if (this.config.hideControls) { + // Watch for cursor over controls so they don't hide when trying to interact + utils.on(this.elements.controls, 'mouseenter mouseleave', event => { + this.elements.controls.hover = event.type === 'mouseenter'; + }); + + // Watch for cursor over controls so they don't hide when trying to interact + utils.on(this.elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => { + this.elements.controls.pressed = [ + 'mousedown', + 'touchstart', + ].includes(event.type); + }); + + // Focus in/out on controls + utils.on(this.elements.controls, 'focusin focusout', event => { + this.toggleControls(event); + }); + } + + // Mouse wheel for volume + utils.on( + this.elements.inputs.volume, + 'wheel', + event => + proxy(event, 'volume', () => { + // Detect "natural" scroll - suppored on OS X Safari only + // Other browsers on OS X will be inverted until support improves + const inverted = event.webkitDirectionInvertedFromDevice; + const step = 1 / 50; + let direction = 0; + + // Scroll down (or up on natural) to decrease + if (event.deltaY < 0 || event.deltaX > 0) { + if (inverted) { + this.decreaseVolume(step); + direction = -1; + } else { + this.increaseVolume(step); + direction = 1; + } + } + + // Scroll up (or down on natural) to increase + if (event.deltaY > 0 || event.deltaX < 0) { + if (inverted) { + this.increaseVolume(step); + direction = 1; + } else { + this.decreaseVolume(step); + direction = -1; + } + } + + // Don't break page scrolling at max and min + if ((direction === 1 && this.media.volume < 1) || (direction === -1 && this.media.volume > 0)) { + event.preventDefault(); + } + }), + false + ); + }, +}; + +export default listeners; diff --git a/src/js/media.js b/src/js/media.js new file mode 100644 index 00000000..4019c1a7 --- /dev/null +++ b/src/js/media.js @@ -0,0 +1,106 @@ +// ========================================================================== +// Plyr Media +// ========================================================================== + +import support from './support'; +import utils from './utils'; +import youtube from './plugins/youtube'; +import vimeo from './plugins/vimeo'; +import ui from './ui'; + +// Sniff out the browser +const browser = utils.getBrowser(); + +const media = { + // Setup media + setup() { + // If there's no media, bail + if (!this.media) { + this.debug.warn('No media element found!'); + return; + } + + // Add type class + utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true); + + // Add provider class + utils.toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true); + + // Add video class for embeds + // This will require changes if audio embeds are added + if (this.isEmbed) { + utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true); + } + + if (this.supported.ui) { + // Check for picture-in-picture support + utils.toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo); + + // Check for airplay support + utils.toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5); + + // If there's no autoplay attribute, assume the video is stopped and add state class + utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.config.autoplay); + + // Add iOS class + utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos); + + // Add touch class + utils.toggleClass(this.elements.container, this.config.classNames.isTouch, support.touch); + } + + // Inject the player wrapper + if (this.isVideo || this.isYouTube || this.isVimeo) { + // Create the wrapper div + this.elements.wrapper = utils.createElement('div', { + class: this.config.classNames.video, + }); + + // Wrap the video in a container + utils.wrap(this.media, this.elements.wrapper); + } + + if (this.isEmbed) { + switch (this.provider) { + case 'youtube': + youtube.setup.call(this); + break; + + case 'vimeo': + vimeo.setup.call(this); + break; + + default: + break; + } + } else if (this.isHTML5) { + ui.setTitle.call(this); + } + }, + + // Cancel current network requests + // See https://github.com/sampotts/plyr/issues/174 + cancelRequests() { + if (!this.isHTML5) { + return; + } + + // Remove child sources + Array.from(this.media.querySelectorAll('source')).forEach(utils.removeElement); + + // Set blank video src attribute + // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error + // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection + this.media.setAttribute('src', this.config.blankVideo); + + // Load the new empty source + // This will cancel existing requests + // See https://github.com/sampotts/plyr/issues/174 + this.media.load(); + + // Debugging + this.debug.log('Cancelled network requests'); + }, +}; + +export default media; diff --git a/src/js/plugins/vimeo.js b/src/js/plugins/vimeo.js new file mode 100644 index 00000000..c77ecd20 --- /dev/null +++ b/src/js/plugins/vimeo.js @@ -0,0 +1,310 @@ +// ========================================================================== +// Vimeo plugin +// ========================================================================== + +import utils from './../utils'; +import captions from './../captions'; +import ui from './../ui'; + +const vimeo = { + setup() { + // Remove old containers + const containers = utils.getElements.call(this, `[id^="${this.provider}-"]`); + Array.from(containers).forEach(utils.removeElement); + + // Add embed class for responsive + utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true); + + // Set intial ratio + vimeo.setAspectRatio.call(this); + + // Set ID + this.media.setAttribute('id', utils.generateId(this.provider)); + + // Load the API if not already + if (!utils.is.object(window.Vimeo)) { + utils.loadScript(this.config.urls.vimeo.api, () => { + vimeo.ready.call(this); + }); + } else { + vimeo.ready.call(this); + } + }, + + // Set aspect ratio + // For Vimeo we have an extra 300% height <div> to hide the standard controls and UI + setAspectRatio(input) { + const ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':'); + const padding = 100 / ratio[0] * ratio[1]; + const height = 200; + const offset = (height - padding) / (height / 50); + this.elements.wrapper.style.paddingBottom = `${padding}%`; + this.media.style.transform = `translateY(-${offset}%)`; + }, + + // API Ready + ready() { + const player = this; + + // Get Vimeo params for the iframe + const options = { + loop: player.config.loop.active, + autoplay: player.autoplay, + byline: false, + portrait: false, + title: false, + speed: true, + transparent: 0, + gesture: 'media', + }; + const params = utils.buildUrlParameters(options); + const id = utils.parseVimeoId(player.embedId); + + // Build an iframe + const iframe = utils.createElement('iframe'); + const src = `https://player.vimeo.com/video/${id}?${params}`; + iframe.setAttribute('src', src); + iframe.setAttribute('allowfullscreen', ''); + player.media.appendChild(iframe); + + // Setup instance + // https://github.com/vimeo/player.js + player.embed = new window.Vimeo.Player(iframe); + + player.media.paused = true; + player.media.currentTime = 0; + + // Create a faux HTML5 API using the Vimeo API + player.media.play = () => { + player.embed.play().then(() => { + player.media.paused = false; + }); + }; + + player.media.pause = () => { + player.embed.pause().then(() => { + player.media.paused = true; + }); + }; + + player.media.stop = () => { + player.embed.stop().then(() => { + player.media.paused = true; + player.currentTime = 0; + }); + }; + + // Seeking + let { currentTime } = player.media; + Object.defineProperty(player.media, 'currentTime', { + get() { + return currentTime; + }, + set(time) { + // Get current paused state + // Vimeo will automatically play on seek + const { paused } = player.media; + + // Set seeking flag + player.media.seeking = true; + + // Trigger seeking + utils.dispatchEvent.call(player, player.media, 'seeking'); + + // Seek after events + player.embed.setCurrentTime(time); + + // Restore pause state + if (paused) { + player.pause(); + } + }, + }); + + // Playback speed + let speed = player.config.speed.selected; + Object.defineProperty(player.media, 'playbackRate', { + get() { + return speed; + }, + set(input) { + player.embed.setPlaybackRate(input).then(() => { + speed = input; + utils.dispatchEvent.call(player, player.media, 'ratechange'); + }); + }, + }); + + // Volume + let { volume } = player.config; + Object.defineProperty(player.media, 'volume', { + get() { + return volume; + }, + set(input) { + player.embed.setVolume(input).then(() => { + volume = input; + utils.dispatchEvent.call(player, player.media, 'volumechange'); + }); + }, + }); + + // Muted + let { muted } = player.config; + Object.defineProperty(player.media, 'muted', { + get() { + return muted; + }, + set(input) { + const toggle = utils.is.boolean(input) ? input : false; + + player.embed.setVolume(toggle ? 0 : player.config.volume).then(() => { + muted = toggle; + utils.dispatchEvent.call(player, player.media, 'volumechange'); + }); + }, + }); + + // Loop + let { loop } = player.config; + Object.defineProperty(player.media, 'loop', { + get() { + return loop; + }, + set(input) { + const toggle = utils.is.boolean(input) ? input : player.config.loop.active; + + player.embed.setLoop(toggle).then(() => { + loop = toggle; + }); + }, + }); + + // Source + let currentSrc; + player.embed.getVideoUrl().then(value => { + currentSrc = value; + }); + Object.defineProperty(player.media, 'currentSrc', { + get() { + return currentSrc; + }, + }); + + // Ended + Object.defineProperty(player.media, 'ended', { + get() { + return player.currentTime === player.duration; + }, + }); + + // Set aspect ratio based on video size + Promise.all([ + player.embed.getVideoWidth(), + player.embed.getVideoHeight(), + ]).then(dimensions => { + const ratio = utils.getAspectRatio(dimensions[0], dimensions[1]); + vimeo.setAspectRatio.call(this, ratio); + }); + + // Set autopause + player.embed.setAutopause(player.config.autopause).then(state => { + player.config.autopause = state; + }); + + // Get title + player.embed.getVideoTitle().then(title => { + player.config.title = title; + ui.setTitle.call(this); + }); + + // Get current time + player.embed.getCurrentTime().then(value => { + currentTime = value; + utils.dispatchEvent.call(player, player.media, 'timeupdate'); + }); + + // Get duration + player.embed.getDuration().then(value => { + player.media.duration = value; + utils.dispatchEvent.call(player, player.media, 'durationchange'); + }); + + // Get captions + player.embed.getTextTracks().then(tracks => { + player.media.textTracks = tracks; + captions.setup.call(player); + }); + + player.embed.on('cuechange', data => { + let cue = null; + + if (data.cues.length) { + cue = utils.stripHTML(data.cues[0].text); + } + + captions.setText.call(player, cue); + }); + + player.embed.on('loaded', () => { + if (utils.is.element(player.embed.element) && player.supported.ui) { + const frame = player.embed.element; + + // Fix keyboard focus issues + // https://github.com/sampotts/plyr/issues/317 + frame.setAttribute('tabindex', -1); + } + }); + + player.embed.on('play', () => { + // Only fire play if paused before + if (player.media.paused) { + utils.dispatchEvent.call(player, player.media, 'play'); + } + player.media.paused = false; + utils.dispatchEvent.call(player, player.media, 'playing'); + }); + + player.embed.on('pause', () => { + player.media.paused = true; + utils.dispatchEvent.call(player, player.media, 'pause'); + }); + + player.embed.on('timeupdate', data => { + player.media.seeking = false; + currentTime = data.seconds; + utils.dispatchEvent.call(player, player.media, 'timeupdate'); + }); + + player.embed.on('progress', data => { + player.media.buffered = data.percent; + utils.dispatchEvent.call(player, player.media, 'progress'); + + // Check all loaded + if (parseInt(data.percent, 10) === 1) { + utils.dispatchEvent.call(player, player.media, 'canplaythrough'); + } + }); + + player.embed.on('seeked', () => { + player.media.seeking = false; + utils.dispatchEvent.call(player, player.media, 'seeked'); + utils.dispatchEvent.call(player, player.media, 'play'); + }); + + player.embed.on('ended', () => { + player.media.paused = true; + utils.dispatchEvent.call(player, player.media, 'ended'); + }); + + player.embed.on('error', detail => { + player.media.error = detail; + utils.dispatchEvent.call(player, player.media, 'error'); + }); + + // Rebuild UI + window.setTimeout(() => ui.build.call(player), 0); + }, +}; + +export default vimeo; diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js new file mode 100644 index 00000000..67f1ca95 --- /dev/null +++ b/src/js/plugins/youtube.js @@ -0,0 +1,408 @@ +// ========================================================================== +// YouTube plugin +// ========================================================================== + +import utils from './../utils'; +import controls from './../controls'; +import ui from './../ui'; + +const youtube = { + setup() { + const videoId = utils.parseYouTubeId(this.embedId); + + // Remove old containers + const containers = utils.getElements.call(this, `[id^="${this.provider}-"]`); + Array.from(containers).forEach(utils.removeElement); + + // Add embed class for responsive + utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true); + + // Set aspect ratio + youtube.setAspectRatio.call(this); + + // Set ID + this.media.setAttribute('id', utils.generateId(this.provider)); + + // Setup API + if (utils.is.object(window.YT)) { + youtube.ready.call(this, videoId); + } else { + // Load the API + utils.loadScript(this.config.urls.youtube.api); + + // Setup callback for the API + // YouTube has it's own system of course... + window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || []; + + // Add to queue + window.onYouTubeReadyCallbacks.push(() => { + youtube.ready.call(this, videoId); + }); + + // Set callback to process queue + window.onYouTubeIframeAPIReady = () => { + window.onYouTubeReadyCallbacks.forEach(callback => { + callback(); + }); + }; + } + }, + + // Get the media title + getTitle() { + // Try via undocumented API method first + // This method disappears now and then though... + // https://github.com/sampotts/plyr/issues/709 + if (utils.is.function(this.embed.getVideoData)) { + const { title } = this.embed.getVideoData(); + + if (utils.is.empty(title)) { + this.config.title = title; + ui.setTitle.call(this); + return; + } + } + + // Or via Google API + const key = this.config.keys.google; + const videoId = utils.parseYouTubeId(this.embedId); + if (utils.is.string(key) && !utils.is.empty(key)) { + const url = `https://www.googleapis.com/youtube/v3/videos?id=${videoId}&key=${key}&fields=items(snippet(title))&part=snippet`; + + fetch(url) + .then(response => (response.ok ? response.json() : null)) + .then(result => { + if (result !== null && utils.is.object(result)) { + this.config.title = result.items[0].snippet.title; + ui.setTitle.call(this); + } + }) + .catch(() => {}); + } + }, + + // Set aspect ratio + setAspectRatio() { + const ratio = this.config.ratio.split(':'); + this.elements.wrapper.style.paddingBottom = `${100 / ratio[0] * ratio[1]}%`; + }, + + // API ready + ready(videoId) { + const player = this; + + // Setup instance + // https://developers.google.com/youtube/iframe_api_reference + player.embed = new window.YT.Player(player.media.id, { + videoId, + playerVars: { + autoplay: player.config.autoplay ? 1 : 0, // Autoplay + controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported + rel: 0, // No related vids + showinfo: 0, // Hide info + iv_load_policy: 3, // Hide annotations + modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused) + disablekb: 1, // Disable keyboard as we handle it + playsinline: 1, // Allow iOS inline playback + + // Tracking for stats + origin: window && window.location.hostname, + widget_referrer: window && window.location.href, + + // Captions are flaky on YouTube + cc_load_policy: this.captions.active ? 1 : 0, + cc_lang_pref: this.config.captions.language, + }, + events: { + onError(event) { + // If we've already fired an error, don't do it again + // YouTube fires onError twice + if (utils.is.object(player.media.error)) { + return; + } + + const detail = { + code: event.data, + }; + + // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError + switch (event.data) { + case 2: + detail.message = + 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.'; + break; + + case 5: + detail.message = + 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.'; + break; + + case 100: + detail.message = + 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.'; + break; + + case 101: + case 150: + detail.message = 'The owner of the requested video does not allow it to be played in embedded players.'; + break; + + default: + detail.message = 'An unknown error occured'; + break; + } + + player.media.error = detail; + + utils.dispatchEvent.call(player, player.media, 'error'); + }, + onPlaybackQualityChange(event) { + // Get the instance + const instance = event.target; + + // Get current quality + player.media.quality = instance.getPlaybackQuality(); + + utils.dispatchEvent.call(player, player.media, 'qualitychange'); + }, + onPlaybackRateChange(event) { + // Get the instance + const instance = event.target; + + // Get current speed + player.media.playbackRate = instance.getPlaybackRate(); + + utils.dispatchEvent.call(player, player.media, 'ratechange'); + }, + onReady(event) { + // Get the instance + const instance = event.target; + + // Get the title + youtube.getTitle.call(player); + + // Create a faux HTML5 API using the YouTube API + player.media.play = () => { + instance.playVideo(); + player.media.paused = false; + }; + + player.media.pause = () => { + instance.pauseVideo(); + player.media.paused = true; + }; + + player.media.stop = () => { + instance.stopVideo(); + player.media.paused = true; + }; + + player.media.duration = instance.getDuration(); + player.media.paused = true; + + // Seeking + player.media.currentTime = 0; + Object.defineProperty(player.media, 'currentTime', { + get() { + return Number(instance.getCurrentTime()); + }, + set(time) { + // Set seeking flag + player.media.seeking = true; + + // Trigger seeking + utils.dispatchEvent.call(player, player.media, 'seeking'); + + // Seek after events sent + instance.seekTo(time); + }, + }); + + // Playback speed + Object.defineProperty(player.media, 'playbackRate', { + get() { + return instance.getPlaybackRate(); + }, + set(input) { + instance.setPlaybackRate(input); + }, + }); + + // Quality + Object.defineProperty(player.media, 'quality', { + get() { + return instance.getPlaybackQuality(); + }, + set(input) { + // Trigger request event + utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, { + quality: input, + }); + + instance.setPlaybackQuality(input); + }, + }); + + // Volume + let { volume } = player.config; + Object.defineProperty(player.media, 'volume', { + get() { + return volume; + }, + set(input) { + volume = input; + instance.setVolume(volume * 100); + utils.dispatchEvent.call(player, player.media, 'volumechange'); + }, + }); + + // Muted + let { muted } = player.config; + Object.defineProperty(player.media, 'muted', { + get() { + return muted; + }, + set(input) { + const toggle = utils.is.boolean(input) ? input : muted; + muted = toggle; + instance[toggle ? 'mute' : 'unMute'](); + utils.dispatchEvent.call(player, player.media, 'volumechange'); + }, + }); + + // Source + Object.defineProperty(player.media, 'currentSrc', { + get() { + return instance.getVideoUrl(); + }, + }); + + // Ended + Object.defineProperty(player.media, 'ended', { + get() { + return player.currentTime === player.duration; + }, + }); + + // Get available speeds + player.options.speed = instance.getAvailablePlaybackRates(); + + // Set the tabindex to avoid focus entering iframe + if (player.supported.ui) { + player.media.setAttribute('tabindex', -1); + } + + utils.dispatchEvent.call(player, player.media, 'timeupdate'); + utils.dispatchEvent.call(player, player.media, 'durationchange'); + + // Reset timer + window.clearInterval(player.timers.buffering); + + // Setup buffering + player.timers.buffering = window.setInterval(() => { + // Get loaded % from YouTube + player.media.buffered = instance.getVideoLoadedFraction(); + + // Trigger progress only when we actually buffer something + if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) { + utils.dispatchEvent.call(player, player.media, 'progress'); + } + + // Set last buffer point + player.media.lastBuffered = player.media.buffered; + + // Bail if we're at 100% + if (player.media.buffered === 1) { + window.clearInterval(player.timers.buffering); + + // Trigger event + utils.dispatchEvent.call(player, player.media, 'canplaythrough'); + } + }, 200); + + // Rebuild UI + window.setTimeout(() => ui.build.call(player), 50); + }, + onStateChange(event) { + // Get the instance + const instance = event.target; + + // Reset timer + window.clearInterval(player.timers.playing); + + // Handle events + // -1 Unstarted + // 0 Ended + // 1 Playing + // 2 Paused + // 3 Buffering + // 5 Video cued + switch (event.data) { + case 0: + player.media.paused = true; + + // YouTube doesn't support loop for a single video, so mimick it. + if (player.media.loop) { + // YouTube needs a call to `stopVideo` before playing again + instance.stopVideo(); + instance.playVideo(); + } else { + utils.dispatchEvent.call(player, player.media, 'ended'); + } + + break; + + case 1: + // If we were seeking, fire seeked event + if (player.media.seeking) { + utils.dispatchEvent.call(player, player.media, 'seeked'); + } + player.media.seeking = false; + + // Only fire play if paused before + if (player.media.paused) { + utils.dispatchEvent.call(player, player.media, 'play'); + } + player.media.paused = false; + + utils.dispatchEvent.call(player, player.media, 'playing'); + + // Poll to get playback progress + player.timers.playing = window.setInterval(() => { + utils.dispatchEvent.call(player, player.media, 'timeupdate'); + }, 50); + + // Check duration again due to YouTube bug + // https://github.com/sampotts/plyr/issues/374 + // https://code.google.com/p/gdata-issues/issues/detail?id=8690 + if (player.media.duration !== instance.getDuration()) { + player.media.duration = instance.getDuration(); + utils.dispatchEvent.call(player, player.media, 'durationchange'); + } + + // Get quality + controls.setQualityMenu.call(player, instance.getAvailableQualityLevels()); + + break; + + case 2: + player.media.paused = true; + + utils.dispatchEvent.call(player, player.media, 'pause'); + + break; + + default: + break; + } + + utils.dispatchEvent.call(player, player.elements.container, 'statechange', false, { + code: event.data, + }); + }, + }, + }); + }, +}; + +export default youtube; diff --git a/src/js/plyr.js b/src/js/plyr.js index afd1b997..e6df286c 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -1,3961 +1,1174 @@ -// ========================================================================== +// ========================================================================== // Plyr -// plyr.js v2.0.18 +// plyr.js v3.0.0 // https://github.com/sampotts/plyr // License: The MIT License (MIT) // ========================================================================== -// Credits: http://paypal.github.io/accessible-html5-video-player/ -// ========================================================================== -(function(root, factory) { - 'use strict'; - /*global define,module*/ - - if (typeof module === 'object' && typeof module.exports === 'object') { - // Node, CommonJS-like - module.exports = factory(root, document); - } else if (typeof define === 'function' && define.amd) { - // AMD - define([], function() { - return factory(root, document); - }); - } else { - // Browser globals (root is window) - root.plyr = factory(root, document); - } -})(typeof window !== 'undefined' ? window : this, function(window, document) { - 'use strict'; - - // Globals - var fullscreen, - scroll = { x: 0, y: 0 }, - // Default config - defaults = { - enabled: true, - debug: false, - autoplay: false, - loop: false, - seekTime: 10, - volume: 10, - volumeMin: 0, - volumeMax: 10, - volumeStep: 1, - duration: null, - displayDuration: true, - loadSprite: true, - iconPrefix: 'plyr', - iconUrl: 'https://cdn.plyr.io/2.0.18/plyr.svg', - blankUrl: 'https://cdn.plyr.io/static/blank.mp4', - clickToPlay: true, - hideControls: true, - showPosterOnEnd: false, - disableContextMenu: true, - keyboardShorcuts: { - focused: true, - global: false, - }, - tooltips: { - controls: false, - seek: true, - }, - selectors: { - html5: 'video, audio', - embed: '[data-type]', - editable: 'input, textarea, select, [contenteditable]', - container: '.plyr', - controls: { - container: null, - wrapper: '.plyr__controls', - }, - labels: '[data-plyr]', - buttons: { - seek: '[data-plyr="seek"]', - play: '[data-plyr="play"]', - pause: '[data-plyr="pause"]', - restart: '[data-plyr="restart"]', - rewind: '[data-plyr="rewind"]', - forward: '[data-plyr="fast-forward"]', - mute: '[data-plyr="mute"]', - captions: '[data-plyr="captions"]', - fullscreen: '[data-plyr="fullscreen"]', - }, - volume: { - input: '[data-plyr="volume"]', - display: '.plyr__volume--display', - }, - progress: { - container: '.plyr__progress', - buffer: '.plyr__progress--buffer', - played: '.plyr__progress--played', - }, - captions: '.plyr__captions', - currentTime: '.plyr__time--current', - duration: '.plyr__time--duration', - }, - classes: { - setup: 'plyr--setup', - ready: 'plyr--ready', - videoWrapper: 'plyr__video-wrapper', - embedWrapper: 'plyr__video-embed', - type: 'plyr--{0}', - stopped: 'plyr--stopped', - playing: 'plyr--playing', - muted: 'plyr--muted', - loading: 'plyr--loading', - hover: 'plyr--hover', - tooltip: 'plyr__tooltip', - hidden: 'plyr__sr-only', - hideControls: 'plyr--hide-controls', - isIos: 'plyr--is-ios', - isTouch: 'plyr--is-touch', - captions: { - enabled: 'plyr--captions-enabled', - active: 'plyr--captions-active', - }, - fullscreen: { - enabled: 'plyr--fullscreen-enabled', - fallback: 'plyr--fullscreen-fallback', - active: 'plyr--fullscreen-active', - }, - tabFocus: 'tab-focus', - }, - captions: { - defaultActive: false, - }, - fullscreen: { - enabled: true, - fallback: true, - allowAudio: false, - }, - storage: { - enabled: true, - key: 'plyr', - }, - controls: ['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'fullscreen'], - i18n: { - restart: 'Restart', - rewind: 'Rewind {seektime} secs', - play: 'Play', - pause: 'Pause', - forward: 'Forward {seektime} secs', - played: 'played', - buffered: 'buffered', - currentTime: 'Current time', - duration: 'Duration', - volume: 'Volume', - toggleMute: 'Toggle Mute', - toggleCaptions: 'Toggle Captions', - toggleFullscreen: 'Toggle Fullscreen', - frameTitle: 'Player for {title}', - }, - types: { - embed: ['youtube', 'vimeo', 'soundcloud'], - html5: ['video', 'audio'], - }, - // URLs - urls: { - vimeo: { - api: 'https://player.vimeo.com/api/player.js', - }, - youtube: { - api: 'https://www.youtube.com/iframe_api', - }, - soundcloud: { - api: 'https://w.soundcloud.com/player/api.js', - }, - }, - // Custom control listeners - listeners: { - seek: null, - play: null, - pause: null, - restart: null, - rewind: null, - forward: null, - mute: null, - volume: null, - captions: null, - fullscreen: null, +import { providers, types } from './types'; +import defaults from './defaults'; +import support from './support'; +import utils from './utils'; + +import Console from './console'; +import Storage from './storage'; + +import captions from './captions'; +import controls from './controls'; +import fullscreen from './fullscreen'; +import listeners from './listeners'; +import media from './media'; +import source from './source'; +import ui from './ui'; + +// Private properties +// TODO: Use a WeakMap for private globals +// const globals = new WeakMap(); + +// Globals +let scrollPosition = { + x: 0, + y: 0, +}; + +// Plyr instance +class Plyr { + constructor(target, options) { + this.timers = {}; + + // State + this.ready = false; + this.loading = false; + this.failed = false; + + // Set the media element + this.media = target; + + // String selector passed + if (utils.is.string(this.media)) { + this.media = document.querySelectorAll(this.media); + } + + // jQuery, NodeList or Array passed, use first element + if ((window.jQuery && this.media instanceof jQuery) || utils.is.nodeList(this.media) || utils.is.array(this.media)) { + // eslint-disable-next-line + this.media = this.media[0]; + } + + // Set config + this.config = utils.extend( + {}, + defaults, + options, + (() => { + try { + return JSON.parse(this.media.getAttribute('data-plyr-config')); + } catch (e) { + return {}; + } + })() + ); + + // Elements cache + this.elements = { + container: null, + buttons: {}, + display: {}, + progress: {}, + inputs: {}, + settings: { + menu: null, + panes: {}, + tabs: {}, }, - // Events to watch on HTML5 media elements - events: [ - 'ready', - 'ended', - 'progress', - 'stalled', - 'playing', - 'waiting', - 'canplay', - 'canplaythrough', - 'loadstart', - 'loadeddata', - 'loadedmetadata', - 'timeupdate', - 'volumechange', - 'play', - 'pause', - 'error', - 'seeking', - 'seeked', - 'emptied', - ], - // Logging - logPrefix: '[Plyr]', + captions: null, }; - // Credits: http://paypal.github.io/accessible-html5-video-player/ - // Unfortunately, due to mixed support, UA sniffing is required - function _browserSniff() { - var ua = navigator.userAgent, - name = navigator.appName, - fullVersion = '' + parseFloat(navigator.appVersion), - majorVersion = parseInt(navigator.appVersion, 10), - nameOffset, - verOffset, - ix, - isIE = false, - isFirefox = false, - isChrome = false, - isSafari = false; - - if (navigator.appVersion.indexOf('Windows NT') !== -1 && navigator.appVersion.indexOf('rv:11') !== -1) { - // MSIE 11 - isIE = true; - name = 'IE'; - fullVersion = '11'; - } else if ((verOffset = ua.indexOf('MSIE')) !== -1) { - // MSIE - isIE = true; - name = 'IE'; - fullVersion = ua.substring(verOffset + 5); - } else if ((verOffset = ua.indexOf('Chrome')) !== -1) { - // Chrome - isChrome = true; - name = 'Chrome'; - fullVersion = ua.substring(verOffset + 7); - } else if ((verOffset = ua.indexOf('Safari')) !== -1) { - // Safari - isSafari = true; - name = 'Safari'; - fullVersion = ua.substring(verOffset + 7); - if ((verOffset = ua.indexOf('Version')) !== -1) { - fullVersion = ua.substring(verOffset + 8); - } - } else if ((verOffset = ua.indexOf('Firefox')) !== -1) { - // Firefox - isFirefox = true; - name = 'Firefox'; - fullVersion = ua.substring(verOffset + 8); - } else if ((nameOffset = ua.lastIndexOf(' ') + 1) < (verOffset = ua.lastIndexOf('/'))) { - // In most other browsers, 'name/version' is at the end of userAgent - name = ua.substring(nameOffset, verOffset); - fullVersion = ua.substring(verOffset + 1); - - if (name.toLowerCase() === name.toUpperCase()) { - name = navigator.appName; - } - } - - // Trim the fullVersion string at semicolon/space if present - if ((ix = fullVersion.indexOf(';')) !== -1) { - fullVersion = fullVersion.substring(0, ix); - } - if ((ix = fullVersion.indexOf(' ')) !== -1) { - fullVersion = fullVersion.substring(0, ix); - } + // Captions + this.captions = { + active: null, + currentTrack: null, + }; - // Get major version - majorVersion = parseInt('' + fullVersion, 10); - if (isNaN(majorVersion)) { - fullVersion = '' + parseFloat(navigator.appVersion); - majorVersion = parseInt(navigator.appVersion, 10); - } + // Fullscreen + this.fullscreen = { + active: false, + }; - // Return data - return { - name: name, - version: majorVersion, - isIE: isIE, - isFirefox: isFirefox, - isChrome: isChrome, - isSafari: isSafari, - isIos: /(iPad|iPhone|iPod)/g.test(navigator.platform), - isIphone: /(iPhone|iPod)/g.test(navigator.userAgent), - isTouch: 'ontouchstart' in document.documentElement, + // Options + this.options = { + speed: [], + quality: [], }; - } - // Check for mime type support against a player instance - // Credits: http://diveintohtml5.info/everything.html - // Related: http://www.leanbackplyr.com/test/h5mt.html - function _supportMime(plyr, mimeType) { - var media = plyr.media; - - if (plyr.type === 'video') { - // Check type - switch (mimeType) { - case 'video/webm': - return !!(media.canPlayType && media.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/, '')); - case 'video/mp4': - return !!(media.canPlayType && media.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, '')); - case 'video/ogg': - return !!(media.canPlayType && media.canPlayType('video/ogg; codecs="theora"').replace(/no/, '')); - } - } else if (plyr.type === 'audio') { - // Check type - switch (mimeType) { - case 'audio/mpeg': - return !!(media.canPlayType && media.canPlayType('audio/mpeg;').replace(/no/, '')); - case 'audio/ogg': - return !!(media.canPlayType && media.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/, '')); - case 'audio/wav': - return !!(media.canPlayType && media.canPlayType('audio/wav; codecs="1"').replace(/no/, '')); - } - } + // Debugging + // TODO: move to globals + this.debug = new Console(this); - // If we got this far, we're stuffed - return false; - } + // Log config options and support + this.debug.log('Config', this.config); + this.debug.log('Support', support); - // Inject a script - function _injectScript(source) { - if (document.querySelectorAll('script[src="' + source + '"]').length) { + // We need an element to setup + if (utils.is.nullOrUndefined(this.media) || !utils.is.element(this.media)) { + this.debug.error('Setup failed: no suitable element passed'); return; } - var tag = document.createElement('script'); - tag.src = source; - var firstScriptTag = document.getElementsByTagName('script')[0]; - firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); - } - - // Element exists in an array - function _inArray(haystack, needle) { - return Array.prototype.indexOf && haystack.indexOf(needle) !== -1; - } - - // Replace all - function _replaceAll(string, find, replace) { - return string.replace(new RegExp(find.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g, '\\$1'), 'g'), replace); - } - - // Wrap an element - function _wrap(elements, wrapper) { - // Convert `elements` to an array, if necessary. - if (!elements.length) { - elements = [elements]; + // Bail if the element is initialized + if (this.media.plyr) { + this.debug.warn('Target already setup'); + return; } - // Loops backwards to prevent having to clone the wrapper on the - // first element (see `child` below). - for (var i = elements.length - 1; i >= 0; i--) { - var child = i > 0 ? wrapper.cloneNode(true) : wrapper; - var element = elements[i]; - - // Cache the current parent and sibling. - var parent = element.parentNode; - var sibling = element.nextSibling; - - // Wrap the element (is automatically removed from its current - // parent). - child.appendChild(element); - - // If the element had a sibling, insert the wrapper before - // the sibling to maintain the HTML structure; otherwise, just - // append it to the parent. - if (sibling) { - parent.insertBefore(child, sibling); - } else { - parent.appendChild(child); - } - - return child; + // Bail if not enabled + if (!this.config.enabled) { + this.debug.error('Setup failed: disabled by config'); + return; } - } - - // Unwrap an element - // http://plainjs.com/javascript/manipulation/unwrap-a-dom-element-35/ - /*function _unwrap(wrapper) { - // Get the element's parent node - var parent = wrapper.parentNode; - // Move all children out of the element - while (wrapper.firstChild) { - parent.insertBefore(wrapper.firstChild, wrapper); + // Bail if disabled or no basic support + // You may want to disable certain UAs etc + if (!support.check().api) { + this.debug.error('Setup failed: no support'); + return; } - // Remove the empty element - parent.removeChild(wrapper); - }*/ + // Cache original element state for .destroy() + this.elements.original = this.media.cloneNode(true); - // Remove an element - function _remove(element) { - if (!element) { - return; - } - element.parentNode.removeChild(element); - } + // Set media type based on tag or data attribute + // Supported: video, audio, vimeo, youtube + const type = this.media.tagName.toLowerCase(); - // Prepend child - function _prependChild(parent, element) { - parent.insertBefore(element, parent.firstChild); - } + // Embed attributes + const attributes = { + provider: 'data-plyr-provider', + id: 'data-plyr-embed-id', + }; - // Set attributes - function _setAttributes(element, attributes) { - for (var key in attributes) { - element.setAttribute(key, _is.boolean(attributes[key]) && attributes[key] ? '' : attributes[key]); - } - } + // Different setup based on type + switch (type) { + // TODO: Handle passing an iframe for true progressive enhancement + // case 'iframe': + case 'div': + this.type = types.video; // Audio will come later for external providers + this.provider = this.media.getAttribute(attributes.provider); + this.embedId = this.media.getAttribute(attributes.id); + + if (utils.is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) { + this.debug.error('Setup failed: Invalid provider'); + return; + } - // Insert a HTML element - function _insertElement(type, parent, attributes) { - // Create a new <element> - var element = document.createElement(type); + // Try and get the embed id + if (utils.is.empty(this.embedId)) { + this.debug.error('Setup failed: Embed ID or URL missing'); + return; + } - // Set all passed attributes - _setAttributes(element, attributes); + // Clean up + this.media.removeAttribute(attributes.provider); + this.media.removeAttribute(attributes.id); - // Inject the new element - _prependChild(parent, element); - } + break; - // Get a classname from selector - function _getClassname(selector) { - return selector.replace('.', ''); - } + case 'video': + case 'audio': + this.type = type; + this.provider = providers.html5; - // Toggle class on an element - function _toggleClass(element, className, state) { - if (element) { - if (element.classList) { - element.classList[state ? 'add' : 'remove'](className); - } else { - var name = (' ' + element.className + ' ').replace(/\s+/g, ' ').replace(' ' + className + ' ', ''); - element.className = name + (state ? ' ' + className : ''); - } - } - } + if (this.media.hasAttribute('crossorigin')) { + this.config.crossorigin = true; + } - // Has class name - function _hasClass(element, className) { - if (element) { - if (element.classList) { - return element.classList.contains(className); - } else { - return new RegExp('(\\s|^)' + className + '(\\s|$)').test(element.className); - } - } - return false; - } + if (this.media.hasAttribute('autoplay')) { + this.config.autoplay = true; + } - // Element matches selector - function _matches(element, selector) { - var p = Element.prototype; + if (this.media.hasAttribute('playsinline')) { + this.config.inline = true; + } - var f = - p.matches || - p.webkitMatchesSelector || - p.mozMatchesSelector || - p.msMatchesSelector || - function(s) { - return [].indexOf.call(document.querySelectorAll(s), this) !== -1; - }; + if (this.media.hasAttribute('muted')) { + this.config.muted = true; + } - return f.call(element, selector); - } + if (this.media.hasAttribute('loop')) { + this.config.loop.active = true; + } + + break; - // Bind along with custom handler - function _proxyListener(element, eventName, userListener, defaultListener, useCapture) { - if (userListener) { - // Register this before defaultListener - _on( - element, - eventName, - function(event) { - userListener.apply(element, [event]); - }, - useCapture - ); + default: + this.debug.error('Setup failed: unsupported type'); + return; } - _on( - element, - eventName, - function(event) { - defaultListener.apply(element, [event]); - }, - useCapture - ); - } - // Toggle event listener - function _toggleListener(element, events, callback, toggle, useCapture) { - var eventList = events.split(' '); + // Setup local storage for user settings + this.storage = new Storage(this); - // Whether the listener is a capturing listener or not - // Default to false - if (!_is.boolean(useCapture)) { - useCapture = false; - } + // Check for support again but with type + this.supported = support.check(this.type, this.provider, this.config.inline); - // If a nodelist is passed, call itself on each node - if (element instanceof NodeList) { - for (var x = 0; x < element.length; x++) { - if (element[x] instanceof Node) { - _toggleListener(element[x], arguments[1], arguments[2], arguments[3]); - } - } + // If no support for even API, bail + if (!this.supported.api) { + this.debug.error('Setup failed: no support'); return; } - // If a single node is passed, bind the event listener - for (var i = 0; i < eventList.length; i++) { - element[toggle ? 'addEventListener' : 'removeEventListener'](eventList[i], callback, useCapture); - } - } + // Store reference + this.media.plyr = this; - // Bind event - function _on(element, events, callback, useCapture) { - if (element) { - _toggleListener(element, events, callback, true, useCapture); - } - } - - // Unbind event - function _off(element, events, callback, useCapture) { - if (element) { - _toggleListener(element, events, callback, false, useCapture); - } - } + // Wrap media + this.elements.container = utils.createElement('div'); + utils.wrap(this.media, this.elements.container); - // Trigger event - function _event(element, type, bubbles, properties) { - // Bail if no element - if (!element || !type) { - return; - } + // Allow focus to be captured + this.elements.container.setAttribute('tabindex', 0); - // Default bubbles to false - if (!_is.boolean(bubbles)) { - bubbles = false; - } + // Global listeners + listeners.global.call(this); - // Create and dispatch the event - var event = new CustomEvent(type, { - bubbles: bubbles, - detail: properties, - }); + // Add style hook + ui.addStyleHook.call(this); - // Dispatch the event - element.dispatchEvent(event); - } + // Setup media + media.setup.call(this); - // Toggle aria-pressed state on a toggle button - // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles - function _toggleState(target, state) { - // Bail if no target - if (!target) { - return; + // Listen for events if debugging + if (this.config.debug) { + utils.on(this.elements.container, this.config.events.join(' '), event => { + this.debug.log(`event: ${event.type}`); + }); } - // Get state - state = _is.boolean(state) ? state : !target.getAttribute('aria-pressed'); + // Setup interface + // If embed but not fully supported, build interface now to avoid flash of controls + if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) { + ui.build.call(this); + } + } - // Set the attribute on target - target.setAttribute('aria-pressed', state); + // --------------------------------------- + // API + // --------------------------------------- - return state; + /** + * Types and provider helpers + */ + get isHTML5() { + return this.provider === providers.html5; } - - // Get percentage - function _getPercentage(current, max) { - if (current === 0 || max === 0 || isNaN(current) || isNaN(max)) { - return 0; - } - return (current / max * 100).toFixed(2); + get isEmbed() { + return this.isYouTube || this.isVimeo; + } + get isYouTube() { + return this.provider === providers.youtube; + } + get isVimeo() { + return this.provider === providers.vimeo; + } + get isVideo() { + return this.type === types.video; + } + get isAudio() { + return this.type === types.audio; } - // Deep extend/merge destination object with N more objects - // http://andrewdupont.net/2009/08/28/deep-extending-objects-in-javascript/ - // Removed call to arguments.callee (used explicit function name instead) - function _extend() { - // Get arguments - var objects = arguments; + /** + * Play the media + */ + play() { + return this.media.play(); + } - // Bail if nothing to merge - if (!objects.length) { + /** + * Pause the media + */ + pause() { + if (!this.playing) { return; } - // Return first if specified but nothing to merge - if (objects.length === 1) { - return objects[0]; - } - - // First object is the destination - var destination = Array.prototype.shift.call(objects), - length = objects.length; - - // Loop through all objects to merge - for (var i = 0; i < length; i++) { - var source = objects[i]; - - for (var property in source) { - if (source[property] && source[property].constructor && source[property].constructor === Object) { - destination[property] = destination[property] || {}; - _extend(destination[property], source[property]); - } else { - destination[property] = source[property]; - } - } - } + this.media.pause(); + } - return destination; + /** + * Get paused state + */ + get paused() { + return this.media.paused; } - // Check variable types - var _is = { - object: function(input) { - return input !== null && typeof input === 'object'; - }, - array: function(input) { - return input !== null && (typeof input === 'object' && input.constructor === Array); - }, - number: function(input) { - return input !== null && ((typeof input === 'number' && !isNaN(input - 0)) || (typeof input === 'object' && input.constructor === Number)); - }, - string: function(input) { - return input !== null && (typeof input === 'string' || (typeof input === 'object' && input.constructor === String)); - }, - boolean: function(input) { - return input !== null && typeof input === 'boolean'; - }, - nodeList: function(input) { - return input !== null && input instanceof NodeList; - }, - htmlElement: function(input) { - return input !== null && input instanceof HTMLElement; - }, - function: function(input) { - return input !== null && typeof input === 'function'; - }, - undefined: function(input) { - return input !== null && typeof input === 'undefined'; - }, - }; - - // Parse YouTube ID from url - function _parseYouTubeId(url) { - var regex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/; - return url.match(regex) ? RegExp.$2 : url; + /** + * Get playing state + */ + get playing() { + return !this.paused && !this.ended && (this.isHTML5 ? this.media.readyState > 2 : true); } - // Parse Vimeo ID from url - function _parseVimeoId(url) { - var regex = /^.*(vimeo.com\/|video\/)(\d+).*/; - return url.match(regex) ? RegExp.$2 : url; + /** + * Get ended state + */ + get ended() { + return this.media.ended; } - // Fullscreen API - function _fullscreen() { - var fullscreen = { - supportsFullScreen: false, - isFullScreen: function() { - return false; - }, - requestFullScreen: function() {}, - cancelFullScreen: function() {}, - fullScreenEventName: '', - element: null, - prefix: '', - }, - browserPrefixes = 'webkit o moz ms khtml'.split(' '); + /** + * Toggle playback based on current status + * @param {boolean} input + */ + togglePlay(input) { + // Toggle based on current state if nothing passed + const toggle = utils.is.boolean(input) ? input : !this.playing; - // Check for native support - if (!_is.undefined(document.cancelFullScreen)) { - fullscreen.supportsFullScreen = true; + if (toggle) { + this.play(); } else { - // Check for fullscreen support by vendor prefix - for (var i = 0, il = browserPrefixes.length; i < il; i++) { - fullscreen.prefix = browserPrefixes[i]; - - if (!_is.undefined(document[fullscreen.prefix + 'CancelFullScreen'])) { - fullscreen.supportsFullScreen = true; - break; - } else if (!_is.undefined(document.msExitFullscreen) && document.msFullscreenEnabled) { - // Special case for MS (when isn't it?) - fullscreen.prefix = 'ms'; - fullscreen.supportsFullScreen = true; - break; - } - } - } - - // Update methods to do something useful - if (fullscreen.supportsFullScreen) { - // Yet again Microsoft awesomeness, - // Sometimes the prefix is 'ms', sometimes 'MS' to keep you on your toes - fullscreen.fullScreenEventName = fullscreen.prefix === 'ms' ? 'MSFullscreenChange' : fullscreen.prefix + 'fullscreenchange'; - - fullscreen.isFullScreen = function(element) { - if (_is.undefined(element)) { - element = document.body; - } - switch (this.prefix) { - case '': - return document.fullscreenElement === element; - case 'moz': - return document.mozFullScreenElement === element; - default: - return document[this.prefix + 'FullscreenElement'] === element; - } - }; - fullscreen.requestFullScreen = function(element) { - if (_is.undefined(element)) { - element = document.body; - } - return this.prefix === '' - ? element.requestFullScreen() - : element[this.prefix + (this.prefix === 'ms' ? 'RequestFullscreen' : 'RequestFullScreen')](); - }; - fullscreen.cancelFullScreen = function() { - return this.prefix === '' - ? document.cancelFullScreen() - : document[this.prefix + (this.prefix === 'ms' ? 'ExitFullscreen' : 'CancelFullScreen')](); - }; - fullscreen.element = function() { - return this.prefix === '' ? document.fullscreenElement : document[this.prefix + 'FullscreenElement']; - }; + this.pause(); } + } - return fullscreen; + /** + * Stop playback + */ + stop() { + this.restart(); + this.pause(); } - // Local storage - var _storage = { - supported: (function() { - // Try to use it (it might be disabled, e.g. user is in private/porn mode) - // see: https://github.com/sampotts/plyr/issues/131 - try { - // Add test item - window.localStorage.setItem('___test', 'OK'); + /** + * Restart playback + */ + restart() { + this.currentTime = 0; + } - // Get the test item - var result = window.localStorage.getItem('___test'); + /** + * Rewind + * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime + */ + rewind(seekTime) { + this.currentTime = this.currentTime - (utils.is.number(seekTime) ? seekTime : this.config.seekTime); + } - // Clean up - window.localStorage.removeItem('___test'); + /** + * Fast forward + * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime + */ + forward(seekTime) { + this.currentTime = this.currentTime + (utils.is.number(seekTime) ? seekTime : this.config.seekTime); + } - // Check if value matches - return result === 'OK'; - } catch (e) { - return false; - } + /** + * Seek to a time + * @param {number} input - where to seek to in seconds. Defaults to 0 (the start) + */ + set currentTime(input) { + let targetTime = 0; - return false; - })(), - }; - - // Player instance - function Plyr(media, config) { - var plyr = this, - timers = {}, - api; - - // Set media - plyr.media = media; - var original = media.cloneNode(true); - - // Trigger events, with plyr instance passed - function _triggerEvent(element, type, bubbles, properties) { - _event( - element, - type, - bubbles, - _extend({}, properties, { - plyr: api, - }) - ); + if (utils.is.number(input)) { + targetTime = input; } - // Debugging - function _console(type, args) { - if (config.debug && window.console) { - args = Array.prototype.slice.call(args); - - if (_is.string(config.logPrefix) && config.logPrefix.length) { - args.unshift(config.logPrefix); - } - - console[type].apply(console, args); - } - } - var _log = function() { - _console('log', arguments); - }, - _warn = function() { - _console('warn', arguments); - }; - - // Log config options - _log('Config', config); - - // Get icon URL - function _getIconUrl() { - return { - url: config.iconUrl, - // If you're using svg4everybody you don't need absolute paths - absolute: config.iconUrl.indexOf('http') === 0 || (plyr.browser.isIE && !window.svg4everybody), - }; + // Normalise targetTime + if (targetTime < 0) { + targetTime = 0; + } else if (targetTime > this.duration) { + targetTime = this.duration; } - // Build the default HTML - function _buildControls() { - // Create html array - var html = [], - iconUrl = _getIconUrl(), - iconPath = (!iconUrl.absolute ? iconUrl.url : '') + '#' + config.iconPrefix; - - // Larger overlaid play button - if (_inArray(config.controls, 'play-large')) { - html.push( - '<button type="button" data-plyr="play" class="plyr__play-large">', - '<svg><use xlink:href="' + iconPath + '-play" /></svg>', - '<span class="plyr__sr-only">' + config.i18n.play + '</span>', - '</button>' - ); - } + // Set + this.media.currentTime = targetTime.toFixed(4); - html.push('<div class="plyr__controls">'); - - // Restart button - if (_inArray(config.controls, 'restart')) { - html.push( - '<button type="button" data-plyr="restart">', - '<svg><use xlink:href="' + iconPath + '-restart" /></svg>', - '<span class="plyr__sr-only">' + config.i18n.restart + '</span>', - '</button>' - ); - } - - // Rewind button - if (_inArray(config.controls, 'rewind')) { - html.push( - '<button type="button" data-plyr="rewind">', - '<svg><use xlink:href="' + iconPath + '-rewind" /></svg>', - '<span class="plyr__sr-only">' + config.i18n.rewind + '</span>', - '</button>' - ); - } - - // Play Pause button - // TODO: This should be a toggle button really? - if (_inArray(config.controls, 'play')) { - html.push( - '<button type="button" data-plyr="play">', - '<svg><use xlink:href="' + iconPath + '-play" /></svg>', - '<span class="plyr__sr-only">' + config.i18n.play + '</span>', - '</button>', - '<button type="button" data-plyr="pause">', - '<svg><use xlink:href="' + iconPath + '-pause" /></svg>', - '<span class="plyr__sr-only">' + config.i18n.pause + '</span>', - '</button>' - ); - } - - // Fast forward button - if (_inArray(config.controls, 'fast-forward')) { - html.push( - '<button type="button" data-plyr="fast-forward">', - '<svg><use xlink:href="' + iconPath + '-fast-forward" /></svg>', - '<span class="plyr__sr-only">' + config.i18n.forward + '</span>', - '</button>' - ); - } - - // Progress - if (_inArray(config.controls, 'progress')) { - // Create progress - html.push( - '<span class="plyr__progress">', - '<label for="seek{id}" class="plyr__sr-only">Seek</label>', - '<input id="seek{id}" class="plyr__progress--seek" type="range" min="0" max="100" step="0.1" value="0" data-plyr="seek">', - '<progress class="plyr__progress--played" max="100" value="0" role="presentation"></progress>', - '<progress class="plyr__progress--buffer" max="100" value="0">', - '<span>0</span>% ' + config.i18n.buffered, - '</progress>' - ); - - // Seek tooltip - if (config.tooltips.seek) { - html.push('<span class="plyr__tooltip">00:00</span>'); - } - - // Close - html.push('</span>'); - } - - // Media current time display - if (_inArray(config.controls, 'current-time')) { - html.push( - '<span class="plyr__time">', - '<span class="plyr__sr-only">' + config.i18n.currentTime + '</span>', - '<span class="plyr__time--current">00:00</span>', - '</span>' - ); - } + // Logging + this.debug.log(`Seeking to ${this.currentTime} seconds`); + } - // Media duration display - if (_inArray(config.controls, 'duration')) { - html.push( - '<span class="plyr__time">', - '<span class="plyr__sr-only">' + config.i18n.duration + '</span>', - '<span class="plyr__time--duration">00:00</span>', - '</span>' - ); - } + /** + * Get current time + */ + get currentTime() { + return Number(this.media.currentTime); + } - // Toggle mute button - if (_inArray(config.controls, 'mute')) { - html.push( - '<button type="button" data-plyr="mute">', - '<svg class="icon--muted"><use xlink:href="' + iconPath + '-muted" /></svg>', - '<svg><use xlink:href="' + iconPath + '-volume" /></svg>', - '<span class="plyr__sr-only">' + config.i18n.toggleMute + '</span>', - '</button>' - ); - } + /** + * Get seeking status + */ + get seeking() { + return this.media.seeking; + } - // Volume range control - if (_inArray(config.controls, 'volume')) { - html.push( - '<span class="plyr__volume">', - '<label for="volume{id}" class="plyr__sr-only">' + config.i18n.volume + '</label>', - '<input id="volume{id}" class="plyr__volume--input" type="range" min="' + - config.volumeMin + - '" max="' + - config.volumeMax + - '" value="' + - config.volume + - '" data-plyr="volume">', - '<progress class="plyr__volume--display" max="' + config.volumeMax + '" value="' + config.volumeMin + '" role="presentation"></progress>', - '</span>' - ); - } + /** + * Get the duration of the current media + */ + get duration() { + // Faux duration set via config + const fauxDuration = parseInt(this.config.duration, 10); - // Toggle captions button - if (_inArray(config.controls, 'captions')) { - html.push( - '<button type="button" data-plyr="captions">', - '<svg class="icon--captions-on"><use xlink:href="' + iconPath + '-captions-on" /></svg>', - '<svg><use xlink:href="' + iconPath + '-captions-off" /></svg>', - '<span class="plyr__sr-only">' + config.i18n.toggleCaptions + '</span>', - '</button>' - ); - } + // True duration + const realDuration = Number(this.media.duration); - // Toggle fullscreen button - if (_inArray(config.controls, 'fullscreen')) { - html.push( - '<button type="button" data-plyr="fullscreen">', - '<svg class="icon--exit-fullscreen"><use xlink:href="' + iconPath + '-exit-fullscreen" /></svg>', - '<svg><use xlink:href="' + iconPath + '-enter-fullscreen" /></svg>', - '<span class="plyr__sr-only">' + config.i18n.toggleFullscreen + '</span>', - '</button>' - ); - } + // If custom duration is funky, use regular duration + return !Number.isNaN(fauxDuration) ? fauxDuration : realDuration; + } - // Close everything - html.push('</div>'); + /** + * Set the player volume + * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage + */ + set volume(value) { + let volume = value; + const max = 1; + const min = 0; - return html.join(''); + if (utils.is.string(volume)) { + volume = Number(volume); } - // Setup fullscreen - function _setupFullscreen() { - if (!plyr.supported.full) { - return; - } - - if ((plyr.type !== 'audio' || config.fullscreen.allowAudio) && config.fullscreen.enabled) { - // Check for native support - var nativeSupport = fullscreen.supportsFullScreen; - - if (nativeSupport || (config.fullscreen.fallback && !_inFrame())) { - _log((nativeSupport ? 'Native' : 'Fallback') + ' fullscreen enabled'); - - // Add styling hook - if (!nativeSupport) { - _toggleClass(plyr.container, config.classes.fullscreen.fallback, true); - } - - // Add styling hook - _toggleClass(plyr.container, config.classes.fullscreen.enabled, true); - } else { - _log('Fullscreen not supported and fallback disabled'); - } - - // Toggle state - if (plyr.buttons && plyr.buttons.fullscreen) { - _toggleState(plyr.buttons.fullscreen, false); - } - - // Setup focus trap - _focusTrap(); - } + // Load volume from storage if no value specified + if (!utils.is.number(volume)) { + volume = this.storage.get('volume'); } - // Setup captions - function _setupCaptions() { - // Bail if not HTML5 video - if (plyr.type !== 'video') { - return; - } - - // Inject the container - if (!_getElement(config.selectors.captions)) { - plyr.videoContainer.insertAdjacentHTML('afterbegin', '<div class="' + _getClassname(config.selectors.captions) + '"></div>'); - } - - // Determine if HTML5 textTracks is supported - plyr.usingTextTracks = false; - if (plyr.media.textTracks) { - plyr.usingTextTracks = true; - } - - // Get URL of caption file if exists - var captionSrc = '', - kind, - children = plyr.media.childNodes; - - for (var i = 0; i < children.length; i++) { - if (children[i].nodeName.toLowerCase() === 'track') { - kind = children[i].kind; - if (kind === 'captions' || kind === 'subtitles') { - captionSrc = children[i].getAttribute('src'); - } - } - } - - // Record if caption file exists or not - plyr.captionExists = true; - if (captionSrc === '') { - plyr.captionExists = false; - _log('No caption track found'); - } else { - _log('Caption track found; URI: ' + captionSrc); - } - - // If no caption file exists, hide container for caption text - if (!plyr.captionExists) { - _toggleClass(plyr.container, config.classes.captions.enabled); - } else { - // Turn off native caption rendering to avoid double captions - // This doesn't seem to work in Safari 7+, so the <track> elements are removed from the dom below - var tracks = plyr.media.textTracks; - for (var x = 0; x < tracks.length; x++) { - tracks[x].mode = 'hidden'; - } - - // Enable UI - _showCaptions(plyr); - - // Disable unsupported browsers than report false positive - // Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1033144 - if ((plyr.browser.isIE && plyr.browser.version >= 10) || (plyr.browser.isFirefox && plyr.browser.version >= 31)) { - // Debugging - _log('Detected browser with known TextTrack issues - using manual fallback'); - - // Set to false so skips to 'manual' captioning - plyr.usingTextTracks = false; - } - - // Rendering caption tracks - // Native support required - http://caniuse.com/webvtt - if (plyr.usingTextTracks) { - _log('TextTracks supported'); - - for (var y = 0; y < tracks.length; y++) { - var track = tracks[y]; - - if (track.kind === 'captions' || track.kind === 'subtitles') { - _on(track, 'cuechange', function() { - // Display a cue, if there is one - if (this.activeCues[0] && 'text' in this.activeCues[0]) { - _setCaption(this.activeCues[0].getCueAsHTML()); - } else { - _setCaption(); - } - }); - } - } - } else { - // Caption tracks not natively supported - _log('TextTracks not supported so rendering captions manually'); - - // Render captions from array at appropriate time - plyr.currentCaption = ''; - plyr.captions = []; - - if (captionSrc !== '') { - // Create XMLHttpRequest Object - var xhr = new XMLHttpRequest(); - - xhr.onreadystatechange = function() { - if (xhr.readyState === 4) { - if (xhr.status === 200) { - var captions = [], - caption, - req = xhr.responseText; - - //According to webvtt spec, line terminator consists of one of the following - // CRLF (U+000D U+000A), LF (U+000A) or CR (U+000D) - var lineSeparator = '\r\n'; - if (req.indexOf(lineSeparator + lineSeparator) === -1) { - if (req.indexOf('\r\r') !== -1) { - lineSeparator = '\r'; - } else { - lineSeparator = '\n'; - } - } - - captions = req.split(lineSeparator + lineSeparator); - - for (var r = 0; r < captions.length; r++) { - caption = captions[r]; - plyr.captions[r] = []; - - // Get the parts of the captions - var parts = caption.split(lineSeparator), - index = 0; - - // Incase caption numbers are added - if (parts[index].indexOf(':') === -1) { - index = 1; - } - - plyr.captions[r] = [parts[index], parts[index + 1]]; - } - - // Remove first element ('VTT') - plyr.captions.shift(); - - _log('Successfully loaded the caption file via AJAX'); - } else { - _warn(config.logPrefix + 'There was a problem loading the caption file via AJAX'); - } - } - }; - - xhr.open('get', captionSrc, true); - - xhr.send(); - } - } - } + // Use config if all else fails + if (!utils.is.number(volume)) { + ({ volume } = this.config); } - // Set the current caption - function _setCaption(caption) { - /* jshint unused:false */ - var container = _getElement(config.selectors.captions), - content = document.createElement('span'); - - // Empty the container - container.innerHTML = ''; - - // Default to empty - if (_is.undefined(caption)) { - caption = ''; - } - - // Set the span content - if (_is.string(caption)) { - content.innerHTML = caption.trim(); - } else { - content.appendChild(caption); - } - - // Set new caption text - container.appendChild(content); - - // Force redraw (for Safari) - var redraw = container.offsetHeight; + // Maximum is volumeMax + if (volume > max) { + volume = max; } - - // Captions functions - // Seek the manual caption time and update UI - function _seekManualCaptions(time) { - // Utilities for caption time codes - function _timecodeCommon(tc, pos) { - var tcpair = []; - tcpair = tc.split(' --> '); - for (var i = 0; i < tcpair.length; i++) { - // WebVTT allows for extra meta data after the timestamp line - // So get rid of this if it exists - tcpair[i] = tcpair[i].replace(/(\d+:\d+:\d+\.\d+).*/, '$1'); - } - return _subTcSecs(tcpair[pos]); - } - function _timecodeMin(tc) { - return _timecodeCommon(tc, 0); - } - function _timecodeMax(tc) { - return _timecodeCommon(tc, 1); - } - function _subTcSecs(tc) { - if (tc === null || tc === undefined) { - return 0; - } else { - var tc1 = [], - tc2 = [], - seconds; - tc1 = tc.split(','); - tc2 = tc1[0].split(':'); - seconds = Math.floor(tc2[0] * 60 * 60) + Math.floor(tc2[1] * 60) + Math.floor(tc2[2]); - return seconds; - } - } - - // If it's not video, or we're using textTracks, bail. - if (plyr.usingTextTracks || plyr.type !== 'video' || !plyr.supported.full) { - return; - } - - // Reset subcount - plyr.subcount = 0; - - // Check time is a number, if not use currentTime - // IE has a bug where currentTime doesn't go to 0 - // https://twitter.com/Sam_Potts/status/573715746506731521 - time = _is.number(time) ? time : plyr.media.currentTime; - - // If there's no subs available, bail - if (!plyr.captions[plyr.subcount]) { - return; - } - - while (_timecodeMax(plyr.captions[plyr.subcount][0]) < time.toFixed(1)) { - plyr.subcount++; - if (plyr.subcount > plyr.captions.length - 1) { - plyr.subcount = plyr.captions.length - 1; - break; - } - } - - // Check if the next caption is in the current time range - if ( - plyr.media.currentTime.toFixed(1) >= _timecodeMin(plyr.captions[plyr.subcount][0]) && - plyr.media.currentTime.toFixed(1) <= _timecodeMax(plyr.captions[plyr.subcount][0]) - ) { - plyr.currentCaption = plyr.captions[plyr.subcount][1]; - - // Render the caption - _setCaption(plyr.currentCaption); - } else { - _setCaption(); - } + // Minimum is volumeMin + if (volume < min) { + volume = min; } - // Display captions container and button (for initialization) - function _showCaptions() { - // If there's no caption toggle, bail - if (!plyr.buttons.captions) { - return; - } - - _toggleClass(plyr.container, config.classes.captions.enabled, true); + // Update config + this.config.volume = volume; - // Try to load the value from storage - var active = plyr.storage.captionsEnabled; + // Set the player volume + this.media.volume = volume; - // Otherwise fall back to the default config - if (!_is.boolean(active)) { - active = config.captions.defaultActive; - } - - if (active) { - _toggleClass(plyr.container, config.classes.captions.active, true); - _toggleState(plyr.buttons.captions, true); - } + // If muted, and we're increasing volume, reset muted state + if (this.muted && volume > 0) { + this.muted = false; } + } - // Find all elements - function _getElements(selector) { - return plyr.container.querySelectorAll(selector); - } + /** + * Get the current player volume + */ + get volume() { + return this.media.volume; + } - // Find a single element - function _getElement(selector) { - return _getElements(selector)[0]; - } + /** + * Increase volume + * @param {boolean} step - How much to decrease by (between 0 and 1) + */ + increaseVolume(step) { + const volume = this.media.muted ? 0 : this.volume; + this.volume = volume + (utils.is.number(step) ? step : 1); + } - // Determine if we're in an iframe - function _inFrame() { - try { - return window.self !== window.top; - } catch (e) { - return true; - } - } + /** + * Decrease volume + * @param {boolean} step - How much to decrease by (between 0 and 1) + */ + decreaseVolume(step) { + const volume = this.media.muted ? 0 : this.volume; + this.volume = volume - (utils.is.number(step) ? step : 1); + } - // Trap focus inside container - function _focusTrap() { - var tabbables = _getElements('input:not([disabled]), button:not([disabled])'), - first = tabbables[0], - last = tabbables[tabbables.length - 1]; - - function _checkFocus(event) { - // If it is TAB - if (event.which === 9 && plyr.isFullscreen) { - if (event.target === last && !event.shiftKey) { - // Move focus to first element that can be tabbed if Shift isn't used - event.preventDefault(); - first.focus(); - } else if (event.target === first && event.shiftKey) { - // Move focus to last element that can be tabbed if Shift is used - event.preventDefault(); - last.focus(); - } - } - } + /** + * Set muted state + * @param {boolean} mute + */ + set muted(mute) { + let toggle = mute; - // Bind the handler - _on(plyr.container, 'keydown', _checkFocus); + // Load muted state from storage + if (!utils.is.boolean(toggle)) { + toggle = this.storage.get('muted'); } - // Add elements to HTML5 media (source, tracks, etc) - function _insertChildElements(type, attributes) { - if (_is.string(attributes)) { - _insertElement(type, plyr.media, { src: attributes }); - } else if (attributes.constructor === Array) { - for (var i = attributes.length - 1; i >= 0; i--) { - _insertElement(type, plyr.media, attributes[i]); - } - } + // Use config if all else fails + if (!utils.is.boolean(toggle)) { + toggle = this.config.muted; } - // Insert controls - function _injectControls() { - // Sprite - if (config.loadSprite) { - var iconUrl = _getIconUrl(); - - // Only load external sprite using AJAX - if (iconUrl.absolute) { - _log('AJAX loading absolute SVG sprite' + (plyr.browser.isIE ? ' (due to IE)' : '')); - loadSprite(iconUrl.url, 'sprite-plyr'); - } else { - _log('Sprite will be used as external resource directly'); - } - } - - // Make a copy of the html - var html = config.html; - - // Insert custom video controls - _log('Injecting custom controls'); - - // If no controls are specified, create default - if (!html) { - html = _buildControls(); - } - - // Replace seek time instances - html = _replaceAll(html, '{seektime}', config.seekTime); + // Update config + this.config.muted = toggle; - // Replace all id references with random numbers - html = _replaceAll(html, '{id}', Math.floor(Math.random() * 10000)); - - // Replace Title, if it exists - if (config.title) { - html = _replaceAll(html, '{title}', config.title); - } - - // Controls container - var target; - - // Inject to custom location - if (_is.string(config.selectors.controls.container)) { - target = document.querySelector(config.selectors.controls.container); - } - - // Inject into the container by default - if (!_is.htmlElement(target)) { - target = plyr.container; - } - - // Inject controls HTML - target.insertAdjacentHTML('beforeend', html); - - // Setup tooltips - if (config.tooltips.controls) { - var labels = _getElements([config.selectors.controls.wrapper, ' ', config.selectors.labels, ' .', config.classes.hidden].join('')); + // Set mute on the player + this.media.muted = toggle; + } - for (var i = labels.length - 1; i >= 0; i--) { - var label = labels[i]; + /** + * Get current muted state + */ + get muted() { + return this.media.muted; + } - _toggleClass(label, config.classes.hidden, false); - _toggleClass(label, config.classes.tooltip, true); - } - } + /** + * Check if the media has audio + */ + get hasAudio() { + // Assume yes for all non HTML5 (as we can't tell...) + if (!this.isHTML5) { + return true; } - // Find the UI controls and store references - function _findElements() { - try { - plyr.controls = _getElement(config.selectors.controls.wrapper); - - // Buttons - plyr.buttons = {}; - plyr.buttons.seek = _getElement(config.selectors.buttons.seek); - plyr.buttons.play = _getElements(config.selectors.buttons.play); - plyr.buttons.pause = _getElement(config.selectors.buttons.pause); - plyr.buttons.restart = _getElement(config.selectors.buttons.restart); - plyr.buttons.rewind = _getElement(config.selectors.buttons.rewind); - plyr.buttons.forward = _getElement(config.selectors.buttons.forward); - plyr.buttons.fullscreen = _getElement(config.selectors.buttons.fullscreen); - - // Inputs - plyr.buttons.mute = _getElement(config.selectors.buttons.mute); - plyr.buttons.captions = _getElement(config.selectors.buttons.captions); - - // Progress - plyr.progress = {}; - plyr.progress.container = _getElement(config.selectors.progress.container); - - // Progress - Buffering - plyr.progress.buffer = {}; - plyr.progress.buffer.bar = _getElement(config.selectors.progress.buffer); - plyr.progress.buffer.text = plyr.progress.buffer.bar && plyr.progress.buffer.bar.getElementsByTagName('span')[0]; - - // Progress - Played - plyr.progress.played = _getElement(config.selectors.progress.played); - - // Seek tooltip - plyr.progress.tooltip = plyr.progress.container && plyr.progress.container.querySelector('.' + config.classes.tooltip); - - // Volume - plyr.volume = {}; - plyr.volume.input = _getElement(config.selectors.volume.input); - plyr.volume.display = _getElement(config.selectors.volume.display); - - // Timing - plyr.duration = _getElement(config.selectors.duration); - plyr.currentTime = _getElement(config.selectors.currentTime); - plyr.seekTime = _getElements(config.selectors.seekTime); - - return true; - } catch (e) { - _warn('It looks like there is a problem with your controls HTML'); + // Get audio tracks + return this.media.mozHasAudio || Boolean(this.media.webkitAudioDecodedByteCount) || Boolean(this.media.audioTracks && this.media.audioTracks.length); + } - // Restore native video controls - _toggleNativeControls(true); + /** + * Set playback speed + * @param {decimal} speed - the speed of playback (0.5-2.0) + */ + set speed(input) { + let speed = null; - return false; - } + if (utils.is.number(input)) { + speed = input; } - // Toggle style hook - function _toggleStyleHook() { - _toggleClass(plyr.container, config.selectors.container.replace('.', ''), plyr.supported.full); + if (!utils.is.number(speed)) { + speed = this.storage.get('speed'); } - // Toggle native controls - function _toggleNativeControls(toggle) { - if (toggle && _inArray(config.types.html5, plyr.type)) { - plyr.media.setAttribute('controls', ''); - } else { - plyr.media.removeAttribute('controls'); - } + if (!utils.is.number(speed)) { + speed = this.config.speed.selected; } - // Setup aria attribute for play and iframe title - function _setTitle(iframe) { - // Find the current text - var label = config.i18n.play; - - // If there's a media title set, use that for the label - if (_is.string(config.title) && config.title.length) { - label += ', ' + config.title; - - // Set container label - plyr.container.setAttribute('aria-label', config.title); - } - - // If there's a play button, set label - if (plyr.supported.full && plyr.buttons.play) { - for (var i = plyr.buttons.play.length - 1; i >= 0; i--) { - plyr.buttons.play[i].setAttribute('aria-label', label); - } - } - - // Set iframe title - // https://github.com/sampotts/plyr/issues/124 - if (_is.htmlElement(iframe)) { - iframe.setAttribute('title', config.i18n.frameTitle.replace('{title}', config.title)); - } + // Set min/max + if (speed < 0.1) { + speed = 0.1; } - - // Setup localStorage - function _setupStorage() { - var value = null; - plyr.storage = {}; - - // Bail if we don't have localStorage support or it's disabled - if (!_storage.supported || !config.storage.enabled) { - return; - } - - // Clean up old volume - // https://github.com/sampotts/plyr/issues/171 - window.localStorage.removeItem('plyr-volume'); - - // load value from the current key - value = window.localStorage.getItem(config.storage.key); - - if (!value) { - // Key wasn't set (or had been cleared), move along - return; - } else if (/^\d+(\.\d+)?$/.test(value)) { - // If value is a number, it's probably volume from an older - // version of plyr. See: https://github.com/sampotts/plyr/pull/313 - // Update the key to be JSON - _updateStorage({ volume: parseFloat(value) }); - } else { - // Assume it's JSON from this or a later version of plyr - plyr.storage = JSON.parse(value); - } + if (speed > 2.0) { + speed = 2.0; } - // Save a value back to local storage - function _updateStorage(value) { - // Bail if we don't have localStorage support or it's disabled - if (!_storage.supported || !config.storage.enabled) { - return; - } - - // Update the working copy of the values - _extend(plyr.storage, value); - - // Update storage - window.localStorage.setItem(config.storage.key, JSON.stringify(plyr.storage)); + if (!this.config.speed.options.includes(speed)) { + this.debug.warn(`Unsupported speed (${speed})`); + return; } - // Setup media - function _setupMedia() { - // If there's no media, bail - if (!plyr.media) { - _warn('No media element found!'); - return; - } - - if (plyr.supported.full) { - // Add type class - _toggleClass(plyr.container, config.classes.type.replace('{0}', plyr.type), true); - - // Add video class for embeds - // This will require changes if audio embeds are added - if (_inArray(config.types.embed, plyr.type)) { - _toggleClass(plyr.container, config.classes.type.replace('{0}', 'video'), true); - } - - // If there's no autoplay attribute, assume the video is stopped and add state class - _toggleClass(plyr.container, config.classes.stopped, config.autoplay); - - // Add iOS class - _toggleClass(plyr.container, config.classes.isIos, plyr.browser.isIos); - - // Add touch class - _toggleClass(plyr.container, config.classes.isTouch, plyr.browser.isTouch); + // Update config + this.config.speed.selected = speed; - // Inject the player wrapper - if (plyr.type === 'video') { - // Create the wrapper div - var wrapper = document.createElement('div'); - wrapper.setAttribute('class', config.classes.videoWrapper); + // Set media speed + this.media.playbackRate = speed; + } - // Wrap the video in a container - _wrap(plyr.media, wrapper); + /** + * Get current playback speed + */ + get speed() { + return this.media.playbackRate; + } - // Cache the container - plyr.videoContainer = wrapper; - } - } + /** + * Set playback quality + * Currently YouTube only + * @param {string} input - Quality level + */ + set quality(input) { + let quality = null; - // Embeds - if (_inArray(config.types.embed, plyr.type)) { - _setupEmbed(); - } + if (utils.is.string(input)) { + quality = input; } - // Setup YouTube/Vimeo - function _setupEmbed() { - var container = document.createElement('div'), - mediaId, - mediaUrl, - id = plyr.type + '-' + Math.floor(Math.random() * 10000); - - // Parse IDs from URLs if supplied - switch (plyr.type) { - case 'youtube': - mediaId = _parseYouTubeId(plyr.embedId); - break; - - case 'vimeo': - mediaId = _parseVimeoId(plyr.embedId); - break; - - default: - mediaId = plyr.embedId; - } - - // Remove old containers - var containers = _getElements('[id^="' + plyr.type + '-"]'); - for (var i = containers.length - 1; i >= 0; i--) { - _remove(containers[i]); - } - - // Add embed class for responsive - _toggleClass(plyr.media, config.classes.videoWrapper, true); - _toggleClass(plyr.media, config.classes.embedWrapper, true); - - if (plyr.type === 'youtube') { - // Create the YouTube container - plyr.media.appendChild(container); - - // Set ID - container.setAttribute('id', id); - - // Setup API - if (_is.object(window.YT)) { - _youTubeReady(mediaId, container); - } else { - // Load the API - _injectScript(config.urls.youtube.api); - - // Setup callback for the API - window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || []; - - // Add to queue - window.onYouTubeReadyCallbacks.push(function() { - _youTubeReady(mediaId, container); - }); - - // Set callback to process queue - window.onYouTubeIframeAPIReady = function() { - window.onYouTubeReadyCallbacks.forEach(function(callback) { - callback(); - }); - }; - } - } else if (plyr.type === 'vimeo') { - // Vimeo needs an extra div to hide controls on desktop (which has full support) - if (plyr.supported.full) { - plyr.media.appendChild(container); - } else { - container = plyr.media; - } - - // Set ID - container.setAttribute('id', id); - - // Load the API if not already - if (!_is.object(window.Vimeo)) { - _injectScript(config.urls.vimeo.api); - - // Wait for fragaloop load - var vimeoTimer = window.setInterval(function() { - if (_is.object(window.Vimeo)) { - window.clearInterval(vimeoTimer); - _vimeoReady(mediaId, container); - } - }, 50); - } else { - _vimeoReady(mediaId, container); - } - } else if (plyr.type === 'soundcloud') { - // TODO: Currently unsupported and undocumented - // Inject the iframe - var soundCloud = document.createElement('iframe'); - - // Watch for iframe load - soundCloud.loaded = false; - _on(soundCloud, 'load', function() { - soundCloud.loaded = true; - }); - - _setAttributes(soundCloud, { - src: 'https://w.soundcloud.com/player/?url=https://api.soundcloud.com/tracks/' + mediaId, - id: id, - }); - - container.appendChild(soundCloud); - plyr.media.appendChild(container); - - // Load the API if not already - if (!window.SC) { - _injectScript(config.urls.soundcloud.api); - } - - // Wait for SC load - var soundCloudTimer = window.setInterval(function() { - if (window.SC && soundCloud.loaded) { - window.clearInterval(soundCloudTimer); - _soundcloudReady.call(soundCloud); - } - }, 50); - } + if (!utils.is.string(quality)) { + quality = this.storage.get('quality'); } - // When embeds are ready - function _embedReady() { - // Setup the UI and call ready if full support - if (plyr.supported.full) { - _setupInterface(); - _ready(); - } - - // Set title - _setTitle(_getElement('iframe')); + if (!utils.is.string(quality)) { + quality = this.config.quality.selected; } - // Handle YouTube API ready - function _youTubeReady(videoId, container) { - // Setup instance - // https://developers.google.com/youtube/iframe_api_reference - plyr.embed = new window.YT.Player(container.id, { - videoId: videoId, - playerVars: { - autoplay: config.autoplay ? 1 : 0, - controls: plyr.supported.full ? 0 : 1, - rel: 0, - showinfo: 0, - iv_load_policy: 3, - cc_load_policy: config.captions.defaultActive ? 1 : 0, - cc_lang_pref: 'en', - wmode: 'transparent', - modestbranding: 1, - disablekb: 1, - origin: '*', // https://code.google.com/p/gdata-issues/issues/detail?id=5788#c45 - }, - events: { - onError: function(event) { - _triggerEvent(plyr.container, 'error', true, { - code: event.data, - embed: event.target, - }); - }, - onReady: function(event) { - // Get the instance - var instance = event.target; - - // Create a faux HTML5 API using the YouTube API - plyr.media.play = function() { - instance.playVideo(); - plyr.media.paused = false; - }; - plyr.media.pause = function() { - instance.pauseVideo(); - plyr.media.paused = true; - }; - plyr.media.stop = function() { - instance.stopVideo(); - plyr.media.paused = true; - }; - plyr.media.duration = instance.getDuration(); - plyr.media.paused = true; - plyr.media.currentTime = 0; - plyr.media.muted = instance.isMuted(); - - // Set title if possible - if (typeof instance.getVideoData === 'function') { - config.title = instance.getVideoData().title; - } - - // Set the tabindex - if (plyr.supported.full) { - plyr.media.querySelector('iframe').setAttribute('tabindex', '-1'); - } - - // Update UI - _embedReady(); - - // Trigger timeupdate - _triggerEvent(plyr.media, 'timeupdate'); - - // Trigger timeupdate - _triggerEvent(plyr.media, 'durationchange'); - - // Reset timer - window.clearInterval(timers.buffering); - - // Setup buffering - timers.buffering = window.setInterval(function() { - // Get loaded % from YouTube - plyr.media.buffered = instance.getVideoLoadedFraction(); - - // Trigger progress only when we actually buffer something - if (plyr.media.lastBuffered === null || plyr.media.lastBuffered < plyr.media.buffered) { - _triggerEvent(plyr.media, 'progress'); - } - - // Set last buffer point - plyr.media.lastBuffered = plyr.media.buffered; - - // Bail if we're at 100% - if (plyr.media.buffered === 1) { - window.clearInterval(timers.buffering); - - // Trigger event - _triggerEvent(plyr.media, 'canplaythrough'); - } - }, 200); - }, - onStateChange: function(event) { - // Get the instance - var instance = event.target; - - // Reset timer - window.clearInterval(timers.playing); - - // Handle events - // -1 Unstarted - // 0 Ended - // 1 Playing - // 2 Paused - // 3 Buffering - // 5 Video cued - switch (event.data) { - case 0: - plyr.media.paused = true; - _triggerEvent(plyr.media, 'ended'); - break; - - case 1: - plyr.media.paused = false; - - // If we were seeking, fire seeked event - if (plyr.media.seeking) { - _triggerEvent(plyr.media, 'seeked'); - } - - plyr.media.seeking = false; - _triggerEvent(plyr.media, 'play'); - _triggerEvent(plyr.media, 'playing'); - - // Poll to get playback progress - timers.playing = window.setInterval(function() { - // Set the current time - plyr.media.currentTime = instance.getCurrentTime(); - - // Trigger timeupdate - _triggerEvent(plyr.media, 'timeupdate'); - }, 100); - - // Check duration again due to YouTube bug - // https://github.com/sampotts/plyr/issues/374 - // https://code.google.com/p/gdata-issues/issues/detail?id=8690 - if (plyr.media.duration !== instance.getDuration()) { - plyr.media.duration = instance.getDuration(); - _triggerEvent(plyr.media, 'durationchange'); - } - - break; - - case 2: - plyr.media.paused = true; - _triggerEvent(plyr.media, 'pause'); - break; - } - - _triggerEvent(plyr.container, 'statechange', false, { - code: event.data, - }); - }, - }, - }); + if (!this.options.quality.includes(quality)) { + this.debug.warn(`Unsupported quality option (${quality})`); + return; } - // Vimeo ready - function _vimeoReady(mediaId, container) { - // Setup instance - // https://github.com/vimeo/player.js - - var options = { - loop: config.loop, - autoplay: config.autoplay, - byline: false, - portrait: false, - title: false, - speed: true, - transparent: 0, - }; - - // Convert options into URL params for iframe - function buildUrlParameters(options) { - return Object.keys(options) - .map(function(key) { - return encodeURIComponent(key) + '=' + encodeURIComponent(options[key]); - }) - .join('&'); - } + // Update config + this.config.quality.selected = quality; - // Get Vimeo params for the iframe - var params = buildUrlParameters(options); - - // Build an iframe - var iframe = document.createElement('iframe'); - var src = 'https://player.vimeo.com/video/' + mediaId + '?' + params; - iframe.setAttribute('src', src); - iframe.setAttribute('allowfullscreen', ''); - container.appendChild(iframe); - - plyr.embed = new window.Vimeo.Player(iframe); - - // Create a faux HTML5 API using the Vimeo API - plyr.media.play = function() { - plyr.embed.play(); - plyr.media.paused = false; - }; - plyr.media.pause = function() { - plyr.embed.pause(); - plyr.media.paused = true; - }; - plyr.media.stop = function() { - plyr.embed.stop(); - plyr.media.paused = true; - }; - - plyr.media.paused = true; - plyr.media.currentTime = 0; - - // Update UI - _embedReady(); - - plyr.embed.getCurrentTime().then(function(value) { - plyr.media.currentTime = value; - - // Trigger timeupdate - _triggerEvent(plyr.media, 'timeupdate'); - }); + // Set quality + this.media.quality = quality; + } - plyr.embed.getDuration().then(function(value) { - plyr.media.duration = value; + /** + * Get current quality level + */ + get quality() { + return this.media.quality; + } - // Trigger timeupdate - _triggerEvent(plyr.media, 'durationchange'); - }); + /** + * Toggle loop + * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config + * @param {boolean} input - Whether to loop or not + */ + set loop(input) { + const toggle = utils.is.boolean(input) ? input : this.config.loop.active; + this.config.loop.active = toggle; + this.media.loop = toggle; - // TODO: Captions - /*if (config.captions.defaultActive) { - plyr.embed.enableTextTrack('en'); - }*/ + // Set default to be a true toggle + /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle'; - plyr.embed.on('loaded', function() { - // Fix keyboard focus issues - // https://github.com/sampotts/plyr/issues/317 - if (_is.htmlElement(plyr.embed.element) && plyr.supported.full) { - plyr.embed.element.setAttribute('tabindex', '-1'); + switch (type) { + case 'start': + if (this.config.loop.end && this.config.loop.end <= this.currentTime) { + this.config.loop.end = null; } - }); - - plyr.embed.on('play', function() { - plyr.media.paused = false; - _triggerEvent(plyr.media, 'play'); - _triggerEvent(plyr.media, 'playing'); - }); - - plyr.embed.on('pause', function() { - plyr.media.paused = true; - _triggerEvent(plyr.media, 'pause'); - }); - - plyr.embed.on('timeupdate', function(data) { - plyr.media.seeking = false; - plyr.media.currentTime = data.seconds; - _triggerEvent(plyr.media, 'timeupdate'); - }); - - plyr.embed.on('progress', function(data) { - plyr.media.buffered = data.percent; - _triggerEvent(plyr.media, 'progress'); + this.config.loop.start = this.currentTime; + // this.config.loop.indicator.start = this.elements.display.played.value; + break; - if (parseInt(data.percent) === 1) { - // Trigger event - _triggerEvent(plyr.media, 'canplaythrough'); + case 'end': + if (this.config.loop.start >= this.currentTime) { + return this; } - }); - - plyr.embed.on('seeked', function() { - plyr.media.seeking = false; - _triggerEvent(plyr.media, 'seeked'); - _triggerEvent(plyr.media, 'play'); - }); - - plyr.embed.on('ended', function() { - plyr.media.paused = true; - _triggerEvent(plyr.media, 'ended'); - }); - } - - // Soundcloud ready - function _soundcloudReady() { - /* jshint validthis: true */ - plyr.embed = window.SC.Widget(this); - - // Setup on ready - plyr.embed.bind(window.SC.Widget.Events.READY, function() { - // Create a faux HTML5 API using the Soundcloud API - plyr.media.play = function() { - plyr.embed.play(); - plyr.media.paused = false; - }; - plyr.media.pause = function() { - plyr.embed.pause(); - plyr.media.paused = true; - }; - plyr.media.stop = function() { - plyr.embed.seekTo(0); - plyr.embed.pause(); - plyr.media.paused = true; - }; - - plyr.media.paused = true; - plyr.media.currentTime = 0; - - plyr.embed.getDuration(function(value) { - plyr.media.duration = value / 1000; - - // Update UI - _embedReady(); - }); - - plyr.embed.getPosition(function(value) { - plyr.media.currentTime = value; - - // Trigger timeupdate - _triggerEvent(plyr.media, 'timeupdate'); - }); - - plyr.embed.bind(window.SC.Widget.Events.PLAY, function() { - plyr.media.paused = false; - _triggerEvent(plyr.media, 'play'); - _triggerEvent(plyr.media, 'playing'); - }); - - plyr.embed.bind(window.SC.Widget.Events.PAUSE, function() { - plyr.media.paused = true; - _triggerEvent(plyr.media, 'pause'); - }); - - plyr.embed.bind(window.SC.Widget.Events.PLAY_PROGRESS, function(data) { - plyr.media.seeking = false; - plyr.media.currentTime = data.currentPosition / 1000; - _triggerEvent(plyr.media, 'timeupdate'); - }); - - plyr.embed.bind(window.SC.Widget.Events.LOAD_PROGRESS, function(data) { - plyr.media.buffered = data.loadProgress; - _triggerEvent(plyr.media, 'progress'); - - if (parseInt(data.loadProgress) === 1) { - // Trigger event - _triggerEvent(plyr.media, 'canplaythrough'); - } - }); + this.config.loop.end = this.currentTime; + // this.config.loop.indicator.end = this.elements.display.played.value; + break; - plyr.embed.bind(window.SC.Widget.Events.FINISH, function() { - plyr.media.paused = true; - _triggerEvent(plyr.media, 'ended'); - }); - }); - } + case 'all': + this.config.loop.start = 0; + this.config.loop.end = this.duration - 2; + this.config.loop.indicator.start = 0; + this.config.loop.indicator.end = 100; + break; - // Play media - function _play() { - if ('play' in plyr.media) { - plyr.media.play(); - } - } + case 'toggle': + if (this.config.loop.active) { + this.config.loop.start = 0; + this.config.loop.end = null; + } else { + this.config.loop.start = 0; + this.config.loop.end = this.duration - 2; + } + break; - // Pause media - function _pause() { - if ('pause' in plyr.media) { - plyr.media.pause(); - } - } + default: + this.config.loop.start = 0; + this.config.loop.end = null; + break; + } */ + } - // Toggle playback - function _togglePlay(toggle) { - // True toggle - if (!_is.boolean(toggle)) { - toggle = plyr.media.paused; - } + /** + * Get current loop state + */ + get loop() { + return this.media.loop; + } - if (toggle) { - _play(); - } else { - _pause(); - } + /** + * Set new media source + * @param {object} input - The new source object (see docs) + */ + set source(input) { + source.change.call(this, input); + } - return toggle; - } + /** + * Get current source + */ + get source() { + return this.media.currentSrc; + } - // Rewind - function _rewind(seekTime) { - // Use default if needed - if (!_is.number(seekTime)) { - seekTime = config.seekTime; - } - _seek(plyr.media.currentTime - seekTime); + /** + * Set the poster image for a HTML5 video + * @param {input} - the URL for the new poster image + */ + set poster(input) { + if (!this.isHTML5 || !this.isVideo) { + this.debug.warn('Poster can only be set on HTML5 video'); + return; } - // Fast forward - function _forward(seekTime) { - // Use default if needed - if (!_is.number(seekTime)) { - seekTime = config.seekTime; - } - _seek(plyr.media.currentTime + seekTime); + if (utils.is.string(input)) { + this.media.setAttribute('poster', input); } + } - // Seek to time - // The input parameter can be an event or a number - function _seek(input) { - var targetTime = 0, - paused = plyr.media.paused, - duration = _getDuration(); - - if (_is.number(input)) { - targetTime = input; - } else if (_is.object(input) && _inArray(['input', 'change'], input.type)) { - // It's the seek slider - // Seek to the selected time - targetTime = input.target.value / input.target.max * duration; - } - - // Normalise targetTime - if (targetTime < 0) { - targetTime = 0; - } else if (targetTime > duration) { - targetTime = duration; - } - - // Update seek range and progress - _updateSeekDisplay(targetTime); - - // Set the current time - // Try/catch incase the media isn't set and we're calling seek() from source() and IE moans - try { - plyr.media.currentTime = targetTime.toFixed(4); - } catch (e) {} - - // Embeds - if (_inArray(config.types.embed, plyr.type)) { - switch (plyr.type) { - case 'youtube': - plyr.embed.seekTo(targetTime); - break; - - case 'vimeo': - // Round to nearest second for vimeo - plyr.embed.setCurrentTime(targetTime.toFixed(0)); - break; - - case 'soundcloud': - plyr.embed.seekTo(targetTime * 1000); - break; - } - - if (paused) { - _pause(); - } - - // Trigger timeupdate - _triggerEvent(plyr.media, 'timeupdate'); - - // Set seeking flag - plyr.media.seeking = true; - - // Trigger seeking - _triggerEvent(plyr.media, 'seeking'); - } - - // Logging - _log('Seeking to ' + plyr.media.currentTime + ' seconds'); - - // Special handling for 'manual' captions - _seekManualCaptions(targetTime); + /** + * Get the current poster image + */ + get poster() { + if (!this.isHTML5 || !this.isVideo) { + return null; } - // Get the duration (or custom if set) - function _getDuration() { - // It should be a number, but parse it just incase - var duration = parseInt(config.duration), - // True duration - mediaDuration = 0; - - // Only if duration available - if (plyr.media.duration !== null && !isNaN(plyr.media.duration)) { - mediaDuration = plyr.media.duration; - } - - // If custom duration is funky, use regular duration - return isNaN(duration) ? mediaDuration : duration; - } + return this.media.getAttribute('poster'); + } - // Check playing state - function _checkPlaying() { - _toggleClass(plyr.container, config.classes.playing, !plyr.media.paused); + /** + * Set the autoplay state + * @param {boolean} input - Whether to autoplay or not + */ + set autoplay(input) { + const toggle = utils.is.boolean(input) ? input : this.config.autoplay; + this.config.autoplay = toggle; + } - _toggleClass(plyr.container, config.classes.stopped, plyr.media.paused); + /** + * Get the current autoplay state + */ + get autoplay() { + return this.config.autoplay; + } - _toggleControls(plyr.media.paused); + /** + * Toggle captions + * @param {boolean} input - Whether to enable captions + */ + toggleCaptions(input) { + // If there's no full support, or there's no caption toggle + if (!this.supported.ui || !utils.is.element(this.elements.buttons.captions)) { + return; } - // Save scroll position - function _saveScrollPosition() { - scroll = { - x: window.pageXOffset || 0, - y: window.pageYOffset || 0, - }; - } + // If the method is called without parameter, toggle based on current value + const show = utils.is.boolean(input) ? input : this.elements.container.className.indexOf(this.config.classNames.captions.active) === -1; - // Restore scroll position - function _restoreScrollPosition() { - window.scrollTo(scroll.x, scroll.y); + // Nothing to change... + if (this.captions.active === show) { + return; } - // Toggle fullscreen - function _toggleFullscreen(event) { - // We don't allow fullscreen on audio player - if (plyr.type === 'audio') { - return - } - - // Check for native support - var nativeSupport = fullscreen.supportsFullScreen; - - if (nativeSupport) { - // If it's a fullscreen change event, update the UI - if (event && event.type === fullscreen.fullScreenEventName) { - plyr.isFullscreen = fullscreen.isFullScreen(plyr.container); - } else { - // Else it's a user request to enter or exit - if (!fullscreen.isFullScreen(plyr.container)) { - // Save scroll position - _saveScrollPosition(); - - // Request full screen - fullscreen.requestFullScreen(plyr.container); - } else { - // Bail from fullscreen - fullscreen.cancelFullScreen(); - } - - // Check if we're actually full screen (it could fail) - plyr.isFullscreen = fullscreen.isFullScreen(plyr.container); - - return; - } - } else { - // Otherwise, it's a simple toggle - plyr.isFullscreen = !plyr.isFullscreen; + // Set global + this.captions.active = show; - // Bind/unbind escape key - document.body.style.overflow = plyr.isFullscreen ? 'hidden' : ''; - } + // Toggle state + utils.toggleState(this.elements.buttons.captions, this.captions.active); - // Set class hook - _toggleClass(plyr.container, config.classes.fullscreen.active, plyr.isFullscreen); - - // Trap focus - _focusTrap(plyr.isFullscreen); - - // Set button state - if (plyr.buttons && plyr.buttons.fullscreen) { - _toggleState(plyr.buttons.fullscreen, plyr.isFullscreen); - } + // Add class hook + utils.toggleClass(this.elements.container, this.config.classNames.captions.active, this.captions.active); - // Trigger an event - _triggerEvent(plyr.container, plyr.isFullscreen ? 'enterfullscreen' : 'exitfullscreen', true); + // Trigger an event + utils.dispatchEvent.call(this, this.media, this.captions.active ? 'captionsenabled' : 'captionsdisabled'); + } - // Restore scroll position - if (!plyr.isFullscreen && nativeSupport) { - _restoreScrollPosition(); - } + /** + * Set the captions language + * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc) + */ + set language(input) { + // Nothing specified + if (!utils.is.string(input)) { + return; } - // Mute - function _toggleMute(muted) { - // If the method is called without parameter, toggle based on current value - if (!_is.boolean(muted)) { - muted = !plyr.media.muted; - } - - // Set button state - _toggleState(plyr.buttons.mute, muted); - - // Set mute on the player - plyr.media.muted = muted; - - // If volume is 0 after unmuting, set to default - if (plyr.media.volume === 0) { - _setVolume(config.volume); - } - - // Embeds - if (_inArray(config.types.embed, plyr.type)) { - // YouTube - switch (plyr.type) { - case 'youtube': - plyr.embed[plyr.media.muted ? 'mute' : 'unMute'](); - break; - - case 'vimeo': - case 'soundcloud': - plyr.embed.setVolume(plyr.media.muted ? 0 : parseFloat(config.volume / config.volumeMax)); - break; - } + // Toggle captions based on input + this.toggleCaptions(!utils.is.empty(input)); - // Trigger volumechange for embeds - _triggerEvent(plyr.media, 'volumechange'); - } + // If empty string is passed, assume disable captions + if (utils.is.empty(input)) { + return; } - // Set volume - function _setVolume(volume) { - var max = config.volumeMax, - min = config.volumeMin; - - // Load volume from storage if no value specified - if (_is.undefined(volume)) { - volume = plyr.storage.volume; - } + // Normalize + const language = input.toLowerCase(); - // Use config if all else fails - if (volume === null || isNaN(volume)) { - volume = config.volume; - } - - // Maximum is volumeMax - if (volume > max) { - volume = max; - } - // Minimum is volumeMin - if (volume < min) { - volume = min; - } - - // Set the player volume - plyr.media.volume = parseFloat(volume / max); - - // Set the display - if (plyr.volume.display) { - plyr.volume.display.value = volume; - } - - // Embeds - if (_inArray(config.types.embed, plyr.type)) { - switch (plyr.type) { - case 'youtube': - plyr.embed.setVolume(plyr.media.volume * 100); - break; - - case 'vimeo': - case 'soundcloud': - plyr.embed.setVolume(plyr.media.volume); - break; - } - - // Trigger volumechange for embeds - _triggerEvent(plyr.media, 'volumechange'); - } - - // Toggle muted state - if (volume === 0) { - plyr.media.muted = true; - } else if (plyr.media.muted && volume > 0) { - _toggleMute(); - } + // If nothing to change, bail + if (this.language === language) { + return; } - // Increase volume - function _increaseVolume(step) { - var volume = plyr.media.muted ? 0 : plyr.media.volume * config.volumeMax; + // Update config + this.captions.language = language; - if (!_is.number(step)) { - step = config.volumeStep; - } + // Clear caption + captions.setText.call(this, null); - _setVolume(volume + step); - } + // Update captions + captions.setLanguage.call(this); - // Decrease volume - function _decreaseVolume(step) { - var volume = plyr.media.muted ? 0 : plyr.media.volume * config.volumeMax; + // Trigger an event + utils.dispatchEvent.call(this, this.media, 'languagechange'); + } - if (!_is.number(step)) { - step = config.volumeStep; - } + /** + * Get the current captions language + */ + get language() { + return this.captions.language; + } - _setVolume(volume - step); + /** + * Toggle fullscreen playback + * Requires user input event + * @param {event} event + */ + toggleFullscreen(event) { + // Video only + if (this.isAudio) { + return; } - // Update volume UI and storage - function _updateVolume() { - // Get the current volume - var volume = plyr.media.muted ? 0 : plyr.media.volume * config.volumeMax; - - // Update the <input type="range"> if present - if (plyr.supported.full) { - if (plyr.volume.input) { - plyr.volume.input.value = volume; - } - if (plyr.volume.display) { - plyr.volume.display.value = volume; + // Check for native support + if (fullscreen.enabled) { + if (utils.is.event(event) && event.type === fullscreen.eventType) { + // If it's a fullscreen change event, update the state + this.fullscreen.active = fullscreen.isFullScreen(this.elements.container); + } else { + // Else it's a user request to enter or exit + if (!this.fullscreen.active) { + fullscreen.requestFullScreen(this.elements.container); + } else { + fullscreen.cancelFullScreen(); } - } - - // Update the volume in storage - _updateStorage({ volume: volume }); - - // Toggle class if muted - _toggleClass(plyr.container, config.classes.muted, volume === 0); - - // Update checkbox for mute state - if (plyr.supported.full && plyr.buttons.mute) { - _toggleState(plyr.buttons.mute, volume === 0); - } - } - // Toggle captions - function _toggleCaptions(show) { - // If there's no full support, or there's no caption toggle - if (!plyr.supported.full || !plyr.buttons.captions) { return; } - - // If the method is called without parameter, toggle based on current value - if (!_is.boolean(show)) { - show = plyr.container.className.indexOf(config.classes.captions.active) === -1; - } - - // Set global - plyr.captionsEnabled = show; - - // Toggle state - _toggleState(plyr.buttons.captions, plyr.captionsEnabled); + } else { + // Otherwise, it's a simple toggle + this.fullscreen.active = !this.fullscreen.active; // Add class hook - _toggleClass(plyr.container, config.classes.captions.active, plyr.captionsEnabled); - - // Trigger an event - _triggerEvent(plyr.container, plyr.captionsEnabled ? 'captionsenabled' : 'captionsdisabled', true); - - // Save captions state to localStorage - _updateStorage({ captionsEnabled: plyr.captionsEnabled }); - } - - // Check if media is loading - function _checkLoading(event) { - var loading = event.type === 'waiting'; - - // Clear timer - clearTimeout(timers.loading); - - // Timer to prevent flicker when seeking - timers.loading = setTimeout(function() { - // Toggle container class hook - _toggleClass(plyr.container, config.classes.loading, loading); - - // Show controls if loading, hide if done - _toggleControls(loading); - }, loading ? 250 : 0); - } + utils.toggleClass(this.elements.container, this.config.classNames.fullscreen.fallback, this.fullscreen.active); - // Update <progress> elements - function _updateProgress(event) { - if (!plyr.supported.full) { - return; - } - - var progress = plyr.progress.played, - value = 0, - duration = _getDuration(); - - if (event) { - switch (event.type) { - // Video playing - case 'timeupdate': - case 'seeking': - if (plyr.controls.pressed) { - return; - } - - value = _getPercentage(plyr.media.currentTime, duration); - - // Set seek range value only if it's a 'natural' time event - if (event.type === 'timeupdate' && plyr.buttons.seek) { - plyr.buttons.seek.value = value; - } - - break; - - // Check buffer status - case 'playing': - case 'progress': - progress = plyr.progress.buffer; - value = (function() { - var buffered = plyr.media.buffered; - - if (buffered && buffered.length) { - // HTML5 - return _getPercentage(buffered.end(0), duration); - } else if (_is.number(buffered)) { - // YouTube returns between 0 and 1 - return buffered * 100; - } - - return 0; - })(); - - break; - } + // Make sure we don't lose scroll position + if (this.fullscreen.active) { + scrollPosition = { + x: window.pageXOffset || 0, + y: window.pageYOffset || 0, + }; + } else { + window.scrollTo(scrollPosition.x, scrollPosition.y); } - // Set values - _setProgress(progress, value); + // Bind/unbind escape key + document.body.style.overflow = this.fullscreen.active ? 'hidden' : ''; } - // Set <progress> value - function _setProgress(progress, value) { - if (!plyr.supported.full) { - return; - } - - // Default to 0 - if (_is.undefined(value)) { - value = 0; - } - // Default to buffer or bail - if (_is.undefined(progress)) { - if (plyr.progress && plyr.progress.buffer) { - progress = plyr.progress.buffer; - } else { - return; - } - } - - // One progress element passed - if (_is.htmlElement(progress)) { - progress.value = value; - } else if (progress) { - // Object of progress + text element - if (progress.bar) { - progress.bar.value = value; - } - if (progress.text) { - progress.text.innerHTML = value; - } - } + // Set button state + if (utils.is.element(this.elements.buttons.fullscreen)) { + utils.toggleState(this.elements.buttons.fullscreen, this.fullscreen.active); } - // Update the displayed time - function _updateTimeDisplay(time, element) { - // Bail if there's no duration display - if (!element) { - return; - } - - // Fallback to 0 - if (isNaN(time)) { - time = 0; - } - - plyr.secs = parseInt(time % 60); - plyr.mins = parseInt((time / 60) % 60); - plyr.hours = parseInt((time / 60 / 60) % 60); - - // Do we need to display hours? - var displayHours = parseInt((_getDuration() / 60 / 60) % 60) > 0; + // Trigger an event + utils.dispatchEvent.call(this, this.media, this.fullscreen.active ? 'enterfullscreen' : 'exitfullscreen'); + } - // Ensure it's two digits. For example, 03 rather than 3. - plyr.secs = ('0' + plyr.secs).slice(-2); - plyr.mins = ('0' + plyr.mins).slice(-2); + /** + * Toggle picture-in-picture playback on WebKit/MacOS + * TODO: update player with state, support, enabled + * TODO: detect outside changes + */ + set pip(input) { + const states = { + pip: 'picture-in-picture', + inline: 'inline', + }; - // Render - element.innerHTML = (displayHours ? plyr.hours + ':' : '') + plyr.mins + ':' + plyr.secs; + // Bail if no support + if (!support.pip) { + return; } - // Show the duration on metadataloaded - function _displayDuration() { - if (!plyr.supported.full) { - return; - } + // Toggle based on current state if not passed + const toggle = utils.is.boolean(input) ? input : this.pip === states.inline; - // Determine duration - var duration = _getDuration() || 0; - - // If there's only one time display, display duration there - if (!plyr.duration && config.displayDuration && plyr.media.paused) { - _updateTimeDisplay(duration, plyr.currentTime); - } - - // If there's a duration element, update content - if (plyr.duration) { - _updateTimeDisplay(duration, plyr.duration); - } + // Toggle based on current state + this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline); + } - // Update the tooltip (if visible) - _updateSeekTooltip(); + /** + * Get the current picture-in-picture state + */ + get pip() { + if (!support.pip) { + return null; } - // Handle time change event - function _timeUpdate(event) { - // Duration - _updateTimeDisplay(plyr.media.currentTime, plyr.currentTime); - - // Ignore updates while seeking - if (event && event.type === 'timeupdate' && plyr.media.seeking) { - return; - } + return this.media.webkitPresentationMode; + } - // Playing progress - _updateProgress(event); + /** + * Trigger the airplay dialog + * TODO: update player with state, support, enabled + */ + airplay() { + // Show dialog if supported + if (support.airplay) { + this.media.webkitShowPlaybackTargetPicker(); } + } - // Update seek range and progress - function _updateSeekDisplay(time) { - // Default to 0 - if (!_is.number(time)) { - time = 0; - } - - var duration = _getDuration(), - value = _getPercentage(time, duration); - - // Update progress - if (plyr.progress && plyr.progress.played) { - plyr.progress.played.value = value; - } - - // Update seek range input - if (plyr.buttons && plyr.buttons.seek) { - plyr.buttons.seek.value = value; - } + /** + * Toggle the player controls + * @param {boolean} toggle - Whether to show the controls + */ + toggleControls(toggle) { + // We need controls of course... + if (!utils.is.element(this.elements.controls)) { + return; } - // Update hover tooltip for seeking - function _updateSeekTooltip(event) { - var duration = _getDuration(); - - // Bail if setting not true - if (!config.tooltips.seek || !plyr.progress.container || duration === 0) { - return; - } - - // Calculate percentage - var clientRect = plyr.progress.container.getBoundingClientRect(), - percent = 0, - visible = config.classes.tooltip + '--visible'; - - // Determine percentage, if already visible - if (!event) { - if (_hasClass(plyr.progress.tooltip, visible)) { - percent = plyr.progress.tooltip.style.left.replace('%', ''); - } else { - return; - } - } else { - percent = 100 / clientRect.width * (event.pageX - clientRect.left); - } - - // Set bounds - if (percent < 0) { - percent = 0; - } else if (percent > 100) { - percent = 100; - } - - // Display the time a click would seek to - _updateTimeDisplay(duration / 100 * percent, plyr.progress.tooltip); - - // Set position - plyr.progress.tooltip.style.left = percent + '%'; - - // Show/hide the tooltip - // If the event is a moues in/out and percentage is inside bounds - if (event && _inArray(['mouseenter', 'mouseleave'], event.type)) { - _toggleClass(plyr.progress.tooltip, visible, event.type === 'mouseenter'); - } + // Don't hide if no UI support or it's audio + if (!this.supported.ui || this.isAudio) { + return; } - // Show the player controls in fullscreen mode - function _toggleControls(toggle) { - // Don't hide if config says not to, it's audio, or not ready or loading - if (!config.hideControls || plyr.type === 'audio') { - return; - } - - var delay = 0, - isEnterFullscreen = false, - show = toggle, - loading = _hasClass(plyr.container, config.classes.loading); - - // Default to false if no boolean - if (!_is.boolean(toggle)) { - if (toggle && toggle.type) { - // Is the enter fullscreen event - isEnterFullscreen = toggle.type === 'enterfullscreen'; - - // Whether to show controls - show = _inArray(['mousemove', 'touchstart', 'mouseenter', 'focus'], toggle.type); - - // Delay hiding on move events - if (_inArray(['mousemove', 'touchmove'], toggle.type)) { - delay = 2000; - } - - // Delay a little more for keyboard users - if (toggle.type === 'focus') { - delay = 3000; - } - } else { - show = _hasClass(plyr.container, config.classes.hideControls); - } - } - - // Clear timer every movement - window.clearTimeout(timers.hover); - - // If the mouse is not over the controls, set a timeout to hide them - if (show || plyr.media.paused || loading) { - _toggleClass(plyr.container, config.classes.hideControls, false); - - // Always show controls when paused or if touch - if (plyr.media.paused || loading) { - return; - } - - // Delay for hiding on touch - if (plyr.browser.isTouch) { + let delay = 0; + let show = toggle; + let isEnterFullscreen = false; + + // Get toggle state if not set + if (!utils.is.boolean(toggle)) { + if (utils.is.event(toggle)) { + // Is the enter fullscreen event + isEnterFullscreen = toggle.type === 'enterfullscreen'; + + // Whether to show controls + show = [ + 'mouseenter', + 'mousemove', + 'touchstart', + 'touchmove', + 'focusin', + ].includes(toggle.type); + + // Delay hiding on move events + if ([ + 'mousemove', + 'touchmove', + 'touchend', + ].includes(toggle.type)) { + delay = 2000; + } + + // Delay a little more for keyboard users + if (toggle.type === 'focusin') { delay = 3000; + utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, true); } - } - - // If toggle is false or if we're playing (regardless of toggle), - // then set the timer to hide the controls - if (!show || !plyr.media.paused) { - timers.hover = window.setTimeout(function() { - // If the mouse is over the controls (and not entering fullscreen), bail - if ((plyr.controls.pressed || plyr.controls.hover) && !isEnterFullscreen) { - return; - } - - _toggleClass(plyr.container, config.classes.hideControls, true); - }, delay); + } else { + show = utils.hasClass(this.elements.container, this.config.classNames.hideControls); } } - // Add common function to retrieve media source - function _source(source) { - // If not null or undefined, parse it - if (!_is.undefined(source)) { - _updateSource(source); - return; - } + // Clear timer on every call + window.clearTimeout(this.timers.controls); - // Return the current source - var url; - switch (plyr.type) { - case 'youtube': - url = plyr.embed.getVideoUrl(); - break; - - case 'vimeo': - plyr.embed.getVideoUrl.then(function(value) { - url = value; - }); - break; - - case 'soundcloud': - plyr.embed.getCurrentSound(function(object) { - url = object.permalink_url; - }); - break; - - default: - url = plyr.media.currentSrc; - break; - } + // If the mouse is not over the controls, set a timeout to hide them + if (show || this.paused || this.loading) { + // Check if controls toggled + const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, false); - return url || ''; - } - - // Update source - // Sources are not checked for support so be careful - function _updateSource(source) { - if (!_is.object(source) || !('sources' in source) || !source.sources.length) { - _warn('Invalid source format'); - return; + // Trigger event + if (toggled) { + utils.dispatchEvent.call(this, this.media, 'controlsshown'); } - // Remove ready class hook - _toggleClass(plyr.container, config.classes.ready, false); - - // Pause playback - _pause(); - - // Update seek range and progress - _updateSeekDisplay(); - - // Reset buffer progress - _setProgress(); - - // Cancel current network requests - _cancelRequests(); - - // Setup new source - function setup() { - // Remove embed object - plyr.embed = null; - - // Remove the old media - _remove(plyr.media); - - // Remove video container - if (plyr.type === 'video' && plyr.videoContainer) { - _remove(plyr.videoContainer); - } - - // Reset class name - if (plyr.container) { - plyr.container.removeAttribute('class'); - } - - // Set the type - if ('type' in source) { - plyr.type = source.type; - - // Get child type for video (it might be an embed) - if (plyr.type === 'video') { - var firstSource = source.sources[0]; - - if ('type' in firstSource && _inArray(config.types.embed, firstSource.type)) { - plyr.type = firstSource.type; - } - } - } - - // Check for support - plyr.supported = supported(plyr.type); - - // Create new markup - switch (plyr.type) { - case 'video': - plyr.media = document.createElement('video'); - break; - - case 'audio': - plyr.media = document.createElement('audio'); - break; - - case 'youtube': - case 'vimeo': - case 'soundcloud': - plyr.media = document.createElement('div'); - plyr.embedId = source.sources[0].src; - break; - } - - // Inject the new element - _prependChild(plyr.container, plyr.media); - - // Autoplay the new source? - if (_is.boolean(source.autoplay)) { - config.autoplay = source.autoplay; - } - - // Set attributes for audio and video - if (_inArray(config.types.html5, plyr.type)) { - if (config.crossorigin) { - plyr.media.setAttribute('crossorigin', ''); - } - if (config.autoplay) { - plyr.media.setAttribute('autoplay', ''); - } - if ('poster' in source) { - plyr.media.setAttribute('poster', source.poster); - } - if (config.loop) { - plyr.media.setAttribute('loop', ''); - } - } - - // Restore class hooks - _toggleClass(plyr.container, config.classes.fullscreen.active, plyr.isFullscreen); - _toggleClass(plyr.container, config.classes.captions.active, plyr.captionsEnabled); - _toggleStyleHook(); - - // Set new sources for html5 - if (_inArray(config.types.html5, plyr.type)) { - _insertChildElements('source', source.sources); - } - - // Set up from scratch - _setupMedia(); - - // HTML5 stuff - if (_inArray(config.types.html5, plyr.type)) { - // Setup captions - if ('tracks' in source) { - _insertChildElements('track', source.tracks); - } - - // Load HTML5 sources - plyr.media.load(); - } - - // If HTML5 or embed but not fully supported, setupInterface and call ready now - if (_inArray(config.types.html5, plyr.type) || (_inArray(config.types.embed, plyr.type) && !plyr.supported.full)) { - // Setup interface - _setupInterface(); - - // Call ready - _ready(); - } - - // Set aria title and iframe title - config.title = source.title; - _setTitle(); + // Always show controls when paused or if touch + if (this.paused || this.loading) { + return; } - // Destroy instance adn wait for callback - // Vimeo throws a wobbly if you don't wait - _destroy(setup, false); - } - - // Update poster - function _updatePoster(source) { - if (plyr.type === 'video') { - plyr.media.setAttribute('poster', source); + // Delay for hiding on touch + if (support.touch) { + delay = 3000; } } - function onBodyClick() { - _toggleClass(_getElement('.' + config.classes.tabFocus), config.classes.tabFocus, false); - } - - // Listen for control events - function _controlListeners() { - // IE doesn't support input event, so we fallback to change - var inputEvent = plyr.browser.isIE ? 'change' : 'input'; - - // Click play/pause helper - function togglePlay() { - var play = _togglePlay(); - - // Determine which buttons - var trigger = plyr.buttons[play ? 'play' : 'pause'], - target = plyr.buttons[play ? 'pause' : 'play']; - - // Get the last play button to account for the large play button - if (target) { - if (target.length > 1) { - target = target[target.length - 1]; - } else { - target = target[0]; - } - } - - // Setup focus and tab focus - if (target) { - var hadTabFocus = _hasClass(trigger, config.classes.tabFocus); - - setTimeout(function() { - target.focus(); - - if (hadTabFocus) { - _toggleClass(trigger, config.classes.tabFocus, false); - _toggleClass(target, config.classes.tabFocus, true); - } - }, 100); - } - } - - // Get the focused element - function getFocusElement() { - var focused = document.activeElement; - - if (!focused || focused === document.body) { - focused = null; - } else { - focused = document.querySelector(':focus'); - } - - return focused; - } - - // Get the key code for an event - function getKeyCode(event) { - return event.keyCode ? event.keyCode : event.which; - } - - // Detect tab focus - function checkTabFocus(focused) { - for (var button in plyr.buttons) { - var element = plyr.buttons[button]; - - if (_is.nodeList(element)) { - for (var i = 0; i < element.length; i++) { - _toggleClass(element[i], config.classes.tabFocus, element[i] === focused); - } - } else { - _toggleClass(element, config.classes.tabFocus, element === focused); - } - } - } - - // Keyboard shortcuts - if (config.keyboardShorcuts.focused) { - var last = null; - - // Handle global presses - if (config.keyboardShorcuts.global) { - _on(window, 'keydown keyup', function(event) { - var code = getKeyCode(event), - focused = getFocusElement(), - allowed = [48, 49, 50, 51, 52, 53, 54, 56, 57, 75, 77, 70, 67], - count = get().length; - - // Only handle global key press if there's only one player - // and the key is in the allowed keys - // and if the focused element is not editable (e.g. text input) - // and any that accept key input http://webaim.org/techniques/keyboard/ - if (count === 1 && _inArray(allowed, code) && (!_is.htmlElement(focused) || !_matches(focused, config.selectors.editable))) { - handleKey(event); - } - }); - } + // If toggle is false or if we're playing (regardless of toggle), + // then set the timer to hide the controls + if (!show || this.playing) { + this.timers.controls = window.setTimeout(() => { + /* this.debug.warn({ + pressed: this.elements.controls.pressed, + hover: this.elements.controls.pressed, + playing: this.playing, + paused: this.paused, + loading: this.loading, + }); */ - // Handle presses on focused - _on(plyr.container, 'keydown keyup', handleKey); - } - - function handleKey(event) { - var code = getKeyCode(event), - pressed = event.type === 'keydown', - held = pressed && code === last; - - // If the event is bubbled from the media element - // Firefox doesn't get the keycode for whatever reason - if (!_is.number(code)) { + // If the mouse is over the controls (and not entering fullscreen), bail + if ((this.elements.controls.pressed || this.elements.controls.hover) && !isEnterFullscreen) { return; } - // Seek by the number keys - function seekByKey() { - // Get current duration - var duration = plyr.media.duration; - - // Bail if we have no duration set - if (!_is.number(duration)) { - return; - } - - // Divide the max duration into 10th's and times by the number value - _seek(duration / 10 * (code - 48)); + // Restore transition behaviour + if (!utils.hasClass(this.elements.container, this.config.classNames.hideControls)) { + utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, false); } - // Handle the key on keydown - // Reset on keyup - if (pressed) { - // Which keycodes should we prevent default - var preventDefault = [48, 49, 50, 51, 52, 53, 54, 56, 57, 32, 75, 38, 40, 77, 39, 37, 70, 67]; - - // If the code is found prevent default (e.g. prevent scrolling for arrows) - if (_inArray(preventDefault, code)) { - event.preventDefault(); - event.stopPropagation(); - } + // Check if controls toggled + const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, true); - switch (code) { - // 0-9 - case 48: - case 49: - case 50: - case 51: - case 52: - case 53: - case 54: - case 55: - case 56: - case 57: - if (!held) { - seekByKey(); - } - break; - // Space and K key - case 32: - case 75: - if (!held) { - _togglePlay(); - } - break; - // Arrow up - case 38: - _increaseVolume(); - break; - // Arrow down - case 40: - _decreaseVolume(); - break; - // M key - case 77: - if (!held) { - _toggleMute(); - } - break; - // Arrow forward - case 39: - _forward(); - break; - // Arrow back - case 37: - _rewind(); - break; - // F key - case 70: - _toggleFullscreen(); - break; - // C key - case 67: - if (!held) { - _toggleCaptions(); - } - break; - } + // Trigger event and close menu + if (toggled) { + utils.dispatchEvent.call(this, this.media, 'controlshidden'); - // Escape is handle natively when in full screen - // So we only need to worry about non native - if (!fullscreen.supportsFullScreen && plyr.isFullscreen && code === 27) { - _toggleFullscreen(); + if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) { + controls.toggleMenu.call(this, false); } - - // Store last code for next cycle - last = code; - } else { - last = null; - } - } - - // Focus/tab management - _on(window, 'keyup', function(event) { - var code = getKeyCode(event), - focused = getFocusElement(); - - if (code === 9) { - checkTabFocus(focused); } - }); - _on(document.body, 'click', onBodyClick); - for (var button in plyr.buttons) { - var element = plyr.buttons[button]; - - _on(element, 'blur', function() { - _toggleClass(element, 'tab-focus', false); - }); - } - - // Play - _proxyListener(plyr.buttons.play, 'click', config.listeners.play, togglePlay); - - // Pause - _proxyListener(plyr.buttons.pause, 'click', config.listeners.pause, togglePlay); - - // Restart - _proxyListener(plyr.buttons.restart, 'click', config.listeners.restart, _seek); - - // Rewind - _proxyListener(plyr.buttons.rewind, 'click', config.listeners.rewind, _rewind); - - // Fast forward - _proxyListener(plyr.buttons.forward, 'click', config.listeners.forward, _forward); - - // Seek - _proxyListener(plyr.buttons.seek, inputEvent, config.listeners.seek, _seek); - - // Set volume - _proxyListener(plyr.volume.input, inputEvent, config.listeners.volume, function() { - _setVolume(plyr.volume.input.value); - }); - - // Mute - _proxyListener(plyr.buttons.mute, 'click', config.listeners.mute, _toggleMute); - - // Fullscreen - _proxyListener(plyr.buttons.fullscreen, 'click', config.listeners.fullscreen, _toggleFullscreen); - - // Toggle fullscreen when user double clicks on video wrapper - _proxyListener(plyr.container, 'dblclick', config.listeners.fullscreen, _toggleFullscreen); - - // Handle user exiting fullscreen by escaping etc - if (fullscreen.supportsFullScreen) { - _on(document, fullscreen.fullScreenEventName, _toggleFullscreen); - } - - // Captions - _proxyListener(plyr.buttons.captions, 'click', config.listeners.captions, _toggleCaptions); - - // Seek tooltip - _on(plyr.progress.container, 'mouseenter mouseleave mousemove', _updateSeekTooltip); - - // Toggle controls visibility based on mouse movement - if (config.hideControls) { - // Toggle controls on mouse events and entering fullscreen - _on(plyr.container, 'mouseenter mouseleave mousemove touchstart touchend touchcancel touchmove enterfullscreen', _toggleControls); - - // Watch for cursor over controls so they don't hide when trying to interact - _on(plyr.controls, 'mouseenter mouseleave', function(event) { - plyr.controls.hover = event.type === 'mouseenter'; - }); - - // Watch for cursor over controls so they don't hide when trying to interact - _on(plyr.controls, 'mousedown mouseup touchstart touchend touchcancel', function(event) { - plyr.controls.pressed = _inArray(['mousedown', 'touchstart'], event.type); - }); - - // Focus in/out on controls - _on(plyr.controls, 'focus blur', _toggleControls, true); - } - - // Adjust volume on scroll - _on(plyr.volume.input, 'wheel', function(event) { - event.preventDefault(); - - // Detect "natural" scroll - suppored on OS X Safari only - // Other browsers on OS X will be inverted until support improves - var inverted = event.webkitDirectionInvertedFromDevice, - step = config.volumeStep / 5; - - // Scroll down (or up on natural) to decrease - if (event.deltaY < 0 || event.deltaX > 0) { - if (inverted) { - _decreaseVolume(step); - } else { - _increaseVolume(step); - } - } - - // Scroll up (or down on natural) to increase - if (event.deltaY > 0 || event.deltaX < 0) { - if (inverted) { - _increaseVolume(step); - } else { - _decreaseVolume(step); - } - } - }); + }, delay); } + } - // Listen for media events - function _mediaListeners() { - // Time change on media - _on(plyr.media, 'timeupdate seeking', _timeUpdate); - - // Update manual captions - _on(plyr.media, 'timeupdate', _seekManualCaptions); - - // Display duration - _on(plyr.media, 'durationchange loadedmetadata', _displayDuration); - - // Handle the media finishing - _on(plyr.media, 'ended', function() { - // Show poster on end - if (plyr.type === 'video' && config.showPosterOnEnd) { - // Clear - if (plyr.type === 'video') { - _setCaption(); - } - - // Restart - _seek(); - - // Re-load media - plyr.media.load(); - } - }); - - // Check for buffer progress - _on(plyr.media, 'progress playing', _updateProgress); - - // Handle native mute - _on(plyr.media, 'volumechange', _updateVolume); - - // Handle native play/pause - _on(plyr.media, 'play pause ended', _checkPlaying); - - // Loading - _on(plyr.media, 'waiting canplay seeked', _checkLoading); - - // Click video - if (config.clickToPlay && plyr.type !== 'audio') { - // Re-fetch the wrapper - var wrapper = _getElement('.' + config.classes.videoWrapper); + /** + * Add event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ + on(event, callback) { + utils.on(this.elements.container, event, callback); + } - // Bail if there's no wrapper (this should never happen) - if (!wrapper) { - return; - } + /** + * Remove event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ + off(event, callback) { + utils.off(this.elements.container, event, callback); + } - // Set cursor - wrapper.style.cursor = 'pointer'; - // On click play, pause ore restart - _on(wrapper, 'click', function() { - // Touch devices will just show controls (if we're hiding controls) - if (config.hideControls && plyr.browser.isTouch && !plyr.media.paused) { - return; - } - if (plyr.media.paused) { - _play(); - } else if (plyr.media.ended) { - _seek(); - _play(); - } else { - _pause(); + /** + * Destroy an instance + * Event listeners are removed when elements are removed + * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory + * @param {function} callback - Callback for when destroy is complete + * @param {boolean} soft - Whether it's a soft destroy (for source changes etc) + */ + destroy(callback, soft = false) { + const done = () => { + // Reset overflow (incase destroyed while in fullscreen) + document.body.style.overflow = ''; + + // GC for embed + this.embed = null; + this.embedId = null; + + // If it's a soft destroy, make minimal changes + if (soft) { + if (Object.keys(this.elements).length) { + // Remove buttons + if (this.elements.buttons && this.elements.buttons.play) { + Array.from(this.elements.buttons.play).forEach(button => utils.removeElement(button)); } - }); - } - - // Disable right click - if (config.disableContextMenu) { - _on(plyr.media, 'contextmenu', function(event) { - event.preventDefault(); - }); - } - - // Proxy events to container - // Bubble up key events for Edge - _on(plyr.media, config.events.concat(['keyup', 'keydown']).join(' '), function(event) { - _triggerEvent(plyr.container, event.type, true); - }); - } - - // Cancel current network requests - // See https://github.com/sampotts/plyr/issues/174 - function _cancelRequests() { - if (!_inArray(config.types.html5, plyr.type)) { - return; - } - - // Remove child sources - var sources = plyr.media.querySelectorAll('source'); - for (var i = 0; i < sources.length; i++) { - _remove(sources[i]); - } - - // Set blank video src attribute - // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error - // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection - plyr.media.setAttribute('src', config.blankUrl); - - // Load the new empty source - // This will cancel existing requests - // See https://github.com/sampotts/plyr/issues/174 - plyr.media.load(); - - // Debugging - _log('Cancelled network requests'); - } - - // Destroy an instance - // Event listeners are removed when elements are removed - // http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory - function _destroy(callback, restore) { - // Bail if the element is not initialized - if (!plyr.init) { - return null; - } - - // Type specific stuff - switch (plyr.type) { - case 'youtube': - // Clear timers - window.clearInterval(timers.buffering); - window.clearInterval(timers.playing); - - // Destroy YouTube API - plyr.embed.destroy(); - - // Clean up - cleanUp(); - - break; - case 'vimeo': - // Destroy Vimeo API - // then clean up (wait, to prevent postmessage errors) - plyr.embed.unload().then(cleanUp); + // Remove others + utils.removeElement(this.elements.captions); + utils.removeElement(this.elements.controls); + utils.removeElement(this.elements.wrapper); - // Vimeo does not always return - timers.cleanUp = window.setTimeout(cleanUp, 200); - - break; - - case 'video': - case 'audio': - // Restore native video controls - _toggleNativeControls(true); - - // Clean up - cleanUp(); - - break; - } - - function cleanUp() { - clearTimeout(timers.cleanUp); - - // Default to restore original element - if (!_is.boolean(restore)) { - restore = true; + // Clear for GC + this.elements.buttons.play = null; + this.elements.captions = null; + this.elements.controls = null; + this.elements.wrapper = null; } // Callback - if (_is.function(callback)) { - callback.call(original); + if (utils.is.function(callback)) { + callback(); } - - // Bail if we don't need to restore the original element - if (!restore) { - return; - } - - // Remove init flag - plyr.init = false; - + } else { // Replace the container with the original element provided - plyr.container.parentNode.replaceChild(original, plyr.container); - - // Free container in order for GC to remove it and prevent memory leaks due to added events - plyr.container = null; - - // Allow overflow (set on fullscreen) - document.body.style.overflow = ''; + const parent = this.elements.container.parentNode; - //remove events - _off(document.body, 'click', onBodyClick); + if (utils.is.element(parent)) { + parent.replaceChild(this.elements.original, this.elements.container); + } // Event - _triggerEvent(original, 'destroyed', true); - } - } - - // Setup a player - function _init() { - // Bail if the element is initialized - if (plyr.init) { - return null; - } - - // Setup the fullscreen api - fullscreen = _fullscreen(); - - // Sniff out the browser - plyr.browser = _browserSniff(); + utils.dispatchEvent.call(this, this.elements.original, 'destroyed', true); - // Bail if nothing to setup - if (!_is.htmlElement(plyr.media)) { - return; - } - - // Load saved settings from localStorage - _setupStorage(); - - // Set media type based on tag or data attribute - // Supported: video, audio, vimeo, youtube - var tagName = media.tagName.toLowerCase(); - if (tagName === 'div') { - plyr.type = media.getAttribute('data-type'); - plyr.embedId = media.getAttribute('data-video-id'); - - // Clean up - media.removeAttribute('data-type'); - media.removeAttribute('data-video-id'); - } else { - plyr.type = tagName; - config.crossorigin = media.getAttribute('crossorigin') !== null; - config.autoplay = config.autoplay || media.getAttribute('autoplay') !== null; - config.loop = config.loop || media.getAttribute('loop') !== null; - } - - // Check for support - plyr.supported = supported(plyr.type); - - // If no native support, bail - if (!plyr.supported.basic) { - return; - } - - // Wrap media - plyr.container = _wrap(media, document.createElement('div')); - - // Allow focus to be captured - plyr.container.setAttribute('tabindex', 0); - - // Add style hook - _toggleStyleHook(); - - // Debug info - _log('' + plyr.browser.name + ' ' + plyr.browser.version); - - // Setup media - _setupMedia(); - - // Setup interface - // If embed but not fully supported, setupInterface (to avoid flash of controls) and call ready now - if (_inArray(config.types.html5, plyr.type) || (_inArray(config.types.embed, plyr.type) && !plyr.supported.full)) { - // Setup UI - _setupInterface(); - - // Call ready - _ready(); - - // Set title on button and frame - _setTitle(); - } - - // Successful setup - plyr.init = true; - } - - // Setup the UI - function _setupInterface() { - // Don't setup interface if no support - if (!plyr.supported.full) { - _warn('Basic support only', plyr.type); - - // Remove controls - _remove(_getElement(config.selectors.controls.wrapper)); - - // Remove large play - _remove(_getElement(config.selectors.buttons.play)); - - // Restore native controls - _toggleNativeControls(true); - - // Bail - return; - } - - // Inject custom controls if not present - var controlsMissing = !_getElements(config.selectors.controls.wrapper).length; - if (controlsMissing) { - // Inject custom controls - _injectControls(); - } - - // Find the elements - if (!_findElements()) { - return; - } + // Callback + if (utils.is.function(callback)) { + callback.call(this.elements.original); + } - // If the controls are injected, re-bind listeners for controls - if (controlsMissing) { - _controlListeners(); + // Clear for GC + this.elements = null; } - - // Media element listeners - _mediaListeners(); - - // Remove native controls - _toggleNativeControls(); - - // Setup fullscreen - _setupFullscreen(); - - // Captions - _setupCaptions(); - - // Set volume - _setVolume(); - _updateVolume(); - - // Reset time display - _timeUpdate(); - - // Update the UI - _checkPlaying(); - - // Display duration - _displayDuration(); - } - - api = { - getOriginal: function() { - return original; - }, - getContainer: function() { - return plyr.container; - }, - getEmbed: function() { - return plyr.embed; - }, - getMedia: function() { - return plyr.media; - }, - getType: function() { - return plyr.type; - }, - getDuration: _getDuration, - getCurrentTime: function() { - return plyr.media.currentTime; - }, - getVolume: function() { - return plyr.media.volume; - }, - isMuted: function() { - return plyr.media.muted; - }, - isReady: function() { - return _hasClass(plyr.container, config.classes.ready); - }, - isLoading: function() { - return _hasClass(plyr.container, config.classes.loading); - }, - isPaused: function() { - return plyr.media.paused; - }, - on: function(event, callback) { - _on(plyr.container, event, callback); - return this; - }, - play: _play, - pause: _pause, - stop: function() { - _pause(); - _seek(); - }, - restart: _seek, - rewind: _rewind, - forward: _forward, - seek: _seek, - source: _source, - poster: _updatePoster, - setVolume: _setVolume, - togglePlay: _togglePlay, - toggleMute: _toggleMute, - toggleCaptions: _toggleCaptions, - toggleFullscreen: _toggleFullscreen, - toggleControls: _toggleControls, - isFullscreen: function() { - return plyr.isFullscreen || false; - }, - support: function(mimeType) { - return _supportMime(plyr, mimeType); - }, - destroy: _destroy, }; - // Everything done - function _ready() { - // Ready event at end of execution stack - window.setTimeout(function() { - _triggerEvent(plyr.media, 'ready'); - }, 0); - - // Set class hook on media element - _toggleClass(plyr.media, defaults.classes.setup, true); - - // Set container class for ready - _toggleClass(plyr.container, config.classes.ready, true); - - // Store a refernce to instance - plyr.media.plyr = api; - - // Autoplay - if (config.autoplay) { - _play(); - } - } - - // Initialize instance - _init(); - - // If init failed, return null - if (!plyr.init) { - return null; - } - - return api; - } - - // Load a sprite - function loadSprite(url, id) { - var x = new XMLHttpRequest(); - - // If the id is set and sprite exists, bail - if (_is.string(id) && _is.htmlElement(document.querySelector('#' + id))) { - return; - } - - // Create placeholder (to prevent loading twice) - var container = document.createElement('div'); - container.setAttribute('hidden', ''); - if (_is.string(id)) { - container.setAttribute('id', id); - } - document.body.insertBefore(container, document.body.childNodes[0]); - - // Check for CORS support - if ('withCredentials' in x) { - x.open('GET', url, true); - } else { - return; - } + // Type specific stuff + switch (`${this.provider}:${this.type}`) { + case 'html5:video': + case 'html5:audio': + // Restore native video controls + ui.toggleNativeControls.call(this, true); - // Inject hidden div with sprite on load - x.onload = function() { - container.innerHTML = x.responseText; - }; + // Clean up + done(); - x.send(); - } + break; - // Check for support - function supported(type) { - var browser = _browserSniff(), - isOldIE = browser.isIE && browser.version <= 9, - isIos = browser.isIos, - isIphone = browser.isIphone, - audioSupport = !!document.createElement('audio').canPlayType, - videoSupport = !!document.createElement('video').canPlayType, - basic = false, - full = false; + case 'youtube:video': + // Clear timers + window.clearInterval(this.timers.buffering); + window.clearInterval(this.timers.playing); - switch (type) { - case 'video': - basic = videoSupport; - full = basic && (!isOldIE && !isIphone); - break; + // Destroy YouTube API + this.embed.destroy(); - case 'audio': - basic = audioSupport; - full = basic && !isOldIE; - break; + // Clean up + done(); - // Vimeo does not seem to be supported on iOS via API - // Issue raised https://github.com/vimeo/player.js/issues/87 - case 'vimeo': - basic = true; - full = !isOldIE && !isIos; break; - case 'youtube': - basic = true; - full = !isOldIE && !isIos; - - // YouTube seems to work on iOS 10+ on iPad - if (isIos && !isIphone && browser.version >= 10) { - full = true; - } + case 'vimeo:video': + // Destroy Vimeo API + // then clean up (wait, to prevent postmessage errors) + this.embed.unload().then(done); - break; + // Vimeo does not always return + window.setTimeout(done, 200); - case 'soundcloud': - basic = true; - full = !isOldIE && !isIphone; break; default: - basic = audioSupport && videoSupport; - full = basic && !isOldIE; + break; } - - return { - basic: basic, - full: full, - }; } - // Setup function - function setup(targets, options) { - // Get the players - var players = [], - instances = [], - selector = [defaults.selectors.html5, defaults.selectors.embed].join(','); - - // Select the elements - if (_is.string(targets)) { - // String selector passed - targets = document.querySelectorAll(targets); - } else if (_is.htmlElement(targets)) { - // Single HTMLElement passed - targets = [targets]; - } else if (!_is.nodeList(targets) && !_is.array(targets) && !_is.string(targets)) { - // No selector passed, possibly options as first argument - // If options are the first argument - if (_is.undefined(options) && _is.object(targets)) { - options = targets; - } - - // Use default selector - targets = document.querySelectorAll(selector); - } - - // Convert NodeList to array - if (_is.nodeList(targets)) { - targets = Array.prototype.slice.call(targets); - } - - // Bail if disabled or no basic support - // You may want to disable certain UAs etc - if (!supported().basic || !targets.length) { - return false; - } - - // Add to container list - function add(target, media) { - if (!_hasClass(media, defaults.classes.hook)) { - players.push({ - // Always wrap in a <div> for styling - //container: _wrap(media, document.createElement('div')), - // Could be a container or the media itself - target: target, - // This should be the <video>, <audio> or <div> (YouTube/Vimeo) - media: media, - }); - } - } - - // Check if the targets have multiple media elements - for (var i = 0; i < targets.length; i++) { - var target = targets[i]; - - // Get children - var children = target.querySelectorAll(selector); - - // If there's more than one media element child, wrap them - if (children.length) { - for (var x = 0; x < children.length; x++) { - add(target, children[x]); - } - } else if (_matches(target, selector)) { - // Target is media element - add(target, target); - } - } - - // Create a player instance for each element - players.forEach(function(player) { - var element = player.target, - media = player.media, - match = false; - - // The target element can also be the media element - if (media === element) { - match = true; - } - - // Setup a player instance and add to the element - // Create instance-specific config - var data = {}; - - // Try parsing data attribute config - try { - data = JSON.parse(element.getAttribute('data-plyr')); - } catch (e) {} - - var config = _extend({}, defaults, options, data); - - // Bail if not enabled - if (!config.enabled) { - return null; - } - - // Create new instance - var instance = new Plyr(media, config); - - // Go to next if setup failed - if (!_is.object(instance)) { - return; - } - - // Listen for events if debugging - if (config.debug) { - var events = config.events.concat(['setup', 'statechange', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled']); - - _on(instance.getContainer(), events.join(' '), function(event) { - console.log([config.logPrefix, 'event:', event.type].join(' '), event.detail.plyr); - }); - } - - // Callback - _event(instance.getContainer(), 'setup', true, { - plyr: instance, - }); - - // Add to return array even if it's already setup - instances.push(instance); - }); - - return instances; - } - - // Get all instances within a provided container - function get(container) { - if (_is.string(container)) { - // Get selector if string passed - container = document.querySelector(container); - } else if (_is.undefined(container)) { - // Use body by default to get all on page - container = document.body; - } - - // If we have a HTML element - if (_is.htmlElement(container)) { - var elements = container.querySelectorAll('.' + defaults.classes.setup), - instances = []; - - Array.prototype.slice.call(elements).forEach(function(element) { - if (_is.object(element.plyr)) { - instances.push(element.plyr); - } - }); - - return instances; - } - - return []; + /** + * Check for support for a mime type (HTML5 only) + * @param {string} type - Mime type + */ + supports(type) { + return support.mime.call(this, type); } - return { - setup: setup, - supported: supported, - loadSprite: loadSprite, - get: get, - }; -}); - -// Custom event polyfill -// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent -(function() { - if (typeof window.CustomEvent === 'function') { - return; + /** + * Check for support + * @param {string} type - Player type (audio/video) + * @param {string} provider - Provider (html5/youtube/vimeo) + * @param {bool} inline - Where player has `playsinline` sttribute + */ + static supported(type, provider, inline) { + return support.check(type, provider, inline); } - function CustomEvent(event, params) { - params = params || { bubbles: false, cancelable: false, detail: undefined }; - var evt = document.createEvent('CustomEvent'); - evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); - return evt; + /** + * Load an SVG sprite into the page + * @param {string} url - URL for the SVG sprite + * @param {string} [id] - Unique ID + */ + static loadSprite(url, id) { + return utils.loadSprite(url, id); } +} - CustomEvent.prototype = window.Event.prototype; - - window.CustomEvent = CustomEvent; -})(); +export default Plyr; diff --git a/src/js/source.js b/src/js/source.js new file mode 100644 index 00000000..80620bdf --- /dev/null +++ b/src/js/source.js @@ -0,0 +1,144 @@ +// ========================================================================== +// Plyr source update +// ========================================================================== + +import { providers } from './types'; +import utils from './utils'; +import media from './media'; +import ui from './ui'; +import support from './support'; + +const source = { + // Add elements to HTML5 media (source, tracks, etc) + insertElements(type, attributes) { + if (utils.is.string(attributes)) { + utils.insertElement(type, this.media, { + src: attributes, + }); + } else if (utils.is.array(attributes)) { + attributes.forEach(attribute => { + utils.insertElement(type, this.media, attribute); + }); + } + }, + + // Update source + // Sources are not checked for support so be careful + change(input) { + if (!utils.is.object(input) || !('sources' in input) || !input.sources.length) { + this.debug.warn('Invalid source format'); + return; + } + + // Cancel current network requests + media.cancelRequests.call(this); + + // Destroy instance and re-setup + this.destroy.call( + this, + () => { + // TODO: Reset menus here + + // Remove elements + utils.removeElement(this.media); + this.media = null; + + // Reset class name + if (utils.is.element(this.elements.container)) { + this.elements.container.removeAttribute('class'); + } + + // Set the type and provider + this.type = input.type; + this.provider = !utils.is.empty(input.sources[0].provider) ? input.sources[0].provider : providers.html5; + + // Check for support + this.supported = support.check(this.type, this.provider, this.config.inline); + + // Create new markup + switch (`${this.provider}:${this.type}`) { + case 'html5:video': + this.media = utils.createElement('video'); + break; + + case 'html5:audio': + this.media = utils.createElement('audio'); + break; + + case 'youtube:video': + case 'vimeo:video': + this.media = utils.createElement('div'); + this.embedId = input.sources[0].src; + break; + + default: + break; + } + + // Inject the new element + this.elements.container.appendChild(this.media); + + // Autoplay the new source? + if (utils.is.boolean(input.autoplay)) { + this.config.autoplay = input.autoplay; + } + + // Set attributes for audio and video + if (this.isHTML5) { + if (this.config.crossorigin) { + this.media.setAttribute('crossorigin', ''); + } + if (this.config.autoplay) { + this.media.setAttribute('autoplay', ''); + } + if ('poster' in input) { + this.media.setAttribute('poster', input.poster); + } + if (this.config.loop.active) { + this.media.setAttribute('loop', ''); + } + if (this.config.muted) { + this.media.setAttribute('muted', ''); + } + if (this.config.inline) { + this.media.setAttribute('playsinline', ''); + } + } + + // Restore class hook + ui.addStyleHook.call(this); + + // Set new sources for html5 + if (this.isHTML5) { + source.insertElements.call(this, 'source', input.sources); + } + + // Set video title + this.config.title = input.title; + + // Set up from scratch + media.setup.call(this); + + // HTML5 stuff + if (this.isHTML5) { + // Setup captions + if ('tracks' in input) { + source.insertElements.call(this, 'track', input.tracks); + } + + // Load HTML5 sources + this.media.load(); + } + + // If HTML5 or embed but not fully supported, setupInterface and call ready now + if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) { + // Setup interface + ui.build.call(this); + } + }, + true + ); + }, +}; + +export default source; diff --git a/src/js/storage.js b/src/js/storage.js new file mode 100644 index 00000000..f876f107 --- /dev/null +++ b/src/js/storage.js @@ -0,0 +1,66 @@ +// ========================================================================== +// Plyr storage +// ========================================================================== + +import utils from './utils'; + +class Storage { + constructor(player) { + this.enabled = player.config.storage.enabled; + this.key = player.config.storage.key; + } + + // Check for actual support (see if we can use it) + static get supported() { + if (!('localStorage' in window)) { + return false; + } + + const test = '___test'; + + // Try to use it (it might be disabled, e.g. user is in private mode) + // see: https://github.com/sampotts/plyr/issues/131 + try { + window.localStorage.setItem(test, test); + window.localStorage.removeItem(test); + return true; + } catch (e) { + return false; + } + } + + get(key) { + const store = window.localStorage.getItem(this.key); + + if (!Storage.supported || utils.is.empty(store)) { + return null; + } + + const json = JSON.parse(store); + + return utils.is.string(key) && key.length ? json[key] : json; + } + + set(object) { + // Bail if we don't have localStorage support or it's disabled + if (!Storage.supported || !this.enabled) { + return; + } + + // Can only store objectst + if (!utils.is.object(object)) { + return; + } + + // Get current storage + const storage = this.get(); + + // Update the working copy of the values + utils.extend(storage, object); + + // Update storage + window.localStorage.setItem(this.key, JSON.stringify(storage)); + } +} + +export default Storage; diff --git a/src/js/support.js b/src/js/support.js new file mode 100644 index 00000000..f75517d6 --- /dev/null +++ b/src/js/support.js @@ -0,0 +1,161 @@ +// ========================================================================== +// Plyr support checks +// ========================================================================== + +import utils from './utils'; + +// Check for feature support +const support = { + // Basic support + audio: 'canPlayType' in document.createElement('audio'), + video: 'canPlayType' in document.createElement('video'), + + // Check for support + // Basic functionality vs full UI + check(type, provider, inline) { + let api = false; + let ui = false; + const browser = utils.getBrowser(); + const playsInline = browser.isIPhone && inline && support.inline; + + switch (`${provider}:${type}`) { + case 'html5:video': + api = support.video; + ui = api && support.rangeInput && (!browser.isIPhone || playsInline); + break; + + case 'html5:audio': + api = support.audio; + ui = api && support.rangeInput; + break; + + case 'youtube:video': + api = true; + ui = support.rangeInput && (!browser.isIPhone || playsInline); + break; + + case 'vimeo:video': + api = true; + ui = support.rangeInput && !browser.isIPhone; + break; + + default: + api = support.audio && support.video; + ui = api && support.rangeInput; + } + + return { + api, + ui, + }; + }, + + // Picture-in-picture support + // Safari only currently + pip: (() => { + const browser = utils.getBrowser(); + return !browser.isIPhone && utils.is.function(utils.createElement('video').webkitSetPresentationMode); + })(), + + // Airplay support + // Safari only currently + airplay: utils.is.function(window.WebKitPlaybackTargetAvailabilityEvent), + + // Inline playback support + // https://webkit.org/blog/6784/new-video-policies-for-ios/ + inline: 'playsInline' in document.createElement('video'), + + // Check for mime type support against a player instance + // Credits: http://diveintohtml5.info/everything.html + // Related: http://www.leanbackplayer.com/test/h5mt.html + mime(type) { + const { media } = this; + + try { + // Bail if no checking function + if (!this.isHTML5 || !utils.is.function(media.canPlayType)) { + return false; + } + + // Type specific checks + if (this.isVideo) { + switch (type) { + case 'video/webm': + return media.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/, ''); + + case 'video/mp4': + return media.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, ''); + + case 'video/ogg': + return media.canPlayType('video/ogg; codecs="theora"').replace(/no/, ''); + + default: + return false; + } + } else if (this.isAudio) { + switch (type) { + case 'audio/mpeg': + return media.canPlayType('audio/mpeg;').replace(/no/, ''); + + case 'audio/ogg': + return media.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/, ''); + + case 'audio/wav': + return media.canPlayType('audio/wav; codecs="1"').replace(/no/, ''); + + default: + return false; + } + } + } catch (e) { + return false; + } + + // If we got this far, we're stuffed + return false; + }, + + // Check for textTracks support + textTracks: 'textTracks' in document.createElement('video'), + + // Check for passive event listener support + // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md + // https://www.youtube.com/watch?v=NPM6172J22g + passiveListeners: (() => { + // Test via a getter in the options object to see if the passive property is accessed + let supported = false; + try { + const options = Object.defineProperty({}, 'passive', { + get() { + supported = true; + return null; + }, + }); + window.addEventListener('test', null, options); + } catch (e) { + // Do nothing + } + + return supported; + })(), + + // <input type="range"> Sliders + rangeInput: (() => { + const range = document.createElement('input'); + range.type = 'range'; + return range.type === 'range'; + })(), + + // Touch + // Remember a device can be moust + touch enabled + touch: 'ontouchstart' in document.documentElement, + + // Detect transitions support + transitions: utils.transitionEnd !== false, + + // Reduced motion iOS & MacOS setting + // https://webkit.org/blog/7551/responsive-design-for-motion/ + reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches, +}; + +export default support; diff --git a/src/js/types.js b/src/js/types.js new file mode 100644 index 00000000..35716c3c --- /dev/null +++ b/src/js/types.js @@ -0,0 +1,16 @@ +// ========================================================================== +// Plyr supported types and providers +// ========================================================================== + +export const providers = { + html5: 'html5', + youtube: 'youtube', + vimeo: 'vimeo', +}; + +export const types = { + audio: 'audio', + video: 'video', +}; + +export default { providers, types }; diff --git a/src/js/ui.js b/src/js/ui.js new file mode 100644 index 00000000..7a45a6c3 --- /dev/null +++ b/src/js/ui.js @@ -0,0 +1,363 @@ +// ========================================================================== +// Plyr UI +// ========================================================================== + +import utils from './utils'; +import captions from './captions'; +import controls from './controls'; +import fullscreen from './fullscreen'; +import listeners from './listeners'; + +const ui = { + addStyleHook() { + utils.toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true); + utils.toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui); + }, + + // Toggle native HTML5 media controls + toggleNativeControls(toggle = false) { + if (toggle && this.isHTML5) { + this.media.setAttribute('controls', ''); + } else { + this.media.removeAttribute('controls'); + } + }, + + // Setup the UI + build() { + // Re-attach media element listeners + // TODO: Use event bubbling + listeners.media.call(this); + + // Don't setup interface if no support + if (!this.supported.ui) { + this.debug.warn(`Basic support only for ${this.provider} ${this.type}`); + + // Remove controls + utils.removeElement.call(this, 'controls'); + + // Remove large play + utils.removeElement.call(this, 'buttons.play'); + + // Restore native controls + ui.toggleNativeControls.call(this, true); + + // Bail + return; + } + + // Inject custom controls if not present + if (!utils.is.element(this.elements.controls)) { + // Inject custom controls + controls.inject.call(this); + + // Re-attach control listeners + listeners.controls.call(this); + } + + // If there's no controls, bail + if (!utils.is.element(this.elements.controls)) { + return; + } + + // Remove native controls + ui.toggleNativeControls.call(this); + + // Setup fullscreen + fullscreen.setup.call(this); + + // Captions + captions.setup.call(this); + + // Reset volume + this.volume = null; + + // Reset mute state + this.muted = null; + + // Reset speed + this.speed = null; + + // Reset loop state + this.loop = null; + + // Reset quality options + this.options.quality = []; + + // Reset time display + ui.timeUpdate.call(this); + + // Update the UI + ui.checkPlaying.call(this); + + // Ready for API calls + this.ready = true; + + // Ready event at end of execution stack + utils.dispatchEvent.call(this, this.media, 'ready'); + + // Set the title + ui.setTitle.call(this); + }, + + // Setup aria attribute for play and iframe title + setTitle() { + // Find the current text + let label = this.config.i18n.play; + + // If there's a media title set, use that for the label + if (utils.is.string(this.config.title) && !utils.is.empty(this.config.title)) { + label += `, ${this.config.title}`; + + // Set container label + this.elements.container.setAttribute('aria-label', this.config.title); + } + + // If there's a play button, set label + if (utils.is.nodeList(this.elements.buttons.play)) { + Array.from(this.elements.buttons.play).forEach(button => { + button.setAttribute('aria-label', label); + }); + } + + // Set iframe title + // https://github.com/sampotts/plyr/issues/124 + if (this.isEmbed) { + const iframe = utils.getElement.call(this, 'iframe'); + + if (!utils.is.element(iframe)) { + return; + } + + // Default to media type + const title = !utils.is.empty(this.config.title) ? this.config.title : 'video'; + + iframe.setAttribute('title', this.config.i18n.frameTitle.replace('{title}', title)); + } + }, + + // Check playing state + checkPlaying() { + // Class hooks + utils.toggleClass(this.elements.container, this.config.classNames.playing, this.playing); + utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.paused); + + // Set aria state + if (utils.is.nodeList(this.elements.buttons.play)) { + Array.from(this.elements.buttons.play).forEach(button => utils.toggleState(button, this.playing)); + } + + // Toggle controls + this.toggleControls(!this.playing); + }, + + // Check if media is loading + checkLoading(event) { + this.loading = this.media.networkState === 2 || [ + 'stalled', + 'waiting', + ].includes(event.type); + + // Clear timer + clearTimeout(this.timers.loading); + + // Timer to prevent flicker when seeking + this.timers.loading = setTimeout(() => { + // Toggle container class hook + utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading); + + // Show controls if loading, hide if done + this.toggleControls(this.loading); + }, this.loading ? 250 : 0); + }, + + // Check if media failed to load + checkFailed() { + // https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/networkState + this.failed = this.media.networkState === 3; + + if (this.failed) { + utils.toggleClass(this.elements.container, this.config.classNames.loading, false); + utils.toggleClass(this.elements.container, this.config.classNames.error, true); + } + + // Clear timer + clearTimeout(this.timers.failed); + + // Timer to prevent flicker when seeking + this.timers.loading = setTimeout(() => { + // Toggle container class hook + utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading); + + // Show controls if loading, hide if done + this.toggleControls(this.loading); + }, this.loading ? 250 : 0); + }, + + // Update volume UI and storage + updateVolume() { + if (!this.supported.ui) { + return; + } + + // Update range + if (utils.is.element(this.elements.inputs.volume)) { + ui.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume); + } + + // Update mute state + if (utils.is.element(this.elements.buttons.mute)) { + utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0); + } + }, + + // Update seek value and lower fill + setRange(target, value = 0) { + if (!utils.is.element(target)) { + return; + } + + // eslint-disable-next-line + target.value = value; + + // Webkit range fill + controls.updateRangeFill.call(this, target); + }, + + // Set <progress> value + setProgress(target, input) { + const value = utils.is.number(input) ? input : 0; + const progress = utils.is.element(target) ? target : this.elements.display.buffer; + + // Update value and label + if (utils.is.element(progress)) { + progress.value = value; + + // Update text label inside + const label = progress.getElementsByTagName('span')[0]; + if (utils.is.element(label)) { + label.childNodes[0].nodeValue = value; + } + } + }, + + // Update <progress> elements + updateProgress(event) { + if (!this.supported.ui || !utils.is.event(event)) { + return; + } + + let value = 0; + + if (event) { + switch (event.type) { + // Video playing + case 'timeupdate': + case 'seeking': + value = utils.getPercentage(this.currentTime, this.duration); + + // Set seek range value only if it's a 'natural' time event + if (event.type === 'timeupdate') { + ui.setRange.call(this, this.elements.inputs.seek, value); + } + + break; + + // Check buffer status + case 'playing': + case 'progress': + value = (() => { + const { buffered } = this.media; + + if (buffered && buffered.length) { + // HTML5 + return utils.getPercentage(buffered.end(0), this.duration); + } else if (utils.is.number(buffered)) { + // YouTube returns between 0 and 1 + return buffered * 100; + } + + return 0; + })(); + + ui.setProgress.call(this, this.elements.display.buffer, value); + + break; + + default: + break; + } + } + }, + + // Update the displayed time + updateTimeDisplay(target = null, time = 0, inverted = false) { + // Bail if there's no element to display or the value isn't a number + if (!utils.is.element(target) || !utils.is.number(time)) { + return; + } + + // Format time component to add leading zero + const format = value => `0${value}`.slice(-2); + + // Helpers + const getHours = value => parseInt((value / 60 / 60) % 60, 10); + const getMinutes = value => parseInt((value / 60) % 60, 10); + const getSeconds = value => parseInt(value % 60, 10); + + // Breakdown to hours, mins, secs + let hours = getHours(time); + const mins = getMinutes(time); + const secs = getSeconds(time); + + // Do we need to display hours? + if (getHours(this.duration) > 0) { + hours = `${hours}:`; + } else { + hours = ''; + } + + // Render + // eslint-disable-next-line no-param-reassign + target.textContent = `${inverted ? '-' : ''}${hours}${format(mins)}:${format(secs)}`; + }, + + // Handle time change event + timeUpdate(event) { + // Only invert if only one time element is displayed and used for both duration and currentTime + const invert = !utils.is.element(this.elements.display.duration) && this.config.invertTime; + + // Duration + ui.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert); + + // Ignore updates while seeking + if (event && event.type === 'timeupdate' && this.media.seeking) { + return; + } + + // Playing progress + ui.updateProgress.call(this, event); + }, + + // Show the duration on metadataloaded + durationUpdate() { + if (!this.supported.ui) { + return; + } + + // If there's only one time display, display duration there + if (!utils.is.element(this.elements.display.duration) && this.config.displayDuration && this.paused) { + ui.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration); + } + + // If there's a duration element, update content + if (utils.is.element(this.elements.display.duration)) { + ui.updateTimeDisplay.call(this, this.elements.display.duration, this.duration); + } + + // Update the tooltip (if visible) + controls.updateSeekTooltip.call(this); + }, +}; + +export default ui; diff --git a/src/js/utils.js b/src/js/utils.js new file mode 100644 index 00000000..d9dd3df1 --- /dev/null +++ b/src/js/utils.js @@ -0,0 +1,689 @@ +// ========================================================================== +// Plyr utils +// ========================================================================== + +import support from './support'; + +const utils = { + // Check variable types + is: { + plyr(input) { + return this.instanceof(input, Plyr); + }, + object(input) { + return this.getConstructor(input) === Object; + }, + number(input) { + return this.getConstructor(input) === Number && !Number.isNaN(input); + }, + string(input) { + return this.getConstructor(input) === String; + }, + boolean(input) { + return this.getConstructor(input) === Boolean; + }, + function(input) { + return this.getConstructor(input) === Function; + }, + array(input) { + return !this.nullOrUndefined(input) && Array.isArray(input); + }, + weakMap(input) { + return this.instanceof(input, window.WeakMap); + }, + nodeList(input) { + return this.instanceof(input, window.NodeList); + }, + element(input) { + return this.instanceof(input, window.Element); + }, + textNode(input) { + return this.getConstructor(input) === Text; + }, + event(input) { + return this.instanceof(input, window.Event); + }, + cue(input) { + return this.instanceof(input, window.TextTrackCue) || this.instanceof(input, window.VTTCue); + }, + track(input) { + return this.instanceof(input, TextTrack) || (!this.nullOrUndefined(input) && this.string(input.kind)); + }, + nullOrUndefined(input) { + return input === null || typeof input === 'undefined'; + }, + empty(input) { + return ( + this.nullOrUndefined(input) || + ((this.string(input) || this.array(input) || this.nodeList(input)) && !input.length) || + (this.object(input) && !Object.keys(input).length) + ); + }, + instanceof(input, constructor) { + return Boolean(input && constructor && input instanceof constructor); + }, + getConstructor(input) { + return !this.nullOrUndefined(input) ? input.constructor : null; + }, + }, + + // Unfortunately, due to mixed support, UA sniffing is required + getBrowser() { + return { + isIE: /* @cc_on!@ */ false || !!document.documentMode, + isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent), + isIPhone: /(iPhone|iPod)/gi.test(navigator.platform), + isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform), + }; + }, + + // Load an external script + loadScript(url, callback) { + const current = document.querySelector(`script[src="${url}"]`); + + // Check script is not already referenced, if so wait for load + if (current !== null) { + current.callbacks = current.callbacks || []; + current.callbacks.push(callback); + return; + } + + // Build the element + const element = document.createElement('script'); + + // Callback queue + element.callbacks = element.callbacks || []; + element.callbacks.push(callback); + + // Bind callback + if (utils.is.function(callback)) { + element.addEventListener( + 'load', + event => { + element.callbacks.forEach(cb => cb.call(null, event)); + element.callbacks = null; + }, + false + ); + } + + // Set the URL after binding callback + element.src = url; + + // Inject + const first = document.getElementsByTagName('script')[0]; + first.parentNode.insertBefore(element, first); + }, + + // Load an external SVG sprite + loadSprite(url, id) { + if (!utils.is.string(url)) { + return; + } + + const prefix = 'cache-'; + const hasId = utils.is.string(id); + let isCached = false; + + function updateSprite(data) { + // Inject content + this.innerHTML = data; + + // Inject the SVG to the body + document.body.insertBefore(this, document.body.childNodes[0]); + } + + // Only load once + if (!hasId || !document.querySelectorAll(`#${id}`).length) { + // Create container + const container = document.createElement('div'); + utils.toggleHidden(container, true); + + if (hasId) { + container.setAttribute('id', id); + } + + // Check in cache + if (support.storage) { + const cached = window.localStorage.getItem(prefix + id); + isCached = cached !== null; + + if (isCached) { + const data = JSON.parse(cached); + updateSprite.call(container, data.content); + return; + } + } + + // Get the sprite + fetch(url) + .then(response => (response.ok ? response.text() : null)) + .then(text => { + if (text === null) { + return; + } + + if (support.storage) { + window.localStorage.setItem( + prefix + id, + JSON.stringify({ + content: text, + }) + ); + } + + updateSprite.call(container, text); + }) + .catch(() => {}); + } + }, + + // Generate a random ID + generateId(prefix) { + return `${prefix}-${Math.floor(Math.random() * 10000)}`; + }, + + // Determine if we're in an iframe + inFrame() { + try { + return window.self !== window.top; + } catch (e) { + return true; + } + }, + + // Wrap an element + wrap(elements, wrapper) { + // Convert `elements` to an array, if necessary. + const targets = elements.length ? elements : [elements]; + + // Loops backwards to prevent having to clone the wrapper on the + // first element (see `child` below). + Array.from(targets) + .reverse() + .forEach((element, index) => { + const child = index > 0 ? wrapper.cloneNode(true) : wrapper; + + // Cache the current parent and sibling. + const parent = element.parentNode; + const sibling = element.nextSibling; + + // Wrap the element (is automatically removed from its current + // parent). + child.appendChild(element); + + // If the element had a sibling, insert the wrapper before + // the sibling to maintain the HTML structure; otherwise, just + // append it to the parent. + if (sibling) { + parent.insertBefore(child, sibling); + } else { + parent.appendChild(child); + } + }); + }, + + // Create a DocumentFragment + createElement(type, attributes, text) { + // Create a new <element> + const element = document.createElement(type); + + // Set all passed attributes + if (utils.is.object(attributes)) { + utils.setAttributes(element, attributes); + } + + // Add text node + if (utils.is.string(text)) { + element.textContent = text; + } + + // Return built element + return element; + }, + + // Inaert an element after another + insertAfter(element, target) { + target.parentNode.insertBefore(element, target.nextSibling); + }, + + // Insert a DocumentFragment + insertElement(type, parent, attributes, text) { + // Inject the new <element> + parent.appendChild(utils.createElement(type, attributes, text)); + }, + + // Remove an element + removeElement(element) { + if (!utils.is.element(element) || !utils.is.element(element.parentNode)) { + return null; + } + + element.parentNode.removeChild(element); + + return element; + }, + + // Remove all child elements + emptyElement(element) { + let { length } = element.childNodes; + + while (length > 0) { + element.removeChild(element.lastChild); + length -= 1; + } + }, + + // Set attributes + setAttributes(element, attributes) { + if (!utils.is.element(element) || utils.is.empty(attributes)) { + return; + } + + Object.keys(attributes).forEach(key => { + element.setAttribute(key, attributes[key]); + }); + }, + + // Get an attribute object from a string selector + getAttributesFromSelector(sel, existingAttributes) { + // For example: + // '.test' to { class: 'test' } + // '#test' to { id: 'test' } + // '[data-test="test"]' to { 'data-test': 'test' } + + if (!utils.is.string(sel) || utils.is.empty(sel)) { + return {}; + } + + const attributes = {}; + const existing = existingAttributes; + + sel.split(',').forEach(s => { + // Remove whitespace + const selector = s.trim(); + const className = selector.replace('.', ''); + const stripped = selector.replace(/[[\]]/g, ''); + + // Get the parts and value + const parts = stripped.split('='); + const key = parts[0]; + const value = parts.length > 1 ? parts[1].replace(/["']/g, '') : ''; + + // Get the first character + const start = selector.charAt(0); + + switch (start) { + case '.': + // Add to existing classname + if (utils.is.object(existing) && utils.is.string(existing.class)) { + existing.class += ` ${className}`; + } + + attributes.class = className; + break; + + case '#': + // ID selector + attributes.id = selector.replace('#', ''); + break; + + case '[': + // Attribute selector + attributes[key] = value; + + break; + + default: + break; + } + }); + + return attributes; + }, + + // Toggle class on an element + toggleClass(element, className, toggle) { + if (utils.is.element(element)) { + const contains = element.classList.contains(className); + + element.classList[toggle ? 'add' : 'remove'](className); + + return (toggle && !contains) || (!toggle && contains); + } + + return null; + }, + + // Has class name + hasClass(element, className) { + return utils.is.element(element) && element.classList.contains(className); + }, + + // Toggle hidden attribute on an element + toggleHidden(element, toggle) { + if (!utils.is.element(element)) { + return; + } + + if (toggle) { + element.setAttribute('hidden', ''); + } else { + element.removeAttribute('hidden'); + } + }, + + // Element matches selector + matches(element, selector) { + const prototype = { Element }; + + function match() { + return Array.from(document.querySelectorAll(selector)).includes(this); + } + + const matches = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match; + + return matches.call(element, selector); + }, + + // Find all elements + getElements(selector) { + return this.elements.container.querySelectorAll(selector); + }, + + // Find a single element + getElement(selector) { + return this.elements.container.querySelector(selector); + }, + + // Find the UI controls and store references in custom controls + // TODO: Allow settings menus with custom controls + findElements() { + try { + this.elements.controls = utils.getElement.call(this, this.config.selectors.controls.wrapper); + + // Buttons + this.elements.buttons = { + play: utils.getElements.call(this, this.config.selectors.buttons.play), + pause: utils.getElement.call(this, this.config.selectors.buttons.pause), + restart: utils.getElement.call(this, this.config.selectors.buttons.restart), + rewind: utils.getElement.call(this, this.config.selectors.buttons.rewind), + forward: utils.getElement.call(this, this.config.selectors.buttons.forward), + mute: utils.getElement.call(this, this.config.selectors.buttons.mute), + pip: utils.getElement.call(this, this.config.selectors.buttons.pip), + airplay: utils.getElement.call(this, this.config.selectors.buttons.airplay), + settings: utils.getElement.call(this, this.config.selectors.buttons.settings), + captions: utils.getElement.call(this, this.config.selectors.buttons.captions), + fullscreen: utils.getElement.call(this, this.config.selectors.buttons.fullscreen), + }; + + // Progress + this.elements.progress = utils.getElement.call(this, this.config.selectors.progress); + + // Inputs + this.elements.inputs = { + seek: utils.getElement.call(this, this.config.selectors.inputs.seek), + volume: utils.getElement.call(this, this.config.selectors.inputs.volume), + }; + + // Display + this.elements.display = { + buffer: utils.getElement.call(this, this.config.selectors.display.buffer), + duration: utils.getElement.call(this, this.config.selectors.display.duration), + currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime), + }; + + // Seek tooltip + if (utils.is.element(this.elements.progress)) { + this.elements.display.seekTooltip = this.elements.progress.querySelector(`.${this.config.classNames.tooltip}`); + } + + return true; + } catch (error) { + // Log it + this.debug.warn('It looks like there is a problem with your custom controls HTML', error); + + // Restore native video controls + this.toggleNativeControls(true); + + return false; + } + }, + + // Get the focused element + getFocusElement() { + let focused = document.activeElement; + + if (!focused || focused === document.body) { + focused = null; + } else { + focused = document.querySelector(':focus'); + } + + return focused; + }, + + // Trap focus inside container + trapFocus() { + const focusable = utils.getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]'); + const first = focusable[0]; + const last = focusable[focusable.length - 1]; + + utils.on( + this.elements.container, + 'keydown', + event => { + // Bail if not tab key or not fullscreen + if (event.key !== 'Tab' || event.keyCode !== 9 || !this.fullscreen.active) { + return; + } + + // Get the current focused element + const focused = utils.getFocusElement(); + + if (focused === last && !event.shiftKey) { + // Move focus to first element that can be tabbed if Shift isn't used + first.focus(); + event.preventDefault(); + } else if (focused === first && event.shiftKey) { + // Move focus to last element that can be tabbed if Shift is used + last.focus(); + event.preventDefault(); + } + }, + false + ); + }, + + // Toggle event listener + toggleListener(elements, event, callback, toggle, passive, capture) { + // Bail if no elements + if (utils.is.nullOrUndefined(elements)) { + return; + } + + // If a nodelist is passed, call itself on each node + if (utils.is.nodeList(elements)) { + // Create listener for each node + Array.from(elements).forEach(element => { + if (element instanceof Node) { + utils.toggleListener.call(null, element, event, callback, toggle, passive, capture); + } + }); + + return; + } + + // Allow multiple events + const events = event.split(' '); + + // Build options + // Default to just capture boolean + let options = utils.is.boolean(capture) ? capture : false; + + // If passive events listeners are supported + if (support.passiveListeners) { + options = { + // Whether the listener can be passive (i.e. default never prevented) + passive: utils.is.boolean(passive) ? passive : true, + // Whether the listener is a capturing listener or not + capture: utils.is.boolean(capture) ? capture : false, + }; + } + + // If a single node is passed, bind the event listener + events.forEach(type => { + elements[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options); + }); + }, + + // Bind event handler + on(element, events, callback, passive, capture) { + utils.toggleListener(element, events, callback, true, passive, capture); + }, + + // Unbind event handler + off(element, events, callback, passive, capture) { + utils.toggleListener(element, events, callback, false, passive, capture); + }, + + // Trigger event + dispatchEvent(element, type, bubbles, detail) { + // Bail if no element + if (!element || !type) { + return; + } + + // Create and dispatch the event + const event = new CustomEvent(type, { + bubbles: utils.is.boolean(bubbles) ? bubbles : false, + detail: Object.assign({}, detail, { + plyr: this instanceof Plyr ? this : null, + }), + }); + + // Dispatch the event + element.dispatchEvent(event); + }, + + // Toggle aria-pressed state on a toggle button + // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles + toggleState(element, input) { + // Bail if no target + if (!utils.is.element(element)) { + return; + } + + // Get state + const pressed = element.getAttribute('aria-pressed') === 'true'; + const state = utils.is.boolean(input) ? input : !pressed; + + // Set the attribute on target + element.setAttribute('aria-pressed', state); + }, + + // Get percentage + getPercentage(current, max) { + if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) { + return 0; + } + return (current / max * 100).toFixed(2); + }, + + // Deep extend destination object with N more objects + extend(target = {}, ...sources) { + if (!sources.length) { + return target; + } + + const source = sources.shift(); + + if (!utils.is.object(source)) { + return target; + } + + Object.keys(source).forEach(key => { + if (utils.is.object(source[key])) { + if (!Object.keys(target).includes(key)) { + Object.assign(target, { [key]: {} }); + } + + utils.extend(target[key], source[key]); + } else { + Object.assign(target, { [key]: source[key] }); + } + }); + + return utils.extend(target, ...sources); + }, + + // Parse YouTube ID from URL + parseYouTubeId(url) { + const regex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/; + return url.match(regex) ? RegExp.$2 : url; + }, + + // Parse Vimeo ID from URL + parseVimeoId(url) { + if (utils.is.number(Number(url))) { + return url; + } + + const regex = /^.*(vimeo.com\/|video\/)(\d+).*/; + return url.match(regex) ? RegExp.$2 : url; + }, + + // Convert object to URL parameters + buildUrlParameters(input) { + if (!utils.is.object(input)) { + return ''; + } + + return Object.keys(input) + .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(input[key])}`) + .join('&'); + }, + + // Remove HTML from a string + stripHTML(source) { + const fragment = document.createDocumentFragment(); + const element = document.createElement('div'); + fragment.appendChild(element); + element.innerHTML = source; + return fragment.firstChild.innerText; + }, + + // Get aspect ratio for dimensions + getAspectRatio(width, height) { + const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h)); + const ratio = getRatio(width, height); + return `${width / ratio}:${height / ratio}`; + }, + + // Get the transition end event + transitionEnd: (() => { + const element = document.createElement('span'); + + const events = { + WebkitTransition: 'webkitTransitionEnd', + MozTransition: 'transitionend', + OTransition: 'oTransitionEnd otransitionend', + transition: 'transitionend', + }; + + const type = Object.keys(events).find(event => element.style[event] !== undefined); + + return typeof type === 'string' ? type : false; + })(), + + // Force repaint of element + repaint(element) { + window.setTimeout(() => { + element.setAttribute('hidden', ''); + element.offsetHeight; // eslint-disable-line + element.removeAttribute('hidden'); + }, 0); + }, +}; + +export default utils; diff --git a/src/less/mixins.less b/src/less/mixins.less deleted file mode 100644 index 25f43761..00000000 --- a/src/less/mixins.less +++ /dev/null @@ -1,29 +0,0 @@ -// ========================================================================== -// Plyr mixins -// https://github.com/selz/plyr -// ========================================================================== - -// <input type="range"> styling -.plyr-range-track() { - height: @plyr-range-track-height; - background: transparent; - border: 0; - border-radius: (@plyr-range-track-height / 2); - user-select: none; -} -.plyr-range-thumb() { - position: relative; - height: @plyr-range-thumb-height; - width: @plyr-range-thumb-width; - background: @plyr-range-thumb-bg; - border: @plyr-range-thumb-border; - border-radius: 100%; - transition: background .2s ease, border .2s ease, transform .2s ease; - box-shadow: @plyr-range-thumb-shadow; - box-sizing: border-box; -} -.plyr-range-thumb-active() { - background: @plyr-range-thumb-active-bg; - border-color: @plyr-range-thumb-active-border-color; - transform: scale(@plyr-range-thumb-active-scale); -}
\ No newline at end of file diff --git a/src/less/plyr.less b/src/less/plyr.less deleted file mode 100644 index b701a6ce..00000000 --- a/src/less/plyr.less +++ /dev/null @@ -1,770 +0,0 @@ -// ========================================================================== -// Plyr styles -// https://github.com/selz/plyr -// ========================================================================== - -@import 'variables'; -@import 'mixins'; - -// Animation -// --------------------------------------- -@keyframes plyr-progress { - to { - background-position: @plyr-progress-loading-size 0; - } -} - -// Styles -// ------------------------------- -// Base -.plyr { - position: relative; - max-width: 100%; - min-width: 200px; - font-family: @plyr-font-family; - direction: ltr; - - & when (@plyr-border-box = true) { - // border-box everything - // http://paulirish.com/2012/box-sizing-border-box-ftw/ - &, - *, - *::after, - *::before { - box-sizing: border-box; - } - } - - & when (@plyr-touch-action = true) { - // Fix 300ms delay - a, - button, - input, - label { - touch-action: manipulation; - } - } - - // Focus - &:focus { - outline: 0; - } - - // Media elements - video, - audio { - width: 100%; - height: auto; - vertical-align: middle; - border-radius: inherit; - } - - // Range inputs - // Specificity is for bootstrap compatibility - input[type='range'] { - display: block; - height: (@plyr-range-thumb-height * @plyr-range-thumb-active-scale); - width: 100%; - margin: 0; - padding: 0; - - -webkit-appearance: none; - -moz-appearance: none; - cursor: pointer; - border: none; - background: transparent; - - // WebKit - &::-webkit-slider-runnable-track { - .plyr-range-track(); - } - &::-webkit-slider-thumb { - -webkit-appearance: none; - margin-top: -((@plyr-range-thumb-height - @plyr-range-track-height) / 2); - .plyr-range-thumb(); - } - - // Mozilla - &::-moz-range-track { - .plyr-range-track(); - } - &::-moz-range-thumb { - .plyr-range-thumb(); - } - - // Microsoft - &::-ms-track { - height: @plyr-range-track-height; - background: transparent; - border: 0; - color: transparent; - } - &::-ms-fill-upper { - .plyr-range-track(); - } - &::-ms-fill-lower { - .plyr-range-track(); - background: @plyr-range-selected-bg; - } - &::-ms-thumb { - .plyr-range-thumb(); - // For some reason, Edge uses the -webkit margin above - margin-top: 0; - } - &::-ms-tooltip { - display: none; - } - - // Focus styles - &:focus { - outline: 0; - } - &::-moz-focus-outer { - border: 0; - } - &.tab-focus:focus { - outline-offset: 3px; - } - - // Pressed styles - &:active { - &::-webkit-slider-thumb { - .plyr-range-thumb-active(); - } - &::-moz-range-thumb { - .plyr-range-thumb-active(); - } - &::-ms-thumb { - .plyr-range-thumb-active(); - } - } - } -} - -// Video range inputs -.plyr--video input[type='range'].tab-focus:focus { - outline: 1px dotted fade(@plyr-video-control-color, 50%); -} - -// Audio range inputs -.plyr--audio input[type='range'].tab-focus:focus { - outline: 1px dotted fade(@plyr-audio-control-color, 50%); -} - -// Screen reader only elements -.plyr__sr-only { - clip: rect(1px, 1px, 1px, 1px); - overflow: hidden; - - // !important is not always needed - & when (@plyr-sr-only-important = true) { - position: absolute !important; - padding: 0 !important; - border: 0 !important; - height: 1px !important; - width: 1px !important; - } - & when (@plyr-sr-only-important = false) { - position: absolute; - padding: 0; - border: 0; - height: 1px; - width: 1px; - } -} - -// Video -.plyr__video-wrapper { - position: relative; - background: #000; - border-radius: inherit; -} - -// Container for embeds -.plyr__video-embed { - padding-bottom: 56.25%; /* 16:9 */ - height: 0; - border-radius: inherit; - - // Require overflow and z-index to force border-radius - overflow: hidden; - z-index: 0; - - iframe { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - border: 0; - user-select: none; - } - - // Vimeo hack - > div { - position: relative; - padding-bottom: 200%; - transform: translateY(-35.95%); - } -} -// To allow mouse events to be captured if full support -.plyr .plyr__video-embed iframe { - pointer-events: none; -} - -// Captions -// -------------------------------------------------------------- -// Hide default captions -.plyr video::-webkit-media-text-track-container { - display: none; -} -.plyr__captions { - display: none; - position: absolute; - bottom: 0; - left: 0; - width: 100%; - padding: (@plyr-control-spacing * 2); - transform: translateY(-(@plyr-control-spacing * 4)); - transition: transform 0.3s ease; - color: @plyr-captions-color; - font-size: @plyr-font-size-captions-base; - text-align: center; - font-weight: 400; - - span { - border-radius: 2px; - padding: floor(@plyr-control-spacing / 3) @plyr-control-spacing; - background: @plyr-captions-bg; - box-decoration-break: clone; - line-height: 150%; - } - span:empty { - display: none; - } - - @media (min-width: @plyr-bp-screen-md) { - font-size: @plyr-font-size-captions-medium; - } -} -.plyr--captions-active .plyr__captions { - display: block; -} -.plyr--hide-controls .plyr__captions { - transform: translateY(-(@plyr-control-spacing * 1.5)); -} -// Large captions in full screen on larger screens -@media (min-width: @plyr-bp-screen-lg) { - .plyr--fullscreen-active .plyr__captions { - font-size: @plyr-font-size-captions-large; - } -} - -// Controls -// -------------------------------------------------------------- -// Hide native controls -.plyr ::-webkit-media-controls { - display: none; -} - -// Playback controls -.plyr__controls { - display: flex; - align-items: center; - line-height: 1; - text-align: center; - pointer-events: none; - - & > * { - pointer-events: all; - } - - // Spacing - > button, - .plyr__progress, - .plyr__time { - margin-left: (@plyr-control-spacing / 2); - - &:first-child { - margin-left: 0; - } - } - .plyr__volume { - margin-left: (@plyr-control-spacing / 2); - } - [data-plyr='pause'] { - margin-left: 0; - } - - // Buttons - button { - position: relative; - display: inline-block; - flex-shrink: 0; - overflow: visible; // IE11 - vertical-align: middle; - padding: @plyr-control-padding; - border: 0; - background: transparent; - border-radius: 3px; - cursor: pointer; - transition: background 0.3s ease, color 0.3s ease, opacity 0.3s ease; - color: inherit; - - svg { - width: @plyr-control-icon-size; - height: @plyr-control-icon-size; - display: block; - fill: currentColor; - } - - // Default focus - &:focus { - outline: 0; - } - } - - // Hide toggle icons by default - .icon--exit-fullscreen, - .icon--muted, - .icon--captions-on { - display: none; - } - - @media (min-width: @plyr-bp-screen-sm) { - > button, - .plyr__progress, - .plyr__time { - margin-left: @plyr-control-spacing; - } - } -} -// Hide controls -.plyr--hide-controls .plyr__controls { - opacity: 0; - pointer-events: none; -} - -// Video controls -.plyr--video .plyr__controls { - position: absolute; - left: 0; - right: 0; - bottom: 0; - z-index: 2; - padding: (@plyr-control-spacing * 5) @plyr-control-spacing @plyr-control-spacing; - background: linear-gradient(fade(@plyr-video-controls-bg, 0%), fade(@plyr-video-controls-bg, 50%)); - border-bottom-left-radius: inherit; - border-bottom-right-radius: inherit; - color: @plyr-video-control-color; - transition: opacity 0.3s ease; - - button { - // Hover and tab focus - &.tab-focus:focus, - &:hover { - background: @plyr-video-control-bg-hover; - color: @plyr-video-control-color-hover; - } - } -} - -// Audio controls -.plyr--audio .plyr__controls { - padding: @plyr-control-spacing; - border-radius: inherit; - background: @plyr-audio-controls-bg; - border: @plyr-audio-controls-border; - color: @plyr-audio-control-color; - - button { - // Hover and tab focus - &.tab-focus:focus, - &:hover { - background: @plyr-audio-control-bg-hover; - color: @plyr-audio-control-color-hover; - } - } -} - -// Large play button (video only) -.plyr__play-large { - display: none; - position: absolute; - z-index: 1; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - padding: @plyr-control-spacing; - background: @plyr-video-control-bg-hover; - border: 4px solid currentColor; - border-radius: 100%; - box-shadow: 0 1px 1px fade(#000, 15%); - color: @plyr-video-control-color; - transition: all 0.3s ease; - - svg { - position: relative; - left: 2px; - width: 20px; - height: 20px; - display: block; - fill: currentColor; - } - - &:focus { - outline: 1px dotted fade(@plyr-video-control-color, 50%); - } -} -.plyr .plyr__play-large { - display: inline-block; -} -.plyr--audio .plyr__play-large { - display: none; -} -.plyr--playing .plyr__play-large { - opacity: 0; - visibility: hidden; -} - -// States -.plyr__controls [data-plyr='pause'], -.plyr--playing .plyr__controls [data-plyr='play'] { - display: none; -} -.plyr--playing .plyr__controls [data-plyr='pause'] { - display: inline-block; -} - -// Change icons on state change -.plyr--fullscreen-active .icon--exit-fullscreen, -.plyr--muted .plyr__controls .icon--muted, -.plyr--captions-active .plyr__controls .icon--captions-on { - display: block; - - & + svg { - display: none; - } -} - -// Some options are hidden by default -.plyr [data-plyr='captions'], -.plyr [data-plyr='fullscreen'] { - display: none; -} -.plyr--captions-enabled [data-plyr='captions'], -.plyr--fullscreen-enabled [data-plyr='fullscreen'] { - display: inline-block; -} - -// Tooltips -// -------------------------------------------------------------- -.plyr__tooltip { - position: absolute; - z-index: 2; - bottom: 100%; - margin-bottom: (@plyr-tooltip-padding * 2); - padding: @plyr-tooltip-padding (@plyr-tooltip-padding * 1.5); - pointer-events: none; - - opacity: 0; - background: @plyr-tooltip-bg; - border-radius: @plyr-tooltip-radius; - - color: @plyr-tooltip-color; - font-size: @plyr-font-size-small; - line-height: 1.3; - - transform: translate(-50%, 10px) scale(0.8); - transform-origin: 50% 100%; - transition: transform 0.2s 0.1s ease, opacity 0.2s 0.1s ease; - - &::before { - // Arrows - content: ''; - position: absolute; - width: 0; - height: 0; - left: 50%; - transform: translateX(-50%); - - // The background triangle - bottom: -@plyr-tooltip-arrow-size; - border-right: @plyr-tooltip-arrow-size solid transparent; - border-top: @plyr-tooltip-arrow-size solid @plyr-tooltip-bg; - border-left: @plyr-tooltip-arrow-size solid transparent; - z-index: 2; - } -} -.plyr button:hover .plyr__tooltip, -.plyr button.tab-focus:focus .plyr__tooltip, -.plyr__tooltip--visible { - opacity: 1; - transform: translate(-50%, 0) scale(1); -} -.plyr button:hover .plyr__tooltip { - z-index: 3; -} - -// First tooltip -.plyr__controls button:first-child .plyr__tooltip { - left: 0; - transform: translate(0, 10px) scale(0.8); - transform-origin: 0 100%; - - &::before { - left: (@plyr-control-icon-size / 2) + @plyr-control-padding; - } -} - -// Last tooltip -.plyr__controls button:last-child .plyr__tooltip { - right: 0; - transform: translate(0, 10px) scale(0.8); - transform-origin: 100% 100%; - - &::before { - left: auto; - right: (@plyr-control-icon-size / 2) + @plyr-control-padding; - transform: translateX(50%); - } -} - -.plyr__controls button:first-child, -.plyr__controls button:last-child { - &:hover .plyr__tooltip, - &.tab-focus:focus .plyr__tooltip, - .plyr__tooltip--visible { - transform: translate(0, 0) scale(1); - } -} - -// Playback progress -// -------------------------------------------------------------- -// <progress> element -.plyr__progress { - position: relative; - display: none; - flex: 1; - - input[type='range'] { - position: relative; - z-index: 2; - - &::-webkit-slider-runnable-track { - background: transparent; - } - &::-moz-range-track { - background: transparent; - } - &::-ms-fill-upper { - background: transparent; - } - } - - // Seek tooltip to show time - .plyr__tooltip { - left: 0; - } -} -.plyr .plyr__progress { - display: inline-block; -} - -.plyr__progress--buffer, -.plyr__progress--played, -.plyr__volume--display { - position: absolute; - left: 0; - top: 50%; - width: 100%; - height: @plyr-range-track-height; - margin: -(@plyr-range-track-height / 2) 0 0; - padding: 0; - vertical-align: top; - -webkit-appearance: none; - -moz-appearance: none; - border: none; - border-radius: 100px; - - &::-webkit-progress-bar { - background: transparent; - } - &::-webkit-progress-value { - background: currentColor; - border-radius: 100px; - min-width: @plyr-range-track-height; - } - &::-moz-progress-bar { - background: currentColor; - border-radius: 100px; - min-width: @plyr-range-track-height; - } - &::-ms-fill { - border-radius: 100px; - } -} -.plyr__progress--played, -.plyr__volume--display { - z-index: 1; - color: @plyr-range-selected-bg; - background: transparent; - transition: none; - - &::-webkit-progress-value { - min-width: @plyr-range-track-height; - max-width: 99%; - border-top-right-radius: 0; - border-bottom-right-radius: 0; - transition: none; - } - &::-moz-progress-bar { - min-width: @plyr-range-track-height; - max-width: 99%; - border-top-right-radius: 0; - border-bottom-right-radius: 0; - transition: none; - } - &::-ms-fill { - display: none; - } -} -.plyr__progress--buffer { - &::-webkit-progress-value { - transition: width 0.2s ease; - } - &::-moz-progress-bar { - transition: width 0.2s ease; - } - &::-ms-fill { - transition: width 0.2s ease; - } -} -.plyr--video .plyr__progress--buffer, -.plyr--video .plyr__volume--display { - background: @plyr-video-range-track-bg; -} -.plyr--video .plyr__progress--buffer { - color: @plyr-video-progress-buffered-bg; -} -.plyr--audio .plyr__progress--buffer, -.plyr--audio .plyr__volume--display { - background: @plyr-audio-range-track-bg; -} -.plyr--audio .plyr__progress--buffer { - color: @plyr-audio-progress-buffered-bg; -} - -// Loading state -.plyr--loading .plyr__progress--buffer { - animation: plyr-progress 1s linear infinite; - background-size: @plyr-progress-loading-size @plyr-progress-loading-size; - background-repeat: repeat-x; - background-image: linear-gradient( - -45deg, - @plyr-progress-loading-bg 25%, - transparent 25%, - transparent 50%, - @plyr-progress-loading-bg 50%, - @plyr-progress-loading-bg 75%, - transparent 75%, - transparent - ); - color: transparent; -} -.plyr--video.plyr--loading .plyr__progress--buffer { - background-color: @plyr-video-progress-buffered-bg; -} -.plyr--audio.plyr--loading .plyr__progress--buffer { - background-color: @plyr-audio-progress-buffered-bg; -} - -// Time -// -------------------------------------------------------------- -.plyr__time { - display: inline-block; - vertical-align: middle; - font-size: @plyr-font-size-small; -} -// Media duration hidden on small screens -.plyr__time + .plyr__time { - display: none; - - @media (min-width: @plyr-bp-screen-md) { - display: inline-block; - } - - // Add a slash in before - &::before { - content: '\2044'; - margin-right: @plyr-control-spacing; - } -} - -// Volume -// -------------------------------------------------------------- -.plyr__volume { - display: none; -} -.plyr .plyr__volume { - flex: 1; - position: relative; - - input[type='range'] { - position: relative; - z-index: 2; - } - @media (min-width: @plyr-bp-screen-sm) { - display: block; - max-width: 60px; - } - @media (min-width: @plyr-bp-screen-md) { - max-width: 100px; - } -} - -// Hide sound controls on iOS -// It's not supported to change volume using JavaScript: -// https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html -.plyr--is-ios .plyr__volume, -.plyr--is-ios [data-plyr='mute'] { - display: none !important; -} - -// Fullscreen -// -------------------------------------------------------------- -.plyr--fullscreen-active { - height: 100%; - width: 100%; - background: #000; - border-radius: 0 !important; - - video { - height: 100%; - } - .plyr__video-wrapper { - height: 100%; - width: 100%; - } - .plyr__video-embed { - // Revert overflow change - overflow: visible; - } - - // Vimeo requires some different styling - &.plyr--vimeo .plyr__video-wrapper { - height: 0; - top: 50%; - transform: translateY(-50%); - } -} - -// Fallback for unsupported browsers -.plyr--fullscreen-fallback.plyr--fullscreen-active { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 10000000; -} diff --git a/src/less/variables.less b/src/less/variables.less deleted file mode 100644 index 807d0854..00000000 --- a/src/less/variables.less +++ /dev/null @@ -1,72 +0,0 @@ -// ========================================================================== -// Plyr variables -// https://github.com/selz/plyr -// ========================================================================== - -// Settings -@plyr-border-box: true; -@plyr-touch-action: true; -@plyr-sr-only-important: true; - -// Colors -@plyr-color-main: #3498db; - -// Font -@plyr-font-family: Avenir, 'Avenir Next', 'Helvetica Neue', 'Segoe UI', Helvetica, Arial, sans-serif; -@plyr-font-size-small: 14px; -@plyr-font-size-base: 16px; - -// Captions -@plyr-captions-bg: fade(#000, 70%); -@plyr-captions-color: #fff; -@plyr-font-size-captions-base: @plyr-font-size-base; -@plyr-font-size-captions-medium: ceil(@plyr-font-size-base * 1.5); -@plyr-font-size-captions-large: (@plyr-font-size-base * 2); - -// Controls -@plyr-control-icon-size: 18px; -@plyr-control-spacing: 10px; -@plyr-control-padding: (@plyr-control-spacing * .7); -@plyr-video-controls-bg: #000; -@plyr-video-control-color: #fff; -@plyr-video-control-color-hover: #fff; -@plyr-video-control-bg-hover: @plyr-color-main; -@plyr-audio-controls-bg: #fff; -@plyr-audio-controls-border: 1px solid #dbe3e8; -@plyr-audio-control-color: #565D64; -@plyr-audio-control-color-hover: #fff; -@plyr-audio-control-bg-hover: @plyr-color-main; - -// Tooltips -@plyr-tooltip-bg: fade(#000, 70%); -@plyr-tooltip-color: #fff; -@plyr-tooltip-padding: (@plyr-control-spacing / 2); -@plyr-tooltip-arrow-size: 4px; -@plyr-tooltip-radius: 3px; - -// Progress -@plyr-progress-loading-size: 25px; -@plyr-progress-loading-bg: fade(#000, 15%); -@plyr-video-progress-bg: fade(#fff, 25%); -@plyr-video-progress-buffered-bg: @plyr-video-progress-bg; -@plyr-audio-progress-bg: fade(#C6D6DB, 66%); -@plyr-audio-progress-buffered-bg: @plyr-audio-progress-bg; - -// Range sliders -@plyr-range-track-height: 8px; -@plyr-range-thumb-height: floor(@plyr-range-track-height * 2); -@plyr-range-thumb-width: floor(@plyr-range-track-height * 2); -@plyr-range-thumb-bg: #fff; -@plyr-range-thumb-border: 2px solid transparent; -@plyr-range-thumb-shadow: 0 1px 1px fade(@plyr-video-controls-bg, 15%), 0 0 0 1px fade(#000, 15%); -@plyr-range-thumb-active-border-color: #fff; -@plyr-range-thumb-active-bg: @plyr-video-control-bg-hover; -@plyr-range-thumb-active-scale: 1.25; -@plyr-video-range-track-bg: @plyr-video-progress-buffered-bg; -@plyr-audio-range-track-bg: @plyr-audio-progress-buffered-bg; -@plyr-range-selected-bg: @plyr-color-main; - -// Breakpoints -@plyr-bp-screen-sm: 480px; -@plyr-bp-screen-md: 768px; -@plyr-bp-screen-lg: 1024px;
\ No newline at end of file diff --git a/src/sass/base.scss b/src/sass/base.scss new file mode 100644 index 00000000..307da36e --- /dev/null +++ b/src/sass/base.scss @@ -0,0 +1,58 @@ +// -------------------------------------------------------------- +// Base styling +// -------------------------------------------------------------- + +// Base +.plyr { + @include plyr-font-smoothing($plyr-font-smoothing); + + direction: ltr; + font-family: $plyr-font-family; + font-weight: $plyr-font-weight-regular; + line-height: $plyr-line-height; + max-width: 100%; + min-width: 200px; + position: relative; + text-shadow: none; + transition: box-shadow 0.3s ease; + + // Media elements + video, + audio { + border-radius: inherit; + height: auto; + vertical-align: middle; + width: 100%; + } + + // Ignore focus + &:focus { + outline: 0; + } +} + +// border-box everything +// http://paulirish.com/2012/box-sizing-border-box-ftw/ +@if $plyr-border-box { + .plyr--full-ui { + box-sizing: border-box; + + *, + *::after, + *::before { + box-sizing: inherit; + } + } +} + +// Fix 300ms delay +@if $plyr-touch-action { + .plyr--full-ui { + a, + button, + input, + label { + touch-action: manipulation; + } + } +} diff --git a/src/sass/components/badges.scss b/src/sass/components/badges.scss new file mode 100644 index 00000000..7d28ffaf --- /dev/null +++ b/src/sass/components/badges.scss @@ -0,0 +1,12 @@ +// -------------------------------------------------------------- +// Badges +// -------------------------------------------------------------- + +.plyr__badge { + background: $plyr-menu-color; + border-radius: 2px; + color: $plyr-menu-bg; + font-size: $plyr-font-size-badge; + line-height: 1; + padding: 3px 4px; +} diff --git a/src/sass/components/captions.scss b/src/sass/components/captions.scss new file mode 100644 index 00000000..9dfc2be8 --- /dev/null +++ b/src/sass/components/captions.scss @@ -0,0 +1,58 @@ +// -------------------------------------------------------------- +// Captions +// -------------------------------------------------------------- + +// Hide default captions +.plyr--full-ui ::-webkit-media-text-track-container { + display: none; +} + +.plyr__captions { + animation: plyr-fade-in 0.3s ease; + bottom: 0; + color: $plyr-captions-color; + display: none; + font-size: $plyr-font-size-captions-small; + left: 0; + padding: $plyr-control-spacing; + position: absolute; + text-align: center; + transform: translateY(-($plyr-control-spacing * 4)); + transition: transform 0.4s ease-in-out; + width: 100%; + + span { + background: $plyr-captions-bg; + border-radius: 2px; + box-decoration-break: clone; + line-height: 185%; + padding: 0.2em 0.5em; + white-space: pre-wrap; + + // Firefox adds a <div> when using getCueAsHTML() + div { + display: inline; + } + } + + span:empty { + display: none; + } + + @media (min-width: $plyr-bp-sm) { + font-size: $plyr-font-size-captions-base; + padding: ($plyr-control-spacing * 2); + } + + @media (min-width: $plyr-bp-md) { + font-size: $plyr-font-size-captions-medium; + } +} + +.plyr--captions-active .plyr__captions { + display: block; +} + +.plyr--hide-controls .plyr__captions { + transform: translateY(-($plyr-control-spacing * 1.5)); +} diff --git a/src/sass/components/control.scss b/src/sass/components/control.scss new file mode 100644 index 00000000..52716805 --- /dev/null +++ b/src/sass/components/control.scss @@ -0,0 +1,89 @@ +// -------------------------------------------------------------- +// Control buttons +// -------------------------------------------------------------- + +.plyr__control { + background: transparent; + border: 0; + border-radius: $plyr-control-radius; + color: inherit; + cursor: pointer; + flex-shrink: 0; + overflow: visible; // IE11 + padding: $plyr-control-padding; + position: relative; + transition: all 0.3s ease; + + svg { + display: block; + fill: currentColor; + height: $plyr-control-icon-size; + pointer-events: none; + width: $plyr-control-icon-size; + } + + // Default focus + &:focus { + outline: 0; + } + + // Tab focus + &.plyr__tab-focus { + @include plyr-tab-focus(); + } +} + +// Change icons on state change +.plyr__control[aria-pressed='false'] .icon--pressed, +.plyr__control[aria-pressed='true'] .icon--not-pressed, +.plyr__control[aria-pressed='false'] .label--pressed, +.plyr__control[aria-pressed='true'] .label--not-pressed { + display: none; +} + +// Audio styles +.plyr--audio .plyr__control { + &.plyr__tab-focus, + &:hover, + &[aria-expanded='true'] { + background: $plyr-audio-control-bg-hover; + color: $plyr-audio-control-color-hover; + } +} + +// Large play button (video only) +.plyr__control--overlaid { + background: rgba($plyr-video-control-bg-hover, 0.8); + border: 0; + border-radius: 100%; + box-shadow: 0 1px 1px rgba(#000, 0.15); + color: $plyr-video-control-color; + display: none; + left: 50%; + padding: ceil($plyr-control-spacing * 1.5); + position: absolute; + top: 50%; + transform: translate(-50%, -50%); + z-index: 2; + + svg { + height: $plyr-control-icon-size-large; + left: 2px; // Offset to make the play button look right + position: relative; + width: $plyr-control-icon-size-large; + } + + &:hover, + &:focus { + background: $plyr-video-control-bg-hover; + } +} + +.plyr--playing .plyr__control--overlaid { + opacity: 0; + visibility: hidden; +} + +.plyr--full-ui.plyr--video .plyr__control--overlaid { + display: block; +} diff --git a/src/sass/components/controls.scss b/src/sass/components/controls.scss new file mode 100644 index 00000000..91db1b20 --- /dev/null +++ b/src/sass/components/controls.scss @@ -0,0 +1,105 @@ +// -------------------------------------------------------------- +// Controls +// -------------------------------------------------------------- + +// Hide native controls +.plyr--full-ui ::-webkit-media-controls { + display: none; +} + +// Playback controls +.plyr__controls { + align-items: center; + display: flex; + text-align: center; + + // Spacing + > .plyr__control, + .plyr__progress, + .plyr__time, + .plyr__menu { + margin-left: ($plyr-control-spacing / 2); + + &:first-child, + &:first-child + [data-plyr='pause'] { + margin-left: 0; + } + } + + .plyr__volume { + margin-left: ($plyr-control-spacing / 2); + } + + @media (min-width: $plyr-bp-sm) { + > .plyr__control, + .plyr__progress, + .plyr__time, + .plyr__menu { + margin-left: $plyr-control-spacing; + } + + > .plyr__control + .plyr__control, + .plyr__menu + .plyr__control, + > .plyr__control + .plyr__menu { + margin-left: ($plyr-control-spacing / 2); + } + } +} + +// Video controls +.plyr--video .plyr__controls { + background: linear-gradient(rgba($plyr-video-controls-bg, 0), rgba($plyr-video-controls-bg, 0.7)); + border-bottom-left-radius: inherit; + border-bottom-right-radius: inherit; + bottom: 0; + color: $plyr-video-control-color; + left: 0; + padding: ($plyr-control-spacing * 3.5) $plyr-control-spacing $plyr-control-spacing; + position: absolute; + right: 0; + transition: opacity 0.4s ease-in-out, transform 0.4s ease-in-out; + z-index: 2; + + .plyr__control { + svg { + filter: drop-shadow(0 1px 1px rgba(#000, 0.15)); + } + + // Hover and tab focus + &.plyr__tab-focus, + &:hover, + &[aria-expanded='true'] { + background: $plyr-video-control-bg-hover; + color: $plyr-video-control-color-hover; + } + } +} + +// Audio controls +.plyr--audio .plyr__controls { + background: $plyr-audio-controls-bg; + border-radius: inherit; + color: $plyr-audio-control-color; + padding: $plyr-control-spacing; +} + +// Hide controls +.plyr--video.plyr--hide-controls .plyr__controls { + opacity: 0; + pointer-events: none; + transform: translateY(100%); +} + +// Some options are hidden by default +.plyr [data-plyr='captions'], +.plyr [data-plyr='pip'], +.plyr [data-plyr='airplay'], +.plyr [data-plyr='fullscreen'] { + display: none; +} +.plyr--captions-enabled [data-plyr='captions'], +.plyr--pip-supported [data-plyr='pip'], +.plyr--airplay-supported [data-plyr='airplay'], +.plyr--fullscreen-enabled [data-plyr='fullscreen'] { + display: inline-block; +} diff --git a/src/sass/components/embed.scss b/src/sass/components/embed.scss new file mode 100644 index 00000000..d9349052 --- /dev/null +++ b/src/sass/components/embed.scss @@ -0,0 +1,35 @@ +// -------------------------------------------------------------- +// Embedded players +// YouTube, Vimeo, etc +// -------------------------------------------------------------- + +.plyr__video-embed { + // Default to 16:9 ratio but this is set by JavaScript based on config + $padding: ((100 / 16) * 9); + $height: 200; + $offset: to-percentage(($height - $padding) / ($height / 50)); + + height: 0; + padding-bottom: to-percentage($padding); + + iframe { + border: 0; + height: 100%; + left: 0; + position: absolute; + top: 0; + user-select: none; + width: 100%; + } + + // Vimeo hack + > div { + padding-bottom: to-percentage($height); + position: relative; + transform: translateY(-$offset); + } +} +// To allow mouse events to be captured if full support +.plyr--full-ui .plyr__video-embed iframe { + pointer-events: none; +} diff --git a/src/sass/components/menus.scss b/src/sass/components/menus.scss new file mode 100644 index 00000000..35fc580d --- /dev/null +++ b/src/sass/components/menus.scss @@ -0,0 +1,190 @@ +// -------------------------------------------------------------- +// Menus +// -------------------------------------------------------------- + +.plyr__menu { + display: flex; // Edge fix + position: relative; + + // Animate the icon + .plyr__control svg { + transition: transform 0.3s ease; + } + .plyr__control[aria-expanded='true'] { + svg { + transform: rotate(90deg); + } + + // Hide tooltip + .plyr__tooltip { + display: none; + } + } + + // The actual menu container + &__container { + animation: plyr-popup 0.2s ease; + background: $plyr-menu-bg; + border-radius: 4px; + bottom: 100%; + box-shadow: $plyr-menu-shadow; + color: $plyr-menu-color; + font-size: $plyr-font-size-base; + margin-bottom: 10px; + position: absolute; + right: -3px; + text-align: left; + white-space: nowrap; + z-index: 1; + + > div { + overflow: hidden; + transition: height 0.35s cubic-bezier(0.4, 0, 0.2, 1), width 0.35s cubic-bezier(0.4, 0, 0.2, 1); + } + + // Arrow + &::after { + border: 4px solid transparent; + border-top-color: $plyr-menu-bg; + content: ''; + height: 0; + position: absolute; + right: 15px; + top: 100%; + width: 0; + } + + ul { + list-style: none; + margin: 0; + overflow: hidden; + padding: $plyr-control-padding; + } + + // Options + .plyr__control { + align-items: center; + color: $plyr-menu-color; + display: flex; + padding: ceil($plyr-control-padding / 2) ($plyr-control-padding * 2); + user-select: none; + width: 100%; + + &::after { + border: 4px solid transparent; + content: ''; + position: absolute; + top: 50%; + transform: translateY(-50%); + transition: border-color 0.2s ease; + } + + &--forward { + padding-right: ceil($plyr-control-padding * 4); + + &::after { + border-left-color: rgba($plyr-menu-color, 0.8); + right: 5px; + } + + &.plyr__tab-focus::after, + &:hover::after { + border-left-color: currentColor; + } + } + + &--back { + $horizontal-padding: ($plyr-control-padding * 2); + font-weight: $plyr-font-weight-regular; + margin: $plyr-control-padding; + margin-bottom: floor($plyr-control-padding / 2); + padding-left: ceil($plyr-control-padding * 4); + position: relative; + + width: calc(100% - #{$horizontal-padding}); + + &::after { + border-right-color: rgba($plyr-menu-color, 0.8); + left: $plyr-control-padding; + } + + &::before { + background: $plyr-menu-border-color; + box-shadow: 0 1px 0 $plyr-menu-border-shadow-color; + content: ''; + height: 1px; + left: 0; + margin-top: ceil($plyr-control-padding / 2); + overflow: hidden; + position: absolute; + right: 0; + top: 100%; + } + + &.plyr__tab-focus::after, + &:hover::after { + border-right-color: currentColor; + } + } + } + + label.plyr__control { + padding-left: $plyr-control-padding; + + input[type='radio'] + span { + background: rgba(#000, 0.1); + border-radius: 100%; + display: block; + flex-shrink: 0; + height: 16px; + margin-right: $plyr-control-spacing; + position: relative; + transition: all 0.3s ease; + width: 16px; + + &::after { + background: #fff; + border-radius: 100%; + content: ''; + height: 6px; + left: 5px; + opacity: 0; + position: absolute; + top: 5px; + transform: scale(0); + transition: transform 0.3s ease, opacity 0.3s ease; + width: 6px; + } + } + + input[type='radio']:checked + span { + background: $plyr-color-main; + + &::after { + opacity: 1; + transform: scale(1); + } + } + + input[type='radio']:focus + span { + @include plyr-tab-focus(); + } + + &.plyr__tab-focus input[type='radio'] + span, + &:hover input[type='radio'] + span { + background: rgba(#000, 0.1); + } + } + + // Option value + .plyr__menu__value { + align-items: center; + display: flex; + margin-left: auto; + margin-right: -$plyr-control-padding; + overflow: hidden; + padding-left: ceil($plyr-control-padding * 3.5); + pointer-events: none; + } + } +} diff --git a/src/sass/components/progress.scss b/src/sass/components/progress.scss new file mode 100644 index 00000000..7490ee17 --- /dev/null +++ b/src/sass/components/progress.scss @@ -0,0 +1,94 @@ +// -------------------------------------------------------------- +// Playback progress +// -------------------------------------------------------------- + +.plyr__progress { + display: flex; + flex: 1; + position: relative; + + input[type='range'] { + position: relative; + z-index: 2; + } + + // Seek tooltip to show time + .plyr__tooltip { + font-size: $plyr-font-size-time; + left: 0; + } +} + +.plyr__progress--buffer { + -webkit-appearance: none; /* stylelint-disable-line */ + background: transparent; + border: 0; + border-radius: 100px; + height: $plyr-range-track-height; + left: 0; + margin: -($plyr-range-track-height / 2) 0 0; + padding: 0; + position: absolute; + top: 50%; + width: 100%; + + &::-webkit-progress-bar { + background: transparent; + transition: width 0.2s ease; + } + + &::-webkit-progress-value { + background: currentColor; + border-radius: 100px; + min-width: $plyr-range-track-height; + } + + // Mozilla + &::-moz-progress-bar { + background: currentColor; + border-radius: 100px; + min-width: $plyr-range-track-height; + transition: width 0.2s ease; + } + + // Microsoft + &::-ms-fill { + border-radius: 100px; + transition: width 0.2s ease; + } +} + +.plyr--video .plyr__progress--buffer { + box-shadow: 0 1px 1px rgba(#000, 0.15); + color: $plyr-video-progress-buffered-bg; +} + +.plyr--audio .plyr__progress--buffer { + color: $plyr-audio-progress-buffered-bg; +} + +// Loading state +.plyr--loading .plyr__progress--buffer { + animation: plyr-progress 1s linear infinite; + background-image: linear-gradient( + -45deg, + $plyr-progress-loading-bg 25%, + transparent 25%, + transparent 50%, + $plyr-progress-loading-bg 50%, + $plyr-progress-loading-bg 75%, + transparent 75%, + transparent + ); + background-repeat: repeat-x; + background-size: $plyr-progress-loading-size $plyr-progress-loading-size; + color: transparent; +} + +.plyr--video.plyr--loading .plyr__progress--buffer { + background-color: $plyr-video-progress-buffered-bg; +} + +.plyr--audio.plyr--loading .plyr__progress--buffer { + background-color: $plyr-audio-progress-buffered-bg; +} diff --git a/src/sass/components/sliders.scss b/src/sass/components/sliders.scss new file mode 100644 index 00000000..7ede4415 --- /dev/null +++ b/src/sass/components/sliders.scss @@ -0,0 +1,139 @@ +// -------------------------------------------------------------- +// Slider inputs - <input type="range"> +// -------------------------------------------------------------- + +.plyr--full-ui input[type='range'] { + // WebKit + -webkit-appearance: none; /* stylelint-disable-line */ + background: transparent; + border: 0; + border-radius: ($plyr-range-thumb-height * 2); + // color is used in JS to populate lower fill for WebKit + color: $plyr-range-fill-bg; + cursor: pointer; + display: block; + height: $plyr-range-max-height; + margin: 0; + padding: 0; + transition: box-shadow 0.3s ease; + width: 100%; + + &::-webkit-slider-runnable-track { + @include plyr-range-track(); + } + + &::-webkit-slider-thumb { + @include plyr-range-thumb(); + -webkit-appearance: none; /* stylelint-disable-line */ + margin-top: -(($plyr-range-thumb-height - $plyr-range-track-height) / 2); + } + + // Mozilla + &::-moz-range-track { + @include plyr-range-track(); + } + + &::-moz-range-thumb { + @include plyr-range-thumb(); + } + + &::-moz-range-progress { + background: currentColor; + border-radius: ($plyr-range-track-height / 2); + height: $plyr-range-track-height; + } + + // Microsoft + &::-ms-track { + @include plyr-range-track(); + color: transparent; + } + + &::-ms-fill-upper { + @include plyr-range-track(); + } + + &::-ms-fill-lower { + @include plyr-range-track(); + + background: currentColor; + } + + &::-ms-thumb { + @include plyr-range-thumb(); + // For some reason, Edge uses the -webkit margin above + margin-top: 0; + } + + &::-ms-tooltip { + display: none; + } + + // Focus styles + &:focus { + outline: 0; + } + + &::-moz-focus-outer { + border: 0; + } + + &.plyr__tab-focus { + &::-webkit-slider-runnable-track { + @include plyr-tab-focus(); + } + + &::-moz-range-track { + @include plyr-tab-focus(); + } + + &::-ms-track { + @include plyr-tab-focus(); + } + } + + // Pressed styles + &:active { + &::-webkit-slider-thumb { + @include plyr-range-thumb-active(); + } + + &::-moz-range-thumb { + @include plyr-range-thumb-active(); + } + + &::-ms-thumb { + @include plyr-range-thumb-active(); + } + } +} + +// Video range inputs +.plyr--full-ui.plyr--video input[type='range'] { + &::-webkit-slider-runnable-track { + background: $plyr-video-range-track-bg; + } + + &::-moz-range-track { + background: $plyr-video-range-track-bg; + } + + &::-ms-track { + background: $plyr-video-range-track-bg; + } +} + +// Audio range inputs +.plyr--full-ui.plyr--audio input[type='range'] { + &::-webkit-slider-runnable-track { + background: $plyr-audio-range-track-bg; + } + + &::-moz-range-track { + background: $plyr-audio-range-track-bg; + } + + &::-ms-track { + background: $plyr-audio-range-track-bg; + } +} diff --git a/src/sass/components/times.scss b/src/sass/components/times.scss new file mode 100644 index 00000000..240d3528 --- /dev/null +++ b/src/sass/components/times.scss @@ -0,0 +1,24 @@ +// -------------------------------------------------------------- +// Time +// -------------------------------------------------------------- + +.plyr__time { + font-size: $plyr-font-size-time; +} + +// Media duration hidden on small screens +.plyr__time + .plyr__time { + // Add a slash in before + &::before { + content: '\2044'; + margin-right: $plyr-control-spacing; + } + + @media (max-width: $plyr-bp-sm-max) { + display: none; + } +} + +.plyr--video .plyr__time { + text-shadow: 0 1px 1px rgba(#000, 0.15); +} diff --git a/src/sass/components/tooltips.scss b/src/sass/components/tooltips.scss new file mode 100644 index 00000000..19a9ce56 --- /dev/null +++ b/src/sass/components/tooltips.scss @@ -0,0 +1,85 @@ +// -------------------------------------------------------------- +// Tooltips +// -------------------------------------------------------------- + +.plyr__tooltip { + background: $plyr-tooltip-bg; + border-radius: $plyr-tooltip-radius; + bottom: 100%; + box-shadow: $plyr-tooltip-shadow; + color: $plyr-tooltip-color; + font-size: $plyr-font-size-small; + font-weight: $plyr-font-weight-regular; + line-height: 1.3; + margin-bottom: ($plyr-tooltip-padding * 2); + opacity: 0; + padding: $plyr-tooltip-padding ($plyr-tooltip-padding * 1.5); + pointer-events: none; + position: absolute; + transform: translate(-50%, 10px) scale(0.8); + transform-origin: 50% 100%; + transition: transform 0.2s 0.1s ease, opacity 0.2s 0.1s ease; + z-index: 2; + + // The background triangle + &::before { + border-left: $plyr-tooltip-arrow-size solid transparent; + border-right: $plyr-tooltip-arrow-size solid transparent; + border-top: $plyr-tooltip-arrow-size solid $plyr-tooltip-bg; + bottom: -$plyr-tooltip-arrow-size; + content: ''; + height: 0; + left: 50%; + position: absolute; + transform: translateX(-50%); + width: 0; + z-index: 2; + } +} + +// Displaying +.plyr .plyr__control:hover .plyr__tooltip, +.plyr .plyr__control.plyr__tab-focus .plyr__tooltip, +.plyr__tooltip--visible { + opacity: 1; + transform: translate(-50%, 0) scale(1); +} + +.plyr .plyr__control:hover .plyr__tooltip { + z-index: 3; +} + +// First tooltip +.plyr__controls > .plyr__control:first-child .plyr__tooltip, +.plyr__controls > .plyr__control:first-child + .plyr__control .plyr__tooltip { + left: 0; + transform: translate(0, 10px) scale(0.8); + transform-origin: 0 100%; + + &::before { + left: ($plyr-control-icon-size / 2) + $plyr-control-padding; + } +} + +// Last tooltip +.plyr__controls > .plyr__control:last-child .plyr__tooltip { + right: 0; + transform: translate(0, 10px) scale(0.8); + transform-origin: 100% 100%; + + &::before { + left: auto; + right: ($plyr-control-icon-size / 2) + $plyr-control-padding; + transform: translateX(50%); + } +} + +.plyr__controls > .plyr__control:first-child, +.plyr__controls > .plyr__control:first-child + .plyr__control, +.plyr__controls > .plyr__control:last-child { + &:hover .plyr__tooltip, + &.plyr__tab-focus .plyr__tooltip, + .plyr__tooltip--visible { + transform: translate(0, 0) scale(1); + } +} diff --git a/src/sass/components/video.scss b/src/sass/components/video.scss new file mode 100644 index 00000000..3caf866d --- /dev/null +++ b/src/sass/components/video.scss @@ -0,0 +1,21 @@ +// -------------------------------------------------------------- +// Video styles +// -------------------------------------------------------------- + +.plyr--video { + overflow: hidden; + + // Menu open + &.plyr--menu-open { + overflow: visible; + } +} + +.plyr__video-wrapper { + background: #000; + border-radius: inherit; + overflow: hidden; + position: relative; + // Require z-index to force border-radius + z-index: 0; +} diff --git a/src/sass/components/volume.scss b/src/sass/components/volume.scss new file mode 100644 index 00000000..e12dc675 --- /dev/null +++ b/src/sass/components/volume.scss @@ -0,0 +1,29 @@ +// -------------------------------------------------------------- +// Volume +// -------------------------------------------------------------- + +.plyr__volume { + flex: 1; + position: relative; + + input[type='range'] { + position: relative; + z-index: 2; + } + + @media (min-width: $plyr-bp-sm) { + max-width: 50px; + } + + @media (min-width: $plyr-bp-md) { + max-width: 80px; + } +} + +// Hide sound controls on iOS +// It's not supported to change volume using JavaScript: +// https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html +.plyr--is-ios .plyr__volume, +.plyr--is-ios [data-plyr='mute'] { + display: none !important; +} diff --git a/src/sass/lib/animation.scss b/src/sass/lib/animation.scss new file mode 100644 index 00000000..b6c22d42 --- /dev/null +++ b/src/sass/lib/animation.scss @@ -0,0 +1,31 @@ +// -------------------------------------------------------------- +// Animations +// -------------------------------------------------------------- + +@keyframes plyr-progress { + to { + background-position: $plyr-progress-loading-size 0; + } +} + +@keyframes plyr-popup { + 0% { + opacity: 0.5; + transform: translateY(10px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes plyr-fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} diff --git a/src/sass/lib/functions.scss b/src/sass/lib/functions.scss new file mode 100644 index 00000000..a99a1b80 --- /dev/null +++ b/src/sass/lib/functions.scss @@ -0,0 +1,7 @@ +// ========================================================================== +// Useful functions +// ========================================================================== + +@function to-percentage($input) { + @return $input * 1%; +} diff --git a/src/sass/lib/mixins.scss b/src/sass/lib/mixins.scss new file mode 100644 index 00000000..2abe6b8f --- /dev/null +++ b/src/sass/lib/mixins.scss @@ -0,0 +1,96 @@ +// ========================================================================== +// Mixins +// ========================================================================== + +// Nicer focus styles +// --------------------------------------- +@mixin plyr-tab-focus($color: $plyr-tab-focus-default-color) { + box-shadow: 0 0 0 3px rgba($color, 0.35); + outline: 0; +} + +// Font smoothing +// --------------------------------------- +@mixin plyr-font-smoothing($mode: true) { + @if $mode { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + } @else { + -moz-osx-font-smoothing: auto; + -webkit-font-smoothing: subpixel-antialiased; + } +} + +// <input type="range"> styling +// --------------------------------------- +@mixin plyr-range-track() { + background: transparent; + border: 0; + border-radius: ($plyr-range-track-height / 2); + height: $plyr-range-track-height; + transition: all 0.3s ease; + user-select: none; +} + +@mixin plyr-range-thumb() { + background: $plyr-range-thumb-bg; + border: 0; + border-radius: 100%; + box-shadow: $plyr-range-thumb-shadow; + box-sizing: border-box; + height: $plyr-range-thumb-height; + position: relative; + transition: all 0.2s ease; + width: $plyr-range-thumb-height; +} + +@mixin plyr-range-thumb-active() { + box-shadow: 0 0 0 $plyr-range-thumb-active-shadow-width transparentize($plyr-range-thumb-bg, 0.5); +} + +// Fullscreen styles +// --------------------------------------- +@mixin plyr-fullscreen-active() { + background: #000; + border-radius: 0 !important; + height: 100%; + margin: 0; + width: 100%; + + video { + height: 100%; + } + + .plyr__video-wrapper { + height: 100%; + width: 100%; + } + + .plyr__video-embed { + // Revert overflow change + overflow: visible; + } + + // Vimeo requires some different styling + &.plyr--vimeo .plyr__video-wrapper { + height: 0; + top: 50%; + transform: translateY(-50%); + } + + // Display correct icon + .plyr__control .icon--exit-fullscreen { + display: block; + + + svg { + display: none; + } + } + + // Large captions in full screen on larger screens + @media (min-width: $plyr-bp-lg) { + .plyr__captions { + font-size: $plyr-font-size-captions-large; + } + } +} diff --git a/src/sass/plyr.scss b/src/sass/plyr.scss new file mode 100644 index 00000000..362c89b7 --- /dev/null +++ b/src/sass/plyr.scss @@ -0,0 +1,44 @@ +// ========================================================================== +// Plyr styles +// https://github.com/sampotts/plyr +// TODO: Review use of BEM classnames +// ========================================================================== +@charset 'UTF-8'; + +@import 'settings/breakpoints'; +@import 'settings/colors'; +@import 'settings/cosmetics'; +@import 'settings/type'; + +@import 'settings/captions'; +@import 'settings/controls'; +@import 'settings/helpers'; +@import 'settings/menus'; +@import 'settings/progress'; +@import 'settings/sliders'; +@import 'settings/tooltips'; + +@import 'lib/animation'; +@import 'lib/functions'; +@import 'lib/mixins'; + +@import 'base'; + +@import 'components/badges'; +@import 'components/captions'; +@import 'components/control'; +@import 'components/controls'; +@import 'components/embed'; +@import 'components/menus'; +@import 'components/progress'; +@import 'components/sliders'; +@import 'components/times'; +@import 'components/tooltips'; +@import 'components/video'; +@import 'components/volume'; + +@import 'states/error'; +@import 'states/fullscreen'; + +@import 'utils/animation'; +@import 'utils/hidden'; diff --git a/src/sass/settings/breakpoints.scss b/src/sass/settings/breakpoints.scss new file mode 100644 index 00000000..77a5b93a --- /dev/null +++ b/src/sass/settings/breakpoints.scss @@ -0,0 +1,12 @@ +// ========================================================================== +// Breakpoints +// ========================================================================== + +$plyr-bp-sm: 480px !default; +$plyr-bp-md: 768px !default; +$plyr-bp-lg: 1024px !default; + +// Max-width media queries +$plyr-bp-xs-max: ($plyr-bp-sm - 1); +$plyr-bp-sm-max: ($plyr-bp-md - 1); +$plyr-bp-md-max: ($plyr-bp-lg - 1); diff --git a/src/sass/settings/captions.scss b/src/sass/settings/captions.scss new file mode 100644 index 00000000..0c259046 --- /dev/null +++ b/src/sass/settings/captions.scss @@ -0,0 +1,10 @@ +// ========================================================================== +// Captions +// ========================================================================== + +$plyr-captions-bg: rgba(#000, 0.8) !default; +$plyr-captions-color: #fff !default; +$plyr-font-size-captions-base: $plyr-font-size-base !default; +$plyr-font-size-captions-small: $plyr-font-size-small !default; +$plyr-font-size-captions-medium: $plyr-font-size-large !default; +$plyr-font-size-captions-large: $plyr-font-size-xlarge !default; diff --git a/src/sass/settings/colors.scss b/src/sass/settings/colors.scss new file mode 100644 index 00000000..c9ea580c --- /dev/null +++ b/src/sass/settings/colors.scss @@ -0,0 +1,9 @@ +// ========================================================================== +// Colors +// ========================================================================== + +$plyr-color-main: #1aafff !default; +$plyr-color-gunmetal: #2f343d !default; +$plyr-color-fiord: #4f5b5f !default; +$plyr-color-lynch: #6b7d85 !default; +$plyr-color-heather: #b7c5cd !default; diff --git a/src/sass/settings/controls.scss b/src/sass/settings/controls.scss new file mode 100644 index 00000000..64f05cec --- /dev/null +++ b/src/sass/settings/controls.scss @@ -0,0 +1,19 @@ +// ========================================================================== +// Controls +// ========================================================================== + +$plyr-control-icon-size: 18px !default; +$plyr-control-icon-size-large: 20px !default; +$plyr-control-spacing: 10px !default; +$plyr-control-padding: ($plyr-control-spacing * 0.7) !default; +$plyr-control-radius: 3px !default; + +$plyr-video-controls-bg: #000 !default; +$plyr-video-control-color: #fff !default; +$plyr-video-control-color-hover: #fff !default; +$plyr-video-control-bg-hover: $plyr-color-main !default; + +$plyr-audio-controls-bg: #fff !default; +$plyr-audio-control-color: $plyr-color-fiord !default; +$plyr-audio-control-color-hover: #fff !default; +$plyr-audio-control-bg-hover: $plyr-color-main !default; diff --git a/src/sass/settings/cosmetics.scss b/src/sass/settings/cosmetics.scss new file mode 100644 index 00000000..d6e4b86d --- /dev/null +++ b/src/sass/settings/cosmetics.scss @@ -0,0 +1,5 @@ +// ========================================================================== +// Cosmetic +// ========================================================================== + +$plyr-tab-focus-default-color: $plyr-color-main !default; diff --git a/src/sass/settings/helpers.scss b/src/sass/settings/helpers.scss new file mode 100644 index 00000000..fd70f523 --- /dev/null +++ b/src/sass/settings/helpers.scss @@ -0,0 +1,7 @@ +// ========================================================================== +// Enable helpers +// ========================================================================== + +$plyr-border-box: true !default; +$plyr-touch-action: true !default; +$plyr-sr-only-important: true !default; diff --git a/src/sass/settings/menus.scss b/src/sass/settings/menus.scss new file mode 100644 index 00000000..64df9863 --- /dev/null +++ b/src/sass/settings/menus.scss @@ -0,0 +1,10 @@ +// ========================================================================== +// Menus +// ========================================================================== + +$plyr-menu-bg: rgba(#fff, 0.9) !default; +$plyr-menu-color: $plyr-color-fiord !default; +$plyr-menu-arrow-size: 6px !default; +$plyr-menu-border-color: $plyr-color-heather !default; +$plyr-menu-border-shadow-color: #fff !default; +$plyr-menu-shadow: 0 1px 2px rgba(#000, 0.15) !default; diff --git a/src/sass/settings/progress.scss b/src/sass/settings/progress.scss new file mode 100644 index 00000000..074ee3c6 --- /dev/null +++ b/src/sass/settings/progress.scss @@ -0,0 +1,11 @@ +// ========================================================================== +// Progress +// ========================================================================== + +// Loading +$plyr-progress-loading-size: 25px !default; +$plyr-progress-loading-bg: rgba($plyr-color-gunmetal, 0.6) !default; + +// Buffered +$plyr-video-progress-buffered-bg: rgba(#fff, 0.25) !default; +$plyr-audio-progress-buffered-bg: rgba($plyr-color-heather, 0.66) !default; diff --git a/src/sass/settings/sliders.scss b/src/sass/settings/sliders.scss new file mode 100644 index 00000000..25d64c05 --- /dev/null +++ b/src/sass/settings/sliders.scss @@ -0,0 +1,23 @@ +// ========================================================================== +// Sliders +// ========================================================================== + +// Active state +$plyr-range-thumb-active-shadow-width: 3px !default; + +// Thumb +$plyr-range-thumb-height: 14px !default; +$plyr-range-thumb-bg: #fff !default; +$plyr-range-thumb-border: 2px solid transparent !default; +$plyr-range-thumb-shadow: 0 1px 1px rgba($plyr-video-controls-bg, 0.15), 0 0 0 1px rgba($plyr-color-gunmetal, 0.2) !default; + +// Track +$plyr-range-track-height: 6px !default; +$plyr-range-max-height: ($plyr-range-thumb-active-shadow-width * 2) + $plyr-range-thumb-height !default; + +// Fill +$plyr-range-fill-bg: $plyr-color-main !default; + +// Type specific +$plyr-video-range-track-bg: $plyr-video-progress-buffered-bg !default; +$plyr-audio-range-track-bg: $plyr-audio-progress-buffered-bg !default; diff --git a/src/sass/settings/tooltips.scss b/src/sass/settings/tooltips.scss new file mode 100644 index 00000000..fd304d60 --- /dev/null +++ b/src/sass/settings/tooltips.scss @@ -0,0 +1,10 @@ +// ========================================================================== +// Tooltips +// ========================================================================== + +$plyr-tooltip-bg: rgba(#fff, 0.9) !default; +$plyr-tooltip-color: $plyr-color-fiord !default; +$plyr-tooltip-padding: ($plyr-control-spacing / 2) !default; +$plyr-tooltip-arrow-size: 4px !default; +$plyr-tooltip-radius: 3px !default; +$plyr-tooltip-shadow: 0 1px 2px rgba(#000, 0.15) !default; diff --git a/src/sass/settings/type.scss b/src/sass/settings/type.scss new file mode 100644 index 00000000..7c587446 --- /dev/null +++ b/src/sass/settings/type.scss @@ -0,0 +1,19 @@ +// ========================================================================== +// Typography +// ========================================================================== + +$plyr-font-family: Avenir, 'Avenir Next', 'Helvetica Neue', 'Segoe UI', Helvetica, Arial, sans-serif !default; +$plyr-font-size-base: 16px !default; +$plyr-font-size-small: 14px !default; +$plyr-font-size-large: 18px !default; +$plyr-font-size-xlarge: 21px !default; + +$plyr-font-size-time: 14px !default; +$plyr-font-size-badge: 9px !default; + +$plyr-font-weight-regular: 500 !default; +$plyr-font-weight-bold: 600 !default; + +$plyr-line-height: 1.7 !default; + +$plyr-font-smoothing: true !default; diff --git a/src/sass/states/error.scss b/src/sass/states/error.scss new file mode 100644 index 00000000..64d05c7b --- /dev/null +++ b/src/sass/states/error.scss @@ -0,0 +1,25 @@ +// -------------------------------------------------------------- +// Error state +// -------------------------------------------------------------- + +.plyr--has-error { + pointer-events: none; + + &::after { + align-items: center; + background: rgba(#000, 90%); + color: #fff; + content: attr(data-plyr-error); + display: flex; + font-size: $plyr-font-size-base; + height: 100%; + justify-content: center; + left: 0; + position: absolute; + text-align: center; + text-shadow: 0 1px 1px rgba(#000, 10%); + top: 0; + width: 100%; + z-index: 10; + } +} diff --git a/src/sass/states/fullscreen.scss b/src/sass/states/fullscreen.scss new file mode 100644 index 00000000..5632a60f --- /dev/null +++ b/src/sass/states/fullscreen.scss @@ -0,0 +1,34 @@ +// -------------------------------------------------------------- +// Fullscreen +// -------------------------------------------------------------- + +.plyr:fullscreen { + @include plyr-fullscreen-active(); +} + +/* stylelint-disable-next-line */ +.plyr:-webkit-full-screen { + @include plyr-fullscreen-active(); +} + +/* stylelint-disable-next-line */ +.plyr:-moz-full-screen { + @include plyr-fullscreen-active(); +} + +/* stylelint-disable-next-line */ +.plyr:-ms-fullscreen { + @include plyr-fullscreen-active(); +} + +// Fallback for unsupported browsers +.plyr--fullscreen-fallback { + @include plyr-fullscreen-active(); + + bottom: 0; + left: 0; + position: fixed; + right: 0; + top: 0; + z-index: 10000000; +} diff --git a/src/sass/utils/animation.scss b/src/sass/utils/animation.scss new file mode 100644 index 00000000..4a5b6b90 --- /dev/null +++ b/src/sass/utils/animation.scss @@ -0,0 +1,7 @@ +// -------------------------------------------------------------- +// Animation utils +// -------------------------------------------------------------- + +.plyr--no-transition { + transition: none !important; +} diff --git a/src/sass/utils/hidden.scss b/src/sass/utils/hidden.scss new file mode 100644 index 00000000..f3b46147 --- /dev/null +++ b/src/sass/utils/hidden.scss @@ -0,0 +1,33 @@ +// -------------------------------------------------------------- +// Hiding content nicely +// -------------------------------------------------------------- + +// Attributes +.plyr--full-ui [hidden] { + display: none; +} + +.plyr--full-ui [aria-hidden='true'] { + display: none; +} + +// Screen reader only elements +.plyr__sr-only { + clip: rect(1px, 1px, 1px, 1px); + overflow: hidden; + + // !important is not always needed + @if $plyr-sr-only-important { + border: 0 !important; + height: 1px !important; + padding: 0 !important; + position: absolute !important; + width: 1px !important; + } @else { + border: 0; + height: 1px; + padding: 0; + position: absolute; + width: 1px; + } +} diff --git a/src/scss/mixins.scss b/src/scss/mixins.scss deleted file mode 100644 index b4bfca6a..00000000 --- a/src/scss/mixins.scss +++ /dev/null @@ -1,29 +0,0 @@ -// ========================================================================== -// Plyr mixins -// https://github.com/selz/plyr -// ========================================================================== - -// <input type="range"> styling -@mixin plyr-range-track() { - height: $plyr-range-track-height; - background: transparent; - border: 0; - border-radius: ($plyr-range-track-height / 2); - user-select: none; -} -@mixin plyr-range-thumb() { - position: relative; - height: $plyr-range-thumb-height; - width: $plyr-range-thumb-width; - background: $plyr-range-thumb-bg; - border: $plyr-range-thumb-border; - border-radius: 100%; - transition: background .2s ease, border .2s ease, transform .2s ease; - box-shadow: $plyr-range-thumb-shadow; - box-sizing: border-box; -} -@mixin plyr-range-thumb-active() { - background: $plyr-range-thumb-active-bg; - border-color: $plyr-range-thumb-active-border-color; - transform: scale($plyr-range-thumb-active-scale); -}
\ No newline at end of file diff --git a/src/scss/plyr.scss b/src/scss/plyr.scss deleted file mode 100644 index 11488ae4..00000000 --- a/src/scss/plyr.scss +++ /dev/null @@ -1,770 +0,0 @@ -// ========================================================================== -// Plyr styles -// https://github.com/selz/plyr -// ========================================================================== - -@import "variables"; -@import "mixins"; - -// Animation -// --------------------------------------- -@keyframes plyr-progress { - to { - background-position: $plyr-progress-loading-size 0; - } -} - -// Styles -// ------------------------------- -// Base -.plyr { - position: relative; - max-width: 100%; - min-width: 200px; - font-family: $plyr-font-family; - direction: ltr; - - @if $plyr-border-box == true { - // border-box everything - // http://paulirish.com/2012/box-sizing-border-box-ftw/ - &, - *, - *::after, - *::before { - box-sizing: border-box; - } - } - - @if $plyr-touch-action == true { - // Fix 300ms delay - a, - button, - input, - label { - touch-action: manipulation; - } - } - - // Focus - &:focus { - outline: 0; - } - - // Media elements - video, - audio { - width: 100%; - height: auto; - vertical-align: middle; - border-radius: inherit; - } - - // Range inputs - // Specificity is for bootstrap compatibility - input[type="range"] { - display: block; - height: ($plyr-range-thumb-height * $plyr-range-thumb-active-scale); - width: 100%; - margin: 0; - padding: 0; - vertical-align: middle; - - appearance: none; - cursor: pointer; - border: none; - background: transparent; - - // WebKit - &::-webkit-slider-runnable-track { - @include plyr-range-track(); - } - &::-webkit-slider-thumb { - -webkit-appearance: none; - margin-top: -(($plyr-range-thumb-height - $plyr-range-track-height) / 2); - @include plyr-range-thumb(); - } - - // Mozilla - &::-moz-range-track { - @include plyr-range-track(); - } - &::-moz-range-thumb { - @include plyr-range-thumb(); - } - - // Microsoft - &::-ms-track { - height: $plyr-range-track-height; - background: transparent; - border: 0; - color: transparent; - } - &::-ms-fill-upper { - @include plyr-range-track(); - } - &::-ms-fill-lower { - @include plyr-range-track(); - background: $plyr-range-selected-bg; - } - &::-ms-thumb { - @include plyr-range-thumb(); - // For some reason, Edge uses the -webkit margin above - margin-top: 0; - } - &::-ms-tooltip { - display: none; - } - - // Focus styles - &:focus { - outline: 0; - } - &::-moz-focus-outer { - border: 0; - } - &.tab-focus:focus { - outline-offset: 3px; - } - - // Pressed styles - &:active { - &::-webkit-slider-thumb { - @include plyr-range-thumb-active(); - } - &::-moz-range-thumb { - @include plyr-range-thumb-active(); - } - &::-ms-thumb { - @include plyr-range-thumb-active(); - } - } - } -} - -// Video range inputs -.plyr--video input[type="range"].tab-focus:focus { - outline: 1px dotted transparentize($plyr-video-control-color, 0.5); -} - -// Audio range inputs -.plyr--audio input[type="range"].tab-focus:focus { - outline: 1px dotted transparentize($plyr-audio-control-color, 0.5); -} - -// Screen reader only elements -.plyr__sr-only { - clip: rect(1px, 1px, 1px, 1px); - overflow: hidden; - - // !important is not always needed - @if $plyr-sr-only-important == true { - position: absolute !important; - padding: 0 !important; - border: 0 !important; - height: 1px !important; - width: 1px !important; - } @else { - position: absolute; - padding: 0; - border: 0; - height: 1px; - width: 1px; - } -} - -// Video -.plyr__video-wrapper { - position: relative; - background: #000; - border-radius: inherit; -} - -// Container for embeds -.plyr__video-embed { - padding-bottom: 56.25%; /* 16:9 */ - height: 0; - border-radius: inherit; - - // Require overflow and z-index to force border-radius - overflow: hidden; - z-index: 0; - - iframe { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - border: 0; - user-select: none; - } - - // Vimeo hack - > div { - position: relative; - padding-bottom: 200%; - transform: translateY(-35.95%); - } -} -// To allow mouse events to be captured if full support -.plyr .plyr__video-embed iframe { - pointer-events: none; -} - -// Captions -// -------------------------------------------------------------- -// Hide default captions -.plyr video::-webkit-media-text-track-container { - display: none; -} -.plyr__captions { - display: none; - position: absolute; - bottom: 0; - left: 0; - width: 100%; - padding: ($plyr-control-spacing * 2); - transform: translateY(-($plyr-control-spacing * 6)); - transition: transform 0.3s ease; - color: $plyr-captions-color; - font-size: $plyr-font-size-captions-base; - text-align: center; - font-weight: 400; - - span { - border-radius: 2px; - padding: floor($plyr-control-spacing / 3) $plyr-control-spacing; - background: $plyr-captions-bg; - box-decoration-break: clone; - line-height: 150%; - } - span:empty { - display: none; - } - - @media (min-width: $plyr-bp-screen-md) { - font-size: $plyr-font-size-captions-medium; - } -} -.plyr--captions-active .plyr__captions { - display: block; -} -.plyr--hide-controls .plyr__captions { - transform: translateY(-($plyr-control-spacing * 2)); -} -// Large captions in full screen on larger screens -@media (min-width: $plyr-bp-screen-lg) { - .plyr--fullscreen-active .plyr__captions { - font-size: $plyr-font-size-captions-large; - } -} - -// Controls -// -------------------------------------------------------------- -// Hide native controls -.plyr ::-webkit-media-controls { - display: none; -} - -// Playback controls -.plyr__controls { - display: flex; - align-items: center; - line-height: 1; - text-align: center; - pointer-events: none; - - & > * { - pointer-events: all; - } - - // Spacing - > button, - .plyr__progress, - .plyr__time { - margin-left: ($plyr-control-spacing / 2); - - &:first-child { - margin-left: 0; - } - } - .plyr__volume { - margin-left: ($plyr-control-spacing / 2); - } - [data-plyr="pause"] { - margin-left: 0; - } - - // Buttons - button { - position: relative; - display: inline-block; - flex-shrink: 0; - overflow: visible; // IE11 - vertical-align: middle; - padding: ($plyr-control-spacing * 0.7); - border: 0; - background: transparent; - border-radius: 3px; - cursor: pointer; - transition: background 0.3s ease, color 0.3s ease, opacity 0.3s ease; - color: inherit; - - svg { - width: $plyr-control-icon-size; - height: $plyr-control-icon-size; - display: block; - fill: currentColor; - } - - // Default focus - &:focus { - outline: 0; - } - } - - // Hide toggle icons by default - .icon--exit-fullscreen, - .icon--muted, - .icon--captions-on { - display: none; - } - - @media (min-width: $plyr-bp-screen-sm) { - > button, - .plyr__progress, - .plyr__time { - margin-left: $plyr-control-spacing; - } - } -} -// Hide controls -.plyr--hide-controls .plyr__controls { - opacity: 0; - pointer-events: none; -} - -// Video controls -.plyr--video .plyr__controls { - position: absolute; - left: 0; - right: 0; - bottom: 0; - padding: ($plyr-control-spacing * 5) $plyr-control-spacing $plyr-control-spacing; - background: linear-gradient( - transparentize($plyr-video-controls-bg, 1), - transparentize($plyr-video-controls-bg, 0.5) - ); - border-bottom-left-radius: inherit; - border-bottom-right-radius: inherit; - color: $plyr-video-control-color; - transition: opacity 0.3s ease; - - button { - // Hover and tab focus - &.tab-focus:focus, - &:hover { - background: $plyr-video-control-bg-hover; - color: $plyr-video-control-color-hover; - } - } -} - -// Audio controls -.plyr--audio .plyr__controls { - padding: $plyr-control-spacing; - border-radius: inherit; - background: $plyr-audio-controls-bg; - border: $plyr-audio-controls-border; - color: $plyr-audio-control-color; - - button { - // Hover and tab focus - &.tab-focus:focus, - &:hover { - background: $plyr-audio-control-bg-hover; - color: $plyr-audio-control-color-hover; - } - } -} - -// Large play button (video only) -.plyr__play-large { - display: none; - position: absolute; - z-index: 1; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - padding: $plyr-control-spacing; - background: $plyr-video-control-bg-hover; - border: 4px solid currentColor; - border-radius: 100%; - box-shadow: 0 1px 1px transparentize(#000, 0.85); - color: $plyr-video-control-color; - transition: all 0.3s ease; - - svg { - position: relative; - left: 2px; - width: 20px; - height: 20px; - display: block; - fill: currentColor; - } - - &:focus { - outline: 1px dotted transparentize($plyr-video-control-color, 0.5); - } -} -.plyr .plyr__play-large { - display: inline-block; -} -.plyr--audio .plyr__play-large { - display: none; -} -.plyr--playing .plyr__play-large { - opacity: 0; - visibility: hidden; -} - -// States -.plyr__controls [data-plyr="pause"], -.plyr--playing .plyr__controls [data-plyr="play"] { - display: none; -} -.plyr--playing .plyr__controls [data-plyr="pause"] { - display: inline-block; -} - -// Change icons on state change -.plyr--fullscreen-active .icon--exit-fullscreen, -.plyr--muted .plyr__controls .icon--muted, -.plyr--captions-active .plyr__controls .icon--captions-on { - display: block; - - & + svg { - display: none; - } -} - -// Some options are hidden by default -.plyr [data-plyr="captions"], -.plyr [data-plyr="fullscreen"] { - display: none; -} -.plyr--captions-enabled [data-plyr="captions"], -.plyr--fullscreen-enabled [data-plyr="fullscreen"] { - display: inline-block; -} - -// Tooltips -// -------------------------------------------------------------- -.plyr__tooltip { - position: absolute; - z-index: 2; - bottom: 100%; - margin-bottom: ($plyr-tooltip-padding * 2); - padding: $plyr-tooltip-padding ($plyr-tooltip-padding * 1.5); - pointer-events: none; - - opacity: 0; - background: $plyr-tooltip-bg; - border-radius: $plyr-tooltip-radius; - - color: $plyr-tooltip-color; - font-size: $plyr-font-size-small; - line-height: 1.3; - - transform: translate(-50%, 10px) scale(0.8); - transform-origin: 50% 100%; - transition: transform 0.2s 0.1s ease, opacity 0.2s 0.1s ease; - - &::before { - // Arrows - content: ""; - position: absolute; - width: 0; - height: 0; - left: 50%; - transform: translateX(-50%); - - // The background triangle - bottom: -$plyr-tooltip-arrow-size; - border-right: $plyr-tooltip-arrow-size solid transparent; - border-top: $plyr-tooltip-arrow-size solid $plyr-tooltip-bg; - border-left: $plyr-tooltip-arrow-size solid transparent; - z-index: 2; - } -} -.plyr button:hover .plyr__tooltip, -.plyr button.tab-focus:focus .plyr__tooltip, -.plyr__tooltip--visible { - opacity: 1; - transform: translate(-50%, 0) scale(1); -} -.plyr button:hover .plyr__tooltip { - z-index: 3; -} - -// First tooltip -.plyr__controls button:first-child .plyr__tooltip { - left: 0; - transform: translate(0, 10px) scale(0.8); - transform-origin: 0 100%; - - &::before { - left: ($plyr-control-icon-size / 2) + $plyr-control-padding; - } -} - -// Last tooltip -.plyr__controls button:last-child .plyr__tooltip { - right: 0; - transform: translate(0, 10px) scale(0.8); - transform-origin: 100% 100%; - - &::before { - left: auto; - right: ($plyr-control-icon-size / 2) + $plyr-control-padding; - transform: translateX(50%); - } -} - -.plyr__controls button:first-child, -.plyr__controls button:last-child { - &:hover .plyr__tooltip, - &.tab-focus:focus .plyr__tooltip, - .plyr__tooltip--visible { - transform: translate(0, 0) scale(1); - } -} - -// Playback progress -// -------------------------------------------------------------- -// <progress> element -.plyr__progress { - display: none; - position: relative; - flex: 1; - - input[type="range"] { - position: relative; - z-index: 2; - - &::-webkit-slider-runnable-track { - background: transparent; - } - &::-moz-range-track { - background: transparent; - } - &::-ms-fill-upper { - background: transparent; - } - } - - // Seek tooltip to show time - .plyr__tooltip { - left: 0; - } -} -.plyr .plyr__progress { - display: inline-block; -} - -.plyr__progress--buffer, -.plyr__progress--played, -.plyr__volume--display { - position: absolute; - left: 0; - top: 50%; - width: 100%; - height: $plyr-range-track-height; - margin: -($plyr-range-track-height / 2) 0 0; - padding: 0; - vertical-align: top; - appearance: none; - border: none; - border-radius: 100px; - - &::-webkit-progress-bar { - background: transparent; - } - &::-webkit-progress-value { - background: currentColor; - border-radius: 100px; - min-width: $plyr-range-track-height; - } - &::-moz-progress-bar { - background: currentColor; - border-radius: 100px; - min-width: $plyr-range-track-height; - } - &::-ms-fill { - border-radius: 100px; - } -} -.plyr__progress--played, -.plyr__volume--display { - z-index: 1; - color: $plyr-range-selected-bg; - background: transparent; - transition: none; - - &::-webkit-progress-value { - min-width: $plyr-range-track-height; - max-width: 99%; - border-top-right-radius: 0; - border-bottom-right-radius: 0; - transition: none; - } - &::-moz-progress-bar { - min-width: $plyr-range-track-height; - max-width: 99%; - border-top-right-radius: 0; - border-bottom-right-radius: 0; - transition: none; - } - &::-ms-fill { - display: none; - } -} -.plyr__progress--buffer { - &::-webkit-progress-value { - transition: width 0.2s ease; - } - &::-moz-progress-bar { - transition: width 0.2s ease; - } - &::-ms-fill { - transition: width 0.2s ease; - } -} -.plyr--video .plyr__progress--buffer, -.plyr--video .plyr__volume--display { - background: $plyr-video-range-track-bg; -} -.plyr--video .plyr__progress--buffer { - color: $plyr-video-progress-buffered-bg; -} -.plyr--audio .plyr__progress--buffer, -.plyr--audio .plyr__volume--display { - background: $plyr-audio-range-track-bg; -} -.plyr--audio .plyr__progress--buffer { - color: $plyr-audio-progress-buffered-bg; -} - -// Loading state -.plyr--loading .plyr__progress--buffer { - animation: plyr-progress 1s linear infinite; - background-size: $plyr-progress-loading-size $plyr-progress-loading-size; - background-repeat: repeat-x; - background-image: linear-gradient( - -45deg, - $plyr-progress-loading-bg 25%, - transparent 25%, - transparent 50%, - $plyr-progress-loading-bg 50%, - $plyr-progress-loading-bg 75%, - transparent 75%, - transparent - ); - color: transparent; -} -.plyr--video.plyr--loading .plyr__progress--buffer { - background-color: $plyr-video-progress-buffered-bg; -} -.plyr--audio.plyr--loading .plyr__progress--buffer { - background-color: $plyr-audio-progress-buffered-bg; -} - -// Time -// -------------------------------------------------------------- -.plyr__time { - display: inline-block; - vertical-align: middle; - font-size: $plyr-font-size-small; -} -// Media duration hidden on small screens -.plyr__time + .plyr__time { - display: none; - - @media (min-width: $plyr-bp-screen-md) { - display: inline-block; - } - - // Add a slash in before - &::before { - content: "\2044"; - margin-right: $plyr-control-spacing; - } -} - -// Volume -// -------------------------------------------------------------- -.plyr__volume { - display: none; -} -.plyr .plyr__volume { - flex: 1; - position: relative; - - input[type="range"] { - position: relative; - z-index: 2; - } - @media (min-width: $plyr-bp-screen-sm) { - display: block; - max-width: 60px; - } - @media (min-width: $plyr-bp-screen-md) { - max-width: 100px; - } -} - -// Hide sound controls on iOS -// It's not supported to change volume using JavaScript: -// https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html -.plyr--is-ios .plyr__volume, -.plyr--is-ios [data-plyr="mute"] { - display: none !important; -} - -// Fullscreen -// -------------------------------------------------------------- -.plyr--fullscreen-active { - height: 100%; - width: 100%; - background: #000; - border-radius: 0 !important; - - video { - height: 100%; - } - .plyr__video-wrapper { - height: 100%; - width: 100%; - } - .plyr__video-embed { - // Revert overflow change - overflow: visible; - } - - // Vimeo requires some different styling - &.plyr--vimeo .plyr__video-wrapper { - height: 0; - top: 50%; - transform: translateY(-50%); - } -} - -// Fallback for unsupported browsers -.plyr--fullscreen-fallback.plyr--fullscreen-active { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 10000000; -} diff --git a/src/scss/variables.scss b/src/scss/variables.scss deleted file mode 100644 index da75f11a..00000000 --- a/src/scss/variables.scss +++ /dev/null @@ -1,73 +0,0 @@ -// ========================================================================== -// Plyr variables -// https://github.com/selz/plyr -// https://robots.thoughtbot.com/sass-default -// ========================================================================== - -// Settings -$plyr-border-box: true !default; -$plyr-touch-action: true !default; -$plyr-sr-only-important: true !default; - -// Colors -$plyr-color-main: #3498db !default; - -// Font sizes -$plyr-font-family: Avenir, 'Avenir Next', 'Helvetica Neue', 'Segoe UI', Helvetica, Arial, sans-serif !default; -$plyr-font-size-small: 14px !default; -$plyr-font-size-base: 16px !default; - -// Captions -$plyr-captions-bg: transparentize(#000, .3) !default; -$plyr-captions-color: #fff !default; -$plyr-font-size-captions-base: $plyr-font-size-base !default; -$plyr-font-size-captions-medium: ceil($plyr-font-size-base * 1.5) !default; -$plyr-font-size-captions-large: ($plyr-font-size-base * 2) !default; - -// Controls -$plyr-control-icon-size: 18px !default; -$plyr-control-spacing: 10px !default; -$plyr-control-padding: ($plyr-control-spacing * .7) !default; -$plyr-video-controls-bg: #000 !default; -$plyr-video-control-color: #fff !default; -$plyr-video-control-color-hover: #fff !default; -$plyr-video-control-bg-hover: $plyr-color-main !default; -$plyr-audio-controls-bg: #fff !default; -$plyr-audio-controls-border: 1px solid #dbe3e8 !default; -$plyr-audio-control-color: #565D64 !default; -$plyr-audio-control-color-hover: #fff !default; -$plyr-audio-control-bg-hover: $plyr-color-main; - -// Tooltips -$plyr-tooltip-bg: transparentize(#000, .3) !default; -$plyr-tooltip-color: #fff !default; -$plyr-tooltip-padding: ($plyr-control-spacing / 2) !default; -$plyr-tooltip-arrow-size: 4px !default; -$plyr-tooltip-radius: 3px !default; - -// Progress -$plyr-progress-loading-size: 25px !default; -$plyr-progress-loading-bg: transparentize(#000, .85) !default; -$plyr-video-progress-bg: transparentize(#fff, .75) !default; -$plyr-video-progress-buffered-bg: $plyr-video-progress-bg !default; -$plyr-audio-progress-bg: transparentize(#C6D6DB, .33) !default; -$plyr-audio-progress-buffered-bg: $plyr-audio-progress-bg !default; - -// Range sliders -$plyr-range-track-height: 8px !default; -$plyr-range-thumb-height: floor($plyr-range-track-height * 2) !default; -$plyr-range-thumb-width: floor($plyr-range-track-height * 2) !default; -$plyr-range-thumb-bg: #fff !default; -$plyr-range-thumb-border: 2px solid transparent !default; -$plyr-range-thumb-shadow: 0 1px 1px transparentize($plyr-video-controls-bg, .85), 0 0 0 1px transparentize(#000, .85) !default; -$plyr-range-thumb-active-border-color: #fff !default; -$plyr-range-thumb-active-bg: $plyr-video-control-bg-hover !default; -$plyr-range-thumb-active-scale: 1.25 !default; -$plyr-video-range-track-bg: $plyr-video-progress-buffered-bg !default; -$plyr-audio-range-track-bg: $plyr-audio-progress-buffered-bg !default; -$plyr-range-selected-bg: $plyr-color-main !default; - -// Breakpoints -$plyr-bp-screen-sm: 480px !default; -$plyr-bp-screen-md: 768px !default; -$plyr-bp-screen-lg: 1024px !default;
\ No newline at end of file diff --git a/src/sprite/plyr-airplay.svg b/src/sprite/plyr-airplay.svg new file mode 100644 index 00000000..45c55414 --- /dev/null +++ b/src/sprite/plyr-airplay.svg @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <g> + <path d="M16,1 L2,1 C1.447,1 1,1.447 1,2 L1,12 C1,12.553 1.447,13 2,13 L5,13 L5,11 L3,11 L3,3 L15,3 L15,11 L13,11 L13,13 L16,13 C16.553,13 17,12.553 17,12 L17,2 C17,1.447 16.553,1 16,1 L16,1 Z"></path> + <polygon points="4 17 14 17 9 11"></polygon> + </g> +</svg>
\ No newline at end of file diff --git a/src/sprite/plyr-pip.svg b/src/sprite/plyr-pip.svg new file mode 100644 index 00000000..d841fce5 --- /dev/null +++ b/src/sprite/plyr-pip.svg @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <g> + <polygon points="13.293 3.293 7.022 9.564 8.436 10.978 14.707 4.707 17 7 17 1 11 1"></polygon> + <path d="M13,15 L3,15 L3,5 L8,5 L8,3 L2,3 C1.448,3 1,3.448 1,4 L1,16 C1,16.552 1.448,17 2,17 L14,17 C14.552,17 15,16.552 15,16 L15,10 L13,10 L13,15 L13,15 Z"></path> + </g> +</svg>
\ No newline at end of file diff --git a/src/sprite/plyr-settings.svg b/src/sprite/plyr-settings.svg new file mode 100644 index 00000000..fbf8ecd1 --- /dev/null +++ b/src/sprite/plyr-settings.svg @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <g> + <path d="M16.135,7.784 C14.832,7.458 14.214,5.966 14.905,4.815 C15.227,4.279 15.13,3.817 14.811,3.499 L14.501,3.189 C14.183,2.871 13.721,2.774 13.185,3.095 C12.033,3.786 10.541,3.168 10.216,1.865 C10.065,1.258 9.669,1 9.219,1 L8.781,1 C8.331,1 7.936,1.258 7.784,1.865 C7.458,3.168 5.966,3.786 4.815,3.095 C4.279,2.773 3.816,2.87 3.498,3.188 L3.188,3.498 C2.87,3.816 2.773,4.279 3.095,4.815 C3.786,5.967 3.168,7.459 1.865,7.784 C1.26,7.935 1,8.33 1,8.781 L1,9.219 C1,9.669 1.258,10.064 1.865,10.216 C3.168,10.542 3.786,12.034 3.095,13.185 C2.773,13.721 2.87,14.183 3.189,14.501 L3.499,14.811 C3.818,15.13 4.281,15.226 4.815,14.905 C5.967,14.214 7.459,14.832 7.784,16.135 C7.935,16.742 8.331,17 8.781,17 L9.219,17 C9.669,17 10.064,16.742 10.216,16.135 C10.542,14.832 12.034,14.214 13.185,14.905 C13.72,15.226 14.182,15.13 14.501,14.811 L14.811,14.501 C15.129,14.183 15.226,13.72 14.905,13.185 C14.214,12.033 14.832,10.541 16.135,10.216 C16.742,10.065 17,9.669 17,9.219 L17,8.781 C17,8.33 16.74,7.935 16.135,7.784 L16.135,7.784 Z M9,12 C7.343,12 6,10.657 6,9 C6,7.343 7.343,6 9,6 C10.657,6 12,7.343 12,9 C12,10.657 10.657,12 9,12 L9,12 Z"></path> + </g> +</svg>
\ No newline at end of file diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..8e51f8e1 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,5731 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@7.0.0-beta.31": + version "7.0.0-beta.31" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.31.tgz#473d021ecc573a2cce1c07d5b509d5215f46ba35" + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + +"@babel/helper-function-name@7.0.0-beta.31": + version "7.0.0-beta.31" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.31.tgz#afe63ad799209989348b1109b44feb66aa245f57" + dependencies: + "@babel/helper-get-function-arity" "7.0.0-beta.31" + "@babel/template" "7.0.0-beta.31" + "@babel/traverse" "7.0.0-beta.31" + "@babel/types" "7.0.0-beta.31" + +"@babel/helper-get-function-arity@7.0.0-beta.31": + version "7.0.0-beta.31" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.31.tgz#1176d79252741218e0aec872ada07efb2b37a493" + dependencies: + "@babel/types" "7.0.0-beta.31" + +"@babel/template@7.0.0-beta.31": + version "7.0.0-beta.31" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.31.tgz#577bb29389f6c497c3e7d014617e7d6713f68bda" + dependencies: + "@babel/code-frame" "7.0.0-beta.31" + "@babel/types" "7.0.0-beta.31" + babylon "7.0.0-beta.31" + lodash "^4.2.0" + +"@babel/traverse@7.0.0-beta.31": + version "7.0.0-beta.31" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.31.tgz#db399499ad74aefda014f0c10321ab255134b1df" + dependencies: + "@babel/code-frame" "7.0.0-beta.31" + "@babel/helper-function-name" "7.0.0-beta.31" + "@babel/types" "7.0.0-beta.31" + babylon "7.0.0-beta.31" + debug "^3.0.1" + globals "^10.0.0" + invariant "^2.2.0" + lodash "^4.2.0" + +"@babel/types@7.0.0-beta.31": + version "7.0.0-beta.31" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.31.tgz#42c9c86784f674c173fb21882ca9643334029de4" + dependencies: + esutils "^2.0.2" + lodash "^4.2.0" + to-fast-properties "^2.0.0" + +"@gulp-sourcemaps/identity-map@1.X": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz#cfa23bc5840f9104ce32a65e74db7e7a974bbee1" + dependencies: + acorn "^5.0.3" + css "^2.2.1" + normalize-path "^2.1.1" + source-map "^0.5.6" + through2 "^2.0.3" + +"@gulp-sourcemaps/map-sources@1.X": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz#890ae7c5d8c877f6d384860215ace9d7ec945bda" + dependencies: + normalize-path "^2.0.1" + through2 "^2.0.3" + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + dependencies: + acorn "^3.0.4" + +acorn@4.X: + version "4.0.13" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" + +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + +acorn@^5.0.3, acorn@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.2.1.tgz#317ac7821826c22c702d66189ab8359675f135d7" + +ajv-keywords@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" + +ajv@^5.1.0, ajv@^5.2.3, ajv@^5.3.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + +ansi-escapes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92" + +ansi-gray@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" + dependencies: + ansi-wrap "0.1.0" + +ansi-regex@^0.2.0, ansi-regex@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + +ansi-styles@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" + dependencies: + color-convert "^1.9.0" + +ansi-wrap@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + +are-we-there-yet@~1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + dependencies: + sprintf-js "~1.0.2" + +aria-query@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-0.7.0.tgz#4af10a1e61573ddea0cf3b99b51c52c05b424d24" + dependencies: + ast-types-flow "0.0.7" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + +arr-flatten@^1.0.1, arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + +array-differ@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" + +array-each@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" + +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + +array-includes@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.7.0" + +array-iterate@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-iterate/-/array-iterate-1.1.1.tgz#865bf7f8af39d6b0982c60902914ac76bc0108f6" + +array-slice@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4" + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1, array-uniq@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + +arrify@^1.0.0, arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + +ast-types-flow@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" + +async-foreach@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" + +async@: + version "2.6.0" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" + dependencies: + lodash "^4.14.0" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +atob@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.0.3.tgz#19c7a760473774468f20b2d2d03372ad7d4cbf5d" + +atob@~1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773" + +autoprefixer@^7.0.0, autoprefixer@^7.1.2: + version "7.2.3" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.2.3.tgz#c2841e38b7940c2d0a9bbffd72c75f33637854f8" + dependencies: + browserslist "^2.10.0" + caniuse-lite "^1.0.30000783" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^6.0.14" + postcss-value-parser "^3.2.3" + +aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + +aws4@^1.2.1, aws4@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" + +axobject-query@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-0.1.0.tgz#62f59dbc59c9f9242759ca349960e7a2fe3c36c0" + dependencies: + ast-types-flow "0.0.7" + +babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.0" + debug "^2.6.8" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.7" + slash "^1.0.0" + source-map "^0.5.6" + +babel-eslint@^8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.0.3.tgz#f29ecf02336be438195325cd47c468da81ee4e98" + dependencies: + "@babel/code-frame" "7.0.0-beta.31" + "@babel/traverse" "7.0.0-beta.31" + "@babel/types" "7.0.0-beta.31" + babylon "7.0.0-beta.31" + +babel-generator@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.6" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-external-helpers@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-external-helpers/-/babel-plugin-external-helpers-6.22.0.tgz#2285f48b02bd5dede85175caf8c62e86adccefa1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-preset-env@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.1.tgz#a18b564cc9b9afdf4aae57ae3c1b0d99188e6f48" + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^2.1.2" + invariant "^2.2.2" + semver "^5.3.0" + +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon@7.0.0-beta.31: + version "7.0.0-beta.31" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.31.tgz#7ec10f81e0e456fd0f855ad60fa30c2ac454283f" + +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + +bail@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.2.tgz#f7d6c1731630a9f9f0d4d35ed1f962e2074a1764" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" + dependencies: + tweetnacl "^0.14.3" + +beeper@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" + +binaryextensions@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-1.0.1.tgz#1e637488b35b58bda5f4774bf96a5212a8c90755" + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + dependencies: + inherits "~2.0.0" + +boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + +boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + +boom@4.x.x: + version "4.3.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" + dependencies: + hoek "4.x.x" + +boom@5.x.x: + version "5.2.0" + resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" + dependencies: + hoek "4.x.x" + +brace-expansion@^1.0.0, brace-expansion@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +braces@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.0.tgz#a46941cb5fb492156b3d6a656e06c35364e3e66e" + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + define-property "^1.0.0" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +browser-resolve@^1.11.0: + version "1.11.2" + resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce" + dependencies: + resolve "1.1.7" + +browserslist@^2.1.2, browserslist@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.10.0.tgz#bac5ee1cc69ca9d96403ffb8a3abdc5b6aed6346" + dependencies: + caniuse-lite "^1.0.30000780" + electron-to-chromium "^1.3.28" + +builtin-modules@^1.0.0, builtin-modules@^1.1.0, builtin-modules@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + +camelcase-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + dependencies: + camelcase "^2.0.0" + map-obj "^1.0.0" + +camelcase-keys@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" + dependencies: + camelcase "^4.1.0" + map-obj "^2.0.0" + quick-lru "^1.0.0" + +camelcase@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + +caniuse-lite@^1.0.30000780, caniuse-lite@^1.0.30000783: + version "1.0.30000784" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000784.tgz#129ced74e9a1280a441880b6cd2bce30ef59e6c0" + +caseless@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +ccount@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.2.tgz#53b6a2f815bb77b9c2871f7b9a72c3a25f1d8e89" + +chalk@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" + dependencies: + ansi-styles "^1.1.0" + escape-string-regexp "^1.0.0" + has-ansi "^0.1.0" + strip-ansi "^0.3.0" + supports-color "^0.2.0" + +chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + +character-entities-html4@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.1.tgz#359a2a4a0f7e29d3dc2ac99bdbe21ee39438ea50" + +character-entities-legacy@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz#f40779df1a101872bb510a3d295e1fccf147202f" + +character-entities@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.1.tgz#f76871be5ef66ddb7f8f8e3478ecc374c27d6dca" + +character-reference-invalid@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.1.tgz#942835f750e4ec61a308e60c2ef8cc1011202efc" + +chardet@^0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" + +cheerio@0.*: + version "0.22.0" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.0" + entities "~1.1.1" + htmlparser2 "^3.9.1" + lodash.assignin "^4.0.9" + lodash.bind "^4.1.4" + lodash.defaults "^4.0.1" + lodash.filter "^4.4.0" + lodash.flatten "^4.2.0" + lodash.foreach "^4.3.0" + lodash.map "^4.4.0" + lodash.merge "^4.4.0" + lodash.pick "^4.2.1" + lodash.reduce "^4.4.0" + lodash.reject "^4.4.0" + lodash.some "^4.4.0" + +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + +clap@^1.0.9: + version "1.2.3" + resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51" + dependencies: + chalk "^1.1.3" + +class-utils@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.5.tgz#17e793103750f9627b2176ea34cfd1b565903c80" + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + lazy-cache "^2.0.2" + static-extend "^0.1.1" + +clean-css@4.1.9: + version "4.1.9" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.1.9.tgz#35cee8ae7687a49b98034f70de00c4edd3826301" + dependencies: + source-map "0.5.x" + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + dependencies: + restore-cursor "^2.0.0" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +clone-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" + +clone-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-1.0.0.tgz#eae0a2413f55c0942f818c229fefce845d7f3b1c" + dependencies: + is-regexp "^1.0.0" + is-supported-regexp-flag "^1.0.0" + +clone-stats@^0.0.1, clone-stats@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" + +clone-stats@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" + +clone@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" + +clone@^1.0.0, clone@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" + +clone@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" + +cloneable-readable@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.0.0.tgz#a6290d413f217a61232f95e458ff38418cfb0117" + dependencies: + inherits "^2.0.1" + process-nextick-args "^1.0.6" + through2 "^2.0.1" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +coa@~1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" + dependencies: + q "^1.1.2" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +collapse-white-space@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.3.tgz#4b906f670e5a963a87b76b0e1689643341b6023c" + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + dependencies: + color-name "^1.1.1" + +color-name@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + +colors@^1.1.2, colors@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + +combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" + dependencies: + delayed-stream "~1.0.0" + +commander@^2.9.0, commander@~2.12.1: + version "2.12.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555" + +component-emitter@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +concat-with-sourcemaps@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.4.tgz#f55b3be2aeb47601b10a2d5259ccfb70fd2f1dd6" + dependencies: + source-map "^0.5.1" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + +convert-source-map@1.X, convert-source-map@^1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + +core-js@^1.0.0: + version "1.2.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" + +core-js@^2.4.0, core-js@^2.5.0: + version "2.5.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cosmiconfig@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-3.1.0.tgz#640a94bf9847f321800403cd273af60665c73397" + dependencies: + is-directory "^0.3.1" + js-yaml "^3.9.0" + parse-json "^3.0.0" + require-from-string "^2.0.1" + +cross-spawn@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" + +cross-spawn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + +cryptiles@3.x.x: + version "3.1.2" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" + dependencies: + boom "5.x.x" + +css-select@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" + dependencies: + boolbase "~1.0.0" + css-what "2.1" + domutils "1.5.1" + nth-check "~1.0.1" + +css-what@2.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" + +css@2.X, css@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/css/-/css-2.2.1.tgz#73a4c81de85db664d4ee674f7d47085e3b2d55dc" + dependencies: + inherits "^2.0.1" + source-map "^0.1.38" + source-map-resolve "^0.3.0" + urix "^0.1.0" + +csso@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" + dependencies: + clap "^1.0.9" + source-map "^0.5.3" + +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + dependencies: + array-find-index "^1.0.1" + +d@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" + dependencies: + es5-ext "^0.10.9" + +damerau-levenshtein@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz#03191c432cb6eea168bb77f3a55ffdccb8978514" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +dateformat@^1.0.7-1.2.3: + version "1.0.12" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" + dependencies: + get-stdin "^4.0.1" + meow "^3.3.0" + +dateformat@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" + +debug-fabulous@>=0.1.1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-1.0.0.tgz#57f6648646097b1b0849dcda0017362c1ec00f8b" + dependencies: + debug "3.X" + memoizee "0.4.X" + object-assign "4.X" + +debug@3.X, debug@^3.0.0, debug@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + dependencies: + ms "2.0.0" + +debug@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-1.0.5.tgz#f7241217430f99dec4c2b473eab92228e874c2ac" + dependencies: + ms "2.0.0" + +debug@^2.2.0, debug@^2.3.3, debug@^2.6.8: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +decamelize-keys@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" + +decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +defaults@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + dependencies: + clone "^1.0.2" + +define-properties@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + dependencies: + is-descriptor "^1.0.0" + +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + +del@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5" + dependencies: + globby "^6.1.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + p-map "^1.1.1" + pify "^3.0.0" + rimraf "^2.2.8" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +deprecated@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19" + +detect-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" + +detect-newline@2.X: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" + +dir-glob@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" + dependencies: + arrify "^1.0.1" + path-type "^3.0.0" + +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +doctrine@^2.0.0, doctrine@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.2.tgz#68f96ce8efc56cc42651f1faadb4f175273b0075" + dependencies: + esutils "^2.0.2" + +dom-serializer@0, dom-serializer@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" + dependencies: + domelementtype "~1.1.1" + entities "~1.1.1" + +domelementtype@1, domelementtype@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + +domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + +domhandler@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.1.tgz#892e47000a99be55bbf3774ffea0561d8879c259" + dependencies: + domelementtype "1" + +domutils@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + dependencies: + dom-serializer "0" + domelementtype "1" + +domutils@^1.5.1: + version "1.6.2" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.6.2.tgz#1958cc0b4c9426e9ed367fb1c8e854891b0fa3ff" + dependencies: + dom-serializer "0" + domelementtype "1" + +dot-prop@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + dependencies: + is-obj "^1.0.0" + +duplexer2@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" + dependencies: + readable-stream "~1.1.9" + +duplexer@^0.1.1, duplexer@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + +electron-to-chromium@^1.3.28: + version "1.3.29" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.29.tgz#7a58236b95468c3e7660091348522d65d7736b36" + +emoji-regex@^6.1.0: + version "6.5.1" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.5.1.tgz#9baea929b155565c11ea41c6626eaa65cef992c2" + +encoding@^0.1.11: + version "0.1.12" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" + dependencies: + iconv-lite "~0.4.13" + +end-of-stream@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-0.1.5.tgz#8e177206c3c80837d85632e8b9359dfe8b2f6eaf" + dependencies: + once "~1.3.0" + +entities@^1.1.1, entities@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.7.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864" + dependencies: + es-to-primitive "^1.1.1" + function-bind "^1.1.1" + has "^1.0.1" + is-callable "^1.1.3" + is-regex "^1.0.4" + +es-to-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" + dependencies: + is-callable "^1.1.1" + is-date-object "^1.0.1" + is-symbol "^1.0.1" + +es5-ext@^0.10.14, es5-ext@^0.10.30, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2: + version "0.10.37" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.37.tgz#0ee741d148b80069ba27d020393756af257defc3" + dependencies: + es6-iterator "~2.0.1" + es6-symbol "~3.1.1" + +es6-iterator@^2.0.1, es6-iterator@~2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + dependencies: + d "1" + es5-ext "~0.10.14" + +es6-weak-map@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" + dependencies: + d "1" + es5-ext "^0.10.14" + es6-iterator "^2.0.1" + es6-symbol "^3.1.1" + +escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +eslint-config-airbnb-base@^12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-12.1.0.tgz#386441e54a12ccd957b0a92564a4bafebd747944" + dependencies: + eslint-restricted-globals "^0.1.1" + +eslint-config-airbnb@^16.1.0: + version "16.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-16.1.0.tgz#2546bfb02cc9fe92284bf1723ccf2e87bc45ca46" + dependencies: + eslint-config-airbnb-base "^12.1.0" + +eslint-config-prettier@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz#5ecd65174d486c22dff389fe036febf502d468a3" + dependencies: + get-stdin "^5.0.1" + +eslint-import-resolver-node@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz#4422574cde66a9a7b099938ee4d508a199e0e3cc" + dependencies: + debug "^2.6.8" + resolve "^1.2.0" + +eslint-module-utils@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449" + dependencies: + debug "^2.6.8" + pkg-dir "^1.0.0" + +eslint-plugin-import@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz#fa1b6ef31fcb3c501c09859c1b86f1fc5b986894" + dependencies: + builtin-modules "^1.1.1" + contains-path "^0.1.0" + debug "^2.6.8" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.1" + eslint-module-utils "^2.1.1" + has "^1.0.1" + lodash.cond "^4.3.0" + minimatch "^3.0.3" + read-pkg-up "^2.0.0" + +eslint-plugin-jsx-a11y@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.0.3.tgz#54583d1ae442483162e040e13cc31865465100e5" + dependencies: + aria-query "^0.7.0" + array-includes "^3.0.3" + ast-types-flow "0.0.7" + axobject-query "^0.1.0" + damerau-levenshtein "^1.0.0" + emoji-regex "^6.1.0" + jsx-ast-utils "^2.0.0" + +eslint-plugin-react@^7.5.1: + version "7.5.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.5.1.tgz#52e56e8d80c810de158859ef07b880d2f56ee30b" + dependencies: + doctrine "^2.0.0" + has "^1.0.1" + jsx-ast-utils "^2.0.0" + prop-types "^15.6.0" + +eslint-restricted-globals@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz#35f0d5cbc64c2e3ed62e93b4b1a7af05ba7ed4d7" + +eslint-scope@^3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint@^4.13.1: + version "4.13.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.13.1.tgz#0055e0014464c7eb7878caf549ef2941992b444f" + dependencies: + ajv "^5.3.0" + babel-code-frame "^6.22.0" + chalk "^2.1.0" + concat-stream "^1.6.0" + cross-spawn "^5.1.0" + debug "^3.0.1" + doctrine "^2.0.2" + eslint-scope "^3.7.1" + espree "^3.5.2" + esquery "^1.0.0" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.0.1" + ignore "^3.3.3" + imurmurhash "^0.1.4" + inquirer "^3.0.6" + is-resolvable "^1.0.0" + js-yaml "^3.9.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.4" + minimatch "^3.0.2" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + pluralize "^7.0.0" + progress "^2.0.0" + require-uncached "^1.0.3" + semver "^5.3.0" + strip-ansi "^4.0.0" + strip-json-comments "~2.0.1" + table "^4.0.1" + text-table "~0.2.0" + +espree@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.2.tgz#756ada8b979e9dcfcdb30aad8d1a9304a905e1ca" + dependencies: + acorn "^5.2.1" + acorn-jsx "^3.0.0" + +esprima@^2.6.0: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + +esprima@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + +esquery@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" + dependencies: + estraverse "^4.1.0" + object-assign "^4.0.1" + +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +estree-walker@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" + +estree-walker@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.3.1.tgz#e6b1a51cf7292524e7237c312e5fe6660c1ce1aa" + +estree-walker@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.1.tgz#64fc375053abc6f57d73e9bd2f004644ad3c5854" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + dependencies: + d "1" + es5-ext "~0.10.14" + +event-stream@*: + version "3.3.4" + resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" + dependencies: + duplexer "~0.1.1" + from "~0" + map-stream "~0.1.0" + pause-stream "0.0.11" + split "0.3" + stream-combiner "~0.0.4" + through "~2.3.1" + +execall@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execall/-/execall-1.0.0.tgz#73d0904e395b3cab0658b08d09ec25307f29bb73" + dependencies: + clone-regexp "^1.0.0" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + +expand-tilde@^2.0.0, expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + dependencies: + homedir-polyfill "^1.0.1" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.1.tgz#4b6d8c49b147fee029dc9eb9484adb770f689844" + dependencies: + is-extendable "^1.0.1" + +extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" + +external-editor@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.1.0.tgz#3d026a21b7f95b5726387d4200ac160d372c3b48" + dependencies: + chardet "^0.4.0" + iconv-lite "^0.4.17" + tmp "^0.0.33" + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + +extglob@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.2.tgz#3290f46208db1b2e8eb8be0c94ed9e6ad80edbe2" + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + +fancy-log@^1.1.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" + dependencies: + ansi-gray "^0.1.1" + color-support "^1.1.3" + time-stamp "^1.0.0" + +fast-deep-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +fbjs@^0.8.16: + version "0.8.16" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" + dependencies: + core-js "^1.0.0" + isomorphic-fetch "^2.1.1" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.9" + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + +fill-range@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^1.1.3" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +find-index@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/find-index/-/find-index-0.1.1.tgz#675d358b2ca3892d795a1ab47232f8b6e2e0dde4" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + +findup-sync@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" + dependencies: + detect-file "^1.0.0" + is-glob "^3.1.0" + micromatch "^3.0.4" + resolve-dir "^1.0.1" + +fined@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476" + dependencies: + expand-tilde "^2.0.2" + is-plain-object "^2.0.3" + object.defaults "^1.1.0" + object.pick "^1.2.0" + parse-filepath "^1.0.1" + +first-chunk-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" + +flagged-respawn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.0.tgz#4e79ae9b2eb38bf86b3bb56bf3e0a56aa5fcabd7" + +flat-cache@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" + dependencies: + circular-json "^0.3.1" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + +for-in@^1.0.1, for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + dependencies: + for-in "^1.0.1" + +for-own@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" + dependencies: + for-in "^1.0.1" + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +form-data@~2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + dependencies: + map-cache "^0.2.2" + +from@~0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +fstream@^1.0.0, fstream@^1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +function-bind@^1.0.2, function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +gaze@^0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-0.5.2.tgz#40b709537d24d1d45767db5a908689dfe69ac44f" + dependencies: + globule "~0.1.0" + +gaze@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.2.tgz#847224677adb8870d679257ed3388fdb61e40105" + dependencies: + globule "^1.0.0" + +generate-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" + +generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + dependencies: + is-property "^1.0.0" + +get-caller-file@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + +get-stdin@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + +glob-stream@^3.1.5: + version "3.1.18" + resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-3.1.18.tgz#9170a5f12b790306fdfe598f313f8f7954fd143b" + dependencies: + glob "^4.3.1" + glob2base "^0.0.12" + minimatch "^2.0.1" + ordered-read-streams "^0.1.0" + through2 "^0.6.1" + unique-stream "^1.0.0" + +glob-watcher@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-0.0.6.tgz#b95b4a8df74b39c83298b0c05c978b4d9a3b710b" + dependencies: + gaze "^0.5.1" + +glob2base@^0.0.12: + version "0.0.12" + resolved "https://registry.yarnpkg.com/glob2base/-/glob2base-0.0.12.tgz#9d419b3e28f12e83a362164a277055922c9c0d56" + dependencies: + find-index "^0.1.1" + +glob@^4.3.1: + version "4.5.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "^2.0.1" + once "^1.3.0" + +glob@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@~7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@~3.1.21: + version "3.1.21" + resolved "https://registry.yarnpkg.com/glob/-/glob-3.1.21.tgz#d29e0a055dea5138f4d07ed40e8982e83c2066cd" + dependencies: + graceful-fs "~1.2.0" + inherits "1" + minimatch "~0.2.11" + +global-modules@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + dependencies: + global-prefix "^1.0.1" + is-windows "^1.0.1" + resolve-dir "^1.0.0" + +global-prefix@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + dependencies: + expand-tilde "^2.0.2" + homedir-polyfill "^1.0.1" + ini "^1.3.4" + is-windows "^1.0.1" + which "^1.2.14" + +globals@^10.0.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-10.4.0.tgz#5c477388b128a9e4c5c5d01c7a2aca68c68b2da7" + +globals@^11.0.1: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.1.0.tgz#632644457f5f0e3ae711807183700ebf2e4633e4" + +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +globby@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" + dependencies: + array-union "^1.0.1" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +globby@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" + dependencies: + array-union "^1.0.1" + dir-glob "^2.0.0" + glob "^7.1.2" + ignore "^3.3.5" + pify "^3.0.0" + slash "^1.0.0" + +globjoin@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" + +globule@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.0.tgz#1dc49c6822dd9e8a2fa00ba2a295006e8664bd09" + dependencies: + glob "~7.1.1" + lodash "~4.17.4" + minimatch "~3.0.2" + +globule@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/globule/-/globule-0.1.0.tgz#d9c8edde1da79d125a151b79533b978676346ae5" + dependencies: + glob "~3.1.21" + lodash "~1.0.1" + minimatch "~0.2.11" + +glogg@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.0.tgz#7fe0f199f57ac906cf512feead8f90ee4a284fc5" + dependencies: + sparkles "^1.0.0" + +gonzales-pe@^4.0.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.3.tgz#41091703625433285e0aee3aa47829fc1fbeb6f2" + dependencies: + minimist "1.1.x" + +graceful-fs@4.X, graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +graceful-fs@^3.0.0: + version "3.0.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.11.tgz#7613c778a1afea62f25c630a086d7f3acbbdd818" + dependencies: + natives "^1.1.0" + +graceful-fs@~1.2.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364" + +gulp-autoprefixer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/gulp-autoprefixer/-/gulp-autoprefixer-4.0.0.tgz#e00a8c571b85d06516ac26341be90dfd9fc1eab0" + dependencies: + autoprefixer "^7.0.0" + gulp-util "^3.0.0" + postcss "^6.0.1" + through2 "^2.0.0" + vinyl-sourcemaps-apply "^0.2.0" + +gulp-better-rollup@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/gulp-better-rollup/-/gulp-better-rollup-2.0.0.tgz#e0792758bcd59084b5a1b15e34f62eaf22afdaed" + dependencies: + gulp-util "^3.0.8" + lodash.camelcase "^4.3.0" + rollup "^0.50.0" + vinyl-sourcemaps-apply "^0.2.1" + +gulp-clean-css@^3.9.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/gulp-clean-css/-/gulp-clean-css-3.9.0.tgz#e43e4c8d695060f6ba08a154d8e76d0d87b1c822" + dependencies: + clean-css "4.1.9" + gulp-util "3.0.8" + through2 "2.0.3" + vinyl-sourcemaps-apply "0.2.1" + +gulp-concat@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/gulp-concat/-/gulp-concat-2.6.1.tgz#633d16c95d88504628ad02665663cee5a4793353" + dependencies: + concat-with-sourcemaps "^1.0.0" + through2 "^2.0.0" + vinyl "^2.0.0" + +gulp-open@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/gulp-open/-/gulp-open-2.0.0.tgz#a16f67e95cea8b2061b63a3b8c389bc559b8e1ce" + dependencies: + colors "^1.1.2" + gulp-util "^3.0.2" + open "0.0.5" + through2 "^2.0.1" + +gulp-rename@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.2.2.tgz#3ad4428763f05e2764dec1c67d868db275687817" + +gulp-replace@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/gulp-replace/-/gulp-replace-0.6.1.tgz#11bf8c8fce533e33e2f6a8f2f430b955ba0be066" + dependencies: + istextorbinary "1.0.2" + readable-stream "^2.0.1" + replacestream "^4.0.0" + +gulp-s3@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/gulp-s3/-/gulp-s3-0.11.0.tgz#9e302b5645206e217a525d20befa1ed293442492" + dependencies: + async "" + event-stream "*" + gulp-util "~2.2.6" + knox "" + mime "~1.2.11" + +gulp-sass@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-3.1.0.tgz#53dc4b68a1f5ddfe4424ab4c247655269a8b74b7" + dependencies: + gulp-util "^3.0" + lodash.clonedeep "^4.3.2" + node-sass "^4.2.0" + through2 "^2.0.0" + vinyl-sourcemaps-apply "^0.2.0" + +gulp-size@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/gulp-size/-/gulp-size-2.1.0.tgz#1c2b64f17f9071d5abd99d154b7b3481f8fba128" + dependencies: + chalk "^1.0.0" + gulp-util "^3.0.0" + gzip-size "^3.0.0" + object-assign "^4.0.1" + pretty-bytes "^3.0.1" + stream-counter "^1.0.0" + through2 "^2.0.0" + +gulp-sourcemaps@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-2.6.1.tgz#833a4e28f0b8f4661075032cd782417f7cd8fb0b" + dependencies: + "@gulp-sourcemaps/identity-map" "1.X" + "@gulp-sourcemaps/map-sources" "1.X" + acorn "4.X" + convert-source-map "1.X" + css "2.X" + debug-fabulous ">=0.1.1" + detect-newline "2.X" + graceful-fs "4.X" + source-map "0.X" + strip-bom-string "1.X" + through2 "2.X" + vinyl "1.X" + +gulp-svgmin@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/gulp-svgmin/-/gulp-svgmin-1.2.4.tgz#a4aa9e2615cf1105ef555aea86e86296cc20e273" + dependencies: + gulp-util "^3.0.4" + svgo "^0.7.0" + +gulp-svgstore@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/gulp-svgstore/-/gulp-svgstore-6.1.0.tgz#04b203ac0e13f8ed6dbfc940d25965c4e2456676" + dependencies: + cheerio "0.*" + gulp-util "^3.0.0" + +gulp-util@3.0.8, gulp-util@^3.0, gulp-util@^3.0.0, gulp-util@^3.0.2, gulp-util@^3.0.4, gulp-util@^3.0.8: + version "3.0.8" + resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" + dependencies: + array-differ "^1.0.0" + array-uniq "^1.0.2" + beeper "^1.0.0" + chalk "^1.0.0" + dateformat "^2.0.0" + fancy-log "^1.1.0" + gulplog "^1.0.0" + has-gulplog "^0.1.0" + lodash._reescape "^3.0.0" + lodash._reevaluate "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.template "^3.0.0" + minimist "^1.1.0" + multipipe "^0.1.2" + object-assign "^3.0.0" + replace-ext "0.0.1" + through2 "^2.0.0" + vinyl "^0.5.0" + +gulp-util@~2.2.6: + version "2.2.20" + resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-2.2.20.tgz#d7146e5728910bd8f047a6b0b1e549bc22dbd64c" + dependencies: + chalk "^0.5.0" + dateformat "^1.0.7-1.2.3" + lodash._reinterpolate "^2.4.1" + lodash.template "^2.4.1" + minimist "^0.2.0" + multipipe "^0.1.0" + through2 "^0.5.0" + vinyl "^0.2.1" + +gulp@^3.9.1: + version "3.9.1" + resolved "https://registry.yarnpkg.com/gulp/-/gulp-3.9.1.tgz#571ce45928dd40af6514fc4011866016c13845b4" + dependencies: + archy "^1.0.0" + chalk "^1.0.0" + deprecated "^0.0.1" + gulp-util "^3.0.0" + interpret "^1.0.0" + liftoff "^2.1.0" + minimist "^1.1.0" + orchestrator "^0.3.0" + pretty-hrtime "^1.0.0" + semver "^4.1.0" + tildify "^1.0.0" + v8flags "^2.0.2" + vinyl-fs "^0.3.0" + +gulplog@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" + dependencies: + glogg "^1.0.0" + +gzip-size@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-3.0.0.tgz#546188e9bdc337f673772f81660464b389dce520" + dependencies: + duplexer "^0.1.1" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + +har-validator@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" + dependencies: + chalk "^1.1.1" + commander "^2.9.0" + is-my-json-valid "^2.12.4" + pinkie-promise "^2.0.0" + +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + +has-ansi@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-0.1.0.tgz#84f265aae8c0e6a88a12d7022894b7568894c62e" + dependencies: + ansi-regex "^0.2.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + +has-gulplog@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" + dependencies: + sparkles "^1.0.0" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + dependencies: + function-bind "^1.0.2" + +hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + +hawk@~6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" + dependencies: + boom "4.x.x" + cryptiles "3.x.x" + hoek "4.x.x" + sntp "2.x.x" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + +hoek@4.x.x: + version "4.2.0" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +homedir-polyfill@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" + dependencies: + parse-passwd "^1.0.0" + +hosted-git-info@^2.1.4: + version "2.5.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" + +html-tags@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b" + +htmlparser2@^3.9.1, htmlparser2@^3.9.2: + version "3.9.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" + dependencies: + domelementtype "^1.3.0" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^2.0.2" + +http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +iconv-lite@^0.4.17, iconv-lite@~0.4.13: + version "0.4.19" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" + +ignore@^3.3.3, ignore@^3.3.5: + version "3.3.7" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +in-publish@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51" + +indent-string@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + dependencies: + repeating "^2.0.0" + +indent-string@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b" + +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +ini@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + +inquirer@^3.0.6: + version "3.3.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.4" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.1.0" + strip-ansi "^4.0.0" + through "^2.3.6" + +interpret@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" + +invariant@^2.2.0, invariant@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + +is-absolute@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + dependencies: + is-relative "^1.0.0" + is-windows "^1.0.1" + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + dependencies: + kind-of "^3.0.2" + +is-alphabetical@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.1.tgz#c77079cc91d4efac775be1034bf2d243f95e6f08" + +is-alphanumeric@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz#4a9cef71daf4c001c1d81d63d140cf53fd6889f4" + +is-alphanumerical@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz#dfb4aa4d1085e33bdb61c2dee9c80e9c6c19f53b" + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-buffer@^1.1.4, is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-callable@^1.1.1, is-callable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + dependencies: + kind-of "^3.0.2" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + +is-decimal@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.1.tgz#f5fb6a94996ad9e8e3761fbfbd091f1fca8c4e82" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.1.tgz#2c6023599bde2de9d5d2c8b9a9d94082036b6ef2" + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + +is-extglob@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + dependencies: + is-extglob "^2.1.0" + +is-hexadecimal@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz#6e084bbc92061fbb0971ec58b6ce6d404e24da69" + +is-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + +is-my-json-valid@^2.12.4: + version "2.17.1" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471" + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + dependencies: + kind-of "^3.0.2" + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + +is-odd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-1.0.0.tgz#3b8a932eb028b3775c39bb09e91767accdb69088" + dependencies: + is-number "^3.0.0" + +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + +is-path-in-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + dependencies: + path-is-inside "^1.0.1" + +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + dependencies: + isobject "^3.0.1" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + +is-promise@^2.1, is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + +is-property@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + dependencies: + has "^1.0.1" + +is-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + +is-relative@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + dependencies: + is-unc-path "^1.0.0" + +is-resolvable@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.1.tgz#acca1cd36dbe44b974b924321555a70ba03b1cf4" + +is-stream@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +is-supported-regexp-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.0.tgz#8b520c85fae7a253382d4b02652e045576e13bb8" + +is-symbol@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +is-unc-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + dependencies: + unc-path-regex "^0.1.2" + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + +is-whitespace-character@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz#9ae0176f3282b65457a1992cdb084f8a5f833e3b" + +is-windows@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9" + +is-word-character@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.1.tgz#5a03fa1ea91ace8a6eb0c7cd770eb86d65c8befb" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + +isomorphic-fetch@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + dependencies: + node-fetch "^1.0.1" + whatwg-fetch ">=0.10.0" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +istextorbinary@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-1.0.2.tgz#ace19354d1a9a0173efeb1084ce0f87b0ad7decf" + dependencies: + binaryextensions "~1.0.0" + textextensions "~1.0.0" + +js-base64@^2.1.8, js-base64@^2.1.9: + version "2.4.0" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.0.tgz#9e566fee624751a1d720c966cd6226d29d4025aa" + +js-tokens@^3.0.0, js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +js-yaml@^3.9.0, js-yaml@^3.9.1: + version "3.10.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@~3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" + dependencies: + argparse "^1.0.7" + esprima "^2.6.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + +json-parse-better-errors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + +jsonpointer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +jsx-ast-utils@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz#e801b1b39985e20fffc87b40e3748080e2dcac7f" + dependencies: + array-includes "^3.0.3" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.1.0, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0, kind-of@^5.0.2: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + +kind-of@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + +known-css-properties@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.5.0.tgz#6ff66943ed4a5b55657ee095779a91f4536f8084" + +knox@: + version "0.9.2" + resolved "https://registry.yarnpkg.com/knox/-/knox-0.9.2.tgz#3736593669e24f024fdaf723b6a1dc4afd839a71" + dependencies: + debug "^1.0.2" + mime "*" + once "^1.3.0" + stream-counter "^1.0.0" + xml2js "^0.4.4" + +lazy-cache@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264" + dependencies: + set-getter "^0.1.0" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +liftoff@^2.1.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.5.0.tgz#2009291bb31cea861bbf10a7c15a28caf75c31ec" + dependencies: + extend "^3.0.0" + findup-sync "^2.0.0" + fined "^1.0.1" + flagged-respawn "^1.0.0" + is-plain-object "^2.0.4" + object.map "^1.0.0" + rechoir "^0.6.2" + resolve "^1.1.7" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +load-json-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + dependencies: + graceful-fs "^4.1.2" + parse-json "^4.0.0" + pify "^3.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + +lodash._basetostring@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" + +lodash._basevalues@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" + +lodash._escapehtmlchar@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz#df67c3bb6b7e8e1e831ab48bfa0795b92afe899d" + dependencies: + lodash._htmlescapes "~2.4.1" + +lodash._escapestringchar@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz#ecfe22618a2ade50bfeea43937e51df66f0edb72" + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + +lodash._htmlescapes@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz#32d14bf0844b6de6f8b62a051b4f67c228b624cb" + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + +lodash._isnative@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._isnative/-/lodash._isnative-2.4.1.tgz#3ea6404b784a7be836c7b57580e1cdf79b14832c" + +lodash._objecttypes@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz#7c0b7f69d98a1f76529f890b0cdb1b4dfec11c11" + +lodash._reescape@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" + +lodash._reevaluate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" + +lodash._reinterpolate@^2.4.1, lodash._reinterpolate@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz#4f1227aa5a8711fc632f5b07a1f4607aab8b3222" + +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + +lodash._reunescapedhtml@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz#747c4fc40103eb3bb8a0976e571f7a2659e93ba7" + dependencies: + lodash._htmlescapes "~2.4.1" + lodash.keys "~2.4.1" + +lodash._root@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + +lodash._shimkeys@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz#6e9cc9666ff081f0b5a6c978b83e242e6949d203" + dependencies: + lodash._objecttypes "~2.4.1" + +lodash.assign@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + +lodash.assignin@^4.0.9: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" + +lodash.bind@^4.1.4: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + +lodash.clonedeep@^4.3.2: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + +lodash.cond@^4.3.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" + +lodash.defaults@^4.0.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + +lodash.defaults@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-2.4.1.tgz#a7e8885f05e68851144b6e12a8f3678026bc4c54" + dependencies: + lodash._objecttypes "~2.4.1" + lodash.keys "~2.4.1" + +lodash.escape@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" + dependencies: + lodash._root "^3.0.0" + +lodash.escape@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-2.4.1.tgz#2ce12c5e084db0a57dda5e5d1eeeb9f5d175a3b4" + dependencies: + lodash._escapehtmlchar "~2.4.1" + lodash._reunescapedhtml "~2.4.1" + lodash.keys "~2.4.1" + +lodash.filter@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" + +lodash.flatten@^4.2.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + +lodash.foreach@^4.3.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + +lodash.isobject@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-2.4.1.tgz#5a2e47fe69953f1ee631a7eba1fe64d2d06558f5" + dependencies: + lodash._objecttypes "~2.4.1" + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +lodash.keys@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-2.4.1.tgz#48dea46df8ff7632b10d706b8acb26591e2b3727" + dependencies: + lodash._isnative "~2.4.1" + lodash._shimkeys "~2.4.1" + lodash.isobject "~2.4.1" + +lodash.map@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" + +lodash.merge@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5" + +lodash.mergewith@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55" + +lodash.pick@^4.2.1: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" + +lodash.reduce@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" + +lodash.reject@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" + +lodash.restparam@^3.0.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" + +lodash.some@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" + +lodash.template@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-2.4.1.tgz#9e611007edf629129a974ab3c48b817b3e1cf20d" + dependencies: + lodash._escapestringchar "~2.4.1" + lodash._reinterpolate "~2.4.1" + lodash.defaults "~2.4.1" + lodash.escape "~2.4.1" + lodash.keys "~2.4.1" + lodash.templatesettings "~2.4.1" + lodash.values "~2.4.1" + +lodash.template@^3.0.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" + dependencies: + lodash._basecopy "^3.0.0" + lodash._basetostring "^3.0.0" + lodash._basevalues "^3.0.0" + lodash._isiterateecall "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.0.0" + lodash.keys "^3.0.0" + lodash.restparam "^3.0.0" + lodash.templatesettings "^3.0.0" + +lodash.templatesettings@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.0.0" + +lodash.templatesettings@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz#ea76c75d11eb86d4dbe89a83893bb861929ac699" + dependencies: + lodash._reinterpolate "~2.4.1" + lodash.escape "~2.4.1" + +lodash.values@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-2.4.1.tgz#abf514436b3cb705001627978cbcf30b1280eea4" + dependencies: + lodash.keys "~2.4.1" + +lodash@>=3.10.0, lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@~4.17.4: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +lodash@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" + +log-symbols@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.1.0.tgz#f35fa60e278832b538dc4dddcbb478a45d3e3be6" + dependencies: + chalk "^2.0.1" + +longest-streak@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e" + +loose-envify@^1.0.0, loose-envify@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" + dependencies: + js-tokens "^3.0.0" + +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + +lru-cache@2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" + +lru-cache@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +lru-queue@0.1: + version "0.1.0" + resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + dependencies: + es5-ext "~0.10.2" + +magic-string@^0.22.4: + version "0.22.4" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.4.tgz#31039b4e40366395618c1d6cf8193c53917475ff" + dependencies: + vlq "^0.2.1" + +make-iterator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.0.tgz#57bef5dc85d23923ba23767324d8e8f8f3d9694b" + dependencies: + kind-of "^3.1.0" + +map-cache@^0.2.0, map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + +map-obj@^1.0.0, map-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + +map-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" + +map-stream@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + dependencies: + object-visit "^1.0.0" + +markdown-escapes@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.1.tgz#1994df2d3af4811de59a6714934c2b2292734518" + +markdown-table@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.1.tgz#4b3dd3a133d1518b8ef0dbc709bf2a1b4824bc8c" + +mathml-tag-names@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.0.1.tgz#8d41268168bf86d1102b98109e28e531e7a34578" + +mdast-util-compact@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz#cdb5f84e2b6a2d3114df33bd05d9cb32e3c4083a" + dependencies: + unist-util-modify-children "^1.0.0" + unist-util-visit "^1.1.0" + +memoizee@0.4.X: + version "0.4.11" + resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.11.tgz#bde9817663c9e40fdb2a4ea1c367296087ae8c8f" + dependencies: + d "1" + es5-ext "^0.10.30" + es6-weak-map "^2.0.2" + event-emitter "^0.3.5" + is-promise "^2.1" + lru-queue "0.1" + next-tick "1" + timers-ext "^0.1.2" + +meow@^3.3.0, meow@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + dependencies: + camelcase-keys "^2.0.0" + decamelize "^1.1.2" + loud-rejection "^1.0.0" + map-obj "^1.0.1" + minimist "^1.1.3" + normalize-package-data "^2.3.4" + object-assign "^4.0.1" + read-pkg-up "^1.0.1" + redent "^1.0.0" + trim-newlines "^1.0.0" + +meow@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-4.0.0.tgz#fd5855dd008db5b92c552082db1c307cba20b29d" + dependencies: + camelcase-keys "^4.0.0" + decamelize-keys "^1.0.0" + loud-rejection "^1.0.0" + minimist "^1.1.3" + minimist-options "^3.0.1" + normalize-package-data "^2.3.4" + read-pkg-up "^3.0.0" + redent "^2.0.0" + trim-newlines "^2.0.0" + +micromatch@^2.3.11: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +micromatch@^3.0.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.4.tgz#bb812e741a41f982c854e42b421a7eac458796f4" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.0" + define-property "^1.0.0" + extend-shallow "^2.0.1" + extglob "^2.0.2" + fragment-cache "^0.2.1" + kind-of "^6.0.0" + nanomatch "^1.2.5" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +mime-db@~1.30.0: + version "1.30.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" + +mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7: + version "2.1.17" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" + dependencies: + mime-db "~1.30.0" + +mime@*: + version "2.0.3" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.0.3.tgz#4353337854747c48ea498330dc034f9f4bbbcc0b" + +mime@~1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.2.11.tgz#58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10" + +mimic-fn@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" + +"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimatch@^2.0.1: + version "2.0.10" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.10.tgz#8d087c39c6b38c001b97fca7ce6d0e1e80afbac7" + dependencies: + brace-expansion "^1.0.0" + +minimatch@~0.2.11: + version "0.2.14" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a" + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +minimist-options@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@1.1.x: + version "1.1.3" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8" + +minimist@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.2.0.tgz#4dffe525dae2b864c66c2e23c6271d7afdecefce" + +minimist@^1.1.0, minimist@^1.1.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +mixin-deep@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.0.tgz#47a8732ba97799457c8c1eca28f95132d7e8150a" + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +multipipe@^0.1.0, multipipe@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" + dependencies: + duplexer2 "0.0.2" + +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + +nan@^2.3.2: + version "2.8.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" + +nanomatch@^1.2.5: + version "1.2.6" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.6.tgz#f27233e97c34a8706b7e781a4bc611c957a81625" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^1.0.0" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + is-odd "^1.0.0" + kind-of "^5.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +natives@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.1.tgz#011acce1f7cbd87f7ba6b3093d6cd9392be1c574" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + +next-tick@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + +node-fetch@^1.0.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + +node-gyp@^3.3.1: + version "3.6.2" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.6.2.tgz#9bfbe54562286284838e750eac05295853fa1c60" + dependencies: + fstream "^1.0.0" + glob "^7.0.3" + graceful-fs "^4.1.2" + minimatch "^3.0.2" + mkdirp "^0.5.0" + nopt "2 || 3" + npmlog "0 || 1 || 2 || 3 || 4" + osenv "0" + request "2" + rimraf "2" + semver "~5.3.0" + tar "^2.0.0" + which "1" + +node-sass@^4.2.0: + version "4.7.2" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.7.2.tgz#9366778ba1469eb01438a9e8592f4262bcb6794e" + dependencies: + async-foreach "^0.1.3" + chalk "^1.1.1" + cross-spawn "^3.0.0" + gaze "^1.0.0" + get-stdin "^4.0.1" + glob "^7.0.3" + in-publish "^2.0.0" + lodash.assign "^4.2.0" + lodash.clonedeep "^4.3.2" + lodash.mergewith "^4.6.0" + meow "^3.7.0" + mkdirp "^0.5.1" + nan "^2.3.2" + node-gyp "^3.3.1" + npmlog "^4.0.0" + request "~2.79.0" + sass-graph "^2.2.4" + stdout-stream "^1.4.0" + "true-case-path" "^1.0.2" + +"nopt@2 || 3": + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + dependencies: + abbrev "1" + +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.0.1, normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + +normalize-selector@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" + +"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +nth-check@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4" + dependencies: + boolbase "~1.0.0" + +num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.8.1, oauth-sign@~0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@4.X, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object-assign@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-keys@^1.0.8: + version "1.0.11" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + dependencies: + isobject "^3.0.0" + +object.defaults@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" + dependencies: + array-each "^1.0.1" + array-slice "^1.0.0" + for-own "^1.0.0" + isobject "^3.0.0" + +object.map@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.0.tgz#92aef871cd6dcbced31fe29c0921db8395624597" + dependencies: + for-own "^0.1.4" + make-iterator "^1.0.0" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +object.pick@^1.2.0, object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + dependencies: + isobject "^3.0.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +once@~1.3.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + dependencies: + mimic-fn "^1.0.0" + +open@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/open/-/open-0.0.5.tgz#42c3e18ec95466b6bf0dc42f3a2945c3f0cad8fc" + +optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +orchestrator@^0.3.0: + version "0.3.8" + resolved "https://registry.yarnpkg.com/orchestrator/-/orchestrator-0.3.8.tgz#14e7e9e2764f7315fbac184e506c7aa6df94ad7e" + dependencies: + end-of-stream "~0.1.5" + sequencify "~0.0.7" + stream-consume "~0.1.0" + +ordered-read-streams@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz#fd565a9af8eb4473ba69b6ed8a34352cb552f126" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + dependencies: + lcid "^1.0.0" + +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +osenv@0: + version "0.1.4" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-limit@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + dependencies: + p-limit "^1.1.0" + +p-map@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" + +parse-entities@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.1.1.tgz#8112d88471319f27abae4d64964b122fe4e1b890" + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + +parse-filepath@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" + dependencies: + is-absolute "^1.0.0" + map-cache "^0.2.0" + path-root "^0.1.1" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +parse-json@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-3.0.0.tgz#fa6f47b18e23826ead32f263e744d0e1e847fb13" + dependencies: + error-ex "^1.3.1" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-is-inside@^1.0.1, path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-root-regex@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" + +path-root@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" + dependencies: + path-root-regex "^0.1.0" + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + dependencies: + pify "^2.0.0" + +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + dependencies: + pify "^3.0.0" + +pause-stream@0.0.11: + version "0.0.11" + resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" + dependencies: + through "~2.3" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pkg-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + dependencies: + find-up "^1.0.0" + +pluralize@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + +postcss-bem-linter@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-bem-linter/-/postcss-bem-linter-3.1.0.tgz#55352412fb481aad0d05148185a990734e1ca030" + dependencies: + minimatch "^3.0.3" + postcss "^6.0.6" + postcss-resolve-nested-selector "^0.1.1" + +postcss-html@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.12.0.tgz#39b6adb4005dfc5464df7999c0f81c95bced7e50" + dependencies: + htmlparser2 "^3.9.2" + remark "^8.0.0" + unist-util-find-all-after "^1.0.1" + +postcss-less@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-1.1.3.tgz#6930525271bfe38d5793d33ac09c1a546b87bb51" + dependencies: + postcss "^5.2.16" + +postcss-media-query-parser@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244" + +postcss-reporter@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-5.0.0.tgz#a14177fd1342829d291653f2786efd67110332c3" + dependencies: + chalk "^2.0.1" + lodash "^4.17.4" + log-symbols "^2.0.0" + postcss "^6.0.8" + +postcss-resolve-nested-selector@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz#29ccbc7c37dedfac304e9fff0bf1596b3f6a0e4e" + +postcss-safe-parser@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-3.0.1.tgz#b753eff6c7c0aea5e8375fbe4cde8bf9063ff142" + dependencies: + postcss "^6.0.6" + +postcss-sass@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.2.0.tgz#e55516441e9526ba4b380a730d3a02e9eaa78c7a" + dependencies: + gonzales-pe "^4.0.3" + postcss "^6.0.6" + +postcss-scss@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-1.0.2.tgz#ff45cf3354b879ee89a4eb68680f46ac9bb14f94" + dependencies: + postcss "^6.0.3" + +postcss-selector-parser@^3.1.0, postcss-selector-parser@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" + dependencies: + dot-prop "^4.1.1" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-sorting@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-sorting/-/postcss-sorting-3.1.0.tgz#af7c90ee73ad12569a57664eaf06735c2e25bec0" + dependencies: + lodash "^4.17.4" + postcss "^6.0.13" + +postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" + +postcss@>=5.0.19, postcss@^6.0.1, postcss@^6.0.13, postcss@^6.0.14, postcss@^6.0.3, postcss@^6.0.6, postcss@^6.0.8: + version "6.0.14" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.14.tgz#5534c72114739e75d0afcf017db853099f562885" + dependencies: + chalk "^2.3.0" + source-map "^0.6.1" + supports-color "^4.4.0" + +postcss@^5.2.16: + version "5.2.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" + dependencies: + chalk "^1.1.3" + js-base64 "^2.1.9" + source-map "^0.5.6" + supports-color "^3.2.3" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + +pretty-bytes@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-3.0.1.tgz#27d0008d778063a0b4811bb35c79f1bd5d5fbccf" + dependencies: + number-is-nan "^1.0.0" + +pretty-hrtime@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + +private@^0.1.6, private@^0.1.7: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + +process-nextick-args@^1.0.6, process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +progress@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" + +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + dependencies: + asap "~2.0.3" + +prop-types@^15.6.0: + version "15.6.0" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.3.1" + object-assign "^4.1.1" + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +q@^1.1.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + +qs@~6.3.0: + version "6.3.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" + +qs@~6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" + +quick-lru@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" + +randomatic@^1.1.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" + dependencies: + find-up "^2.0.0" + read-pkg "^3.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +read-pkg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + dependencies: + load-json-file "^4.0.0" + normalize-package-data "^2.3.2" + path-type "^3.0.0" + +"readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@~1.0.17: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + safe-buffer "~5.1.1" + string_decoder "~1.0.3" + util-deprecate "~1.0.1" + +readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + dependencies: + resolve "^1.1.6" + +redent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + dependencies: + indent-string "^2.1.0" + strip-indent "^1.0.1" + +redent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" + dependencies: + indent-string "^3.0.0" + strip-indent "^2.0.0" + +regenerate@^1.2.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + dependencies: + is-equal-shallow "^0.1.3" + +regex-not@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.0.tgz#42f83e39771622df826b02af176525d6a5f157f9" + dependencies: + extend-shallow "^2.0.1" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + dependencies: + jsesc "~0.5.0" + +remark-parse@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-4.0.0.tgz#99f1f049afac80382366e2e0d0bd55429dd45d8b" + dependencies: + collapse-white-space "^1.0.2" + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-whitespace-character "^1.0.0" + is-word-character "^1.0.0" + markdown-escapes "^1.0.0" + parse-entities "^1.0.2" + repeat-string "^1.5.4" + state-toggle "^1.0.0" + trim "0.0.1" + trim-trailing-lines "^1.0.0" + unherit "^1.0.4" + unist-util-remove-position "^1.0.0" + vfile-location "^2.0.0" + xtend "^4.0.1" + +remark-stringify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-4.0.0.tgz#4431884c0418f112da44991b4e356cfe37facd87" + dependencies: + ccount "^1.0.0" + is-alphanumeric "^1.0.0" + is-decimal "^1.0.0" + is-whitespace-character "^1.0.0" + longest-streak "^2.0.1" + markdown-escapes "^1.0.0" + markdown-table "^1.1.0" + mdast-util-compact "^1.0.0" + parse-entities "^1.0.2" + repeat-string "^1.5.4" + state-toggle "^1.0.0" + stringify-entities "^1.0.1" + unherit "^1.0.4" + xtend "^4.0.1" + +remark@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/remark/-/remark-8.0.0.tgz#287b6df2fe1190e263c1d15e486d3fa835594d6d" + dependencies: + remark-parse "^4.0.0" + remark-stringify "^4.0.0" + unified "^6.0.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +replace-ext@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" + +replace-ext@1.0.0, replace-ext@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" + +replacestream@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/replacestream/-/replacestream-4.0.3.tgz#3ee5798092be364b1cdb1484308492cb3dff2f36" + dependencies: + escape-string-regexp "^1.0.3" + object-assign "^4.0.1" + readable-stream "^2.0.2" + +request@2: + version "2.83.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + hawk "~6.0.2" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + stringstream "~0.0.5" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + +request@~2.79.0: + version "2.79.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + qs "~6.3.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + uuid "^3.0.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + +require-from-string@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.1.tgz#c545233e9d7da6616e9d59adfb39fc9f588676ff" + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + +require-uncached@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +resolve-dir@^1.0.0, resolve-dir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + dependencies: + expand-tilde "^2.0.0" + global-modules "^1.0.0" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + +resolve-url@^0.2.1, resolve-url@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + +resolve@1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.2.0, resolve@^1.4.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + dependencies: + path-parse "^1.0.5" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +rimraf@2, rimraf@^2.2.8: + version "2.6.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +rollup-plugin-babel@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-3.0.3.tgz#63adedc863130327512a4a9006efc2241c5b7c15" + dependencies: + rollup-pluginutils "^1.5.0" + +rollup-plugin-commonjs@^8.2.6: + version "8.2.6" + resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-8.2.6.tgz#27e5b9069ff94005bb01e01bb46a1e4873784677" + dependencies: + acorn "^5.2.1" + estree-walker "^0.5.0" + magic-string "^0.22.4" + resolve "^1.4.0" + rollup-pluginutils "^2.0.1" + +rollup-plugin-node-resolve@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.0.0.tgz#8b897c4c3030d5001277b0514b25d2ca09683ee0" + dependencies: + browser-resolve "^1.11.0" + builtin-modules "^1.1.0" + is-module "^1.0.0" + resolve "^1.1.6" + +rollup-plugin-uglify@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-uglify/-/rollup-plugin-uglify-2.0.1.tgz#67b37ad1efdafbd83af4c36b40c189ee4866c969" + dependencies: + uglify-js "^3.0.9" + +rollup-pluginutils@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" + dependencies: + estree-walker "^0.2.1" + minimatch "^3.0.2" + +rollup-pluginutils@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz#7ec95b3573f6543a46a6461bd9a7c544525d0fc0" + dependencies: + estree-walker "^0.3.0" + micromatch "^2.3.11" + +rollup@^0.50.0: + version "0.50.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.50.1.tgz#e4dafcbf8d2bb0d9f5589d0cc6f64d76b8815730" + +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + dependencies: + is-promise "^2.1.0" + +run-sequence@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/run-sequence/-/run-sequence-2.2.0.tgz#b3f8d42836db89d08b2fe704eaf0c93dfd8335e2" + dependencies: + chalk "^1.1.3" + gulp-util "^3.0.8" + +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + +safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + +sass-graph@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" + dependencies: + glob "^7.0.0" + lodash "^4.0.0" + scss-tokenizer "^0.2.3" + yargs "^7.0.0" + +sax@>=0.6.0, sax@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + +scss-tokenizer@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" + dependencies: + js-base64 "^2.1.8" + source-map "^0.4.2" + +"semver@2 || 3 || 4 || 5", semver@^5.3.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + +semver@^4.1.0: + version "4.3.6" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" + +semver@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + +sequencify@~0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/sequencify/-/sequencify-0.0.7.tgz#90cff19d02e07027fd767f5ead3e7b95d1e7380c" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-getter@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376" + dependencies: + to-object-path "^0.3.0" + +set-value@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.1" + to-object-path "^0.3.0" + +set-value@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + +sigmund@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + +slice-ansi@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + dependencies: + is-fullwidth-code-point "^2.0.0" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.1.tgz#e12b5487faded3e3dea0ac91e9400bf75b401370" + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^2.0.0" + +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + +sntp@2.x.x: + version "2.1.0" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" + dependencies: + hoek "4.x.x" + +source-map-resolve@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.3.1.tgz#610f6122a445b8dd51535a2a71b783dfc1248761" + dependencies: + atob "~1.1.0" + resolve-url "~0.2.1" + source-map-url "~0.3.0" + urix "~0.1.0" + +source-map-resolve@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.1.tgz#7ad0f593f2281598e854df80f19aae4b92d7a11a" + dependencies: + atob "^2.0.0" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + dependencies: + source-map "^0.5.6" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + +source-map-url@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9" + +source-map@0.5.x, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + +source-map@0.X, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + +source-map@^0.1.38: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + dependencies: + amdefine ">=0.0.4" + +source-map@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + dependencies: + amdefine ">=0.0.4" + +sparkles@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" + +spdx-correct@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" + dependencies: + spdx-license-ids "^1.0.2" + +spdx-expression-parse@~1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" + +spdx-license-ids@^1.0.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" + +specificity@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.3.2.tgz#99e6511eceef0f8d9b57924937aac2cb13d13c42" + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + dependencies: + extend-shallow "^3.0.0" + +split@0.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" + dependencies: + through "2" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +sshpk@^1.7.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +state-toggle@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.0.tgz#d20f9a616bb4f0c3b98b91922d25b640aa2bc425" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +stdout-stream@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b" + dependencies: + readable-stream "^2.0.1" + +stream-combiner@~0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" + dependencies: + duplexer "~0.1.1" + +stream-consume@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.0.tgz#a41ead1a6d6081ceb79f65b061901b6d8f3d1d0f" + +stream-counter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-counter/-/stream-counter-1.0.0.tgz#91cf2569ce4dc5061febcd7acb26394a5a114751" + +string-width@^1.0.1, string-width@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^2.1.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +string_decoder@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + dependencies: + safe-buffer "~5.1.0" + +stringify-entities@^1.0.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-1.3.1.tgz#b150ec2d72ac4c1b5f324b51fb6b28c9cdff058c" + dependencies: + character-entities-html4 "^1.0.0" + character-entities-legacy "^1.0.0" + is-alphanumerical "^1.0.0" + is-hexadecimal "^1.0.0" + +stringstream@~0.0.4, stringstream@~0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + +strip-ansi@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.3.0.tgz#25f48ea22ca79187f3174a4db8759347bb126220" + dependencies: + ansi-regex "^0.2.1" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + +strip-bom-string@1.X: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" + +strip-bom@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-1.0.0.tgz#85b8862f3844b5a6d5ec8467a93598173a36f794" + dependencies: + first-chunk-stream "^1.0.0" + is-utf8 "^0.2.0" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +strip-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + dependencies: + get-stdin "^4.0.1" + +strip-indent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +style-search@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902" + +stylelint-config-prettier@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/stylelint-config-prettier/-/stylelint-config-prettier-2.0.0.tgz#0f671435294ebe4a215971855e1e576f5f227a21" + +stylelint-config-recommended@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-2.0.1.tgz#4746119ec85f5f4663c7b5107c05c13ed0e2ab0d" + +stylelint-config-sass-guidelines@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/stylelint-config-sass-guidelines/-/stylelint-config-sass-guidelines-4.0.1.tgz#c64f353e07575ad06f6405d6dd902066aa5bc8c4" + +stylelint-config-standard@^18.0.0: + version "18.0.0" + resolved "https://registry.yarnpkg.com/stylelint-config-standard/-/stylelint-config-standard-18.0.0.tgz#0d872b40fafdcddcf4188fb5b64ddb3887e8aefc" + dependencies: + stylelint-config-recommended "^2.0.0" + +stylelint-order@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/stylelint-order/-/stylelint-order-0.8.0.tgz#49da5615cb91ed077ebd274687f4df3d6feeb4e4" + dependencies: + lodash "^4.17.4" + postcss "^6.0.14" + postcss-sorting "^3.1.0" + +stylelint-scss@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-2.2.0.tgz#3e324bf13346db7af21cd24ad57fe3202f7c3823" + dependencies: + lodash "^4.17.4" + postcss-media-query-parser "^0.2.3" + postcss-resolve-nested-selector "^0.1.1" + postcss-selector-parser "^3.1.1" + postcss-value-parser "^3.3.0" + +stylelint-selector-bem-pattern@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/stylelint-selector-bem-pattern/-/stylelint-selector-bem-pattern-2.0.0.tgz#9a6130c9c90963b30e925c917079d6c8fed73f45" + dependencies: + lodash ">=3.10.0" + postcss ">=5.0.19" + postcss-bem-linter "^3.0.0" + stylelint ">=3.0.2" + +stylelint@>=3.0.2, stylelint@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-8.4.0.tgz#c2dbaeb17236917819f9206e1c0df5fddf6f83c3" + dependencies: + autoprefixer "^7.1.2" + balanced-match "^1.0.0" + chalk "^2.0.1" + cosmiconfig "^3.1.0" + debug "^3.0.0" + execall "^1.0.0" + file-entry-cache "^2.0.0" + get-stdin "^5.0.1" + globby "^7.0.0" + globjoin "^0.1.4" + html-tags "^2.0.0" + ignore "^3.3.3" + imurmurhash "^0.1.4" + known-css-properties "^0.5.0" + lodash "^4.17.4" + log-symbols "^2.0.0" + mathml-tag-names "^2.0.1" + meow "^4.0.0" + micromatch "^2.3.11" + normalize-selector "^0.2.0" + pify "^3.0.0" + postcss "^6.0.6" + postcss-html "^0.12.0" + postcss-less "^1.1.0" + postcss-media-query-parser "^0.2.3" + postcss-reporter "^5.0.0" + postcss-resolve-nested-selector "^0.1.1" + postcss-safe-parser "^3.0.1" + postcss-sass "^0.2.0" + postcss-scss "^1.0.2" + postcss-selector-parser "^3.1.0" + postcss-value-parser "^3.3.0" + resolve-from "^4.0.0" + specificity "^0.3.1" + string-width "^2.1.0" + style-search "^0.1.0" + sugarss "^1.0.0" + svg-tags "^1.0.0" + table "^4.0.1" + +sugarss@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-1.0.1.tgz#be826d9003e0f247735f92365dc3fd7f1bae9e44" + dependencies: + postcss "^6.0.14" + +supports-color@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + dependencies: + has-flag "^1.0.0" + +supports-color@^4.0.0, supports-color@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + dependencies: + has-flag "^2.0.0" + +svg-tags@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" + +svgo@^0.7.0: + version "0.7.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" + dependencies: + coa "~1.0.1" + colors "~1.1.2" + csso "~2.3.1" + js-yaml "~3.7.0" + mkdirp "~0.5.1" + sax "~1.2.1" + whet.extend "~0.9.9" + +table@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" + dependencies: + ajv "^5.2.3" + ajv-keywords "^2.1.0" + chalk "^2.1.0" + lodash "^4.17.4" + slice-ansi "1.0.0" + string-width "^2.1.1" + +tar@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" + +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + +textextensions@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-1.0.2.tgz#65486393ee1f2bb039a60cbba05b0b68bd9501d2" + +through2@2.0.3, through2@2.X, through2@^2.0.0, through2@^2.0.1, through2@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +through2@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.5.1.tgz#dfdd012eb9c700e2323fd334f38ac622ab372da7" + dependencies: + readable-stream "~1.0.17" + xtend "~3.0.0" + +through2@^0.6.1: + version "0.6.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" + dependencies: + readable-stream ">=1.0.33-1 <1.1.0-0" + xtend ">=4.0.0 <4.1.0-0" + +through@2, through@^2.3.6, through@~2.3, through@~2.3.1: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +tildify@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a" + dependencies: + os-homedir "^1.0.0" + +time-stamp@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" + +timers-ext@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.2.tgz#61cc47a76c1abd3195f14527f978d58ae94c5204" + dependencies: + es5-ext "~0.10.14" + next-tick "1" + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + dependencies: + os-tmpdir "~1.0.2" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.1.tgz#15358bee4a2c83bd76377ba1dc049d0f18837aae" + dependencies: + define-property "^0.2.5" + extend-shallow "^2.0.1" + regex-not "^1.0.0" + +tough-cookie@~2.3.0, tough-cookie@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" + dependencies: + punycode "^1.4.1" + +trim-newlines@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" + +trim-newlines@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + +trim-trailing-lines@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz#7aefbb7808df9d669f6da2e438cac8c46ada7684" + +trim@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + +trough@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.1.tgz#a9fd8b0394b0ae8fff82e0633a0a36ccad5b5f86" + +"true-case-path@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.2.tgz#7ec91130924766c7f573be3020c34f8fdfd00d62" + dependencies: + glob "^6.0.4" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tunnel-agent@~0.4.1: + version "0.4.3" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +ua-parser-js@^0.7.9: + version "0.7.17" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" + +uglify-es@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.2.2.tgz#15c62b7775002c81b7987a1c49ecd3f126cace73" + dependencies: + commander "~2.12.1" + source-map "~0.6.1" + +uglify-js@^3.0.9: + version "3.2.2" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.2.2.tgz#870e4b34ed733d179284f9998efd3293f7fd73f6" + dependencies: + commander "~2.12.1" + source-map "~0.6.1" + +unc-path-regex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + +unherit@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.0.tgz#6b9aaedfbf73df1756ad9e316dd981885840cd7d" + dependencies: + inherits "^2.0.1" + xtend "^4.0.1" + +unified@^6.0.0: + version "6.1.6" + resolved "https://registry.yarnpkg.com/unified/-/unified-6.1.6.tgz#5ea7f807a0898f1f8acdeefe5f25faa010cc42b1" + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-plain-obj "^1.1.0" + trough "^1.0.0" + vfile "^2.0.0" + x-is-function "^1.0.4" + x-is-string "^0.1.0" + +union-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^0.4.3" + +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + +unique-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-1.0.0.tgz#d59a4a75427447d9aa6c91e70263f8d26a4b104b" + +unist-util-find-all-after@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-1.0.1.tgz#4e5512abfef7e0616781aecf7b1ed751c00af908" + dependencies: + unist-util-is "^2.0.0" + +unist-util-is@^2.0.0, unist-util-is@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-2.1.1.tgz#0c312629e3f960c66e931e812d3d80e77010947b" + +unist-util-modify-children@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unist-util-modify-children/-/unist-util-modify-children-1.1.1.tgz#66d7e6a449e6f67220b976ab3cb8b5ebac39e51d" + dependencies: + array-iterate "^1.0.0" + +unist-util-remove-position@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz#5a85c1555fc1ba0c101b86707d15e50fa4c871bb" + dependencies: + unist-util-visit "^1.1.0" + +unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz#3ccbdc53679eed6ecf3777dd7f5e3229c1b6aa3c" + +unist-util-visit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.3.0.tgz#41ca7c82981fd1ce6c762aac397fc24e35711444" + dependencies: + unist-util-is "^2.1.1" + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +urix@^0.1.0, urix@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + +use@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/use/-/use-2.0.2.tgz#ae28a0d72f93bf22422a18a2e379993112dec8e8" + dependencies: + define-property "^0.2.5" + isobject "^3.0.0" + lazy-cache "^2.0.2" + +user-home@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +uuid@^3.0.0, uuid@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" + +v8flags@^2.0.2: + version "2.1.1" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" + dependencies: + user-home "^1.1.1" + +validate-npm-package-license@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" + dependencies: + spdx-correct "~1.0.0" + spdx-expression-parse "~1.0.0" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vfile-location@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.2.tgz#d3675c59c877498e492b4756ff65e4af1a752255" + +vfile-message@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.0.0.tgz#a6adb0474ea400fa25d929f1d673abea6a17e359" + dependencies: + unist-util-stringify-position "^1.1.1" + +vfile@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a" + dependencies: + is-buffer "^1.1.4" + replace-ext "1.0.0" + unist-util-stringify-position "^1.0.0" + vfile-message "^1.0.0" + +vinyl-fs@^0.3.0: + version "0.3.14" + resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-0.3.14.tgz#9a6851ce1cac1c1cea5fe86c0931d620c2cfa9e6" + dependencies: + defaults "^1.0.0" + glob-stream "^3.1.5" + glob-watcher "^0.0.6" + graceful-fs "^3.0.0" + mkdirp "^0.5.0" + strip-bom "^1.0.0" + through2 "^0.6.1" + vinyl "^0.4.0" + +vinyl-sourcemaps-apply@0.2.1, vinyl-sourcemaps-apply@^0.2.0, vinyl-sourcemaps-apply@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" + dependencies: + source-map "^0.5.1" + +vinyl@1.X: + version "1.2.0" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" + dependencies: + clone "^1.0.0" + clone-stats "^0.0.1" + replace-ext "0.0.1" + +vinyl@^0.2.1: + version "0.2.3" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.2.3.tgz#bca938209582ec5a49ad538a00fa1f125e513252" + dependencies: + clone-stats "~0.0.1" + +vinyl@^0.4.0: + version "0.4.6" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" + dependencies: + clone "^0.2.0" + clone-stats "^0.0.1" + +vinyl@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" + dependencies: + clone "^1.0.0" + clone-stats "^0.0.1" + replace-ext "0.0.1" + +vinyl@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.1.0.tgz#021f9c2cf951d6b939943c89eb5ee5add4fd924c" + dependencies: + clone "^2.1.1" + clone-buffer "^1.0.0" + clone-stats "^1.0.0" + cloneable-readable "^1.0.0" + remove-trailing-separator "^1.0.1" + replace-ext "^1.0.0" + +vlq@^0.2.1: + version "0.2.3" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" + +whatwg-fetch@>=0.10.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" + +whet.extend@~0.9.9: + version "0.9.9" + resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" + +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + +which@1, which@^1.2.14, which@^1.2.9: + version "1.3.0" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" + dependencies: + string-width "^1.0.2" + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + dependencies: + mkdirp "^0.5.1" + +x-is-function@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/x-is-function/-/x-is-function-1.0.4.tgz#5d294dc3d268cbdd062580e0c5df77a391d1fa1e" + +x-is-string@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" + +xml2js@^0.4.4: + version "0.4.19" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" + dependencies: + sax ">=0.6.0" + xmlbuilder "~9.0.1" + +xmlbuilder@~9.0.1: + version "9.0.4" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.4.tgz#519cb4ca686d005a8420d3496f3f0caeecca580f" + +"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +xtend@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-3.0.0.tgz#5cce7407baf642cba7becda568111c493f59665a" + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yargs-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" + dependencies: + camelcase "^3.0.0" + +yargs@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^5.0.0" |